@helpway/react 0.13.2 → 0.14.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.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../../widget-core/src/client.ts","../../widget-core/src/visitor-id.ts","../../types/src/realtime-events.ts","../../widget-core/src/ws.ts","../../widget-core/src/store.ts","../../widget-core/src/api.ts","../../widget-core/src/theme.ts","../../widget-core/src/events.ts","../../widget-core/src/i18n.ts","../../widget-core/src/utils.ts","../src/provider.tsx","../src/themed/default-widget.tsx","../src/hooks/use-announcements.ts","../src/hooks/use-composer.ts","../src/hooks/use-conversations.ts","../src/hooks/use-i18n.ts","../src/hooks/use-presence.ts","../src/hooks/use-timeline.ts","../src/hooks/use-unread.ts","../src/hooks/use-widget.ts","../src/themed/composer.tsx","../src/themed/icons.tsx","../src/themed/message-bubble.tsx","../src/themed/content/simple-markdown.tsx","../src/themed/debug-overlay.tsx","../src/themed/content/content-tab-view.tsx","../src/hooks/use-content-tab.ts","../src/themed/content/content-detail-view.tsx","../src/themed/content/content-list-view.tsx","../src/themed/content/grouped-content-tab-view.tsx","../src/hooks/use-grouped-content-tab.ts","../src/themed/content/tab-icon.tsx","../src/themed/announcement-previews.tsx","../src/themed/strip-markdown.ts","../src/themed/message-list.tsx","../src/themed/message-preview.tsx","#style-inject:#style-inject","../src/themed/styles.css","../src/helpway-widget.tsx","../src/hooks/use-realtime.ts"],"sourcesContent":["import { createTRPCClient, httpBatchLink } from \"@trpc/client\";\nimport { getOrCreateVisitorId } from \"./visitor-id\";\n\n// The real AppRouter lives in apps/api/src/trpc/ but importing it pulls in CF Worker\n// source files. We type the client as `any` here — real type safety is in the\n// Zustand store (widget-react). The tRPC link config is the same at runtime.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type WidgetClient = any;\n\n/**\n * Create a tRPC vanilla client for widget API calls.\n *\n * Visitor identity uses a dual strategy:\n * 1. X-Visitor-Id header (localStorage-based) — always works, even cross-origin\n * 2. hw_visitor cookie (server-set) — additional persistence layer\n *\n * This ensures visitor identity survives 3rd-party cookie blocking\n * (Safari ITP, Firefox ETP, Chrome Privacy Sandbox).\n */\nexport function createWidgetClient(config: {\n\tapiUrl: string;\n\tapiKey: string;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\n}): any {\n\treturn createTRPCClient({\n\t\tlinks: [\n\t\t\thttpBatchLink({\n\t\t\t\turl: `${config.apiUrl}/trpc`,\n\t\t\t\theaders() {\n\t\t\t\t\treturn {\n\t\t\t\t\t\t\"X-Public-Key\": config.apiKey,\n\t\t\t\t\t\t\"X-Visitor-Id\": getOrCreateVisitorId(config.apiKey),\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t\tfetch(url, options) {\n\t\t\t\t\t// credentials: \"include\" sends cookies cross-origin (when not blocked)\n\t\t\t\t\treturn globalThis.fetch(url, { ...options, credentials: \"include\" });\n\t\t\t\t},\n\t\t\t}),\n\t\t],\n\t});\n}\n","/**\n * Per-site visitor identity storage (localStorage).\n *\n * Matches Intercom's `intercom-id-[app_id]` pattern — each publicKey gets\n * its own localStorage slot so a single browser visiting multiple Helpway\n * workspaces never bleeds identities across them.\n *\n * Storage key: `helpway:visitor:<publicKey-suffix>` (last 16 chars of the key,\n * which is always random — see `generatePublicKey` in apps/api/src/lib/id.ts).\n */\n\nconst PREFIX = \"helpway:visitor\";\nconst LEGACY_KEY = \"helpway:visitor-id\";\n\nfunction keyFor(publicKey: string): string {\n\t// Last 16 chars of publicKey — enough uniqueness (2^80 collision space for nanoid alphabet)\n\t// and keeps localStorage key short. Stable for a given site.\n\tconst suffix = publicKey.slice(-16);\n\treturn `${PREFIX}:${suffix}`;\n}\n\nfunction generateId(): string {\n\tconst ts = Date.now().toString(36);\n\tconst rand = Math.random().toString(36).slice(2, 10);\n\treturn `${ts}${rand}`;\n}\n\n/**\n * Get or create a persistent visitor ID scoped to `publicKey`.\n * Returns a stable per-site ID across page loads.\n */\nexport function getOrCreateVisitorId(publicKey: string): string {\n\ttry {\n\t\tconst storageKey = keyFor(publicKey);\n\t\tconst existing = localStorage.getItem(storageKey);\n\t\tif (existing) return existing;\n\n\t\t// One-time migration: if a legacy global key exists AND no per-site key\n\t\t// is set yet, seed this site with it. Keeps returning visitors identified\n\t\t// on their FIRST post-upgrade site load. Subsequent sites get fresh IDs.\n\t\tconst legacy = localStorage.getItem(LEGACY_KEY);\n\t\tif (legacy) {\n\t\t\tlocalStorage.setItem(storageKey, legacy);\n\t\t\tlocalStorage.removeItem(LEGACY_KEY);\n\t\t\treturn legacy;\n\t\t}\n\n\t\tconst id = generateId();\n\t\tlocalStorage.setItem(storageKey, id);\n\t\treturn id;\n\t} catch {\n\t\t// localStorage unavailable (SSR, private mode, quota exceeded)\n\t\treturn generateId();\n\t}\n}\n\n/** Sync the server-assigned canonical visitor ID back into localStorage. */\nexport function syncVisitorId(publicKey: string, serverVisitorId: string): void {\n\ttry {\n\t\tlocalStorage.setItem(keyFor(publicKey), serverVisitorId);\n\t} catch {\n\t\t// ignore\n\t}\n}\n\n/** Clear the visitor ID for a specific site (used by playground \"simulate anonymous\"). */\nexport function clearVisitorId(publicKey: string): void {\n\ttry {\n\t\tlocalStorage.removeItem(keyFor(publicKey));\n\t} catch {\n\t\t// ignore\n\t}\n}\n","import type { Conversation } from \"./conversation\";\nimport type { TimelineItem } from \"./timeline-item\";\n\n// ── Event type constants ─────────────────────────────────\n\nexport const WsEventType = {\n\tConnectionEstablished: \"connectionEstablished\",\n\tConversationCreated: \"conversationCreated\",\n\tConversationUpdated: \"conversationUpdated\",\n\tTimelineItemCreated: \"timelineItemCreated\",\n\tTimelineItemUpdated: \"timelineItemUpdated\",\n\tTimelineItemDeleted: \"timelineItemDeleted\",\n\tConversationSeen: \"conversationSeen\",\n\tConversationTyping: \"conversationTyping\",\n\tAiProcessingProgress: \"aiProcessingProgress\",\n\tAiProcessingCompleted: \"aiProcessingCompleted\",\n\tAiStreamChunk: \"aiStreamChunk\",\n\tVisitorPresenceChanged: \"visitorPresenceChanged\",\n\tMemberUpdated: \"memberUpdated\",\n\tWorkspaceUnreadCounts: \"workspaceUnreadCounts\",\n} as const;\n\n// ── Union of all realtime events ──────────────────────────\n\nexport type RealtimeEvent =\n\t| ConnectionEstablishedEvent\n\t| ConversationCreatedEvent\n\t| ConversationUpdatedEvent\n\t| TimelineItemCreatedEvent\n\t| TimelineItemUpdatedEvent\n\t| TimelineItemDeletedEvent\n\t| ConversationSeenEvent\n\t| ConversationTypingEvent\n\t| AiProcessingProgressEvent\n\t| AiProcessingCompletedEvent\n\t| AiStreamChunkEvent\n\t| VisitorPresenceChangedEvent\n\t| MemberUpdatedEvent\n\t| WorkspaceUnreadCountsEvent;\n\n// ── Connection ────────────────────────────────────────────\n\nexport interface ConnectionEstablishedEvent {\n\ttype: \"connectionEstablished\";\n\tconnectionId: string;\n}\n\n// ── Conversation lifecycle ────────────────────────────────\n\nexport interface ConversationCreatedEvent {\n\ttype: \"conversationCreated\";\n\tconversation: Conversation;\n}\n\nexport interface ConversationUpdatedEvent {\n\ttype: \"conversationUpdated\";\n\tconversationId: string;\n\tupdates: Partial<Conversation>;\n}\n\n// ── Timeline items ────────────────────────────────────────\n\nexport interface TimelineItemCreatedEvent {\n\ttype: \"timelineItemCreated\";\n\tconversationId: string;\n\titem: TimelineItem;\n}\n\nexport interface TimelineItemUpdatedEvent {\n\ttype: \"timelineItemUpdated\";\n\tconversationId: string;\n\titem: TimelineItem;\n}\n\nexport interface TimelineItemDeletedEvent {\n\ttype: \"timelineItemDeleted\";\n\tconversationId: string;\n\titemId: string;\n}\n\n// ── Presence / read receipts ──────────────────────────────\n\nexport interface ConversationSeenEvent {\n\ttype: \"conversationSeen\";\n\tconversationId: string;\n\tuserId?: string;\n\tvisitorId?: string;\n\tlastSeenAt: string;\n}\n\nexport interface ConversationTypingEvent {\n\ttype: \"conversationTyping\";\n\tconversationId: string;\n\tuserId?: string;\n\tvisitorId?: string;\n\tisTyping: boolean;\n}\n\n// ── AI processing indicators ──────────────────────────────\n\nexport interface AiProcessingProgressEvent {\n\ttype: \"aiProcessingProgress\";\n\tconversationId: string;\n\tphase: \"thinking\" | \"searching\" | \"responding\";\n}\n\nexport interface AiProcessingCompletedEvent {\n\ttype: \"aiProcessingCompleted\";\n\tconversationId: string;\n\tstatus: \"success\" | \"error\" | \"skipped\";\n}\n\nexport interface AiStreamChunkEvent {\n\ttype: \"aiStreamChunk\";\n\tconversationId: string;\n\t/** Incremental text delta — widget appends to the streaming bubble. */\n\tdelta: string;\n\t/** True when this is the final chunk — widget should finalize the bubble. */\n\tdone: boolean;\n}\n\n// ── Visitor presence ─────────────────────────────────────\n\nexport interface VisitorPresenceChangedEvent {\n\ttype: \"visitorPresenceChanged\";\n\tvisitorId: string;\n\tstatus: \"online\" | \"offline\";\n}\n\n// ── Organization team ────────────────────────────────────\n\nexport interface MemberUpdatedEvent {\n\ttype: \"memberUpdated\";\n\taction: \"added\" | \"removed\" | \"roleChanged\";\n\tmemberId: string;\n}\n\n// ── Workspace meta events ───────────────────────────────\n\nexport interface WorkspaceUnreadCountsEvent {\n\ttype: \"workspaceUnreadCounts\";\n\tcounts: Record<string, number>;\n}\n\n// ── Event type guard helper ───────────────────────────────\n\nexport function isRealtimeEvent(data: unknown): data is RealtimeEvent {\n\treturn (\n\t\ttypeof data === \"object\" &&\n\t\tdata !== null &&\n\t\t\"type\" in data &&\n\t\ttypeof (data as RealtimeEvent).type === \"string\"\n\t);\n}\n","import { type RealtimeEvent, isRealtimeEvent } from \"@helpway/types\";\n\nexport type EventHandler = (event: RealtimeEvent) => void;\n\ninterface WebSocketManagerConfig {\n\tapiUrl: string;\n\tvisitorId: string;\n\twebsiteId: string;\n}\n\n/**\n * WebSocket connection manager for ChatRoom Durable Object.\n * Handles connect, disconnect, auto-reconnect with exponential backoff,\n * ping/pong keep-alive, and event dispatching.\n *\n * Ping gating — visibility-aware:\n * Ping doubles as a presence heartbeat on the server (refreshes KV\n * presence key with a 150s TTL). When the tab is hidden we pause the\n * ping so a forgotten background tab naturally drops offline within\n * ~2.5 minutes. The socket itself stays open; only the heartbeat stops.\n */\nexport class WebSocketManager {\n\tprivate ws: WebSocket | null = null;\n\tprivate handlers = new Set<EventHandler>();\n\tprivate config: WebSocketManagerConfig;\n\tprivate reconnectAttempts = 0;\n\tprivate maxReconnectAttempts = 10;\n\tprivate reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n\tprivate pingTimer: ReturnType<typeof setInterval> | null = null;\n\tprivate isDestroyed = false;\n\tprivate visibilityHandler: (() => void) | null = null;\n\n\tconstructor(config: WebSocketManagerConfig) {\n\t\tthis.config = config;\n\t\tthis.setupVisibilityListener();\n\t}\n\n\tprivate setupVisibilityListener(): void {\n\t\tif (typeof document === \"undefined\") return;\n\t\tthis.visibilityHandler = () => {\n\t\t\tif (document.visibilityState === \"hidden\") {\n\t\t\t\t// Tab backgrounded — stop heartbeat so KV TTL drops user offline.\n\t\t\t\tthis.stopPing();\n\t\t\t} else if (this.ws?.readyState === WebSocket.OPEN) {\n\t\t\t\t// Tab visible again — resume heartbeat immediately to restore presence.\n\t\t\t\tthis.startPing();\n\t\t\t\tthis.send({ type: \"ping\" });\n\t\t\t}\n\t\t};\n\t\tdocument.addEventListener(\"visibilitychange\", this.visibilityHandler);\n\t}\n\n\t/** Update connection parameters (call before connect) */\n\tconfigure(params: Partial<WebSocketManagerConfig>): void {\n\t\tObject.assign(this.config, params);\n\t}\n\n\t/** Connect to the ChatRoom Durable Object WebSocket */\n\tconnect(): void {\n\t\tif (this.ws?.readyState === WebSocket.OPEN) return;\n\t\t// Reset destroyed flag — allows reconnect after React StrictMode remount\n\t\tthis.isDestroyed = false;\n\n\t\tconst protocol = this.config.apiUrl.startsWith(\"https\") ? \"wss\" : \"ws\";\n\t\tconst base = this.config.apiUrl.replace(/^https?/, protocol);\n\t\tconst params = new URLSearchParams({\n\t\t\ttype: \"visitor\",\n\t\t\tid: this.config.visitorId,\n\t\t\twebsiteId: this.config.websiteId,\n\t\t});\n\n\t\tconst ws = new WebSocket(`${base}/ws?${params}`);\n\n\t\tws.onopen = () => {\n\t\t\tthis.reconnectAttempts = 0;\n\t\t\t// Only start heartbeat if the tab is visible — the visibility\n\t\t\t// listener resumes it automatically when the user returns.\n\t\t\tif (typeof document === \"undefined\" || document.visibilityState === \"visible\") {\n\t\t\t\tthis.startPing();\n\t\t\t}\n\t\t};\n\n\t\tws.onmessage = (event) => {\n\t\t\ttry {\n\t\t\t\tconst data = JSON.parse(event.data as string);\n\t\t\t\tif (data.type === \"pong\") return;\n\t\t\t\tif (isRealtimeEvent(data)) {\n\t\t\t\t\tfor (const handler of this.handlers) {\n\t\t\t\t\t\thandler(data);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Malformed message — ignore\n\t\t\t}\n\t\t};\n\n\t\tws.onclose = () => {\n\t\t\tthis.stopPing();\n\t\t\tthis.ws = null;\n\t\t\tif (!this.isDestroyed) {\n\t\t\t\tthis.scheduleReconnect();\n\t\t\t}\n\t\t};\n\n\t\tws.onerror = () => {\n\t\t\t// onclose will fire after onerror\n\t\t};\n\n\t\tthis.ws = ws;\n\t}\n\n\t/** Disconnect and stop reconnecting */\n\tdisconnect(): void {\n\t\tthis.isDestroyed = true;\n\t\tthis.stopPing();\n\t\tif (this.reconnectTimer) {\n\t\t\tclearTimeout(this.reconnectTimer);\n\t\t\tthis.reconnectTimer = null;\n\t\t}\n\t\tif (this.visibilityHandler && typeof document !== \"undefined\") {\n\t\t\tdocument.removeEventListener(\"visibilitychange\", this.visibilityHandler);\n\t\t\tthis.visibilityHandler = null;\n\t\t}\n\t\tif (this.ws) {\n\t\t\tthis.ws.close(1000, \"Client disconnect\");\n\t\t\tthis.ws = null;\n\t\t}\n\t}\n\n\t/** Send a JSON message through the WebSocket */\n\tsend(data: Record<string, unknown>): void {\n\t\tif (this.ws?.readyState === WebSocket.OPEN) {\n\t\t\tthis.ws.send(JSON.stringify(data));\n\t\t}\n\t}\n\n\t/** Send typing indicator */\n\tsendTyping(conversationId: string, isTyping: boolean): void {\n\t\tthis.send({ type: \"typing\", conversationId, isTyping });\n\t}\n\n\t/** Subscribe to realtime events */\n\tonEvent(handler: EventHandler): () => void {\n\t\tthis.handlers.add(handler);\n\t\treturn () => {\n\t\t\tthis.handlers.delete(handler);\n\t\t};\n\t}\n\n\t/** Check if connected */\n\tget isConnected(): boolean {\n\t\treturn this.ws?.readyState === WebSocket.OPEN;\n\t}\n\n\t// ── Private ──────────────────────────────────────────\n\n\tprivate scheduleReconnect(): void {\n\t\tif (this.reconnectAttempts >= this.maxReconnectAttempts) return;\n\n\t\tconst delay = Math.min(1000 * 2 ** this.reconnectAttempts, 30000);\n\t\tthis.reconnectAttempts++;\n\n\t\tthis.reconnectTimer = setTimeout(() => {\n\t\t\tthis.connect();\n\t\t}, delay);\n\t}\n\n\tprivate startPing(): void {\n\t\tthis.stopPing();\n\t\tthis.pingTimer = setInterval(() => {\n\t\t\tthis.send({ type: \"ping\" });\n\t\t}, 25000);\n\t}\n\n\tprivate stopPing(): void {\n\t\tif (this.pingTimer) {\n\t\t\tclearInterval(this.pingTimer);\n\t\t\tthis.pingTimer = null;\n\t\t}\n\t}\n}\n","import { WsEventType } from \"@helpway/types\";\nimport type { PublicVisitor, RealtimeEvent, TimelineItem } from \"@helpway/types\";\nimport { createStore } from \"zustand/vanilla\";\n\n// ── Agent Config (from bootstrap) ────────────────────────\n\nexport interface WidgetContentTab {\n\tid: string;\n\tlabel: string;\n\ticon: string;\n\tmodelSlug: string;\n\tdisplay?: {\n\t\tsubtitleField?: string;\n\t\tbadgeField?: string;\n\t\timageField?: string;\n\t\tdateField?: string;\n\t};\n\ttabType?: \"flat\" | \"grouped\";\n\titemsModelSlug?: string;\n\tgroupField?: string;\n\t/** Marks this tab as the \"What's New\" / announcements source.\n\t * Only one tab should have this flag — the first match wins. */\n\tisAnnouncements?: boolean;\n}\n\nexport interface AgentConfig {\n\tid: string;\n\tname: string;\n\tavatarUrl: string | null;\n\tavatarPreset: string | null;\n\twelcomeMessage: string | null;\n\tsubtitleText: string | null;\n\tbrandColor: string;\n\twidgetPosition: \"bottom-right\" | \"bottom-left\";\n\tlauncherStyle: \"icon\" | \"bubble\" | \"help\";\n\t/** Custom image rendered inside the launcher bubble. NULL → fall back\n\t * to the chat-header chain (avatarUrl → avatarPreset → website logo). */\n\tlauncherIconUrl: string | null;\n\tbubbleStyle: \"rounded\" | \"square\" | \"pill\";\n\t/** Show/hide Messages tab in widget footer */\n\tshowMessagesTab: boolean;\n\t/** Require visitor to provide email before starting a conversation */\n\trequireVisitorEmail: boolean;\n\t/** Dynamic content tabs from Better i18n Content CMS integration */\n\tcontentTabs: WidgetContentTab[];\n}\n\n// ── Content Cache ──────────────────────────────────────────\n\nexport interface ContentCacheEntry {\n\tdata: unknown;\n\tts: number;\n}\n\nexport const CONTENT_CACHE_TTL = 5 * 60 * 1000; // 5 minutes\n\n// ── State Shape ──────────────────────────────────────────\n\nexport interface WidgetState {\n\t// Connection\n\tisReady: boolean;\n\tisConnecting: boolean;\n\n\t// Identity\n\tvisitor: PublicVisitor | null;\n\twebsite: { id: string; name: string; domain: string | null; logoUrl: string | null } | null;\n\n\t// Agent config (from bootstrap)\n\tagentConfig: AgentConfig | null;\n\n\t// Conversations\n\tconversations: ConversationSummary[];\n\tactiveConversationId: string | null;\n\n\t// Messages per conversation\n\tmessages: Map<string, TimelineItem[]>;\n\n\t// Presence\n\ttypingUsers: Map<string, boolean>; // conversationId → someone is typing\n\taiProcessing: Map<string, boolean>; // conversationId → AI is processing\n\tstreamingText: Map<string, string>; // conversationId → accumulated streamed text\n\n\t// UI state\n\tisOpen: boolean;\n\tisDismissed: boolean;\n\tview: \"home\" | \"conversation\" | \"new\";\n\n\t// Incoming message preview (shown when widget is closed)\n\tincomingPreview: {\n\t\ttext: string;\n\t\tconversationId: string;\n\t\ttimestamp: number;\n\t\tmessages?: Array<{ text: string }>;\n\t\tquickReplies?: {\n\t\t\tstepId: string;\n\t\t\tprompt: string | null;\n\t\t\toptions: Array<{ id: string; label: string }>;\n\t\t};\n\t} | null;\n\n\t// Announcement previews (shown when widget is closed and unseen content exists)\n\t// Multiple previews stack when several isAnnouncements tabs have new content.\n\tannouncementPreviews: Array<{\n\t\ttitle: string;\n\t\tbody: string | null;\n\t\tslug: string;\n\t\ttabId: string;\n\t\tbadge: string | null;\n\t}>;\n\n\t// Number of unseen announcement entries (drives launcher dot + tab badge)\n\tunseenAnnouncementCount: number;\n\n\t// Pre-filled text for new conversation (set via global API)\n\tnewConversationPrefill: string | null;\n\n\t// Pending content-detail open intent — when set, DefaultWidget\n\t// navigates to the matching content tab + entry detail on the next\n\t// render and clears it. Used so consumers rendering anchored\n\t// announcement previews (or any external trigger) can deep-link a\n\t// visitor straight into a specific entry instead of dropping them\n\t// on the home surface. The launcher's onOpen does this internally;\n\t// this field makes the same navigation reachable from outside\n\t// DefaultWidget's local state.\n\tpendingContentDetail: { slug: string; tabId: string } | null;\n\n\t// Content cache (survives tab switches — keyed by request params)\n\tcontentCache: Map<string, ContentCacheEntry>;\n}\n\nexport interface ConversationSummary {\n\tid: string;\n\ttitle: string | null;\n\tstatus: string;\n\tlastMessageText: string | null;\n\tlastMessageAt: string | null;\n\tlastMessageSenderType: string | null;\n\tlastMessageSenderName: string | null;\n\tlastMessageSenderImage: string | null;\n\t/** Display-only fields for the assigned support user. NULL when no\n\t * human is assigned (AI agent is handling). UserId is intentionally\n\t * not exposed — only what the chat header needs to render. */\n\tassigneeName: string | null;\n\tassigneeImage: string | null;\n\tunreadCount: number;\n}\n\n// ── Actions ──────────────────────────────────────────────\n\nexport interface WidgetActions {\n\t// Lifecycle\n\tsetReady(\n\t\tvisitor: WidgetState[\"visitor\"],\n\t\twebsite: WidgetState[\"website\"],\n\t\tagentConfig?: AgentConfig | null,\n\t): void;\n\tsetConnecting(connecting: boolean): void;\n\n\t// Conversations\n\tsetConversations(conversations: ConversationSummary[]): void;\n\taddConversation(conversation: ConversationSummary): void;\n\tsetActiveConversation(id: string | null): void;\n\n\t// Messages\n\tsetMessages(conversationId: string, items: TimelineItem[]): void;\n\taddMessage(conversationId: string, item: TimelineItem): void;\n\t/**\n\t * Replace a message by ID (used by optimistic send — swaps\n\t * temp `optimistic-*` id for the server-confirmed item).\n\t */\n\treplaceMessage(conversationId: string, oldId: string, item: TimelineItem): void;\n\t/** Remove a message by ID (used for optimistic rollback on send failure) */\n\tremoveMessage(conversationId: string, id: string): void;\n\t/**\n\t * Move an optimistic conversation to its server-assigned ID.\n\t * Copies messages + updates activeConversationId + conversations list.\n\t */\n\tremapConversationId(oldId: string, newId: string): void;\n\n\t// Presence\n\tsetTyping(conversationId: string, isTyping: boolean): void;\n\tsetAiProcessing(conversationId: string, processing: boolean): void;\n\tappendStreamChunk(conversationId: string, delta: string, done: boolean): void;\n\n\t// Identity\n\tupdateVisitorContact(contact: { id: string; name: string | null; email: string | null }): void;\n\n\t// Unread\n\tclearUnread(conversationId: string): void;\n\n\t// UI\n\tsetOpen(open: boolean): void;\n\tsetDismissed(dismissed: boolean): void;\n\tsetView(view: WidgetState[\"view\"]): void;\n\tsetNewConversationPrefill(text: string | null): void;\n\t/** Schedule a deep-link into a specific content entry's detail\n\t * view. DefaultWidget consumes it on the next render — call\n\t * `setOpen(true)` alongside to reveal the panel. Pass `null` to\n\t * clear (DefaultWidget does this automatically once it\n\t * navigates). */\n\tsetPendingContentDetail(value: { slug: string; tabId: string } | null): void;\n\tdismissPreview(): void;\n\n\t// Announcements\n\tsetAnnouncementPreview(preview: WidgetState[\"announcementPreviews\"][number]): void;\n\tdismissAnnouncementPreview(slug?: string): void;\n\tsetUnseenAnnouncementCount(count: number): void;\n\n\t// Content cache\n\tsetContentCache(key: string, data: unknown): void;\n\n\t// Realtime\n\thandleRealtimeEvent(event: RealtimeEvent): void;\n}\n\nexport type WidgetStore = WidgetState & WidgetActions;\n\n// ── Store Factory ────────────────────────────────────────\n\n// Proactive incoming-message previews must survive a page reload —\n// otherwise an agent/AI ping vanishes the moment the visitor refreshes\n// (it lived only in the in-memory store). Persist the single\n// `incomingPreview` field to localStorage; the existing clear paths\n// (setOpen-when-open, dismissPreview) flow through the subscription\n// below, so closing or replying still wipes it. Per-browser only\n// (localStorage) — not cross-device, fine for a transient affordance.\nconst PREVIEW_STORAGE_KEY = \"helpway:incoming-preview\";\n\nfunction loadPersistedPreview(): WidgetStore[\"incomingPreview\"] {\n\tif (typeof window === \"undefined\") return null;\n\ttry {\n\t\tconst raw = window.localStorage.getItem(PREVIEW_STORAGE_KEY);\n\t\treturn raw ? (JSON.parse(raw) as WidgetStore[\"incomingPreview\"]) : null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction persistPreview(preview: WidgetStore[\"incomingPreview\"]): void {\n\tif (typeof window === \"undefined\") return;\n\ttry {\n\t\tif (preview) {\n\t\t\twindow.localStorage.setItem(PREVIEW_STORAGE_KEY, JSON.stringify(preview));\n\t\t} else {\n\t\t\twindow.localStorage.removeItem(PREVIEW_STORAGE_KEY);\n\t\t}\n\t} catch {\n\t\t// quota / privacy-mode / SSR — non-fatal, preview just won't persist\n\t}\n}\n\nexport function createWidgetStore() {\n\tconst store = createStore<WidgetStore>((set, get) => ({\n\t\t// Initial state\n\t\tisReady: false,\n\t\tisConnecting: true,\n\t\tvisitor: null,\n\t\twebsite: null,\n\t\tagentConfig: null,\n\t\tconversations: [],\n\t\tactiveConversationId: null,\n\t\tmessages: new Map(),\n\t\ttypingUsers: new Map(),\n\t\taiProcessing: new Map(),\n\t\tstreamingText: new Map(),\n\t\tisOpen: false,\n\t\tisDismissed: false,\n\t\tview: \"home\",\n\t\tincomingPreview: loadPersistedPreview(),\n\t\tannouncementPreviews: [],\n\t\tunseenAnnouncementCount: 0,\n\t\tnewConversationPrefill: null,\n\t\tpendingContentDetail: null,\n\t\tcontentCache: new Map(),\n\n\t\t// ── Lifecycle ────────────────────────────────────\n\n\t\tsetReady(visitor, website, agentConfig) {\n\t\t\tset({\n\t\t\t\tisReady: true,\n\t\t\t\tisConnecting: false,\n\t\t\t\tvisitor,\n\t\t\t\twebsite,\n\t\t\t\tagentConfig: agentConfig ?? null,\n\t\t\t});\n\t\t},\n\n\t\tsetConnecting(connecting) {\n\t\t\tset({ isConnecting: connecting });\n\t\t},\n\n\t\t// ── Conversations ────────────────────────────────\n\n\t\tsetConversations(conversations) {\n\t\t\tset({ conversations });\n\t\t},\n\n\t\taddConversation(conversation) {\n\t\t\tset((state) => ({\n\t\t\t\tconversations: [conversation, ...state.conversations],\n\t\t\t}));\n\t\t},\n\n\t\tsetActiveConversation(id) {\n\t\t\tset({ activeConversationId: id, view: id ? \"conversation\" : \"home\" });\n\t\t},\n\n\t\t// ── Messages ─────────────────────────────────────\n\n\t\tsetMessages(conversationId, items) {\n\t\t\tset((state) => {\n\t\t\t\tconst next = new Map(state.messages);\n\t\t\t\tnext.set(conversationId, items);\n\t\t\t\treturn { messages: next };\n\t\t\t});\n\t\t},\n\n\t\taddMessage(conversationId, item) {\n\t\t\tset((state) => {\n\t\t\t\tconst next = new Map(state.messages);\n\t\t\t\tconst existing = next.get(conversationId) ?? [];\n\t\t\t\t// Deduplicate by ID — WS echoes may arrive twice (once from broadcast,\n\t\t\t\t// once from the mutation response path).\n\t\t\t\tif (existing.some((m) => m.id === item.id)) return state;\n\t\t\t\t// Agent welcome messages are always the opener of a conversation.\n\t\t\t\t// If the first existing item is a visitor message, prepend the welcome\n\t\t\t\t// so the greeting stays above — don't rely on createdAt (client clock\n\t\t\t\t// vs server clock drift can flip the order).\n\t\t\t\tconst isAgentWelcome = !!item.aiAgentId && !item.visitorId;\n\t\t\t\tconst firstIsVisitor = existing[0]?.visitorId != null;\n\t\t\t\tif (isAgentWelcome && firstIsVisitor) {\n\t\t\t\t\tnext.set(conversationId, [item, ...existing]);\n\t\t\t\t\treturn { messages: next };\n\t\t\t\t}\n\t\t\t\t// General case: insert chronologically. Sort only when the newcomer\n\t\t\t\t// is older than the current tail (rare — WS reorders).\n\t\t\t\tconst last = existing[existing.length - 1];\n\t\t\t\tconst isOutOfOrder = last && item.createdAt < last.createdAt;\n\t\t\t\tconst merged = [...existing, item];\n\t\t\t\tif (isOutOfOrder) {\n\t\t\t\t\tmerged.sort((a, b) => a.createdAt.localeCompare(b.createdAt));\n\t\t\t\t}\n\t\t\t\tnext.set(conversationId, merged);\n\t\t\t\treturn { messages: next };\n\t\t\t});\n\t\t},\n\n\t\treplaceMessage(conversationId, oldId, item) {\n\t\t\tset((state) => {\n\t\t\t\tconst next = new Map(state.messages);\n\t\t\t\tconst existing = next.get(conversationId) ?? [];\n\t\t\t\t// Race with WS echo: if the real item already landed, just drop the optimistic\n\t\t\t\tif (existing.some((m) => m.id === item.id && m.id !== oldId)) {\n\t\t\t\t\tnext.set(\n\t\t\t\t\t\tconversationId,\n\t\t\t\t\t\texisting.filter((m) => m.id !== oldId),\n\t\t\t\t\t);\n\t\t\t\t\treturn { messages: next };\n\t\t\t\t}\n\t\t\t\t// Preserve the optimistic ID as _stableKey so the React key\n\t\t\t\t// stays constant across the optimistic → real ID swap.\n\t\t\t\tnext.set(\n\t\t\t\t\tconversationId,\n\t\t\t\t\texisting.map((m) =>\n\t\t\t\t\t\tm.id === oldId\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t...item,\n\t\t\t\t\t\t\t\t\t_stableKey: (m as unknown as { _stableKey?: string })._stableKey ?? oldId,\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: m,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\treturn { messages: next };\n\t\t\t});\n\t\t},\n\n\t\tremoveMessage(conversationId, id) {\n\t\t\tset((state) => {\n\t\t\t\tconst next = new Map(state.messages);\n\t\t\t\tconst existing = next.get(conversationId);\n\t\t\t\tif (!existing) return state;\n\t\t\t\tnext.set(\n\t\t\t\t\tconversationId,\n\t\t\t\t\texisting.filter((m) => m.id !== id),\n\t\t\t\t);\n\t\t\t\treturn { messages: next };\n\t\t\t});\n\t\t},\n\n\t\tremapConversationId(oldId, newId) {\n\t\t\tset((state) => {\n\t\t\t\t// Merge messages from tempId + newId — WS echo may have inserted\n\t\t\t\t// items under the real id BEFORE the createConversation mutation\n\t\t\t\t// resolved. Dedupe by id so we don't lose the WS-delivered items.\n\t\t\t\tconst nextMessages = new Map(state.messages);\n\t\t\t\tconst tempItems = nextMessages.get(oldId) ?? [];\n\t\t\t\tconst existingItems = nextMessages.get(newId) ?? [];\n\t\t\t\tconst tempRewritten = tempItems.map((m) => ({ ...m, conversationId: newId }));\n\t\t\t\tconst isAgentMsg = (m: TimelineItem) => !!m.aiAgentId && !m.visitorId && !m.userId;\n\t\t\t\t// Prefer the seed welcome that came in via the temp conversation.\n\t\t\t\t// Keeping its DOM node stable is the whole point of openNewConversation\n\t\t\t\t// seeding; if we let the server-welcome (different id, same text)\n\t\t\t\t// take its slot, React unmounts the seed bubble and the animation\n\t\t\t\t// replays — exactly the \"git-gel\" the seed exists to prevent.\n\t\t\t\tconst seen = new Set<string>();\n\t\t\t\tconst merged: TimelineItem[] = [];\n\t\t\t\tlet keptAgentWelcome = false;\n\t\t\t\tfor (const m of tempRewritten) {\n\t\t\t\t\tif (seen.has(m.id)) continue;\n\t\t\t\t\tseen.add(m.id);\n\t\t\t\t\tmerged.push(m);\n\t\t\t\t\tif (isAgentMsg(m) && merged.length === 1) keptAgentWelcome = true;\n\t\t\t\t}\n\t\t\t\t// The server's welcome echo is the agent item that predates the\n\t\t\t\t// visitor's first server item (the API stamps it visitorTs - 1ms).\n\t\t\t\t// WS delivery is ordered, so if a genuine AI reply made it into\n\t\t\t\t// existingItems, the visitor item did too — when no visitor item\n\t\t\t\t// is present, the only agent item that can have arrived is the\n\t\t\t\t// welcome. Graft its identity onto the seed bubble (same DOM node\n\t\t\t\t// via _stableKey, real ULID for future dedup) instead of dropping\n\t\t\t\t// it; later agent items are genuine AI replies and MUST be kept.\n\t\t\t\tconst serverVisitorTs = existingItems.find((x) => x.visitorId)?.createdAt;\n\t\t\t\tlet graftedWelcome = false;\n\t\t\t\tfor (const m of existingItems) {\n\t\t\t\t\tif (seen.has(m.id)) continue;\n\t\t\t\t\tconst isWelcomeEcho =\n\t\t\t\t\t\tisAgentMsg(m) &&\n\t\t\t\t\t\tkeptAgentWelcome &&\n\t\t\t\t\t\t!graftedWelcome &&\n\t\t\t\t\t\t(!serverVisitorTs || m.createdAt <= serverVisitorTs);\n\t\t\t\t\tif (isWelcomeEcho) {\n\t\t\t\t\t\tconst seed = merged[0];\n\t\t\t\t\t\tmerged[0] = {\n\t\t\t\t\t\t\t...m,\n\t\t\t\t\t\t\t_stableKey: seed\n\t\t\t\t\t\t\t\t? ((seed as unknown as { _stableKey?: string })._stableKey ?? seed.id)\n\t\t\t\t\t\t\t\t: m.id,\n\t\t\t\t\t\t} as TimelineItem;\n\t\t\t\t\t\tseen.add(m.id);\n\t\t\t\t\t\tgraftedWelcome = true;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tseen.add(m.id);\n\t\t\t\t\tmerged.push(m);\n\t\t\t\t}\n\t\t\t\tnextMessages.delete(oldId);\n\t\t\t\tnextMessages.set(newId, merged);\n\n\t\t\t\t// Dedupe conversation list — WS conversationCreated may have\n\t\t\t\t// prepended newId already; in that case drop the temp entry.\n\t\t\t\tconst hasNewId = state.conversations.some((c) => c.id === newId);\n\t\t\t\tconst conversations = hasNewId\n\t\t\t\t\t? state.conversations.filter((c) => c.id !== oldId)\n\t\t\t\t\t: state.conversations.map((c) => (c.id === oldId ? { ...c, id: newId } : c));\n\n\t\t\t\treturn {\n\t\t\t\t\tmessages: nextMessages,\n\t\t\t\t\tconversations,\n\t\t\t\t\tactiveConversationId:\n\t\t\t\t\t\tstate.activeConversationId === oldId ? newId : state.activeConversationId,\n\t\t\t\t};\n\t\t\t});\n\t\t},\n\n\t\t// ── Presence ─────────────────────────────────────\n\n\t\tsetTyping(conversationId, isTyping) {\n\t\t\tset((state) => {\n\t\t\t\tconst next = new Map(state.typingUsers);\n\t\t\t\tnext.set(conversationId, isTyping);\n\t\t\t\treturn { typingUsers: next };\n\t\t\t});\n\t\t},\n\n\t\tsetAiProcessing(conversationId, processing) {\n\t\t\tset((state) => {\n\t\t\t\tconst next = new Map(state.aiProcessing);\n\t\t\t\tnext.set(conversationId, processing);\n\t\t\t\treturn { aiProcessing: next };\n\t\t\t});\n\t\t},\n\n\t\tappendStreamChunk(conversationId, delta, done) {\n\t\t\tset((state) => {\n\t\t\t\tconst next = new Map(state.streamingText);\n\t\t\t\tconst prev = next.get(conversationId) ?? \"\";\n\t\t\t\tif (done) {\n\t\t\t\t\tnext.delete(conversationId);\n\t\t\t\t} else {\n\t\t\t\t\tnext.set(conversationId, prev + delta);\n\t\t\t\t}\n\t\t\t\treturn { streamingText: next };\n\t\t\t});\n\t\t},\n\n\t\t// ── Identity ─────────────────────────────────────\n\n\t\tupdateVisitorContact(contact) {\n\t\t\tset((state) => ({\n\t\t\t\tvisitor: state.visitor ? { ...state.visitor, contact } : state.visitor,\n\t\t\t}));\n\t\t},\n\n\t\t// ── Unread ───────────────────────────────────────\n\n\t\tclearUnread(conversationId) {\n\t\t\tset((s) => ({\n\t\t\t\tconversations: s.conversations.map((c) =>\n\t\t\t\t\tc.id === conversationId ? { ...c, unreadCount: 0 } : c,\n\t\t\t\t),\n\t\t\t}));\n\t\t},\n\n\t\t// ── UI ───────────────────────────────────────────\n\n\t\tsetOpen(open) {\n\t\t\tset((s) => ({\n\t\t\t\tisOpen: open,\n\t\t\t\tincomingPreview: open ? null : s.incomingPreview,\n\t\t\t\tannouncementPreviews: open ? [] : s.announcementPreviews,\n\t\t\t}));\n\t\t},\n\n\t\tsetPendingContentDetail(value) {\n\t\t\tset({ pendingContentDetail: value });\n\t\t},\n\n\t\tsetDismissed(dismissed) {\n\t\t\tset({ isDismissed: dismissed });\n\t\t},\n\n\t\tsetView(view) {\n\t\t\tset({ view });\n\t\t},\n\n\t\tsetNewConversationPrefill(text) {\n\t\t\tset({ newConversationPrefill: text });\n\t\t},\n\n\t\tdismissPreview() {\n\t\t\tset({ incomingPreview: null });\n\t\t},\n\n\t\t// ── Announcements ────────────────────────────────\n\n\t\tsetAnnouncementPreview(preview) {\n\t\t\tset((s) => ({\n\t\t\t\tannouncementPreviews: [\n\t\t\t\t\t...s.announcementPreviews.filter((p) => p.tabId !== preview.tabId),\n\t\t\t\t\tpreview,\n\t\t\t\t],\n\t\t\t}));\n\t\t},\n\n\t\tdismissAnnouncementPreview(slug) {\n\t\t\tif (slug) {\n\t\t\t\tset((s) => ({\n\t\t\t\t\tannouncementPreviews: s.announcementPreviews.filter((p) => p.slug !== slug),\n\t\t\t\t}));\n\t\t\t} else {\n\t\t\t\tset({ announcementPreviews: [] });\n\t\t\t}\n\t\t},\n\n\t\tsetUnseenAnnouncementCount(count) {\n\t\t\tset({ unseenAnnouncementCount: count });\n\t\t},\n\n\t\t// ── Content Cache ────────────────────────────────\n\n\t\tsetContentCache(key, data) {\n\t\t\tget().contentCache.set(key, { data, ts: Date.now() });\n\t\t},\n\n\t\t// ── Realtime Event Handler ───────────────────────\n\n\t\thandleRealtimeEvent(event) {\n\t\t\tconst state = get();\n\n\t\t\tswitch (event.type) {\n\t\t\t\tcase WsEventType.TimelineItemCreated: {\n\t\t\t\t\t// Only add public messages (widget shouldn't see private notes)\n\t\t\t\t\tif (event.item.visibility === \"public\") {\n\t\t\t\t\t\t// When the widget seeded a local welcome bubble (openNewConversation)\n\t\t\t\t\t\t// the server's createConversation path ALSO emits its own welcome\n\t\t\t\t\t\t// timeline item. The echo usually lands AFTER the optimistic visitor\n\t\t\t\t\t\t// message is already in the list, so we can't gate on list length.\n\t\t\t\t\t\t// The reliable discriminator is the timestamp: the API stamps the\n\t\t\t\t\t\t// welcome 1ms BEFORE the visitor's first message, while a genuine\n\t\t\t\t\t\t// AI reply is always stamped after it — and by the time the seed\n\t\t\t\t\t\t// exists under the server conversation id, the visitor item has\n\t\t\t\t\t\t// already been swapped to its server-stamped twin, so both sides\n\t\t\t\t\t\t// of the comparison come from the server clock (drift-safe).\n\t\t\t\t\t\tconst isAgentAuthored =\n\t\t\t\t\t\t\t!!event.item.aiAgentId && !event.item.visitorId && !event.item.userId;\n\t\t\t\t\t\tconst existing = state.messages.get(event.conversationId);\n\t\t\t\t\t\tconst seedId = existing?.[0]?.id;\n\t\t\t\t\t\tconst hasSeedWelcome = typeof seedId === \"string\" && seedId.startsWith(\"seed-welcome-\");\n\t\t\t\t\t\tif (isAgentAuthored && hasSeedWelcome) {\n\t\t\t\t\t\t\tconst firstVisitorTs = existing?.find((m) => m.visitorId)?.createdAt;\n\t\t\t\t\t\t\tconst isWelcomeEcho = !firstVisitorTs || event.item.createdAt <= firstVisitorTs;\n\t\t\t\t\t\t\tif (isWelcomeEcho) {\n\t\t\t\t\t\t\t\t// Adopt the server identity onto the seed bubble instead of\n\t\t\t\t\t\t\t\t// dropping the event — replaceMessage keeps the seed id as\n\t\t\t\t\t\t\t\t// _stableKey (no remount/flash) and future hydrations dedupe\n\t\t\t\t\t\t\t\t// against the real ULID instead of the synthetic seed id.\n\t\t\t\t\t\t\t\tstate.replaceMessage(event.conversationId, seedId, event.item);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstate.addMessage(event.conversationId, event.item);\n\t\t\t\t\t}\n\t\t\t\t\t// Clear typing/processing indicators as soon as the AI message arrives\n\t\t\t\t\t// (don't wait for aiProcessingCompleted which comes later after auto-title etc.)\n\t\t\t\t\tif (event.item.aiAgentId) {\n\t\t\t\t\t\tstate.setAiProcessing(event.conversationId, false);\n\t\t\t\t\t\tstate.setTyping(event.conversationId, false);\n\t\t\t\t\t}\n\t\t\t\t\t// Update conversation preview + unread count\n\t\t\t\t\tif (event.item.type === \"message\" && event.item.text) {\n\t\t\t\t\t\tconst isIncoming = !event.item.visitorId; // team or AI message\n\t\t\t\t\t\tconst currentState = get();\n\t\t\t\t\t\tconst isViewingThis =\n\t\t\t\t\t\t\tcurrentState.isOpen && currentState.activeConversationId === event.conversationId;\n\n\t\t\t\t\t\tset((s) => ({\n\t\t\t\t\t\t\tconversations: s.conversations.map((c) =>\n\t\t\t\t\t\t\t\tc.id === event.conversationId\n\t\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\t\t...c,\n\t\t\t\t\t\t\t\t\t\t\tlastMessageText: event.item.text,\n\t\t\t\t\t\t\t\t\t\t\tlastMessageAt: event.item.createdAt,\n\t\t\t\t\t\t\t\t\t\t\t// Increment unread if incoming and not actively viewing\n\t\t\t\t\t\t\t\t\t\t\t...(isIncoming && !isViewingThis ? { unreadCount: c.unreadCount + 1 } : {}),\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t: c,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t// Show preview bubble if widget is closed and message is incoming\n\t\t\t\t\t\t\t...(isIncoming && !currentState.isOpen\n\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\tincomingPreview: {\n\t\t\t\t\t\t\t\t\t\t\ttext: event.item.text ?? \"\",\n\t\t\t\t\t\t\t\t\t\t\tconversationId: event.conversationId,\n\t\t\t\t\t\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t}));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase WsEventType.ConversationUpdated: {\n\t\t\t\t\tset((s) => ({\n\t\t\t\t\t\tconversations: s.conversations.map((c) =>\n\t\t\t\t\t\t\tc.id === event.conversationId ? { ...c, ...event.updates } : c,\n\t\t\t\t\t\t),\n\t\t\t\t\t}));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase WsEventType.ConversationTyping: {\n\t\t\t\t\t// Only show typing for non-visitor (team/AI typing)\n\t\t\t\t\tif (!event.visitorId) {\n\t\t\t\t\t\tstate.setTyping(event.conversationId, event.isTyping);\n\t\t\t\t\t\t// Auto-clear after 5 seconds\n\t\t\t\t\t\tif (event.isTyping) {\n\t\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\t\tstate.setTyping(event.conversationId, false);\n\t\t\t\t\t\t\t}, 5000);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase WsEventType.AiProcessingProgress: {\n\t\t\t\t\t// Track AI processing separately for distinct UI indicator\n\t\t\t\t\tstate.setAiProcessing(event.conversationId, true);\n\t\t\t\t\tstate.setTyping(event.conversationId, true);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase WsEventType.AiProcessingCompleted: {\n\t\t\t\t\tstate.setAiProcessing(event.conversationId, false);\n\t\t\t\t\tstate.setTyping(event.conversationId, false);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase WsEventType.AiStreamChunk: {\n\t\t\t\t\tstate.setAiProcessing(event.conversationId, false);\n\t\t\t\t\tstate.setTyping(event.conversationId, false);\n\t\t\t\t\tstate.appendStreamChunk(event.conversationId, event.delta, event.done);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase WsEventType.ConversationCreated: {\n\t\t\t\t\t// Race-safe insert: WS may arrive before OR after the HTTP\n\t\t\t\t\t// createConversation response. If after, remapConversationId\n\t\t\t\t\t// already renamed tempId → realId, so the entry exists.\n\t\t\t\t\t// If before, we prepend here; the later remap call hits the\n\t\t\t\t\t// `hasNewId=true` branch and drops the temp entry.\n\t\t\t\t\tconst conv = event.conversation as unknown as {\n\t\t\t\t\t\tid: string;\n\t\t\t\t\t\ttitle: string | null;\n\t\t\t\t\t\tstatus: string;\n\t\t\t\t\t\tlastMessageText?: string | null;\n\t\t\t\t\t\tlastMessageAt?: string | null;\n\t\t\t\t\t\tlastMessageSenderType?: string | null;\n\t\t\t\t\t};\n\t\t\t\t\tconst alreadyPresent = state.conversations.some((c) => c.id === conv.id);\n\t\t\t\t\tif (alreadyPresent) break;\n\t\t\t\t\tstate.addConversation({\n\t\t\t\t\t\tid: conv.id,\n\t\t\t\t\t\ttitle: conv.title,\n\t\t\t\t\t\tstatus: conv.status,\n\t\t\t\t\t\tlastMessageText: conv.lastMessageText ?? null,\n\t\t\t\t\t\tlastMessageAt: conv.lastMessageAt ?? null,\n\t\t\t\t\t\tlastMessageSenderType: conv.lastMessageSenderType ?? null,\n\t\t\t\t\t\tlastMessageSenderName: null,\n\t\t\t\t\t\tlastMessageSenderImage: null,\n\t\t\t\t\t\tassigneeName: null,\n\t\t\t\t\t\tassigneeImage: null,\n\t\t\t\t\t\tunreadCount: 0,\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t},\n\t}));\n\n\t// Single source of persistence for the proactive preview: every\n\t// transition (WS set, setOpen-clears, dismissPreview) passes through\n\t// here, so we don't have to touch each call site.\n\tif (typeof window !== \"undefined\") {\n\t\tlet last = store.getState().incomingPreview;\n\t\tstore.subscribe((s) => {\n\t\t\tif (s.incomingPreview !== last) {\n\t\t\t\tlast = s.incomingPreview;\n\t\t\t\tpersistPreview(s.incomingPreview);\n\t\t\t}\n\t\t});\n\t}\n\n\treturn store;\n}\n","import type { StoreApi } from \"zustand/vanilla\";\nimport type { Listener, WidgetEventEmitter, WidgetEventName, WidgetEvents } from \"./events\";\nimport type { WidgetStore } from \"./store\";\nimport { clearVisitorId } from \"./visitor-id\";\n\n/**\n * The programmatic widget API — all the methods consumers can call\n * once the widget is mounted. Returned by `createHelpwayAPI()`.\n *\n * The global `window.Helpway` is the *callable* wrapper around this\n * (see `HelpwayAPI` and `installCallable`).\n */\nexport interface HelpwayMethods {\n\t/** Open the widget panel */\n\topen(): void;\n\t/** Close the widget panel */\n\tclose(): void;\n\t/** Toggle the widget panel open/closed */\n\ttoggle(): void;\n\t/** Dismiss the widget entirely (launcher + panel). Use for page-specific hiding. */\n\tdismiss(): void;\n\t/** Show the widget again after dismiss */\n\tshow(): void;\n\t/** Full reset: clear session, cookies, visitor identity */\n\tshutdown(): void;\n\t/** Identify the visitor (link to contact) */\n\tidentify(data: {\n\t\texternalId: string;\n\t\temail?: string;\n\t\tname?: string;\n\t\timage?: string;\n\t\tmetadata?: Record<string, unknown>;\n\t}): Promise<void>;\n\t/** Open a new conversation, optionally pre-filling the message */\n\tnewConversation(prefill?: string): void;\n\t/** Open a specific conversation by ID */\n\topenConversation(id: string): void;\n\t/** Get the current unread count */\n\treadonly unreadCount: number;\n\t/** Whether the widget panel is currently open */\n\treadonly isOpen: boolean;\n\t/** Subscribe to widget events */\n\ton<K extends WidgetEventName>(event: K, fn: Listener<WidgetEvents[K]>): void;\n\t/** Unsubscribe from widget events */\n\toff<K extends WidgetEventName>(event: K, fn: Listener<WidgetEvents[K]>): void;\n}\n\n/**\n * The global `window.Helpway` shape: callable (Intercom-style snippet API)\n * AND object (typed methods). Build one of these from a `HelpwayMethods`\n * via `installCallable()`.\n */\nexport interface HelpwayAPI extends HelpwayMethods {\n\t(command: string, ...args: unknown[]): unknown;\n}\n\n/**\n * Install a callable wrapper around any methods object onto `window.Helpway`,\n * draining any calls that the snippet stub queued before the widget mounted.\n * Returns the callable so callers can compare identities on cleanup.\n *\n * Generic in `T` so both the rich `HelpwayMethods` (from widget-react) and\n * the slimmer script-tag API (from widget-embed) can use the same plumbing.\n */\nexport function installCallable<T extends object>(\n\tmethods: T,\n): T & ((command: string, ...args: unknown[]) => unknown) {\n\tconst dispatch = (command: string, ...args: unknown[]): unknown => {\n\t\tconst fn = (methods as unknown as Record<string, unknown>)[command];\n\t\tif (typeof fn === \"function\") {\n\t\t\treturn (fn as (...a: unknown[]) => unknown)(...args);\n\t\t}\n\t\tconsole.warn(`[Helpway] Unknown command: ${command}`);\n\t\treturn undefined;\n\t};\n\tconst callable = Object.assign(dispatch, methods);\n\tconst previous = window.Helpway as { q?: unknown[][] } | undefined;\n\twindow.Helpway = callable as unknown as HelpwayAPI;\n\tconst queue = previous?.q;\n\tif (queue?.length) {\n\t\tfor (const entry of queue) {\n\t\t\ttry {\n\t\t\t\tdispatch(...(entry as [string, ...unknown[]]));\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"[Helpway] queued call failed:\", err);\n\t\t\t}\n\t\t}\n\t}\n\treturn callable;\n}\n\nexport function createHelpwayAPI(deps: {\n\tstore: StoreApi<WidgetStore>;\n\temitter: WidgetEventEmitter;\n\tidentify: (data: {\n\t\texternalId: string;\n\t\temail?: string;\n\t\tname?: string;\n\t\timage?: string;\n\t\tmetadata?: Record<string, unknown>;\n\t}) => Promise<void>;\n\tapiKey: string;\n}): HelpwayMethods {\n\tconst { store, emitter, identify, apiKey } = deps;\n\n\treturn {\n\t\topen() {\n\t\t\tstore.getState().setOpen(true);\n\t\t\tstore.getState().setDismissed(false);\n\t\t},\n\n\t\tclose() {\n\t\t\tstore.getState().setOpen(false);\n\t\t},\n\n\t\ttoggle() {\n\t\t\tconst s = store.getState();\n\t\t\tif (s.isDismissed) {\n\t\t\t\ts.setDismissed(false);\n\t\t\t\ts.setOpen(true);\n\t\t\t\temitter.emit(\"show\");\n\t\t\t} else {\n\t\t\t\ts.setOpen(!s.isOpen);\n\t\t\t}\n\t\t},\n\n\t\tdismiss() {\n\t\t\tstore.getState().setOpen(false);\n\t\t\tstore.getState().setDismissed(true);\n\t\t\temitter.emit(\"dismiss\");\n\t\t},\n\n\t\tshow() {\n\t\t\tstore.getState().setDismissed(false);\n\t\t\temitter.emit(\"show\");\n\t\t},\n\n\t\tshutdown() {\n\t\t\tstore.getState().setOpen(false);\n\t\t\tstore.getState().setDismissed(false);\n\t\t\tclearVisitorId(apiKey);\n\t\t\tif (typeof document !== \"undefined\") {\n\t\t\t\tdocument.cookie = \"hw_visitor=; Path=/; Max-Age=0\";\n\t\t\t}\n\t\t},\n\n\t\tidentify,\n\n\t\tnewConversation(prefill?: string) {\n\t\t\tconst s = store.getState();\n\t\t\ts.setDismissed(false);\n\t\t\ts.setOpen(true);\n\t\t\ts.setNewConversationPrefill(prefill ?? \"\");\n\t\t},\n\n\t\topenConversation(id: string) {\n\t\t\tconst s = store.getState();\n\t\t\ts.setDismissed(false);\n\t\t\ts.setActiveConversation(id);\n\t\t\ts.setOpen(true);\n\t\t},\n\n\t\tget unreadCount() {\n\t\t\treturn store.getState().conversations.reduce((sum, c) => sum + c.unreadCount, 0);\n\t\t},\n\n\t\tget isOpen() {\n\t\t\treturn store.getState().isOpen;\n\t\t},\n\n\t\ton(event, fn) {\n\t\t\temitter.on(event, fn);\n\t\t},\n\n\t\toff(event, fn) {\n\t\t\temitter.off(event, fn);\n\t\t},\n\t};\n}\n","/**\n * Widget theming — typed surface over the CSS custom properties baked\n * into the default themed widget. Consumers pass a `WidgetTheme` object;\n * `applyTheme` writes the values onto the host element so the cascade\n * picks them up inside the Shadow DOM.\n *\n * Common cases (color, position, radius) get their own first-class\n * fields. Anything else can still be set via `cssVariables` — it's a\n * raw passthrough for custom var names we don't model yet.\n *\n * **Note for SDK consumers:** prefer dashboard-driven theming when you\n * can — changes go live without a redeploy. This API is for runtime-\n * resolved values (multi-tenant, dark/light sync with the host app).\n *\n * @see https://helpway.ai/docs/customization for the full reference,\n * the dashboard config UI, and the multi-tenant example.\n */\n\nexport type WidgetPosition = \"bottom-right\" | \"bottom-left\";\n\nexport interface WidgetTheme {\n\t/** Launcher background + accent color. Hover variant is auto-derived. */\n\tprimaryColor?: string;\n\t/** Text/icon color rendered ON TOP of `primaryColor`. Defaults to white. */\n\tonPrimaryColor?: string;\n\t/** Visitor (outgoing) message bubble background. Defaults to `primaryColor`. */\n\tbubbleColor?: string;\n\t/** Visitor message bubble text color. Defaults to `onPrimaryColor`. */\n\tbubbleTextColor?: string;\n\t/** Widget panel background color. */\n\tbackgroundColor?: string;\n\t/** Widget panel text color. */\n\ttextColor?: string;\n\t/** Border color used inside the panel. */\n\tborderColor?: string;\n\t/** Corner radius for the panel + cards (any valid CSS length). */\n\tradius?: string;\n\t/** Font family stack for everything inside the widget. */\n\tfontFamily?: string;\n\t/** Launcher + panel placement. Defaults to \"bottom-right\". */\n\tposition?: WidgetPosition;\n\t/**\n\t * Escape hatch: any CSS custom property not modeled above. Keys must\n\t * start with `--`. Wins over the typed fields above when both set.\n\t */\n\tcssVariables?: Record<`--${string}`, string>;\n}\n\n/** Validate a hex like `#aabbcc`. We're conservative on purpose. */\nfunction isValidHex(color: string): boolean {\n\treturn /^#[0-9a-fA-F]{6}$/.test(color);\n}\n\n/**\n * Lighten a #rrggbb hex by a fixed amount (used as the hover variant\n * of `primaryColor`). Non-hex inputs return unchanged so callers can\n * pass `oklch(...)`, `hsl(...)`, etc. and bring their own hover.\n */\nfunction lighten(hex: string): string {\n\tif (!isValidHex(hex)) return hex;\n\tconst r = Math.min(255, Number.parseInt(hex.slice(1, 3), 16) + 30);\n\tconst g = Math.min(255, Number.parseInt(hex.slice(3, 5), 16) + 30);\n\tconst b = Math.min(255, Number.parseInt(hex.slice(5, 7), 16) + 30);\n\tconst hex2 = (n: number) => n.toString(16).padStart(2, \"0\");\n\treturn `#${hex2(r)}${hex2(g)}${hex2(b)}`;\n}\n\n/** Map a single typed field onto its CSS variable(s). */\nfunction setVar(host: HTMLElement, name: string, value: string | undefined) {\n\tif (value == null || value === \"\") return;\n\thost.style.setProperty(name, value);\n}\n\n/**\n * Write a `WidgetTheme` onto the host element. Safe to call multiple\n * times — every call is incremental, only the keys you provide are\n * touched. Pass `undefined` for a field to leave the existing value alone;\n * call `clearTheme()` if you want to reset.\n */\nexport function applyTheme(host: HTMLElement, theme: WidgetTheme | undefined) {\n\tif (!host || !theme) return;\n\n\tif (theme.primaryColor) {\n\t\tsetVar(host, \"--hw-primary\", theme.primaryColor);\n\t\tsetVar(host, \"--hw-primary-hover\", lighten(theme.primaryColor));\n\t\tsetVar(host, \"--hw-brand\", theme.primaryColor);\n\t}\n\tsetVar(host, \"--hw-on-brand\", theme.onPrimaryColor);\n\tsetVar(host, \"--hw-visitor-bubble-bg\", theme.bubbleColor ?? theme.primaryColor);\n\tsetVar(host, \"--hw-visitor-bubble-text\", theme.bubbleTextColor ?? theme.onPrimaryColor);\n\tsetVar(host, \"--hw-bg\", theme.backgroundColor);\n\tsetVar(host, \"--hw-text\", theme.textColor);\n\tsetVar(host, \"--hw-border\", theme.borderColor);\n\tsetVar(host, \"--hw-radius\", theme.radius);\n\tsetVar(host, \"--hw-font\", theme.fontFamily);\n\n\tif (theme.position === \"bottom-left\") {\n\t\tsetVar(host, \"--hw-position-right\", \"auto\");\n\t\tsetVar(host, \"--hw-position-left\", \"20px\");\n\t\tsetVar(host, \"--hw-window-right\", \"auto\");\n\t\tsetVar(host, \"--hw-window-left\", \"0\");\n\t} else if (theme.position === \"bottom-right\") {\n\t\thost.style.removeProperty(\"--hw-position-right\");\n\t\thost.style.removeProperty(\"--hw-position-left\");\n\t\thost.style.removeProperty(\"--hw-window-right\");\n\t\thost.style.removeProperty(\"--hw-window-left\");\n\t}\n\n\tif (theme.cssVariables) {\n\t\tfor (const [key, value] of Object.entries(theme.cssVariables)) {\n\t\t\tif (key.startsWith(\"--\")) host.style.setProperty(key, value);\n\t\t}\n\t}\n}\n","export type Listener<T = unknown> = (data: T) => void;\n\nexport interface WidgetEvents {\n\topen: undefined;\n\tclose: undefined;\n\tdismiss: undefined;\n\tshow: undefined;\n\tunreadChange: number;\n\tmessageReceived: { conversationId: string; text: string; senderName: string | null };\n\tready: undefined;\n}\n\nexport type WidgetEventName = keyof WidgetEvents;\n\nexport class WidgetEventEmitter {\n\tprivate listeners = new Map<string, Set<Listener>>();\n\n\ton<K extends WidgetEventName>(event: K, fn: Listener<WidgetEvents[K]>): void {\n\t\tif (!this.listeners.has(event)) this.listeners.set(event, new Set());\n\t\tthis.listeners.get(event)!.add(fn as Listener);\n\t}\n\n\toff<K extends WidgetEventName>(event: K, fn: Listener<WidgetEvents[K]>): void {\n\t\tthis.listeners.get(event)?.delete(fn as Listener);\n\t}\n\n\temit<K extends WidgetEventName>(\n\t\tevent: K,\n\t\t...args: WidgetEvents[K] extends undefined ? [] : [WidgetEvents[K]]\n\t): void {\n\t\tconst data = args[0];\n\t\tthis.listeners.get(event)?.forEach((fn) => {\n\t\t\ttry {\n\t\t\t\tfn(data);\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(`[Helpway] Event handler error (${event}):`, err);\n\t\t\t}\n\t\t});\n\t}\n\n\tremoveAll(): void {\n\t\tthis.listeners.clear();\n\t}\n}\n","/**\n * Widget i18n — lightweight, zero-dependency translation system.\n *\n * Architecture:\n * - English strings bundled as fallback (zero-latency, always works)\n * - Other locales fetched from Better i18n CDN at runtime\n * - Locale detection: data-locale > identify metadata > navigator.language > \"en\"\n * - Simple key-value lookup with t(\"widget.key\") syntax\n *\n * CDN URL: https://cdn.better-i18n.com/helpway/widget/{locale}/translations.json\n */\n\n// ── Bundled English fallback strings ────────────────────────\n\nconst en: Record<string, string> = {\n\t// Navigation & tabs\n\t\"widget.home\": \"Home\",\n\t\"widget.messages\": \"Messages\",\n\t\"widget.help\": \"Help\",\n\n\t// Home screen\n\t\"widget.send_us_message\": \"Send us a message\",\n\t\"widget.reply_time\": \"We typically reply in a few minutes\",\n\t\"widget.recent_conversations\": \"Recent conversations\",\n\t\"widget.see_all\": \"See all conversations\",\n\t\"widget.whats_new\": \"What's New\",\n\t\"widget.view_all\": \"View all\",\n\n\t// Messages tab\n\t\"widget.no_messages\": \"No messages yet\",\n\t\"widget.no_messages_desc\": \"Start a conversation to get help\",\n\t\"widget.start_conversation\": \"Start a conversation\",\n\t\"widget.no_preview\": \"No messages yet\",\n\n\t// Conversation\n\t\"widget.new_conversation\": \"New conversation\",\n\t\"widget.resolved_text\": \"This conversation has been resolved\",\n\t\"widget.send_followup\": \"Send a follow-up\",\n\t\"widget.start_a_conversation\": \"Start a conversation\",\n\n\t// Composer\n\t\"widget.placeholder\": \"Send a message...\",\n\t\"widget.placeholder_new\": \"How can we help?\",\n\t\"widget.drop_files\": \"Drop files here\",\n\n\t// CSAT\n\t\"widget.csat_label\": \"How was your experience?\",\n\t\"widget.csat_thanks\": \"Thanks for your feedback!\",\n\n\t// Inline email collection (after AI reply)\n\t\"widget.email_title\": \"Don't miss our reply\",\n\t\"widget.email_subtitle\": \"We'll email you when we respond\",\n\t\"widget.email_placeholder\": \"you@email.com\",\n\t\"widget.email_continue\": \"Send\",\n\t\"widget.email_saved\": \"You'll be notified by email\",\n\t\"widget.email_dismiss\": \"No thanks\",\n\n\t// Errors\n\t\"widget.error_title\": \"Something went wrong\",\n\t\"widget.error_desc\": \"Failed to load. Please try again.\",\n\t\"widget.retry\": \"Retry\",\n\t\"widget.reconnecting\": \"Reconnecting...\",\n\t\"widget.send_error\": \"Message not sent\",\n\n\t// Date separators (today is implicit — never rendered)\n\t\"widget.yesterday\": \"Yesterday\",\n\n\t// Sender labels\n\t\"widget.helpway_ai\": \"Helpway AI\",\n\t\"widget.support\": \"Support\",\n\n\t// Events\n\t\"widget.joined\": \"joined the conversation\",\n\t\"widget.left\": \"left the conversation\",\n\n\t// Content/search\n\t\"widget.content\": \"Content\",\n\t\"widget.search\": \"Search...\",\n\t\"widget.no_results\": \"No results found\",\n\t\"widget.try_different\": \"Try a different search term\",\n\t\"widget.nothing_yet\": \"Nothing here yet\",\n\t\"widget.check_back\": \"Check back later for updates\",\n\t\"widget.load_more\": \"Load more\",\n\t\"widget.loading\": \"Loading...\",\n\n\t// Copy\n\t\"widget.copy\": \"Copy message\",\n\t\"widget.copied\": \"Copied\",\n\n\t// File upload\n\t\"widget.file_too_large\": \"File too large (max 10 MB)\",\n\t\"widget.click_to_open\": \"Click to open\",\n\t\"widget.caption_required\": \"Add a message to send with your attachment\",\n\n\t// Accessibility\n\t\"widget.aria_chat\": \"Support chat\",\n\t\"widget.aria_close\": \"Close\",\n\t\"widget.aria_back\": \"Back\",\n\t\"widget.aria_send\": \"Send message\",\n\t\"widget.aria_attach\": \"Attach file\",\n\t\"widget.aria_input\": \"Message input\",\n\t\"widget.aria_remove\": \"Remove\",\n\t\"widget.aria_dismiss\": \"Dismiss\",\n\t\"widget.aria_open\": \"Open support\",\n\t\"widget.aria_close_support\": \"Close support\",\n\t\"widget.aria_good\": \"Good\",\n\t\"widget.aria_bad\": \"Bad\",\n\t\"widget.aria_messages\": \"Messages\",\n\n\t// Time (relative)\n\t\"widget.time_now\": \"now\",\n\t\"widget.time_yesterday\": \"Yesterday\",\n\n\t// Powered by\n\t\"widget.powered_by\": \"Powered by\",\n\n\t// Hero / home screen\n\t\"widget.welcome_message\": \"Hi there 👋\\nHow can we help?\",\n\t\"widget.subtitle_text\": \"Usually replies in minutes\",\n};\n\n// ── State ───────────────────────────────────────────────────\n\nlet currentLocale = \"en\";\nlet translations: Record<string, string> = {};\nlet isLoaded = false;\nlet revision = 0; // Incremented on every translation change — React hook watches this\nconst listeners: Array<() => void> = [];\n\n// ── Public API ──────────────────────────────────────────────\n\n/**\n * Translate a key. Falls back to English bundled string, then to the key itself.\n *\n * Supports simple interpolation: t(\"widget.key\", { name: \"John\" })\n * Template: \"Hello {{name}}\" → \"Hello John\"\n */\nexport function t(key: string, params?: Record<string, string | number>): string {\n\tconst value = translations[key] ?? en[key] ?? key;\n\n\tif (!params) return value;\n\n\treturn value.replace(/\\{\\{(\\w+)\\}\\}/g, (_, k: string) => {\n\t\treturn params[k]?.toString() ?? `{{${k}}}`;\n\t});\n}\n\n/** Get the current locale code */\nexport function getLocale(): string {\n\treturn currentLocale;\n}\n\n/** Get current revision number — changes when translations are loaded/updated */\nexport function getI18nRevision(): number {\n\treturn revision;\n}\n\n/** Check if translations have been loaded */\nexport function isI18nReady(): boolean {\n\treturn isLoaded;\n}\n\n/** Subscribe to locale/translation changes. Returns unsubscribe fn. */\nexport function onLocaleChange(fn: () => void): () => void {\n\tlisteners.push(fn);\n\treturn () => {\n\t\tconst idx = listeners.indexOf(fn);\n\t\tif (idx >= 0) listeners.splice(idx, 1);\n\t};\n}\n\n// ── Initialization ──────────────────────────────────────────\n\n/**\n * Detect locale from available signals and fetch translations.\n *\n * Priority:\n * 1. Explicit `locale` param (from data-locale attribute)\n * 2. navigator.language (browser preference)\n * 3. \"en\" fallback\n */\nexport async function initI18n(options?: { locale?: string; cdnBase?: string }): Promise<void> {\n\tif (options?.cdnBase) {\n\t\tcdnBase = options.cdnBase;\n\t}\n\n\tconst detected =\n\t\toptions?.locale ?? (typeof navigator !== \"undefined\" ? navigator.language : \"en\");\n\n\t// Normalize: \"fr-FR\" → \"fr\", \"pt-BR\" → \"pt-BR\" (keep regional if meaningful)\n\tcurrentLocale = normalizeLocale(detected);\n\n\t// English is bundled — no fetch needed\n\tif (currentLocale === \"en\") {\n\t\tisLoaded = true;\n\t\tnotify();\n\t\treturn;\n\t}\n\n\t// Fetch from CDN\n\ttry {\n\t\tconst data = await fetchTranslations(currentLocale);\n\t\tif (data) {\n\t\t\t// Only pick widget.* keys from the full namespace bundle\n\t\t\tfor (const [key, value] of Object.entries(data)) {\n\t\t\t\tif (typeof value === \"string\") {\n\t\t\t\t\ttranslations[`widget.${key}`] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch (err) {\n\t\tconsole.warn(`[Helpway] Failed to fetch ${currentLocale} translations, using English`, err);\n\t}\n\n\tisLoaded = true;\n\tnotify();\n}\n\n/**\n * Update locale at runtime (e.g., after identify() provides metadata.locale).\n * Re-fetches translations if locale changed.\n */\nexport async function setLocale(locale: string): Promise<void> {\n\tconst normalized = normalizeLocale(locale);\n\tif (normalized === currentLocale) return;\n\n\tcurrentLocale = normalized;\n\ttranslations = {}; // Clear old translations\n\n\tif (normalized === \"en\") {\n\t\tnotify();\n\t\treturn;\n\t}\n\n\ttry {\n\t\tconst data = await fetchTranslations(normalized);\n\t\tif (data) {\n\t\t\tfor (const [key, value] of Object.entries(data)) {\n\t\t\t\tif (typeof value === \"string\") {\n\t\t\t\t\ttranslations[`widget.${key}`] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Silent fallback to English\n\t}\n\n\tnotify();\n}\n\n// ── Internals ───────────────────────────────────────────────\n\nlet cdnBase = \"https://cdn.better-i18n.com/helpway/widget\";\n\nasync function fetchTranslations(locale: string): Promise<Record<string, string> | null> {\n\t// All namespaces live in a single translations.json — widget keys nested under \"widget\" key\n\tconst url = `${cdnBase}/${locale}/translations.json`;\n\n\tlet res = await fetch(url);\n\tif (!res.ok && locale.includes(\"-\")) {\n\t\t// Try base locale: \"pt-BR\" → \"pt\"\n\t\tconst base = locale.split(\"-\")[0];\n\t\tres = await fetch(`${cdnBase}/${base}/translations.json`);\n\t}\n\tif (!res.ok) return null;\n\n\tconst data: Record<string, unknown> = await res.json();\n\t// CDN structure is nested: { \"widget\": { \"home\": \"Ana Sayfa\", ... }, \"sidebar\": {...} }\n\tconst widgetNs = data.widget;\n\tif (widgetNs && typeof widgetNs === \"object\" && !Array.isArray(widgetNs)) {\n\t\tconst result: Record<string, string> = {};\n\t\tfor (const [k, v] of Object.entries(widgetNs)) {\n\t\t\tif (typeof v === \"string\") result[k] = v;\n\t\t}\n\t\treturn result;\n\t}\n\treturn null;\n}\n\nfunction normalizeLocale(input: string): string {\n\t// Keep regional variants that are commonly distinct: pt-BR, zh-CN, zh-TW\n\tconst regional = [\"pt-br\", \"zh-cn\", \"zh-tw\", \"zh-hk\"];\n\tconst lower = input.toLowerCase().replace(\"_\", \"-\");\n\n\tfor (const r of regional) {\n\t\tif (lower.startsWith(r)) return r;\n\t}\n\n\t// Otherwise just use base: \"fr-FR\" → \"fr\"\n\treturn lower.split(\"-\")[0] ?? \"en\";\n}\n\nfunction notify(): void {\n\trevision++;\n\tfor (const fn of listeners) {\n\t\ttry {\n\t\t\tfn();\n\t\t} catch {\n\t\t\t/* ignore */\n\t\t}\n\t}\n}\n","import { t, getLocale } from \"./i18n\";\n\n/**\n * Format a date as relative time string.\n * Uses i18n for \"now\" and \"Yesterday\". Locale-aware date formatting.\n */\nexport function formatRelativeTime(date: string | Date): string {\n\tconst now = Date.now();\n\tconst then = typeof date === \"string\" ? new Date(date).getTime() : date.getTime();\n\tconst diffMs = now - then;\n\tconst diffMin = Math.floor(diffMs / 60000);\n\tconst diffHour = Math.floor(diffMs / 3600000);\n\tconst diffDay = Math.floor(diffMs / 86400000);\n\n\tif (diffMin < 1) return t(\"widget.time_now\");\n\tif (diffMin < 60) return `${diffMin}m`;\n\tif (diffHour < 24) return `${diffHour}h`;\n\tif (diffDay === 1) return t(\"widget.time_yesterday\");\n\tif (diffDay < 7) return `${diffDay}d`;\n\n\tconst d = typeof date === \"string\" ? new Date(date) : date;\n\treturn d.toLocaleDateString(getLocale(), { month: \"short\", day: \"numeric\" });\n}\n\n/**\n * Format time for message bubbles (HH:MM).\n */\nexport function formatTime(date: string | Date): string {\n\tconst d = typeof date === \"string\" ? new Date(date) : date;\n\treturn d.toLocaleTimeString(undefined, { hour: \"2-digit\", minute: \"2-digit\" });\n}\n\n/**\n * Resolve a label that may be a translation key (\"widget.*\") or plain text.\n * When the key resolves to itself (missing), falls back to a humanized form\n * so the UI never leaks raw \"widget.changelog\" strings to the visitor.\n */\nexport function resolveLabel(label: string): string {\n\tif (!label.startsWith(\"widget.\")) return label;\n\tconst resolved = t(label);\n\tif (resolved === label) {\n\t\treturn label\n\t\t\t.replace(\"widget.\", \"\")\n\t\t\t.replace(/_/g, \" \")\n\t\t\t.replace(/^\\w/, (c) => c.toUpperCase());\n\t}\n\treturn resolved;\n}\n\n/**\n * Get initials from a name or email.\n */\nexport function getInitials(value: string): string {\n\tif (!value) return \"?\";\n\n\t// Email: take first letter\n\tif (value.includes(\"@\")) return (value[0] ?? \"?\").toUpperCase();\n\n\t// Name: take first letter of first two words\n\tconst parts = value.trim().split(/\\s+/);\n\tif (parts.length >= 2) {\n\t\treturn ((parts[0]?.[0] ?? \"\") + (parts[1]?.[0] ?? \"\")).toUpperCase();\n\t}\n\treturn (parts[0]?.[0] ?? \"?\").toUpperCase();\n}\n","\"use client\";\n\nimport {\n\tWebSocketManager,\n\tWidgetEventEmitter,\n\ttype HelpwayMethods,\n\ttype WidgetClient,\n\ttype WidgetStore,\n\ttype WidgetTheme,\n\tapplyTheme,\n\tcreateHelpwayAPI,\n\tcreateWidgetClient,\n\tcreateWidgetStore,\n\tinitI18n,\n\tinstallCallable,\n\tsetLocale,\n\tsyncVisitorId,\n} from \"@helpway/widget-core\";\nimport {\n\ttype ReactNode,\n\tcreateContext,\n\tuseCallback,\n\tuseContext,\n\tuseEffect,\n\tuseRef,\n\tuseState,\n} from \"react\";\nimport { type StoreApi, useStore } from \"zustand\";\n\n// ── Context ──────────────────────────────────────────────\n\nexport interface IdentifyData {\n\texternalId: string;\n\temail?: string;\n\tname?: string;\n\timage?: string;\n\tmetadata?: Record<string, unknown>;\n}\n\ninterface WidgetContextValue {\n\tclient: WidgetClient;\n\tstore: StoreApi<WidgetStore>;\n\tws: WebSocketManager;\n\tidentify: (data: IdentifyData) => Promise<void>;\n\tapi: HelpwayMethods;\n\temitter: WidgetEventEmitter;\n\thasBootstrapError: boolean;\n\twsDisconnected: boolean;\n\tretryBootstrap: () => void;\n}\n\nconst WidgetContext = createContext<WidgetContextValue | null>(null);\n\nexport function useWidgetContext(): WidgetContextValue {\n\tconst ctx = useContext(WidgetContext);\n\tif (!ctx) {\n\t\tthrow new Error(\"useWidgetContext must be used within <SupportProvider>\");\n\t}\n\treturn ctx;\n}\n\n/** Use a slice of the widget store with auto re-render */\nexport function useWidgetStore<T>(selector: (state: WidgetStore) => T): T {\n\tconst { store } = useWidgetContext();\n\treturn useStore(store, selector);\n}\n\n/** Hook to identify the current visitor (link to customer contact) */\nexport function useIdentify() {\n\tconst { identify } = useWidgetContext();\n\treturn identify;\n}\n\n/** Raw tRPC client — used by interactive components that need to call\n * mutations not exposed via the public HelpwayMethods (e.g. workflow\n * quick-reply taps). The client is `any`-typed by design (see\n * packages/widget-core/src/client.ts) so callers must spell mutation\n * paths explicitly. */\nexport function useWidgetClient(): WidgetClient {\n\tconst { client } = useWidgetContext();\n\treturn client;\n}\n\n// ── Provider ─────────────────────────────────────────────\n\ninterface SupportProviderProps {\n\tapiKey: string;\n\tapiUrl?: string;\n\tlocale?: string;\n\tinitialConversationId?: string;\n\tdeepLinkToken?: string;\n\tonReady?: (api: HelpwayMethods) => void;\n\tcustomLauncherSelector?: string;\n\tonOpen?: () => void;\n\tonClose?: () => void;\n\tonUnreadChange?: (count: number) => void;\n\t/**\n\t * Developer-side theme override. Most consumers should configure\n\t * appearance in the Helpway dashboard (see\n\t * https://helpway.ai/docs/customization) so changes apply without\n\t * a redeploy. Use this prop only when you need the widget to inherit\n\t * a host-app theme that the dashboard can't see (e.g. a tenant-\n\t * specific brand color resolved at runtime). Values here are written\n\t * as CSS custom properties on the widget host and override the\n\t * dashboard config for this mount only.\n\t */\n\ttheme?: WidgetTheme;\n\tchildren: ReactNode;\n}\n\n/**\n * Root provider for the Helpway widget.\n * Creates tRPC client, WebSocket connection, and state store.\n *\n * Visitor identity is managed via server-side cookies (hw_visitor).\n * No localStorage or client-side ID management needed.\n */\nexport function SupportProvider({\n\tapiKey,\n\tapiUrl,\n\tlocale,\n\tinitialConversationId,\n\tdeepLinkToken,\n\tonReady,\n\tcustomLauncherSelector,\n\tonOpen,\n\tonClose,\n\tonUnreadChange,\n\ttheme,\n\tchildren,\n}: SupportProviderProps) {\n\tconst initRef = useRef<{\n\t\tclient: WidgetClient;\n\t\tstore: StoreApi<WidgetStore>;\n\t\tws: WebSocketManager;\n\t\tidentify: (data: IdentifyData) => Promise<void>;\n\t\tapi: HelpwayMethods;\n\t\temitter: WidgetEventEmitter;\n\t} | null>(null);\n\tconst [hasBootstrapError, setHasBootstrapError] = useState(false);\n\tconst [wsDisconnected, setWsDisconnected] = useState(false);\n\tconst [bootstrapAttempt, setBootstrapAttempt] = useState(0);\n\n\tif (!initRef.current) {\n\t\tconst resolvedApiUrl = apiUrl ?? inferApiUrl();\n\n\t\tconst client = createWidgetClient({\n\t\t\tapiUrl: resolvedApiUrl,\n\t\t\tapiKey,\n\t\t});\n\n\t\tconst store = createWidgetStore();\n\t\tconst emitter = new WidgetEventEmitter();\n\n\t\tconst ws = new WebSocketManager({\n\t\t\tapiUrl: resolvedApiUrl,\n\t\t\tvisitorId: \"\",\n\t\t\twebsiteId: \"\",\n\t\t});\n\n\t\tconst identify = async (data: IdentifyData) => {\n\t\t\ttry {\n\t\t\t\tconst result = await client.widget.identify.mutate(data);\n\t\t\t\tif (result.contact) {\n\t\t\t\t\tstore.getState().updateVisitorContact({\n\t\t\t\t\t\tid: result.contact.id,\n\t\t\t\t\t\tname: result.contact.name ?? null,\n\t\t\t\t\t\temail: result.contact.email ?? null,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst metaLocale = data.metadata?.locale;\n\t\t\t\tif (typeof metaLocale === \"string\" && metaLocale.length > 0) {\n\t\t\t\t\tsetLocale(metaLocale);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"[Helpway] identify failed:\", err);\n\t\t\t}\n\t\t};\n\n\t\tconst api = createHelpwayAPI({ store, emitter, identify, apiKey });\n\n\t\tinitRef.current = { client, store, ws, identify, api, emitter };\n\t}\n\n\tconst { client, store, ws, identify, api, emitter } = initRef.current;\n\n\tconst retryBootstrap = useCallback(() => {\n\t\tsetHasBootstrapError(false);\n\t\tsetBootstrapAttempt((n) => n + 1);\n\t}, []);\n\n\t// Bootstrap on mount (re-runs on retry)\n\tuseEffect(() => {\n\t\tlet cancelled = false;\n\n\t\tasync function bootstrap() {\n\t\t\ttry {\n\t\t\t\tconst data = await client.widget.bootstrap.query();\n\t\t\t\tif (cancelled) return;\n\n\t\t\t\t// Initialize i18n BEFORE setReady to avoid flash of English text.\n\t\t\t\t// Priority: explicit `locale` prop → server-side detection\n\t\t\t\t// (Accept-Language + CF-IPCountry) → widget-core bundled default.\n\t\t\t\tconst resolvedLocale =\n\t\t\t\t\tlocale ?? (data as { detectedLocale?: string | null }).detectedLocale ?? undefined;\n\t\t\t\tawait initI18n({\n\t\t\t\t\tlocale: resolvedLocale,\n\t\t\t\t\tcdnBase: (data.agentConfig as { i18nCdnBase?: string } | null)?.i18nCdnBase ?? undefined,\n\t\t\t\t});\n\n\t\t\t\tstore.getState().setReady(data.visitor, data.website, data.agentConfig);\n\t\t\t\tsetHasBootstrapError(false);\n\n\t\t\t\t// Sync server-assigned visitor ID to localStorage\n\t\t\t\t// Ensures client uses canonical ID on subsequent page loads\n\t\t\t\tif (data.visitor?.id) {\n\t\t\t\t\tsyncVisitorId(apiKey, data.visitor.id);\n\t\t\t\t}\n\n\t\t\t\tconst convData = await client.widget.listConversations.query();\n\t\t\t\tif (cancelled) return;\n\n\t\t\t\tconst mapConversation = (c: {\n\t\t\t\t\tid: string;\n\t\t\t\t\ttitle: string | null;\n\t\t\t\t\tstatus: string;\n\t\t\t\t\tlastMessageText: string | null;\n\t\t\t\t\tlastMessageAt: string | null;\n\t\t\t\t\tlastMessageSenderType: string | null;\n\t\t\t\t\tlastMessageSenderName: string | null;\n\t\t\t\t\tlastMessageSenderImage: string | null;\n\t\t\t\t}) => ({\n\t\t\t\t\tid: c.id,\n\t\t\t\t\ttitle: c.title,\n\t\t\t\t\tstatus: c.status,\n\t\t\t\t\tlastMessageText: c.lastMessageText,\n\t\t\t\t\tlastMessageAt: c.lastMessageAt,\n\t\t\t\t\tlastMessageSenderType: c.lastMessageSenderType,\n\t\t\t\t\tlastMessageSenderName: c.lastMessageSenderName,\n\t\t\t\t\tlastMessageSenderImage: c.lastMessageSenderImage,\n\t\t\t\t\tunreadCount: 0,\n\t\t\t\t});\n\n\t\t\t\tstore.getState().setConversations(\n\t\t\t\t\tconvData.conversations.map(mapConversation),\n\t\t\t\t);\n\n\t\t\t\t// Connect WebSocket BEFORE the proactive check so the visitor-channel\n\t\t\t\t// subscription is live by the time the workflow orchestrator emits\n\t\t\t\t// timelineItemCreated. Without this, the greeting message is broadcast\n\t\t\t\t// to a not-yet-subscribed client and the launcher preview bubble never\n\t\t\t\t// appears (only the unread badge increments via REST).\n\t\t\t\tif (data.website?.id && data.visitor?.id) {\n\t\t\t\t\tws.configure({ websiteId: data.website.id, visitorId: data.visitor.id });\n\t\t\t\t\tws.connect();\n\t\t\t\t}\n\n\t\t\t\tif (convData.conversations.length === 0 && !initialConversationId) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst proactive = await client.widget.proactiveCheck.mutate();\n\t\t\t\t\t\tif (cancelled || !proactive.triggered) {\n\t\t\t\t\t\t\t// nothing to do\n\t\t\t\t\t\t} else if (proactive.ephemeral) {\n\t\t\t\t\t\t\t// Render the greeting + (optional) quick replies entirely\n\t\t\t\t\t\t\t// client-side. No server-side conversation exists yet — we\n\t\t\t\t\t\t\t// materialize on the visitor's first reply.\n\t\t\t\t\t\t\thandleEphemeralProactive(store, proactive.ephemeral);\n\t\t\t\t\t\t} else if (proactive.conversationId) {\n\t\t\t\t\t\t\t// Fallback path for complex workflows that needed the\n\t\t\t\t\t\t\t// orchestrator up-front (delays, AI agent before any\n\t\t\t\t\t\t\t// visitor input, etc).\n\t\t\t\t\t\t\tconst nowIso = new Date().toISOString();\n\t\t\t\t\t\t\tstore.getState().addConversation({\n\t\t\t\t\t\t\t\tid: proactive.conversationId,\n\t\t\t\t\t\t\t\ttitle: null,\n\t\t\t\t\t\t\t\tstatus: \"open\",\n\t\t\t\t\t\t\t\tlastMessageText: proactive.lastMessageText ?? null,\n\t\t\t\t\t\t\t\tlastMessageAt: proactive.lastMessageAt ?? nowIso,\n\t\t\t\t\t\t\t\tlastMessageSenderType: proactive.lastMessageSenderType ?? null,\n\t\t\t\t\t\t\t\tlastMessageSenderName: null,\n\t\t\t\t\t\t\t\tlastMessageSenderImage: null,\n\t\t\t\t\t\t\t\tassigneeName: null,\n\t\t\t\t\t\t\t\tassigneeImage: null,\n\t\t\t\t\t\t\t\tunreadCount: 1,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (proactive.lastMessageText && !store.getState().isOpen) {\n\t\t\t\t\t\t\t\tstore.setState({\n\t\t\t\t\t\t\t\t\tincomingPreview: {\n\t\t\t\t\t\t\t\t\t\ttext: proactive.lastMessageText,\n\t\t\t\t\t\t\t\t\t\tconversationId: proactive.conversationId,\n\t\t\t\t\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// proactive check is best-effort\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (typeof window !== \"undefined\") {\n\t\t\t\t\tclient.widget.updatePage\n\t\t\t\t\t\t.mutate({\n\t\t\t\t\t\t\turl: window.location.href,\n\t\t\t\t\t\t\ttitle: document.title || window.location.pathname,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.catch(() => {});\n\t\t\t\t}\n\n\t\t\t\tif (initialConversationId && !cancelled) {\n\t\t\t\t\tif (deepLinkToken) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst redeemed = await client.widget.redeemDeepLink.mutate({ token: deepLinkToken });\n\t\t\t\t\t\t\tif (!cancelled && redeemed?.visitorId && redeemed.visitorId !== data.visitor?.id) {\n\t\t\t\t\t\t\t\tsyncVisitorId(apiKey, redeemed.visitorId);\n\t\t\t\t\t\t\t\tconst freshData = await client.widget.bootstrap.query();\n\t\t\t\t\t\t\t\tif (!cancelled) {\n\t\t\t\t\t\t\t\t\tstore.getState().setReady(freshData.visitor, freshData.website, freshData.agentConfig);\n\t\t\t\t\t\t\t\t\tconst freshConvs = await client.widget.listConversations.query();\n\t\t\t\t\t\t\t\t\tif (!cancelled) {\n\t\t\t\t\t\t\t\t\t\tstore.getState().setConversations(\n\t\t\t\t\t\t\t\t\t\t\tfreshConvs.conversations.map(mapConversation),\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// Token invalid/expired — still open widget but without identity restoration\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!cancelled) {\n\t\t\t\t\t\tstore.getState().setActiveConversation(initialConversationId);\n\t\t\t\t\t\tstore.getState().setOpen(true);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\temitter.emit(\"ready\");\n\t\t\t\tonReady?.(initRef.current!.api);\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"[Helpway] Bootstrap failed:\", err);\n\t\t\t\tif (!cancelled) {\n\t\t\t\t\tstore.getState().setConnecting(false);\n\t\t\t\t\tsetHasBootstrapError(true);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tbootstrap();\n\n\t\t// SPA route tracking — patches pushState/replaceState + listens for\n\t\t// popstate so updatePage fires whenever the visitor navigates without\n\t\t// a full reload. Server stores last 20 page views in visitor.pageHistory\n\t\t// for support agent context.\n\t\tlet pageDebounce: ReturnType<typeof setTimeout> | null = null;\n\t\tconst reportPage = () => {\n\t\t\tif (typeof window === \"undefined\") return;\n\t\t\tif (pageDebounce) clearTimeout(pageDebounce);\n\t\t\tpageDebounce = setTimeout(() => {\n\t\t\t\tclient.widget.updatePage\n\t\t\t\t\t.mutate({\n\t\t\t\t\t\turl: window.location.href,\n\t\t\t\t\t\ttitle: document.title || window.location.pathname,\n\t\t\t\t\t})\n\t\t\t\t\t.catch(() => {});\n\t\t\t}, 250);\n\t\t};\n\n\t\tconst origPush = window.history.pushState.bind(window.history);\n\t\tconst origReplace = window.history.replaceState.bind(window.history);\n\t\twindow.history.pushState = function patchedPush(...args) {\n\t\t\torigPush(...args);\n\t\t\treportPage();\n\t\t};\n\t\twindow.history.replaceState = function patchedReplace(...args) {\n\t\t\torigReplace(...args);\n\t\t\treportPage();\n\t\t};\n\t\twindow.addEventListener(\"popstate\", reportPage);\n\n\t\t// Debounced markSeen — coalesces rapid events (AI may stream multiple\n\t\t// messages, plus the typing/processing events fire too).\n\t\tlet markSeenTimer: ReturnType<typeof setTimeout> | null = null;\n\t\tconst scheduleMarkSeen = (conversationId: string) => {\n\t\t\tif (markSeenTimer) clearTimeout(markSeenTimer);\n\t\t\tmarkSeenTimer = setTimeout(() => {\n\t\t\t\tclient.widget.markSeen.mutate({ conversationId }).catch(() => {});\n\t\t\t\tstore.getState().clearUnread(conversationId);\n\t\t\t}, 400);\n\t\t};\n\n\t\tconst unsub = ws.onEvent((event) => {\n\t\t\tstore.getState().handleRealtimeEvent(event);\n\n\t\t\tif (event.type === \"timelineItemCreated\") {\n\t\t\t\tconst item = event.item;\n\t\t\t\tconst isPublicIncoming = item?.visibility === \"public\" && !item.visitorId;\n\n\t\t\t\t// Emit messageReceived for public incoming messages\n\t\t\t\tif (isPublicIncoming && item?.text) {\n\t\t\t\t\temitter.emit(\"messageReceived\", {\n\t\t\t\t\t\tconversationId: event.conversationId,\n\t\t\t\t\t\ttext: item.text,\n\t\t\t\t\t\tsenderName: \"aiAgentId\" in item && item.aiAgentId ? \"AI\" : null,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif (!isPublicIncoming) return;\n\t\t\t\tconst s = store.getState();\n\t\t\t\tconst isViewing = s.isOpen && s.activeConversationId === event.conversationId;\n\t\t\t\tif (isViewing) scheduleMarkSeen(event.conversationId);\n\t\t\t}\n\t\t});\n\n\t\t// Monitor WebSocket connection state\n\t\tconst wsCheck = setInterval(() => {\n\t\t\tsetWsDisconnected(!ws.isConnected);\n\t\t}, 3000);\n\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t\tunsub();\n\t\t\tclearInterval(wsCheck);\n\t\t\tif (markSeenTimer) clearTimeout(markSeenTimer);\n\t\t\tif (pageDebounce) clearTimeout(pageDebounce);\n\t\t\twindow.history.pushState = origPush;\n\t\t\twindow.history.replaceState = origReplace;\n\t\t\twindow.removeEventListener(\"popstate\", reportPage);\n\t\t\tws.disconnect();\n\t\t};\n\t}, [client, store, ws, bootstrapAttempt]);\n\n\t// Re-initialize translations when locale prop changes after bootstrap\n\tuseEffect(() => {\n\t\tif (locale != null) {\n\t\t\tsetLocale(locale);\n\t\t}\n\t}, [locale]);\n\n\t// Wire up event callbacks: emit open/close events\n\tuseEffect(() => {\n\t\tconst unsub = store.subscribe((state, prev) => {\n\t\t\tif (state.isOpen && !prev.isOpen) {\n\t\t\t\temitter.emit(\"open\");\n\t\t\t\tonOpen?.();\n\t\t\t}\n\t\t\tif (!state.isOpen && prev.isOpen) {\n\t\t\t\temitter.emit(\"close\");\n\t\t\t\tonClose?.();\n\t\t\t}\n\t\t\tconst prevUnread = prev.conversations.reduce((s, c) => s + c.unreadCount, 0);\n\t\t\tconst nextUnread = state.conversations.reduce((s, c) => s + c.unreadCount, 0);\n\t\t\tif (nextUnread !== prevUnread) {\n\t\t\t\temitter.emit(\"unreadChange\", nextUnread);\n\t\t\t\tonUnreadChange?.(nextUnread);\n\t\t\t}\n\t\t});\n\t\treturn unsub;\n\t}, [store, emitter, onOpen, onClose, onUnreadChange]);\n\n\t// Custom launcher selector: attach click handler with MutationObserver fallback for SPAs\n\tuseEffect(() => {\n\t\tif (!customLauncherSelector) return;\n\t\tconst handler = (e: Event) => {\n\t\t\te.preventDefault();\n\t\t\tapi.toggle();\n\t\t};\n\n\t\tconst attach = () => {\n\t\t\tconst el = document.querySelector(customLauncherSelector);\n\t\t\tif (el) {\n\t\t\t\tel.addEventListener(\"click\", handler);\n\t\t\t\treturn el;\n\t\t\t}\n\t\t\treturn null;\n\t\t};\n\n\t\tlet el = attach();\n\t\tlet observer: MutationObserver | null = null;\n\n\t\tif (!el) {\n\t\t\tobserver = new MutationObserver(() => {\n\t\t\t\tel = attach();\n\t\t\t\tif (el) observer?.disconnect();\n\t\t\t});\n\t\t\tobserver.observe(document.body, { childList: true, subtree: true });\n\t\t}\n\n\t\treturn () => {\n\t\t\tel?.removeEventListener(\"click\", handler);\n\t\t\tobserver?.disconnect();\n\t\t};\n\t}, [customLauncherSelector, api]);\n\n\t// Sync window.Helpway with the current api instance on mount,\n\t// restore on unmount. Must live in an effect (not the init block)\n\t// so React StrictMode's double mount/unmount cycle doesn't leave\n\t// the global undefined: the effect re-runs on each mount and\n\t// re-installs the callable, while the init block only fires once\n\t// because initRef.current is preserved across remounts.\n\t//\n\t// IMPORTANT: window.Helpway is exposed as a CALLABLE function (Intercom-style)\n\t// so that `Helpway(\"identify\", payload)` works alongside `Helpway.identify(payload)`.\n\t// Earlier versions assigned the raw `api` object here, which clobbered the\n\t// callable installed by the widget-embed loader and made the documented\n\t// `Helpway(\"cmd\", ...)` form throw \"is not a function\" downstream.\n\t// Apply developer-side theme overrides. We target the host that the\n\t// widget script created (#helpway-widget) when running under the\n\t// embed loader; otherwise fall back to documentElement so the CSS\n\t// vars cascade into a Light-DOM React mount. See:\n\t// https://helpway.ai/docs/customization\n\tuseEffect(() => {\n\t\tif (!theme || typeof document === \"undefined\") return;\n\t\tconst target =\n\t\t\t(document.getElementById(\"helpway-widget\") as HTMLElement | null) ??\n\t\t\tdocument.documentElement;\n\t\tapplyTheme(target, theme);\n\t}, [theme]);\n\n\tuseEffect(() => {\n\t\tif (typeof window === \"undefined\") return;\n\t\tconst callable = installCallable(api);\n\t\treturn () => {\n\t\t\tif (window.Helpway === callable) {\n\t\t\t\twindow.Helpway = undefined;\n\t\t\t}\n\t\t\temitter.removeAll();\n\t\t};\n\t}, [api, emitter]);\n\n\tconst ctxValue: WidgetContextValue = {\n\t\tclient,\n\t\tstore,\n\t\tws,\n\t\tidentify,\n\t\tapi,\n\t\temitter,\n\t\thasBootstrapError,\n\t\twsDisconnected,\n\t\tretryBootstrap,\n\t};\n\n\treturn <WidgetContext.Provider value={ctxValue}>{children}</WidgetContext.Provider>;\n}\n\n// ── Helpers ──────────────────────────────────────────────\n\n/**\n * Resolve the API origin when the consumer doesn't pass `apiUrl` explicitly.\n *\n * Order of precedence:\n * 1. CDN script-tag origin — when the widget loads via\n * `<script src=\"https://cdn.helpway.ai/widget.js\" data-key=\"...\">` we\n * derive the origin from the script's URL so the bootstrap call hits\n * the API that owns the public key.\n * 2. Production default — `https://api.helpway.ai`. Matches the JSDoc\n * contract on the `apiUrl` prop.\n *\n * Earlier versions fell back to `window.location.origin` after the script\n * lookup, which broke any framework integration without the script tag\n * (Next App Router, Vite SPA, etc.) — bootstrap hit the consumer's own\n * server and 404'd. The `https://api.helpway.ai` fallback removes that\n * footgun.\n */\n/**\n * Synthetic conversation id prefix used for ephemeral proactive workflows.\n * The send-message flow checks for this prefix and routes to\n * `materializeFromProactive` instead of `sendMessage`/`createConversation`,\n * which is the moment we actually persist the conversation.\n */\nexport const EPHEMERAL_CONV_PREFIX = \"eph-\";\n\ninterface EphemeralProactivePayload {\n\tworkflowId: string;\n\tpathId: string;\n\tmessages: Array<{ stepId: string; text: string; sender: \"ai\" }>;\n\tquickReplies?: {\n\t\tstepId: string;\n\t\tprompt: string;\n\t\toptions: Array<{ id: string; label: string; goToPathId: string }>;\n\t};\n}\n\nfunction handleEphemeralProactive(\n\tstore: StoreApi<WidgetStore>,\n\tpayload: EphemeralProactivePayload,\n) {\n\tconst synthId = `${EPHEMERAL_CONV_PREFIX}${payload.workflowId}`;\n\tconst now = Date.now();\n\tconst lastMessage = payload.messages[payload.messages.length - 1];\n\tconst previewText = lastMessage?.text ?? \"\";\n\n\t// Inject the greeting (and quick replies) as if they came from the\n\t// server. Stagger timestamps so order is preserved if the visitor\n\t// scrolls through them later.\n\tconst items = payload.messages.map((m, i) => ({\n\t\tid: `${synthId}-msg-${m.stepId}`,\n\t\tconversationId: synthId,\n\t\ttype: \"message\" as const,\n\t\ttext: m.text,\n\t\tvisibility: \"public\" as const,\n\t\tuserId: null,\n\t\tvisitorId: null,\n\t\taiAgentId: null,\n\t\tcreatedAt: new Date(now - (payload.messages.length - i) * 100).toISOString(),\n\t\teditedAt: null,\n\t\tdeletedAt: null,\n\t}));\n\n\tif (payload.quickReplies) {\n\t\tconst qrFallback =\n\t\t\tpayload.quickReplies.prompt ||\n\t\t\tpayload.quickReplies.options.map((o) => `• ${o.label}`).join(\"\\n\");\n\t\titems.push({\n\t\t\tid: `${synthId}-qr-${payload.quickReplies.stepId}`,\n\t\t\tconversationId: synthId,\n\t\t\ttype: \"message\",\n\t\t\ttext: qrFallback,\n\t\t\tvisibility: \"public\",\n\t\t\tuserId: null,\n\t\t\tvisitorId: null,\n\t\t\taiAgentId: null,\n\t\t\tcreatedAt: new Date(now).toISOString(),\n\t\t\teditedAt: null,\n\t\t\tdeletedAt: null,\n\t\t\tmetadata: {\n\t\t\t\tkind: \"quick_replies\" as const,\n\t\t\t\tprompt: payload.quickReplies.prompt ?? null,\n\t\t\t\toptions: payload.quickReplies.options.map((o) => ({ id: o.id, label: o.label })),\n\t\t\t\tstepId: payload.quickReplies.stepId,\n\t\t\t},\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: metadata is widely typed\n\t\t} as any);\n\t}\n\n\tconst s = store.getState();\n\ts.addConversation({\n\t\tid: synthId,\n\t\ttitle: null,\n\t\tstatus: \"open\",\n\t\tlastMessageText: previewText,\n\t\tlastMessageAt: new Date(now).toISOString(),\n\t\tlastMessageSenderType: \"ai\",\n\t\tlastMessageSenderName: null,\n\t\tlastMessageSenderImage: null,\n\t\tassigneeName: null,\n\t\tassigneeImage: null,\n\t\tunreadCount: items.length,\n\t});\n\t// biome-ignore lint/suspicious/noExplicitAny: synthetic items match TimelineItem shape\n\ts.setMessages(synthId, items as any);\n\n\tif (!s.isOpen && previewText) {\n\t\tstore.setState({\n\t\t\tincomingPreview: {\n\t\t\t\ttext: previewText,\n\t\t\t\tconversationId: synthId,\n\t\t\t\ttimestamp: now,\n\t\t\t\tmessages: payload.messages.map((m) => ({ text: m.text })),\n\t\t\t\t...(payload.quickReplies\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tquickReplies: {\n\t\t\t\t\t\t\t\tstepId: payload.quickReplies.stepId,\n\t\t\t\t\t\t\t\tprompt: payload.quickReplies.prompt ?? null,\n\t\t\t\t\t\t\t\toptions: payload.quickReplies.options.map((o) => ({\n\t\t\t\t\t\t\t\t\tid: o.id,\n\t\t\t\t\t\t\t\t\tlabel: o.label,\n\t\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t});\n\t}\n}\n\nfunction inferApiUrl(): string {\n\tif (typeof document !== \"undefined\") {\n\t\tconst script = document.querySelector(\"script[data-key][src]\");\n\t\tif (script) {\n\t\t\tconst src = script.getAttribute(\"src\");\n\t\t\tif (src) {\n\t\t\t\ttry {\n\t\t\t\t\tconst url = new URL(src);\n\t\t\t\t\treturn `${url.protocol}//${url.host}`;\n\t\t\t\t} catch {\n\t\t\t\t\t// Fall through to the production default.\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn \"https://api.helpway.ai\";\n}\n","\"use client\";\n\nimport { formatRelativeTime, t } from \"@helpway/widget-core\";\nimport type { ConversationSummary, WidgetContentTab } from \"@helpway/widget-core\";\nimport type { TimelineItem } from \"@helpway/types\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\n/** Resolve a label that might be a translation key (widget.*) or raw text */\nfunction resolveLabel(label: string): string {\n\tif (!label.startsWith(\"widget.\")) return label;\n\tconst resolved = t(label);\n\t// If t() returned the key itself (no translation found), humanize it\n\tif (resolved === label)\n\t\treturn label\n\t\t\t.replace(\"widget.\", \"\")\n\t\t\t.replace(/_/g, \" \")\n\t\t\t.replace(/^\\w/, (c) => c.toUpperCase());\n\treturn resolved;\n}\n\nimport { useAnnouncements } from \"../hooks/use-announcements\";\nimport type { UnseenAnnouncementEntry } from \"../hooks/use-announcements\";\nimport { useComposer } from \"../hooks/use-composer\";\nimport { useConversations } from \"../hooks/use-conversations\";\nimport { useI18n } from \"../hooks/use-i18n\";\nimport { usePresence } from \"../hooks/use-presence\";\nimport { useTimeline } from \"../hooks/use-timeline\";\nimport { useUnread } from \"../hooks/use-unread\";\nimport { useWidget } from \"../hooks/use-widget\";\nimport { useWidgetContext, useWidgetStore } from \"../provider\";\nimport { Composer } from \"./composer\";\nimport { WidgetDebugOverlay } from \"./debug-overlay\";\nimport { ContentTabView } from \"./content/content-tab-view\";\nimport { ContentTabIconComponent } from \"./content/tab-icon\";\nimport { HomeIcon, MessagesIcon, SendIcon, XIcon } from \"./icons\";\nimport { AnnouncementPreviews } from \"./announcement-previews\";\nimport { MessageBubble } from \"./message-bubble\";\nimport { MessageList } from \"./message-list\";\nimport { MessagePreview } from \"./message-preview\";\nimport { stripMarkdown } from \"./strip-markdown\";\n\nimport type { SubView, Tab } from \"./default-widget/types\";\n\nconst EMPTY_CONTENT_TABS: WidgetContentTab[] = [];\n\n/**\n * Factory-default admin strings. If the admin never customized these\n * values, the widget falls back to t() so visitors see their locale's\n * translation from the CDN bundle instead of frozen English.\n *\n * Keep in sync with packages/api seed defaults + widget-core/src/i18n.ts.\n */\nconst DEFAULT_EN_WELCOME = \"Hi there 👋\\nHow can we help?\";\nconst DEFAULT_EN_SUBTITLE = \"Usually replies in minutes\";\n\n/**\n * Helpway brand mark — octagonal outer with stylized \"W\" inside. Used as\n * the widget's own fallback avatar when the customer hasn't configured a\n * custom avatar/preset and the host site didn't set a logo either. Keeps\n * unconfigured widgets looking intentional rather than generic.\n */\nfunction HelpwayMark({ className }: { className?: string }) {\n\treturn (\n\t\t<svg\n\t\t\tclassName={className}\n\t\t\twidth=\"100%\"\n\t\t\theight=\"100%\"\n\t\t\tviewBox=\"0 0 42 42\"\n\t\t\tfill=\"none\"\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\taria-hidden=\"true\"\n\t\t>\n\t\t\t<path\n\t\t\t\td=\"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\"\n\t\t\t\tfill=\"currentColor\"\n\t\t\t/>\n\t\t</svg>\n\t);\n}\n\n/**\n * WidgetLogo — chat-header avatar. Renders WHO is talking to the\n * visitor right now. Resolution chain:\n * 1. Active conversation's assigned support user (assigneeName +\n * assigneeImage from the widget API). When a human takes over a\n * conversation the visitor sees that human, not the AI agent.\n * 2. Agent uploaded image (agentConfig.avatarUrl)\n * 3. Agent icon preset (avatarPreset + brandColor)\n * 4. Website logo (website.logoUrl)\n * 5. Helpway brand mark (octagonal) as the true last-resort fallback\n *\n * The `forceAgent` escape hatch skips the assignee lookup — used by\n * surfaces that mean \"the agent\" specifically (welcome card, conversation\n * list rows where we want the persistent brand, etc.) rather than \"the\n * person currently helping you\".\n */\nexport function WidgetLogo({\n\tclassName,\n\tforceAgent = false,\n}: {\n\tclassName?: string;\n\tforceAgent?: boolean;\n}) {\n\tconst agentConfig = useWidgetStore((s) => s.agentConfig);\n\tconst logoUrl = useWidgetStore((s) => s.website?.logoUrl);\n\tconst activeId = useWidgetStore((s) => s.activeConversationId);\n\tconst assignee = useWidgetStore((s) => {\n\t\tif (forceAgent || !s.activeConversationId) return null;\n\t\tconst c = s.conversations.find((c) => c.id === s.activeConversationId);\n\t\treturn c?.assigneeName || c?.assigneeImage ? c : null;\n\t});\n\n\t// In the launcher bubble (forceAgent=true), uploaded images are\n\t// treated as brand logos — `contain` + padding so SVG/PNG marks\n\t// don't get cropped by the rounded bubble. In the chat-header\n\t// context, face-photo avatars keep `cover` behavior.\n\tconst logoClass = forceAgent ? \"hw-agent-img--logo\" : \"\";\n\n\t// Assigned human takes priority over the AI agent default — but only\n\t// when we actually have an active conversation we're rendering for.\n\tif (!forceAgent && activeId && assignee?.assigneeImage) {\n\t\treturn (\n\t\t\t<img\n\t\t\t\tsrc={assignee.assigneeImage}\n\t\t\t\talt={assignee.assigneeName ?? \"\"}\n\t\t\t\tclassName={`hw-agent-img ${className ?? \"\"}`}\n\t\t\t/>\n\t\t);\n\t}\n\n\t// Agent uploaded image\n\tif (agentConfig?.avatarUrl) {\n\t\treturn <img src={agentConfig.avatarUrl} alt=\"\" className={`hw-agent-img ${logoClass} ${className ?? \"\"}`} />;\n\t}\n\n\t// Agent icon preset — use the same CSS variable as the welcome hero\n\t// so both surfaces stay color-synced. `--hw-primary` is fed by either\n\t// the inline style on `.hw-widget` (from agentConfig.brandColor) or\n\t// a `theme` prop override; reading the literal `agentConfig.brandColor`\n\t// here used to drift apart from the hero whenever the prop won.\n\tif (agentConfig?.avatarPreset) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tclassName={`hw-agent-icon ${className ?? \"\"}`}\n\t\t\t\tstyle={{\n\t\t\t\t\tbackgroundColor: \"var(--hw-primary)\",\n\t\t\t\t\tdisplay: \"flex\",\n\t\t\t\t\talignItems: \"center\",\n\t\t\t\t\tjustifyContent: \"center\",\n\t\t\t\t\tborderRadius: 8,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<AgentPresetIcon presetId={agentConfig.avatarPreset} />\n\t\t\t</div>\n\t\t);\n\t}\n\n\t// Website logo — always a brand mark, never a face avatar. Apply\n\t// --logo class regardless of context so it stays uncropped in both\n\t// launcher bubble and chat-header circles.\n\tif (logoUrl) {\n\t\treturn <img src={logoUrl} alt=\"\" className={`hw-agent-img hw-agent-img--logo ${className ?? \"\"}`} />;\n\t}\n\n\treturn <HelpwayMark className={className} />;\n}\n\n/**\n * LauncherIcon — what the visitor sees on the always-visible bubble\n * BEFORE opening the widget. Brand-stable, doesn't change per\n * conversation. Resolution chain:\n * 1. Custom launcher icon (agentConfig.launcherIconUrl) — admin upload\n * 2. Agent avatar (avatarUrl) — same image as the chat header default\n * 3. Agent icon preset\n * 4. Website logo\n * 5. Helpway brand mark\n */\nfunction LauncherIcon({ className }: { className?: string }) {\n\tconst agentConfig = useWidgetStore((s) => s.agentConfig);\n\tconst [imgLoaded, setImgLoaded] = useState(false);\n\tconst imgSrc = agentConfig?.launcherIconUrl ?? null;\n\n\tuseEffect(() => {\n\t\tif (!imgSrc) return;\n\t\tsetImgLoaded(false);\n\t\tconst img = new Image();\n\t\timg.src = imgSrc;\n\t\tif (img.complete) { setImgLoaded(true); return; }\n\t\timg.onload = () => setImgLoaded(true);\n\t\timg.onerror = () => setImgLoaded(true);\n\t}, [imgSrc]);\n\n\tif (imgSrc) {\n\t\treturn (\n\t\t\t<img\n\t\t\t\tsrc={imgSrc}\n\t\t\t\talt=\"\"\n\t\t\t\tclassName={`hw-agent-img hw-agent-img--logo ${className ?? \"\"}`}\n\t\t\t\tstyle={{ opacity: imgLoaded ? 1 : 0, transition: \"opacity 0.15s ease\" }}\n\t\t\t/>\n\t\t);\n\t}\n\treturn <WidgetLogo className={className} forceAgent />;\n}\n\n/**\n * Exact SVG paths extracted from @central-icons-react at build time.\n * Pixel-perfect match with the dashboard picker. Using static trusted\n * strings (NOT user input) rendered via innerHTML — safe because content\n * is hardcoded SVG from our own icon library, never from external sources.\n */\nconst PRESET_SVG: Record<string, string> = {\n\t// Helpway brand mark — octagonal chamfer with stylized \"W\" inside.\n\t// First entry so it's the default preset for new orgs.\n\thelpway:\n\t\t'<path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M16.4 0H7.31L0 7.31V16.4L7.31 23.71H16.4L23.71 16.4V7.31L16.4 0ZM8.57 16.51L3.89 11.83L8.57 7.14C10.34 5.37 13.26 5.37 15.03 7.14L19.71 11.83L15.03 16.51C13.26 18.29 10.4 18.29 8.57 16.51Z\" fill=\"white\"/>',\n\tatom: '<path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M9.67904 3.29155C10.7467 1.56948 13.2537 1.56948 14.3214 3.29155L15.1308 4.59707C15.2462 4.7833 15.3634 4.9684 15.4823 5.15233C15.7005 5.1305 15.9185 5.10662 16.1363 5.08068L17.6626 4.89893C19.6747 4.65934 21.2396 6.61723 20.5571 8.52637L20.0401 9.97255C19.9664 10.1786 19.8947 10.3854 19.825 10.5927C19.9779 10.7493 20.1323 10.9045 20.2882 11.0583L21.3821 12.1371C22.8256 13.5609 22.2668 16.0039 20.3491 16.6605L18.895 17.1584C18.6876 17.2294 18.4809 17.3023 18.275 17.3772C18.2478 17.5943 18.2226 17.8117 18.1995 18.0294L18.0372 19.5565C17.823 21.572 15.5635 22.6577 13.8546 21.5695L12.5584 20.7442C12.3734 20.6264 12.1873 20.5103 12.0002 20.3961C11.8131 20.5103 11.627 20.6264 11.442 20.7442L10.1458 21.5695C8.4369 22.6577 6.17739 21.572 5.96321 19.5565L5.80094 18.0294C5.7778 17.8117 5.75263 17.5943 5.72541 17.3772C5.51949 17.3023 5.31282 17.2294 5.10542 17.1584L3.65133 16.6605C1.7336 16.0039 1.17475 13.5609 2.61829 12.1371L3.71216 11.0583C3.86807 10.9045 4.0225 10.7493 4.17541 10.5927C4.10567 10.3854 4.03395 10.1786 3.96028 9.97255L3.44329 8.52637C2.7608 6.61723 4.32567 4.65934 6.33777 4.89893L7.86408 5.08068C8.08191 5.10662 8.29993 5.1305 8.5181 5.15233C8.63698 4.9684 8.75417 4.7833 8.86963 4.59707L9.67904 3.29155ZM7.61407 6.4827L6.16966 6.31071C5.20357 6.19567 4.45578 7.13505 4.78207 8.04778L5.2716 9.41715C6.10452 8.48167 6.88648 7.5021 7.61407 6.4827ZM5.78854 10.961C7.04552 9.61105 8.19784 8.16742 9.23549 6.64268C11.076 6.78287 12.9244 6.78287 14.7649 6.64268C15.8026 8.16743 16.9549 9.61105 18.2119 10.961C17.6657 12.722 17.2545 14.522 16.9818 16.3454C15.2628 17.0169 13.5974 17.8181 12.0002 18.7422C10.403 17.8181 8.73761 17.0169 7.01863 16.3454C6.74592 14.522 6.3347 12.722 5.78854 10.961ZM4.65269 12.1275L3.61666 13.1494C2.92581 13.8308 3.19234 15.0006 4.11188 15.3154L5.48873 15.7868C5.27593 14.553 4.99684 13.3315 4.65269 12.1275ZM7.22343 17.9611L7.377 19.4062C7.47946 20.3704 8.56185 20.8926 9.38218 20.3703L10.6083 19.5895C9.51004 18.9865 8.38012 18.4429 7.22343 17.9611ZM13.3921 19.5895L14.6182 20.3703C15.4385 20.8926 16.5209 20.3704 16.6234 19.4062L16.777 17.9611C15.6203 18.4429 14.4903 18.9865 13.3921 19.5895ZM18.5117 15.7868L19.8885 15.3154C20.8081 15.0006 21.0746 13.8308 20.3837 13.1494L19.3477 12.1275C19.0035 13.3315 18.7245 14.553 18.5117 15.7868ZM18.7288 9.41715L19.2183 8.04778C19.5446 7.13505 18.7968 6.19567 17.8307 6.31071L16.3863 6.4827C17.1139 7.5021 17.8959 8.48167 18.7288 9.41715ZM13.8786 5.2756C12.6272 5.3429 11.3731 5.3429 10.1218 5.2756L10.8874 4.04072C11.3991 3.21542 12.6013 3.21542 13.113 4.04072L13.8786 5.2756Z\" fill=\"white\"/>',\n\tbrain:\n\t\t'<path d=\"M15 10C13.3431 10 12 8.65685 12 7\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M9 14C10.6569 14 12 15.3431 12 17\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M12 3.53516L12 20.2422\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M21 14.5C21 15.9633 20.102 17.2168 18.8271 17.7396C18.2888 19.6221 16.5553 21 14.5 21C13.5749 21 12.7151 20.7209 12 20.2422C11.285 20.7209 10.4251 21 9.5 21C7.44468 21 5.71119 19.6221 5.17291 17.7396C3.89797 17.2168 3 15.9633 3 14.5C3 13.5207 3.40223 12.6353 4.05051 12C3.40223 11.3647 3 10.4793 3 9.5C3 7.69511 4.36618 6.20931 6.12085 6.0203C6.55779 4.28478 8.12886 3 10 3C10.7286 3 11.4117 3.19479 12 3.53513C12.5883 3.19479 13.2714 3 14 3C15.8711 3 17.4422 4.28478 17.8792 6.0203C19.6338 6.20931 21 7.69511 21 9.5C21 10.4793 20.5978 11.3647 19.9495 12C20.5978 12.6353 21 13.5207 21 14.5Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\trobot:\n\t\t'<path d=\"M12 4H7C5.89543 4 5 4.89543 5 6V11C5 12.1046 5.89543 13 7 13H17C18.1046 13 19 12.1046 19 11V6C19 4.89543 18.1046 4 17 4H12ZM12 4V2M6 15L4 17M6 15C6 18.3137 8.68629 21 12 21C15.3137 21 18 18.3137 18 15M6 15V13M18 15L20 17M18 15V13M9 8V9M15 8V9\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tsparkle:\n\t\t'<path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M21 12.5C14.75 12.5 12 15.4028 12 22C12 15.4028 9.25 12.5 3 12.5C9.25 12.5 12 9.59722 12 3C12 9.59722 14.75 12.5 21 12.5Z\" stroke=\"white\" stroke-width=\"2\" stroke-linejoin=\"round\"/>',\n\tbolt: '<path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M13.1981 20.0571C11.7326 20.0571 10.2936 19.5252 9.46756 18.3817L9.1762 19.7304L3.79688 22.5824L4.3776 19.7304L8.2951 2H13.0916L11.7059 8.24953C12.8251 7.02621 13.8643 6.57412 15.1967 6.57412C18.0746 6.57412 19.9931 8.46227 19.9931 11.9194C19.9931 15.483 17.7815 20.0571 13.1981 20.0571ZM15.0368 12.9301C15.0368 14.5788 13.8643 15.8287 12.3455 15.8287C11.4927 15.8287 10.72 15.5096 10.2137 14.9511L10.9598 11.6802C11.5194 11.1216 12.1589 10.8025 12.905 10.8025C14.0509 10.8025 15.0368 11.6536 15.0368 12.9301Z\" fill=\"white\"/>',\n\tagent:\n\t\t'<path d=\"M12 8.5V12M12 12H8C6.89543 12 6 12.8954 6 14V15.5M12 12H16C17.1046 12 18 12.8954 18 14V15.5\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><circle cx=\"12\" cy=\"6\" r=\"2.5\" stroke=\"white\" stroke-width=\"2\"/><circle cx=\"6\" cy=\"18\" r=\"2.5\" stroke=\"white\" stroke-width=\"2\"/><circle cx=\"18\" cy=\"18\" r=\"2.5\" stroke=\"white\" stroke-width=\"2\"/>',\n\tbubble:\n\t\t'<path d=\"M4.00195 6.00003C4.00195 4.89546 4.89738 4.00003 6.00195 4.00002L18.0019 4C19.1065 4 20.002 4.89543 20.002 6V16.0358C20.002 17.1403 19.1065 18.0358 18.002 18.0358L15.3757 18.0358C15.1427 18.0358 14.9171 18.1171 14.7377 18.2657L11.9977 20.5358L9.29398 18.2694C9.11393 18.1185 8.8865 18.0358 8.65157 18.0358H6.00195C4.89738 18.0358 4.00195 17.1403 4.00195 16.0358V6.00003Z\" fill=\"white\"/><path d=\"M13.2395 9.43518L12.5426 7.62334C12.4561 7.39842 12.24 7.25 11.999 7.25C11.758 7.25 11.5419 7.39842 11.4554 7.62334L10.7586 9.43518C10.657 9.69927 10.4483 9.90797 10.1842 10.0095L8.37236 10.7064C8.14744 10.7929 7.99902 11.009 7.99902 11.25C7.99902 11.491 8.14744 11.7071 8.37236 11.7936L10.1842 12.4905C10.4483 12.592 10.657 12.8007 10.7586 13.0648L11.4554 14.8767C11.5419 15.1016 11.758 15.25 11.999 15.25C12.24 15.25 12.4561 15.1016 12.5426 14.8767L13.2395 13.0648C13.3411 12.8007 13.5498 12.592 13.8138 12.4905L15.6257 11.7936C15.8506 11.7071 15.999 11.491 15.999 11.25C15.999 11.009 15.8506 10.7929 15.6257 10.7064L13.8138 10.0095C13.5498 9.90797 13.3411 9.69927 13.2395 9.43518Z\" fill=\"white\"/>',\n\tlightbulb:\n\t\t'<path d=\"M10 21H14M15.6076 15C17.6404 13.7751 19 11.5463 19 9C19 5.13401 15.866 2 12 2C8.13401 2 5 5.13401 5 9C5 11.5463 6.35958 13.7751 8.39241 15M15.6076 15C15.4111 15.1184 15.2084 15.2274 15 15.3264V17C15 17.5523 14.5523 18 14 18H10C9.44772 18 9 17.5523 9 17V15.3264C8.7916 15.2274 8.58886 15.1184 8.39241 15M15.6076 15H8.39241\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\twand: '<path d=\"M11.3908 12.6089L4 19.9996\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M18.3943 5.2792C18.5999 5.1944 18.8056 5.40008 18.7208 5.60565L17.1697 9.36581C17.1339 9.45248 17.1497 9.55186 17.2105 9.62323L19.8476 12.72C19.9918 12.8894 19.8597 13.1485 19.638 13.1314L15.5826 12.8182C15.4891 12.811 15.3994 12.8566 15.3503 12.9365L13.22 16.4015C13.1035 16.591 12.8163 16.5455 12.764 16.3293L11.8087 12.3756C11.7867 12.2844 11.7156 12.2133 11.6244 12.1913L7.67069 11.236C7.45453 11.1837 7.40903 10.8964 7.59847 10.78L11.0635 8.64965C11.1434 8.60055 11.189 8.51089 11.1818 8.41743L10.8686 4.36198C10.8515 4.14027 11.1106 4.00822 11.2799 4.15239L14.3768 6.78952C14.4481 6.8503 14.5475 6.86604 14.6342 6.83029L18.3943 5.2792Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tchip: '<path d=\"M8 5.5V4M12 5.5V4M16 5.5V4M8 20V18.5M12 20V18.5M16 20V18.5M8.75 15H15.25C15.6642 15 16 14.6642 16 14.25V9.75C16 9.33579 15.6642 9 15.25 9H8.75C8.33579 9 8 9.33579 8 9.75V14.25C8 14.6642 8.33579 15 8.75 15ZM6 20H18C19.1046 20 20 19.1046 20 18V6C20 4.89543 19.1046 4 18 4H6C4.89543 4 4 4.89543 4 6V18C4 19.1046 4.89543 20 6 20Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tcode: '<path d=\"M10 9.5L8.20711 11.2929C7.81658 11.6834 7.81658 12.3166 8.20711 12.7071L10 14.5M14 9.5L15.7929 11.2929C16.1834 11.6834 16.1834 12.3166 15.7929 12.7071L14 14.5M6 20H18C19.1046 20 20 19.1046 20 18V6C20 4.89543 19.1046 4 18 4H6C4.89543 4 4 4.89543 4 6V18C4 19.1046 4.89543 20 6 20Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tlightning:\n\t\t'<path d=\"M4.11593 12.2764L8.61593 3.27639C8.70063 3.107 8.87376 3 9.06315 3H17.121C17.5097 3 17.7497 3.42399 17.5498 3.75725L15.4585 7.24275C15.2585 7.57601 15.4986 8 15.8872 8H20.6909C21.1505 8 21.3666 8.56776 21.0235 8.87338L7.38117 21.0236C7.00034 21.3628 6.41568 20.981 6.57301 20.4959L8.79194 13.6543C8.8967 13.3312 8.6559 13 8.31633 13H4.56314C4.19145 13 3.94971 12.6088 4.11593 12.2764Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tvibe: '<path d=\"M18.9847 2.4329C18.9568 2.18651 18.7485 2.00025 18.5005 2C18.2525 1.99975 18.0438 2.18557 18.0154 2.43191C17.838 3.96993 16.9699 4.83801 15.4319 5.01541C15.1856 5.04382 14.9997 5.25253 15 5.5005C15.0003 5.74847 15.1865 5.9568 15.4329 5.9847C16.9491 6.15645 17.8774 7.01617 18.0141 8.55536C18.0365 8.80725 18.2477 9.00028 18.5005 9C18.7534 8.99971 18.9642 8.80621 18.986 8.55426C19.1173 7.03683 20.0368 6.11734 21.5543 5.98599C21.8062 5.96418 21.9997 5.75344 22 5.50055C22.0003 5.24766 21.8073 5.03648 21.5554 5.01411C20.0162 4.87738 19.1564 3.94911 18.9847 2.4329Z\" fill=\"white\"/><path d=\"M2 20C2 16.6863 4.68629 14 8 14H8.5\" fill=\"white\"/><path d=\"M11 20L12.6892 14.0879C12.8732 13.444 13.4617 13 14.1315 13H20.5417C21.2725 13 21.8001 13.6995 21.5994 14.4022L20.2072 19.2747C20.0846 19.704 19.6922 20 19.2457 20H11ZM11 20H7\" fill=\"white\"/><circle cx=\"8.75\" cy=\"7.5\" r=\"3.5\" stroke=\"white\" stroke-width=\"2\"/>',\n\tnetwork:\n\t\t'<path d=\"M12 6.8501L16 7.2501M17.75 10.0001L16.55 14.0001M13.5 14.3572L12 12.0001L10.4091 9.5001M6.25 14.0001L7.45 10.0001M8 16.7501L12 17.1501\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><circle cx=\"18.5\" cy=\"7.5\" r=\"2.5\" stroke=\"white\" stroke-width=\"2\"/><circle cx=\"5.5\" cy=\"16.5\" r=\"2.5\" stroke=\"white\" stroke-width=\"2\"/><circle cx=\"8.5\" cy=\"6.5\" r=\"3.5\" stroke=\"white\" stroke-width=\"2\"/><circle cx=\"15.5\" cy=\"17.5\" r=\"3.5\" stroke=\"white\" stroke-width=\"2\"/>',\n\tconsole:\n\t\t'<path d=\"M7.5 8L9.25 9.75L7.5 11.5M12 11.5H14M6 20H18C19.1046 20 20 19.1046 20 18V6C20 4.89543 19.1046 4 18 4H6C4.89543 4 4 4.89543 4 6V18C4 19.1046 4.89543 20 6 20Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tprompt:\n\t\t'<path d=\"M6 5H5C3.89543 5 3 5.89543 3 7V8\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M18 5H19C20.1046 5 21 5.89543 21 7V8\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M21 16V17C21 18.1046 20.1046 19 19 19H18\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M6 19H5C3.89543 19 3 18.1046 3 17V16\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M8 10H16\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M8 14H14\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tglobe:\n\t\t'<path d=\"M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M21 12H3\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M12 21C10.067 21 8.5 16.9706 8.5 12C8.5 7.02944 10.067 3 12 3C13.933 3 15.5 7.02944 15.5 12C15.5 16.9706 13.933 21 12 21Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\ttarget:\n\t\t'<path d=\"M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M17 12C17 14.7614 14.7614 17 12 17C9.23858 17 7 14.7614 7 12C7 9.23858 9.23858 7 12 7C14.7614 7 17 9.23858 17 12Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M13 12C13 12.5523 12.5523 13 12 13C11.4477 13 11 12.5523 11 12C11 11.4477 11.4477 11 12 11C12.5523 11 13 11.4477 13 12Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tdiamond:\n\t\t'<path d=\"M8.28256 4C7.77978 4 7.29545 4.18937 6.926 4.53039L2.53016 8.58809C1.69548 9.35857 1.66929 10.6687 2.47251 11.4719L10.5864 19.5858C11.3674 20.3668 12.6338 20.3668 13.4148 19.5858L21.5287 11.4719C22.3319 10.6687 22.3057 9.35857 21.471 8.58809L17.0752 4.53039C16.7057 4.18937 16.2214 4 15.7186 4H8.28256Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M9.5 8L7.5 10L9.5 12\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tstar: '<path d=\"M11.5288 2.29524C11.7179 1.90159 12.2821 1.90159 12.4712 2.29524L14.9458 7.44648C15.0219 7.60491 15.1735 7.71434 15.3487 7.73728L21.0456 8.4832C21.4809 8.5402 21.6552 9.07312 21.3368 9.37342L17.1693 13.303C17.0412 13.4238 16.9832 13.6009 17.0154 13.7735L18.0616 19.3857C18.1416 19.8146 17.6852 20.144 17.2993 19.9359L12.249 17.2133C12.0937 17.1296 11.9063 17.1296 11.751 17.2133L6.70073 19.9359C6.3148 20.144 5.85841 19.8146 5.93837 19.3857L6.98459 13.7735C7.01677 13.6009 6.95885 13.4238 6.83068 13.303L2.66324 9.37342C2.34476 9.07312 2.51909 8.5402 2.95444 8.4832L8.65127 7.73728C8.82648 7.71434 8.97811 7.60491 9.05422 7.44648L11.5288 2.29524Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\theart:\n\t\t'<path d=\"M21 10C21 15.75 12.75 20 12 20C11.25 20 3 15.75 3 10C3 6 5.5 4 8 4C10.5 4 12 5.5 12 5.5C12 5.5 13.5 4 16 4C18.5 4 21 6 21 10Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tshield:\n\t\t'<path d=\"M20 7.17737C20 6.32338 19.4578 5.56361 18.6502 5.286L12.6502 3.2235C12.2288 3.07866 11.7712 3.07866 11.3498 3.22349L5.34984 5.286C4.54224 5.56361 4 6.32338 4 7.17737V11.9123C4 16.8848 8 19 12 21.1579C16 19 20 16.8848 20 11.9123V7.17737Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\trocket:\n\t\t'<path d=\"M3 21H5C6.10457 21 7 20.1046 7 19C7 17.8954 6.10457 17 5 17C3.89543 17 3 17.8954 3 19V21Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M7.00098 13H4.76717C3.98987 13 3.50976 12.152 3.90968 11.4855L5.41837 8.97101C5.77982 8.3686 6.43083 8 7.13336 8H11.251C13.7671 5.25513 16.4925 3.3474 20.0017 3.04278C20.5519 2.99502 21.006 3.44906 20.9582 3.99927C20.6536 7.50845 18.7459 10.2339 16.001 12.75V16.8676C16.001 17.5701 15.6324 18.2212 15.03 18.5826L12.5155 20.0913C11.849 20.4912 11.001 20.0111 11.001 19.2338V17L7.00098 13Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M7 13L11.25 8\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M16 12.75L11 17\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tcrown:\n\t\t'<path d=\"M4.16831 17.4079L2 7L8 10L12 4L16 10L22 7L19.8317 17.4079C19.6385 18.3353 18.8211 19 17.8737 19H6.12628C5.17892 19 4.36153 18.3353 4.16831 17.4079Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\ttrophy:\n\t\t'<path d=\"M12.0039 17V14\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M18 5H19C20.1046 5 21 5.89543 21 7C21 8.65685 19.6569 10 18 10\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M6 5C6 3.89543 6.89543 3 8 3H16C17.1046 3 18 3.89543 18 5V8C18 11.3137 15.3137 14 12 14C8.68629 14 6 11.3137 6 8V5Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M7 19C7 17.8954 7.89543 17 9 17H15C16.1046 17 17 17.8954 17 19C17 20.1046 16.1046 21 15 21H9C7.89543 21 7 20.1046 7 19Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M6 5H5C3.89543 5 3 5.89543 3 7C3 8.65685 4.34315 10 6 10\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tcompass:\n\t\t'<path d=\"M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M14.6558 8.73023L10.5513 9.84965C10.2097 9.94281 9.94281 10.2097 9.84965 10.5513L8.73023 14.6558C8.62843 15.0291 8.97092 15.3716 9.34417 15.2698L13.4487 14.1504C13.7903 14.0572 14.0572 13.7903 14.1504 13.4487L15.2698 9.34417C15.3716 8.97092 15.0291 8.62843 14.6558 8.73023Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tfire: '<path d=\"M19.5 13.8122C19.5 23.3907 4.5 23.4012 4.5 13.8122C4.5 6.61352 12 2.5 12 2.5C12 2.5 19.5 6.61352 19.5 13.8122Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M15.5 17.4061C15.5 22.1954 8.5 22.2006 8.5 17.4061C8.5 13.8068 12 11.75 12 11.75C12 11.75 15.5 13.8068 15.5 17.4061Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tkey: '<path d=\"M20.8002 9.8753L20.0194 10.5L20.0194 10.5L20.8002 9.8753ZM22.0002 11.3753L21.2194 12V12L22.0002 11.3753ZM22.0002 12.6247L21.2194 12V12L22.0002 12.6247ZM20.8002 14.1247L20.0194 13.5L20.0194 13.5L20.8002 14.1247ZM18 14.5L17.5528 15.3944C17.6916 15.4639 17.8448 15.5 18 15.5V14.5ZM16 13.5L16.4472 12.6056C16.1657 12.4648 15.8343 12.4648 15.5528 12.6056L16 13.5ZM14 14.5V15.5C14.1552 15.5 14.3084 15.4639 14.4472 15.3944L14 14.5ZM11.0141 9.01843L11.8165 8.42152L11.8165 8.42152L11.0141 9.01843ZM11.0141 14.9816L10.2118 14.3847V14.3847L11.0141 14.9816ZM6.5 12C6.5 11.7239 6.72386 11.5 7 11.5V13.5C7.82843 13.5 8.5 12.8284 8.5 12H6.5ZM7 11.5C7.27614 11.5 7.5 11.7239 7.5 12H5.5C5.5 12.8284 6.17157 13.5 7 13.5V11.5ZM7.5 12C7.5 12.2761 7.27614 12.5 7 12.5V10.5C6.17157 10.5 5.5 11.1716 5.5 12H7.5ZM7 12.5C6.72386 12.5 6.5 12.2761 6.5 12H8.5C8.5 11.1716 7.82843 10.5 7 10.5V12.5ZM6.5 13H7.5V11H6.5V13ZM7 16C4.79086 16 3 14.2091 3 12H1C1 15.3137 3.68629 18 7 18V16ZM3 12C3 9.79086 4.79086 8 7 8V6C3.68629 6 1 8.68629 1 12H3ZM20.0194 10.5L21.2194 12L22.7811 10.7506L21.5811 9.25061L20.0194 10.5ZM21.2194 12L20.0194 13.5L21.5811 14.7494L22.7811 13.2494L21.2194 12ZM20.0194 13.5H18V15.5H20.0194V13.5ZM18.4472 13.6056L16.4472 12.6056L15.5528 14.3944L17.5528 15.3944L18.4472 13.6056ZM15.5528 12.6056L13.5528 13.6056L14.4472 15.3944L16.4472 14.3944L15.5528 12.6056ZM11.9079 10.5H20.0194V8.5H11.9079V10.5ZM7 8C8.31459 8 9.48107 8.63311 10.2118 9.61533L11.8165 8.42152C10.7246 6.9539 8.97356 6 7 6V8ZM14 13.5H11.9079V15.5H14V13.5ZM10.2118 14.3847C9.48107 15.3669 8.31459 16 7 16V18C8.97356 18 10.7246 17.0461 11.8165 15.5785L10.2118 14.3847ZM11.9079 13.5C11.1751 13.5 10.5749 13.8967 10.2118 14.3847L11.8165 15.5785C11.8445 15.5408 11.8734 15.5183 11.8929 15.5074C11.9106 15.4976 11.9148 15.5 11.9079 15.5V13.5ZM20.0194 13.5L20.0194 13.5V15.5C20.6269 15.5 21.2016 15.2238 21.5811 14.7494L20.0194 13.5ZM11.9079 8.5C11.9148 8.5 11.9106 8.50239 11.8929 8.49258C11.8734 8.48172 11.8445 8.45923 11.8165 8.42152L10.2118 9.61533C10.5749 10.1033 11.1751 10.5 11.9079 10.5V8.5ZM21.2194 12V12L22.7811 13.2494C23.3655 12.519 23.3655 11.481 22.7811 10.7506L21.2194 12ZM21.5811 9.25061C21.2016 8.77618 20.6269 8.5 20.0194 8.5V10.5L20.0194 10.5L21.5811 9.25061Z\" fill=\"white\"/>',\n\tlock: '<path d=\"M5 12C5 10.8954 5.89543 10 7 10H17C18.1046 10 19 10.8954 19 12V19C19 20.1046 18.1046 21 17 21H7C5.89543 21 5 20.1046 5 19V12Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M16 9.5V7C16 4.79086 14.2091 3 12 3C9.79086 3 8 4.79086 8 7V9.5\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M12 14V17\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tbookmark:\n\t\t'<path d=\"M19 19.9948V5C19 3.89543 18.1046 3 17 3H7C5.89543 3 5 3.89543 5 5V19.9948C5 20.8047 5.91243 21.2787 6.57503 20.813L10.8499 17.8083C11.54 17.3233 12.46 17.3233 13.1501 17.8083L17.425 20.813C18.0876 21.2787 19 20.8047 19 19.9948Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tstore:\n\t\t'<path d=\"M4 10V18C4 19.1046 4.89543 20 6 20H18C19.1046 20 20 19.1046 20 18V10\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M14.4996 4H9.49956L9.2133 8.00762C9.0978 9.62461 10.3785 11 11.9996 11C13.6207 11 14.9013 9.62461 14.7858 8.00763L14.4996 4Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M9.50047 4H5.73506C4.73976 4 3.89592 4.73186 3.75516 5.71716L3.4699 7.71396C3.22214 9.44831 4.56792 11 6.31987 11C7.83025 11 9.08385 9.83276 9.19146 8.32621L9.50047 4Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M18.2654 4H14.5L14.809 8.32621C14.9166 9.83276 16.1702 11 17.6806 11C19.4326 11 20.7783 9.44831 20.5306 7.71396L20.2453 5.71716C20.1046 4.73186 19.2607 4 18.2654 4Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tbag: '<path d=\"M15.0001 8C15.0001 9.65685 13.6569 11 12.0001 11C10.3432 11 9.00008 9.65685 9.00008 8M4.88288 5.87524L4.13288 17.8752C4.06092 19.0266 4.97534 20 6.12899 20H17.8712C19.0248 20 19.9392 19.0266 19.8673 17.8752L19.1173 5.87524C19.0514 4.82117 18.1773 4 17.1212 4H6.87899C5.82286 4 4.94876 4.82117 4.88288 5.87524Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\t\"credit-card\":\n\t\t'<path d=\"M3 10V17C3 18.1046 3.89543 19 5 19H19C20.1046 19 21 18.1046 21 17V10M3 10V7C3 5.89543 3.89543 5 5 5H19C20.1046 5 21 5.89518 21 6.99975V10M3 10H21\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\treceipt:\n\t\t'<path d=\"M9 8H15M9 12H11M19 21V5C19 3.89543 18.1046 3 17 3H7C5.89543 3 5 3.89543 5 5V21L7.33333 19L9.66667 21L12 19L14.3333 21L16.6667 19L19 21Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tbank: '<path d=\"M11.1056 2.94723L3.68328 6.65838C3.26452 6.86776 3 7.29576 3 7.76395C3 8.44661 3.55341 9.00002 4.23607 9.00002H19.7639C20.4466 9.00002 21 8.44661 21 7.76395C21 7.29576 20.7355 6.86776 20.3167 6.65838L12.8944 2.94723C12.3314 2.6657 11.6686 2.6657 11.1056 2.94723Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M19.6126 20H4.38749C3.70493 20 3.22296 19.3313 3.4388 18.6838L3.54421 18.3675C3.81644 17.5509 4.58072 17 5.44158 17H18.5585C19.4194 17 20.1837 17.5509 20.4559 18.3675L20.5613 18.6838C20.7772 19.3313 20.2952 20 19.6126 20Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M19 9V17\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M15 17V9\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M5 9V17\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M9 17V9\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\twallet:\n\t\t'<path d=\"M3 8V7C3 5.89543 3.89543 5 5 5H19C20.1046 5 21 5.89543 21 7V8M3 8H21M3 8V11M21 8V11M21 11V17C21 18.1046 20.1046 19 19 19H5C3.89543 19 3 18.1046 3 17V11M21 11H15C15 12.1046 14.1046 13 13 13H11C9.89543 13 9 12.1046 9 11H3\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tpackage:\n\t\t'<path d=\"M9 4V7.5C9 8.32843 9.67157 9 10.5 9H13.5C14.3284 9 15 8.32843 15 7.5V4M14 16H16M4 6V18C4 19.1046 4.89543 20 6 20H18C19.1046 20 20 19.1046 20 18V6C20 4.89543 19.1046 4 18 4H6C4.89543 4 4 4.89543 4 6Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\ttruck:\n\t\t'<path d=\"M10 16.5C10 17.8807 8.88071 19 7.5 19C6.11929 19 5 17.8807 5 16.5C5 15.1193 6.11929 14 7.5 14C8.88071 14 10 15.1193 10 16.5Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M19 16.5C19 17.8807 17.8807 19 16.5 19C15.1193 19 14 17.8807 14 16.5C14 15.1193 15.1193 14 16.5 14C17.8807 14 19 15.1193 19 16.5Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M10 16H14\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M9 14V7H6.07037C5.40166 7 4.7772 7.3342 4.40627 7.8906L3.3359 9.49615C3.11688 9.82469 3 10.2107 3 10.6056V14.2857C3 15.2325 3.76751 16 4.71429 16\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M9 9V7C9 5.89543 9.89543 5 11 5H19C20.1046 5 21 5.89543 21 7V14C21 15.1046 20.1046 16 19 16\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tmegaphone:\n\t\t'<path d=\"M17.9961 14.0001C19.6529 14.0001 20.9961 12.657 20.9961 11.0001C20.9961 9.34325 19.6529 8.0001 17.9961 8.0001M12.8254 18.0001C12.4136 19.1653 11.3023 20.0001 9.99609 20.0001C8.33924 20.0001 6.99609 18.657 6.99609 17.0001V15.5001M6.99829 6.5001V15.5001M17.9961 5.73752V16.2627C17.9961 17.617 16.6784 18.5797 15.3882 18.1681L4.38819 14.6585C3.55899 14.394 2.99609 13.6235 2.99609 12.7532V9.24704C2.99609 8.37667 3.55899 7.60622 4.38819 7.34167L15.3882 3.83215C16.6784 3.42051 17.9961 4.38325 17.9961 5.73752Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\temail:\n\t\t'<path d=\"M20.782 6.09202L19.891 6.54601L19.891 6.54601L20.782 6.09202ZM19.908 5.21799L20.362 4.32698V4.32698L19.908 5.21799ZM4.09202 5.21799L3.63803 4.32698L3.63803 4.32698L4.09202 5.21799ZM3.21799 6.09202L2.32698 5.63803L2.32698 5.63803L3.21799 6.09202ZM3.21799 17.908L4.10899 17.454L4.10899 17.454L3.21799 17.908ZM4.09202 18.782L4.54601 17.891H4.54601L4.09202 18.782ZM19.908 18.782L20.362 19.673V19.673L19.908 18.782ZM20.782 17.908L19.891 17.454L19.891 17.454L20.782 17.908ZM21 8.2H20V15.8H21H22V8.2H21ZM21 8.2H22C22 7.65645 22.0008 7.18864 21.9694 6.80497C21.9371 6.40963 21.8658 6.01641 21.673 5.63803L20.782 6.09202L19.891 6.54601C19.9162 6.59545 19.9539 6.69617 19.9761 6.96784C19.9992 7.25117 20 7.62345 20 8.2H21ZM20.782 6.09202L21.673 5.63803C21.3854 5.07354 20.9265 4.6146 20.362 4.32698L19.908 5.21799L19.454 6.10899C19.6422 6.20487 19.7951 6.35785 19.891 6.54601L20.782 6.09202ZM17.8 5V6C18.3766 6 18.7488 6.00078 19.0322 6.02393C19.3038 6.04612 19.4045 6.0838 19.454 6.10899L19.908 5.21799L20.362 4.32698C19.9836 4.13419 19.5904 4.06287 19.195 4.03057C18.8114 3.99922 18.3436 4 17.8 4V5ZM6.2 5V6H17.8V5V4H6.2V5ZM6.2 5V4C5.65645 4 5.18864 3.99922 4.80497 4.03057C4.40963 4.06287 4.01641 4.13419 3.63803 4.32698L4.09202 5.21799L4.54601 6.10899C4.59545 6.0838 4.69617 6.04612 4.96784 6.02393C5.25117 6.00078 5.62345 6 6.2 6V5ZM3.21799 6.09202L4.10899 6.54601C4.20487 6.35785 4.35785 6.20487 4.54601 6.10899L4.09202 5.21799L3.63803 4.32698C3.07354 4.6146 2.6146 5.07354 2.32698 5.63803L3.21799 6.09202ZM3 8.2H4C4 7.62345 4.00078 7.25117 4.02393 6.96784C4.04612 6.69617 4.0838 6.59545 4.10899 6.54601L3.21799 6.09202L2.32698 5.63803C2.13419 6.01641 2.06287 6.40963 2.03057 6.80497C1.99922 7.18864 2 7.65645 2 8.2H3ZM3 15.8H4V8.2H3H2V15.8H3ZM3 15.8H2C2 16.3435 1.99922 16.8114 2.03057 17.195C2.06287 17.5904 2.13419 17.9836 2.32698 18.362L3.21799 17.908L4.10899 17.454C4.0838 17.4045 4.04612 17.3038 4.02393 17.0322C4.00078 16.7488 4 16.3765 4 15.8H3ZM4.09202 18.782L4.54601 17.891C4.35785 17.7951 4.20487 17.6421 4.10899 17.454L3.21799 17.908L2.32698 18.362C2.6146 18.9265 3.07354 19.3854 3.63803 19.673L4.09202 18.782ZM6.2 19V18C5.62345 18 5.25117 17.9992 4.96784 17.9761C4.69617 17.9539 4.59545 17.9162 4.54601 17.891L4.09202 18.782L3.63803 19.673C4.01641 19.8658 4.40963 19.9371 4.80497 19.9694C5.18864 20.0008 5.65645 20 6.2 20V19ZM17.8 19V18H6.2V19V20H17.8V19ZM17.8 19V20C18.3436 20 18.8114 20.0008 19.195 19.9694C19.5904 19.9371 19.9836 19.8658 20.362 19.673L19.908 18.782L19.454 17.891C19.4045 17.9162 19.3038 17.9539 19.0322 17.9761C18.7488 17.9992 18.3766 18 17.8 18V19ZM20.782 17.908L19.891 17.454C19.7951 17.6421 19.6422 17.7951 19.454 17.891L19.908 18.782L20.362 19.673C20.9265 19.3854 21.3854 18.9265 21.673 18.362L20.782 17.908ZM21 15.8H20C20 16.3765 19.9992 16.7488 19.9761 17.0322C19.9539 17.3038 19.9162 17.4045 19.891 17.454L20.782 17.908L21.673 18.362C21.8658 17.9836 21.9371 17.5904 21.9694 17.195C22.0008 16.8114 22 16.3435 22 15.8H21Z\" fill=\"white\"/><path d=\"M21 5.63635L13.2665 11.9638C12.5297 12.5666 11.4703 12.5666 10.7335 11.9638L3 5.63635\" fill=\"white\"/>',\n\tbell: '<path d=\"M4.69376 9.44981C5.15435 5.76511 8.28661 3 12 3C15.7134 3 18.8456 5.76511 19.3062 9.44981L19.969 14.7519C20.1182 15.9456 19.1874 17 17.9844 17H6.01555C4.81256 17 3.88178 15.9456 4.031 14.7519L4.69376 9.44981Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M16 17C16 19.2091 14.2091 21 12 21C9.79086 21 8 19.2091 8 17\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tpeople:\n\t\t'<path d=\"M15.5 6.5C15.5 8.433 13.933 10 12 10C10.067 10 8.5 8.433 8.5 6.5C8.5 4.567 10.067 3 12 3C13.933 3 15.5 4.567 15.5 6.5Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M12.0011 13C8.60997 13 6.03711 15.0143 4.9836 17.8629C4.5748 18.9682 5.51944 20 6.69796 20H17.3043C18.4828 20 19.4274 18.9682 19.0186 17.8629C17.9651 15.0143 15.3923 13 12.0011 13Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tsupport:\n\t\t'<path d=\"M6 10H4.5C3.67157 10 3 10.6716 3 11.5V15C3 15.8284 3.67157 16.5 4.5 16.5H6V10Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M20 10H18.5V16.5H20C20.8284 16.5 21.5 15.8284 21.5 15V11.5C21.5 10.6716 20.8284 10 20 10Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M19.5 10V9.75C19.5 6.02208 16.2541 3 12.25 3C8.24594 3 5 6.02208 5 9.75V10\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M12 19V19.5C12 20.3284 12.6716 21 13.5 21H15.25C17.7353 21 19.75 18.9853 19.75 16.5\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\thandshake:\n\t\t'<path d=\"M11.8305 5.68856C9.57907 3.43715 5.92881 3.43715 3.6774 5.68856C1.57785 7.78811 1.40103 11.1544 3.42019 13.3313C5.71921 15.8101 8.14783 18.1408 10.7345 20.3519C11.4619 20.9737 12.5313 20.9737 13.2587 20.3519C15.8453 18.1408 18.2739 15.8101 20.573 13.3313C22.5921 11.1544 22.4153 7.78811 20.3158 5.68856C18.0644 3.43715 14.4141 3.43715 12.1627 5.68856L8.8146 9.03664C8.22881 9.62243 8.22881 10.5722 8.8146 11.158C9.98617 12.3295 11.8857 12.3295 13.0572 11.158L13.7643 10.4509C14.1549 10.0603 14.788 10.0603 15.1786 10.4509L18.7141 13.9864\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tpill: '<path d=\"M17.4541 10.0962C18.6109 8.31497 18.4083 5.90826 16.8462 4.34619C15.0513 2.55127 12.1411 2.55127 10.3462 4.34619L4.34619 10.3462C2.55127 12.1411 2.55127 15.0513 4.34619 16.8462C5.90826 18.4083 8.31497 18.6109 10.0962 17.4541\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M7.5 7.5L11 11\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M16.5 20.5L14.5 10.5\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><circle cx=\"15.5\" cy=\"15.5\" r=\"5.5\" stroke=\"white\" stroke-width=\"2\"/>',\n\t\"heart-beat\":\n\t\t'<path d=\"M16 12H14.5L13 14L10.5 10L9.25 12H8M12 5.76835C18.1619 -0.481837 28.7252 11.1257 12 20.5C-4.72523 11.1257 5.83803 -0.481838 12 5.76835Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tbook: '<path d=\"M9 6C8.44772 6 8 6.44772 8 7C8 7.55228 8.44772 8 9 8V6ZM15 8C15.5523 8 16 7.55228 16 7C16 6.44772 15.5523 6 15 6V8ZM9 10C8.44772 10 8 10.4477 8 11C8 11.5523 8.44772 12 9 12V10ZM12 12C12.5523 12 13 11.5523 13 11C13 10.4477 12.5523 10 12 10V12ZM7 4H17V2H7V4ZM18 5V19H20V5H18ZM17 20H7V22H17V20ZM6 19V5H4V19H6ZM7 20C6.44771 20 6 19.5523 6 19H4C4 20.6569 5.34315 22 7 22V20ZM18 19C18 19.5523 17.5523 20 17 20V22C18.6569 22 20 20.6569 20 19H18ZM17 4C17.5523 4 18 4.44772 18 5H20C20 3.34315 18.6569 2 17 2V4ZM7 2C5.34315 2 4 3.34315 4 5H6C6 4.44772 6.44772 4 7 4V2ZM18 12V15H20V12H18ZM17 16H7V18H17V16ZM7 22H10V20H7V22ZM7 16C5.34315 16 4 17.3431 4 19H6C6 18.4477 6.44772 18 7 18V16ZM18 15C18 15.5523 17.5523 16 17 16V18C18.6569 18 20 16.6569 20 15H18ZM9 8H15V6H9V8ZM9 12H12V10H9V12Z\" fill=\"white\"/>',\n\tgraduate:\n\t\t'<path d=\"M23 9L12 14L1 9L12 4L23 9ZM23 9V16M5 11V15.3025C5 16.0398 5.40565 16.7173 6.05556 17.0655L11.0556 19.744C11.6455 20.0601 12.3545 20.0601 12.9444 19.744L17.9444 17.0655C18.5944 16.7173 19 16.0398 19 15.3025V11\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n};\n\n/**\n * Renders preset icon SVG — uses trusted static SVG content extracted from\n * @central-icons-react at build time. Content is hardcoded (not user input),\n * so innerHTML usage is safe from XSS.\n */\nfunction AgentPresetIcon({ presetId }: { presetId: string }) {\n\tconst svgContent = PRESET_SVG[presetId] ?? PRESET_SVG.sparkle;\n\treturn (\n\t\t// biome-ignore lint: trusted static SVG content from our icon library\n\t\t<svg\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tstyle={{ width: \"55%\", height: \"55%\" }}\n\t\t\tdangerouslySetInnerHTML={{ __html: svgContent ?? \"\" }}\n\t\t/>\n\t);\n}\n\n/**\n * Unified support widget — Intercom-style with tab navigation.\n * Two tabs: Home + Messages. Sub-views: conversation + new conversation.\n */\nexport function DefaultWidget({ hideLauncher = false }: { hideLauncher?: boolean } = {}) {\n\tconst { isReady, website, agentConfig } = useWidget();\n\tuseI18n();\n\tconst { client, store, hasBootstrapError, wsDisconnected, retryBootstrap } = useWidgetContext();\n\tconst { conversations, create, isCreating, setActiveConversation } = useConversations();\n\tconst activeId = useWidgetStore((s) => s.activeConversationId);\n\tconst isDismissed = useWidgetStore((s) => s.isDismissed);\n\tconst { totalUnread } = useUnread();\n\n\tconst contentTabs = useWidgetStore((s) => s.agentConfig?.contentTabs) ?? EMPTY_CONTENT_TABS;\n\tconst { announcementTabs, markEntrySeen, getUnseenEntries } = useAnnouncements();\n\tconst unseenAnnouncementCount = useWidgetStore((s) => s.unseenAnnouncementCount);\n\n\tconst visitorContact = useWidgetStore((s) => s.visitor?.contact);\n\n\t// DEV: email prompt debug\n\tif (process.env.NODE_ENV !== \"production\") {\n\t\tconsole.debug(\"[Widget]\", {\n\t\t\treqEmail: agentConfig?.requireVisitorEmail,\n\t\t\tcontact: visitorContact?.email ?? null,\n\t\t\tactiveId,\n\t\t});\n\t}\n\n\tconst storeIsOpen = useWidgetStore((s) => s.isOpen);\n\tconst [isClosing, setIsClosing] = useState(false);\n\tconst isOpen = storeIsOpen || isClosing;\n\tconst [activeTab, setActiveTab] = useState<Tab>(\"home\");\n\tconst [subView, setSubView] = useState<SubView>(null);\n\tconst [newText, setNewText] = useState(\"\");\n\tconst [contentDetailSlug, setContentDetailSlug] = useState<string | null>(null);\n\tconst [contentCategoryName, setContentCategoryName] = useState<string | null>(null);\n\n\t// Sync API-driven navigation: when store.activeConversationId changes externally\n\t// (via window.Helpway.openConversation), drive the local subView to match.\n\tconst prevActiveIdRef = useRef(activeId);\n\tuseEffect(() => {\n\t\tif (activeId && activeId !== prevActiveIdRef.current && subView !== \"conversation\") {\n\t\t\tsetSubView(\"conversation\");\n\t\t}\n\t\tprevActiveIdRef.current = activeId;\n\t}, [activeId, subView]);\n\n\t// Consume newConversationPrefill from global API (window.Helpway.newConversation)\n\tconst prefill = useWidgetStore((s) => s.newConversationPrefill);\n\tuseEffect(() => {\n\t\tif (prefill !== null) {\n\t\t\tif (prefill.length > 0) setNewText(prefill);\n\t\t\tsetSubView(\"new\");\n\t\t\tsetActiveTab(\"home\");\n\t\t\tstore.getState().setNewConversationPrefill(null);\n\t\t}\n\t}, [prefill, store]);\n\n\tconst closeTimerRef = useRef<ReturnType<typeof setTimeout>>(undefined);\n\n\t// Resolve welcome/subtitle here (used both by openNewConversation seed\n\t// and by the header). Hoisted above openNewConversation so the callback\n\t// captures a defined binding instead of hitting the TDZ at closure time.\n\tconst welcomeMsgRaw = agentConfig?.welcomeMessage;\n\tconst welcomeIsFactoryDefault =\n\t\t!welcomeMsgRaw || welcomeMsgRaw === DEFAULT_EN_WELCOME;\n\tconst welcomeMessage = welcomeMsgRaw?.startsWith(\"widget.\")\n\t\t? t(welcomeMsgRaw)\n\t\t: welcomeIsFactoryDefault\n\t\t\t? t(\"widget.welcome_message\")\n\t\t\t: welcomeMsgRaw;\n\n\tconst openConversation = useCallback(\n\t\t(id: string) => {\n\t\t\tsetActiveConversation(id);\n\t\t\tsetSubView(\"conversation\");\n\t\t},\n\t\t[setActiveConversation],\n\t);\n\n\tconst openNewConversation = useCallback(() => {\n\t\t// Seed a temp conversation + a stable welcome bubble and drop the user\n\t\t// straight into \"conversation\" view. This keeps the welcome bubble\n\t\t// mounted in the SAME React subtree across the first-send transition\n\t\t// (previously: \"new\" view → \"conversation\" view = unmount + remount =\n\t\t// CSS `hw-msg-appear` animation replays = the \"git-gel\" flash).\n\t\t//\n\t\t// useComposer notices the temp id and routes through createConversation\n\t\t// when the visitor sends their first message.\n\t\tconst agentId = agentConfig?.id;\n\t\tif (!agentId) {\n\t\t\t// No agent config yet — skip the seed and let the server decide.\n\t\t\t// The user can still compose; submit will call createConversation.\n\t\t\tsetSubView(\"new\");\n\t\t\treturn;\n\t\t}\n\t\tconst tempId = `temp-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;\n\t\tconst seedWelcome: TimelineItem = {\n\t\t\tid: `seed-welcome-${tempId}`,\n\t\t\tconversationId: tempId,\n\t\t\torganizationId: \"\",\n\t\t\ttype: \"message\",\n\t\t\tvisibility: \"public\",\n\t\t\ttext: welcomeMessage,\n\t\t\tparts: null,\n\t\t\tuserId: null,\n\t\t\tvisitorId: null,\n\t\t\taiAgentId: agentId,\n\t\t\tcreatedAt: new Date().toISOString(),\n\t\t\teditedAt: null,\n\t\t\tdeletedAt: null,\n\t\t};\n\t\tstore.getState().setMessages(tempId, [seedWelcome]);\n\t\tsetActiveConversation(tempId);\n\t\tsetSubView(\"conversation\");\n\t}, [agentConfig?.id, store, setActiveConversation, welcomeMessage]);\n\n\tconst goBack = useCallback(() => {\n\t\tif (subView === \"content-detail\") {\n\t\t\t// If inside a grouped tab, go back to category items, not all the way to categories\n\t\t\tconst tabId = activeTab.startsWith(\"content:\") ? activeTab.slice(8) : null;\n\t\t\tconst activeContentTab = tabId ? contentTabs.find((t) => t.id === tabId) : null;\n\t\t\tif (activeContentTab?.tabType === \"grouped\" && contentCategoryName) {\n\t\t\t\tsetSubView(\"content-category\");\n\t\t\t\tsetContentDetailSlug(null);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsetSubView(null);\n\t\t\tsetContentDetailSlug(null);\n\t\t\treturn;\n\t\t}\n\t\tif (subView === \"content-category\") {\n\t\t\tsetSubView(null);\n\t\t\tsetContentCategoryName(null);\n\t\t\treturn;\n\t\t}\n\t\t// Race-immune mark-seen: when leaving a conversation, the visitor has\n\t\t// effectively \"seen\" everything currently in it — including any AI reply\n\t\t// that may have arrived via WS milliseconds before they tapped back.\n\t\t// Without this, the WS event arriving AFTER setActiveConversation(null)\n\t\t// finds isViewing=false and increments unreadCount.\n\t\t// Skip temp-* IDs (server doesn't know about them yet).\n\t\tconst leavingId = store.getState().activeConversationId;\n\t\tif (leavingId && !leavingId.startsWith(\"temp-\")) {\n\t\t\tstore.getState().clearUnread(leavingId);\n\t\t\tclient.widget.markSeen.mutate({ conversationId: leavingId }).catch(() => {});\n\t\t}\n\t\tsetActiveConversation(null);\n\t\tsetSubView(null);\n\t}, [setActiveConversation, subView, activeTab, contentTabs, contentCategoryName, client, store]);\n\n\tconst switchTab = useCallback(\n\t\t(tab: Tab) => {\n\t\t\t// Save current tab state\n\t\t\ttabStateRef.current[activeTab] = { subView, activeId };\n\t\t\t// Restore target tab state (if any)\n\t\t\tconst saved = tabStateRef.current[tab];\n\t\t\tsetActiveTab(tab);\n\t\t\tsetSubView(saved?.subView ?? null);\n\t\t\tif (saved?.activeId != null) {\n\t\t\t\tsetActiveConversation(saved.activeId);\n\t\t\t} else if (!saved) {\n\t\t\t\tsetActiveConversation(null);\n\t\t\t}\n\t\t},\n\t\t[activeTab, subView, activeId, setActiveConversation],\n\t);\n\n\t// Consume pendingContentDetail — set by anchored consumers (or any\n\t// external trigger) that want to deep-link the visitor into a\n\t// specific content entry's detail view instead of dropping them on\n\t// the home surface. Mirrors what the launcher's announcement onOpen\n\t// does internally: mark the entry seen, switch to the right content\n\t// tab, open its detail, then clear the pending state. Sits after\n\t// `switchTab` so the dep array can reference the stable useCallback.\n\tconst pendingContentDetail = useWidgetStore((s) => s.pendingContentDetail);\n\tuseEffect(() => {\n\t\tif (!pendingContentDetail) return;\n\t\tconst { slug, tabId } = pendingContentDetail;\n\t\tmarkEntrySeen(slug);\n\t\tswitchTab(`content:${tabId}`);\n\t\tsetContentDetailSlug(slug);\n\t\tsetSubView(\"content-detail\");\n\t\tstore.getState().setPendingContentDetail(null);\n\t}, [pendingContentDetail, markEntrySeen, switchTab, store]);\n\n\tconst setStoreOpen = useWidgetStore((s) => s.setOpen);\n\n\tconst handleBubbleClick = useCallback(() => {\n\t\tif (storeIsOpen) {\n\t\t\tconst leavingId = store.getState().activeConversationId;\n\t\t\tif (leavingId && !leavingId.startsWith(\"temp-\")) {\n\t\t\t\tstore.getState().clearUnread(leavingId);\n\t\t\t\tclient.widget.markSeen.mutate({ conversationId: leavingId }).catch(() => {});\n\t\t\t}\n\t\t\tsetIsClosing(true);\n\t\t\tcloseTimerRef.current = setTimeout(() => {\n\t\t\t\tsetIsClosing(false);\n\t\t\t\tsetStoreOpen(false);\n\t\t\t}, 200);\n\t\t} else {\n\t\t\tsetIsClosing(false);\n\t\t\tsetSubView(null);\n\t\t\tsetActiveTab(\"home\");\n\t\t\tsetStoreOpen(true);\n\t\t}\n\t}, [storeIsOpen, setStoreOpen, client, store]);\n\n\tconst handleClose = useCallback(() => {\n\t\tconst leavingId = store.getState().activeConversationId;\n\t\tif (leavingId && !leavingId.startsWith(\"temp-\")) {\n\t\t\tstore.getState().clearUnread(leavingId);\n\t\t\tclient.widget.markSeen.mutate({ conversationId: leavingId }).catch(() => {});\n\t\t}\n\t\tsetIsClosing(true);\n\t\tcloseTimerRef.current = setTimeout(() => {\n\t\t\tsetIsClosing(false);\n\t\t\tsetStoreOpen(false);\n\t\t}, 200);\n\t}, [setStoreOpen, client, store]);\n\n\tconst handleNewConversation = useCallback(async () => {\n\t\tconst trimmed = newText.trim();\n\t\tif (!trimmed || isCreating) return;\n\t\tconst conv = await create(trimmed);\n\t\tif (conv) {\n\t\t\tsetNewText(\"\");\n\t\t\tsetSubView(\"conversation\");\n\t\t}\n\t}, [newText, isCreating, create]);\n\n\tconst windowRef = useRef<HTMLDivElement>(null);\n\tconst bubbleRef = useRef<HTMLButtonElement>(null);\n\tconst tabStateRef = useRef<{ [tab: string]: { subView: SubView; activeId: string | null } }>({});\n\tconst touchStartY = useRef(0);\n\tconst touchDeltaY = useRef(0);\n\n\tconst handleTouchStart = useCallback((e: React.TouchEvent) => {\n\t\ttouchStartY.current = e.touches[0]?.clientY ?? 0;\n\t\ttouchDeltaY.current = 0;\n\t}, []);\n\n\tconst handleTouchMove = useCallback((e: React.TouchEvent) => {\n\t\tconst delta = (e.touches[0]?.clientY ?? 0) - touchStartY.current;\n\t\ttouchDeltaY.current = delta;\n\t\tif (delta > 0 && windowRef.current) {\n\t\t\twindowRef.current.style.transform = `translateY(${Math.min(delta, 200)}px)`;\n\t\t\twindowRef.current.style.opacity = `${Math.max(1 - delta / 400, 0.5)}`;\n\t\t}\n\t}, []);\n\n\tconst handleTouchEnd = useCallback(() => {\n\t\tif (windowRef.current) {\n\t\t\twindowRef.current.style.transform = \"\";\n\t\t\twindowRef.current.style.opacity = \"\";\n\t\t}\n\t\tif (touchDeltaY.current > 80) {\n\t\t\thandleClose();\n\t\t}\n\t}, [handleClose]);\n\n\t// iOS virtual keyboard — `height: 100%` in CSS refers to the LAYOUT\n\t// viewport, which doesn't shrink when the keyboard opens on iOS Safari.\n\t// The result: composer gets pushed below the visible area and visitors\n\t// can't see what they're typing. visualViewport.height is the one\n\t// reliable API that reflects post-keyboard space. We write it to a CSS\n\t// custom property the mobile @media block consumes.\n\tuseEffect(() => {\n\t\tif (!isOpen || !windowRef.current) return;\n\t\tconst vv = window.visualViewport;\n\t\tif (!vv) return;\n\t\tconst win = windowRef.current;\n\t\tconst applyHeight = () => {\n\t\t\twin.style.setProperty(\"--hw-visible-height\", `${vv.height}px`);\n\t\t};\n\t\tapplyHeight();\n\t\tvv.addEventListener(\"resize\", applyHeight);\n\t\tvv.addEventListener(\"scroll\", applyHeight);\n\t\treturn () => {\n\t\t\tvv.removeEventListener(\"resize\", applyHeight);\n\t\t\tvv.removeEventListener(\"scroll\", applyHeight);\n\t\t\twin.style.removeProperty(\"--hw-visible-height\");\n\t\t};\n\t}, [isOpen]);\n\n\t// Escape to close / back — listener attached to the widget window, NOT\n\t// document. Two reasons: (1) widget lives inside a shadow DOM; document\n\t// listeners fire for host-page key events too, which would close the\n\t// widget when a visitor presses ESC in the host site's own search box.\n\t// (2) WCAG 2.1 AA requires focus-scoped escape behavior for dialogs.\n\tuseEffect(() => {\n\t\tif (!isOpen || !windowRef.current) return;\n\t\tconst win = windowRef.current;\n\t\tconst handleKeyDown = (e: KeyboardEvent) => {\n\t\t\tif (e.key === \"Escape\") {\n\t\t\t\tif (subView) {\n\t\t\t\t\tgoBack();\n\t\t\t\t} else {\n\t\t\t\t\thandleClose();\n\t\t\t\t\tsetTimeout(() => bubbleRef.current?.focus(), 220);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\twin.addEventListener(\"keydown\", handleKeyDown);\n\t\treturn () => win.removeEventListener(\"keydown\", handleKeyDown);\n\t}, [isOpen, subView, handleClose, goBack]);\n\n\t// Focus trap — same rationale: listen on the widget window so only\n\t// keydowns inside the widget are trapped. `document.activeElement`\n\t// returns the shadow HOST when focus is inside a shadow root; to find\n\t// the actually-focused element we walk into the shadow root.\n\t//\n\t// Skipped entirely under `hideLauncher` (embedded/anchored consumers\n\t// like a sidebar Help item): in that mode the widget shares space\n\t// with the host's own inputs, so grabbing focus on open silently\n\t// steals the visitor's typing/paste context — Cmd+V after opening\n\t// the panel would land in our composer instead of whatever the host\n\t// had focused (paste hijack). Trapping Tab would also fight the\n\t// host's keyboard nav. Both belong to the modal launcher use case,\n\t// not to embedded consumption.\n\tuseEffect(() => {\n\t\tif (!isOpen || !windowRef.current || hideLauncher) return;\n\t\tconst win = windowRef.current;\n\t\tconst getFocusable = () =>\n\t\t\twin.querySelectorAll<HTMLElement>(\n\t\t\t\t'button:not([disabled]), [href], input:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])',\n\t\t\t);\n\t\tconst getActive = (): Element | null => {\n\t\t\t// Prefer the shadow root's activeElement so focus tracking works\n\t\t\t// even when the widget is mounted inside a closed/open shadow DOM.\n\t\t\tconst root = win.getRootNode();\n\t\t\tif (root instanceof ShadowRoot) return root.activeElement;\n\t\t\treturn document.activeElement;\n\t\t};\n\t\tconst handleTab = (e: KeyboardEvent) => {\n\t\t\tif (e.key !== \"Tab\") return;\n\t\t\tconst focusable = getFocusable();\n\t\t\tif (focusable.length === 0) return;\n\t\t\tconst first = focusable[0];\n\t\t\tconst last = focusable[focusable.length - 1];\n\t\t\tconst active = getActive();\n\t\t\tif (e.shiftKey && active === first) {\n\t\t\t\te.preventDefault();\n\t\t\t\tlast?.focus();\n\t\t\t} else if (!e.shiftKey && active === last) {\n\t\t\t\te.preventDefault();\n\t\t\t\tfirst?.focus();\n\t\t\t}\n\t\t};\n\t\twin.addEventListener(\"keydown\", handleTab);\n\t\tconst focusable = getFocusable();\n\t\tif (focusable.length > 0) focusable[0]?.focus();\n\t\treturn () => win.removeEventListener(\"keydown\", handleTab);\n\t}, [isOpen, hideLauncher]);\n\n\tconst showTabBar = subView === null;\n\tconst activeConvSummary = useWidgetStore((s) => {\n\t\tconst id = s.activeConversationId;\n\t\treturn id ? s.conversations.find((c) => c.id === id) : null;\n\t});\n\t// Header name resolution mirrors WidgetLogo's avatar resolution:\n\t// 1. Assigned support user (sticky once a human takes over)\n\t// 2. Last team-side sender (in case there's no formal assignment\n\t// but a teammate jumped in for one message)\n\t// 3. AI agent name / website name\n\tconst assigneeName = activeConvSummary?.assigneeName;\n\tconst hasTeamAgent =\n\t\tactiveConvSummary?.lastMessageSenderType === \"team\" &&\n\t\tactiveConvSummary?.lastMessageSenderName;\n\tconst headerName = assigneeName\n\t\t? assigneeName\n\t\t: hasTeamAgent\n\t\t\t? activeConvSummary.lastMessageSenderName!\n\t\t\t: (agentConfig?.name ?? website?.name ?? \"Support\");\n\tconst companyName = agentConfig?.name ?? website?.name ?? \"Support\";\n\tconst subtitleMsg = agentConfig?.subtitleText;\n\tconst subtitleIsFactoryDefault =\n\t\t!subtitleMsg || subtitleMsg === DEFAULT_EN_SUBTITLE;\n\tconst subtitleText = subtitleMsg?.startsWith(\"widget.\")\n\t\t? t(subtitleMsg)\n\t\t: subtitleIsFactoryDefault\n\t\t\t? t(\"widget.subtitle_text\")\n\t\t\t: subtitleMsg;\n\tconst brandColor = agentConfig?.brandColor ?? \"#0a0a0a\";\n\tconst widgetPosition = agentConfig?.widgetPosition ?? \"bottom-right\";\n\tconst launcherStyle = agentConfig?.launcherStyle ?? \"icon\";\n\tconst bubbleStyle = agentConfig?.bubbleStyle ?? \"rounded\";\n\n\t// Smart default: when the org uploaded a logo as the agent avatar\n\t// (vs a face photo), tint the chat-header circle with the brand\n\t// color and switch the image to `contain` so the mark isn't cropped.\n\t// `--hw-agent-bg-default` is consumed by the styles.css fallback\n\t// chain — site-side `:root { --hw-agent-bg: ... }` still wins.\n\tconst hasUploadedAvatar = !!agentConfig?.avatarUrl;\n\n\treturn (\n\t\t<div\n\t\t\tclassName=\"hw-widget\"\n\t\t\tdata-has-avatar={hasUploadedAvatar ? \"true\" : \"false\"}\n\t\t\tstyle={\n\t\t\t\t{\n\t\t\t\t\t\"--hw-primary\": brandColor,\n\t\t\t\t\t\"--hw-position-right\": widgetPosition === \"bottom-right\" ? \"20px\" : \"auto\",\n\t\t\t\t\t\"--hw-position-left\": widgetPosition === \"bottom-left\" ? \"20px\" : \"auto\",\n\t\t\t\t\t\"--hw-window-right\": widgetPosition === \"bottom-right\" ? \"0\" : \"auto\",\n\t\t\t\t\t\"--hw-window-left\": widgetPosition === \"bottom-left\" ? \"0\" : \"auto\",\n\t\t\t\t} as React.CSSProperties\n\t\t\t}\n\t\t>\n\t\t\t{isOpen && !isReady && !hasBootstrapError && (\n\t\t\t\t<div className={`hw-window ${isClosing ? \"hw-window--closing\" : \"\"}`}>\n\t\t\t\t\t<div className=\"hw-skeleton-loading\">\n\t\t\t\t\t\t<div className=\"hw-skeleton hw-skeleton-line\" style={{ width: 120 }} />\n\t\t\t\t\t\t<div className=\"hw-skeleton hw-skeleton-line\" style={{ width: 200 }} />\n\t\t\t\t\t\t<div className=\"hw-skeleton hw-skeleton-line\" style={{ width: 160 }} />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t{isOpen && hasBootstrapError && (\n\t\t\t\t<div className={`hw-window ${isClosing ? \"hw-window--closing\" : \"\"}`}>\n\t\t\t\t\t<div className=\"hw-bootstrap-error\">\n\t\t\t\t\t\t<div className=\"hw-bootstrap-error-text\">{t(\"widget.error_desc\")}</div>\n\t\t\t\t\t\t<button type=\"button\" className=\"hw-bootstrap-error-retry\" onClick={retryBootstrap}>\n\t\t\t\t\t\t\t{t(\"widget.retry\")}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t{isOpen && isReady && (\n\t\t\t\t<div\n\t\t\t\t\tref={windowRef}\n\t\t\t\t\tclassName={`hw-window ${isClosing ? \"hw-window--closing\" : \"\"} ${\n\t\t\t\t\t\tsubView === \"content-detail\" ? \"hw-window--reading\" : \"\"\n\t\t\t\t\t}`}\n\t\t\t\t\trole=\"dialog\"\n\t\t\t\t\taria-label={t(\"widget.aria_chat\")}\n\t\t\t\t\taria-modal=\"true\"\n\t\t\t\t\tonTouchStart={handleTouchStart}\n\t\t\t\t\tonTouchMove={handleTouchMove}\n\t\t\t\t\tonTouchEnd={handleTouchEnd}\n\t\t\t\t>\n\t\t\t\t\t{/* Drag handle for mobile swipe-down */}\n\t\t\t\t\t<div className=\"hw-drag-handle\">\n\t\t\t\t\t\t<div className=\"hw-drag-handle-pill\" />\n\t\t\t\t\t</div>\n\t\t\t\t\t{/* WebSocket disconnect banner */}\n\t\t\t\t\t{wsDisconnected && (\n\t\t\t\t\t\t<div className=\"hw-disconnect\">\n\t\t\t\t\t\t\t<div className=\"hw-disconnect-dot\" />\n\t\t\t\t\t\t\t{t(\"widget.reconnecting\")}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t\t{/* ── Sub-view header: content-detail/content-category gets centered title ── */}\n\t\t\t\t\t{(subView === \"content-detail\" || subView === \"content-category\") &&\n\t\t\t\t\t\t(() => {\n\t\t\t\t\t\t\tconst tabId = activeTab.replace(\"content:\", \"\");\n\t\t\t\t\t\t\tconst contentTab = contentTabs.find((t) => t.id === tabId);\n\t\t\t\t\t\t\t// Show category name when viewing items within a category\n\t\t\t\t\t\t\tconst headerTitle =\n\t\t\t\t\t\t\t\tsubView === \"content-category\" && contentCategoryName\n\t\t\t\t\t\t\t\t\t? contentCategoryName\n\t\t\t\t\t\t\t\t\t: contentTab?.label\n\t\t\t\t\t\t\t\t\t\t? resolveLabel(contentTab.label)\n\t\t\t\t\t\t\t\t\t\t: t(\"widget.content\");\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<div className=\"hw-header hw-header--centered\">\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"hw-header-back\"\n\t\t\t\t\t\t\t\t\t\tonClick={goBack}\n\t\t\t\t\t\t\t\t\t\taria-label={t(\"widget.aria_back\")}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\t\t\t\tstrokeWidth={2}\n\t\t\t\t\t\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<path d=\"M15 18l-6-6 6-6\" />\n\t\t\t\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t<div className=\"hw-header-title\">{headerTitle}</div>\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"hw-header-close\"\n\t\t\t\t\t\t\t\t\t\tonClick={handleClose}\n\t\t\t\t\t\t\t\t\t\taria-label={t(\"widget.aria_close\")}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<XIcon size={20} />\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})()}\n\t\t\t\t\t{subView !== null && subView !== \"content-detail\" && subView !== \"content-category\" && (\n\t\t\t\t\t\t<div className=\"hw-header hw-header--sub\">\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclassName=\"hw-header-back\"\n\t\t\t\t\t\t\t\tonClick={goBack}\n\t\t\t\t\t\t\t\taria-label={t(\"widget.aria_back\")}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\t\tstrokeWidth={2}\n\t\t\t\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<path d=\"M15 18l-6-6 6-6\" />\n\t\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t<div className=\"hw-header-identity\">\n\t\t\t\t\t\t\t\t<div className={`hw-header-bot-icon${hasTeamAgent ? \" hw-header-bot-icon--team\" : \"\"}`}>\n\t\t\t\t\t\t\t\t\t{hasTeamAgent && activeConvSummary?.lastMessageSenderImage ? (\n\t\t\t\t\t\t\t\t\t\t<img src={activeConvSummary.lastMessageSenderImage} alt={headerName} className=\"hw-header-agent-img\" />\n\t\t\t\t\t\t\t\t\t) : hasTeamAgent ? (\n\t\t\t\t\t\t\t\t\t\t<span className=\"hw-header-agent-initials\">\n\t\t\t\t\t\t\t\t\t\t\t{headerName.split(\" \").map((w: string) => w[0]).join(\"\").slice(0, 2).toUpperCase()}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t<WidgetLogo />\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div className=\"hw-header-info\">\n\t\t\t\t\t\t\t\t\t<div className=\"hw-header-name\">{headerName}</div>\n\t\t\t\t\t\t\t\t\t{/* Keep the subtitle identical in both \"new\" and \"conversation\"\n\t\t\t\t\t\t\t\t\t sub-views — otherwise the header reads \"New conversation\"\n\t\t\t\t\t\t\t\t\t while composing and snaps to \"Usually replies in minutes\"\n\t\t\t\t\t\t\t\t\t the moment you send, which feels like the whole header\n\t\t\t\t\t\t\t\t\t rebuilt. */}\n\t\t\t\t\t\t\t\t\t<div className=\"hw-header-status\">{subtitleText}</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclassName=\"hw-header-close\"\n\t\t\t\t\t\t\t\tonClick={handleClose}\n\t\t\t\t\t\t\t\taria-label={t(\"widget.aria_close\")}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<XIcon size={20} />\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{/* ── Home: hero header with gradient + sheet overlay ── */}\n\t\t\t\t\t{subView === null && activeTab === \"home\" && (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<div className=\"hw-hero\">\n\t\t\t\t\t\t\t\t<div className=\"hw-hero-top\">\n\t\t\t\t\t\t\t\t\t<div className=\"hw-hero-bot-icon\">\n\t\t\t\t\t\t\t\t\t\t<WidgetLogo />\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"hw-hero-close\"\n\t\t\t\t\t\t\t\t\t\tonClick={handleClose}\n\t\t\t\t\t\t\t\t\t\taria-label={t(\"widget.aria_close\")}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<XIcon size={20} />\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div className=\"hw-hero-greeting\">\n\t\t\t\t\t\t\t\t\t{welcomeMessage.split(\"\\n\").map((line, i) => (\n\t\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\t\tkey={i}\n\t\t\t\t\t\t\t\t\t\t\tclassName={i === 0 ? \"hw-hero-greeting-name\" : \"hw-hero-greeting-question\"}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{i > 0 && <br />}\n\t\t\t\t\t\t\t\t\t\t\t{line}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div className=\"hw-hero-subtitle\">{subtitleText}</div>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t{/* Sheet — overlaps hero, Intercom-style white drawer */}\n\t\t\t\t\t\t\t<div className=\"hw-sheet\">\n\t\t\t\t\t\t\t\t<div className=\"hw-sheet-inner\">\n\t\t\t\t\t\t\t\t\t<button type=\"button\" className=\"hw-card\" onClick={openNewConversation}>\n\t\t\t\t\t\t\t\t\t\t<div className=\"hw-card-body\">\n\t\t\t\t\t\t\t\t\t\t\t<div className=\"hw-card-title\">{t(\"widget.send_us_message\")}</div>\n\t\t\t\t\t\t\t\t\t\t\t<div className=\"hw-card-meta\">{t(\"widget.reply_time\")}</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t<div className=\"hw-card-arrow\">\n\t\t\t\t\t\t\t\t\t\t\t<SendIcon />\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t{announcementTabs.length > 0 && (\n\t\t\t\t\t\t\t\t\t\t<WhatsNewCard\n\t\t\t\t\t\t\t\t\t\t\tgetUnseenEntries={getUnseenEntries}\n\t\t\t\t\t\t\t\t\t\t\tannouncementTabs={announcementTabs}\n\t\t\t\t\t\t\t\t\t\t\tonViewAll={() => {\n\t\t\t\t\t\t\t\t\t\t\t\tswitchTab(`content:${announcementTabs[0]!.id}`);\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\tonSelect={(slug, tabId) => {\n\t\t\t\t\t\t\t\t\t\t\t\tswitchTab(`content:${tabId}`);\n\t\t\t\t\t\t\t\t\t\t\t\tsetContentDetailSlug(slug);\n\t\t\t\t\t\t\t\t\t\t\t\tsetSubView(\"content-detail\");\n\t\t\t\t\t\t\t\t\t\t\t\tmarkEntrySeen(slug);\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t<HomeView\n\t\t\t\t\t\t\t\t\t\tconversations={conversations}\n\t\t\t\t\t\t\t\t\t\tonSelect={openConversation}\n\t\t\t\t\t\t\t\t\t\tonMessagesClick={() => switchTab(\"messages\")}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{/* ── Messages tab header ── */}\n\t\t\t\t\t{subView === null && activeTab === \"messages\" && (\n\t\t\t\t\t\t<div className=\"hw-header hw-header--centered\">\n\t\t\t\t\t\t\t<div className=\"hw-header-spacer\" />\n\t\t\t\t\t\t\t<div className=\"hw-header-title\">{t(\"widget.messages\")}</div>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclassName=\"hw-header-close\"\n\t\t\t\t\t\t\t\tonClick={handleClose}\n\t\t\t\t\t\t\t\taria-label={t(\"widget.aria_close\")}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<XIcon size={20} />\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{/* ── Content tab header (list view, not detail) ── */}\n\t\t\t\t\t{subView === null &&\n\t\t\t\t\t\tactiveTab.startsWith(\"content:\") &&\n\t\t\t\t\t\t(() => {\n\t\t\t\t\t\t\tconst tabId = activeTab.replace(\"content:\", \"\");\n\t\t\t\t\t\t\tconst contentTab = contentTabs.find((t) => t.id === tabId);\n\t\t\t\t\t\t\tif (!contentTab) return null;\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<div className=\"hw-header hw-header--centered\">\n\t\t\t\t\t\t\t\t\t<div className=\"hw-header-spacer\" />\n\t\t\t\t\t\t\t\t\t<div className=\"hw-header-title\">{resolveLabel(contentTab.label)}</div>\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"hw-header-close\"\n\t\t\t\t\t\t\t\t\t\tonClick={handleClose}\n\t\t\t\t\t\t\t\t\t\taria-label={t(\"widget.aria_close\")}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<XIcon size={20} />\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})()}\n\n\t\t\t\t\t{/* ── Content (non-home views) ── */}\n\t\t\t\t\t{(subView !== null || activeTab !== \"home\") && (\n\t\t\t\t\t\t<div className=\"hw-content\">\n\t\t\t\t\t\t\t{subView === null && activeTab === \"messages\" && (\n\t\t\t\t\t\t\t\t<MessagesView\n\t\t\t\t\t\t\t\t\tconversations={conversations}\n\t\t\t\t\t\t\t\t\tonSelect={openConversation}\n\t\t\t\t\t\t\t\t\tonNewClick={openNewConversation}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t{subView === \"new\" && (\n\t\t\t\t\t\t\t\t<NewConversationView\n\t\t\t\t\t\t\t\t\ttext={newText}\n\t\t\t\t\t\t\t\t\tonTextChange={setNewText}\n\t\t\t\t\t\t\t\t\tonSubmit={handleNewConversation}\n\t\t\t\t\t\t\t\t\tisSubmitting={isCreating}\n\t\t\t\t\t\t\t\t\twelcomeMessage={welcomeMessage}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t{subView === \"conversation\" && activeId && (\n\t\t\t\t\t\t\t\t<ConversationView conversationId={activeId} />\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t{/* ── Content tab views ── */}\n\t\t\t\t\t\t\t{activeTab.startsWith(\"content:\") &&\n\t\t\t\t\t\t\t\t(() => {\n\t\t\t\t\t\t\t\t\tconst tabId = activeTab.replace(\"content:\", \"\");\n\t\t\t\t\t\t\t\t\tconst contentTab = contentTabs.find((t) => t.id === tabId);\n\t\t\t\t\t\t\t\t\tif (!contentTab) return null;\n\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t<ContentTabView\n\t\t\t\t\t\t\t\t\t\t\ttab={contentTab}\n\t\t\t\t\t\t\t\t\t\t\tshowDetail={subView === \"content-detail\"}\n\t\t\t\t\t\t\t\t\t\t\tdetailSlug={contentDetailSlug}\n\t\t\t\t\t\t\t\t\t\t\tsubView={subView}\n\t\t\t\t\t\t\t\t\t\t\tonSelectEntry={(slug) => {\n\t\t\t\t\t\t\t\t\t\t\t\tsetContentDetailSlug(slug);\n\t\t\t\t\t\t\t\t\t\t\t\tsetSubView(\"content-detail\");\n\t\t\t\t\t\t\t\t\t\t\t\t// Mark seen on open, mirroring the home-tab and\n\t\t\t\t\t\t\t\t\t\t\t\t// deep-link paths. Without this, opening a changelog\n\t\t\t\t\t\t\t\t\t\t\t\t// entry from the content tab left the unseen badge\n\t\t\t\t\t\t\t\t\t\t\t\t// stuck until another path happened to clear it.\n\t\t\t\t\t\t\t\t\t\t\t\tmarkEntrySeen(slug);\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\tonSelectCategory={(cat) => {\n\t\t\t\t\t\t\t\t\t\t\t\tsetContentCategoryName(cat.title);\n\t\t\t\t\t\t\t\t\t\t\t\tsetSubView(\"content-category\");\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t})()}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{/* ── Tab Bar ── */}\n\t\t\t\t\t{showTabBar && (\n\t\t\t\t\t\t<TabBar\n\t\t\t\t\t\t\tactiveTab={activeTab}\n\t\t\t\t\t\t\tonTabChange={switchTab}\n\t\t\t\t\t\t\tunreadCount={totalUnread}\n\t\t\t\t\t\t\tcontentTabs={contentTabs}\n\t\t\t\t\t\t\tshowMessagesTab={agentConfig?.showMessagesTab ?? true}\n\t\t\t\t\t\t\tunseenAnnouncementCount={unseenAnnouncementCount}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{/* ── Footer ── */}\n\t\t\t\t\t<div className=\"hw-powered\">\n\t\t\t\t\t\t{t(\"widget.powered_by\")}{\" \"}\n\t\t\t\t\t\t<a href=\"https://helpway.ai\" target=\"_blank\" rel=\"noopener noreferrer\">\n\t\t\t\t\t\t\tHelpway\n\t\t\t\t\t\t</a>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Message Preview — shown when widget is closed and not dismissed.\n\t\t\t Gated on isReady alongside the bubble so the proactive teaser\n\t\t\t doesn't pop in with default content before bootstrap. */}\n\t\t\t{isReady && !isOpen && !isDismissed && !hideLauncher && (\n\t\t\t\t<MessagePreview onOpen={handleBubbleClick} avatar={<WidgetLogo />} />\n\t\t\t)}\n\n\t\t\t{/* Announcement Previews — shown when widget is closed and unseen announcements exist */}\n\t\t\t{isReady && !isOpen && !isDismissed && !hideLauncher && (\n\t\t\t\t<AnnouncementPreviews\n\t\t\t\t\tavatar={<WidgetLogo />}\n\t\t\t\t\tonOpen={(slug, tabId) => {\n\t\t\t\t\t\tmarkEntrySeen(slug);\n\t\t\t\t\t\thandleBubbleClick();\n\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\tswitchTab(`content:${tabId}`);\n\t\t\t\t\t\t\tsetContentDetailSlug(slug);\n\t\t\t\t\t\t\tsetSubView(\"content-detail\");\n\t\t\t\t\t\t}, 50);\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t{/* Dev-only debug overlay — activates via ?hwdebug=1 or localStorage hw:debug=1 */}\n\t\t\t<WidgetDebugOverlay />\n\n\t\t\t{/* Bubble — hidden until bootstrap completes so visitors don't\n\t\t\t see a flash of the default Helpway brand mark + neutral\n\t\t\t color before the org's custom icon + brand color arrive.\n\t\t\t isReady flips true once and stays true, so the bubble\n\t\t\t remains visible across the rest of the session. */}\n\t\t\t{isReady && !isDismissed && (!hideLauncher || isOpen) && (\n\t\t\t\t<button\n\t\t\t\t\tref={bubbleRef}\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName={[\n\t\t\t\t\t\t\"hw-bubble\",\n\t\t\t\t\t\t`hw-bubble--${bubbleStyle}`,\n\t\t\t\t\t\tlauncherStyle !== \"icon\" ? `hw-bubble--launcher-${launcherStyle}` : \"\",\n\t\t\t\t\t\tisOpen ? \"hw-bubble--open\" : \"\",\n\t\t\t\t\t\t(agentConfig?.launcherIconUrl || agentConfig?.avatarUrl || website?.logoUrl) ? \"hw-bubble--avatar\" : \"\",\n\t\t\t\t\t]\n\t\t\t\t\t\t.filter(Boolean)\n\t\t\t\t\t\t.join(\" \")}\n\t\t\t\t\tonClick={handleBubbleClick}\n\t\t\t\t\taria-label={isOpen ? t(\"widget.aria_close_support\") : t(\"widget.aria_open\")}\n\t\t\t\t\taria-expanded={isOpen}\n\t\t\t\t\taria-haspopup=\"dialog\"\n\t\t\t\t>\n\t\t\t\t\t<span\n\t\t\t\t\t\tclassName={`hw-bubble-icon hw-bubble-icon--bot ${isOpen ? \"hw-bubble-icon--hidden\" : \"\"}`}\n\t\t\t\t\t>\n\t\t\t\t\t\t<LauncherIcon />\n\t\t\t\t\t</span>\n\t\t\t\t\t<span\n\t\t\t\t\t\tclassName={`hw-bubble-icon hw-bubble-icon--close ${!isOpen ? \"hw-bubble-icon--hidden\" : \"\"}`}\n\t\t\t\t\t>\n\t\t\t\t\t\t<XIcon size={24} />\n\t\t\t\t\t</span>\n\t\t\t\t\t{launcherStyle !== \"icon\" && !isOpen && (\n\t\t\t\t\t\t<span className=\"hw-bubble-label\">\n\t\t\t\t\t\t\t{launcherStyle === \"help\" ? t(\"widget.help\") : companyName}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t)}\n\t\t\t\t\t{!isOpen && (totalUnread > 0 || unseenAnnouncementCount > 0) && (\n\t\t\t\t\t\t<div className=\"hw-bubble-badge\">\n\t\t\t\t\t\t\t{totalUnread > 0 ? totalUnread : \"\"}\n\t\t\t\t\t\t\t{totalUnread === 0 && unseenAnnouncementCount > 0 && (\n\t\t\t\t\t\t\t\t<span className=\"hw-bubble-badge-dot\" />\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</button>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\n// ── Tab Bar ─────────────────────────────────────────────\n\nfunction TabBar({\n\tactiveTab,\n\tonTabChange,\n\tunreadCount,\n\tcontentTabs,\n\tshowMessagesTab = true,\n\tunseenAnnouncementCount = 0,\n}: {\n\tactiveTab: Tab;\n\tonTabChange: (tab: Tab) => void;\n\tunreadCount: number;\n\tcontentTabs: WidgetContentTab[];\n\tshowMessagesTab?: boolean;\n\tunseenAnnouncementCount?: number;\n}) {\n\treturn (\n\t\t<div className=\"hw-tabs\" role=\"tablist\">\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tclassName={`hw-tabs-item ${activeTab === \"home\" ? \"hw-tabs-item--active\" : \"\"}`}\n\t\t\t\tonClick={() => onTabChange(\"home\")}\n\t\t\t\trole=\"tab\"\n\t\t\t\taria-selected={activeTab === \"home\"}\n\t\t\t>\n\t\t\t\t<HomeIcon />\n\t\t\t\t<span>{t(\"widget.home\")}</span>\n\t\t\t</button>\n\t\t\t{showMessagesTab && (\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName={`hw-tabs-item ${activeTab === \"messages\" ? \"hw-tabs-item--active\" : \"\"}`}\n\t\t\t\t\tonClick={() => onTabChange(\"messages\")}\n\t\t\t\t\trole=\"tab\"\n\t\t\t\t\taria-selected={activeTab === \"messages\"}\n\t\t\t\t>\n\t\t\t\t\t<span className=\"hw-tabs-icon-wrap\">\n\t\t\t\t\t\t<MessagesIcon />\n\t\t\t\t\t\t{unreadCount > 0 && (\n\t\t\t\t\t\t\t<span className=\"hw-tabs-badge\">{unreadCount > 99 ? \"99+\" : unreadCount}</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</span>\n\t\t\t\t\t<span>{t(\"widget.messages\")}</span>\n\t\t\t\t</button>\n\t\t\t)}\n\t\t\t{/* Dynamic content tabs from Better i18n Content CMS */}\n\t\t\t{contentTabs.map((tab) => (\n\t\t\t\t<button\n\t\t\t\t\tkey={tab.id}\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName={`hw-tabs-item ${activeTab === `content:${tab.id}` ? \"hw-tabs-item--active\" : \"\"}`}\n\t\t\t\t\tonClick={() => onTabChange(`content:${tab.id}`)}\n\t\t\t\t\trole=\"tab\"\n\t\t\t\t\taria-selected={activeTab === `content:${tab.id}`}\n\t\t\t\t>\n\t\t\t\t\t<span className=\"hw-tabs-icon-wrap\">\n\t\t\t\t\t\t<ContentTabIconComponent icon={tab.icon} />\n\t\t\t\t\t\t{tab.isAnnouncements && unseenAnnouncementCount > 0 && (\n\t\t\t\t\t\t\t<span className=\"hw-tabs-dot\" />\n\t\t\t\t\t\t)}\n\t\t\t\t\t</span>\n\t\t\t\t\t<span>{resolveLabel(tab.label)}</span>\n\t\t\t\t</button>\n\t\t\t))}\n\t\t</div>\n\t);\n}\n\n// ── Home Tab ────────────────────────────────────────────\n\nfunction HomeView({\n\tconversations,\n\tonSelect,\n\tonMessagesClick,\n}: {\n\tconversations: ConversationSummary[];\n\tonSelect: (id: string) => void;\n\tonMessagesClick: () => void;\n}) {\n\tconst recent = conversations.slice(0, 3);\n\tif (recent.length === 0) return null;\n\n\treturn (\n\t\t<div className=\"hw-recent-card\">\n\t\t\t<div className=\"hw-recent-header\">{t(\"widget.recent_conversations\")}</div>\n\t\t\t{recent.map((conv, i) => (\n\t\t\t\t<ConversationRow\n\t\t\t\t\tkey={conv.id}\n\t\t\t\t\tconversation={conv}\n\t\t\t\t\tonSelect={onSelect}\n\t\t\t\t\tisLast={i === recent.length - 1}\n\t\t\t\t/>\n\t\t\t))}\n\t\t\t{conversations.length > 3 && (\n\t\t\t\t<button type=\"button\" className=\"hw-recent-see-all\" onClick={onMessagesClick}>\n\t\t\t\t\t{t(\"widget.see_all\")}\n\t\t\t\t</button>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\n// ── Messages Tab ────────────────────────────────────────\n\nfunction MessagesView({\n\tconversations,\n\tonSelect,\n\tonNewClick,\n}: {\n\tconversations: ConversationSummary[];\n\tonSelect: (id: string) => void;\n\tonNewClick: () => void;\n}) {\n\tif (conversations.length === 0) {\n\t\treturn (\n\t\t\t<div className=\"hw-empty-state\">\n\t\t\t\t<div className=\"hw-empty-icon-wrap\">\n\t\t\t\t\t<MessagesIcon />\n\t\t\t\t</div>\n\t\t\t\t<div className=\"hw-empty-title\">{t(\"widget.no_messages\")}</div>\n\t\t\t\t<div className=\"hw-empty-desc\">{t(\"widget.no_messages_desc\")}</div>\n\t\t\t\t<button type=\"button\" className=\"hw-empty-btn\" onClick={onNewClick}>\n\t\t\t\t\t{t(\"widget.start_conversation\")}\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<div className=\"hw-msgs-tab\">\n\t\t\t{conversations.map((conv) => (\n\t\t\t\t<ConversationCard key={conv.id} conversation={conv} onSelect={onSelect} />\n\t\t\t))}\n\t\t</div>\n\t);\n}\n\n// ── Shared conversation body (avatar + name + time + preview) ──\n\nfunction ConvCardBody({ conv }: { conv: ConversationSummary }) {\n\tconst agentName = useWidgetStore((s) => s.agentConfig?.name) ?? \"Support\";\n\tconst isTeam = conv.lastMessageSenderType === \"team\" && conv.lastMessageSenderName;\n\tconst displayName = isTeam ? conv.lastMessageSenderName! : agentName;\n\tconst preview = conv.lastMessageText ?? t(\"widget.no_preview\");\n\treturn (\n\t\t<>\n\t\t\t<div className={`hw-conv-card-avatar${isTeam ? \" hw-conv-card-avatar--team\" : \"\"}`}>\n\t\t\t\t{isTeam ? (\n\t\t\t\t\tconv.lastMessageSenderImage ? (\n\t\t\t\t\t\t<img src={conv.lastMessageSenderImage} alt={displayName} className=\"hw-conv-card-avatar-img\" />\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<span className=\"hw-conv-card-avatar-initials\">\n\t\t\t\t\t\t\t{displayName.split(\" \").map((w) => w[0]).join(\"\").slice(0, 2).toUpperCase()}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t)\n\t\t\t\t) : (\n\t\t\t\t\t<WidgetLogo />\n\t\t\t\t)}\n\t\t\t</div>\n\t\t\t<div className=\"hw-conv-card-content\">\n\t\t\t\t<div className=\"hw-conv-card-top\">\n\t\t\t\t\t<span className=\"hw-conv-card-name\">{displayName}</span>\n\t\t\t\t\t{conv.lastMessageAt && (\n\t\t\t\t\t\t<span className=\"hw-conv-card-time\">{formatRelativeTime(conv.lastMessageAt)}</span>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t<div className=\"hw-conv-card-preview\">{preview}</div>\n\t\t\t</div>\n\t\t</>\n\t);\n}\n\n// ── Conversation Card (Intercom-style, Messages tab) ─────\n\nfunction ConversationCard({\n\tconversation: conv,\n\tonSelect,\n}: {\n\tconversation: ConversationSummary;\n\tonSelect: (id: string) => void;\n}) {\n\tconst hasUnread = conv.unreadCount > 0;\n\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tclassName={`hw-conv-card ${hasUnread ? \"hw-conv-card--unread\" : \"\"}`}\n\t\t\tonClick={() => onSelect(conv.id)}\n\t\t>\n\t\t\t<div className=\"hw-conv-card-row\">\n\t\t\t\t<ConvCardBody conv={conv} />\n\t\t\t</div>\n\t\t\t{hasUnread && <div className=\"hw-conv-card-badge\">{conv.unreadCount}</div>}\n\t\t</button>\n\t);\n}\n\n// ── Conversation Row (inside Home tab grouped card) ───────\n\nfunction ConversationRow({\n\tconversation: conv,\n\tonSelect,\n\tisLast,\n}: {\n\tconversation: ConversationSummary;\n\tonSelect: (id: string) => void;\n\tisLast: boolean;\n}) {\n\tconst hasUnread = conv.unreadCount > 0;\n\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tclassName={`hw-recent-row ${hasUnread ? \"hw-recent-row--unread\" : \"\"} ${isLast ? \"hw-recent-row--last\" : \"\"}`}\n\t\t\tonClick={() => onSelect(conv.id)}\n\t\t>\n\t\t\t<ConvCardBody conv={conv} />\n\t\t\t{hasUnread && <div className=\"hw-recent-row-badge\">{conv.unreadCount}</div>}\n\t\t</button>\n\t);\n}\n\n// ── Inline Email Prompt (post-first-reply) ─────────────\n\nfunction InlineEmailPrompt({ conversationId }: { conversationId?: string }) {\n\tconst { client, store } = useWidgetContext();\n\tconst updateContact = useWidgetStore((s) => s.updateVisitorContact);\n\tconst [email, setEmail] = useState(\"\");\n\tconst [isSubmitting, setIsSubmitting] = useState(false);\n\tconst [isSuccess, setIsSuccess] = useState(false);\n\tconst [hasError, setHasError] = useState(false);\n\n\tconst handleSubmit = async () => {\n\t\tconst trimmed = email.trim();\n\t\tif (!trimmed || !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(trimmed)) {\n\t\t\tsetHasError(true);\n\t\t\treturn;\n\t\t}\n\t\tsetHasError(false);\n\n\t\tconst previousContact = store.getState().visitor?.contact ?? null;\n\t\tconst optimisticContactId = previousContact?.id ?? `optimistic-contact-${Date.now()}`;\n\t\tupdateContact({\n\t\t\tid: optimisticContactId,\n\t\t\tname: previousContact?.name ?? null,\n\t\t\temail: trimmed,\n\t\t});\n\t\tsetIsSuccess(true);\n\t\tsetIsSubmitting(true);\n\t\ttry {\n\t\t\tconst result = await client.widget.collectEmail.mutate({\n\t\t\t\temail: trimmed,\n\t\t\t\t...(conversationId ? { conversationId } : {}),\n\t\t\t});\n\t\t\tif (result.contact) {\n\t\t\t\tupdateContact({\n\t\t\t\t\tid: result.contact.id,\n\t\t\t\t\tname: result.contact.name,\n\t\t\t\t\temail: result.contact.email,\n\t\t\t\t});\n\t\t\t}\n\t\t\t// needsEmail will become false via optimistic contact update\n\t\t} catch {\n\t\t\tif (previousContact) {\n\t\t\t\tupdateContact(previousContact);\n\t\t\t} else {\n\t\t\t\tupdateContact({ id: \"\", name: null, email: null });\n\t\t\t}\n\t\t\tsetIsSuccess(false);\n\t\t} finally {\n\t\t\tsetIsSubmitting(false);\n\t\t}\n\t};\n\n\tif (isSuccess) {\n\t\treturn (\n\t\t\t<div className=\"hw-email-card hw-email-card--success\">\n\t\t\t\t<svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#22c55e\" strokeWidth={2.5} strokeLinecap=\"round\" strokeLinejoin=\"round\">\n\t\t\t\t\t<polyline points=\"20 6 9 17 4 12\" />\n\t\t\t\t</svg>\n\t\t\t\t{t(\"widget.email_saved\")}\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<div className=\"hw-email-card\">\n\t\t\t<div className=\"hw-email-card-header\">\n\t\t\t\t<div className=\"hw-email-card-icon\">\n\t\t\t\t\t<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\">\n\t\t\t\t\t\t<rect x=\"2\" y=\"4\" width=\"20\" height=\"16\" rx=\"2\" />\n\t\t\t\t\t\t<path d=\"M22 7l-10 7L2 7\" />\n\t\t\t\t\t</svg>\n\t\t\t\t</div>\n\t\t\t\t<div>\n\t\t\t\t\t<p className=\"hw-email-card-title\">{t(\"widget.email_title\")}</p>\n\t\t\t\t\t<p className=\"hw-email-card-subtitle\">{t(\"widget.email_subtitle\")}</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<input\n\t\t\t\ttype=\"email\"\n\t\t\t\tclassName={`hw-email-card-input${hasError ? \" hw-email-card-input--error\" : \"\"}`}\n\t\t\t\tvalue={email}\n\t\t\t\tonChange={(e) => { setEmail(e.target.value); setHasError(false); }}\n\t\t\t\tonKeyDown={(e) => { if (e.key === \"Enter\") handleSubmit(); }}\n\t\t\t\tplaceholder={t(\"widget.email_placeholder\")}\n\t\t\t/>\n\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tclassName=\"hw-email-card-submit\"\n\t\t\t\tonClick={handleSubmit}\n\t\t\t\tdisabled={isSubmitting || !email.trim()}\n\t\t\t>\n\t\t\t\t{isSubmitting ? (\n\t\t\t\t\t<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2}>\n\t\t\t\t\t\t<circle cx=\"12\" cy=\"12\" r=\"10\" strokeDasharray=\"32\" strokeDashoffset=\"32\">\n\t\t\t\t\t\t\t<animate attributeName=\"stroke-dashoffset\" values=\"32;0\" dur=\"1s\" repeatCount=\"indefinite\" />\n\t\t\t\t\t\t</circle>\n\t\t\t\t\t</svg>\n\t\t\t\t) : t(\"widget.email_continue\")}\n\t\t\t</button>\n\n\t\t</div>\n\t);\n}\n\n// ── New Conversation ────────────────────────────────────\n\nfunction NewConversationView({\n\ttext,\n\tonTextChange,\n\tonSubmit,\n\tisSubmitting,\n\twelcomeMessage,\n}: {\n\ttext: string;\n\tonTextChange: (t: string) => void;\n\tonSubmit: () => void;\n\tisSubmitting: boolean;\n\twelcomeMessage: string;\n}) {\n\t// Stable timestamp so the bubble doesn't tick/re-render while the user types.\n\treturn (\n\t\t<div className=\"hw-new\">\n\t\t\t{/* Use the same MessageBubble that renders inside ConversationView so\n\t\t\t the welcome message looks IDENTICAL before and after the first send\n\t\t\t — same markdown rendering (line breaks preserved), same styles,\n\t\t\t same meta row. Without this the \"new\" view uses a raw string render\n\t\t\t and the user sees the bubble visually change the moment the\n\t\t\t conversation is created. */}\n\t\t\t<div className=\"hw-new-welcome\">\n\t\t\t\t<MessageBubble\n\t\t\t\t\ttext={welcomeMessage}\n\t\t\t\t\tsender=\"ai\"\n\t\t\t\t\tparts={null}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t\t<Composer\n\t\t\t\ttext={text}\n\t\t\t\tonTextChange={onTextChange}\n\t\t\t\tonSubmit={onSubmit}\n\t\t\t\tisSubmitting={isSubmitting}\n\t\t\t\tplaceholder={t(\"widget.placeholder_new\")}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n\n// ── Conversation View ───────────────────────────────────\n\nfunction ConversationView({ conversationId }: { conversationId: string }) {\n\tconst { items, isLoading, hasMore, loadMore } = useTimeline(conversationId);\n\tconst {\n\t\ttext,\n\t\tsetText,\n\t\tsubmit,\n\t\tisSubmitting,\n\t\tattachments,\n\t\taddFiles,\n\t\tremoveAttachment,\n\t\tsendError,\n\t\tclearSendError,\n\t\temailGateConvId,\n\t} = useComposer(conversationId);\n\tconst { isTyping, isAiProcessing, setTyping } = usePresence(conversationId);\n\tconst streamingText = useWidgetStore((s) => s.streamingText.get(conversationId) ?? \"\");\n\tconst agentConfig = useWidgetStore((s) => s.agentConfig);\n\tconst visitorContact = useWidgetStore((s) => s.visitor?.contact);\n\n\tconst isResolved = useWidgetStore((s) => {\n\t\tconst conv = s.conversations.find((c) => c.id === conversationId);\n\t\treturn conv?.status === \"resolved\";\n\t});\n\n\t// Email prompt gate (BETTER-227 — Intercom pattern).\n\t// Show ONLY after:\n\t// (1) visitor sent at least one real message (not the welcome bubble), AND\n\t// (2) AI has replied at least once (so the visitor has seen value from the widget)\n\t// Prevents the \"Get notified when we reply\" card from appearing on widget open\n\t// before the visitor has even typed. Matches Intercom's post-first-response flow.\n\tconst visitorMessageCount = items.filter(\n\t\t(it) => it.type === \"message\" && Boolean((it as { visitorId?: string | null }).visitorId),\n\t).length;\n\tconst hasAiReply = items.some(\n\t\t(it) => it.type === \"message\" && Boolean((it as { aiAgentId?: string | null }).aiAgentId),\n\t);\n\t// Email is satisfied if EITHER the contact has one (fully identified\n\t// visitor) OR the visitor itself has one (collected via the gate but\n\t// not yet linked to a Contact row). Without the visitor.email fallback,\n\t// the gate re-shows on every refresh until a Contact is created.\n\tconst visitorOwnEmail = useWidgetStore((s) => s.visitor?.email);\n\tconst hasEmail = !!visitorContact?.email || !!visitorOwnEmail;\n\tconst needsEmailPostReply =\n\t\t!!agentConfig?.requireVisitorEmail &&\n\t\t!hasEmail &&\n\t\tvisitorMessageCount >= 2 &&\n\t\thasAiReply;\n\tconst needsEmail = needsEmailPostReply || !!emailGateConvId;\n\n\tif (isLoading && items.length === 0) {\n\t\treturn (\n\t\t\t<div className=\"hw-messages\">\n\t\t\t\t<div className=\"hw-skeleton-messages\">\n\t\t\t\t\t{/* AI message skeleton */}\n\t\t\t\t\t<div className=\"hw-skeleton-msg\">\n\t\t\t\t\t\t<div className=\"hw-skeleton hw-skeleton-avatar\" />\n\t\t\t\t\t\t<div className=\"hw-skeleton-bubble\">\n\t\t\t\t\t\t\t<div className=\"hw-skeleton hw-skeleton-line\" style={{ width: 140 }} />\n\t\t\t\t\t\t\t<div className=\"hw-skeleton hw-skeleton-line\" style={{ width: 200 }} />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t{/* Visitor message skeleton */}\n\t\t\t\t\t<div className=\"hw-skeleton-msg hw-skeleton-msg--right\">\n\t\t\t\t\t\t<div className=\"hw-skeleton-bubble\" style={{ alignItems: \"flex-end\" }}>\n\t\t\t\t\t\t\t<div className=\"hw-skeleton hw-skeleton-line\" style={{ width: 160 }} />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t{/* AI reply skeleton */}\n\t\t\t\t\t<div className=\"hw-skeleton-msg\">\n\t\t\t\t\t\t<div className=\"hw-skeleton hw-skeleton-avatar\" />\n\t\t\t\t\t\t<div className=\"hw-skeleton-bubble\">\n\t\t\t\t\t\t\t<div className=\"hw-skeleton hw-skeleton-line\" style={{ width: 180 }} />\n\t\t\t\t\t\t\t<div className=\"hw-skeleton hw-skeleton-line\" style={{ width: 120 }} />\n\t\t\t\t\t\t\t<div className=\"hw-skeleton hw-skeleton-line\" style={{ width: 80 }} />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<>\n\t\t\t<MessageList\n\t\t\t\titems={items}\n\t\t\t\tisTyping={isTyping}\n\t\t\t\tisAiProcessing={isAiProcessing}\n\t\t\t\tstreamingText={streamingText || undefined}\n\t\t\t\thasMore={hasMore}\n\t\t\t\tisLoadingMore={isLoading}\n\t\t\t\tonLoadMore={loadMore}\n\t\t\t/>\n\t\t\t{/* Resolved → show the CSAT banner ABOVE the composer, never INSTEAD\n\t\t\t of it. Keeping the composer mounted means a follow-up just\n\t\t\t works: the server reopens the thread (widget.sendMessage →\n\t\t\t status: open) so resolved is never a dead-end. */}\n\t\t\t{isResolved && <ResolvedBanner conversationId={conversationId} />}\n\t\t\t{needsEmail && <InlineEmailPrompt conversationId={emailGateConvId ?? undefined} />}\n\t\t\t{sendError && (\n\t\t\t\t<div className=\"hw-send-error\">\n\t\t\t\t\t{sendError}\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"hw-send-error-retry\"\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tclearSendError();\n\t\t\t\t\t\t\tsubmit();\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"widget.retry\")}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t<Composer\n\t\t\t\ttext={text}\n\t\t\t\tonTextChange={setText}\n\t\t\t\tonSubmit={submit}\n\t\t\t\tonTyping={setTyping}\n\t\t\t\tisSubmitting={isSubmitting}\n\t\t\t\tattachments={attachments}\n\t\t\t\tonAddFiles={addFiles}\n\t\t\t\tonRemoveAttachment={removeAttachment}\n\t\t\t\tdisabled={needsEmail}\n\t\t\t/>\n\t\t</>\n\t);\n}\n\n// ── Resolved Banner with CSAT ───────────────────────────\n\nfunction ResolvedBanner({ conversationId }: { conversationId: string }) {\n\tconst { client } = useWidgetContext();\n\tconst [csatRating, setCsatRating] = useState<\"good\" | \"bad\" | null>(null);\n\tconst [csatSubmitted, setCsatSubmitted] = useState(false);\n\n\tconst handleCsat = (rating: \"good\" | \"bad\") => {\n\t\tsetCsatRating(rating);\n\t\tsetCsatSubmitted(true);\n\t\t// Send CSAT via API (fire and forget)\n\t\tclient.widget.sendCsat.mutate({ conversationId, rating }).catch(() => {});\n\t};\n\n\treturn (\n\t\t<div className=\"hw-resolved\">\n\t\t\t<div className=\"hw-resolved-text\">{t(\"widget.resolved_text\")}</div>\n\t\t\t{!csatSubmitted ? (\n\t\t\t\t<div className=\"hw-csat\">\n\t\t\t\t\t<div className=\"hw-csat-label\">{t(\"widget.csat_label\")}</div>\n\t\t\t\t\t<div className=\"hw-csat-buttons\">\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tclassName={`hw-csat-btn ${csatRating === \"good\" ? \"hw-csat-btn--selected\" : \"\"}`}\n\t\t\t\t\t\t\tonClick={() => handleCsat(\"good\")}\n\t\t\t\t\t\t\taria-label={t(\"widget.aria_good\")}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t👍\n\t\t\t\t\t\t</button>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tclassName={`hw-csat-btn ${csatRating === \"bad\" ? \"hw-csat-btn--selected\" : \"\"}`}\n\t\t\t\t\t\t\tonClick={() => handleCsat(\"bad\")}\n\t\t\t\t\t\t\taria-label={t(\"widget.aria_bad\")}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t👎\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t<div className=\"hw-csat-thanks\">{t(\"widget.csat_thanks\")}</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\n// ── Message Preview Bubble ─────────────────────\n// MessagePreview moved to ./message-preview.tsx so `hideLauncher`\n// integrations can render the same proactive bubble next to their own\n// trigger. DefaultWidget composes it with the launcher placement +\n// <WidgetLogo /> avatar above.\n\n// ── Announcement Preview Bubble ─────────────────\n// AnnouncementPreviews + AnnouncementPreviewItem (and the stripMarkdown\n// helper) moved to ./announcement-previews.tsx + ./strip-markdown.ts so\n// `hideLauncher` integrations can render the same proactive cards next\n// to their own trigger. DefaultWidget composes the export above with\n// the launcher placement + <WidgetLogo /> avatar.\n\n// ── What's New Card (Home tab) ──────────────────\n\nfunction WhatsNewCard({\n\tgetUnseenEntries,\n\tannouncementTabs,\n\tonViewAll,\n\tonSelect,\n}: {\n\tgetUnseenEntries: () => UnseenAnnouncementEntry[];\n\tannouncementTabs: WidgetContentTab[];\n\tonViewAll: () => void;\n\tonSelect: (slug: string, tabId: string) => void;\n}) {\n\tconst unseen = getUnseenEntries();\n\tif (unseen.length === 0) return null;\n\n\tconst display = unseen.slice(0, 3);\n\tconst badgeFieldMap = new Map(\n\t\tannouncementTabs.map((t) => [t.id, t.display?.badgeField]),\n\t);\n\n\treturn (\n\t\t<div className=\"hw-whats-new\">\n\t\t\t<div className=\"hw-whats-new-header\">\n\t\t\t\t<span className=\"hw-whats-new-title\">{resolveLabel(\"widget.whats_new\")}</span>\n\t\t\t\t<button type=\"button\" className=\"hw-whats-new-view-all\" onClick={onViewAll}>\n\t\t\t\t\t{resolveLabel(\"widget.view_all\")} →\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t\t<div className=\"hw-whats-new-list\">\n\t\t\t\t{display.map((entry) => {\n\t\t\t\t\tconst badgeField = badgeFieldMap.get(entry.tabId);\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\tkey={entry.slug}\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tclassName=\"hw-whats-new-item\"\n\t\t\t\t\t\t\tonClick={() => onSelect(entry.slug, entry.tabId)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{badgeField && entry.customFields[badgeField] && (\n\t\t\t\t\t\t\t\t<div className=\"hw-whats-new-item-top\">\n\t\t\t\t\t\t\t\t\t<span className=\"hw-whats-new-badge\">\n\t\t\t\t\t\t\t\t\t\t{entry.customFields[badgeField]}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t{entry.publishedAt && (\n\t\t\t\t\t\t\t\t\t\t<span className=\"hw-whats-new-time\">\n\t\t\t\t\t\t\t\t\t\t\t{formatRelativeTime(entry.publishedAt)}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t<div className=\"hw-whats-new-item-title\">\n\t\t\t\t\t\t\t\t{entry.title}\n\t\t\t\t\t\t\t\t{!badgeField && entry.publishedAt && (\n\t\t\t\t\t\t\t\t\t<span className=\"hw-whats-new-time-inline\">\n\t\t\t\t\t\t\t\t\t\t{formatRelativeTime(entry.publishedAt)}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t{entry.body && (() => {\n\t\t\t\t\t\t\t\tconst clean = stripMarkdown(entry.body);\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<div className=\"hw-whats-new-item-body\">\n\t\t\t\t\t\t\t\t\t\t{clean.length > 80 ? `${clean.slice(0, 80)}…` : clean}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t})()}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","import { CONTENT_CACHE_TTL, getLocale } from \"@helpway/widget-core\";\nimport type { WidgetContentTab } from \"@helpway/widget-core\";\nimport { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { useWidgetContext, useWidgetStore } from \"../provider\";\n\ninterface AnnouncementEntry {\n\tslug: string;\n\ttitle: string;\n\tbody: string | null;\n\tpublishedAt: string | null;\n\tcustomFields: Record<string, string | null>;\n}\n\nexport interface UnseenAnnouncementEntry extends AnnouncementEntry {\n\ttabId: string;\n}\n\n// ── Per-entry localStorage tracking ──\n\nfunction storageKey(websiteId: string, visitorId: string): string {\n\treturn `helpway:${websiteId}:${visitorId}:announcements:seen`;\n}\n\nfunction hasSeenKey(websiteId: string, visitorId: string): boolean {\n\ttry {\n\t\treturn localStorage.getItem(storageKey(websiteId, visitorId)) !== null;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction getSeenSlugs(websiteId: string, visitorId: string): Set<string> {\n\ttry {\n\t\tconst raw = localStorage.getItem(storageKey(websiteId, visitorId));\n\t\tif (!raw) return new Set();\n\t\treturn new Set(JSON.parse(raw) as string[]);\n\t} catch {\n\t\treturn new Set();\n\t}\n}\n\nfunction addSeenSlug(websiteId: string, visitorId: string, slug: string): void {\n\ttry {\n\t\tconst seen = getSeenSlugs(websiteId, visitorId);\n\t\tseen.add(slug);\n\t\tlocalStorage.setItem(storageKey(websiteId, visitorId), JSON.stringify([...seen]));\n\t} catch {\n\t\t// storage full or blocked\n\t}\n}\n\nfunction addSeenSlugs(websiteId: string, visitorId: string, slugs: string[]): void {\n\ttry {\n\t\tconst seen = getSeenSlugs(websiteId, visitorId);\n\t\tfor (const s of slugs) seen.add(s);\n\t\tlocalStorage.setItem(storageKey(websiteId, visitorId), JSON.stringify([...seen]));\n\t} catch {\n\t\t// storage full or blocked\n\t}\n}\n\nfunction filterUnseen(entries: AnnouncementEntry[], seen: Set<string>): AnnouncementEntry[] {\n\treturn entries.filter((e) => !seen.has(e.slug));\n}\n\nconst EMPTY_TABS: WidgetContentTab[] = [];\n\n/**\n * Per-entry announcement tracking across all tabs with isAnnouncements.\n *\n * Anonymous visitors (no contact) skip first-visit seeding — they always\n * see announcement previews. Identified visitors seed on first visit so\n * existing entries don't flood as unread.\n *\n * Multiple announcement tabs supported: previews stack, unseen count\n * aggregates, and each entry carries its tabId for correct navigation.\n */\nexport function useAnnouncements() {\n\tconst { client, store } = useWidgetContext();\n\tconst isReady = useWidgetStore((s) => s.isReady);\n\tconst websiteId = useWidgetStore((s) => s.website?.id) ?? null;\n\tconst visitorId = useWidgetStore((s) => s.visitor?.id) ?? null;\n\tconst isAnonymous = useWidgetStore((s) => !s.visitor?.contact);\n\tconst contentTabs = useWidgetStore((s) => s.agentConfig?.contentTabs) ?? EMPTY_TABS;\n\tconst announcementTabs = useMemo(\n\t\t() => contentTabs.filter((t) => t.isAnnouncements),\n\t\t[contentTabs],\n\t);\n\tconst checkedRef = useRef(false);\n\n\tuseEffect(() => {\n\t\tif (!isReady || !websiteId || !visitorId || announcementTabs.length === 0) return;\n\t\tif (checkedRef.current) return;\n\t\tcheckedRef.current = true;\n\n\t\tconst isFirstVisit = !hasSeenKey(websiteId, visitorId);\n\t\tlet pending = announcementTabs.length;\n\t\tlet totalUnseen = 0;\n\t\tconst allSlugs: string[] = [];\n\n\t\tfunction onTabDone(entries: AnnouncementEntry[], tab: WidgetContentTab) {\n\t\t\tallSlugs.push(...entries.map((e) => e.slug));\n\n\t\t\t// Identified user's first visit: defer unseen computation until\n\t\t\t// all tabs are collected so we can seed everything at once.\n\t\t\tif (!(isFirstVisit && !isAnonymous) && entries.length > 0) {\n\t\t\t\tconst seen = getSeenSlugs(websiteId!, visitorId!);\n\t\t\t\tconst unseen = filterUnseen(entries, seen);\n\t\t\t\ttotalUnseen += unseen.length;\n\n\t\t\t\tconst newest = unseen[0];\n\t\t\t\tif (newest && !store.getState().isOpen) {\n\t\t\t\t\tconst badgeField = tab.display?.badgeField;\n\t\t\t\t\tstore.getState().setAnnouncementPreview({\n\t\t\t\t\t\ttitle: newest.title,\n\t\t\t\t\t\tbody: newest.body,\n\t\t\t\t\t\tslug: newest.slug,\n\t\t\t\t\t\ttabId: tab.id,\n\t\t\t\t\t\tbadge: badgeField ? (newest.customFields[badgeField] ?? null) : null,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpending--;\n\t\t\tif (pending === 0) {\n\t\t\t\tif (isFirstVisit && !isAnonymous) {\n\t\t\t\t\t// Seed all entries across all tabs at once\n\t\t\t\t\tif (allSlugs.length > 0) {\n\t\t\t\t\t\taddSeenSlugs(websiteId!, visitorId!, allSlugs);\n\t\t\t\t\t}\n\t\t\t\t\tstore.getState().setUnseenAnnouncementCount(0);\n\t\t\t\t} else {\n\t\t\t\t\tstore.getState().setUnseenAnnouncementCount(totalUnseen);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (const tab of announcementTabs) {\n\t\t\tconst cacheKey = `announcements:${tab.id}:${getLocale()}`;\n\t\t\tconst cached = store.getState().contentCache.get(cacheKey);\n\t\t\tif (cached && Date.now() - cached.ts < CONTENT_CACHE_TTL) {\n\t\t\t\tonTabDone(cached.data as AnnouncementEntry[], tab);\n\t\t\t} else {\n\t\t\t\tclient.widget.getContent\n\t\t\t\t\t.query({ tabId: tab.id, page: 1, limit: 5, language: getLocale() })\n\t\t\t\t\t.then((result: { items?: AnnouncementEntry[] }) => {\n\t\t\t\t\t\tconst entries = result.items ?? [];\n\t\t\t\t\t\tstore.getState().setContentCache(cacheKey, entries);\n\t\t\t\t\t\tonTabDone(entries, tab);\n\t\t\t\t\t})\n\t\t\t\t\t.catch(() => {\n\t\t\t\t\t\tonTabDone([], tab);\n\t\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}, [isReady, websiteId, visitorId, isAnonymous, announcementTabs, client, store]);\n\n\tconst markEntrySeen = useCallback(\n\t\t(slug: string) => {\n\t\t\tif (!websiteId || !visitorId || announcementTabs.length === 0) return;\n\t\t\taddSeenSlug(websiteId, visitorId, slug);\n\n\t\t\t// Recompute total unseen count across all tabs\n\t\t\tconst seen = getSeenSlugs(websiteId, visitorId);\n\t\t\tlet total = 0;\n\t\t\tfor (const tab of announcementTabs) {\n\t\t\t\tconst cacheKey = `announcements:${tab.id}:${getLocale()}`;\n\t\t\t\tconst cached = store.getState().contentCache.get(cacheKey);\n\t\t\t\tif (cached) {\n\t\t\t\t\ttotal += filterUnseen(cached.data as AnnouncementEntry[], seen).length;\n\t\t\t\t}\n\t\t\t}\n\t\t\tstore.getState().setUnseenAnnouncementCount(total);\n\t\t\tstore.getState().dismissAnnouncementPreview(slug);\n\t\t},\n\t\t[websiteId, visitorId, announcementTabs, store],\n\t);\n\n\tconst markAllSeen = useCallback(() => {\n\t\tif (!websiteId || !visitorId || announcementTabs.length === 0) return;\n\t\tfor (const tab of announcementTabs) {\n\t\t\tconst cacheKey = `announcements:${tab.id}:${getLocale()}`;\n\t\t\tconst cached = store.getState().contentCache.get(cacheKey);\n\t\t\tif (cached) {\n\t\t\t\tconst entries = cached.data as AnnouncementEntry[];\n\t\t\t\taddSeenSlugs(websiteId, visitorId, entries.map((e) => e.slug));\n\t\t\t}\n\t\t}\n\t\tstore.getState().setUnseenAnnouncementCount(0);\n\t\tstore.getState().dismissAnnouncementPreview();\n\t}, [websiteId, visitorId, announcementTabs, store]);\n\n\tconst getUnseenEntries = useCallback((): UnseenAnnouncementEntry[] => {\n\t\tif (announcementTabs.length === 0 || !websiteId || !visitorId) return [];\n\t\tconst seen = getSeenSlugs(websiteId, visitorId);\n\t\tconst result: UnseenAnnouncementEntry[] = [];\n\t\tfor (const tab of announcementTabs) {\n\t\t\tconst cacheKey = `announcements:${tab.id}:${getLocale()}`;\n\t\t\tconst cached = store.getState().contentCache.get(cacheKey);\n\t\t\tif (cached) {\n\t\t\t\tfor (const entry of filterUnseen(cached.data as AnnouncementEntry[], seen)) {\n\t\t\t\t\tresult.push({ ...entry, tabId: tab.id });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}, [announcementTabs, websiteId, visitorId, store]);\n\n\treturn {\n\t\tannouncementTabs,\n\t\tmarkEntrySeen,\n\t\tmarkAllSeen,\n\t\tgetUnseenEntries,\n\t};\n}\n","import type { TimelineItem } from \"@helpway/types\";\nimport { t } from \"@helpway/widget-core\";\nimport { useCallback, useState } from \"react\";\nimport { useWidgetContext } from \"../provider\";\n\nexport interface PendingAttachment {\n\tid: string;\n\tfile: File;\n\tpreviewUrl: string | null; // blob URL for images\n\tisUploading: boolean;\n\terror: string | null;\n\t/** Resolved after upload — the part to include in sendMessage */\n\tpart:\n\t\t| { type: \"image\"; url: string; mimeType: string }\n\t\t| { type: \"file\"; url: string; fileName: string; fileSize: number; mimeType: string }\n\t\t| null;\n}\n\nconst MAX_ATTACHMENTS = 10;\nconst MAX_FILE_SIZE = 10 * 1024 * 1024; // 10 MB\n\n/**\n * Composer state — text input + attachments + submit for a conversation.\n */\nexport function useComposer(conversationId: string | null) {\n\tconst { client, ws, store } = useWidgetContext();\n\tconst [text, setText] = useState(\"\");\n\tconst [isSubmitting, setIsSubmitting] = useState(false);\n\tconst [attachments, setAttachments] = useState<PendingAttachment[]>([]);\n\tconst [sendError, setSendError] = useState<string | null>(null);\n\tconst [emailGateConvId, setEmailGateConvId] = useState<string | null>(null);\n\n\tconst addFiles = useCallback(\n\t\tasync (files: File[]) => {\n\t\t\tif (!conversationId) return;\n\n\t\t\tconst remaining = MAX_ATTACHMENTS - attachments.length;\n\t\t\tconst toAdd = files.slice(0, remaining);\n\t\t\tif (toAdd.length === 0) return;\n\n\t\t\t// Create pending entries\n\t\t\tconst pending: PendingAttachment[] = toAdd.map((file) => ({\n\t\t\t\tid: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n\t\t\t\tfile,\n\t\t\t\tpreviewUrl: file.type.startsWith(\"image/\") ? URL.createObjectURL(file) : null,\n\t\t\t\tisUploading: true,\n\t\t\t\terror: null,\n\t\t\t\tpart: null,\n\t\t\t}));\n\n\t\t\tsetAttachments((prev) => [...prev, ...pending]);\n\n\t\t\t// Upload each file\n\t\t\tfor (const item of pending) {\n\t\t\t\ttry {\n\t\t\t\t\tif (item.file.size > MAX_FILE_SIZE) {\n\t\t\t\t\t\tthrow new Error(t(\"widget.file_too_large\"));\n\t\t\t\t\t}\n\n\t\t\t\t\t// Read file as base64\n\t\t\t\t\tconst base64 = await fileToBase64(item.file);\n\n\t\t\t\t\t// For temp conversations (before first send) skip the\n\t\t\t\t\t// conversationId — server scopes the R2 key to the visitor\n\t\t\t\t\t// and the file is attached to the timeline item by\n\t\t\t\t\t// createConversation when submit fires.\n\t\t\t\t\tconst convIdForUpload = conversationId.startsWith(\"temp-\")\n\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t: conversationId;\n\t\t\t\t\tconst result = await client.widget.uploadAttachment.mutate({\n\t\t\t\t\t\t...(convIdForUpload ? { conversationId: convIdForUpload } : {}),\n\t\t\t\t\t\tbase64,\n\t\t\t\t\t\tmimeType: item.file.type || \"application/octet-stream\",\n\t\t\t\t\t\tfileName: item.file.name,\n\t\t\t\t\t});\n\n\t\t\t\t\tsetAttachments((prev) =>\n\t\t\t\t\t\tprev.map((a) =>\n\t\t\t\t\t\t\ta.id === item.id ? { ...a, isUploading: false, part: result.part } : a,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconst message = err instanceof Error ? err.message : \"Upload failed\";\n\t\t\t\t\tsetAttachments((prev) =>\n\t\t\t\t\t\tprev.map((a) => (a.id === item.id ? { ...a, isUploading: false, error: message } : a)),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[conversationId, attachments.length, client],\n\t);\n\n\tconst removeAttachment = useCallback((id: string) => {\n\t\tsetAttachments((prev) => {\n\t\t\tconst item = prev.find((a) => a.id === id);\n\t\t\tif (item?.previewUrl) URL.revokeObjectURL(item.previewUrl);\n\t\t\treturn prev.filter((a) => a.id !== id);\n\t\t});\n\t}, []);\n\n\tconst submit = useCallback(async () => {\n\t\tconst trimmed = text.trim();\n\t\tconst readyParts = attachments.filter((a) => a.part !== null).map((a) => a.part!);\n\t\tconst hasText = trimmed.length > 0;\n\t\tconst hasAttachments = readyParts.length > 0;\n\n\t\tif (!conversationId || isSubmitting) return;\n\n\t\t// Policy 2026-04-19: every outgoing message must have a text body.\n\t\t// An attachment on its own renders as an empty bubble in the\n\t\t// dashboard and leaves the AI with no caption to reason about.\n\t\t// Surface a soft inline error instead of silently no-op'ing so\n\t\t// the visitor understands *why* the send didn't go through.\n\t\tif (!hasText) {\n\t\t\tif (hasAttachments) {\n\t\t\t\tsetSendError(t(\"widget.caption_required\"));\n\t\t\t\tsetTimeout(() => setSendError(null), 4000);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Don't send while uploads are in progress\n\t\tconst stillUploading = attachments.some((a) => a.isUploading);\n\t\tif (stillUploading) return;\n\n\t\t// ── OPTIMISTIC: message appears in the widget INSTANTLY ──\n\t\t// The user sees their message the moment they hit send; the mutation\n\t\t// runs in the background. On success we swap the optimistic placeholder\n\t\t// for the server-confirmed item (preserving scroll + bubble position).\n\t\t// On failure we remove the placeholder and restore the composer text.\n\t\tconst optimisticId = `optimistic-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;\n\t\tconst now = new Date().toISOString();\n\t\tconst currentVisitorId = store.getState().visitor?.id ?? null;\n\t\tconst optimisticItem: TimelineItem = {\n\t\t\tid: optimisticId,\n\t\t\tconversationId,\n\t\t\torganizationId: \"\",\n\t\t\ttype: \"message\",\n\t\t\tvisibility: \"public\",\n\t\t\ttext: hasText ? trimmed : null,\n\t\t\tparts:\n\t\t\t\thasText || hasAttachments\n\t\t\t\t\t? ([\n\t\t\t\t\t\t\t...(hasText ? [{ type: \"text\" as const, text: trimmed }] : []),\n\t\t\t\t\t\t\t...readyParts,\n\t\t\t\t\t\t] as TimelineItem[\"parts\"])\n\t\t\t\t\t: null,\n\t\t\tuserId: null,\n\t\t\tvisitorId: currentVisitorId,\n\t\t\taiAgentId: null,\n\t\t\tcreatedAt: now,\n\t\t\teditedAt: null,\n\t\t\tdeletedAt: null,\n\t\t};\n\n\t\t// Flush UI immediately\n\t\tconst attachmentsSnapshot = attachments;\n\t\tconst textSnapshot = text;\n\t\tstore.getState().addMessage(conversationId, optimisticItem);\n\t\tsetText(\"\");\n\t\tsetAttachments([]);\n\t\tws.sendTyping(conversationId, false);\n\t\tsetIsSubmitting(true);\n\t\ttry {\n\t\t\t// Temp conversation IDs (seeded by openNewConversation) don't exist on\n\t\t\t// the server yet. On the first send we have to call createConversation\n\t\t\t// instead — the API allocates the real ID and returns the visitor item.\n\t\t\t// The welcome item from the response is DROPPED because the widget is\n\t\t\t// already showing a seed welcome bubble; keeping the same bubble\n\t\t\t// instance across this transition is what prevents the \"git-gel\" flash.\n\t\t\tconst isTempConversation = conversationId.startsWith(\"temp-\");\n\t\t\t// Ephemeral proactive conversation — only exists in the widget\n\t\t\t// store, server hasn't seen it yet. First reply triggers\n\t\t\t// materialization (creates conversation + writes greeting +\n\t\t\t// visitor message in one go).\n\t\t\tconst isEphemeralConversation = conversationId.startsWith(\"eph-\");\n\t\t\tif (isEphemeralConversation) {\n\t\t\t\tconst workflowId = conversationId.slice(\"eph-\".length);\n\t\t\t\tconst result = await client.widget.materializeFromProactive.mutate({\n\t\t\t\t\tworkflowId,\n\t\t\t\t\t...(hasText ? { text: trimmed } : {}),\n\t\t\t\t});\n\t\t\t\t// Pull the real conversation onto the synthetic id so all the\n\t\t\t\t// in-flight optimistic state (visitor bubble, scroll position,\n\t\t\t\t// active id) carries over without a flash.\n\t\t\t\tstore.getState().remapConversationId(conversationId, result.conversationId);\n\t\t\t\t// Hydrate canonical timeline from server — replaces synthetic\n\t\t\t\t// greeting ids with real ULIDs and surfaces the persisted\n\t\t\t\t// visitor message. We keep the optimistic placeholder in the\n\t\t\t\t// store so the visitor sees their bubble immediately; the\n\t\t\t\t// canonical setMessages dedupes by id, but our optimistic id\n\t\t\t\t// won't collide so it'll be shadowed cleanly.\n\t\t\t\ttry {\n\t\t\t\t\tconst timeline = await client.widget.getTimeline.query({\n\t\t\t\t\t\tconversationId: result.conversationId,\n\t\t\t\t\t\tlimit: 50,\n\t\t\t\t\t});\n\t\t\t\t\tif (timeline?.items) {\n\t\t\t\t\t\tstore\n\t\t\t\t\t\t\t.getState()\n\t\t\t\t\t\t\t.setMessages(result.conversationId, timeline.items as TimelineItem[]);\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Best-effort: optimistic state is still on screen, next\n\t\t\t\t\t// WS event or refresh will hydrate.\n\t\t\t\t}\n\t\t\t} else if (isTempConversation) {\n\t\t\t\tconst result = await client.widget.createConversation.mutate({\n\t\t\t\t\t...(hasText ? { text: trimmed } : {}),\n\t\t\t\t\t...(hasAttachments ? { parts: readyParts } : {}),\n\t\t\t\t});\n\t\t\t\tconst conv = result.conversation;\n\t\t\t\t// Move the temp conversation's messages (seed welcome + optimistic\n\t\t\t\t// visitor) onto the server-assigned id. remapConversationId merges\n\t\t\t\t// with any existing items under the real id (WS races are fine).\n\t\t\t\tstore.getState().remapConversationId(conversationId, conv.id);\n\t\t\t\tif (result.item) {\n\t\t\t\t\tstore\n\t\t\t\t\t\t.getState()\n\t\t\t\t\t\t.replaceMessage(conv.id, optimisticId, result.item as TimelineItem);\n\t\t\t\t}\n\t\t\t\tif (result.requireEmail) {\n\t\t\t\t\tsetEmailGateConvId(conv.id);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst result = await client.widget.sendMessage.mutate({\n\t\t\t\t\tconversationId,\n\t\t\t\t\t...(hasText ? { text: trimmed } : {}),\n\t\t\t\t\t...(hasAttachments ? { parts: readyParts } : {}),\n\t\t\t\t});\n\n\t\t\t\t// Replace optimistic placeholder with server-confirmed item.\n\t\t\t\t// If the WS echo already landed with the real id, replaceMessage\n\t\t\t\t// just drops the placeholder (race-safe, see store implementation).\n\t\t\t\tstore.getState().replaceMessage(conversationId, optimisticId, result.item as TimelineItem);\n\t\t\t}\n\n\t\t\t// Clean up blob URLs for uploaded attachments\n\t\t\tfor (const a of attachmentsSnapshot) {\n\t\t\t\tif (a.previewUrl) URL.revokeObjectURL(a.previewUrl);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tconsole.error(\"[useComposer] Send failed:\", err);\n\t\t\t// Roll back: remove placeholder, restore text + attachments so user can retry\n\t\t\tstore.getState().removeMessage(conversationId, optimisticId);\n\t\t\tsetText(textSnapshot);\n\t\t\tsetAttachments(attachmentsSnapshot);\n\t\t\tsetSendError(err instanceof Error ? err.message : t(\"widget.send_error\"));\n\t\t\t// Auto-clear after 5 seconds\n\t\t\tsetTimeout(() => setSendError(null), 5000);\n\t\t} finally {\n\t\t\tsetIsSubmitting(false);\n\t\t}\n\t}, [text, attachments, conversationId, isSubmitting, client, ws, store]);\n\n\tconst clearSendError = useCallback(() => setSendError(null), []);\n\n\treturn {\n\t\ttext,\n\t\tsetText,\n\t\tsubmit,\n\t\tisSubmitting,\n\t\tattachments,\n\t\taddFiles,\n\t\tremoveAttachment,\n\t\tsendError,\n\t\tclearSendError,\n\t\temailGateConvId,\n\t};\n}\n\n// ── Helpers ─────────────────────────────────────\n\nfunction fileToBase64(file: File): Promise<string> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst reader = new FileReader();\n\t\treader.onload = () => {\n\t\t\t// result is \"data:<mime>;base64,<data>\" — strip the prefix\n\t\t\tconst result = reader.result as string;\n\t\t\tconst base64 = result.split(\",\")[1];\n\t\t\tif (!base64) return reject(new Error(\"Failed to encode file\"));\n\t\t\tresolve(base64);\n\t\t};\n\t\treader.onerror = () => reject(new Error(\"Failed to read file\"));\n\t\treader.readAsDataURL(file);\n\t});\n}\n","import type { TimelineItem } from \"@helpway/types\";\nimport { useCallback, useRef, useState } from \"react\";\nimport { useWidgetContext, useWidgetStore } from \"../provider\";\n\n/**\n * Conversation list + create new conversation.\n */\nexport function useConversations() {\n\tconst { client, store } = useWidgetContext();\n\tconst conversations = useWidgetStore((s) => s.conversations);\n\tconst setActiveConversation = useWidgetStore((s) => s.setActiveConversation);\n\tconst [isCreating, setIsCreating] = useState(false);\n\n\tconst clientRef = useRef(client);\n\tconst storeRef = useRef(store);\n\tclientRef.current = client;\n\tstoreRef.current = store;\n\n\tconst create = useCallback(async (text: string) => {\n\t\tsetIsCreating(true);\n\n\t\t// OPTIMISTIC: show the visitor's message + open the conversation view\n\t\t// BEFORE the server roundtrip completes. The conversation gets a temp\n\t\t// id (`temp-<random>`) that's remapped to the server id on success.\n\t\t// Welcome message + any AI reply flow in via the same path the API\n\t\t// returns them — either by replacing the temp conv or via WS.\n\t\tconst tempConversationId = `temp-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;\n\t\tconst now = new Date().toISOString();\n\t\tconst optimisticMessageId = `optimistic-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;\n\t\tconst currentVisitorId = storeRef.current.getState().visitor?.id ?? null;\n\n\t\tconst optimisticMsg: TimelineItem = {\n\t\t\tid: optimisticMessageId,\n\t\t\tconversationId: tempConversationId,\n\t\t\torganizationId: \"\",\n\t\t\ttype: \"message\",\n\t\t\tvisibility: \"public\",\n\t\t\ttext,\n\t\t\tparts: null,\n\t\t\tuserId: null,\n\t\t\tvisitorId: currentVisitorId,\n\t\t\taiAgentId: null,\n\t\t\tcreatedAt: now,\n\t\t\teditedAt: null,\n\t\t\tdeletedAt: null,\n\t\t};\n\n\t\t// Flush UI immediately: fake conversation + message + switch view\n\t\tconst store = storeRef.current.getState();\n\t\tstore.addConversation({\n\t\t\tid: tempConversationId,\n\t\t\ttitle: null,\n\t\t\tstatus: \"open\",\n\t\t\tlastMessageText: text,\n\t\t\tlastMessageAt: now,\n\t\t\tlastMessageSenderType: \"visitor\",\n\t\t\tlastMessageSenderName: null,\n\t\t\tlastMessageSenderImage: null,\n\t\t\tassigneeName: null,\n\t\t\tassigneeImage: null,\n\t\t\tunreadCount: 0,\n\t\t});\n\t\tstore.setMessages(tempConversationId, [optimisticMsg]);\n\t\tstore.setActiveConversation(tempConversationId);\n\n\t\ttry {\n\t\t\tconst result = await clientRef.current.widget.createConversation.mutate({ text });\n\t\t\tconst conv = result.conversation;\n\n\t\t\t// Remap temp ID → real ID (rewrites conversations list + messages map + active ref).\n\t\t\t// The optimistic message's id becomes stale (conversationId changed) — replaceMessage\n\t\t\t// with the server-confirmed item.\n\t\t\tstoreRef.current.getState().remapConversationId(tempConversationId, conv.id);\n\t\t\tif (result.item) {\n\t\t\t\tstoreRef.current\n\t\t\t\t\t.getState()\n\t\t\t\t\t.replaceMessage(conv.id, optimisticMessageId, result.item as TimelineItem);\n\t\t\t}\n\t\t\t// Insert welcome message if the agent sent one.\n\t\t\t// The welcome is ALWAYS the very first item in a new conversation, so\n\t\t\t// we place it at index 0 deterministically — never trust createdAt sort,\n\t\t\t// because client-clock (optimistic visitor) vs server-clock (welcome)\n\t\t\t// can be off by enough to re-order the pair. Dedup by id so a WS echo\n\t\t\t// doesn't double-insert.\n\t\t\tif (result.welcomeItem) {\n\t\t\t\tconst welcome = result.welcomeItem as TimelineItem;\n\t\t\t\tconst existing = storeRef.current.getState().messages.get(conv.id) ?? [];\n\t\t\t\tconst withoutWelcome = existing.filter((m) => m.id !== welcome.id);\n\t\t\t\tstoreRef.current.getState().setMessages(conv.id, [welcome, ...withoutWelcome]);\n\t\t\t}\n\t\t\treturn conv;\n\t\t} catch (err) {\n\t\t\t// Roll back: remove the fake conversation + message; let the caller surface the error\n\t\t\tstoreRef.current.getState().removeMessage(tempConversationId, optimisticMessageId);\n\t\t\tconst convs = storeRef.current\n\t\t\t\t.getState()\n\t\t\t\t.conversations.filter((c) => c.id !== tempConversationId);\n\t\t\tstoreRef.current.setState({ conversations: convs, activeConversationId: null });\n\t\t\tthrow err;\n\t\t} finally {\n\t\t\tsetIsCreating(false);\n\t\t}\n\t}, []);\n\n\treturn { conversations, create, isCreating, setActiveConversation };\n}\n","import { useEffect, useState } from \"react\";\nimport { onLocaleChange, getI18nRevision } from \"@helpway/widget-core\";\n\n/**\n * React hook that triggers re-render when widget translations load or locale changes.\n * Place this in the top-level widget component so all children get fresh t() values.\n *\n * Returns the current i18n revision number (for debugging).\n */\nexport function useI18n(): number {\n\tconst [rev, setRev] = useState(() => getI18nRevision());\n\n\tuseEffect(() => {\n\t\t// Subscribe to locale/translation changes\n\t\treturn onLocaleChange(() => {\n\t\t\tsetRev(getI18nRevision());\n\t\t});\n\t}, []);\n\n\treturn rev;\n}\n","import { useCallback, useRef } from \"react\";\nimport { useWidgetContext, useWidgetStore } from \"../provider\";\n\n/**\n * Typing presence — show \"is typing\" + send own typing status.\n *\n * Debounced: only sends WS event when typing state *changes*.\n * While typing, auto-stops after 3 seconds of inactivity.\n *\n * Usage:\n * ```tsx\n * const { isTyping, setTyping } = usePresence(conversationId)\n * ```\n */\nexport function usePresence(conversationId: string | null) {\n\tconst { ws } = useWidgetContext();\n\tconst isTyping = useWidgetStore((s) =>\n\t\tconversationId ? (s.typingUsers.get(conversationId) ?? false) : false,\n\t);\n\tconst isAiProcessing = useWidgetStore((s) =>\n\t\tconversationId ? (s.aiProcessing.get(conversationId) ?? false) : false,\n\t);\n\tconst typingTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\tconst isSendingTyping = useRef(false);\n\n\tconst setTyping = useCallback(\n\t\t(typing: boolean) => {\n\t\t\tif (!conversationId) return;\n\n\t\t\t// Clear any pending auto-stop\n\t\t\tif (typingTimer.current) clearTimeout(typingTimer.current);\n\n\t\t\tif (typing) {\n\t\t\t\t// Only send \"typing: true\" if we haven't already\n\t\t\t\tif (!isSendingTyping.current) {\n\t\t\t\t\tisSendingTyping.current = true;\n\t\t\t\t\tws.sendTyping(conversationId, true);\n\t\t\t\t}\n\t\t\t\t// Auto-stop after 3 seconds of inactivity\n\t\t\t\ttypingTimer.current = setTimeout(() => {\n\t\t\t\t\tisSendingTyping.current = false;\n\t\t\t\t\tws.sendTyping(conversationId, false);\n\t\t\t\t}, 3000);\n\t\t\t} else {\n\t\t\t\t// Immediately send stop\n\t\t\t\tif (isSendingTyping.current) {\n\t\t\t\t\tisSendingTyping.current = false;\n\t\t\t\t\tws.sendTyping(conversationId, false);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[conversationId, ws],\n\t);\n\n\treturn { isTyping, isAiProcessing, setTyping };\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useWidgetContext, useWidgetStore } from \"../provider\";\n\nimport type { TimelineItem } from \"@helpway/types\";\n\nconst EMPTY_ITEMS: TimelineItem[] = [];\n\n/**\n * Timeline items for a conversation + real-time updates.\n */\nexport function useTimeline(conversationId: string | null) {\n\tconst { client, store } = useWidgetContext();\n\tconst messages = useWidgetStore((s) =>\n\t\tconversationId ? s.messages.get(conversationId) ?? EMPTY_ITEMS : EMPTY_ITEMS,\n\t);\n\tconst [isLoading, setIsLoading] = useState(false);\n\tconst [hasMore, setHasMore] = useState(false);\n\tconst cursorRef = useRef<string | undefined>(undefined);\n\n\t// Stable refs to avoid effect re-triggers\n\tconst clientRef = useRef(client);\n\tconst storeRef = useRef(store);\n\tclientRef.current = client;\n\tstoreRef.current = store;\n\n\t// Load initial timeline when conversation changes\n\tuseEffect(() => {\n\t\tif (!conversationId) return;\n\n\t\t// Skip server fetch for optimistic temp IDs — they don't exist server-side.\n\t\t// useConversations.create() owns the seed for these; once remap fires this\n\t\t// effect re-runs with the real id and the fetch happens then.\n\t\tif (conversationId.startsWith(\"temp-\")) return;\n\n\t\tlet cancelled = false;\n\n\t\t// If createConversation already seeded the messages store (welcome + first\n\t\t// visitor message), the server has nothing new to tell us — skip the fetch.\n\t\t// Overwriting the seed with the server payload causes a full array-identity\n\t\t// flip, a brief key-swap for the optimistic→server id transition, and\n\t\t// restarts CSS enter animations — the \"mesajlar gidip tekrar geliyor\" flash.\n\t\t// New items still flow in via WS.addMessage, which dedupes by id.\n\t\tconst existingMessages = storeRef.current.getState().messages.get(conversationId);\n\t\tconst hasSeed = !!existingMessages && existingMessages.length > 0;\n\t\tif (hasSeed) {\n\t\t\tstoreRef.current.getState().clearUnread(conversationId);\n\t\t\tclientRef.current.widget.markSeen\n\t\t\t\t.mutate({ conversationId })\n\t\t\t\t.catch(() => {});\n\t\t\treturn () => {\n\t\t\t\tcancelled = true;\n\t\t\t};\n\t\t}\n\n\t\tsetIsLoading(true);\n\t\tasync function load() {\n\t\t\ttry {\n\t\t\t\tconst data = await clientRef.current.widget.getTimeline.query({\n\t\t\t\t\tconversationId: conversationId!,\n\t\t\t\t\tlimit: 50,\n\t\t\t\t});\n\n\t\t\t\tif (cancelled) return;\n\n\t\t\t\t// Only overwrite if API returned items — don't wipe seed messages with empty response\n\t\t\t\tif (data.items.length > 0) {\n\t\t\t\t\tstoreRef.current.getState().setMessages(conversationId!, data.items as TimelineItem[]);\n\t\t\t\t}\n\t\t\t\tsetHasMore(data.hasMore);\n\t\t\t\tcursorRef.current = data.nextCursor ?? undefined;\n\n\t\t\t\t// Mark as seen + clear local unread count\n\t\t\t\tstoreRef.current.getState().clearUnread(conversationId!);\n\t\t\t\tclientRef.current.widget.markSeen.mutate({ conversationId: conversationId! }).catch(() => {});\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"[useTimeline] Failed to load:\", err);\n\t\t\t} finally {\n\t\t\t\tif (!cancelled) setIsLoading(false);\n\t\t\t}\n\t\t}\n\n\t\tload();\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t};\n\t}, [conversationId]); // Only re-run when conversationId changes\n\n\tconst loadMore = useCallback(async () => {\n\t\tif (!conversationId || !hasMore || isLoading) return;\n\n\t\tsetIsLoading(true);\n\t\ttry {\n\t\t\tconst data = await clientRef.current.widget.getTimeline.query({\n\t\t\t\tconversationId,\n\t\t\t\tcursor: cursorRef.current,\n\t\t\t\tlimit: 50,\n\t\t\t});\n\n\t\t\tconst existing = storeRef.current.getState().messages.get(conversationId) ?? [];\n\t\t\tstoreRef.current.getState().setMessages(conversationId, [...data.items as TimelineItem[], ...existing]);\n\t\t\tsetHasMore(data.hasMore);\n\t\t\tcursorRef.current = data.nextCursor ?? undefined;\n\t\t} finally {\n\t\t\tsetIsLoading(false);\n\t\t}\n\t}, [conversationId, hasMore, isLoading]);\n\n\treturn { items: messages, isLoading, hasMore, loadMore };\n}\n","import { useWidgetStore } from \"../provider\";\n\n/**\n * Total unread count across all conversations.\n *\n * Usage:\n * ```tsx\n * const { totalUnread } = useUnread()\n * ```\n */\nexport function useUnread() {\n\tconst totalUnread = useWidgetStore((s) =>\n\t\ts.conversations.reduce((sum, c) => sum + c.unreadCount, 0),\n\t);\n\n\treturn { totalUnread };\n}\n","import { useWidgetContext, useWidgetStore } from \"../provider\";\n\n/**\n * Core widget state — connection status, visitor identity, website info.\n *\n * Usage:\n * ```tsx\n * const { isReady, visitor, website, identify } = useWidget()\n * ```\n */\nexport function useWidget() {\n\tconst { client } = useWidgetContext();\n\tconst isReady = useWidgetStore((s) => s.isReady);\n\tconst isConnecting = useWidgetStore((s) => s.isConnecting);\n\tconst visitor = useWidgetStore((s) => s.visitor);\n\tconst website = useWidgetStore((s) => s.website);\n\tconst agentConfig = useWidgetStore((s) => s.agentConfig);\n\n\tasync function identify(data: {\n\t\texternalId: string;\n\t\temail?: string;\n\t\tname?: string;\n\t\timage?: string;\n\t\tmetadata?: Record<string, unknown>;\n\t}) {\n\t\treturn client.widget.identify.mutate(data);\n\t}\n\n\treturn { isReady, isConnecting, visitor, website, agentConfig, identify };\n}\n","import { useCallback, useRef, useState } from \"react\";\nimport { t } from \"@helpway/widget-core\";\nimport type { PendingAttachment } from \"../hooks/use-composer\";\nimport { SendIcon, PaperclipIcon, XIcon } from \"./icons\";\nimport { AnchoredPreview } from \"./message-bubble\";\n\nconst MAX_CHARS = 5000;\nconst CHAR_WARN_THRESHOLD = 4800;\n\nconst ACCEPTED_TYPES = [\n\t\"image/png\", \"image/jpeg\", \"image/gif\", \"image/webp\", \"image/svg+xml\",\n\t\"application/pdf\", \"text/plain\", \"text/csv\", \"application/zip\",\n\t\"application/msword\",\n\t\"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n\t\"application/vnd.ms-excel\",\n\t\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n].join(\",\");\n\ninterface ComposerProps {\n\ttext: string;\n\tonTextChange: (text: string) => void;\n\tonSubmit: () => void;\n\tonTyping?: (isTyping: boolean) => void;\n\tisSubmitting?: boolean;\n\tplaceholder?: string;\n\t/** Compact mode — single-line input without footer row */\n\tcompact?: boolean;\n\t/** Pending attachments to preview */\n\tattachments?: PendingAttachment[];\n\t/** Called when files are added (paste, drop, or file picker) */\n\tonAddFiles?: (files: File[]) => void;\n\t/** Called to remove a pending attachment */\n\tonRemoveAttachment?: (id: string) => void;\n\t/** Disable entire composer (e.g. email required before sending) */\n\tdisabled?: boolean;\n}\n\n/** Widget composer — auto-resize, Enter-to-send, paste/drop attachments */\nexport function Composer({\n\ttext,\n\tonTextChange,\n\tonSubmit,\n\tonTyping,\n\tisSubmitting,\n\tplaceholder,\n\tcompact,\n\tattachments,\n\tonAddFiles,\n\tonRemoveAttachment,\n\tdisabled,\n}: ComposerProps) {\n\tconst ref = useRef<HTMLTextAreaElement>(null);\n\tconst fileInputRef = useRef<HTMLInputElement>(null);\n\n\t// Feature-detect once per mount. CSS.supports is cheap but doing it\n\t// inside handleChange would run on every keystroke.\n\tconst supportsFieldSizing = useRef(\n\t\ttypeof CSS !== \"undefined\" && CSS.supports?.(\"field-sizing\", \"content\"),\n\t);\n\n\tconst handleKeyDown = useCallback(\n\t\t(e: React.KeyboardEvent) => {\n\t\t\tif (e.key === \"Enter\" && !e.shiftKey) {\n\t\t\t\te.preventDefault();\n\t\t\t\tonSubmit();\n\t\t\t}\n\t\t},\n\t\t[onSubmit],\n\t);\n\n\tconst handleChange = useCallback(\n\t\t(e: React.ChangeEvent<HTMLTextAreaElement>) => {\n\t\t\tconst value = e.target.value;\n\t\t\tif (value.length > MAX_CHARS) return; // Hard cap\n\t\t\tonTextChange(value);\n\t\t\tonTyping?.(value.length > 0);\n\n\t\t\t// Auto-resize fallback for engines without `field-sizing: content`\n\t\t\t// (Safari <17.4, Firefox <132, Chrome <123). Modern browsers handle\n\t\t\t// the resize in CSS — running this on every keystroke would force\n\t\t\t// a redundant reflow and briefly snap the textarea to min-height\n\t\t\t// before the new height is applied. Kept in sync with the 220px\n\t\t\t// max-height on .hw-composer-input.\n\t\t\tif (!supportsFieldSizing.current) {\n\t\t\t\tconst el = ref.current;\n\t\t\t\tif (el) {\n\t\t\t\t\tel.style.height = \"auto\";\n\t\t\t\t\tel.style.height = `${Math.min(el.scrollHeight, 220)}px`;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[onTextChange, onTyping],\n\t);\n\n\t// ── Clipboard paste ──────────────────────────\n\tconst handlePaste = useCallback(\n\t\t(e: React.ClipboardEvent) => {\n\t\t\tif (!onAddFiles) return;\n\t\t\tconst files = extractFiles(e.clipboardData);\n\t\t\tif (files.length > 0) {\n\t\t\t\te.preventDefault();\n\t\t\t\tonAddFiles(files);\n\t\t\t}\n\t\t},\n\t\t[onAddFiles],\n\t);\n\n\t// ── Drag & drop ──────────────────────────────\n\tconst [isDragging, setIsDragging] = useState(false);\n\tconst dragCountRef = useRef(0);\n\n\tconst handleDragEnter = useCallback((e: React.DragEvent) => {\n\t\te.preventDefault();\n\t\tdragCountRef.current++;\n\t\tif (dragCountRef.current === 1) setIsDragging(true);\n\t}, []);\n\n\tconst handleDragLeave = useCallback((e: React.DragEvent) => {\n\t\te.preventDefault();\n\t\tdragCountRef.current--;\n\t\tif (dragCountRef.current === 0) setIsDragging(false);\n\t}, []);\n\n\tconst handleDragOver = useCallback((e: React.DragEvent) => {\n\t\te.preventDefault();\n\t\te.dataTransfer.dropEffect = \"copy\";\n\t}, []);\n\n\tconst handleDrop = useCallback(\n\t\t(e: React.DragEvent) => {\n\t\t\te.preventDefault();\n\t\t\tdragCountRef.current = 0;\n\t\t\tsetIsDragging(false);\n\t\t\tif (!onAddFiles) return;\n\t\t\tconst files = extractFiles(e.dataTransfer);\n\t\t\tif (files.length > 0) onAddFiles(files);\n\t\t},\n\t\t[onAddFiles],\n\t);\n\n\t// ── File picker ──────────────────────────────\n\tconst handleFileClick = useCallback(() => {\n\t\tfileInputRef.current?.click();\n\t}, []);\n\n\tconst handleFileChange = useCallback(\n\t\t(e: React.ChangeEvent<HTMLInputElement>) => {\n\t\t\tif (!onAddFiles || !e.target.files) return;\n\t\t\tonAddFiles(Array.from(e.target.files));\n\t\t\te.target.value = \"\"; // reset so same file can be picked again\n\t\t},\n\t\t[onAddFiles],\n\t);\n\n\tconst hasText = text.trim().length > 0;\n\tconst hasAttachments = attachments && attachments.some((a) => a.part !== null);\n\tconst stillUploading = attachments?.some((a) => a.isUploading) ?? false;\n\t// Button stays clickable whenever there's *something* to send — the\n\t// actual text-required guard lives in `useComposer.submit` and\n\t// surfaces as an inline error if the visitor tries to send an\n\t// attachment without a caption. Feels less sticky than a disabled\n\t// arrow the user can't interpret.\n\tconst canSend = (hasText || hasAttachments) && !stillUploading;\n\tconst showCharCount = text.length >= CHAR_WARN_THRESHOLD;\n\tconst isOverLimit = text.length > MAX_CHARS;\n\n\treturn (\n\t\t<div\n\t\t\tclassName={`hw-composer ${compact ? \"hw-composer--compact\" : \"\"} ${isDragging ? \"hw-composer--dragging\" : \"\"}`}\n\t\t\tonDragEnter={handleDragEnter}\n\t\t\tonDragLeave={handleDragLeave}\n\t\t\tonDragOver={handleDragOver}\n\t\t\tonDrop={handleDrop}\n\t\t>\n\t\t\t<div className=\"hw-composer-box\" style={{ position: \"relative\" }}>\n\t\t\t\t{/* Drag overlay */}\n\t\t\t\t{isDragging && (\n\t\t\t\t\t<div className=\"hw-composer-drop-overlay\">\n\t\t\t\t\t\t<span className=\"hw-composer-drop-text\">{t(\"widget.drop_files\")}</span>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t\t{/* Attachment previews */}\n\t\t\t\t{attachments && attachments.length > 0 && (\n\t\t\t\t\t<div className=\"hw-composer-previews\">\n\t\t\t\t\t\t{attachments.map((a) => (\n\t\t\t\t\t\t\t<PreviewThumb\n\t\t\t\t\t\t\t\tkey={a.id}\n\t\t\t\t\t\t\t\tattachment={a}\n\t\t\t\t\t\t\t\tonRemove={onRemoveAttachment ? () => onRemoveAttachment(a.id) : undefined}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t<textarea\n\t\t\t\t\tref={ref}\n\t\t\t\t\tclassName=\"hw-composer-input\"\n\t\t\t\t\tvalue={text}\n\t\t\t\t\tonChange={handleChange}\n\t\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\t\tonPaste={handlePaste}\n\t\t\t\t\tplaceholder={placeholder ?? t(\"widget.placeholder\")}\n\t\t\t\t\trows={1}\n\t\t\t\t\tdisabled={disabled || isSubmitting}\n\t\t\t\t\taria-label={t(\"widget.aria_input\")}\n\t\t\t\t/>\n\t\t\t\t<div className=\"hw-composer-toolbar\">\n\t\t\t\t\t<div className=\"hw-composer-toolbar-left\">\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tclassName=\"hw-composer-attach\"\n\t\t\t\t\t\t\tonClick={handleFileClick}\n\t\t\t\t\t\t\tdisabled={disabled || isSubmitting}\n\t\t\t\t\t\t\taria-label={t(\"widget.aria_attach\")}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<PaperclipIcon />\n\t\t\t\t\t\t</button>\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\tref={fileInputRef}\n\t\t\t\t\t\t\ttype=\"file\"\n\t\t\t\t\t\t\taccept={ACCEPTED_TYPES}\n\t\t\t\t\t\t\tmultiple\n\t\t\t\t\t\t\thidden\n\t\t\t\t\t\t\tonChange={handleFileChange}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t{showCharCount && (\n\t\t\t\t\t\t\t<span className={`hw-composer-charcount ${isOverLimit ? \"hw-composer-charcount--over\" : \"\"}`}>\n\t\t\t\t\t\t\t\t{MAX_CHARS - text.length}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName={`hw-composer-send ${canSend && !isOverLimit && !disabled ? \"hw-composer-send--active\" : \"hw-composer-send--inactive\"}`}\n\t\t\t\t\t\tonClick={onSubmit}\n\t\t\t\t\t\tdisabled={disabled || !canSend || isSubmitting || isOverLimit}\n\t\t\t\t\t\taria-label={t(\"widget.aria_send\")}\n\t\t\t\t\t>\n\t\t\t\t\t\t<SendIcon />\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\n// ── Preview thumbnail with hover ─────────────────\n\nfunction PreviewThumb({ attachment: a, onRemove }: { attachment: PendingAttachment; onRemove?: () => void }) {\n\tconst [hover, setHover] = useState(false);\n\tconst ref = useRef<HTMLDivElement>(null);\n\n\treturn (\n\t\t<div\n\t\t\tref={ref}\n\t\t\tclassName={`hw-composer-preview ${a.error ? \"hw-composer-preview--error\" : \"\"}`}\n\t\t\tonMouseEnter={() => setHover(true)}\n\t\t\tonMouseLeave={() => setHover(false)}\n\t\t>\n\t\t\t{a.previewUrl ? (\n\t\t\t\t<img src={a.previewUrl} alt={a.file.name} className=\"hw-composer-preview-img\" />\n\t\t\t) : (\n\t\t\t\t<div className=\"hw-composer-preview-file\">\n\t\t\t\t\t<span className=\"hw-composer-preview-ext\">\n\t\t\t\t\t\t{a.file.name.split(\".\").pop()?.toUpperCase() ?? \"FILE\"}\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t{a.isUploading && <div className=\"hw-composer-preview-loader\" />}\n\t\t\t{a.error && <div className=\"hw-composer-preview-badge\" title={a.error}>!</div>}\n\t\t\t{onRemove && (\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"hw-composer-preview-remove\"\n\t\t\t\t\tonClick={onRemove}\n\t\t\t\t\taria-label={t(\"widget.aria_remove\")}\n\t\t\t\t>\n\t\t\t\t\t<XIcon />\n\t\t\t\t</button>\n\t\t\t)}\n\t\t\t{/* Hover preview for images */}\n\t\t\t{hover && a.previewUrl && !a.isUploading && (\n\t\t\t\t<AnchoredPreview src={a.previewUrl} anchorRef={ref} />\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\n// ── Helpers ──────────────────────────────────────\n\nfunction extractFiles(data: DataTransfer): File[] {\n\tconst files: File[] = [];\n\tif (data.files) {\n\t\tfor (let i = 0; i < data.files.length; i++) {\n\t\t\tconst file = data.files[i];\n\t\t\tif (file) files.push(file);\n\t\t}\n\t}\n\treturn files;\n}\n","// AUTO-GENERATED — DO NOT EDIT.\n// Run `bun scripts/sync-icons.ts` to regenerate from\n// @central-icons-react/round-outlined-radius-2-stroke-2 (devDep, not shipped).\n//\n// To add or rename an icon: edit MANIFEST in scripts/sync-icons.ts, re-run.\n\nimport type { SVGProps } from \"react\";\n\ntype IconProps = SVGProps<SVGSVGElement> & { size?: number | string };\n\n// IconBubble2\nexport function MessageIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M5.00195 4H19.002C20.1065 4 21.002 4.89543 21.002 6V16C21.002 17.1046 20.1065 18 19.002 18H12.002L7.00195 21V18H5.00195C3.89738 18 3.00195 17.1046 3.00195 16V6C3.00195 4.89543 3.89738 4 5.00195 4Z\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"square\" strokeLinejoin=\"round\" />\n\t\t</svg>\n\t);\n}\n\n// IconCrossMedium\nexport function XIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M6.5 6.5L17.5 17.5M17.5 6.5L6.5 17.5\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" />\n\t\t</svg>\n\t);\n}\n\n// IconArrowLeft\nexport function ArrowLeftIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M10 6L4 12L10 18\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n\t\t\t<path d=\"M5 12H20\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n\t\t</svg>\n\t);\n}\n\n// IconChevronRight\nexport function ChevronRightIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M9 4L15.5858 10.5858C16.3668 11.3668 16.3668 12.6331 15.5858 13.4142L9 20\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n\t\t</svg>\n\t);\n}\n\n// IconSparklesSoft\nexport function SparklesIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M19 13C14.0987 13.4243 11.4243 16.0987 11 21C10.5578 16.0225 7.89737 13.5547 3 13C7.97478 12.4262 10.4262 9.97478 11 5C11.5547 9.89737 14.0225 12.5578 19 13Z\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n\t\t\t<path d=\"M18.8864 2.34512C18.8642 2.14869 18.6981 2.0002 18.5004 2C18.3027 1.9998 18.1363 2.14794 18.1137 2.34433C18.0082 3.25861 17.7367 3.88584 17.3113 4.31127C16.8858 4.7367 16.2586 5.00822 15.3443 5.11367C15.1479 5.13632 14.9998 5.30271 15 5.5004C15.0002 5.69809 15.1487 5.86417 15.3451 5.88642C16.2439 5.98823 16.8855 6.25969 17.3217 6.68804C17.7556 7.11407 18.0322 7.74041 18.1126 8.64552C18.1305 8.84634 18.2988 9.00023 18.5004 9C18.702 8.99977 18.8701 8.84551 18.8874 8.64465C18.9645 7.75483 19.2409 7.11438 19.6776 6.67764C20.1144 6.24091 20.7548 5.96446 21.6446 5.88744C21.8455 5.87005 21.9998 5.70205 22 5.50044C22.0002 5.29883 21.8463 5.13048 21.6455 5.11264C20.7404 5.03224 20.1141 4.75557 19.688 4.3217C19.2597 3.88545 18.9882 3.24394 18.8864 2.34512Z\" fill=\"currentColor\" />\n\t\t</svg>\n\t);\n}\n\n// IconPaperPlaneTopRight\nexport function SendIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M9.61946 10.8613L20.9997 4.55422M9.04735 10.9043L4.10061 5.68812C3.49632 5.05091 3.94803 4 4.82621 4H20.2513C21.0247 4 21.5054 4.84039 21.1132 5.50702L13.1902 18.9762C12.7433 19.7358 11.6035 19.5879 11.3654 18.7393L9.28458 11.3223C9.24066 11.1658 9.15923 11.0223 9.04735 10.9043Z\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n\t\t</svg>\n\t);\n}\n\n// IconPaperclip1\nexport function PaperclipIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M6 11V15C6 18.3137 8.68629 21 12 21C15.3137 21 18 18.3137 18 15V7C18 4.79086 16.2091 3 14 3C11.7909 3 10 4.79086 10 7V15C10 16.1046 10.8954 17 12 17C13.1046 17 14 16.1046 14 15V7\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" />\n\t\t</svg>\n\t);\n}\n\n// IconArrowUp\nexport function ArrowUpIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M12 5V20\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n\t\t\t<path d=\"M6 10L12 4L18 10\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n\t\t</svg>\n\t);\n}\n\n// IconHome\nexport function HomeIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M4 9.77313C4 9.2136 4 8.93383 4.07063 8.67517C4.1332 8.446 4.23609 8.22982 4.3745 8.03675C4.53071 7.81882 4.74784 7.6424 5.1821 7.28957L9.9821 3.38956C10.7014 2.80513 11.0611 2.51291 11.4609 2.40099C11.8135 2.30229 12.1865 2.30229 12.5391 2.40099C12.9389 2.51291 13.2986 2.80513 14.0179 3.38957L18.8179 7.28957C19.2522 7.6424 19.4693 7.81882 19.6255 8.03675C19.7639 8.22982 19.8668 8.446 19.9294 8.67517C20 8.93383 20 9.2136 20 9.77313V16.8C20 17.9201 20 18.4802 19.782 18.908C19.5903 19.2843 19.2843 19.5903 18.908 19.782C18.4802 20 17.9201 20 16.8 20H7.2C6.07989 20 5.51984 20 5.09202 19.782C4.71569 19.5903 4.40973 19.2843 4.21799 18.908C4 18.4802 4 17.9201 4 16.8V9.77313Z\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinejoin=\"round\" />\n\t\t</svg>\n\t);\n}\n\n// IconBubbleDots\nexport function MessagesIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M4.00195 6.00003C4.00195 4.89546 4.89738 4.00003 6.00195 4.00002L18.0019 4C19.1065 4 20.002 4.89543 20.002 6V16.0358C20.002 17.1403 19.1065 18.0358 18.002 18.0358L15.3757 18.0358C15.1427 18.0358 14.9171 18.1171 14.7377 18.2657L11.9977 20.5358L9.29398 18.2694C9.11393 18.1185 8.8865 18.0358 8.65157 18.0358H6.00195C4.89738 18.0358 4.00195 17.1403 4.00195 16.0358V6.00003Z\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinejoin=\"round\" />\n\t\t\t<path d=\"M6.875 11.25C6.875 11.7332 7.26675 12.125 7.75 12.125C8.23325 12.125 8.625 11.7332 8.625 11.25C8.625 10.7668 8.23325 10.375 7.75 10.375C7.26675 10.375 6.875 10.7668 6.875 11.25ZM11.125 11.25C11.125 11.7332 11.5168 12.125 12 12.125C12.4832 12.125 12.875 11.7332 12.875 11.25C12.875 10.7668 12.4832 10.375 12 10.375C11.5168 10.375 11.125 10.7668 11.125 11.25ZM15.375 11.25C15.375 11.7332 15.7668 12.125 16.25 12.125C16.7332 12.125 17.125 11.7332 17.125 11.25C17.125 10.7668 16.7332 10.375 16.25 10.375C15.7668 10.375 15.375 10.7668 15.375 11.25Z\" fill=\"currentColor\" stroke=\"currentColor\" strokeWidth=\"0.75\" strokeLinecap=\"square\" />\n\t\t</svg>\n\t);\n}\n\n// IconMagnifyingGlass\nexport function SearchIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M11 18C14.866 18 18 14.866 18 11C18 7.13401 14.866 4 11 4C7.13401 4 4 7.13401 4 11C4 14.866 7.13401 18 11 18Z\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" />\n\t\t\t<path d=\"M20 20L16.05 16.05\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" />\n\t\t</svg>\n\t);\n}\n\n// IconBubblePlus\nexport function NewChatIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M11.9998 8L11.9998 11M11.9998 11V14M11.9998 11H8.99976M11.9998 11H14.9998M11.9977 20.5358L14.7377 18.2657C14.9171 18.1171 15.1427 18.0358 15.3757 18.0358L18.002 18.0358C19.1065 18.0357 20.002 17.1403 20.002 16.0358V6C20.002 4.89543 19.1065 4 18.0019 4L6.00195 4.00002C4.89738 4.00002 4.00195 4.89545 4.00195 6.00002V16.0358C4.00195 17.1403 4.89738 18.0358 6.00195 18.0358H8.65157C8.8865 18.0358 9.11393 18.1185 9.29398 18.2694L11.9977 20.5358Z\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n\t\t</svg>\n\t);\n}\n\n// IconAppleIntelligence\nexport function BotIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path fillRule=\"evenodd\" clipRule=\"evenodd\" d=\"M9.67904 3.29155C10.7467 1.56948 13.2537 1.56948 14.3214 3.29155L15.1308 4.59707C15.2462 4.7833 15.3634 4.9684 15.4823 5.15233C15.7005 5.1305 15.9185 5.10662 16.1363 5.08068L17.6626 4.89893C19.6747 4.65934 21.2396 6.61723 20.5571 8.52637L20.0401 9.97255C19.9664 10.1786 19.8947 10.3854 19.825 10.5927C19.9779 10.7493 20.1323 10.9045 20.2882 11.0583L21.3821 12.1371C22.8256 13.5609 22.2668 16.0039 20.3491 16.6605L18.895 17.1584C18.6876 17.2294 18.4809 17.3023 18.275 17.3772C18.2478 17.5943 18.2226 17.8117 18.1995 18.0294L18.0372 19.5565C17.823 21.572 15.5635 22.6577 13.8546 21.5695L12.5584 20.7442C12.3734 20.6264 12.1873 20.5103 12.0002 20.3961C11.8131 20.5103 11.627 20.6264 11.442 20.7442L10.1458 21.5695C8.4369 22.6577 6.17739 21.572 5.96321 19.5565L5.80094 18.0294C5.7778 17.8117 5.75263 17.5943 5.72541 17.3772C5.51949 17.3023 5.31282 17.2294 5.10542 17.1584L3.65133 16.6605C1.7336 16.0039 1.17475 13.5609 2.61829 12.1371L3.71216 11.0583C3.86807 10.9045 4.0225 10.7493 4.17541 10.5927C4.10567 10.3854 4.03395 10.1786 3.96028 9.97255L3.44329 8.52637C2.7608 6.61723 4.32567 4.65934 6.33777 4.89893L7.86408 5.08068C8.08191 5.10662 8.29993 5.1305 8.5181 5.15233C8.63698 4.9684 8.75417 4.7833 8.86963 4.59707L9.67904 3.29155ZM7.61407 6.4827L6.16966 6.31071C5.20357 6.19567 4.45578 7.13505 4.78207 8.04778L5.2716 9.41715C6.10452 8.48167 6.88648 7.5021 7.61407 6.4827ZM5.78854 10.961C7.04552 9.61105 8.19784 8.16742 9.23549 6.64268C11.076 6.78287 12.9244 6.78287 14.7649 6.64268C15.8026 8.16743 16.9549 9.61105 18.2119 10.961C17.6657 12.722 17.2545 14.522 16.9818 16.3454C15.2628 17.0169 13.5974 17.8181 12.0002 18.7422C10.403 17.8181 8.73761 17.0169 7.01863 16.3454C6.74592 14.522 6.3347 12.722 5.78854 10.961ZM4.65269 12.1275L3.61666 13.1494C2.92581 13.8308 3.19234 15.0006 4.11188 15.3154L5.48873 15.7868C5.27593 14.553 4.99684 13.3315 4.65269 12.1275ZM7.22343 17.9611L7.377 19.4062C7.47946 20.3704 8.56185 20.8926 9.38218 20.3703L10.6083 19.5895C9.51004 18.9865 8.38012 18.4429 7.22343 17.9611ZM13.3921 19.5895L14.6182 20.3703C15.4385 20.8926 16.5209 20.3704 16.6234 19.4062L16.777 17.9611C15.6203 18.4429 14.4903 18.9865 13.3921 19.5895ZM18.5117 15.7868L19.8885 15.3154C20.8081 15.0006 21.0746 13.8308 20.3837 13.1494L19.3477 12.1275C19.0035 13.3315 18.7245 14.553 18.5117 15.7868ZM18.7288 9.41715L19.2183 8.04778C19.5446 7.13505 18.7968 6.19567 17.8307 6.31071L16.3863 6.4827C17.1139 7.5021 17.8959 8.48167 18.7288 9.41715ZM13.8786 5.2756C12.6272 5.3429 11.3731 5.3429 10.1218 5.2756L10.8874 4.04072C11.3991 3.21542 12.6013 3.21542 13.113 4.04072L13.8786 5.2756Z\" fill=\"currentColor\" />\n\t\t</svg>\n\t);\n}\n\n// IconBook\nexport function BookIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M9 6C8.44772 6 8 6.44772 8 7C8 7.55228 8.44772 8 9 8V6ZM15 8C15.5523 8 16 7.55228 16 7C16 6.44772 15.5523 6 15 6V8ZM9 10C8.44772 10 8 10.4477 8 11C8 11.5523 8.44772 12 9 12V10ZM12 12C12.5523 12 13 11.5523 13 11C13 10.4477 12.5523 10 12 10V12ZM7 4H17V2H7V4ZM18 5V19H20V5H18ZM17 20H7V22H17V20ZM6 19V5H4V19H6ZM7 20C6.44771 20 6 19.5523 6 19H4C4 20.6569 5.34315 22 7 22V20ZM18 19C18 19.5523 17.5523 20 17 20V22C18.6569 22 20 20.6569 20 19H18ZM17 4C17.5523 4 18 4.44772 18 5H20C20 3.34315 18.6569 2 17 2V4ZM7 2C5.34315 2 4 3.34315 4 5H6C6 4.44772 6.44772 4 7 4V2ZM18 12V15H20V12H18ZM17 16H7V18H17V16ZM7 22H10V20H7V22ZM7 16C5.34315 16 4 17.3431 4 19H6C6 18.4477 6.44772 18 7 18V16ZM18 15C18 15.5523 17.5523 16 17 16V18C18.6569 18 20 16.6569 20 15H18ZM9 8H15V6H9V8ZM9 12H12V10H9V12Z\" fill=\"currentColor\" />\n\t\t</svg>\n\t);\n}\n\n// IconMegaphone\nexport function MegaphoneIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M17.9961 14.0001C19.6529 14.0001 20.9961 12.657 20.9961 11.0001C20.9961 9.34325 19.6529 8.0001 17.9961 8.0001M12.8254 18.0001C12.4136 19.1653 11.3023 20.0001 9.99609 20.0001C8.33924 20.0001 6.99609 18.657 6.99609 17.0001V15.5001M6.99829 6.5001V15.5001M17.9961 5.73752V16.2627C17.9961 17.617 16.6784 18.5797 15.3882 18.1681L4.38819 14.6585C3.55899 14.394 2.99609 13.6235 2.99609 12.7532V9.24704C2.99609 8.37667 3.55899 7.60622 4.38819 7.34167L15.3882 3.83215C16.6784 3.42051 17.9961 4.38325 17.9961 5.73752Z\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n\t\t</svg>\n\t);\n}\n\n// IconLightBulb\nexport function LightbulbIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M10 21H14M15.6076 15C17.6404 13.7751 19 11.5463 19 9C19 5.13401 15.866 2 12 2C8.13401 2 5 5.13401 5 9C5 11.5463 6.35958 13.7751 8.39241 15M15.6076 15C15.4111 15.1184 15.2084 15.2274 15 15.3264V17C15 17.5523 14.5523 18 14 18H10C9.44772 18 9 17.5523 9 17V15.3264C8.7916 15.2274 8.58886 15.1184 8.39241 15M15.6076 15H8.39241\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n\t\t</svg>\n\t);\n}\n\n// IconCircleQuestionmark\nexport function HelpCircleIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21Z\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n\t\t\t<path d=\"M12 16V16.01\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" />\n\t\t\t<path d=\"M12 13C12 11.3608 14 11.9319 14 10C14 8.89543 13.1046 8 12 8C11.2597 8 10.6134 8.4022 10.2676 9\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n\t\t</svg>\n\t);\n}\n\n// IconNewspaper\nexport function NewspaperIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M16 12V6C16 4.89543 15.1046 4 14 4H5C3.89543 4 3 4.89543 3 6V17.5C3 18.8807 4.11929 20 5.5 20H18.5M16 12V17.5C16 18.8807 17.1193 20 18.5 20M16 12H19C20.1046 12 21 12.8954 21 14V17.5C21 18.8807 19.8807 20 18.5 20M7 16H12M7 8H12V12H7V8Z\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n\t\t</svg>\n\t);\n}\n\n// IconStar\nexport function StarIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M11.5288 2.29524C11.7179 1.90159 12.2821 1.90159 12.4712 2.29524L14.9458 7.44648C15.0219 7.60491 15.1735 7.71434 15.3487 7.73728L21.0456 8.4832C21.4809 8.5402 21.6552 9.07312 21.3368 9.37342L17.1693 13.303C17.0412 13.4238 16.9832 13.6009 17.0154 13.7735L18.0616 19.3857C18.1416 19.8146 17.6852 20.144 17.2993 19.9359L12.249 17.2133C12.0937 17.1296 11.9063 17.1296 11.751 17.2133L6.70073 19.9359C6.3148 20.144 5.85841 19.8146 5.93837 19.3857L6.98459 13.7735C7.01677 13.6009 6.95885 13.4238 6.83068 13.303L2.66324 9.37342C2.34476 9.07312 2.51909 8.5402 2.95444 8.4832L8.65127 7.73728C8.82648 7.71434 8.97811 7.60491 9.05422 7.44648L11.5288 2.29524Z\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n\t\t</svg>\n\t);\n}\n","import type { LinkPreviewPart, TimelineItemMetadata, TimelineItemPart } from \"@helpway/types\";\nimport { t } from \"@helpway/widget-core\";\nimport { useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { handleCodeBlockClick, linkifyText, renderMarkdown } from \"./content/simple-markdown\";\n\ninterface MessageBubbleProps {\n\ttext: string;\n\tsender: \"visitor\" | \"team\" | \"ai\";\n\tsenderName?: string;\n\tparts?: TimelineItemPart[] | null;\n\ttimestamp?: string;\n\t/** Variant payload for interactive messages (quick replies, …). */\n\tmetadata?: TimelineItemMetadata | null;\n\t/** Called when the visitor taps a quick-reply option. */\n\tonQuickReplyTap?: (optionId: string, stepId: string) => void;\n}\n\n/** Single message bubble — Intercom-style, renders text + image/file parts */\nexport function MessageBubble({\n\ttext,\n\tsender,\n\tsenderName,\n\tparts,\n\ttimestamp,\n\tmetadata,\n\tonQuickReplyTap,\n}: MessageBubbleProps) {\n\tconst senderClass = `hw-msg--${sender}`;\n\tconst bubbleRef = useRef<HTMLDivElement>(null);\n\n\tconst imageParts =\n\t\tparts?.filter((p): p is Extract<TimelineItemPart, { type: \"image\" }> => p.type === \"image\") ??\n\t\t[];\n\tconst fileParts =\n\t\tparts?.filter((p): p is Extract<TimelineItemPart, { type: \"file\" }> => p.type === \"file\") ?? [];\n\tconst linkPreviews =\n\t\tparts?.filter(\n\t\t\t(p): p is Extract<TimelineItemPart, { type: \"link-preview\" }> => p.type === \"link-preview\",\n\t\t) ?? [];\n\tconst hasText = text.length > 0;\n\n\tuseEffect(() => {\n\t\tconst bubble = bubbleRef.current;\n\t\tif (!bubble || (sender !== \"ai\" && sender !== \"team\")) return;\n\t\tconst handleClick = (event: Event) => {\n\t\t\thandleCodeBlockClick(event, bubble);\n\t\t};\n\t\tbubble.addEventListener(\"click\", handleClick);\n\t\treturn () => {\n\t\t\tbubble.removeEventListener(\"click\", handleClick);\n\t\t};\n\t}, [sender]);\n\n\treturn (\n\t\t<div className={`hw-msg ${senderClass}`}>\n\t\t\t<div className=\"hw-msg-body\">\n\t\t\t\t{/*\n\t\t\t\t * Team members keep the sender label ABOVE the bubble (real-person\n\t\t\t\t * context matters — visitor wants to know a human is replying).\n\t\t\t\t * AI messages only show the label in the meta row BELOW the bubble\n\t\t\t\t * to avoid double-branding (agent name twice on the same message).\n\t\t\t\t */}\n\t\t\t\t{sender === \"team\" && (\n\t\t\t\t\t<div className=\"hw-msg-sender\">{senderName ?? t(\"widget.support\")}</div>\n\t\t\t\t)}\n\n\t\t\t\t{/* Image attachments */}\n\t\t\t\t{imageParts.length > 0 && (\n\t\t\t\t\t<div className=\"hw-msg-images\">\n\t\t\t\t\t\t{imageParts.map((img, i) => (\n\t\t\t\t\t\t\t<PreviewableThumbnail key={i} src={img.url} />\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{/* Text bubble.\n\t\t\t\t - AI + team messages → renderMarkdown (team composer uses Tiptap → markdown output).\n\t\t\t\t - Visitor messages → linkifyText (widget composer is plain text).\n\t\t\t\t renderMarkdown escapes HTML entities first (&, <, >), so raw HTML cannot be injected.\n\t\t\t\t See packages/widget-react/src/themed/content/simple-markdown.ts for the safety guarantee. */}\n\t\t\t\t{hasText && (\n\t\t\t\t\t<div className=\"hw-msg-bubble\" ref={bubbleRef}>\n\t\t\t\t\t\t{sender === \"ai\" || sender === \"team\" ? (\n\t\t\t\t\t\t\t<span dangerouslySetInnerHTML={{ __html: renderMarkdown(text) }} />\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<span dangerouslySetInnerHTML={{ __html: linkifyText(text) }} />\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{/* File attachments */}\n\t\t\t\t{fileParts.length > 0 && (\n\t\t\t\t\t<div className=\"hw-msg-files\">\n\t\t\t\t\t\t{fileParts.map((file, i) => (\n\t\t\t\t\t\t\t<FileCard key={i} file={file} />\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{/* Link preview cards */}\n\t\t\t\t{linkPreviews.length > 0 && (\n\t\t\t\t\t<div className=\"hw-msg-links\">\n\t\t\t\t\t\t{linkPreviews.map((lp, i) => (\n\t\t\t\t\t\t\t<LinkPreviewCard key={i} preview={lp} />\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{/* Quick reply buttons — workflow is paused awaiting visitor input.\n\t\t\t\t Disabled when metadata.cancelled is set (visitor typed instead). */}\n\t\t\t\t{metadata?.kind === \"quick_replies\" && (\n\t\t\t\t\t<QuickReplyButtons metadata={metadata} onTap={onQuickReplyTap} />\n\t\t\t\t)}\n\n\t\t\t\t{timestamp && (\n\t\t\t\t\t<div className=\"hw-msg-meta\">\n\t\t\t\t\t\t<span className=\"hw-msg-time\">{timestamp}</span>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\n// ── Quick reply buttons (interactive workflow) ────────\n\nfunction QuickReplyButtons({\n\tmetadata,\n\tonTap,\n}: {\n\tmetadata: Extract<TimelineItemMetadata, { kind: \"quick_replies\" }>;\n\tonTap?: (optionId: string, stepId: string) => void;\n}) {\n\tconst [tappedId, setTappedId] = useState<string | null>(null);\n\tconst isLocked = metadata.cancelled || tappedId !== null;\n\n\tconst handleTap = (optionId: string) => {\n\t\tif (isLocked) return;\n\t\tsetTappedId(optionId);\n\t\tonTap?.(optionId, metadata.stepId);\n\t};\n\n\treturn (\n\t\t<div\n\t\t\tclassName=\"hw-quick-replies\"\n\t\t\tdata-cancelled={metadata.cancelled ? \"true\" : undefined}\n\t\t>\n\t\t\t{metadata.options.map((opt) => {\n\t\t\t\tconst isTapped = tappedId === opt.id;\n\t\t\t\treturn (\n\t\t\t\t\t<button\n\t\t\t\t\t\tkey={opt.id}\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"hw-quick-reply-btn\"\n\t\t\t\t\t\tdata-tapped={isTapped ? \"true\" : undefined}\n\t\t\t\t\t\tdisabled={isLocked}\n\t\t\t\t\t\tonClick={() => handleTap(opt.id)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{opt.label}\n\t\t\t\t\t</button>\n\t\t\t\t);\n\t\t\t})}\n\t\t</div>\n\t);\n}\n\n// ── Previewable thumbnail (image) ────────────────\n\nfunction PreviewableThumbnail({ src }: { src: string }) {\n\tconst [hover, setHover] = useState(false);\n\tconst ref = useRef<HTMLAnchorElement>(null);\n\n\treturn (\n\t\t<>\n\t\t\t<a\n\t\t\t\tref={ref}\n\t\t\t\thref={src}\n\t\t\t\ttarget=\"_blank\"\n\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\tclassName=\"hw-msg-image-link\"\n\t\t\t\tonMouseEnter={() => setHover(true)}\n\t\t\t\tonMouseLeave={() => setHover(false)}\n\t\t\t>\n\t\t\t\t<img src={src} alt=\"\" className=\"hw-msg-image\" loading=\"lazy\" />\n\t\t\t</a>\n\t\t\t{hover && <AnchoredPreview src={src} anchorRef={ref} href={src} />}\n\t\t</>\n\t);\n}\n\n// ── File card with hover preview for previewable types ───\n\nconst PREVIEWABLE_EXTS = new Set([\"pdf\", \"csv\", \"png\", \"jpg\", \"jpeg\", \"gif\", \"webp\", \"svg\"]);\n\nfunction FileCard({ file }: { file: Extract<TimelineItemPart, { type: \"file\" }> }) {\n\tconst [hover, setHover] = useState(false);\n\tconst ref = useRef<HTMLAnchorElement>(null);\n\tconst ext = file.fileName.split(\".\").pop()?.toLowerCase() ?? \"\";\n\tconst isPreviewable = PREVIEWABLE_EXTS.has(ext);\n\tconst isImage = file.mimeType.startsWith(\"image/\");\n\n\treturn (\n\t\t<>\n\t\t\t<a\n\t\t\t\tref={ref}\n\t\t\t\thref={file.url}\n\t\t\t\ttarget=\"_blank\"\n\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\tclassName=\"hw-msg-file\"\n\t\t\t\tonMouseEnter={() => isPreviewable && setHover(true)}\n\t\t\t\tonMouseLeave={() => setHover(false)}\n\t\t\t>\n\t\t\t\t<span className=\"hw-msg-file-icon\">\n\t\t\t\t\t<FileTypeIcon ext={ext} />\n\t\t\t\t</span>\n\t\t\t\t<span className=\"hw-msg-file-info\">\n\t\t\t\t\t<span className=\"hw-msg-file-name\">{file.fileName}</span>\n\t\t\t\t\t<span className=\"hw-msg-file-size\">{formatFileSize(file.fileSize)}</span>\n\t\t\t\t</span>\n\t\t\t</a>\n\t\t\t{hover &&\n\t\t\t\tisPreviewable &&\n\t\t\t\t(isImage ? (\n\t\t\t\t\t<AnchoredPreview src={file.url} anchorRef={ref} href={file.url} />\n\t\t\t\t) : (\n\t\t\t\t\t<AnchoredDocPreview fileName={file.fileName} ext={ext} anchorRef={ref} href={file.url} />\n\t\t\t\t))}\n\t\t</>\n\t);\n}\n\n// ── Anchored preview — card popover above the element ──\n\nexport function AnchoredPreview({\n\tsrc,\n\tanchorRef,\n\thref,\n\tonOpen,\n}: {\n\tsrc: string;\n\tanchorRef: React.RefObject<HTMLElement | null>;\n\thref?: string;\n\tonOpen?: () => void;\n}) {\n\tconst [style, setStyle] = useState<React.CSSProperties>({ opacity: 0 });\n\tconst [portalTarget, setPortalTarget] = useState<Element | DocumentFragment | null>(null);\n\n\tuseLayoutEffect(() => {\n\t\tconst anchor = anchorRef.current;\n\t\tif (!anchor) return;\n\n\t\tconst rect = anchor.getBoundingClientRect();\n\t\tconst pw = 260;\n\t\tconst gap = 8;\n\t\tconst vw = window.innerWidth;\n\n\t\tlet left = rect.left + rect.width / 2 - pw / 2;\n\t\tif (left < 8) left = 8;\n\t\tif (left + pw > vw - 8) left = vw - pw - 8;\n\n\t\tconst estimatedH = 200;\n\t\tlet top = rect.top - estimatedH - gap;\n\t\tif (top < 8) top = rect.bottom + gap;\n\n\t\tsetStyle({ left, top, width: pw, opacity: 1 });\n\t\t// Portal into the same root as the anchor so shadow-DOM widgets keep\n\t\t// --hw-* CSS token inheritance and the preview participates in the\n\t\t// widget's z-index stack. Falls back to document.body when the widget\n\t\t// isn't shadow-encapsulated.\n\t\tconst root = anchor.getRootNode();\n\t\tsetPortalTarget(root instanceof ShadowRoot ? root : document.body);\n\t}, [anchorRef]);\n\n\tconst handleClick = () => {\n\t\tif (onOpen) onOpen();\n\t\telse if (href) window.open(href, \"_blank\");\n\t};\n\n\tif (!portalTarget) return null;\n\n\treturn createPortal(\n\t\t<div className=\"hw-hover-preview\" style={style} onClick={handleClick}>\n\t\t\t<img src={src} alt=\"\" className=\"hw-hover-preview-img\" />\n\t\t</div>,\n\t\tportalTarget,\n\t);\n}\n\n// ── Document preview popover (PDF, CSV) ──────────\n\nfunction AnchoredDocPreview({\n\tfileName,\n\text,\n\tanchorRef,\n\thref,\n}: {\n\tfileName: string;\n\text: string;\n\tanchorRef: React.RefObject<HTMLElement | null>;\n\thref: string;\n}) {\n\tconst [style, setStyle] = useState<React.CSSProperties>({ opacity: 0 });\n\tconst [portalTarget, setPortalTarget] = useState<Element | DocumentFragment | null>(null);\n\n\tuseLayoutEffect(() => {\n\t\tconst anchor = anchorRef.current;\n\t\tif (!anchor) return;\n\n\t\tconst rect = anchor.getBoundingClientRect();\n\t\tconst pw = 220;\n\t\tconst ph = 80;\n\t\tconst gap = 8;\n\t\tconst vw = window.innerWidth;\n\n\t\tlet left = rect.left + rect.width / 2 - pw / 2;\n\t\tif (left < 8) left = 8;\n\t\tif (left + pw > vw - 8) left = vw - pw - 8;\n\n\t\tlet top = rect.top - ph - gap;\n\t\tif (top < 8) top = rect.bottom + gap;\n\n\t\tsetStyle({ left, top, width: pw, opacity: 1 });\n\t\tconst root = anchor.getRootNode();\n\t\tsetPortalTarget(root instanceof ShadowRoot ? root : document.body);\n\t}, [anchorRef]);\n\n\tif (!portalTarget) return null;\n\n\treturn createPortal(\n\t\t<div\n\t\t\tclassName=\"hw-hover-preview hw-hover-preview--doc\"\n\t\t\tstyle={style}\n\t\t\tonClick={() => window.open(href, \"_blank\")}\n\t\t>\n\t\t\t<div className=\"hw-hover-preview-doc-icon\">\n\t\t\t\t<FileTypeIcon ext={ext} />\n\t\t\t</div>\n\t\t\t<div className=\"hw-hover-preview-doc-info\">\n\t\t\t\t<span className=\"hw-hover-preview-doc-name\">{fileName}</span>\n\t\t\t\t<span className=\"hw-hover-preview-doc-hint\">{t(\"widget.click_to_open\")}</span>\n\t\t\t</div>\n\t\t</div>,\n\t\tportalTarget,\n\t);\n}\n\n// ── Helpers ──────────────────────────────────────\n\nfunction formatFileSize(bytes: number): string {\n\tif (bytes < 1024) return `${bytes} B`;\n\tif (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} KB`;\n\treturn `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nfunction FileTypeIcon({ ext }: { ext: string }) {\n\t// Color-coded by file type\n\tconst colors: Record<string, string> = {\n\t\tpdf: \"#ef4444\",\n\t\tcsv: \"#22c55e\",\n\t\tdoc: \"#3b82f6\",\n\t\tdocx: \"#3b82f6\",\n\t\txls: \"#22c55e\",\n\t\txlsx: \"#22c55e\",\n\t\ttxt: \"#6b7280\",\n\t\tzip: \"#f59e0b\",\n\t};\n\tconst color = colors[ext] ?? \"currentColor\";\n\n\treturn (\n\t\t<svg\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth={1.5}\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t>\n\t\t\t<path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\" />\n\t\t\t<polyline points=\"14 2 14 8 20 8\" />\n\t\t\t{ext === \"pdf\" && (\n\t\t\t\t<text x=\"8\" y=\"18\" fontSize=\"6\" fill={color} stroke=\"none\" fontWeight=\"700\">\n\t\t\t\t\tPDF\n\t\t\t\t</text>\n\t\t\t)}\n\t\t\t{ext === \"csv\" && (\n\t\t\t\t<text x=\"7\" y=\"18\" fontSize=\"6\" fill={color} stroke=\"none\" fontWeight=\"700\">\n\t\t\t\t\tCSV\n\t\t\t\t</text>\n\t\t\t)}\n\t\t</svg>\n\t);\n}\n\n// ── Link preview card (Intercom-style) ──────────────\n\nfunction LinkPreviewCard({ preview }: { preview: LinkPreviewPart }) {\n\tconst hostname = (() => {\n\t\ttry { return new URL(preview.url).hostname; } catch { return preview.url; }\n\t})();\n\treturn (\n\t\t<a\n\t\t\thref={preview.url}\n\t\t\ttarget=\"_blank\"\n\t\t\trel=\"noopener noreferrer\"\n\t\t\tclassName=\"hw-link-preview\"\n\t\t\tonClick={(e) => e.stopPropagation()}\n\t\t>\n\t\t\t{preview.imageUrl && (\n\t\t\t\t<img\n\t\t\t\t\tsrc={preview.imageUrl}\n\t\t\t\t\talt=\"\"\n\t\t\t\t\tclassName=\"hw-link-preview-img\"\n\t\t\t\t\tloading=\"lazy\"\n\t\t\t\t\tonError={(e) => { (e.target as HTMLImageElement).style.display = \"none\"; }}\n\t\t\t\t/>\n\t\t\t)}\n\t\t\t<div className=\"hw-link-preview-body\">\n\t\t\t\t{preview.favicon && (\n\t\t\t\t\t<img\n\t\t\t\t\t\tsrc={preview.favicon}\n\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\tclassName=\"hw-link-preview-favicon\"\n\t\t\t\t\t\twidth={16}\n\t\t\t\t\t\theight={16}\n\t\t\t\t\t\tonError={(e) => { (e.target as HTMLImageElement).style.display = \"none\"; }}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t\t{preview.title && <div className=\"hw-link-preview-title\">{preview.title}</div>}\n\t\t\t\t{preview.description && (\n\t\t\t\t\t<div className=\"hw-link-preview-desc\">{preview.description.slice(0, 120)}</div>\n\t\t\t\t)}\n\t\t\t\t<div className=\"hw-link-preview-url\">{hostname}</div>\n\t\t\t</div>\n\t\t</a>\n\t);\n}\n","import { useEffect, useRef } from \"react\";\n\nconst 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>`;\n\nconst 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>`;\n\nfunction inferCodeLanguage(code: string, lang?: string): string {\n\tif (lang) return lang;\n\tconst trimmed = code.trim();\n\tif (/^(npm|pnpm|yarn|bun|npx|curl|cd|mkdir|cp|mv|rm|export)\\b/m.test(trimmed)) return \"bash\";\n\tif (/\\b(import|export)\\b/.test(trimmed) && /<[A-Z_a-z][\\w.:-]*(\\s|>)/.test(trimmed)) return \"tsx\";\n\tif (/\\b(import|export|const|let|function|type|interface)\\b/.test(trimmed)) return \"ts\";\n\tif (/^\\s*[{[]/.test(trimmed)) return \"json\";\n\treturn \"code\";\n}\n\nexport function handleCodeBlockClick(e: Event, root: HTMLElement): void {\n\tconst target = e.target as HTMLElement | null;\n\tconst btn = target?.closest<HTMLButtonElement>(\".hw-code-copy\");\n\tif (!btn || !root.contains(btn)) return;\n\tconst block = btn.closest(\".hw-code\");\n\tconst code = block?.querySelector(\"pre code\");\n\tconst text = code?.textContent ?? \"\";\n\tif (!text) return;\n\tvoid navigator.clipboard?.writeText(text).then(\n\t\t() => flashCopied(btn),\n\t\t() => flashCopied(btn, true),\n\t);\n}\n\n/**\n * Lightweight Markdown → HTML renderer.\n * Zero dependencies. Handles common patterns:\n * headings, bold, italic, code, links, lists, blockquotes, images, hr.\n *\n * Security note: Content is served from Better i18n Content CMS which only\n * accepts authenticated writes (secret API key). The CMS sanitizes content\n * server-side. Additionally, our renderMarkdown escapes HTML entities before\n * processing markdown syntax, preventing injection of raw HTML tags.\n */\nexport function renderMarkdown(md: string): string {\n\t// Stash fenced code blocks BEFORE any other pass. Fence content must be\n\t// preserved verbatim: no bold, no autolink, no newline→<br> — otherwise\n\t// a curl command or JSON sample gets shredded. We also escape HTML inside\n\t// the block (the global escape below runs only on the remaining markdown).\n\tconst codeBlocks: string[] = [];\n\tconst codeBlockPlaceholder = (i: number) => `\\u0000CODEBLOCK${i}\\u0000`;\n\tconst body = md.replace(\n\t\t// Eat ALL newlines around the fence (zero-or-more both sides). The\n\t\t// replacement re-emits its own `\\n\\n` pair so the paragraph splitter\n\t\t// cleanly bookends the fence. Without this, `before\\n\\n` + `\\n\\n` from\n\t\t// us = 3 newlines, the extra one becomes <br /> and lands inside a <p>.\n\t\t/\\n*```(\\w+)?\\n?([\\s\\S]*?)```\\n*/g,\n\t\t(_match, lang: string | undefined, code: string) => {\n\t\t\tconst escaped = code.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n\t\t\tconst langLabel = inferCodeLanguage(code, lang);\n\t\t\tconst className = langLabel !== \"code\" ? ` class=\"language-${langLabel}\"` : \"\";\n\t\t\t// Render every fenced block with a header bar (language label + copy\n\t\t\t// button) so it reads like a proper code card, not a bare <pre>.\n\t\t\t// The actual copy action is wired up in MarkdownContent via event\n\t\t\t// delegation — we only need the markup + a stable attribute to key\n\t\t\t// off of.\n\t\t\tconst trimmed = escaped.replace(/\\n$/, \"\");\n\t\t\tcodeBlocks.push(\n\t\t\t\t`<div class=\"hw-code\" data-hw-code=\"1\"><div class=\"hw-code-header\"><span class=\"hw-code-lang\">${langLabel}</span><div class=\"hw-code-actions\"><button type=\"button\" class=\"hw-code-action hw-code-copy\" aria-label=\"Copy code\" title=\"Copy code\">${COPY_ICON}${CHECK_ICON}<span class=\"hw-code-copy-label\">Copy</span></button></div></div><pre><code${className}>${trimmed}</code></pre></div>`,\n\t\t\t);\n\t\t\t// Sandwich the placeholder in blank lines so the paragraph splitter\n\t\t\t// treats it as its own block. Otherwise a fence that follows a\n\t\t\t// paragraph without a separating blank line ends up inside a <p>\n\t\t\t// (invalid HTML, collapses the <pre>).\n\t\t\treturn `\\n\\n${codeBlockPlaceholder(codeBlocks.length - 1)}\\n\\n`;\n\t\t},\n\t);\n\n\tlet html = body\n\t\t// Escape HTML entities FIRST — prevents XSS from raw HTML in markdown\n\t\t.replace(/&/g, \"&amp;\")\n\t\t.replace(/</g, \"&lt;\")\n\t\t.replace(/>/g, \"&gt;\")\n\t\t// Headings (### h3, ## h2, # h1)\n\t\t.replace(/^### (.+)$/gm, \"<h3>$1</h3>\")\n\t\t.replace(/^## (.+)$/gm, \"<h2>$1</h2>\")\n\t\t.replace(/^# (.+)$/gm, \"<h1>$1</h1>\")\n\t\t// Horizontal rule\n\t\t.replace(/^---$/gm, \"<hr />\")\n\t\t// Bold + italic\n\t\t.replace(/\\*\\*\\*(.+?)\\*\\*\\*/g, \"<strong><em>$1</em></strong>\")\n\t\t// Bold\n\t\t.replace(/\\*\\*(.+?)\\*\\*/g, \"<strong>$1</strong>\")\n\t\t// Italic\n\t\t.replace(/\\*(.+?)\\*/g, \"<em>$1</em>\")\n\t\t// Inline code\n\t\t.replace(/`([^`]+)`/g, \"<code>$1</code>\")\n\t\t// Images\n\t\t.replace(/!\\[([^\\]]*)\\]\\(([^)]+)\\)/g, '<img src=\"$2\" alt=\"$1\" />')\n\t\t// Links (markdown format)\n\t\t.replace(\n\t\t\t/\\[([^\\]]+)\\]\\(([^)]+)\\)/g,\n\t\t\t'<a href=\"$2\" target=\"_blank\" rel=\"noopener noreferrer\">$1</a>',\n\t\t)\n\t\t// Auto-link bare URLs (not already inside an href or markdown link)\n\t\t.replace(\n\t\t\t/(?<!\")(?<!=)(https?:\\/\\/[^\\s<)]+)/g,\n\t\t\t'<a href=\"$1\" target=\"_blank\" rel=\"noopener noreferrer\">$1</a>',\n\t\t)\n\t\t// Blockquotes\n\t\t.replace(/^&gt; (.+)$/gm, \"<blockquote>$1</blockquote>\")\n\t\t// Unordered lists\n\t\t.replace(/^[*-] (.+)$/gm, \"<li>$1</li>\")\n\t\t// Ordered lists — temp <oli> tag so the <ul> wrapper below can't claim\n\t\t// them; renamed to <li> when wrapped in <ol>.\n\t\t.replace(/^\\d+\\. (.+)$/gm, \"<oli>$1</oli>\");\n\n\t// Tables — must run while real newlines still exist (before the <br> pass).\n\t// Runs AFTER the inline passes so bold/links inside cells are already HTML.\n\t// Stashed as placeholders like code blocks so the paragraph splitter can't\n\t// chop a <table> in half.\n\tconst tables: string[] = [];\n\tconst tablePlaceholder = (i: number) => `\\u0000TABLE${i}\\u0000`;\n\thtml = html.replace(\n\t\t// header row | separator row (only - : | spaces) | 1+ body rows\n\t\t/^(\\|.+\\|)[ \\t]*\\n\\|[ \\t:|-]+\\|[ \\t]*\\n((?:\\|.+\\|[ \\t]*(?:\\n|$))+)/gm,\n\t\t(_match, headerLine: string, bodyLines: string) => {\n\t\t\tconst cells = (line: string) =>\n\t\t\t\tline.trim().replace(/^\\||\\|$/g, \"\").split(\"|\").map((c) => c.trim());\n\t\t\tconst head = cells(headerLine)\n\t\t\t\t.map((c) => `<th>${c}</th>`)\n\t\t\t\t.join(\"\");\n\t\t\tconst rows = bodyLines\n\t\t\t\t.trim()\n\t\t\t\t.split(\"\\n\")\n\t\t\t\t.map((line) => `<tr>${cells(line).map((c) => `<td>${c}</td>`).join(\"\")}</tr>`)\n\t\t\t\t.join(\"\");\n\t\t\ttables.push(\n\t\t\t\t`<div class=\"hw-table-wrap\"><table class=\"hw-table\"><thead><tr>${head}</tr></thead><tbody>${rows}</tbody></table></div>`,\n\t\t\t);\n\t\t\treturn `\\n\\n${tablePlaceholder(tables.length - 1)}\\n\\n`;\n\t\t},\n\t);\n\n\t// Wrap consecutive list items BEFORE newlines become <br /> — the old\n\t// post-<br> wrap could only ever see one <li> at a time, producing a\n\t// separate <ul> per item with stray <br />s in between.\n\thtml = html\n\t\t.replace(/((?:<li>.*<\\/li>\\n?)+)/g, (m) => `<ul>${m.replace(/\\n/g, \"\")}</ul>\\n`)\n\t\t.replace(\n\t\t\t/((?:<oli>.*<\\/oli>\\n?)+)/g,\n\t\t\t(m) => `<ol>${m.replace(/\\n/g, \"\").replace(/<(\\/?)oli>/g, \"<$1li>\")}</ol>\\n`,\n\t\t);\n\n\thtml = html\n\t\t// Paragraphs (double newline)\n\t\t.replace(/\\n\\n/g, \"</p><p>\")\n\t\t// Single newlines → br\n\t\t.replace(/\\n/g, \"<br />\");\n\n\t// Lists glued to surrounding text by a single newline pick up a stray\n\t// <br /> neighbor — drop it so spacing comes from CSS, not phantom breaks.\n\t// Same for a <br /> opening a paragraph (left over from placeholder seams).\n\thtml = html\n\t\t.replace(/<br \\/>(\\s*<(?:ul|ol)>)/g, \"$1\")\n\t\t.replace(/(<\\/(?:ul|ol)>\\s*)<br \\/>/g, \"$1\")\n\t\t.replace(/<p><br \\/>/g, \"<p>\");\n\n\t// Wrap in paragraph if not starting with a block element\n\tif (\n\t\t!html.startsWith(\"<h\") &&\n\t\t!html.startsWith(\"<ul\") &&\n\t\t!html.startsWith(\"<ol\") &&\n\t\t!html.startsWith(\"<blockquote\") &&\n\t\t!html.startsWith(\"<hr\")\n\t) {\n\t\thtml = `<p>${html}</p>`;\n\t}\n\n\t// Re-inject tables (same placeholder mechanics as code blocks below).\n\tif (tables.length > 0) {\n\t\t// biome-ignore lint/suspicious/noControlCharactersInRegex: placeholders use NUL sentinels intentionally.\n\t\thtml = html.replace(/\\u0000TABLE(\\d+)\\u0000/g, (_m, idx: string) => {\n\t\t\tconst i = Number.parseInt(idx, 10);\n\t\t\treturn tables[i] ?? \"\";\n\t\t});\n\t\t// Unwrap a <p> that ended up directly around a table (no blank-line\n\t\t// separator in the source) — invalid nesting collapses the layout.\n\t\thtml = html.replace(/<p>(\\s*<div class=\"hw-table-wrap\"[\\s\\S]*?<\\/div>\\s*)<\\/p>/g, \"$1\");\n\t}\n\n\t// A list that landed inside a <p> (single blank line before it) is invalid\n\t// nesting — unwrap like the code-block case below.\n\thtml = html.replace(/<p>(\\s*<(?:ul|ol)>[\\s\\S]*?<\\/(?:ul|ol)>\\s*)<\\/p>/g, \"$1\");\n\n\t// Re-inject code blocks now that surrounding paragraphs / <br> passes are\n\t// done. Placeholders used NUL sentinels so they can't collide with user\n\t// content or be accidentally wrapped by the block-element heuristics above.\n\tif (codeBlocks.length > 0) {\n\t\t// biome-ignore lint/suspicious/noControlCharactersInRegex: placeholders use NUL sentinels intentionally.\n\t\thtml = html.replace(/\\u0000CODEBLOCK(\\d+)\\u0000/g, (_m, idx: string) => {\n\t\t\tconst i = Number.parseInt(idx, 10);\n\t\t\treturn codeBlocks[i] ?? \"\";\n\t\t});\n\t\t// A code block that landed inside a <p> (because the preceding line had no\n\t\t// blank-line separator) becomes invalid nesting (<p><div><pre>). Unwrap\n\t\t// the outer <p> so the block stands on its own.\n\t\thtml = html.replace(/<p>(\\s*<div class=\"hw-code\"[\\s\\S]*?<\\/div>\\s*)<\\/p>/g, \"$1\");\n\t}\n\n\treturn html;\n}\n\n/**\n * Convert bare URLs in plain text to clickable links.\n * Used for visitor/team messages (not full markdown).\n * HTML-escaped for safety.\n */\nexport function linkifyText(text: string): string {\n\treturn text\n\t\t.replace(/&/g, \"&amp;\")\n\t\t.replace(/</g, \"&lt;\")\n\t\t.replace(/>/g, \"&gt;\")\n\t\t.replace(\n\t\t\t/(https?:\\/\\/[^\\s<]+)/g,\n\t\t\t'<a href=\"$1\" target=\"_blank\" rel=\"noopener noreferrer\">$1</a>',\n\t\t)\n\t\t.replace(/\\n/g, \"<br />\");\n}\n\n/**\n * Renders markdown or pre-rendered HTML content.\n * Prefers bodyHtml (server-sanitized by CMS) when available,\n * falls back to client-side markdown rendering (HTML-escaped).\n */\nexport function MarkdownContent({\n\tbodyHtml,\n\tbodyMarkdown,\n\tclassName,\n}: {\n\tbodyHtml?: string | null;\n\tbodyMarkdown?: string | null;\n\tclassName?: string;\n}) {\n\tconst rootRef = useRef<HTMLDivElement>(null);\n\tconst html = bodyHtml ?? (bodyMarkdown ? renderMarkdown(bodyMarkdown) : \"\");\n\n\t// Strip whitespace-only block elements after the HTML lands in the DOM.\n\t// PlateJS/Slate/ProseMirror CMS bodies emit <p>&nbsp;</p> or <div> </div>\n\t// to represent visual line breaks. CSS `:empty` doesn't match these (the\n\t// nbsp/space is a text node) and CSS has no text-content selector, so we\n\t// clean them up here. Runs once per html change.\n\tuseEffect(() => {\n\t\tconst root = rootRef.current;\n\t\tif (!root) return;\n\n\t\tconst isWhitespaceOnly = (el: Element): boolean => {\n\t\t\t// No element children OR only <br> children, AND text is whitespace/empty\n\t\t\tconst hasNonBrChild = Array.from(el.children).some(\n\t\t\t\t(c) => c.tagName !== \"BR\",\n\t\t\t);\n\t\t\tif (hasNonBrChild) return false;\n\t\t\tconst text = el.textContent ?? \"\";\n\t\t\treturn text.replace(/[\\s ]/g, \"\") === \"\";\n\t\t};\n\n\t\tconst removeEmpties = () => {\n\t\t\tconst candidates = root.querySelectorAll(\"p, div\");\n\t\t\tcandidates.forEach((el) => {\n\t\t\t\tif (isWhitespaceOnly(el)) el.remove();\n\t\t\t});\n\t\t};\n\t\tremoveEmpties();\n\t}, [html]);\n\n\t// Event-delegated copy handler for any `.hw-code-copy` button inside the\n\t// rendered tree. Using delegation instead of rendering each code block as\n\t// a React component keeps the markdown → HTML path zero-dep.\n\tuseEffect(() => {\n\t\tconst root = rootRef.current;\n\t\tif (!root) return;\n\t\tconst handler = (e: Event) => {\n\t\t\thandleCodeBlockClick(e, root);\n\t\t};\n\t\troot.addEventListener(\"click\", handler);\n\t\treturn () => {\n\t\t\troot.removeEventListener(\"click\", handler);\n\t\t};\n\t}, []);\n\n\tif (!html) return null;\n\n\treturn (\n\t\t<div\n\t\t\tref={rootRef}\n\t\t\tclassName={`hw-markdown ${className ?? \"\"}`}\n\t\t\t// Content is from authenticated CMS (server-sanitized bodyHtml)\n\t\t\t// or client-side rendered with HTML entity escaping (renderMarkdown).\n\t\t\t// biome-ignore lint/security/noDangerouslySetInnerHtml: trusted CMS content\n\t\t\tdangerouslySetInnerHTML={{ __html: html }}\n\t\t/>\n\t);\n}\n\nfunction flashCopied(btn: HTMLButtonElement, failed = false) {\n\tconst label = btn.querySelector(\".hw-code-copy-label\");\n\tif (!label) return;\n\tconst original = label.textContent ?? \"Copy\";\n\tlabel.textContent = failed ? \"Failed\" : \"Copied\";\n\tbtn.classList.add(failed ? \"hw-code-copy--failed\" : \"hw-code-copy--copied\");\n\tsetTimeout(() => {\n\t\tlabel.textContent = original;\n\t\tbtn.classList.remove(\"hw-code-copy--copied\", \"hw-code-copy--failed\");\n\t}, 1500);\n}\n","import type { TimelineItem } from \"@helpway/types\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { useWidgetContext, useWidgetStore } from \"../provider\";\n\ninterface DebugEvent {\n\tid: string;\n\tt: number;\n\tkind: \"trpc\" | \"ws\" | \"store\" | \"error\";\n\tlabel: string;\n\tdetail?: string;\n}\n\nconst MAX_EVENTS = 60;\n\nfunction isDebugEnabled(): boolean {\n\tif (typeof window === \"undefined\") return false;\n\tif (typeof window.localStorage !== \"undefined\" && window.localStorage.getItem(\"hw:debug\") === \"1\") {\n\t\treturn true;\n\t}\n\tconst search = window.location?.search ?? \"\";\n\treturn search.includes(\"hwdebug=1\") || search.includes(\"debug=hw\");\n}\n\nfunction senderOf(item: TimelineItem): string {\n\tif (item.visitorId) return \"visitor\";\n\tif (item.aiAgentId) return \"ai\";\n\tif (item.userId) return \"team\";\n\treturn item.type;\n}\n\nexport function WidgetDebugOverlay() {\n\tconst [enabled, setEnabled] = useState(false);\n\tconst [open, setOpen] = useState(true);\n\tconst [events, setEvents] = useState<DebugEvent[]>([]);\n\tconst eventsRef = useRef<DebugEvent[]>([]);\n\n\t// Subscribe to each field individually — returning a fresh object from a\n\t// selector triggers an infinite re-render loop with zustand because each\n\t// render produces a new object reference.\n\tconst activeId = useWidgetStore((s) => s.activeConversationId);\n\tconst messagesMap = useWidgetStore((s) => s.messages);\n\tconst typingUsers = useWidgetStore((s) => s.typingUsers);\n\tconst aiProcessingMap = useWidgetStore((s) => s.aiProcessing);\n\tconst { store } = useWidgetContext();\n\n\tuseEffect(() => {\n\t\tsetEnabled(isDebugEnabled());\n\t}, []);\n\n\tconst pushEvent = useMemo(\n\t\t() => (ev: Omit<DebugEvent, \"id\" | \"t\">) => {\n\t\t\tconst e: DebugEvent = {\n\t\t\t\t...ev,\n\t\t\t\tid: `${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,\n\t\t\t\tt: Date.now(),\n\t\t\t};\n\t\t\teventsRef.current = [e, ...eventsRef.current].slice(0, MAX_EVENTS);\n\t\t\tsetEvents(eventsRef.current);\n\t\t},\n\t\t[],\n\t);\n\n\t// Intercept fetch to log tRPC calls — works with any tRPC proxy shape\n\t// because we observe at the network boundary, not the client object.\n\tuseEffect(() => {\n\t\tif (!enabled) return;\n\t\tif (typeof window === \"undefined\" || typeof window.fetch !== \"function\") return;\n\t\tconst originalFetch = window.fetch.bind(window);\n\t\tconst patched = (async (input: RequestInfo | URL, init?: RequestInit) => {\n\t\t\tconst url = typeof input === \"string\" ? input : input instanceof URL ? input.toString() : input.url;\n\t\t\tconst isTrpc = url.includes(\"/trpc/\");\n\t\t\tif (isTrpc) {\n\t\t\t\tconst method = init?.method ?? (typeof input !== \"string\" && !(input instanceof URL) ? input.method : \"GET\");\n\t\t\t\tconst label = url.split(\"/trpc/\")[1]?.split(\"?\")[0] ?? url;\n\t\t\t\tpushEvent({ kind: \"trpc\", label: `→ ${method} ${label}`, detail: shortJson(init?.body) });\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst res = await originalFetch(input, init);\n\t\t\t\tif (isTrpc) {\n\t\t\t\t\tconst label = url.split(\"/trpc/\")[1]?.split(\"?\")[0] ?? url;\n\t\t\t\t\tpushEvent({ kind: \"trpc\", label: `← ${res.status} ${label}` });\n\t\t\t\t}\n\t\t\t\treturn res;\n\t\t\t} catch (err) {\n\t\t\t\tif (isTrpc) {\n\t\t\t\t\tconst label = url.split(\"/trpc/\")[1]?.split(\"?\")[0] ?? url;\n\t\t\t\t\tpushEvent({ kind: \"error\", label: `✘ ${label}`, detail: err instanceof Error ? err.message : String(err) });\n\t\t\t\t}\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t}) as unknown as typeof window.fetch;\n\t\twindow.fetch = patched;\n\t\treturn () => {\n\t\t\twindow.fetch = originalFetch;\n\t\t};\n\t}, [enabled, pushEvent]);\n\n\t// Tap WebSocket events by wrapping the store's handleRealtimeEvent\n\tuseEffect(() => {\n\t\tif (!enabled) return;\n\t\tconst original = store.getState().handleRealtimeEvent;\n\t\tstore.setState({\n\t\t\thandleRealtimeEvent: (ev) => {\n\t\t\t\tpushEvent({ kind: \"ws\", label: ev.type, detail: shortJson(ev) });\n\t\t\t\toriginal(ev);\n\t\t\t},\n\t\t});\n\t\treturn () => {\n\t\t\tstore.setState({ handleRealtimeEvent: original });\n\t\t};\n\t}, [enabled, store, pushEvent]);\n\n\t// Emit a marker when messages array changes for the active conversation\n\tconst activeMessages = activeId ? messagesMap.get(activeId) ?? [] : [];\n\tconst lastMsgSignature = useMemo(\n\t\t() => activeMessages.map((m) => `${m.id}:${senderOf(m)}:${m.createdAt}`).join(\"|\"),\n\t\t[activeMessages],\n\t);\n\tconst prevSigRef = useRef(lastMsgSignature);\n\tuseEffect(() => {\n\t\tif (!enabled) return;\n\t\tif (prevSigRef.current !== lastMsgSignature) {\n\t\t\tprevSigRef.current = lastMsgSignature;\n\t\t\tpushEvent({\n\t\t\t\tkind: \"store\",\n\t\t\t\tlabel: `messages[${activeMessages.length}]`,\n\t\t\t\tdetail: activeMessages\n\t\t\t\t\t.map((m, i) => `${i}:${senderOf(m)}=${(m.text ?? \"\").slice(0, 24)}`)\n\t\t\t\t\t.join(\" | \"),\n\t\t\t});\n\t\t}\n\t}, [lastMsgSignature, activeMessages, enabled, pushEvent]);\n\n\tif (!enabled) return null;\n\n\tconst isTyping = activeId ? typingUsers.get(activeId) : false;\n\tconst isAi = activeId ? aiProcessingMap.get(activeId) : false;\n\n\treturn (\n\t\t<div style={styles.wrap}>\n\t\t\t<div style={styles.header}>\n\t\t\t\t<strong>hw debug</strong>\n\t\t\t\t<span style={styles.meta}>\n\t\t\t\t\t{\" \"}· conv {activeId ? activeId.slice(0, 10) : \"—\"} · items {activeMessages.length} · typing {isTyping ? \"Y\" : \"n\"} · ai {isAi ? \"Y\" : \"n\"}\n\t\t\t\t</span>\n\t\t\t\t<button type=\"button\" style={styles.btn} onClick={() => setOpen((v) => !v)}>{open ? \"hide\" : \"show\"}</button>\n\t\t\t\t<button type=\"button\" style={styles.btn} onClick={() => { eventsRef.current = []; setEvents([]); }}>clear</button>\n\t\t\t</div>\n\t\t\t{open && (\n\t\t\t\t<div style={styles.body}>\n\t\t\t\t\t<div style={styles.section}>\n\t\t\t\t\t\t<div style={styles.sectionTitle}>messages (active)</div>\n\t\t\t\t\t\t{activeMessages.length === 0 ? (\n\t\t\t\t\t\t\t<div style={styles.empty}>empty</div>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\tactiveMessages.map((m, i) => (\n\t\t\t\t\t\t\t\t<div key={m.id} style={styles.row}>\n\t\t\t\t\t\t\t\t\t<span style={{ ...styles.badge, background: colorFor(senderOf(m)) }}>{i}</span>\n\t\t\t\t\t\t\t\t\t<span style={styles.sender}>{senderOf(m)}</span>\n\t\t\t\t\t\t\t\t\t<span style={styles.ts}>{m.createdAt.slice(11, 23)}</span>\n\t\t\t\t\t\t\t\t\t<span style={styles.text}>{(m.text ?? \"\").slice(0, 60)}</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t))\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div style={styles.section}>\n\t\t\t\t\t\t<div style={styles.sectionTitle}>events</div>\n\t\t\t\t\t\t{events.length === 0 ? (\n\t\t\t\t\t\t\t<div style={styles.empty}>no events yet — send a message</div>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\tevents.map((e) => (\n\t\t\t\t\t\t\t\t<div key={e.id} style={styles.row}>\n\t\t\t\t\t\t\t\t\t<span style={{ ...styles.badge, background: kindColor(e.kind) }}>{e.kind}</span>\n\t\t\t\t\t\t\t\t\t<span style={styles.ts}>{new Date(e.t).toISOString().slice(11, 23)}</span>\n\t\t\t\t\t\t\t\t\t<span style={styles.evLabel}>{e.label}</span>\n\t\t\t\t\t\t\t\t\t{e.detail && <span style={styles.detail}>{e.detail}</span>}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t))\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nfunction shortJson(v: unknown): string {\n\tif (v === undefined) return \"\";\n\ttry {\n\t\tconst s = JSON.stringify(v);\n\t\tif (!s) return \"\";\n\t\treturn s.length > 180 ? `${s.slice(0, 177)}…` : s;\n\t} catch {\n\t\treturn String(v);\n\t}\n}\n\nfunction colorFor(sender: string): string {\n\tswitch (sender) {\n\t\tcase \"visitor\":\n\t\t\treturn \"#1d4ed8\";\n\t\tcase \"ai\":\n\t\t\treturn \"#7c3aed\";\n\t\tcase \"team\":\n\t\t\treturn \"#16a34a\";\n\t\tdefault:\n\t\t\treturn \"#6b7280\";\n\t}\n}\n\nfunction kindColor(kind: DebugEvent[\"kind\"]): string {\n\tswitch (kind) {\n\t\tcase \"trpc\":\n\t\t\treturn \"#0ea5e9\";\n\t\tcase \"ws\":\n\t\t\treturn \"#f97316\";\n\t\tcase \"store\":\n\t\t\treturn \"#64748b\";\n\t\tcase \"error\":\n\t\t\treturn \"#dc2626\";\n\t}\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n\twrap: {\n\t\tposition: \"fixed\",\n\t\tright: 12,\n\t\tbottom: 12,\n\t\tzIndex: 2147483000,\n\t\twidth: 420,\n\t\tmaxHeight: \"70vh\",\n\t\tbackground: \"rgba(9,9,11,0.94)\",\n\t\tcolor: \"#e5e7eb\",\n\t\tborderRadius: 10,\n\t\tfontFamily: \"ui-monospace, SFMono-Regular, Menlo, monospace\",\n\t\tfontSize: 11,\n\t\tboxShadow: \"0 12px 30px rgba(0,0,0,0.35)\",\n\t\toverflow: \"hidden\",\n\t\tpointerEvents: \"auto\",\n\t},\n\theader: {\n\t\tdisplay: \"flex\",\n\t\talignItems: \"center\",\n\t\tgap: 6,\n\t\tpadding: \"6px 10px\",\n\t\tbackground: \"#18181b\",\n\t\tborderBottom: \"1px solid #27272a\",\n\t},\n\tmeta: { flex: 1, color: \"#a1a1aa\", fontSize: 10 },\n\tbtn: {\n\t\tbackground: \"#27272a\",\n\t\tcolor: \"#e4e4e7\",\n\t\tborder: \"1px solid #3f3f46\",\n\t\tborderRadius: 4,\n\t\tpadding: \"2px 8px\",\n\t\tcursor: \"pointer\",\n\t\tfontSize: 10,\n\t},\n\tbody: { display: \"flex\", flexDirection: \"column\", maxHeight: \"calc(70vh - 32px)\", overflow: \"auto\" },\n\tsection: { borderBottom: \"1px solid #27272a\", padding: \"6px 10px\" },\n\tsectionTitle: { color: \"#a1a1aa\", fontSize: 10, textTransform: \"uppercase\", letterSpacing: 0.6, marginBottom: 4 },\n\trow: {\n\t\tdisplay: \"grid\",\n\t\tgridTemplateColumns: \"32px 56px 72px 1fr\",\n\t\tgap: 6,\n\t\talignItems: \"baseline\",\n\t\tpadding: \"2px 0\",\n\t\tborderTop: \"1px dashed #27272a\",\n\t},\n\tbadge: {\n\t\tdisplay: \"inline-block\",\n\t\tborderRadius: 3,\n\t\tpadding: \"1px 4px\",\n\t\tcolor: \"white\",\n\t\tfontSize: 9,\n\t\ttextAlign: \"center\",\n\t},\n\tsender: { color: \"#d4d4d8\" },\n\tts: { color: \"#71717a\", fontSize: 10 },\n\ttext: { color: \"#e4e4e7\", whiteSpace: \"nowrap\", overflow: \"hidden\", textOverflow: \"ellipsis\" },\n\tevLabel: { color: \"#e4e4e7\" },\n\tdetail: { gridColumn: \"1 / -1\", color: \"#a1a1aa\", fontSize: 10, whiteSpace: \"pre-wrap\", wordBreak: \"break-all\" },\n\tempty: { color: \"#52525b\", fontStyle: \"italic\", fontSize: 10 },\n};\n","import { resolveLabel, t } from \"@helpway/widget-core\";\nimport type { WidgetContentTab } from \"@helpway/widget-core\";\nimport { useCallback, useEffect } from \"react\";\nimport { useContentTab } from \"../../hooks/use-content-tab\";\nimport type { ContentEntryItem } from \"../../hooks/use-content-tab\";\nimport { ContentDetailView } from \"./content-detail-view\";\nimport { ContentListView } from \"./content-list-view\";\nimport { GroupedContentTabView } from \"./grouped-content-tab-view\";\n\n/**\n * Content tab dispatcher:\n * - \"flat\" (default) → simple list → detail\n * - \"grouped\" → categories → items → detail\n */\nexport function ContentTabView({\n\ttab,\n\tshowDetail,\n\tdetailSlug,\n\tsubView,\n\tonSelectEntry,\n\tonSelectCategory,\n}: {\n\ttab: WidgetContentTab;\n\tshowDetail: boolean;\n\tdetailSlug: string | null;\n\tsubView?: string | null;\n\tonSelectEntry: (slug: string) => void;\n\tonSelectCategory?: (category: ContentEntryItem) => void;\n}) {\n\t// ── Grouped tab ──\n\tif (tab.tabType === \"grouped\" && tab.itemsModelSlug) {\n\t\treturn (\n\t\t\t<GroupedContentTabView\n\t\t\t\ttab={tab}\n\t\t\t\tsubView={subView ?? null}\n\t\t\t\tdetailSlug={detailSlug}\n\t\t\t\tonSelectCategory={onSelectCategory ?? (() => {})}\n\t\t\t\tonSelectEntry={onSelectEntry}\n\t\t\t/>\n\t\t);\n\t}\n\n\t// ── Flat tab (default) ──\n\treturn (\n\t\t<FlatContentTabView\n\t\t\ttab={tab}\n\t\t\tshowDetail={showDetail}\n\t\t\tdetailSlug={detailSlug}\n\t\t\tonSelectEntry={onSelectEntry}\n\t\t/>\n\t);\n}\n\n// ── Flat (original behavior) ─────────────────────────────\n\nfunction FlatContentTabView({\n\ttab,\n\tshowDetail,\n\tdetailSlug,\n\tonSelectEntry,\n}: {\n\ttab: WidgetContentTab;\n\tshowDetail: boolean;\n\tdetailSlug: string | null;\n\tonSelectEntry: (slug: string) => void;\n}) {\n\tconst {\n\t\tentries,\n\t\tdetail,\n\t\tisLoading,\n\t\tisLoadingDetail,\n\t\thasMore,\n\t\tfetchEntries,\n\t\tloadMore,\n\t\tfetchDetail,\n\t} = useContentTab(tab.id);\n\n\tuseEffect(() => {\n\t\tif (detailSlug) fetchDetail(detailSlug);\n\t}, [detailSlug, fetchDetail]);\n\n\tconst handleSearch = useCallback(\n\t\t(query: string) => {\n\t\t\tfetchEntries({ page: 1, search: query || undefined, reset: true });\n\t\t},\n\t\t[fetchEntries],\n\t);\n\n\tif (showDetail && detailSlug) {\n\t\treturn <ContentDetailView entry={detail} isLoading={isLoadingDetail} />;\n\t}\n\n\treturn (\n\t\t<ContentListView\n\t\t\tentries={entries}\n\t\t\tisLoading={isLoading}\n\t\t\thasMore={hasMore}\n\t\t\tonSelect={onSelectEntry}\n\t\t\tonLoadMore={loadMore}\n\t\t\tonSearch={handleSearch}\n\t\t\tsearchPlaceholder={`${t(\"widget.search\")} ${resolveLabel(tab.label).toLowerCase()}...`}\n\t\t\tdisplay={tab.display}\n\t\t/>\n\t);\n}\n","import type { WidgetContentTab } from \"@helpway/widget-core\";\nimport { CONTENT_CACHE_TTL, getLocale } from \"@helpway/widget-core\";\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useWidgetContext, useWidgetStore } from \"../provider\";\n\ninterface ContentEntryItem {\n\tslug: string;\n\ttitle: string;\n\tbody: string | null;\n\tpublishedAt: string | null;\n\tcustomFields: Record<string, string | null>;\n}\n\ninterface ContentEntryDetail {\n\tslug: string;\n\ttitle: string;\n\tbody: string | null;\n\tbodyHtml: string | null;\n\tpublishedAt: string | null;\n\tsourceLanguage: string;\n\tavailableLanguages: string[];\n\tcustomFields: Record<string, string | null>;\n}\n\nconst EMPTY_TABS: WidgetContentTab[] = [];\n\n// ── Cache key helpers ──\n\nfunction listKey(tabId: string, lang: string) {\n\treturn `flat:${tabId}:${lang}:list`;\n}\n\nfunction detailKey(tabId: string, lang: string, slug: string) {\n\treturn `flat:${tabId}:${lang}:detail:${slug}`;\n}\n\ninterface CachedList {\n\titems: ContentEntryItem[];\n\ttotal: number;\n\thasMore: boolean;\n\tpage: number;\n}\n\nfunction readCache<T>(cache: Map<string, { data: unknown; ts: number }>, key: string): T | null {\n\tconst entry = cache.get(key);\n\tif (!entry) return null;\n\tif (Date.now() - entry.ts > CONTENT_CACHE_TTL) return null;\n\treturn entry.data as T;\n}\n\n/**\n * Hook for fetching content from a dynamic content tab.\n * Content is cached in the Zustand store so tab switches don't re-fetch.\n */\nexport function useContentTab(tabId: string) {\n\tconst { client, store } = useWidgetContext();\n\tconst contentTabs = useWidgetStore((s) => s.agentConfig?.contentTabs) ?? EMPTY_TABS;\n\tconst tab = contentTabs.find((t) => t.id === tabId) ?? null;\n\n\tconst lang = getLocale();\n\tconst cache = store.getState().contentCache;\n\n\tconst [entries, setEntries] = useState<ContentEntryItem[]>(\n\t\t() => readCache<CachedList>(cache, listKey(tabId, lang))?.items ?? [],\n\t);\n\tconst [detail, setDetail] = useState<ContentEntryDetail | null>(null);\n\tconst [isLoading, setIsLoading] = useState(false);\n\tconst [isLoadingDetail, setIsLoadingDetail] = useState(false);\n\tconst [hasMore, setHasMore] = useState(\n\t\t() => readCache<CachedList>(cache, listKey(tabId, lang))?.hasMore ?? false,\n\t);\n\tconst [total, setTotal] = useState(\n\t\t() => readCache<CachedList>(cache, listKey(tabId, lang))?.total ?? 0,\n\t);\n\tconst [page, setPage] = useState(\n\t\t() => readCache<CachedList>(cache, listKey(tabId, lang))?.page ?? 1,\n\t);\n\n\tconst fetchEntries = useCallback(\n\t\tasync (opts?: { page?: number; search?: string; reset?: boolean }) => {\n\t\t\tif (!tab) return;\n\t\t\tconst p = opts?.page ?? 1;\n\t\t\tconst reset = opts?.reset ?? p === 1;\n\n\t\t\tsetIsLoading(true);\n\t\t\ttry {\n\t\t\t\tconst result = await client.widget.getContent.query({\n\t\t\t\t\ttabId,\n\t\t\t\t\tpage: p,\n\t\t\t\t\tlimit: 10,\n\t\t\t\t\tsearch: opts?.search,\n\t\t\t\t\tlanguage: getLocale(),\n\t\t\t\t});\n\n\t\t\t\tif (result.items) {\n\t\t\t\t\tsetEntries((prev) => {\n\t\t\t\t\t\tconst nextItems = reset ? result.items! : [...prev, ...result.items!];\n\t\t\t\t\t\tif (!opts?.search) {\n\t\t\t\t\t\t\tstore.getState().setContentCache(listKey(tabId, getLocale()), {\n\t\t\t\t\t\t\t\titems: nextItems,\n\t\t\t\t\t\t\t\ttotal: result.total,\n\t\t\t\t\t\t\t\thasMore: result.hasMore,\n\t\t\t\t\t\t\t\tpage: p,\n\t\t\t\t\t\t\t} satisfies CachedList);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn nextItems;\n\t\t\t\t\t});\n\t\t\t\t\tsetHasMore(result.hasMore);\n\t\t\t\t\tsetTotal(result.total);\n\t\t\t\t\tsetPage(p);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"[useContentTab] fetch error:\", err);\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false);\n\t\t\t}\n\t\t},\n\t\t[client, tabId, tab, store],\n\t);\n\n\tconst loadMore = useCallback(() => {\n\t\tif (!hasMore || isLoading) return;\n\t\tfetchEntries({ page: page + 1 });\n\t}, [fetchEntries, hasMore, isLoading, page]);\n\n\tconst fetchDetail = useCallback(\n\t\tasync (slug: string) => {\n\t\t\tif (!tab) return;\n\n\t\t\t// Check detail cache\n\t\t\tconst cached = readCache<ContentEntryDetail>(\n\t\t\t\tstore.getState().contentCache,\n\t\t\t\tdetailKey(tabId, getLocale(), slug),\n\t\t\t);\n\t\t\tif (cached) {\n\t\t\t\tsetDetail(cached);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsetIsLoadingDetail(true);\n\t\t\ttry {\n\t\t\t\tconst result = await client.widget.getContent.query({\n\t\t\t\t\ttabId,\n\t\t\t\t\tslug,\n\t\t\t\t\tlanguage: getLocale(),\n\t\t\t\t});\n\t\t\t\tif (result.entry) {\n\t\t\t\t\tconst entry = result.entry as ContentEntryDetail;\n\t\t\t\t\tsetDetail(entry);\n\t\t\t\t\tstore.getState().setContentCache(\n\t\t\t\t\t\tdetailKey(tabId, getLocale(), slug),\n\t\t\t\t\t\tentry,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"[useContentTab] detail error:\", err);\n\t\t\t} finally {\n\t\t\t\tsetIsLoadingDetail(false);\n\t\t\t}\n\t\t},\n\t\t[client, tabId, tab, store],\n\t);\n\n\tconst clearDetail = useCallback(() => {\n\t\tsetDetail(null);\n\t}, []);\n\n\t// Initial fetch — only if cache was empty\n\tuseEffect(() => {\n\t\tif (tab && entries.length === 0) {\n\t\t\tfetchEntries({ page: 1, reset: true });\n\t\t}\n\t}, [tab]); // eslint-disable-line react-hooks/exhaustive-deps\n\n\treturn {\n\t\ttab,\n\t\tentries,\n\t\tdetail,\n\t\tisLoading,\n\t\tisLoadingDetail,\n\t\thasMore,\n\t\ttotal,\n\t\tfetchEntries,\n\t\tloadMore,\n\t\tfetchDetail,\n\t\tclearDetail,\n\t};\n}\n\nexport type { ContentEntryItem, ContentEntryDetail, WidgetContentTab };\n","import { formatRelativeTime } from \"@helpway/widget-core\";\nimport type { ContentEntryDetail } from \"../../hooks/use-content-tab\";\nimport { MarkdownContent } from \"./simple-markdown\";\n\nexport function ContentDetailView({\n\tentry,\n\tisLoading,\n}: {\n\tentry: ContentEntryDetail | null;\n\tisLoading: boolean;\n}) {\n\tif (isLoading || !entry) {\n\t\treturn <ArticleSkeleton />;\n\t}\n\n\tconst badge = entry.customFields.version ?? entry.customFields.priority ?? entry.customFields.type ?? null;\n\n\treturn (\n\t\t<div className=\"hw-content-detail\">\n\t\t\t<div className=\"hw-content-detail-header\">\n\t\t\t\t<h1 className=\"hw-content-detail-title\">{entry.title}</h1>\n\t\t\t\t{(badge || entry.publishedAt) && (\n\t\t\t\t\t<div className=\"hw-content-detail-meta\">\n\t\t\t\t\t\t{badge && <span className=\"hw-content-entry-badge\">{badge}</span>}\n\t\t\t\t\t\t{entry.publishedAt && (\n\t\t\t\t\t\t\t<span className=\"hw-content-detail-date\">\n\t\t\t\t\t\t\t\t{formatRelativeTime(entry.publishedAt)}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t\t{(entry.body || entry.bodyHtml) && (\n\t\t\t\t<div className=\"hw-content-detail-body\">\n\t\t\t\t\t<MarkdownContent bodyHtml={entry.bodyHtml} bodyMarkdown={entry.body} />\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\n/**\n * Article-shaped skeleton.\n *\n * Uses the real .hw-content-detail / .hw-content-detail-header / .hw-content-detail-body / .hw-markdown\n * wrapper classes so all padding, font metrics, and adjacency-spacing rules\n * apply identically to the skeleton — guaranteeing the content lands without\n * any reflow when it arrives.\n *\n * Layout maps 1:1 to the rendered changelog:\n * <h1>Title</h1>\n * <div class=\"meta\"> badge + date </div>\n * <h2>Section</h2>\n * <ul><li>Bullet 1, 2 lines</li></ul>\n * <ul><li>Bullet 2, 2 lines</li></ul>\n * ...\n */\nfunction ArticleSkeleton() {\n\tconst sections: { headerWidth: string; items: { l1: string; l2: string }[] }[] = [\n\t\t{\n\t\t\theaderWidth: \"30%\",\n\t\t\titems: [\n\t\t\t\t{ l1: \"98%\", l2: \"62%\" },\n\t\t\t\t{ l1: \"94%\", l2: \"48%\" },\n\t\t\t\t{ l1: \"96%\", l2: \"70%\" },\n\t\t\t],\n\t\t},\n\t\t{\n\t\t\theaderWidth: \"26%\",\n\t\t\titems: [\n\t\t\t\t{ l1: \"92%\", l2: \"55%\" },\n\t\t\t\t{ l1: \"88%\", l2: \"40%\" },\n\t\t\t],\n\t\t},\n\t];\n\n\treturn (\n\t\t<div className=\"hw-content-detail\">\n\t\t\t<div className=\"hw-content-detail-header\">\n\t\t\t\t<h1 className=\"hw-content-detail-title\">\n\t\t\t\t\t<span className=\"hw-skeleton hw-skeleton-title\" />\n\t\t\t\t</h1>\n\t\t\t\t<div className=\"hw-content-detail-meta\">\n\t\t\t\t\t<span className=\"hw-skeleton hw-skeleton-badge\" />\n\t\t\t\t\t<span className=\"hw-skeleton hw-skeleton-date\" />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div className=\"hw-content-detail-body\">\n\t\t\t\t<div className=\"hw-markdown\">\n\t\t\t\t\t{sections.map((s, i) => (\n\t\t\t\t\t\t<SkeletonSection\n\t\t\t\t\t\t\tkey={i}\n\t\t\t\t\t\t\theaderWidth={s.headerWidth}\n\t\t\t\t\t\t\titems={s.items}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nfunction SkeletonSection({\n\theaderWidth,\n\titems,\n}: {\n\theaderWidth: string;\n\titems: { l1: string; l2: string }[];\n}) {\n\treturn (\n\t\t<>\n\t\t\t<h2>\n\t\t\t\t<span\n\t\t\t\t\tclassName=\"hw-skeleton hw-skeleton-h2\"\n\t\t\t\t\tstyle={{ display: \"block\", width: headerWidth }}\n\t\t\t\t/>\n\t\t\t</h2>\n\t\t\t{items.map((item, j) => (\n\t\t\t\t<ul key={j}>\n\t\t\t\t\t<li>\n\t\t\t\t\t\t<div className=\"hw-skeleton-bullet-lines\">\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\tclassName=\"hw-skeleton hw-skeleton-bullet-line\"\n\t\t\t\t\t\t\t\tstyle={{ display: \"block\", width: item.l1 }}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\tclassName=\"hw-skeleton hw-skeleton-bullet-line\"\n\t\t\t\t\t\t\t\tstyle={{ display: \"block\", width: item.l2, marginTop: 8 }}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</li>\n\t\t\t\t</ul>\n\t\t\t))}\n\t\t</>\n\t);\n}\n","import { formatRelativeTime, t } from \"@helpway/widget-core\";\nimport type { ContentTabDisplay } from \"@helpway/types\";\nimport { useCallback, useRef, useState } from \"react\";\nimport type { ContentEntryItem } from \"../../hooks/use-content-tab\";\n\n/**\n * Content entry list — Intercom-style clean card layout.\n * Search bar at top, card entries with title + description + chevron.\n */\nexport function ContentListView({\n\tentries,\n\tisLoading,\n\thasMore,\n\tonSelect,\n\tonLoadMore,\n\tonSearch,\n\tsearchPlaceholder,\n\tdisplay,\n}: {\n\tentries: ContentEntryItem[];\n\tisLoading: boolean;\n\thasMore: boolean;\n\tonSelect: (slug: string) => void;\n\tonLoadMore: () => void;\n\tonSearch?: (query: string) => void;\n\tsearchPlaceholder?: string;\n\tdisplay?: ContentTabDisplay;\n}) {\n\tconst [searchText, setSearchText] = useState(\"\");\n\tconst debounceRef = useRef<ReturnType<typeof setTimeout>>(undefined);\n\n\tconst handleSearch = useCallback(\n\t\t(value: string) => {\n\t\t\tsetSearchText(value);\n\t\t\tif (!onSearch) return;\n\t\t\tclearTimeout(debounceRef.current);\n\t\t\tdebounceRef.current = setTimeout(() => {\n\t\t\t\tonSearch(value.trim());\n\t\t\t}, 300);\n\t\t},\n\t\t[onSearch],\n\t);\n\n\treturn (\n\t\t<div className=\"hw-content-list\">\n\t\t\t{/* Search */}\n\t\t\t{onSearch && (\n\t\t\t\t<div className=\"hw-content-search\">\n\t\t\t\t\t<div className=\"hw-content-search-box\">\n\t\t\t\t\t\t<svg className=\"hw-content-search-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n\t\t\t\t\t\t\t<circle cx=\"11\" cy=\"11\" r=\"8\" />\n\t\t\t\t\t\t\t<line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\" />\n\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\tclassName=\"hw-content-search-input\"\n\t\t\t\t\t\t\tplaceholder={searchPlaceholder ?? t(\"widget.search\")}\n\t\t\t\t\t\t\tvalue={searchText}\n\t\t\t\t\t\t\tonChange={(e) => handleSearch(e.target.value)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Loading */}\n\t\t\t{isLoading && entries.length === 0 && (\n\t\t\t\t<div className=\"hw-skeleton-content\">\n\t\t\t\t\t{[1, 2, 3].map((i) => (\n\t\t\t\t\t\t<div key={i} className=\"hw-skeleton-content-item\">\n\t\t\t\t\t\t\t<div className=\"hw-skeleton hw-skeleton-line\" style={{ width: \"70%\", height: 14 }} />\n\t\t\t\t\t\t\t<div className=\"hw-skeleton hw-skeleton-line\" style={{ width: \"90%\", height: 12 }} />\n\t\t\t\t\t\t\t<div className=\"hw-skeleton hw-skeleton-line\" style={{ width: \"40%\", height: 10 }} />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Empty */}\n\t\t\t{!isLoading && entries.length === 0 && (\n\t\t\t\t<div className=\"hw-content-empty\">\n\t\t\t\t\t<div className=\"hw-content-empty-title\">\n\t\t\t\t\t\t{searchText ? t(\"widget.no_results\") : t(\"widget.nothing_yet\")}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"hw-content-empty-desc\">\n\t\t\t\t\t\t{searchText ? t(\"widget.try_different\") : t(\"widget.check_back\")}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Entries */}\n\t\t\t{entries.length > 0 && (\n\t\t\t\t<div className=\"hw-content-entries\">\n\t\t\t\t\t{entries.map((entry) => (\n\t\t\t\t\t\t<ContentEntryCard key={entry.slug} entry={entry} onSelect={onSelect} display={display} />\n\t\t\t\t\t))}\n\t\t\t\t\t{hasMore && (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tclassName=\"hw-content-load-more\"\n\t\t\t\t\t\t\tonClick={onLoadMore}\n\t\t\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{isLoading ? t(\"widget.loading\") : t(\"widget.load_more\")}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\n// ── Entry Card — Intercom-style ──────────────────────────\n\nfunction truncateText(text: string | null, maxLen = 80): string {\n\tif (!text) return \"\";\n\tconst clean = text.replace(/[#*_`>\\[\\]!()-]/g, \"\").trim();\n\treturn clean.length > maxLen ? `${clean.slice(0, maxLen)}...` : clean;\n}\n\nfunction ContentEntryCard({\n\tentry,\n\tonSelect,\n\tdisplay,\n}: {\n\tentry: ContentEntryItem;\n\tonSelect: (slug: string) => void;\n\tdisplay?: ContentTabDisplay;\n}) {\n\tconst { customFields } = entry;\n\n\t// Use display mapping if configured, otherwise auto-detect from common field names\n\tconst badge = display?.badgeField\n\t\t? customFields[display.badgeField] ?? null\n\t\t: customFields.version ?? customFields.priority ?? customFields.type ?? null;\n\n\tconst subtitleValue = display?.subtitleField\n\t\t? (display.subtitleField === \"body\" ? entry.body : customFields[display.subtitleField]) ?? null\n\t\t: customFields.excerpt ?? customFields.summary ?? customFields.description ?? null;\n\n\tconst preview = subtitleValue ? truncateText(subtitleValue) : truncateText(entry.body);\n\n\treturn (\n\t\t<button type=\"button\" className=\"hw-content-entry\" onClick={() => onSelect(entry.slug)}>\n\t\t\t<div className=\"hw-content-entry-main\">\n\t\t\t\t<div className=\"hw-content-entry-text\">\n\t\t\t\t\t<span className=\"hw-content-entry-title\">{entry.title}</span>\n\t\t\t\t\t{preview && (\n\t\t\t\t\t\t<span className=\"hw-content-entry-desc\">{preview}</span>\n\t\t\t\t\t)}\n\t\t\t\t\t{(badge || entry.publishedAt) && (\n\t\t\t\t\t\t<div className=\"hw-content-entry-meta\">\n\t\t\t\t\t\t\t{badge && <span className=\"hw-content-entry-badge\">{badge}</span>}\n\t\t\t\t\t\t\t{entry.publishedAt && (\n\t\t\t\t\t\t\t\t<span className=\"hw-content-entry-date\">{formatRelativeTime(entry.publishedAt)}</span>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t<svg className=\"hw-content-entry-chevron\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n\t\t\t\t\t<polyline points=\"9 18 15 12 9 6\" />\n\t\t\t\t</svg>\n\t\t\t</div>\n\t\t</button>\n\t);\n}\n","import type { WidgetContentTab } from \"@helpway/widget-core\";\nimport { t } from \"@helpway/widget-core\";\nimport { useEffect, useRef } from \"react\";\nimport { useGroupedContentTab } from \"../../hooks/use-grouped-content-tab\";\nimport type { ContentEntryItem } from \"../../hooks/use-content-tab\";\nimport { ContentDetailView } from \"./content-detail-view\";\nimport { ContentListView } from \"./content-list-view\";\n\n/**\n * Grouped content tab — category → items → detail drill-down.\n *\n * Three views managed by parent (DefaultWidget):\n * - subView = null → show categories\n * - subView = \"content-category\" → show items for activeCategory\n * - subView = \"content-detail\" → show item detail\n */\nexport function GroupedContentTabView({\n\ttab,\n\tsubView,\n\tdetailSlug,\n\tonSelectCategory,\n\tonSelectEntry,\n}: {\n\ttab: WidgetContentTab;\n\tsubView: string | null;\n\tdetailSlug: string | null;\n\tonSelectCategory: (category: ContentEntryItem) => void;\n\tonSelectEntry: (slug: string) => void;\n}) {\n\tconst {\n\t\tcategories,\n\t\tisCategoriesLoading,\n\t\titems,\n\t\tisItemsLoading,\n\t\titemsHasMore,\n\t\tactiveCategory,\n\t\tdetail,\n\t\tisLoadingDetail,\n\t\tinitFetch,\n\t\tselectCategory,\n\t\tsearchCategories,\n\t\tloadMoreItems,\n\t\tsearchItems,\n\t\tfetchDetail,\n\t\tclearCategory,\n\t} = useGroupedContentTab(tab.id);\n\n\t// Init fetch categories on mount\n\tuseEffect(() => {\n\t\tinitFetch();\n\t}, [initFetch]);\n\n\t// Fetch detail when slug changes\n\tuseEffect(() => {\n\t\tif (detailSlug && subView === \"content-detail\") {\n\t\t\tfetchDetail(detailSlug);\n\t\t}\n\t}, [detailSlug, subView, fetchDetail]);\n\n\t// Clean up hook state when navigating back to category list\n\tconst prevSubView = useRef(subView);\n\tuseEffect(() => {\n\t\tif (prevSubView.current === \"content-category\" && subView === null) {\n\t\t\tclearCategory();\n\t\t}\n\t\tprevSubView.current = subView;\n\t}, [subView, clearCategory]);\n\n\t// ── Detail view ──\n\tif (subView === \"content-detail\" && detailSlug) {\n\t\treturn <ContentDetailView entry={detail} isLoading={isLoadingDetail} />;\n\t}\n\n\t// ── Items list (within a category) ──\n\tif (subView === \"content-category\" && activeCategory) {\n\t\treturn (\n\t\t\t<ContentListView\n\t\t\t\tentries={items}\n\t\t\t\tisLoading={isItemsLoading}\n\t\t\t\thasMore={itemsHasMore}\n\t\t\t\tonSelect={onSelectEntry}\n\t\t\t\tonLoadMore={loadMoreItems}\n\t\t\t\tonSearch={searchItems}\n\t\t\t\tsearchPlaceholder={t(\"widget.search\")}\n\t\t\t\tdisplay={tab.display}\n\t\t\t/>\n\t\t);\n\t}\n\n\t// ── Categories list (with search) ──\n\treturn (\n\t\t<ContentListView\n\t\t\tentries={categories}\n\t\t\tisLoading={isCategoriesLoading}\n\t\t\thasMore={false}\n\t\t\tonSelect={(slug) => {\n\t\t\t\tconst cat = categories.find((c) => c.slug === slug);\n\t\t\t\tif (cat) {\n\t\t\t\t\tselectCategory(cat);\n\t\t\t\t\tonSelectCategory(cat);\n\t\t\t\t}\n\t\t\t}}\n\t\t\tonLoadMore={() => {}}\n\t\t\tonSearch={searchCategories}\n\t\t\tsearchPlaceholder={t(\"widget.search\")}\n\t\t/>\n\t);\n}\n","import type { WidgetContentTab } from \"@helpway/widget-core\";\nimport { CONTENT_CACHE_TTL, getLocale } from \"@helpway/widget-core\";\nimport { useCallback, useRef, useState } from \"react\";\nimport { useWidgetContext, useWidgetStore } from \"../provider\";\nimport type { ContentEntryItem, ContentEntryDetail } from \"./use-content-tab\";\n\nconst EMPTY_TABS: WidgetContentTab[] = [];\n\n// ── Cache key helpers ──\n\nfunction categoriesKey(tabId: string, lang: string) {\n\treturn `grouped:${tabId}:${lang}:categories`;\n}\n\nfunction itemsKey(tabId: string, lang: string, groupSlug: string) {\n\treturn `grouped:${tabId}:${lang}:items:${groupSlug}`;\n}\n\nfunction detailKey(tabId: string, lang: string, slug: string) {\n\treturn `grouped:${tabId}:${lang}:detail:${slug}`;\n}\n\ninterface CachedItems {\n\titems: ContentEntryItem[];\n\thasMore: boolean;\n\tpage: number;\n}\n\nfunction readCache<T>(cache: Map<string, { data: unknown; ts: number }>, key: string): T | null {\n\tconst entry = cache.get(key);\n\tif (!entry) return null;\n\tif (Date.now() - entry.ts > CONTENT_CACHE_TTL) return null;\n\treturn entry.data as T;\n}\n\n/**\n * Hook for grouped content tabs (category → items drill-down).\n * Content is cached in the Zustand store so tab switches don't re-fetch.\n */\nexport function useGroupedContentTab(tabId: string) {\n\tconst { client, store } = useWidgetContext();\n\tconst contentTabs = useWidgetStore((s) => s.agentConfig?.contentTabs) ?? EMPTY_TABS;\n\tconst tab = contentTabs.find((t) => t.id === tabId) ?? null;\n\n\tconst lang = getLocale();\n\tconst cache = store.getState().contentCache;\n\n\t// ── Categories (top level) ──\n\tconst cachedCategories = readCache<ContentEntryItem[]>(cache, categoriesKey(tabId, lang));\n\tconst [categories, setCategories] = useState<ContentEntryItem[]>(cachedCategories ?? []);\n\tconst [isCategoriesLoading, setIsCategoriesLoading] = useState(false);\n\n\t// ── Items (within a category) ──\n\tconst [items, setItems] = useState<ContentEntryItem[]>([]);\n\tconst [isItemsLoading, setIsItemsLoading] = useState(false);\n\tconst [itemsHasMore, setItemsHasMore] = useState(false);\n\tconst itemsPageRef = useRef(1);\n\n\t// ── Detail (single item) ──\n\tconst [detail, setDetail] = useState<ContentEntryDetail | null>(null);\n\tconst [isLoadingDetail, setIsLoadingDetail] = useState(false);\n\n\t// ── Active category ──\n\tconst [activeCategory, setActiveCategory] = useState<ContentEntryItem | null>(null);\n\n\t// ── All categories (unfiltered, for client-side search) ──\n\tconst allCategoriesRef = useRef<ContentEntryItem[]>(cachedCategories ?? []);\n\n\t// ── Fetch categories ──\n\tconst fetchCategories = useCallback(async () => {\n\t\tif (!tab) return;\n\t\tsetIsCategoriesLoading(true);\n\t\ttry {\n\t\t\tconst result = await client.widget.getContent.query({\n\t\t\t\ttabId,\n\t\t\t\tpage: 1,\n\t\t\t\tlimit: 50,\n\t\t\t\tlanguage: getLocale(),\n\t\t\t});\n\t\t\tif (result.items) {\n\t\t\t\tallCategoriesRef.current = result.items;\n\t\t\t\tsetCategories(result.items);\n\t\t\t\tstore.getState().setContentCache(categoriesKey(tabId, getLocale()), result.items);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tconsole.error(\"[useGroupedContentTab] categories error:\", err);\n\t\t} finally {\n\t\t\tsetIsCategoriesLoading(false);\n\t\t}\n\t}, [client, tabId, tab, store]);\n\n\t// Init — only fetch if cache was empty\n\tconst initFetch = useCallback(() => {\n\t\tif (tab && categories.length === 0) {\n\t\t\tfetchCategories();\n\t\t}\n\t}, [fetchCategories, tab, categories.length]);\n\n\t// ── Fetch items for a category ──\n\tconst fetchItems = useCallback(\n\t\tasync (opts?: { page?: number; search?: string; reset?: boolean; groupSlug?: string }) => {\n\t\t\tif (!tab?.itemsModelSlug) return;\n\t\t\tconst p = opts?.page ?? 1;\n\t\t\tconst reset = opts?.reset ?? p === 1;\n\n\t\t\tsetIsItemsLoading(true);\n\t\t\ttry {\n\t\t\t\tconst result = await client.widget.getContent.query({\n\t\t\t\t\ttabId,\n\t\t\t\t\tpage: p,\n\t\t\t\t\tlimit: 10,\n\t\t\t\t\tsearch: opts?.search,\n\t\t\t\t\tgroupSlug: opts?.groupSlug,\n\t\t\t\t\titemsModel: tab.itemsModelSlug,\n\t\t\t\t\tlanguage: getLocale(),\n\t\t\t\t});\n\t\t\t\tif (result.items) {\n\t\t\t\t\tsetItems((prev) => {\n\t\t\t\t\t\tconst nextItems = reset ? result.items! : [...prev, ...result.items!];\n\t\t\t\t\t\tif (!opts?.search && opts?.groupSlug) {\n\t\t\t\t\t\t\tstore.getState().setContentCache(\n\t\t\t\t\t\t\t\titemsKey(tabId, getLocale(), opts.groupSlug),\n\t\t\t\t\t\t\t\t{ items: nextItems, hasMore: result.hasMore, page: p } satisfies CachedItems,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn nextItems;\n\t\t\t\t\t});\n\t\t\t\t\tsetItemsHasMore(result.hasMore);\n\t\t\t\t\titemsPageRef.current = p;\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"[useGroupedContentTab] items error:\", err);\n\t\t\t} finally {\n\t\t\t\tsetIsItemsLoading(false);\n\t\t\t}\n\t\t},\n\t\t[client, tabId, tab, store],\n\t);\n\n\t// ── Select a category → load items from cache or fetch ──\n\tconst selectCategory = useCallback(\n\t\t(category: ContentEntryItem) => {\n\t\t\tsetActiveCategory(category);\n\t\t\tsetDetail(null);\n\n\t\t\tconst cached = readCache<CachedItems>(\n\t\t\t\tstore.getState().contentCache,\n\t\t\t\titemsKey(tabId, getLocale(), category.slug),\n\t\t\t);\n\t\t\tif (cached) {\n\t\t\t\tsetItems(cached.items);\n\t\t\t\tsetItemsHasMore(cached.hasMore);\n\t\t\t\titemsPageRef.current = cached.page;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsetItems([]);\n\t\t\tfetchItems({ page: 1, reset: true, groupSlug: category.slug });\n\t\t},\n\t\t[fetchItems, store, tabId],\n\t);\n\n\t// ── Load more items ──\n\tconst loadMoreItems = useCallback(() => {\n\t\tif (!itemsHasMore || isItemsLoading || !activeCategory) return;\n\t\tfetchItems({\n\t\t\tpage: itemsPageRef.current + 1,\n\t\t\tgroupSlug: activeCategory.slug,\n\t\t});\n\t}, [fetchItems, itemsHasMore, isItemsLoading, activeCategory]);\n\n\t// ── Search items (cross-category) ──\n\tconst searchItems = useCallback(\n\t\t(query: string) => {\n\t\t\tsetItems([]);\n\t\t\tfetchItems({\n\t\t\t\tpage: 1,\n\t\t\t\treset: true,\n\t\t\t\tsearch: query || undefined,\n\t\t\t\tgroupSlug: query ? undefined : activeCategory?.slug,\n\t\t\t});\n\t\t},\n\t\t[fetchItems, activeCategory],\n\t);\n\n\t// ── Fetch item detail ──\n\tconst fetchDetail = useCallback(\n\t\tasync (slug: string) => {\n\t\t\tif (!tab?.itemsModelSlug) return;\n\n\t\t\tconst cached = readCache<ContentEntryDetail>(\n\t\t\t\tstore.getState().contentCache,\n\t\t\t\tdetailKey(tabId, getLocale(), slug),\n\t\t\t);\n\t\t\tif (cached) {\n\t\t\t\tsetDetail(cached);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsetIsLoadingDetail(true);\n\t\t\ttry {\n\t\t\t\tconst result = await client.widget.getContent.query({\n\t\t\t\t\ttabId,\n\t\t\t\t\tslug,\n\t\t\t\t\titemsModel: tab.itemsModelSlug,\n\t\t\t\t\tlanguage: getLocale(),\n\t\t\t\t});\n\t\t\t\tif (result.entry) {\n\t\t\t\t\tconst entry = result.entry as ContentEntryDetail;\n\t\t\t\t\tsetDetail(entry);\n\t\t\t\t\tstore.getState().setContentCache(\n\t\t\t\t\t\tdetailKey(tabId, getLocale(), slug),\n\t\t\t\t\t\tentry,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"[useGroupedContentTab] detail error:\", err);\n\t\t\t} finally {\n\t\t\t\tsetIsLoadingDetail(false);\n\t\t\t}\n\t\t},\n\t\t[client, tabId, tab, store],\n\t);\n\n\t// ── Search categories (client-side, instant) ──\n\tconst searchCategories = useCallback(\n\t\t(query: string) => {\n\t\t\tif (!query.trim()) {\n\t\t\t\tsetCategories(allCategoriesRef.current);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst q = query.toLowerCase();\n\t\t\tsetCategories(\n\t\t\t\tallCategoriesRef.current.filter((cat) =>\n\t\t\t\t\tcat.title.toLowerCase().includes(q) ||\n\t\t\t\t\t(cat.customFields.description ?? \"\").toLowerCase().includes(q),\n\t\t\t\t),\n\t\t\t);\n\t\t},\n\t\t[],\n\t);\n\n\tconst clearDetail = useCallback(() => {\n\t\tsetDetail(null);\n\t}, []);\n\n\tconst clearCategory = useCallback(() => {\n\t\tsetActiveCategory(null);\n\t\tsetItems([]);\n\t\tsetDetail(null);\n\t}, []);\n\n\treturn {\n\t\ttab,\n\t\tcategories,\n\t\tisCategoriesLoading,\n\t\titems,\n\t\tisItemsLoading,\n\t\titemsHasMore,\n\t\tactiveCategory,\n\t\tdetail,\n\t\tisLoadingDetail,\n\t\tinitFetch,\n\t\tselectCategory,\n\t\tsearchCategories,\n\t\tloadMoreItems,\n\t\tsearchItems,\n\t\tfetchDetail,\n\t\tclearDetail,\n\t\tclearCategory,\n\t};\n}\n","import {\n\tBookIcon,\n\tHelpCircleIcon,\n\tLightbulbIcon,\n\tMegaphoneIcon,\n\tNewspaperIcon,\n\tStarIcon,\n} from \"../icons\";\n\n/**\n * Maps icon string keys to Central Icons components.\n * Dashboard lets users pick from this set when configuring a content tab.\n * Falls back to BookIcon for unknown keys.\n */\nconst ICON_MAP: Record<string, React.FC> = {\n\tbook: BookIcon,\n\tmegaphone: MegaphoneIcon,\n\tlightbulb: LightbulbIcon,\n\t\"help-circle\": HelpCircleIcon,\n\tnewspaper: NewspaperIcon,\n\tstar: StarIcon,\n};\n\nexport function ContentTabIconComponent({ icon }: { icon: string }) {\n\tconst Icon = ICON_MAP[icon] ?? BookIcon;\n\treturn <Icon />;\n}\n","\"use client\";\n\nimport { t } from \"@helpway/widget-core\";\nimport type { MouseEvent, ReactNode } from \"react\";\nimport { useState } from \"react\";\nimport { useWidgetStore } from \"../provider\";\nimport { XIcon } from \"./icons\";\nimport { stripMarkdown } from \"./strip-markdown\";\n\n/** Placement of the announcement stack — mirrors `MessagePreviewPlacement`. */\nexport type AnnouncementPreviewsPlacement = \"launcher\" | \"anchored\";\n\n/** Shape of a single announcement entry as it lives in the widget store. */\nexport interface AnnouncementPreviewEntry {\n\ttitle: string;\n\tbody: string | null;\n\tslug: string;\n\ttabId: string;\n\tbadge: string | null;\n}\n\nexport interface AnnouncementPreviewsProps {\n\t/** Called when the visitor taps an announcement card. Receives the\n\t * entry's slug + the parent tab id. The consumer decides what to\n\t * do — at minimum `setOpen(true)`, optionally deep-link into the\n\t * matching content tab + detail. */\n\tonOpen: (slug: string, tabId: string) => void;\n\t/** The avatar node shown in each card's header. Injected so the\n\t * component is decoupled from avatar resolution; pass\n\t * `<WidgetLogo />` for the SDK default. */\n\tavatar: ReactNode;\n\t/**\n\t * Outer positioning mode. `\"launcher\"` (default) keeps the stack\n\t * pinned above the floating bubble; `\"anchored\"` drops that and\n\t * lets the consumer's positioned wrapper place the stack — and\n\t * each card stretches to the wrapper width instead of the launcher\n\t * 300px (via the same `.hw-preview--anchored` modifier the\n\t * message preview uses).\n\t */\n\tplacement?: AnnouncementPreviewsPlacement;\n\t/**\n\t * Optional caption rendered as a separated footer beneath each\n\t * card (e.g. a \"via X\" provenance line). Omitted on the launcher\n\t * so its visual stays byte-identical to the original.\n\t */\n\tfooter?: ReactNode;\n}\n\n/**\n * `<AnnouncementPreviews>` — proactive \"new content\" cards shown when\n * the widget panel is closed and the visitor hasn't seen the latest\n * entries from a \"Promote new content\" tab yet. Stacks multiple\n * entries vertically.\n *\n * Extracted from the default widget so `hideLauncher` integrations can\n * surface the *exact same* cards next to their own UI instead of the\n * floating launcher. Visual/markup is byte-identical to the launcher\n * version — only the outer positioning is parameterised via\n * `placement`. Announcements never auto-dismiss (visitors need time to\n * read); they're cleared by tapping the card or the ✕.\n *\n * Must be rendered inside `<SupportProvider>`.\n */\nexport function AnnouncementPreviews({\n\tonOpen,\n\tavatar,\n\tplacement = \"launcher\",\n\tfooter,\n}: AnnouncementPreviewsProps) {\n\tconst previews = useWidgetStore((s) => s.announcementPreviews);\n\tconst dismissPreview = useWidgetStore((s) => s.dismissAnnouncementPreview);\n\tconst agentName = useWidgetStore((s) => s.agentConfig?.name) ?? \"Support\";\n\n\tif (previews.length === 0) return null;\n\n\tconst stackPlacementClass =\n\t\tplacement === \"anchored\" ? \"hw-preview-stack--anchored \" : \"\";\n\n\treturn (\n\t\t<div className={`hw-preview-stack ${stackPlacementClass}`.trim()}>\n\t\t\t{previews.map((preview) => (\n\t\t\t\t<AnnouncementPreviewItem\n\t\t\t\t\tkey={preview.slug}\n\t\t\t\t\tpreview={preview}\n\t\t\t\t\tagentName={agentName}\n\t\t\t\t\tavatar={avatar}\n\t\t\t\t\tplacement={placement}\n\t\t\t\t\tfooter={footer}\n\t\t\t\t\tonOpen={onOpen}\n\t\t\t\t\tonDismiss={(slug) => dismissPreview(slug)}\n\t\t\t\t/>\n\t\t\t))}\n\t\t</div>\n\t);\n}\n\nfunction AnnouncementPreviewItem({\n\tpreview,\n\tagentName,\n\tavatar,\n\tplacement,\n\tfooter,\n\tonOpen,\n\tonDismiss,\n}: {\n\tpreview: AnnouncementPreviewEntry;\n\tagentName: string;\n\tavatar: ReactNode;\n\tplacement: AnnouncementPreviewsPlacement;\n\tfooter?: ReactNode;\n\tonOpen: (slug: string, tabId: string) => void;\n\tonDismiss: (slug: string) => void;\n}) {\n\tconst [closing, setClosing] = useState(false);\n\n\tconst handleClose = (e: MouseEvent) => {\n\t\te.stopPropagation();\n\t\tsetClosing(true);\n\t\tsetTimeout(() => {\n\t\t\tonDismiss(preview.slug);\n\t\t\tsetClosing(false);\n\t\t}, 200);\n\t};\n\n\tconst placementClass = placement === \"anchored\" ? \"hw-preview--anchored \" : \"\";\n\n\treturn (\n\t\t<div\n\t\t\tclassName={`hw-preview hw-preview--announcement ${placementClass}${closing ? \"hw-preview--closing\" : \"\"}`.trim()}\n\t\t\tonClick={() => onOpen(preview.slug, preview.tabId)}\n\t\t\trole=\"button\"\n\t\t\ttabIndex={0}\n\t\t>\n\t\t\t<div className=\"hw-preview-header\">\n\t\t\t\t<div className=\"hw-preview-avatar\">{avatar}</div>\n\t\t\t\t<div className=\"hw-preview-name\">{agentName}</div>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"hw-preview-close\"\n\t\t\t\t\tonClick={handleClose}\n\t\t\t\t\taria-label={t(\"widget.aria_dismiss\")}\n\t\t\t\t>\n\t\t\t\t\t<XIcon size={20} />\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t\t<div className=\"hw-preview-body hw-preview-body--title\">{preview.title}</div>\n\t\t\t{preview.body &&\n\t\t\t\t(() => {\n\t\t\t\t\tconst clean = stripMarkdown(preview.body);\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div className=\"hw-preview-body hw-preview-body--desc\">\n\t\t\t\t\t\t\t{clean.length > 120 ? `${clean.slice(0, 120)}…` : clean}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t})()}\n\t\t\t{preview.badge && (\n\t\t\t\t<div className=\"hw-announcement-badge\">{preview.badge}</div>\n\t\t\t)}\n\t\t\t{footer != null && footer !== false && (\n\t\t\t\t<div className=\"hw-preview-footer\">{footer}</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","/**\n * Strip the most common Markdown affordances so a body excerpt reads as\n * plain text inside a preview bubble. Intentionally minimal — covers\n * headings, bold/italic, lists, links, inline code, and newlines. Not\n * a full Markdown renderer; meant for short truncated descriptions\n * where the rendered styling would clash with the surrounding chrome.\n */\nexport function stripMarkdown(text: string): string {\n\treturn text\n\t\t.replace(/^#{1,6}\\s+/gm, \"\")\n\t\t.replace(/\\*\\*(.+?)\\*\\*/g, \"$1\")\n\t\t.replace(/\\*(.+?)\\*/g, \"$1\")\n\t\t.replace(/^[-*+]\\s+/gm, \"\")\n\t\t.replace(/\\[(.+?)\\]\\(.+?\\)/g, \"$1\")\n\t\t.replace(/`(.+?)`/g, \"$1\")\n\t\t.replace(/\\n{2,}/g, \" \")\n\t\t.replace(/\\n/g, \" \")\n\t\t.trim();\n}\n","import type { TimelineItem, TimelineItemMetadata, TimelineItemPart } from \"@helpway/types\";\nimport { getInitials, getLocale, t } from \"@helpway/widget-core\";\nimport React, { useEffect, useRef } from \"react\";\nimport { useWidgetClient, useWidgetStore } from \"../provider\";\nimport { renderMarkdown } from \"./content/simple-markdown\";\nimport { MessageBubble } from \"./message-bubble\";\n\n/**\n * Close dangling markdown delimiters in a partial (still-streaming) message\n * so renderMarkdown doesn't show raw syntax mid-stream: an unclosed ```fence\n * renders as literal backticks, an odd ** shows asterisks. The final message\n * replaces this bubble entirely, so the patch only ever affects transient UI.\n */\nfunction closeDanglingMarkdown(partial: string): string {\n\tlet out = partial;\n\tconst fences = (out.match(/```/g) ?? []).length;\n\tif (fences % 2 === 1) out += \"\\n```\";\n\t// Inline code / bold counted on the remainder outside fences is overkill\n\t// for a transient frame — a simple global parity check is good enough.\n\tconst bold = (out.match(/\\*\\*/g) ?? []).length;\n\tif (bold % 2 === 1) out += \"**\";\n\treturn out;\n}\n\nfunction parseParts(raw: TimelineItemPart[] | string | null): TimelineItemPart[] | null {\n\tif (!raw) return null;\n\tif (Array.isArray(raw)) return raw;\n\ttry {\n\t\tconst parsed = JSON.parse(raw);\n\t\treturn Array.isArray(parsed) ? parsed : null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Tolerate both shapes: when the API hydrates metadata it's already an\n * object; when it round-trips through CF tRPC over the wire it can land\n * as a JSON string. parseMetadata covers both.\n */\nfunction parseMetadata(\n\traw: TimelineItemMetadata | string | null | undefined,\n): TimelineItemMetadata | null {\n\tif (!raw) return null;\n\tif (typeof raw === \"object\") return raw;\n\ttry {\n\t\tconst parsed = JSON.parse(raw);\n\t\treturn parsed && typeof parsed === \"object\" ? (parsed as TimelineItemMetadata) : null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\ninterface MessageListProps {\n\titems: TimelineItem[];\n\tvisitorName?: string;\n\tisTyping?: boolean;\n\tisAiProcessing?: boolean;\n\tstreamingText?: string;\n\thasMore?: boolean;\n\tisLoadingMore?: boolean;\n\tonLoadMore?: () => void;\n\t/** Slot rendered after all messages but before typing indicators (e.g. email prompt) */\n\trenderAfterMessages?: React.ReactNode;\n}\n\n/** Timeline with date separators, typing indicator, infinite scroll, and AI processing state */\nexport function MessageList({\n\titems,\n\tvisitorName,\n\tisTyping,\n\tisAiProcessing,\n\tstreamingText,\n\thasMore,\n\tisLoadingMore,\n\tonLoadMore,\n\trenderAfterMessages,\n}: MessageListProps) {\n\tconst bottomRef = useRef<HTMLDivElement>(null);\n\tconst topRef = useRef<HTMLDivElement>(null);\n\tconst containerRef = useRef<HTMLDivElement>(null);\n\tconst prevItemCountRef = useRef(items.length);\n\tconst isInitialLoadRef = useRef(true);\n\t// Single source of truth — agent name comes from dashboard config.\n\tconst agentName = useWidgetStore((s) => s.agentConfig?.name) ?? t(\"widget.helpway_ai\");\n\tconst client = useWidgetClient();\n\tconst activeConversationId = useWidgetStore((s) => s.activeConversationId);\n\n\tconst handleQuickReplyTap = React.useCallback(\n\t\t(optionId: string, stepId: string) => {\n\t\t\tif (!activeConversationId) return;\n\t\t\t// Fire-and-forget — orchestrator runs the resume in the background\n\t\t\t// and emits new messages over WebSocket. Failure is swallowed so\n\t\t\t// the visitor never sees a tRPC error toast for this UX action.\n\t\t\tclient.widget.workflowReply\n\t\t\t\t.mutate({ conversationId: activeConversationId, stepId, optionId })\n\t\t\t\t.catch((err: unknown) => {\n\t\t\t\t\tconsole.warn(\"[helpway] workflowReply failed:\", err);\n\t\t\t\t});\n\t\t},\n\t\t[client, activeConversationId],\n\t);\n\n\t// Auto-scroll to bottom on new messages (but NOT when loading older ones at top)\n\tuseEffect(() => {\n\t\tconst prevCount = prevItemCountRef.current;\n\t\tconst newCount = items.length;\n\t\tprevItemCountRef.current = newCount;\n\n\t\t// Initial load or new messages added at the end → scroll to bottom\n\t\tif (isInitialLoadRef.current || newCount > prevCount) {\n\t\t\t// Only scroll if the new items were appended (not prepended)\n\t\t\tconst lastItem = items[items.length - 1];\n\t\t\tconst prevLastItem = prevCount > 0 ? items[prevCount - 1] : null;\n\n\t\t\tif (isInitialLoadRef.current || !prevLastItem || lastItem?.id !== prevLastItem?.id) {\n\t\t\t\tbottomRef.current?.scrollIntoView({\n\t\t\t\t\tbehavior: isInitialLoadRef.current ? \"instant\" : \"smooth\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tisInitialLoadRef.current = false;\n\t\t}\n\t}, [items]);\n\n\t// Scroll to bottom when typing/AI indicators appear\n\tuseEffect(() => {\n\t\tif (isTyping || isAiProcessing) {\n\t\t\tbottomRef.current?.scrollIntoView({ behavior: \"smooth\" });\n\t\t}\n\t}, [isTyping, isAiProcessing]);\n\n\t// Infinite scroll — IntersectionObserver on the top sentinel\n\tuseEffect(() => {\n\t\tif (!hasMore || !onLoadMore || !topRef.current) return;\n\n\t\tconst observer = new IntersectionObserver(\n\t\t\t(entries) => {\n\t\t\t\tif (entries[0]?.isIntersecting && !isLoadingMore) {\n\t\t\t\t\t// Save scroll position before loading\n\t\t\t\t\tconst container = containerRef.current;\n\t\t\t\t\tconst prevScrollHeight = container?.scrollHeight ?? 0;\n\t\t\t\t\tconst prevScrollTop = container?.scrollTop ?? 0;\n\n\t\t\t\t\tonLoadMore();\n\n\t\t\t\t\t// Restore scroll position after DOM update (next frame)\n\t\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\t\tif (container) {\n\t\t\t\t\t\t\tconst newScrollHeight = container.scrollHeight;\n\t\t\t\t\t\t\tcontainer.scrollTop = prevScrollTop + (newScrollHeight - prevScrollHeight);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ root: containerRef.current, threshold: 0.1 },\n\t\t);\n\n\t\tobserver.observe(topRef.current);\n\t\treturn () => observer.disconnect();\n\t}, [hasMore, onLoadMore, isLoadingMore]);\n\n\tif (items.length === 0) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tclassName=\"hw-messages\"\n\t\t\t\trole=\"log\"\n\t\t\t\taria-label={t(\"widget.aria_messages\")}\n\t\t\t\taria-live=\"polite\"\n\t\t\t>\n\t\t\t\t<div className=\"hw-empty\">\n\t\t\t\t\t<div className=\"hw-empty-icon\">\n\t\t\t\t\t\t<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.5}>\n\t\t\t\t\t\t\t<path d=\"M7.9 20A9 9 0 1 0 4 16.1L2 22Z\" />\n\t\t\t\t\t\t</svg>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"hw-empty-text\">{t(\"widget.start_a_conversation\")}</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t);\n\t}\n\n\tlet lastDateKey = \"\";\n\t// Stable \"today\" key (YYYY-MM-DD in local time) for separator gating.\n\t// We HIDE the separator for today entirely — matches Intercom/WhatsApp:\n\t// the date is implicit when \"now\", and showing it on every fresh\n\t// conversation creates a jarring vertical jump as the view fills in.\n\tconst todayKey = new Date().toLocaleDateString(\"en-CA\"); // en-CA is YYYY-MM-DD\n\tconst yesterday = new Date();\n\tyesterday.setDate(yesterday.getDate() - 1);\n\tconst yesterdayKey = yesterday.toLocaleDateString(\"en-CA\");\n\n\treturn (\n\t\t<div\n\t\t\tref={containerRef}\n\t\t\tclassName=\"hw-messages\"\n\t\t\trole=\"log\"\n\t\t\taria-label={t(\"widget.aria_messages\")}\n\t\t\taria-live=\"polite\"\n\t\t>\n\t\t\t{/* Top sentinel for infinite scroll */}\n\t\t\t<div ref={topRef} className=\"hw-load-more-trigger\">\n\t\t\t\t{isLoadingMore && (\n\t\t\t\t\t<div className=\"hw-load-more-spinner\">\n\t\t\t\t\t\t<div />\n\t\t\t\t\t\t<div />\n\t\t\t\t\t\t<div />\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t{items.map((item) => {\n\t\t\t\tif (item.type === \"event\") {\n\t\t\t\t\treturn <EventCard key={(item as unknown as { _stableKey?: string })._stableKey ?? item.id} text={item.text ?? \"\"} />;\n\t\t\t\t}\n\n\t\t\t\t// Date separator — bucket by local YYYY-MM-DD; skip rendering\n\t\t\t\t// when the bucket is \"today\" so today's chats stay flush at the top.\n\t\t\t\tconst itemDate = new Date(item.createdAt);\n\t\t\t\tconst dateKey = itemDate.toLocaleDateString(\"en-CA\");\n\t\t\t\tconst isNewBucket = dateKey !== lastDateKey;\n\t\t\t\tif (isNewBucket) lastDateKey = dateKey;\n\t\t\t\tconst showDateSep = isNewBucket && dateKey !== todayKey;\n\t\t\t\tconst dateLabel =\n\t\t\t\t\tdateKey === yesterdayKey\n\t\t\t\t\t\t? t(\"widget.yesterday\")\n\t\t\t\t\t\t: itemDate.toLocaleDateString(getLocale(), {\n\t\t\t\t\t\t\t\tweekday: \"long\",\n\t\t\t\t\t\t\t\tmonth: \"short\",\n\t\t\t\t\t\t\t\tday: \"numeric\",\n\t\t\t\t\t\t\t});\n\n\t\t\t\t// Determine sender\n\t\t\t\tconst sender = item.visitorId ? \"visitor\" : item.aiAgentId ? \"ai\" : \"team\";\n\n\t\t\t\t// Show timestamp on the last message in a consecutive group from the same sender\n\t\t\t\tconst idx = items.indexOf(item);\n\t\t\t\tconst nextItem = items[idx + 1];\n\t\t\t\tconst nextSender = nextItem?.type === \"message\"\n\t\t\t\t\t? (nextItem.visitorId ? \"visitor\" : nextItem.aiAgentId ? \"ai\" : \"team\")\n\t\t\t\t\t: null;\n\t\t\t\tconst isLastInGroup = nextSender !== sender || nextItem?.type === \"event\";\n\t\t\t\tconst timeLabel = isLastInGroup\n\t\t\t\t\t? itemDate.toLocaleTimeString(getLocale(), { hour: \"2-digit\", minute: \"2-digit\" })\n\t\t\t\t\t: undefined;\n\n\t\t\t\treturn (\n\t\t\t\t\t<React.Fragment key={(item as unknown as { _stableKey?: string })._stableKey ?? item.id}>\n\t\t\t\t\t\t{showDateSep && (\n\t\t\t\t\t\t\t<div className=\"hw-date-sep\">\n\t\t\t\t\t\t\t\t<div className=\"hw-date-sep-line\" />\n\t\t\t\t\t\t\t\t<div className=\"hw-date-sep-text\">{dateLabel}</div>\n\t\t\t\t\t\t\t\t<div className=\"hw-date-sep-line\" />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<MessageBubble\n\t\t\t\t\t\t\ttext={item.text ?? \"\"}\n\t\t\t\t\t\t\tsender={sender}\n\t\t\t\t\t\t\tsenderName={sender === \"visitor\" ? visitorName : (item.userName ?? undefined)}\n\t\t\t\t\t\t\tparts={parseParts(item.parts)}\n\t\t\t\t\t\t\tmetadata={parseMetadata(\n\t\t\t\t\t\t\t\t(item as TimelineItem & { metadata?: TimelineItemMetadata | string | null })\n\t\t\t\t\t\t\t\t\t.metadata,\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\tonQuickReplyTap={handleQuickReplyTap}\n\t\t\t\t\t\t\ttimestamp={timeLabel}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</React.Fragment>\n\t\t\t\t);\n\t\t\t})}\n\n\t\t\t{/* Slot for inline content after messages (e.g. email prompt) */}\n\t\t\t{renderAfterMessages}\n\n\t\t\t{/* Streaming AI response — shows text flowing in word by word.\n\t\t\t MUST mirror MessageBubble's AI markup (hw-msg/hw-msg--ai/hw-msg-bubble)\n\t\t\t and go through renderMarkdown: the old hw-message-ai/hw-bubble-ai\n\t\t\t classes had no CSS at all, so the stream rendered as unstyled raw\n\t\t\t markdown and then \"jumped\" into the formatted bubble on finish. */}\n\t\t\t{streamingText && (\n\t\t\t\t<div className=\"hw-msg hw-msg--ai\">\n\t\t\t\t\t<div className=\"hw-msg-body\">\n\t\t\t\t\t\t<div className=\"hw-msg-bubble\">\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\tdangerouslySetInnerHTML={{\n\t\t\t\t\t\t\t\t\t__html: renderMarkdown(closeDanglingMarkdown(streamingText)),\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<span className=\"hw-streaming-cursor\" />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* AI processing indicator (thinking dots — hidden during streaming) */}\n\t\t\t{isAiProcessing && !streamingText && (\n\t\t\t\t<div className=\"hw-typing\">\n\t\t\t\t\t<div className=\"hw-typing-label\">{agentName}</div>\n\t\t\t\t\t<div className=\"hw-typing-dots\">\n\t\t\t\t\t\t<div className=\"hw-typing-dot\" />\n\t\t\t\t\t\t<div className=\"hw-typing-dot\" />\n\t\t\t\t\t\t<div className=\"hw-typing-dot\" />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Typing indicator (team, not AI) */}\n\t\t\t{isTyping && !isAiProcessing && (\n\t\t\t\t<div className=\"hw-typing\">\n\t\t\t\t\t<div className=\"hw-typing-dots\">\n\t\t\t\t\t\t<div className=\"hw-typing-dot\" />\n\t\t\t\t\t\t<div className=\"hw-typing-dot\" />\n\t\t\t\t\t\t<div className=\"hw-typing-dot\" />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t<div ref={bottomRef} />\n\t\t</div>\n\t);\n}\n\n// ── Event Card ────────────────────────────────────────\n\ninterface EventData {\n\taction: string;\n\tname: string;\n\timage?: string | null;\n}\n\nfunction parseEventData(text: string): EventData | null {\n\tif (!text.startsWith(\"{\")) return null;\n\ttry {\n\t\tconst data = JSON.parse(text);\n\t\tif (data.action && data.name) return data as EventData;\n\t} catch {\n\t\t/* plain text fallback */\n\t}\n\treturn null;\n}\n\nfunction EventCard({ text }: { text: string }) {\n\tconst data = parseEventData(text);\n\n\t// Structured event — rich card with avatar\n\tif (data) {\n\t\tconst message = data.action === \"joined\" ? t(\"widget.joined\") : t(\"widget.left\");\n\n\t\treturn (\n\t\t\t<div className=\"hw-event hw-event--card\">\n\t\t\t\t<div className=\"hw-event-avatar\">\n\t\t\t\t\t{data.image ? (\n\t\t\t\t\t\t<img src={data.image} alt=\"\" className=\"hw-event-avatar-img\" />\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<span>{getInitials(data.name)}</span>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t<div className=\"hw-event-body\">\n\t\t\t\t\t<span className=\"hw-event-name\">{data.name}</span>{\" \"}\n\t\t\t\t\t<span className=\"hw-event-action\">{message}</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t);\n\t}\n\n\t// Plain text event (resolve, reopen, etc.)\n\treturn (\n\t\t<div className=\"hw-event\">\n\t\t\t<div className=\"hw-event-text\">{text}</div>\n\t\t</div>\n\t);\n}\n","\"use client\";\n\nimport { t } from \"@helpway/widget-core\";\nimport type { MouseEvent, ReactNode } from \"react\";\nimport { useEffect, useState } from \"react\";\nimport { useWidgetStore } from \"../provider\";\nimport { XIcon } from \"./icons\";\n\n/** Where the preview is anchored — controls only the outer positioning. */\nexport type MessagePreviewPlacement = \"launcher\" | \"anchored\";\n\nexport interface MessagePreviewProps {\n\t/** Called when the visitor taps the preview (or a quick reply). The\n\t * active conversation is already switched to the one that pinged —\n\t * the consumer just has to reveal the chat surface. */\n\tonOpen: () => void;\n\t/**\n\t * The avatar node shown in the header. Injected by the consumer so\n\t * this component stays decoupled from avatar resolution — the default\n\t * widget passes `<WidgetLogo />`; a custom surface can pass its own.\n\t */\n\tavatar: ReactNode;\n\t/**\n\t * Outer positioning mode. `\"launcher\"` (default) keeps the original\n\t * absolute placement above the floating bubble — DefaultWidget relies\n\t * on this, so the default is unchanged. `\"anchored\"` drops the\n\t * absolute/bottom/right rules (via `hw-preview--anchored`) so a\n\t * consumer can pin it to their own trigger (e.g. a sidebar item).\n\t */\n\tplacement?: MessagePreviewPlacement;\n\t/**\n\t * Auto-dismiss delay in ms. Default `8000` (the launcher behaviour).\n\t * Pass `null` (or `0`) to keep the preview until the visitor acts on\n\t * it — useful for an anchored surface where it isn't competing with\n\t * page content for attention. Quick-reply previews never auto-dismiss\n\t * regardless, since the visitor needs time to choose.\n\t */\n\tautoDismissMs?: number | null;\n\t/**\n\t * Optional caption rendered as a separated footer beneath the message\n\t * (e.g. a source label like \"via Helpway\"). Omitted for the launcher\n\t * so its visual stays byte-identical to the original.\n\t */\n\tfooter?: ReactNode;\n}\n\n/**\n * `<MessagePreview>` — the proactive incoming-message bubble shown while\n * the chat surface is closed. Reads `incomingPreview` from the widget\n * store, auto-dismisses after 8s (unless quick replies are present), and\n * on tap switches to the pinging conversation before calling `onOpen`.\n *\n * Extracted from the default widget so `hideLauncher` integrations can\n * surface the *exact same* preview next to their own UI instead of the\n * floating launcher. Visual/markup is byte-identical to the launcher\n * version — only the outer positioning is parameterised via `placement`.\n *\n * Must be rendered inside `<SupportProvider>`.\n */\nexport function MessagePreview({\n\tonOpen,\n\tavatar,\n\tplacement = \"launcher\",\n\tautoDismissMs = 8000,\n\tfooter,\n}: MessagePreviewProps) {\n\tconst preview = useWidgetStore((s) => s.incomingPreview);\n\tconst dismissPreview = useWidgetStore((s) => s.dismissPreview);\n\tconst setActiveConversation = useWidgetStore((s) => s.setActiveConversation);\n\tconst agentName = useWidgetStore((s) => s.agentConfig?.name) ?? \"Support\";\n\tconst [closing, setClosing] = useState(false);\n\n\t// Auto-dismiss after `autoDismissMs` (skip when quick replies are\n\t// present — visitor needs time to read and decide — or when the\n\t// consumer opted out with null/0 for a persistent anchored surface).\n\tuseEffect(() => {\n\t\tif (!preview || preview.quickReplies) return;\n\t\tif (autoDismissMs == null || autoDismissMs <= 0) return;\n\t\tconst timer = setTimeout(() => {\n\t\t\tsetClosing(true);\n\t\t\tsetTimeout(() => dismissPreview(), 200);\n\t\t}, autoDismissMs);\n\t\treturn () => clearTimeout(timer);\n\t}, [preview, dismissPreview, autoDismissMs]);\n\n\tif (!preview) return null;\n\n\tconst handleClose = (e: MouseEvent) => {\n\t\te.stopPropagation();\n\t\tsetClosing(true);\n\t\tsetTimeout(() => {\n\t\t\tdismissPreview();\n\t\t\tsetClosing(false);\n\t\t}, 200);\n\t};\n\n\tconst handleClick = () => {\n\t\t// Bubble click is an explicit \"I want to read this\" — open the\n\t\t// widget AND jump straight to the conversation that pinged. Without\n\t\t// the setActiveConversation, the visitor lands on the home screen\n\t\t// and has to find the unread row themselves.\n\t\tconst targetConvId = preview.conversationId;\n\t\tdismissPreview();\n\t\tsetActiveConversation(targetConvId);\n\t\tonOpen();\n\t};\n\n\tconst messages = preview.messages?.length ? preview.messages : [{ text: preview.text }];\n\tconst hasQr = preview.quickReplies && preview.quickReplies.options.length > 0;\n\n\tconst placementClass = placement === \"anchored\" ? \"hw-preview--anchored \" : \"\";\n\n\treturn (\n\t\t<div\n\t\t\tclassName={`hw-preview ${placementClass}${closing ? \"hw-preview--closing\" : \"\"}`}\n\t\t\tonClick={handleClick}\n\t\t\trole=\"button\"\n\t\t\ttabIndex={0}\n\t\t>\n\t\t\t<div className=\"hw-preview-header\">\n\t\t\t\t<div className=\"hw-preview-avatar\">{avatar}</div>\n\t\t\t\t<div className=\"hw-preview-name\">{agentName}</div>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"hw-preview-close\"\n\t\t\t\t\tonClick={handleClose}\n\t\t\t\t\taria-label={t(\"widget.aria_dismiss\")}\n\t\t\t\t>\n\t\t\t\t\t<XIcon size={20} />\n\t\t\t\t</button>\n\t\t\t</div>\n\n\t\t\t{messages.map((m, i) => (\n\t\t\t\t<div key={i} className=\"hw-preview-body\">\n\t\t\t\t\t{m.text}\n\t\t\t\t</div>\n\t\t\t))}\n\n\t\t\t{hasQr && (\n\t\t\t\t<>\n\t\t\t\t\t{preview.quickReplies!.prompt && (\n\t\t\t\t\t\t<div className=\"hw-preview-body\">{preview.quickReplies!.prompt}</div>\n\t\t\t\t\t)}\n\t\t\t\t\t<div className=\"hw-preview-quick-replies\">\n\t\t\t\t\t\t{preview.quickReplies!.options.map((opt) => (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\tkey={opt.id}\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclassName=\"hw-preview-qr-btn\"\n\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\tdismissPreview();\n\t\t\t\t\t\t\t\t\tsetActiveConversation(preview.conversationId);\n\t\t\t\t\t\t\t\t\tonOpen();\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{opt.label}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\t\t\t\t</>\n\t\t\t)}\n\n\t\t\t{footer != null && footer !== false && (\n\t\t\t\t<div className=\"hw-preview-footer\">{footer}</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","\n export default function styleInject(css, { insertAt } = {}) {\n if (!css || typeof document === 'undefined') return\n \n const head = document.head || document.getElementsByTagName('head')[0]\n const style = document.createElement('style')\n style.type = 'text/css'\n \n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild)\n } else {\n head.appendChild(style)\n }\n } else {\n head.appendChild(style)\n }\n \n if (style.styleSheet) {\n style.styleSheet.cssText = css\n } else {\n style.appendChild(document.createTextNode(css))\n }\n }\n ","import styleInject from '#style-inject';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-stack.hw-preview-stack--anchored {\\n position: static;\\n bottom: auto;\\n right: auto;\\n width: 100%;\\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.hw-markdown ol {\\n margin: 0;\\n padding-left: 20px;\\n}\\n.hw-markdown li {\\n margin: 4px 0;\\n}\\n.hw-markdown code {\\n font-family:\\n ui-monospace,\\n \\\"SF Mono\\\",\\n monospace;\\n font-size: 12px;\\n background: var(--hw-bg-hover);\\n padding: 1px 5px;\\n border-radius: 4px;\\n}\\n.hw-table-wrap {\\n margin: 10px 0;\\n overflow-x: auto;\\n border: 1px solid var(--hw-border, rgba(0, 0, 0, 0.08));\\n border-radius: 10px;\\n}\\n.hw-table {\\n width: 100%;\\n border-collapse: collapse;\\n font-size: 13px;\\n}\\n.hw-table th {\\n text-align: left;\\n font-weight: 600;\\n font-size: 12px;\\n padding: 8px 12px;\\n background: var(--hw-bg-hover, #f5f5f4);\\n border-bottom: 1px solid var(--hw-border, rgba(0, 0, 0, 0.08));\\n}\\n.hw-table td {\\n padding: 8px 12px;\\n border-bottom: 1px solid var(--hw-border, rgba(0, 0, 0, 0.06));\\n vertical-align: top;\\n}\\n.hw-table tbody tr:last-child td {\\n border-bottom: none;\\n}\\n.hw-code {\\n margin: 10px 0;\\n border-radius: 10px;\\n overflow: hidden;\\n border: 1px solid var(--hw-border, rgba(0, 0, 0, 0.08));\\n background: var(--hw-bg-hover, #f5f5f4);\\n font-family:\\n ui-monospace,\\n \\\"SF Mono\\\",\\n \\\"Menlo\\\",\\n monospace;\\n}\\n.hw-code-header {\\n display: flex;\\n align-items: center;\\n justify-content: space-between;\\n gap: 10px;\\n padding: 7px 8px 7px 12px;\\n font-size: 11px;\\n color: var(--hw-text-2, #6b7280);\\n background: rgba(0, 0, 0, 0.03);\\n border-bottom: 1px solid var(--hw-border, rgba(0, 0, 0, 0.06));\\n}\\n.hw-code-lang {\\n text-transform: lowercase;\\n letter-spacing: 0.02em;\\n font-weight: 500;\\n}\\n.hw-code-actions {\\n display: inline-flex;\\n align-items: center;\\n gap: 1px;\\n}\\n.hw-code-action {\\n position: relative;\\n display: inline-flex;\\n align-items: center;\\n justify-content: center;\\n width: 22px;\\n height: 22px;\\n padding: 0;\\n font-family: inherit;\\n color: var(--hw-text-2, #6b7280);\\n background: transparent;\\n border: 1px solid transparent;\\n border-radius: 6px;\\n cursor: pointer;\\n opacity: 0.62;\\n transition:\\n background 120ms ease,\\n color 120ms ease,\\n opacity 120ms ease,\\n scale 120ms ease;\\n}\\n.hw-code-action:hover {\\n color: var(--hw-text, #111);\\n background: rgba(0, 0, 0, 0.06);\\n opacity: 1;\\n}\\n.hw-code-action:active {\\n scale: 0.96;\\n}\\n.hw-code-action svg {\\n width: 13px;\\n height: 13px;\\n}\\n.hw-code-copy-icon,\\n.hw-code-check-icon {\\n position: absolute;\\n inset: 50% auto auto 50%;\\n transition:\\n opacity 180ms cubic-bezier(0.2, 0, 0, 1),\\n scale 180ms cubic-bezier(0.2, 0, 0, 1),\\n filter 180ms cubic-bezier(0.2, 0, 0, 1);\\n translate: -50% -50%;\\n}\\n.hw-code-check-icon {\\n filter: blur(4px);\\n opacity: 0;\\n scale: 0.25;\\n}\\n.hw-code-copy--copied .hw-code-copy-icon {\\n filter: blur(4px);\\n opacity: 0;\\n scale: 0.25;\\n}\\n.hw-code-copy--copied .hw-code-check-icon {\\n filter: blur(0);\\n opacity: 1;\\n scale: 1;\\n}\\n.hw-code-copy-label {\\n position: absolute;\\n width: 1px;\\n height: 1px;\\n overflow: hidden;\\n clip: rect(0, 0, 0, 0);\\n white-space: nowrap;\\n}\\n.hw-code-copy--copied {\\n color: #16a34a;\\n}\\n.hw-code-copy--failed {\\n color: #dc2626;\\n}\\n.hw-code pre {\\n margin: 0;\\n padding: 10px 12px;\\n background: transparent;\\n border-radius: 0;\\n overflow-x: auto;\\n max-width: 100%;\\n max-height: 320px;\\n scrollbar-color: rgba(0, 0, 0, 0.22) transparent;\\n scrollbar-width: thin;\\n}\\n.hw-code pre::-webkit-scrollbar {\\n width: 10px;\\n height: 10px;\\n}\\n.hw-code pre::-webkit-scrollbar-track {\\n background: transparent;\\n}\\n.hw-code pre::-webkit-scrollbar-thumb {\\n background: rgba(0, 0, 0, 0.18);\\n background-clip: content-box;\\n border: 3px solid transparent;\\n border-radius: 999px;\\n}\\n.hw-code pre::-webkit-scrollbar-thumb:hover {\\n background: rgba(0, 0, 0, 0.28);\\n background-clip: content-box;\\n}\\n.hw-code pre code {\\n display: block;\\n background: transparent;\\n padding: 0;\\n font-size: 12px;\\n line-height: 1.55;\\n white-space: pre;\\n color: var(--hw-text, #111);\\n}\\n@media (prefers-color-scheme: dark) {\\n .hw-code {\\n background: rgba(255, 255, 255, 0.04);\\n border-color: rgba(255, 255, 255, 0.08);\\n }\\n .hw-code-header {\\n background: rgba(255, 255, 255, 0.03);\\n border-bottom-color: rgba(255, 255, 255, 0.06);\\n }\\n .hw-code-action:hover,\\n .hw-code-action:focus-visible {\\n background: rgba(255, 255, 255, 0.08);\\n }\\n .hw-code pre {\\n scrollbar-color: rgba(255, 255, 255, 0.26) transparent;\\n }\\n .hw-code pre::-webkit-scrollbar-thumb {\\n background: rgba(255, 255, 255, 0.22);\\n background-clip: content-box;\\n }\\n .hw-code pre::-webkit-scrollbar-thumb:hover {\\n background: rgba(255, 255, 255, 0.32);\\n background-clip: content-box;\\n }\\n}\\n.hw-markdown pre {\\n margin: 8px 0;\\n padding: 10px 12px;\\n background: var(--hw-bg-hover);\\n border-radius: 8px;\\n overflow-x: auto;\\n max-width: 100%;\\n}\\n.hw-markdown pre code {\\n display: block;\\n background: transparent;\\n padding: 0;\\n border-radius: 0;\\n font-size: 12px;\\n line-height: 1.5;\\n white-space: pre;\\n word-break: normal;\\n color: inherit;\\n}\\n.hw-msg-bubble pre {\\n margin: 6px 0;\\n padding: 8px 10px;\\n background: rgba(0, 0, 0, 0.06);\\n border-radius: 6px;\\n overflow-x: auto;\\n max-width: 100%;\\n}\\n.hw-msg-bubble pre code {\\n background: transparent;\\n padding: 0;\\n font-size: 12px;\\n line-height: 1.5;\\n white-space: pre;\\n}\\n.hw-msg-bubble .hw-code pre {\\n margin: 0;\\n padding: 10px 12px;\\n background: transparent;\\n border-radius: 0;\\n}\\n.hw-msg-bubble .hw-code pre code {\\n background: transparent;\\n padding: 0;\\n font-size: 12px;\\n line-height: 1.55;\\n}\\n.hw-msg--team .hw-msg-bubble pre,\\n.hw-msg--visitor .hw-msg-bubble pre {\\n background: rgba(255, 255, 255, 0.12);\\n}\\n.hw-markdown blockquote {\\n margin: 0 0 12px;\\n padding: 8px 12px;\\n border-left: 3px solid var(--hw-border);\\n color: var(--hw-text-2);\\n font-style: italic;\\n}\\n.hw-markdown a {\\n color: var(--hw-primary);\\n text-decoration: underline;\\n text-underline-offset: 2px;\\n}\\n.hw-markdown img {\\n max-width: 100%;\\n border-radius: 8px;\\n margin: 8px 0;\\n outline: 1px solid rgba(0, 0, 0, 0.08);\\n outline-offset: -1px;\\n}\\n.hw-markdown hr {\\n border: none;\\n border-top: 1px solid var(--hw-border);\\n margin: 16px 0;\\n}\\n.hw-content-empty {\\n display: flex;\\n flex-direction: column;\\n align-items: center;\\n justify-content: center;\\n padding: 40px 20px;\\n text-align: center;\\n}\\n.hw-content-empty-title {\\n font-size: 14px;\\n font-weight: 600;\\n color: var(--hw-text-1);\\n margin-bottom: 4px;\\n}\\n.hw-content-empty-desc {\\n font-size: 12px;\\n color: var(--hw-text-3);\\n}\\n.hw-content-loading {\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n padding: 40px 20px;\\n}\\n.hw-content-load-more {\\n display: block;\\n width: 100%;\\n padding: 10px;\\n border: none;\\n background: none;\\n color: var(--hw-primary);\\n font-size: 13px;\\n font-weight: 500;\\n cursor: pointer;\\n text-align: center;\\n}\\n.hw-content-load-more:hover {\\n background: var(--hw-bg-hover);\\n}\\n.hw-content-load-more:disabled {\\n opacity: 0.5;\\n cursor: default;\\n}\\n@media (hover: none) {\\n .hw-composer-preview-remove {\\n opacity: 0.7;\\n }\\n}\\n.hw-composer--dragging .hw-composer-box {\\n border-color: var(--hw-primary);\\n background: color-mix(in srgb, var(--hw-primary) 4%, transparent);\\n}\\n.hw-composer-drop-overlay {\\n position: absolute;\\n inset: 0;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n background: color-mix(in srgb, var(--hw-bg) 90%, transparent);\\n border: 2px dashed var(--hw-primary);\\n border-radius: 12px;\\n z-index: 10;\\n pointer-events: none;\\n animation: hw-drop-pulse 1.5s ease-in-out infinite;\\n}\\n.hw-composer-drop-text {\\n font-size: 13px;\\n font-weight: 500;\\n color: var(--hw-primary);\\n}\\n@keyframes hw-drop-pulse {\\n 0%, 100% {\\n opacity: 0.8;\\n }\\n 50% {\\n opacity: 1;\\n }\\n}\\n.hw-disconnect {\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n gap: 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\")","\"use client\";\n\n/**\n * `<HelpwayWidget />` — one-line drop-in React component that renders\n * the full Helpway widget natively in React.\n *\n * Since v0.2, this is a native React render (not a script tag injection).\n * The widget-core + widget-react code is bundled with your app, so widget\n * updates ship via `npm update @helpway/react` — no separate widget.js\n * deploy required. Bundle impact: ~120KB gzipped (shared with any other\n * helpway/react imports in your app, so subsequent uses are free).\n *\n * Power-user alternative: import `{ SupportProvider, DefaultWidget, useWidget, … }`\n * directly for programmatic control (render your own chat UI, expose\n * identify() via hook instead of global, etc.).\n *\n * @see https://helpway.ai/docs/quick-start for setup\n * @see https://helpway.ai/docs/react-sdk for the three integration layers\n * (drop-in, provider + hooks, fully headless)\n * @see https://helpway.ai/docs/customization for theming via `theme` prop\n * and the dashboard config\n * @see https://helpway.ai/docs/integration-notes for CSP, SSR, multi-tenant\n */\n\nimport type { WidgetTheme } from \"@helpway/widget-core\";\nimport { SupportProvider } from \"./provider\";\nimport { DefaultWidget } from \"./themed/default-widget\";\n// Auto-import CSS so consumers don't need a separate `import \"@helpway/react/styles.css\"` step.\n// Side-effect import — evaluated once per bundle, tree-shaker preserves it via `sideEffects: [\"*.css\"]`.\nimport \"./themed/styles.css\";\n\nexport interface HelpwayWidgetProps {\n\t/**\n\t * Public API key from the Helpway dashboard. Required.\n\t * Format: `pk_live_…` or `pk_test_…`.\n\t */\n\tapiKey: string;\n\t/**\n\t * Override the default API URL. Almost no one needs this —\n\t * exposed for staging / self-hosted setups.\n\t * @default \"https://api.helpway.ai\"\n\t */\n\tapiUrl?: string;\n\t/**\n\t * Widget locale (e.g. \"tr\", \"en\", \"de\"). Falls back to server-side\n\t * detection (Accept-Language + CF-IPCountry) then widget-core default.\n\t */\n\tlocale?: string;\n\t/**\n\t * Deep link: auto-open this conversation after bootstrap.\n\t * Usually sourced from `?hw_conv=` URL param for email CTAs.\n\t */\n\tinitialConversationId?: string;\n\t/**\n\t * HMAC-signed token for cross-device visitor identity restoration.\n\t * Sourced from `#hw_token=` URL fragment in email deep-links.\n\t */\n\tdeepLinkToken?: string;\n\t/**\n\t * Called once after the widget has bootstrapped and exposes\n\t * the full programmatic API object (also available as `window.Helpway`).\n\t */\n\tonReady?: (api: HelpwayPublicAPI) => void;\n\t/**\n\t * Hide the default floating launcher button. Use with\n\t * `customLauncherSelector` or `window.Helpway.open()` to trigger\n\t * the widget from your own UI.\n\t */\n\thideLauncher?: boolean;\n\t/**\n\t * CSS selector for a custom trigger element (e.g. `\"#support-btn\"`).\n\t * Clicking the matched element calls `Helpway.open()`. Combine with\n\t * `hideLauncher` to fully replace the default bubble.\n\t */\n\tcustomLauncherSelector?: string;\n\t/** Fires when the widget panel opens */\n\tonOpen?: () => void;\n\t/** Fires when the widget panel closes */\n\tonClose?: () => void;\n\t/** Fires when the unread count changes */\n\tonUnreadChange?: (count: number) => void;\n\t/**\n\t * Developer-side theme override. Most consumers should configure\n\t * appearance from the dashboard so changes apply without a redeploy\n\t * — see https://helpway.ai/docs/customization. Use this prop only\n\t * for runtime-resolved theming (multi-tenant brand colors, dark/\n\t * light sync with the host app, etc). Values map to CSS custom\n\t * properties on the widget host. See the `WidgetTheme` type for\n\t * the full set of supported keys.\n\t */\n\ttheme?: WidgetTheme;\n\t/**\n\t * @deprecated Legacy prop from the v0.1 script-loader era. If set,\n\t * the `/widget.js` suffix is stripped to derive `apiUrl`. New code\n\t * should use `apiUrl` instead.\n\t */\n\tsrc?: string;\n}\n\n// Re-export for consumers who use the onReady callback type.\n// `onReady` receives the programmatic methods object; the global\n// `window.Helpway` is the callable wrapper around it (HelpwayAPI).\nimport type { HelpwayMethods } from \"@helpway/widget-core\";\nexport type HelpwayPublicAPI = HelpwayMethods;\n\n/**\n * Render this once at the root of your app (e.g. in `_app.tsx`,\n * `layout.tsx`, or `main.tsx`). Unmounting cleanly tears down the\n * widget and its WebSocket connection — useful for route-scoped mounts.\n */\nexport function HelpwayWidget({\n\tapiKey,\n\tapiUrl,\n\tlocale,\n\tinitialConversationId,\n\tdeepLinkToken,\n\tonReady,\n\thideLauncher,\n\tcustomLauncherSelector,\n\tonOpen,\n\tonClose,\n\tonUnreadChange,\n\ttheme,\n\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\tsrc,\n}: HelpwayWidgetProps) {\n\tconst resolvedApiUrl = apiUrl ?? (src ? src.replace(/\\/widget\\.js$/, \"\") : undefined);\n\n\treturn (\n\t\t<SupportProvider\n\t\t\tapiKey={apiKey}\n\t\t\tapiUrl={resolvedApiUrl}\n\t\t\tlocale={locale}\n\t\t\tinitialConversationId={initialConversationId}\n\t\t\tdeepLinkToken={deepLinkToken}\n\t\t\tonReady={onReady}\n\t\t\tcustomLauncherSelector={customLauncherSelector}\n\t\t\tonOpen={onOpen}\n\t\t\tonClose={onClose}\n\t\t\tonUnreadChange={onUnreadChange}\n\t\t\ttheme={theme}\n\t\t>\n\t\t\t<DefaultWidget hideLauncher={hideLauncher} />\n\t\t</SupportProvider>\n\t);\n}\n","import { useEffect } from \"react\";\nimport type { RealtimeEvent } from \"@helpway/types\";\nimport { useWidgetContext } from \"../provider\";\n\n/**\n * Subscribe to raw WebSocket events.\n * For advanced usage — most apps should use useTimeline/usePresence instead.\n *\n * Usage:\n * ```tsx\n * useRealtime((event) => {\n * if (event.type === 'timelineItemCreated') { ... }\n * })\n * ```\n */\nexport function useRealtime(handler: (event: RealtimeEvent) => void) {\n\tconst { ws } = useWidgetContext();\n\n\tuseEffect(() => {\n\t\treturn ws.onEvent(handler);\n\t}, [ws, handler]);\n}\n"],"mappings":"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","names":["storageKey","client","store","emitter","ws","identify","api","el","useCallback","useEffect","useRef","useState","useCallback","useEffect","useRef","t","useRef","useEffect","useCallback","useCallback","useState","useState","useCallback","useCallback","useRef","useState","useState","useRef","useCallback","store","useEffect","useState","useState","useEffect","useCallback","useRef","useRef","useCallback","useCallback","useEffect","useRef","useState","useState","useRef","useEffect","useCallback","useCallback","useRef","useState","jsx","jsx","jsx","jsx","jsx","useEffect","useRef","useState","useEffect","useRef","jsx","jsx","jsxs","useRef","useEffect","useState","jsx","jsxs","useRef","useCallback","useState","useEffect","useMemo","useRef","useState","jsx","jsxs","useState","useRef","useEffect","useMemo","useCallback","useEffect","useCallback","useEffect","useState","EMPTY_TABS","t","useState","useCallback","useEffect","Fragment","jsx","jsxs","useCallback","useRef","useState","jsx","jsxs","useEffect","useRef","useCallback","useRef","useState","EMPTY_TABS","detailKey","readCache","t","useState","useRef","useCallback","jsx","useEffect","useRef","jsx","useEffect","useCallback","jsx","useState","jsx","jsxs","useState","useEffect","useRef","jsx","jsxs","useRef","useEffect","useEffect","useState","Fragment","jsx","jsxs","useState","useEffect","Fragment","jsx","jsxs","resolveLabel","c","useState","useEffect","useRef","useCallback","t","focusable","jsx","useEffect","useEffect"]}
1
+ {"version":3,"sources":["../../widget-core/src/client.ts","../../widget-core/src/visitor-id.ts","../../types/src/realtime-events.ts","../../types/src/doc-nav-icons.ts","../../widget-core/src/ws.ts","../../widget-core/src/store.ts","../../widget-core/src/api.ts","../../widget-core/src/theme.ts","../../widget-core/src/events.ts","../../widget-core/src/i18n.ts","../../widget-core/src/utils.ts","../src/provider.tsx","../src/themed/default-widget.tsx","../src/hooks/use-announcements.ts","../src/hooks/use-composer.ts","../src/hooks/use-conversations.ts","../src/hooks/use-i18n.ts","../src/hooks/use-presence.ts","../src/hooks/use-timeline.ts","../src/hooks/use-unread.ts","../src/hooks/use-widget.ts","../src/themed/composer.tsx","../src/themed/icons.tsx","../src/themed/debug-overlay.tsx","../src/shell/docked-bar.tsx","../src/themed/content/content-tab-view.tsx","../src/hooks/use-content-tab.ts","../src/themed/content/simple-markdown.tsx","../src/themed/content/content-detail-view.tsx","../src/themed/content/content-list-view.tsx","../src/themed/content/grouped-content-tab-view.tsx","../src/hooks/use-grouped-content-tab.ts","../src/themed/content/tab-icon.tsx","../src/themed/announcement-previews.tsx","../src/themed/strip-markdown.ts","../src/themed/message-bubble.tsx","../src/themed/message-list.tsx","../src/themed/message-preview.tsx","#style-inject:#style-inject","../src/themed/styles.css","../src/helpway-widget.tsx","../src/hooks/use-realtime.ts"],"sourcesContent":["import { createTRPCClient, httpBatchLink } from \"@trpc/client\";\nimport { getOrCreateVisitorId } from \"./visitor-id\";\n\n// The real AppRouter lives in apps/api/src/trpc/ but importing it pulls in CF Worker\n// source files. We type the client as `any` here — real type safety is in the\n// Zustand store (widget-react). The tRPC link config is the same at runtime.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type WidgetClient = any;\n\n/**\n * Create a tRPC vanilla client for widget API calls.\n *\n * Visitor identity uses a dual strategy:\n * 1. X-Visitor-Id header (localStorage-based) — always works, even cross-origin\n * 2. hw_visitor cookie (server-set) — additional persistence layer\n *\n * This ensures visitor identity survives 3rd-party cookie blocking\n * (Safari ITP, Firefox ETP, Chrome Privacy Sandbox).\n */\nexport function createWidgetClient(config: {\n\tapiUrl: string;\n\tapiKey: string;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\n}): any {\n\treturn createTRPCClient({\n\t\tlinks: [\n\t\t\thttpBatchLink({\n\t\t\t\turl: `${config.apiUrl}/trpc`,\n\t\t\t\theaders() {\n\t\t\t\t\treturn {\n\t\t\t\t\t\t\"X-Public-Key\": config.apiKey,\n\t\t\t\t\t\t\"X-Visitor-Id\": getOrCreateVisitorId(config.apiKey),\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t\tfetch(url, options) {\n\t\t\t\t\t// credentials: \"include\" sends cookies cross-origin (when not blocked)\n\t\t\t\t\treturn globalThis.fetch(url, { ...options, credentials: \"include\" });\n\t\t\t\t},\n\t\t\t}),\n\t\t],\n\t});\n}\n","/**\n * Per-site visitor identity storage (localStorage).\n *\n * Matches Intercom's `intercom-id-[app_id]` pattern — each publicKey gets\n * its own localStorage slot so a single browser visiting multiple Helpway\n * workspaces never bleeds identities across them.\n *\n * Storage key: `helpway:visitor:<publicKey-suffix>` (last 16 chars of the key,\n * which is always random — see `generatePublicKey` in apps/api/src/lib/id.ts).\n */\n\nconst PREFIX = \"helpway:visitor\";\nconst LEGACY_KEY = \"helpway:visitor-id\";\n\nfunction keyFor(publicKey: string): string {\n\t// Last 16 chars of publicKey — enough uniqueness (2^80 collision space for nanoid alphabet)\n\t// and keeps localStorage key short. Stable for a given site.\n\tconst suffix = publicKey.slice(-16);\n\treturn `${PREFIX}:${suffix}`;\n}\n\nfunction generateId(): string {\n\tconst ts = Date.now().toString(36);\n\tconst rand = Math.random().toString(36).slice(2, 10);\n\treturn `${ts}${rand}`;\n}\n\n/**\n * Get or create a persistent visitor ID scoped to `publicKey`.\n * Returns a stable per-site ID across page loads.\n */\nexport function getOrCreateVisitorId(publicKey: string): string {\n\ttry {\n\t\tconst storageKey = keyFor(publicKey);\n\t\tconst existing = localStorage.getItem(storageKey);\n\t\tif (existing) return existing;\n\n\t\t// One-time migration: if a legacy global key exists AND no per-site key\n\t\t// is set yet, seed this site with it. Keeps returning visitors identified\n\t\t// on their FIRST post-upgrade site load. Subsequent sites get fresh IDs.\n\t\tconst legacy = localStorage.getItem(LEGACY_KEY);\n\t\tif (legacy) {\n\t\t\tlocalStorage.setItem(storageKey, legacy);\n\t\t\tlocalStorage.removeItem(LEGACY_KEY);\n\t\t\treturn legacy;\n\t\t}\n\n\t\tconst id = generateId();\n\t\tlocalStorage.setItem(storageKey, id);\n\t\treturn id;\n\t} catch {\n\t\t// localStorage unavailable (SSR, private mode, quota exceeded)\n\t\treturn generateId();\n\t}\n}\n\n/** Sync the server-assigned canonical visitor ID back into localStorage. */\nexport function syncVisitorId(publicKey: string, serverVisitorId: string): void {\n\ttry {\n\t\tlocalStorage.setItem(keyFor(publicKey), serverVisitorId);\n\t} catch {\n\t\t// ignore\n\t}\n}\n\n/** Clear the visitor ID for a specific site (used by playground \"simulate anonymous\"). */\nexport function clearVisitorId(publicKey: string): void {\n\ttry {\n\t\tlocalStorage.removeItem(keyFor(publicKey));\n\t} catch {\n\t\t// ignore\n\t}\n}\n","import type { Conversation } from \"./conversation\";\nimport type { TimelineItem } from \"./timeline-item\";\n\n// ── Event type constants ─────────────────────────────────\n\nexport const WsEventType = {\n\tConnectionEstablished: \"connectionEstablished\",\n\tConversationCreated: \"conversationCreated\",\n\tConversationUpdated: \"conversationUpdated\",\n\tTimelineItemCreated: \"timelineItemCreated\",\n\tTimelineItemUpdated: \"timelineItemUpdated\",\n\tTimelineItemDeleted: \"timelineItemDeleted\",\n\tConversationSeen: \"conversationSeen\",\n\tConversationTyping: \"conversationTyping\",\n\tAiProcessingProgress: \"aiProcessingProgress\",\n\tAiProcessingCompleted: \"aiProcessingCompleted\",\n\tAiStreamChunk: \"aiStreamChunk\",\n\tVisitorPresenceChanged: \"visitorPresenceChanged\",\n\tMemberUpdated: \"memberUpdated\",\n\tWorkspaceUnreadCounts: \"workspaceUnreadCounts\",\n} as const;\n\n// ── Union of all realtime events ──────────────────────────\n\nexport type RealtimeEvent =\n\t| ConnectionEstablishedEvent\n\t| ConversationCreatedEvent\n\t| ConversationUpdatedEvent\n\t| TimelineItemCreatedEvent\n\t| TimelineItemUpdatedEvent\n\t| TimelineItemDeletedEvent\n\t| ConversationSeenEvent\n\t| ConversationTypingEvent\n\t| AiProcessingProgressEvent\n\t| AiProcessingCompletedEvent\n\t| AiStreamChunkEvent\n\t| VisitorPresenceChangedEvent\n\t| MemberUpdatedEvent\n\t| WorkspaceUnreadCountsEvent;\n\n// ── Connection ────────────────────────────────────────────\n\nexport interface ConnectionEstablishedEvent {\n\ttype: \"connectionEstablished\";\n\tconnectionId: string;\n}\n\n// ── Conversation lifecycle ────────────────────────────────\n\nexport interface ConversationCreatedEvent {\n\ttype: \"conversationCreated\";\n\tconversation: Conversation;\n}\n\nexport interface ConversationUpdatedEvent {\n\ttype: \"conversationUpdated\";\n\tconversationId: string;\n\tupdates: Partial<Conversation>;\n}\n\n// ── Timeline items ────────────────────────────────────────\n\nexport interface TimelineItemCreatedEvent {\n\ttype: \"timelineItemCreated\";\n\tconversationId: string;\n\titem: TimelineItem;\n}\n\nexport interface TimelineItemUpdatedEvent {\n\ttype: \"timelineItemUpdated\";\n\tconversationId: string;\n\titem: TimelineItem;\n}\n\nexport interface TimelineItemDeletedEvent {\n\ttype: \"timelineItemDeleted\";\n\tconversationId: string;\n\titemId: string;\n}\n\n// ── Presence / read receipts ──────────────────────────────\n\nexport interface ConversationSeenEvent {\n\ttype: \"conversationSeen\";\n\tconversationId: string;\n\tuserId?: string;\n\tvisitorId?: string;\n\tlastSeenAt: string;\n}\n\nexport interface ConversationTypingEvent {\n\ttype: \"conversationTyping\";\n\tconversationId: string;\n\tuserId?: string;\n\tvisitorId?: string;\n\tisTyping: boolean;\n}\n\n// ── AI processing indicators ──────────────────────────────\n\nexport interface AiProcessingProgressEvent {\n\ttype: \"aiProcessingProgress\";\n\tconversationId: string;\n\tphase: \"thinking\" | \"searching\" | \"responding\";\n}\n\nexport interface AiProcessingCompletedEvent {\n\ttype: \"aiProcessingCompleted\";\n\tconversationId: string;\n\tstatus: \"success\" | \"error\" | \"skipped\";\n}\n\nexport interface AiStreamChunkEvent {\n\ttype: \"aiStreamChunk\";\n\tconversationId: string;\n\t/** Incremental text delta — widget appends to the streaming bubble. */\n\tdelta: string;\n\t/** True when this is the final chunk — widget should finalize the bubble. */\n\tdone: boolean;\n}\n\n// ── Visitor presence ─────────────────────────────────────\n\nexport interface VisitorPresenceChangedEvent {\n\ttype: \"visitorPresenceChanged\";\n\tvisitorId: string;\n\tstatus: \"online\" | \"offline\";\n}\n\n// ── Organization team ────────────────────────────────────\n\nexport interface MemberUpdatedEvent {\n\ttype: \"memberUpdated\";\n\taction: \"added\" | \"removed\" | \"roleChanged\";\n\tmemberId: string;\n}\n\n// ── Workspace meta events ───────────────────────────────\n\nexport interface WorkspaceUnreadCountsEvent {\n\ttype: \"workspaceUnreadCounts\";\n\tcounts: Record<string, number>;\n}\n\n// ── Event type guard helper ───────────────────────────────\n\nexport function isRealtimeEvent(data: unknown): data is RealtimeEvent {\n\treturn (\n\t\ttypeof data === \"object\" &&\n\t\tdata !== null &&\n\t\t\"type\" in data &&\n\t\ttypeof (data as RealtimeEvent).type === \"string\"\n\t);\n}\n","/**\n * Single source of truth for the docs/help-center sidebar nav icon allowlist.\n *\n * Shared so the content portal (dashboard) and the public content-site never\n * drift: the portal lists/validates these names, the content-site renders them.\n * Stored as structured primitives (not raw SVG markup) so consumers render real\n * SVG elements — no `dangerouslySetInnerHTML`, no XSS surface, no React in this\n * (types) package. Each consumer wraps these in its own `<svg viewBox=\"0 0 24\n * 24\" stroke=\"currentColor\" stroke-width=\"1.75\">`.\n *\n * Authors may still set a raw `<svg>` string instead of a name (rendered by the\n * content-site through an <img> data-URI); this allowlist is the curated set.\n */\n\nexport type DocNavIconShape =\n\t| { t: \"path\"; d: string }\n\t| { t: \"polyline\"; points: string }\n\t| { t: \"polygon\"; points: string }\n\t| { t: \"circle\"; cx: number; cy: number; r: number }\n\t| { t: \"rect\"; x: number; y: number; width: number; height: number; rx?: number }\n\t| { t: \"line\"; x1: number; y1: number; x2: number; y2: number };\n\nexport interface DocNavIcon {\n\t/** Stable key authors type (lowercase). */\n\tname: string;\n\t/** Human label for a picker. */\n\tlabel: string;\n\tshapes: DocNavIconShape[];\n}\n\nexport const DOC_NAV_ICONS: DocNavIcon[] = [\n\t{\n\t\tname: \"globe\",\n\t\tlabel: \"Globe\",\n\t\tshapes: [\n\t\t\t{ t: \"circle\", cx: 12, cy: 12, r: 10 },\n\t\t\t{\n\t\t\t\tt: \"path\",\n\t\t\t\td: \"M2 12h20M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z\",\n\t\t\t},\n\t\t],\n\t},\n\t{\n\t\tname: \"code\",\n\t\tlabel: \"Code\",\n\t\tshapes: [\n\t\t\t{ t: \"polyline\", points: \"16 18 22 12 16 6\" },\n\t\t\t{ t: \"polyline\", points: \"8 6 2 12 8 18\" },\n\t\t],\n\t},\n\t{\n\t\tname: \"book\",\n\t\tlabel: \"Book\",\n\t\tshapes: [\n\t\t\t{ t: \"path\", d: \"M4 19.5A2.5 2.5 0 0 1 6.5 17H20\" },\n\t\t\t{ t: \"path\", d: \"M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z\" },\n\t\t],\n\t},\n\t{\n\t\tname: \"rocket\",\n\t\tlabel: \"Rocket\",\n\t\tshapes: [\n\t\t\t{\n\t\t\t\tt: \"path\",\n\t\t\t\td: \"M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z\",\n\t\t\t},\n\t\t\t{\n\t\t\t\tt: \"path\",\n\t\t\t\td: \"m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z\",\n\t\t\t},\n\t\t\t{\n\t\t\t\tt: \"path\",\n\t\t\t\td: \"M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5\",\n\t\t\t},\n\t\t],\n\t},\n\t{\n\t\tname: \"terminal\",\n\t\tlabel: \"Terminal\",\n\t\tshapes: [\n\t\t\t{ t: \"polyline\", points: \"4 17 10 11 4 5\" },\n\t\t\t{ t: \"line\", x1: 12, y1: 19, x2: 20, y2: 19 },\n\t\t],\n\t},\n\t{\n\t\tname: \"smartphone\",\n\t\tlabel: \"Smartphone\",\n\t\tshapes: [\n\t\t\t{ t: \"rect\", x: 5, y: 2, width: 14, height: 20, rx: 2 },\n\t\t\t{ t: \"line\", x1: 12, y1: 18, x2: 12.01, y2: 18 },\n\t\t],\n\t},\n\t{\n\t\tname: \"server\",\n\t\tlabel: \"Server\",\n\t\tshapes: [\n\t\t\t{ t: \"rect\", x: 2, y: 2, width: 20, height: 8, rx: 2 },\n\t\t\t{ t: \"rect\", x: 2, y: 14, width: 20, height: 8, rx: 2 },\n\t\t\t{ t: \"line\", x1: 6, y1: 6, x2: 6.01, y2: 6 },\n\t\t\t{ t: \"line\", x1: 6, y1: 18, x2: 6.01, y2: 18 },\n\t\t],\n\t},\n\t{\n\t\tname: \"key\",\n\t\tlabel: \"Key\",\n\t\tshapes: [\n\t\t\t{ t: \"circle\", cx: 7.5, cy: 15.5, r: 5.5 },\n\t\t\t{ t: \"path\", d: \"m21 2-9.6 9.6M16 6l4 4\" },\n\t\t],\n\t},\n\t{\n\t\tname: \"puzzle\",\n\t\tlabel: \"Puzzle\",\n\t\tshapes: [\n\t\t\t{\n\t\t\t\tt: \"path\",\n\t\t\t\td: \"M19.439 7.85c-.049.322.059.648.289.878l1.568 1.568c.47.47.706 1.087.706 1.704s-.235 1.233-.706 1.704l-1.611 1.611a.98.98 0 0 1-.837.276c-.47-.07-.802-.48-.968-.925a2.501 2.501 0 1 0-3.214 3.214c.446.166.855.497.925.968a.979.979 0 0 1-.276.837l-1.61 1.61a2.404 2.404 0 0 1-1.704.706 2.402 2.402 0 0 1-1.704-.706l-1.568-1.568a1.026 1.026 0 0 0-.877-.29c-.493.074-.84.504-1.02.968a2.5 2.5 0 1 1-3.237-3.237c.464-.18.894-.527.967-1.02a1.026 1.026 0 0 0-.289-.877l-1.568-1.568A2.402 2.402 0 0 1 1.998 12c0-.617.236-1.234.706-1.704L4.28 8.687c.24-.24.581-.353.925-.29.493.074.84.504 1.02.968a2.5 2.5 0 1 0 3.237-3.237c-.464-.18-.894-.527-.967-1.02a1.026 1.026 0 0 1 .289-.877l1.568-1.568A2.402 2.402 0 0 1 12 1.998c.617 0 1.234.236 1.704.706l1.568 1.568c.23.23.556.338.877.29.493-.074.84-.504 1.02-.968a2.5 2.5 0 1 1 3.237 3.237c-.18.464-.527.894-1.02.968z\",\n\t\t\t},\n\t\t],\n\t},\n\t{\n\t\tname: \"file\",\n\t\tlabel: \"File\",\n\t\tshapes: [\n\t\t\t{ t: \"path\", d: \"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\" },\n\t\t\t{ t: \"polyline\", points: \"14 2 14 8 20 8\" },\n\t\t],\n\t},\n\t{\n\t\tname: \"settings\",\n\t\tlabel: \"Settings\",\n\t\tshapes: [\n\t\t\t{ t: \"circle\", cx: 12, cy: 12, r: 3 },\n\t\t\t{\n\t\t\t\tt: \"path\",\n\t\t\t\td: \"M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z\",\n\t\t\t},\n\t\t],\n\t},\n\t{\n\t\tname: \"zap\",\n\t\tlabel: \"Zap\",\n\t\tshapes: [{ t: \"polygon\", points: \"13 2 3 14 12 14 11 22 21 10 12 10 13 2\" }],\n\t},\n\t{\n\t\tname: \"layers\",\n\t\tlabel: \"Layers\",\n\t\tshapes: [\n\t\t\t{ t: \"polygon\", points: \"12 2 2 7 12 12 22 7 12 2\" },\n\t\t\t{ t: \"polyline\", points: \"2 17 12 22 22 17\" },\n\t\t\t{ t: \"polyline\", points: \"2 12 12 17 22 12\" },\n\t\t],\n\t},\n\t{\n\t\tname: \"plug\",\n\t\tlabel: \"Plug\",\n\t\tshapes: [\n\t\t\t{ t: \"path\", d: \"M12 22v-5\" },\n\t\t\t{ t: \"path\", d: \"M9 8V2M15 8V2\" },\n\t\t\t{ t: \"path\", d: \"M18 8v5a6 6 0 0 1-12 0V8z\" },\n\t\t],\n\t},\n\t{\n\t\tname: \"message\",\n\t\tlabel: \"Message\",\n\t\tshapes: [{ t: \"path\", d: \"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" }],\n\t},\n\t{\n\t\tname: \"inbox\",\n\t\tlabel: \"Inbox\",\n\t\tshapes: [\n\t\t\t{ t: \"polyline\", points: \"22 12 16 12 14 15 10 15 8 12 2 12\" },\n\t\t\t{\n\t\t\t\tt: \"path\",\n\t\t\t\td: \"M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z\",\n\t\t\t},\n\t\t],\n\t},\n\t{\n\t\tname: \"users\",\n\t\tlabel: \"Users\",\n\t\tshapes: [\n\t\t\t{ t: \"path\", d: \"M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2\" },\n\t\t\t{ t: \"circle\", cx: 9, cy: 7, r: 4 },\n\t\t\t{ t: \"path\", d: \"M23 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75\" },\n\t\t],\n\t},\n\t{\n\t\tname: \"mail\",\n\t\tlabel: \"Mail\",\n\t\tshapes: [\n\t\t\t{ t: \"rect\", x: 2, y: 4, width: 20, height: 16, rx: 2 },\n\t\t\t{ t: \"path\", d: \"m22 7-10 5L2 7\" },\n\t\t],\n\t},\n\t{\n\t\tname: \"credit-card\",\n\t\tlabel: \"Credit card\",\n\t\tshapes: [\n\t\t\t{ t: \"rect\", x: 1, y: 4, width: 22, height: 16, rx: 2 },\n\t\t\t{ t: \"line\", x1: 1, y1: 10, x2: 23, y2: 10 },\n\t\t],\n\t},\n\t{\n\t\tname: \"sparkles\",\n\t\tlabel: \"Sparkles\",\n\t\tshapes: [\n\t\t\t{\n\t\t\t\tt: \"path\",\n\t\t\t\td: \"m12 3-1.9 5.8a2 2 0 0 1-1.3 1.3L3 12l5.8 1.9a2 2 0 0 1 1.3 1.3L12 21l1.9-5.8a2 2 0 0 1 1.3-1.3L21 12l-5.8-1.9a2 2 0 0 1-1.3-1.3z\",\n\t\t\t},\n\t\t],\n\t},\n\t{\n\t\tname: \"bell\",\n\t\tlabel: \"Bell\",\n\t\tshapes: [\n\t\t\t{ t: \"path\", d: \"M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9\" },\n\t\t\t{ t: \"path\", d: \"M10.3 21a1.94 1.94 0 0 0 3.4 0\" },\n\t\t],\n\t},\n\t{\n\t\tname: \"search\",\n\t\tlabel: \"Search\",\n\t\tshapes: [\n\t\t\t{ t: \"circle\", cx: 11, cy: 11, r: 8 },\n\t\t\t{ t: \"path\", d: \"m21 21-4.3-4.3\" },\n\t\t],\n\t},\n\t{\n\t\tname: \"wrench\",\n\t\tlabel: \"Wrench\",\n\t\tshapes: [\n\t\t\t{\n\t\t\t\tt: \"path\",\n\t\t\t\td: \"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z\",\n\t\t\t},\n\t\t],\n\t},\n\t{\n\t\tname: \"shield\",\n\t\tlabel: \"Shield\",\n\t\tshapes: [\n\t\t\t{ t: \"path\", d: \"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z\" },\n\t\t\t{ t: \"path\", d: \"m9 12 2 2 4-4\" },\n\t\t],\n\t},\n\t{\n\t\tname: \"lifebuoy\",\n\t\tlabel: \"Life buoy\",\n\t\tshapes: [\n\t\t\t{ t: \"circle\", cx: 12, cy: 12, r: 10 },\n\t\t\t{ t: \"circle\", cx: 12, cy: 12, r: 4 },\n\t\t\t{ t: \"line\", x1: 4.93, y1: 4.93, x2: 9.17, y2: 9.17 },\n\t\t\t{ t: \"line\", x1: 14.83, y1: 14.83, x2: 19.07, y2: 19.07 },\n\t\t\t{ t: \"line\", x1: 14.83, y1: 9.17, x2: 19.07, y2: 4.93 },\n\t\t\t{ t: \"line\", x1: 4.93, y1: 19.07, x2: 9.17, y2: 14.83 },\n\t\t],\n\t},\n\t{\n\t\tname: \"chart\",\n\t\tlabel: \"Chart\",\n\t\tshapes: [\n\t\t\t{ t: \"line\", x1: 12, y1: 20, x2: 12, y2: 10 },\n\t\t\t{ t: \"line\", x1: 18, y1: 20, x2: 18, y2: 4 },\n\t\t\t{ t: \"line\", x1: 6, y1: 20, x2: 6, y2: 16 },\n\t\t],\n\t},\n\t{\n\t\tname: \"share\",\n\t\tlabel: \"Share\",\n\t\tshapes: [\n\t\t\t{ t: \"circle\", cx: 18, cy: 5, r: 3 },\n\t\t\t{ t: \"circle\", cx: 6, cy: 12, r: 3 },\n\t\t\t{ t: \"circle\", cx: 18, cy: 19, r: 3 },\n\t\t\t{ t: \"line\", x1: 8.59, y1: 13.51, x2: 15.42, y2: 17.49 },\n\t\t\t{ t: \"line\", x1: 15.41, y1: 6.51, x2: 8.59, y2: 10.49 },\n\t\t],\n\t},\n];\n\n/** Lowercase name set for O(1) validation. */\nexport const DOC_NAV_ICON_NAMES: string[] = DOC_NAV_ICONS.map((i) => i.name);\n\nconst DOC_NAV_ICON_MAP: Record<string, DocNavIcon> = Object.fromEntries(\n\tDOC_NAV_ICONS.map((i) => [i.name, i]),\n);\n\n/**\n * Lucide names the imported docs corpus uses, mapped to the nearest icon we ship.\n *\n * The MDX cards were authored against fumadocs, which passes icon names straight to\n * lucide — so a card can ask for `FileCode` or `WifiOff`, which this allowlist has\n * never heard of. Unresolved, they showed as nothing at best: `Box` is three\n * characters, so it fell through to the emoji branch and the word \"Box\" rendered on\n * the card where its icon belonged.\n *\n * These are deliberate approximations, not a lucide port: the goal is a card that\n * looks intentional, and every entry here is a name that actually appears in the\n * corpus. Add to it when a new name shows up rather than widening the emoji branch.\n */\nconst DOC_NAV_ICON_ALIASES: Record<string, string> = {\n\tfilecode: \"file\",\n\tbookopen: \"book\",\n\tdatabase: \"server\",\n\tbot: \"message\",\n\troute: \"share\",\n\trepeat: \"share\",\n\twifioff: \"plug\",\n\thook: \"plug\",\n\tbox: \"puzzle\",\n\tshoppingcart: \"credit-card\",\n\ttype: \"code\",\n\tcalendar: \"bell\",\n\tpause: \"settings\",\n\tflaskconical: \"wrench\",\n};\n\n/** Resolve a named icon (case-insensitive). Returns undefined for unknown names. */\nexport function getDocNavIcon(name: string): DocNavIcon | undefined {\n\tconst key = name.trim().toLowerCase();\n\treturn DOC_NAV_ICON_MAP[key] ?? DOC_NAV_ICON_MAP[DOC_NAV_ICON_ALIASES[key] ?? \"\"];\n}\n","import { type RealtimeEvent, isRealtimeEvent } from \"@helpway/types\";\n\nexport type EventHandler = (event: RealtimeEvent) => void;\n\ninterface WebSocketManagerConfig {\n\tapiUrl: string;\n\tvisitorId: string;\n\twebsiteId: string;\n\t/** Public API key — appended as ?key= on the WS upgrade URL so the server\n\t * can authenticate the widget without relying on custom headers (which the\n\t * browser's native WebSocket API does not support). */\n\tapiKey: string;\n}\n\n/**\n * WebSocket connection manager for ChatRoom Durable Object.\n * Handles connect, disconnect, auto-reconnect with exponential backoff,\n * ping/pong keep-alive, and event dispatching.\n *\n * Ping gating — visibility-aware:\n * Ping doubles as a presence heartbeat on the server (refreshes KV\n * presence key with a 150s TTL). When the tab is hidden we pause the\n * ping so a forgotten background tab naturally drops offline within\n * ~2.5 minutes. The socket itself stays open; only the heartbeat stops.\n */\nexport class WebSocketManager {\n\tprivate ws: WebSocket | null = null;\n\tprivate handlers = new Set<EventHandler>();\n\tprivate config: WebSocketManagerConfig;\n\tprivate reconnectAttempts = 0;\n\tprivate maxReconnectAttempts = 10;\n\tprivate reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n\tprivate pingTimer: ReturnType<typeof setInterval> | null = null;\n\tprivate isDestroyed = false;\n\tprivate visibilityHandler: (() => void) | null = null;\n\n\tconstructor(config: WebSocketManagerConfig) {\n\t\tthis.config = config;\n\t\tthis.setupVisibilityListener();\n\t}\n\n\tprivate setupVisibilityListener(): void {\n\t\tif (typeof document === \"undefined\") return;\n\t\tthis.visibilityHandler = () => {\n\t\t\tif (document.visibilityState === \"hidden\") {\n\t\t\t\t// Tab backgrounded — stop heartbeat so KV TTL drops user offline.\n\t\t\t\tthis.stopPing();\n\t\t\t} else if (this.ws?.readyState === WebSocket.OPEN) {\n\t\t\t\t// Tab visible again — resume heartbeat immediately to restore presence.\n\t\t\t\tthis.startPing();\n\t\t\t\tthis.send({ type: \"ping\" });\n\t\t\t}\n\t\t};\n\t\tdocument.addEventListener(\"visibilitychange\", this.visibilityHandler);\n\t}\n\n\t/** Update connection parameters (call before connect) */\n\tconfigure(params: Partial<WebSocketManagerConfig>): void {\n\t\tObject.assign(this.config, params);\n\t}\n\n\t/** Connect to the ChatRoom Durable Object WebSocket */\n\tconnect(): void {\n\t\tif (this.ws?.readyState === WebSocket.OPEN) return;\n\t\t// Reset destroyed flag — allows reconnect after React StrictMode remount\n\t\tthis.isDestroyed = false;\n\n\t\tconst protocol = this.config.apiUrl.startsWith(\"https\") ? \"wss\" : \"ws\";\n\t\tconst base = this.config.apiUrl.replace(/^https?/, protocol);\n\t\tconst params = new URLSearchParams({\n\t\t\ttype: \"visitor\",\n\t\t\tid: this.config.visitorId,\n\t\t\twebsiteId: this.config.websiteId,\n\t\t\tkey: this.config.apiKey,\n\t\t});\n\n\t\tconst ws = new WebSocket(`${base}/ws?${params}`);\n\n\t\tws.onopen = () => {\n\t\t\tthis.reconnectAttempts = 0;\n\t\t\t// Only start heartbeat if the tab is visible — the visibility\n\t\t\t// listener resumes it automatically when the user returns.\n\t\t\tif (typeof document === \"undefined\" || document.visibilityState === \"visible\") {\n\t\t\t\tthis.startPing();\n\t\t\t}\n\t\t};\n\n\t\tws.onmessage = (event) => {\n\t\t\ttry {\n\t\t\t\tconst data = JSON.parse(event.data as string);\n\t\t\t\tif (data.type === \"pong\") return;\n\t\t\t\tif (isRealtimeEvent(data)) {\n\t\t\t\t\tfor (const handler of this.handlers) {\n\t\t\t\t\t\thandler(data);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Malformed message — ignore\n\t\t\t}\n\t\t};\n\n\t\tws.onclose = () => {\n\t\t\tthis.stopPing();\n\t\t\tthis.ws = null;\n\t\t\tif (!this.isDestroyed) {\n\t\t\t\tthis.scheduleReconnect();\n\t\t\t}\n\t\t};\n\n\t\tws.onerror = () => {\n\t\t\t// onclose will fire after onerror\n\t\t};\n\n\t\tthis.ws = ws;\n\t}\n\n\t/** Disconnect and stop reconnecting */\n\tdisconnect(): void {\n\t\tthis.isDestroyed = true;\n\t\tthis.stopPing();\n\t\tif (this.reconnectTimer) {\n\t\t\tclearTimeout(this.reconnectTimer);\n\t\t\tthis.reconnectTimer = null;\n\t\t}\n\t\tif (this.visibilityHandler && typeof document !== \"undefined\") {\n\t\t\tdocument.removeEventListener(\"visibilitychange\", this.visibilityHandler);\n\t\t\tthis.visibilityHandler = null;\n\t\t}\n\t\tif (this.ws) {\n\t\t\tthis.ws.close(1000, \"Client disconnect\");\n\t\t\tthis.ws = null;\n\t\t}\n\t}\n\n\t/** Send a JSON message through the WebSocket */\n\tsend(data: Record<string, unknown>): void {\n\t\tif (this.ws?.readyState === WebSocket.OPEN) {\n\t\t\tthis.ws.send(JSON.stringify(data));\n\t\t}\n\t}\n\n\t/** Send typing indicator */\n\tsendTyping(conversationId: string, isTyping: boolean): void {\n\t\tthis.send({ type: \"typing\", conversationId, isTyping });\n\t}\n\n\t/** Subscribe to realtime events */\n\tonEvent(handler: EventHandler): () => void {\n\t\tthis.handlers.add(handler);\n\t\treturn () => {\n\t\t\tthis.handlers.delete(handler);\n\t\t};\n\t}\n\n\t/** Check if connected */\n\tget isConnected(): boolean {\n\t\treturn this.ws?.readyState === WebSocket.OPEN;\n\t}\n\n\t// ── Private ──────────────────────────────────────────\n\n\tprivate scheduleReconnect(): void {\n\t\tif (this.reconnectAttempts >= this.maxReconnectAttempts) return;\n\n\t\tconst delay = Math.min(1000 * 2 ** this.reconnectAttempts, 30000);\n\t\tthis.reconnectAttempts++;\n\n\t\tthis.reconnectTimer = setTimeout(() => {\n\t\t\tthis.connect();\n\t\t}, delay);\n\t}\n\n\tprivate startPing(): void {\n\t\tthis.stopPing();\n\t\tthis.pingTimer = setInterval(() => {\n\t\t\tthis.send({ type: \"ping\" });\n\t\t}, 25000);\n\t}\n\n\tprivate stopPing(): void {\n\t\tif (this.pingTimer) {\n\t\t\tclearInterval(this.pingTimer);\n\t\t\tthis.pingTimer = null;\n\t\t}\n\t}\n}\n","import { WsEventType } from \"@helpway/types\";\nimport type { PublicVisitor, RealtimeEvent, TimelineItem } from \"@helpway/types\";\nimport { createStore } from \"zustand/vanilla\";\n\n// ── Agent Config (from bootstrap) ────────────────────────\n\nexport interface WidgetContentTab {\n\tid: string;\n\tlabel: string;\n\ticon: string;\n\tmodelSlug: string;\n\tdisplay?: {\n\t\tsubtitleField?: string;\n\t\tbadgeField?: string;\n\t\timageField?: string;\n\t\tdateField?: string;\n\t};\n\ttabType?: \"flat\" | \"grouped\";\n\titemsModelSlug?: string;\n\tgroupField?: string;\n\t/** Marks this tab as the \"What's New\" / announcements source.\n\t * Only one tab should have this flag — the first match wins. */\n\tisAnnouncements?: boolean;\n}\n\nexport interface AgentConfig {\n\tid: string;\n\tname: string;\n\tavatarUrl: string | null;\n\tavatarPreset: string | null;\n\twelcomeMessage: string | null;\n\tsubtitleText: string | null;\n\tbrandColor: string;\n\twidgetPosition: \"bottom-right\" | \"bottom-left\";\n\tlauncherStyle: \"icon\" | \"bubble\" | \"help\";\n\t/** Custom image rendered inside the launcher bubble. NULL → fall back\n\t * to the chat-header chain (avatarUrl → avatarPreset → website logo). */\n\tlauncherIconUrl: string | null;\n\tbubbleStyle: \"rounded\" | \"square\" | \"pill\";\n\t/** Show/hide Messages tab in widget footer */\n\tshowMessagesTab: boolean;\n\t/** Require visitor to provide email before starting a conversation */\n\trequireVisitorEmail: boolean;\n\t/** Dynamic content tabs from Better i18n Content CMS integration */\n\tcontentTabs: WidgetContentTab[];\n}\n\n// ── Content Cache ──────────────────────────────────────────\n\nexport interface ContentCacheEntry {\n\tdata: unknown;\n\tts: number;\n}\n\nexport const CONTENT_CACHE_TTL = 5 * 60 * 1000; // 5 minutes\n\n// ── State Shape ──────────────────────────────────────────\n\nexport interface WidgetState {\n\t// Connection\n\tisReady: boolean;\n\tisConnecting: boolean;\n\n\t// Identity\n\tvisitor: PublicVisitor | null;\n\twebsite: { id: string; name: string; domain: string | null; logoUrl: string | null } | null;\n\n\t// Agent config (from bootstrap)\n\tagentConfig: AgentConfig | null;\n\n\t// Conversations\n\tconversations: ConversationSummary[];\n\tactiveConversationId: string | null;\n\n\t// Messages per conversation\n\tmessages: Map<string, TimelineItem[]>;\n\n\t// Presence\n\ttypingUsers: Map<string, boolean>; // conversationId → someone is typing\n\taiProcessing: Map<string, boolean>; // conversationId → AI is processing\n\tstreamingText: Map<string, string>; // conversationId → accumulated streamed text\n\n\t// UI state\n\tisOpen: boolean;\n\tisDismissed: boolean;\n\tview: \"home\" | \"conversation\" | \"new\";\n\n\t// Incoming message preview (shown when widget is closed)\n\tincomingPreview: {\n\t\ttext: string;\n\t\tconversationId: string;\n\t\ttimestamp: number;\n\t\t/** Who sent it. A human reply used to surface under the AI's name\n\t\t * because the card only ever read agentConfig — the event carries\n\t\t * userName/userImage, they were simply dropped here. Null for the AI,\n\t\t * which is the case the agent name is actually right for. */\n\t\tsenderName?: string | null;\n\t\tsenderImage?: string | null;\n\t\tmessages?: Array<{ text: string }>;\n\t\tquickReplies?: {\n\t\t\tstepId: string;\n\t\t\tprompt: string | null;\n\t\t\toptions: Array<{ id: string; label: string }>;\n\t\t};\n\t} | null;\n\n\t// Announcement previews (shown when widget is closed and unseen content exists)\n\t// Multiple previews stack when several isAnnouncements tabs have new content.\n\tannouncementPreviews: Array<{\n\t\ttitle: string;\n\t\tbody: string | null;\n\t\tslug: string;\n\t\ttabId: string;\n\t\tbadge: string | null;\n\t}>;\n\n\t// Number of unseen announcement entries (drives launcher dot + tab badge)\n\tunseenAnnouncementCount: number;\n\n\t// Pre-filled text for new conversation (set via global API)\n\tnewConversationPrefill: string | null;\n\n\t// Pending content-detail open intent — when set, DefaultWidget\n\t// navigates to the matching content tab + entry detail on the next\n\t// render and clears it. Used so consumers rendering anchored\n\t// announcement previews (or any external trigger) can deep-link a\n\t// visitor straight into a specific entry instead of dropping them\n\t// on the home surface. The launcher's onOpen does this internally;\n\t// this field makes the same navigation reachable from outside\n\t// DefaultWidget's local state.\n\tpendingContentDetail: { slug: string; tabId: string } | null;\n\n\t// Content cache (survives tab switches — keyed by request params)\n\tcontentCache: Map<string, ContentCacheEntry>;\n}\n\nexport interface ConversationSummary {\n\tid: string;\n\ttitle: string | null;\n\tstatus: string;\n\tlastMessageText: string | null;\n\tlastMessageAt: string | null;\n\tlastMessageSenderType: string | null;\n\tlastMessageSenderName: string | null;\n\tlastMessageSenderImage: string | null;\n\t/** Display-only fields for the assigned support user. NULL when no\n\t * human is assigned (AI agent is handling). UserId is intentionally\n\t * not exposed — only what the chat header needs to render. */\n\tassigneeName: string | null;\n\tassigneeImage: string | null;\n\tunreadCount: number;\n}\n\n// ── Actions ──────────────────────────────────────────────\n\nexport interface WidgetActions {\n\t// Lifecycle\n\tsetReady(\n\t\tvisitor: WidgetState[\"visitor\"],\n\t\twebsite: WidgetState[\"website\"],\n\t\tagentConfig?: AgentConfig | null,\n\t): void;\n\tsetConnecting(connecting: boolean): void;\n\n\t// Conversations\n\tsetConversations(conversations: ConversationSummary[]): void;\n\taddConversation(conversation: ConversationSummary): void;\n\tsetActiveConversation(id: string | null): void;\n\n\t// Messages\n\tsetMessages(conversationId: string, items: TimelineItem[]): void;\n\taddMessage(conversationId: string, item: TimelineItem): void;\n\t/**\n\t * Replace a message by ID (used by optimistic send — swaps\n\t * temp `optimistic-*` id for the server-confirmed item).\n\t */\n\treplaceMessage(conversationId: string, oldId: string, item: TimelineItem): void;\n\t/** Remove a message by ID (used for optimistic rollback on send failure) */\n\tremoveMessage(conversationId: string, id: string): void;\n\t/**\n\t * Move an optimistic conversation to its server-assigned ID.\n\t * Copies messages + updates activeConversationId + conversations list.\n\t */\n\tremapConversationId(oldId: string, newId: string): void;\n\n\t// Presence\n\tsetTyping(conversationId: string, isTyping: boolean): void;\n\tsetAiProcessing(conversationId: string, processing: boolean): void;\n\tappendStreamChunk(conversationId: string, delta: string, done: boolean): void;\n\n\t// Identity\n\tupdateVisitorContact(contact: { id: string; name: string | null; email: string | null }): void;\n\n\t// Unread\n\tclearUnread(conversationId: string): void;\n\n\t// UI\n\tsetOpen(open: boolean): void;\n\tsetDismissed(dismissed: boolean): void;\n\tsetView(view: WidgetState[\"view\"]): void;\n\tsetNewConversationPrefill(text: string | null): void;\n\t/** Schedule a deep-link into a specific content entry's detail\n\t * view. DefaultWidget consumes it on the next render — call\n\t * `setOpen(true)` alongside to reveal the panel. Pass `null` to\n\t * clear (DefaultWidget does this automatically once it\n\t * navigates). */\n\tsetPendingContentDetail(value: { slug: string; tabId: string } | null): void;\n\tdismissPreview(): void;\n\n\t// Announcements\n\tsetAnnouncementPreview(preview: WidgetState[\"announcementPreviews\"][number]): void;\n\tdismissAnnouncementPreview(slug?: string): void;\n\tsetUnseenAnnouncementCount(count: number): void;\n\n\t// Content cache\n\tsetContentCache(key: string, data: unknown): void;\n\n\t// Realtime\n\thandleRealtimeEvent(event: RealtimeEvent): void;\n}\n\nexport type WidgetStore = WidgetState & WidgetActions;\n\n// ── Store Factory ────────────────────────────────────────\n\n// Proactive incoming-message previews must survive a page reload —\n// otherwise an agent/AI ping vanishes the moment the visitor refreshes\n// (it lived only in the in-memory store). Persist the single\n// `incomingPreview` field to localStorage; the existing clear paths\n// (setOpen-when-open, dismissPreview) flow through the subscription\n// below, so closing or replying still wipes it. Per-browser only\n// (localStorage) — not cross-device, fine for a transient affordance.\nconst PREVIEW_STORAGE_KEY = \"helpway:incoming-preview\";\n\nfunction loadPersistedPreview(): WidgetStore[\"incomingPreview\"] {\n\tif (typeof window === \"undefined\") return null;\n\ttry {\n\t\tconst raw = window.localStorage.getItem(PREVIEW_STORAGE_KEY);\n\t\treturn raw ? (JSON.parse(raw) as WidgetStore[\"incomingPreview\"]) : null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction persistPreview(preview: WidgetStore[\"incomingPreview\"]): void {\n\tif (typeof window === \"undefined\") return;\n\ttry {\n\t\tif (preview) {\n\t\t\twindow.localStorage.setItem(PREVIEW_STORAGE_KEY, JSON.stringify(preview));\n\t\t} else {\n\t\t\twindow.localStorage.removeItem(PREVIEW_STORAGE_KEY);\n\t\t}\n\t} catch {\n\t\t// quota / privacy-mode / SSR — non-fatal, preview just won't persist\n\t}\n}\n\n/**\n * The escalation/join event carries its payload as JSON in the item's text:\n * `{action:\"joined\", name, image}` when a specific person took the thread. The\n * unassigned case is a plain sentence (\"Connecting you with a team member…\"), and\n * that is not a handoff to anyone in particular — so only the JSON shape counts.\n */\nfunction parseJoinEvent(text: string): { name: string | null; image: string | null } | null {\n\tif (!text.startsWith(\"{\")) return null;\n\ttry {\n\t\tconst parsed = JSON.parse(text) as {\n\t\t\taction?: string;\n\t\t\tname?: string | null;\n\t\t\timage?: string | null;\n\t\t};\n\t\tif (parsed.action !== \"joined\") return null;\n\t\treturn { name: parsed.name ?? null, image: parsed.image ?? null };\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Who, if anyone, has taken this thread — read off the timeline rather than waited\n * for as a separate signal.\n *\n * The obvious place for this was the realtime reducer, and it does not work there:\n * the join event reaches the widget through the timeline refetch that follows the\n * AI's turn, not through a `timelineItemCreated` frame, so a reducer branch never\n * fires. Both paths end in the message list, so the message list is where the\n * handoff is learned. Last join wins — reassignment is a later join.\n */\nfunction latestAssignee(\n\titems: readonly { type?: string | null; text?: string | null }[],\n): { name: string | null; image: string | null } | null {\n\tfor (let i = items.length - 1; i >= 0; i--) {\n\t\tconst item = items[i];\n\t\tif (item?.type !== \"event\" || !item.text) continue;\n\t\tconst joined = parseJoinEvent(item.text);\n\t\tif (joined) return joined;\n\t}\n\treturn null;\n}\n\nexport function createWidgetStore() {\n\tconst store = createStore<WidgetStore>((set, get) => ({\n\t\t// Initial state\n\t\tisReady: false,\n\t\tisConnecting: true,\n\t\tvisitor: null,\n\t\twebsite: null,\n\t\tagentConfig: null,\n\t\tconversations: [],\n\t\tactiveConversationId: null,\n\t\tmessages: new Map(),\n\t\ttypingUsers: new Map(),\n\t\taiProcessing: new Map(),\n\t\tstreamingText: new Map(),\n\t\tisOpen: false,\n\t\tisDismissed: false,\n\t\tview: \"home\",\n\t\tincomingPreview: loadPersistedPreview(),\n\t\tannouncementPreviews: [],\n\t\tunseenAnnouncementCount: 0,\n\t\tnewConversationPrefill: null,\n\t\tpendingContentDetail: null,\n\t\tcontentCache: new Map(),\n\n\t\t// ── Lifecycle ────────────────────────────────────\n\n\t\tsetReady(visitor, website, agentConfig) {\n\t\t\tset({\n\t\t\t\tisReady: true,\n\t\t\t\tisConnecting: false,\n\t\t\t\tvisitor,\n\t\t\t\twebsite,\n\t\t\t\tagentConfig: agentConfig ?? null,\n\t\t\t});\n\t\t},\n\n\t\tsetConnecting(connecting) {\n\t\t\tset({ isConnecting: connecting });\n\t\t},\n\n\t\t// ── Conversations ────────────────────────────────\n\n\t\tsetConversations(conversations) {\n\t\t\tset({ conversations });\n\t\t},\n\n\t\taddConversation(conversation) {\n\t\t\tset((state) => ({\n\t\t\t\tconversations: [conversation, ...state.conversations],\n\t\t\t}));\n\t\t},\n\n\t\tsetActiveConversation(id) {\n\t\t\tset({ activeConversationId: id, view: id ? \"conversation\" : \"home\" });\n\t\t},\n\n\t\t// ── Messages ─────────────────────────────────────\n\n\t\tsetMessages(conversationId, items) {\n\t\t\tconst joined = latestAssignee(items);\n\t\t\tset((state) => {\n\t\t\t\tconst next = new Map(state.messages);\n\t\t\t\tnext.set(conversationId, items);\n\t\t\t\treturn {\n\t\t\t\t\tmessages: next,\n\t\t\t\t\t/* Hydrating a thread that already contains a handoff means the header\n\t\t\t\t\t should open as that person, not as the AI who answered before them. */\n\t\t\t\t\t...(joined\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tconversations: state.conversations.map((c) =>\n\t\t\t\t\t\t\t\t\tc.id === conversationId\n\t\t\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\t\t\t...c,\n\t\t\t\t\t\t\t\t\t\t\t\tassigneeName: joined.name ?? c.assigneeName,\n\t\t\t\t\t\t\t\t\t\t\t\tassigneeImage: joined.image ?? c.assigneeImage,\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t: c,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: {}),\n\t\t\t\t};\n\t\t\t});\n\t\t},\n\n\t\taddMessage(conversationId, item) {\n\t\t\tconst joined = item.type === \"event\" && item.text ? parseJoinEvent(item.text) : null;\n\t\t\tif (joined) {\n\t\t\t\tset((state) => ({\n\t\t\t\t\tconversations: state.conversations.map((c) =>\n\t\t\t\t\t\tc.id === conversationId\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t...c,\n\t\t\t\t\t\t\t\t\tassigneeName: joined.name ?? c.assigneeName,\n\t\t\t\t\t\t\t\t\tassigneeImage: joined.image ?? c.assigneeImage,\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: c,\n\t\t\t\t\t),\n\t\t\t\t}));\n\t\t\t}\n\t\t\tset((state) => {\n\t\t\t\tconst next = new Map(state.messages);\n\t\t\t\tconst existing = next.get(conversationId) ?? [];\n\t\t\t\t// Deduplicate by ID — WS echoes may arrive twice (once from broadcast,\n\t\t\t\t// once from the mutation response path).\n\t\t\t\tif (existing.some((m) => m.id === item.id)) return state;\n\t\t\t\t/* The visitor's own message, echoed back under its server id while the\n\t\t\t\t optimistic copy is still on screen. Appending it and letting\n\t\t\t\t replaceMessage drop the optimistic one later costs a REMOUNT: the\n\t\t\t\t node the visitor is looking at is destroyed and a new one takes its\n\t\t\t\t place ~180ms after, so the appear animation runs a second time and\n\t\t\t\t the bubble visibly flashes. Swapping in place keeps _stableKey, so\n\t\t\t\t React reuses the same DOM node and nothing replays. */\n\t\t\t\tconst echoIndex = item.visitorId\n\t\t\t\t\t? existing.findIndex(\n\t\t\t\t\t\t\t(m) => !!m.visitorId && m.text === item.text && m.id.startsWith(\"optimistic-\"),\n\t\t\t\t\t\t)\n\t\t\t\t\t: -1;\n\t\t\t\tif (echoIndex >= 0) {\n\t\t\t\t\tconst optimistic = existing[echoIndex] as TimelineItem & { _stableKey?: string };\n\t\t\t\t\tconst merged = [...existing];\n\t\t\t\t\tmerged[echoIndex] = {\n\t\t\t\t\t\t...item,\n\t\t\t\t\t\t_stableKey: optimistic._stableKey ?? optimistic.id,\n\t\t\t\t\t} as TimelineItem;\n\t\t\t\t\tnext.set(conversationId, merged);\n\t\t\t\t\treturn { messages: next };\n\t\t\t\t}\n\t\t\t\t// Agent welcome messages are always the opener of a conversation.\n\t\t\t\t// If the first existing item is a visitor message, prepend the welcome\n\t\t\t\t// so the greeting stays above — don't rely on createdAt (client clock\n\t\t\t\t// vs server clock drift can flip the order).\n\t\t\t\tconst isAgentWelcome = !!item.aiAgentId && !item.visitorId;\n\t\t\t\tconst firstIsVisitor = existing[0]?.visitorId != null;\n\t\t\t\tif (isAgentWelcome && firstIsVisitor) {\n\t\t\t\t\tnext.set(conversationId, [item, ...existing]);\n\t\t\t\t\treturn { messages: next };\n\t\t\t\t}\n\t\t\t\t// General case: insert chronologically. Sort only when the newcomer\n\t\t\t\t// is older than the current tail (rare — WS reorders).\n\t\t\t\tconst last = existing[existing.length - 1];\n\t\t\t\tconst isOutOfOrder = last && item.createdAt < last.createdAt;\n\t\t\t\tconst merged = [...existing, item];\n\t\t\t\tif (isOutOfOrder) {\n\t\t\t\t\tmerged.sort((a, b) => a.createdAt.localeCompare(b.createdAt));\n\t\t\t\t}\n\t\t\t\tnext.set(conversationId, merged);\n\t\t\t\treturn { messages: next };\n\t\t\t});\n\t\t},\n\n\t\treplaceMessage(conversationId, oldId, item) {\n\t\t\tset((state) => {\n\t\t\t\tconst next = new Map(state.messages);\n\t\t\t\tconst existing = next.get(conversationId) ?? [];\n\t\t\t\t// Race with WS echo: if the real item already landed, just drop the optimistic\n\t\t\t\tif (existing.some((m) => m.id === item.id && m.id !== oldId)) {\n\t\t\t\t\tnext.set(\n\t\t\t\t\t\tconversationId,\n\t\t\t\t\t\texisting.filter((m) => m.id !== oldId),\n\t\t\t\t\t);\n\t\t\t\t\treturn { messages: next };\n\t\t\t\t}\n\t\t\t\t// Preserve the optimistic ID as _stableKey so the React key\n\t\t\t\t// stays constant across the optimistic → real ID swap.\n\t\t\t\tnext.set(\n\t\t\t\t\tconversationId,\n\t\t\t\t\texisting.map((m) =>\n\t\t\t\t\t\tm.id === oldId\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t...item,\n\t\t\t\t\t\t\t\t\t_stableKey: (m as unknown as { _stableKey?: string })._stableKey ?? oldId,\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: m,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\treturn { messages: next };\n\t\t\t});\n\t\t},\n\n\t\tremoveMessage(conversationId, id) {\n\t\t\tset((state) => {\n\t\t\t\tconst next = new Map(state.messages);\n\t\t\t\tconst existing = next.get(conversationId);\n\t\t\t\tif (!existing) return state;\n\t\t\t\tnext.set(\n\t\t\t\t\tconversationId,\n\t\t\t\t\texisting.filter((m) => m.id !== id),\n\t\t\t\t);\n\t\t\t\treturn { messages: next };\n\t\t\t});\n\t\t},\n\n\t\tremapConversationId(oldId, newId) {\n\t\t\tset((state) => {\n\t\t\t\t// Merge messages from tempId + newId — WS echo may have inserted\n\t\t\t\t// items under the real id BEFORE the createConversation mutation\n\t\t\t\t// resolved. Dedupe by id so we don't lose the WS-delivered items.\n\t\t\t\tconst nextMessages = new Map(state.messages);\n\t\t\t\tconst tempItems = nextMessages.get(oldId) ?? [];\n\t\t\t\tconst existingItems = nextMessages.get(newId) ?? [];\n\t\t\t\tconst tempRewritten = tempItems.map((m) => ({ ...m, conversationId: newId }));\n\t\t\t\tconst isAgentMsg = (m: TimelineItem) => !!m.aiAgentId && !m.visitorId && !m.userId;\n\t\t\t\t// Prefer the seed welcome that came in via the temp conversation.\n\t\t\t\t// Keeping its DOM node stable is the whole point of openNewConversation\n\t\t\t\t// seeding; if we let the server-welcome (different id, same text)\n\t\t\t\t// take its slot, React unmounts the seed bubble and the animation\n\t\t\t\t// replays — exactly the \"git-gel\" the seed exists to prevent.\n\t\t\t\tconst seen = new Set<string>();\n\t\t\t\tconst merged: TimelineItem[] = [];\n\t\t\t\tlet keptAgentWelcome = false;\n\t\t\t\tfor (const m of tempRewritten) {\n\t\t\t\t\tif (seen.has(m.id)) continue;\n\t\t\t\t\tseen.add(m.id);\n\t\t\t\t\tmerged.push(m);\n\t\t\t\t\tif (isAgentMsg(m) && merged.length === 1) keptAgentWelcome = true;\n\t\t\t\t}\n\t\t\t\t// The server's welcome echo is the agent item that predates the\n\t\t\t\t// visitor's first server item (the API stamps it visitorTs - 1ms).\n\t\t\t\t// WS delivery is ordered, so if a genuine AI reply made it into\n\t\t\t\t// existingItems, the visitor item did too — when no visitor item\n\t\t\t\t// is present, the only agent item that can have arrived is the\n\t\t\t\t// welcome. Graft its identity onto the seed bubble (same DOM node\n\t\t\t\t// via _stableKey, real ULID for future dedup) instead of dropping\n\t\t\t\t// it; later agent items are genuine AI replies and MUST be kept.\n\t\t\t\tconst serverVisitorTs = existingItems.find((x) => x.visitorId)?.createdAt;\n\t\t\t\t/* The visitor's own message needs the same graft the welcome gets.\n\t\t\t\t It was sent optimistically under the temp conversation with a\n\t\t\t\t client id, and the server echoes it back under a real ULID — two\n\t\t\t\t different ids, so the id-only dedupe above keeps both and the\n\t\t\t\t visitor watches their own bubble render twice. Matched on text and\n\t\t\t\t claimed once, so sending the same words twice still shows twice. */\n\t\t\t\tconst isVisitorMsg = (m: TimelineItem) => !!m.visitorId && !m.aiAgentId && !m.userId;\n\t\t\t\tconst pendingVisitor = new Map<string, number>();\n\t\t\t\tmerged.forEach((m, i) => {\n\t\t\t\t\tif (isVisitorMsg(m) && typeof m.text === \"string\" && !pendingVisitor.has(m.text)) {\n\t\t\t\t\t\tpendingVisitor.set(m.text, i);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tlet graftedWelcome = false;\n\t\t\t\tfor (const m of existingItems) {\n\t\t\t\t\tif (seen.has(m.id)) continue;\n\t\t\t\t\tif (isVisitorMsg(m) && typeof m.text === \"string\" && pendingVisitor.has(m.text)) {\n\t\t\t\t\t\tconst idx = pendingVisitor.get(m.text) as number;\n\t\t\t\t\t\tpendingVisitor.delete(m.text);\n\t\t\t\t\t\tconst optimistic = merged[idx];\n\t\t\t\t\t\tmerged[idx] = {\n\t\t\t\t\t\t\t...m,\n\t\t\t\t\t\t\t_stableKey: optimistic\n\t\t\t\t\t\t\t\t? ((optimistic as unknown as { _stableKey?: string })._stableKey ?? optimistic.id)\n\t\t\t\t\t\t\t\t: m.id,\n\t\t\t\t\t\t} as TimelineItem;\n\t\t\t\t\t\tseen.add(m.id);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tconst isWelcomeEcho =\n\t\t\t\t\t\tisAgentMsg(m) &&\n\t\t\t\t\t\tkeptAgentWelcome &&\n\t\t\t\t\t\t!graftedWelcome &&\n\t\t\t\t\t\t(!serverVisitorTs || m.createdAt <= serverVisitorTs);\n\t\t\t\t\tif (isWelcomeEcho) {\n\t\t\t\t\t\tconst seed = merged[0];\n\t\t\t\t\t\tmerged[0] = {\n\t\t\t\t\t\t\t...m,\n\t\t\t\t\t\t\t_stableKey: seed\n\t\t\t\t\t\t\t\t? ((seed as unknown as { _stableKey?: string })._stableKey ?? seed.id)\n\t\t\t\t\t\t\t\t: m.id,\n\t\t\t\t\t\t} as TimelineItem;\n\t\t\t\t\t\tseen.add(m.id);\n\t\t\t\t\t\tgraftedWelcome = true;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tseen.add(m.id);\n\t\t\t\t\tmerged.push(m);\n\t\t\t\t}\n\t\t\t\tnextMessages.delete(oldId);\n\t\t\t\tnextMessages.set(newId, merged);\n\n\t\t\t\t// Dedupe conversation list — WS conversationCreated may have\n\t\t\t\t// prepended newId already; in that case drop the temp entry.\n\t\t\t\tconst hasNewId = state.conversations.some((c) => c.id === newId);\n\t\t\t\tconst conversations = hasNewId\n\t\t\t\t\t? state.conversations.filter((c) => c.id !== oldId)\n\t\t\t\t\t: state.conversations.map((c) => (c.id === oldId ? { ...c, id: newId } : c));\n\n\t\t\t\treturn {\n\t\t\t\t\tmessages: nextMessages,\n\t\t\t\t\tconversations,\n\t\t\t\t\tactiveConversationId:\n\t\t\t\t\t\tstate.activeConversationId === oldId ? newId : state.activeConversationId,\n\t\t\t\t};\n\t\t\t});\n\t\t},\n\n\t\t// ── Presence ─────────────────────────────────────\n\n\t\tsetTyping(conversationId, isTyping) {\n\t\t\tset((state) => {\n\t\t\t\tconst next = new Map(state.typingUsers);\n\t\t\t\tnext.set(conversationId, isTyping);\n\t\t\t\treturn { typingUsers: next };\n\t\t\t});\n\t\t},\n\n\t\tsetAiProcessing(conversationId, processing) {\n\t\t\tset((state) => {\n\t\t\t\tconst next = new Map(state.aiProcessing);\n\t\t\t\tnext.set(conversationId, processing);\n\t\t\t\treturn { aiProcessing: next };\n\t\t\t});\n\t\t},\n\n\t\tappendStreamChunk(conversationId, delta, done) {\n\t\t\tset((state) => {\n\t\t\t\tconst next = new Map(state.streamingText);\n\t\t\t\tconst prev = next.get(conversationId) ?? \"\";\n\t\t\t\tif (done) {\n\t\t\t\t\tnext.delete(conversationId);\n\t\t\t\t} else {\n\t\t\t\t\tnext.set(conversationId, prev + delta);\n\t\t\t\t}\n\t\t\t\treturn { streamingText: next };\n\t\t\t});\n\t\t},\n\n\t\t// ── Identity ─────────────────────────────────────\n\n\t\tupdateVisitorContact(contact) {\n\t\t\tset((state) => ({\n\t\t\t\tvisitor: state.visitor ? { ...state.visitor, contact } : state.visitor,\n\t\t\t}));\n\t\t},\n\n\t\t// ── Unread ───────────────────────────────────────\n\n\t\tclearUnread(conversationId) {\n\t\t\tset((s) => ({\n\t\t\t\tconversations: s.conversations.map((c) =>\n\t\t\t\t\tc.id === conversationId ? { ...c, unreadCount: 0 } : c,\n\t\t\t\t),\n\t\t\t}));\n\t\t},\n\n\t\t// ── UI ───────────────────────────────────────────\n\n\t\tsetOpen(open) {\n\t\t\tset((s) => ({\n\t\t\t\tisOpen: open,\n\t\t\t\tincomingPreview: open ? null : s.incomingPreview,\n\t\t\t\tannouncementPreviews: open ? [] : s.announcementPreviews,\n\t\t\t}));\n\t\t},\n\n\t\tsetPendingContentDetail(value) {\n\t\t\tset({ pendingContentDetail: value });\n\t\t},\n\n\t\tsetDismissed(dismissed) {\n\t\t\tset({ isDismissed: dismissed });\n\t\t},\n\n\t\tsetView(view) {\n\t\t\tset({ view });\n\t\t},\n\n\t\tsetNewConversationPrefill(text) {\n\t\t\tset({ newConversationPrefill: text });\n\t\t},\n\n\t\tdismissPreview() {\n\t\t\tset({ incomingPreview: null });\n\t\t},\n\n\t\t// ── Announcements ────────────────────────────────\n\n\t\tsetAnnouncementPreview(preview) {\n\t\t\tset((s) => ({\n\t\t\t\tannouncementPreviews: [\n\t\t\t\t\t...s.announcementPreviews.filter((p) => p.tabId !== preview.tabId),\n\t\t\t\t\tpreview,\n\t\t\t\t],\n\t\t\t}));\n\t\t},\n\n\t\tdismissAnnouncementPreview(slug) {\n\t\t\tif (slug) {\n\t\t\t\tset((s) => ({\n\t\t\t\t\tannouncementPreviews: s.announcementPreviews.filter((p) => p.slug !== slug),\n\t\t\t\t}));\n\t\t\t} else {\n\t\t\t\tset({ announcementPreviews: [] });\n\t\t\t}\n\t\t},\n\n\t\tsetUnseenAnnouncementCount(count) {\n\t\t\tset({ unseenAnnouncementCount: count });\n\t\t},\n\n\t\t// ── Content Cache ────────────────────────────────\n\n\t\tsetContentCache(key, data) {\n\t\t\tget().contentCache.set(key, { data, ts: Date.now() });\n\t\t},\n\n\t\t// ── Realtime Event Handler ───────────────────────\n\n\t\thandleRealtimeEvent(event) {\n\t\t\tconst state = get();\n\n\t\t\tswitch (event.type) {\n\t\t\t\tcase WsEventType.TimelineItemCreated: {\n\t\t\t\t\t// Only add public messages (widget shouldn't see private notes)\n\t\t\t\t\tif (event.item.visibility === \"public\") {\n\t\t\t\t\t\t// When the widget seeded a local welcome bubble (openNewConversation)\n\t\t\t\t\t\t// the server's createConversation path ALSO emits its own welcome\n\t\t\t\t\t\t// timeline item. The echo usually lands AFTER the optimistic visitor\n\t\t\t\t\t\t// message is already in the list, so we can't gate on list length.\n\t\t\t\t\t\t// The reliable discriminator is the timestamp: the API stamps the\n\t\t\t\t\t\t// welcome 1ms BEFORE the visitor's first message, while a genuine\n\t\t\t\t\t\t// AI reply is always stamped after it — and by the time the seed\n\t\t\t\t\t\t// exists under the server conversation id, the visitor item has\n\t\t\t\t\t\t// already been swapped to its server-stamped twin, so both sides\n\t\t\t\t\t\t// of the comparison come from the server clock (drift-safe).\n\t\t\t\t\t\tconst isAgentAuthored =\n\t\t\t\t\t\t\t!!event.item.aiAgentId && !event.item.visitorId && !event.item.userId;\n\t\t\t\t\t\tconst existing = state.messages.get(event.conversationId);\n\t\t\t\t\t\tconst seedId = existing?.[0]?.id;\n\t\t\t\t\t\tconst hasSeedWelcome = typeof seedId === \"string\" && seedId.startsWith(\"seed-welcome-\");\n\t\t\t\t\t\tif (isAgentAuthored && hasSeedWelcome) {\n\t\t\t\t\t\t\tconst firstVisitorTs = existing?.find((m) => m.visitorId)?.createdAt;\n\t\t\t\t\t\t\tconst isWelcomeEcho = !firstVisitorTs || event.item.createdAt <= firstVisitorTs;\n\t\t\t\t\t\t\tif (isWelcomeEcho) {\n\t\t\t\t\t\t\t\t// Adopt the server identity onto the seed bubble instead of\n\t\t\t\t\t\t\t\t// dropping the event — replaceMessage keeps the seed id as\n\t\t\t\t\t\t\t\t// _stableKey (no remount/flash) and future hydrations dedupe\n\t\t\t\t\t\t\t\t// against the real ULID instead of the synthetic seed id.\n\t\t\t\t\t\t\t\tstate.replaceMessage(event.conversationId, seedId, event.item);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstate.addMessage(event.conversationId, event.item);\n\t\t\t\t\t}\n\t\t\t\t\t// Clear typing/processing indicators as soon as the AI message arrives\n\t\t\t\t\t// (don't wait for aiProcessingCompleted which comes later after auto-title etc.)\n\t\t\t\t\tif (event.item.aiAgentId) {\n\t\t\t\t\t\tstate.setAiProcessing(event.conversationId, false);\n\t\t\t\t\t\tstate.setTyping(event.conversationId, false);\n\t\t\t\t\t}\n\t\t\t\t\t// Update conversation preview + unread count\n\t\t\t\t\tif (event.item.type === \"message\" && event.item.text) {\n\t\t\t\t\t\tconst isIncoming = !event.item.visitorId; // team or AI message\n\t\t\t\t\t\tconst currentState = get();\n\t\t\t\t\t\tconst isViewingThis =\n\t\t\t\t\t\t\tcurrentState.isOpen && currentState.activeConversationId === event.conversationId;\n\n\t\t\t\t\t\tset((s) => ({\n\t\t\t\t\t\t\tconversations: s.conversations.map((c) =>\n\t\t\t\t\t\t\t\tc.id === event.conversationId\n\t\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\t\t...c,\n\t\t\t\t\t\t\t\t\t\t\tlastMessageText: event.item.text,\n\t\t\t\t\t\t\t\t\t\t\tlastMessageAt: event.item.createdAt,\n\t\t\t\t\t\t\t\t\t\t\t// Increment unread if incoming and not actively viewing\n\t\t\t\t\t\t\t\t\t\t\t...(isIncoming && !isViewingThis ? { unreadCount: c.unreadCount + 1 } : {}),\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t: c,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t// Show preview bubble if widget is closed and message is incoming\n\t\t\t\t\t\t\t...(isIncoming && !currentState.isOpen\n\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\tincomingPreview: {\n\t\t\t\t\t\t\t\t\t\t\ttext: event.item.text ?? \"\",\n\t\t\t\t\t\t\t\t\t\t\tconversationId: event.conversationId,\n\t\t\t\t\t\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\t\t\t\t\t\tsenderName:\n\t\t\t\t\t\t\t\t\t\t\t\t(event.item as { userName?: string | null }).userName ?? null,\n\t\t\t\t\t\t\t\t\t\t\tsenderImage:\n\t\t\t\t\t\t\t\t\t\t\t\t(event.item as { userImage?: string | null }).userImage ?? null,\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t}));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase WsEventType.ConversationUpdated: {\n\t\t\t\t\tset((s) => ({\n\t\t\t\t\t\tconversations: s.conversations.map((c) =>\n\t\t\t\t\t\t\tc.id === event.conversationId ? { ...c, ...event.updates } : c,\n\t\t\t\t\t\t),\n\t\t\t\t\t}));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase WsEventType.ConversationTyping: {\n\t\t\t\t\t// Only show typing for non-visitor (team/AI typing)\n\t\t\t\t\tif (!event.visitorId) {\n\t\t\t\t\t\tstate.setTyping(event.conversationId, event.isTyping);\n\t\t\t\t\t\t// Auto-clear after 5 seconds\n\t\t\t\t\t\tif (event.isTyping) {\n\t\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\t\tstate.setTyping(event.conversationId, false);\n\t\t\t\t\t\t\t}, 5000);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase WsEventType.AiProcessingProgress: {\n\t\t\t\t\t// Track AI processing separately for distinct UI indicator\n\t\t\t\t\tstate.setAiProcessing(event.conversationId, true);\n\t\t\t\t\tstate.setTyping(event.conversationId, true);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase WsEventType.AiProcessingCompleted: {\n\t\t\t\t\tstate.setAiProcessing(event.conversationId, false);\n\t\t\t\t\tstate.setTyping(event.conversationId, false);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase WsEventType.AiStreamChunk: {\n\t\t\t\t\tstate.setAiProcessing(event.conversationId, false);\n\t\t\t\t\tstate.setTyping(event.conversationId, false);\n\t\t\t\t\tstate.appendStreamChunk(event.conversationId, event.delta, event.done);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase WsEventType.ConversationCreated: {\n\t\t\t\t\t// Race-safe insert: WS may arrive before OR after the HTTP\n\t\t\t\t\t// createConversation response. If after, remapConversationId\n\t\t\t\t\t// already renamed tempId → realId, so the entry exists.\n\t\t\t\t\t// If before, we prepend here; the later remap call hits the\n\t\t\t\t\t// `hasNewId=true` branch and drops the temp entry.\n\t\t\t\t\tconst conv = event.conversation as unknown as {\n\t\t\t\t\t\tid: string;\n\t\t\t\t\t\ttitle: string | null;\n\t\t\t\t\t\tstatus: string;\n\t\t\t\t\t\tlastMessageText?: string | null;\n\t\t\t\t\t\tlastMessageAt?: string | null;\n\t\t\t\t\t\tlastMessageSenderType?: string | null;\n\t\t\t\t\t};\n\t\t\t\t\tconst alreadyPresent = state.conversations.some((c) => c.id === conv.id);\n\t\t\t\t\tif (alreadyPresent) break;\n\t\t\t\t\tstate.addConversation({\n\t\t\t\t\t\tid: conv.id,\n\t\t\t\t\t\ttitle: conv.title,\n\t\t\t\t\t\tstatus: conv.status,\n\t\t\t\t\t\tlastMessageText: conv.lastMessageText ?? null,\n\t\t\t\t\t\tlastMessageAt: conv.lastMessageAt ?? null,\n\t\t\t\t\t\tlastMessageSenderType: conv.lastMessageSenderType ?? null,\n\t\t\t\t\t\tlastMessageSenderName: null,\n\t\t\t\t\t\tlastMessageSenderImage: null,\n\t\t\t\t\t\tassigneeName: null,\n\t\t\t\t\t\tassigneeImage: null,\n\t\t\t\t\t\tunreadCount: 0,\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t},\n\t}));\n\n\t// Single source of persistence for the proactive preview: every\n\t// transition (WS set, setOpen-clears, dismissPreview) passes through\n\t// here, so we don't have to touch each call site.\n\tif (typeof window !== \"undefined\") {\n\t\tlet last = store.getState().incomingPreview;\n\t\tstore.subscribe((s) => {\n\t\t\tif (s.incomingPreview !== last) {\n\t\t\t\tlast = s.incomingPreview;\n\t\t\t\tpersistPreview(s.incomingPreview);\n\t\t\t}\n\t\t});\n\t}\n\n\treturn store;\n}\n","import type { StoreApi } from \"zustand/vanilla\";\nimport type { Listener, WidgetEventEmitter, WidgetEventName, WidgetEvents } from \"./events\";\nimport type { WidgetStore } from \"./store\";\nimport { clearVisitorId } from \"./visitor-id\";\n\n/**\n * The programmatic widget API — all the methods consumers can call\n * once the widget is mounted. Returned by `createHelpwayAPI()`.\n *\n * The global `window.Helpway` is the *callable* wrapper around this\n * (see `HelpwayAPI` and `installCallable`).\n */\nexport interface HelpwayMethods {\n\t/** Open the widget panel */\n\topen(): void;\n\t/** Close the widget panel */\n\tclose(): void;\n\t/** Toggle the widget panel open/closed */\n\ttoggle(): void;\n\t/** Dismiss the widget entirely (launcher + panel). Use for page-specific hiding. */\n\tdismiss(): void;\n\t/** Show the widget again after dismiss */\n\tshow(): void;\n\t/** Full reset: clear session, cookies, visitor identity */\n\tshutdown(): void;\n\t/** Identify the visitor (link to contact) */\n\tidentify(data: {\n\t\texternalId: string;\n\t\temail?: string;\n\t\tname?: string;\n\t\timage?: string;\n\t\tmetadata?: Record<string, unknown>;\n\t}): Promise<void>;\n\t/** Open a new conversation, optionally pre-filling the message */\n\tnewConversation(prefill?: string): void;\n\t/** Open a specific conversation by ID */\n\topenConversation(id: string): void;\n\t/** Get the current unread count */\n\treadonly unreadCount: number;\n\t/** Whether the widget panel is currently open */\n\treadonly isOpen: boolean;\n\t/** Subscribe to widget events */\n\ton<K extends WidgetEventName>(event: K, fn: Listener<WidgetEvents[K]>): void;\n\t/** Unsubscribe from widget events */\n\toff<K extends WidgetEventName>(event: K, fn: Listener<WidgetEvents[K]>): void;\n}\n\n/**\n * The global `window.Helpway` shape: callable (Intercom-style snippet API)\n * AND object (typed methods). Build one of these from a `HelpwayMethods`\n * via `installCallable()`.\n */\nexport interface HelpwayAPI extends HelpwayMethods {\n\t(command: string, ...args: unknown[]): unknown;\n}\n\n/**\n * Install a callable wrapper around any methods object onto `window.Helpway`,\n * draining any calls that the snippet stub queued before the widget mounted.\n * Returns the callable so callers can compare identities on cleanup.\n *\n * Generic in `T` so both the rich `HelpwayMethods` (from widget-react) and\n * the slimmer script-tag API (from widget-embed) can use the same plumbing.\n */\nexport function installCallable<T extends object>(\n\tmethods: T,\n): T & ((command: string, ...args: unknown[]) => unknown) {\n\tconst dispatch = (command: string, ...args: unknown[]): unknown => {\n\t\tconst fn = (methods as unknown as Record<string, unknown>)[command];\n\t\tif (typeof fn === \"function\") {\n\t\t\treturn (fn as (...a: unknown[]) => unknown)(...args);\n\t\t}\n\t\tconsole.warn(`[Helpway] Unknown command: ${command}`);\n\t\treturn undefined;\n\t};\n\tconst callable = Object.assign(dispatch, methods);\n\tconst previous = window.Helpway as { q?: unknown[][] } | undefined;\n\twindow.Helpway = callable as unknown as HelpwayAPI;\n\tconst queue = previous?.q;\n\tif (queue?.length) {\n\t\tfor (const entry of queue) {\n\t\t\ttry {\n\t\t\t\tdispatch(...(entry as [string, ...unknown[]]));\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"[Helpway] queued call failed:\", err);\n\t\t\t}\n\t\t}\n\t}\n\treturn callable;\n}\n\nexport function createHelpwayAPI(deps: {\n\tstore: StoreApi<WidgetStore>;\n\temitter: WidgetEventEmitter;\n\tidentify: (data: {\n\t\texternalId: string;\n\t\temail?: string;\n\t\tname?: string;\n\t\timage?: string;\n\t\tmetadata?: Record<string, unknown>;\n\t}) => Promise<void>;\n\tapiKey: string;\n}): HelpwayMethods {\n\tconst { store, emitter, identify, apiKey } = deps;\n\n\treturn {\n\t\topen() {\n\t\t\tstore.getState().setOpen(true);\n\t\t\tstore.getState().setDismissed(false);\n\t\t},\n\n\t\tclose() {\n\t\t\tstore.getState().setOpen(false);\n\t\t},\n\n\t\ttoggle() {\n\t\t\tconst s = store.getState();\n\t\t\tif (s.isDismissed) {\n\t\t\t\ts.setDismissed(false);\n\t\t\t\ts.setOpen(true);\n\t\t\t\temitter.emit(\"show\");\n\t\t\t} else {\n\t\t\t\ts.setOpen(!s.isOpen);\n\t\t\t}\n\t\t},\n\n\t\tdismiss() {\n\t\t\tstore.getState().setOpen(false);\n\t\t\tstore.getState().setDismissed(true);\n\t\t\temitter.emit(\"dismiss\");\n\t\t},\n\n\t\tshow() {\n\t\t\tstore.getState().setDismissed(false);\n\t\t\temitter.emit(\"show\");\n\t\t},\n\n\t\tshutdown() {\n\t\t\tstore.getState().setOpen(false);\n\t\t\tstore.getState().setDismissed(false);\n\t\t\tclearVisitorId(apiKey);\n\t\t\tif (typeof document !== \"undefined\") {\n\t\t\t\tdocument.cookie = \"hw_visitor=; Path=/; Max-Age=0\";\n\t\t\t}\n\t\t},\n\n\t\tidentify,\n\n\t\tnewConversation(prefill?: string) {\n\t\t\tconst s = store.getState();\n\t\t\ts.setDismissed(false);\n\t\t\ts.setOpen(true);\n\t\t\ts.setNewConversationPrefill(prefill ?? \"\");\n\t\t},\n\n\t\topenConversation(id: string) {\n\t\t\tconst s = store.getState();\n\t\t\ts.setDismissed(false);\n\t\t\ts.setActiveConversation(id);\n\t\t\ts.setOpen(true);\n\t\t},\n\n\t\tget unreadCount() {\n\t\t\treturn store.getState().conversations.reduce((sum, c) => sum + c.unreadCount, 0);\n\t\t},\n\n\t\tget isOpen() {\n\t\t\treturn store.getState().isOpen;\n\t\t},\n\n\t\ton(event, fn) {\n\t\t\temitter.on(event, fn);\n\t\t},\n\n\t\toff(event, fn) {\n\t\t\temitter.off(event, fn);\n\t\t},\n\t};\n}\n","/**\n * Widget theming — typed surface over the CSS custom properties baked\n * into the default themed widget. Consumers pass a `WidgetTheme` object;\n * `applyTheme` writes the values onto the host element so the cascade\n * picks them up inside the Shadow DOM.\n *\n * Common cases (color, position, radius) get their own first-class\n * fields. Anything else can still be set via `cssVariables` — it's a\n * raw passthrough for custom var names we don't model yet.\n *\n * **Note for SDK consumers:** prefer dashboard-driven theming when you\n * can — changes go live without a redeploy. This API is for runtime-\n * resolved values (multi-tenant, dark/light sync with the host app).\n *\n * @see https://helpway.ai/docs/customization for the full reference,\n * the dashboard config UI, and the multi-tenant example.\n */\n\nexport type WidgetPosition = \"bottom-right\" | \"bottom-left\";\n\n/**\n * Where the widget lives on the page. The conversation UI is identical\n * across all of these — only the shell moves, so this is one prop rather\n * than six components.\n *\n * - `bubble` launcher bottom-right, panel above it (the default)\n * - `docked` composer bar pinned to the foot of the page; the bar IS\n * the composer, so the panel above it renders without one\n * - `spotlight` centred over a scrim, opened by a shortcut\n * - `sidebar` docked full-height rail that pushes page content\n * - `page` the widget is the whole route (e.g. /help)\n * - `mobile` full-height sheet; a placement, not a breakpoint\n */\nexport type WidgetPlacement =\n\t| \"bubble\"\n\t| \"docked\"\n\t| \"spotlight\"\n\t| \"sidebar\"\n\t| \"page\"\n\t| \"mobile\";\n\n/**\n * A way in offered before the visitor has said anything. A bare string is\n * the question; the object form adds the short category label that makes a\n * list of three scannable instead of three sentences to read.\n */\nexport type DockSuggestion = string | { label: string; question: string };\n\nexport interface WidgetTheme {\n\t/** Launcher background + accent color. Hover variant is auto-derived. */\n\tprimaryColor?: string;\n\t/** Text/icon color rendered ON TOP of `primaryColor`. Defaults to white. */\n\tonPrimaryColor?: string;\n\t/** Visitor (outgoing) message bubble background. Defaults to `primaryColor`. */\n\tbubbleColor?: string;\n\t/** Visitor message bubble text color. Defaults to `onPrimaryColor`. */\n\tbubbleTextColor?: string;\n\t/** Widget panel background color. */\n\tbackgroundColor?: string;\n\t/** Widget panel text color. */\n\ttextColor?: string;\n\t/** Border color used inside the panel. */\n\tborderColor?: string;\n\t/** Corner radius for the panel + cards (any valid CSS length). */\n\tradius?: string;\n\t/** Font family stack for everything inside the widget. */\n\tfontFamily?: string;\n\t/** Launcher + panel placement. Defaults to \"bottom-right\". */\n\tposition?: WidgetPosition;\n\t/**\n\t * Which appearance the widget takes.\n\t *\n\t * `\"system\"` follows the VISITOR'S OS, which is the historical default\n\t * and is usually wrong: an embedded support widget lives inside someone\n\t * else's page, and a light page in a dark-OS browser gets a dark widget\n\t * stapled to it. Pass `\"light\"` or `\"dark\"` to match the host page.\n\t * @default \"system\"\n\t */\n\tcolorScheme?: \"light\" | \"dark\" | \"system\";\n\t/**\n\t * Which shell the widget renders in. Defaults to \"bubble\".\n\t * See {@link WidgetPlacement}.\n\t */\n\tplacement?: WidgetPlacement;\n\t/**\n\t * Drop to the `mobile` sheet automatically below `mobileBreakpoint`.\n\t * Defaults to true — a 400px panel on a 390px screen is not a panel.\n\t */\n\tautoMobile?: boolean;\n\t/** Width under which `autoMobile` takes over, in px. Defaults to 480. */\n\tmobileBreakpoint?: number;\n\t/**\n\t * Escape hatch: any CSS custom property not modeled above. Keys must\n\t * start with `--`. Wins over the typed fields above when both set.\n\t */\n\tcssVariables?: Record<`--${string}`, string>;\n}\n\n/** Validate a hex like `#aabbcc`. We're conservative on purpose. */\nfunction isValidHex(color: string): boolean {\n\treturn /^#[0-9a-fA-F]{6}$/.test(color);\n}\n\n/**\n * Lighten a #rrggbb hex by a fixed amount (used as the hover variant\n * of `primaryColor`). Non-hex inputs return unchanged so callers can\n * pass `oklch(...)`, `hsl(...)`, etc. and bring their own hover.\n */\nfunction lighten(hex: string): string {\n\tif (!isValidHex(hex)) return hex;\n\tconst r = Math.min(255, Number.parseInt(hex.slice(1, 3), 16) + 30);\n\tconst g = Math.min(255, Number.parseInt(hex.slice(3, 5), 16) + 30);\n\tconst b = Math.min(255, Number.parseInt(hex.slice(5, 7), 16) + 30);\n\tconst hex2 = (n: number) => n.toString(16).padStart(2, \"0\");\n\treturn `#${hex2(r)}${hex2(g)}${hex2(b)}`;\n}\n\n/** Map a single typed field onto its CSS variable(s). */\nfunction setVar(host: HTMLElement, name: string, value: string | undefined) {\n\tif (value == null || value === \"\") return;\n\thost.style.setProperty(name, value);\n}\n\n/**\n * Write a `WidgetTheme` onto the host element. Safe to call multiple\n * times — every call is incremental, only the keys you provide are\n * touched. Pass `undefined` for a field to leave the existing value alone;\n * call `clearTheme()` if you want to reset.\n */\nexport function applyTheme(host: HTMLElement, theme: WidgetTheme | undefined) {\n\tif (!host || !theme) return;\n\n\tif (theme.primaryColor) {\n\t\tsetVar(host, \"--hw-primary\", theme.primaryColor);\n\t\tsetVar(host, \"--hw-primary-hover\", lighten(theme.primaryColor));\n\t\tsetVar(host, \"--hw-brand\", theme.primaryColor);\n\t}\n\tsetVar(host, \"--hw-on-brand\", theme.onPrimaryColor);\n\tsetVar(host, \"--hw-visitor-bubble-bg\", theme.bubbleColor ?? theme.primaryColor);\n\tsetVar(host, \"--hw-visitor-bubble-text\", theme.bubbleTextColor ?? theme.onPrimaryColor);\n\tsetVar(host, \"--hw-bg\", theme.backgroundColor);\n\tsetVar(host, \"--hw-text\", theme.textColor);\n\tsetVar(host, \"--hw-border\", theme.borderColor);\n\tsetVar(host, \"--hw-radius\", theme.radius);\n\tsetVar(host, \"--hw-font\", theme.fontFamily);\n\n\tif (theme.position === \"bottom-left\") {\n\t\tsetVar(host, \"--hw-position-right\", \"auto\");\n\t\tsetVar(host, \"--hw-position-left\", \"20px\");\n\t\tsetVar(host, \"--hw-window-right\", \"auto\");\n\t\tsetVar(host, \"--hw-window-left\", \"0\");\n\t} else if (theme.position === \"bottom-right\") {\n\t\thost.style.removeProperty(\"--hw-position-right\");\n\t\thost.style.removeProperty(\"--hw-position-left\");\n\t\thost.style.removeProperty(\"--hw-window-right\");\n\t\thost.style.removeProperty(\"--hw-window-left\");\n\t}\n\n\t// The shell reads placement off the host as a data attribute rather\n\t// than a CSS variable — CSS variables cannot drive selectors, and every\n\t// shell rule is a selector (`[data-hw-placement=\"docked\"] .hw-panel`).\n\tif (theme.placement) host.dataset.hwPlacement = theme.placement;\n\n\t// The dark-token blocks are all guarded with\n\t// `.hw-widget:not([data-theme=\"light\"])`, so writing this attribute is\n\t// what actually pins the appearance. \"system\" leaves it unset and the\n\t// prefers-color-scheme media query decides.\n\tif (theme.colorScheme === \"light\" || theme.colorScheme === \"dark\") {\n\t\thost.dataset.theme = theme.colorScheme;\n\t} else if (theme.colorScheme === \"system\") {\n\t\tdelete host.dataset.theme;\n\t}\n\n\tif (theme.cssVariables) {\n\t\tfor (const [key, value] of Object.entries(theme.cssVariables)) {\n\t\t\tif (key.startsWith(\"--\")) host.style.setProperty(key, value);\n\t\t}\n\t}\n}\n\n/**\n * Resolve the placement actually in effect, folding in the automatic\n * mobile drop. Kept out of `applyTheme` so the React layer can call it on\n * every resize without re-writing the whole token set.\n */\nexport function resolvePlacement(\n\ttheme: WidgetTheme | undefined,\n\tviewportWidth: number,\n): WidgetPlacement {\n\tconst requested = theme?.placement ?? \"bubble\";\n\tif (requested === \"mobile\") return \"mobile\";\n\tconst auto = theme?.autoMobile ?? true;\n\tconst breakpoint = theme?.mobileBreakpoint ?? 480;\n\t// `page` owns its whole route, so it stays a page on a phone — it is\n\t// already full-bleed and has no launcher to get in the way.\n\tif (auto && requested !== \"page\" && viewportWidth < breakpoint) return \"mobile\";\n\treturn requested;\n}\n","export type Listener<T = unknown> = (data: T) => void;\n\nexport interface WidgetEvents {\n\topen: undefined;\n\tclose: undefined;\n\tdismiss: undefined;\n\tshow: undefined;\n\tunreadChange: number;\n\tmessageReceived: { conversationId: string; text: string; senderName: string | null };\n\tready: undefined;\n}\n\nexport type WidgetEventName = keyof WidgetEvents;\n\nexport class WidgetEventEmitter {\n\tprivate listeners = new Map<string, Set<Listener>>();\n\n\ton<K extends WidgetEventName>(event: K, fn: Listener<WidgetEvents[K]>): void {\n\t\tif (!this.listeners.has(event)) this.listeners.set(event, new Set());\n\t\tthis.listeners.get(event)!.add(fn as Listener);\n\t}\n\n\toff<K extends WidgetEventName>(event: K, fn: Listener<WidgetEvents[K]>): void {\n\t\tthis.listeners.get(event)?.delete(fn as Listener);\n\t}\n\n\temit<K extends WidgetEventName>(\n\t\tevent: K,\n\t\t...args: WidgetEvents[K] extends undefined ? [] : [WidgetEvents[K]]\n\t): void {\n\t\tconst data = args[0];\n\t\tthis.listeners.get(event)?.forEach((fn) => {\n\t\t\ttry {\n\t\t\t\tfn(data);\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(`[Helpway] Event handler error (${event}):`, err);\n\t\t\t}\n\t\t});\n\t}\n\n\tremoveAll(): void {\n\t\tthis.listeners.clear();\n\t}\n}\n","/**\n * Widget i18n — lightweight, zero-dependency translation system.\n *\n * Architecture:\n * - English strings bundled as fallback (zero-latency, always works)\n * - Other locales fetched from Better i18n CDN at runtime\n * - Locale detection: data-locale > identify metadata > navigator.language > \"en\"\n * - Simple key-value lookup with t(\"widget.key\") syntax\n *\n * CDN URL: https://cdn.better-i18n.com/helpway/widget/{locale}/translations.json\n */\n\n// ── Bundled English fallback strings ────────────────────────\n\nconst en: Record<string, string> = {\n\t// Navigation & tabs\n\t\"widget.home\": \"Home\",\n\t\"widget.messages\": \"Messages\",\n\t\"widget.help\": \"Help\",\n\n\t// Home screen\n\t\"widget.send_us_message\": \"Send us a message\",\n\t\"widget.reply_time\": \"We typically reply in a few minutes\",\n\t\"widget.recent_conversations\": \"Recent conversations\",\n\t\"widget.see_all\": \"See all conversations\",\n\t\"widget.whats_new\": \"What's New\",\n\t\"widget.view_all\": \"View all\",\n\n\t// Messages tab\n\t\"widget.no_messages\": \"No messages yet\",\n\t\"widget.no_messages_desc\": \"Start a conversation to get help\",\n\t\"widget.start_conversation\": \"Start a conversation\",\n\t\"widget.no_preview\": \"No messages yet\",\n\n\t// Conversation\n\t\"widget.new_conversation\": \"New conversation\",\n\t\"widget.talk_to_human\": \"Talk to a human\",\n\t\"widget.talk_to_human_message\": \"I'd like to talk to a human, please.\",\n\t\"widget.aria_options\": \"Conversation options\",\n\t\"widget.resolved_text\": \"This conversation has been resolved\",\n\t\"widget.send_followup\": \"Send a follow-up\",\n\t\"widget.start_a_conversation\": \"Start a conversation\",\n\n\t// Composer\n\t\"widget.placeholder\": \"Send a message...\",\n\t\"widget.placeholder_new\": \"How can we help?\",\n\t\"widget.drop_files\": \"Drop files here\",\n\n\t// CSAT\n\t\"widget.csat_label\": \"How was your experience?\",\n\t\"widget.csat_thanks\": \"Thanks for your feedback!\",\n\n\t// Inline email collection (after AI reply)\n\t\"widget.email_title\": \"Don't miss our reply\",\n\t\"widget.email_subtitle\": \"We'll email you when we respond\",\n\t\"widget.email_placeholder\": \"you@email.com\",\n\t\"widget.email_continue\": \"Send\",\n\t\"widget.email_saved\": \"You'll be notified by email\",\n\t\"widget.email_dismiss\": \"No thanks\",\n\n\t// Errors\n\t\"widget.error_title\": \"Something went wrong\",\n\t\"widget.error_desc\": \"Failed to load. Please try again.\",\n\t\"widget.retry\": \"Retry\",\n\t\"widget.reconnecting\": \"Reconnecting...\",\n\t\"widget.send_error\": \"Message not sent\",\n\n\t// Date separators (today is implicit — never rendered)\n\t\"widget.yesterday\": \"Yesterday\",\n\n\t// Sender labels\n\t\"widget.helpway_ai\": \"Helpway AI\",\n\t\"widget.support\": \"Support\",\n\n\t// Events\n\t\"widget.joined\": \"joined the conversation\",\n\t\"widget.left\": \"left the conversation\",\n\n\t// Content/search\n\t\"widget.content\": \"Content\",\n\t\"widget.search\": \"Search...\",\n\t\"widget.no_results\": \"No results found\",\n\t\"widget.try_different\": \"Try a different search term\",\n\t\"widget.nothing_yet\": \"Nothing here yet\",\n\t\"widget.check_back\": \"Check back later for updates\",\n\t\"widget.load_more\": \"Load more\",\n\t\"widget.loading\": \"Loading...\",\n\n\t// Copy\n\t\"widget.copy\": \"Copy message\",\n\t\"widget.copied\": \"Copied\",\n\n\t// File upload\n\t\"widget.file_too_large\": \"File too large (max 10 MB)\",\n\t\"widget.click_to_open\": \"Click to open\",\n\t\"widget.caption_required\": \"Add a message to send with your attachment\",\n\n\t// Accessibility\n\t\"widget.aria_chat\": \"Support chat\",\n\t\"widget.aria_close\": \"Close\",\n\t\"widget.aria_back\": \"Back\",\n\t\"widget.aria_send\": \"Send message\",\n\t\"widget.aria_open_image\": \"Open image\",\n\t\"widget.aria_attach\": \"Attach file\",\n\t\"widget.aria_dictate\": \"Dictate message\",\n\t\"widget.aria_input\": \"Message input\",\n\t\"widget.aria_remove\": \"Remove\",\n\t\"widget.aria_dismiss\": \"Dismiss\",\n\t\"widget.aria_open\": \"Open support\",\n\t\"widget.aria_close_support\": \"Close support\",\n\t\"widget.aria_good\": \"Good\",\n\t\"widget.aria_bad\": \"Bad\",\n\t\"widget.aria_messages\": \"Messages\",\n\n\t// Time (relative)\n\t\"widget.time_now\": \"now\",\n\t\"widget.time_yesterday\": \"Yesterday\",\n\n\t// Powered by\n\t\"widget.powered_by\": \"Powered by\",\n\n\t// Hero / home screen\n\t\"widget.welcome_message\": \"Hi there 👋\\nHow can we help?\",\n\t\"widget.subtitle_text\": \"Usually replies in minutes\",\n};\n\n// ── State ───────────────────────────────────────────────────\n\nlet currentLocale = \"en\";\nlet translations: Record<string, string> = {};\nlet isLoaded = false;\nlet revision = 0; // Incremented on every translation change — React hook watches this\nconst listeners: Array<() => void> = [];\n\n// ── Public API ──────────────────────────────────────────────\n\n/**\n * Translate a key. Falls back to English bundled string, then to the key itself.\n *\n * Supports simple interpolation: t(\"widget.key\", { name: \"John\" })\n * Template: \"Hello {{name}}\" → \"Hello John\"\n */\nexport function t(key: string, params?: Record<string, string | number>): string {\n\tconst value = translations[key] ?? en[key] ?? key;\n\n\tif (!params) return value;\n\n\treturn value.replace(/\\{\\{(\\w+)\\}\\}/g, (_, k: string) => {\n\t\treturn params[k]?.toString() ?? `{{${k}}}`;\n\t});\n}\n\n/** Get the current locale code */\nexport function getLocale(): string {\n\treturn currentLocale;\n}\n\n/** Get current revision number — changes when translations are loaded/updated */\nexport function getI18nRevision(): number {\n\treturn revision;\n}\n\n/** Check if translations have been loaded */\nexport function isI18nReady(): boolean {\n\treturn isLoaded;\n}\n\n/** Subscribe to locale/translation changes. Returns unsubscribe fn. */\nexport function onLocaleChange(fn: () => void): () => void {\n\tlisteners.push(fn);\n\treturn () => {\n\t\tconst idx = listeners.indexOf(fn);\n\t\tif (idx >= 0) listeners.splice(idx, 1);\n\t};\n}\n\n// ── Initialization ──────────────────────────────────────────\n\n/**\n * Detect locale from available signals and fetch translations.\n *\n * Priority:\n * 1. Explicit `locale` param (from data-locale attribute)\n * 2. navigator.language (browser preference)\n * 3. \"en\" fallback\n */\nexport async function initI18n(options?: { locale?: string; cdnBase?: string }): Promise<void> {\n\tif (options?.cdnBase) {\n\t\tcdnBase = options.cdnBase;\n\t}\n\n\tconst detected =\n\t\toptions?.locale ?? (typeof navigator !== \"undefined\" ? navigator.language : \"en\");\n\n\t// Normalize: \"fr-FR\" → \"fr\", \"pt-BR\" → \"pt-BR\" (keep regional if meaningful)\n\tcurrentLocale = normalizeLocale(detected);\n\n\t// English is bundled — no fetch needed\n\tif (currentLocale === \"en\") {\n\t\tisLoaded = true;\n\t\tnotify();\n\t\treturn;\n\t}\n\n\t// Fetch from CDN\n\ttry {\n\t\tconst data = await fetchTranslations(currentLocale);\n\t\tif (data) {\n\t\t\t// Only pick widget.* keys from the full namespace bundle\n\t\t\tfor (const [key, value] of Object.entries(data)) {\n\t\t\t\tif (typeof value === \"string\") {\n\t\t\t\t\ttranslations[`widget.${key}`] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch (err) {\n\t\tconsole.warn(`[Helpway] Failed to fetch ${currentLocale} translations, using English`, err);\n\t}\n\n\tisLoaded = true;\n\tnotify();\n}\n\n/**\n * Update locale at runtime (e.g., after identify() provides metadata.locale).\n * Re-fetches translations if locale changed.\n */\nexport async function setLocale(locale: string): Promise<void> {\n\tconst normalized = normalizeLocale(locale);\n\tif (normalized === currentLocale) return;\n\n\tcurrentLocale = normalized;\n\ttranslations = {}; // Clear old translations\n\n\tif (normalized === \"en\") {\n\t\tnotify();\n\t\treturn;\n\t}\n\n\ttry {\n\t\tconst data = await fetchTranslations(normalized);\n\t\tif (data) {\n\t\t\tfor (const [key, value] of Object.entries(data)) {\n\t\t\t\tif (typeof value === \"string\") {\n\t\t\t\t\ttranslations[`widget.${key}`] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Silent fallback to English\n\t}\n\n\tnotify();\n}\n\n// ── Internals ───────────────────────────────────────────────\n\nlet cdnBase = \"https://cdn.better-i18n.com/helpway/widget\";\n\nasync function fetchTranslations(locale: string): Promise<Record<string, string> | null> {\n\t// All namespaces live in a single translations.json — widget keys nested under \"widget\" key\n\tconst url = `${cdnBase}/${locale}/translations.json`;\n\n\tlet res = await fetch(url);\n\tif (!res.ok && locale.includes(\"-\")) {\n\t\t// Try base locale: \"pt-BR\" → \"pt\"\n\t\tconst base = locale.split(\"-\")[0];\n\t\tres = await fetch(`${cdnBase}/${base}/translations.json`);\n\t}\n\tif (!res.ok) return null;\n\n\tconst data: Record<string, unknown> = await res.json();\n\t// CDN structure is nested: { \"widget\": { \"home\": \"Ana Sayfa\", ... }, \"sidebar\": {...} }\n\tconst widgetNs = data.widget;\n\tif (widgetNs && typeof widgetNs === \"object\" && !Array.isArray(widgetNs)) {\n\t\tconst result: Record<string, string> = {};\n\t\tfor (const [k, v] of Object.entries(widgetNs)) {\n\t\t\tif (typeof v === \"string\") result[k] = v;\n\t\t}\n\t\treturn result;\n\t}\n\treturn null;\n}\n\nfunction normalizeLocale(input: string): string {\n\t// Keep regional variants that are commonly distinct: pt-BR, zh-CN, zh-TW\n\tconst regional = [\"pt-br\", \"zh-cn\", \"zh-tw\", \"zh-hk\"];\n\tconst lower = input.toLowerCase().replace(\"_\", \"-\");\n\n\tfor (const r of regional) {\n\t\tif (lower.startsWith(r)) return r;\n\t}\n\n\t// Otherwise just use base: \"fr-FR\" → \"fr\"\n\treturn lower.split(\"-\")[0] ?? \"en\";\n}\n\nfunction notify(): void {\n\trevision++;\n\tfor (const fn of listeners) {\n\t\ttry {\n\t\t\tfn();\n\t\t} catch {\n\t\t\t/* ignore */\n\t\t}\n\t}\n}\n","import { t, getLocale } from \"./i18n\";\n\n/**\n * Format a date as relative time string.\n * Uses i18n for \"now\" and \"Yesterday\". Locale-aware date formatting.\n */\nexport function formatRelativeTime(date: string | Date): string {\n\tconst now = Date.now();\n\tconst then = typeof date === \"string\" ? new Date(date).getTime() : date.getTime();\n\tconst diffMs = now - then;\n\tconst diffMin = Math.floor(diffMs / 60000);\n\tconst diffHour = Math.floor(diffMs / 3600000);\n\tconst diffDay = Math.floor(diffMs / 86400000);\n\n\tif (diffMin < 1) return t(\"widget.time_now\");\n\tif (diffMin < 60) return `${diffMin}m`;\n\tif (diffHour < 24) return `${diffHour}h`;\n\tif (diffDay === 1) return t(\"widget.time_yesterday\");\n\tif (diffDay < 7) return `${diffDay}d`;\n\n\tconst d = typeof date === \"string\" ? new Date(date) : date;\n\treturn d.toLocaleDateString(getLocale(), { month: \"short\", day: \"numeric\" });\n}\n\n/**\n * Format time for message bubbles (HH:MM).\n */\nexport function formatTime(date: string | Date): string {\n\tconst d = typeof date === \"string\" ? new Date(date) : date;\n\treturn d.toLocaleTimeString(undefined, { hour: \"2-digit\", minute: \"2-digit\" });\n}\n\n/**\n * Resolve a label that may be a translation key (\"widget.*\") or plain text.\n * When the key resolves to itself (missing), falls back to a humanized form\n * so the UI never leaks raw \"widget.changelog\" strings to the visitor.\n */\nexport function resolveLabel(label: string): string {\n\tif (!label.startsWith(\"widget.\")) return label;\n\tconst resolved = t(label);\n\tif (resolved === label) {\n\t\treturn label\n\t\t\t.replace(\"widget.\", \"\")\n\t\t\t.replace(/_/g, \" \")\n\t\t\t.replace(/^\\w/, (c) => c.toUpperCase());\n\t}\n\treturn resolved;\n}\n\n/**\n * Get initials from a name or email.\n */\nexport function getInitials(value: string): string {\n\tif (!value) return \"?\";\n\n\t// Email: take first letter\n\tif (value.includes(\"@\")) return (value[0] ?? \"?\").toUpperCase();\n\n\t// Name: take first letter of first two words\n\tconst parts = value.trim().split(/\\s+/);\n\tif (parts.length >= 2) {\n\t\treturn ((parts[0]?.[0] ?? \"\") + (parts[1]?.[0] ?? \"\")).toUpperCase();\n\t}\n\treturn (parts[0]?.[0] ?? \"?\").toUpperCase();\n}\n","\"use client\";\n\nimport {\n\tWebSocketManager,\n\tWidgetEventEmitter,\n\ttype HelpwayMethods,\n\ttype WidgetClient,\n\ttype WidgetStore,\n\ttype WidgetTheme,\n\tapplyTheme,\n\tcreateHelpwayAPI,\n\tcreateWidgetClient,\n\tcreateWidgetStore,\n\tinitI18n,\n\tinstallCallable,\n\tsetLocale,\n\tsyncVisitorId,\n} from \"@helpway/widget-core\";\nimport {\n\ttype ReactNode,\n\tcreateContext,\n\tuseCallback,\n\tuseContext,\n\tuseEffect,\n\tuseRef,\n\tuseState,\n} from \"react\";\nimport { type StoreApi, useStore } from \"zustand\";\n\n// ── Context ──────────────────────────────────────────────\n\nexport interface IdentifyData {\n\texternalId: string;\n\temail?: string;\n\tname?: string;\n\timage?: string;\n\tmetadata?: Record<string, unknown>;\n}\n\ninterface WidgetContextValue {\n\tclient: WidgetClient;\n\tstore: StoreApi<WidgetStore>;\n\tws: WebSocketManager;\n\tidentify: (data: IdentifyData) => Promise<void>;\n\tapi: HelpwayMethods;\n\temitter: WidgetEventEmitter;\n\thasBootstrapError: boolean;\n\twsDisconnected: boolean;\n\tretryBootstrap: () => void;\n}\n\nconst WidgetContext = createContext<WidgetContextValue | null>(null);\n\nexport function useWidgetContext(): WidgetContextValue {\n\tconst ctx = useContext(WidgetContext);\n\tif (!ctx) {\n\t\tthrow new Error(\"useWidgetContext must be used within <SupportProvider>\");\n\t}\n\treturn ctx;\n}\n\n/** Use a slice of the widget store with auto re-render */\nexport function useWidgetStore<T>(selector: (state: WidgetStore) => T): T {\n\tconst { store } = useWidgetContext();\n\treturn useStore(store, selector);\n}\n\n/** Hook to identify the current visitor (link to customer contact) */\nexport function useIdentify() {\n\tconst { identify } = useWidgetContext();\n\treturn identify;\n}\n\n/** Raw tRPC client — used by interactive components that need to call\n * mutations not exposed via the public HelpwayMethods (e.g. workflow\n * quick-reply taps). The client is `any`-typed by design (see\n * packages/widget-core/src/client.ts) so callers must spell mutation\n * paths explicitly. */\nexport function useWidgetClient(): WidgetClient {\n\tconst { client } = useWidgetContext();\n\treturn client;\n}\n\n// ── Provider ─────────────────────────────────────────────\n\ninterface SupportProviderProps {\n\tapiKey: string;\n\tapiUrl?: string;\n\tlocale?: string;\n\tinitialConversationId?: string;\n\tdeepLinkToken?: string;\n\tonReady?: (api: HelpwayMethods) => void;\n\tcustomLauncherSelector?: string;\n\tonOpen?: () => void;\n\tonClose?: () => void;\n\tonUnreadChange?: (count: number) => void;\n\t/**\n\t * Developer-side theme override. Most consumers should configure\n\t * appearance in the Helpway dashboard (see\n\t * https://helpway.ai/docs/customization) so changes apply without\n\t * a redeploy. Use this prop only when you need the widget to inherit\n\t * a host-app theme that the dashboard can't see (e.g. a tenant-\n\t * specific brand color resolved at runtime). Values here are written\n\t * as CSS custom properties on the widget host and override the\n\t * dashboard config for this mount only.\n\t */\n\ttheme?: WidgetTheme;\n\tchildren: ReactNode;\n}\n\n/**\n * Root provider for the Helpway widget.\n * Creates tRPC client, WebSocket connection, and state store.\n *\n * Visitor identity is managed via server-side cookies (hw_visitor).\n * No localStorage or client-side ID management needed.\n */\nexport function SupportProvider({\n\tapiKey,\n\tapiUrl,\n\tlocale,\n\tinitialConversationId,\n\tdeepLinkToken,\n\tonReady,\n\tcustomLauncherSelector,\n\tonOpen,\n\tonClose,\n\tonUnreadChange,\n\ttheme,\n\tchildren,\n}: SupportProviderProps) {\n\tconst initRef = useRef<{\n\t\tclient: WidgetClient;\n\t\tstore: StoreApi<WidgetStore>;\n\t\tws: WebSocketManager;\n\t\tidentify: (data: IdentifyData) => Promise<void>;\n\t\tapi: HelpwayMethods;\n\t\temitter: WidgetEventEmitter;\n\t} | null>(null);\n\tconst [hasBootstrapError, setHasBootstrapError] = useState(false);\n\tconst [wsDisconnected, setWsDisconnected] = useState(false);\n\tconst [bootstrapAttempt, setBootstrapAttempt] = useState(0);\n\n\tif (!initRef.current) {\n\t\tconst resolvedApiUrl = apiUrl ?? inferApiUrl();\n\n\t\tconst client = createWidgetClient({\n\t\t\tapiUrl: resolvedApiUrl,\n\t\t\tapiKey,\n\t\t});\n\n\t\tconst store = createWidgetStore();\n\t\tconst emitter = new WidgetEventEmitter();\n\n\t\tconst ws = new WebSocketManager({\n\t\t\tapiUrl: resolvedApiUrl,\n\t\t\tvisitorId: \"\",\n\t\t\twebsiteId: \"\",\n\t\t\tapiKey,\n\t\t});\n\n\t\tconst identify = async (data: IdentifyData) => {\n\t\t\ttry {\n\t\t\t\tconst result = await client.widget.identify.mutate(data);\n\t\t\t\tif (result.contact) {\n\t\t\t\t\tstore.getState().updateVisitorContact({\n\t\t\t\t\t\tid: result.contact.id,\n\t\t\t\t\t\tname: result.contact.name ?? null,\n\t\t\t\t\t\temail: result.contact.email ?? null,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst metaLocale = data.metadata?.locale;\n\t\t\t\tif (typeof metaLocale === \"string\" && metaLocale.length > 0) {\n\t\t\t\t\tsetLocale(metaLocale);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"[Helpway] identify failed:\", err);\n\t\t\t}\n\t\t};\n\n\t\tconst api = createHelpwayAPI({ store, emitter, identify, apiKey });\n\n\t\t// Lazy init, once. react-doctor flags this as a ref mutated during\n\t\t// render and it is wrong to \"fix\": the values are consumed on this\n\t\t// same render two lines down, so moving the assignment into an\n\t\t// effect leaves client/store undefined on first paint. This is the\n\t\t// shape React's own docs sanction for expensive one-time setup.\n\t\tinitRef.current = { client, store, ws, identify, api, emitter };\n\t}\n\n\tconst { client, store, ws, identify, api, emitter } = initRef.current;\n\n\tconst retryBootstrap = useCallback(() => {\n\t\tsetHasBootstrapError(false);\n\t\tsetBootstrapAttempt((n) => n + 1);\n\t}, []);\n\n\t// Bootstrap on mount (re-runs on retry)\n\tuseEffect(() => {\n\t\tlet cancelled = false;\n\n\t\tasync function bootstrap() {\n\t\t\ttry {\n\t\t\t\tconst data = await client.widget.bootstrap.query();\n\t\t\t\tif (cancelled) return;\n\n\t\t\t\t// Initialize i18n BEFORE setReady to avoid flash of English text.\n\t\t\t\t// Priority: explicit `locale` prop → server-side detection\n\t\t\t\t// (Accept-Language + CF-IPCountry) → widget-core bundled default.\n\t\t\t\tconst resolvedLocale =\n\t\t\t\t\tlocale ?? (data as { detectedLocale?: string | null }).detectedLocale ?? undefined;\n\t\t\t\tawait initI18n({\n\t\t\t\t\tlocale: resolvedLocale,\n\t\t\t\t\tcdnBase: (data.agentConfig as { i18nCdnBase?: string } | null)?.i18nCdnBase ?? undefined,\n\t\t\t\t});\n\n\t\t\t\tstore.getState().setReady(data.visitor, data.website, data.agentConfig);\n\t\t\t\tsetHasBootstrapError(false);\n\n\t\t\t\t// Sync server-assigned visitor ID to localStorage\n\t\t\t\t// Ensures client uses canonical ID on subsequent page loads\n\t\t\t\tif (data.visitor?.id) {\n\t\t\t\t\tsyncVisitorId(apiKey, data.visitor.id);\n\t\t\t\t}\n\n\t\t\t\tconst convData = await client.widget.listConversations.query();\n\t\t\t\tif (cancelled) return;\n\n\t\t\t\tconst mapConversation = (c: {\n\t\t\t\t\tid: string;\n\t\t\t\t\ttitle: string | null;\n\t\t\t\t\tstatus: string;\n\t\t\t\t\tlastMessageText: string | null;\n\t\t\t\t\tlastMessageAt: string | null;\n\t\t\t\t\tlastMessageSenderType: string | null;\n\t\t\t\t\tlastMessageSenderName: string | null;\n\t\t\t\t\tlastMessageSenderImage: string | null;\n\t\t\t\t}) => ({\n\t\t\t\t\tid: c.id,\n\t\t\t\t\ttitle: c.title,\n\t\t\t\t\tstatus: c.status,\n\t\t\t\t\tlastMessageText: c.lastMessageText,\n\t\t\t\t\tlastMessageAt: c.lastMessageAt,\n\t\t\t\t\tlastMessageSenderType: c.lastMessageSenderType,\n\t\t\t\t\tlastMessageSenderName: c.lastMessageSenderName,\n\t\t\t\t\tlastMessageSenderImage: c.lastMessageSenderImage,\n\t\t\t\t\tunreadCount: 0,\n\t\t\t\t});\n\n\t\t\t\tstore.getState().setConversations(\n\t\t\t\t\tconvData.conversations.map(mapConversation),\n\t\t\t\t);\n\n\t\t\t\t// Connect WebSocket BEFORE the proactive check so the visitor-channel\n\t\t\t\t// subscription is live by the time the workflow orchestrator emits\n\t\t\t\t// timelineItemCreated. Without this, the greeting message is broadcast\n\t\t\t\t// to a not-yet-subscribed client and the launcher preview bubble never\n\t\t\t\t// appears (only the unread badge increments via REST).\n\t\t\t\tif (data.website?.id && data.visitor?.id) {\n\t\t\t\t\tws.configure({ websiteId: data.website.id, visitorId: data.visitor.id });\n\t\t\t\t\tws.connect();\n\t\t\t\t}\n\n\t\t\t\tif (convData.conversations.length === 0 && !initialConversationId) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst proactive = await client.widget.proactiveCheck.mutate();\n\t\t\t\t\t\tif (cancelled || !proactive.triggered) {\n\t\t\t\t\t\t\t// nothing to do\n\t\t\t\t\t\t} else if (proactive.ephemeral) {\n\t\t\t\t\t\t\t// Render the greeting + (optional) quick replies entirely\n\t\t\t\t\t\t\t// client-side. No server-side conversation exists yet — we\n\t\t\t\t\t\t\t// materialize on the visitor's first reply.\n\t\t\t\t\t\t\thandleEphemeralProactive(store, proactive.ephemeral);\n\t\t\t\t\t\t} else if (proactive.conversationId) {\n\t\t\t\t\t\t\t// Fallback path for complex workflows that needed the\n\t\t\t\t\t\t\t// orchestrator up-front (delays, AI agent before any\n\t\t\t\t\t\t\t// visitor input, etc).\n\t\t\t\t\t\t\tconst nowIso = new Date().toISOString();\n\t\t\t\t\t\t\tstore.getState().addConversation({\n\t\t\t\t\t\t\t\tid: proactive.conversationId,\n\t\t\t\t\t\t\t\ttitle: null,\n\t\t\t\t\t\t\t\tstatus: \"open\",\n\t\t\t\t\t\t\t\tlastMessageText: proactive.lastMessageText ?? null,\n\t\t\t\t\t\t\t\tlastMessageAt: proactive.lastMessageAt ?? nowIso,\n\t\t\t\t\t\t\t\tlastMessageSenderType: proactive.lastMessageSenderType ?? null,\n\t\t\t\t\t\t\t\tlastMessageSenderName: null,\n\t\t\t\t\t\t\t\tlastMessageSenderImage: null,\n\t\t\t\t\t\t\t\tassigneeName: null,\n\t\t\t\t\t\t\t\tassigneeImage: null,\n\t\t\t\t\t\t\t\tunreadCount: 1,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (proactive.lastMessageText && !store.getState().isOpen) {\n\t\t\t\t\t\t\t\tstore.setState({\n\t\t\t\t\t\t\t\t\tincomingPreview: {\n\t\t\t\t\t\t\t\t\t\ttext: proactive.lastMessageText,\n\t\t\t\t\t\t\t\t\t\tconversationId: proactive.conversationId,\n\t\t\t\t\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// proactive check is best-effort\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (typeof window !== \"undefined\") {\n\t\t\t\t\tclient.widget.updatePage\n\t\t\t\t\t\t.mutate({\n\t\t\t\t\t\t\turl: window.location.href,\n\t\t\t\t\t\t\ttitle: document.title || window.location.pathname,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.catch(() => {});\n\t\t\t\t}\n\n\t\t\t\tif (initialConversationId && !cancelled) {\n\t\t\t\t\tif (deepLinkToken) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst redeemed = await client.widget.redeemDeepLink.mutate({ token: deepLinkToken });\n\t\t\t\t\t\t\tif (!cancelled && redeemed?.visitorId && redeemed.visitorId !== data.visitor?.id) {\n\t\t\t\t\t\t\t\tsyncVisitorId(apiKey, redeemed.visitorId);\n\t\t\t\t\t\t\t\tconst freshData = await client.widget.bootstrap.query();\n\t\t\t\t\t\t\t\tif (!cancelled) {\n\t\t\t\t\t\t\t\t\tstore.getState().setReady(freshData.visitor, freshData.website, freshData.agentConfig);\n\t\t\t\t\t\t\t\t\tconst freshConvs = await client.widget.listConversations.query();\n\t\t\t\t\t\t\t\t\tif (!cancelled) {\n\t\t\t\t\t\t\t\t\t\tstore.getState().setConversations(\n\t\t\t\t\t\t\t\t\t\t\tfreshConvs.conversations.map(mapConversation),\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// Token invalid/expired — still open widget but without identity restoration\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!cancelled) {\n\t\t\t\t\t\tstore.getState().setActiveConversation(initialConversationId);\n\t\t\t\t\t\tstore.getState().setOpen(true);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\temitter.emit(\"ready\");\n\t\t\t\tonReady?.(initRef.current!.api);\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"[Helpway] Bootstrap failed:\", err);\n\t\t\t\tif (!cancelled) {\n\t\t\t\t\tstore.getState().setConnecting(false);\n\t\t\t\t\tsetHasBootstrapError(true);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tbootstrap();\n\n\t\t// SPA route tracking — patches pushState/replaceState + listens for\n\t\t// popstate so updatePage fires whenever the visitor navigates without\n\t\t// a full reload. Server stores last 20 page views in visitor.pageHistory\n\t\t// for support agent context.\n\t\tlet pageDebounce: ReturnType<typeof setTimeout> | null = null;\n\t\tconst reportPage = () => {\n\t\t\tif (typeof window === \"undefined\") return;\n\t\t\tif (pageDebounce) clearTimeout(pageDebounce);\n\t\t\tpageDebounce = setTimeout(() => {\n\t\t\t\tclient.widget.updatePage\n\t\t\t\t\t.mutate({\n\t\t\t\t\t\turl: window.location.href,\n\t\t\t\t\t\ttitle: document.title || window.location.pathname,\n\t\t\t\t\t})\n\t\t\t\t\t.catch(() => {});\n\t\t\t}, 250);\n\t\t};\n\n\t\tconst origPush = window.history.pushState.bind(window.history);\n\t\tconst origReplace = window.history.replaceState.bind(window.history);\n\t\twindow.history.pushState = function patchedPush(...args) {\n\t\t\torigPush(...args);\n\t\t\treportPage();\n\t\t};\n\t\twindow.history.replaceState = function patchedReplace(...args) {\n\t\t\torigReplace(...args);\n\t\t\treportPage();\n\t\t};\n\t\twindow.addEventListener(\"popstate\", reportPage);\n\n\t\t// Debounced markSeen — coalesces rapid events (AI may stream multiple\n\t\t// messages, plus the typing/processing events fire too).\n\t\tlet markSeenTimer: ReturnType<typeof setTimeout> | null = null;\n\t\tconst scheduleMarkSeen = (conversationId: string) => {\n\t\t\tif (markSeenTimer) clearTimeout(markSeenTimer);\n\t\t\tmarkSeenTimer = setTimeout(() => {\n\t\t\t\tclient.widget.markSeen.mutate({ conversationId }).catch(() => {});\n\t\t\t\tstore.getState().clearUnread(conversationId);\n\t\t\t}, 400);\n\t\t};\n\n\t\tconst unsub = ws.onEvent((event) => {\n\t\t\tstore.getState().handleRealtimeEvent(event);\n\n\t\t\tif (event.type === \"timelineItemCreated\") {\n\t\t\t\tconst item = event.item;\n\t\t\t\tconst isPublicIncoming = item?.visibility === \"public\" && !item.visitorId;\n\n\t\t\t\t// Emit messageReceived for public incoming messages\n\t\t\t\tif (isPublicIncoming && item?.text) {\n\t\t\t\t\temitter.emit(\"messageReceived\", {\n\t\t\t\t\t\tconversationId: event.conversationId,\n\t\t\t\t\t\ttext: item.text,\n\t\t\t\t\t\tsenderName: \"aiAgentId\" in item && item.aiAgentId ? \"AI\" : null,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif (!isPublicIncoming) return;\n\t\t\t\tconst s = store.getState();\n\t\t\t\tconst isViewing = s.isOpen && s.activeConversationId === event.conversationId;\n\t\t\t\tif (isViewing) scheduleMarkSeen(event.conversationId);\n\t\t\t}\n\t\t});\n\n\t\t// Monitor WebSocket connection state\n\t\tconst wsCheck = setInterval(() => {\n\t\t\tsetWsDisconnected(!ws.isConnected);\n\t\t}, 3000);\n\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t\tunsub();\n\t\t\tclearInterval(wsCheck);\n\t\t\tif (markSeenTimer) clearTimeout(markSeenTimer);\n\t\t\tif (pageDebounce) clearTimeout(pageDebounce);\n\t\t\twindow.history.pushState = origPush;\n\t\t\twindow.history.replaceState = origReplace;\n\t\t\twindow.removeEventListener(\"popstate\", reportPage);\n\t\t\tws.disconnect();\n\t\t};\n\t}, [client, store, ws, bootstrapAttempt]);\n\n\t// Re-initialize translations when locale prop changes after bootstrap\n\tuseEffect(() => {\n\t\tif (locale != null) {\n\t\t\tsetLocale(locale);\n\t\t}\n\t}, [locale]);\n\n\t// Wire up event callbacks: emit open/close events\n\tuseEffect(() => {\n\t\tconst unsub = store.subscribe((state, prev) => {\n\t\t\tif (state.isOpen && !prev.isOpen) {\n\t\t\t\temitter.emit(\"open\");\n\t\t\t\tonOpen?.();\n\t\t\t}\n\t\t\tif (!state.isOpen && prev.isOpen) {\n\t\t\t\temitter.emit(\"close\");\n\t\t\t\tonClose?.();\n\t\t\t}\n\t\t\tconst prevUnread = prev.conversations.reduce((s, c) => s + c.unreadCount, 0);\n\t\t\tconst nextUnread = state.conversations.reduce((s, c) => s + c.unreadCount, 0);\n\t\t\tif (nextUnread !== prevUnread) {\n\t\t\t\temitter.emit(\"unreadChange\", nextUnread);\n\t\t\t\tonUnreadChange?.(nextUnread);\n\t\t\t}\n\t\t});\n\t\treturn unsub;\n\t}, [store, emitter, onOpen, onClose, onUnreadChange]);\n\n\t// Custom launcher selector: attach click handler with MutationObserver fallback for SPAs\n\tuseEffect(() => {\n\t\tif (!customLauncherSelector) return;\n\t\tconst handler = (e: Event) => {\n\t\t\te.preventDefault();\n\t\t\tapi.toggle();\n\t\t};\n\n\t\tconst attach = () => {\n\t\t\tconst el = document.querySelector(customLauncherSelector);\n\t\t\tif (el) {\n\t\t\t\tel.addEventListener(\"click\", handler);\n\t\t\t\treturn el;\n\t\t\t}\n\t\t\treturn null;\n\t\t};\n\n\t\tlet el = attach();\n\t\tlet observer: MutationObserver | null = null;\n\n\t\tif (!el) {\n\t\t\tobserver = new MutationObserver(() => {\n\t\t\t\tel = attach();\n\t\t\t\tif (el) observer?.disconnect();\n\t\t\t});\n\t\t\tobserver.observe(document.body, { childList: true, subtree: true });\n\t\t}\n\n\t\treturn () => {\n\t\t\tel?.removeEventListener(\"click\", handler);\n\t\t\tobserver?.disconnect();\n\t\t};\n\t}, [customLauncherSelector, api]);\n\n\t// Sync window.Helpway with the current api instance on mount,\n\t// restore on unmount. Must live in an effect (not the init block)\n\t// so React StrictMode's double mount/unmount cycle doesn't leave\n\t// the global undefined: the effect re-runs on each mount and\n\t// re-installs the callable, while the init block only fires once\n\t// because initRef.current is preserved across remounts.\n\t//\n\t// IMPORTANT: window.Helpway is exposed as a CALLABLE function (Intercom-style)\n\t// so that `Helpway(\"identify\", payload)` works alongside `Helpway.identify(payload)`.\n\t// Earlier versions assigned the raw `api` object here, which clobbered the\n\t// callable installed by the widget-embed loader and made the documented\n\t// `Helpway(\"cmd\", ...)` form throw \"is not a function\" downstream.\n\t// Apply developer-side theme overrides. We target the host that the\n\t// widget script created (#helpway-widget) when running under the\n\t// embed loader; otherwise fall back to documentElement so the CSS\n\t// vars cascade into a Light-DOM React mount. See:\n\t// https://helpway.ai/docs/customization\n\tuseEffect(() => {\n\t\tif (!theme || typeof document === \"undefined\") return;\n\t\tconst target =\n\t\t\t(document.getElementById(\"helpway-widget\") as HTMLElement | null) ??\n\t\t\tdocument.documentElement;\n\t\tapplyTheme(target, theme);\n\t}, [theme]);\n\n\tuseEffect(() => {\n\t\tif (typeof window === \"undefined\") return;\n\t\tconst callable = installCallable(api);\n\t\treturn () => {\n\t\t\tif (window.Helpway === callable) {\n\t\t\t\twindow.Helpway = undefined;\n\t\t\t}\n\t\t\temitter.removeAll();\n\t\t};\n\t}, [api, emitter]);\n\n\tconst ctxValue: WidgetContextValue = {\n\t\tclient,\n\t\tstore,\n\t\tws,\n\t\tidentify,\n\t\tapi,\n\t\temitter,\n\t\thasBootstrapError,\n\t\twsDisconnected,\n\t\tretryBootstrap,\n\t};\n\n\treturn <WidgetContext.Provider value={ctxValue}>{children}</WidgetContext.Provider>;\n}\n\n// ── Helpers ──────────────────────────────────────────────\n\n/**\n * Resolve the API origin when the consumer doesn't pass `apiUrl` explicitly.\n *\n * Order of precedence:\n * 1. CDN script-tag origin — when the widget loads via\n * `<script src=\"https://cdn.helpway.ai/widget.js\" data-key=\"...\">` we\n * derive the origin from the script's URL so the bootstrap call hits\n * the API that owns the public key.\n * 2. Production default — `https://api.helpway.ai`. Matches the JSDoc\n * contract on the `apiUrl` prop.\n *\n * Earlier versions fell back to `window.location.origin` after the script\n * lookup, which broke any framework integration without the script tag\n * (Next App Router, Vite SPA, etc.) — bootstrap hit the consumer's own\n * server and 404'd. The `https://api.helpway.ai` fallback removes that\n * footgun.\n */\n/**\n * Synthetic conversation id prefix used for ephemeral proactive workflows.\n * The send-message flow checks for this prefix and routes to\n * `materializeFromProactive` instead of `sendMessage`/`createConversation`,\n * which is the moment we actually persist the conversation.\n */\nexport const EPHEMERAL_CONV_PREFIX = \"eph-\";\n\ninterface EphemeralProactivePayload {\n\tworkflowId: string;\n\tpathId: string;\n\tmessages: Array<{ stepId: string; text: string; sender: \"ai\" }>;\n\tquickReplies?: {\n\t\tstepId: string;\n\t\tprompt: string;\n\t\toptions: Array<{ id: string; label: string; goToPathId: string }>;\n\t};\n}\n\nfunction handleEphemeralProactive(\n\tstore: StoreApi<WidgetStore>,\n\tpayload: EphemeralProactivePayload,\n) {\n\tconst synthId = `${EPHEMERAL_CONV_PREFIX}${payload.workflowId}`;\n\tconst now = Date.now();\n\tconst lastMessage = payload.messages[payload.messages.length - 1];\n\tconst previewText = lastMessage?.text ?? \"\";\n\n\t// Inject the greeting (and quick replies) as if they came from the\n\t// server. Stagger timestamps so order is preserved if the visitor\n\t// scrolls through them later.\n\tconst items = payload.messages.map((m, i) => ({\n\t\tid: `${synthId}-msg-${m.stepId}`,\n\t\tconversationId: synthId,\n\t\ttype: \"message\" as const,\n\t\ttext: m.text,\n\t\tvisibility: \"public\" as const,\n\t\tuserId: null,\n\t\tvisitorId: null,\n\t\taiAgentId: null,\n\t\tcreatedAt: new Date(now - (payload.messages.length - i) * 100).toISOString(),\n\t\teditedAt: null,\n\t\tdeletedAt: null,\n\t}));\n\n\tif (payload.quickReplies) {\n\t\tconst qrFallback =\n\t\t\tpayload.quickReplies.prompt ||\n\t\t\tpayload.quickReplies.options.map((o) => `• ${o.label}`).join(\"\\n\");\n\t\titems.push({\n\t\t\tid: `${synthId}-qr-${payload.quickReplies.stepId}`,\n\t\t\tconversationId: synthId,\n\t\t\ttype: \"message\",\n\t\t\ttext: qrFallback,\n\t\t\tvisibility: \"public\",\n\t\t\tuserId: null,\n\t\t\tvisitorId: null,\n\t\t\taiAgentId: null,\n\t\t\tcreatedAt: new Date(now).toISOString(),\n\t\t\teditedAt: null,\n\t\t\tdeletedAt: null,\n\t\t\tmetadata: {\n\t\t\t\tkind: \"quick_replies\" as const,\n\t\t\t\tprompt: payload.quickReplies.prompt ?? null,\n\t\t\t\toptions: payload.quickReplies.options.map((o) => ({ id: o.id, label: o.label })),\n\t\t\t\tstepId: payload.quickReplies.stepId,\n\t\t\t},\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: metadata is widely typed\n\t\t} as any);\n\t}\n\n\tconst s = store.getState();\n\ts.addConversation({\n\t\tid: synthId,\n\t\ttitle: null,\n\t\tstatus: \"open\",\n\t\tlastMessageText: previewText,\n\t\tlastMessageAt: new Date(now).toISOString(),\n\t\tlastMessageSenderType: \"ai\",\n\t\tlastMessageSenderName: null,\n\t\tlastMessageSenderImage: null,\n\t\tassigneeName: null,\n\t\tassigneeImage: null,\n\t\tunreadCount: items.length,\n\t});\n\t// biome-ignore lint/suspicious/noExplicitAny: synthetic items match TimelineItem shape\n\ts.setMessages(synthId, items as any);\n\n\tif (!s.isOpen && previewText) {\n\t\tstore.setState({\n\t\t\tincomingPreview: {\n\t\t\t\ttext: previewText,\n\t\t\t\tconversationId: synthId,\n\t\t\t\ttimestamp: now,\n\t\t\t\tmessages: payload.messages.map((m) => ({ text: m.text })),\n\t\t\t\t...(payload.quickReplies\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tquickReplies: {\n\t\t\t\t\t\t\t\tstepId: payload.quickReplies.stepId,\n\t\t\t\t\t\t\t\tprompt: payload.quickReplies.prompt ?? null,\n\t\t\t\t\t\t\t\toptions: payload.quickReplies.options.map((o) => ({\n\t\t\t\t\t\t\t\t\tid: o.id,\n\t\t\t\t\t\t\t\t\tlabel: o.label,\n\t\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t});\n\t}\n}\n\nfunction inferApiUrl(): string {\n\tif (typeof document !== \"undefined\") {\n\t\tconst script = document.querySelector(\"script[data-key][src]\");\n\t\tif (script) {\n\t\t\tconst src = script.getAttribute(\"src\");\n\t\t\tif (src) {\n\t\t\t\ttry {\n\t\t\t\t\tconst url = new URL(src);\n\t\t\t\t\treturn `${url.protocol}//${url.host}`;\n\t\t\t\t} catch {\n\t\t\t\t\t// Fall through to the production default.\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn \"https://api.helpway.ai\";\n}\n","\"use client\";\n\nimport { formatRelativeTime, t } from \"@helpway/widget-core\";\nimport type {\n\tConversationSummary,\n\tDockSuggestion,\n\tWidgetContentTab,\n\tWidgetPlacement,\n} from \"@helpway/widget-core\";\nimport type { TimelineItem } from \"@helpway/types\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\n/** Resolve a label that might be a translation key (widget.*) or raw text */\nfunction resolveLabel(label: string): string {\n\tif (!label.startsWith(\"widget.\")) return label;\n\tconst resolved = t(label);\n\t// If t() returned the key itself (no translation found), humanize it\n\tif (resolved === label)\n\t\treturn label\n\t\t\t.replace(\"widget.\", \"\")\n\t\t\t.replace(/_/g, \" \")\n\t\t\t.replace(/^\\w/, (c) => c.toUpperCase());\n\treturn resolved;\n}\n\nimport { useAnnouncements } from \"../hooks/use-announcements\";\nimport type { UnseenAnnouncementEntry } from \"../hooks/use-announcements\";\nimport { useComposer } from \"../hooks/use-composer\";\nimport { useConversations } from \"../hooks/use-conversations\";\nimport { useI18n } from \"../hooks/use-i18n\";\nimport { usePresence } from \"../hooks/use-presence\";\nimport { useTimeline } from \"../hooks/use-timeline\";\nimport { useUnread } from \"../hooks/use-unread\";\nimport { useWidget } from \"../hooks/use-widget\";\nimport { useWidgetContext, useWidgetStore } from \"../provider\";\nimport { Composer } from \"./composer\";\nimport { WidgetDebugOverlay } from \"./debug-overlay\";\nimport { DockedBar } from \"../shell/docked-bar\";\nimport { ChevronRightIcon, DotsIcon, NewChatIcon } from \"./icons\";\nimport { ContentTabView } from \"./content/content-tab-view\";\nimport { ContentTabIconComponent } from \"./content/tab-icon\";\nimport { HomeIcon, MessagesIcon, SendIcon, XIcon } from \"./icons\";\nimport { AnnouncementPreviews } from \"./announcement-previews\";\nimport { MessageBubble } from \"./message-bubble\";\nimport { MessageList } from \"./message-list\";\nimport { MessagePreview } from \"./message-preview\";\nimport { stripMarkdown } from \"./strip-markdown\";\n\nimport type { SubView, Tab } from \"./default-widget/types\";\n\nconst EMPTY_CONTENT_TABS: WidgetContentTab[] = [];\n\n/**\n * Factory-default admin strings. If the admin never customized these\n * values, the widget falls back to t() so visitors see their locale's\n * translation from the CDN bundle instead of frozen English.\n *\n * Keep in sync with packages/api seed defaults + widget-core/src/i18n.ts.\n */\nconst DEFAULT_EN_WELCOME = \"Hi there 👋\\nHow can we help?\";\nconst DEFAULT_EN_SUBTITLE = \"Usually replies in minutes\";\n\n/**\n * Helpway brand mark — octagonal outer with stylized \"W\" inside. Used as\n * the widget's own fallback avatar when the customer hasn't configured a\n * custom avatar/preset and the host site didn't set a logo either. Keeps\n * unconfigured widgets looking intentional rather than generic.\n */\nfunction HelpwayMark({ className }: { className?: string }) {\n\treturn (\n\t\t<svg\n\t\t\tclassName={className}\n\t\t\twidth=\"100%\"\n\t\t\theight=\"100%\"\n\t\t\tviewBox=\"0 0 42 42\"\n\t\t\tfill=\"none\"\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\taria-hidden=\"true\"\n\t\t>\n\t\t\t<path\n\t\t\t\td=\"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\"\n\t\t\t\tfill=\"currentColor\"\n\t\t\t/>\n\t\t</svg>\n\t);\n}\n\n/**\n * WidgetLogo — chat-header avatar. Renders WHO is talking to the\n * visitor right now. Resolution chain:\n * 1. Active conversation's assigned support user (assigneeName +\n * assigneeImage from the widget API). When a human takes over a\n * conversation the visitor sees that human, not the AI agent.\n * 2. Agent uploaded image (agentConfig.avatarUrl)\n * 3. Agent icon preset (avatarPreset + brandColor)\n * 4. Website logo (website.logoUrl)\n * 5. Helpway brand mark (octagonal) as the true last-resort fallback\n *\n * The `forceAgent` escape hatch skips the assignee lookup — used by\n * surfaces that mean \"the agent\" specifically (welcome card, conversation\n * list rows where we want the persistent brand, etc.) rather than \"the\n * person currently helping you\".\n */\nexport function WidgetLogo({\n\tclassName,\n\tforceAgent = false,\n}: {\n\tclassName?: string;\n\tforceAgent?: boolean;\n}) {\n\tconst agentConfig = useWidgetStore((s) => s.agentConfig);\n\tconst logoUrl = useWidgetStore((s) => s.website?.logoUrl);\n\tconst activeId = useWidgetStore((s) => s.activeConversationId);\n\tconst assignee = useWidgetStore((s) => {\n\t\tif (forceAgent || !s.activeConversationId) return null;\n\t\tconst c = s.conversations.find((c) => c.id === s.activeConversationId);\n\t\treturn c?.assigneeName || c?.assigneeImage ? c : null;\n\t});\n\n\t// In the launcher bubble (forceAgent=true), uploaded images are\n\t// treated as brand logos — `contain` + padding so SVG/PNG marks\n\t// don't get cropped by the rounded bubble. In the chat-header\n\t// context, face-photo avatars keep `cover` behavior.\n\tconst logoClass = forceAgent ? \"hw-agent-img--logo\" : \"\";\n\n\t// Assigned human takes priority over the AI agent default — but only\n\t// when we actually have an active conversation we're rendering for.\n\tif (!forceAgent && activeId && assignee?.assigneeImage) {\n\t\treturn (\n\t\t\t<img\n\t\t\t\tsrc={assignee.assigneeImage}\n\t\t\t\talt={assignee.assigneeName ?? \"\"}\n\t\t\t\tclassName={`hw-agent-img ${className ?? \"\"}`}\n\t\t\t/>\n\t\t);\n\t}\n\n\t// Agent uploaded image\n\tif (agentConfig?.avatarUrl) {\n\t\treturn <img src={agentConfig.avatarUrl} alt=\"\" className={`hw-agent-img ${logoClass} ${className ?? \"\"}`} />;\n\t}\n\n\t// Agent icon preset — use the same CSS variable as the welcome hero\n\t// so both surfaces stay color-synced. `--hw-primary` is fed by either\n\t// the inline style on `.hw-widget` (from agentConfig.brandColor) or\n\t// a `theme` prop override; reading the literal `agentConfig.brandColor`\n\t// here used to drift apart from the hero whenever the prop won.\n\tif (agentConfig?.avatarPreset) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tclassName={`hw-agent-icon ${className ?? \"\"}`}\n\t\t\t\tstyle={{\n\t\t\t\t\tbackgroundColor: \"var(--hw-primary)\",\n\t\t\t\t\tdisplay: \"flex\",\n\t\t\t\t\talignItems: \"center\",\n\t\t\t\t\tjustifyContent: \"center\",\n\t\t\t\t\tborderRadius: 8,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<AgentPresetIcon presetId={agentConfig.avatarPreset} />\n\t\t\t</div>\n\t\t);\n\t}\n\n\t// Website logo — always a brand mark, never a face avatar. Apply\n\t// --logo class regardless of context so it stays uncropped in both\n\t// launcher bubble and chat-header circles.\n\tif (logoUrl) {\n\t\treturn <img src={logoUrl} alt=\"\" className={`hw-agent-img hw-agent-img--logo ${className ?? \"\"}`} />;\n\t}\n\n\treturn <HelpwayMark className={className} />;\n}\n\n/**\n * LauncherIcon — what the visitor sees on the always-visible bubble\n * BEFORE opening the widget. Brand-stable, doesn't change per\n * conversation. Resolution chain:\n * 1. Custom launcher icon (agentConfig.launcherIconUrl) — admin upload\n * 2. Agent avatar (avatarUrl) — same image as the chat header default\n * 3. Agent icon preset\n * 4. Website logo\n * 5. Helpway brand mark\n */\nfunction LauncherIcon({ className }: { className?: string }) {\n\tconst agentConfig = useWidgetStore((s) => s.agentConfig);\n\tconst [imgLoaded, setImgLoaded] = useState(false);\n\tconst imgSrc = agentConfig?.launcherIconUrl ?? null;\n\n\tuseEffect(() => {\n\t\tif (!imgSrc) return;\n\t\tsetImgLoaded(false);\n\t\tconst img = new Image();\n\t\timg.src = imgSrc;\n\t\tif (img.complete) { setImgLoaded(true); return; }\n\t\timg.onload = () => setImgLoaded(true);\n\t\timg.onerror = () => setImgLoaded(true);\n\t}, [imgSrc]);\n\n\tif (imgSrc) {\n\t\treturn (\n\t\t\t<img\n\t\t\t\tsrc={imgSrc}\n\t\t\t\talt=\"\"\n\t\t\t\tclassName={`hw-agent-img hw-agent-img--logo ${className ?? \"\"}`}\n\t\t\t\tstyle={{ opacity: imgLoaded ? 1 : 0, transition: \"opacity 0.15s ease\" }}\n\t\t\t/>\n\t\t);\n\t}\n\treturn <WidgetLogo className={className} forceAgent />;\n}\n\n/**\n * Exact SVG paths extracted from @central-icons-react at build time.\n * Pixel-perfect match with the dashboard picker. Using static trusted\n * strings (NOT user input) rendered via innerHTML — safe because content\n * is hardcoded SVG from our own icon library, never from external sources.\n */\nconst PRESET_SVG: Record<string, string> = {\n\t// Helpway brand mark — octagonal chamfer with stylized \"W\" inside.\n\t// First entry so it's the default preset for new orgs.\n\thelpway:\n\t\t'<path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M16.4 0H7.31L0 7.31V16.4L7.31 23.71H16.4L23.71 16.4V7.31L16.4 0ZM8.57 16.51L3.89 11.83L8.57 7.14C10.34 5.37 13.26 5.37 15.03 7.14L19.71 11.83L15.03 16.51C13.26 18.29 10.4 18.29 8.57 16.51Z\" fill=\"white\"/>',\n\tatom: '<path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M9.67904 3.29155C10.7467 1.56948 13.2537 1.56948 14.3214 3.29155L15.1308 4.59707C15.2462 4.7833 15.3634 4.9684 15.4823 5.15233C15.7005 5.1305 15.9185 5.10662 16.1363 5.08068L17.6626 4.89893C19.6747 4.65934 21.2396 6.61723 20.5571 8.52637L20.0401 9.97255C19.9664 10.1786 19.8947 10.3854 19.825 10.5927C19.9779 10.7493 20.1323 10.9045 20.2882 11.0583L21.3821 12.1371C22.8256 13.5609 22.2668 16.0039 20.3491 16.6605L18.895 17.1584C18.6876 17.2294 18.4809 17.3023 18.275 17.3772C18.2478 17.5943 18.2226 17.8117 18.1995 18.0294L18.0372 19.5565C17.823 21.572 15.5635 22.6577 13.8546 21.5695L12.5584 20.7442C12.3734 20.6264 12.1873 20.5103 12.0002 20.3961C11.8131 20.5103 11.627 20.6264 11.442 20.7442L10.1458 21.5695C8.4369 22.6577 6.17739 21.572 5.96321 19.5565L5.80094 18.0294C5.7778 17.8117 5.75263 17.5943 5.72541 17.3772C5.51949 17.3023 5.31282 17.2294 5.10542 17.1584L3.65133 16.6605C1.7336 16.0039 1.17475 13.5609 2.61829 12.1371L3.71216 11.0583C3.86807 10.9045 4.0225 10.7493 4.17541 10.5927C4.10567 10.3854 4.03395 10.1786 3.96028 9.97255L3.44329 8.52637C2.7608 6.61723 4.32567 4.65934 6.33777 4.89893L7.86408 5.08068C8.08191 5.10662 8.29993 5.1305 8.5181 5.15233C8.63698 4.9684 8.75417 4.7833 8.86963 4.59707L9.67904 3.29155ZM7.61407 6.4827L6.16966 6.31071C5.20357 6.19567 4.45578 7.13505 4.78207 8.04778L5.2716 9.41715C6.10452 8.48167 6.88648 7.5021 7.61407 6.4827ZM5.78854 10.961C7.04552 9.61105 8.19784 8.16742 9.23549 6.64268C11.076 6.78287 12.9244 6.78287 14.7649 6.64268C15.8026 8.16743 16.9549 9.61105 18.2119 10.961C17.6657 12.722 17.2545 14.522 16.9818 16.3454C15.2628 17.0169 13.5974 17.8181 12.0002 18.7422C10.403 17.8181 8.73761 17.0169 7.01863 16.3454C6.74592 14.522 6.3347 12.722 5.78854 10.961ZM4.65269 12.1275L3.61666 13.1494C2.92581 13.8308 3.19234 15.0006 4.11188 15.3154L5.48873 15.7868C5.27593 14.553 4.99684 13.3315 4.65269 12.1275ZM7.22343 17.9611L7.377 19.4062C7.47946 20.3704 8.56185 20.8926 9.38218 20.3703L10.6083 19.5895C9.51004 18.9865 8.38012 18.4429 7.22343 17.9611ZM13.3921 19.5895L14.6182 20.3703C15.4385 20.8926 16.5209 20.3704 16.6234 19.4062L16.777 17.9611C15.6203 18.4429 14.4903 18.9865 13.3921 19.5895ZM18.5117 15.7868L19.8885 15.3154C20.8081 15.0006 21.0746 13.8308 20.3837 13.1494L19.3477 12.1275C19.0035 13.3315 18.7245 14.553 18.5117 15.7868ZM18.7288 9.41715L19.2183 8.04778C19.5446 7.13505 18.7968 6.19567 17.8307 6.31071L16.3863 6.4827C17.1139 7.5021 17.8959 8.48167 18.7288 9.41715ZM13.8786 5.2756C12.6272 5.3429 11.3731 5.3429 10.1218 5.2756L10.8874 4.04072C11.3991 3.21542 12.6013 3.21542 13.113 4.04072L13.8786 5.2756Z\" fill=\"white\"/>',\n\tbrain:\n\t\t'<path d=\"M15 10C13.3431 10 12 8.65685 12 7\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M9 14C10.6569 14 12 15.3431 12 17\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M12 3.53516L12 20.2422\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M21 14.5C21 15.9633 20.102 17.2168 18.8271 17.7396C18.2888 19.6221 16.5553 21 14.5 21C13.5749 21 12.7151 20.7209 12 20.2422C11.285 20.7209 10.4251 21 9.5 21C7.44468 21 5.71119 19.6221 5.17291 17.7396C3.89797 17.2168 3 15.9633 3 14.5C3 13.5207 3.40223 12.6353 4.05051 12C3.40223 11.3647 3 10.4793 3 9.5C3 7.69511 4.36618 6.20931 6.12085 6.0203C6.55779 4.28478 8.12886 3 10 3C10.7286 3 11.4117 3.19479 12 3.53513C12.5883 3.19479 13.2714 3 14 3C15.8711 3 17.4422 4.28478 17.8792 6.0203C19.6338 6.20931 21 7.69511 21 9.5C21 10.4793 20.5978 11.3647 19.9495 12C20.5978 12.6353 21 13.5207 21 14.5Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\trobot:\n\t\t'<path d=\"M12 4H7C5.89543 4 5 4.89543 5 6V11C5 12.1046 5.89543 13 7 13H17C18.1046 13 19 12.1046 19 11V6C19 4.89543 18.1046 4 17 4H12ZM12 4V2M6 15L4 17M6 15C6 18.3137 8.68629 21 12 21C15.3137 21 18 18.3137 18 15M6 15V13M18 15L20 17M18 15V13M9 8V9M15 8V9\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tsparkle:\n\t\t'<path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M21 12.5C14.75 12.5 12 15.4028 12 22C12 15.4028 9.25 12.5 3 12.5C9.25 12.5 12 9.59722 12 3C12 9.59722 14.75 12.5 21 12.5Z\" stroke=\"white\" stroke-width=\"2\" stroke-linejoin=\"round\"/>',\n\tbolt: '<path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M13.1981 20.0571C11.7326 20.0571 10.2936 19.5252 9.46756 18.3817L9.1762 19.7304L3.79688 22.5824L4.3776 19.7304L8.2951 2H13.0916L11.7059 8.24953C12.8251 7.02621 13.8643 6.57412 15.1967 6.57412C18.0746 6.57412 19.9931 8.46227 19.9931 11.9194C19.9931 15.483 17.7815 20.0571 13.1981 20.0571ZM15.0368 12.9301C15.0368 14.5788 13.8643 15.8287 12.3455 15.8287C11.4927 15.8287 10.72 15.5096 10.2137 14.9511L10.9598 11.6802C11.5194 11.1216 12.1589 10.8025 12.905 10.8025C14.0509 10.8025 15.0368 11.6536 15.0368 12.9301Z\" fill=\"white\"/>',\n\tagent:\n\t\t'<path d=\"M12 8.5V12M12 12H8C6.89543 12 6 12.8954 6 14V15.5M12 12H16C17.1046 12 18 12.8954 18 14V15.5\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><circle cx=\"12\" cy=\"6\" r=\"2.5\" stroke=\"white\" stroke-width=\"2\"/><circle cx=\"6\" cy=\"18\" r=\"2.5\" stroke=\"white\" stroke-width=\"2\"/><circle cx=\"18\" cy=\"18\" r=\"2.5\" stroke=\"white\" stroke-width=\"2\"/>',\n\tbubble:\n\t\t'<path d=\"M4.00195 6.00003C4.00195 4.89546 4.89738 4.00003 6.00195 4.00002L18.0019 4C19.1065 4 20.002 4.89543 20.002 6V16.0358C20.002 17.1403 19.1065 18.0358 18.002 18.0358L15.3757 18.0358C15.1427 18.0358 14.9171 18.1171 14.7377 18.2657L11.9977 20.5358L9.29398 18.2694C9.11393 18.1185 8.8865 18.0358 8.65157 18.0358H6.00195C4.89738 18.0358 4.00195 17.1403 4.00195 16.0358V6.00003Z\" fill=\"white\"/><path d=\"M13.2395 9.43518L12.5426 7.62334C12.4561 7.39842 12.24 7.25 11.999 7.25C11.758 7.25 11.5419 7.39842 11.4554 7.62334L10.7586 9.43518C10.657 9.69927 10.4483 9.90797 10.1842 10.0095L8.37236 10.7064C8.14744 10.7929 7.99902 11.009 7.99902 11.25C7.99902 11.491 8.14744 11.7071 8.37236 11.7936L10.1842 12.4905C10.4483 12.592 10.657 12.8007 10.7586 13.0648L11.4554 14.8767C11.5419 15.1016 11.758 15.25 11.999 15.25C12.24 15.25 12.4561 15.1016 12.5426 14.8767L13.2395 13.0648C13.3411 12.8007 13.5498 12.592 13.8138 12.4905L15.6257 11.7936C15.8506 11.7071 15.999 11.491 15.999 11.25C15.999 11.009 15.8506 10.7929 15.6257 10.7064L13.8138 10.0095C13.5498 9.90797 13.3411 9.69927 13.2395 9.43518Z\" fill=\"white\"/>',\n\tlightbulb:\n\t\t'<path d=\"M10 21H14M15.6076 15C17.6404 13.7751 19 11.5463 19 9C19 5.13401 15.866 2 12 2C8.13401 2 5 5.13401 5 9C5 11.5463 6.35958 13.7751 8.39241 15M15.6076 15C15.4111 15.1184 15.2084 15.2274 15 15.3264V17C15 17.5523 14.5523 18 14 18H10C9.44772 18 9 17.5523 9 17V15.3264C8.7916 15.2274 8.58886 15.1184 8.39241 15M15.6076 15H8.39241\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\twand: '<path d=\"M11.3908 12.6089L4 19.9996\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M18.3943 5.2792C18.5999 5.1944 18.8056 5.40008 18.7208 5.60565L17.1697 9.36581C17.1339 9.45248 17.1497 9.55186 17.2105 9.62323L19.8476 12.72C19.9918 12.8894 19.8597 13.1485 19.638 13.1314L15.5826 12.8182C15.4891 12.811 15.3994 12.8566 15.3503 12.9365L13.22 16.4015C13.1035 16.591 12.8163 16.5455 12.764 16.3293L11.8087 12.3756C11.7867 12.2844 11.7156 12.2133 11.6244 12.1913L7.67069 11.236C7.45453 11.1837 7.40903 10.8964 7.59847 10.78L11.0635 8.64965C11.1434 8.60055 11.189 8.51089 11.1818 8.41743L10.8686 4.36198C10.8515 4.14027 11.1106 4.00822 11.2799 4.15239L14.3768 6.78952C14.4481 6.8503 14.5475 6.86604 14.6342 6.83029L18.3943 5.2792Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tchip: '<path d=\"M8 5.5V4M12 5.5V4M16 5.5V4M8 20V18.5M12 20V18.5M16 20V18.5M8.75 15H15.25C15.6642 15 16 14.6642 16 14.25V9.75C16 9.33579 15.6642 9 15.25 9H8.75C8.33579 9 8 9.33579 8 9.75V14.25C8 14.6642 8.33579 15 8.75 15ZM6 20H18C19.1046 20 20 19.1046 20 18V6C20 4.89543 19.1046 4 18 4H6C4.89543 4 4 4.89543 4 6V18C4 19.1046 4.89543 20 6 20Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tcode: '<path d=\"M10 9.5L8.20711 11.2929C7.81658 11.6834 7.81658 12.3166 8.20711 12.7071L10 14.5M14 9.5L15.7929 11.2929C16.1834 11.6834 16.1834 12.3166 15.7929 12.7071L14 14.5M6 20H18C19.1046 20 20 19.1046 20 18V6C20 4.89543 19.1046 4 18 4H6C4.89543 4 4 4.89543 4 6V18C4 19.1046 4.89543 20 6 20Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tlightning:\n\t\t'<path d=\"M4.11593 12.2764L8.61593 3.27639C8.70063 3.107 8.87376 3 9.06315 3H17.121C17.5097 3 17.7497 3.42399 17.5498 3.75725L15.4585 7.24275C15.2585 7.57601 15.4986 8 15.8872 8H20.6909C21.1505 8 21.3666 8.56776 21.0235 8.87338L7.38117 21.0236C7.00034 21.3628 6.41568 20.981 6.57301 20.4959L8.79194 13.6543C8.8967 13.3312 8.6559 13 8.31633 13H4.56314C4.19145 13 3.94971 12.6088 4.11593 12.2764Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tvibe: '<path d=\"M18.9847 2.4329C18.9568 2.18651 18.7485 2.00025 18.5005 2C18.2525 1.99975 18.0438 2.18557 18.0154 2.43191C17.838 3.96993 16.9699 4.83801 15.4319 5.01541C15.1856 5.04382 14.9997 5.25253 15 5.5005C15.0003 5.74847 15.1865 5.9568 15.4329 5.9847C16.9491 6.15645 17.8774 7.01617 18.0141 8.55536C18.0365 8.80725 18.2477 9.00028 18.5005 9C18.7534 8.99971 18.9642 8.80621 18.986 8.55426C19.1173 7.03683 20.0368 6.11734 21.5543 5.98599C21.8062 5.96418 21.9997 5.75344 22 5.50055C22.0003 5.24766 21.8073 5.03648 21.5554 5.01411C20.0162 4.87738 19.1564 3.94911 18.9847 2.4329Z\" fill=\"white\"/><path d=\"M2 20C2 16.6863 4.68629 14 8 14H8.5\" fill=\"white\"/><path d=\"M11 20L12.6892 14.0879C12.8732 13.444 13.4617 13 14.1315 13H20.5417C21.2725 13 21.8001 13.6995 21.5994 14.4022L20.2072 19.2747C20.0846 19.704 19.6922 20 19.2457 20H11ZM11 20H7\" fill=\"white\"/><circle cx=\"8.75\" cy=\"7.5\" r=\"3.5\" stroke=\"white\" stroke-width=\"2\"/>',\n\tnetwork:\n\t\t'<path d=\"M12 6.8501L16 7.2501M17.75 10.0001L16.55 14.0001M13.5 14.3572L12 12.0001L10.4091 9.5001M6.25 14.0001L7.45 10.0001M8 16.7501L12 17.1501\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><circle cx=\"18.5\" cy=\"7.5\" r=\"2.5\" stroke=\"white\" stroke-width=\"2\"/><circle cx=\"5.5\" cy=\"16.5\" r=\"2.5\" stroke=\"white\" stroke-width=\"2\"/><circle cx=\"8.5\" cy=\"6.5\" r=\"3.5\" stroke=\"white\" stroke-width=\"2\"/><circle cx=\"15.5\" cy=\"17.5\" r=\"3.5\" stroke=\"white\" stroke-width=\"2\"/>',\n\tconsole:\n\t\t'<path d=\"M7.5 8L9.25 9.75L7.5 11.5M12 11.5H14M6 20H18C19.1046 20 20 19.1046 20 18V6C20 4.89543 19.1046 4 18 4H6C4.89543 4 4 4.89543 4 6V18C4 19.1046 4.89543 20 6 20Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tprompt:\n\t\t'<path d=\"M6 5H5C3.89543 5 3 5.89543 3 7V8\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M18 5H19C20.1046 5 21 5.89543 21 7V8\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M21 16V17C21 18.1046 20.1046 19 19 19H18\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M6 19H5C3.89543 19 3 18.1046 3 17V16\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M8 10H16\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M8 14H14\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tglobe:\n\t\t'<path d=\"M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M21 12H3\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M12 21C10.067 21 8.5 16.9706 8.5 12C8.5 7.02944 10.067 3 12 3C13.933 3 15.5 7.02944 15.5 12C15.5 16.9706 13.933 21 12 21Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\ttarget:\n\t\t'<path d=\"M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M17 12C17 14.7614 14.7614 17 12 17C9.23858 17 7 14.7614 7 12C7 9.23858 9.23858 7 12 7C14.7614 7 17 9.23858 17 12Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M13 12C13 12.5523 12.5523 13 12 13C11.4477 13 11 12.5523 11 12C11 11.4477 11.4477 11 12 11C12.5523 11 13 11.4477 13 12Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tdiamond:\n\t\t'<path d=\"M8.28256 4C7.77978 4 7.29545 4.18937 6.926 4.53039L2.53016 8.58809C1.69548 9.35857 1.66929 10.6687 2.47251 11.4719L10.5864 19.5858C11.3674 20.3668 12.6338 20.3668 13.4148 19.5858L21.5287 11.4719C22.3319 10.6687 22.3057 9.35857 21.471 8.58809L17.0752 4.53039C16.7057 4.18937 16.2214 4 15.7186 4H8.28256Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M9.5 8L7.5 10L9.5 12\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tstar: '<path d=\"M11.5288 2.29524C11.7179 1.90159 12.2821 1.90159 12.4712 2.29524L14.9458 7.44648C15.0219 7.60491 15.1735 7.71434 15.3487 7.73728L21.0456 8.4832C21.4809 8.5402 21.6552 9.07312 21.3368 9.37342L17.1693 13.303C17.0412 13.4238 16.9832 13.6009 17.0154 13.7735L18.0616 19.3857C18.1416 19.8146 17.6852 20.144 17.2993 19.9359L12.249 17.2133C12.0937 17.1296 11.9063 17.1296 11.751 17.2133L6.70073 19.9359C6.3148 20.144 5.85841 19.8146 5.93837 19.3857L6.98459 13.7735C7.01677 13.6009 6.95885 13.4238 6.83068 13.303L2.66324 9.37342C2.34476 9.07312 2.51909 8.5402 2.95444 8.4832L8.65127 7.73728C8.82648 7.71434 8.97811 7.60491 9.05422 7.44648L11.5288 2.29524Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\theart:\n\t\t'<path d=\"M21 10C21 15.75 12.75 20 12 20C11.25 20 3 15.75 3 10C3 6 5.5 4 8 4C10.5 4 12 5.5 12 5.5C12 5.5 13.5 4 16 4C18.5 4 21 6 21 10Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tshield:\n\t\t'<path d=\"M20 7.17737C20 6.32338 19.4578 5.56361 18.6502 5.286L12.6502 3.2235C12.2288 3.07866 11.7712 3.07866 11.3498 3.22349L5.34984 5.286C4.54224 5.56361 4 6.32338 4 7.17737V11.9123C4 16.8848 8 19 12 21.1579C16 19 20 16.8848 20 11.9123V7.17737Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\trocket:\n\t\t'<path d=\"M3 21H5C6.10457 21 7 20.1046 7 19C7 17.8954 6.10457 17 5 17C3.89543 17 3 17.8954 3 19V21Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M7.00098 13H4.76717C3.98987 13 3.50976 12.152 3.90968 11.4855L5.41837 8.97101C5.77982 8.3686 6.43083 8 7.13336 8H11.251C13.7671 5.25513 16.4925 3.3474 20.0017 3.04278C20.5519 2.99502 21.006 3.44906 20.9582 3.99927C20.6536 7.50845 18.7459 10.2339 16.001 12.75V16.8676C16.001 17.5701 15.6324 18.2212 15.03 18.5826L12.5155 20.0913C11.849 20.4912 11.001 20.0111 11.001 19.2338V17L7.00098 13Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M7 13L11.25 8\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M16 12.75L11 17\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tcrown:\n\t\t'<path d=\"M4.16831 17.4079L2 7L8 10L12 4L16 10L22 7L19.8317 17.4079C19.6385 18.3353 18.8211 19 17.8737 19H6.12628C5.17892 19 4.36153 18.3353 4.16831 17.4079Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\ttrophy:\n\t\t'<path d=\"M12.0039 17V14\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M18 5H19C20.1046 5 21 5.89543 21 7C21 8.65685 19.6569 10 18 10\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M6 5C6 3.89543 6.89543 3 8 3H16C17.1046 3 18 3.89543 18 5V8C18 11.3137 15.3137 14 12 14C8.68629 14 6 11.3137 6 8V5Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M7 19C7 17.8954 7.89543 17 9 17H15C16.1046 17 17 17.8954 17 19C17 20.1046 16.1046 21 15 21H9C7.89543 21 7 20.1046 7 19Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M6 5H5C3.89543 5 3 5.89543 3 7C3 8.65685 4.34315 10 6 10\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tcompass:\n\t\t'<path d=\"M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M14.6558 8.73023L10.5513 9.84965C10.2097 9.94281 9.94281 10.2097 9.84965 10.5513L8.73023 14.6558C8.62843 15.0291 8.97092 15.3716 9.34417 15.2698L13.4487 14.1504C13.7903 14.0572 14.0572 13.7903 14.1504 13.4487L15.2698 9.34417C15.3716 8.97092 15.0291 8.62843 14.6558 8.73023Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tfire: '<path d=\"M19.5 13.8122C19.5 23.3907 4.5 23.4012 4.5 13.8122C4.5 6.61352 12 2.5 12 2.5C12 2.5 19.5 6.61352 19.5 13.8122Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M15.5 17.4061C15.5 22.1954 8.5 22.2006 8.5 17.4061C8.5 13.8068 12 11.75 12 11.75C12 11.75 15.5 13.8068 15.5 17.4061Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tkey: '<path d=\"M20.8002 9.8753L20.0194 10.5L20.0194 10.5L20.8002 9.8753ZM22.0002 11.3753L21.2194 12V12L22.0002 11.3753ZM22.0002 12.6247L21.2194 12V12L22.0002 12.6247ZM20.8002 14.1247L20.0194 13.5L20.0194 13.5L20.8002 14.1247ZM18 14.5L17.5528 15.3944C17.6916 15.4639 17.8448 15.5 18 15.5V14.5ZM16 13.5L16.4472 12.6056C16.1657 12.4648 15.8343 12.4648 15.5528 12.6056L16 13.5ZM14 14.5V15.5C14.1552 15.5 14.3084 15.4639 14.4472 15.3944L14 14.5ZM11.0141 9.01843L11.8165 8.42152L11.8165 8.42152L11.0141 9.01843ZM11.0141 14.9816L10.2118 14.3847V14.3847L11.0141 14.9816ZM6.5 12C6.5 11.7239 6.72386 11.5 7 11.5V13.5C7.82843 13.5 8.5 12.8284 8.5 12H6.5ZM7 11.5C7.27614 11.5 7.5 11.7239 7.5 12H5.5C5.5 12.8284 6.17157 13.5 7 13.5V11.5ZM7.5 12C7.5 12.2761 7.27614 12.5 7 12.5V10.5C6.17157 10.5 5.5 11.1716 5.5 12H7.5ZM7 12.5C6.72386 12.5 6.5 12.2761 6.5 12H8.5C8.5 11.1716 7.82843 10.5 7 10.5V12.5ZM6.5 13H7.5V11H6.5V13ZM7 16C4.79086 16 3 14.2091 3 12H1C1 15.3137 3.68629 18 7 18V16ZM3 12C3 9.79086 4.79086 8 7 8V6C3.68629 6 1 8.68629 1 12H3ZM20.0194 10.5L21.2194 12L22.7811 10.7506L21.5811 9.25061L20.0194 10.5ZM21.2194 12L20.0194 13.5L21.5811 14.7494L22.7811 13.2494L21.2194 12ZM20.0194 13.5H18V15.5H20.0194V13.5ZM18.4472 13.6056L16.4472 12.6056L15.5528 14.3944L17.5528 15.3944L18.4472 13.6056ZM15.5528 12.6056L13.5528 13.6056L14.4472 15.3944L16.4472 14.3944L15.5528 12.6056ZM11.9079 10.5H20.0194V8.5H11.9079V10.5ZM7 8C8.31459 8 9.48107 8.63311 10.2118 9.61533L11.8165 8.42152C10.7246 6.9539 8.97356 6 7 6V8ZM14 13.5H11.9079V15.5H14V13.5ZM10.2118 14.3847C9.48107 15.3669 8.31459 16 7 16V18C8.97356 18 10.7246 17.0461 11.8165 15.5785L10.2118 14.3847ZM11.9079 13.5C11.1751 13.5 10.5749 13.8967 10.2118 14.3847L11.8165 15.5785C11.8445 15.5408 11.8734 15.5183 11.8929 15.5074C11.9106 15.4976 11.9148 15.5 11.9079 15.5V13.5ZM20.0194 13.5L20.0194 13.5V15.5C20.6269 15.5 21.2016 15.2238 21.5811 14.7494L20.0194 13.5ZM11.9079 8.5C11.9148 8.5 11.9106 8.50239 11.8929 8.49258C11.8734 8.48172 11.8445 8.45923 11.8165 8.42152L10.2118 9.61533C10.5749 10.1033 11.1751 10.5 11.9079 10.5V8.5ZM21.2194 12V12L22.7811 13.2494C23.3655 12.519 23.3655 11.481 22.7811 10.7506L21.2194 12ZM21.5811 9.25061C21.2016 8.77618 20.6269 8.5 20.0194 8.5V10.5L20.0194 10.5L21.5811 9.25061Z\" fill=\"white\"/>',\n\tlock: '<path d=\"M5 12C5 10.8954 5.89543 10 7 10H17C18.1046 10 19 10.8954 19 12V19C19 20.1046 18.1046 21 17 21H7C5.89543 21 5 20.1046 5 19V12Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M16 9.5V7C16 4.79086 14.2091 3 12 3C9.79086 3 8 4.79086 8 7V9.5\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M12 14V17\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tbookmark:\n\t\t'<path d=\"M19 19.9948V5C19 3.89543 18.1046 3 17 3H7C5.89543 3 5 3.89543 5 5V19.9948C5 20.8047 5.91243 21.2787 6.57503 20.813L10.8499 17.8083C11.54 17.3233 12.46 17.3233 13.1501 17.8083L17.425 20.813C18.0876 21.2787 19 20.8047 19 19.9948Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tstore:\n\t\t'<path d=\"M4 10V18C4 19.1046 4.89543 20 6 20H18C19.1046 20 20 19.1046 20 18V10\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M14.4996 4H9.49956L9.2133 8.00762C9.0978 9.62461 10.3785 11 11.9996 11C13.6207 11 14.9013 9.62461 14.7858 8.00763L14.4996 4Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M9.50047 4H5.73506C4.73976 4 3.89592 4.73186 3.75516 5.71716L3.4699 7.71396C3.22214 9.44831 4.56792 11 6.31987 11C7.83025 11 9.08385 9.83276 9.19146 8.32621L9.50047 4Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M18.2654 4H14.5L14.809 8.32621C14.9166 9.83276 16.1702 11 17.6806 11C19.4326 11 20.7783 9.44831 20.5306 7.71396L20.2453 5.71716C20.1046 4.73186 19.2607 4 18.2654 4Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tbag: '<path d=\"M15.0001 8C15.0001 9.65685 13.6569 11 12.0001 11C10.3432 11 9.00008 9.65685 9.00008 8M4.88288 5.87524L4.13288 17.8752C4.06092 19.0266 4.97534 20 6.12899 20H17.8712C19.0248 20 19.9392 19.0266 19.8673 17.8752L19.1173 5.87524C19.0514 4.82117 18.1773 4 17.1212 4H6.87899C5.82286 4 4.94876 4.82117 4.88288 5.87524Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\t\"credit-card\":\n\t\t'<path d=\"M3 10V17C3 18.1046 3.89543 19 5 19H19C20.1046 19 21 18.1046 21 17V10M3 10V7C3 5.89543 3.89543 5 5 5H19C20.1046 5 21 5.89518 21 6.99975V10M3 10H21\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\treceipt:\n\t\t'<path d=\"M9 8H15M9 12H11M19 21V5C19 3.89543 18.1046 3 17 3H7C5.89543 3 5 3.89543 5 5V21L7.33333 19L9.66667 21L12 19L14.3333 21L16.6667 19L19 21Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tbank: '<path d=\"M11.1056 2.94723L3.68328 6.65838C3.26452 6.86776 3 7.29576 3 7.76395C3 8.44661 3.55341 9.00002 4.23607 9.00002H19.7639C20.4466 9.00002 21 8.44661 21 7.76395C21 7.29576 20.7355 6.86776 20.3167 6.65838L12.8944 2.94723C12.3314 2.6657 11.6686 2.6657 11.1056 2.94723Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M19.6126 20H4.38749C3.70493 20 3.22296 19.3313 3.4388 18.6838L3.54421 18.3675C3.81644 17.5509 4.58072 17 5.44158 17H18.5585C19.4194 17 20.1837 17.5509 20.4559 18.3675L20.5613 18.6838C20.7772 19.3313 20.2952 20 19.6126 20Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M19 9V17\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M15 17V9\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M5 9V17\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M9 17V9\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\twallet:\n\t\t'<path d=\"M3 8V7C3 5.89543 3.89543 5 5 5H19C20.1046 5 21 5.89543 21 7V8M3 8H21M3 8V11M21 8V11M21 11V17C21 18.1046 20.1046 19 19 19H5C3.89543 19 3 18.1046 3 17V11M21 11H15C15 12.1046 14.1046 13 13 13H11C9.89543 13 9 12.1046 9 11H3\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tpackage:\n\t\t'<path d=\"M9 4V7.5C9 8.32843 9.67157 9 10.5 9H13.5C14.3284 9 15 8.32843 15 7.5V4M14 16H16M4 6V18C4 19.1046 4.89543 20 6 20H18C19.1046 20 20 19.1046 20 18V6C20 4.89543 19.1046 4 18 4H6C4.89543 4 4 4.89543 4 6Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\ttruck:\n\t\t'<path d=\"M10 16.5C10 17.8807 8.88071 19 7.5 19C6.11929 19 5 17.8807 5 16.5C5 15.1193 6.11929 14 7.5 14C8.88071 14 10 15.1193 10 16.5Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M19 16.5C19 17.8807 17.8807 19 16.5 19C15.1193 19 14 17.8807 14 16.5C14 15.1193 15.1193 14 16.5 14C17.8807 14 19 15.1193 19 16.5Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M10 16H14\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M9 14V7H6.07037C5.40166 7 4.7772 7.3342 4.40627 7.8906L3.3359 9.49615C3.11688 9.82469 3 10.2107 3 10.6056V14.2857C3 15.2325 3.76751 16 4.71429 16\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M9 9V7C9 5.89543 9.89543 5 11 5H19C20.1046 5 21 5.89543 21 7V14C21 15.1046 20.1046 16 19 16\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tmegaphone:\n\t\t'<path d=\"M17.9961 14.0001C19.6529 14.0001 20.9961 12.657 20.9961 11.0001C20.9961 9.34325 19.6529 8.0001 17.9961 8.0001M12.8254 18.0001C12.4136 19.1653 11.3023 20.0001 9.99609 20.0001C8.33924 20.0001 6.99609 18.657 6.99609 17.0001V15.5001M6.99829 6.5001V15.5001M17.9961 5.73752V16.2627C17.9961 17.617 16.6784 18.5797 15.3882 18.1681L4.38819 14.6585C3.55899 14.394 2.99609 13.6235 2.99609 12.7532V9.24704C2.99609 8.37667 3.55899 7.60622 4.38819 7.34167L15.3882 3.83215C16.6784 3.42051 17.9961 4.38325 17.9961 5.73752Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\temail:\n\t\t'<path d=\"M20.782 6.09202L19.891 6.54601L19.891 6.54601L20.782 6.09202ZM19.908 5.21799L20.362 4.32698V4.32698L19.908 5.21799ZM4.09202 5.21799L3.63803 4.32698L3.63803 4.32698L4.09202 5.21799ZM3.21799 6.09202L2.32698 5.63803L2.32698 5.63803L3.21799 6.09202ZM3.21799 17.908L4.10899 17.454L4.10899 17.454L3.21799 17.908ZM4.09202 18.782L4.54601 17.891H4.54601L4.09202 18.782ZM19.908 18.782L20.362 19.673V19.673L19.908 18.782ZM20.782 17.908L19.891 17.454L19.891 17.454L20.782 17.908ZM21 8.2H20V15.8H21H22V8.2H21ZM21 8.2H22C22 7.65645 22.0008 7.18864 21.9694 6.80497C21.9371 6.40963 21.8658 6.01641 21.673 5.63803L20.782 6.09202L19.891 6.54601C19.9162 6.59545 19.9539 6.69617 19.9761 6.96784C19.9992 7.25117 20 7.62345 20 8.2H21ZM20.782 6.09202L21.673 5.63803C21.3854 5.07354 20.9265 4.6146 20.362 4.32698L19.908 5.21799L19.454 6.10899C19.6422 6.20487 19.7951 6.35785 19.891 6.54601L20.782 6.09202ZM17.8 5V6C18.3766 6 18.7488 6.00078 19.0322 6.02393C19.3038 6.04612 19.4045 6.0838 19.454 6.10899L19.908 5.21799L20.362 4.32698C19.9836 4.13419 19.5904 4.06287 19.195 4.03057C18.8114 3.99922 18.3436 4 17.8 4V5ZM6.2 5V6H17.8V5V4H6.2V5ZM6.2 5V4C5.65645 4 5.18864 3.99922 4.80497 4.03057C4.40963 4.06287 4.01641 4.13419 3.63803 4.32698L4.09202 5.21799L4.54601 6.10899C4.59545 6.0838 4.69617 6.04612 4.96784 6.02393C5.25117 6.00078 5.62345 6 6.2 6V5ZM3.21799 6.09202L4.10899 6.54601C4.20487 6.35785 4.35785 6.20487 4.54601 6.10899L4.09202 5.21799L3.63803 4.32698C3.07354 4.6146 2.6146 5.07354 2.32698 5.63803L3.21799 6.09202ZM3 8.2H4C4 7.62345 4.00078 7.25117 4.02393 6.96784C4.04612 6.69617 4.0838 6.59545 4.10899 6.54601L3.21799 6.09202L2.32698 5.63803C2.13419 6.01641 2.06287 6.40963 2.03057 6.80497C1.99922 7.18864 2 7.65645 2 8.2H3ZM3 15.8H4V8.2H3H2V15.8H3ZM3 15.8H2C2 16.3435 1.99922 16.8114 2.03057 17.195C2.06287 17.5904 2.13419 17.9836 2.32698 18.362L3.21799 17.908L4.10899 17.454C4.0838 17.4045 4.04612 17.3038 4.02393 17.0322C4.00078 16.7488 4 16.3765 4 15.8H3ZM4.09202 18.782L4.54601 17.891C4.35785 17.7951 4.20487 17.6421 4.10899 17.454L3.21799 17.908L2.32698 18.362C2.6146 18.9265 3.07354 19.3854 3.63803 19.673L4.09202 18.782ZM6.2 19V18C5.62345 18 5.25117 17.9992 4.96784 17.9761C4.69617 17.9539 4.59545 17.9162 4.54601 17.891L4.09202 18.782L3.63803 19.673C4.01641 19.8658 4.40963 19.9371 4.80497 19.9694C5.18864 20.0008 5.65645 20 6.2 20V19ZM17.8 19V18H6.2V19V20H17.8V19ZM17.8 19V20C18.3436 20 18.8114 20.0008 19.195 19.9694C19.5904 19.9371 19.9836 19.8658 20.362 19.673L19.908 18.782L19.454 17.891C19.4045 17.9162 19.3038 17.9539 19.0322 17.9761C18.7488 17.9992 18.3766 18 17.8 18V19ZM20.782 17.908L19.891 17.454C19.7951 17.6421 19.6422 17.7951 19.454 17.891L19.908 18.782L20.362 19.673C20.9265 19.3854 21.3854 18.9265 21.673 18.362L20.782 17.908ZM21 15.8H20C20 16.3765 19.9992 16.7488 19.9761 17.0322C19.9539 17.3038 19.9162 17.4045 19.891 17.454L20.782 17.908L21.673 18.362C21.8658 17.9836 21.9371 17.5904 21.9694 17.195C22.0008 16.8114 22 16.3435 22 15.8H21Z\" fill=\"white\"/><path d=\"M21 5.63635L13.2665 11.9638C12.5297 12.5666 11.4703 12.5666 10.7335 11.9638L3 5.63635\" fill=\"white\"/>',\n\tbell: '<path d=\"M4.69376 9.44981C5.15435 5.76511 8.28661 3 12 3C15.7134 3 18.8456 5.76511 19.3062 9.44981L19.969 14.7519C20.1182 15.9456 19.1874 17 17.9844 17H6.01555C4.81256 17 3.88178 15.9456 4.031 14.7519L4.69376 9.44981Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M16 17C16 19.2091 14.2091 21 12 21C9.79086 21 8 19.2091 8 17\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tpeople:\n\t\t'<path d=\"M15.5 6.5C15.5 8.433 13.933 10 12 10C10.067 10 8.5 8.433 8.5 6.5C8.5 4.567 10.067 3 12 3C13.933 3 15.5 4.567 15.5 6.5Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M12.0011 13C8.60997 13 6.03711 15.0143 4.9836 17.8629C4.5748 18.9682 5.51944 20 6.69796 20H17.3043C18.4828 20 19.4274 18.9682 19.0186 17.8629C17.9651 15.0143 15.3923 13 12.0011 13Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tsupport:\n\t\t'<path d=\"M6 10H4.5C3.67157 10 3 10.6716 3 11.5V15C3 15.8284 3.67157 16.5 4.5 16.5H6V10Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M20 10H18.5V16.5H20C20.8284 16.5 21.5 15.8284 21.5 15V11.5C21.5 10.6716 20.8284 10 20 10Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M19.5 10V9.75C19.5 6.02208 16.2541 3 12.25 3C8.24594 3 5 6.02208 5 9.75V10\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M12 19V19.5C12 20.3284 12.6716 21 13.5 21H15.25C17.7353 21 19.75 18.9853 19.75 16.5\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\thandshake:\n\t\t'<path d=\"M11.8305 5.68856C9.57907 3.43715 5.92881 3.43715 3.6774 5.68856C1.57785 7.78811 1.40103 11.1544 3.42019 13.3313C5.71921 15.8101 8.14783 18.1408 10.7345 20.3519C11.4619 20.9737 12.5313 20.9737 13.2587 20.3519C15.8453 18.1408 18.2739 15.8101 20.573 13.3313C22.5921 11.1544 22.4153 7.78811 20.3158 5.68856C18.0644 3.43715 14.4141 3.43715 12.1627 5.68856L8.8146 9.03664C8.22881 9.62243 8.22881 10.5722 8.8146 11.158C9.98617 12.3295 11.8857 12.3295 13.0572 11.158L13.7643 10.4509C14.1549 10.0603 14.788 10.0603 15.1786 10.4509L18.7141 13.9864\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tpill: '<path d=\"M17.4541 10.0962C18.6109 8.31497 18.4083 5.90826 16.8462 4.34619C15.0513 2.55127 12.1411 2.55127 10.3462 4.34619L4.34619 10.3462C2.55127 12.1411 2.55127 15.0513 4.34619 16.8462C5.90826 18.4083 8.31497 18.6109 10.0962 17.4541\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M7.5 7.5L11 11\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M16.5 20.5L14.5 10.5\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><circle cx=\"15.5\" cy=\"15.5\" r=\"5.5\" stroke=\"white\" stroke-width=\"2\"/>',\n\t\"heart-beat\":\n\t\t'<path d=\"M16 12H14.5L13 14L10.5 10L9.25 12H8M12 5.76835C18.1619 -0.481837 28.7252 11.1257 12 20.5C-4.72523 11.1257 5.83803 -0.481838 12 5.76835Z\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n\tbook: '<path d=\"M9 6C8.44772 6 8 6.44772 8 7C8 7.55228 8.44772 8 9 8V6ZM15 8C15.5523 8 16 7.55228 16 7C16 6.44772 15.5523 6 15 6V8ZM9 10C8.44772 10 8 10.4477 8 11C8 11.5523 8.44772 12 9 12V10ZM12 12C12.5523 12 13 11.5523 13 11C13 10.4477 12.5523 10 12 10V12ZM7 4H17V2H7V4ZM18 5V19H20V5H18ZM17 20H7V22H17V20ZM6 19V5H4V19H6ZM7 20C6.44771 20 6 19.5523 6 19H4C4 20.6569 5.34315 22 7 22V20ZM18 19C18 19.5523 17.5523 20 17 20V22C18.6569 22 20 20.6569 20 19H18ZM17 4C17.5523 4 18 4.44772 18 5H20C20 3.34315 18.6569 2 17 2V4ZM7 2C5.34315 2 4 3.34315 4 5H6C6 4.44772 6.44772 4 7 4V2ZM18 12V15H20V12H18ZM17 16H7V18H17V16ZM7 22H10V20H7V22ZM7 16C5.34315 16 4 17.3431 4 19H6C6 18.4477 6.44772 18 7 18V16ZM18 15C18 15.5523 17.5523 16 17 16V18C18.6569 18 20 16.6569 20 15H18ZM9 8H15V6H9V8ZM9 12H12V10H9V12Z\" fill=\"white\"/>',\n\tgraduate:\n\t\t'<path d=\"M23 9L12 14L1 9L12 4L23 9ZM23 9V16M5 11V15.3025C5 16.0398 5.40565 16.7173 6.05556 17.0655L11.0556 19.744C11.6455 20.0601 12.3545 20.0601 12.9444 19.744L17.9444 17.0655C18.5944 16.7173 19 16.0398 19 15.3025V11\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n};\n\n/**\n * Renders preset icon SVG — uses trusted static SVG content extracted from\n * @central-icons-react at build time. Content is hardcoded (not user input),\n * so innerHTML usage is safe from XSS.\n */\nfunction AgentPresetIcon({ presetId }: { presetId: string }) {\n\tconst svgContent = PRESET_SVG[presetId] ?? PRESET_SVG.sparkle;\n\treturn (\n\t\t// biome-ignore lint: trusted static SVG content from our icon library\n\t\t<svg\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tstyle={{ width: \"55%\", height: \"55%\" }}\n\t\t\tdangerouslySetInnerHTML={{ __html: svgContent ?? \"\" }}\n\t\t/>\n\t);\n}\n\n/**\n * What the header's dismiss control does depends on the shell.\n *\n * In the bubble shell the panel goes away and the launcher is all that is left, so\n * an × is the truth. Docked, the bar stays on the page and keeps the thread one\n * keystroke away — nothing is closed, the conversation folds back into the bar.\n * A chevron says that; an × promises a disappearance that does not happen.\n */\nfunction CloseGlyph({ docked }: { docked: boolean }) {\n\tif (!docked) return <XIcon size={20} />;\n\treturn (\n\t\t<svg\n\t\t\twidth=\"20\"\n\t\t\theight=\"20\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t>\n\t\t\t<path d=\"M6 9.5 12 15.5 18 9.5\" />\n\t\t</svg>\n\t);\n}\n\n/**\n * Unified support widget — Intercom-style with tab navigation.\n * Two tabs: Home + Messages. Sub-views: conversation + new conversation.\n */\nexport function DefaultWidget({\n\thideLauncher = false,\n\tplacement = \"bubble\",\n\tcolorScheme,\n\tdockSuggestions,\n}: {\n\thideLauncher?: boolean;\n\tplacement?: WidgetPlacement;\n\t/**\n\t * Pin the appearance instead of following the visitor's OS. An embedded\n\t * widget lives in someone else's page; matching that page beats matching\n\t * the machine it is being read on.\n\t */\n\tcolorScheme?: \"light\" | \"dark\" | \"system\";\n\t/**\n\t * Ways in offered above the docked bar before the visitor types.\n\t * A prop for now — this belongs on AgentConfig once the API returns\n\t * per-workspace (and eventually per-page) suggestions.\n\t */\n\tdockSuggestions?: readonly DockSuggestion[];\n} = {}) {\n\tconst { isReady, website, agentConfig } = useWidget();\n\tuseI18n();\n\tconst { client, store, hasBootstrapError, wsDisconnected, retryBootstrap } = useWidgetContext();\n\tconst { conversations, create, isCreating, setActiveConversation } = useConversations();\n\tconst activeId = useWidgetStore((s) => s.activeConversationId);\n\tconst isDismissed = useWidgetStore((s) => s.isDismissed);\n\tconst { totalUnread } = useUnread();\n\n\tconst contentTabs = useWidgetStore((s) => s.agentConfig?.contentTabs) ?? EMPTY_CONTENT_TABS;\n\tconst { announcementTabs, markEntrySeen, getUnseenEntries } = useAnnouncements();\n\tconst unseenAnnouncementCount = useWidgetStore((s) => s.unseenAnnouncementCount);\n\n\tconst visitorContact = useWidgetStore((s) => s.visitor?.contact);\n\n\t// DEV: email prompt debug\n\tif (process.env.NODE_ENV !== \"production\") {\n\t\tconsole.debug(\"[Widget]\", {\n\t\t\treqEmail: agentConfig?.requireVisitorEmail,\n\t\t\tcontact: visitorContact?.email ?? null,\n\t\t\tactiveId,\n\t\t});\n\t}\n\n\tconst storeIsOpen = useWidgetStore((s) => s.isOpen);\n\tconst [isClosing, setIsClosing] = useState(false);\n\tconst isOpen = storeIsOpen || isClosing;\n\tconst [activeTab, setActiveTab] = useState<Tab>(\"home\");\n\tconst [subView, setSubView] = useState<SubView>(null);\n\tconst [newText, setNewText] = useState(\"\");\n\tconst [contentDetailSlug, setContentDetailSlug] = useState<string | null>(null);\n\tconst [contentCategoryName, setContentCategoryName] = useState<string | null>(null);\n\n\t// Sync API-driven navigation: when store.activeConversationId changes externally\n\t// (via window.Helpway.openConversation), drive the local subView to match.\n\tconst prevActiveIdRef = useRef(activeId);\n\tuseEffect(() => {\n\t\tif (activeId && activeId !== prevActiveIdRef.current && subView !== \"conversation\") {\n\t\t\tsetSubView(\"conversation\");\n\t\t}\n\t\tprevActiveIdRef.current = activeId;\n\t}, [activeId, subView]);\n\n\t// Consume newConversationPrefill from global API (window.Helpway.newConversation)\n\tconst prefill = useWidgetStore((s) => s.newConversationPrefill);\n\tuseEffect(() => {\n\t\tif (prefill !== null) {\n\t\t\tif (prefill.length > 0) setNewText(prefill);\n\t\t\tsetSubView(\"new\");\n\t\t\tsetActiveTab(\"home\");\n\t\t\tstore.getState().setNewConversationPrefill(null);\n\t\t}\n\t}, [prefill, store]);\n\n\tconst closeTimerRef = useRef<ReturnType<typeof setTimeout>>(undefined);\n\n\t// Resolve welcome/subtitle here (used both by openNewConversation seed\n\t// and by the header). Hoisted above openNewConversation so the callback\n\t// captures a defined binding instead of hitting the TDZ at closure time.\n\tconst welcomeMsgRaw = agentConfig?.welcomeMessage;\n\tconst welcomeIsFactoryDefault =\n\t\t!welcomeMsgRaw || welcomeMsgRaw === DEFAULT_EN_WELCOME;\n\tconst welcomeMessage = welcomeMsgRaw?.startsWith(\"widget.\")\n\t\t? t(welcomeMsgRaw)\n\t\t: welcomeIsFactoryDefault\n\t\t\t? t(\"widget.welcome_message\")\n\t\t\t: welcomeMsgRaw;\n\n\tconst openConversation = useCallback(\n\t\t(id: string) => {\n\t\t\tsetActiveConversation(id);\n\t\t\tsetSubView(\"conversation\");\n\t\t},\n\t\t[setActiveConversation],\n\t);\n\n\tconst openNewConversation = useCallback(() => {\n\t\t// Seed a temp conversation + a stable welcome bubble and drop the user\n\t\t// straight into \"conversation\" view. This keeps the welcome bubble\n\t\t// mounted in the SAME React subtree across the first-send transition\n\t\t// (previously: \"new\" view → \"conversation\" view = unmount + remount =\n\t\t// CSS `hw-msg-appear` animation replays = the \"git-gel\" flash).\n\t\t//\n\t\t// useComposer notices the temp id and routes through createConversation\n\t\t// when the visitor sends their first message.\n\t\tconst agentId = agentConfig?.id;\n\t\tif (!agentId) {\n\t\t\t// No agent config yet — skip the seed and let the server decide.\n\t\t\t// The user can still compose; submit will call createConversation.\n\t\t\tsetSubView(\"new\");\n\t\t\treturn;\n\t\t}\n\t\tconst tempId = `temp-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;\n\t\tconst seedWelcome: TimelineItem = {\n\t\t\tid: `seed-welcome-${tempId}`,\n\t\t\tconversationId: tempId,\n\t\t\torganizationId: \"\",\n\t\t\ttype: \"message\",\n\t\t\tvisibility: \"public\",\n\t\t\ttext: welcomeMessage,\n\t\t\tparts: null,\n\t\t\tuserId: null,\n\t\t\tvisitorId: null,\n\t\t\taiAgentId: agentId,\n\t\t\tcreatedAt: new Date().toISOString(),\n\t\t\teditedAt: null,\n\t\t\tdeletedAt: null,\n\t\t};\n\t\tstore.getState().setMessages(tempId, [seedWelcome]);\n\t\tsetActiveConversation(tempId);\n\t\tsetSubView(\"conversation\");\n\t}, [agentConfig?.id, store, setActiveConversation, welcomeMessage]);\n\n\t// Open straight into a conversation — never onto a home screen.\n\t// First-timers get the seeded welcome + a focused composer; returning\n\t// visitors resume their most recent thread. Every screen between the\n\t// launcher and the composer is a place people drop out, so there isn't\n\t// one: the tab bar only exists once you navigate back to a list.\n\t// Ref-guarded so this fires once per open, and never fights a caller\n\t// that already routed us somewhere (openConversation / prefill).\n\tconst didAutoOpenRef = useRef(false);\n\tuseEffect(() => {\n\t\tif (!isOpen) {\n\t\t\tdidAutoOpenRef.current = false;\n\t\t\treturn;\n\t\t}\n\t\tif (didAutoOpenRef.current || !isReady) return;\n\t\tdidAutoOpenRef.current = true;\n\t\tif (subView !== null) return;\n\t\tconst mostRecent = conversations[0];\n\t\tif (mostRecent) openConversation(mostRecent.id);\n\t\telse openNewConversation();\n\t}, [\n\t\tisOpen,\n\t\tisReady,\n\t\tsubView,\n\t\tconversations,\n\t\topenConversation,\n\t\topenNewConversation,\n\t]);\n\n\t// ── Docked shell ───────────────────────────────────────────────────\n\t// In `placement=\"docked\"` the bar IS the composer, so it needs its own\n\t// composer state — the panel's is hidden. Sending from a cold start\n\t// has to open a conversation first, and useComposer binds its\n\t// conversation id at call time, so the text waits in a ref for one\n\t// render rather than being sent against a stale id.\n\tconst dockComposer = useComposer(activeId);\n\tconst dockRef = useRef(dockComposer);\n\t// Synced after commit, never during render — the ref is only read from\n\t// callbacks and timeouts, which all run after this effect.\n\tuseEffect(() => {\n\t\tdockRef.current = dockComposer;\n\t});\n\tconst pendingDockText = useRef<string | null>(null);\n\n\t/* Folding the panel away leaves the conversation intact — activeConversationId\n\t and the thread both survive — so pressing the bar again should put the\n\t visitor back in it. Guarded on an existing real conversation: on a docs page\n\t a press that opens an empty panel over the article is noise, and sending is\n\t already the thing that opens one from cold. */\n\tconst reopenFromDock = useCallback(() => {\n\t\tconst state = store.getState();\n\t\tif (state.isOpen) return;\n\t\tconst resumable = state.conversations.some((conv) => !conv.id.startsWith(\"temp-\"));\n\t\tif (!resumable) return;\n\t\tstate.setOpen(true);\n\t}, [store]);\n\n\tconst submitFromDock = useCallback(\n\t\t(override?: string) => {\n\t\t\tconst text = (override ?? dockRef.current.text).trim();\n\t\t\t/* An attachment with no caption still has to reach the composer. This guard\n\t\t\t used to be `if (!text) return`, which swallowed the press: the composer's\n\t\t\t caption policy — the thing that produces a visible \"add a message\" error —\n\t\t\t never ran, so a visitor who picked a file and pressed send got a dead\n\t\t\t button and no reason. Empty text is now the composer's call to refuse,\n\t\t\t which it does out loud. */\n\t\t\tconst stagedAttachment = dockRef.current.attachments.some((a) => a.part !== null);\n\t\t\tif (!text && !stagedAttachment) return;\n\t\t\t// The docked shell has no launcher, so sending is the only thing\n\t\t\t// that can reveal the panel — without this the conversation is\n\t\t\t// created and answered while nothing is on screen. Read off the\n\t\t\t// store rather than the hook: the hook binding is declared\n\t\t\t// further down this component.\n\t\t\tstore.getState().setOpen(true);\n\t\t\tif (activeId) {\n\t\t\t\tdockRef.current.setText(\"\");\n\t\t\t\tvoid dockRef.current.submit({ text, conversationId: activeId });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Cold start: openNewConversation seeds the temp conversation through\n\t\t\t// the zustand store, which is synchronous — the id is readable on the\n\t\t\t// next line, before any render. Handing it to submit is what makes a\n\t\t\t// suggestion pill actually send. The previous version staged the text\n\t\t\t// in a ref and fired a 0ms timer, and when the pill lost that race the\n\t\t\t// panel opened onto an empty composer with the question dropped.\n\t\t\topenNewConversation();\n\t\t\tconst seededId = store.getState().activeConversationId;\n\t\t\tdockRef.current.setText(\"\");\n\t\t\tif (!seededId) {\n\t\t\t\t// No agent config yet, so openNewConversation could only route to\n\t\t\t\t// the \"new\" view — the text waits until an id exists.\n\t\t\t\tpendingDockText.current = text;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvoid dockRef.current.submit({ text, conversationId: seededId });\n\t\t},\n\t\t[activeId, openNewConversation, store],\n\t);\n\n\tuseEffect(() => {\n\t\tif (!activeId || pendingDockText.current == null) return;\n\t\tconst text = pendingDockText.current;\n\t\tpendingDockText.current = null;\n\t\tvoid dockRef.current.submit({ text, conversationId: activeId });\n\t}, [activeId]);\n\n\t// Conversation options. The header's only affordance was a close\n\t// button, so expanding the panel or starting over had no home.\n\tconst [menuOpen, setMenuOpen] = useState(false);\n\tuseEffect(() => {\n\t\tif (!menuOpen) return;\n\t\tconst close = () => setMenuOpen(false);\n\t\tconst onKey = (event: KeyboardEvent) => {\n\t\t\tif (event.key === \"Escape\") setMenuOpen(false);\n\t\t};\n\t\tdocument.addEventListener(\"click\", close);\n\t\tdocument.addEventListener(\"keydown\", onKey);\n\t\treturn () => {\n\t\t\tdocument.removeEventListener(\"click\", close);\n\t\t\tdocument.removeEventListener(\"keydown\", onKey);\n\t\t};\n\t}, [menuOpen]);\n\n\tconst goBack = useCallback(() => {\n\t\tif (subView === \"content-detail\") {\n\t\t\t// If inside a grouped tab, go back to category items, not all the way to categories\n\t\t\tconst tabId = activeTab.startsWith(\"content:\") ? activeTab.slice(8) : null;\n\t\t\tconst activeContentTab = tabId ? contentTabs.find((t) => t.id === tabId) : null;\n\t\t\tif (activeContentTab?.tabType === \"grouped\" && contentCategoryName) {\n\t\t\t\tsetSubView(\"content-category\");\n\t\t\t\tsetContentDetailSlug(null);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsetSubView(null);\n\t\t\tsetContentDetailSlug(null);\n\t\t\treturn;\n\t\t}\n\t\tif (subView === \"content-category\") {\n\t\t\tsetSubView(null);\n\t\t\tsetContentCategoryName(null);\n\t\t\treturn;\n\t\t}\n\t\t// Race-immune mark-seen: when leaving a conversation, the visitor has\n\t\t// effectively \"seen\" everything currently in it — including any AI reply\n\t\t// that may have arrived via WS milliseconds before they tapped back.\n\t\t// Without this, the WS event arriving AFTER setActiveConversation(null)\n\t\t// finds isViewing=false and increments unreadCount.\n\t\t// Skip temp-* IDs (server doesn't know about them yet).\n\t\tconst leavingId = store.getState().activeConversationId;\n\t\tif (leavingId && !leavingId.startsWith(\"temp-\")) {\n\t\t\tstore.getState().clearUnread(leavingId);\n\t\t\tclient.widget.markSeen.mutate({ conversationId: leavingId }).catch(() => {});\n\t\t}\n\t\tsetActiveConversation(null);\n\t\tsetSubView(null);\n\t}, [setActiveConversation, subView, activeTab, contentTabs, contentCategoryName, client, store]);\n\n\tconst switchTab = useCallback(\n\t\t(tab: Tab) => {\n\t\t\t// Save current tab state\n\t\t\ttabStateRef.current[activeTab] = { subView, activeId };\n\t\t\t// Restore target tab state (if any)\n\t\t\tconst saved = tabStateRef.current[tab];\n\t\t\tsetActiveTab(tab);\n\t\t\tsetSubView(saved?.subView ?? null);\n\t\t\tif (saved?.activeId != null) {\n\t\t\t\tsetActiveConversation(saved.activeId);\n\t\t\t} else if (!saved) {\n\t\t\t\tsetActiveConversation(null);\n\t\t\t}\n\t\t},\n\t\t[activeTab, subView, activeId, setActiveConversation],\n\t);\n\n\t// Consume pendingContentDetail — set by anchored consumers (or any\n\t// external trigger) that want to deep-link the visitor into a\n\t// specific content entry's detail view instead of dropping them on\n\t// the home surface. Mirrors what the launcher's announcement onOpen\n\t// does internally: mark the entry seen, switch to the right content\n\t// tab, open its detail, then clear the pending state. Sits after\n\t// `switchTab` so the dep array can reference the stable useCallback.\n\tconst pendingContentDetail = useWidgetStore((s) => s.pendingContentDetail);\n\tuseEffect(() => {\n\t\tif (!pendingContentDetail) return;\n\t\tconst { slug, tabId } = pendingContentDetail;\n\t\tmarkEntrySeen(slug);\n\t\tswitchTab(`content:${tabId}`);\n\t\tsetContentDetailSlug(slug);\n\t\tsetSubView(\"content-detail\");\n\t\tstore.getState().setPendingContentDetail(null);\n\t}, [pendingContentDetail, markEntrySeen, switchTab, store]);\n\n\tconst setStoreOpen = useWidgetStore((s) => s.setOpen);\n\n\tconst handleBubbleClick = useCallback(() => {\n\t\tif (storeIsOpen) {\n\t\t\tconst leavingId = store.getState().activeConversationId;\n\t\t\tif (leavingId && !leavingId.startsWith(\"temp-\")) {\n\t\t\t\tstore.getState().clearUnread(leavingId);\n\t\t\t\tclient.widget.markSeen.mutate({ conversationId: leavingId }).catch(() => {});\n\t\t\t}\n\t\t\tsetIsClosing(true);\n\t\t\tcloseTimerRef.current = setTimeout(() => {\n\t\t\t\tsetIsClosing(false);\n\t\t\t\tsetStoreOpen(false);\n\t\t\t}, 200);\n\t\t} else {\n\t\t\tsetIsClosing(false);\n\t\t\tsetSubView(null);\n\t\t\tsetActiveTab(\"home\");\n\t\t\tsetStoreOpen(true);\n\t\t}\n\t}, [storeIsOpen, setStoreOpen, client, store]);\n\n\tconst handleClose = useCallback(() => {\n\t\tconst leavingId = store.getState().activeConversationId;\n\t\tif (leavingId && !leavingId.startsWith(\"temp-\")) {\n\t\t\tstore.getState().clearUnread(leavingId);\n\t\t\tclient.widget.markSeen.mutate({ conversationId: leavingId }).catch(() => {});\n\t\t}\n\t\tsetIsClosing(true);\n\t\tcloseTimerRef.current = setTimeout(() => {\n\t\t\tsetIsClosing(false);\n\t\t\tsetStoreOpen(false);\n\t\t}, 200);\n\t}, [setStoreOpen, client, store]);\n\n\tconst handleNewConversation = useCallback(async () => {\n\t\tconst trimmed = newText.trim();\n\t\tif (!trimmed || isCreating) return;\n\t\tconst conv = await create(trimmed);\n\t\tif (conv) {\n\t\t\tsetNewText(\"\");\n\t\t\tsetSubView(\"conversation\");\n\t\t}\n\t}, [newText, isCreating, create]);\n\n\tconst windowRef = useRef<HTMLDivElement>(null);\n\tconst bubbleRef = useRef<HTMLButtonElement>(null);\n\tconst tabStateRef = useRef<{ [tab: string]: { subView: SubView; activeId: string | null } }>({});\n\tconst touchStartY = useRef(0);\n\tconst touchDeltaY = useRef(0);\n\n\tconst handleTouchStart = useCallback((e: React.TouchEvent) => {\n\t\ttouchStartY.current = e.touches[0]?.clientY ?? 0;\n\t\ttouchDeltaY.current = 0;\n\t}, []);\n\n\tconst handleTouchMove = useCallback((e: React.TouchEvent) => {\n\t\tconst delta = (e.touches[0]?.clientY ?? 0) - touchStartY.current;\n\t\ttouchDeltaY.current = delta;\n\t\tif (delta > 0 && windowRef.current) {\n\t\t\twindowRef.current.style.transform = `translateY(${Math.min(delta, 200)}px)`;\n\t\t\twindowRef.current.style.opacity = `${Math.max(1 - delta / 400, 0.5)}`;\n\t\t}\n\t}, []);\n\n\tconst handleTouchEnd = useCallback(() => {\n\t\tif (windowRef.current) {\n\t\t\twindowRef.current.style.transform = \"\";\n\t\t\twindowRef.current.style.opacity = \"\";\n\t\t}\n\t\tif (touchDeltaY.current > 80) {\n\t\t\thandleClose();\n\t\t}\n\t}, [handleClose]);\n\n\t// iOS virtual keyboard — `height: 100%` in CSS refers to the LAYOUT\n\t// viewport, which doesn't shrink when the keyboard opens on iOS Safari.\n\t// The result: composer gets pushed below the visible area and visitors\n\t// can't see what they're typing. visualViewport.height is the one\n\t// reliable API that reflects post-keyboard space. We write it to a CSS\n\t// custom property the mobile @media block consumes.\n\tuseEffect(() => {\n\t\tif (!isOpen || !windowRef.current) return;\n\t\tconst vv = window.visualViewport;\n\t\tif (!vv) return;\n\t\tconst win = windowRef.current;\n\t\tconst applyHeight = () => {\n\t\t\twin.style.setProperty(\"--hw-visible-height\", `${vv.height}px`);\n\t\t};\n\t\tapplyHeight();\n\t\tvv.addEventListener(\"resize\", applyHeight);\n\t\tvv.addEventListener(\"scroll\", applyHeight);\n\t\treturn () => {\n\t\t\tvv.removeEventListener(\"resize\", applyHeight);\n\t\t\tvv.removeEventListener(\"scroll\", applyHeight);\n\t\t\twin.style.removeProperty(\"--hw-visible-height\");\n\t\t};\n\t}, [isOpen]);\n\n\t// Escape to close / back — listener attached to the widget window, NOT\n\t// document. Two reasons: (1) widget lives inside a shadow DOM; document\n\t// listeners fire for host-page key events too, which would close the\n\t// widget when a visitor presses ESC in the host site's own search box.\n\t// (2) WCAG 2.1 AA requires focus-scoped escape behavior for dialogs.\n\tuseEffect(() => {\n\t\tif (!isOpen || !windowRef.current) return;\n\t\tconst win = windowRef.current;\n\t\tconst handleKeyDown = (e: KeyboardEvent) => {\n\t\t\tif (e.key === \"Escape\") {\n\t\t\t\tif (subView) {\n\t\t\t\t\tgoBack();\n\t\t\t\t} else {\n\t\t\t\t\thandleClose();\n\t\t\t\t\tsetTimeout(() => bubbleRef.current?.focus(), 220);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\twin.addEventListener(\"keydown\", handleKeyDown);\n\t\treturn () => win.removeEventListener(\"keydown\", handleKeyDown);\n\t}, [isOpen, subView, handleClose, goBack]);\n\n\t// Focus trap — same rationale: listen on the widget window so only\n\t// keydowns inside the widget are trapped. `document.activeElement`\n\t// returns the shadow HOST when focus is inside a shadow root; to find\n\t// the actually-focused element we walk into the shadow root.\n\t//\n\t// Skipped entirely under `hideLauncher` (embedded/anchored consumers\n\t// like a sidebar Help item): in that mode the widget shares space\n\t// with the host's own inputs, so grabbing focus on open silently\n\t// steals the visitor's typing/paste context — Cmd+V after opening\n\t// the panel would land in our composer instead of whatever the host\n\t// had focused (paste hijack). Trapping Tab would also fight the\n\t// host's keyboard nav. Both belong to the modal launcher use case,\n\t// not to embedded consumption.\n\tuseEffect(() => {\n\t\tif (!isOpen || !windowRef.current || hideLauncher) return;\n\t\tconst win = windowRef.current;\n\t\tconst getFocusable = () =>\n\t\t\twin.querySelectorAll<HTMLElement>(\n\t\t\t\t'button:not([disabled]), [href], input:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])',\n\t\t\t);\n\t\tconst getActive = (): Element | null => {\n\t\t\t// Prefer the shadow root's activeElement so focus tracking works\n\t\t\t// even when the widget is mounted inside a closed/open shadow DOM.\n\t\t\tconst root = win.getRootNode();\n\t\t\tif (root instanceof ShadowRoot) return root.activeElement;\n\t\t\treturn document.activeElement;\n\t\t};\n\t\tconst handleTab = (e: KeyboardEvent) => {\n\t\t\tif (e.key !== \"Tab\") return;\n\t\t\tconst focusable = getFocusable();\n\t\t\tif (focusable.length === 0) return;\n\t\t\tconst first = focusable[0];\n\t\t\tconst last = focusable[focusable.length - 1];\n\t\t\tconst active = getActive();\n\t\t\tif (e.shiftKey && active === first) {\n\t\t\t\te.preventDefault();\n\t\t\t\tlast?.focus();\n\t\t\t} else if (!e.shiftKey && active === last) {\n\t\t\t\te.preventDefault();\n\t\t\t\tfirst?.focus();\n\t\t\t}\n\t\t};\n\t\twin.addEventListener(\"keydown\", handleTab);\n\t\t/* Docked keeps its focus where it was. The composer is the dock bar, which\n\t\t lives OUTSIDE this window — so pulling focus to the panel's first button\n\t\t took it off the field the visitor was mid-sentence in: type, press\n\t\t Enter, and the caret jumped to the header. In the bubble placement the\n\t\t composer IS inside the window, so focusing into it is the right move. */\n\t\tif (placement !== \"docked\") {\n\t\t\tconst focusable = getFocusable();\n\t\t\tif (focusable.length > 0) focusable[0]?.focus();\n\t\t}\n\t\treturn () => win.removeEventListener(\"keydown\", handleTab);\n\t}, [isOpen, hideLauncher, placement]);\n\n\tconst showTabBar = subView === null;\n\tconst activeConvSummary = useWidgetStore((s) => {\n\t\tconst id = s.activeConversationId;\n\t\treturn id ? s.conversations.find((c) => c.id === id) : null;\n\t});\n\t// Header name resolution mirrors WidgetLogo's avatar resolution:\n\t// 1. Assigned support user (sticky once a human takes over)\n\t// 2. Last team-side sender (in case there's no formal assignment\n\t// but a teammate jumped in for one message)\n\t// 3. AI agent name / website name\n\t/* Name AND photo come from the same decision, which they did not before: the\n\t name preferred the assignee while the avatar only ever looked at the last\n\t team-side sender. Assign someone who has not typed yet and the header read\n\t as that person over the bot's logo — half a handoff. */\n\tconst teamSender =\n\t\tactiveConvSummary?.lastMessageSenderType === \"team\" &&\n\t\tactiveConvSummary?.lastMessageSenderName\n\t\t\t? activeConvSummary\n\t\t\t: null;\n\tconst humanName = activeConvSummary?.assigneeName ?? teamSender?.lastMessageSenderName ?? null;\n\tconst humanImage = activeConvSummary?.assigneeImage ?? teamSender?.lastMessageSenderImage ?? null;\n\tconst hasTeamAgent = !!humanName;\n\tconst headerName = humanName ?? (agentConfig?.name ?? website?.name ?? \"Support\");\n\tconst companyName = agentConfig?.name ?? website?.name ?? \"Support\";\n\tconst subtitleMsg = agentConfig?.subtitleText;\n\tconst subtitleIsFactoryDefault =\n\t\t!subtitleMsg || subtitleMsg === DEFAULT_EN_SUBTITLE;\n\tconst subtitleText = subtitleMsg?.startsWith(\"widget.\")\n\t\t? t(subtitleMsg)\n\t\t: subtitleIsFactoryDefault\n\t\t\t? t(\"widget.subtitle_text\")\n\t\t\t: subtitleMsg;\n\tconst brandColor = agentConfig?.brandColor ?? \"#0a0a0a\";\n\tconst widgetPosition = agentConfig?.widgetPosition ?? \"bottom-right\";\n\tconst launcherStyle = agentConfig?.launcherStyle ?? \"icon\";\n\tconst bubbleStyle = agentConfig?.bubbleStyle ?? \"rounded\";\n\n\t// Smart default: when the org uploaded a logo as the agent avatar\n\t// (vs a face photo), tint the chat-header circle with the brand\n\t// color and switch the image to `contain` so the mark isn't cropped.\n\t// `--hw-agent-bg-default` is consumed by the styles.css fallback\n\t// chain — site-side `:root { --hw-agent-bg: ... }` still wins.\n\tconst hasUploadedAvatar = !!agentConfig?.avatarUrl;\n\n\treturn (\n\t\t<div\n\t\t\tclassName=\"hw-widget\"\n\t\t\tdata-hw-placement={placement}\n\t\t\t/* Lets the docked shell close the gap between the panel and the bar while a\n\t\t\t conversation is open: the two become one card with the composer at its\n\t\t\t foot, instead of a floating panel over a separate pill. */\n\t\t\tdata-hw-open={isOpen ? \"true\" : \"false\"}\n\t\t\tdata-theme={colorScheme === \"system\" ? undefined : colorScheme}\n\t\t\tdata-has-avatar={hasUploadedAvatar ? \"true\" : \"false\"}\n\t\t\tstyle={\n\t\t\t\t{\n\t\t\t\t\t\"--hw-primary\": brandColor,\n\t\t\t\t\t\"--hw-position-right\": widgetPosition === \"bottom-right\" ? \"20px\" : \"auto\",\n\t\t\t\t\t\"--hw-position-left\": widgetPosition === \"bottom-left\" ? \"20px\" : \"auto\",\n\t\t\t\t\t\"--hw-window-right\": widgetPosition === \"bottom-right\" ? \"0\" : \"auto\",\n\t\t\t\t\t\"--hw-window-left\": widgetPosition === \"bottom-left\" ? \"0\" : \"auto\",\n\t\t\t\t} as React.CSSProperties\n\t\t\t}\n\t\t>\n\t\t\t{placement === \"docked\" && isReady && (\n\t\t\t\t<DockedBar\n\t\t\t\t\tvalue={dockComposer.text}\n\t\t\t\t\tonChange={dockComposer.setText}\n\t\t\t\t\tonSubmit={() => submitFromDock()}\n\t\t\t\t\tdisabled={dockComposer.isSubmitting}\n\t\t\t\t\tsuggestions={activeId ? undefined : dockSuggestions}\n\t\t\t\t\tonSuggestion={(question) => submitFromDock(question)}\n\t\t\t\t\tattachments={dockComposer.attachments}\n\t\t\t\t\tonAddFiles={dockComposer.addFiles}\n\t\t\t\t\tonRemoveAttachment={dockComposer.removeAttachment}\n\t\t\t\t\tonReopen={reopenFromDock}\n\t\t\t\t\tsendError={dockComposer.sendError}\n\t\t\t\t\tonClearSendError={dockComposer.clearSendError}\n\t\t\t\t/>\n\t\t\t)}\n\t\t\t{isOpen && !isReady && !hasBootstrapError && (\n\t\t\t\t<div className={`hw-window ${isClosing ? \"hw-window--closing\" : \"\"}`}>\n\t\t\t\t\t<div className=\"hw-skeleton-loading\">\n\t\t\t\t\t\t<div className=\"hw-skeleton hw-skeleton-line\" style={{ width: 120 }} />\n\t\t\t\t\t\t<div className=\"hw-skeleton hw-skeleton-line\" style={{ width: 200 }} />\n\t\t\t\t\t\t<div className=\"hw-skeleton hw-skeleton-line\" style={{ width: 160 }} />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t{isOpen && hasBootstrapError && (\n\t\t\t\t<div className={`hw-window ${isClosing ? \"hw-window--closing\" : \"\"}`}>\n\t\t\t\t\t<div className=\"hw-bootstrap-error\">\n\t\t\t\t\t\t<div className=\"hw-bootstrap-error-text\">{t(\"widget.error_desc\")}</div>\n\t\t\t\t\t\t<button type=\"button\" className=\"hw-bootstrap-error-retry\" onClick={retryBootstrap}>\n\t\t\t\t\t\t\t{t(\"widget.retry\")}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t{isOpen && isReady && (\n\t\t\t\t<div\n\t\t\t\t\tref={windowRef}\n\t\t\t\t\tclassName={`hw-window ${isClosing ? \"hw-window--closing\" : \"\"} ${\n\t\t\t\t\t\tsubView === \"content-detail\" ? \"hw-window--reading\" : \"\"\n\t\t\t\t\t}`}\n\t\t\t\t\trole=\"dialog\"\n\t\t\t\t\taria-label={t(\"widget.aria_chat\")}\n\t\t\t\t\taria-modal=\"true\"\n\t\t\t\t\tonTouchStart={handleTouchStart}\n\t\t\t\t\tonTouchMove={handleTouchMove}\n\t\t\t\t\tonTouchEnd={handleTouchEnd}\n\t\t\t\t>\n\t\t\t\t\t{/* Drag handle for mobile swipe-down */}\n\t\t\t\t\t<div className=\"hw-drag-handle\">\n\t\t\t\t\t\t<div className=\"hw-drag-handle-pill\" />\n\t\t\t\t\t</div>\n\t\t\t\t\t{/* WebSocket disconnect banner */}\n\t\t\t\t\t{wsDisconnected && (\n\t\t\t\t\t\t<div className=\"hw-disconnect\">\n\t\t\t\t\t\t\t<div className=\"hw-disconnect-dot\" />\n\t\t\t\t\t\t\t{t(\"widget.reconnecting\")}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t\t{/* ── Sub-view header: content-detail/content-category gets centered title ── */}\n\t\t\t\t\t{(subView === \"content-detail\" || subView === \"content-category\") &&\n\t\t\t\t\t\t(() => {\n\t\t\t\t\t\t\tconst tabId = activeTab.replace(\"content:\", \"\");\n\t\t\t\t\t\t\tconst contentTab = contentTabs.find((t) => t.id === tabId);\n\t\t\t\t\t\t\t// Show category name when viewing items within a category\n\t\t\t\t\t\t\tconst headerTitle =\n\t\t\t\t\t\t\t\tsubView === \"content-category\" && contentCategoryName\n\t\t\t\t\t\t\t\t\t? contentCategoryName\n\t\t\t\t\t\t\t\t\t: contentTab?.label\n\t\t\t\t\t\t\t\t\t\t? resolveLabel(contentTab.label)\n\t\t\t\t\t\t\t\t\t\t: t(\"widget.content\");\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<div className=\"hw-header hw-header--centered\">\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"hw-header-back\"\n\t\t\t\t\t\t\t\t\t\tonClick={goBack}\n\t\t\t\t\t\t\t\t\t\taria-label={t(\"widget.aria_back\")}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\t\t\t\tstrokeWidth={2}\n\t\t\t\t\t\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<path d=\"M15 18l-6-6 6-6\" />\n\t\t\t\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t<div className=\"hw-header-title\">{headerTitle}</div>\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"hw-header-close\"\n\t\t\t\t\t\t\t\t\t\tonClick={handleClose}\n\t\t\t\t\t\t\t\t\t\taria-label={t(\"widget.aria_close\")}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<CloseGlyph docked={placement === \"docked\"} />\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})()}\n\t\t\t\t\t{subView !== null && subView !== \"content-detail\" && subView !== \"content-category\" && (\n\t\t\t\t\t\t<div className=\"hw-header hw-header--sub\">\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclassName=\"hw-header-back\"\n\t\t\t\t\t\t\t\tonClick={goBack}\n\t\t\t\t\t\t\t\taria-label={t(\"widget.aria_back\")}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\t\tstrokeWidth={2}\n\t\t\t\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<path d=\"M15 18l-6-6 6-6\" />\n\t\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t<div className=\"hw-header-identity\">\n\t\t\t\t\t\t\t\t<div className={`hw-header-bot-icon${hasTeamAgent ? \" hw-header-bot-icon--team\" : \"\"}`}>\n\t\t\t\t\t\t\t\t\t{hasTeamAgent && humanImage ? (\n\t\t\t\t\t\t\t\t\t\t<img src={humanImage} alt={headerName} className=\"hw-header-agent-img\" />\n\t\t\t\t\t\t\t\t\t) : hasTeamAgent ? (\n\t\t\t\t\t\t\t\t\t\t<span className=\"hw-header-agent-initials\">\n\t\t\t\t\t\t\t\t\t\t\t{headerName.split(\" \").map((w: string) => w[0]).join(\"\").slice(0, 2).toUpperCase()}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t<WidgetLogo />\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div className=\"hw-header-info\">\n\t\t\t\t\t\t\t\t\t<div className=\"hw-header-name\">{headerName}</div>\n\t\t\t\t\t\t\t\t\t{/* Keep the subtitle identical in both \"new\" and \"conversation\"\n\t\t\t\t\t\t\t\t\t sub-views — otherwise the header reads \"New conversation\"\n\t\t\t\t\t\t\t\t\t while composing and snaps to \"Usually replies in minutes\"\n\t\t\t\t\t\t\t\t\t the moment you send, which feels like the whole header\n\t\t\t\t\t\t\t\t\t rebuilt. */}\n\t\t\t\t\t\t\t\t\t<div className=\"hw-header-status\">{subtitleText}</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div className=\"hw-header-actions\">\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclassName=\"hw-header-menu-btn\"\n\t\t\t\t\t\t\t\t\taria-haspopup=\"menu\"\n\t\t\t\t\t\t\t\t\taria-expanded={menuOpen}\n\t\t\t\t\t\t\t\t\taria-label={t(\"widget.aria_options\")}\n\t\t\t\t\t\t\t\t\tonClick={(event) => {\n\t\t\t\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t\t\t\t\tsetMenuOpen((open) => !open);\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<DotsIcon size={18} />\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclassName=\"hw-header-close\"\n\t\t\t\t\t\t\t\t\tonClick={handleClose}\n\t\t\t\t\t\t\t\t\taria-label={t(\"widget.aria_close\")}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<CloseGlyph docked={placement === \"docked\"} />\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t{menuOpen && (\n\t\t\t\t\t\t\t\t\t<div className=\"hw-header-menu\" role=\"menu\">\n\t\t\t\t\t\t\t\t\t\t{/* The docked shell has no tab bar and no list screen, so a visitor\n\t\t\t\t\t\t\t\t\t\t with three threads had no way back to the other two — the menu\n\t\t\t\t\t\t\t\t\t\t offered starting a fourth. Their own conversations belong here,\n\t\t\t\t\t\t\t\t\t\t ahead of the button that makes new ones. */}\n\t\t\t\t\t\t\t\t\t\t{conversations.length > 0 && (\n\t\t\t\t\t\t\t\t\t\t\t<div className=\"hw-header-menu-convs\">\n\t\t\t\t\t\t\t\t\t\t\t\t{conversations.slice(0, 3).map((conv) => (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\trole=\"menuitem\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tkey={conv.id}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"hw-header-menu-conv\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata-active={conv.id === activeId ? \"true\" : undefined}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetMenuOpen(false);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\topenConversation(conv.id);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"hw-header-menu-conv-top\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"hw-header-menu-conv-name\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{conv.assigneeName ??\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(conv.lastMessageSenderType === \"team\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? conv.lastMessageSenderName\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: null) ??\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcompanyName}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{conv.lastMessageAt && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"hw-header-menu-conv-time\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{formatRelativeTime(conv.lastMessageAt)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"hw-header-menu-conv-preview\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{conv.lastMessageText ?? t(\"widget.no_preview\")}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\trole=\"menuitem\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\t\tsetMenuOpen(false);\n\t\t\t\t\t\t\t\t\t\t\t\topenNewConversation();\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<NewChatIcon size={16} />\n\t\t\t\t\t\t\t\t\t\t\t{t(\"widget.new_conversation\")}\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{/* ── Home: hero header with gradient + sheet overlay ── */}\n\t\t\t\t\t{subView === null && activeTab === \"home\" && (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<div className=\"hw-hero\">\n\t\t\t\t\t\t\t\t<div className=\"hw-hero-top\">\n\t\t\t\t\t\t\t\t\t<div className=\"hw-hero-bot-icon\">\n\t\t\t\t\t\t\t\t\t\t<WidgetLogo />\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"hw-hero-close\"\n\t\t\t\t\t\t\t\t\t\tonClick={handleClose}\n\t\t\t\t\t\t\t\t\t\taria-label={t(\"widget.aria_close\")}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<CloseGlyph docked={placement === \"docked\"} />\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div className=\"hw-hero-greeting\">\n\t\t\t\t\t\t\t\t\t{welcomeMessage.split(\"\\n\").map((line, i) => (\n\t\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\t\tkey={i}\n\t\t\t\t\t\t\t\t\t\t\tclassName={i === 0 ? \"hw-hero-greeting-name\" : \"hw-hero-greeting-question\"}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{i > 0 && <br />}\n\t\t\t\t\t\t\t\t\t\t\t{line}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div className=\"hw-hero-subtitle\">{subtitleText}</div>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t{/* Sheet — overlaps hero, Intercom-style white drawer */}\n\t\t\t\t\t\t\t<div className=\"hw-sheet\">\n\t\t\t\t\t\t\t\t<div className=\"hw-sheet-inner\">\n\t\t\t\t\t\t\t\t\t<button type=\"button\" className=\"hw-card\" onClick={openNewConversation}>\n\t\t\t\t\t\t\t\t\t\t<div className=\"hw-card-body\">\n\t\t\t\t\t\t\t\t\t\t\t<div className=\"hw-card-title\">{t(\"widget.send_us_message\")}</div>\n\t\t\t\t\t\t\t\t\t\t\t<div className=\"hw-card-meta\">{t(\"widget.reply_time\")}</div>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t<div className=\"hw-card-arrow\">\n\t\t\t\t\t\t\t\t\t\t\t<SendIcon />\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t{announcementTabs.length > 0 && (\n\t\t\t\t\t\t\t\t\t\t<WhatsNewCard\n\t\t\t\t\t\t\t\t\t\t\tgetUnseenEntries={getUnseenEntries}\n\t\t\t\t\t\t\t\t\t\t\tannouncementTabs={announcementTabs}\n\t\t\t\t\t\t\t\t\t\t\tonViewAll={() => {\n\t\t\t\t\t\t\t\t\t\t\t\tswitchTab(`content:${announcementTabs[0]!.id}`);\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\tonSelect={(slug, tabId) => {\n\t\t\t\t\t\t\t\t\t\t\t\tswitchTab(`content:${tabId}`);\n\t\t\t\t\t\t\t\t\t\t\t\tsetContentDetailSlug(slug);\n\t\t\t\t\t\t\t\t\t\t\t\tsetSubView(\"content-detail\");\n\t\t\t\t\t\t\t\t\t\t\t\tmarkEntrySeen(slug);\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t<HomeView\n\t\t\t\t\t\t\t\t\t\tconversations={conversations}\n\t\t\t\t\t\t\t\t\t\tonSelect={openConversation}\n\t\t\t\t\t\t\t\t\t\tonMessagesClick={() => switchTab(\"messages\")}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{/* ── Messages tab header ── */}\n\t\t\t\t\t{subView === null && activeTab === \"messages\" && (\n\t\t\t\t\t\t<div className=\"hw-header hw-header--centered\">\n\t\t\t\t\t\t\t<div className=\"hw-header-spacer\" />\n\t\t\t\t\t\t\t<div className=\"hw-header-title\">{t(\"widget.messages\")}</div>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclassName=\"hw-header-close\"\n\t\t\t\t\t\t\t\tonClick={handleClose}\n\t\t\t\t\t\t\t\taria-label={t(\"widget.aria_close\")}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<CloseGlyph docked={placement === \"docked\"} />\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{/* ── Content tab header (list view, not detail) ── */}\n\t\t\t\t\t{subView === null &&\n\t\t\t\t\t\tactiveTab.startsWith(\"content:\") &&\n\t\t\t\t\t\t(() => {\n\t\t\t\t\t\t\tconst tabId = activeTab.replace(\"content:\", \"\");\n\t\t\t\t\t\t\tconst contentTab = contentTabs.find((t) => t.id === tabId);\n\t\t\t\t\t\t\tif (!contentTab) return null;\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<div className=\"hw-header hw-header--centered\">\n\t\t\t\t\t\t\t\t\t<div className=\"hw-header-spacer\" />\n\t\t\t\t\t\t\t\t\t<div className=\"hw-header-title\">{resolveLabel(contentTab.label)}</div>\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"hw-header-close\"\n\t\t\t\t\t\t\t\t\t\tonClick={handleClose}\n\t\t\t\t\t\t\t\t\t\taria-label={t(\"widget.aria_close\")}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<CloseGlyph docked={placement === \"docked\"} />\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})()}\n\n\t\t\t\t\t{/* ── Content (non-home views) ── */}\n\t\t\t\t\t{(subView !== null || activeTab !== \"home\") && (\n\t\t\t\t\t\t<div className=\"hw-content\">\n\t\t\t\t\t\t\t{subView === null && activeTab === \"messages\" && (\n\t\t\t\t\t\t\t\t<MessagesView\n\t\t\t\t\t\t\t\t\tconversations={conversations}\n\t\t\t\t\t\t\t\t\tonSelect={openConversation}\n\t\t\t\t\t\t\t\t\tonNewClick={openNewConversation}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t{subView === \"new\" && (\n\t\t\t\t\t\t\t\t<NewConversationView\n\t\t\t\t\t\t\t\t\ttext={newText}\n\t\t\t\t\t\t\t\t\tonTextChange={setNewText}\n\t\t\t\t\t\t\t\t\tonSubmit={handleNewConversation}\n\t\t\t\t\t\t\t\t\tisSubmitting={isCreating}\n\t\t\t\t\t\t\t\t\twelcomeMessage={welcomeMessage}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t{subView === \"conversation\" && activeId && (\n\t\t\t\t\t\t\t\t<ConversationView conversationId={activeId} starters={dockSuggestions} />\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t{/* ── Content tab views ── */}\n\t\t\t\t\t\t\t{activeTab.startsWith(\"content:\") &&\n\t\t\t\t\t\t\t\t(() => {\n\t\t\t\t\t\t\t\t\tconst tabId = activeTab.replace(\"content:\", \"\");\n\t\t\t\t\t\t\t\t\tconst contentTab = contentTabs.find((t) => t.id === tabId);\n\t\t\t\t\t\t\t\t\tif (!contentTab) return null;\n\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t<ContentTabView\n\t\t\t\t\t\t\t\t\t\t\ttab={contentTab}\n\t\t\t\t\t\t\t\t\t\t\tshowDetail={subView === \"content-detail\"}\n\t\t\t\t\t\t\t\t\t\t\tdetailSlug={contentDetailSlug}\n\t\t\t\t\t\t\t\t\t\t\tsubView={subView}\n\t\t\t\t\t\t\t\t\t\t\tonSelectEntry={(slug) => {\n\t\t\t\t\t\t\t\t\t\t\t\tsetContentDetailSlug(slug);\n\t\t\t\t\t\t\t\t\t\t\t\tsetSubView(\"content-detail\");\n\t\t\t\t\t\t\t\t\t\t\t\t// Mark seen on open, mirroring the home-tab and\n\t\t\t\t\t\t\t\t\t\t\t\t// deep-link paths. Without this, opening a changelog\n\t\t\t\t\t\t\t\t\t\t\t\t// entry from the content tab left the unseen badge\n\t\t\t\t\t\t\t\t\t\t\t\t// stuck until another path happened to clear it.\n\t\t\t\t\t\t\t\t\t\t\t\tmarkEntrySeen(slug);\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\tonSelectCategory={(cat) => {\n\t\t\t\t\t\t\t\t\t\t\t\tsetContentCategoryName(cat.title);\n\t\t\t\t\t\t\t\t\t\t\t\tsetSubView(\"content-category\");\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t})()}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{/* ── Tab Bar ── */}\n\t\t\t\t\t{showTabBar && (\n\t\t\t\t\t\t<TabBar\n\t\t\t\t\t\t\tactiveTab={activeTab}\n\t\t\t\t\t\t\tonTabChange={switchTab}\n\t\t\t\t\t\t\tunreadCount={totalUnread}\n\t\t\t\t\t\t\tcontentTabs={contentTabs}\n\t\t\t\t\t\t\tshowMessagesTab={agentConfig?.showMessagesTab ?? true}\n\t\t\t\t\t\t\tunseenAnnouncementCount={unseenAnnouncementCount}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{/* ── Footer ── */}\n\t\t\t\t\t<div className=\"hw-powered\">\n\t\t\t\t\t\t{t(\"widget.powered_by\")}{\" \"}\n\t\t\t\t\t\t<a href=\"https://helpway.ai\" target=\"_blank\" rel=\"noopener noreferrer\">\n\t\t\t\t\t\t\tHelpway\n\t\t\t\t\t\t</a>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Message Preview — shown when widget is closed and not dismissed.\n\t\t\t Gated on isReady alongside the bubble so the proactive teaser\n\t\t\t doesn't pop in with default content before bootstrap. */}\n\t\t\t{isReady && !isOpen && !isDismissed && !hideLauncher && (\n\t\t\t\t/* No auto-dismiss. This card only ever carries a real incoming reply,\n\t\t\t\t and the old 8-second timer deleted it: a visitor who looked away\n\t\t\t\t for a moment lost the notification entirely — the unread count\n\t\t\t\t stayed, the words did not. It now waits for the visitor to open\n\t\t\t\t the thread or close the card, which is what a notification is\n\t\t\t\t supposed to do. */\n\t\t\t\t<MessagePreview\n\t\t\t\t\tonOpen={handleBubbleClick}\n\t\t\t\t\tavatar={<WidgetLogo />}\n\t\t\t\t\tautoDismissMs={null}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t{/* Announcement Previews — shown when widget is closed and unseen announcements exist */}\n\t\t\t{isReady && !isOpen && !isDismissed && !hideLauncher && (\n\t\t\t\t<AnnouncementPreviews\n\t\t\t\t\tavatar={<WidgetLogo />}\n\t\t\t\t\tonOpen={(slug, tabId) => {\n\t\t\t\t\t\tmarkEntrySeen(slug);\n\t\t\t\t\t\thandleBubbleClick();\n\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\tswitchTab(`content:${tabId}`);\n\t\t\t\t\t\t\tsetContentDetailSlug(slug);\n\t\t\t\t\t\t\tsetSubView(\"content-detail\");\n\t\t\t\t\t\t}, 50);\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t{/* Dev-only debug overlay — activates via ?hwdebug=1 or localStorage hw:debug=1 */}\n\t\t\t<WidgetDebugOverlay />\n\n\t\t\t{/* Bubble — hidden until bootstrap completes so visitors don't\n\t\t\t see a flash of the default Helpway brand mark + neutral\n\t\t\t color before the org's custom icon + brand color arrive.\n\t\t\t isReady flips true once and stays true, so the bubble\n\t\t\t remains visible across the rest of the session. */}\n\t\t\t{isReady && !isDismissed && (!hideLauncher || isOpen) && (\n\t\t\t\t<button\n\t\t\t\t\tref={bubbleRef}\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName={[\n\t\t\t\t\t\t\"hw-bubble\",\n\t\t\t\t\t\t`hw-bubble--${bubbleStyle}`,\n\t\t\t\t\t\tlauncherStyle !== \"icon\" ? `hw-bubble--launcher-${launcherStyle}` : \"\",\n\t\t\t\t\t\tisOpen ? \"hw-bubble--open\" : \"\",\n\t\t\t\t\t\t(agentConfig?.launcherIconUrl || agentConfig?.avatarUrl || website?.logoUrl) ? \"hw-bubble--avatar\" : \"\",\n\t\t\t\t\t]\n\t\t\t\t\t\t.filter(Boolean)\n\t\t\t\t\t\t.join(\" \")}\n\t\t\t\t\tonClick={handleBubbleClick}\n\t\t\t\t\taria-label={isOpen ? t(\"widget.aria_close_support\") : t(\"widget.aria_open\")}\n\t\t\t\t\taria-expanded={isOpen}\n\t\t\t\t\taria-haspopup=\"dialog\"\n\t\t\t\t>\n\t\t\t\t\t<span\n\t\t\t\t\t\tclassName={`hw-bubble-icon hw-bubble-icon--bot ${isOpen ? \"hw-bubble-icon--hidden\" : \"\"}`}\n\t\t\t\t\t>\n\t\t\t\t\t\t<LauncherIcon />\n\t\t\t\t\t</span>\n\t\t\t\t\t<span\n\t\t\t\t\t\tclassName={`hw-bubble-icon hw-bubble-icon--close ${!isOpen ? \"hw-bubble-icon--hidden\" : \"\"}`}\n\t\t\t\t\t>\n\t\t\t\t\t\t<XIcon size={24} />\n\t\t\t\t\t</span>\n\t\t\t\t\t{launcherStyle !== \"icon\" && !isOpen && (\n\t\t\t\t\t\t<span className=\"hw-bubble-label\">\n\t\t\t\t\t\t\t{launcherStyle === \"help\" ? t(\"widget.help\") : companyName}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t)}\n\t\t\t\t\t{!isOpen && (totalUnread > 0 || unseenAnnouncementCount > 0) && (\n\t\t\t\t\t\t<div className=\"hw-bubble-badge\">\n\t\t\t\t\t\t\t{totalUnread > 0 ? totalUnread : \"\"}\n\t\t\t\t\t\t\t{totalUnread === 0 && unseenAnnouncementCount > 0 && (\n\t\t\t\t\t\t\t\t<span className=\"hw-bubble-badge-dot\" />\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</button>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\n// ── Tab Bar ─────────────────────────────────────────────\n\nfunction TabBar({\n\tactiveTab,\n\tonTabChange,\n\tunreadCount,\n\tcontentTabs,\n\tshowMessagesTab = true,\n\tunseenAnnouncementCount = 0,\n}: {\n\tactiveTab: Tab;\n\tonTabChange: (tab: Tab) => void;\n\tunreadCount: number;\n\tcontentTabs: WidgetContentTab[];\n\tshowMessagesTab?: boolean;\n\tunseenAnnouncementCount?: number;\n}) {\n\treturn (\n\t\t<div className=\"hw-tabs\" role=\"tablist\">\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tclassName={`hw-tabs-item ${activeTab === \"home\" ? \"hw-tabs-item--active\" : \"\"}`}\n\t\t\t\tonClick={() => onTabChange(\"home\")}\n\t\t\t\trole=\"tab\"\n\t\t\t\taria-selected={activeTab === \"home\"}\n\t\t\t>\n\t\t\t\t<HomeIcon />\n\t\t\t\t<span>{t(\"widget.home\")}</span>\n\t\t\t</button>\n\t\t\t{showMessagesTab && (\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName={`hw-tabs-item ${activeTab === \"messages\" ? \"hw-tabs-item--active\" : \"\"}`}\n\t\t\t\t\tonClick={() => onTabChange(\"messages\")}\n\t\t\t\t\trole=\"tab\"\n\t\t\t\t\taria-selected={activeTab === \"messages\"}\n\t\t\t\t>\n\t\t\t\t\t<span className=\"hw-tabs-icon-wrap\">\n\t\t\t\t\t\t<MessagesIcon />\n\t\t\t\t\t\t{unreadCount > 0 && (\n\t\t\t\t\t\t\t<span className=\"hw-tabs-badge\">{unreadCount > 99 ? \"99+\" : unreadCount}</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</span>\n\t\t\t\t\t<span>{t(\"widget.messages\")}</span>\n\t\t\t\t</button>\n\t\t\t)}\n\t\t\t{/* Dynamic content tabs from Better i18n Content CMS */}\n\t\t\t{contentTabs.map((tab) => (\n\t\t\t\t<button\n\t\t\t\t\tkey={tab.id}\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName={`hw-tabs-item ${activeTab === `content:${tab.id}` ? \"hw-tabs-item--active\" : \"\"}`}\n\t\t\t\t\tonClick={() => onTabChange(`content:${tab.id}`)}\n\t\t\t\t\trole=\"tab\"\n\t\t\t\t\taria-selected={activeTab === `content:${tab.id}`}\n\t\t\t\t>\n\t\t\t\t\t<span className=\"hw-tabs-icon-wrap\">\n\t\t\t\t\t\t<ContentTabIconComponent icon={tab.icon} />\n\t\t\t\t\t\t{tab.isAnnouncements && unseenAnnouncementCount > 0 && (\n\t\t\t\t\t\t\t<span className=\"hw-tabs-dot\" />\n\t\t\t\t\t\t)}\n\t\t\t\t\t</span>\n\t\t\t\t\t<span>{resolveLabel(tab.label)}</span>\n\t\t\t\t</button>\n\t\t\t))}\n\t\t</div>\n\t);\n}\n\n// ── Home Tab ────────────────────────────────────────────\n\nfunction HomeView({\n\tconversations,\n\tonSelect,\n\tonMessagesClick,\n}: {\n\tconversations: ConversationSummary[];\n\tonSelect: (id: string) => void;\n\tonMessagesClick: () => void;\n}) {\n\tconst recent = conversations.slice(0, 3);\n\tif (recent.length === 0) return null;\n\n\treturn (\n\t\t<div className=\"hw-recent-card\">\n\t\t\t<div className=\"hw-recent-header\">{t(\"widget.recent_conversations\")}</div>\n\t\t\t{recent.map((conv, i) => (\n\t\t\t\t<ConversationRow\n\t\t\t\t\tkey={conv.id}\n\t\t\t\t\tconversation={conv}\n\t\t\t\t\tonSelect={onSelect}\n\t\t\t\t\tisLast={i === recent.length - 1}\n\t\t\t\t/>\n\t\t\t))}\n\t\t\t{conversations.length > 3 && (\n\t\t\t\t<button type=\"button\" className=\"hw-recent-see-all\" onClick={onMessagesClick}>\n\t\t\t\t\t{t(\"widget.see_all\")}\n\t\t\t\t</button>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\n// ── Messages Tab ────────────────────────────────────────\n\nfunction MessagesView({\n\tconversations,\n\tonSelect,\n\tonNewClick,\n}: {\n\tconversations: ConversationSummary[];\n\tonSelect: (id: string) => void;\n\tonNewClick: () => void;\n}) {\n\tif (conversations.length === 0) {\n\t\treturn (\n\t\t\t<div className=\"hw-empty-state\">\n\t\t\t\t<div className=\"hw-empty-icon-wrap\">\n\t\t\t\t\t<MessagesIcon />\n\t\t\t\t</div>\n\t\t\t\t<div className=\"hw-empty-title\">{t(\"widget.no_messages\")}</div>\n\t\t\t\t<div className=\"hw-empty-desc\">{t(\"widget.no_messages_desc\")}</div>\n\t\t\t\t<button type=\"button\" className=\"hw-empty-btn\" onClick={onNewClick}>\n\t\t\t\t\t{t(\"widget.start_conversation\")}\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<div className=\"hw-msgs-tab\">\n\t\t\t{conversations.map((conv) => (\n\t\t\t\t<ConversationCard key={conv.id} conversation={conv} onSelect={onSelect} />\n\t\t\t))}\n\t\t</div>\n\t);\n}\n\n// ── Shared conversation body (avatar + name + time + preview) ──\n\nfunction ConvCardBody({ conv }: { conv: ConversationSummary }) {\n\tconst agentName = useWidgetStore((s) => s.agentConfig?.name) ?? \"Support\";\n\tconst isTeam = conv.lastMessageSenderType === \"team\" && conv.lastMessageSenderName;\n\tconst displayName = isTeam ? conv.lastMessageSenderName! : agentName;\n\tconst preview = conv.lastMessageText ?? t(\"widget.no_preview\");\n\treturn (\n\t\t<>\n\t\t\t<div className={`hw-conv-card-avatar${isTeam ? \" hw-conv-card-avatar--team\" : \"\"}`}>\n\t\t\t\t{isTeam ? (\n\t\t\t\t\tconv.lastMessageSenderImage ? (\n\t\t\t\t\t\t<img src={conv.lastMessageSenderImage} alt={displayName} className=\"hw-conv-card-avatar-img\" />\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<span className=\"hw-conv-card-avatar-initials\">\n\t\t\t\t\t\t\t{displayName.split(\" \").map((w) => w[0]).join(\"\").slice(0, 2).toUpperCase()}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t)\n\t\t\t\t) : (\n\t\t\t\t\t<WidgetLogo />\n\t\t\t\t)}\n\t\t\t</div>\n\t\t\t<div className=\"hw-conv-card-content\">\n\t\t\t\t<div className=\"hw-conv-card-top\">\n\t\t\t\t\t<span className=\"hw-conv-card-name\">{displayName}</span>\n\t\t\t\t\t{conv.lastMessageAt && (\n\t\t\t\t\t\t<span className=\"hw-conv-card-time\">{formatRelativeTime(conv.lastMessageAt)}</span>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t<div className=\"hw-conv-card-preview\">{preview}</div>\n\t\t\t</div>\n\t\t</>\n\t);\n}\n\n// ── Conversation Card (Intercom-style, Messages tab) ─────\n\nfunction ConversationCard({\n\tconversation: conv,\n\tonSelect,\n}: {\n\tconversation: ConversationSummary;\n\tonSelect: (id: string) => void;\n}) {\n\tconst hasUnread = conv.unreadCount > 0;\n\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tclassName={`hw-conv-card ${hasUnread ? \"hw-conv-card--unread\" : \"\"}`}\n\t\t\tonClick={() => onSelect(conv.id)}\n\t\t>\n\t\t\t<div className=\"hw-conv-card-row\">\n\t\t\t\t<ConvCardBody conv={conv} />\n\t\t\t</div>\n\t\t\t{hasUnread && <div className=\"hw-conv-card-badge\">{conv.unreadCount}</div>}\n\t\t</button>\n\t);\n}\n\n// ── Conversation Row (inside Home tab grouped card) ───────\n\nfunction ConversationRow({\n\tconversation: conv,\n\tonSelect,\n\tisLast,\n}: {\n\tconversation: ConversationSummary;\n\tonSelect: (id: string) => void;\n\tisLast: boolean;\n}) {\n\tconst hasUnread = conv.unreadCount > 0;\n\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tclassName={`hw-recent-row ${hasUnread ? \"hw-recent-row--unread\" : \"\"} ${isLast ? \"hw-recent-row--last\" : \"\"}`}\n\t\t\tonClick={() => onSelect(conv.id)}\n\t\t>\n\t\t\t<ConvCardBody conv={conv} />\n\t\t\t{hasUnread && <div className=\"hw-recent-row-badge\">{conv.unreadCount}</div>}\n\t\t</button>\n\t);\n}\n\n// ── Inline Email Prompt (post-first-reply) ─────────────\n\nfunction InlineEmailPrompt({ conversationId }: { conversationId?: string }) {\n\tconst { client, store } = useWidgetContext();\n\tconst updateContact = useWidgetStore((s) => s.updateVisitorContact);\n\tconst [email, setEmail] = useState(\"\");\n\tconst [isSubmitting, setIsSubmitting] = useState(false);\n\tconst [isSuccess, setIsSuccess] = useState(false);\n\tconst [hasError, setHasError] = useState(false);\n\n\tconst handleSubmit = async () => {\n\t\tconst trimmed = email.trim();\n\t\tif (!trimmed || !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(trimmed)) {\n\t\t\tsetHasError(true);\n\t\t\treturn;\n\t\t}\n\t\tsetHasError(false);\n\n\t\tconst previousContact = store.getState().visitor?.contact ?? null;\n\t\tconst optimisticContactId = previousContact?.id ?? `optimistic-contact-${Date.now()}`;\n\t\tupdateContact({\n\t\t\tid: optimisticContactId,\n\t\t\tname: previousContact?.name ?? null,\n\t\t\temail: trimmed,\n\t\t});\n\t\tsetIsSuccess(true);\n\t\tsetIsSubmitting(true);\n\t\ttry {\n\t\t\tconst result = await client.widget.collectEmail.mutate({\n\t\t\t\temail: trimmed,\n\t\t\t\t...(conversationId ? { conversationId } : {}),\n\t\t\t});\n\t\t\tif (result.contact) {\n\t\t\t\tupdateContact({\n\t\t\t\t\tid: result.contact.id,\n\t\t\t\t\tname: result.contact.name,\n\t\t\t\t\temail: result.contact.email,\n\t\t\t\t});\n\t\t\t}\n\t\t\t// needsEmail will become false via optimistic contact update\n\t\t} catch {\n\t\t\tif (previousContact) {\n\t\t\t\tupdateContact(previousContact);\n\t\t\t} else {\n\t\t\t\tupdateContact({ id: \"\", name: null, email: null });\n\t\t\t}\n\t\t\tsetIsSuccess(false);\n\t\t} finally {\n\t\t\tsetIsSubmitting(false);\n\t\t}\n\t};\n\n\tif (isSuccess) {\n\t\treturn (\n\t\t\t<div className=\"hw-email-card hw-email-card--success\">\n\t\t\t\t<svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#22c55e\" strokeWidth={2.5} strokeLinecap=\"round\" strokeLinejoin=\"round\">\n\t\t\t\t\t<polyline points=\"20 6 9 17 4 12\" />\n\t\t\t\t</svg>\n\t\t\t\t{t(\"widget.email_saved\")}\n\t\t\t</div>\n\t\t);\n\t}\n\n\t/* Asking for an email is a one-field favour, and it was built like a form: an\n\t icon tile, two lines of header, a full-width input and a full-width button —\n\t four stacked blocks and about 150px of thread for one address. It is a\n\t labelled row now, with the submit inside the field, so it reads as part of\n\t the conversation rather than an interruption of it. */\n\treturn (\n\t\t<div className=\"hw-email-card\">\n\t\t\t<p className=\"hw-email-card-title\">{t(\"widget.email_title\")}</p>\n\t\t\t<p className=\"hw-email-card-subtitle\">{t(\"widget.email_subtitle\")}</p>\n\t\t\t<div className=\"hw-email-card-row\">\n\t\t\t\t<input\n\t\t\t\t\ttype=\"email\"\n\t\t\t\t\tclassName={`hw-email-card-input${hasError ? \" hw-email-card-input--error\" : \"\"}`}\n\t\t\t\t\tvalue={email}\n\t\t\t\t\tonChange={(e) => { setEmail(e.target.value); setHasError(false); }}\n\t\t\t\t\tonKeyDown={(e) => { if (e.key === \"Enter\") handleSubmit(); }}\n\t\t\t\t\tplaceholder={t(\"widget.email_placeholder\")}\n\t\t\t\t/>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"hw-email-card-submit\"\n\t\t\t\t\tonClick={handleSubmit}\n\t\t\t\t\tdisabled={isSubmitting || !email.trim()}\n\t\t\t\t\taria-label={t(\"widget.email_continue\")}\n\t\t\t\t>\n\t\t\t\t\t{isSubmitting ? (\n\t\t\t\t\t\t<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} aria-hidden=\"true\">\n\t\t\t\t\t\t\t<circle cx=\"12\" cy=\"12\" r=\"10\" strokeDasharray=\"32\" strokeDashoffset=\"32\">\n\t\t\t\t\t\t\t\t<animate attributeName=\"stroke-dashoffset\" values=\"32;0\" dur=\"1s\" repeatCount=\"indefinite\" />\n\t\t\t\t\t\t\t</circle>\n\t\t\t\t\t\t</svg>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2.2} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n\t\t\t\t\t\t\t<path d=\"M5 12h13M12 5l7 7-7 7\" />\n\t\t\t\t\t\t</svg>\n\t\t\t\t\t)}\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\n// ── New Conversation ────────────────────────────────────\n\nfunction NewConversationView({\n\ttext,\n\tonTextChange,\n\tonSubmit,\n\tisSubmitting,\n\twelcomeMessage,\n}: {\n\ttext: string;\n\tonTextChange: (t: string) => void;\n\tonSubmit: () => void;\n\tisSubmitting: boolean;\n\twelcomeMessage: string;\n}) {\n\t// Stable timestamp so the bubble doesn't tick/re-render while the user types.\n\treturn (\n\t\t<div className=\"hw-new\">\n\t\t\t{/* Use the same MessageBubble that renders inside ConversationView so\n\t\t\t the welcome message looks IDENTICAL before and after the first send\n\t\t\t — same markdown rendering (line breaks preserved), same styles,\n\t\t\t same meta row. Without this the \"new\" view uses a raw string render\n\t\t\t and the user sees the bubble visually change the moment the\n\t\t\t conversation is created. */}\n\t\t\t<div className=\"hw-new-welcome\">\n\t\t\t\t<MessageBubble\n\t\t\t\t\ttext={welcomeMessage}\n\t\t\t\t\tsender=\"ai\"\n\t\t\t\t\tparts={null}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t\t<Composer\n\t\t\t\ttext={text}\n\t\t\t\tonTextChange={onTextChange}\n\t\t\t\tonSubmit={onSubmit}\n\t\t\t\tisSubmitting={isSubmitting}\n\t\t\t\tplaceholder={t(\"widget.placeholder_new\")}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n\n// ── Conversation View ───────────────────────────────────\n\nfunction ConversationView({\n\tconversationId,\n\tstarters,\n}: {\n\tconversationId: string;\n\t/** Offered under the greeting until the visitor has said something. */\n\tstarters?: readonly DockSuggestion[];\n}) {\n\tconst { items, isLoading, hasMore, loadMore } = useTimeline(conversationId);\n\tconst {\n\t\ttext,\n\t\tsetText,\n\t\tsubmit,\n\t\tisSubmitting,\n\t\tattachments,\n\t\taddFiles,\n\t\tremoveAttachment,\n\t\tsendError,\n\t\tclearSendError,\n\t\temailGateConvId,\n\t} = useComposer(conversationId);\n\tconst { isTyping, isAiProcessing, setTyping } = usePresence(conversationId);\n\tconst streamingText = useWidgetStore((s) => s.streamingText.get(conversationId) ?? \"\");\n\tconst agentConfig = useWidgetStore((s) => s.agentConfig);\n\tconst visitorContact = useWidgetStore((s) => s.visitor?.contact);\n\n\t// Only while the thread is still nothing but the seeded welcome. The\n\t// first rule here checked for a visitor message, which left the\n\t// suggestions sitting under \"<name> joined the conversation\" — a human\n\t// arriving is exactly the moment canned questions stop being helpful.\n\t// Any second item at all means something happened, so that is the test.\n\tconst showStarters = !!starters?.length && items.length <= 1;\n\n\t// Reaching a human is something the agent offers, not a control the\n\t// visitor has to find. Fin has none anywhere and gates the request\n\t// behind an email form; this is one tap and never gated. Shown once\n\t// the agent has actually said something, and dropped as soon as a\n\t// human is in the thread.\n\n\n\tconst isResolved = useWidgetStore((s) => {\n\t\tconst conv = s.conversations.find((c) => c.id === conversationId);\n\t\treturn conv?.status === \"resolved\";\n\t});\n\n\t// Email prompt gate (BETTER-227 — Intercom pattern).\n\t// Show ONLY after:\n\t// (1) visitor sent at least one real message (not the welcome bubble), AND\n\t// (2) AI has replied at least once (so the visitor has seen value from the widget)\n\t// Prevents the \"Get notified when we reply\" card from appearing on widget open\n\t// before the visitor has even typed. Matches Intercom's post-first-response flow.\n\tconst visitorMessageCount = items.filter(\n\t\t(it) => it.type === \"message\" && Boolean((it as { visitorId?: string | null }).visitorId),\n\t).length;\n\tconst hasAiReply = items.some(\n\t\t(it) => it.type === \"message\" && Boolean((it as { aiAgentId?: string | null }).aiAgentId),\n\t);\n\t// Email is satisfied if EITHER the contact has one (fully identified\n\t// visitor) OR the visitor itself has one (collected via the gate but\n\t// not yet linked to a Contact row). Without the visitor.email fallback,\n\t// the gate re-shows on every refresh until a Contact is created.\n\tconst visitorOwnEmail = useWidgetStore((s) => s.visitor?.email);\n\tconst hasEmail = !!visitorContact?.email || !!visitorOwnEmail;\n\tconst needsEmailPostReply =\n\t\t!!agentConfig?.requireVisitorEmail &&\n\t\t!hasEmail &&\n\t\tvisitorMessageCount >= 2 &&\n\t\thasAiReply;\n\tconst needsEmail = needsEmailPostReply || !!emailGateConvId;\n\n\tif (isLoading && items.length === 0) {\n\t\treturn (\n\t\t\t<div className=\"hw-messages\">\n\t\t\t\t<div className=\"hw-skeleton-messages\">\n\t\t\t\t\t{/* AI message skeleton */}\n\t\t\t\t\t<div className=\"hw-skeleton-msg\">\n\t\t\t\t\t\t<div className=\"hw-skeleton hw-skeleton-avatar\" />\n\t\t\t\t\t\t<div className=\"hw-skeleton-bubble\">\n\t\t\t\t\t\t\t<div className=\"hw-skeleton hw-skeleton-line\" style={{ width: 140 }} />\n\t\t\t\t\t\t\t<div className=\"hw-skeleton hw-skeleton-line\" style={{ width: 200 }} />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t{/* Visitor message skeleton */}\n\t\t\t\t\t<div className=\"hw-skeleton-msg hw-skeleton-msg--right\">\n\t\t\t\t\t\t<div className=\"hw-skeleton-bubble\" style={{ alignItems: \"flex-end\" }}>\n\t\t\t\t\t\t\t<div className=\"hw-skeleton hw-skeleton-line\" style={{ width: 160 }} />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t{/* AI reply skeleton */}\n\t\t\t\t\t<div className=\"hw-skeleton-msg\">\n\t\t\t\t\t\t<div className=\"hw-skeleton hw-skeleton-avatar\" />\n\t\t\t\t\t\t<div className=\"hw-skeleton-bubble\">\n\t\t\t\t\t\t\t<div className=\"hw-skeleton hw-skeleton-line\" style={{ width: 180 }} />\n\t\t\t\t\t\t\t<div className=\"hw-skeleton hw-skeleton-line\" style={{ width: 120 }} />\n\t\t\t\t\t\t\t<div className=\"hw-skeleton hw-skeleton-line\" style={{ width: 80 }} />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<>\n\t\t\t<MessageList\n\t\t\t\titems={items}\n\t\t\t\tisTyping={isTyping}\n\t\t\t\tisAiProcessing={isAiProcessing}\n\t\t\t\tstreamingText={streamingText || undefined}\n\t\t\t\thasMore={hasMore}\n\t\t\t\tisLoadingMore={isLoading}\n\t\t\t\tonLoadMore={loadMore}\n\t\t\t\t/* No \"Talk to a human\" offer here any more. The pipeline escalates on its\n\t\t\t\t own the moment it cannot answer — that is what the escalate tool is\n\t\t\t\t for — so the button was a second, manual path to something that had\n\t\t\t\t already happened, and it sat under every answer including the ones\n\t\t\t\t that were fine. */\n\t\t\t\t/* The email ask belongs IN the thread. Pinned under the list it read as\n\t\t\t\t chrome — a form the panel had grown at the bottom, competing with the\n\t\t\t\t composer directly below it — when what it actually is is the agent\n\t\t\t\t asking one more question. Inside the scroller it arrives after the last\n\t\t\t\t message, scrolls with it, and the reader answers it the way they\n\t\t\t\t answered everything else. */\n\t\t\t\trenderAfterMessages={\n\t\t\t\t\tneedsEmail || showStarters ? (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t{needsEmail && (\n\t\t\t\t\t\t\t\t<InlineEmailPrompt conversationId={emailGateConvId ?? undefined} />\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{showStarters && (\n\t\t\t\t\t\t\t\t<div className=\"hw-starters\">\n\t\t\t\t\t\t\t{starters?.map((entry, index) => {\n\t\t\t\t\t\t\t\tconst question = typeof entry === \"string\" ? entry : entry.question;\n\t\t\t\t\t\t\t\tconst label = typeof entry === \"string\" ? null : entry.label;\n\t\t\t\t\t\t\t\t/* The label leads and the question explains it. Side by side\n\t\t\t\t\t\t\t\t they fought for the same line: labels are short words in\n\t\t\t\t\t\t\t\t some configs (\"Pricing\") and half-sentences in others\n\t\t\t\t\t\t\t\t (\"Pick a framework\"), and a fixed-width column had to be\n\t\t\t\t\t\t\t\t wrong for one of them. Stacked, both lengths read the same.\n\t\t\t\t\t\t\t\t With no label the question IS the line, so it moves up. */\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\tkey={question}\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"hw-starter\"\n\t\t\t\t\t\t\t\t\t\tstyle={{ animationDelay: `${90 + index * 70}ms` }}\n\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\tvoid submit({ text: question });\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<span className=\"hw-starter-text\">\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"hw-starter-k\">{label ?? question}</span>\n\t\t\t\t\t\t\t\t\t\t\t{label && <span className=\"hw-starter-q\">{question}</span>}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t<ChevronRightIcon size={14} />\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</>\n\t\t\t\t\t) : undefined\n\t\t\t\t}\n\t\t\t/>\n\t\t\t{/* Resolved → show the CSAT banner ABOVE the composer, never INSTEAD\n\t\t\t of it. Keeping the composer mounted means a follow-up just\n\t\t\t works: the server reopens the thread (widget.sendMessage →\n\t\t\t status: open) so resolved is never a dead-end. */}\n\t\t\t{isResolved && <ResolvedBanner conversationId={conversationId} />}\n\t\t\t{sendError && (\n\t\t\t\t<div className=\"hw-send-error\">\n\t\t\t\t\t{sendError}\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"hw-send-error-retry\"\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tclearSendError();\n\t\t\t\t\t\t\tsubmit();\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"widget.retry\")}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t<Composer\n\t\t\t\ttext={text}\n\t\t\t\tonTextChange={setText}\n\t\t\t\tonSubmit={submit}\n\t\t\t\tonTyping={setTyping}\n\t\t\t\tisSubmitting={isSubmitting}\n\t\t\t\tattachments={attachments}\n\t\t\t\tonAddFiles={addFiles}\n\t\t\t\tonRemoveAttachment={removeAttachment}\n\t\t\t\tdisabled={needsEmail}\n\t\t\t/>\n\t\t</>\n\t);\n}\n\n// ── Resolved Banner with CSAT ───────────────────────────\n\nfunction ResolvedBanner({ conversationId }: { conversationId: string }) {\n\tconst { client } = useWidgetContext();\n\tconst [csatRating, setCsatRating] = useState<\"good\" | \"bad\" | null>(null);\n\tconst [csatSubmitted, setCsatSubmitted] = useState(false);\n\n\tconst handleCsat = (rating: \"good\" | \"bad\") => {\n\t\tsetCsatRating(rating);\n\t\tsetCsatSubmitted(true);\n\t\t// Send CSAT via API (fire and forget)\n\t\tclient.widget.sendCsat.mutate({ conversationId, rating }).catch(() => {});\n\t};\n\n\treturn (\n\t\t<div className=\"hw-resolved\">\n\t\t\t<div className=\"hw-resolved-text\">{t(\"widget.resolved_text\")}</div>\n\t\t\t{!csatSubmitted ? (\n\t\t\t\t<div className=\"hw-csat\">\n\t\t\t\t\t<div className=\"hw-csat-label\">{t(\"widget.csat_label\")}</div>\n\t\t\t\t\t<div className=\"hw-csat-buttons\">\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tclassName={`hw-csat-btn ${csatRating === \"good\" ? \"hw-csat-btn--selected\" : \"\"}`}\n\t\t\t\t\t\t\tonClick={() => handleCsat(\"good\")}\n\t\t\t\t\t\t\taria-label={t(\"widget.aria_good\")}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t👍\n\t\t\t\t\t\t</button>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tclassName={`hw-csat-btn ${csatRating === \"bad\" ? \"hw-csat-btn--selected\" : \"\"}`}\n\t\t\t\t\t\t\tonClick={() => handleCsat(\"bad\")}\n\t\t\t\t\t\t\taria-label={t(\"widget.aria_bad\")}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t👎\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t<div className=\"hw-csat-thanks\">{t(\"widget.csat_thanks\")}</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\n// ── Message Preview Bubble ─────────────────────\n// MessagePreview moved to ./message-preview.tsx so `hideLauncher`\n// integrations can render the same proactive bubble next to their own\n// trigger. DefaultWidget composes it with the launcher placement +\n// <WidgetLogo /> avatar above.\n\n// ── Announcement Preview Bubble ─────────────────\n// AnnouncementPreviews + AnnouncementPreviewItem (and the stripMarkdown\n// helper) moved to ./announcement-previews.tsx + ./strip-markdown.ts so\n// `hideLauncher` integrations can render the same proactive cards next\n// to their own trigger. DefaultWidget composes the export above with\n// the launcher placement + <WidgetLogo /> avatar.\n\n// ── What's New Card (Home tab) ──────────────────\n\nfunction WhatsNewCard({\n\tgetUnseenEntries,\n\tannouncementTabs,\n\tonViewAll,\n\tonSelect,\n}: {\n\tgetUnseenEntries: () => UnseenAnnouncementEntry[];\n\tannouncementTabs: WidgetContentTab[];\n\tonViewAll: () => void;\n\tonSelect: (slug: string, tabId: string) => void;\n}) {\n\tconst unseen = getUnseenEntries();\n\tif (unseen.length === 0) return null;\n\n\tconst display = unseen.slice(0, 3);\n\tconst badgeFieldMap = new Map(\n\t\tannouncementTabs.map((t) => [t.id, t.display?.badgeField]),\n\t);\n\n\treturn (\n\t\t<div className=\"hw-whats-new\">\n\t\t\t<div className=\"hw-whats-new-header\">\n\t\t\t\t<span className=\"hw-whats-new-title\">{resolveLabel(\"widget.whats_new\")}</span>\n\t\t\t\t<button type=\"button\" className=\"hw-whats-new-view-all\" onClick={onViewAll}>\n\t\t\t\t\t{resolveLabel(\"widget.view_all\")} →\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t\t<div className=\"hw-whats-new-list\">\n\t\t\t\t{display.map((entry) => {\n\t\t\t\t\tconst badgeField = badgeFieldMap.get(entry.tabId);\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\tkey={entry.slug}\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tclassName=\"hw-whats-new-item\"\n\t\t\t\t\t\t\tonClick={() => onSelect(entry.slug, entry.tabId)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{badgeField && entry.customFields[badgeField] && (\n\t\t\t\t\t\t\t\t<div className=\"hw-whats-new-item-top\">\n\t\t\t\t\t\t\t\t\t<span className=\"hw-whats-new-badge\">\n\t\t\t\t\t\t\t\t\t\t{entry.customFields[badgeField]}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t{entry.publishedAt && (\n\t\t\t\t\t\t\t\t\t\t<span className=\"hw-whats-new-time\">\n\t\t\t\t\t\t\t\t\t\t\t{formatRelativeTime(entry.publishedAt)}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t<div className=\"hw-whats-new-item-title\">\n\t\t\t\t\t\t\t\t{entry.title}\n\t\t\t\t\t\t\t\t{!badgeField && entry.publishedAt && (\n\t\t\t\t\t\t\t\t\t<span className=\"hw-whats-new-time-inline\">\n\t\t\t\t\t\t\t\t\t\t{formatRelativeTime(entry.publishedAt)}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t{entry.body && (() => {\n\t\t\t\t\t\t\t\tconst clean = stripMarkdown(entry.body);\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<div className=\"hw-whats-new-item-body\">\n\t\t\t\t\t\t\t\t\t\t{clean.length > 80 ? `${clean.slice(0, 80)}…` : clean}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t})()}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","import { CONTENT_CACHE_TTL, getLocale } from \"@helpway/widget-core\";\nimport type { WidgetContentTab } from \"@helpway/widget-core\";\nimport { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { useWidgetContext, useWidgetStore } from \"../provider\";\n\ninterface AnnouncementEntry {\n\tslug: string;\n\ttitle: string;\n\tbody: string | null;\n\tpublishedAt: string | null;\n\tcustomFields: Record<string, string | null>;\n}\n\nexport interface UnseenAnnouncementEntry extends AnnouncementEntry {\n\ttabId: string;\n}\n\n// ── Per-entry localStorage tracking ──\n\nfunction storageKey(websiteId: string, visitorId: string): string {\n\treturn `helpway:${websiteId}:${visitorId}:announcements:seen`;\n}\n\nfunction hasSeenKey(websiteId: string, visitorId: string): boolean {\n\ttry {\n\t\treturn localStorage.getItem(storageKey(websiteId, visitorId)) !== null;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction getSeenSlugs(websiteId: string, visitorId: string): Set<string> {\n\ttry {\n\t\tconst raw = localStorage.getItem(storageKey(websiteId, visitorId));\n\t\tif (!raw) return new Set();\n\t\treturn new Set(JSON.parse(raw) as string[]);\n\t} catch {\n\t\treturn new Set();\n\t}\n}\n\nfunction addSeenSlug(websiteId: string, visitorId: string, slug: string): void {\n\ttry {\n\t\tconst seen = getSeenSlugs(websiteId, visitorId);\n\t\tseen.add(slug);\n\t\tlocalStorage.setItem(storageKey(websiteId, visitorId), JSON.stringify([...seen]));\n\t} catch {\n\t\t// storage full or blocked\n\t}\n}\n\nfunction addSeenSlugs(websiteId: string, visitorId: string, slugs: string[]): void {\n\ttry {\n\t\tconst seen = getSeenSlugs(websiteId, visitorId);\n\t\tfor (const s of slugs) seen.add(s);\n\t\tlocalStorage.setItem(storageKey(websiteId, visitorId), JSON.stringify([...seen]));\n\t} catch {\n\t\t// storage full or blocked\n\t}\n}\n\nfunction filterUnseen(entries: AnnouncementEntry[], seen: Set<string>): AnnouncementEntry[] {\n\treturn entries.filter((e) => !seen.has(e.slug));\n}\n\nconst EMPTY_TABS: WidgetContentTab[] = [];\n\n/**\n * Per-entry announcement tracking across all tabs with isAnnouncements.\n *\n * Anonymous visitors (no contact) skip first-visit seeding — they always\n * see announcement previews. Identified visitors seed on first visit so\n * existing entries don't flood as unread.\n *\n * Multiple announcement tabs supported: previews stack, unseen count\n * aggregates, and each entry carries its tabId for correct navigation.\n */\nexport function useAnnouncements() {\n\tconst { client, store } = useWidgetContext();\n\tconst isReady = useWidgetStore((s) => s.isReady);\n\tconst websiteId = useWidgetStore((s) => s.website?.id) ?? null;\n\tconst visitorId = useWidgetStore((s) => s.visitor?.id) ?? null;\n\tconst isAnonymous = useWidgetStore((s) => !s.visitor?.contact);\n\tconst contentTabs = useWidgetStore((s) => s.agentConfig?.contentTabs) ?? EMPTY_TABS;\n\tconst announcementTabs = useMemo(\n\t\t() => contentTabs.filter((t) => t.isAnnouncements),\n\t\t[contentTabs],\n\t);\n\tconst checkedRef = useRef(false);\n\n\tuseEffect(() => {\n\t\tif (!isReady || !websiteId || !visitorId || announcementTabs.length === 0) return;\n\t\tif (checkedRef.current) return;\n\t\tcheckedRef.current = true;\n\n\t\tconst isFirstVisit = !hasSeenKey(websiteId, visitorId);\n\t\tlet pending = announcementTabs.length;\n\t\tlet totalUnseen = 0;\n\t\tconst allSlugs: string[] = [];\n\n\t\tfunction onTabDone(entries: AnnouncementEntry[], tab: WidgetContentTab) {\n\t\t\tallSlugs.push(...entries.map((e) => e.slug));\n\n\t\t\t// Identified user's first visit: defer unseen computation until\n\t\t\t// all tabs are collected so we can seed everything at once.\n\t\t\tif (!(isFirstVisit && !isAnonymous) && entries.length > 0) {\n\t\t\t\tconst seen = getSeenSlugs(websiteId!, visitorId!);\n\t\t\t\tconst unseen = filterUnseen(entries, seen);\n\t\t\t\ttotalUnseen += unseen.length;\n\n\t\t\t\tconst newest = unseen[0];\n\t\t\t\tif (newest && !store.getState().isOpen) {\n\t\t\t\t\tconst badgeField = tab.display?.badgeField;\n\t\t\t\t\tstore.getState().setAnnouncementPreview({\n\t\t\t\t\t\ttitle: newest.title,\n\t\t\t\t\t\tbody: newest.body,\n\t\t\t\t\t\tslug: newest.slug,\n\t\t\t\t\t\ttabId: tab.id,\n\t\t\t\t\t\tbadge: badgeField ? (newest.customFields[badgeField] ?? null) : null,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpending--;\n\t\t\tif (pending === 0) {\n\t\t\t\tif (isFirstVisit && !isAnonymous) {\n\t\t\t\t\t// Seed all entries across all tabs at once\n\t\t\t\t\tif (allSlugs.length > 0) {\n\t\t\t\t\t\taddSeenSlugs(websiteId!, visitorId!, allSlugs);\n\t\t\t\t\t}\n\t\t\t\t\tstore.getState().setUnseenAnnouncementCount(0);\n\t\t\t\t} else {\n\t\t\t\t\tstore.getState().setUnseenAnnouncementCount(totalUnseen);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (const tab of announcementTabs) {\n\t\t\tconst cacheKey = `announcements:${tab.id}:${getLocale()}`;\n\t\t\tconst cached = store.getState().contentCache.get(cacheKey);\n\t\t\tif (cached && Date.now() - cached.ts < CONTENT_CACHE_TTL) {\n\t\t\t\tonTabDone(cached.data as AnnouncementEntry[], tab);\n\t\t\t} else {\n\t\t\t\tclient.widget.getContent\n\t\t\t\t\t.query({ tabId: tab.id, page: 1, limit: 5, language: getLocale() })\n\t\t\t\t\t.then((result: { items?: AnnouncementEntry[] }) => {\n\t\t\t\t\t\tconst entries = result.items ?? [];\n\t\t\t\t\t\tstore.getState().setContentCache(cacheKey, entries);\n\t\t\t\t\t\tonTabDone(entries, tab);\n\t\t\t\t\t})\n\t\t\t\t\t.catch(() => {\n\t\t\t\t\t\tonTabDone([], tab);\n\t\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}, [isReady, websiteId, visitorId, isAnonymous, announcementTabs, client, store]);\n\n\tconst markEntrySeen = useCallback(\n\t\t(slug: string) => {\n\t\t\tif (!websiteId || !visitorId || announcementTabs.length === 0) return;\n\t\t\taddSeenSlug(websiteId, visitorId, slug);\n\n\t\t\t// Recompute total unseen count across all tabs\n\t\t\tconst seen = getSeenSlugs(websiteId, visitorId);\n\t\t\tlet total = 0;\n\t\t\tfor (const tab of announcementTabs) {\n\t\t\t\tconst cacheKey = `announcements:${tab.id}:${getLocale()}`;\n\t\t\t\tconst cached = store.getState().contentCache.get(cacheKey);\n\t\t\t\tif (cached) {\n\t\t\t\t\ttotal += filterUnseen(cached.data as AnnouncementEntry[], seen).length;\n\t\t\t\t}\n\t\t\t}\n\t\t\tstore.getState().setUnseenAnnouncementCount(total);\n\t\t\tstore.getState().dismissAnnouncementPreview(slug);\n\t\t},\n\t\t[websiteId, visitorId, announcementTabs, store],\n\t);\n\n\tconst markAllSeen = useCallback(() => {\n\t\tif (!websiteId || !visitorId || announcementTabs.length === 0) return;\n\t\tfor (const tab of announcementTabs) {\n\t\t\tconst cacheKey = `announcements:${tab.id}:${getLocale()}`;\n\t\t\tconst cached = store.getState().contentCache.get(cacheKey);\n\t\t\tif (cached) {\n\t\t\t\tconst entries = cached.data as AnnouncementEntry[];\n\t\t\t\taddSeenSlugs(websiteId, visitorId, entries.map((e) => e.slug));\n\t\t\t}\n\t\t}\n\t\tstore.getState().setUnseenAnnouncementCount(0);\n\t\tstore.getState().dismissAnnouncementPreview();\n\t}, [websiteId, visitorId, announcementTabs, store]);\n\n\tconst getUnseenEntries = useCallback((): UnseenAnnouncementEntry[] => {\n\t\tif (announcementTabs.length === 0 || !websiteId || !visitorId) return [];\n\t\tconst seen = getSeenSlugs(websiteId, visitorId);\n\t\tconst result: UnseenAnnouncementEntry[] = [];\n\t\tfor (const tab of announcementTabs) {\n\t\t\tconst cacheKey = `announcements:${tab.id}:${getLocale()}`;\n\t\t\tconst cached = store.getState().contentCache.get(cacheKey);\n\t\t\tif (cached) {\n\t\t\t\tfor (const entry of filterUnseen(cached.data as AnnouncementEntry[], seen)) {\n\t\t\t\t\tresult.push({ ...entry, tabId: tab.id });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}, [announcementTabs, websiteId, visitorId, store]);\n\n\treturn {\n\t\tannouncementTabs,\n\t\tmarkEntrySeen,\n\t\tmarkAllSeen,\n\t\tgetUnseenEntries,\n\t};\n}\n","import type { TimelineItem } from \"@helpway/types\";\nimport { t } from \"@helpway/widget-core\";\nimport { useCallback, useState } from \"react\";\nimport { useWidgetContext } from \"../provider\";\n\n/**\n * The page the visitor is on, shaped for `sendMessage`.\n *\n * Returns nothing off the browser (SSR) or when the URL is unreadable, so the\n * field simply stays absent rather than sending an empty page the server would\n * have to defend against.\n */\nfunction currentPagePayload(): { page?: { url: string; title: string } } {\n\tif (typeof window === \"undefined\") return {};\n\tconst url = window.location.href;\n\tif (!url) return {};\n\treturn { page: { url, title: document.title || window.location.pathname } };\n}\n\nexport interface PendingAttachment {\n\tid: string;\n\tfile: File;\n\tpreviewUrl: string | null; // blob URL for images\n\tisUploading: boolean;\n\terror: string | null;\n\t/** Resolved after upload — the part to include in sendMessage */\n\tpart:\n\t\t| { type: \"image\"; url: string; mimeType: string }\n\t\t| { type: \"file\"; url: string; fileName: string; fileSize: number; mimeType: string }\n\t\t| null;\n}\n\nconst MAX_ATTACHMENTS = 10;\nconst MAX_FILE_SIZE = 10 * 1024 * 1024; // 10 MB\n\n/**\n * Composer state — text input + attachments + submit for a conversation.\n */\n/**\n * What the file picker will offer. Lives with the attachment hook rather than in\n * the composer that renders the picker: the docked bar has a picker of its own,\n * and two lists of accepted types drift the moment one of them gains a format.\n */\nexport const ACCEPTED_TYPES = [\n\t\"image/png\",\n\t\"image/jpeg\",\n\t\"image/gif\",\n\t\"image/webp\",\n\t\"image/svg+xml\",\n\t\"application/pdf\",\n\t\"text/plain\",\n\t\"text/csv\",\n\t\"application/zip\",\n\t\"application/msword\",\n\t\"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n\t\"application/vnd.ms-excel\",\n\t\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n].join(\",\");\n\nexport function useComposer(boundConversationId: string | null) {\n\tconst { client, ws, store } = useWidgetContext();\n\t// Alias so every callback below keeps reading `conversationId` while\n\t// `submit` is free to shadow it with a caller-supplied id (see there).\n\tconst conversationId = boundConversationId;\n\tconst [text, setText] = useState(\"\");\n\tconst [isSubmitting, setIsSubmitting] = useState(false);\n\tconst [attachments, setAttachments] = useState<PendingAttachment[]>([]);\n\tconst [sendError, setSendError] = useState<string | null>(null);\n\tconst [emailGateConvId, setEmailGateConvId] = useState<string | null>(null);\n\n\tconst addFiles = useCallback(\n\t\tasync (files: File[]) => {\n\t\t\tif (!conversationId) return;\n\n\t\t\tconst remaining = MAX_ATTACHMENTS - attachments.length;\n\t\t\tconst toAdd = files.slice(0, remaining);\n\t\t\tif (toAdd.length === 0) return;\n\n\t\t\t// Create pending entries\n\t\t\tconst pending: PendingAttachment[] = toAdd.map((file) => ({\n\t\t\t\tid: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n\t\t\t\tfile,\n\t\t\t\tpreviewUrl: file.type.startsWith(\"image/\") ? URL.createObjectURL(file) : null,\n\t\t\t\tisUploading: true,\n\t\t\t\terror: null,\n\t\t\t\tpart: null,\n\t\t\t}));\n\n\t\t\tsetAttachments((prev) => [...prev, ...pending]);\n\n\t\t\t// Upload each file\n\t\t\tfor (const item of pending) {\n\t\t\t\ttry {\n\t\t\t\t\tif (item.file.size > MAX_FILE_SIZE) {\n\t\t\t\t\t\tthrow new Error(t(\"widget.file_too_large\"));\n\t\t\t\t\t}\n\n\t\t\t\t\t// Read file as base64\n\t\t\t\t\tconst base64 = await fileToBase64(item.file);\n\n\t\t\t\t\t// For temp conversations (before first send) skip the\n\t\t\t\t\t// conversationId — server scopes the R2 key to the visitor\n\t\t\t\t\t// and the file is attached to the timeline item by\n\t\t\t\t\t// createConversation when submit fires.\n\t\t\t\t\tconst convIdForUpload = conversationId.startsWith(\"temp-\") ? undefined : conversationId;\n\t\t\t\t\tconst result = await client.widget.uploadAttachment.mutate({\n\t\t\t\t\t\t...(convIdForUpload ? { conversationId: convIdForUpload } : {}),\n\t\t\t\t\t\tbase64,\n\t\t\t\t\t\tmimeType: item.file.type || \"application/octet-stream\",\n\t\t\t\t\t\tfileName: item.file.name,\n\t\t\t\t\t});\n\n\t\t\t\t\tsetAttachments((prev) =>\n\t\t\t\t\t\tprev.map((a) =>\n\t\t\t\t\t\t\ta.id === item.id ? { ...a, isUploading: false, part: result.part } : a,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconst message = err instanceof Error ? err.message : \"Upload failed\";\n\t\t\t\t\tsetAttachments((prev) =>\n\t\t\t\t\t\tprev.map((a) => (a.id === item.id ? { ...a, isUploading: false, error: message } : a)),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[conversationId, attachments.length, client],\n\t);\n\n\tconst removeAttachment = useCallback((id: string) => {\n\t\tsetAttachments((prev) => {\n\t\t\tconst item = prev.find((a) => a.id === id);\n\t\t\tif (item?.previewUrl) URL.revokeObjectURL(item.previewUrl);\n\t\t\treturn prev.filter((a) => a.id !== id);\n\t\t});\n\t}, []);\n\n\t/**\n\t * `override` exists because the caller sometimes knows the text and the\n\t * conversation before this closure does: a suggestion pill sends a question\n\t * the composer state has never held, and the docked shell creates the\n\t * conversation in the same click that sends its first message. Passing both\n\t * in replaces the old setText → wait-a-tick → submit dance, which dropped\n\t * the message whenever the re-render didn't land before the timer.\n\t */\n\tconst submit = useCallback(\n\t\tasync (override?: { text?: string; conversationId?: string }) => {\n\t\t\tconst conversationId = override?.conversationId ?? boundConversationId;\n\t\t\tconst source = override?.text ?? text;\n\t\t\tconst trimmed = source.trim();\n\t\t\tconst readyParts = attachments.filter((a) => a.part !== null).map((a) => a.part!);\n\t\t\tconst hasText = trimmed.length > 0;\n\t\t\tconst hasAttachments = readyParts.length > 0;\n\n\t\t\tif (!conversationId || isSubmitting) return;\n\n\t\t\t// Policy 2026-04-19: every outgoing message must have a text body.\n\t\t\t// An attachment on its own renders as an empty bubble in the\n\t\t\t// dashboard and leaves the AI with no caption to reason about.\n\t\t\t// Surface a soft inline error instead of silently no-op'ing so\n\t\t\t// the visitor understands *why* the send didn't go through.\n\t\t\tif (!hasText) {\n\t\t\t\tif (hasAttachments) {\n\t\t\t\t\tsetSendError(t(\"widget.caption_required\"));\n\t\t\t\t\tsetTimeout(() => setSendError(null), 4000);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Don't send while uploads are in progress\n\t\t\tconst stillUploading = attachments.some((a) => a.isUploading);\n\t\t\tif (stillUploading) return;\n\n\t\t\t// ── OPTIMISTIC: message appears in the widget INSTANTLY ──\n\t\t\t// The user sees their message the moment they hit send; the mutation\n\t\t\t// runs in the background. On success we swap the optimistic placeholder\n\t\t\t// for the server-confirmed item (preserving scroll + bubble position).\n\t\t\t// On failure we remove the placeholder and restore the composer text.\n\t\t\tconst optimisticId = `optimistic-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;\n\t\t\tconst now = new Date().toISOString();\n\t\t\tconst currentVisitorId = store.getState().visitor?.id ?? null;\n\t\t\tconst optimisticItem: TimelineItem = {\n\t\t\t\tid: optimisticId,\n\t\t\t\tconversationId,\n\t\t\t\torganizationId: \"\",\n\t\t\t\ttype: \"message\",\n\t\t\t\tvisibility: \"public\",\n\t\t\t\ttext: hasText ? trimmed : null,\n\t\t\t\tparts:\n\t\t\t\t\thasText || hasAttachments\n\t\t\t\t\t\t? ([\n\t\t\t\t\t\t\t\t...(hasText ? [{ type: \"text\" as const, text: trimmed }] : []),\n\t\t\t\t\t\t\t\t...readyParts,\n\t\t\t\t\t\t\t] as TimelineItem[\"parts\"])\n\t\t\t\t\t\t: null,\n\t\t\t\tuserId: null,\n\t\t\t\tvisitorId: currentVisitorId,\n\t\t\t\taiAgentId: null,\n\t\t\t\tcreatedAt: now,\n\t\t\t\teditedAt: null,\n\t\t\t\tdeletedAt: null,\n\t\t\t};\n\n\t\t\t// Flush UI immediately\n\t\t\tconst attachmentsSnapshot = attachments;\n\t\t\tconst textSnapshot = source;\n\t\t\tstore.getState().addMessage(conversationId, optimisticItem);\n\t\t\tsetText(\"\");\n\t\t\tsetAttachments([]);\n\t\t\tws.sendTyping(conversationId, false);\n\t\t\tsetIsSubmitting(true);\n\t\t\ttry {\n\t\t\t\t// Temp conversation IDs (seeded by openNewConversation) don't exist on\n\t\t\t\t// the server yet. On the first send we have to call createConversation\n\t\t\t\t// instead — the API allocates the real ID and returns the visitor item.\n\t\t\t\t// The welcome item from the response is DROPPED because the widget is\n\t\t\t\t// already showing a seed welcome bubble; keeping the same bubble\n\t\t\t\t// instance across this transition is what prevents the \"git-gel\" flash.\n\t\t\t\tconst isTempConversation = conversationId.startsWith(\"temp-\");\n\t\t\t\t// Ephemeral proactive conversation — only exists in the widget\n\t\t\t\t// store, server hasn't seen it yet. First reply triggers\n\t\t\t\t// materialization (creates conversation + writes greeting +\n\t\t\t\t// visitor message in one go).\n\t\t\t\tconst isEphemeralConversation = conversationId.startsWith(\"eph-\");\n\t\t\t\tif (isEphemeralConversation) {\n\t\t\t\t\tconst workflowId = conversationId.slice(\"eph-\".length);\n\t\t\t\t\tconst result = await client.widget.materializeFromProactive.mutate({\n\t\t\t\t\t\tworkflowId,\n\t\t\t\t\t\t...(hasText ? { text: trimmed } : {}),\n\t\t\t\t\t});\n\t\t\t\t\t// Pull the real conversation onto the synthetic id so all the\n\t\t\t\t\t// in-flight optimistic state (visitor bubble, scroll position,\n\t\t\t\t\t// active id) carries over without a flash.\n\t\t\t\t\tstore.getState().remapConversationId(conversationId, result.conversationId);\n\t\t\t\t\t// Hydrate canonical timeline from server — replaces synthetic\n\t\t\t\t\t// greeting ids with real ULIDs and surfaces the persisted\n\t\t\t\t\t// visitor message. We keep the optimistic placeholder in the\n\t\t\t\t\t// store so the visitor sees their bubble immediately; the\n\t\t\t\t\t// canonical setMessages dedupes by id, but our optimistic id\n\t\t\t\t\t// won't collide so it'll be shadowed cleanly.\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst timeline = await client.widget.getTimeline.query({\n\t\t\t\t\t\t\tconversationId: result.conversationId,\n\t\t\t\t\t\t\tlimit: 50,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (timeline?.items) {\n\t\t\t\t\t\t\tstore.getState().setMessages(result.conversationId, timeline.items as TimelineItem[]);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Best-effort: optimistic state is still on screen, next\n\t\t\t\t\t\t// WS event or refresh will hydrate.\n\t\t\t\t\t}\n\t\t\t\t} else if (isTempConversation) {\n\t\t\t\t\tconst result = await client.widget.createConversation.mutate({\n\t\t\t\t\t\t...(hasText ? { text: trimmed } : {}),\n\t\t\t\t\t\t...(hasAttachments ? { parts: readyParts } : {}),\n\t\t\t\t\t\t/* The first message is the one that most needs this — someone\n\t\t\t\t\t\t lands on a page and immediately asks what it is. */\n\t\t\t\t\t\t...currentPagePayload(),\n\t\t\t\t\t});\n\t\t\t\t\tconst conv = result.conversation;\n\t\t\t\t\t// Move the temp conversation's messages (seed welcome + optimistic\n\t\t\t\t\t// visitor) onto the server-assigned id. remapConversationId merges\n\t\t\t\t\t// with any existing items under the real id (WS races are fine).\n\t\t\t\t\tstore.getState().remapConversationId(conversationId, conv.id);\n\t\t\t\t\tif (result.item) {\n\t\t\t\t\t\tstore.getState().replaceMessage(conv.id, optimisticId, result.item as TimelineItem);\n\t\t\t\t\t}\n\t\t\t\t\tif (result.requireEmail) {\n\t\t\t\t\t\tsetEmailGateConvId(conv.id);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tconst result = await client.widget.sendMessage.mutate({\n\t\t\t\t\t\tconversationId,\n\t\t\t\t\t\t...(hasText ? { text: trimmed } : {}),\n\t\t\t\t\t\t...(hasAttachments ? { parts: readyParts } : {}),\n\t\t\t\t\t\t/* Carry the page with the question. The provider reports it on\n\t\t\t\t\t\t bootstrap too, but that call is fire-and-forget — a visitor who\n\t\t\t\t\t\t lands and immediately asks \"what is this page about\" beat it,\n\t\t\t\t\t\t and the agent answered with no idea where they were. */\n\t\t\t\t\t\t...currentPagePayload(),\n\t\t\t\t\t});\n\n\t\t\t\t\t// Replace optimistic placeholder with server-confirmed item.\n\t\t\t\t\t// If the WS echo already landed with the real id, replaceMessage\n\t\t\t\t\t// just drops the placeholder (race-safe, see store implementation).\n\t\t\t\t\tstore\n\t\t\t\t\t\t.getState()\n\t\t\t\t\t\t.replaceMessage(conversationId, optimisticId, result.item as TimelineItem);\n\t\t\t\t}\n\n\t\t\t\t// Clean up blob URLs for uploaded attachments\n\t\t\t\tfor (const a of attachmentsSnapshot) {\n\t\t\t\t\tif (a.previewUrl) URL.revokeObjectURL(a.previewUrl);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"[useComposer] Send failed:\", err);\n\t\t\t\t// Roll back: remove placeholder, restore text + attachments so user can retry\n\t\t\t\tstore.getState().removeMessage(conversationId, optimisticId);\n\t\t\t\tsetText(textSnapshot);\n\t\t\t\tsetAttachments(attachmentsSnapshot);\n\t\t\t\tsetSendError(err instanceof Error ? err.message : t(\"widget.send_error\"));\n\t\t\t\t// Auto-clear after 5 seconds\n\t\t\t\tsetTimeout(() => setSendError(null), 5000);\n\t\t\t} finally {\n\t\t\t\tsetIsSubmitting(false);\n\t\t\t}\n\t\t},\n\t\t[text, attachments, boundConversationId, isSubmitting, client, ws, store],\n\t);\n\n\tconst clearSendError = useCallback(() => setSendError(null), []);\n\n\treturn {\n\t\ttext,\n\t\tsetText,\n\t\tsubmit,\n\t\tisSubmitting,\n\t\tattachments,\n\t\taddFiles,\n\t\tremoveAttachment,\n\t\tsendError,\n\t\tclearSendError,\n\t\temailGateConvId,\n\t};\n}\n\n// ── Helpers ─────────────────────────────────────\n\nfunction fileToBase64(file: File): Promise<string> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst reader = new FileReader();\n\t\treader.onload = () => {\n\t\t\t// result is \"data:<mime>;base64,<data>\" — strip the prefix\n\t\t\tconst result = reader.result as string;\n\t\t\tconst base64 = result.split(\",\")[1];\n\t\t\tif (!base64) return reject(new Error(\"Failed to encode file\"));\n\t\t\tresolve(base64);\n\t\t};\n\t\treader.onerror = () => reject(new Error(\"Failed to read file\"));\n\t\treader.readAsDataURL(file);\n\t});\n}\n","import type { TimelineItem } from \"@helpway/types\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useWidgetContext, useWidgetStore } from \"../provider\";\n\n/**\n * Conversation list + create new conversation.\n */\nexport function useConversations() {\n\tconst { client, store } = useWidgetContext();\n\tconst conversations = useWidgetStore((s) => s.conversations);\n\tconst setActiveConversation = useWidgetStore((s) => s.setActiveConversation);\n\tconst [isCreating, setIsCreating] = useState(false);\n\n\tconst clientRef = useRef(client);\n\tconst storeRef = useRef(store);\n\n\t// Synced after commit, never during render. Every read of these refs\n\t// happens inside an effect or an async callback, all of which run after\n\t// this one, so the value is always current by the time it is used.\n\tuseEffect(() => {\n\t\tclientRef.current = client;\n\t\tstoreRef.current = store;\n\t});\n\n\tconst create = useCallback(async (text: string) => {\n\t\tsetIsCreating(true);\n\n\t\t// OPTIMISTIC: show the visitor's message + open the conversation view\n\t\t// BEFORE the server roundtrip completes. The conversation gets a temp\n\t\t// id (`temp-<random>`) that's remapped to the server id on success.\n\t\t// Welcome message + any AI reply flow in via the same path the API\n\t\t// returns them — either by replacing the temp conv or via WS.\n\t\tconst tempConversationId = `temp-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;\n\t\tconst now = new Date().toISOString();\n\t\tconst optimisticMessageId = `optimistic-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;\n\t\tconst currentVisitorId = storeRef.current.getState().visitor?.id ?? null;\n\n\t\tconst optimisticMsg: TimelineItem = {\n\t\t\tid: optimisticMessageId,\n\t\t\tconversationId: tempConversationId,\n\t\t\torganizationId: \"\",\n\t\t\ttype: \"message\",\n\t\t\tvisibility: \"public\",\n\t\t\ttext,\n\t\t\tparts: null,\n\t\t\tuserId: null,\n\t\t\tvisitorId: currentVisitorId,\n\t\t\taiAgentId: null,\n\t\t\tcreatedAt: now,\n\t\t\teditedAt: null,\n\t\t\tdeletedAt: null,\n\t\t};\n\n\t\t// Flush UI immediately: fake conversation + message + switch view\n\t\tconst store = storeRef.current.getState();\n\t\tstore.addConversation({\n\t\t\tid: tempConversationId,\n\t\t\ttitle: null,\n\t\t\tstatus: \"open\",\n\t\t\tlastMessageText: text,\n\t\t\tlastMessageAt: now,\n\t\t\tlastMessageSenderType: \"visitor\",\n\t\t\tlastMessageSenderName: null,\n\t\t\tlastMessageSenderImage: null,\n\t\t\tassigneeName: null,\n\t\t\tassigneeImage: null,\n\t\t\tunreadCount: 0,\n\t\t});\n\t\tstore.setMessages(tempConversationId, [optimisticMsg]);\n\t\tstore.setActiveConversation(tempConversationId);\n\n\t\ttry {\n\t\t\tconst result = await clientRef.current.widget.createConversation.mutate({ text });\n\t\t\tconst conv = result.conversation;\n\n\t\t\t// Remap temp ID → real ID (rewrites conversations list + messages map + active ref).\n\t\t\t// The optimistic message's id becomes stale (conversationId changed) — replaceMessage\n\t\t\t// with the server-confirmed item.\n\t\t\tstoreRef.current.getState().remapConversationId(tempConversationId, conv.id);\n\t\t\tif (result.item) {\n\t\t\t\tstoreRef.current\n\t\t\t\t\t.getState()\n\t\t\t\t\t.replaceMessage(conv.id, optimisticMessageId, result.item as TimelineItem);\n\t\t\t}\n\t\t\t// Insert welcome message if the agent sent one.\n\t\t\t// The welcome is ALWAYS the very first item in a new conversation, so\n\t\t\t// we place it at index 0 deterministically — never trust createdAt sort,\n\t\t\t// because client-clock (optimistic visitor) vs server-clock (welcome)\n\t\t\t// can be off by enough to re-order the pair. Dedup by id so a WS echo\n\t\t\t// doesn't double-insert.\n\t\t\tif (result.welcomeItem) {\n\t\t\t\tconst welcome = result.welcomeItem as TimelineItem;\n\t\t\t\tconst existing = storeRef.current.getState().messages.get(conv.id) ?? [];\n\t\t\t\tconst withoutWelcome = existing.filter((m) => m.id !== welcome.id);\n\t\t\t\tstoreRef.current.getState().setMessages(conv.id, [welcome, ...withoutWelcome]);\n\t\t\t}\n\t\t\treturn conv;\n\t\t} catch (err) {\n\t\t\t// Roll back: remove the fake conversation + message; let the caller surface the error\n\t\t\tstoreRef.current.getState().removeMessage(tempConversationId, optimisticMessageId);\n\t\t\tconst convs = storeRef.current\n\t\t\t\t.getState()\n\t\t\t\t.conversations.filter((c) => c.id !== tempConversationId);\n\t\t\tstoreRef.current.setState({ conversations: convs, activeConversationId: null });\n\t\t\tthrow err;\n\t\t} finally {\n\t\t\tsetIsCreating(false);\n\t\t}\n\t}, []);\n\n\treturn { conversations, create, isCreating, setActiveConversation };\n}\n","import { useEffect, useState } from \"react\";\nimport { onLocaleChange, getI18nRevision } from \"@helpway/widget-core\";\n\n/**\n * React hook that triggers re-render when widget translations load or locale changes.\n * Place this in the top-level widget component so all children get fresh t() values.\n *\n * Returns the current i18n revision number (for debugging).\n */\nexport function useI18n(): number {\n\tconst [rev, setRev] = useState(() => getI18nRevision());\n\n\tuseEffect(() => {\n\t\t// Subscribe to locale/translation changes\n\t\treturn onLocaleChange(() => {\n\t\t\tsetRev(getI18nRevision());\n\t\t});\n\t}, []);\n\n\treturn rev;\n}\n","import { useCallback, useRef } from \"react\";\nimport { useWidgetContext, useWidgetStore } from \"../provider\";\n\n/**\n * Typing presence — show \"is typing\" + send own typing status.\n *\n * Debounced: only sends WS event when typing state *changes*.\n * While typing, auto-stops after 3 seconds of inactivity.\n *\n * Usage:\n * ```tsx\n * const { isTyping, setTyping } = usePresence(conversationId)\n * ```\n */\nexport function usePresence(conversationId: string | null) {\n\tconst { ws } = useWidgetContext();\n\tconst isTyping = useWidgetStore((s) =>\n\t\tconversationId ? (s.typingUsers.get(conversationId) ?? false) : false,\n\t);\n\tconst isAiProcessing = useWidgetStore((s) =>\n\t\tconversationId ? (s.aiProcessing.get(conversationId) ?? false) : false,\n\t);\n\tconst typingTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\tconst isSendingTyping = useRef(false);\n\n\tconst setTyping = useCallback(\n\t\t(typing: boolean) => {\n\t\t\tif (!conversationId) return;\n\n\t\t\t// Clear any pending auto-stop\n\t\t\tif (typingTimer.current) clearTimeout(typingTimer.current);\n\n\t\t\tif (typing) {\n\t\t\t\t// Only send \"typing: true\" if we haven't already\n\t\t\t\tif (!isSendingTyping.current) {\n\t\t\t\t\tisSendingTyping.current = true;\n\t\t\t\t\tws.sendTyping(conversationId, true);\n\t\t\t\t}\n\t\t\t\t// Auto-stop after 3 seconds of inactivity\n\t\t\t\ttypingTimer.current = setTimeout(() => {\n\t\t\t\t\tisSendingTyping.current = false;\n\t\t\t\t\tws.sendTyping(conversationId, false);\n\t\t\t\t}, 3000);\n\t\t\t} else {\n\t\t\t\t// Immediately send stop\n\t\t\t\tif (isSendingTyping.current) {\n\t\t\t\t\tisSendingTyping.current = false;\n\t\t\t\t\tws.sendTyping(conversationId, false);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[conversationId, ws],\n\t);\n\n\treturn { isTyping, isAiProcessing, setTyping };\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useWidgetContext, useWidgetStore } from \"../provider\";\n\nimport type { TimelineItem } from \"@helpway/types\";\n\nconst EMPTY_ITEMS: TimelineItem[] = [];\n\n/**\n * Timeline items for a conversation + real-time updates.\n */\nexport function useTimeline(conversationId: string | null) {\n\tconst { client, store } = useWidgetContext();\n\tconst messages = useWidgetStore((s) =>\n\t\tconversationId ? s.messages.get(conversationId) ?? EMPTY_ITEMS : EMPTY_ITEMS,\n\t);\n\tconst [isLoading, setIsLoading] = useState(false);\n\tconst [hasMore, setHasMore] = useState(false);\n\tconst cursorRef = useRef<string | undefined>(undefined);\n\n\t// Stable refs to avoid effect re-triggers\n\tconst clientRef = useRef(client);\n\tconst storeRef = useRef(store);\n\n\t// Synced after commit, never during render. Every read of these refs\n\t// happens inside an effect or an async callback, all of which run after\n\t// this one, so the value is always current by the time it is used.\n\tuseEffect(() => {\n\t\tclientRef.current = client;\n\t\tstoreRef.current = store;\n\t});\n\n\t// Load initial timeline when conversation changes\n\tuseEffect(() => {\n\t\tif (!conversationId) return;\n\n\t\t// Skip server fetch for optimistic temp IDs — they don't exist server-side.\n\t\t// useConversations.create() owns the seed for these; once remap fires this\n\t\t// effect re-runs with the real id and the fetch happens then.\n\t\tif (conversationId.startsWith(\"temp-\")) return;\n\n\t\tlet cancelled = false;\n\n\t\t// If createConversation already seeded the messages store (welcome + first\n\t\t// visitor message), the server has nothing new to tell us — skip the fetch.\n\t\t// Overwriting the seed with the server payload causes a full array-identity\n\t\t// flip, a brief key-swap for the optimistic→server id transition, and\n\t\t// restarts CSS enter animations — the \"mesajlar gidip tekrar geliyor\" flash.\n\t\t// New items still flow in via WS.addMessage, which dedupes by id.\n\t\tconst existingMessages = storeRef.current.getState().messages.get(conversationId);\n\t\tconst hasSeed = !!existingMessages && existingMessages.length > 0;\n\t\tif (hasSeed) {\n\t\t\tstoreRef.current.getState().clearUnread(conversationId);\n\t\t\tclientRef.current.widget.markSeen\n\t\t\t\t.mutate({ conversationId })\n\t\t\t\t.catch(() => {});\n\t\t\treturn () => {\n\t\t\t\tcancelled = true;\n\t\t\t};\n\t\t}\n\n\t\tsetIsLoading(true);\n\t\tasync function load() {\n\t\t\ttry {\n\t\t\t\tconst data = await clientRef.current.widget.getTimeline.query({\n\t\t\t\t\tconversationId: conversationId!,\n\t\t\t\t\tlimit: 50,\n\t\t\t\t});\n\n\t\t\t\tif (cancelled) return;\n\n\t\t\t\t// Only overwrite if API returned items — don't wipe seed messages with empty response\n\t\t\t\tif (data.items.length > 0) {\n\t\t\t\t\tstoreRef.current.getState().setMessages(conversationId!, data.items as TimelineItem[]);\n\t\t\t\t}\n\t\t\t\tsetHasMore(data.hasMore);\n\t\t\t\tcursorRef.current = data.nextCursor ?? undefined;\n\n\t\t\t\t// Mark as seen + clear local unread count\n\t\t\t\tstoreRef.current.getState().clearUnread(conversationId!);\n\t\t\t\tclientRef.current.widget.markSeen.mutate({ conversationId: conversationId! }).catch(() => {});\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"[useTimeline] Failed to load:\", err);\n\t\t\t} finally {\n\t\t\t\tif (!cancelled) setIsLoading(false);\n\t\t\t}\n\t\t}\n\n\t\tload();\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t};\n\t}, [conversationId]); // Only re-run when conversationId changes\n\n\tconst loadMore = useCallback(async () => {\n\t\tif (!conversationId || !hasMore || isLoading) return;\n\n\t\tsetIsLoading(true);\n\t\ttry {\n\t\t\tconst data = await clientRef.current.widget.getTimeline.query({\n\t\t\t\tconversationId,\n\t\t\t\tcursor: cursorRef.current,\n\t\t\t\tlimit: 50,\n\t\t\t});\n\n\t\t\tconst existing = storeRef.current.getState().messages.get(conversationId) ?? [];\n\t\t\tstoreRef.current.getState().setMessages(conversationId, [...data.items as TimelineItem[], ...existing]);\n\t\t\tsetHasMore(data.hasMore);\n\t\t\tcursorRef.current = data.nextCursor ?? undefined;\n\t\t} finally {\n\t\t\tsetIsLoading(false);\n\t\t}\n\t}, [conversationId, hasMore, isLoading]);\n\n\treturn { items: messages, isLoading, hasMore, loadMore };\n}\n","import { useWidgetStore } from \"../provider\";\n\n/**\n * Total unread count across all conversations.\n *\n * Usage:\n * ```tsx\n * const { totalUnread } = useUnread()\n * ```\n */\nexport function useUnread() {\n\tconst totalUnread = useWidgetStore((s) =>\n\t\ts.conversations.reduce((sum, c) => sum + c.unreadCount, 0),\n\t);\n\n\treturn { totalUnread };\n}\n","import { useWidgetContext, useWidgetStore } from \"../provider\";\n\n/**\n * Core widget state — connection status, visitor identity, website info.\n *\n * Usage:\n * ```tsx\n * const { isReady, visitor, website, identify } = useWidget()\n * ```\n */\nexport function useWidget() {\n\tconst { client } = useWidgetContext();\n\tconst isReady = useWidgetStore((s) => s.isReady);\n\tconst isConnecting = useWidgetStore((s) => s.isConnecting);\n\tconst visitor = useWidgetStore((s) => s.visitor);\n\tconst website = useWidgetStore((s) => s.website);\n\tconst agentConfig = useWidgetStore((s) => s.agentConfig);\n\n\tasync function identify(data: {\n\t\texternalId: string;\n\t\temail?: string;\n\t\tname?: string;\n\t\timage?: string;\n\t\tmetadata?: Record<string, unknown>;\n\t}) {\n\t\treturn client.widget.identify.mutate(data);\n\t}\n\n\treturn { isReady, isConnecting, visitor, website, agentConfig, identify };\n}\n","import { useCallback, useRef, useState } from \"react\";\nimport { t } from \"@helpway/widget-core\";\nimport { ACCEPTED_TYPES, type PendingAttachment } from \"../hooks/use-composer\";\nimport { SendIcon, PaperclipIcon, XIcon } from \"./icons\";\n\nconst MAX_CHARS = 5000;\nconst CHAR_WARN_THRESHOLD = 4800;\n\n\ninterface ComposerProps {\n\ttext: string;\n\tonTextChange: (text: string) => void;\n\tonSubmit: () => void;\n\tonTyping?: (isTyping: boolean) => void;\n\tisSubmitting?: boolean;\n\tplaceholder?: string;\n\t/** Compact mode — single-line input without footer row */\n\tcompact?: boolean;\n\t/** Pending attachments to preview */\n\tattachments?: PendingAttachment[];\n\t/** Called when files are added (paste, drop, or file picker) */\n\tonAddFiles?: (files: File[]) => void;\n\t/** Called to remove a pending attachment */\n\tonRemoveAttachment?: (id: string) => void;\n\t/** Disable entire composer (e.g. email required before sending) */\n\tdisabled?: boolean;\n}\n\n/** Widget composer — auto-resize, Enter-to-send, paste/drop attachments */\nexport function Composer({\n\ttext,\n\tonTextChange,\n\tonSubmit,\n\tonTyping,\n\tisSubmitting,\n\tplaceholder,\n\tcompact,\n\tattachments,\n\tonAddFiles,\n\tonRemoveAttachment,\n\tdisabled,\n}: ComposerProps) {\n\tconst ref = useRef<HTMLTextAreaElement>(null);\n\tconst fileInputRef = useRef<HTMLInputElement>(null);\n\n\t// Feature-detect once per mount. CSS.supports is cheap but doing it\n\t// inside handleChange would run on every keystroke.\n\tconst supportsFieldSizing = useRef(\n\t\ttypeof CSS !== \"undefined\" && CSS.supports?.(\"field-sizing\", \"content\"),\n\t);\n\n\tconst handleKeyDown = useCallback(\n\t\t(e: React.KeyboardEvent) => {\n\t\t\tif (e.key === \"Enter\" && !e.shiftKey) {\n\t\t\t\te.preventDefault();\n\t\t\t\tonSubmit();\n\t\t\t}\n\t\t},\n\t\t[onSubmit],\n\t);\n\n\tconst handleChange = useCallback(\n\t\t(e: React.ChangeEvent<HTMLTextAreaElement>) => {\n\t\t\tconst value = e.target.value;\n\t\t\tif (value.length > MAX_CHARS) return; // Hard cap\n\t\t\tonTextChange(value);\n\t\t\tonTyping?.(value.length > 0);\n\n\t\t\t// Auto-resize fallback for engines without `field-sizing: content`\n\t\t\t// (Safari <17.4, Firefox <132, Chrome <123). Modern browsers handle\n\t\t\t// the resize in CSS — running this on every keystroke would force\n\t\t\t// a redundant reflow and briefly snap the textarea to min-height\n\t\t\t// before the new height is applied. Kept in sync with the 220px\n\t\t\t// max-height on .hw-composer-input.\n\t\t\tif (!supportsFieldSizing.current) {\n\t\t\t\tconst el = ref.current;\n\t\t\t\tif (el) {\n\t\t\t\t\tel.style.height = \"auto\";\n\t\t\t\t\tel.style.height = `${Math.min(el.scrollHeight, 220)}px`;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[onTextChange, onTyping],\n\t);\n\n\t// ── Clipboard paste ──────────────────────────\n\tconst handlePaste = useCallback(\n\t\t(e: React.ClipboardEvent) => {\n\t\t\tif (!onAddFiles) return;\n\t\t\tconst files = extractFiles(e.clipboardData);\n\t\t\tif (files.length > 0) {\n\t\t\t\te.preventDefault();\n\t\t\t\tonAddFiles(files);\n\t\t\t}\n\t\t},\n\t\t[onAddFiles],\n\t);\n\n\t// ── Drag & drop ──────────────────────────────\n\tconst [isDragging, setIsDragging] = useState(false);\n\tconst dragCountRef = useRef(0);\n\n\tconst handleDragEnter = useCallback((e: React.DragEvent) => {\n\t\te.preventDefault();\n\t\tdragCountRef.current++;\n\t\tif (dragCountRef.current === 1) setIsDragging(true);\n\t}, []);\n\n\tconst handleDragLeave = useCallback((e: React.DragEvent) => {\n\t\te.preventDefault();\n\t\tdragCountRef.current--;\n\t\tif (dragCountRef.current === 0) setIsDragging(false);\n\t}, []);\n\n\tconst handleDragOver = useCallback((e: React.DragEvent) => {\n\t\te.preventDefault();\n\t\te.dataTransfer.dropEffect = \"copy\";\n\t}, []);\n\n\tconst handleDrop = useCallback(\n\t\t(e: React.DragEvent) => {\n\t\t\te.preventDefault();\n\t\t\tdragCountRef.current = 0;\n\t\t\tsetIsDragging(false);\n\t\t\tif (!onAddFiles) return;\n\t\t\tconst files = extractFiles(e.dataTransfer);\n\t\t\tif (files.length > 0) onAddFiles(files);\n\t\t},\n\t\t[onAddFiles],\n\t);\n\n\t// ── File picker ──────────────────────────────\n\tconst handleFileClick = useCallback(() => {\n\t\tfileInputRef.current?.click();\n\t}, []);\n\n\tconst handleFileChange = useCallback(\n\t\t(e: React.ChangeEvent<HTMLInputElement>) => {\n\t\t\tif (!onAddFiles || !e.target.files) return;\n\t\t\tonAddFiles(Array.from(e.target.files));\n\t\t\te.target.value = \"\"; // reset so same file can be picked again\n\t\t},\n\t\t[onAddFiles],\n\t);\n\n\tconst hasText = text.trim().length > 0;\n\tconst hasAttachments = attachments && attachments.some((a) => a.part !== null);\n\tconst stillUploading = attachments?.some((a) => a.isUploading) ?? false;\n\t// Button stays clickable whenever there's *something* to send — the\n\t// actual text-required guard lives in `useComposer.submit` and\n\t// surfaces as an inline error if the visitor tries to send an\n\t// attachment without a caption. Feels less sticky than a disabled\n\t// arrow the user can't interpret.\n\tconst canSend = (hasText || hasAttachments) && !stillUploading;\n\tconst showCharCount = text.length >= CHAR_WARN_THRESHOLD;\n\tconst isOverLimit = text.length > MAX_CHARS;\n\n\treturn (\n\t\t<div\n\t\t\tclassName={`hw-composer ${compact ? \"hw-composer--compact\" : \"\"} ${isDragging ? \"hw-composer--dragging\" : \"\"}`}\n\t\t\tonDragEnter={handleDragEnter}\n\t\t\tonDragLeave={handleDragLeave}\n\t\t\tonDragOver={handleDragOver}\n\t\t\tonDrop={handleDrop}\n\t\t>\n\t\t\t<div className=\"hw-composer-box\" style={{ position: \"relative\" }}>\n\t\t\t\t{/* Drag overlay */}\n\t\t\t\t{isDragging && (\n\t\t\t\t\t<div className=\"hw-composer-drop-overlay\">\n\t\t\t\t\t\t<span className=\"hw-composer-drop-text\">{t(\"widget.drop_files\")}</span>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t\t{/* Attachment previews */}\n\t\t\t\t{attachments && attachments.length > 0 && (\n\t\t\t\t\t<div className=\"hw-composer-previews\">\n\t\t\t\t\t\t{attachments.map((a) => (\n\t\t\t\t\t\t\t<PreviewThumb\n\t\t\t\t\t\t\t\tkey={a.id}\n\t\t\t\t\t\t\t\tattachment={a}\n\t\t\t\t\t\t\t\tonRemove={onRemoveAttachment ? () => onRemoveAttachment(a.id) : undefined}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t<textarea\n\t\t\t\t\tref={ref}\n\t\t\t\t\tclassName=\"hw-composer-input\"\n\t\t\t\t\tvalue={text}\n\t\t\t\t\tonChange={handleChange}\n\t\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\t\tonPaste={handlePaste}\n\t\t\t\t\tplaceholder={placeholder ?? t(\"widget.placeholder\")}\n\t\t\t\t\trows={1}\n\t\t\t\t\tdisabled={disabled || isSubmitting}\n\t\t\t\t\taria-label={t(\"widget.aria_input\")}\n\t\t\t\t/>\n\t\t\t\t<div className=\"hw-composer-toolbar\">\n\t\t\t\t\t<div className=\"hw-composer-toolbar-left\">\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tclassName=\"hw-composer-attach\"\n\t\t\t\t\t\t\tonClick={handleFileClick}\n\t\t\t\t\t\t\tdisabled={disabled || isSubmitting}\n\t\t\t\t\t\t\taria-label={t(\"widget.aria_attach\")}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<PaperclipIcon />\n\t\t\t\t\t\t</button>\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\tref={fileInputRef}\n\t\t\t\t\t\t\ttype=\"file\"\n\t\t\t\t\t\t\taccept={ACCEPTED_TYPES}\n\t\t\t\t\t\t\tmultiple\n\t\t\t\t\t\t\thidden\n\t\t\t\t\t\t\tonChange={handleFileChange}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t{showCharCount && (\n\t\t\t\t\t\t\t<span className={`hw-composer-charcount ${isOverLimit ? \"hw-composer-charcount--over\" : \"\"}`}>\n\t\t\t\t\t\t\t\t{MAX_CHARS - text.length}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName={`hw-composer-send ${canSend && !isOverLimit && !disabled ? \"hw-composer-send--active\" : \"hw-composer-send--inactive\"}`}\n\t\t\t\t\t\tonClick={() => onSubmit()}\n\t\t\t\t\t\tdisabled={disabled || !canSend || isSubmitting || isOverLimit}\n\t\t\t\t\t\taria-label={t(\"widget.aria_send\")}\n\t\t\t\t\t>\n\t\t\t\t\t\t<SendIcon />\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\n// ── Preview thumbnail with hover ─────────────────\n\n/**\n * The thumbnail for a file staged in the composer.\n *\n * Deliberately has no hover popover. Sent attachments get one — peeking at an\n * image someone else posted is worth a 260px card. Here the visitor picked the\n * file a second ago; the card only threw a white rectangle across the page they\n * were reading, anchored to a 48px square they were about to type past.\n */\nexport function PreviewThumb({ attachment: a, onRemove }: { attachment: PendingAttachment; onRemove?: () => void }) {\n\treturn (\n\t\t<div className={`hw-composer-preview ${a.error ? \"hw-composer-preview--error\" : \"\"}`}>\n\t\t\t{a.previewUrl ? (\n\t\t\t\t<img src={a.previewUrl} alt={a.file.name} className=\"hw-composer-preview-img\" />\n\t\t\t) : (\n\t\t\t\t<div className=\"hw-composer-preview-file\">\n\t\t\t\t\t<span className=\"hw-composer-preview-ext\">\n\t\t\t\t\t\t{a.file.name.split(\".\").pop()?.toUpperCase() ?? \"FILE\"}\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t{a.isUploading && <div className=\"hw-composer-preview-loader\" />}\n\t\t\t{a.error && <div className=\"hw-composer-preview-badge\" title={a.error}>!</div>}\n\t\t\t{onRemove && (\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"hw-composer-preview-remove\"\n\t\t\t\t\tonClick={onRemove}\n\t\t\t\t\taria-label={t(\"widget.aria_remove\")}\n\t\t\t\t>\n\t\t\t\t\t<XIcon />\n\t\t\t\t</button>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\n// ── Helpers ──────────────────────────────────────\n\nfunction extractFiles(data: DataTransfer): File[] {\n\tconst files: File[] = [];\n\tif (data.files) {\n\t\tfor (let i = 0; i < data.files.length; i++) {\n\t\t\tconst file = data.files[i];\n\t\t\tif (file) files.push(file);\n\t\t}\n\t}\n\treturn files;\n}\n","// AUTO-GENERATED — DO NOT EDIT.\n// Run `bun scripts/sync-icons.ts` to regenerate from\n// @central-icons-react/round-outlined-radius-2-stroke-2 (devDep, not shipped).\n//\n// To add or rename an icon: edit MANIFEST in scripts/sync-icons.ts, re-run.\n\nimport type { SVGProps } from \"react\";\n\ntype IconProps = SVGProps<SVGSVGElement> & { size?: number | string };\n\n// IconBubble2\nexport function MessageIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M5.00195 4H19.002C20.1065 4 21.002 4.89543 21.002 6V16C21.002 17.1046 20.1065 18 19.002 18H12.002L7.00195 21V18H5.00195C3.89738 18 3.00195 17.1046 3.00195 16V6C3.00195 4.89543 3.89738 4 5.00195 4Z\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"square\" strokeLinejoin=\"round\" />\n\t\t</svg>\n\t);\n}\n\n// IconCrossMedium\nexport function XIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M6.5 6.5L17.5 17.5M17.5 6.5L6.5 17.5\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" />\n\t\t</svg>\n\t);\n}\n\n// IconArrowLeft\nexport function ArrowLeftIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M10 6L4 12L10 18\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n\t\t\t<path d=\"M5 12H20\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n\t\t</svg>\n\t);\n}\n\n// IconChevronRight\nexport function ChevronRightIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M9 4L15.5858 10.5858C16.3668 11.3668 16.3668 12.6331 15.5858 13.4142L9 20\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n\t\t</svg>\n\t);\n}\n\n// IconSparklesSoft\nexport function SparklesIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M19 13C14.0987 13.4243 11.4243 16.0987 11 21C10.5578 16.0225 7.89737 13.5547 3 13C7.97478 12.4262 10.4262 9.97478 11 5C11.5547 9.89737 14.0225 12.5578 19 13Z\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n\t\t\t<path d=\"M18.8864 2.34512C18.8642 2.14869 18.6981 2.0002 18.5004 2C18.3027 1.9998 18.1363 2.14794 18.1137 2.34433C18.0082 3.25861 17.7367 3.88584 17.3113 4.31127C16.8858 4.7367 16.2586 5.00822 15.3443 5.11367C15.1479 5.13632 14.9998 5.30271 15 5.5004C15.0002 5.69809 15.1487 5.86417 15.3451 5.88642C16.2439 5.98823 16.8855 6.25969 17.3217 6.68804C17.7556 7.11407 18.0322 7.74041 18.1126 8.64552C18.1305 8.84634 18.2988 9.00023 18.5004 9C18.702 8.99977 18.8701 8.84551 18.8874 8.64465C18.9645 7.75483 19.2409 7.11438 19.6776 6.67764C20.1144 6.24091 20.7548 5.96446 21.6446 5.88744C21.8455 5.87005 21.9998 5.70205 22 5.50044C22.0002 5.29883 21.8463 5.13048 21.6455 5.11264C20.7404 5.03224 20.1141 4.75557 19.688 4.3217C19.2597 3.88545 18.9882 3.24394 18.8864 2.34512Z\" fill=\"currentColor\" />\n\t\t</svg>\n\t);\n}\n\n// IconPaperPlaneTopRight\nexport function SendIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M9.61946 10.8613L20.9997 4.55422M9.04735 10.9043L4.10061 5.68812C3.49632 5.05091 3.94803 4 4.82621 4H20.2513C21.0247 4 21.5054 4.84039 21.1132 5.50702L13.1902 18.9762C12.7433 19.7358 11.6035 19.5879 11.3654 18.7393L9.28458 11.3223C9.24066 11.1658 9.15923 11.0223 9.04735 10.9043Z\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n\t\t</svg>\n\t);\n}\n\n// IconPaperclip1\nexport function PaperclipIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M6 11V15C6 18.3137 8.68629 21 12 21C15.3137 21 18 18.3137 18 15V7C18 4.79086 16.2091 3 14 3C11.7909 3 10 4.79086 10 7V15C10 16.1046 10.8954 17 12 17C13.1046 17 14 16.1046 14 15V7\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" />\n\t\t</svg>\n\t);\n}\n\n// IconArrowUp\nexport function ArrowUpIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M12 5V20\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n\t\t\t<path d=\"M6 10L12 4L18 10\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n\t\t</svg>\n\t);\n}\n\n// IconHome\nexport function HomeIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M4 9.77313C4 9.2136 4 8.93383 4.07063 8.67517C4.1332 8.446 4.23609 8.22982 4.3745 8.03675C4.53071 7.81882 4.74784 7.6424 5.1821 7.28957L9.9821 3.38956C10.7014 2.80513 11.0611 2.51291 11.4609 2.40099C11.8135 2.30229 12.1865 2.30229 12.5391 2.40099C12.9389 2.51291 13.2986 2.80513 14.0179 3.38957L18.8179 7.28957C19.2522 7.6424 19.4693 7.81882 19.6255 8.03675C19.7639 8.22982 19.8668 8.446 19.9294 8.67517C20 8.93383 20 9.2136 20 9.77313V16.8C20 17.9201 20 18.4802 19.782 18.908C19.5903 19.2843 19.2843 19.5903 18.908 19.782C18.4802 20 17.9201 20 16.8 20H7.2C6.07989 20 5.51984 20 5.09202 19.782C4.71569 19.5903 4.40973 19.2843 4.21799 18.908C4 18.4802 4 17.9201 4 16.8V9.77313Z\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinejoin=\"round\" />\n\t\t</svg>\n\t);\n}\n\n// IconBubbleDots\nexport function MessagesIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M4.00195 6.00003C4.00195 4.89546 4.89738 4.00003 6.00195 4.00002L18.0019 4C19.1065 4 20.002 4.89543 20.002 6V16.0358C20.002 17.1403 19.1065 18.0358 18.002 18.0358L15.3757 18.0358C15.1427 18.0358 14.9171 18.1171 14.7377 18.2657L11.9977 20.5358L9.29398 18.2694C9.11393 18.1185 8.8865 18.0358 8.65157 18.0358H6.00195C4.89738 18.0358 4.00195 17.1403 4.00195 16.0358V6.00003Z\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinejoin=\"round\" />\n\t\t\t<path d=\"M6.875 11.25C6.875 11.7332 7.26675 12.125 7.75 12.125C8.23325 12.125 8.625 11.7332 8.625 11.25C8.625 10.7668 8.23325 10.375 7.75 10.375C7.26675 10.375 6.875 10.7668 6.875 11.25ZM11.125 11.25C11.125 11.7332 11.5168 12.125 12 12.125C12.4832 12.125 12.875 11.7332 12.875 11.25C12.875 10.7668 12.4832 10.375 12 10.375C11.5168 10.375 11.125 10.7668 11.125 11.25ZM15.375 11.25C15.375 11.7332 15.7668 12.125 16.25 12.125C16.7332 12.125 17.125 11.7332 17.125 11.25C17.125 10.7668 16.7332 10.375 16.25 10.375C15.7668 10.375 15.375 10.7668 15.375 11.25Z\" fill=\"currentColor\" stroke=\"currentColor\" strokeWidth=\"0.75\" strokeLinecap=\"square\" />\n\t\t</svg>\n\t);\n}\n\n// IconMagnifyingGlass\nexport function SearchIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M11 18C14.866 18 18 14.866 18 11C18 7.13401 14.866 4 11 4C7.13401 4 4 7.13401 4 11C4 14.866 7.13401 18 11 18Z\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" />\n\t\t\t<path d=\"M20 20L16.05 16.05\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" />\n\t\t</svg>\n\t);\n}\n\n// IconBubblePlus\nexport function NewChatIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M11.9998 8L11.9998 11M11.9998 11V14M11.9998 11H8.99976M11.9998 11H14.9998M11.9977 20.5358L14.7377 18.2657C14.9171 18.1171 15.1427 18.0358 15.3757 18.0358L18.002 18.0358C19.1065 18.0357 20.002 17.1403 20.002 16.0358V6C20.002 4.89543 19.1065 4 18.0019 4L6.00195 4.00002C4.89738 4.00002 4.00195 4.89545 4.00195 6.00002V16.0358C4.00195 17.1403 4.89738 18.0358 6.00195 18.0358H8.65157C8.8865 18.0358 9.11393 18.1185 9.29398 18.2694L11.9977 20.5358Z\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n\t\t</svg>\n\t);\n}\n\n// IconAppleIntelligence\nexport function BotIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path fillRule=\"evenodd\" clipRule=\"evenodd\" d=\"M9.67904 3.29155C10.7467 1.56948 13.2537 1.56948 14.3214 3.29155L15.1308 4.59707C15.2462 4.7833 15.3634 4.9684 15.4823 5.15233C15.7005 5.1305 15.9185 5.10662 16.1363 5.08068L17.6626 4.89893C19.6747 4.65934 21.2396 6.61723 20.5571 8.52637L20.0401 9.97255C19.9664 10.1786 19.8947 10.3854 19.825 10.5927C19.9779 10.7493 20.1323 10.9045 20.2882 11.0583L21.3821 12.1371C22.8256 13.5609 22.2668 16.0039 20.3491 16.6605L18.895 17.1584C18.6876 17.2294 18.4809 17.3023 18.275 17.3772C18.2478 17.5943 18.2226 17.8117 18.1995 18.0294L18.0372 19.5565C17.823 21.572 15.5635 22.6577 13.8546 21.5695L12.5584 20.7442C12.3734 20.6264 12.1873 20.5103 12.0002 20.3961C11.8131 20.5103 11.627 20.6264 11.442 20.7442L10.1458 21.5695C8.4369 22.6577 6.17739 21.572 5.96321 19.5565L5.80094 18.0294C5.7778 17.8117 5.75263 17.5943 5.72541 17.3772C5.51949 17.3023 5.31282 17.2294 5.10542 17.1584L3.65133 16.6605C1.7336 16.0039 1.17475 13.5609 2.61829 12.1371L3.71216 11.0583C3.86807 10.9045 4.0225 10.7493 4.17541 10.5927C4.10567 10.3854 4.03395 10.1786 3.96028 9.97255L3.44329 8.52637C2.7608 6.61723 4.32567 4.65934 6.33777 4.89893L7.86408 5.08068C8.08191 5.10662 8.29993 5.1305 8.5181 5.15233C8.63698 4.9684 8.75417 4.7833 8.86963 4.59707L9.67904 3.29155ZM7.61407 6.4827L6.16966 6.31071C5.20357 6.19567 4.45578 7.13505 4.78207 8.04778L5.2716 9.41715C6.10452 8.48167 6.88648 7.5021 7.61407 6.4827ZM5.78854 10.961C7.04552 9.61105 8.19784 8.16742 9.23549 6.64268C11.076 6.78287 12.9244 6.78287 14.7649 6.64268C15.8026 8.16743 16.9549 9.61105 18.2119 10.961C17.6657 12.722 17.2545 14.522 16.9818 16.3454C15.2628 17.0169 13.5974 17.8181 12.0002 18.7422C10.403 17.8181 8.73761 17.0169 7.01863 16.3454C6.74592 14.522 6.3347 12.722 5.78854 10.961ZM4.65269 12.1275L3.61666 13.1494C2.92581 13.8308 3.19234 15.0006 4.11188 15.3154L5.48873 15.7868C5.27593 14.553 4.99684 13.3315 4.65269 12.1275ZM7.22343 17.9611L7.377 19.4062C7.47946 20.3704 8.56185 20.8926 9.38218 20.3703L10.6083 19.5895C9.51004 18.9865 8.38012 18.4429 7.22343 17.9611ZM13.3921 19.5895L14.6182 20.3703C15.4385 20.8926 16.5209 20.3704 16.6234 19.4062L16.777 17.9611C15.6203 18.4429 14.4903 18.9865 13.3921 19.5895ZM18.5117 15.7868L19.8885 15.3154C20.8081 15.0006 21.0746 13.8308 20.3837 13.1494L19.3477 12.1275C19.0035 13.3315 18.7245 14.553 18.5117 15.7868ZM18.7288 9.41715L19.2183 8.04778C19.5446 7.13505 18.7968 6.19567 17.8307 6.31071L16.3863 6.4827C17.1139 7.5021 17.8959 8.48167 18.7288 9.41715ZM13.8786 5.2756C12.6272 5.3429 11.3731 5.3429 10.1218 5.2756L10.8874 4.04072C11.3991 3.21542 12.6013 3.21542 13.113 4.04072L13.8786 5.2756Z\" fill=\"currentColor\" />\n\t\t</svg>\n\t);\n}\n\n// IconBook\nexport function BookIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M9 6C8.44772 6 8 6.44772 8 7C8 7.55228 8.44772 8 9 8V6ZM15 8C15.5523 8 16 7.55228 16 7C16 6.44772 15.5523 6 15 6V8ZM9 10C8.44772 10 8 10.4477 8 11C8 11.5523 8.44772 12 9 12V10ZM12 12C12.5523 12 13 11.5523 13 11C13 10.4477 12.5523 10 12 10V12ZM7 4H17V2H7V4ZM18 5V19H20V5H18ZM17 20H7V22H17V20ZM6 19V5H4V19H6ZM7 20C6.44771 20 6 19.5523 6 19H4C4 20.6569 5.34315 22 7 22V20ZM18 19C18 19.5523 17.5523 20 17 20V22C18.6569 22 20 20.6569 20 19H18ZM17 4C17.5523 4 18 4.44772 18 5H20C20 3.34315 18.6569 2 17 2V4ZM7 2C5.34315 2 4 3.34315 4 5H6C6 4.44772 6.44772 4 7 4V2ZM18 12V15H20V12H18ZM17 16H7V18H17V16ZM7 22H10V20H7V22ZM7 16C5.34315 16 4 17.3431 4 19H6C6 18.4477 6.44772 18 7 18V16ZM18 15C18 15.5523 17.5523 16 17 16V18C18.6569 18 20 16.6569 20 15H18ZM9 8H15V6H9V8ZM9 12H12V10H9V12Z\" fill=\"currentColor\" />\n\t\t</svg>\n\t);\n}\n\n// IconMegaphone\nexport function MegaphoneIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M17.9961 14.0001C19.6529 14.0001 20.9961 12.657 20.9961 11.0001C20.9961 9.34325 19.6529 8.0001 17.9961 8.0001M12.8254 18.0001C12.4136 19.1653 11.3023 20.0001 9.99609 20.0001C8.33924 20.0001 6.99609 18.657 6.99609 17.0001V15.5001M6.99829 6.5001V15.5001M17.9961 5.73752V16.2627C17.9961 17.617 16.6784 18.5797 15.3882 18.1681L4.38819 14.6585C3.55899 14.394 2.99609 13.6235 2.99609 12.7532V9.24704C2.99609 8.37667 3.55899 7.60622 4.38819 7.34167L15.3882 3.83215C16.6784 3.42051 17.9961 4.38325 17.9961 5.73752Z\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n\t\t</svg>\n\t);\n}\n\n// IconLightBulb\nexport function LightbulbIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M10 21H14M15.6076 15C17.6404 13.7751 19 11.5463 19 9C19 5.13401 15.866 2 12 2C8.13401 2 5 5.13401 5 9C5 11.5463 6.35958 13.7751 8.39241 15M15.6076 15C15.4111 15.1184 15.2084 15.2274 15 15.3264V17C15 17.5523 14.5523 18 14 18H10C9.44772 18 9 17.5523 9 17V15.3264C8.7916 15.2274 8.58886 15.1184 8.39241 15M15.6076 15H8.39241\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n\t\t</svg>\n\t);\n}\n\n// IconCircleQuestionmark\nexport function HelpCircleIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21Z\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n\t\t\t<path d=\"M12 16V16.01\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" />\n\t\t\t<path d=\"M12 13C12 11.3608 14 11.9319 14 10C14 8.89543 13.1046 8 12 8C11.2597 8 10.6134 8.4022 10.2676 9\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n\t\t</svg>\n\t);\n}\n\n// IconNewspaper\nexport function NewspaperIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M16 12V6C16 4.89543 15.1046 4 14 4H5C3.89543 4 3 4.89543 3 6V17.5C3 18.8807 4.11929 20 5.5 20H18.5M16 12V17.5C16 18.8807 17.1193 20 18.5 20M16 12H19C20.1046 12 21 12.8954 21 14V17.5C21 18.8807 19.8807 20 18.5 20M7 16H12M7 8H12V12H7V8Z\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n\t\t</svg>\n\t);\n}\n\n// IconStar\nexport function StarIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={typeof size === \"number\" ? `${size}px` : size}\n\t\t\theight={typeof size === \"number\" ? `${size}px` : size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\taria-hidden={true}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path d=\"M11.5288 2.29524C11.7179 1.90159 12.2821 1.90159 12.4712 2.29524L14.9458 7.44648C15.0219 7.60491 15.1735 7.71434 15.3487 7.73728L21.0456 8.4832C21.4809 8.5402 21.6552 9.07312 21.3368 9.37342L17.1693 13.303C17.0412 13.4238 16.9832 13.6009 17.0154 13.7735L18.0616 19.3857C18.1416 19.8146 17.6852 20.144 17.2993 19.9359L12.249 17.2133C12.0937 17.1296 11.9063 17.1296 11.751 17.2133L6.70073 19.9359C6.3148 20.144 5.85841 19.8146 5.93837 19.3857L6.98459 13.7735C7.01677 13.6009 6.95885 13.4238 6.83068 13.303L2.66324 9.37342C2.34476 9.07312 2.51909 8.5402 2.95444 8.4832L8.65127 7.73728C8.82648 7.71434 8.97811 7.60491 9.05422 7.44648L11.5288 2.29524Z\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n\t\t</svg>\n\t);\n}\n\n/**\n * Conversation options. Not in the Central Icons snapshot — three dots on\n * the same 24 grid, filled to match the set's solid glyphs.\n */\nexport function DotsIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\taria-hidden=\"true\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<circle cx=\"5\" cy=\"12\" r=\"1.7\" fill=\"currentColor\" />\n\t\t\t<circle cx=\"12\" cy=\"12\" r=\"1.7\" fill=\"currentColor\" />\n\t\t\t<circle cx=\"19\" cy=\"12\" r=\"1.7\" fill=\"currentColor\" />\n\t\t</svg>\n\t);\n}\n\n/** A person, for the hand-off-to-a-human offer. Same 24 grid as the set. */\nexport function PersonIcon({ size = 24, ...props }: IconProps) {\n\treturn (\n\t\t<svg\n\t\t\twidth={size}\n\t\t\theight={size}\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\taria-hidden=\"true\"\n\t\t\t{...props}\n\t\t>\n\t\t\t<path\n\t\t\t\td=\"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2\"\n\t\t\t\tstroke=\"currentColor\"\n\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t/>\n\t\t\t<circle cx=\"12\" cy=\"7\" r=\"4\" stroke=\"currentColor\" strokeWidth=\"2\" />\n\t\t</svg>\n\t);\n}\n","import type { TimelineItem } from \"@helpway/types\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { useWidgetContext, useWidgetStore } from \"../provider\";\n\ninterface DebugEvent {\n\tid: string;\n\tt: number;\n\tkind: \"trpc\" | \"ws\" | \"store\" | \"error\";\n\tlabel: string;\n\tdetail?: string;\n}\n\nconst MAX_EVENTS = 60;\n\nfunction isDebugEnabled(): boolean {\n\tif (typeof window === \"undefined\") return false;\n\tif (typeof window.localStorage !== \"undefined\" && window.localStorage.getItem(\"hw:debug\") === \"1\") {\n\t\treturn true;\n\t}\n\tconst search = window.location?.search ?? \"\";\n\treturn search.includes(\"hwdebug=1\") || search.includes(\"debug=hw\");\n}\n\nfunction senderOf(item: TimelineItem): string {\n\tif (item.visitorId) return \"visitor\";\n\tif (item.aiAgentId) return \"ai\";\n\tif (item.userId) return \"team\";\n\treturn item.type;\n}\n\nexport function WidgetDebugOverlay() {\n\tconst [enabled, setEnabled] = useState(false);\n\tconst [open, setOpen] = useState(true);\n\tconst [events, setEvents] = useState<DebugEvent[]>([]);\n\tconst eventsRef = useRef<DebugEvent[]>([]);\n\n\t// Subscribe to each field individually — returning a fresh object from a\n\t// selector triggers an infinite re-render loop with zustand because each\n\t// render produces a new object reference.\n\tconst activeId = useWidgetStore((s) => s.activeConversationId);\n\tconst messagesMap = useWidgetStore((s) => s.messages);\n\tconst typingUsers = useWidgetStore((s) => s.typingUsers);\n\tconst aiProcessingMap = useWidgetStore((s) => s.aiProcessing);\n\tconst { store } = useWidgetContext();\n\n\tuseEffect(() => {\n\t\tsetEnabled(isDebugEnabled());\n\t}, []);\n\n\tconst pushEvent = useMemo(\n\t\t() => (ev: Omit<DebugEvent, \"id\" | \"t\">) => {\n\t\t\tconst e: DebugEvent = {\n\t\t\t\t...ev,\n\t\t\t\tid: `${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,\n\t\t\t\tt: Date.now(),\n\t\t\t};\n\t\t\teventsRef.current = [e, ...eventsRef.current].slice(0, MAX_EVENTS);\n\t\t\tsetEvents(eventsRef.current);\n\t\t},\n\t\t[],\n\t);\n\n\t// Intercept fetch to log tRPC calls — works with any tRPC proxy shape\n\t// because we observe at the network boundary, not the client object.\n\tuseEffect(() => {\n\t\tif (!enabled) return;\n\t\tif (typeof window === \"undefined\" || typeof window.fetch !== \"function\") return;\n\t\tconst originalFetch = window.fetch.bind(window);\n\t\tconst patched = (async (input: RequestInfo | URL, init?: RequestInit) => {\n\t\t\tconst url = typeof input === \"string\" ? input : input instanceof URL ? input.toString() : input.url;\n\t\t\tconst isTrpc = url.includes(\"/trpc/\");\n\t\t\tif (isTrpc) {\n\t\t\t\tconst method = init?.method ?? (typeof input !== \"string\" && !(input instanceof URL) ? input.method : \"GET\");\n\t\t\t\tconst label = url.split(\"/trpc/\")[1]?.split(\"?\")[0] ?? url;\n\t\t\t\tpushEvent({ kind: \"trpc\", label: `→ ${method} ${label}`, detail: shortJson(init?.body) });\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst res = await originalFetch(input, init);\n\t\t\t\tif (isTrpc) {\n\t\t\t\t\tconst label = url.split(\"/trpc/\")[1]?.split(\"?\")[0] ?? url;\n\t\t\t\t\tpushEvent({ kind: \"trpc\", label: `← ${res.status} ${label}` });\n\t\t\t\t}\n\t\t\t\treturn res;\n\t\t\t} catch (err) {\n\t\t\t\tif (isTrpc) {\n\t\t\t\t\tconst label = url.split(\"/trpc/\")[1]?.split(\"?\")[0] ?? url;\n\t\t\t\t\tpushEvent({ kind: \"error\", label: `✘ ${label}`, detail: err instanceof Error ? err.message : String(err) });\n\t\t\t\t}\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t}) as unknown as typeof window.fetch;\n\t\twindow.fetch = patched;\n\t\treturn () => {\n\t\t\twindow.fetch = originalFetch;\n\t\t};\n\t}, [enabled, pushEvent]);\n\n\t// Tap WebSocket events by wrapping the store's handleRealtimeEvent\n\tuseEffect(() => {\n\t\tif (!enabled) return;\n\t\tconst original = store.getState().handleRealtimeEvent;\n\t\tstore.setState({\n\t\t\thandleRealtimeEvent: (ev) => {\n\t\t\t\tpushEvent({ kind: \"ws\", label: ev.type, detail: shortJson(ev) });\n\t\t\t\toriginal(ev);\n\t\t\t},\n\t\t});\n\t\treturn () => {\n\t\t\tstore.setState({ handleRealtimeEvent: original });\n\t\t};\n\t}, [enabled, store, pushEvent]);\n\n\t// Emit a marker when messages array changes for the active conversation\n\tconst activeMessages = activeId ? messagesMap.get(activeId) ?? [] : [];\n\tconst lastMsgSignature = useMemo(\n\t\t() => activeMessages.map((m) => `${m.id}:${senderOf(m)}:${m.createdAt}`).join(\"|\"),\n\t\t[activeMessages],\n\t);\n\tconst prevSigRef = useRef(lastMsgSignature);\n\tuseEffect(() => {\n\t\tif (!enabled) return;\n\t\tif (prevSigRef.current !== lastMsgSignature) {\n\t\t\tprevSigRef.current = lastMsgSignature;\n\t\t\tpushEvent({\n\t\t\t\tkind: \"store\",\n\t\t\t\tlabel: `messages[${activeMessages.length}]`,\n\t\t\t\tdetail: activeMessages\n\t\t\t\t\t.map((m, i) => `${i}:${senderOf(m)}=${(m.text ?? \"\").slice(0, 24)}`)\n\t\t\t\t\t.join(\" | \"),\n\t\t\t});\n\t\t}\n\t}, [lastMsgSignature, activeMessages, enabled, pushEvent]);\n\n\tif (!enabled) return null;\n\n\tconst isTyping = activeId ? typingUsers.get(activeId) : false;\n\tconst isAi = activeId ? aiProcessingMap.get(activeId) : false;\n\n\treturn (\n\t\t<div style={styles.wrap}>\n\t\t\t<div style={styles.header}>\n\t\t\t\t<strong>hw debug</strong>\n\t\t\t\t<span style={styles.meta}>\n\t\t\t\t\t{\" \"}· conv {activeId ? activeId.slice(0, 10) : \"—\"} · items {activeMessages.length} · typing {isTyping ? \"Y\" : \"n\"} · ai {isAi ? \"Y\" : \"n\"}\n\t\t\t\t</span>\n\t\t\t\t<button type=\"button\" style={styles.btn} onClick={() => setOpen((v) => !v)}>{open ? \"hide\" : \"show\"}</button>\n\t\t\t\t<button type=\"button\" style={styles.btn} onClick={() => { eventsRef.current = []; setEvents([]); }}>clear</button>\n\t\t\t</div>\n\t\t\t{open && (\n\t\t\t\t<div style={styles.body}>\n\t\t\t\t\t<div style={styles.section}>\n\t\t\t\t\t\t<div style={styles.sectionTitle}>messages (active)</div>\n\t\t\t\t\t\t{activeMessages.length === 0 ? (\n\t\t\t\t\t\t\t<div style={styles.empty}>empty</div>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\tactiveMessages.map((m, i) => (\n\t\t\t\t\t\t\t\t<div key={m.id} style={styles.row}>\n\t\t\t\t\t\t\t\t\t<span style={{ ...styles.badge, background: colorFor(senderOf(m)) }}>{i}</span>\n\t\t\t\t\t\t\t\t\t<span style={styles.sender}>{senderOf(m)}</span>\n\t\t\t\t\t\t\t\t\t<span style={styles.ts}>{m.createdAt.slice(11, 23)}</span>\n\t\t\t\t\t\t\t\t\t<span style={styles.text}>{(m.text ?? \"\").slice(0, 60)}</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t))\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div style={styles.section}>\n\t\t\t\t\t\t<div style={styles.sectionTitle}>events</div>\n\t\t\t\t\t\t{events.length === 0 ? (\n\t\t\t\t\t\t\t<div style={styles.empty}>no events yet — send a message</div>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\tevents.map((e) => (\n\t\t\t\t\t\t\t\t<div key={e.id} style={styles.row}>\n\t\t\t\t\t\t\t\t\t<span style={{ ...styles.badge, background: kindColor(e.kind) }}>{e.kind}</span>\n\t\t\t\t\t\t\t\t\t<span style={styles.ts}>{new Date(e.t).toISOString().slice(11, 23)}</span>\n\t\t\t\t\t\t\t\t\t<span style={styles.evLabel}>{e.label}</span>\n\t\t\t\t\t\t\t\t\t{e.detail && <span style={styles.detail}>{e.detail}</span>}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t))\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nfunction shortJson(v: unknown): string {\n\tif (v === undefined) return \"\";\n\ttry {\n\t\tconst s = JSON.stringify(v);\n\t\tif (!s) return \"\";\n\t\treturn s.length > 180 ? `${s.slice(0, 177)}…` : s;\n\t} catch {\n\t\treturn String(v);\n\t}\n}\n\nfunction colorFor(sender: string): string {\n\tswitch (sender) {\n\t\tcase \"visitor\":\n\t\t\treturn \"#1d4ed8\";\n\t\tcase \"ai\":\n\t\t\treturn \"#7c3aed\";\n\t\tcase \"team\":\n\t\t\treturn \"#16a34a\";\n\t\tdefault:\n\t\t\treturn \"#6b7280\";\n\t}\n}\n\nfunction kindColor(kind: DebugEvent[\"kind\"]): string {\n\tswitch (kind) {\n\t\tcase \"trpc\":\n\t\t\treturn \"#0ea5e9\";\n\t\tcase \"ws\":\n\t\t\treturn \"#f97316\";\n\t\tcase \"store\":\n\t\t\treturn \"#64748b\";\n\t\tcase \"error\":\n\t\t\treturn \"#dc2626\";\n\t}\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n\twrap: {\n\t\tposition: \"fixed\",\n\t\tright: 12,\n\t\tbottom: 12,\n\t\tzIndex: 2147483000,\n\t\twidth: 420,\n\t\tmaxHeight: \"70vh\",\n\t\tbackground: \"rgba(9,9,11,0.94)\",\n\t\tcolor: \"#e5e7eb\",\n\t\tborderRadius: 10,\n\t\tfontFamily: \"ui-monospace, SFMono-Regular, Menlo, monospace\",\n\t\tfontSize: 11,\n\t\tboxShadow: \"0 12px 30px rgba(0,0,0,0.35)\",\n\t\toverflow: \"hidden\",\n\t\tpointerEvents: \"auto\",\n\t},\n\theader: {\n\t\tdisplay: \"flex\",\n\t\talignItems: \"center\",\n\t\tgap: 6,\n\t\tpadding: \"6px 10px\",\n\t\tbackground: \"#18181b\",\n\t\tborderBottom: \"1px solid #27272a\",\n\t},\n\tmeta: { flex: 1, color: \"#a1a1aa\", fontSize: 10 },\n\tbtn: {\n\t\tbackground: \"#27272a\",\n\t\tcolor: \"#e4e4e7\",\n\t\tborder: \"1px solid #3f3f46\",\n\t\tborderRadius: 4,\n\t\tpadding: \"2px 8px\",\n\t\tcursor: \"pointer\",\n\t\tfontSize: 10,\n\t},\n\tbody: { display: \"flex\", flexDirection: \"column\", maxHeight: \"calc(70vh - 32px)\", overflow: \"auto\" },\n\tsection: { borderBottom: \"1px solid #27272a\", padding: \"6px 10px\" },\n\tsectionTitle: { color: \"#a1a1aa\", fontSize: 10, textTransform: \"uppercase\", letterSpacing: 0.6, marginBottom: 4 },\n\trow: {\n\t\tdisplay: \"grid\",\n\t\tgridTemplateColumns: \"32px 56px 72px 1fr\",\n\t\tgap: 6,\n\t\talignItems: \"baseline\",\n\t\tpadding: \"2px 0\",\n\t\tborderTop: \"1px dashed #27272a\",\n\t},\n\tbadge: {\n\t\tdisplay: \"inline-block\",\n\t\tborderRadius: 3,\n\t\tpadding: \"1px 4px\",\n\t\tcolor: \"white\",\n\t\tfontSize: 9,\n\t\ttextAlign: \"center\",\n\t},\n\tsender: { color: \"#d4d4d8\" },\n\tts: { color: \"#71717a\", fontSize: 10 },\n\ttext: { color: \"#e4e4e7\", whiteSpace: \"nowrap\", overflow: \"hidden\", textOverflow: \"ellipsis\" },\n\tevLabel: { color: \"#e4e4e7\" },\n\tdetail: { gridColumn: \"1 / -1\", color: \"#a1a1aa\", fontSize: 10, whiteSpace: \"pre-wrap\", wordBreak: \"break-all\" },\n\tempty: { color: \"#52525b\", fontStyle: \"italic\", fontSize: 10 },\n};\n","import { t } from \"@helpway/widget-core\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\nimport type { DockSuggestion } from \"@helpway/widget-core\";\n\nimport { ACCEPTED_TYPES, type PendingAttachment } from \"../hooks/use-composer\";\nimport { PreviewThumb } from \"../themed/composer\";\nimport { ArrowUpIcon, PaperclipIcon } from \"../themed/icons\";\n\n/**\n * The composer bar for `placement=\"docked\"`.\n *\n * Unlike the bubble shell, the bar is persistent chrome and it IS the\n * composer — the conversation panel above it renders without one. That\n * is why this lives in `shell/` rather than inside the conversation:\n * moving the widget must never change the conversation UI.\n *\n * It shares the panel's measure so bar and panel read as one column, and\n * it grows with its content instead of scrolling a one-line field.\n */\nexport interface DockedBarProps {\n\tvalue: string;\n\tonChange: (next: string) => void;\n\tonSubmit: () => void;\n\tdisabled?: boolean;\n\t/**\n\t * Ways in offered before the visitor has typed anything. Rendered as\n\t * pills floating above the bar, over the page — there is no panel to\n\t * put them in yet, and a panel would read as demanding attention\n\t * where pills read as offering.\n\t */\n\tsuggestions?: readonly DockSuggestion[];\n\tonSuggestion?: (question: string) => void;\n\tplaceholder?: string;\n\t/**\n\t * Attachment plumbing, same three pieces the bubble composer gets from\n\t * `useComposer`. The docked bar IS the composer, so leaving these out\n\t * meant the docked shell was the one place a visitor could not send a\n\t * screenshot — the single most common thing a support thread needs.\n\t */\n\tattachments?: PendingAttachment[];\n\tonAddFiles?: (files: File[]) => void;\n\tonRemoveAttachment?: (id: string) => void;\n\t/**\n\t * Reaching for the bar again after folding the panel away. The thread is still\n\t * there — the visitor closed a panel, not a conversation — so touching the\n\t * composer brings it back where they left it. Only wired to a pointer press:\n\t * on `focus` it would also fire for someone tabbing through the page, and a\n\t * panel that appears over the article you are reading because you pressed Tab\n\t * is worse than one that never reappears.\n\t */\n\tonReopen?: () => void;\n\t/**\n\t * Why a send did not happen. The composer refuses an attachment with no caption\n\t * on purpose and sets this instead of failing silently — but in the docked shell\n\t * there was nothing rendering it, so the refusal WAS silent: the file sat in the\n\t * bar, the button did nothing, and no reason was ever given.\n\t */\n\tsendError?: string | null;\n\tonClearSendError?: () => void;\n}\n\n/**\n * The pills float over the host page, so on a content-heavy page they sit on top of\n * whatever is behind them — a code block, a table row. Offering them is right; being\n * unable to put them away is not.\n *\n * One control clears the whole offer rather than one × per pill. The pills are a single\n * gesture from the agent (\"here are ways in\"), so declining them is a single gesture\n * back; asking the visitor to refuse three times to see the page under them is the\n * problem restated, not solved.\n *\n * The dismissal is keyed by the offer's own questions, not a bare boolean: local state,\n * so it returns on the next page load, but if the host swaps in a different set of\n * suggestions that IS a new offer and gets shown.\n */\nfunction useDismissableOffer(suggestions: readonly DockSuggestion[] | undefined) {\n\tconst [dismissedKey, setDismissedKey] = useState<string | null>(null);\n\tconst questions = (suggestions ?? []).map((entry) =>\n\t\ttypeof entry === \"string\" ? entry : entry.question,\n\t);\n\tconst key = questions.join(\"|\");\n\treturn {\n\t\tquestions: dismissedKey === key ? [] : questions,\n\t\tdismiss: () => setDismissedKey(key),\n\t};\n}\n\n/* ── Dictation ─────────────────────────────────────────────────────────────\n The reference composer we are matching offers a mic beside the clip, and on\n a docked bar — often the only input on a docs page — speaking a question is\n faster than typing it. Wired to the platform's own recognizer rather than an\n upload-and-transcribe round trip: no audio leaves the page, and there is no\n server cost to a visitor who trails off mid-sentence.\n\n Typed against a minimal surface instead of `any`: we touch six members, and\n the vendor-prefixed constructor is still the only one Safari exposes. The\n button renders only where the constructor exists, so it is never a control\n that looks live and does nothing. */\ninterface SpeechAlternative {\n\ttranscript: string;\n}\ninterface SpeechResult {\n\treadonly length: number;\n\tisFinal: boolean;\n\t[index: number]: SpeechAlternative;\n}\ninterface SpeechResultList {\n\treadonly length: number;\n\t[index: number]: SpeechResult;\n}\ninterface SpeechEvent {\n\tresultIndex: number;\n\tresults: SpeechResultList;\n}\ninterface Recognition {\n\tlang: string;\n\tcontinuous: boolean;\n\tinterimResults: boolean;\n\tstart(): void;\n\tstop(): void;\n\tonresult: ((event: SpeechEvent) => void) | null;\n\tonend: (() => void) | null;\n\tonerror: (() => void) | null;\n}\ntype RecognitionCtor = new () => Recognition;\n\nfunction recognitionCtor(): RecognitionCtor | null {\n\tif (typeof window === \"undefined\") return null;\n\tconst scope = window as unknown as {\n\t\tSpeechRecognition?: RecognitionCtor;\n\t\twebkitSpeechRecognition?: RecognitionCtor;\n\t};\n\treturn scope.SpeechRecognition ?? scope.webkitSpeechRecognition ?? null;\n}\n\n/**\n * Dictation as an append, not a replace: the visitor may have typed half a\n * sentence before reaching for the mic, and eating it would be worse than not\n * offering the mic at all. Interim results are ignored — a field that rewrites\n * itself while you speak is unreadable — so only settled phrases land.\n */\nfunction useDictation(onText: (chunk: string) => void) {\n\tconst [listening, setListening] = useState(false);\n\tconst recRef = useRef<Recognition | null>(null);\n\t/* The recognizer outlives the render that started it, so the callback is read\n\t through a ref — synced in an effect rather than assigned during render, which\n\t would be a write to shared state in the render phase. */\n\tconst onTextRef = useRef(onText);\n\tuseEffect(() => {\n\t\tonTextRef.current = onText;\n\t}, [onText]);\n\n\t// Support is a property of the browser, so it is resolved once rather than\n\t// on every render, and it decides whether the button exists at all.\n\tconst [supported] = useState(() => recognitionCtor() !== null);\n\n\t// A recognizer left running after unmount keeps the mic indicator lit in the\n\t// tab strip long after the widget is gone.\n\tuseEffect(\n\t\t() => () => {\n\t\t\trecRef.current?.stop();\n\t\t\trecRef.current = null;\n\t\t},\n\t\t[],\n\t);\n\n\tconst toggle = useCallback(() => {\n\t\tif (recRef.current) {\n\t\t\trecRef.current.stop();\n\t\t\treturn;\n\t\t}\n\t\tconst Ctor = recognitionCtor();\n\t\tif (!Ctor) return;\n\t\tconst rec = new Ctor();\n\t\trec.lang = typeof document !== \"undefined\" ? document.documentElement.lang || \"en\" : \"en\";\n\t\trec.continuous = false;\n\t\trec.interimResults = false;\n\t\trec.onresult = (event) => {\n\t\t\tfor (let i = event.resultIndex; i < event.results.length; i++) {\n\t\t\t\tconst result = event.results[i];\n\t\t\t\tif (!result?.isFinal) continue;\n\t\t\t\tconst said = result[0]?.transcript?.trim();\n\t\t\t\tif (said) onTextRef.current(said);\n\t\t\t}\n\t\t};\n\t\tconst finish = () => {\n\t\t\trecRef.current = null;\n\t\t\tsetListening(false);\n\t\t};\n\t\trec.onend = finish;\n\t\trec.onerror = finish;\n\t\trecRef.current = rec;\n\t\tsetListening(true);\n\t\trec.start();\n\t}, []);\n\n\t/* Stopping has to be callable from outside the button, because the button is not\n\t the only thing that ends a dictation — see the blur handler. */\n\tconst stop = useCallback(() => {\n\t\trecRef.current?.stop();\n\t}, []);\n\n\treturn { supported, listening, toggle, stop };\n}\n\n/** Matches --hw-bar-max-height in styles.css. */\nconst MAX_HEIGHT = 148;\n/** Above this the field is no longer one line, so the pill squares off. */\nconst GROWN_AT = 40;\n\n/** Paste and drop both hand us a DataTransfer; only files are interesting. */\nfunction filesFrom(data: DataTransfer | null): File[] {\n\tif (!data?.files) return [];\n\tconst out: File[] = [];\n\tfor (let i = 0; i < data.files.length; i++) {\n\t\tconst file = data.files[i];\n\t\tif (file) out.push(file);\n\t}\n\treturn out;\n}\n\nexport function DockedBar({\n\tvalue,\n\tonChange,\n\tonSubmit,\n\tdisabled = false,\n\tsuggestions,\n\tonSuggestion,\n\tplaceholder,\n\tattachments,\n\tonAddFiles,\n\tonRemoveAttachment,\n\tonReopen,\n\tsendError,\n\tonClearSendError,\n}: DockedBarProps) {\n\tconst [focused, setFocused] = useState(false);\n\tconst inputRef = useRef<HTMLTextAreaElement>(null);\n\tconst boxRef = useRef<HTMLDivElement>(null);\n\tconst fileInputRef = useRef<HTMLInputElement>(null);\n\tconst { questions: visibleQuestions, dismiss: dismissOffer } = useDismissableOffer(suggestions);\n\n\t/* Dictation writes into the same field as the keyboard, appended with a space\n\t so two dictated phrases don't fuse into one word. */\n\tconst dictation = useDictation((chunk) => {\n\t\tconst current = inputRef.current?.value ?? value;\n\t\tonChange(current ? `${current.replace(/\\s+$/, \"\")} ${chunk}` : chunk);\n\t\tinputRef.current?.focus();\n\t});\n\n\t// Height is derived from content on every change rather than held in\n\t// state — a render pass per keystroke to store a number the DOM\n\t// already knows is wasted work.\n\tconst grow = useCallback(() => {\n\t\tconst el = inputRef.current;\n\t\tconst box = boxRef.current;\n\t\tif (!el || !box) return;\n\t\tel.style.height = \"auto\";\n\t\tconst next = Math.min(MAX_HEIGHT, el.scrollHeight);\n\t\tel.style.height = `${next}px`;\n\t\tbox.dataset.grown = next > GROWN_AT ? \"true\" : \"false\";\n\t}, []);\n\n\t// Re-measure when the value is cleared from outside (submit, reset).\n\tuseEffect(grow, [grow, value]);\n\n\tconst handleKeyDown = useCallback(\n\t\t(event: React.KeyboardEvent<HTMLTextAreaElement>) => {\n\t\t\tif (event.key !== \"Enter\" || event.shiftKey) return;\n\t\t\tevent.preventDefault();\n\t\t\tif (!value.trim() || disabled) return;\n\t\t\tonSubmit();\n\t\t},\n\t\t[value, disabled, onSubmit],\n\t);\n\n\t/* A screenshot pasted straight into the field is how most support threads start,\n\t so paste is handled here and not only behind the clip. */\n\tconst handlePaste = useCallback(\n\t\t(event: React.ClipboardEvent<HTMLTextAreaElement>) => {\n\t\t\tif (!onAddFiles) return;\n\t\t\tconst files = filesFrom(event.clipboardData);\n\t\t\tif (!files.length) return;\n\t\t\tevent.preventDefault();\n\t\t\tonAddFiles(files);\n\t\t},\n\t\t[onAddFiles],\n\t);\n\n\t/* Shown when the composer has the visitor's attention, not on arrival.\n\t Three pills stacked above the bar take roughly 240px of viewport, and they float\n\t over the page — so on every content page they landed on whatever was behind them:\n\t a card, a callout's body text, the one code line an install section exists to\n\t show. The visitor had asked for none of it. Offering ways in is right; doing it\n\t over the thing they came to read is not. Focus anywhere in the dock is the signal\n\t that they are looking at it rather than at the article. */\n\tconst showSuggestions = focused && !!visibleQuestions.length && !value.trim();\n\n\t/* Focus tracked on the whole dock rather than the textarea, so clicking a pill —\n\t which moves focus out of the field — does not unmount the pill under the pointer\n\t before the click lands. `relatedTarget` outside the dock is a real exit. */\n\tconst onDockBlur = (event: React.FocusEvent<HTMLDivElement>) => {\n\t\tconst next = event.relatedTarget as Node | null;\n\t\tif (next && event.currentTarget.contains(next)) return;\n\t\tsetFocused(false);\n\t\t/* And stop listening. The unmount cleanup was the wrong hook for this: the bar\n\t\t is persistent chrome, so folding the panel away — or clicking back into the\n\t\t article — never unmounts it, and a recognizer started here kept the browser's\n\t\t mic indicator lit long after the visitor thought they had closed the chat.\n\t\t Focus is the honest signal: dictation belongs to the composer being used. */\n\t\tdictation.stop();\n\t};\n\n\t/* Same rule as the bubble composer: an attachment that is still uploading is not\n\t sendable yet, and text alone or a settled attachment both are. */\n\tconst uploading = attachments?.some((a) => a.isUploading) ?? false;\n\tconst hasAttachment = attachments?.some((a) => a.part !== null) ?? false;\n\tconst canSend = (!!value.trim() || hasAttachment) && !uploading && !disabled;\n\n\treturn (\n\t\t<div className=\"hw-dock\" onFocus={() => setFocused(true)} onBlur={onDockBlur}>\n\t\t\t{showSuggestions && (\n\t\t\t\t<div className=\"hw-dock-suggestions\">\n\t\t\t\t\t{visibleQuestions.map((question, index) => (\n\t\t\t\t\t\t/* The pill stays a button and the dismiss is a sibling, not a nested\n\t\t\t\t\t\t button — a button inside a button is invalid and the inner click\n\t\t\t\t\t\t would still fire the outer one. Only the first row carries the ×,\n\t\t\t\t\t\t since it closes the whole offer. */\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tkey={question}\n\t\t\t\t\t\t\tclassName=\"hw-dock-pill-row\"\n\t\t\t\t\t\t\tstyle={{ animationDelay: `${120 + index * 90}ms` }}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclassName=\"hw-dock-pill\"\n\t\t\t\t\t\t\t\tonClick={() => onSuggestion?.(question)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{question}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t{index === 0 && (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclassName=\"hw-dock-pill-dismiss\"\n\t\t\t\t\t\t\t\t\taria-label={t(\"widget.aria_dismiss\")}\n\t\t\t\t\t\t\t\t\tonClick={dismissOffer}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\t\t\tstrokeWidth=\"2.5\"\n\t\t\t\t\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<path d=\"M18 6 6 18M6 6l12 12\" />\n\t\t\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{sendError && (\n\t\t\t\t<div className=\"hw-dock-error\" role=\"alert\">\n\t\t\t\t\t{sendError}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t<div\n\t\t\t\tclassName=\"hw-dock-bar\"\n\t\t\t\tref={boxRef}\n\t\t\t\tdata-grown=\"false\"\n\t\t\t\tonMouseDown={onReopen}\n\t\t\t\tonTouchStart={onReopen}\n\t\t\t>\n\t\t\t\t{/* Above the field rather than beside it: a thumbnail in the row would\n\t\t\t\t shove the caption into a sliver on the one bar width we control. */}\n\t\t\t\t{!!attachments?.length && (\n\t\t\t\t\t<div className=\"hw-dock-previews\">\n\t\t\t\t\t\t{attachments.map((a) => (\n\t\t\t\t\t\t\t<PreviewThumb\n\t\t\t\t\t\t\t\tkey={a.id}\n\t\t\t\t\t\t\t\tattachment={a}\n\t\t\t\t\t\t\t\tonRemove={onRemoveAttachment ? () => onRemoveAttachment(a.id) : undefined}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t\t{/* Never disabled while a send is in flight. The browser blurs a\n\t\t\t\t disabled element, so locking the field for the ~200ms round trip\n\t\t\t\t threw the caret out of it — the visitor pressed Enter and lost\n\t\t\t\t the field they were typing in. `canSend` and the Enter handler\n\t\t\t\t already refuse a second submit, which is the part that actually\n\t\t\t\t needed guarding. */}\n\t\t\t\t<textarea\n\t\t\t\t\tref={inputRef}\n\t\t\t\t\tclassName=\"hw-dock-input\"\n\t\t\t\t\trows={1}\n\t\t\t\t\tvalue={value}\n\t\t\t\t\tplaceholder={placeholder ?? t(\"widget.placeholder_new\")}\n\t\t\t\t\taria-label={t(\"widget.placeholder_new\")}\n\t\t\t\t\tonChange={(event) => {\n\t\t\t\t\t\tonChange(event.target.value);\n\t\t\t\t\t\tif (sendError) onClearSendError?.();\n\t\t\t\t\t\tgrow();\n\t\t\t\t\t}}\n\t\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\t\tonPaste={handlePaste}\n\t\t\t\t/>\n\t\t\t\t<div className=\"hw-dock-actions\">\n\t\t\t\t\t{dictation.supported && (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tclassName=\"hw-dock-tool\"\n\t\t\t\t\t\t\tdata-active={dictation.listening ? \"true\" : undefined}\n\t\t\t\t\t\t\taria-label={t(\"widget.aria_dictate\")}\n\t\t\t\t\t\t\taria-pressed={dictation.listening}\n\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\tonClick={dictation.toggle}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<MicGlyph />\n\t\t\t\t\t\t</button>\n\t\t\t\t\t)}\n\t\t\t\t\t{onAddFiles && (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclassName=\"hw-dock-tool\"\n\t\t\t\t\t\t\t\taria-label={t(\"widget.aria_attach\")}\n\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\tonClick={() => fileInputRef.current?.click()}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<PaperclipIcon size={17} />\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\tref={fileInputRef}\n\t\t\t\t\t\t\t\ttype=\"file\"\n\t\t\t\t\t\t\t\taccept={ACCEPTED_TYPES}\n\t\t\t\t\t\t\t\tmultiple\n\t\t\t\t\t\t\t\thidden\n\t\t\t\t\t\t\t\tonChange={(event) => {\n\t\t\t\t\t\t\t\t\tif (!event.target.files) return;\n\t\t\t\t\t\t\t\t\tonAddFiles(Array.from(event.target.files));\n\t\t\t\t\t\t\t\t\t// Reset so picking the same file twice still fires a change.\n\t\t\t\t\t\t\t\t\tevent.target.value = \"\";\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"hw-dock-send\"\n\t\t\t\t\t\taria-label={t(\"widget.aria_send\")}\n\t\t\t\t\t\tdisabled={!canSend}\n\t\t\t\t\t\tonClick={onSubmit}\n\t\t\t\t\t>\n\t\t\t\t\t\t<ArrowUpIcon size={16} />\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\n/** Local glyph — the shipped icon snapshot has no mic, and one path is cheaper\n than another entry in the generated set. */\nfunction MicGlyph() {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"17\"\n\t\t\theight=\"17\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\"\n\t\t>\n\t\t\t<path d=\"M12 3.5a3 3 0 0 1 3 3v4.5a3 3 0 0 1-6 0V6.5a3 3 0 0 1 3-3Z\" />\n\t\t\t<path d=\"M5.5 11v.5a6.5 6.5 0 0 0 13 0V11\" />\n\t\t\t<path d=\"M12 18v3\" />\n\t\t</svg>\n\t);\n}\n","import { resolveLabel, t } from \"@helpway/widget-core\";\nimport type { WidgetContentTab } from \"@helpway/widget-core\";\nimport { useCallback, useEffect } from \"react\";\nimport { useContentTab } from \"../../hooks/use-content-tab\";\nimport type { ContentEntryItem } from \"../../hooks/use-content-tab\";\nimport { ContentDetailView } from \"./content-detail-view\";\nimport { ContentListView } from \"./content-list-view\";\nimport { GroupedContentTabView } from \"./grouped-content-tab-view\";\n\n/**\n * Content tab dispatcher:\n * - \"flat\" (default) → simple list → detail\n * - \"grouped\" → categories → items → detail\n */\nexport function ContentTabView({\n\ttab,\n\tshowDetail,\n\tdetailSlug,\n\tsubView,\n\tonSelectEntry,\n\tonSelectCategory,\n}: {\n\ttab: WidgetContentTab;\n\tshowDetail: boolean;\n\tdetailSlug: string | null;\n\tsubView?: string | null;\n\tonSelectEntry: (slug: string) => void;\n\tonSelectCategory?: (category: ContentEntryItem) => void;\n}) {\n\t// ── Grouped tab ──\n\tif (tab.tabType === \"grouped\" && tab.itemsModelSlug) {\n\t\treturn (\n\t\t\t<GroupedContentTabView\n\t\t\t\ttab={tab}\n\t\t\t\tsubView={subView ?? null}\n\t\t\t\tdetailSlug={detailSlug}\n\t\t\t\tonSelectCategory={onSelectCategory ?? (() => {})}\n\t\t\t\tonSelectEntry={onSelectEntry}\n\t\t\t/>\n\t\t);\n\t}\n\n\t// ── Flat tab (default) ──\n\treturn (\n\t\t<FlatContentTabView\n\t\t\ttab={tab}\n\t\t\tshowDetail={showDetail}\n\t\t\tdetailSlug={detailSlug}\n\t\t\tonSelectEntry={onSelectEntry}\n\t\t/>\n\t);\n}\n\n// ── Flat (original behavior) ─────────────────────────────\n\nfunction FlatContentTabView({\n\ttab,\n\tshowDetail,\n\tdetailSlug,\n\tonSelectEntry,\n}: {\n\ttab: WidgetContentTab;\n\tshowDetail: boolean;\n\tdetailSlug: string | null;\n\tonSelectEntry: (slug: string) => void;\n}) {\n\tconst {\n\t\tentries,\n\t\tdetail,\n\t\tisLoading,\n\t\tisLoadingDetail,\n\t\thasMore,\n\t\tfetchEntries,\n\t\tloadMore,\n\t\tfetchDetail,\n\t} = useContentTab(tab.id);\n\n\tuseEffect(() => {\n\t\tif (detailSlug) fetchDetail(detailSlug);\n\t}, [detailSlug, fetchDetail]);\n\n\tconst handleSearch = useCallback(\n\t\t(query: string) => {\n\t\t\tfetchEntries({ page: 1, search: query || undefined, reset: true });\n\t\t},\n\t\t[fetchEntries],\n\t);\n\n\tif (showDetail && detailSlug) {\n\t\treturn <ContentDetailView entry={detail} isLoading={isLoadingDetail} />;\n\t}\n\n\treturn (\n\t\t<ContentListView\n\t\t\tentries={entries}\n\t\t\tisLoading={isLoading}\n\t\t\thasMore={hasMore}\n\t\t\tonSelect={onSelectEntry}\n\t\t\tonLoadMore={loadMore}\n\t\t\tonSearch={handleSearch}\n\t\t\tsearchPlaceholder={`${t(\"widget.search\")} ${resolveLabel(tab.label).toLowerCase()}...`}\n\t\t\tdisplay={tab.display}\n\t\t/>\n\t);\n}\n","import type { WidgetContentTab } from \"@helpway/widget-core\";\nimport { CONTENT_CACHE_TTL, getLocale } from \"@helpway/widget-core\";\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useWidgetContext, useWidgetStore } from \"../provider\";\n\ninterface ContentEntryItem {\n\tslug: string;\n\ttitle: string;\n\tbody: string | null;\n\tpublishedAt: string | null;\n\tcustomFields: Record<string, string | null>;\n}\n\ninterface ContentEntryDetail {\n\tslug: string;\n\ttitle: string;\n\tbody: string | null;\n\tbodyHtml: string | null;\n\tpublishedAt: string | null;\n\tsourceLanguage: string;\n\tavailableLanguages: string[];\n\tcustomFields: Record<string, string | null>;\n}\n\nconst EMPTY_TABS: WidgetContentTab[] = [];\n\n// ── Cache key helpers ──\n\nfunction listKey(tabId: string, lang: string) {\n\treturn `flat:${tabId}:${lang}:list`;\n}\n\nfunction detailKey(tabId: string, lang: string, slug: string) {\n\treturn `flat:${tabId}:${lang}:detail:${slug}`;\n}\n\ninterface CachedList {\n\titems: ContentEntryItem[];\n\ttotal: number;\n\thasMore: boolean;\n\tpage: number;\n}\n\nfunction readCache<T>(cache: Map<string, { data: unknown; ts: number }>, key: string): T | null {\n\tconst entry = cache.get(key);\n\tif (!entry) return null;\n\tif (Date.now() - entry.ts > CONTENT_CACHE_TTL) return null;\n\treturn entry.data as T;\n}\n\n/**\n * Hook for fetching content from a dynamic content tab.\n * Content is cached in the Zustand store so tab switches don't re-fetch.\n */\nexport function useContentTab(tabId: string) {\n\tconst { client, store } = useWidgetContext();\n\tconst contentTabs = useWidgetStore((s) => s.agentConfig?.contentTabs) ?? EMPTY_TABS;\n\tconst tab = contentTabs.find((t) => t.id === tabId) ?? null;\n\n\tconst lang = getLocale();\n\tconst cache = store.getState().contentCache;\n\n\tconst [entries, setEntries] = useState<ContentEntryItem[]>(\n\t\t() => readCache<CachedList>(cache, listKey(tabId, lang))?.items ?? [],\n\t);\n\tconst [detail, setDetail] = useState<ContentEntryDetail | null>(null);\n\tconst [isLoading, setIsLoading] = useState(false);\n\tconst [isLoadingDetail, setIsLoadingDetail] = useState(false);\n\tconst [hasMore, setHasMore] = useState(\n\t\t() => readCache<CachedList>(cache, listKey(tabId, lang))?.hasMore ?? false,\n\t);\n\tconst [total, setTotal] = useState(\n\t\t() => readCache<CachedList>(cache, listKey(tabId, lang))?.total ?? 0,\n\t);\n\tconst [page, setPage] = useState(\n\t\t() => readCache<CachedList>(cache, listKey(tabId, lang))?.page ?? 1,\n\t);\n\n\tconst fetchEntries = useCallback(\n\t\tasync (opts?: { page?: number; search?: string; reset?: boolean }) => {\n\t\t\tif (!tab) return;\n\t\t\tconst p = opts?.page ?? 1;\n\t\t\tconst reset = opts?.reset ?? p === 1;\n\n\t\t\tsetIsLoading(true);\n\t\t\ttry {\n\t\t\t\tconst result = await client.widget.getContent.query({\n\t\t\t\t\ttabId,\n\t\t\t\t\tpage: p,\n\t\t\t\t\tlimit: 10,\n\t\t\t\t\tsearch: opts?.search,\n\t\t\t\t\tlanguage: getLocale(),\n\t\t\t\t});\n\n\t\t\t\tif (result.items) {\n\t\t\t\t\tsetEntries((prev) => {\n\t\t\t\t\t\tconst nextItems = reset ? result.items! : [...prev, ...result.items!];\n\t\t\t\t\t\tif (!opts?.search) {\n\t\t\t\t\t\t\tstore.getState().setContentCache(listKey(tabId, getLocale()), {\n\t\t\t\t\t\t\t\titems: nextItems,\n\t\t\t\t\t\t\t\ttotal: result.total,\n\t\t\t\t\t\t\t\thasMore: result.hasMore,\n\t\t\t\t\t\t\t\tpage: p,\n\t\t\t\t\t\t\t} satisfies CachedList);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn nextItems;\n\t\t\t\t\t});\n\t\t\t\t\tsetHasMore(result.hasMore);\n\t\t\t\t\tsetTotal(result.total);\n\t\t\t\t\tsetPage(p);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"[useContentTab] fetch error:\", err);\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false);\n\t\t\t}\n\t\t},\n\t\t[client, tabId, tab, store],\n\t);\n\n\tconst loadMore = useCallback(() => {\n\t\tif (!hasMore || isLoading) return;\n\t\tfetchEntries({ page: page + 1 });\n\t}, [fetchEntries, hasMore, isLoading, page]);\n\n\tconst fetchDetail = useCallback(\n\t\tasync (slug: string) => {\n\t\t\tif (!tab) return;\n\n\t\t\t// Check detail cache\n\t\t\tconst cached = readCache<ContentEntryDetail>(\n\t\t\t\tstore.getState().contentCache,\n\t\t\t\tdetailKey(tabId, getLocale(), slug),\n\t\t\t);\n\t\t\tif (cached) {\n\t\t\t\tsetDetail(cached);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsetIsLoadingDetail(true);\n\t\t\ttry {\n\t\t\t\tconst result = await client.widget.getContent.query({\n\t\t\t\t\ttabId,\n\t\t\t\t\tslug,\n\t\t\t\t\tlanguage: getLocale(),\n\t\t\t\t});\n\t\t\t\tif (result.entry) {\n\t\t\t\t\tconst entry = result.entry as ContentEntryDetail;\n\t\t\t\t\tsetDetail(entry);\n\t\t\t\t\tstore.getState().setContentCache(\n\t\t\t\t\t\tdetailKey(tabId, getLocale(), slug),\n\t\t\t\t\t\tentry,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"[useContentTab] detail error:\", err);\n\t\t\t} finally {\n\t\t\t\tsetIsLoadingDetail(false);\n\t\t\t}\n\t\t},\n\t\t[client, tabId, tab, store],\n\t);\n\n\tconst clearDetail = useCallback(() => {\n\t\tsetDetail(null);\n\t}, []);\n\n\t// Initial fetch — only if cache was empty\n\tuseEffect(() => {\n\t\tif (tab && entries.length === 0) {\n\t\t\tfetchEntries({ page: 1, reset: true });\n\t\t}\n\t}, [tab]); // eslint-disable-line react-hooks/exhaustive-deps\n\n\treturn {\n\t\ttab,\n\t\tentries,\n\t\tdetail,\n\t\tisLoading,\n\t\tisLoadingDetail,\n\t\thasMore,\n\t\ttotal,\n\t\tfetchEntries,\n\t\tloadMore,\n\t\tfetchDetail,\n\t\tclearDetail,\n\t};\n}\n\nexport type { ContentEntryItem, ContentEntryDetail, WidgetContentTab };\n","import { useEffect, useRef } from \"react\";\n\nconst 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>`;\n\nconst 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>`;\n\nfunction inferCodeLanguage(code: string, lang?: string): string {\n\tif (lang) return lang;\n\tconst trimmed = code.trim();\n\tif (/^(npm|pnpm|yarn|bun|npx|curl|cd|mkdir|cp|mv|rm|export)\\b/m.test(trimmed)) return \"bash\";\n\tif (/\\b(import|export)\\b/.test(trimmed) && /<[A-Z_a-z][\\w.:-]*(\\s|>)/.test(trimmed)) return \"tsx\";\n\tif (/\\b(import|export|const|let|function|type|interface)\\b/.test(trimmed)) return \"ts\";\n\tif (/^\\s*[{[]/.test(trimmed)) return \"json\";\n\treturn \"code\";\n}\n\nexport function handleCodeBlockClick(e: Event, root: HTMLElement): void {\n\tconst target = e.target as HTMLElement | null;\n\tconst btn = target?.closest<HTMLButtonElement>(\".hw-code-copy\");\n\tif (!btn || !root.contains(btn)) return;\n\tconst block = btn.closest(\".hw-code\");\n\tconst code = block?.querySelector(\"pre code\");\n\tconst text = code?.textContent ?? \"\";\n\tif (!text) return;\n\tvoid navigator.clipboard?.writeText(text).then(\n\t\t() => flashCopied(btn),\n\t\t() => flashCopied(btn, true),\n\t);\n}\n\n/**\n * Lightweight Markdown → HTML renderer.\n * Zero dependencies. Handles common patterns:\n * headings, bold, italic, code, links, lists, blockquotes, images, hr.\n *\n * Security note: Content is served from Better i18n Content CMS which only\n * accepts authenticated writes (secret API key). The CMS sanitizes content\n * server-side. Additionally, our renderMarkdown escapes HTML entities before\n * processing markdown syntax, preventing injection of raw HTML tags.\n */\nexport function renderMarkdown(md: string): string {\n\t// Stash fenced code blocks BEFORE any other pass. Fence content must be\n\t// preserved verbatim: no bold, no autolink, no newline→<br> — otherwise\n\t// a curl command or JSON sample gets shredded. We also escape HTML inside\n\t// the block (the global escape below runs only on the remaining markdown).\n\tconst codeBlocks: string[] = [];\n\tconst codeBlockPlaceholder = (i: number) => `\\u0000CODEBLOCK${i}\\u0000`;\n\tconst body = md.replace(\n\t\t// Eat ALL newlines around the fence (zero-or-more both sides). The\n\t\t// replacement re-emits its own `\\n\\n` pair so the paragraph splitter\n\t\t// cleanly bookends the fence. Without this, `before\\n\\n` + `\\n\\n` from\n\t\t// us = 3 newlines, the extra one becomes <br /> and lands inside a <p>.\n\t\t/\\n*```(\\w+)?\\n?([\\s\\S]*?)```\\n*/g,\n\t\t(_match, lang: string | undefined, code: string) => {\n\t\t\tconst escaped = code.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n\t\t\tconst langLabel = inferCodeLanguage(code, lang);\n\t\t\tconst className = langLabel !== \"code\" ? ` class=\"language-${langLabel}\"` : \"\";\n\t\t\t// Render every fenced block with a header bar (language label + copy\n\t\t\t// button) so it reads like a proper code card, not a bare <pre>.\n\t\t\t// The actual copy action is wired up in MarkdownContent via event\n\t\t\t// delegation — we only need the markup + a stable attribute to key\n\t\t\t// off of.\n\t\t\tconst trimmed = escaped.replace(/\\n$/, \"\");\n\t\t\tcodeBlocks.push(\n\t\t\t\t`<div class=\"hw-code\" data-hw-code=\"1\"><div class=\"hw-code-header\"><span class=\"hw-code-lang\">${langLabel}</span><div class=\"hw-code-actions\"><button type=\"button\" class=\"hw-code-action hw-code-copy\" aria-label=\"Copy code\" title=\"Copy code\">${COPY_ICON}${CHECK_ICON}<span class=\"hw-code-copy-label\">Copy</span></button></div></div><pre><code${className}>${trimmed}</code></pre></div>`,\n\t\t\t);\n\t\t\t// Sandwich the placeholder in blank lines so the paragraph splitter\n\t\t\t// treats it as its own block. Otherwise a fence that follows a\n\t\t\t// paragraph without a separating blank line ends up inside a <p>\n\t\t\t// (invalid HTML, collapses the <pre>).\n\t\t\treturn `\\n\\n${codeBlockPlaceholder(codeBlocks.length - 1)}\\n\\n`;\n\t\t},\n\t);\n\n\tlet html = body\n\t\t// Escape HTML entities FIRST — prevents XSS from raw HTML in markdown\n\t\t.replace(/&/g, \"&amp;\")\n\t\t.replace(/</g, \"&lt;\")\n\t\t.replace(/>/g, \"&gt;\")\n\t\t// Headings (### h3, ## h2, # h1)\n\t\t.replace(/^### (.+)$/gm, \"<h3>$1</h3>\")\n\t\t.replace(/^## (.+)$/gm, \"<h2>$1</h2>\")\n\t\t.replace(/^# (.+)$/gm, \"<h1>$1</h1>\")\n\t\t// Horizontal rule\n\t\t.replace(/^---$/gm, \"<hr />\")\n\t\t// Bold + italic\n\t\t.replace(/\\*\\*\\*(.+?)\\*\\*\\*/g, \"<strong><em>$1</em></strong>\")\n\t\t// Bold\n\t\t.replace(/\\*\\*(.+?)\\*\\*/g, \"<strong>$1</strong>\")\n\t\t// Italic\n\t\t.replace(/\\*(.+?)\\*/g, \"<em>$1</em>\")\n\t\t// Inline code\n\t\t.replace(/`([^`]+)`/g, \"<code>$1</code>\")\n\t\t// Images\n\t\t.replace(/!\\[([^\\]]*)\\]\\(([^)]+)\\)/g, '<img src=\"$2\" alt=\"$1\" />')\n\t\t// Links (markdown format)\n\t\t.replace(\n\t\t\t/\\[([^\\]]+)\\]\\(([^)]+)\\)/g,\n\t\t\t'<a href=\"$2\" target=\"_blank\" rel=\"noopener noreferrer\">$1</a>',\n\t\t)\n\t\t// Auto-link bare URLs (not already inside an href or markdown link)\n\t\t.replace(\n\t\t\t/(?<!\")(?<!=)(https?:\\/\\/[^\\s<)]+)/g,\n\t\t\t'<a href=\"$1\" target=\"_blank\" rel=\"noopener noreferrer\">$1</a>',\n\t\t)\n\t\t// Blockquotes\n\t\t.replace(/^&gt; (.+)$/gm, \"<blockquote>$1</blockquote>\")\n\t\t// Unordered lists\n\t\t.replace(/^[*-] (.+)$/gm, \"<li>$1</li>\")\n\t\t// Ordered lists — temp <oli> tag so the <ul> wrapper below can't claim\n\t\t// them; renamed to <li> when wrapped in <ol>.\n\t\t.replace(/^\\d+\\. (.+)$/gm, \"<oli>$1</oli>\");\n\n\t// Tables — must run while real newlines still exist (before the <br> pass).\n\t// Runs AFTER the inline passes so bold/links inside cells are already HTML.\n\t// Stashed as placeholders like code blocks so the paragraph splitter can't\n\t// chop a <table> in half.\n\tconst tables: string[] = [];\n\tconst tablePlaceholder = (i: number) => `\\u0000TABLE${i}\\u0000`;\n\thtml = html.replace(\n\t\t// header row | separator row (only - : | spaces) | 1+ body rows\n\t\t/^(\\|.+\\|)[ \\t]*\\n\\|[ \\t:|-]+\\|[ \\t]*\\n((?:\\|.+\\|[ \\t]*(?:\\n|$))+)/gm,\n\t\t(_match, headerLine: string, bodyLines: string) => {\n\t\t\tconst cells = (line: string) =>\n\t\t\t\tline.trim().replace(/^\\||\\|$/g, \"\").split(\"|\").map((c) => c.trim());\n\t\t\tconst head = cells(headerLine)\n\t\t\t\t.map((c) => `<th>${c}</th>`)\n\t\t\t\t.join(\"\");\n\t\t\tconst rows = bodyLines\n\t\t\t\t.trim()\n\t\t\t\t.split(\"\\n\")\n\t\t\t\t.map((line) => `<tr>${cells(line).map((c) => `<td>${c}</td>`).join(\"\")}</tr>`)\n\t\t\t\t.join(\"\");\n\t\t\ttables.push(\n\t\t\t\t`<div class=\"hw-table-wrap\"><table class=\"hw-table\"><thead><tr>${head}</tr></thead><tbody>${rows}</tbody></table></div>`,\n\t\t\t);\n\t\t\treturn `\\n\\n${tablePlaceholder(tables.length - 1)}\\n\\n`;\n\t\t},\n\t);\n\n\t// Wrap consecutive list items BEFORE newlines become <br /> — the old\n\t// post-<br> wrap could only ever see one <li> at a time, producing a\n\t// separate <ul> per item with stray <br />s in between.\n\thtml = html\n\t\t.replace(/((?:<li>.*<\\/li>\\n?)+)/g, (m) => `<ul>${m.replace(/\\n/g, \"\")}</ul>\\n`)\n\t\t.replace(\n\t\t\t/((?:<oli>.*<\\/oli>\\n?)+)/g,\n\t\t\t(m) => `<ol>${m.replace(/\\n/g, \"\").replace(/<(\\/?)oli>/g, \"<$1li>\")}</ol>\\n`,\n\t\t);\n\n\thtml = html\n\t\t// Paragraphs (double newline)\n\t\t.replace(/\\n\\n/g, \"</p><p>\")\n\t\t// Single newlines → br\n\t\t.replace(/\\n/g, \"<br />\");\n\n\t// Lists glued to surrounding text by a single newline pick up a stray\n\t// <br /> neighbor — drop it so spacing comes from CSS, not phantom breaks.\n\t// Same for a <br /> opening a paragraph (left over from placeholder seams).\n\thtml = html\n\t\t.replace(/<br \\/>(\\s*<(?:ul|ol)>)/g, \"$1\")\n\t\t.replace(/(<\\/(?:ul|ol)>\\s*)<br \\/>/g, \"$1\")\n\t\t.replace(/<p><br \\/>/g, \"<p>\");\n\n\t// Wrap in paragraph if not starting with a block element\n\tif (\n\t\t!html.startsWith(\"<h\") &&\n\t\t!html.startsWith(\"<ul\") &&\n\t\t!html.startsWith(\"<ol\") &&\n\t\t!html.startsWith(\"<blockquote\") &&\n\t\t!html.startsWith(\"<hr\")\n\t) {\n\t\thtml = `<p>${html}</p>`;\n\t}\n\n\t// Re-inject tables (same placeholder mechanics as code blocks below).\n\tif (tables.length > 0) {\n\t\t// biome-ignore lint/suspicious/noControlCharactersInRegex: placeholders use NUL sentinels intentionally.\n\t\thtml = html.replace(/\\u0000TABLE(\\d+)\\u0000/g, (_m, idx: string) => {\n\t\t\tconst i = Number.parseInt(idx, 10);\n\t\t\treturn tables[i] ?? \"\";\n\t\t});\n\t\t// Unwrap a <p> that ended up directly around a table (no blank-line\n\t\t// separator in the source) — invalid nesting collapses the layout.\n\t\thtml = html.replace(/<p>(\\s*<div class=\"hw-table-wrap\"[\\s\\S]*?<\\/div>\\s*)<\\/p>/g, \"$1\");\n\t}\n\n\t// A list that landed inside a <p> (single blank line before it) is invalid\n\t// nesting — unwrap like the code-block case below.\n\thtml = html.replace(/<p>(\\s*<(?:ul|ol)>[\\s\\S]*?<\\/(?:ul|ol)>\\s*)<\\/p>/g, \"$1\");\n\n\t// Re-inject code blocks now that surrounding paragraphs / <br> passes are\n\t// done. Placeholders used NUL sentinels so they can't collide with user\n\t// content or be accidentally wrapped by the block-element heuristics above.\n\tif (codeBlocks.length > 0) {\n\t\t// biome-ignore lint/suspicious/noControlCharactersInRegex: placeholders use NUL sentinels intentionally.\n\t\thtml = html.replace(/\\u0000CODEBLOCK(\\d+)\\u0000/g, (_m, idx: string) => {\n\t\t\tconst i = Number.parseInt(idx, 10);\n\t\t\treturn codeBlocks[i] ?? \"\";\n\t\t});\n\t\t// A code block that landed inside a <p> (because the preceding line had no\n\t\t// blank-line separator) becomes invalid nesting (<p><div><pre>). Unwrap\n\t\t// the outer <p> so the block stands on its own.\n\t\thtml = html.replace(/<p>(\\s*<div class=\"hw-code\"[\\s\\S]*?<\\/div>\\s*)<\\/p>/g, \"$1\");\n\t}\n\n\treturn html;\n}\n\n/**\n * Convert bare URLs in plain text to clickable links.\n * Used for visitor/team messages (not full markdown).\n * HTML-escaped for safety.\n */\nexport function linkifyText(text: string): string {\n\treturn text\n\t\t.replace(/&/g, \"&amp;\")\n\t\t.replace(/</g, \"&lt;\")\n\t\t.replace(/>/g, \"&gt;\")\n\t\t.replace(\n\t\t\t/(https?:\\/\\/[^\\s<]+)/g,\n\t\t\t'<a href=\"$1\" target=\"_blank\" rel=\"noopener noreferrer\">$1</a>',\n\t\t)\n\t\t.replace(/\\n/g, \"<br />\");\n}\n\n/**\n * Renders markdown or pre-rendered HTML content.\n * Prefers bodyHtml (server-sanitized by CMS) when available,\n * falls back to client-side markdown rendering (HTML-escaped).\n */\nexport function MarkdownContent({\n\tbodyHtml,\n\tbodyMarkdown,\n\tclassName,\n}: {\n\tbodyHtml?: string | null;\n\tbodyMarkdown?: string | null;\n\tclassName?: string;\n}) {\n\tconst rootRef = useRef<HTMLDivElement>(null);\n\tconst html = bodyHtml ?? (bodyMarkdown ? renderMarkdown(bodyMarkdown) : \"\");\n\n\t// Strip whitespace-only block elements after the HTML lands in the DOM.\n\t// PlateJS/Slate/ProseMirror CMS bodies emit <p>&nbsp;</p> or <div> </div>\n\t// to represent visual line breaks. CSS `:empty` doesn't match these (the\n\t// nbsp/space is a text node) and CSS has no text-content selector, so we\n\t// clean them up here. Runs once per html change.\n\tuseEffect(() => {\n\t\tconst root = rootRef.current;\n\t\tif (!root) return;\n\n\t\tconst isWhitespaceOnly = (el: Element): boolean => {\n\t\t\t// No element children OR only <br> children, AND text is whitespace/empty\n\t\t\tconst hasNonBrChild = Array.from(el.children).some(\n\t\t\t\t(c) => c.tagName !== \"BR\",\n\t\t\t);\n\t\t\tif (hasNonBrChild) return false;\n\t\t\tconst text = el.textContent ?? \"\";\n\t\t\treturn text.replace(/[\\s ]/g, \"\") === \"\";\n\t\t};\n\n\t\tconst removeEmpties = () => {\n\t\t\tconst candidates = root.querySelectorAll(\"p, div\");\n\t\t\tcandidates.forEach((el) => {\n\t\t\t\tif (isWhitespaceOnly(el)) el.remove();\n\t\t\t});\n\t\t};\n\t\tremoveEmpties();\n\t}, [html]);\n\n\t// Event-delegated copy handler for any `.hw-code-copy` button inside the\n\t// rendered tree. Using delegation instead of rendering each code block as\n\t// a React component keeps the markdown → HTML path zero-dep.\n\tuseEffect(() => {\n\t\tconst root = rootRef.current;\n\t\tif (!root) return;\n\t\tconst handler = (e: Event) => {\n\t\t\thandleCodeBlockClick(e, root);\n\t\t};\n\t\troot.addEventListener(\"click\", handler);\n\t\treturn () => {\n\t\t\troot.removeEventListener(\"click\", handler);\n\t\t};\n\t}, []);\n\n\tif (!html) return null;\n\n\treturn (\n\t\t<div\n\t\t\tref={rootRef}\n\t\t\tclassName={`hw-markdown ${className ?? \"\"}`}\n\t\t\t// Content is from authenticated CMS (server-sanitized bodyHtml)\n\t\t\t// or client-side rendered with HTML entity escaping (renderMarkdown).\n\t\t\t// biome-ignore lint/security/noDangerouslySetInnerHtml: trusted CMS content\n\t\t\tdangerouslySetInnerHTML={{ __html: html }}\n\t\t/>\n\t);\n}\n\nfunction flashCopied(btn: HTMLButtonElement, failed = false) {\n\tconst label = btn.querySelector(\".hw-code-copy-label\");\n\tif (!label) return;\n\tconst original = label.textContent ?? \"Copy\";\n\tlabel.textContent = failed ? \"Failed\" : \"Copied\";\n\tbtn.classList.add(failed ? \"hw-code-copy--failed\" : \"hw-code-copy--copied\");\n\tsetTimeout(() => {\n\t\tlabel.textContent = original;\n\t\tbtn.classList.remove(\"hw-code-copy--copied\", \"hw-code-copy--failed\");\n\t}, 1500);\n}\n","import { formatRelativeTime } from \"@helpway/widget-core\";\nimport type { ContentEntryDetail } from \"../../hooks/use-content-tab\";\nimport { MarkdownContent } from \"./simple-markdown\";\n\nexport function ContentDetailView({\n\tentry,\n\tisLoading,\n}: {\n\tentry: ContentEntryDetail | null;\n\tisLoading: boolean;\n}) {\n\tif (isLoading || !entry) {\n\t\treturn <ArticleSkeleton />;\n\t}\n\n\tconst badge = entry.customFields.version ?? entry.customFields.priority ?? entry.customFields.type ?? null;\n\n\treturn (\n\t\t<div className=\"hw-content-detail\">\n\t\t\t<div className=\"hw-content-detail-header\">\n\t\t\t\t<h1 className=\"hw-content-detail-title\">{entry.title}</h1>\n\t\t\t\t{(badge || entry.publishedAt) && (\n\t\t\t\t\t<div className=\"hw-content-detail-meta\">\n\t\t\t\t\t\t{badge && <span className=\"hw-content-entry-badge\">{badge}</span>}\n\t\t\t\t\t\t{entry.publishedAt && (\n\t\t\t\t\t\t\t<span className=\"hw-content-detail-date\">\n\t\t\t\t\t\t\t\t{formatRelativeTime(entry.publishedAt)}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t\t{(entry.body || entry.bodyHtml) && (\n\t\t\t\t<div className=\"hw-content-detail-body\">\n\t\t\t\t\t<MarkdownContent bodyHtml={entry.bodyHtml} bodyMarkdown={entry.body} />\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\n/**\n * Article-shaped skeleton.\n *\n * Uses the real .hw-content-detail / .hw-content-detail-header / .hw-content-detail-body / .hw-markdown\n * wrapper classes so all padding, font metrics, and adjacency-spacing rules\n * apply identically to the skeleton — guaranteeing the content lands without\n * any reflow when it arrives.\n *\n * Layout maps 1:1 to the rendered changelog:\n * <h1>Title</h1>\n * <div class=\"meta\"> badge + date </div>\n * <h2>Section</h2>\n * <ul><li>Bullet 1, 2 lines</li></ul>\n * <ul><li>Bullet 2, 2 lines</li></ul>\n * ...\n */\nfunction ArticleSkeleton() {\n\tconst sections: { headerWidth: string; items: { l1: string; l2: string }[] }[] = [\n\t\t{\n\t\t\theaderWidth: \"30%\",\n\t\t\titems: [\n\t\t\t\t{ l1: \"98%\", l2: \"62%\" },\n\t\t\t\t{ l1: \"94%\", l2: \"48%\" },\n\t\t\t\t{ l1: \"96%\", l2: \"70%\" },\n\t\t\t],\n\t\t},\n\t\t{\n\t\t\theaderWidth: \"26%\",\n\t\t\titems: [\n\t\t\t\t{ l1: \"92%\", l2: \"55%\" },\n\t\t\t\t{ l1: \"88%\", l2: \"40%\" },\n\t\t\t],\n\t\t},\n\t];\n\n\treturn (\n\t\t<div className=\"hw-content-detail\">\n\t\t\t<div className=\"hw-content-detail-header\">\n\t\t\t\t<h1 className=\"hw-content-detail-title\">\n\t\t\t\t\t<span className=\"hw-skeleton hw-skeleton-title\" />\n\t\t\t\t</h1>\n\t\t\t\t<div className=\"hw-content-detail-meta\">\n\t\t\t\t\t<span className=\"hw-skeleton hw-skeleton-badge\" />\n\t\t\t\t\t<span className=\"hw-skeleton hw-skeleton-date\" />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div className=\"hw-content-detail-body\">\n\t\t\t\t<div className=\"hw-markdown\">\n\t\t\t\t\t{sections.map((s, i) => (\n\t\t\t\t\t\t<SkeletonSection\n\t\t\t\t\t\t\tkey={i}\n\t\t\t\t\t\t\theaderWidth={s.headerWidth}\n\t\t\t\t\t\t\titems={s.items}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nfunction SkeletonSection({\n\theaderWidth,\n\titems,\n}: {\n\theaderWidth: string;\n\titems: { l1: string; l2: string }[];\n}) {\n\treturn (\n\t\t<>\n\t\t\t<h2>\n\t\t\t\t<span\n\t\t\t\t\tclassName=\"hw-skeleton hw-skeleton-h2\"\n\t\t\t\t\tstyle={{ display: \"block\", width: headerWidth }}\n\t\t\t\t/>\n\t\t\t</h2>\n\t\t\t{items.map((item, j) => (\n\t\t\t\t<ul key={j}>\n\t\t\t\t\t<li>\n\t\t\t\t\t\t<div className=\"hw-skeleton-bullet-lines\">\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\tclassName=\"hw-skeleton hw-skeleton-bullet-line\"\n\t\t\t\t\t\t\t\tstyle={{ display: \"block\", width: item.l1 }}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\tclassName=\"hw-skeleton hw-skeleton-bullet-line\"\n\t\t\t\t\t\t\t\tstyle={{ display: \"block\", width: item.l2, marginTop: 8 }}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</li>\n\t\t\t\t</ul>\n\t\t\t))}\n\t\t</>\n\t);\n}\n","import { formatRelativeTime, t } from \"@helpway/widget-core\";\nimport type { ContentTabDisplay } from \"@helpway/types\";\nimport { useCallback, useRef, useState } from \"react\";\nimport type { ContentEntryItem } from \"../../hooks/use-content-tab\";\n\n/**\n * Content entry list — Intercom-style clean card layout.\n * Search bar at top, card entries with title + description + chevron.\n */\nexport function ContentListView({\n\tentries,\n\tisLoading,\n\thasMore,\n\tonSelect,\n\tonLoadMore,\n\tonSearch,\n\tsearchPlaceholder,\n\tdisplay,\n}: {\n\tentries: ContentEntryItem[];\n\tisLoading: boolean;\n\thasMore: boolean;\n\tonSelect: (slug: string) => void;\n\tonLoadMore: () => void;\n\tonSearch?: (query: string) => void;\n\tsearchPlaceholder?: string;\n\tdisplay?: ContentTabDisplay;\n}) {\n\tconst [searchText, setSearchText] = useState(\"\");\n\tconst debounceRef = useRef<ReturnType<typeof setTimeout>>(undefined);\n\n\tconst handleSearch = useCallback(\n\t\t(value: string) => {\n\t\t\tsetSearchText(value);\n\t\t\tif (!onSearch) return;\n\t\t\tclearTimeout(debounceRef.current);\n\t\t\tdebounceRef.current = setTimeout(() => {\n\t\t\t\tonSearch(value.trim());\n\t\t\t}, 300);\n\t\t},\n\t\t[onSearch],\n\t);\n\n\treturn (\n\t\t<div className=\"hw-content-list\">\n\t\t\t{/* Search */}\n\t\t\t{onSearch && (\n\t\t\t\t<div className=\"hw-content-search\">\n\t\t\t\t\t<div className=\"hw-content-search-box\">\n\t\t\t\t\t\t<svg className=\"hw-content-search-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n\t\t\t\t\t\t\t<circle cx=\"11\" cy=\"11\" r=\"8\" />\n\t\t\t\t\t\t\t<line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\" />\n\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\tclassName=\"hw-content-search-input\"\n\t\t\t\t\t\t\tplaceholder={searchPlaceholder ?? t(\"widget.search\")}\n\t\t\t\t\t\t\tvalue={searchText}\n\t\t\t\t\t\t\tonChange={(e) => handleSearch(e.target.value)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Loading */}\n\t\t\t{isLoading && entries.length === 0 && (\n\t\t\t\t<div className=\"hw-skeleton-content\">\n\t\t\t\t\t{[1, 2, 3].map((i) => (\n\t\t\t\t\t\t<div key={i} className=\"hw-skeleton-content-item\">\n\t\t\t\t\t\t\t<div className=\"hw-skeleton hw-skeleton-line\" style={{ width: \"70%\", height: 14 }} />\n\t\t\t\t\t\t\t<div className=\"hw-skeleton hw-skeleton-line\" style={{ width: \"90%\", height: 12 }} />\n\t\t\t\t\t\t\t<div className=\"hw-skeleton hw-skeleton-line\" style={{ width: \"40%\", height: 10 }} />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Empty */}\n\t\t\t{!isLoading && entries.length === 0 && (\n\t\t\t\t<div className=\"hw-content-empty\">\n\t\t\t\t\t<div className=\"hw-content-empty-title\">\n\t\t\t\t\t\t{searchText ? t(\"widget.no_results\") : t(\"widget.nothing_yet\")}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"hw-content-empty-desc\">\n\t\t\t\t\t\t{searchText ? t(\"widget.try_different\") : t(\"widget.check_back\")}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Entries */}\n\t\t\t{entries.length > 0 && (\n\t\t\t\t<div className=\"hw-content-entries\">\n\t\t\t\t\t{entries.map((entry) => (\n\t\t\t\t\t\t<ContentEntryCard key={entry.slug} entry={entry} onSelect={onSelect} display={display} />\n\t\t\t\t\t))}\n\t\t\t\t\t{hasMore && (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tclassName=\"hw-content-load-more\"\n\t\t\t\t\t\t\tonClick={onLoadMore}\n\t\t\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{isLoading ? t(\"widget.loading\") : t(\"widget.load_more\")}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\n// ── Entry Card — Intercom-style ──────────────────────────\n\nfunction truncateText(text: string | null, maxLen = 80): string {\n\tif (!text) return \"\";\n\tconst clean = text.replace(/[#*_`>\\[\\]!()-]/g, \"\").trim();\n\treturn clean.length > maxLen ? `${clean.slice(0, maxLen)}...` : clean;\n}\n\nfunction ContentEntryCard({\n\tentry,\n\tonSelect,\n\tdisplay,\n}: {\n\tentry: ContentEntryItem;\n\tonSelect: (slug: string) => void;\n\tdisplay?: ContentTabDisplay;\n}) {\n\tconst { customFields } = entry;\n\n\t// Use display mapping if configured, otherwise auto-detect from common field names\n\tconst badge = display?.badgeField\n\t\t? customFields[display.badgeField] ?? null\n\t\t: customFields.version ?? customFields.priority ?? customFields.type ?? null;\n\n\tconst subtitleValue = display?.subtitleField\n\t\t? (display.subtitleField === \"body\" ? entry.body : customFields[display.subtitleField]) ?? null\n\t\t: customFields.excerpt ?? customFields.summary ?? customFields.description ?? null;\n\n\tconst preview = subtitleValue ? truncateText(subtitleValue) : truncateText(entry.body);\n\n\treturn (\n\t\t<button type=\"button\" className=\"hw-content-entry\" onClick={() => onSelect(entry.slug)}>\n\t\t\t<div className=\"hw-content-entry-main\">\n\t\t\t\t<div className=\"hw-content-entry-text\">\n\t\t\t\t\t<span className=\"hw-content-entry-title\">{entry.title}</span>\n\t\t\t\t\t{preview && (\n\t\t\t\t\t\t<span className=\"hw-content-entry-desc\">{preview}</span>\n\t\t\t\t\t)}\n\t\t\t\t\t{(badge || entry.publishedAt) && (\n\t\t\t\t\t\t<div className=\"hw-content-entry-meta\">\n\t\t\t\t\t\t\t{badge && <span className=\"hw-content-entry-badge\">{badge}</span>}\n\t\t\t\t\t\t\t{entry.publishedAt && (\n\t\t\t\t\t\t\t\t<span className=\"hw-content-entry-date\">{formatRelativeTime(entry.publishedAt)}</span>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t<svg className=\"hw-content-entry-chevron\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n\t\t\t\t\t<polyline points=\"9 18 15 12 9 6\" />\n\t\t\t\t</svg>\n\t\t\t</div>\n\t\t</button>\n\t);\n}\n","import type { WidgetContentTab } from \"@helpway/widget-core\";\nimport { t } from \"@helpway/widget-core\";\nimport { useEffect, useRef } from \"react\";\nimport { useGroupedContentTab } from \"../../hooks/use-grouped-content-tab\";\nimport type { ContentEntryItem } from \"../../hooks/use-content-tab\";\nimport { ContentDetailView } from \"./content-detail-view\";\nimport { ContentListView } from \"./content-list-view\";\n\n/**\n * Grouped content tab — category → items → detail drill-down.\n *\n * Three views managed by parent (DefaultWidget):\n * - subView = null → show categories\n * - subView = \"content-category\" → show items for activeCategory\n * - subView = \"content-detail\" → show item detail\n */\nexport function GroupedContentTabView({\n\ttab,\n\tsubView,\n\tdetailSlug,\n\tonSelectCategory,\n\tonSelectEntry,\n}: {\n\ttab: WidgetContentTab;\n\tsubView: string | null;\n\tdetailSlug: string | null;\n\tonSelectCategory: (category: ContentEntryItem) => void;\n\tonSelectEntry: (slug: string) => void;\n}) {\n\tconst {\n\t\tcategories,\n\t\tisCategoriesLoading,\n\t\titems,\n\t\tisItemsLoading,\n\t\titemsHasMore,\n\t\tactiveCategory,\n\t\tdetail,\n\t\tisLoadingDetail,\n\t\tinitFetch,\n\t\tselectCategory,\n\t\tsearchCategories,\n\t\tloadMoreItems,\n\t\tsearchItems,\n\t\tfetchDetail,\n\t\tclearCategory,\n\t} = useGroupedContentTab(tab.id);\n\n\t// Init fetch categories on mount\n\tuseEffect(() => {\n\t\tinitFetch();\n\t}, [initFetch]);\n\n\t// Fetch detail when slug changes\n\tuseEffect(() => {\n\t\tif (detailSlug && subView === \"content-detail\") {\n\t\t\tfetchDetail(detailSlug);\n\t\t}\n\t}, [detailSlug, subView, fetchDetail]);\n\n\t// Clean up hook state when navigating back to category list\n\tconst prevSubView = useRef(subView);\n\tuseEffect(() => {\n\t\tif (prevSubView.current === \"content-category\" && subView === null) {\n\t\t\tclearCategory();\n\t\t}\n\t\tprevSubView.current = subView;\n\t}, [subView, clearCategory]);\n\n\t// ── Detail view ──\n\tif (subView === \"content-detail\" && detailSlug) {\n\t\treturn <ContentDetailView entry={detail} isLoading={isLoadingDetail} />;\n\t}\n\n\t// ── Items list (within a category) ──\n\tif (subView === \"content-category\" && activeCategory) {\n\t\treturn (\n\t\t\t<ContentListView\n\t\t\t\tentries={items}\n\t\t\t\tisLoading={isItemsLoading}\n\t\t\t\thasMore={itemsHasMore}\n\t\t\t\tonSelect={onSelectEntry}\n\t\t\t\tonLoadMore={loadMoreItems}\n\t\t\t\tonSearch={searchItems}\n\t\t\t\tsearchPlaceholder={t(\"widget.search\")}\n\t\t\t\tdisplay={tab.display}\n\t\t\t/>\n\t\t);\n\t}\n\n\t// ── Categories list (with search) ──\n\treturn (\n\t\t<ContentListView\n\t\t\tentries={categories}\n\t\t\tisLoading={isCategoriesLoading}\n\t\t\thasMore={false}\n\t\t\tonSelect={(slug) => {\n\t\t\t\tconst cat = categories.find((c) => c.slug === slug);\n\t\t\t\tif (cat) {\n\t\t\t\t\tselectCategory(cat);\n\t\t\t\t\tonSelectCategory(cat);\n\t\t\t\t}\n\t\t\t}}\n\t\t\tonLoadMore={() => {}}\n\t\t\tonSearch={searchCategories}\n\t\t\tsearchPlaceholder={t(\"widget.search\")}\n\t\t/>\n\t);\n}\n","import type { WidgetContentTab } from \"@helpway/widget-core\";\nimport { CONTENT_CACHE_TTL, getLocale } from \"@helpway/widget-core\";\nimport { useCallback, useRef, useState } from \"react\";\nimport { useWidgetContext, useWidgetStore } from \"../provider\";\nimport type { ContentEntryItem, ContentEntryDetail } from \"./use-content-tab\";\n\nconst EMPTY_TABS: WidgetContentTab[] = [];\n\n// ── Cache key helpers ──\n\nfunction categoriesKey(tabId: string, lang: string) {\n\treturn `grouped:${tabId}:${lang}:categories`;\n}\n\nfunction itemsKey(tabId: string, lang: string, groupSlug: string) {\n\treturn `grouped:${tabId}:${lang}:items:${groupSlug}`;\n}\n\nfunction detailKey(tabId: string, lang: string, slug: string) {\n\treturn `grouped:${tabId}:${lang}:detail:${slug}`;\n}\n\ninterface CachedItems {\n\titems: ContentEntryItem[];\n\thasMore: boolean;\n\tpage: number;\n}\n\nfunction readCache<T>(cache: Map<string, { data: unknown; ts: number }>, key: string): T | null {\n\tconst entry = cache.get(key);\n\tif (!entry) return null;\n\tif (Date.now() - entry.ts > CONTENT_CACHE_TTL) return null;\n\treturn entry.data as T;\n}\n\n/**\n * Hook for grouped content tabs (category → items drill-down).\n * Content is cached in the Zustand store so tab switches don't re-fetch.\n */\nexport function useGroupedContentTab(tabId: string) {\n\tconst { client, store } = useWidgetContext();\n\tconst contentTabs = useWidgetStore((s) => s.agentConfig?.contentTabs) ?? EMPTY_TABS;\n\tconst tab = contentTabs.find((t) => t.id === tabId) ?? null;\n\n\tconst lang = getLocale();\n\tconst cache = store.getState().contentCache;\n\n\t// ── Categories (top level) ──\n\tconst cachedCategories = readCache<ContentEntryItem[]>(cache, categoriesKey(tabId, lang));\n\tconst [categories, setCategories] = useState<ContentEntryItem[]>(cachedCategories ?? []);\n\tconst [isCategoriesLoading, setIsCategoriesLoading] = useState(false);\n\n\t// ── Items (within a category) ──\n\tconst [items, setItems] = useState<ContentEntryItem[]>([]);\n\tconst [isItemsLoading, setIsItemsLoading] = useState(false);\n\tconst [itemsHasMore, setItemsHasMore] = useState(false);\n\tconst itemsPageRef = useRef(1);\n\n\t// ── Detail (single item) ──\n\tconst [detail, setDetail] = useState<ContentEntryDetail | null>(null);\n\tconst [isLoadingDetail, setIsLoadingDetail] = useState(false);\n\n\t// ── Active category ──\n\tconst [activeCategory, setActiveCategory] = useState<ContentEntryItem | null>(null);\n\n\t// ── All categories (unfiltered, for client-side search) ──\n\tconst allCategoriesRef = useRef<ContentEntryItem[]>(cachedCategories ?? []);\n\n\t// ── Fetch categories ──\n\tconst fetchCategories = useCallback(async () => {\n\t\tif (!tab) return;\n\t\tsetIsCategoriesLoading(true);\n\t\ttry {\n\t\t\tconst result = await client.widget.getContent.query({\n\t\t\t\ttabId,\n\t\t\t\tpage: 1,\n\t\t\t\tlimit: 50,\n\t\t\t\tlanguage: getLocale(),\n\t\t\t});\n\t\t\tif (result.items) {\n\t\t\t\tallCategoriesRef.current = result.items;\n\t\t\t\tsetCategories(result.items);\n\t\t\t\tstore.getState().setContentCache(categoriesKey(tabId, getLocale()), result.items);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tconsole.error(\"[useGroupedContentTab] categories error:\", err);\n\t\t} finally {\n\t\t\tsetIsCategoriesLoading(false);\n\t\t}\n\t}, [client, tabId, tab, store]);\n\n\t// Init — only fetch if cache was empty\n\tconst initFetch = useCallback(() => {\n\t\tif (tab && categories.length === 0) {\n\t\t\tfetchCategories();\n\t\t}\n\t}, [fetchCategories, tab, categories.length]);\n\n\t// ── Fetch items for a category ──\n\tconst fetchItems = useCallback(\n\t\tasync (opts?: { page?: number; search?: string; reset?: boolean; groupSlug?: string }) => {\n\t\t\tif (!tab?.itemsModelSlug) return;\n\t\t\tconst p = opts?.page ?? 1;\n\t\t\tconst reset = opts?.reset ?? p === 1;\n\n\t\t\tsetIsItemsLoading(true);\n\t\t\ttry {\n\t\t\t\tconst result = await client.widget.getContent.query({\n\t\t\t\t\ttabId,\n\t\t\t\t\tpage: p,\n\t\t\t\t\tlimit: 10,\n\t\t\t\t\tsearch: opts?.search,\n\t\t\t\t\tgroupSlug: opts?.groupSlug,\n\t\t\t\t\titemsModel: tab.itemsModelSlug,\n\t\t\t\t\tlanguage: getLocale(),\n\t\t\t\t});\n\t\t\t\tif (result.items) {\n\t\t\t\t\tsetItems((prev) => {\n\t\t\t\t\t\tconst nextItems = reset ? result.items! : [...prev, ...result.items!];\n\t\t\t\t\t\tif (!opts?.search && opts?.groupSlug) {\n\t\t\t\t\t\t\tstore.getState().setContentCache(\n\t\t\t\t\t\t\t\titemsKey(tabId, getLocale(), opts.groupSlug),\n\t\t\t\t\t\t\t\t{ items: nextItems, hasMore: result.hasMore, page: p } satisfies CachedItems,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn nextItems;\n\t\t\t\t\t});\n\t\t\t\t\tsetItemsHasMore(result.hasMore);\n\t\t\t\t\titemsPageRef.current = p;\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"[useGroupedContentTab] items error:\", err);\n\t\t\t} finally {\n\t\t\t\tsetIsItemsLoading(false);\n\t\t\t}\n\t\t},\n\t\t[client, tabId, tab, store],\n\t);\n\n\t// ── Select a category → load items from cache or fetch ──\n\tconst selectCategory = useCallback(\n\t\t(category: ContentEntryItem) => {\n\t\t\tsetActiveCategory(category);\n\t\t\tsetDetail(null);\n\n\t\t\tconst cached = readCache<CachedItems>(\n\t\t\t\tstore.getState().contentCache,\n\t\t\t\titemsKey(tabId, getLocale(), category.slug),\n\t\t\t);\n\t\t\tif (cached) {\n\t\t\t\tsetItems(cached.items);\n\t\t\t\tsetItemsHasMore(cached.hasMore);\n\t\t\t\titemsPageRef.current = cached.page;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsetItems([]);\n\t\t\tfetchItems({ page: 1, reset: true, groupSlug: category.slug });\n\t\t},\n\t\t[fetchItems, store, tabId],\n\t);\n\n\t// ── Load more items ──\n\tconst loadMoreItems = useCallback(() => {\n\t\tif (!itemsHasMore || isItemsLoading || !activeCategory) return;\n\t\tfetchItems({\n\t\t\tpage: itemsPageRef.current + 1,\n\t\t\tgroupSlug: activeCategory.slug,\n\t\t});\n\t}, [fetchItems, itemsHasMore, isItemsLoading, activeCategory]);\n\n\t// ── Search items (cross-category) ──\n\tconst searchItems = useCallback(\n\t\t(query: string) => {\n\t\t\tsetItems([]);\n\t\t\tfetchItems({\n\t\t\t\tpage: 1,\n\t\t\t\treset: true,\n\t\t\t\tsearch: query || undefined,\n\t\t\t\tgroupSlug: query ? undefined : activeCategory?.slug,\n\t\t\t});\n\t\t},\n\t\t[fetchItems, activeCategory],\n\t);\n\n\t// ── Fetch item detail ──\n\tconst fetchDetail = useCallback(\n\t\tasync (slug: string) => {\n\t\t\tif (!tab?.itemsModelSlug) return;\n\n\t\t\tconst cached = readCache<ContentEntryDetail>(\n\t\t\t\tstore.getState().contentCache,\n\t\t\t\tdetailKey(tabId, getLocale(), slug),\n\t\t\t);\n\t\t\tif (cached) {\n\t\t\t\tsetDetail(cached);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsetIsLoadingDetail(true);\n\t\t\ttry {\n\t\t\t\tconst result = await client.widget.getContent.query({\n\t\t\t\t\ttabId,\n\t\t\t\t\tslug,\n\t\t\t\t\titemsModel: tab.itemsModelSlug,\n\t\t\t\t\tlanguage: getLocale(),\n\t\t\t\t});\n\t\t\t\tif (result.entry) {\n\t\t\t\t\tconst entry = result.entry as ContentEntryDetail;\n\t\t\t\t\tsetDetail(entry);\n\t\t\t\t\tstore.getState().setContentCache(\n\t\t\t\t\t\tdetailKey(tabId, getLocale(), slug),\n\t\t\t\t\t\tentry,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"[useGroupedContentTab] detail error:\", err);\n\t\t\t} finally {\n\t\t\t\tsetIsLoadingDetail(false);\n\t\t\t}\n\t\t},\n\t\t[client, tabId, tab, store],\n\t);\n\n\t// ── Search categories (client-side, instant) ──\n\tconst searchCategories = useCallback(\n\t\t(query: string) => {\n\t\t\tif (!query.trim()) {\n\t\t\t\tsetCategories(allCategoriesRef.current);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst q = query.toLowerCase();\n\t\t\tsetCategories(\n\t\t\t\tallCategoriesRef.current.filter((cat) =>\n\t\t\t\t\tcat.title.toLowerCase().includes(q) ||\n\t\t\t\t\t(cat.customFields.description ?? \"\").toLowerCase().includes(q),\n\t\t\t\t),\n\t\t\t);\n\t\t},\n\t\t[],\n\t);\n\n\tconst clearDetail = useCallback(() => {\n\t\tsetDetail(null);\n\t}, []);\n\n\tconst clearCategory = useCallback(() => {\n\t\tsetActiveCategory(null);\n\t\tsetItems([]);\n\t\tsetDetail(null);\n\t}, []);\n\n\treturn {\n\t\ttab,\n\t\tcategories,\n\t\tisCategoriesLoading,\n\t\titems,\n\t\tisItemsLoading,\n\t\titemsHasMore,\n\t\tactiveCategory,\n\t\tdetail,\n\t\tisLoadingDetail,\n\t\tinitFetch,\n\t\tselectCategory,\n\t\tsearchCategories,\n\t\tloadMoreItems,\n\t\tsearchItems,\n\t\tfetchDetail,\n\t\tclearDetail,\n\t\tclearCategory,\n\t};\n}\n","import {\n\tBookIcon,\n\tHelpCircleIcon,\n\tLightbulbIcon,\n\tMegaphoneIcon,\n\tNewspaperIcon,\n\tStarIcon,\n} from \"../icons\";\n\n/**\n * Maps icon string keys to Central Icons components.\n * Dashboard lets users pick from this set when configuring a content tab.\n * Falls back to BookIcon for unknown keys.\n */\nconst ICON_MAP: Record<string, React.FC> = {\n\tbook: BookIcon,\n\tmegaphone: MegaphoneIcon,\n\tlightbulb: LightbulbIcon,\n\t\"help-circle\": HelpCircleIcon,\n\tnewspaper: NewspaperIcon,\n\tstar: StarIcon,\n};\n\nexport function ContentTabIconComponent({ icon }: { icon: string }) {\n\tconst Icon = ICON_MAP[icon] ?? BookIcon;\n\treturn <Icon />;\n}\n","\"use client\";\n\nimport { t } from \"@helpway/widget-core\";\nimport type { MouseEvent, ReactNode } from \"react\";\nimport { useState } from \"react\";\nimport { useWidgetStore } from \"../provider\";\nimport { XIcon } from \"./icons\";\nimport { stripMarkdown } from \"./strip-markdown\";\n\n/** Placement of the announcement stack — mirrors `MessagePreviewPlacement`. */\nexport type AnnouncementPreviewsPlacement = \"launcher\" | \"anchored\";\n\n/** Shape of a single announcement entry as it lives in the widget store. */\nexport interface AnnouncementPreviewEntry {\n\ttitle: string;\n\tbody: string | null;\n\tslug: string;\n\ttabId: string;\n\tbadge: string | null;\n}\n\nexport interface AnnouncementPreviewsProps {\n\t/** Called when the visitor taps an announcement card. Receives the\n\t * entry's slug + the parent tab id. The consumer decides what to\n\t * do — at minimum `setOpen(true)`, optionally deep-link into the\n\t * matching content tab + detail. */\n\tonOpen: (slug: string, tabId: string) => void;\n\t/** The avatar node shown in each card's header. Injected so the\n\t * component is decoupled from avatar resolution; pass\n\t * `<WidgetLogo />` for the SDK default. */\n\tavatar: ReactNode;\n\t/**\n\t * Outer positioning mode. `\"launcher\"` (default) keeps the stack\n\t * pinned above the floating bubble; `\"anchored\"` drops that and\n\t * lets the consumer's positioned wrapper place the stack — and\n\t * each card stretches to the wrapper width instead of the launcher\n\t * 300px (via the same `.hw-preview--anchored` modifier the\n\t * message preview uses).\n\t */\n\tplacement?: AnnouncementPreviewsPlacement;\n\t/**\n\t * Optional caption rendered as a separated footer beneath each\n\t * card (e.g. a \"via X\" provenance line). Omitted on the launcher\n\t * so its visual stays byte-identical to the original.\n\t */\n\tfooter?: ReactNode;\n}\n\n/**\n * `<AnnouncementPreviews>` — proactive \"new content\" cards shown when\n * the widget panel is closed and the visitor hasn't seen the latest\n * entries from a \"Promote new content\" tab yet. Stacks multiple\n * entries vertically.\n *\n * Extracted from the default widget so `hideLauncher` integrations can\n * surface the *exact same* cards next to their own UI instead of the\n * floating launcher. Visual/markup is byte-identical to the launcher\n * version — only the outer positioning is parameterised via\n * `placement`. Announcements never auto-dismiss (visitors need time to\n * read); they're cleared by tapping the card or the ✕.\n *\n * Must be rendered inside `<SupportProvider>`.\n */\nexport function AnnouncementPreviews({\n\tonOpen,\n\tavatar,\n\tplacement = \"launcher\",\n\tfooter,\n}: AnnouncementPreviewsProps) {\n\tconst previews = useWidgetStore((s) => s.announcementPreviews);\n\tconst dismissPreview = useWidgetStore((s) => s.dismissAnnouncementPreview);\n\tconst agentName = useWidgetStore((s) => s.agentConfig?.name) ?? \"Support\";\n\n\tif (previews.length === 0) return null;\n\n\tconst stackPlacementClass =\n\t\tplacement === \"anchored\" ? \"hw-preview-stack--anchored \" : \"\";\n\n\treturn (\n\t\t<div className={`hw-preview-stack ${stackPlacementClass}`.trim()}>\n\t\t\t{previews.map((preview) => (\n\t\t\t\t<AnnouncementPreviewItem\n\t\t\t\t\tkey={preview.slug}\n\t\t\t\t\tpreview={preview}\n\t\t\t\t\tagentName={agentName}\n\t\t\t\t\tavatar={avatar}\n\t\t\t\t\tplacement={placement}\n\t\t\t\t\tfooter={footer}\n\t\t\t\t\tonOpen={onOpen}\n\t\t\t\t\tonDismiss={(slug) => dismissPreview(slug)}\n\t\t\t\t/>\n\t\t\t))}\n\t\t</div>\n\t);\n}\n\nfunction AnnouncementPreviewItem({\n\tpreview,\n\tagentName,\n\tavatar,\n\tplacement,\n\tfooter,\n\tonOpen,\n\tonDismiss,\n}: {\n\tpreview: AnnouncementPreviewEntry;\n\tagentName: string;\n\tavatar: ReactNode;\n\tplacement: AnnouncementPreviewsPlacement;\n\tfooter?: ReactNode;\n\tonOpen: (slug: string, tabId: string) => void;\n\tonDismiss: (slug: string) => void;\n}) {\n\tconst [closing, setClosing] = useState(false);\n\n\tconst handleClose = (e: MouseEvent) => {\n\t\te.stopPropagation();\n\t\tsetClosing(true);\n\t\tsetTimeout(() => {\n\t\t\tonDismiss(preview.slug);\n\t\t\tsetClosing(false);\n\t\t}, 200);\n\t};\n\n\tconst placementClass = placement === \"anchored\" ? \"hw-preview--anchored \" : \"\";\n\n\treturn (\n\t\t<div\n\t\t\tclassName={`hw-preview hw-preview--announcement ${placementClass}${closing ? \"hw-preview--closing\" : \"\"}`.trim()}\n\t\t\tonClick={() => onOpen(preview.slug, preview.tabId)}\n\t\t\trole=\"button\"\n\t\t\ttabIndex={0}\n\t\t>\n\t\t\t<div className=\"hw-preview-header\">\n\t\t\t\t<div className=\"hw-preview-avatar\">{avatar}</div>\n\t\t\t\t<div className=\"hw-preview-name\">{agentName}</div>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"hw-preview-close\"\n\t\t\t\t\tonClick={handleClose}\n\t\t\t\t\taria-label={t(\"widget.aria_dismiss\")}\n\t\t\t\t>\n\t\t\t\t\t<XIcon size={20} />\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t\t<div className=\"hw-preview-body hw-preview-body--title\">{preview.title}</div>\n\t\t\t{preview.body &&\n\t\t\t\t(() => {\n\t\t\t\t\tconst clean = stripMarkdown(preview.body);\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div className=\"hw-preview-body hw-preview-body--desc\">\n\t\t\t\t\t\t\t{clean.length > 120 ? `${clean.slice(0, 120)}…` : clean}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t})()}\n\t\t\t{preview.badge && (\n\t\t\t\t<div className=\"hw-announcement-badge\">{preview.badge}</div>\n\t\t\t)}\n\t\t\t{footer != null && footer !== false && (\n\t\t\t\t<div className=\"hw-preview-footer\">{footer}</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","/**\n * Strip the most common Markdown affordances so a body excerpt reads as\n * plain text inside a preview bubble. Intentionally minimal — covers\n * headings, bold/italic, lists, links, inline code, and newlines. Not\n * a full Markdown renderer; meant for short truncated descriptions\n * where the rendered styling would clash with the surrounding chrome.\n */\nexport function stripMarkdown(text: string): string {\n\treturn text\n\t\t.replace(/^#{1,6}\\s+/gm, \"\")\n\t\t.replace(/\\*\\*(.+?)\\*\\*/g, \"$1\")\n\t\t.replace(/\\*(.+?)\\*/g, \"$1\")\n\t\t.replace(/^[-*+]\\s+/gm, \"\")\n\t\t.replace(/\\[(.+?)\\]\\(.+?\\)/g, \"$1\")\n\t\t.replace(/`(.+?)`/g, \"$1\")\n\t\t.replace(/\\n{2,}/g, \" \")\n\t\t.replace(/\\n/g, \" \")\n\t\t.trim();\n}\n","import type { LinkPreviewPart, TimelineItemMetadata, TimelineItemPart } from \"@helpway/types\";\nimport { t } from \"@helpway/widget-core\";\nimport { useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { handleCodeBlockClick, linkifyText, renderMarkdown } from \"./content/simple-markdown\";\n\ninterface MessageBubbleProps {\n\ttext: string;\n\tsender: \"visitor\" | \"team\" | \"ai\";\n\tsenderName?: string;\n\t/** Name the conversation header is showing; a sender matching it stays unlabelled. */\n\theaderName?: string;\n\tparts?: TimelineItemPart[] | null;\n\ttimestamp?: string;\n\t/**\n\t * Whether this message closes a run from the same sender — the point where\n\t * the author's name belongs. Kept separate from `timestamp` so a clock label\n\t * that would only repeat the one above it can be dropped without taking the\n\t * signature with it.\n\t */\n\tshowAuthor?: boolean;\n\t/** Variant payload for interactive messages (quick replies, …). */\n\tmetadata?: TimelineItemMetadata | null;\n\t/** Called when the visitor taps a quick-reply option. */\n\tonQuickReplyTap?: (optionId: string, stepId: string) => void;\n}\n\n/** Single message bubble — Intercom-style, renders text + image/file parts */\nexport function MessageBubble({\n\ttext,\n\tsender,\n\tsenderName,\n\theaderName,\n\tparts,\n\ttimestamp,\n\tshowAuthor,\n\tmetadata,\n\tonQuickReplyTap,\n}: MessageBubbleProps) {\n\tconst senderClass = `hw-msg--${sender}`;\n\tconst bubbleRef = useRef<HTMLDivElement>(null);\n\n\tconst imageParts =\n\t\tparts?.filter((p): p is Extract<TimelineItemPart, { type: \"image\" }> => p.type === \"image\") ??\n\t\t[];\n\tconst fileParts =\n\t\tparts?.filter((p): p is Extract<TimelineItemPart, { type: \"file\" }> => p.type === \"file\") ?? [];\n\tconst linkPreviews =\n\t\tparts?.filter(\n\t\t\t(p): p is Extract<TimelineItemPart, { type: \"link-preview\" }> => p.type === \"link-preview\",\n\t\t) ?? [];\n\t// Where the answer came from. Shown as a short numbered list under the\n\t// message rather than a footnote block, so the visitor can check the\n\t// claim without leaving the thread.\n\tconst sources =\n\t\tparts?.filter(\n\t\t\t(p): p is Extract<TimelineItemPart, { type: \"source\" }> => p.type === \"source\",\n\t\t) ?? [];\n\tconst hasText = text.length > 0;\n\n\tuseEffect(() => {\n\t\tconst bubble = bubbleRef.current;\n\t\tif (!bubble || (sender !== \"ai\" && sender !== \"team\")) return;\n\t\tconst handleClick = (event: Event) => {\n\t\t\thandleCodeBlockClick(event, bubble);\n\t\t};\n\t\tbubble.addEventListener(\"click\", handleClick);\n\t\treturn () => {\n\t\t\tbubble.removeEventListener(\"click\", handleClick);\n\t\t};\n\t}, [sender]);\n\n\t/* Only name a sender the header is not already naming. Otherwise every\n\t bubble repeats the person whose name sits at the top of the panel. */\n\tconst nameToShow = senderName ?? t(\"widget.support\");\n\tconst namesSomeoneElse = !!headerName && nameToShow !== headerName;\n\n\treturn (\n\t\t<div className={`hw-msg ${senderClass}`}>\n\t\t\t<div className=\"hw-msg-body\">\n\t\t\t\t{sender === \"team\" && namesSomeoneElse && (\n\t\t\t\t\t<div className=\"hw-msg-sender\">{nameToShow}</div>\n\t\t\t\t)}\n\n\t\t\t\t{/* Image attachments */}\n\t\t\t\t{imageParts.length > 0 && (\n\t\t\t\t\t<div className=\"hw-msg-images\">\n\t\t\t\t\t\t{imageParts.map((img, i) => (\n\t\t\t\t\t\t\t<PreviewableThumbnail key={i} src={img.url} />\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{/* Text bubble.\n\t\t\t\t - AI + team messages → renderMarkdown (team composer uses Tiptap → markdown output).\n\t\t\t\t - Visitor messages → linkifyText (widget composer is plain text).\n\t\t\t\t renderMarkdown escapes HTML entities first (&, <, >), so raw HTML cannot be injected.\n\t\t\t\t See packages/widget-react/src/themed/content/simple-markdown.ts for the safety guarantee. */}\n\t\t\t\t{hasText && (\n\t\t\t\t\t<div className=\"hw-msg-bubble\" ref={bubbleRef}>\n\t\t\t\t\t\t{sender === \"ai\" || sender === \"team\" ? (\n\t\t\t\t\t\t\t<span dangerouslySetInnerHTML={{ __html: renderMarkdown(text) }} />\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<span dangerouslySetInnerHTML={{ __html: linkifyText(text) }} />\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{/* File attachments */}\n\t\t\t\t{fileParts.length > 0 && (\n\t\t\t\t\t<div className=\"hw-msg-files\">\n\t\t\t\t\t\t{fileParts.map((file, i) => (\n\t\t\t\t\t\t\t<FileCard key={i} file={file} />\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{/* Link preview cards */}\n\t\t\t\t{linkPreviews.length > 0 && (\n\t\t\t\t\t<div className=\"hw-msg-links\">\n\t\t\t\t\t\t{linkPreviews.map((lp, i) => (\n\t\t\t\t\t\t\t<LinkPreviewCard key={i} preview={lp} />\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{/* Sources for the answer above */}\n\t\t\t\t{sources.length > 0 && (\n\t\t\t\t\t<div className=\"hw-sources\">\n\t\t\t\t\t\t{sources.map((src, i) =>\n\t\t\t\t\t\t\tsrc.sourceUrl ? (\n\t\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\t\tkey={src.knowledgeId}\n\t\t\t\t\t\t\t\t\thref={src.sourceUrl}\n\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\t\t\tclassName=\"hw-source\"\n\t\t\t\t\t\t\t\t\tonClick={(e) => e.stopPropagation()}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<span className=\"hw-source-n\">{i + 1}</span>\n\t\t\t\t\t\t\t\t\t<span className=\"hw-source-title\">{src.title}</span>\n\t\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<div key={src.knowledgeId} className=\"hw-source\">\n\t\t\t\t\t\t\t\t\t<span className=\"hw-source-n\">{i + 1}</span>\n\t\t\t\t\t\t\t\t\t<span className=\"hw-source-title\">{src.title}</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{/* Quick reply buttons — workflow is paused awaiting visitor input.\n\t\t\t\t Disabled when metadata.cancelled is set (visitor typed instead). */}\n\t\t\t\t{metadata?.kind === \"quick_replies\" && (\n\t\t\t\t\t<QuickReplyButtons metadata={metadata} onTap={onQuickReplyTap} />\n\t\t\t\t)}\n\n\t\t\t\t{/* Author and clock are independent now: the row survives a suppressed\n\t\t\t\t timestamp, so the agent keeps signing its answer, and the middot\n\t\t\t\t only appears when there are two things to separate. */}\n\t\t\t\t{(() => {\n\t\t\t\t\tconst withAuthor =\n\t\t\t\t\t\t(showAuthor ?? !!timestamp) && sender !== \"visitor\" && namesSomeoneElse;\n\t\t\t\t\tif (!withAuthor && !timestamp) return null;\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div className=\"hw-msg-meta\">\n\t\t\t\t\t\t\t{withAuthor && (\n\t\t\t\t\t\t\t\t<span className=\"hw-msg-author\">{nameToShow}</span>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{withAuthor && timestamp && <span className=\"hw-msg-meta-sep\">·</span>}\n\t\t\t\t\t\t\t{timestamp && <span className=\"hw-msg-time\">{timestamp}</span>}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t})()}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\n// ── Quick reply buttons (interactive workflow) ────────\n\nfunction QuickReplyButtons({\n\tmetadata,\n\tonTap,\n}: {\n\tmetadata: Extract<TimelineItemMetadata, { kind: \"quick_replies\" }>;\n\tonTap?: (optionId: string, stepId: string) => void;\n}) {\n\tconst [tappedId, setTappedId] = useState<string | null>(null);\n\tconst isLocked = metadata.cancelled || tappedId !== null;\n\n\tconst handleTap = (optionId: string) => {\n\t\tif (isLocked) return;\n\t\tsetTappedId(optionId);\n\t\tonTap?.(optionId, metadata.stepId);\n\t};\n\n\treturn (\n\t\t<div\n\t\t\tclassName=\"hw-quick-replies\"\n\t\t\tdata-cancelled={metadata.cancelled ? \"true\" : undefined}\n\t\t>\n\t\t\t{metadata.options.map((opt) => {\n\t\t\t\tconst isTapped = tappedId === opt.id;\n\t\t\t\treturn (\n\t\t\t\t\t<button\n\t\t\t\t\t\tkey={opt.id}\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"hw-quick-reply-btn\"\n\t\t\t\t\t\tdata-tapped={isTapped ? \"true\" : undefined}\n\t\t\t\t\t\tdisabled={isLocked}\n\t\t\t\t\t\tonClick={() => handleTap(opt.id)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{opt.label}\n\t\t\t\t\t</button>\n\t\t\t\t);\n\t\t\t})}\n\t\t</div>\n\t);\n}\n\n// ── Previewable thumbnail (image) ────────────────\n\nfunction PreviewableThumbnail({ src }: { src: string }) {\n\tconst [hover, setHover] = useState(false);\n\tconst ref = useRef<HTMLAnchorElement>(null);\n\n\treturn (\n\t\t<>\n\t\t\t<a\n\t\t\t\tref={ref}\n\t\t\t\thref={src}\n\t\t\t\ttarget=\"_blank\"\n\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\tclassName=\"hw-msg-image-link\"\n\t\t\t\taria-label={t(\"widget.aria_open_image\")}\n\t\t\t\tonMouseEnter={() => setHover(true)}\n\t\t\t\tonMouseLeave={() => setHover(false)}\n\t\t\t>\n\t\t\t\t{/* alt=\"\" is right — the image is decorative inside a labelled\n\t\t\t\t link — but that leaves the anchor itself nameless, so the\n\t\t\t\t label goes on the anchor. */}\n\t\t\t\t<img src={src} alt=\"\" className=\"hw-msg-image\" loading=\"lazy\" />\n\t\t\t</a>\n\t\t\t{hover && <AnchoredPreview src={src} anchorRef={ref} href={src} />}\n\t\t</>\n\t);\n}\n\n// ── File card with hover preview for previewable types ───\n\nconst PREVIEWABLE_EXTS = new Set([\"pdf\", \"csv\", \"png\", \"jpg\", \"jpeg\", \"gif\", \"webp\", \"svg\"]);\n\nfunction FileCard({ file }: { file: Extract<TimelineItemPart, { type: \"file\" }> }) {\n\tconst [hover, setHover] = useState(false);\n\tconst ref = useRef<HTMLAnchorElement>(null);\n\tconst ext = file.fileName.split(\".\").pop()?.toLowerCase() ?? \"\";\n\tconst isPreviewable = PREVIEWABLE_EXTS.has(ext);\n\tconst isImage = file.mimeType.startsWith(\"image/\");\n\n\treturn (\n\t\t<>\n\t\t\t<a\n\t\t\t\tref={ref}\n\t\t\t\thref={file.url}\n\t\t\t\ttarget=\"_blank\"\n\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\tclassName=\"hw-msg-file\"\n\t\t\t\tonMouseEnter={() => isPreviewable && setHover(true)}\n\t\t\t\tonMouseLeave={() => setHover(false)}\n\t\t\t>\n\t\t\t\t<span className=\"hw-msg-file-icon\">\n\t\t\t\t\t<FileTypeIcon ext={ext} />\n\t\t\t\t</span>\n\t\t\t\t<span className=\"hw-msg-file-info\">\n\t\t\t\t\t<span className=\"hw-msg-file-name\">{file.fileName}</span>\n\t\t\t\t\t<span className=\"hw-msg-file-size\">{formatFileSize(file.fileSize)}</span>\n\t\t\t\t</span>\n\t\t\t</a>\n\t\t\t{hover &&\n\t\t\t\tisPreviewable &&\n\t\t\t\t(isImage ? (\n\t\t\t\t\t<AnchoredPreview src={file.url} anchorRef={ref} href={file.url} />\n\t\t\t\t) : (\n\t\t\t\t\t<AnchoredDocPreview fileName={file.fileName} ext={ext} anchorRef={ref} href={file.url} />\n\t\t\t\t))}\n\t\t</>\n\t);\n}\n\n// ── Anchored preview — card popover above the element ──\n\nexport function AnchoredPreview({\n\tsrc,\n\tanchorRef,\n\thref,\n\tonOpen,\n}: {\n\tsrc: string;\n\tanchorRef: React.RefObject<HTMLElement | null>;\n\thref?: string;\n\tonOpen?: () => void;\n}) {\n\tconst [style, setStyle] = useState<React.CSSProperties>({ opacity: 0 });\n\tconst [portalTarget, setPortalTarget] = useState<Element | DocumentFragment | null>(null);\n\n\tuseLayoutEffect(() => {\n\t\tconst anchor = anchorRef.current;\n\t\tif (!anchor) return;\n\n\t\tconst rect = anchor.getBoundingClientRect();\n\t\tconst pw = 260;\n\t\tconst gap = 8;\n\t\tconst vw = window.innerWidth;\n\n\t\tlet left = rect.left + rect.width / 2 - pw / 2;\n\t\tif (left < 8) left = 8;\n\t\tif (left + pw > vw - 8) left = vw - pw - 8;\n\n\t\tconst estimatedH = 200;\n\t\tlet top = rect.top - estimatedH - gap;\n\t\tif (top < 8) top = rect.bottom + gap;\n\n\t\tsetStyle({ left, top, width: pw, opacity: 1 });\n\t\t// Portal into the same root as the anchor so shadow-DOM widgets keep\n\t\t// --hw-* CSS token inheritance and the preview participates in the\n\t\t// widget's z-index stack. Falls back to document.body when the widget\n\t\t// isn't shadow-encapsulated.\n\t\tconst root = anchor.getRootNode();\n\t\tsetPortalTarget(root instanceof ShadowRoot ? root : document.body);\n\t}, [anchorRef]);\n\n\tconst handleClick = () => {\n\t\tif (onOpen) onOpen();\n\t\t// noopener: without it the opened page gets a handle on window.opener\n\t\t// and can navigate the host page out from under the visitor.\n\t\telse if (href) window.open(href, \"_blank\", \"noopener,noreferrer\");\n\t};\n\n\tif (!portalTarget) return null;\n\n\treturn createPortal(\n\t\t<div className=\"hw-hover-preview\" style={style} onClick={handleClick}>\n\t\t\t<img src={src} alt=\"\" className=\"hw-hover-preview-img\" />\n\t\t</div>,\n\t\tportalTarget,\n\t);\n}\n\n// ── Document preview popover (PDF, CSV) ──────────\n\nfunction AnchoredDocPreview({\n\tfileName,\n\text,\n\tanchorRef,\n\thref,\n}: {\n\tfileName: string;\n\text: string;\n\tanchorRef: React.RefObject<HTMLElement | null>;\n\thref: string;\n}) {\n\tconst [style, setStyle] = useState<React.CSSProperties>({ opacity: 0 });\n\tconst [portalTarget, setPortalTarget] = useState<Element | DocumentFragment | null>(null);\n\n\tuseLayoutEffect(() => {\n\t\tconst anchor = anchorRef.current;\n\t\tif (!anchor) return;\n\n\t\tconst rect = anchor.getBoundingClientRect();\n\t\tconst pw = 220;\n\t\tconst ph = 80;\n\t\tconst gap = 8;\n\t\tconst vw = window.innerWidth;\n\n\t\tlet left = rect.left + rect.width / 2 - pw / 2;\n\t\tif (left < 8) left = 8;\n\t\tif (left + pw > vw - 8) left = vw - pw - 8;\n\n\t\tlet top = rect.top - ph - gap;\n\t\tif (top < 8) top = rect.bottom + gap;\n\n\t\tsetStyle({ left, top, width: pw, opacity: 1 });\n\t\tconst root = anchor.getRootNode();\n\t\tsetPortalTarget(root instanceof ShadowRoot ? root : document.body);\n\t}, [anchorRef]);\n\n\tif (!portalTarget) return null;\n\n\treturn createPortal(\n\t\t<div\n\t\t\tclassName=\"hw-hover-preview hw-hover-preview--doc\"\n\t\t\tstyle={style}\n\t\t\tonClick={() => window.open(href, \"_blank\", \"noopener,noreferrer\")}\n\t\t>\n\t\t\t<div className=\"hw-hover-preview-doc-icon\">\n\t\t\t\t<FileTypeIcon ext={ext} />\n\t\t\t</div>\n\t\t\t<div className=\"hw-hover-preview-doc-info\">\n\t\t\t\t<span className=\"hw-hover-preview-doc-name\">{fileName}</span>\n\t\t\t\t<span className=\"hw-hover-preview-doc-hint\">{t(\"widget.click_to_open\")}</span>\n\t\t\t</div>\n\t\t</div>,\n\t\tportalTarget,\n\t);\n}\n\n// ── Helpers ──────────────────────────────────────\n\nfunction formatFileSize(bytes: number): string {\n\tif (bytes < 1024) return `${bytes} B`;\n\tif (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} KB`;\n\treturn `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\n// Module scope: the palette never varies, so rebuilding it per render was\n// allocation for nothing.\nconst FILE_TYPE_COLORS: Record<string, string> = {\n\tpdf: \"#ef4444\",\n\tcsv: \"#22c55e\",\n\tdoc: \"#3b82f6\",\n\tdocx: \"#3b82f6\",\n\txls: \"#22c55e\",\n\txlsx: \"#22c55e\",\n\ttxt: \"#6b7280\",\n\tzip: \"#f59e0b\",\n};\n\nfunction FileTypeIcon({ ext }: { ext: string }) {\n\tconst color = FILE_TYPE_COLORS[ext] ?? \"currentColor\";\n\n\treturn (\n\t\t<svg\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke={color}\n\t\t\tstrokeWidth={1.5}\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t>\n\t\t\t<path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\" />\n\t\t\t<polyline points=\"14 2 14 8 20 8\" />\n\t\t\t{ext === \"pdf\" && (\n\t\t\t\t<text x=\"8\" y=\"18\" fontSize=\"6\" fill={color} stroke=\"none\" fontWeight=\"700\">\n\t\t\t\t\tPDF\n\t\t\t\t</text>\n\t\t\t)}\n\t\t\t{ext === \"csv\" && (\n\t\t\t\t<text x=\"7\" y=\"18\" fontSize=\"6\" fill={color} stroke=\"none\" fontWeight=\"700\">\n\t\t\t\t\tCSV\n\t\t\t\t</text>\n\t\t\t)}\n\t\t</svg>\n\t);\n}\n\n// ── Link preview card (Intercom-style) ──────────────\n\nfunction LinkPreviewCard({ preview }: { preview: LinkPreviewPart }) {\n\tconst hostname = (() => {\n\t\ttry { return new URL(preview.url).hostname; } catch { return preview.url; }\n\t})();\n\treturn (\n\t\t<a\n\t\t\thref={preview.url}\n\t\t\ttarget=\"_blank\"\n\t\t\trel=\"noopener noreferrer\"\n\t\t\tclassName=\"hw-link-preview\"\n\t\t\tonClick={(e) => e.stopPropagation()}\n\t\t>\n\t\t\t{preview.imageUrl && (\n\t\t\t\t<img\n\t\t\t\t\tsrc={preview.imageUrl}\n\t\t\t\t\talt=\"\"\n\t\t\t\t\tclassName=\"hw-link-preview-img\"\n\t\t\t\t\tloading=\"lazy\"\n\t\t\t\t\tonError={(e) => { (e.target as HTMLImageElement).style.display = \"none\"; }}\n\t\t\t\t/>\n\t\t\t)}\n\t\t\t<div className=\"hw-link-preview-body\">\n\t\t\t\t{preview.favicon && (\n\t\t\t\t\t<img\n\t\t\t\t\t\tsrc={preview.favicon}\n\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\tclassName=\"hw-link-preview-favicon\"\n\t\t\t\t\t\twidth={16}\n\t\t\t\t\t\theight={16}\n\t\t\t\t\t\tonError={(e) => { (e.target as HTMLImageElement).style.display = \"none\"; }}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t\t{preview.title && <div className=\"hw-link-preview-title\">{preview.title}</div>}\n\t\t\t\t{preview.description && (\n\t\t\t\t\t<div className=\"hw-link-preview-desc\">{preview.description.slice(0, 120)}</div>\n\t\t\t\t)}\n\t\t\t\t<div className=\"hw-link-preview-url\">{hostname}</div>\n\t\t\t</div>\n\t\t</a>\n\t);\n}\n","import type { TimelineItem, TimelineItemMetadata, TimelineItemPart } from \"@helpway/types\";\nimport { getInitials, getLocale, t } from \"@helpway/widget-core\";\nimport React, { useEffect, useRef } from \"react\";\nimport { useWidgetClient, useWidgetStore } from \"../provider\";\nimport { renderMarkdown } from \"./content/simple-markdown\";\nimport { MessageBubble } from \"./message-bubble\";\n\n/**\n * Close dangling markdown delimiters in a partial (still-streaming) message\n * so renderMarkdown doesn't show raw syntax mid-stream: an unclosed ```fence\n * renders as literal backticks, an odd ** shows asterisks. The final message\n * replaces this bubble entirely, so the patch only ever affects transient UI.\n */\nfunction closeDanglingMarkdown(partial: string): string {\n\tlet out = partial;\n\tconst fences = (out.match(/```/g) ?? []).length;\n\tif (fences % 2 === 1) out += \"\\n```\";\n\t// Inline code / bold counted on the remainder outside fences is overkill\n\t// for a transient frame — a simple global parity check is good enough.\n\tconst bold = (out.match(/\\*\\*/g) ?? []).length;\n\tif (bold % 2 === 1) out += \"**\";\n\treturn out;\n}\n\nfunction parseParts(raw: TimelineItemPart[] | string | null): TimelineItemPart[] | null {\n\tif (!raw) return null;\n\tif (Array.isArray(raw)) return raw;\n\ttry {\n\t\tconst parsed = JSON.parse(raw);\n\t\treturn Array.isArray(parsed) ? parsed : null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Tolerate both shapes: when the API hydrates metadata it's already an\n * object; when it round-trips through CF tRPC over the wire it can land\n * as a JSON string. parseMetadata covers both.\n */\nfunction parseMetadata(\n\traw: TimelineItemMetadata | string | null | undefined,\n): TimelineItemMetadata | null {\n\tif (!raw) return null;\n\tif (typeof raw === \"object\") return raw;\n\ttry {\n\t\tconst parsed = JSON.parse(raw);\n\t\treturn parsed && typeof parsed === \"object\" ? (parsed as TimelineItemMetadata) : null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\ninterface MessageListProps {\n\titems: TimelineItem[];\n\tvisitorName?: string;\n\tisTyping?: boolean;\n\tisAiProcessing?: boolean;\n\tstreamingText?: string;\n\thasMore?: boolean;\n\tisLoadingMore?: boolean;\n\tonLoadMore?: () => void;\n\t/** Slot rendered after all messages but before typing indicators (e.g. email prompt) */\n\trenderAfterMessages?: React.ReactNode;\n}\n\n/** Timeline with date separators, typing indicator, infinite scroll, and AI processing state */\nexport function MessageList({\n\titems,\n\tvisitorName,\n\tisTyping,\n\tisAiProcessing,\n\tstreamingText,\n\thasMore,\n\tisLoadingMore,\n\tonLoadMore,\n\trenderAfterMessages,\n}: MessageListProps) {\n\tconst bottomRef = useRef<HTMLDivElement>(null);\n\tconst topRef = useRef<HTMLDivElement>(null);\n\tconst containerRef = useRef<HTMLDivElement>(null);\n\tconst prevItemCountRef = useRef(items.length);\n\tconst isInitialLoadRef = useRef(true);\n\t// Single source of truth — agent name comes from dashboard config.\n\tconst agentName = useWidgetStore((s) => s.agentConfig?.name) ?? t(\"widget.helpway_ai\");\n\t/* Who the header is currently showing. A name printed over every bubble by\n\t the same person the header already names is noise — three \"Ali Osman\n\t Delişmen\" labels stacked above three of his messages, with his name in\n\t the header too. The label earns its place only when the sender is someone\n\t else: the AI answering under a human's header, or a human answering under\n\t the AI's. Falls back to the agent name when nobody is assigned, so an\n\t unassigned thread suppresses the AI's label for the same reason. */\n\tconst headerName =\n\t\tuseWidgetStore(\n\t\t\t(s) => s.conversations.find((c) => c.id === s.activeConversationId)?.assigneeName,\n\t\t) ?? agentName;\n\tconst client = useWidgetClient();\n\tconst activeConversationId = useWidgetStore((s) => s.activeConversationId);\n\n\tconst handleQuickReplyTap = React.useCallback(\n\t\t(optionId: string, stepId: string) => {\n\t\t\tif (!activeConversationId) return;\n\t\t\t// Fire-and-forget — orchestrator runs the resume in the background\n\t\t\t// and emits new messages over WebSocket. Failure is swallowed so\n\t\t\t// the visitor never sees a tRPC error toast for this UX action.\n\t\t\tclient.widget.workflowReply\n\t\t\t\t.mutate({ conversationId: activeConversationId, stepId, optionId })\n\t\t\t\t.catch((err: unknown) => {\n\t\t\t\t\tconsole.warn(\"[helpway] workflowReply failed:\", err);\n\t\t\t\t});\n\t\t},\n\t\t[client, activeConversationId],\n\t);\n\n\t// Auto-scroll to bottom on new messages (but NOT when loading older ones at top)\n\tuseEffect(() => {\n\t\tconst prevCount = prevItemCountRef.current;\n\t\tconst newCount = items.length;\n\t\tprevItemCountRef.current = newCount;\n\n\t\t// Initial load or new messages added at the end → scroll to bottom\n\t\tif (isInitialLoadRef.current || newCount > prevCount) {\n\t\t\t// Only scroll if the new items were appended (not prepended)\n\t\t\tconst lastItem = items[items.length - 1];\n\t\t\tconst prevLastItem = prevCount > 0 ? items[prevCount - 1] : null;\n\n\t\t\tif (isInitialLoadRef.current || !prevLastItem || lastItem?.id !== prevLastItem?.id) {\n\t\t\t\tbottomRef.current?.scrollIntoView({\n\t\t\t\t\tbehavior: isInitialLoadRef.current ? \"instant\" : \"smooth\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tisInitialLoadRef.current = false;\n\t\t}\n\t}, [items]);\n\n\t// Scroll to bottom when typing/AI indicators appear\n\tuseEffect(() => {\n\t\tif (isTyping || isAiProcessing) {\n\t\t\tbottomRef.current?.scrollIntoView({ behavior: \"smooth\" });\n\t\t}\n\t}, [isTyping, isAiProcessing]);\n\n\t// Infinite scroll — IntersectionObserver on the top sentinel\n\tuseEffect(() => {\n\t\tif (!hasMore || !onLoadMore || !topRef.current) return;\n\n\t\tconst observer = new IntersectionObserver(\n\t\t\t(entries) => {\n\t\t\t\tif (entries[0]?.isIntersecting && !isLoadingMore) {\n\t\t\t\t\t// Save scroll position before loading\n\t\t\t\t\tconst container = containerRef.current;\n\t\t\t\t\tconst prevScrollHeight = container?.scrollHeight ?? 0;\n\t\t\t\t\tconst prevScrollTop = container?.scrollTop ?? 0;\n\n\t\t\t\t\tonLoadMore();\n\n\t\t\t\t\t// Restore scroll position after DOM update (next frame)\n\t\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\t\tif (container) {\n\t\t\t\t\t\t\tconst newScrollHeight = container.scrollHeight;\n\t\t\t\t\t\t\tcontainer.scrollTop = prevScrollTop + (newScrollHeight - prevScrollHeight);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ root: containerRef.current, threshold: 0.1 },\n\t\t);\n\n\t\tobserver.observe(topRef.current);\n\t\treturn () => observer.disconnect();\n\t}, [hasMore, onLoadMore, isLoadingMore]);\n\n\tif (items.length === 0) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tclassName=\"hw-messages\"\n\t\t\t\trole=\"log\"\n\t\t\t\taria-label={t(\"widget.aria_messages\")}\n\t\t\t\taria-live=\"polite\"\n\t\t\t>\n\t\t\t\t<div className=\"hw-empty\">\n\t\t\t\t\t<div className=\"hw-empty-icon\">\n\t\t\t\t\t\t<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.5}>\n\t\t\t\t\t\t\t<path d=\"M7.9 20A9 9 0 1 0 4 16.1L2 22Z\" />\n\t\t\t\t\t\t</svg>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"hw-empty-text\">{t(\"widget.start_a_conversation\")}</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t);\n\t}\n\n\tlet lastDateKey = \"\";\n\t/* Last clock label actually printed, so an identical one below it is dropped. */\n\tlet lastTimeLabel: string | undefined;\n\t// Stable \"today\" key (YYYY-MM-DD in local time) for separator gating.\n\t// We HIDE the separator for today entirely — matches Intercom/WhatsApp:\n\t// the date is implicit when \"now\", and showing it on every fresh\n\t// conversation creates a jarring vertical jump as the view fills in.\n\tconst todayKey = new Date().toLocaleDateString(\"en-CA\"); // en-CA is YYYY-MM-DD\n\tconst yesterday = new Date();\n\tyesterday.setDate(yesterday.getDate() - 1);\n\tconst yesterdayKey = yesterday.toLocaleDateString(\"en-CA\");\n\n\treturn (\n\t\t<div\n\t\t\tref={containerRef}\n\t\t\tclassName=\"hw-messages\"\n\t\t\trole=\"log\"\n\t\t\taria-label={t(\"widget.aria_messages\")}\n\t\t\taria-live=\"polite\"\n\t\t>\n\t\t\t{/* Top sentinel for infinite scroll */}\n\t\t\t<div ref={topRef} className=\"hw-load-more-trigger\">\n\t\t\t\t{isLoadingMore && (\n\t\t\t\t\t<div className=\"hw-load-more-spinner\">\n\t\t\t\t\t\t<div />\n\t\t\t\t\t\t<div />\n\t\t\t\t\t\t<div />\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t{items.map((item) => {\n\t\t\t\tif (item.type === \"event\") {\n\t\t\t\t\treturn <EventCard key={(item as unknown as { _stableKey?: string })._stableKey ?? item.id} text={item.text ?? \"\"} />;\n\t\t\t\t}\n\n\t\t\t\t// Date separator — bucket by local YYYY-MM-DD; skip rendering\n\t\t\t\t// when the bucket is \"today\" so today's chats stay flush at the top.\n\t\t\t\tconst itemDate = new Date(item.createdAt);\n\t\t\t\tconst dateKey = itemDate.toLocaleDateString(\"en-CA\");\n\t\t\t\tconst isNewBucket = dateKey !== lastDateKey;\n\t\t\t\tif (isNewBucket) lastDateKey = dateKey;\n\t\t\t\tconst showDateSep = isNewBucket && dateKey !== todayKey;\n\t\t\t\tconst dateLabel =\n\t\t\t\t\tdateKey === yesterdayKey\n\t\t\t\t\t\t? t(\"widget.yesterday\")\n\t\t\t\t\t\t: itemDate.toLocaleDateString(getLocale(), {\n\t\t\t\t\t\t\t\tweekday: \"long\",\n\t\t\t\t\t\t\t\tmonth: \"short\",\n\t\t\t\t\t\t\t\tday: \"numeric\",\n\t\t\t\t\t\t\t});\n\n\t\t\t\t// Determine sender\n\t\t\t\tconst sender = item.visitorId ? \"visitor\" : item.aiAgentId ? \"ai\" : \"team\";\n\n\t\t\t\t// Show timestamp on the last message in a consecutive group from the same sender\n\t\t\t\tconst idx = items.indexOf(item);\n\t\t\t\tconst nextItem = items[idx + 1];\n\t\t\t\tconst nextSender = nextItem?.type === \"message\"\n\t\t\t\t\t? (nextItem.visitorId ? \"visitor\" : nextItem.aiAgentId ? \"ai\" : \"team\")\n\t\t\t\t\t: null;\n\t\t\t\tconst isLastInGroup = nextSender !== sender || nextItem?.type === \"event\";\n\t\t\t\t/* A clock label earns its place only when it says something new.\n\t\t\t\t An answer that lands in the same minute the question did — the\n\t\t\t\t normal case for an AI reply, and for a multi-part answer split\n\t\t\t\t across bubbles — printed \"14:32\" under every one of them: the\n\t\t\t\t same fact three times, and the line carrying the agent's name\n\t\t\t\t got noisier for it. Repeats are dropped; a new day always\n\t\t\t\t re-prints, because the reader has lost the thread by then. */\n\t\t\t\tlet timeLabel = isLastInGroup\n\t\t\t\t\t? itemDate.toLocaleTimeString(getLocale(), { hour: \"2-digit\", minute: \"2-digit\" })\n\t\t\t\t\t: undefined;\n\t\t\t\tif (timeLabel && timeLabel === lastTimeLabel && !showDateSep) timeLabel = undefined;\n\t\t\t\tif (timeLabel) lastTimeLabel = timeLabel;\n\n\t\t\t\treturn (\n\t\t\t\t\t<React.Fragment key={(item as unknown as { _stableKey?: string })._stableKey ?? item.id}>\n\t\t\t\t\t\t{showDateSep && (\n\t\t\t\t\t\t\t<div className=\"hw-date-sep\">\n\t\t\t\t\t\t\t\t<div className=\"hw-date-sep-line\" />\n\t\t\t\t\t\t\t\t<div className=\"hw-date-sep-text\">{dateLabel}</div>\n\t\t\t\t\t\t\t\t<div className=\"hw-date-sep-line\" />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<MessageBubble\n\t\t\t\t\t\t\ttext={item.text ?? \"\"}\n\t\t\t\t\t\t\tsender={sender}\n\t\t\t\t\t\t\tsenderName={\n\t\t\t\t\t\t\t\tsender === \"visitor\"\n\t\t\t\t\t\t\t\t\t? visitorName\n\t\t\t\t\t\t\t\t\t: // userName is only set when a human replied. For an AI\n\t\t\t\t\t\t\t\t\t\t// answer it is null, which fell through to the generic\n\t\t\t\t\t\t\t\t\t\t// \"Support\" label — so the agent never signed its own work.\n\t\t\t\t\t\t\t\t\t\t(item.userName ?? (sender === \"ai\" ? agentName : undefined))\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tparts={parseParts(item.parts)}\n\t\t\t\t\t\t\tmetadata={parseMetadata(\n\t\t\t\t\t\t\t\t(item as TimelineItem & { metadata?: TimelineItemMetadata | string | null })\n\t\t\t\t\t\t\t\t\t.metadata,\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\tonQuickReplyTap={handleQuickReplyTap}\n\t\t\t\t\t\t\ttimestamp={timeLabel}\n\t\t\t\t\t\t\tshowAuthor={isLastInGroup}\n\t\t\t\t\t\t\theaderName={headerName}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</React.Fragment>\n\t\t\t\t);\n\t\t\t})}\n\n\t\t\t{/* Slot for inline content after messages (e.g. email prompt) */}\n\t\t\t{renderAfterMessages}\n\n\t\t\t{/* Streaming AI response — shows text flowing in word by word.\n\t\t\t MUST mirror MessageBubble's AI markup (hw-msg/hw-msg--ai/hw-msg-bubble)\n\t\t\t and go through renderMarkdown: the old hw-message-ai/hw-bubble-ai\n\t\t\t classes had no CSS at all, so the stream rendered as unstyled raw\n\t\t\t markdown and then \"jumped\" into the formatted bubble on finish. */}\n\t\t\t{streamingText && (\n\t\t\t\t<div className=\"hw-msg hw-msg--ai\">\n\t\t\t\t\t<div className=\"hw-msg-body\">\n\t\t\t\t\t\t<div className=\"hw-msg-bubble\">\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\tdangerouslySetInnerHTML={{\n\t\t\t\t\t\t\t\t\t__html: renderMarkdown(closeDanglingMarkdown(streamingText)),\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<span className=\"hw-streaming-cursor\" />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* AI processing indicator (thinking dots — hidden during streaming).\n\t\t\t No name above the dots: the answer that follows already carries one\n\t\t\t signature, and repeating it here made \"Better AI\" appear twice for a\n\t\t\t single reply. */}\n\t\t\t{isAiProcessing && !streamingText && (\n\t\t\t\t<div className=\"hw-typing\">\n\t\t\t\t\t<div className=\"hw-typing-dots\">\n\t\t\t\t\t\t<div className=\"hw-typing-dot\" />\n\t\t\t\t\t\t<div className=\"hw-typing-dot\" />\n\t\t\t\t\t\t<div className=\"hw-typing-dot\" />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Typing indicator (team, not AI) */}\n\t\t\t{isTyping && !isAiProcessing && (\n\t\t\t\t<div className=\"hw-typing\">\n\t\t\t\t\t<div className=\"hw-typing-dots\">\n\t\t\t\t\t\t<div className=\"hw-typing-dot\" />\n\t\t\t\t\t\t<div className=\"hw-typing-dot\" />\n\t\t\t\t\t\t<div className=\"hw-typing-dot\" />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t<div ref={bottomRef} />\n\t\t</div>\n\t);\n}\n\n// ── Event Card ────────────────────────────────────────\n\ninterface EventData {\n\taction: string;\n\tname: string;\n\timage?: string | null;\n}\n\nfunction parseEventData(text: string): EventData | null {\n\tif (!text.startsWith(\"{\")) return null;\n\ttry {\n\t\tconst data = JSON.parse(text);\n\t\tif (data.action && data.name) return data as EventData;\n\t} catch {\n\t\t/* plain text fallback */\n\t}\n\treturn null;\n}\n\nfunction EventCard({ text }: { text: string }) {\n\tconst data = parseEventData(text);\n\n\t// Structured event — rich card with avatar\n\tif (data) {\n\t\tconst message = data.action === \"joined\" ? t(\"widget.joined\") : t(\"widget.left\");\n\n\t\treturn (\n\t\t\t<div className=\"hw-event hw-event--card\">\n\t\t\t\t<div className=\"hw-event-avatar\">\n\t\t\t\t\t{data.image ? (\n\t\t\t\t\t\t<img src={data.image} alt=\"\" className=\"hw-event-avatar-img\" />\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<span>{getInitials(data.name)}</span>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t<div className=\"hw-event-body\">\n\t\t\t\t\t<span className=\"hw-event-name\">{data.name}</span>{\" \"}\n\t\t\t\t\t<span className=\"hw-event-action\">{message}</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t);\n\t}\n\n\t// Plain text event (resolve, reopen, etc.)\n\treturn (\n\t\t<div className=\"hw-event\">\n\t\t\t<div className=\"hw-event-text\">{text}</div>\n\t\t</div>\n\t);\n}\n","\"use client\";\n\nimport { t } from \"@helpway/widget-core\";\nimport type { MouseEvent, ReactNode } from \"react\";\nimport { useEffect, useState } from \"react\";\nimport { useWidgetStore } from \"../provider\";\nimport { XIcon } from \"./icons\";\n\n/** Where the preview is anchored — controls only the outer positioning. */\nexport type MessagePreviewPlacement = \"launcher\" | \"anchored\";\n\nexport interface MessagePreviewProps {\n\t/** Called when the visitor taps the preview (or a quick reply). The\n\t * active conversation is already switched to the one that pinged —\n\t * the consumer just has to reveal the chat surface. */\n\tonOpen: () => void;\n\t/**\n\t * The avatar node shown in the header. Injected by the consumer so\n\t * this component stays decoupled from avatar resolution — the default\n\t * widget passes `<WidgetLogo />`; a custom surface can pass its own.\n\t */\n\tavatar: ReactNode;\n\t/**\n\t * Outer positioning mode. `\"launcher\"` (default) keeps the original\n\t * absolute placement above the floating bubble — DefaultWidget relies\n\t * on this, so the default is unchanged. `\"anchored\"` drops the\n\t * absolute/bottom/right rules (via `hw-preview--anchored`) so a\n\t * consumer can pin it to their own trigger (e.g. a sidebar item).\n\t */\n\tplacement?: MessagePreviewPlacement;\n\t/**\n\t * Auto-dismiss delay in ms. Default `8000` (the launcher behaviour).\n\t * Pass `null` (or `0`) to keep the preview until the visitor acts on\n\t * it — useful for an anchored surface where it isn't competing with\n\t * page content for attention. Quick-reply previews never auto-dismiss\n\t * regardless, since the visitor needs time to choose.\n\t */\n\tautoDismissMs?: number | null;\n\t/**\n\t * Optional caption rendered as a separated footer beneath the message\n\t * (e.g. a source label like \"via Helpway\"). Omitted for the launcher\n\t * so its visual stays byte-identical to the original.\n\t */\n\tfooter?: ReactNode;\n}\n\n/**\n * `<MessagePreview>` — the proactive incoming-message bubble shown while\n * the chat surface is closed. Reads `incomingPreview` from the widget\n * store, auto-dismisses after 8s (unless quick replies are present), and\n * on tap switches to the pinging conversation before calling `onOpen`.\n *\n * Extracted from the default widget so `hideLauncher` integrations can\n * surface the *exact same* preview next to their own UI instead of the\n * floating launcher. Visual/markup is byte-identical to the launcher\n * version — only the outer positioning is parameterised via `placement`.\n *\n * Must be rendered inside `<SupportProvider>`.\n */\nexport function MessagePreview({\n\tonOpen,\n\tavatar,\n\tplacement = \"launcher\",\n\tautoDismissMs = 8000,\n\tfooter,\n}: MessagePreviewProps) {\n\tconst preview = useWidgetStore((s) => s.incomingPreview);\n\tconst dismissPreview = useWidgetStore((s) => s.dismissPreview);\n\tconst setActiveConversation = useWidgetStore((s) => s.setActiveConversation);\n\tconst agentName = useWidgetStore((s) => s.agentConfig?.name) ?? \"Support\";\n\t/* A human who replies signs with their own name. The card used to print the\n\t agent's name over every message, so a teammate's answer arrived as if the\n\t AI had written it — the one moment the visitor most needs to know a person\n\t picked this up. The AI keeps the agent name because for it that IS the\n\t sender. */\n\tconst senderName = preview?.senderName || agentName;\n\tconst senderImage = preview?.senderImage || null;\n\tconst [closing, setClosing] = useState(false);\n\n\t// Auto-dismiss after `autoDismissMs` (skip when quick replies are\n\t// present — visitor needs time to read and decide — or when the\n\t// consumer opted out with null/0 for a persistent anchored surface).\n\tuseEffect(() => {\n\t\tif (!preview || preview.quickReplies) return;\n\t\tif (autoDismissMs == null || autoDismissMs <= 0) return;\n\t\tconst timer = setTimeout(() => {\n\t\t\tsetClosing(true);\n\t\t\tsetTimeout(() => dismissPreview(), 200);\n\t\t}, autoDismissMs);\n\t\treturn () => clearTimeout(timer);\n\t}, [preview, dismissPreview, autoDismissMs]);\n\n\tif (!preview) return null;\n\n\tconst handleClose = (e: MouseEvent) => {\n\t\te.stopPropagation();\n\t\tsetClosing(true);\n\t\tsetTimeout(() => {\n\t\t\tdismissPreview();\n\t\t\tsetClosing(false);\n\t\t}, 200);\n\t};\n\n\tconst handleClick = () => {\n\t\t// Bubble click is an explicit \"I want to read this\" — open the\n\t\t// widget AND jump straight to the conversation that pinged. Without\n\t\t// the setActiveConversation, the visitor lands on the home screen\n\t\t// and has to find the unread row themselves.\n\t\tconst targetConvId = preview.conversationId;\n\t\tdismissPreview();\n\t\tsetActiveConversation(targetConvId);\n\t\tonOpen();\n\t};\n\n\tconst messages = preview.messages?.length ? preview.messages : [{ text: preview.text }];\n\tconst hasQr = preview.quickReplies && preview.quickReplies.options.length > 0;\n\n\tconst placementClass = placement === \"anchored\" ? \"hw-preview--anchored \" : \"\";\n\n\treturn (\n\t\t<div\n\t\t\tclassName={`hw-preview ${placementClass}${closing ? \"hw-preview--closing\" : \"\"}`}\n\t\t\tonClick={handleClick}\n\t\t\trole=\"button\"\n\t\t\ttabIndex={0}\n\t\t>\n\t\t\t<div className=\"hw-preview-header\">\n\t\t\t\t<div className=\"hw-preview-avatar\">\n\t\t\t\t\t{senderImage ? <img src={senderImage} alt=\"\" /> : avatar}\n\t\t\t\t</div>\n\t\t\t\t<div className=\"hw-preview-name\">{senderName}</div>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"hw-preview-close\"\n\t\t\t\t\tonClick={handleClose}\n\t\t\t\t\taria-label={t(\"widget.aria_dismiss\")}\n\t\t\t\t>\n\t\t\t\t\t<XIcon size={20} />\n\t\t\t\t</button>\n\t\t\t</div>\n\n\t\t\t{messages.map((m, i) => (\n\t\t\t\t<div key={i} className=\"hw-preview-body\">\n\t\t\t\t\t{m.text}\n\t\t\t\t</div>\n\t\t\t))}\n\n\t\t\t{hasQr && (\n\t\t\t\t<>\n\t\t\t\t\t{preview.quickReplies!.prompt && (\n\t\t\t\t\t\t<div className=\"hw-preview-body\">{preview.quickReplies!.prompt}</div>\n\t\t\t\t\t)}\n\t\t\t\t\t<div className=\"hw-preview-quick-replies\">\n\t\t\t\t\t\t{preview.quickReplies!.options.map((opt) => (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\tkey={opt.id}\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclassName=\"hw-preview-qr-btn\"\n\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\tdismissPreview();\n\t\t\t\t\t\t\t\t\tsetActiveConversation(preview.conversationId);\n\t\t\t\t\t\t\t\t\tonOpen();\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{opt.label}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\t\t\t\t</>\n\t\t\t)}\n\n\t\t\t{footer != null && footer !== false && (\n\t\t\t\t<div className=\"hw-preview-footer\">{footer}</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","\n export default function styleInject(css, { insertAt } = {}) {\n if (!css || typeof document === 'undefined') return\n \n const head = document.head || document.getElementsByTagName('head')[0]\n const style = document.createElement('style')\n style.type = 'text/css'\n \n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild)\n } else {\n head.appendChild(style)\n }\n } else {\n head.appendChild(style)\n }\n \n if (style.styleSheet) {\n style.styleSheet.cssText = css\n } else {\n style.appendChild(document.createTextNode(css))\n }\n }\n ","import styleInject from '#style-inject';styleInject(\":host {\\n all: initial;\\n font-family:\\n -apple-system,\\n BlinkMacSystemFont,\\n \\\"Segoe UI\\\",\\n Roboto,\\n \\\"Helvetica Neue\\\",\\n Arial,\\n sans-serif;\\n font-size: 14px;\\n line-height: 1.5;\\n color: #1a1a1a;\\n -webkit-font-smoothing: antialiased;\\n -moz-osx-font-smoothing: grayscale;\\n}\\n.hw-widget {\\n font-family:\\n -apple-system,\\n BlinkMacSystemFont,\\n \\\"Segoe UI\\\",\\n Roboto,\\n \\\"Helvetica Neue\\\",\\n Arial,\\n sans-serif;\\n font-size: 14px;\\n line-height: 1.5;\\n color: #1a1a1a;\\n -webkit-font-smoothing: antialiased;\\n -moz-osx-font-smoothing: grayscale;\\n}\\n.hw-widget *,\\n.hw-widget *::before,\\n.hw-widget *::after {\\n box-sizing: border-box;\\n margin: 0;\\n padding: 0;\\n}\\n:where(.hw-widget) {\\n --hw-primary: #171717;\\n --hw-primary-hover: #2a2a2a;\\n --hw-brand: #171717;\\n --hw-on-brand: #ffffff;\\n --hw-focus-border: #9ca3af;\\n --hw-focus-ring: rgba(0, 0, 0, 0.06);\\n --hw-accent: #6366f1;\\n --hw-bg: #ffffff;\\n --hw-bg-subtle: #fafaf9;\\n --hw-bg-hover: #f5f5f4;\\n --hw-border: #ebe9e5;\\n --hw-border-md: #e5e5e5;\\n --hw-text: #1c1b19;\\n --hw-text-1: #111;\\n --hw-text-2: #666;\\n --hw-text-3: #8a847c;\\n --hw-text-4: #a8a29a;\\n --hw-radius: 20px;\\n --hw-visitor-bubble-bg: #f5f5f4;\\n --hw-visitor-bubble-text: #1a1a1a;\\n --hw-font:\\n -apple-system,\\n BlinkMacSystemFont,\\n \\\"Segoe UI\\\",\\n Roboto,\\n \\\"Helvetica Neue\\\",\\n Arial,\\n sans-serif;\\n}\\n.hw-agent-img {\\n width: 100%;\\n height: 100%;\\n object-fit: cover;\\n}\\n.hw-agent-icon {\\n width: 100%;\\n height: 100%;\\n border-radius: inherit;\\n}\\n.hw-widget :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: 14px 12px 14px 16px;\\n background: var(--hw-primary);\\n color: white;\\n flex-shrink: 0;\\n gap: 10px;\\n}\\n.hw-header--sub {\\n justify-content: space-between;\\n background: transparent;\\n color: var(--hw-text);\\n border-bottom: 0;\\n}\\n.hw-header-back {\\n width: 28px;\\n height: 28px;\\n border-radius: 8px;\\n border: none;\\n background: transparent;\\n color: var(--hw-text-3);\\n cursor: pointer;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n transition: color 0.15s, background 0.15s;\\n flex-shrink: 0;\\n}\\n.hw-header-back svg {\\n width: 18px;\\n height: 18px;\\n}\\n.hw-header-back:hover {\\n color: var(--hw-text);\\n background: var(--hw-bg-subtle);\\n}\\n.hw-header-identity {\\n display: flex;\\n align-items: center;\\n gap: 10px;\\n flex: 1;\\n min-width: 0;\\n}\\n.hw-header-bot-icon {\\n width: 32px;\\n height: 32px;\\n flex-shrink: 0;\\n color: var(--hw-text);\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n border-radius: 9px;\\n background: var(--hw-agent-bg, var(--hw-agent-bg-default, transparent));\\n}\\n.hw-header-bot-icon svg {\\n width: 24px;\\n height: 24px;\\n}\\n.hw-header-bot-icon--team {\\n background: var(--hw-brand, #0a0a0a);\\n color: var(--hw-on-brand, #fff);\\n}\\n.hw-header-agent-img {\\n width: 100%;\\n height: 100%;\\n object-fit: cover;\\n border-radius: inherit;\\n}\\n.hw-header-bot-icon .hw-agent-img,\\n.hw-header-bot-icon .hw-agent-icon {\\n border-radius: inherit;\\n overflow: hidden;\\n}\\n.hw-header-bot-icon .hw-agent-img {\\n object-fit: var(--hw-agent-fit, var(--hw-agent-fit-default, cover));\\n padding: var(--hw-agent-pad, var(--hw-agent-pad-default, 0));\\n box-sizing: border-box;\\n}\\n.hw-widget[data-has-avatar=true] {\\n --hw-agent-bg-default: var(--hw-primary);\\n --hw-agent-fit-default: contain;\\n --hw-agent-pad-default: 6px;\\n}\\n.hw-header-agent-initials {\\n font-size: 11px;\\n font-weight: 600;\\n line-height: 1;\\n}\\n.hw-header-info {\\n flex: 1;\\n min-width: 0;\\n}\\n.hw-header-name {\\n font-size: 15px;\\n font-weight: 600;\\n line-height: 1.3;\\n}\\n.hw-header-status {\\n font-size: 11px;\\n color: var(--hw-text-3);\\n line-height: 1.3;\\n}\\n.hw-header-close {\\n width: 28px;\\n height: 28px;\\n border-radius: 8px;\\n border: none;\\n background: transparent;\\n color: var(--hw-text-3);\\n cursor: pointer;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n transition:\\n background-color 140ms cubic-bezier(0.23, 1, 0.32, 1),\\n color 140ms cubic-bezier(0.23, 1, 0.32, 1),\\n transform 140ms cubic-bezier(0.23, 1, 0.32, 1);\\n flex-shrink: 0;\\n}\\n.hw-header-close svg {\\n width: 20px;\\n height: 20px;\\n}\\n.hw-header-close:hover {\\n background: var(--hw-bg-subtle);\\n color: var(--hw-text);\\n}\\n.hw-header-close:active {\\n transform: scale(0.92);\\n}\\n.hw-header--centered {\\n justify-content: space-between;\\n background: transparent;\\n color: var(--hw-text);\\n border-bottom: 0;\\n}\\n.hw-header--centered .hw-header-title {\\n position: absolute;\\n left: 50%;\\n transform: translateX(-50%);\\n max-width: calc(100% - 88px);\\n white-space: nowrap;\\n overflow: hidden;\\n text-overflow: ellipsis;\\n text-align: center;\\n}\\n.hw-header-spacer {\\n width: 28px;\\n flex-shrink: 0;\\n}\\n.hw-header--messages {\\n justify-content: space-between;\\n background: transparent;\\n color: var(--hw-text);\\n border-bottom: 0;\\n}\\n.hw-header-title {\\n font-size: 16px;\\n font-weight: 600;\\n}\\n.hw-header-actions {\\n display: flex;\\n align-items: center;\\n gap: 6px;\\n}\\n.hw-header-action {\\n width: 28px;\\n height: 28px;\\n border-radius: 8px;\\n border: none;\\n background: transparent;\\n color: var(--hw-text-3);\\n cursor: pointer;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n transition:\\n background-color 140ms cubic-bezier(0.23, 1, 0.32, 1),\\n color 140ms cubic-bezier(0.23, 1, 0.32, 1),\\n transform 140ms cubic-bezier(0.23, 1, 0.32, 1);\\n}\\n.hw-header-action svg {\\n width: 16px;\\n height: 16px;\\n}\\n.hw-header-action:hover {\\n background: var(--hw-bg-subtle);\\n color: var(--hw-text);\\n}\\n.hw-header-action:active {\\n transform: scale(0.94);\\n}\\n.hw-card {\\n display: flex;\\n align-items: center;\\n gap: 12px;\\n width: 100%;\\n padding: 14px 16px;\\n border-radius: 14px;\\n background: var(--hw-bg);\\n border: 0;\\n box-shadow: inset 0 0 0 1px var(--hw-border);\\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06), 0 0 0 1px rgba(0, 0, 0, 0.03);\\n cursor: pointer;\\n transition: box-shadow 180ms cubic-bezier(0.23, 1, 0.32, 1), transform 180ms cubic-bezier(0.23, 1, 0.32, 1);\\n text-align: left;\\n color: var(--hw-text);\\n font-family: inherit;\\n}\\n.hw-card:hover {\\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.08), 0 0 0 1px rgba(0, 0, 0, 0.05);\\n transform: translateY(-1px);\\n}\\n.hw-card:active {\\n transform: translateY(0) scale(0.99);\\n transition-duration: 120ms;\\n}\\n.hw-card-body {\\n flex: 1;\\n min-width: 0;\\n}\\n.hw-card-title {\\n font-size: 14px;\\n font-weight: 600;\\n line-height: 1.3;\\n color: var(--hw-text);\\n}\\n.hw-card-meta {\\n font-size: 12px;\\n color: var(--hw-text-3);\\n line-height: 1.3;\\n margin-top: 1px;\\n}\\n.hw-card-arrow {\\n width: 32px;\\n height: 32px;\\n border-radius: 50%;\\n background: var(--hw-primary);\\n color: white;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n flex-shrink: 0;\\n}\\n.hw-card-arrow svg {\\n width: 14px;\\n height: 14px;\\n}\\n.hw-msgs-tab {\\n flex: 1;\\n overflow-y: auto;\\n padding: 12px 16px;\\n display: flex;\\n flex-direction: column;\\n gap: 8px;\\n}\\n.hw-recent-card {\\n border-radius: 14px;\\n background: var(--hw-bg);\\n border: 0;\\n box-shadow: inset 0 0 0 1px var(--hw-border);\\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06), 0 0 0 1px rgba(0, 0, 0, 0.03);\\n overflow: hidden;\\n}\\n.hw-recent-header {\\n font-size: 12px;\\n font-weight: 600;\\n color: var(--hw-text-2);\\n padding: 12px 14px 0;\\n}\\n.hw-recent-row {\\n display: flex;\\n align-items: center;\\n gap: 10px;\\n width: 100%;\\n padding: 10px 14px;\\n border: none;\\n border-bottom: 1px solid var(--hw-border);\\n background: none;\\n cursor: pointer;\\n text-align: left;\\n font-family: inherit;\\n color: var(--hw-text);\\n transition: background-color 140ms cubic-bezier(0.23, 1, 0.32, 1), transform 140ms cubic-bezier(0.23, 1, 0.32, 1);\\n position: relative;\\n}\\n.hw-recent-row:hover {\\n background: rgba(0, 0, 0, 0.03);\\n}\\n.hw-recent-row:active {\\n transform: scale(0.995);\\n}\\n.hw-recent-row--last {\\n border-bottom: none;\\n}\\n.hw-recent-row .hw-conv-card-avatar {\\n width: 32px;\\n height: 32px;\\n border-radius: 8px;\\n}\\n.hw-recent-row .hw-conv-card-avatar svg {\\n width: 18px;\\n height: 18px;\\n}\\n.hw-recent-row .hw-conv-card-name {\\n font-size: 13px;\\n}\\n.hw-recent-row .hw-conv-card-preview {\\n font-size: 12px;\\n}\\n.hw-recent-row--unread .hw-conv-card-name {\\n color: var(--hw-text);\\n}\\n.hw-recent-row--unread .hw-conv-card-time {\\n color: var(--hw-primary);\\n font-weight: 500;\\n}\\n.hw-recent-row-badge {\\n min-width: 18px;\\n height: 18px;\\n border-radius: 9px;\\n background: var(--hw-primary);\\n color: white;\\n font-size: 11px;\\n font-weight: 600;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n padding: 0 5px;\\n flex-shrink: 0;\\n font-variant-numeric: tabular-nums;\\n}\\n.hw-recent-see-all {\\n display: block;\\n width: 100%;\\n padding: 10px 14px;\\n text-align: center;\\n font-size: 13px;\\n font-weight: 500;\\n color: var(--hw-text);\\n background: none;\\n border: none;\\n border-top: 1px solid var(--hw-border);\\n cursor: pointer;\\n font-family: inherit;\\n transition: background 0.1s;\\n}\\n.hw-recent-see-all:hover {\\n background: rgba(0, 0, 0, 0.02);\\n}\\n.hw-conv-card {\\n position: relative;\\n display: flex;\\n flex-direction: column;\\n gap: 4px;\\n width: 100%;\\n padding: 14px 16px;\\n border-radius: 14px;\\n background: var(--hw-bg);\\n border: 0;\\n box-shadow: inset 0 0 0 1px var(--hw-border);\\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06), 0 0 0 1px rgba(0, 0, 0, 0.03);\\n cursor: pointer;\\n transition: box-shadow 0.15s, transform 0.1s;\\n text-align: left;\\n font-family: inherit;\\n color: var(--hw-text);\\n}\\n.hw-conv-card:hover {\\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(0, 0, 0, 0.04);\\n}\\n.hw-conv-card:active {\\n transform: scale(0.99);\\n}\\n.hw-conv-card-row {\\n display: flex;\\n align-items: center;\\n gap: 12px;\\n}\\n.hw-conv-card-avatar {\\n width: 36px;\\n height: 36px;\\n border-radius: 10px;\\n background: var(--hw-agent-bg, var(--hw-agent-bg-default, var(--hw-bg-subtle)));\\n color: var(--hw-text-3);\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n flex-shrink: 0;\\n overflow: hidden;\\n}\\n.hw-conv-card-avatar svg {\\n width: 20px;\\n height: 20px;\\n}\\n.hw-conv-card-avatar-img {\\n width: 100%;\\n height: 100%;\\n object-fit: cover;\\n}\\n.hw-conv-card-avatar .hw-agent-img {\\n object-fit: var(--hw-agent-fit, var(--hw-agent-fit-default, cover));\\n padding: var(--hw-agent-pad, var(--hw-agent-pad-default, 0));\\n box-sizing: border-box;\\n}\\n.hw-conv-card-avatar--team {\\n background: var(--hw-brand, #0a0a0a);\\n color: var(--hw-on-brand, #fff);\\n}\\n.hw-conv-card-avatar-initials {\\n font-size: 12px;\\n font-weight: 600;\\n line-height: 1;\\n letter-spacing: 0.02em;\\n}\\n.hw-conv-card-content {\\n flex: 1;\\n min-width: 0;\\n}\\n.hw-conv-card-top {\\n display: flex;\\n align-items: baseline;\\n gap: 8px;\\n}\\n.hw-conv-card-name {\\n flex: 1;\\n font-size: 14px;\\n font-weight: 600;\\n color: var(--hw-text);\\n}\\n.hw-conv-card-time {\\n font-size: 11px;\\n color: var(--hw-text-3);\\n flex-shrink: 0;\\n font-variant-numeric: tabular-nums;\\n}\\n.hw-conv-card-preview {\\n font-size: 13px;\\n color: var(--hw-text-2);\\n overflow: hidden;\\n text-overflow: ellipsis;\\n white-space: nowrap;\\n line-height: 1.4;\\n margin-top: 1px;\\n}\\n.hw-conv-card--unread .hw-conv-card-name {\\n color: var(--hw-text);\\n}\\n.hw-conv-card--unread .hw-conv-card-time {\\n color: var(--hw-primary);\\n font-weight: 500;\\n}\\n.hw-conv-card-badge {\\n position: absolute;\\n top: 12px;\\n right: 12px;\\n min-width: 18px;\\n height: 18px;\\n border-radius: 9px;\\n background: var(--hw-primary);\\n color: white;\\n font-size: 11px;\\n font-weight: 600;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n padding: 0 5px;\\n font-variant-numeric: tabular-nums;\\n}\\n.hw-empty-state {\\n flex: 1;\\n display: flex;\\n flex-direction: column;\\n align-items: center;\\n justify-content: center;\\n padding: 32px;\\n text-align: center;\\n}\\n.hw-empty-icon-wrap {\\n width: 48px;\\n height: 48px;\\n border-radius: 50%;\\n background: var(--hw-bg-subtle);\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n margin-bottom: 16px;\\n color: var(--hw-text-3);\\n}\\n.hw-empty-icon-wrap svg {\\n width: 24px;\\n height: 24px;\\n}\\n.hw-empty-title {\\n font-size: 15px;\\n font-weight: 600;\\n color: var(--hw-text);\\n margin-bottom: 4px;\\n}\\n.hw-empty-desc {\\n font-size: 13px;\\n color: var(--hw-text-3);\\n margin-bottom: 20px;\\n}\\n.hw-empty-btn {\\n padding: 8px 20px;\\n border-radius: 10px;\\n background: var(--hw-primary);\\n color: white;\\n border: none;\\n font-size: 13px;\\n font-weight: 500;\\n cursor: pointer;\\n font-family: inherit;\\n transition: background 0.15s;\\n}\\n.hw-empty-btn:hover {\\n background: var(--hw-primary-hover);\\n}\\n.hw-tabs {\\n display: flex;\\n border-top: 1px solid var(--hw-border);\\n flex-shrink: 0;\\n background: var(--hw-bg-subtle);\\n}\\n.hw-tabs-item {\\n flex: 1;\\n display: flex;\\n flex-direction: column;\\n align-items: center;\\n gap: 2px;\\n padding: 8px 0;\\n border: none;\\n background: none;\\n cursor: pointer;\\n font-family: inherit;\\n font-size: 11px;\\n font-weight: 500;\\n color: var(--hw-text-3);\\n transition: color 0.15s;\\n}\\n.hw-tabs-item svg {\\n width: 22px;\\n height: 22px;\\n overflow: visible;\\n}\\n.hw-tabs-item--active {\\n color: var(--hw-text);\\n}\\n.hw-tabs-item:hover {\\n color: var(--hw-text-2);\\n}\\n.hw-tabs-item:active {\\n transform: scale(0.94);\\n transition: transform 0.14s cubic-bezier(0.23, 1, 0.32, 1), color 0.15s;\\n}\\n.hw-tabs-icon-wrap {\\n position: relative;\\n display: inline-flex;\\n}\\n.hw-tabs-badge {\\n position: absolute;\\n top: -6px;\\n right: -10px;\\n min-width: 16px;\\n height: 16px;\\n border-radius: 8px;\\n background: var(--hw-primary);\\n color: white;\\n font-size: 10px;\\n font-weight: 700;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n padding: 0 4px;\\n font-variant-numeric: tabular-nums;\\n}\\n.hw-messages {\\n flex: 1;\\n overflow-y: auto;\\n overflow-x: hidden;\\n padding: 16px 14px 8px;\\n background: var(--hw-bg-subtle);\\n display: flex;\\n flex-direction: column;\\n gap: 14px;\\n overscroll-behavior: contain;\\n min-width: 0;\\n scrollbar-color: rgba(0, 0, 0, 0.2) transparent;\\n scrollbar-width: thin;\\n}\\n.hw-messages::-webkit-scrollbar {\\n width: 10px;\\n height: 10px;\\n}\\n.hw-messages::-webkit-scrollbar-track {\\n background: transparent;\\n}\\n.hw-messages::-webkit-scrollbar-thumb {\\n background: rgba(0, 0, 0, 0.16);\\n background-clip: content-box;\\n border: 3px solid transparent;\\n border-radius: 999px;\\n}\\n.hw-messages::-webkit-scrollbar-thumb:hover {\\n background: rgba(0, 0, 0, 0.28);\\n background-clip: content-box;\\n}\\n.hw-widget[data-theme=dark] .hw-messages {\\n scrollbar-color: rgba(255, 255, 255, 0.26) transparent;\\n}\\n.hw-widget[data-theme=dark] .hw-messages::-webkit-scrollbar-thumb {\\n background: rgba(255, 255, 255, 0.2);\\n background-clip: content-box;\\n}\\n.hw-widget[data-theme=dark] .hw-messages::-webkit-scrollbar-thumb:hover {\\n background: rgba(255, 255, 255, 0.32);\\n background-clip: content-box;\\n}\\n.hw-empty {\\n flex: 1;\\n display: flex;\\n flex-direction: column;\\n align-items: center;\\n justify-content: center;\\n padding: 32px;\\n color: var(--hw-text-3);\\n text-align: center;\\n}\\n.hw-empty-icon {\\n width: 40px;\\n height: 40px;\\n margin-bottom: 12px;\\n opacity: 0.3;\\n}\\n.hw-empty-text {\\n font-size: 13px;\\n}\\n.hw-date-sep {\\n display: flex;\\n align-items: center;\\n gap: 12px;\\n padding: 12px 0;\\n}\\n.hw-date-sep-line {\\n flex: 1;\\n height: 1px;\\n background: var(--hw-border-md);\\n}\\n.hw-date-sep-text {\\n font-size: 11px;\\n color: var(--hw-text-3);\\n font-weight: 500;\\n white-space: nowrap;\\n}\\n.hw-msg {\\n display: flex;\\n padding: 4px 0;\\n max-width: 75%;\\n min-width: 0;\\n animation: hw-msg-appear 0.25s ease-out;\\n}\\n@keyframes hw-msg-appear {\\n from {\\n opacity: 0;\\n transform: translateY(6px);\\n }\\n to {\\n opacity: 1;\\n transform: translateY(0);\\n }\\n}\\n.hw-msg--visitor {\\n align-self: flex-end;\\n}\\n.hw-msg--team,\\n.hw-msg--ai {\\n align-self: flex-start;\\n}\\n.hw-msg--ai {\\n width: 100%;\\n max-width: 100%;\\n}\\n.hw-msg-body {\\n display: flex;\\n flex-direction: column;\\n min-width: 0;\\n max-width: 100%;\\n}\\n.hw-msg-bubble {\\n padding: 10px 14px;\\n border-radius: 16px;\\n font-size: 14px;\\n line-height: 1.45;\\n white-space: pre-wrap;\\n word-break: break-word;\\n overflow-wrap: anywhere;\\n max-width: 100%;\\n}\\n.hw-msg--visitor .hw-msg-bubble {\\n background: var(--hw-primary);\\n color: white;\\n border-bottom-right-radius: 4px;\\n}\\n.hw-msg--team .hw-msg-bubble {\\n background: var(--hw-visitor-bubble-bg);\\n color: var(--hw-visitor-bubble-text);\\n border-bottom-left-radius: 4px;\\n}\\n.hw-msg--ai .hw-msg-bubble {\\n background: var(--hw-visitor-bubble-bg);\\n color: var(--hw-text);\\n border-bottom-left-radius: 4px;\\n white-space: normal;\\n max-width: min(100%, 640px);\\n}\\n.hw-msg--ai .hw-msg-body {\\n width: 100%;\\n}\\n.hw-msg--ai .hw-msg-bubble:has(.hw-code),\\n.hw-msg--ai .hw-msg-bubble:has(pre) {\\n width: 100%;\\n}\\n.hw-quick-replies {\\n display: flex;\\n flex-wrap: wrap;\\n gap: 6px;\\n margin-top: 8px;\\n}\\n.hw-quick-reply-btn {\\n font: inherit;\\n font-size: 13px;\\n font-weight: 500;\\n padding: 6px 14px;\\n border-radius: 18px;\\n border: 0;\\n box-shadow: inset 0 0 0 1px var(--hw-border);\\n background: var(--hw-bg, #fff);\\n color: var(--hw-text-1, #1a1a1a);\\n cursor: pointer;\\n transition:\\n background 120ms ease,\\n border-color 120ms ease,\\n box-shadow 120ms ease,\\n transform 80ms ease;\\n line-height: 1.3;\\n}\\n.hw-quick-reply-btn:hover:not(:disabled) {\\n border-color: var(--hw-primary);\\n background: color-mix(in srgb, var(--hw-primary) 8%, transparent);\\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);\\n}\\n.hw-quick-reply-btn:active:not(:disabled) {\\n transform: scale(0.97);\\n}\\n.hw-quick-reply-btn:disabled {\\n cursor: default;\\n opacity: 0.4;\\n}\\n.hw-quick-reply-btn[data-tapped=true] {\\n background: var(--hw-primary);\\n color: white;\\n border-color: var(--hw-primary);\\n opacity: 1;\\n}\\n.hw-quick-replies[data-cancelled=true] .hw-quick-reply-btn {\\n border-color: 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-dots {\\n display: flex;\\n gap: 3px;\\n padding: 6px 2px;\\n width: fit-content;\\n}\\n.hw-typing-dot {\\n width: 6px;\\n height: 6px;\\n border-radius: 50%;\\n background: var(--hw-text-3);\\n animation: hw-typing-bounce 1.4s infinite;\\n}\\n.hw-typing-dot:nth-child(2) {\\n animation-delay: 0.2s;\\n}\\n.hw-typing-dot:nth-child(3) {\\n animation-delay: 0.4s;\\n}\\n@keyframes hw-typing-bounce {\\n 0%, 60%, 100% {\\n transform: translateY(0);\\n }\\n 30% {\\n transform: translateY(-4px);\\n }\\n}\\n.hw-streaming-cursor {\\n display: inline-block;\\n width: 2px;\\n height: 1em;\\n background: currentColor;\\n opacity: 0.6;\\n margin-left: 1px;\\n vertical-align: text-bottom;\\n animation: hw-cursor-blink 0.8s step-end infinite;\\n}\\n@keyframes hw-cursor-blink {\\n 50% {\\n opacity: 0;\\n }\\n}\\n.hw-link-preview {\\n display: flex;\\n flex-direction: column;\\n 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 max-width: min(100%, 340px);\\n margin: 0;\\n padding: 0;\\n border: 0;\\n border-radius: 0;\\n background: none;\\n box-shadow: none;\\n animation: hw-email-slide-in 0.25s ease-out;\\n}\\n@keyframes hw-email-slide-in {\\n from {\\n opacity: 0;\\n transform: translateY(8px);\\n }\\n to {\\n opacity: 1;\\n transform: translateY(0);\\n }\\n}\\n.hw-email-card-title {\\n font-size: 14px;\\n font-weight: 550;\\n color: var(--hw-text, #1a1a1a);\\n line-height: 1.3;\\n margin: 0 0 2px;\\n}\\n.hw-email-card-subtitle {\\n font-size: 12px;\\n color: var(--hw-text-2, #888);\\n line-height: 1.4;\\n margin: 0;\\n}\\n.hw-email-card-row {\\n max-width: 300px;\\n display: flex;\\n align-items: center;\\n gap: 6px;\\n margin-top: 9px;\\n padding: 3px 3px 3px 12px;\\n border-radius: 999px;\\n border: 1px solid var(--hw-border, rgba(0,0,0,0.1));\\n background: var(--hw-bg-subtle, #fafafa);\\n transition: border-color 0.15s, box-shadow 0.15s;\\n}\\n.hw-email-card-row:focus-within {\\n border-color: var(--hw-focus-border, rgba(0,0,0,0.2));\\n box-shadow: 0 0 0 2px var(--hw-focus-ring, rgba(0,0,0,0.06));\\n}\\n.hw-email-card-input {\\n flex: 1;\\n min-width: 0;\\n padding: 6px 0;\\n border: 0;\\n background: transparent;\\n color: var(--hw-text, #1a1a1a);\\n font: inherit;\\n font-size: 13px;\\n outline: none;\\n}\\n.hw-email-card-input::placeholder {\\n color: var(--hw-text-3, #999);\\n}\\n.hw-email-card-row:has(.hw-email-card-input--error) {\\n border-color: #ef4444;\\n}\\n.hw-email-card-submit {\\n flex: none;\\n display: grid;\\n place-items: center;\\n width: 28px;\\n height: 28px;\\n border: none;\\n border-radius: 50%;\\n background: var(--hw-brand, #0a0a0a);\\n color: var(--hw-on-brand, #fff);\\n cursor: pointer;\\n transition: opacity 0.15s, transform 0.15s;\\n}\\n.hw-email-card-submit:hover:not(:disabled) {\\n transform: scale(1.06);\\n}\\n.hw-email-card-submit:disabled {\\n opacity: 0.45;\\n cursor: default;\\n}\\n.hw-email-card--success {\\n display: flex;\\n align-items: center;\\n gap: 6px;\\n padding: 2px 0;\\n font-size: 13px;\\n color: var(--hw-text-2, #888);\\n animation: hw-email-slide-in 0.2s ease-out;\\n}\\n.hw-email-card--success svg {\\n flex-shrink: 0;\\n}\\n.hw-composer {\\n display: flex;\\n flex-direction: column;\\n padding: 12px 16px;\\n background: transparent;\\n flex-shrink: 0;\\n}\\n.hw-composer--compact {\\n padding: 8px 12px;\\n}\\n.hw-composer-box {\\n display: flex;\\n flex-direction: column;\\n border: 0;\\n box-shadow: inset 0 0 0 1px var(--hw-border);\\n border-radius: 16px;\\n overflow: hidden;\\n transition: border-color 0.2s;\\n background: var(--hw-bg);\\n}\\n.hw-composer-box:focus-within {\\n border-color: var(--hw-focus-border);\\n box-shadow: 0 0 0 3px var(--hw-focus-ring);\\n}\\n.hw-composer-input {\\n resize: none;\\n border: none;\\n padding: 12px 16px 4px;\\n font-size: 14px;\\n font-family: inherit;\\n line-height: 1.4;\\n outline: none;\\n min-height: 40px;\\n max-height: 220px;\\n background: transparent;\\n color: var(--hw-text);\\n field-sizing: content;\\n}\\n.hw-composer-input:focus {\\n outline: none;\\n}\\n.hw-composer-input:focus-visible {\\n outline: none;\\n}\\n.hw-composer-input::placeholder {\\n color: var(--hw-text-4);\\n}\\n.hw-composer-toolbar {\\n display: flex;\\n align-items: center;\\n justify-content: space-between;\\n padding: 4px 10px 10px;\\n}\\n.hw-composer-toolbar-left {\\n display: flex;\\n align-items: center;\\n gap: 4px;\\n}\\n.hw-composer-send {\\n width: 32px;\\n height: 32px;\\n border-radius: 50%;\\n border: none;\\n cursor: pointer;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n flex-shrink: 0;\\n transition:\\n background-color 140ms cubic-bezier(0.23, 1, 0.32, 1),\\n color 140ms cubic-bezier(0.23, 1, 0.32, 1),\\n transform 140ms cubic-bezier(0.23, 1, 0.32, 1);\\n}\\n.hw-composer-send:active:not(:disabled) {\\n transform: scale(0.9);\\n}\\n.hw-composer-send--active {\\n background: var(--hw-primary);\\n color: white;\\n}\\n.hw-composer-send--inactive {\\n background: var(--hw-border);\\n color: var(--hw-text-4);\\n cursor: default;\\n}\\n.hw-composer-send svg {\\n width: 14px;\\n height: 14px;\\n}\\n.hw-composer-charcount {\\n font-size: 11px;\\n color: var(--hw-text-3);\\n font-variant-numeric: tabular-nums;\\n opacity: 1;\\n transform: translateY(0);\\n transition:\\n color 180ms cubic-bezier(0.23, 1, 0.32, 1),\\n opacity 180ms cubic-bezier(0.23, 1, 0.32, 1),\\n transform 180ms cubic-bezier(0.23, 1, 0.32, 1);\\n}\\n@starting-style {\\n .hw-composer-charcount {\\n opacity: 0;\\n transform: translateY(3px);\\n }\\n}\\n.hw-composer-charcount--over {\\n color: #ef4444;\\n font-weight: 600;\\n}\\n@media (prefers-reduced-motion: reduce) {\\n .hw-composer-charcount {\\n transform: none;\\n transition: color 160ms ease, opacity 160ms ease;\\n }\\n @starting-style {\\n .hw-composer-charcount {\\n transform: none;\\n }\\n }\\n}\\n.hw-composer-previews {\\n display: flex;\\n gap: 6px;\\n padding: 8px 10px 0;\\n overflow-x: auto;\\n scrollbar-width: none;\\n}\\n.hw-composer-previews::-webkit-scrollbar {\\n display: none;\\n}\\n.hw-composer-preview {\\n position: relative;\\n width: 48px;\\n height: 48px;\\n border-radius: 8px;\\n overflow: hidden;\\n flex-shrink: 0;\\n background: var(--hw-border);\\n cursor: pointer;\\n}\\n.hw-composer-preview--error {\\n outline: 2px solid #ef4444;\\n outline-offset: -2px;\\n}\\n.hw-composer-preview-img {\\n width: 100%;\\n height: 100%;\\n object-fit: cover;\\n}\\n.hw-composer-preview-file {\\n width: 100%;\\n height: 100%;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n background: var(--hw-bg-subtle);\\n}\\n.hw-composer-preview-ext {\\n font-size: 10px;\\n font-weight: 700;\\n color: var(--hw-text-3);\\n text-transform: uppercase;\\n}\\n.hw-composer-preview-loader {\\n position: absolute;\\n inset: 0;\\n background: rgba(0, 0, 0, 0.35);\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n}\\n.hw-composer-preview-loader::after {\\n content: \\\"\\\";\\n width: 16px;\\n height: 16px;\\n border: 2px solid rgba(255, 255, 255, 0.3);\\n border-top-color: white;\\n border-radius: 50%;\\n animation: hw-spin 0.6s linear infinite;\\n}\\n@keyframes hw-spin {\\n to {\\n transform: rotate(360deg);\\n }\\n}\\n.hw-composer-preview-badge {\\n position: absolute;\\n top: 2px;\\n right: 2px;\\n width: 16px;\\n height: 16px;\\n border-radius: 50%;\\n background: #ef4444;\\n color: white;\\n font-size: 10px;\\n font-weight: 700;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n}\\n.hw-composer-preview-remove {\\n position: absolute;\\n top: 2px;\\n right: 2px;\\n width: 18px;\\n height: 18px;\\n border-radius: 50%;\\n border: none;\\n background: rgba(0, 0, 0, 0.55);\\n color: white;\\n cursor: pointer;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n opacity: 0;\\n transition: opacity 0.15s;\\n}\\n.hw-composer-preview-remove svg {\\n width: 10px;\\n height: 10px;\\n}\\n.hw-composer-preview:hover .hw-composer-preview-remove {\\n opacity: 1;\\n}\\n.hw-composer-attach {\\n width: 28px;\\n height: 28px;\\n border: none;\\n background: none;\\n color: var(--hw-text-3);\\n cursor: pointer;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n border-radius: 6px;\\n opacity: 0.7;\\n transition: opacity 0.15s;\\n}\\n.hw-composer-attach:hover {\\n opacity: 1;\\n}\\n.hw-composer-attach svg {\\n width: 16px;\\n height: 16px;\\n}\\n.hw-msg-images {\\n display: flex;\\n flex-direction: column;\\n gap: 4px;\\n margin-bottom: 4px;\\n}\\n.hw-msg-image-link {\\n display: block;\\n border-radius: 14px;\\n overflow: hidden;\\n line-height: 0;\\n}\\n.hw-msg-image {\\n max-width: 140px;\\n max-height: 80px;\\n object-fit: cover;\\n border-radius: 8px;\\n outline: 1px solid rgba(0, 0, 0, 0.08);\\n outline-offset: -1px;\\n}\\n.hw-msg-files {\\n display: flex;\\n flex-direction: column;\\n gap: 4px;\\n margin-top: 4px;\\n}\\n.hw-msg-file {\\n display: flex;\\n align-items: center;\\n gap: 8px;\\n padding: 8px 12px;\\n border-radius: 10px;\\n background: var(--hw-bg-subtle);\\n text-decoration: none;\\n color: var(--hw-text);\\n transition: background 0.15s;\\n}\\n.hw-msg-file:hover {\\n background: var(--hw-border);\\n}\\n.hw-msg-file-icon {\\n flex-shrink: 0;\\n width: 20px;\\n height: 20px;\\n color: var(--hw-text-3);\\n}\\n.hw-msg-file-icon svg {\\n width: 100%;\\n height: 100%;\\n}\\n.hw-msg-file-info {\\n display: flex;\\n flex-direction: column;\\n min-width: 0;\\n}\\n.hw-msg-file-name {\\n font-size: 13px;\\n font-weight: 500;\\n white-space: nowrap;\\n overflow: hidden;\\n text-overflow: ellipsis;\\n}\\n.hw-msg-file-size {\\n font-size: 11px;\\n color: var(--hw-text-3);\\n}\\n.hw-msg-image-link {\\n cursor: pointer;\\n border: none;\\n padding: 0;\\n background: none;\\n display: block;\\n line-height: 0;\\n}\\n.hw-hover-preview {\\n position: fixed;\\n z-index: 2147483001;\\n padding: 6px;\\n border-radius: 14px;\\n background: white;\\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18), 0 0 0 1px rgba(0, 0, 0, 0.06);\\n cursor: pointer;\\n animation: hw-hover-in 0.15s ease-out;\\n}\\n@media (prefers-color-scheme: dark) {\\n .hw-hover-preview {\\n background: #1c1c1e;\\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255, 255, 255, 0.08);\\n }\\n}\\n@keyframes hw-hover-in {\\n from {\\n opacity: 0;\\n transform: scale(0.96) translateY(4px);\\n }\\n to {\\n opacity: 1;\\n transform: scale(1) translateY(0);\\n }\\n}\\n.hw-hover-preview-img {\\n width: 100%;\\n max-height: 200px;\\n object-fit: contain;\\n border-radius: 10px;\\n display: block;\\n outline: 1px solid rgba(0, 0, 0, 0.08);\\n outline-offset: -1px;\\n}\\n.hw-hover-preview--doc {\\n display: flex;\\n align-items: center;\\n gap: 10px;\\n padding: 10px 14px;\\n}\\n.hw-hover-preview-doc-icon {\\n width: 28px;\\n height: 28px;\\n flex-shrink: 0;\\n}\\n.hw-hover-preview-doc-icon svg {\\n width: 100%;\\n height: 100%;\\n}\\n.hw-hover-preview-doc-info {\\n display: flex;\\n flex-direction: column;\\n min-width: 0;\\n}\\n.hw-hover-preview-doc-name {\\n font-size: 13px;\\n font-weight: 500;\\n color: var(--hw-text);\\n white-space: nowrap;\\n overflow: hidden;\\n text-overflow: ellipsis;\\n}\\n.hw-hover-preview-doc-hint {\\n font-size: 11px;\\n color: var(--hw-text-3);\\n}\\n.hw-event {\\n display: flex;\\n justify-content: center;\\n padding: 8px 16px;\\n}\\n.hw-event-text {\\n font-size: 12px;\\n color: var(--hw-text-3);\\n text-align: center;\\n}\\n.hw-event--card {\\n justify-content: flex-start;\\n align-items: center;\\n gap: 10px;\\n background: var(--hw-bg-subtle);\\n padding: 10px 14px;\\n border-radius: 12px;\\n margin: 4px 16px;\\n}\\n.hw-event-avatar {\\n width: 32px;\\n height: 32px;\\n border-radius: 50%;\\n background: var(--hw-agent-bg, var(--hw-agent-bg-default, var(--hw-bg-hover, #e0e0e0)));\\n color: var(--hw-text-2, #555);\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n font-size: 11px;\\n font-weight: 600;\\n flex-shrink: 0;\\n overflow: hidden;\\n}\\n.hw-event-avatar-img {\\n width: 100%;\\n height: 100%;\\n object-fit: cover;\\n}\\n.hw-event-avatar .hw-agent-img {\\n object-fit: var(--hw-agent-fit, var(--hw-agent-fit-default, cover));\\n padding: var(--hw-agent-pad, var(--hw-agent-pad-default, 0));\\n box-sizing: border-box;\\n}\\n.hw-event-body {\\n font-size: 13px;\\n line-height: 1.3;\\n}\\n.hw-event-name {\\n font-weight: 600;\\n color: var(--hw-text);\\n}\\n.hw-event-action {\\n color: var(--hw-text-2);\\n}\\n.hw-resolved-banner {\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n padding: 12px 16px;\\n border-top: 1px solid var(--hw-border);\\n background: var(--hw-bg-subtle);\\n color: var(--hw-text-2);\\n font-size: 13px;\\n flex-shrink: 0;\\n}\\n.hw-new {\\n flex: 1;\\n display: flex;\\n flex-direction: column;\\n background: var(--hw-bg-subtle);\\n}\\n.hw-new-body {\\n flex: 1;\\n display: flex;\\n flex-direction: column;\\n align-items: center;\\n justify-content: center;\\n padding: 32px 24px;\\n text-align: center;\\n}\\n.hw-new-welcome {\\n flex: 1;\\n padding: 16px 20px;\\n overflow-y: auto;\\n}\\n.hw-new-heading {\\n font-size: 17px;\\n font-weight: 600;\\n color: var(--hw-text);\\n margin-bottom: 6px;\\n}\\n.hw-new-desc {\\n font-size: 13px;\\n color: var(--hw-text-2);\\n margin-bottom: 24px;\\n}\\n.hw-powered {\\n text-align: center;\\n padding: 8px;\\n font-size: 11px;\\n color: var(--hw-text-4);\\n flex-shrink: 0;\\n}\\n.hw-powered a {\\n color: var(--hw-text-2);\\n text-decoration: none;\\n font-weight: 500;\\n}\\n.hw-powered a:hover {\\n color: var(--hw-text);\\n}\\n@media (max-width: 479px) {\\n .hw-widget {\\n bottom: 16px;\\n right: 16px;\\n left: auto;\\n }\\n .hw-window {\\n position: fixed;\\n top: 0;\\n left: 0;\\n right: 0;\\n bottom: 0;\\n width: 100%;\\n height: var(--hw-visible-height, 100%);\\n border-radius: 0;\\n animation: hw-mob-up 0.3s cubic-bezier(0.22, 1, 0.36, 1);\\n }\\n .hw-window--closing {\\n animation: hw-mob-down 0.2s ease forwards;\\n }\\n @keyframes hw-mob-up {\\n from {\\n opacity: 0;\\n transform: translateY(100%);\\n }\\n to {\\n opacity: 1;\\n transform: translateY(0);\\n }\\n }\\n @keyframes hw-mob-down {\\n from {\\n opacity: 1;\\n transform: translateY(0);\\n }\\n to {\\n opacity: 0;\\n transform: translateY(100%);\\n }\\n }\\n .hw-hero {\\n padding-top: calc(20px + env(safe-area-inset-top, 0px));\\n }\\n .hw-header {\\n padding-top: env(safe-area-inset-top, 0px);\\n }\\n .hw-tabs {\\n padding-bottom: env(safe-area-inset-bottom, 0px);\\n }\\n .hw-composer {\\n padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));\\n }\\n .hw-powered {\\n padding-bottom: calc(5px + env(safe-area-inset-bottom, 0px));\\n }\\n .hw-header-close,\\n .hw-header-back,\\n .hw-header-action {\\n width: 34px;\\n height: 34px;\\n }\\n .hw-composer-send {\\n width: 40px;\\n height: 40px;\\n }\\n .hw-window ~ .hw-bubble {\\n display: none;\\n }\\n .hw-messages {\\n padding: 12px 14px;\\n }\\n .hw-msg {\\n max-width: 82%;\\n }\\n .hw-msg--ai {\\n max-width: 100%;\\n }\\n}\\n.hw-preview {\\n position: absolute;\\n bottom: calc(100% + 12px);\\n right: 0;\\n width: 300px;\\n max-width: calc(100vw - 40px);\\n background: var(--hw-bg);\\n border: 1px solid var(--hw-border);\\n border-radius: 16px;\\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12), 0 2px 8px rgba(0, 0, 0, 0.06);\\n animation: hw-preview-in 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);\\n overflow: hidden;\\n cursor: pointer;\\n transition: transform 0.15s, box-shadow 0.15s;\\n}\\n.hw-preview.hw-preview--anchored {\\n position: static;\\n bottom: auto;\\n right: auto;\\n width: 100%;\\n max-width: 100%;\\n}\\n.hw-preview.hw-preview--anchored .hw-preview-avatar {\\n background: none;\\n}\\n.hw-preview.hw-preview--anchored .hw-preview-avatar img,\\n.hw-preview.hw-preview--anchored .hw-preview-avatar svg {\\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-avatar img {\\n width: 100%;\\n height: 100%;\\n object-fit: cover;\\n display: block;\\n}\\n.hw-preview-name {\\n font-size: 13px;\\n font-weight: 600;\\n color: var(--hw-text);\\n flex: 1;\\n}\\n.hw-preview-close {\\n width: 24px;\\n height: 24px;\\n border: none;\\n background: transparent;\\n color: var(--hw-text-3);\\n cursor: pointer;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n border-radius: 50%;\\n transition: background 0.15s, color 0.15s;\\n flex-shrink: 0;\\n}\\n.hw-preview-close:hover {\\n background: var(--hw-bg-subtle);\\n color: var(--hw-text-2);\\n}\\n.hw-preview-close:active {\\n transform: scale(0.90);\\n transition:\\n transform 0.14s cubic-bezier(0.23, 1, 0.32, 1),\\n background 0.15s,\\n color 0.15s;\\n}\\n.hw-preview-close svg {\\n width: 12px;\\n height: 12px;\\n}\\n.hw-preview-body {\\n padding: 4px 14px;\\n font-size: 14px;\\n line-height: 1.45;\\n color: var(--hw-text-2);\\n}\\n.hw-preview-body:first-of-type {\\n padding-top: 8px;\\n}\\n.hw-preview-body:last-child {\\n padding-bottom: 14px;\\n}\\n.hw-preview-footer {\\n margin-top: 2px;\\n padding: 8px 14px 12px;\\n border-top: 1px solid var(--hw-border);\\n font-size: 11px;\\n line-height: 1.3;\\n color: var(--hw-text-2);\\n opacity: 0.65;\\n}\\n.hw-preview-prompt {\\n padding: 2px 14px 6px;\\n font-size: 14px;\\n font-weight: 500;\\n color: var(--hw-text-1);\\n}\\n.hw-preview-quick-replies {\\n 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-stack.hw-preview-stack--anchored {\\n position: static;\\n bottom: auto;\\n right: auto;\\n width: 100%;\\n}\\n.hw-preview--announcement {\\n width: 340px;\\n}\\n.hw-preview--announcement .hw-preview-body--title {\\n font-weight: 600;\\n color: var(--hw-text);\\n font-size: 15px;\\n line-height: 1.3;\\n padding-top: 10px;\\n}\\n.hw-preview--announcement .hw-preview-body--desc {\\n font-size: 13px;\\n color: var(--hw-text-2);\\n line-height: 1.5;\\n padding-bottom: 16px;\\n}\\n.hw-announcement-badge {\\n display: inline-block;\\n margin: 8px 14px 0;\\n padding: 2px 8px;\\n font-size: 10px;\\n font-weight: 700;\\n text-transform: uppercase;\\n letter-spacing: 0.04em;\\n color: var(--hw-primary);\\n background: color-mix(in srgb, var(--hw-primary) 10%, transparent);\\n border-radius: 4px;\\n}\\n.hw-whats-new {\\n border-radius: 14px;\\n background: var(--hw-bg);\\n border: 0;\\n box-shadow: inset 0 0 0 1px var(--hw-border);\\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06), 0 0 0 1px rgba(0, 0, 0, 0.03);\\n overflow: hidden;\\n}\\n.hw-whats-new-header {\\n display: flex;\\n align-items: center;\\n justify-content: space-between;\\n padding: 12px 14px 0;\\n}\\n.hw-whats-new-title {\\n font-size: 12px;\\n font-weight: 600;\\n color: var(--hw-text-2);\\n}\\n.hw-whats-new-view-all {\\n font-size: 11px;\\n font-weight: 500;\\n color: var(--hw-primary);\\n background: none;\\n border: none;\\n cursor: pointer;\\n padding: 0;\\n font-family: inherit;\\n}\\n.hw-whats-new-view-all:hover {\\n opacity: 0.8;\\n}\\n.hw-whats-new-list {\\n display: flex;\\n flex-direction: column;\\n}\\n.hw-whats-new-item {\\n display: flex;\\n flex-direction: column;\\n gap: 2px;\\n width: 100%;\\n padding: 10px 14px;\\n border: none;\\n border-bottom: 1px solid var(--hw-border);\\n background: none;\\n cursor: pointer;\\n text-align: left;\\n font-family: inherit;\\n color: var(--hw-text);\\n transition: background-color 140ms ease;\\n}\\n.hw-whats-new-item:last-child {\\n border-bottom: none;\\n}\\n.hw-whats-new-item:hover {\\n background: rgba(0, 0, 0, 0.03);\\n}\\n.hw-whats-new-item-top {\\n display: flex;\\n align-items: center;\\n gap: 8px;\\n}\\n.hw-whats-new-badge {\\n font-size: 10px;\\n font-weight: 700;\\n text-transform: uppercase;\\n letter-spacing: 0.04em;\\n color: var(--hw-primary);\\n}\\n.hw-whats-new-time {\\n font-size: 11px;\\n color: var(--hw-text-3);\\n margin-left: auto;\\n}\\n.hw-whats-new-item-title {\\n font-size: 13px;\\n font-weight: 600;\\n color: var(--hw-text);\\n line-height: 1.3;\\n display: flex;\\n align-items: baseline;\\n gap: 8px;\\n}\\n.hw-whats-new-time-inline {\\n font-size: 11px;\\n font-weight: 400;\\n color: var(--hw-text-3);\\n margin-left: auto;\\n flex-shrink: 0;\\n}\\n.hw-whats-new-item-body {\\n font-size: 12px;\\n color: var(--hw-text-2);\\n line-height: 1.4;\\n}\\n.hw-tabs-dot {\\n position: absolute;\\n top: -2px;\\n right: -6px;\\n width: 8px;\\n height: 8px;\\n border-radius: 50%;\\n background: var(--hw-primary);\\n animation: hw-badge-pop 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);\\n}\\n.hw-bubble-badge-dot {\\n display: block;\\n width: 8px;\\n height: 8px;\\n border-radius: 50%;\\n background: white;\\n}\\n.hw-content-search {\\n padding: 10px 16px;\\n}\\n.hw-content-search-box {\\n display: flex;\\n align-items: center;\\n gap: 8px;\\n padding: 8px 12px;\\n background: var(--hw-bg);\\n border: 1px solid var(--hw-border-md);\\n border-radius: 10px;\\n transition: border-color 0.15s, box-shadow 0.15s;\\n}\\n.hw-content-search-box:focus-within {\\n border-color: var(--hw-focus-border);\\n box-shadow: 0 0 0 3px var(--hw-focus-ring);\\n}\\n.hw-content-search-input {\\n flex: 1;\\n border: none !important;\\n outline: none !important;\\n box-shadow: none !important;\\n background: none;\\n font-size: 13px;\\n color: var(--hw-text-1);\\n font-family: inherit;\\n line-height: 1;\\n -webkit-appearance: none;\\n}\\n.hw-content-search-input:focus,\\n.hw-content-search-input:focus-visible {\\n outline: none !important;\\n box-shadow: none !important;\\n border: none !important;\\n}\\n.hw-content-search-input::placeholder {\\n color: var(--hw-text-3);\\n}\\n.hw-content-search-icon {\\n width: 15px;\\n height: 15px;\\n color: var(--hw-text-3);\\n flex-shrink: 0;\\n}\\n.hw-content-list {\\n display: flex;\\n flex-direction: column;\\n height: 100%;\\n}\\n.hw-content-entries {\\n flex: 1;\\n overflow-y: auto;\\n overscroll-behavior: contain;\\n}\\n.hw-content-entry {\\n display: block;\\n width: 100%;\\n padding: 14px 16px;\\n border: none;\\n border-bottom: 1px solid var(--hw-border);\\n background: none;\\n cursor: pointer;\\n text-align: left;\\n transition: background-color 0.15s ease;\\n -webkit-tap-highlight-color: transparent;\\n}\\n.hw-content-entry:hover {\\n background: var(--hw-bg-hover);\\n}\\n.hw-content-entry:active {\\n background: var(--hw-border);\\n}\\n.hw-content-entry:last-child {\\n border-bottom: none;\\n}\\n.hw-content-entry-main {\\n display: flex;\\n align-items: center;\\n gap: 12px;\\n}\\n.hw-content-entry-text {\\n flex: 1;\\n min-width: 0;\\n display: flex;\\n flex-direction: column;\\n gap: 3px;\\n}\\n.hw-content-entry-title {\\n font-size: 14px;\\n font-weight: 600;\\n color: var(--hw-text-1);\\n line-height: 1.3;\\n}\\n.hw-content-entry-desc {\\n font-size: 13px;\\n color: var(--hw-text-2);\\n line-height: 1.4;\\n display: -webkit-box;\\n -webkit-line-clamp: 2;\\n -webkit-box-orient: vertical;\\n overflow: hidden;\\n}\\n.hw-content-entry-meta {\\n display: flex;\\n align-items: center;\\n gap: 6px;\\n margin-top: 2px;\\n}\\n.hw-content-entry-badge {\\n font-size: 11px;\\n font-weight: 500;\\n color: var(--hw-text-3);\\n background: var(--hw-bg-hover);\\n padding: 1px 6px;\\n border-radius: 4px;\\n}\\n.hw-content-entry-date {\\n font-size: 11px;\\n color: var(--hw-text-3);\\n}\\n.hw-content-entry-chevron {\\n width: 16px;\\n height: 16px;\\n color: var(--hw-text-3);\\n flex-shrink: 0;\\n opacity: 0.5;\\n}\\n.hw-content-detail {\\n padding: 16px;\\n overflow-y: auto;\\n overscroll-behavior: contain;\\n flex: 1;\\n min-height: 0;\\n}\\n.hw-content-detail-header {\\n margin-bottom: 16px;\\n}\\n.hw-content-detail-title {\\n font-size: 17px;\\n font-weight: 700;\\n color: var(--hw-text-1);\\n margin: 0 0 6px;\\n line-height: 1.3;\\n display: flex;\\n align-items: center;\\n gap: 6px;\\n}\\n.hw-content-detail-meta {\\n display: flex;\\n align-items: center;\\n gap: 8px;\\n flex-wrap: wrap;\\n}\\n.hw-content-detail-date {\\n font-size: 12px;\\n color: var(--hw-text-3);\\n}\\n.hw-content-detail-body {\\n font-size: 14px;\\n line-height: 1.6;\\n color: var(--hw-text-1);\\n}\\n.hw-markdown h1 {\\n font-size: 17px;\\n font-weight: 700;\\n margin: 0;\\n}\\n.hw-markdown h2 {\\n font-size: 15px;\\n font-weight: 600;\\n margin: 0;\\n}\\n.hw-markdown h3 {\\n font-size: 14px;\\n font-weight: 600;\\n margin: 0;\\n}\\n.hw-markdown p {\\n margin: 0;\\n}\\n.hw-markdown p:empty,\\n.hw-markdown div:empty,\\n.hw-markdown p:has(> br:only-child),\\n.hw-markdown div:has(> br:only-child) {\\n display: none;\\n}\\n.hw-markdown > * + * {\\n margin-top: 12px;\\n}\\n.hw-markdown > * + h1,\\n.hw-markdown > * + h2 {\\n margin-top: 20px;\\n}\\n.hw-markdown > * + h3 {\\n margin-top: 16px;\\n}\\n.hw-markdown > h1 + *,\\n.hw-markdown > h2 + *,\\n.hw-markdown > h3 + * {\\n margin-top: 8px;\\n}\\n.hw-markdown > *:first-child {\\n margin-top: 0;\\n}\\n.hw-markdown > *:last-child {\\n margin-bottom: 0;\\n}\\n.hw-markdown > br {\\n display: none;\\n}\\n.hw-markdown ul,\\n.hw-markdown ol {\\n margin: 0;\\n padding-left: 20px;\\n}\\n.hw-markdown li {\\n margin: 4px 0;\\n}\\n.hw-markdown code {\\n font-family:\\n ui-monospace,\\n \\\"SF Mono\\\",\\n monospace;\\n font-size: 12px;\\n background: var(--hw-bg-hover);\\n padding: 1px 5px;\\n border-radius: 4px;\\n}\\n.hw-table-wrap {\\n margin: 10px 0;\\n overflow-x: auto;\\n border: 1px solid var(--hw-border, rgba(0, 0, 0, 0.08));\\n border-radius: 10px;\\n}\\n.hw-table {\\n width: 100%;\\n border-collapse: collapse;\\n font-size: 13px;\\n}\\n.hw-table th {\\n text-align: left;\\n font-weight: 600;\\n font-size: 12px;\\n padding: 8px 12px;\\n background: var(--hw-bg-hover, #f5f5f4);\\n border-bottom: 1px solid var(--hw-border, rgba(0, 0, 0, 0.08));\\n}\\n.hw-table td {\\n padding: 8px 12px;\\n border-bottom: 1px solid var(--hw-border, rgba(0, 0, 0, 0.06));\\n vertical-align: top;\\n}\\n.hw-table tbody tr:last-child td {\\n border-bottom: none;\\n}\\n.hw-code {\\n margin: 10px 0;\\n border-radius: 10px;\\n overflow: hidden;\\n border: 1px solid var(--hw-border, rgba(0, 0, 0, 0.08));\\n background: var(--hw-bg-hover, #f5f5f4);\\n font-family:\\n ui-monospace,\\n \\\"SF Mono\\\",\\n \\\"Menlo\\\",\\n monospace;\\n}\\n.hw-code-header {\\n display: flex;\\n align-items: center;\\n justify-content: space-between;\\n gap: 10px;\\n padding: 7px 8px 7px 12px;\\n font-size: 11px;\\n color: var(--hw-text-2, #6b7280);\\n background: rgba(0, 0, 0, 0.03);\\n border-bottom: 1px solid var(--hw-border, rgba(0, 0, 0, 0.06));\\n}\\n.hw-code-lang {\\n text-transform: lowercase;\\n letter-spacing: 0.02em;\\n font-weight: 500;\\n}\\n.hw-code-actions {\\n display: inline-flex;\\n align-items: center;\\n gap: 1px;\\n}\\n.hw-code-action {\\n position: relative;\\n display: inline-flex;\\n align-items: center;\\n justify-content: center;\\n width: 22px;\\n height: 22px;\\n padding: 0;\\n font-family: inherit;\\n color: var(--hw-text-2, #6b7280);\\n background: transparent;\\n border: 1px solid transparent;\\n border-radius: 6px;\\n cursor: pointer;\\n opacity: 0.62;\\n transition:\\n background 120ms ease,\\n color 120ms ease,\\n opacity 120ms ease,\\n scale 120ms ease;\\n}\\n.hw-code-action:hover {\\n color: var(--hw-text, #111);\\n background: rgba(0, 0, 0, 0.06);\\n opacity: 1;\\n}\\n.hw-code-action:active {\\n scale: 0.96;\\n}\\n.hw-code-action svg {\\n width: 13px;\\n height: 13px;\\n}\\n.hw-code-copy-icon,\\n.hw-code-check-icon {\\n position: absolute;\\n inset: 50% auto auto 50%;\\n transition:\\n opacity 180ms cubic-bezier(0.2, 0, 0, 1),\\n scale 180ms cubic-bezier(0.2, 0, 0, 1),\\n filter 180ms cubic-bezier(0.2, 0, 0, 1);\\n translate: -50% -50%;\\n}\\n.hw-code-check-icon {\\n filter: blur(4px);\\n opacity: 0;\\n scale: 0.25;\\n}\\n.hw-code-copy--copied .hw-code-copy-icon {\\n filter: blur(4px);\\n opacity: 0;\\n scale: 0.25;\\n}\\n.hw-code-copy--copied .hw-code-check-icon {\\n filter: blur(0);\\n opacity: 1;\\n scale: 1;\\n}\\n.hw-code-copy-label {\\n position: absolute;\\n width: 1px;\\n height: 1px;\\n overflow: hidden;\\n clip: rect(0, 0, 0, 0);\\n white-space: nowrap;\\n}\\n.hw-code-copy--copied {\\n color: #16a34a;\\n}\\n.hw-code-copy--failed {\\n color: #dc2626;\\n}\\n.hw-code pre {\\n margin: 0;\\n padding: 10px 12px;\\n background: transparent;\\n border-radius: 0;\\n overflow-x: auto;\\n max-width: 100%;\\n max-height: 320px;\\n scrollbar-color: rgba(0, 0, 0, 0.22) transparent;\\n scrollbar-width: thin;\\n}\\n.hw-code pre::-webkit-scrollbar {\\n width: 10px;\\n height: 10px;\\n}\\n.hw-code pre::-webkit-scrollbar-track {\\n background: transparent;\\n}\\n.hw-code pre::-webkit-scrollbar-thumb {\\n background: rgba(0, 0, 0, 0.18);\\n background-clip: content-box;\\n border: 3px solid transparent;\\n border-radius: 999px;\\n}\\n.hw-code pre::-webkit-scrollbar-thumb:hover {\\n background: rgba(0, 0, 0, 0.28);\\n background-clip: content-box;\\n}\\n.hw-code pre code {\\n display: block;\\n background: transparent;\\n padding: 0;\\n font-size: 12px;\\n line-height: 1.55;\\n white-space: pre;\\n color: var(--hw-text, #111);\\n}\\n@media (prefers-color-scheme: dark) {\\n .hw-code {\\n background: rgba(255, 255, 255, 0.04);\\n border-color: rgba(255, 255, 255, 0.08);\\n }\\n .hw-code-header {\\n background: rgba(255, 255, 255, 0.03);\\n border-bottom-color: rgba(255, 255, 255, 0.06);\\n }\\n .hw-code-action:hover,\\n .hw-code-action:focus-visible {\\n background: rgba(255, 255, 255, 0.08);\\n }\\n .hw-code pre {\\n scrollbar-color: rgba(255, 255, 255, 0.26) transparent;\\n }\\n .hw-code pre::-webkit-scrollbar-thumb {\\n background: rgba(255, 255, 255, 0.22);\\n background-clip: content-box;\\n }\\n .hw-code pre::-webkit-scrollbar-thumb:hover {\\n background: rgba(255, 255, 255, 0.32);\\n background-clip: content-box;\\n }\\n}\\n.hw-markdown pre {\\n margin: 8px 0;\\n padding: 10px 12px;\\n background: var(--hw-bg-hover);\\n border-radius: 8px;\\n overflow-x: auto;\\n max-width: 100%;\\n}\\n.hw-markdown pre code {\\n display: block;\\n background: transparent;\\n padding: 0;\\n border-radius: 0;\\n font-size: 12px;\\n line-height: 1.5;\\n white-space: pre;\\n word-break: normal;\\n color: inherit;\\n}\\n.hw-msg-bubble pre {\\n margin: 6px 0;\\n padding: 8px 10px;\\n background: rgba(0, 0, 0, 0.06);\\n border-radius: 6px;\\n overflow-x: auto;\\n max-width: 100%;\\n}\\n.hw-msg-bubble pre code {\\n background: transparent;\\n padding: 0;\\n font-size: 12px;\\n line-height: 1.5;\\n white-space: pre;\\n}\\n.hw-msg-bubble .hw-code pre {\\n margin: 0;\\n padding: 10px 12px;\\n background: transparent;\\n border-radius: 0;\\n}\\n.hw-msg-bubble .hw-code pre code {\\n background: transparent;\\n padding: 0;\\n font-size: 12px;\\n line-height: 1.55;\\n}\\n.hw-msg--team .hw-msg-bubble pre,\\n.hw-msg--visitor .hw-msg-bubble pre {\\n background: rgba(255, 255, 255, 0.12);\\n}\\n.hw-markdown blockquote {\\n margin: 0 0 12px;\\n padding: 8px 12px;\\n border-left: 3px solid var(--hw-border);\\n color: var(--hw-text-2);\\n font-style: italic;\\n}\\n.hw-markdown a {\\n color: var(--hw-primary);\\n text-decoration: underline;\\n text-underline-offset: 2px;\\n}\\n.hw-markdown img {\\n max-width: 100%;\\n border-radius: 8px;\\n margin: 8px 0;\\n outline: 1px solid rgba(0, 0, 0, 0.08);\\n outline-offset: -1px;\\n}\\n.hw-markdown hr {\\n border: none;\\n border-top: 1px solid var(--hw-border);\\n margin: 16px 0;\\n}\\n.hw-content-empty {\\n display: flex;\\n flex-direction: column;\\n align-items: center;\\n justify-content: center;\\n padding: 40px 20px;\\n text-align: center;\\n}\\n.hw-content-empty-title {\\n font-size: 14px;\\n font-weight: 600;\\n color: var(--hw-text-1);\\n margin-bottom: 4px;\\n}\\n.hw-content-empty-desc {\\n font-size: 12px;\\n color: var(--hw-text-3);\\n}\\n.hw-content-loading {\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n padding: 40px 20px;\\n}\\n.hw-content-load-more {\\n display: block;\\n width: 100%;\\n padding: 10px;\\n border: none;\\n background: none;\\n color: var(--hw-primary);\\n font-size: 13px;\\n font-weight: 500;\\n cursor: pointer;\\n text-align: center;\\n}\\n.hw-content-load-more:hover {\\n background: var(--hw-bg-hover);\\n}\\n.hw-content-load-more:disabled {\\n opacity: 0.5;\\n cursor: default;\\n}\\n@media (hover: none) {\\n .hw-composer-preview-remove {\\n opacity: 0.7;\\n }\\n}\\n.hw-composer--dragging .hw-composer-box {\\n border-color: var(--hw-primary);\\n background: color-mix(in srgb, var(--hw-primary) 4%, transparent);\\n}\\n.hw-composer-drop-overlay {\\n position: absolute;\\n inset: 0;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n background: color-mix(in srgb, var(--hw-bg) 90%, transparent);\\n border: 2px dashed var(--hw-primary);\\n border-radius: 12px;\\n z-index: 10;\\n pointer-events: none;\\n animation: hw-drop-pulse 1.5s ease-in-out infinite;\\n}\\n.hw-composer-drop-text {\\n font-size: 13px;\\n font-weight: 500;\\n color: var(--hw-primary);\\n}\\n@keyframes hw-drop-pulse {\\n 0%, 100% {\\n opacity: 0.8;\\n }\\n 50% {\\n opacity: 1;\\n }\\n}\\n.hw-disconnect {\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n gap: 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.hw-widget[data-hw-placement=docked] {\\n --hw-dock-width: 600px;\\n --hw-dock-bar-width: 480px;\\n --hw-dock-inset: 24px;\\n --hw-bar-max-height: 148px;\\n --hw-dock-surface: #ffffff;\\n --hw-dock-on-surface: #111111;\\n --hw-dock-pill-bg: rgba(44, 44, 48, 0.66);\\n --hw-dock-pill-fg: rgba(255, 255, 255, 0.94);\\n --hw-dock-pill-border: rgba(255, 255, 255, 0.14);\\n}\\n.hw-widget[data-hw-placement=docked] {\\n z-index: 2147483000;\\n}\\n.hw-widget[data-hw-placement=docked] .hw-dock {\\n position: fixed;\\n left: 0;\\n right: 0;\\n bottom: var(--hw-dock-inset);\\n z-index: 2147483000;\\n display: flex;\\n flex-direction: column;\\n align-items: center;\\n pointer-events: none;\\n}\\n.hw-widget[data-hw-placement=docked] .hw-dock > * {\\n pointer-events: auto;\\n}\\n.hw-dock-suggestions {\\n display: flex;\\n flex-direction: column;\\n align-items: flex-start;\\n gap: 9px;\\n width: var(--hw-dock-bar-width, var(--hw-dock-width));\\n max-width: calc(100vw - 32px);\\n margin-bottom: 14px;\\n}\\n.hw-dock-pill-row {\\n align-self: flex-start;\\n display: inline-flex;\\n align-items: center;\\n gap: 4px;\\n animation: hw-dock-pill-in 0.42s cubic-bezier(0.2, 0.9, 0.3, 1) both;\\n}\\n.hw-dock-pill-dismiss {\\n display: inline-flex;\\n align-items: center;\\n justify-content: center;\\n width: 20px;\\n height: 20px;\\n flex-shrink: 0;\\n padding: 0;\\n border: 0;\\n background: none;\\n color: var(--hw-dock-pill-fg);\\n cursor: pointer;\\n align-self: flex-start;\\n margin-top: 8px;\\n opacity: 0;\\n transform: scale(0.85);\\n transition:\\n opacity 0.12s linear,\\n transform 0.12s cubic-bezier(0.25, 1, 0.5, 1),\\n color 0.12s linear;\\n}\\n.hw-dock-pill-dismiss svg {\\n width: 11px;\\n height: 11px;\\n}\\n.hw-dock-suggestions:hover .hw-dock-pill-dismiss,\\n.hw-dock-suggestions:focus-within .hw-dock-pill-dismiss {\\n opacity: 1;\\n transform: none;\\n}\\n.hw-dock-pill-dismiss:hover {\\n color: var(--hw-dock-on-surface);\\n}\\n@media (prefers-reduced-motion: reduce) {\\n .hw-dock-pill-dismiss {\\n transition: none;\\n }\\n}\\n@media (hover: none) {\\n .hw-dock-pill-dismiss {\\n opacity: 1;\\n transform: none;\\n }\\n}\\n.hw-dock-pill {\\n align-self: flex-start;\\n padding: 10px 18px;\\n border: 1px solid var(--hw-dock-pill-border, transparent);\\n border-radius: 999px;\\n cursor: pointer;\\n font: inherit;\\n font-size: 14px;\\n font-weight: 500;\\n text-align: left;\\n background: var(--hw-dock-pill-bg);\\n color: var(--hw-dock-pill-fg);\\n backdrop-filter: blur(10px) saturate(1.2);\\n -webkit-backdrop-filter: blur(10px) saturate(1.2);\\n box-shadow: 0 4px 14px -8px rgba(12, 11, 10, 0.28);\\n transition:\\n background 0.16s,\\n border-color 0.16s,\\n transform 0.16s;\\n}\\n.hw-dock-pill {\\n backdrop-filter: blur(18px);\\n -webkit-backdrop-filter: blur(18px);\\n}\\n.hw-dock-pill:hover {\\n background: color-mix(in srgb, var(--hw-dock-pill-bg) 100%, var(--hw-dock-on-surface) 8%);\\n border-color: color-mix(in srgb, var(--hw-dock-pill-border) 100%, var(--hw-dock-on-surface) 10%);\\n transform: translateX(3px);\\n}\\n@keyframes hw-dock-pill-in {\\n from {\\n opacity: 0;\\n transform: translateY(10px) scale(0.97);\\n }\\n to {\\n opacity: 1;\\n transform: none;\\n }\\n}\\n.hw-dock-bar {\\n display: flex;\\n align-items: flex-end;\\n gap: 10px;\\n width: var(--hw-dock-bar-width, var(--hw-dock-width));\\n max-width: calc(100vw - 32px);\\n min-height: 52px;\\n padding: 10px 10px 10px 18px;\\n border: 0;\\n border-radius: 26px;\\n background: var(--hw-dock-surface);\\n color: var(--hw-dock-on-surface);\\n box-shadow:\\n inset 0 1px 0 color-mix(in srgb, var(--hw-dock-on-surface) 9%, transparent),\\n 0 0 0 1px color-mix(in srgb, var(--hw-dock-on-surface) 7%, transparent),\\n 0 2px 6px rgba(12, 11, 10, 0.18),\\n 0 20px 48px -14px rgba(12, 11, 10, 0.45);\\n transition:\\n border-radius 0.18s ease,\\n box-shadow 0.2s cubic-bezier(0.2, 0.8, 0.2, 1),\\n width 0.26s cubic-bezier(0.2, 0.8, 0.2, 1);\\n}\\n.hw-dock-bar:focus-within {\\n box-shadow:\\n inset 0 1px 0 color-mix(in srgb, var(--hw-dock-on-surface) 9%, transparent),\\n 0 0 0 1px color-mix(in srgb, var(--hw-primary, #fb923c) 60%, transparent),\\n 0 2px 6px rgba(12, 11, 10, 0.18),\\n 0 20px 48px -14px rgba(12, 11, 10, 0.45);\\n}\\n.hw-dock-bar[data-grown=true] {\\n border-radius: 20px;\\n}\\n.hw-dock-input {\\n flex: 1;\\n min-width: 0;\\n min-height: 20px;\\n max-height: var(--hw-bar-max-height);\\n padding: 6px 0;\\n border: 0;\\n outline: none;\\n resize: none;\\n overflow-y: auto;\\n background: transparent;\\n color: var(--hw-dock-on-surface);\\n font: inherit;\\n font-size: 14px;\\n line-height: 1.45;\\n transition: height 0.12s ease;\\n}\\n.hw-dock-input::placeholder {\\n color: color-mix(in srgb, var(--hw-dock-on-surface) 45%, transparent);\\n}\\n.hw-dock-send {\\n flex: none;\\n width: 32px;\\n height: 32px;\\n margin-bottom: 1px;\\n border: 0;\\n border-radius: 50%;\\n display: grid;\\n place-items: center;\\n cursor: pointer;\\n background: var(--hw-primary, #fb923c);\\n color: var(--hw-on-brand, #fff);\\n transition: transform 0.16s cubic-bezier(0.2, 0.8, 0.2, 1), opacity 0.16s;\\n}\\n.hw-dock-send:hover:not(:disabled) {\\n transform: scale(1.06);\\n}\\n.hw-dock-send:disabled {\\n opacity: 0.45;\\n cursor: default;\\n}\\n.hw-widget[data-hw-placement=docked] .hw-window {\\n position: fixed;\\n left: 50%;\\n right: auto;\\n margin-left: calc(var(--hw-dock-width) / -2);\\n bottom: calc(var(--hw-dock-inset) + 66px);\\n width: var(--hw-dock-width);\\n max-width: calc(100vw - 32px);\\n height: 420px;\\n}\\n@media (max-width: 640px) {\\n .hw-widget[data-hw-placement=docked] .hw-window {\\n left: 16px;\\n right: 16px;\\n margin-left: 0;\\n width: auto;\\n }\\n}\\n.hw-widget[data-hw-placement=docked] .hw-bubble {\\n display: none;\\n}\\n.hw-widget[data-hw-placement=docked][data-hw-open=true] .hw-window {\\n bottom: calc(var(--hw-dock-inset) + 52px + 12px);\\n}\\n.hw-widget[data-hw-placement=docked][data-hw-open=true] .hw-dock-suggestions {\\n display: none;\\n}\\n@media (prefers-reduced-motion: reduce) {\\n .hw-dock-pill,\\n .hw-dock-bar,\\n .hw-dock-input,\\n .hw-dock-send {\\n animation: none;\\n transition: none;\\n }\\n}\\n.hw-widget[data-hw-placement=docked] .hw-composer,\\n.hw-widget[data-hw-placement=docked] .hw-tabs,\\n.hw-widget[data-hw-placement=docked] .hw-footer-tabs {\\n display: none;\\n}\\n.hw-starters {\\n display: flex;\\n flex-direction: column;\\n margin-top: 10px;\\n border-radius: 14px;\\n overflow: hidden;\\n background: var(--hw-bg);\\n box-shadow: inset 0 0 0 1px var(--hw-border);\\n}\\n.hw-starter {\\n display: flex;\\n align-items: center;\\n gap: 10px;\\n width: 100%;\\n padding: 11px 14px;\\n border: 0;\\n border-radius: 0;\\n cursor: pointer;\\n background: transparent;\\n color: var(--hw-text);\\n font: inherit;\\n text-align: left;\\n animation: hw-starter-in 0.3s cubic-bezier(0.2, 0.8, 0.2, 1) both;\\n transition: background 0.12s;\\n}\\n.hw-starter + .hw-starter {\\n box-shadow: inset 0 1px 0 var(--hw-border);\\n}\\n.hw-starter:hover {\\n background: var(--hw-bg-hover);\\n}\\n.hw-starter-text {\\n flex: 1;\\n min-width: 0;\\n display: flex;\\n flex-direction: column;\\n gap: 1px;\\n}\\n.hw-starter-k {\\n font-size: 13px;\\n font-weight: 550;\\n line-height: 1.35;\\n color: var(--hw-text);\\n}\\n.hw-starter-q {\\n font-size: 12px;\\n line-height: 1.35;\\n color: var(--hw-text-3, var(--hw-text-muted));\\n}\\n.hw-starter svg {\\n flex: none;\\n color: var(--hw-text-3, var(--hw-text-muted));\\n opacity: 0.45;\\n transition: opacity 0.15s, transform 0.15s;\\n}\\n.hw-starter:hover svg {\\n opacity: 0.9;\\n transform: translateX(2px);\\n}\\n@keyframes hw-starter-in {\\n from {\\n opacity: 0;\\n transform: translateY(6px);\\n }\\n to {\\n opacity: 1;\\n transform: none;\\n }\\n}\\n.hw-widget[data-hw-placement=docked] .hw-header-back {\\n display: none;\\n}\\n@media (prefers-reduced-motion: reduce) {\\n .hw-starter {\\n animation: none;\\n }\\n}\\n@media (prefers-color-scheme: dark) {\\n .hw-widget:not([data-theme=light])[data-hw-placement=docked] {\\n --hw-dock-surface: #1f1f23;\\n --hw-dock-on-surface: #f4f4f6;\\n --hw-dock-pill-bg: rgba(255, 255, 255, 0.1);\\n --hw-dock-pill-fg: #e4e4e7;\\n --hw-dock-pill-border: rgba(255, 255, 255, 0.14);\\n }\\n}\\n.hw-widget[data-theme=dark][data-hw-placement=docked] {\\n --hw-dock-surface: #1f1f23;\\n --hw-dock-on-surface: #f4f4f6;\\n}\\n.hw-widget[data-hw-placement=docked] .hw-window {\\n --hw-bg: rgba(255, 255, 255, 0.08);\\n --hw-bg-subtle: transparent;\\n --hw-bg-hover: rgba(255, 255, 255, 0.1);\\n --hw-border: rgba(255, 255, 255, 0.14);\\n --hw-border-md: rgba(255, 255, 255, 0.22);\\n --hw-text: rgba(255, 255, 255, 0.94);\\n --hw-text-1: #ffffff;\\n --hw-text-2: rgba(255, 255, 255, 0.72);\\n --hw-text-3: rgba(255, 255, 255, 0.62);\\n --hw-text-4: rgba(255, 255, 255, 0.46);\\n --hw-visitor-bubble-bg: rgba(255, 255, 255, 0.16);\\n --hw-visitor-bubble-text: #ffffff;\\n --hw-brand: rgba(255, 255, 255, 0.92);\\n --hw-on-brand: #17161a;\\n --hw-focus-border: rgba(255, 255, 255, 0.34);\\n --hw-focus-ring: rgba(255, 255, 255, 0.1);\\n height: 500px;\\n max-height: calc(100vh - 180px);\\n border-radius: 24px;\\n color: var(--hw-text);\\n background:\\n linear-gradient(\\n 180deg,\\n rgba(40, 40, 44, 0.72) 0%,\\n rgba(46, 46, 50, 0.7) 55%,\\n rgba(52, 52, 56, 0.68) 100%);\\n backdrop-filter: blur(30px);\\n -webkit-backdrop-filter: blur(30px);\\n box-shadow: 0 24px 60px -20px rgba(12, 11, 10, 0.5), inset 0 0 0 1px rgba(255, 255, 255, 0.1);\\n}\\n@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {\\n .hw-widget[data-hw-placement=docked] .hw-window {\\n background: #2c2c2e;\\n }\\n}\\n@media (max-width: 640px) {\\n .hw-widget[data-hw-placement=docked] .hw-window {\\n height: min(60vh, 460px);\\n }\\n}\\n.hw-widget[data-hw-placement=docked] .hw-header--sub {\\n padding: 14px 12px 8px 16px;\\n}\\n.hw-widget[data-hw-placement=docked] .hw-header-status {\\n display: none;\\n}\\n.hw-widget[data-hw-placement=docked] .hw-header-name {\\n font-size: 15.5px;\\n font-weight: 560;\\n letter-spacing: -0.006em;\\n color: var(--hw-text-1);\\n}\\n.hw-widget[data-hw-placement=docked] .hw-header-menu-conv-name,\\n.hw-widget[data-hw-placement=docked] .hw-event-name {\\n font-weight: 545;\\n}\\n.hw-widget[data-hw-placement=docked] .hw-header-bot-icon {\\n border-radius: 50%;\\n overflow: hidden;\\n}\\n.hw-widget[data-hw-placement=docked] .hw-header-close:hover,\\n.hw-widget[data-hw-placement=docked] .hw-header-menu-btn:hover {\\n background: rgba(255, 255, 255, 0.12);\\n color: #ffffff;\\n}\\n.hw-widget[data-hw-placement=docked] .hw-messages {\\n padding: 4px 22px 16px;\\n gap: 18px;\\n -webkit-mask-image:\\n linear-gradient(\\n 180deg,\\n transparent 0,\\n #000 16px);\\n mask-image:\\n linear-gradient(\\n 180deg,\\n transparent 0,\\n #000 16px);\\n}\\n.hw-widget[data-hw-placement=docked] .hw-msg--ai .hw-msg-bubble,\\n.hw-widget[data-hw-placement=docked] .hw-msg--team .hw-msg-bubble {\\n padding: 0;\\n background: transparent;\\n border-radius: 0;\\n font-size: 15px;\\n line-height: 1.55;\\n color: var(--hw-text);\\n}\\n.hw-widget[data-hw-placement=docked] .hw-msg--ai .hw-msg-meta {\\n display: none;\\n}\\n.hw-widget[data-hw-placement=docked] .hw-msg--visitor .hw-msg-bubble {\\n background: rgba(255, 255, 255, 0.16);\\n color: #ffffff;\\n font-size: 14.5px;\\n line-height: 1.5;\\n}\\n.hw-widget[data-hw-placement=docked] .hw-msg-bubble pre,\\n.hw-widget[data-hw-placement=docked] .hw-msg-bubble code {\\n background: rgba(0, 0, 0, 0.28);\\n color: var(--hw-text-1);\\n}\\n.hw-widget[data-hw-placement=docked] .hw-email-card-row {\\n background: rgba(0, 0, 0, 0.26);\\n border-color: rgba(255, 255, 255, 0.14);\\n}\\n.hw-widget[data-hw-placement=docked] .hw-window :focus-visible {\\n outline-color: rgba(255, 255, 255, 0.55);\\n}\\n.hw-widget[data-hw-placement=docked] .hw-email-card-input:focus,\\n.hw-widget[data-hw-placement=docked] .hw-email-card-input:focus-visible {\\n outline: none;\\n box-shadow: none;\\n}\\n.hw-widget[data-hw-placement=docked] .hw-email-card-row:focus-within {\\n border-color: rgba(255, 255, 255, 0.42);\\n box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.08);\\n}\\n.hw-widget[data-hw-placement=docked] .hw-email-card-submit {\\n background: #ffffff;\\n color: #17161a;\\n}\\n.hw-widget[data-hw-placement=docked] .hw-window .hw-header--sub {\\n position: relative;\\n z-index: 3;\\n}\\n.hw-widget[data-hw-placement=docked] .hw-header-menu {\\n background: #3a3a3f;\\n box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.16), 0 18px 44px -12px rgba(12, 11, 10, 0.62);\\n}\\n.hw-widget[data-hw-placement=docked] .hw-header-menu button:hover {\\n background: rgba(255, 255, 255, 0.11);\\n}\\n.hw-widget[data-hw-placement=docked] .hw-header-menu button.hw-header-menu-conv[data-active=true] {\\n background: rgba(255, 255, 255, 0.09);\\n}\\n.hw-widget[data-hw-placement=docked] .hw-header-menu-convs {\\n border-bottom-color: rgba(255, 255, 255, 0.12);\\n}\\n.hw-widget[data-hw-placement=docked] .hw-event--card {\\n margin: 0;\\n background: rgba(255, 255, 255, 0.08);\\n box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);\\n}\\n.hw-widget[data-hw-placement=docked] .hw-event-avatar {\\n background: rgba(255, 255, 255, 0.14);\\n color: var(--hw-text-1);\\n}\\n.hw-widget[data-hw-placement=docked] .hw-preview {\\n position: fixed;\\n left: 50%;\\n right: auto;\\n margin-left: calc(var(--hw-dock-bar-width, var(--hw-dock-width)) / -2);\\n bottom: calc(var(--hw-dock-inset) + 52px + 12px);\\n width: var(--hw-dock-bar-width, var(--hw-dock-width));\\n max-width: calc(100vw - 32px);\\n border: 0;\\n border-radius: 24px;\\n color: rgba(255, 255, 255, 0.94);\\n background:\\n linear-gradient(\\n 180deg,\\n rgba(40, 40, 44, 0.74) 0%,\\n rgba(52, 52, 56, 0.7) 100%);\\n backdrop-filter: blur(30px);\\n -webkit-backdrop-filter: blur(30px);\\n box-shadow: 0 24px 60px -20px rgba(12, 11, 10, 0.5), inset 0 0 0 1px rgba(255, 255, 255, 0.1);\\n}\\n.hw-widget[data-hw-placement=docked] .hw-preview-name,\\n.hw-widget[data-hw-placement=docked] .hw-preview-body {\\n color: rgba(255, 255, 255, 0.94);\\n}\\n.hw-widget[data-hw-placement=docked] .hw-preview-close {\\n color: rgba(255, 255, 255, 0.6);\\n}\\n.hw-widget[data-hw-placement=docked] .hw-preview-close:hover {\\n background: rgba(255, 255, 255, 0.12);\\n color: #ffffff;\\n}\\n.hw-widget[data-hw-placement=docked] .hw-preview-footer {\\n color: rgba(255, 255, 255, 0.55);\\n border-top-color: rgba(255, 255, 255, 0.1);\\n}\\n@media (max-width: 640px) {\\n .hw-widget[data-hw-placement=docked] .hw-preview {\\n left: 16px;\\n right: 16px;\\n margin-left: 0;\\n width: auto;\\n }\\n}\\n@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {\\n .hw-widget[data-hw-placement=docked] .hw-preview {\\n background: #2c2c2e;\\n }\\n}\\n.hw-widget[data-hw-placement=docked] .hw-quick-reply-btn {\\n padding: 7px 14px;\\n font-size: 13px;\\n font-weight: 550;\\n border-radius: 999px;\\n background: rgba(255, 255, 255, 0.94);\\n box-shadow: 0 1px 3px rgba(12, 11, 10, 0.22);\\n color: #17161a;\\n}\\n.hw-widget[data-hw-placement=docked] .hw-quick-reply-btn:hover:not(:disabled) {\\n background: #ffffff;\\n box-shadow: 0 4px 12px rgba(12, 11, 10, 0.28);\\n transform: translateY(-1px);\\n}\\n.hw-widget[data-hw-placement=docked] .hw-quick-reply-btn[data-tapped=true] {\\n background: rgba(255, 255, 255, 0.22);\\n color: #ffffff;\\n box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.3);\\n transform: none;\\n}\\n.hw-widget[data-hw-placement=docked] .hw-quick-reply-btn svg {\\n opacity: 0.55;\\n}\\n.hw-widget[data-hw-placement=docked] .hw-offer {\\n padding: 7px 14px;\\n font-size: 13px;\\n background: rgba(255, 255, 255, 0.94);\\n color: #17161a;\\n box-shadow: 0 1px 3px rgba(12, 11, 10, 0.22);\\n transition:\\n background 0.15s,\\n box-shadow 0.15s,\\n transform 0.15s;\\n}\\n.hw-widget[data-hw-placement=docked] .hw-offer:hover {\\n background: #ffffff;\\n color: #17161a;\\n box-shadow: 0 4px 12px rgba(12, 11, 10, 0.28);\\n transform: translateY(-1px);\\n}\\n.hw-widget[data-hw-placement=docked] .hw-offer svg {\\n opacity: 0.55;\\n}\\n.hw-widget[data-hw-placement=docked] .hw-dock-bar {\\n --hw-dock-on-surface: rgba(255, 255, 255, 0.94);\\n color: rgba(255, 255, 255, 0.94);\\n background:\\n linear-gradient(\\n 180deg,\\n rgba(44, 44, 48, 0.74) 0%,\\n rgba(52, 52, 56, 0.72) 100%);\\n backdrop-filter: blur(30px);\\n -webkit-backdrop-filter: blur(30px);\\n box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12), 0 18px 40px -16px rgba(12, 11, 10, 0.45);\\n}\\n.hw-widget[data-hw-placement=docked][data-hw-open=true] .hw-dock-bar {\\n width: var(--hw-dock-width);\\n}\\n.hw-widget[data-hw-placement=docked] .hw-dock-bar:focus-within {\\n box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.26), 0 18px 40px -16px rgba(12, 11, 10, 0.5);\\n}\\n.hw-widget[data-hw-placement=docked][data-hw-open=true] .hw-dock-bar {\\n box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.14), 0 22px 52px -18px rgba(12, 11, 10, 0.52);\\n}\\n.hw-widget[data-hw-placement=docked] .hw-dock-send:not(:disabled) {\\n background: #ffffff;\\n color: #17161a;\\n}\\n@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {\\n .hw-widget[data-hw-placement=docked] .hw-dock-bar {\\n background: #2c2c2e;\\n }\\n}\\n.hw-widget[data-hw-placement=docked] .hw-window {\\n transform-origin: 50% 100%;\\n animation: hw-dock-panel-in 0.3s cubic-bezier(0.16, 1, 0.3, 1);\\n}\\n.hw-widget[data-hw-placement=docked] .hw-window--closing {\\n animation: hw-dock-panel-out 0.18s cubic-bezier(0.4, 0, 1, 1) forwards;\\n}\\n@keyframes hw-dock-panel-in {\\n from {\\n opacity: 0;\\n transform: translateY(14px) scale(0.98);\\n }\\n to {\\n opacity: 1;\\n transform: none;\\n }\\n}\\n@keyframes hw-dock-panel-out {\\n from {\\n opacity: 1;\\n transform: none;\\n }\\n to {\\n opacity: 0;\\n transform: translateY(8px) scale(0.99);\\n }\\n}\\n.hw-widget[data-hw-placement=docked] .hw-window .hw-header--sub {\\n animation: hw-dock-settle 0.32s cubic-bezier(0.16, 1, 0.3, 1) 0.06s both;\\n}\\n.hw-widget[data-hw-placement=docked] .hw-window .hw-messages {\\n animation: hw-dock-settle 0.34s cubic-bezier(0.16, 1, 0.3, 1) 0.11s both;\\n}\\n.hw-widget[data-hw-placement=docked] .hw-window--closing .hw-header--sub,\\n.hw-widget[data-hw-placement=docked] .hw-window--closing .hw-messages {\\n animation: none;\\n}\\n@keyframes hw-dock-settle {\\n from {\\n opacity: 0;\\n transform: translateY(7px);\\n }\\n to {\\n opacity: 1;\\n transform: none;\\n }\\n}\\n@media (prefers-reduced-motion: reduce) {\\n .hw-widget[data-hw-placement=docked] .hw-window,\\n .hw-widget[data-hw-placement=docked] .hw-window--closing,\\n .hw-widget[data-hw-placement=docked] .hw-window .hw-header--sub,\\n .hw-widget[data-hw-placement=docked] .hw-window .hw-messages {\\n animation: none;\\n }\\n}\\n.hw-dock-bar {\\n flex-wrap: wrap;\\n padding-left: 18px;\\n padding-right: 8px;\\n}\\n.hw-dock-error {\\n width: var(--hw-dock-width);\\n max-width: calc(100vw - 32px);\\n margin-bottom: 8px;\\n padding: 8px 14px;\\n border-radius: 14px;\\n background: rgba(190, 24, 40, 0.92);\\n color: #ffffff;\\n font-size: 12.5px;\\n line-height: 1.35;\\n box-shadow: 0 10px 26px -12px rgba(12, 11, 10, 0.5);\\n animation: hw-dock-settle 0.22s cubic-bezier(0.16, 1, 0.3, 1) both;\\n}\\n@media (prefers-reduced-motion: reduce) {\\n .hw-dock-error {\\n animation: none;\\n }\\n}\\n.hw-dock-previews {\\n flex: 0 0 100%;\\n order: -1;\\n display: flex;\\n flex-wrap: wrap;\\n gap: 8px;\\n padding: 2px 0 8px;\\n}\\n.hw-dock-actions {\\n flex: none;\\n display: flex;\\n align-items: center;\\n gap: 2px;\\n margin-bottom: 1px;\\n}\\n.hw-dock-tool {\\n display: grid;\\n place-items: center;\\n width: 30px;\\n height: 30px;\\n border: 0;\\n border-radius: 50%;\\n background: transparent;\\n color: color-mix(in srgb, var(--hw-dock-on-surface) 52%, transparent);\\n cursor: pointer;\\n transition: background 0.15s, color 0.15s;\\n}\\n.hw-dock-tool:hover:not(:disabled) {\\n background: color-mix(in srgb, var(--hw-dock-on-surface) 8%, transparent);\\n color: var(--hw-dock-on-surface);\\n}\\n.hw-dock-tool:disabled {\\n opacity: 0.4;\\n cursor: default;\\n}\\n.hw-dock-tool[data-active=true] {\\n color: #e11d48;\\n background: rgba(225, 29, 72, 0.12);\\n animation: hw-dock-listening 1.4s ease-in-out infinite;\\n}\\n@keyframes hw-dock-listening {\\n 0%, 100% {\\n box-shadow: 0 0 0 0 rgba(225, 29, 72, 0.35);\\n }\\n 50% {\\n box-shadow: 0 0 0 4px rgba(225, 29, 72, 0);\\n }\\n}\\n.hw-dock-send:disabled {\\n opacity: 1;\\n background: color-mix(in srgb, var(--hw-dock-on-surface) 9%, transparent);\\n color: color-mix(in srgb, var(--hw-dock-on-surface) 38%, transparent);\\n}\\n@media (prefers-reduced-motion: reduce) {\\n .hw-dock-tool[data-active=true] {\\n animation: none;\\n }\\n .hw-dock-bar {\\n transition: none;\\n }\\n}\\n.hw-dock-input:focus,\\n.hw-dock-input:focus-visible {\\n outline: none;\\n box-shadow: none;\\n}\\n.hw-widget[data-hw-placement=docked] .hw-powered {\\n display: none;\\n}\\n.hw-widget[data-hw-placement=docked] .hw-disconnect {\\n padding: 7px 14px;\\n background: var(--hw-bg-hover);\\n color: var(--hw-text-3, var(--hw-text-muted));\\n font-size: 11.5px;\\n border-radius: 20px 20px 0 0;\\n}\\n.hw-msg-meta {\\n display: flex;\\n align-items: center;\\n gap: 5px;\\n}\\n.hw-msg-author {\\n font-weight: 550;\\n}\\n.hw-msg-meta-sep {\\n opacity: 0.55;\\n}\\n.hw-header-actions {\\n position: relative;\\n display: flex;\\n align-items: center;\\n gap: 2px;\\n}\\n.hw-header-menu-btn {\\n display: grid;\\n place-items: center;\\n width: 30px;\\n height: 30px;\\n border: 0;\\n border-radius: 8px;\\n cursor: pointer;\\n background: transparent;\\n color: var(--hw-text-2, var(--hw-text-muted));\\n transition: background 0.15s, color 0.15s;\\n}\\n.hw-header-menu-btn:hover {\\n background: var(--hw-bg-hover);\\n color: var(--hw-text);\\n}\\n.hw-header-menu {\\n position: absolute;\\n top: 36px;\\n right: 0;\\n z-index: 6;\\n min-width: 236px;\\n max-width: 288px;\\n padding: 5px;\\n border-radius: 14px;\\n background: var(--hw-bg);\\n color: var(--hw-text);\\n box-shadow: 0 0 0 1px var(--hw-border), 0 12px 32px -10px rgba(0, 0, 0, 0.32);\\n animation: hw-menu-in 0.16s cubic-bezier(0.2, 0.8, 0.2, 1) both;\\n}\\n@keyframes hw-menu-in {\\n from {\\n opacity: 0;\\n transform: translateY(-4px) scale(0.98);\\n }\\n to {\\n opacity: 1;\\n transform: none;\\n }\\n}\\n.hw-header-menu button {\\n display: flex;\\n align-items: center;\\n gap: 10px;\\n width: 100%;\\n padding: 9px 10px;\\n border: 0;\\n border-radius: 9px;\\n cursor: pointer;\\n background: transparent;\\n color: var(--hw-text);\\n font: inherit;\\n font-size: 13px;\\n text-align: left;\\n transition: background 0.14s;\\n}\\n.hw-header-menu button:hover {\\n background: var(--hw-bg-hover);\\n}\\n.hw-header-menu button svg {\\n flex: none;\\n color: var(--hw-text-3, var(--hw-text-muted));\\n}\\n.hw-header-menu button:hover svg {\\n color: var(--hw-brand, var(--hw-primary));\\n}\\n.hw-header-menu-convs {\\n display: flex;\\n flex-direction: column;\\n max-height: 168px;\\n overflow-y: auto;\\n padding-bottom: 5px;\\n margin-bottom: 5px;\\n border-bottom: 1px solid var(--hw-border);\\n}\\n.hw-header-menu button.hw-header-menu-conv {\\n flex-direction: column;\\n align-items: stretch;\\n gap: 2px;\\n padding: 8px 10px;\\n}\\n.hw-header-menu button.hw-header-menu-conv[data-active=true] {\\n background: var(--hw-bg-hover);\\n}\\n.hw-header-menu-conv-top {\\n display: flex;\\n align-items: baseline;\\n justify-content: space-between;\\n gap: 8px;\\n}\\n.hw-header-menu-conv-name {\\n overflow: hidden;\\n font-size: 12.5px;\\n font-weight: 600;\\n text-overflow: ellipsis;\\n white-space: nowrap;\\n}\\n.hw-header-menu-conv-time {\\n flex: none;\\n font-size: 11px;\\n color: var(--hw-text-3, var(--hw-text-muted));\\n}\\n.hw-header-menu-conv-preview {\\n overflow: hidden;\\n font-size: 12px;\\n color: var(--hw-text-2);\\n text-overflow: ellipsis;\\n white-space: nowrap;\\n}\\n.hw-offers {\\n display: flex;\\n flex-wrap: wrap;\\n gap: 6px;\\n margin-top: 10px;\\n}\\n.hw-offer {\\n display: inline-flex;\\n align-items: center;\\n gap: 6px;\\n padding: 8px 14px;\\n border: 0;\\n border-radius: 999px;\\n cursor: pointer;\\n background: var(--hw-bg-hover);\\n color: var(--hw-text);\\n font: inherit;\\n font-size: 12.5px;\\n font-weight: 550;\\n transition: background 0.15s, color 0.15s;\\n}\\n.hw-offer:hover {\\n background: var(--hw-brand, var(--hw-primary));\\n color: var(--hw-on-brand, #fff);\\n}\\n.hw-offer svg {\\n flex: none;\\n}\\n.hw-sources {\\n display: flex;\\n flex-direction: column;\\n gap: 2px;\\n margin-top: 8px;\\n}\\n.hw-source {\\n display: flex;\\n align-items: center;\\n gap: 9px;\\n padding: 7px 10px;\\n border-radius: 9px;\\n background: transparent;\\n color: var(--hw-text);\\n text-decoration: none;\\n transition: background 0.15s;\\n}\\na.hw-source {\\n cursor: pointer;\\n}\\na.hw-source:hover {\\n background: var(--hw-bg-hover);\\n}\\n.hw-source-n {\\n display: grid;\\n place-items: center;\\n flex: none;\\n width: 16px;\\n height: 16px;\\n border-radius: 4px;\\n background: var(--hw-brand, var(--hw-primary));\\n color: var(--hw-on-brand, #fff);\\n font-size: 10px;\\n font-weight: 700;\\n font-variant-numeric: tabular-nums;\\n}\\n.hw-source-title {\\n flex: 1;\\n min-width: 0;\\n font-size: 12px;\\n font-weight: 550;\\n overflow: hidden;\\n text-overflow: ellipsis;\\n white-space: nowrap;\\n}\\n\")","\"use client\";\n\n/**\n * `<HelpwayWidget />` — one-line drop-in React component that renders\n * the full Helpway widget natively in React.\n *\n * Since v0.2, this is a native React render (not a script tag injection).\n * The widget-core + widget-react code is bundled with your app, so widget\n * updates ship via `npm update @helpway/react` — no separate widget.js\n * deploy required. Bundle impact: ~120KB gzipped (shared with any other\n * helpway/react imports in your app, so subsequent uses are free).\n *\n * Power-user alternative: import `{ SupportProvider, DefaultWidget, useWidget, … }`\n * directly for programmatic control (render your own chat UI, expose\n * identify() via hook instead of global, etc.).\n *\n * @see https://helpway.ai/docs/quick-start for setup\n * @see https://helpway.ai/docs/react-sdk for the three integration layers\n * (drop-in, provider + hooks, fully headless)\n * @see https://helpway.ai/docs/customization for theming via `theme` prop\n * and the dashboard config\n * @see https://helpway.ai/docs/integration-notes for CSP, SSR, multi-tenant\n */\n\nimport type { DockSuggestion, WidgetPlacement, WidgetTheme } from \"@helpway/widget-core\";\nimport { SupportProvider } from \"./provider\";\nimport { DefaultWidget } from \"./themed/default-widget\";\n// Auto-import CSS so consumers don't need a separate `import \"@helpway/react/styles.css\"` step.\n// Side-effect import — evaluated once per bundle, tree-shaker preserves it via `sideEffects: [\"*.css\"]`.\nimport \"./themed/styles.css\";\n\nexport interface HelpwayWidgetProps {\n\t/**\n\t * Public API key from the Helpway dashboard. Required.\n\t * Format: `pk_live_…` or `pk_test_…`.\n\t */\n\tapiKey: string;\n\t/**\n\t * Override the default API URL. Almost no one needs this —\n\t * exposed for staging / self-hosted setups.\n\t * @default \"https://api.helpway.ai\"\n\t */\n\tapiUrl?: string;\n\t/**\n\t * Widget locale (e.g. \"tr\", \"en\", \"de\"). Falls back to server-side\n\t * detection (Accept-Language + CF-IPCountry) then widget-core default.\n\t */\n\tlocale?: string;\n\t/**\n\t * Deep link: auto-open this conversation after bootstrap.\n\t * Usually sourced from `?hw_conv=` URL param for email CTAs.\n\t */\n\tinitialConversationId?: string;\n\t/**\n\t * HMAC-signed token for cross-device visitor identity restoration.\n\t * Sourced from `#hw_token=` URL fragment in email deep-links.\n\t */\n\tdeepLinkToken?: string;\n\t/**\n\t * Called once after the widget has bootstrapped and exposes\n\t * the full programmatic API object (also available as `window.Helpway`).\n\t */\n\tonReady?: (api: HelpwayPublicAPI) => void;\n\t/**\n\t * Hide the default floating launcher button. Use with\n\t * `customLauncherSelector` or `window.Helpway.open()` to trigger\n\t * the widget from your own UI.\n\t */\n\thideLauncher?: boolean;\n\t/**\n\t * Where the widget lives on the page. The conversation UI is identical\n\t * across placements — only the shell moves.\n\t *\n\t * - `bubble` floating launcher bottom-right (default)\n\t * - `docked` composer bar pinned to the foot of the page; the bar is\n\t * the composer, so the panel above it renders without one\n\t * @default \"bubble\"\n\t */\n\tplacement?: WidgetPlacement;\n\t/**\n\t * Force the widget's appearance instead of following the visitor's OS.\n\t * Set this to match the page you are embedding in — a light page in a\n\t * dark-OS browser otherwise gets a dark widget.\n\t * @default \"system\"\n\t */\n\tcolorScheme?: \"light\" | \"dark\" | \"system\";\n\t/**\n\t * Ways in offered above the docked bar before the visitor types.\n\t * Only used when `placement=\"docked\"`.\n\t */\n\tdockSuggestions?: readonly DockSuggestion[];\n\t/**\n\t * CSS selector for a custom trigger element (e.g. `\"#support-btn\"`).\n\t * Clicking the matched element calls `Helpway.open()`. Combine with\n\t * `hideLauncher` to fully replace the default bubble.\n\t */\n\tcustomLauncherSelector?: string;\n\t/** Fires when the widget panel opens */\n\tonOpen?: () => void;\n\t/** Fires when the widget panel closes */\n\tonClose?: () => void;\n\t/** Fires when the unread count changes */\n\tonUnreadChange?: (count: number) => void;\n\t/**\n\t * Developer-side theme override. Most consumers should configure\n\t * appearance from the dashboard so changes apply without a redeploy\n\t * — see https://helpway.ai/docs/customization. Use this prop only\n\t * for runtime-resolved theming (multi-tenant brand colors, dark/\n\t * light sync with the host app, etc). Values map to CSS custom\n\t * properties on the widget host. See the `WidgetTheme` type for\n\t * the full set of supported keys.\n\t */\n\ttheme?: WidgetTheme;\n\t/**\n\t * @deprecated Legacy prop from the v0.1 script-loader era. If set,\n\t * the `/widget.js` suffix is stripped to derive `apiUrl`. New code\n\t * should use `apiUrl` instead.\n\t */\n\tsrc?: string;\n}\n\n// Re-export for consumers who use the onReady callback type.\n// `onReady` receives the programmatic methods object; the global\n// `window.Helpway` is the callable wrapper around it (HelpwayAPI).\nimport type { HelpwayMethods } from \"@helpway/widget-core\";\nexport type HelpwayPublicAPI = HelpwayMethods;\n\n/**\n * Render this once at the root of your app (e.g. in `_app.tsx`,\n * `layout.tsx`, or `main.tsx`). Unmounting cleanly tears down the\n * widget and its WebSocket connection — useful for route-scoped mounts.\n */\nexport function HelpwayWidget({\n\tapiKey,\n\tapiUrl,\n\tlocale,\n\tinitialConversationId,\n\tdeepLinkToken,\n\tonReady,\n\thideLauncher,\n\tplacement,\n\tcolorScheme,\n\tdockSuggestions,\n\tcustomLauncherSelector,\n\tonOpen,\n\tonClose,\n\tonUnreadChange,\n\ttheme,\n\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\tsrc,\n}: HelpwayWidgetProps) {\n\tconst resolvedApiUrl = apiUrl ?? (src ? src.replace(/\\/widget\\.js$/, \"\") : undefined);\n\n\treturn (\n\t\t<SupportProvider\n\t\t\tapiKey={apiKey}\n\t\t\tapiUrl={resolvedApiUrl}\n\t\t\tlocale={locale}\n\t\t\tinitialConversationId={initialConversationId}\n\t\t\tdeepLinkToken={deepLinkToken}\n\t\t\tonReady={onReady}\n\t\t\tcustomLauncherSelector={customLauncherSelector}\n\t\t\tonOpen={onOpen}\n\t\t\tonClose={onClose}\n\t\t\tonUnreadChange={onUnreadChange}\n\t\t\ttheme={theme}\n\t\t>\n\t\t\t<DefaultWidget\n\t\t\t\thideLauncher={hideLauncher}\n\t\t\t\tplacement={placement}\n\t\t\t\tcolorScheme={colorScheme}\n\t\t\t\tdockSuggestions={dockSuggestions}\n\t\t\t/>\n\t\t</SupportProvider>\n\t);\n}\n","import { useEffect } from \"react\";\nimport type { RealtimeEvent } from \"@helpway/types\";\nimport { useWidgetContext } from \"../provider\";\n\n/**\n * Subscribe to raw WebSocket events.\n * For advanced usage — most apps should use useTimeline/usePresence instead.\n *\n * Usage:\n * ```tsx\n * useRealtime((event) => {\n * if (event.type === 'timelineItemCreated') { ... }\n * })\n * ```\n */\nexport function useRealtime(handler: (event: RealtimeEvent) => void) {\n\tconst { ws } = useWidgetContext();\n\n\tuseEffect(() => {\n\t\treturn ws.onEvent(handler);\n\t}, [ws, handler]);\n}\n"],"mappings":"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","names":["storageKey","merged","client","store","emitter","ws","identify","api","el","useCallback","useEffect","useRef","useState","useCallback","useEffect","useRef","t","useRef","useEffect","useCallback","useCallback","useState","useState","useCallback","conversationId","useCallback","useEffect","useRef","useState","useState","useRef","useEffect","useCallback","store","useEffect","useState","useState","useEffect","useCallback","useRef","useRef","useCallback","useCallback","useEffect","useRef","useState","useState","useRef","useEffect","useCallback","useCallback","useRef","useState","jsx","jsx","jsx","jsx","jsx","jsx","jsx","jsxs","useRef","useCallback","useState","useEffect","useMemo","useRef","useState","jsx","jsxs","useState","useRef","useEffect","useMemo","useCallback","useEffect","useRef","useState","jsx","jsxs","useState","useRef","useEffect","useCallback","useCallback","useEffect","useCallback","useEffect","useState","EMPTY_TABS","t","useState","useCallback","useEffect","useEffect","useRef","jsx","Fragment","jsx","jsxs","useCallback","useRef","useState","jsx","jsxs","useEffect","useRef","useCallback","useRef","useState","EMPTY_TABS","detailKey","readCache","t","useState","useRef","useCallback","jsx","useEffect","useRef","jsx","useEffect","useCallback","jsx","useState","jsx","jsxs","useState","useEffect","useRef","useState","Fragment","jsx","jsxs","useRef","useEffect","useState","useEffect","useRef","jsx","jsxs","useRef","useEffect","useEffect","useState","Fragment","jsx","jsxs","useState","useEffect","Fragment","jsx","jsxs","resolveLabel","c","useState","useEffect","useRef","useCallback","t","jsx","useEffect","useEffect"]}