@namiruai/chat 1.2.0 → 1.4.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.
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts", "../src/core/state-machine.ts", "../src/core/api-client.ts", "../src/core/websocket-client.ts", "../src/core/inactivity-timer.ts", "../src/core/env.ts", "../src/ui/styles.ts", "../src/core/markdown.ts", "../src/ui/icons.ts", "../src/ui/components/chat-header.ts", "../src/ui/components/chat-input.ts", "../src/ui/components/message-bubble.ts", "../src/ui/components/pre-chat-form.ts", "../src/ui/components/feedback-prompt.ts", "../src/ui/components/email-form.ts", "../src/ui/components/contact-form.ts", "../src/ui/components/limit-overlay.ts", "../src/ui/components/chat-window.ts", "../src/ui/components/button-bubble.ts"],
|
|
4
|
-
"sourcesContent": ["export type {\n NamiruChatConfig,\n NamiruChatInstance,\n AgentBrandingData,\n ChatMessage,\n PreChatTemplate,\n PreChatCustomConfig,\n PreChatOption,\n LeadCaptureData,\n} from \"./core/types\";\n\nimport type {\n NamiruChatConfig,\n NamiruChatInstance,\n ChatMessage,\n} from \"./core/types\";\nimport { ChatStore } from \"./core/state-machine\";\nimport { ApiClient } from \"./core/api-client\";\nimport { WebSocketClient } from \"./core/websocket-client\";\nimport { InactivityTimer } from \"./core/inactivity-timer\";\nimport { setHasShadowDom } from \"./core/env\";\nimport { injectStyles, removeStyles } from \"./ui/styles\";\nimport { createChatWindow } from \"./ui/components/chat-window\";\nimport { createButtonBubble } from \"./ui/components/button-bubble\";\n\nfunction mapToWsOrigin(origin: string): string {\n try {\n const url = new URL(origin);\n const wsProtocol = url.protocol === \"https:\" ? \"wss:\" : \"ws:\";\n // Localhost: swap port to 3423 (AI backend WebSocket port)\n if (url.hostname === \"localhost\" || url.hostname === \"127.0.0.1\") {\n url.port = \"3423\";\n url.protocol = wsProtocol;\n return url.origin;\n }\n // Test: test.namiru.ai -> wss://ai-test.namiru.ai\n if (url.hostname === \"test.namiru.ai\") {\n return `${wsProtocol}//ai-test.namiru.ai`;\n }\n // Production: namiru.ai / app.namiru.ai / api.namiru.ai -> wss://ai.namiru.ai\n if (url.hostname === \"namiru.ai\" || url.hostname === \"app.namiru.ai\" || url.hostname === \"api.namiru.ai\") {\n return `${wsProtocol}//ai.namiru.ai`;\n }\n // Fallback: prefix with ai.\n url.protocol = wsProtocol;\n return url.origin;\n } catch {\n const wsProtocol = origin.startsWith(\"https\") ? \"wss\" : \"ws\";\n const host = origin.replace(/^https?:\\/\\//, \"\");\n return `${wsProtocol}://${host}`;\n }\n}\n\nfunction mapToApiOrigin(origin: string): string {\n try {\n const url = new URL(origin);\n // Production: app.namiru.ai -> api.namiru.ai\n if (url.hostname.startsWith(\"app.\")) {\n url.hostname = url.hostname.replace(\"app.\", \"api.\");\n return url.origin;\n }\n // Test/staging: test.namiru.ai -> api-test.namiru.ai\n if (url.hostname === \"test.namiru.ai\") {\n url.hostname = \"api-test.namiru.ai\";\n return url.origin;\n }\n // Bare domain: namiru.ai -> api.namiru.ai\n if (url.hostname === \"namiru.ai\") {\n url.hostname = \"api.namiru.ai\";\n return url.origin;\n }\n // Localhost (any port): map to localhost:3001 (backend-api)\n if (url.hostname === \"localhost\" || url.hostname === \"127.0.0.1\") {\n url.port = \"3001\";\n return url.origin;\n }\n return url.origin;\n } catch {\n return origin;\n }\n}\n\nfunction deriveUrls(config: NamiruChatConfig): {\n apiBase: string;\n wsUrl: string;\n} {\n let apiBase: string;\n let scriptOrigin: string | null = null;\n\n if (config.serverUrl) {\n apiBase = config.serverUrl.replace(/\\/$/, \"\");\n } else {\n // Try to derive from the script src attribute first (takes priority over location.origin)\n const scripts = document.querySelectorAll(\"script[src]\");\n for (let i = scripts.length - 1; i >= 0; i--) {\n const src = (scripts[i] as HTMLScriptElement).src;\n if (src.includes(\"namiru-chat\") || src.includes(\"namiru\")) {\n try {\n const url = new URL(src);\n scriptOrigin = url.origin;\n break;\n } catch {\n // Invalid URL, continue\n }\n }\n }\n // Use script origin if found, otherwise fall back to location.origin\n apiBase = mapToApiOrigin(scriptOrigin || location.origin);\n }\n\n return {\n apiBase,\n wsUrl: config.wsUrl || mapToWsOrigin(scriptOrigin || apiBase),\n };\n}\n\nconst VISITOR_ID_KEY = \"namiru_visitor_id\";\n\nfunction getOrCreateVisitorId(): string {\n try {\n const existing = localStorage.getItem(VISITOR_ID_KEY);\n if (existing) return existing;\n const id = `v_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;\n localStorage.setItem(VISITOR_ID_KEY, id);\n return id;\n } catch {\n // localStorage unavailable (incognito, etc.) - generate ephemeral ID\n return `v_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;\n }\n}\n\nlet messageIdCounter = 0;\n\nfunction createMessageId(): string {\n messageIdCounter++;\n return `msg-${Date.now()}-${messageIdCounter}`;\n}\n\n/**\n * Check if the current page path matches any excluded route pattern.\n * Supports exact match and wildcard suffix (e.g. \"/chat/*\" matches \"/chat/anything\").\n * Empty or missing array means no route exclusions.\n */\nfunction isRouteExcluded(excludedRoutes: string[] | undefined): boolean {\n if (!excludedRoutes || excludedRoutes.length === 0) return false;\n const pathname = window.location.pathname;\n return excludedRoutes.some((pattern) => {\n if (pattern.endsWith('/*')) {\n const prefix = pattern.slice(0, -1); // \"/chat/*\" -> \"/chat/\"\n return pathname.startsWith(prefix) || pathname === prefix.slice(0, -1);\n }\n if (pattern.endsWith('*')) {\n const prefix = pattern.slice(0, -1); // \"/chat*\" -> \"/chat\"\n return pathname.startsWith(prefix);\n }\n return pathname === pattern;\n });\n}\n\n/**\n * Watch for SPA route changes (pushState, replaceState, popstate) and\n * show/hide the widget when navigating to/from excluded routes.\n * Returns a cleanup function that restores the original history methods.\n */\nfunction watchRouteChanges(\n excludedRoutes: string[],\n mountedEl: HTMLElement | null\n): () => void {\n if (!mountedEl) return () => {};\n\n const EVENT_NAME = \"namiru:locationchange\";\n\n const origPushState = history.pushState.bind(history);\n const origReplaceState = history.replaceState.bind(history);\n\n history.pushState = function (...args: Parameters<typeof origPushState>) {\n origPushState(...args);\n window.dispatchEvent(new Event(EVENT_NAME));\n };\n\n history.replaceState = function (...args: Parameters<typeof origReplaceState>) {\n origReplaceState(...args);\n window.dispatchEvent(new Event(EVENT_NAME));\n };\n\n function checkVisibility() {\n if (isRouteExcluded(excludedRoutes)) {\n mountedEl!.style.display = \"none\";\n } else {\n mountedEl!.style.display = \"\";\n }\n }\n\n window.addEventListener(EVENT_NAME, checkVisibility);\n window.addEventListener(\"popstate\", checkVisibility);\n\n return () => {\n history.pushState = origPushState;\n history.replaceState = origReplaceState;\n window.removeEventListener(EVENT_NAME, checkVisibility);\n window.removeEventListener(\"popstate\", checkVisibility);\n };\n}\n\n/**\n * Check if the current hostname matches any of the allowed domains.\n * Supports exact match and subdomain matching.\n * Empty or missing array means no domain restriction.\n */\nfunction isDomainAllowed(allowedDomains: string[] | undefined): boolean {\n if (!allowedDomains || allowedDomains.length === 0) return true;\n const hostname = window.location.hostname.toLowerCase();\n if (hostname === \"localhost\" || hostname === \"127.0.0.1\") return true;\n // Always allow *.namiru.ai and namiru.ai itself\n if (hostname === \"namiru.ai\" || hostname.endsWith(\".namiru.ai\")) return true;\n return allowedDomains.some((domain) => {\n const d = domain.toLowerCase();\n return hostname === d || hostname.endsWith(\".\" + d);\n });\n}\n\nexport function init(config: NamiruChatConfig): NamiruChatInstance {\n if (!config.agentId) {\n throw new Error(\"NamiruChat: agentId is required\");\n }\n\n const mode = config.mode || \"button\";\n const position = \"bottom-right\";\n const { apiBase, wsUrl } = deriveUrls(config);\n\n // Create core instances\n const store = new ChatStore();\n const apiClient = new ApiClient({ baseUrl: apiBase });\n let wsClient: WebSocketClient | null = null;\n let hostEl: HTMLElement | null = null;\n let shadowRoot: ShadowRoot | null = null;\n let rootEl: HTMLElement | null = null;\n let chatWindowEl: HTMLElement | null = null;\n let buttonEl: HTMLElement | null = null;\n let destroyed = false;\n let lastHandoffReason: string = \"handoff_accepted\";\n let pendingEscalationForm = false;\n let inactivityTimer: InactivityTimer | null = null;\n let feedbackEnabled = false;\n let routeCleanup: (() => void) | null = null;\n\n // Create Shadow DOM host for CSS isolation (with fallback for old browsers)\n hostEl = document.createElement(\"div\");\n hostEl.id = \"namiru-widget-host\";\n\n const supportsShadow = typeof hostEl.attachShadow === \"function\";\n setHasShadowDom(supportsShadow);\n\n if (supportsShadow) {\n // Modern path: Shadow DOM provides full CSS isolation\n hostEl.style.cssText = \"all:initial;position:fixed;top:0;left:0;width:0;height:0;overflow:visible;z-index:2147483646;pointer-events:none;\";\n shadowRoot = hostEl.attachShadow({ mode: \"open\" });\n }\n // else: fallback - hostEl is just a plain container, styles go into document.head\n\n // Create the widget root element\n rootEl = document.createElement(\"div\");\n rootEl.className = \"namiru-widget-root\";\n\n // Render root is the shadow root when available, otherwise the host div itself\n const renderRoot: ShadowRoot | HTMLElement = shadowRoot || hostEl;\n\n if (supportsShadow) {\n // Re-enable pointer events on actual widget content inside shadow DOM\n rootEl.style.pointerEvents = \"auto\";\n }\n renderRoot.appendChild(rootEl);\n\n // Initialize: fetch branding, then render\n async function bootstrap(): Promise<void> {\n try {\n const branding = await apiClient.fetchBranding(config.agentId);\n\n if (destroyed) return;\n\n // Domain locking check using allowedDomains from the public config\n if (!isDomainAllowed(branding.allowedDomains)) {\n console.warn(\n `[Namiru Widget] Domain \"${window.location.hostname}\" is not allowed for this agent. Allowed: ${JSON.stringify(branding.allowedDomains)}`\n );\n return; // Do not render the widget\n }\n\n // Route exclusion check using excludedRoutes from the public config\n if (isRouteExcluded(branding.excludedRoutes)) {\n console.info(\n `[Namiru Widget] Widget hidden on excluded route \"${window.location.pathname}\"`\n );\n return; // Do not render the widget on this route\n }\n\n // Note: Branding properties (colors, fonts, messages) are loaded from server\n // and are no longer configurable via client-side config for consistency\n\n // Inject widget styles into the render root (shadow DOM or document.head fallback)\n injectStyles({\n primaryColor: branding.primaryColor,\n accentColor: branding.accentColor,\n headerColor: branding.headerColor,\n fontFamily: branding.fontFamily,\n presetTheme: branding.presetTheme,\n backgroundColor: branding.backgroundColor,\n textColor: branding.textColor,\n fontSize: branding.fontSize,\n userMessageColor: branding.userMessageColor,\n agentMessageColor: branding.agentMessageColor,\n borderColor: branding.borderColor,\n inputColor: branding.inputColor,\n buttonColor: branding.buttonColor,\n }, renderRoot, !supportsShadow);\n\n // Override suggested questions from init config if provided\n if (config.suggestedQuestions && config.suggestedQuestions.length > 0) {\n branding.suggestedQuestions = config.suggestedQuestions;\n }\n console.log(\"[NamiruChat] suggestedQuestions:\", branding.suggestedQuestions);\n\n // Merge server-side config with local config\n const preChatEnabled =\n config.preChatEnabled ??\n branding.preChatConfig?.enabled ??\n false;\n\n // Ensure branding.preChatConfig reflects widget-level overrides so\n // showPreChat() in chat-window.ts can read it correctly\n if (preChatEnabled) {\n if (!branding.preChatConfig) {\n branding.preChatConfig = {\n enabled: true,\n template: config.preChatTemplate ?? null,\n custom: config.preChatCustom,\n };\n } else {\n branding.preChatConfig.enabled = true;\n if (config.preChatTemplate !== undefined) {\n branding.preChatConfig.template = config.preChatTemplate;\n }\n if (config.preChatCustom) {\n branding.preChatConfig.custom = config.preChatCustom;\n }\n }\n }\n feedbackEnabled = branding.feedbackConfig?.enabled ?? false;\n const feedbackInactivityMinutes =\n branding.feedbackConfig?.inactivityMinutes ?? 3;\n\n // Create inactivity timer for feedback prompt\n if (feedbackEnabled) {\n inactivityTimer = new InactivityTimer(feedbackInactivityMinutes, () => {\n const currentState = store.getState();\n if (\n !currentState.feedbackGiven &&\n currentState.state === \"chatting\" &&\n currentState.messages.length > 0\n ) {\n store.dispatch({ type: \"SET_STATE\", state: \"feedback\" });\n }\n });\n }\n\n // Create chat window\n chatWindowEl = createChatWindow({\n store,\n branding,\n agentId: config.agentId,\n mode,\n position,\n onSendMessage: (content: string) => {\n const userMsg: ChatMessage = {\n id: createMessageId(),\n role: \"user\",\n content,\n timestamp: Date.now(),\n };\n store.dispatch({ type: \"ADD_MESSAGE\", message: userMsg });\n store.dispatch({ type: \"SET_LOADING\", isLoading: true });\n\n if (wsClient) {\n wsClient.sendMessage(content);\n }\n },\n onPreChatSelect: (label: string) => {\n store.dispatch({ type: \"SET_QUALIFICATION\", qualification: label });\n store.dispatch({ type: \"SET_STATE\", state: \"connecting\" });\n connectWebSocket(label);\n },\n onFeedback: (rating: \"up\" | \"down\") => {\n const sessionId = store.getState().sessionId;\n if (sessionId) {\n apiClient\n .submitFeedback(config.agentId, { sessionId, rating })\n .catch((err) =>\n console.error(\"NamiruChat: feedback submit failed\", err)\n );\n }\n store.dispatch({ type: \"SET_FEEDBACK_GIVEN\" });\n inactivityTimer?.stop();\n config.onFeedback?.(rating);\n },\n onEscalationEmail: (email: string) => {\n const sessionId = store.getState().sessionId;\n if (sessionId) {\n apiClient\n .submitEscalation(config.agentId, { sessionId, userEmail: email })\n .catch((err) =>\n console.error(\"NamiruChat: escalation submit failed\", err)\n );\n }\n // Also notify backend-ai via WebSocket to persist customerEmail on the session\n if (wsClient) {\n wsClient.sendEscalationEmail(email);\n }\n config.onLeadCapture?.({\n email,\n sessionId: sessionId || \"\",\n source: \"email_fallback\",\n qualification: store.getState().qualification || undefined,\n });\n },\n onTranscriptEmail: (email: string) => {\n const sessionId = store.getState().sessionId;\n if (sessionId) {\n apiClient\n .requestTranscript(config.agentId, sessionId, { email })\n .catch((err) =>\n console.error(\"NamiruChat: transcript request failed\", err)\n );\n }\n },\n onContactFormSubmit: (data: { name: string; email: string; message: string }) => {\n const visitorId = getOrCreateVisitorId();\n const sessionId = store.getState().sessionId;\n apiClient\n .submitLead({\n agentId: config.agentId,\n name: data.name || undefined,\n email: data.email,\n message: data.message,\n visitorId,\n fallbackReason: lastHandoffReason as \"handoff_accepted\" | \"message_limit\" | \"conversation_limit\",\n conversationId: sessionId || undefined,\n })\n .catch((err) =>\n console.error(\"NamiruChat: lead submit failed\", err)\n );\n // Notify backend-ai to persist handoff metadata on the session\n if (wsClient) {\n wsClient.sendHandoffComplete({\n email: data.email,\n name: data.name || undefined,\n reason: lastHandoffReason,\n });\n }\n config.onLeadCapture?.({\n email: data.email,\n sessionId: sessionId || \"\",\n source: \"email_fallback\",\n qualification: store.getState().qualification || undefined,\n });\n },\n onLimitMessage: (data: { message: string; visitorEmail?: string }) => {\n if (data.visitorEmail) {\n // Contact endpoint sends email AND persists lead -- no need\n // to also call limit-message (which would duplicate the email).\n apiClient\n .submitContactMessage(config.agentId, {\n email: data.visitorEmail,\n message: data.message,\n visitorId: getOrCreateVisitorId(),\n })\n .catch((err) =>\n console.error(\"NamiruChat: contact message submit failed\", err)\n );\n } else {\n // No email provided -- limit-message is the only way to\n // notify the owner.\n apiClient\n .submitLimitMessage({\n agentId: config.agentId,\n message: data.message,\n })\n .catch((err) =>\n console.error(\"NamiruChat: limit message submit failed\", err)\n );\n }\n },\n feedbackEnabled,\n onNewChat: () => {\n // Disconnect existing WebSocket\n if (wsClient) {\n wsClient.disconnect();\n wsClient = null;\n }\n // Stop inactivity timer for the old session\n inactivityTimer?.stop();\n // Reset store state (clears messages, session, etc.)\n store.dispatch({ type: \"RESET\" });\n // Keep widget open and show connecting state\n store.dispatch({ type: \"SET_OPEN\", isOpen: true });\n store.dispatch({ type: \"SET_STATE\", state: \"connecting\" });\n connectWebSocket();\n },\n });\n\n rootEl!.appendChild(chatWindowEl);\n\n // Button mode: create the floating bubble\n if (mode === \"button\") {\n buttonEl = createButtonBubble({\n position,\n store,\n welcomeMessage: branding.bubbleGreeting || undefined,\n greetingDelay: config.greetingDelay,\n bubbleStyle: branding.bubbleStyle,\n onCloseRequest: () => {\n const currentState = store.getState();\n // Same logic as X button in chat-header\n if (\n feedbackEnabled &&\n !currentState.feedbackGiven &&\n currentState.state === \"chatting\" &&\n currentState.messages.length > 0\n ) {\n store.dispatch({ type: \"SET_STATE\", state: \"feedback\" });\n return;\n }\n if (currentState.messages.length === 0) {\n store.dispatch({ type: \"SET_OPEN\", isOpen: false });\n return;\n }\n // Show confirmation modal\n const showConfirm = (chatWindowEl as any)?._namiruShowCloseConfirmation;\n if (typeof showConfirm === \"function\") {\n showConfirm();\n } else {\n store.dispatch({ type: \"SET_OPEN\", isOpen: false });\n }\n },\n });\n rootEl!.appendChild(buttonEl);\n }\n\n // Apply fixed dimensions for inline mode\n if (mode === \"inline\" && chatWindowEl) {\n const w = config.width || \"100%\";\n const h = config.height || \"100%\";\n chatWindowEl.style.width = w;\n chatWindowEl.style.height = h;\n chatWindowEl.style.maxHeight = h;\n // Ensure height propagates through the DOM chain\n rootEl!.style.height = \"100%\";\n }\n\n // Mount to DOM\n if (supportsShadow) {\n // Shadow DOM path: mount the host element (which contains the shadow root)\n if (mode === \"inline\" && config.container) {\n hostEl!.style.cssText = \"all:initial;display:block;height:100%;\";\n config.container.appendChild(hostEl!);\n } else {\n document.body.appendChild(hostEl!);\n }\n } else {\n // Fallback path: mount rootEl directly (old behavior)\n if (mode === \"inline\" && config.container) {\n config.container.appendChild(rootEl!);\n } else {\n document.body.appendChild(rootEl!);\n }\n }\n\n // Determine initial state\n // Usage limits are checked by backend-ai during WebSocket init.\n // If limit is reached, backend-ai sends a 'usage_limit' event instead of 'agent_initialized'.\n if (preChatEnabled) {\n store.dispatch({ type: \"SET_STATE\", state: \"pre_chat\" });\n } else {\n store.dispatch({ type: \"SET_STATE\", state: \"connecting\" });\n connectWebSocket();\n }\n\n // Auto-open in inline mode\n if (mode === \"inline\") {\n store.dispatch({ type: \"SET_OPEN\", isOpen: true });\n }\n\n // Watch for SPA route changes to re-evaluate excluded routes\n if (branding.excludedRoutes && branding.excludedRoutes.length > 0) {\n const mountedEl = supportsShadow ? hostEl : rootEl;\n routeCleanup = watchRouteChanges(branding.excludedRoutes, mountedEl);\n }\n } catch (err) {\n console.error(\"NamiruChat: initialization failed\", err);\n store.dispatch({\n type: \"SET_ERROR\",\n error: \"Failed to load chat. Please try again later.\",\n });\n }\n }\n\n function maybeShowPendingEscalation(): void {\n if (!pendingEscalationForm) return;\n pendingEscalationForm = false;\n // Directly call the escalation form display after a short delay\n // to ensure the AI message renders first\n if (chatWindowEl) {\n setTimeout(() => {\n const showFn = (chatWindowEl as any)?._namiruShowEscalation;\n if (typeof showFn === \"function\") {\n showFn();\n }\n }, 100);\n }\n }\n\n function connectWebSocket(qualification?: string): void {\n if (wsClient || destroyed) return;\n\n wsClient = new WebSocketClient({\n url: wsUrl,\n agentId: config.agentId,\n visitorId: getOrCreateVisitorId(),\n });\n\n // Wire WebSocket events to store\n wsClient.on(\"connected\", () => {\n // Connection established, waiting for agent_initialized\n });\n\n wsClient.on(\"agent_initialized\", (event) => {\n store.dispatch({ type: \"SET_STATE\", state: \"chatting\" });\n store.dispatch({ type: \"SET_LOADING\", isLoading: false });\n\n if (event.data.sessionId) {\n store.dispatch({\n type: \"SET_SESSION_ID\",\n sessionId: event.data.sessionId,\n });\n config.onSessionStart?.(event.data.sessionId);\n }\n\n // Send qualification as first message context if present\n if (qualification) {\n wsClient?.sendMessage(\n `[User selected: ${qualification}]`\n );\n }\n\n });\n\n wsClient.on(\"stream_token\", (event) => {\n store.dispatch({ type: \"APPEND_STREAMING\", token: event.data.token });\n });\n\n wsClient.on(\"final_response\", (event) => {\n store.dispatch({ type: \"CLEAR_STREAMING\" });\n const assistantMsg: ChatMessage = {\n id: createMessageId(),\n role: \"assistant\",\n content: event.data.content || event.data.response || \"\",\n timestamp: Date.now(),\n };\n store.dispatch({ type: \"ADD_MESSAGE\", message: assistantMsg });\n store.dispatch({ type: \"SET_LOADING\", isLoading: false });\n\n // Show pending escalation form after the message renders\n maybeShowPendingEscalation();\n\n // If AI signals the conversation may have ended, show feedback immediately\n if (\n feedbackEnabled &&\n event.data.conversationMayHaveEnded &&\n !store.getState().feedbackGiven\n ) {\n // Short delay so the final message renders before feedback appears\n setTimeout(() => {\n const currentState = store.getState();\n if (\n !currentState.feedbackGiven &&\n currentState.state === \"chatting\" &&\n currentState.messages.length > 0\n ) {\n store.dispatch({ type: \"SET_STATE\", state: \"feedback\" });\n }\n }, 800);\n inactivityTimer?.stop();\n } else if (inactivityTimer && !store.getState().feedbackGiven) {\n // Reset inactivity timer after each assistant response\n inactivityTimer.reset();\n }\n });\n\n wsClient.on(\"stream_end\", () => {\n const streamingContent = store.getState().streamingContent;\n if (streamingContent) {\n store.dispatch({ type: \"CLEAR_STREAMING\" });\n const assistantMsg: ChatMessage = {\n id: createMessageId(),\n role: \"assistant\",\n content: streamingContent,\n timestamp: Date.now(),\n };\n store.dispatch({ type: \"ADD_MESSAGE\", message: assistantMsg });\n }\n store.dispatch({ type: \"SET_LOADING\", isLoading: false });\n\n // Show pending escalation form after the message renders\n maybeShowPendingEscalation();\n\n // Reset inactivity timer after each streamed response\n if (inactivityTimer && !store.getState().feedbackGiven) {\n inactivityTimer.reset();\n }\n });\n\n wsClient.on(\"tool_start\", () => {\n store.dispatch({ type: \"SET_LOADING\", isLoading: true });\n });\n\n wsClient.on(\"tool_end\", () => {\n // Loading continues until final_response or stream_end\n });\n\n wsClient.on(\"kit_trigger\", (event) => {\n const trigger = event.data;\n if (\n trigger === \"escalation_email_form\" ||\n trigger?.type === \"escalation_email_form\"\n ) {\n // Set flag so the form is shown AFTER the bot's final response renders\n pendingEscalationForm = true;\n }\n });\n\n // Handle handoff_active event - a human operator is handling this conversation\n wsClient.on(\"handoff_active\", (event) => {\n const msg: ChatMessage = {\n id: createMessageId(),\n role: \"assistant\",\n content: event.data?.message || \"A human operator is currently handling this conversation. Please wait for their response.\",\n timestamp: Date.now(),\n };\n store.dispatch({ type: \"ADD_MESSAGE\", message: msg });\n store.dispatch({ type: \"SET_LOADING\", isLoading: false });\n });\n\n // Handle show_handoff_form event from backend - triggers email fallback form\n wsClient.on(\"show_handoff_form\", (event) => {\n lastHandoffReason = event.data?.reason || \"handoff_accepted\";\n store.dispatch({ type: \"SET_STATE\", state: \"email_fallback\" });\n store.dispatch({ type: \"SET_LOADING\", isLoading: false });\n });\n\n wsClient.on(\"error\", (event) => {\n // If this is a usage limit error, switch to email fallback instead of showing error\n if (event.data?.type === \"usage_limit\" || event.data?.usage_limit) {\n store.dispatch({ type: \"SET_STATE\", state: \"conversation_limit\" });\n store.dispatch({ type: \"SET_LOADING\", isLoading: false });\n return;\n }\n // Domain not authorized - show dedicated error, no reconnect\n if (event.data?.message === \"Domain not authorized\") {\n store.dispatch({ type: \"SET_STATE\", state: \"domain_error\" });\n store.dispatch({ type: \"SET_LOADING\", isLoading: false });\n return;\n }\n console.error(\"NamiruChat: WebSocket error\", event.data);\n store.dispatch({\n type: \"SET_ERROR\",\n error: event.data?.message || \"Connection error. Please try again.\",\n });\n store.dispatch({ type: \"SET_LOADING\", isLoading: false });\n });\n\n wsClient.on(\"disconnected\", () => {\n // Reconnection is handled by WebSocketClient internally\n });\n\n wsClient.connect();\n }\n\n // Start initialization\n bootstrap();\n\n // Track open/close transitions to manage WS lifecycle\n // RESET is dispatched by close handlers BEFORE SET_OPEN:false, not here.\n let prevIsOpen = false;\n let lifecycleGuard = false;\n store.subscribe((state) => {\n if (destroyed || lifecycleGuard) return;\n\n // Close transition\n if (prevIsOpen && !state.isOpen) {\n prevIsOpen = false;\n lifecycleGuard = true;\n if (wsClient) {\n wsClient.disconnect();\n wsClient = null;\n }\n inactivityTimer?.stop();\n lifecycleGuard = false;\n return;\n }\n\n // Reopen transition (only reconnect if WS was disconnected)\n if (!prevIsOpen && state.isOpen && !wsClient) {\n prevIsOpen = true;\n lifecycleGuard = true;\n store.dispatch({ type: \"SET_STATE\", state: \"connecting\" });\n connectWebSocket();\n lifecycleGuard = false;\n return;\n }\n\n prevIsOpen = state.isOpen;\n });\n\n // Return the public API\n return {\n open: () => {\n if (!destroyed) {\n store.dispatch({ type: \"SET_OPEN\", isOpen: true });\n }\n },\n close: () => {\n if (!destroyed) {\n store.dispatch({ type: \"SET_OPEN\", isOpen: false });\n }\n },\n toggle: () => {\n if (!destroyed) {\n const isOpen = store.getState().isOpen;\n store.dispatch({ type: \"SET_OPEN\", isOpen: !isOpen });\n }\n },\n destroy: () => {\n if (destroyed) return;\n destroyed = true;\n\n routeCleanup?.();\n routeCleanup = null;\n wsClient?.disconnect();\n inactivityTimer?.stop();\n removeStyles();\n\n // Remove the mounted element (hostEl for shadow DOM, rootEl for fallback)\n const mountedEl = supportsShadow ? hostEl : rootEl;\n if (mountedEl && mountedEl.parentNode) {\n mountedEl.parentNode.removeChild(mountedEl);\n }\n\n const sessionId = store.getState().sessionId;\n if (sessionId) {\n config.onSessionEnd?.(sessionId);\n }\n\n store.dispatch({ type: \"RESET\" });\n\n hostEl = null;\n shadowRoot = null;\n rootEl = null;\n chatWindowEl = null;\n buttonEl = null;\n wsClient = null;\n },\n updateConfig: (partial: Partial<NamiruChatConfig>) => {\n if (destroyed) return;\n Object.assign(config, partial);\n },\n };\n}\n\n// Auto-init from script tag data attributes for backward compatibility\n// Supports: <script src=\".../widget.js\" data-agent-id=\"xxx\"></script>\nif (typeof document !== \"undefined\" && document.currentScript) {\n const scriptEl = document.currentScript as HTMLScriptElement;\n const agentId = scriptEl.getAttribute(\"data-agent-id\");\n\n if (agentId) {\n const mode =\n (scriptEl.getAttribute(\"data-mode\") as \"button\" | \"inline\") || \"button\";\n const serverUrl = scriptEl.getAttribute(\"data-server-url\") || undefined;\n const containerId = scriptEl.getAttribute(\"data-container-id\");\n\n init({\n agentId,\n mode,\n serverUrl,\n container: containerId\n ? document.getElementById(containerId) || undefined\n : undefined,\n });\n }\n}\n", "import type { ChatMessage } from \"./types\";\n\nexport type ChatState =\n | \"idle\"\n | \"pre_chat\"\n | \"connecting\"\n | \"chatting\"\n | \"feedback\"\n | \"escalation\"\n | \"email_fallback\"\n | \"conversation_limit\"\n | \"domain_error\"\n | \"error\";\n\nexport interface ChatStoreState {\n state: ChatState;\n messages: ChatMessage[];\n isOpen: boolean;\n isLoading: boolean;\n streamingContent: string;\n qualification: string | null;\n feedbackGiven: boolean;\n sessionId: string | null;\n error: string | null;\n}\n\nexport type ChatAction =\n | { type: \"SET_STATE\"; state: ChatState }\n | { type: \"SET_OPEN\"; isOpen: boolean }\n | { type: \"SET_LOADING\"; isLoading: boolean }\n | { type: \"ADD_MESSAGE\"; message: ChatMessage }\n | { type: \"APPEND_STREAMING\"; token: string }\n | { type: \"CLEAR_STREAMING\" }\n | { type: \"SET_QUALIFICATION\"; qualification: string }\n | { type: \"SET_FEEDBACK_GIVEN\" }\n | { type: \"SET_SESSION_ID\"; sessionId: string }\n | { type: \"SET_ERROR\"; error: string | null }\n | { type: \"RESET\" };\n\nexport type StoreSubscriber = (state: ChatStoreState) => void;\n\nfunction createInitialState(): ChatStoreState {\n return {\n state: \"idle\",\n messages: [],\n isOpen: false,\n isLoading: false,\n streamingContent: \"\",\n qualification: null,\n feedbackGiven: false,\n sessionId: null,\n error: null,\n };\n}\n\nfunction reducer(state: ChatStoreState, action: ChatAction): ChatStoreState {\n switch (action.type) {\n case \"SET_STATE\":\n return { ...state, state: action.state, error: null };\n\n case \"SET_OPEN\":\n return { ...state, isOpen: action.isOpen };\n\n case \"SET_LOADING\":\n return { ...state, isLoading: action.isLoading };\n\n case \"ADD_MESSAGE\":\n return { ...state, messages: [...state.messages, action.message] };\n\n case \"APPEND_STREAMING\":\n return {\n ...state,\n streamingContent: state.streamingContent + action.token,\n };\n\n case \"CLEAR_STREAMING\":\n return { ...state, streamingContent: \"\" };\n\n case \"SET_QUALIFICATION\":\n return { ...state, qualification: action.qualification };\n\n case \"SET_FEEDBACK_GIVEN\":\n return { ...state, feedbackGiven: true };\n\n case \"SET_SESSION_ID\":\n return { ...state, sessionId: action.sessionId };\n\n case \"SET_ERROR\":\n return {\n ...state,\n error: action.error,\n state: action.error ? \"error\" : state.state,\n };\n\n case \"RESET\":\n return createInitialState();\n\n default:\n return state;\n }\n}\n\nexport class ChatStore {\n private state: ChatStoreState;\n private subscribers: Set<StoreSubscriber> = new Set();\n\n constructor() {\n this.state = createInitialState();\n }\n\n getState(): ChatStoreState {\n return this.state;\n }\n\n dispatch(action: ChatAction): void {\n const prevState = this.state;\n this.state = reducer(prevState, action);\n if (this.state !== prevState) {\n this.notify();\n }\n }\n\n subscribe(subscriber: StoreSubscriber): () => void {\n this.subscribers.add(subscriber);\n return () => {\n this.subscribers.delete(subscriber);\n };\n }\n\n private notify(): void {\n const snapshot = this.state;\n this.subscribers.forEach((subscriber) => {\n try {\n subscriber(snapshot);\n } catch (err) {\n console.error(\"NamiruChat: error in store subscriber\", err);\n }\n });\n }\n}\n", "import type { AgentBrandingData } from \"./types\";\n\nexport interface ApiClientConfig {\n baseUrl: string;\n}\n\nexport interface FeedbackPayload {\n sessionId: string;\n rating: \"up\" | \"down\";\n comment?: string;\n}\n\nexport interface EscalationPayload {\n sessionId: string;\n userEmail: string;\n}\n\nexport interface TranscriptPayload {\n email: string;\n}\n\nexport interface TranscriptResponse {\n success: boolean;\n}\n\nexport interface LimitMessagePayload {\n agentId: string;\n message: string;\n visitorEmail?: string;\n}\n\nexport interface LeadSubmitPayload {\n agentId: string;\n name?: string;\n email: string;\n message: string;\n visitorId?: string;\n fallbackReason?: \"handoff_accepted\" | \"message_limit\" | \"conversation_limit\";\n conversationId?: string;\n}\n\nexport class ApiClient {\n private baseUrl: string;\n\n constructor(config: ApiClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, \"\");\n }\n\n async fetchBranding(agentId: string): Promise<AgentBrandingData> {\n const response = await fetch(\n `${this.baseUrl}/api/public/agents/${encodeURIComponent(agentId)}/branding`\n );\n\n if (!response.ok) {\n throw new Error(`Failed to fetch agent branding: ${response.status}`);\n }\n\n const data = await response.json();\n\n // Check for a branding sub-object (backward compat with old widget API)\n const branding = data.branding || {};\n\n function validHex(val: unknown, fallback: string): string {\n if (typeof val === \"string\" && /^#[0-9a-fA-F]{3,8}$/.test(val)) return val;\n return fallback;\n }\n\n // Parse suggested questions from JSON string or array\n let suggestedQuestions: string[] = [];\n if (Array.isArray(branding.suggestedQuestions)) {\n suggestedQuestions = branding.suggestedQuestions;\n } else if (typeof branding.suggestedQuestions === \"string\") {\n try {\n const parsed = JSON.parse(branding.suggestedQuestions);\n if (Array.isArray(parsed)) suggestedQuestions = parsed;\n } catch {\n // ignore parse errors\n }\n }\n\n return {\n agentId: data.id,\n name: branding.agentDisplayName || data.name,\n primaryColor: validHex(branding.primaryColor, \"#1f2937\"),\n accentColor: validHex(branding.accentColor, \"#21DFFB\"),\n logoUrl: branding.agentAvatar || branding.logoUrl || undefined,\n agentAvatar: branding.agentAvatar || branding.logoUrl || undefined,\n welcomeMessage: branding.welcomeMessage || undefined,\n showPoweredBy: branding.showPoweredBy ?? true,\n showHeader: branding.showHeader ?? true,\n headerColor: validHex(branding.headerColor, \"\") || undefined,\n headerTitle: branding.headerTitle || undefined,\n headerSubtitle: branding.headerSubtitle || undefined,\n presetTheme: branding.presetTheme || \"light\",\n backgroundColor: validHex(branding.backgroundColor, \"\") || undefined,\n textColor: validHex(branding.textColor, \"\") || undefined,\n bubbleStyle: branding.bubbleStyle || \"modern\",\n fontFamily: branding.fontFamily || \"system\",\n fontSize: branding.fontSize || \"medium\",\n userMessageColor: branding.userMessageColor === '' ? '' : (validHex(branding.userMessageColor, \"\") || undefined),\n agentMessageColor: branding.agentMessageColor === '' ? '' : (validHex(branding.agentMessageColor, \"\") || undefined),\n iconColor: validHex(branding.iconColor, \"\") || undefined,\n borderColor: validHex(branding.borderColor, \"\") || undefined,\n inputColor: validHex(branding.inputColor, \"\") || undefined,\n buttonColor: validHex(branding.buttonColor, \"\") || undefined,\n bubbleGreeting: branding.bubbleGreeting || undefined,\n suggestedQuestions,\n preChatConfig: data.preChatConfig\n ? {\n enabled: data.preChatConfig.enabled,\n template: data.preChatConfig.template,\n custom:\n data.preChatConfig.template === \"custom\" &&\n data.preChatConfig.customQuestion\n ? {\n question: data.preChatConfig.customQuestion,\n options: data.preChatConfig.customOptions || [],\n }\n : undefined,\n }\n : undefined,\n feedbackConfig: data.feedbackConfig ?? undefined,\n escalationConfig: data.escalationConfig\n ? {\n enabled:\n data.escalationConfig.emailFallbackEnabled ||\n data.escalationConfig.liveChatEnabled ||\n false,\n emailFallbackEnabled: data.escalationConfig.emailFallbackEnabled,\n customReplyMessage: data.escalationConfig.customReplyMessage,\n liveChatEnabled: data.escalationConfig.liveChatEnabled,\n }\n : undefined,\n allowedDomains: Array.isArray(data.allowedDomains) ? data.allowedDomains : undefined,\n excludedRoutes: Array.isArray(data.excludedRoutes) ? data.excludedRoutes : undefined,\n };\n }\n\n async submitFeedback(\n agentId: string,\n payload: FeedbackPayload\n ): Promise<void> {\n const response = await fetch(\n `${this.baseUrl}/api/public/agents/${encodeURIComponent(agentId)}/feedback`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n }\n );\n\n if (!response.ok) {\n throw new Error(`Failed to submit feedback: ${response.status}`);\n }\n }\n\n async submitEscalation(\n agentId: string,\n payload: EscalationPayload\n ): Promise<void> {\n const response = await fetch(\n `${this.baseUrl}/api/public/agents/${encodeURIComponent(agentId)}/escalate`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n }\n );\n\n if (!response.ok) {\n throw new Error(`Failed to submit escalation: ${response.status}`);\n }\n }\n\n async requestTranscript(\n agentId: string,\n sessionId: string,\n payload: TranscriptPayload\n ): Promise<TranscriptResponse> {\n const response = await fetch(\n `${this.baseUrl}/api/public/agents/${encodeURIComponent(agentId)}/sessions/${encodeURIComponent(sessionId)}/transcript`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n }\n );\n\n if (!response.ok) {\n throw new Error(`Failed to request transcript: ${response.status}`);\n }\n\n return response.json();\n }\n\n async submitLimitMessage(payload: LimitMessagePayload): Promise<{ success: boolean }> {\n const response = await fetch(`${this.baseUrl}/api/leads/limit-message`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to submit limit message: ${response.status}`);\n }\n\n return response.json();\n }\n\n async submitContactMessage(\n agentId: string,\n payload: { email: string; message: string; visitorId?: string }\n ): Promise<{ success: boolean }> {\n const response = await fetch(\n `${this.baseUrl}/api/public/agents/${encodeURIComponent(agentId)}/contact`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n }\n );\n\n if (!response.ok) {\n throw new Error(`Failed to submit contact message: ${response.status}`);\n }\n\n return response.json();\n }\n\n async submitLead(payload: LeadSubmitPayload): Promise<{ success: boolean }> {\n const response = await fetch(`${this.baseUrl}/api/leads`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to submit lead: ${response.status}`);\n }\n\n return response.json();\n }\n}\n", "export type WebSocketEventType =\n | \"connected\"\n | \"disconnected\"\n | \"agent_initialized\"\n | \"stream_token\"\n | \"final_response\"\n | \"stream_end\"\n | \"tool_start\"\n | \"tool_end\"\n | \"kit_trigger\"\n | \"usage_limit\"\n | \"show_handoff_form\"\n | \"handoff_active\"\n | \"error\"\n | \"status\";\n\nexport interface WebSocketEvent {\n type: WebSocketEventType;\n data: any;\n}\n\nexport type WebSocketEventHandler = (event: WebSocketEvent) => void;\n\nexport interface WebSocketClientConfig {\n url: string;\n agentId: string;\n token?: string;\n visitorId?: string;\n maxReconnectAttempts?: number;\n}\n\nconst MAX_RECONNECT_ATTEMPTS_DEFAULT = 3;\nconst RECONNECT_BASE_DELAY_MS = 1000;\n\nexport class WebSocketClient {\n private ws: WebSocket | null = null;\n private config: WebSocketClientConfig;\n private listeners: Map<WebSocketEventType, Set<WebSocketEventHandler>> =\n new Map();\n private reconnectAttempts = 0;\n private maxReconnectAttempts: number;\n private isDestroyed = false;\n private isInitialized = false;\n\n constructor(config: WebSocketClientConfig) {\n this.config = config;\n this.maxReconnectAttempts =\n config.maxReconnectAttempts ?? MAX_RECONNECT_ATTEMPTS_DEFAULT;\n }\n\n connect(): void {\n if (this.isDestroyed) return;\n\n try {\n this.ws = new WebSocket(this.config.url);\n this.ws.onopen = this.handleOpen.bind(this);\n this.ws.onmessage = this.handleMessage.bind(this);\n this.ws.onclose = this.handleClose.bind(this);\n this.ws.onerror = this.handleError.bind(this);\n } catch (err) {\n this.emit(\"error\", {\n message: err instanceof Error ? err.message : \"WebSocket connection failed\",\n });\n }\n }\n\n disconnect(): void {\n this.isDestroyed = true;\n if (this.ws) {\n this.ws.onclose = null;\n this.ws.close();\n this.ws = null;\n }\n }\n\n sendMessage(content: string): void {\n this.send({ type: \"message\", content });\n }\n\n sendHandoffComplete(data: { email: string; name?: string; reason: string }): void {\n this.send({ type: \"handoff_complete\", ...data });\n }\n\n sendEscalationEmail(email: string): void {\n this.send({ type: \"escalation_email\", email });\n }\n\n on(type: WebSocketEventType, handler: WebSocketEventHandler): () => void {\n if (!this.listeners.has(type)) {\n this.listeners.set(type, new Set());\n }\n this.listeners.get(type)!.add(handler);\n\n return () => {\n this.listeners.get(type)?.delete(handler);\n };\n }\n\n private send(data: Record<string, unknown>): void {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.send(JSON.stringify(data));\n }\n }\n\n private emit(type: WebSocketEventType, data: any = {}): void {\n const event: WebSocketEvent = { type, data };\n this.listeners.get(type)?.forEach((handler) => {\n try {\n handler(event);\n } catch (err) {\n console.error(`NamiruChat: error in ${type} handler`, err);\n }\n });\n }\n\n private handleOpen(): void {\n this.reconnectAttempts = 0;\n this.emit(\"connected\", {});\n\n // Send init_agent on first connection\n if (!this.isInitialized) {\n this.send({\n type: \"init_agent\",\n agentId: this.config.agentId,\n token: this.config.token || \"\",\n visitorId: this.config.visitorId || \"\",\n });\n }\n }\n\n private handleMessage(event: MessageEvent): void {\n let data: any;\n try {\n data = JSON.parse(event.data);\n } catch {\n return;\n }\n\n const type = data.type as WebSocketEventType;\n\n switch (type) {\n case \"agent_initialized\":\n this.isInitialized = true;\n this.emit(\"agent_initialized\", data);\n break;\n\n case \"stream_token\":\n this.emit(\"stream_token\", data);\n break;\n\n case \"final_response\":\n this.emit(\"final_response\", data);\n break;\n\n case \"stream_end\":\n this.emit(\"stream_end\", data);\n break;\n\n case \"tool_start\":\n this.emit(\"tool_start\", data);\n break;\n\n case \"tool_end\":\n // Check for kit triggers in tool output\n this.handleToolEnd(data);\n break;\n\n case \"usage_limit\":\n this.emit(\"usage_limit\", data);\n // Also emit as error so the widget can handle it\n this.emit(\"error\", { ...data, usage_limit: true });\n break;\n\n case \"show_handoff_form\":\n this.emit(\"show_handoff_form\", data);\n break;\n\n case \"handoff_active\":\n this.emit(\"handoff_active\", data);\n break;\n\n case \"error\":\n this.emit(\"error\", data);\n break;\n\n case \"status\":\n this.emit(\"status\", data);\n break;\n\n default:\n // Forward any unhandled types\n break;\n }\n }\n\n private handleToolEnd(data: any): void {\n this.emit(\"tool_end\", data);\n\n // Parse tool output for kit triggers (e.g. escalation_email_form)\n if (data.output) {\n try {\n const output =\n typeof data.output === \"string\" ? JSON.parse(data.output) : data.output;\n if (output.kitTrigger) {\n this.emit(\"kit_trigger\", output.kitTrigger);\n }\n } catch {\n // Not JSON, ignore\n }\n }\n }\n\n private handleClose(event: CloseEvent): void {\n // Close code 1008 = policy violation (e.g. domain not authorized) - do not reconnect\n if (event.code === 1008) {\n this.isDestroyed = true;\n this.emit(\"disconnected\", { code: event.code, reason: event.reason, permanent: true });\n return;\n }\n\n this.emit(\"disconnected\", { code: event.code, reason: event.reason });\n\n if (!this.isDestroyed && this.reconnectAttempts < this.maxReconnectAttempts) {\n this.reconnectAttempts++;\n const delay = RECONNECT_BASE_DELAY_MS * Math.pow(2, this.reconnectAttempts - 1);\n setTimeout(() => this.connect(), delay);\n }\n }\n\n private handleError(): void {\n // The close event will fire after this, triggering reconnection logic\n this.emit(\"error\", { message: \"WebSocket connection error\" });\n }\n}\n", "export class InactivityTimer {\n private timerId: ReturnType<typeof setTimeout> | null = null;\n private minutes: number;\n private callback: () => void;\n\n constructor(minutes: number, callback: () => void) {\n this.minutes = minutes;\n this.callback = callback;\n }\n\n reset(): void {\n this.stop();\n this.timerId = setTimeout(() => {\n this.callback();\n }, this.minutes * 60 * 1000);\n }\n\n stop(): void {\n if (this.timerId !== null) {\n clearTimeout(this.timerId);\n this.timerId = null;\n }\n }\n\n updateMinutes(minutes: number): void {\n this.minutes = minutes;\n // If timer is already running, restart with new duration\n if (this.timerId !== null) {\n this.reset();\n }\n }\n}\n", "/**\n * Shared runtime flag indicating whether the widget is rendered inside Shadow DOM.\n * When false the widget falls back to direct DOM injection and needs !important\n * declarations to resist host-page CSS bleed-through.\n */\nexport let hasShadowDom = false;\n\nexport function setHasShadowDom(value: boolean): void {\n hasShadowDom = value;\n}\n", "export interface StyleOptions {\n primaryColor: string;\n accentColor?: string;\n headerColor?: string;\n fontFamily?: string;\n presetTheme?: \"light\" | \"dark\" | \"custom\";\n backgroundColor?: string;\n textColor?: string;\n fontSize?: \"small\" | \"medium\" | \"large\";\n userMessageColor?: string;\n agentMessageColor?: string;\n borderColor?: string;\n inputColor?: string;\n buttonColor?: string;\n}\n\nlet styleEl: HTMLStyleElement | null = null;\n\n/**\n * Inject widget styles into the given render root (Shadow DOM or fallback element).\n * When `useImportant` is true (fallback mode), key properties get !important\n * to resist host-page CSS bleed-through.\n */\nexport function injectStyles(\n options: string | StyleOptions,\n renderRoot: ShadowRoot | HTMLElement,\n useImportant?: boolean,\n): void {\n const opts: StyleOptions =\n typeof options === \"string\" ? { primaryColor: options } : options;\n\n const style = document.createElement(\"style\");\n style.setAttribute(\"data-namiru\", \"true\");\n\n style.textContent = getStyles(opts, useImportant);\n\n if (renderRoot instanceof ShadowRoot || renderRoot.shadowRoot) {\n renderRoot.appendChild(style);\n } else {\n // Fallback: inject into document.head like original behavior\n document.head.appendChild(style);\n }\n styleEl = style;\n}\n\nexport function removeStyles(): void {\n if (styleEl) {\n styleEl.remove();\n styleEl = null;\n }\n}\n\n\nfunction resolveFontFamily(font?: string): string {\n if (!font || font === \"system\") {\n return '\"Inter\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif';\n }\n if (font === \"modern\") return '\"Inter\", sans-serif';\n if (font === \"classic\") return '\"Georgia\", serif';\n return font;\n}\n\nfunction resolveFontSize(size?: string): string {\n if (size === \"small\") return \"13px\";\n if (size === \"large\") return \"17px\";\n return \"15px\";\n}\n\nfunction isLightColor(hex: string): boolean {\n let c = hex.replace(\"#\", \"\");\n if (c.length === 3) c = c[0] + c[0] + c[1] + c[1] + c[2] + c[2];\n if (c.length < 6 || !/^[0-9a-fA-F]{6}/.test(c)) return false;\n const r = parseInt(c.substring(0, 2), 16);\n const g = parseInt(c.substring(2, 4), 16);\n const b = parseInt(c.substring(4, 6), 16);\n return (r * 299 + g * 587 + b * 114) / 1000 > 150;\n}\n\nfunction getStyles(opts: StyleOptions, useImportant?: boolean): string {\n // Shorthand: appended to property values that host CSS commonly overrides.\n // Empty string when inside Shadow DOM (no need), \" !important\" in fallback mode.\n const _i = useImportant ? \" !important\" : \"\";\n const primary = opts.primaryColor;\n const accent = opts.accentColor || \"#21DFFB\";\n const fontStack = resolveFontFamily(opts.fontFamily);\n const fontSize = resolveFontSize(opts.fontSize);\n\n const isDark = opts.presetTheme === \"dark\";\n const bgColor = opts.backgroundColor || (isDark ? \"#0f0f1a\" : \"#ffffff\");\n const txtColor = opts.textColor || (isDark ? \"#ffffff\" : \"#1f2937\");\n // Use actual background luminance for derived colors (handles custom themes with dark bg)\n const isDarkBg = !isLightColor(bgColor);\n const borderColor = opts.borderColor || (isDarkBg ? \"rgba(255,255,255,0.15)\" : \"rgba(0,0,0,0.1)\");\n const bgSecondary = opts.inputColor || (isDarkBg ? \"rgba(255,255,255,0.08)\" : \"rgba(0,0,0,0.02)\");\n const txtSecondary = isDarkBg ? \"rgba(255,255,255,0.6)\" : \"rgba(0,0,0,0.45)\";\n const scrollThumb = isDarkBg ? \"rgba(255,255,255,0.2)\" : \"rgba(0,0,0,0.12)\";\n // Header background matches the chat background (like the Live Preview),\n // unless the user explicitly set a custom headerColor.\n const headerBg = opts.headerColor || bgColor;\n const headerTextColor = opts.headerColor\n ? (isLightColor(headerBg) ? \"#1f2937\" : \"#ffffff\")\n : txtColor;\n const headerTextSecondary = opts.headerColor\n ? (isLightColor(headerBg) ? \"rgba(0,0,0,0.5)\" : \"rgba(255,255,255,0.7)\")\n : txtSecondary;\n // Button background: custom buttonColor takes priority, then dark bg uses #0f0f1a, light bg uses primary color\n const buttonBg = opts.buttonColor || (isDarkBg ? \"#0f0f1a\" : primary);\n const buttonBgHover = adjustBrightness(buttonBg, -15);\n // User message bg: undefined = not set (use primary), '' = cleared (transparent), '#hex' = custom\n const userMsgBgVal = opts.userMessageColor !== undefined ? (opts.userMessageColor || \"transparent\") : primary;\n // User message text: contrast-aware based on bubble background luminance\n const userMsgText = userMsgBgVal === \"transparent\"\n ? txtColor\n : (isLightColor(userMsgBgVal) ? \"#1f2937\" : \"#ffffff\");\n\n return `\n/* Namiru Chat Widget Styles */\n.namiru-widget-root {\n --namiru-primary: ${primary};\n --namiru-primary-hover: ${adjustBrightness(primary, -15)};\n --namiru-accent: ${accent};\n --namiru-header-bg: ${headerBg};\n --namiru-header-text: ${headerTextColor};\n --namiru-header-text-secondary: ${headerTextSecondary};\n --namiru-bg: ${bgColor};\n --namiru-bg-secondary: ${bgSecondary};\n --namiru-text: ${txtColor};\n --namiru-text-secondary: ${txtSecondary};\n --namiru-border: ${borderColor};\n --namiru-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);\n --namiru-radius: 12px;\n --namiru-font: ${fontStack};\n --namiru-font-size: ${fontSize};\n --namiru-scroll-thumb: ${scrollThumb};\n --namiru-user-msg-bg: ${userMsgBgVal};\n --namiru-user-msg-text: ${userMsgText};\n --namiru-agent-msg-bg: ${opts.agentMessageColor || \"transparent\"};\n --namiru-button-bg: ${buttonBg};\n --namiru-button-bg-hover: ${buttonBgHover};\n font-family: var(--namiru-font)${_i};\n font-size: var(--namiru-font-size)${_i};\n color: var(--namiru-text)${_i};\n line-height: 1.5${_i};\n box-sizing: border-box${_i};\n}\n\n.namiru-widget-root *, .namiru-widget-root *::before, .namiru-widget-root *::after {\n box-sizing: border-box${_i};\n margin: 0;\n padding: 0;\n}\n\n/* Button bubble (floating launcher) */\n.namiru-button {\n position: fixed;\n width: 56px;\n height: 56px;\n border-radius: 50%;\n background: #0f0f1a;\n border: 1px solid var(--namiru-border);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: var(--namiru-shadow);\n transition: transform 0.2s ease, background 0.2s ease;\n z-index: 2147483646;\n color: #ffffff;\n}\n\n.namiru-button:hover {\n transform: scale(1.08);\n background: #1a1a2e;\n}\n\n.namiru-button--bottom-right {\n bottom: 20px;\n right: 20px;\n}\n\n.namiru-button--bottom-left {\n bottom: 20px;\n left: 20px;\n}\n\n.namiru-button svg {\n width: 24px;\n height: 24px;\n fill: currentColor;\n}\n\n/* Chat popup */\n.namiru-popup {\n position: fixed;\n width: 440px;\n height: 600px;\n border-radius: var(--namiru-radius);\n background: var(--namiru-bg);\n border: 1px solid var(--namiru-border);\n box-shadow: var(--namiru-shadow);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n z-index: 2147483647;\n opacity: 0;\n transform: scale(0.95) translateY(10px);\n transition: opacity 0.2s ease, transform 0.2s ease;\n pointer-events: none;\n}\n\n.namiru-popup--open {\n opacity: 1;\n transform: scale(1) translateY(0);\n pointer-events: auto;\n}\n\n.namiru-popup--bottom-right {\n bottom: 88px;\n right: 20px;\n}\n\n.namiru-popup--bottom-left {\n bottom: 88px;\n left: 20px;\n}\n\n/* Inline mode */\n.namiru-inline {\n width: 100%;\n height: 100%;\n border-radius: var(--namiru-radius);\n background: var(--namiru-bg);\n border: 1px solid var(--namiru-border);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n/* Header */\n.namiru-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n background: var(--namiru-header-bg);\n border-bottom: 1px solid var(--namiru-border);\n min-height: 52px;\n flex-shrink: 0;\n}\n\n.namiru-header-left {\n display: flex;\n align-items: center;\n gap: 12px;\n min-width: 0;\n}\n\n.namiru-header-avatar {\n width: 36px;\n height: 36px;\n border-radius: 10px;\n object-fit: cover;\n flex-shrink: 0;\n}\n\n.namiru-header-avatar-fallback {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.namiru-header-info {\n min-width: 0;\n}\n\n.namiru-header-name {\n font-weight: 600;\n font-size: 14px;\n color: var(--namiru-header-text);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.namiru-header-subtitle {\n font-size: 12px;\n color: var(--namiru-header-text-secondary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.namiru-header-actions {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.namiru-header-btn {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--namiru-header-text-secondary);\n padding: 4px;\n border-radius: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: color 0.15s, background 0.15s;\n}\n\n.namiru-header-btn:hover {\n color: var(--namiru-header-text);\n background: var(--namiru-bg-secondary);\n}\n\n.namiru-header-btn svg {\n width: 18px;\n height: 18px;\n}\n\n/* Messages area */\n.namiru-messages {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n padding: 16px calc(max(16px, (100% - 540px) / 2));\n display: flex;\n flex-direction: column;\n gap: 16px;\n background: var(--namiru-bg);\n}\n\n.namiru-messages::-webkit-scrollbar {\n width: 4px;\n}\n\n.namiru-messages::-webkit-scrollbar-thumb {\n background: var(--namiru-scroll-thumb);\n border-radius: 2px;\n}\n\n/* Message rows */\n.namiru-message-row {\n display: flex;\n gap: 12px;\n max-width: 100%;\n}\n\n.namiru-message-row--user {\n justify-content: flex-end;\n}\n\n.namiru-message-row--assistant {\n justify-content: flex-start;\n gap: 6px;\n}\n\n.namiru-message-icon {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: flex-end;\n justify-content: center;\n flex-shrink: 0;\n margin-top: 4px;\n}\n\n.namiru-message-icon svg {\n width: 20px;\n height: 20px;\n margin-top: 3px;\n}\n\n.namiru-message-avatar-img {\n width: 24px;\n height: 24px;\n border-radius: 6px;\n object-fit: cover;\n}\n\n/* Message bubbles */\n.namiru-message {\n max-width: 75%;\n font-size: var(--namiru-font-size);\n line-height: 1.6;\n word-wrap: break-word;\n white-space: pre-wrap;\n}\n\n.namiru-message--user {\n padding: 10px 16px;\n background: var(--namiru-user-msg-bg);\n color: var(--namiru-user-msg-text);\n border-radius: 1.25rem 1.25rem 0.25rem 1.25rem;\n}\n\n.namiru-message--user.namiru-bubble--rounded {\n border-radius: 1rem;\n}\n\n.namiru-message--user.namiru-bubble--square {\n border-radius: 0.25rem;\n}\n\n.namiru-message--assistant {\n color: var(--namiru-text)${_i};\n background: var(--namiru-agent-msg-bg)${_i};\n padding: 10px 8px${_i};\n border-radius: 0.75rem${_i};\n margin-top: 0${_i};\n}\n\n.namiru-message-row--welcome .namiru-message--assistant {\n margin-top: 4px${_i};\n}\n\n/* Input area - rounded pill style */\n.namiru-input-area {\n padding: 12px calc(max(10px, (100% - 540px) / 2)) 8px;\n flex-shrink: 0;\n background: var(--namiru-bg);\n}\n\n.namiru-input-row {\n display: flex;\n align-items: center;\n gap: 8px;\n border-radius: 9999px;\n border: 1px solid var(--namiru-border);\n background: var(--namiru-bg-secondary);\n padding: 6px 6px 6px 16px;\n}\n\n.namiru-input {\n flex: 1;\n border: none${_i};\n background: transparent${_i};\n font-size: 14px${_i};\n font-family: var(--namiru-font)${_i};\n outline: none${_i};\n resize: none${_i};\n max-height: 100px;\n line-height: 1.4${_i};\n color: var(--namiru-text)${_i};\n padding: 4px 0${_i};\n}\n\n.namiru-input::placeholder {\n color: var(--namiru-text-secondary)${_i};\n}\n\n.namiru-send-btn {\n width: 28px;\n height: 28px;\n border-radius: 50%;\n background: var(--namiru-button-bg);\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #ffffff;\n flex-shrink: 0;\n transition: background 0.15s, opacity 0.15s;\n}\n\n.namiru-send-btn:hover {\n background: var(--namiru-button-bg-hover);\n}\n\n.namiru-send-btn:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.namiru-send-btn svg {\n width: 14px;\n height: 14px;\n}\n\n/* Suggested questions */\n.namiru-suggestions {\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n max-width: 70%;\n margin-left: auto;\n gap: 8px;\n padding: 4px 0;\n}\n\n.namiru-suggestion-chip {\n font-size: 12px;\n padding: 6px 12px;\n border-radius: 9999px;\n border: 1px solid var(--namiru-border);\n background: var(--namiru-bg-secondary);\n color: var(--namiru-text);\n cursor: pointer;\n white-space: normal;\n font-family: var(--namiru-font);\n transition: border-color 0.15s, background 0.15s;\n text-align: right;\n}\n\n.namiru-suggestion-chip:hover {\n border-color: var(--namiru-primary);\n background: var(--namiru-bg);\n}\n\n/* Pre-chat form */\n.namiru-prechat {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 24px 20px;\n gap: 20px;\n}\n\n.namiru-prechat-question {\n font-size: 16px;\n font-weight: 600;\n text-align: center;\n color: var(--namiru-text);\n}\n\n.namiru-prechat-options {\n display: flex;\n flex-direction: column;\n gap: 10px;\n width: 100%;\n max-width: 300px;\n}\n\n.namiru-prechat-option {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n border: 1px solid var(--namiru-border);\n border-radius: 10px;\n background: var(--namiru-bg);\n cursor: pointer;\n font-size: 14px;\n font-family: var(--namiru-font);\n color: var(--namiru-text);\n transition: border-color 0.15s, background 0.15s;\n text-align: left;\n width: 100%;\n}\n\n.namiru-prechat-option:hover {\n border-color: var(--namiru-primary);\n background: var(--namiru-bg-secondary);\n}\n\n.namiru-prechat-option svg {\n width: 20px;\n height: 20px;\n flex-shrink: 0;\n color: var(--namiru-primary);\n}\n\n/* Feedback prompt */\n.namiru-feedback {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 10px;\n padding: 20px 20px 12px;\n margin: 12px auto;\n max-width: 540px;\n background: none;\n border: none;\n border-top: 1px solid var(--namiru-border);\n border-radius: 0;\n box-shadow: none;\n}\n\n.namiru-feedback-label {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: var(--namiru-text);\n opacity: 0.85;\n}\n\n.namiru-feedback-text {\n font-size: 13px;\n color: var(--namiru-text-secondary);\n text-align: center;\n line-height: 1.5;\n}\n\n.namiru-feedback-buttons {\n display: flex;\n gap: 12px;\n}\n\n.namiru-feedback-btn {\n width: 40px;\n height: 40px;\n border-radius: 10px;\n border: 1.5px solid var(--namiru-text-secondary);\n background: var(--namiru-bg);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.15s, border-color 0.15s, color 0.15s;\n color: var(--namiru-text-secondary);\n}\n\n.namiru-feedback-btn-up:hover {\n border-color: #22c55e;\n color: #22c55e;\n}\n\n.namiru-feedback-btn-down:hover {\n border-color: #ef4444;\n color: #ef4444;\n}\n\n.namiru-feedback-btn svg {\n width: 20px;\n height: 20px;\n}\n\n.namiru-feedback-thanks {\n font-size: 14px;\n color: var(--namiru-text);\n font-weight: 600;\n padding: 4px 0;\n}\n\n\n/* Email form */\n.namiru-email-form {\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding: 14px;\n margin: 8px 0;\n background: var(--namiru-bg-secondary);\n border-radius: 12px;\n}\n\n.namiru-email-form-text {\n font-size: 13px;\n color: var(--namiru-text-secondary);\n}\n\n.namiru-email-form-row {\n display: flex;\n gap: 8px;\n}\n\n.namiru-email-input {\n flex: 1;\n border: 1px solid var(--namiru-border);\n border-radius: 8px;\n padding: 8px 12px;\n font-size: 13px;\n font-family: var(--namiru-font);\n outline: none;\n background: var(--namiru-bg);\n color: var(--namiru-text);\n}\n\n.namiru-email-input:focus {\n border-color: var(--namiru-primary);\n}\n\n.namiru-email-submit {\n padding: 8px 16px;\n border: none;\n border-radius: 8px;\n background: var(--namiru-primary);\n color: #ffffff;\n font-size: 13px;\n font-family: var(--namiru-font);\n cursor: pointer;\n white-space: nowrap;\n transition: background 0.15s;\n}\n\n.namiru-email-submit:hover {\n background: var(--namiru-primary-hover);\n}\n\n.namiru-email-submit:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.namiru-email-sent {\n font-size: 13px;\n color: var(--namiru-primary);\n font-weight: 500;\n text-align: center;\n padding: 8px;\n}\n\n/* Loading dots */\n.namiru-loading {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 13px 8px;\n align-self: center;\n}\n\n.namiru-loading-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--namiru-text-secondary);\n animation: namiru-bounce 1.4s infinite ease-in-out;\n}\n\n.namiru-loading-dot:nth-child(1) { animation-delay: 0s; }\n.namiru-loading-dot:nth-child(2) { animation-delay: 0.16s; }\n.namiru-loading-dot:nth-child(3) { animation-delay: 0.32s; }\n\n@keyframes namiru-bounce {\n 0%, 80%, 100% { transform: scale(0); }\n 40% { transform: scale(1); }\n}\n\n/* Connecting indicator */\n.namiru-connecting {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1;\n min-height: 80px;\n}\n\n.namiru-loading-dots {\n display: flex;\n gap: 4px;\n}\n\n/* Powered by */\n.namiru-powered {\n text-align: center;\n padding: 4px 6px 12px;\n font-size: 10px;\n color: var(--namiru-text-secondary);\n flex-shrink: 0;\n background: var(--namiru-bg);\n}\n\n.namiru-powered a {\n color: var(--namiru-primary);\n text-decoration: none;\n font-weight: 600;\n}\n\n.namiru-powered a:hover {\n text-decoration: underline;\n}\n\n/* Greeting bubble */\n.namiru-greeting {\n position: fixed;\n background: var(--namiru-bg);\n color: var(--namiru-text);\n padding: 12px 36px 12px 16px;\n border-radius: 12px;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12), 0 1px 4px rgba(0, 0, 0, 0.08);\n border: 1px solid var(--namiru-border);\n max-width: 240px;\n font-family: var(--namiru-font);\n font-size: 14px;\n line-height: 1.4;\n z-index: 2147483647;\n cursor: pointer;\n transition: opacity 0.2s ease, transform 0.2s ease;\n}\n\n.namiru-greeting--bottom-right {\n bottom: 84px;\n right: 20px;\n}\n\n.namiru-greeting--bottom-left {\n bottom: 84px;\n left: 20px;\n}\n\n.namiru-greeting--hidden {\n opacity: 0;\n transform: translateY(4px);\n pointer-events: none;\n}\n\n.namiru-greeting-close {\n position: absolute;\n top: 6px;\n right: 8px;\n width: 20px;\n height: 20px;\n border: none;\n background: transparent;\n cursor: pointer;\n color: var(--namiru-text-secondary);\n font-size: 14px;\n line-height: 1;\n padding: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n}\n\n.namiru-greeting-close:hover {\n color: var(--namiru-text);\n background: var(--namiru-bg-secondary);\n}\n\n/* Classic bubble style */\n.namiru-button--classic {\n border-radius: 16px;\n width: 60px;\n height: 48px;\n}\n\n/* Contact form (email fallback) */\n.namiru-contact-form {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 20px;\n flex: 1;\n overflow-y: auto;\n}\n\n.namiru-contact-heading {\n font-size: 15px;\n font-weight: 500;\n color: var(--namiru-text);\n line-height: 1.5;\n text-align: center;\n padding-bottom: 4px;\n}\n\n.namiru-contact-label {\n font-size: 12px;\n font-weight: 500;\n color: var(--namiru-text-secondary);\n}\n\n.namiru-contact-input {\n border: 1px solid var(--namiru-border);\n border-radius: 8px;\n padding: 10px 12px;\n font-size: 14px;\n font-family: var(--namiru-font);\n outline: none;\n background: var(--namiru-bg);\n color: var(--namiru-text);\n width: 100%;\n}\n\n.namiru-contact-input:focus {\n border-color: var(--namiru-primary);\n}\n\n.namiru-contact-textarea {\n border: 1px solid var(--namiru-border);\n border-radius: 8px;\n padding: 10px 12px;\n font-size: 14px;\n font-family: var(--namiru-font);\n outline: none;\n background: var(--namiru-bg);\n color: var(--namiru-text);\n width: 100%;\n resize: vertical;\n min-height: 80px;\n}\n\n.namiru-contact-textarea:focus {\n border-color: var(--namiru-primary);\n}\n\n.namiru-contact-error {\n font-size: 12px;\n color: #ef4444;\n}\n\n.namiru-contact-submit {\n padding: 10px 20px;\n border: none;\n border-radius: 8px;\n background: var(--namiru-primary);\n color: #ffffff;\n font-size: 14px;\n font-weight: 500;\n font-family: var(--namiru-font);\n cursor: pointer;\n transition: background 0.15s;\n width: 100%;\n}\n\n.namiru-contact-submit:hover {\n background: var(--namiru-primary-hover);\n}\n\n.namiru-contact-submit:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.namiru-contact-confirmation {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1;\n font-size: 15px;\n font-weight: 500;\n color: var(--namiru-primary);\n text-align: center;\n padding: 20px;\n}\n\n/* Limit overlay */\n.namiru-limit-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 24px 20px;\n gap: 12px;\n background: var(--namiru-bg);\n z-index: 10;\n}\n\n.namiru-limit-icon {\n color: var(--namiru-text-secondary);\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.namiru-limit-icon--success {\n color: var(--namiru-primary);\n}\n\n.namiru-limit-heading {\n font-size: 16px;\n font-weight: 600;\n color: var(--namiru-text);\n text-align: center;\n}\n\n.namiru-limit-subtext {\n font-size: 13px;\n color: var(--namiru-text-secondary);\n text-align: center;\n line-height: 1.5;\n max-width: 280px;\n}\n\n.namiru-limit-form {\n display: flex;\n flex-direction: column;\n gap: 10px;\n width: 100%;\n max-width: 300px;\n margin-top: 4px;\n}\n\n.namiru-limit-textarea {\n border: 1px solid var(--namiru-border);\n border-radius: 8px;\n padding: 10px 12px;\n font-size: 14px;\n font-family: var(--namiru-font);\n outline: none;\n background: var(--namiru-bg-secondary);\n color: var(--namiru-text);\n width: 100%;\n resize: vertical;\n min-height: 80px;\n}\n\n.namiru-limit-textarea::placeholder {\n color: var(--namiru-text-secondary);\n}\n\n.namiru-limit-textarea:focus {\n border-color: var(--namiru-primary);\n}\n\n.namiru-limit-email {\n border: 1px solid var(--namiru-border);\n border-radius: 8px;\n padding: 10px 12px;\n font-size: 14px;\n font-family: var(--namiru-font);\n outline: none;\n background: var(--namiru-bg-secondary);\n color: var(--namiru-text);\n width: 100%;\n}\n\n.namiru-limit-email::placeholder {\n color: var(--namiru-text-secondary);\n}\n\n.namiru-limit-email:focus {\n border-color: var(--namiru-primary);\n}\n\n.namiru-limit-submit {\n padding: 10px 20px;\n border: none;\n border-radius: 8px;\n background: var(--namiru-primary);\n color: #ffffff;\n font-size: 14px;\n font-weight: 500;\n font-family: var(--namiru-font);\n cursor: pointer;\n transition: background 0.15s;\n width: 100%;\n}\n\n.namiru-limit-submit:hover {\n background: var(--namiru-primary-hover);\n}\n\n.namiru-limit-submit:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.namiru-limit-confirmation {\n font-size: 15px;\n font-weight: 500;\n color: var(--namiru-primary);\n text-align: center;\n padding: 8px;\n line-height: 1.5;\n}\n\n.namiru-limit-newchat {\n padding: 10px 20px;\n border: 1px solid var(--namiru-border);\n border-radius: 8px;\n background: transparent;\n color: var(--namiru-text);\n font-size: 14px;\n font-weight: 500;\n font-family: var(--namiru-font);\n cursor: pointer;\n transition: background 0.15s;\n width: 100%;\n max-width: 300px;\n margin-top: 4px;\n}\n\n.namiru-limit-newchat:hover {\n background: var(--namiru-bg-secondary);\n}\n\n/* Mobile responsive */\n@media (max-width: 480px) {\n .namiru-popup {\n width: 100vw;\n height: 100vh;\n bottom: 0${_i};\n right: 0${_i};\n left: 0${_i};\n border-radius: 0;\n }\n .namiru-button {\n width: 48px;\n height: 48px;\n }\n .namiru-greeting {\n max-width: calc(100vw - 80px);\n }\n .namiru-greeting--bottom-right,\n .namiru-greeting--bottom-left {\n bottom: 76px;\n }\n}\n\n/* ---- Markdown styles for bot messages ---- */\n.namiru-md,\n.namiru-md *,\n.namiru-md p,\n.namiru-md span,\n.namiru-md li {\n color: var(--namiru-text)${_i};\n}\n\n.namiru-md p {\n margin: 0 0 0.5em 0${_i};\n display: block${_i};\n visibility: visible${_i};\n}\n.namiru-md p:last-child {\n margin-bottom: 0;\n}\n.namiru-md strong {\n font-weight: 700${_i};\n display: inline${_i};\n visibility: visible${_i};\n font-size: inherit${_i};\n opacity: 1${_i};\n}\n.namiru-md em {\n font-style: italic${_i};\n display: inline${_i};\n visibility: visible${_i};\n font-size: inherit${_i};\n opacity: 1${_i};\n}\n.namiru-md a.namiru-md-link {\n color: var(--namiru-primary)${_i};\n text-decoration: underline${_i};\n display: inline${_i};\n visibility: visible${_i};\n}\n.namiru-md a.namiru-md-link:hover {\n opacity: 0.8;\n}\n.namiru-md .namiru-md-code {\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 0.9em;\n background: rgba(0, 0, 0, 0.06);\n padding: 0.15em 0.4em;\n border-radius: 0.25rem;\n}\n.namiru-md .namiru-md-pre {\n background: #1e1e2e;\n color: #cdd6f4;\n padding: 0.75rem 1rem;\n border-radius: 0.5rem;\n overflow-x: auto;\n margin: 0.5em 0;\n font-size: 0.85em;\n}\n.namiru-md .namiru-md-pre code {\n background: transparent;\n padding: 0;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n}\n.namiru-md .namiru-md-ul,\n.namiru-md .namiru-md-ol {\n margin: 0.4em 0;\n padding-left: 1.5em;\n}\n.namiru-md .namiru-md-ul {\n list-style: disc;\n}\n.namiru-md .namiru-md-ol {\n list-style: decimal;\n}\n.namiru-md li {\n margin: 0.2em 0;\n display: list-item${_i};\n visibility: visible${_i};\n}\n.namiru-md .namiru-md-hr {\n border: none;\n border-top: 1px solid rgba(0,0,0,0.1);\n margin: 0.6em 0;\n}\n`;\n}\n\nfunction adjustBrightness(hex: string, amount: number): string {\n const cleaned = hex.replace(\"#\", \"\");\n const num = parseInt(cleaned, 16);\n if (isNaN(num) || cleaned.length < 6) return hex;\n const r = Math.max(0, Math.min(255, ((num >> 16) & 0xff) + amount));\n const g = Math.max(0, Math.min(255, ((num >> 8) & 0xff) + amount));\n const b = Math.max(0, Math.min(255, (num & 0xff) + amount));\n return `#${((r << 16) | (g << 8) | b).toString(16).padStart(6, \"0\")}`;\n}", "import { hasShadowDom } from \"./env\";\n\n/**\n * Lightweight markdown-to-HTML converter for the embeddable chat widget.\n *\n * Supports: **bold**, *italic*, `inline code`, ```code blocks```,\n * [links](url), unordered lists (- / *), ordered lists (1.), and line breaks.\n *\n * Bot messages only -- user messages should remain plain text.\n *\n * Security: output is set via innerHTML so we escape all HTML entities first,\n * then apply markdown transformations on the escaped string.\n */\n\nfunction escapeHtml(text: string): string {\n return text\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\");\n}\n\nexport function renderMarkdown(raw: string): string {\n // Escape HTML entities first to prevent XSS\n let text = escapeHtml(raw);\n\n // Replace em dashes with commas\n text = text.replace(/\\u2014/g, \", \");\n\n // Fenced code blocks: ```lang\\n...\\n```\n text = text.replace(\n /```(?:\\w*)\\n([\\s\\S]*?)```/g,\n '<pre class=\"namiru-md-pre\"><code>$1</code></pre>',\n );\n\n // Inline code: `code`\n text = text.replace(\n /`([^`\\n]+)`/g,\n '<code class=\"namiru-md-code\">$1</code>',\n );\n\n // Bold + italic: ***text*** or ___text___\n text = text.replace(\n /\\*\\*\\*(.+?)\\*\\*\\*/g,\n \"<strong><em>$1</em></strong>\",\n );\n\n // Bold: **text** or __text__\n text = text.replace(/\\*\\*(.+?)\\*\\*/g, \"<strong>$1</strong>\");\n text = text.replace(/__(.+?)__/g, \"<strong>$1</strong>\");\n\n // Italic: *text* or _text_ (but not inside words for _)\n text = text.replace(/\\*(.+?)\\*/g, \"<em>$1</em>\");\n text = text.replace(/(^|[\\s(])_(.+?)_([\\s).,!?]|$)/gm, \"$1<em>$2</em>$3\");\n\n // Links: [text](url)\n text = text.replace(\n /\\[([^\\]]+)\\]\\(([^)]+)\\)/g,\n '<a href=\"$2\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"namiru-md-link\">$1</a>',\n );\n\n // Horizontal rules: ---, ***, ___ (3+ chars, optionally with spaces)\n // Convert to a subtle visual break\n text = text.replace(/^[ \\t]*([-*_])\\s*\\1\\s*\\1[\\s\\-*_]*$/gm, '<hr class=\"namiru-md-hr\">');\n\n // Process line-by-line for lists and paragraphs\n const lines = text.split(\"\\n\");\n const result: string[] = [];\n let inUl = false;\n let inOl = false;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n\n // Skip already-converted horizontal rules (treat as block element)\n if (line.includes('<hr class=\"namiru-md-hr\">')) {\n if (inUl) { result.push(\"</ul>\"); inUl = false; }\n if (inOl) { result.push(\"</ol>\"); inOl = false; }\n result.push(line);\n continue;\n }\n\n const ulMatch = line.match(/^(\\s*)[-*]\\s+(.*)/);\n const olMatch = line.match(/^(\\s*)\\d+\\.\\s+(.*)/);\n\n if (ulMatch) {\n if (!inUl) {\n if (inOl) { result.push(\"</ol>\"); inOl = false; }\n result.push('<ul class=\"namiru-md-ul\">');\n inUl = true;\n }\n result.push(`<li>${ulMatch[2]}</li>`);\n } else if (olMatch) {\n if (!inOl) {\n if (inUl) { result.push(\"</ul>\"); inUl = false; }\n result.push('<ol class=\"namiru-md-ol\">');\n inOl = true;\n }\n result.push(`<li>${olMatch[2]}</li>`);\n } else {\n if (inUl) { result.push(\"</ul>\"); inUl = false; }\n if (inOl) { result.push(\"</ol>\"); inOl = false; }\n\n // Skip empty lines but preserve spacing\n if (line.trim() === \"\") {\n result.push(\"\");\n } else {\n result.push(line);\n }\n }\n }\n\n if (inUl) result.push(\"</ul>\");\n if (inOl) result.push(\"</ol>\");\n\n // Build HTML from result blocks, avoiding <br> inside lists\n let html = \"\";\n let insideList = false;\n\n for (const item of result) {\n if (item.includes(\"<hr\")) {\n html += item;\n } else if (item.startsWith(\"<ul\") || item.startsWith(\"<ol\")) {\n insideList = true;\n html += item;\n } else if (item === \"</ul>\" || item === \"</ol>\") {\n insideList = false;\n html += item;\n } else if (item.startsWith(\"<li>\")) {\n html += item;\n } else if (item.trim() === \"\") {\n // Empty line = paragraph break (only outside lists)\n if (!insideList) html += \"</p><p>\";\n } else {\n // Regular text line\n if (html.length > 0 && !insideList && !html.endsWith(\"<p>\") && !html.endsWith(\"</ul>\") && !html.endsWith(\"</ol>\") && !html.endsWith(\"</pre>\")) {\n html += \"<br>\";\n }\n html += item;\n }\n }\n\n // Wrap in paragraph if not starting with a block element\n if (!html.startsWith(\"<ul\") && !html.startsWith(\"<ol\") && !html.startsWith(\"<pre\")) {\n html = `<p>${html}</p>`;\n }\n\n // Clean up empty paragraphs\n html = html.replace(/<p>\\s*<\\/p>/g, \"\");\n\n // Clean up paragraphs wrapping block elements\n html = html.replace(/<p>(<(?:ul|ol|pre|hr)[^>]*>)/g, \"$1\");\n html = html.replace(/(<\\/(?:ul|ol|pre)>)<\\/p>/g, \"$1\");\n html = html.replace(/(<hr[^>]*>)<\\/p>/g, \"$1\");\n\n // When inside Shadow DOM, plain styles suffice. In fallback mode, !important\n // is needed to resist host-page CSS bleed-through.\n const i = hasShadowDom ? \"\" : \" !important\";\n html = html.replace(/<p>/g, `<p style=\"color: var(--namiru-text)${i}; margin: 0 0 0.5em 0${i}; max-width: 100%${i}; word-wrap: break-word${i}; display: block${i}; visibility: visible${i};\">`);\n html = html.replace(/<li>/g, `<li style=\"color: var(--namiru-text)${i}; margin: 0.2em 0${i}; display: list-item${i}; visibility: visible${i};\">`);\n html = html.replace(/<strong>/g, `<strong style=\"color: var(--namiru-text)${i}; font-weight: 700${i}; display: inline${i}; visibility: visible${i}; font-size: inherit${i}; opacity: 1${i};\">`);\n html = html.replace(/<em>/g, `<em style=\"color: var(--namiru-text)${i}; font-style: italic${i}; display: inline${i}; visibility: visible${i}; font-size: inherit${i}; opacity: 1${i};\">`);\n html = html.replace(/<a href=/g, `<a style=\"color: var(--namiru-primary)${i}; text-decoration: underline${i}; display: inline${i}; visibility: visible${i};\" href=`);\n\n return html;\n}\n", "// SVG icons created via DOM API (Phosphor-style)\n// Never uses innerHTML for security\n\nfunction createSvg(paths: string[], viewBox = \"0 0 256 256\"): SVGElement {\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.setAttribute(\"viewBox\", viewBox);\n svg.setAttribute(\"fill\", \"currentColor\");\n svg.setAttribute(\"xmlns\", \"http://www.w3.org/2000/svg\");\n\n for (const d of paths) {\n const path = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n path.setAttribute(\"d\", d);\n svg.appendChild(path);\n }\n\n return svg;\n}\n\nexport function headerBotIcon(fill?: string): SVGElement {\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.setAttribute(\"viewBox\", \"0 0 256 256\");\n svg.setAttribute(\"xmlns\", \"http://www.w3.org/2000/svg\");\n svg.setAttribute(\"width\", \"18\");\n svg.setAttribute(\"height\", \"18\");\n if (fill) svg.setAttribute(\"fill\", fill);\n else svg.setAttribute(\"fill\", \"currentColor\");\n\n // Phosphor Headset icon\n const path = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n path.setAttribute(\n \"d\",\n \"M201.89,54.66A103.43,103.43,0,0,0,128.79,24H128A104,104,0,0,0,24,128v56a24,24,0,0,0,24,24H64a24,24,0,0,0,24-24V144a24,24,0,0,0-24-24H40.36A88,88,0,0,1,128,40h.67a87.71,87.71,0,0,1,87,80H192a24,24,0,0,0-24,24v40a24,24,0,0,0,24,24h8a8,8,0,0,0,0-16h-8a8,8,0,0,1-8-8V144a8,8,0,0,1,8-8h24a8,8,0,0,1,8,8v56a40,40,0,0,1-40,40H152a8,8,0,0,0,0,16h32a56.06,56.06,0,0,0,56-56V128A103.41,103.41,0,0,0,201.89,54.66ZM64,136a8,8,0,0,1,8,8v40a8,8,0,0,1-8,8H48a8,8,0,0,1-8-8V136Z\"\n );\n svg.appendChild(path);\n return svg;\n}\n\nexport function namiruBirdIcon(fill?: string): SVGElement {\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.setAttribute(\"viewBox\", \"0 0 256 256\");\n svg.setAttribute(\"xmlns\", \"http://www.w3.org/2000/svg\");\n svg.setAttribute(\"width\", \"20\");\n svg.setAttribute(\"height\", \"20\");\n if (fill) svg.setAttribute(\"fill\", fill);\n else svg.setAttribute(\"fill\", \"currentColor\");\n\n // Phosphor Headset icon (same as headerBotIcon)\n const path = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n path.setAttribute(\n \"d\",\n \"M201.89,54.66A103.43,103.43,0,0,0,128.79,24H128A104,104,0,0,0,24,128v56a24,24,0,0,0,24,24H64a24,24,0,0,0,24-24V144a24,24,0,0,0-24-24H40.36A88,88,0,0,1,128,40h.67a87.71,87.71,0,0,1,87,80H192a24,24,0,0,0-24,24v40a24,24,0,0,0,24,24h8a8,8,0,0,0,0-16h-8a8,8,0,0,1-8-8V144a8,8,0,0,1,8-8h24a8,8,0,0,1,8,8v56a40,40,0,0,1-40,40H152a8,8,0,0,0,0,16h32a56.06,56.06,0,0,0,56-56V128A103.41,103.41,0,0,0,201.89,54.66ZM64,136a8,8,0,0,1,8,8v40a8,8,0,0,1-8,8H48a8,8,0,0,1-8-8V136Z\"\n );\n svg.appendChild(path);\n return svg;\n}\n\nexport function paperPlaneIcon(): SVGElement {\n return createSvg([\n \"M236.2,218.31A8,8,0,0,1,228,224a7.8,7.8,0,0,1-2.31-.34L160,205.42l-65.69,18.24a7.8,7.8,0,0,1-2.31.34,8,8,0,0,1-7.26-4.67,7.82,7.82,0,0,1-.58-1.39L32.76,72.8l0-.13A16,16,0,0,1,55.39,56.32l0,.13L236.54,210a8,8,0,0,1-.34,8.31ZM55.08,63.83,160,186.17V136L63.77,57Z\",\n ]);\n}\n\nexport function chatBubbleIcon(): SVGElement {\n return createSvg([\n \"M128,24A104,104,0,0,0,36.18,176.88L24.83,210.93a16,16,0,0,0,20.24,20.24l34.05-11.35A104,104,0,1,0,128,24Zm0,192a88.11,88.11,0,0,1-44.06-11.81,8,8,0,0,0-4-1.08,7.85,7.85,0,0,0-2.53.42L40,216l12.47-37.41a8,8,0,0,0-.66-6.54A88,88,0,1,1,128,216Z\",\n ]);\n}\n\nexport function closeIcon(): SVGElement {\n return createSvg([\n \"M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z\",\n ]);\n}\n\nexport function sendIcon(): SVGElement {\n // Phosphor PaperPlaneRight fill - matches preview PaperPlaneRight weight=\"fill\"\n return createSvg([\n \"M240,127.89a16,16,0,0,1-8.18,14L63.9,237.9A16.15,16.15,0,0,1,56,240a16,16,0,0,1-15-21.33l27-79.95A4,4,0,0,1,71.72,136H144a8,8,0,0,0,8-8.53,8.19,8.19,0,0,0-8.26-7.47h-72a4,4,0,0,1-3.79-2.72l-27-79.94A16,16,0,0,1,63.84,18.07l168,95.89A16,16,0,0,1,240,127.89Z\",\n ]);\n}\n\nexport function thumbsUpIcon(): SVGElement {\n return createSvg([\n \"M234,80.12A24,24,0,0,0,216,72H160V56a40,40,0,0,0-40-40,8,8,0,0,0-7.16,4.42L75.06,96H32a16,16,0,0,0-16,16v88a16,16,0,0,0,16,16H204a24,24,0,0,0,23.82-21.12l12-96A24,24,0,0,0,234,80.12ZM32,112H72v88H32ZM223.94,97l-12,96a8,8,0,0,1-7.94,7H88V105.89l36.71-73.43A24,24,0,0,1,144,56V80a8,8,0,0,0,8,8h64a8,8,0,0,1,7.94,9Z\",\n ]);\n}\n\nexport function thumbsDownIcon(): SVGElement {\n return createSvg([\n \"M239.82,157l-12-96A24,24,0,0,0,204,40H32A16,16,0,0,0,16,56v88a16,16,0,0,0,16,16H75.06l37.78,75.58A8,8,0,0,0,120,240a40,40,0,0,0,40-40V184h56a24,24,0,0,0,23.82-27ZM72,144H32V56H72Zm150,21.29a8,8,0,0,1-6,2.71H152a8,8,0,0,0-8,8v24a24,24,0,0,1-19.29,23.54L88,150.11V56H204a8,8,0,0,1,7.94,7l12,96A8,8,0,0,1,222,165.29Z\",\n ]);\n}\n\nexport function emailIcon(): SVGElement {\n return createSvg([\n \"M224,48H32a8,8,0,0,0-8,8V192a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A8,8,0,0,0,224,48ZM203.43,64,128,133.15,52.57,64ZM216,192H40V74.19l82.59,75.71a8,8,0,0,0,10.82,0L216,74.19V192Z\",\n ]);\n}\n\nexport function shoppingBagIcon(): SVGElement {\n return createSvg([\n \"M216,64H176a48,48,0,0,0-96,0H40A16,16,0,0,0,24,80V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V80A16,16,0,0,0,216,64ZM128,32a32,32,0,0,1,32,32H96A32,32,0,0,1,128,32Zm88,168H40V80H80V96a8,8,0,0,0,16,0V80h64V96a8,8,0,0,0,16,0V80h40Z\",\n ]);\n}\n\nexport function packageIcon(): SVGElement {\n return createSvg([\n \"M223.68,66.15,135.68,18a15.88,15.88,0,0,0-15.36,0l-88,48.17a16,16,0,0,0-8.32,14v95.64a16,16,0,0,0,8.32,14l88,48.17a15.88,15.88,0,0,0,15.36,0l88-48.17a16,16,0,0,0,8.32-14V80.18A16,16,0,0,0,223.68,66.15ZM128,32l80.34,44-29.77,16.3-80.35-44ZM128,120,47.66,76l33.9-18.56,80.34,44ZM40,90l80,43.78v85.79L40,175.82Zm96,129.57V133.82L216,90v85.78Z\",\n ]);\n}\n\nexport function creditCardIcon(): SVGElement {\n return createSvg([\n \"M224,48H32A16,16,0,0,0,16,64V192a16,16,0,0,0,16,16H224a16,16,0,0,0,16-16V64A16,16,0,0,0,224,48Zm0,16V88H32V64ZM32,192V104H224v88Zm16-24a8,8,0,0,1,8-8H96a8,8,0,0,1,0,16H56A8,8,0,0,1,48,168Zm0-32a8,8,0,0,1,8-8h64a8,8,0,0,1,0,16H56A8,8,0,0,1,48,136Z\",\n ]);\n}\n\nexport function chatCircleIcon(): SVGElement {\n return createSvg([\n \"M128,24A104,104,0,0,0,36.18,176.88L24.83,210.93a16,16,0,0,0,20.24,20.24l34.05-11.35A104,104,0,1,0,128,24Zm0,192a88.11,88.11,0,0,1-44.06-11.81,8,8,0,0,0-4-1.08,7.85,7.85,0,0,0-2.53.42L40,216l12.47-37.41a8,8,0,0,0-.66-6.54A88,88,0,1,1,128,216Z\",\n ]);\n}\n\nexport function rocketIcon(): SVGElement {\n return createSvg([\n \"M152,224a8,8,0,0,1-8,8H112a8,8,0,0,1,0-16h32A8,8,0,0,1,152,224Zm73.69-142.23-21.34-21.35C183.42,39.49,156.58,24,128,24s-55.42,15.49-76.35,36.42L30.31,81.77a16,16,0,0,0,0,22.63L64,138.09V184a16,16,0,0,0,4.69,11.31l24,24A16,16,0,0,0,104,224h48a16,16,0,0,0,11.31-4.69l24-24A16,16,0,0,0,192,184V138.09l33.69-33.69A16,16,0,0,0,225.69,81.77ZM128,40c22.59,0,43.85,12.28,60,32H68C84.15,52.28,105.41,40,128,40Zm48,144-24,24H104L80,184V88H176Zm36.28-79.6L192,172.69V88h17.94l4.34,4.34A.64.64,0,0,1,212.28,104.4ZM64,172.69,45.66,104.4a.64.64,0,0,1-2,0L48,100H64Z\",\n ]);\n}\n\nexport function wrenchIcon(): SVGElement {\n return createSvg([\n \"M226.76,69a8,8,0,0,0-12.84-2.88l-40.3,37.19-17.23-3.7-3.7-17.23,37.19-40.3A8,8,0,0,0,187,29.24,72,72,0,0,0,88,96c0,1.3,0,2.6.1,3.89L33.19,147.68a27.7,27.7,0,0,0,0,39.37l36.76,36.76a27.7,27.7,0,0,0,39.37,0l47.79-54.91c1.29.06,2.59.1,3.89.1a72,72,0,0,0,66.76-99ZM148.49,212.49a11.7,11.7,0,0,1-16.57,0L95.16,175.73a8,8,0,0,0-11.58.28L44.49,220.49a11.7,11.7,0,0,1-16.57,0L44.49,204a11.69,11.69,0,0,1,0-16.57l44.48-39.09a8,8,0,0,0,.28-11.58L52.49,100.05a56,56,0,0,1,89.36-63.58l-31.41,34a8,8,0,0,0-1.8,6.49l6,27.92a8,8,0,0,0,6.13,6.13l27.92,6a8,8,0,0,0,6.49-1.8l34-31.41A56,56,0,0,1,148.49,212.49Z\",\n ]);\n}\n\nexport function briefcaseIcon(): SVGElement {\n return createSvg([\n \"M216,56H176V48a24,24,0,0,0-24-24H104A24,24,0,0,0,80,48v8H40A16,16,0,0,0,24,72V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V72A16,16,0,0,0,216,56ZM96,48a8,8,0,0,1,8-8h48a8,8,0,0,1,8,8v8H96ZM216,72v72H40V72Zm0,128H40V160H216v40Z\",\n ]);\n}\n\nexport function userCircleIcon(): SVGElement {\n return createSvg([\n \"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24ZM74.08,197.5a64,64,0,0,1,107.84,0,87.83,87.83,0,0,1-107.84,0ZM96,120a32,32,0,1,1,32,32A32,32,0,0,1,96,120Zm97.76,66.41a79.66,79.66,0,0,0-36.06-28.75,48,48,0,1,0-59.4,0,79.66,79.66,0,0,0-36.06,28.75,88,88,0,1,1,131.52,0Z\",\n ]);\n}\n\nexport function dotsThreeIcon(): SVGElement {\n return createSvg([\n \"M140,128a12,12,0,1,1-12-12A12,12,0,0,1,140,128Zm56-12a12,12,0,1,0,12,12A12,12,0,0,0,196,116ZM60,116a12,12,0,1,0,12,12A12,12,0,0,0,60,116Z\",\n ]);\n}\n\nexport function transcriptIcon(): SVGElement {\n return createSvg([\n \"M213.66,82.34l-56-56A8,8,0,0,0,152,24H56A16,16,0,0,0,40,40V216a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V88A8,8,0,0,0,213.66,82.34ZM160,51.31,188.69,80H160ZM200,216H56V40h88V88a8,8,0,0,0,8,8h48V216Zm-32-80a8,8,0,0,1-8,8H96a8,8,0,0,1,0-16h64A8,8,0,0,1,168,136Zm0,32a8,8,0,0,1-8,8H96a8,8,0,0,1,0-16h64A8,8,0,0,1,168,168Z\",\n ]);\n}\n\nexport function newChatIcon(): SVGElement {\n // Chat bubble with a plus sign (Phosphor ChatPlus style)\n return createSvg([\n \"M216,48H40A16,16,0,0,0,24,64V224a15.84,15.84,0,0,0,9.25,14.5A16.05,16.05,0,0,0,40,240a15.89,15.89,0,0,0,10.25-3.78.69.69,0,0,0,.13-.11L92.69,200H216a16,16,0,0,0,16-16V64A16,16,0,0,0,216,48ZM216,184H92.69a15.86,15.86,0,0,0-10.31,3.78l-.12.11L40,224V64H216ZM152,128a8,8,0,0,1-8,8H136v8a8,8,0,0,1-16,0v-8H112a8,8,0,0,1,0-16h8v-8a8,8,0,0,1,16,0v8h8A8,8,0,0,1,152,128Z\",\n ]);\n}\n\nexport function openInNewWindowIcon(): SVGElement {\n // ArrowSquareOut (Phosphor) - open in new window\n return createSvg([\n \"M224,104a8,8,0,0,1-16,0V59.32l-66.33,66.34a8,8,0,0,1-11.32-11.32L196.68,48H152a8,8,0,0,1,0-16h64a8,8,0,0,1,8,8Zm-40,24a8,8,0,0,0-8,8v72H48V80h72a8,8,0,0,0,0-16H48A16,16,0,0,0,32,80V208a16,16,0,0,0,16,16H176a16,16,0,0,0,16-16V136A8,8,0,0,0,184,128Z\",\n ]);\n}\n\n// Map icon name strings to icon functions\nconst iconMap: Record<string, () => SVGElement> = {\n ShoppingBag: shoppingBagIcon,\n Package: packageIcon,\n CreditCard: creditCardIcon,\n ChatCircle: chatCircleIcon,\n Rocket: rocketIcon,\n Wrench: wrenchIcon,\n Briefcase: briefcaseIcon,\n UserCircle: userCircleIcon,\n DotsThree: dotsThreeIcon,\n};\n\nexport function getIconByName(name: string): SVGElement {\n const factory = iconMap[name];\n if (factory) return factory();\n return chatCircleIcon();\n}\n", "import { ChatStore } from \"../../core/state-machine\";\nimport type { AgentBrandingData } from \"../../core/types\";\nimport { closeIcon, transcriptIcon, headerBotIcon, newChatIcon, openInNewWindowIcon } from \"../icons\";\n\nexport interface ChatHeaderOptions {\n store: ChatStore;\n branding: AgentBrandingData;\n mode: \"button\" | \"inline\";\n onTranscriptClick?: () => void;\n onNewChat?: () => void;\n feedbackEnabled?: boolean;\n}\n\nfunction hexToRgb(hex: string): string {\n let c = hex.replace(\"#\", \"\");\n if (c.length === 3) {\n c = c[0] + c[0] + c[1] + c[1] + c[2] + c[2];\n }\n if (c.length < 6 || !/^[0-9a-fA-F]{6}/.test(c)) return \"74, 127, 255\";\n const r = parseInt(c.substring(0, 2), 16);\n const g = parseInt(c.substring(2, 4), 16);\n const b = parseInt(c.substring(4, 6), 16);\n return `${r}, ${g}, ${b}`;\n}\n\nexport function createChatHeader(options: ChatHeaderOptions): HTMLElement {\n const { store, branding, mode, onTranscriptClick, onNewChat, feedbackEnabled } = options;\n\n // If showHeader is explicitly false, return an empty hidden element\n if (branding.showHeader === false) {\n const empty = document.createElement(\"div\");\n empty.style.display = \"none\";\n return empty;\n }\n\n const header = document.createElement(\"div\");\n header.className = \"namiru-header\";\n\n // Left side: avatar + name/subtitle\n const left = document.createElement(\"div\");\n left.className = \"namiru-header-left\";\n\n const primaryRgb = hexToRgb(branding.primaryColor);\n\n if (branding.agentAvatar || branding.logoUrl) {\n const avatar = document.createElement(\"img\");\n avatar.className = \"namiru-header-avatar\";\n avatar.src = (branding.agentAvatar || branding.logoUrl)!;\n avatar.alt = branding.name;\n left.appendChild(avatar);\n } else {\n // Fallback: headset icon in a tinted box\n const fallback = document.createElement(\"div\");\n fallback.className = \"namiru-header-avatar-fallback\";\n fallback.style.background = `rgba(${primaryRgb}, 0.06)`;\n fallback.style.border = `none`;\n // Use custom iconColor if set, otherwise derive from theme\n const isDark = branding.presetTheme === \"dark\";\n const iconFill = branding.iconColor || (isDark ? \"#ffffff\" : branding.primaryColor);\n const icon = headerBotIcon(iconFill);\n fallback.appendChild(icon);\n left.appendChild(fallback);\n }\n\n const info = document.createElement(\"div\");\n info.className = \"namiru-header-info\";\n\n const name = document.createElement(\"div\");\n name.className = \"namiru-header-name\";\n name.textContent = branding.headerTitle || branding.name;\n info.appendChild(name);\n\n if (branding.headerSubtitle) {\n const subtitle = document.createElement(\"div\");\n subtitle.className = \"namiru-header-subtitle\";\n subtitle.textContent = branding.headerSubtitle;\n info.appendChild(subtitle);\n }\n\n left.appendChild(info);\n header.appendChild(left);\n\n // Right side: actions\n const actions = document.createElement(\"div\");\n actions.className = \"namiru-header-actions\";\n\n // Close button (only in button/popup mode)\n if (mode === \"button\") {\n const closeBtn = document.createElement(\"button\");\n closeBtn.className = \"namiru-header-btn\";\n closeBtn.setAttribute(\"aria-label\", \"Close chat\");\n closeBtn.appendChild(closeIcon());\n closeBtn.addEventListener(\"click\", () => {\n const currentState = store.getState();\n // Show feedback prompt on close if enabled, not yet given, and conversation happened\n if (\n feedbackEnabled &&\n !currentState.feedbackGiven &&\n currentState.state === \"chatting\" &&\n currentState.messages.length > 0\n ) {\n store.dispatch({ type: \"SET_STATE\", state: \"feedback\" });\n return;\n }\n // No messages yet: close immediately without confirmation\n if (currentState.messages.length === 0) {\n store.dispatch({ type: \"SET_OPEN\", isOpen: false });\n return;\n }\n // Has messages: show confirmation modal\n showCloseConfirmation(header, store);\n });\n actions.appendChild(closeBtn);\n }\n\n header.appendChild(actions);\n\n return header;\n}\n\nexport function showCloseConfirmation(headerEl: HTMLElement, store: ChatStore): void {\n // Find the chat window container (parent of header)\n const container = headerEl.parentElement;\n if (!container) {\n store.dispatch({ type: \"SET_OPEN\", isOpen: false });\n return;\n }\n\n // Prevent duplicate modals\n if (container.querySelector(\".namiru-close-confirm-overlay\")) return;\n\n const overlay = document.createElement(\"div\");\n overlay.className = \"namiru-close-confirm-overlay\";\n overlay.style.cssText =\n \"position:absolute;inset:0;z-index:50;display:flex;align-items:center;justify-content:center;padding:16px;background:rgba(0,0,0,0.35);backdrop-filter:blur(2px);animation:namiruConfirmFade 0.15s ease-out;\";\n\n const card = document.createElement(\"div\");\n card.style.cssText =\n \"background:var(--namiru-bg,#fff);border-radius:8px;border:1px solid var(--namiru-border,#e5e7eb);box-shadow:0 8px 24px rgba(0,0,0,0.12);padding:20px;width:100%;max-width:280px;animation:namiruConfirmSlide 0.2s cubic-bezier(0.16,1,0.3,1);\";\n\n const title = document.createElement(\"div\");\n title.style.cssText = \"font-size:14px;font-weight:600;color:var(--namiru-text,#1f2937);margin-bottom:4px;\";\n title.textContent = \"End conversation?\";\n card.appendChild(title);\n\n const subtitle = document.createElement(\"div\");\n subtitle.style.cssText = \"font-size:13px;color:var(--namiru-text-secondary,#6b7280);line-height:1.4;margin-bottom:16px;\";\n subtitle.textContent = \"We've received your message. Your chat history will not be saved.\";\n card.appendChild(subtitle);\n\n const btnRow = document.createElement(\"div\");\n btnRow.style.cssText = \"display:flex;gap:8px;\";\n\n const cancelBtn = document.createElement(\"button\");\n cancelBtn.style.cssText =\n \"flex:1;padding:8px 12px;border-radius:6px;font-size:13px;font-weight:500;cursor:pointer;border:1px solid var(--namiru-border,#e5e7eb);background:var(--namiru-bg,#fff);color:var(--namiru-text,#1f2937);transition:background 0.15s;\";\n cancelBtn.textContent = \"Cancel\";\n cancelBtn.addEventListener(\"mouseenter\", () => {\n cancelBtn.style.background = \"var(--namiru-bg-secondary,#f3f4f6)\";\n });\n cancelBtn.addEventListener(\"mouseleave\", () => {\n cancelBtn.style.background = \"var(--namiru-bg,#fff)\";\n });\n cancelBtn.addEventListener(\"click\", () => overlay.remove());\n\n const endBtn = document.createElement(\"button\");\n endBtn.style.cssText =\n \"flex:1;padding:8px 12px;border-radius:6px;font-size:13px;font-weight:500;cursor:pointer;border:none;background:var(--namiru-text,#1f2937);color:var(--namiru-bg,#fff);transition:opacity 0.15s;\";\n endBtn.textContent = \"End chat\";\n endBtn.addEventListener(\"mouseenter\", () => {\n endBtn.style.opacity = \"0.85\";\n });\n endBtn.addEventListener(\"mouseleave\", () => {\n endBtn.style.opacity = \"1\";\n });\n endBtn.addEventListener(\"click\", () => {\n overlay.remove();\n store.dispatch({ type: \"RESET\" });\n store.dispatch({ type: \"SET_OPEN\", isOpen: false });\n });\n\n btnRow.appendChild(cancelBtn);\n btnRow.appendChild(endBtn);\n card.appendChild(btnRow);\n overlay.appendChild(card);\n\n // Click backdrop to cancel\n overlay.addEventListener(\"click\", (e) => {\n if (e.target === overlay) overlay.remove();\n });\n\n // Inject keyframe animations\n if (!container.querySelector(\"style[data-namiru-confirm]\")) {\n const style = document.createElement(\"style\");\n style.setAttribute(\"data-namiru-confirm\", \"\");\n style.textContent = `\n @keyframes namiruConfirmFade { from { opacity: 0; } to { opacity: 1; } }\n @keyframes namiruConfirmSlide { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }\n `;\n container.appendChild(style);\n }\n\n container.appendChild(overlay);\n}\n", "import { hasShadowDom } from \"../../core/env\";\nimport { sendIcon } from \"../icons\";\n\nexport interface ChatInputOptions {\n onSend: (content: string) => void;\n}\n\nexport function createChatInput(options: ChatInputOptions): HTMLElement {\n const { onSend } = options;\n\n const area = document.createElement(\"div\");\n area.className = \"namiru-input-area\";\n\n const row = document.createElement(\"div\");\n row.className = \"namiru-input-row\";\n\n const input = document.createElement(\"textarea\");\n input.className = \"namiru-input\";\n input.placeholder = \"Type your message...\";\n input.rows = 1;\n input.setAttribute(\"aria-label\", \"Chat message\");\n if (hasShadowDom) {\n input.style.color = \"var(--namiru-text)\";\n } else {\n input.style.setProperty(\"color\", \"var(--namiru-text)\", \"important\");\n }\n\n const sendBtn = document.createElement(\"button\");\n sendBtn.className = \"namiru-send-btn\";\n sendBtn.setAttribute(\"aria-label\", \"Send message\");\n sendBtn.disabled = true;\n sendBtn.appendChild(sendIcon());\n\n function submit(): void {\n const value = input.value.trim();\n if (!value) return;\n onSend(value);\n input.value = \"\";\n input.style.height = \"auto\";\n sendBtn.disabled = true;\n }\n\n input.addEventListener(\"input\", () => {\n sendBtn.disabled = !input.value.trim();\n // Auto-resize\n input.style.height = \"auto\";\n input.style.height = Math.min(input.scrollHeight, 100) + \"px\";\n });\n\n input.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n submit();\n }\n });\n\n sendBtn.addEventListener(\"click\", submit);\n\n row.appendChild(input);\n row.appendChild(sendBtn);\n area.appendChild(row);\n\n return area;\n}\n", "import type { ChatMessage } from \"../../core/types\";\nimport { renderMarkdown } from \"../../core/markdown\";\nimport { namiruBirdIcon } from \"../icons\";\n\nexport interface MessageBubbleOptions {\n textColor?: string;\n bubbleStyle?: \"modern\" | \"rounded\" | \"square\" | \"classic\";\n agentAvatar?: string;\n presetTheme?: \"light\" | \"dark\" | \"custom\";\n iconColor?: string;\n}\n\nfunction createAvatarElement(opts: MessageBubbleOptions): HTMLElement {\n if (opts.agentAvatar) {\n const img = document.createElement(\"img\");\n img.src = opts.agentAvatar;\n img.alt = \"Agent\";\n img.className = \"namiru-message-avatar-img\";\n return img;\n }\n const span = document.createElement(\"span\");\n const isDark = opts.presetTheme === \"dark\";\n const iconFill = opts.iconColor || (isDark ? \"#ffffff\" : opts.textColor);\n span.appendChild(namiruBirdIcon(iconFill));\n return span;\n}\n\nexport function createMessageBubbleFactory(opts: MessageBubbleOptions) {\n return {\n createBubble(message: ChatMessage): HTMLElement {\n if (message.role === \"user\") {\n return createUserBubble(message, opts);\n }\n return createAssistantBubble(message, opts);\n },\n createStreaming(): HTMLElement {\n return createStreamingBubble(opts);\n },\n createLoading(): HTMLElement {\n return createLoadingIndicator(opts);\n },\n };\n}\n\nfunction createUserBubble(\n message: ChatMessage,\n opts: MessageBubbleOptions,\n): HTMLElement {\n const row = document.createElement(\"div\");\n row.className = \"namiru-message-row namiru-message-row--user\";\n\n const bubble = document.createElement(\"div\");\n let cls = \"namiru-message namiru-message--user\";\n if (opts.bubbleStyle === \"rounded\") cls += \" namiru-bubble--rounded\";\n else if (opts.bubbleStyle === \"square\") cls += \" namiru-bubble--square\";\n bubble.className = cls;\n bubble.textContent = message.content;\n\n row.appendChild(bubble);\n return row;\n}\n\nfunction createAssistantBubble(\n message: ChatMessage,\n opts: MessageBubbleOptions,\n): HTMLElement {\n const row = document.createElement(\"div\");\n row.className = \"namiru-message-row namiru-message-row--assistant\";\n\n // Agent avatar or bird icon\n const iconWrap = document.createElement(\"div\");\n iconWrap.className = \"namiru-message-icon\";\n iconWrap.appendChild(createAvatarElement(opts));\n row.appendChild(iconWrap);\n\n // Text (no bubble background, matches AgentChat) - render markdown for bot messages\n // Safe: renderMarkdown() escapes all HTML entities before applying markdown transforms\n const textEl = document.createElement(\"div\");\n textEl.className = \"namiru-message namiru-message--assistant namiru-md\";\n textEl.innerHTML = renderMarkdown(message.content);\n\n row.appendChild(textEl);\n return row;\n}\n\nfunction createStreamingBubble(opts: MessageBubbleOptions): HTMLElement {\n const row = document.createElement(\"div\");\n row.className = \"namiru-message-row namiru-message-row--assistant\";\n\n // Agent avatar or bird icon\n const iconWrap = document.createElement(\"div\");\n iconWrap.className = \"namiru-message-icon\";\n iconWrap.appendChild(createAvatarElement(opts));\n row.appendChild(iconWrap);\n\n const textEl = document.createElement(\"div\");\n textEl.className =\n \"namiru-message namiru-message--assistant namiru-md\";\n textEl.textContent = \"\";\n\n row.appendChild(textEl);\n\n // Expose the text element for content updates\n (row as any)._namiruTextEl = textEl;\n\n return row;\n}\n\nfunction createLoadingIndicator(opts: MessageBubbleOptions): HTMLElement {\n const row = document.createElement(\"div\");\n row.className = \"namiru-message-row namiru-message-row--assistant\";\n\n // Agent avatar or bird icon\n const iconWrap = document.createElement(\"div\");\n iconWrap.className = \"namiru-message-icon\";\n iconWrap.appendChild(createAvatarElement(opts));\n row.appendChild(iconWrap);\n\n const el = document.createElement(\"div\");\n el.className = \"namiru-loading\";\n for (let i = 0; i < 3; i++) {\n const dot = document.createElement(\"div\");\n dot.className = \"namiru-loading-dot\";\n el.appendChild(dot);\n }\n row.appendChild(el);\n return row;\n}\n", "import type { PreChatOption } from \"../../core/types\";\nimport { getIconByName } from \"../icons\";\n\nexport interface PreChatFormOptions {\n question: string;\n options: PreChatOption[];\n onSelect: (label: string) => void;\n}\n\nexport function createPreChatForm(options: PreChatFormOptions): HTMLElement {\n const { question, options: opts, onSelect } = options;\n\n const container = document.createElement(\"div\");\n container.className = \"namiru-prechat\";\n\n const questionEl = document.createElement(\"div\");\n questionEl.className = \"namiru-prechat-question\";\n questionEl.textContent = question;\n container.appendChild(questionEl);\n\n const optionsList = document.createElement(\"div\");\n optionsList.className = \"namiru-prechat-options\";\n\n for (const opt of opts) {\n const btn = document.createElement(\"button\");\n btn.className = \"namiru-prechat-option\";\n\n const icon = getIconByName(opt.icon);\n btn.appendChild(icon);\n\n const label = document.createElement(\"span\");\n label.textContent = opt.label;\n btn.appendChild(label);\n\n btn.addEventListener(\"click\", () => onSelect(opt.label));\n optionsList.appendChild(btn);\n }\n\n container.appendChild(optionsList);\n return container;\n}\n", "import { thumbsUpIcon, thumbsDownIcon } from \"../icons\";\n\nexport interface FeedbackPromptOptions {\n onFeedback: (rating: \"up\" | \"down\") => void;\n softPrompt?: boolean;\n}\n\nexport function createFeedbackPrompt(\n options: FeedbackPromptOptions\n): HTMLElement {\n const { onFeedback, softPrompt } = options;\n\n const container = document.createElement(\"div\");\n container.className = \"namiru-feedback\";\n\n const label = document.createElement(\"div\");\n label.className = \"namiru-feedback-label\";\n label.textContent = \"Feedback\";\n container.appendChild(label);\n\n const text = document.createElement(\"div\");\n text.className = \"namiru-feedback-text\";\n text.textContent = softPrompt\n ? \"How did it go? Your feedback helps us improve.\"\n : \"How was your experience?\";\n container.appendChild(text);\n\n const buttons = document.createElement(\"div\");\n buttons.className = \"namiru-feedback-buttons\";\n\n const upBtn = document.createElement(\"button\");\n upBtn.className = \"namiru-feedback-btn namiru-feedback-btn-up\";\n upBtn.setAttribute(\"aria-label\", \"Thumbs up\");\n upBtn.appendChild(thumbsUpIcon());\n\n const downBtn = document.createElement(\"button\");\n downBtn.className = \"namiru-feedback-btn namiru-feedback-btn-down\";\n downBtn.setAttribute(\"aria-label\", \"Thumbs down\");\n downBtn.appendChild(thumbsDownIcon());\n\n function handleFeedback(rating: \"up\" | \"down\"): void {\n onFeedback(rating);\n // Replace all content with thanks message\n while (container.firstChild) {\n container.removeChild(container.firstChild);\n }\n const thanks = document.createElement(\"div\");\n thanks.className = \"namiru-feedback-thanks\";\n thanks.textContent = \"Thanks for your feedback!\";\n container.appendChild(thanks);\n }\n\n upBtn.addEventListener(\"click\", () => handleFeedback(\"up\"));\n downBtn.addEventListener(\"click\", () => handleFeedback(\"down\"));\n\n buttons.appendChild(upBtn);\n buttons.appendChild(downBtn);\n container.appendChild(buttons);\n\n return container;\n}\n", "export interface EmailFormOptions {\n promptText: string;\n buttonText: string;\n onSubmit: (email: string) => void;\n}\n\nexport function createEmailForm(options: EmailFormOptions): HTMLElement {\n const { promptText, buttonText, onSubmit } = options;\n\n const container = document.createElement(\"div\");\n container.className = \"namiru-email-form\";\n\n const text = document.createElement(\"div\");\n text.className = \"namiru-email-form-text\";\n text.textContent = promptText;\n container.appendChild(text);\n\n const row = document.createElement(\"div\");\n row.className = \"namiru-email-form-row\";\n\n const input = document.createElement(\"input\");\n input.className = \"namiru-email-input\";\n input.type = \"email\";\n input.placeholder = \"your@email.com\";\n input.setAttribute(\"aria-label\", \"Email address\");\n\n const submitBtn = document.createElement(\"button\");\n submitBtn.className = \"namiru-email-submit\";\n submitBtn.textContent = buttonText;\n submitBtn.disabled = true;\n\n input.addEventListener(\"input\", () => {\n submitBtn.disabled = !isValidEmail(input.value);\n });\n\n function submit(): void {\n const email = input.value.trim();\n if (!isValidEmail(email)) return;\n\n onSubmit(email);\n\n // Replace form with confirmation\n row.remove();\n text.remove();\n const sent = document.createElement(\"div\");\n sent.className = \"namiru-email-sent\";\n sent.textContent = \"Thanks, we'll be in touch\";\n container.appendChild(sent);\n }\n\n input.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n submit();\n }\n });\n\n submitBtn.addEventListener(\"click\", submit);\n\n row.appendChild(input);\n row.appendChild(submitBtn);\n container.appendChild(row);\n\n return container;\n}\n\nfunction isValidEmail(email: string): boolean {\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email.trim());\n}\n", "export interface ContactFormOptions {\n onSubmit: (data: { name: string; email: string; message: string }) => void;\n}\n\nexport function createContactForm(options: ContactFormOptions): HTMLElement {\n const { onSubmit } = options;\n\n const container = document.createElement(\"div\");\n container.className = \"namiru-contact-form\";\n\n const heading = document.createElement(\"div\");\n heading.className = \"namiru-contact-heading\";\n heading.textContent =\n \"Our team is here to help! Leave your message and we'll get back to you.\";\n container.appendChild(heading);\n\n // Name field (optional)\n const nameLabel = document.createElement(\"label\");\n nameLabel.className = \"namiru-contact-label\";\n nameLabel.textContent = \"Name (optional)\";\n container.appendChild(nameLabel);\n\n const nameInput = document.createElement(\"input\");\n nameInput.className = \"namiru-contact-input\";\n nameInput.type = \"text\";\n nameInput.placeholder = \"Your name\";\n nameInput.setAttribute(\"aria-label\", \"Name\");\n container.appendChild(nameInput);\n\n // Email field (required)\n const emailLabel = document.createElement(\"label\");\n emailLabel.className = \"namiru-contact-label\";\n emailLabel.textContent = \"Email *\";\n container.appendChild(emailLabel);\n\n const emailInput = document.createElement(\"input\");\n emailInput.className = \"namiru-contact-input\";\n emailInput.type = \"email\";\n emailInput.placeholder = \"your@email.com\";\n emailInput.required = true;\n emailInput.setAttribute(\"aria-label\", \"Email address\");\n container.appendChild(emailInput);\n\n // Message field (required)\n const msgLabel = document.createElement(\"label\");\n msgLabel.className = \"namiru-contact-label\";\n msgLabel.textContent = \"Message *\";\n container.appendChild(msgLabel);\n\n const messageInput = document.createElement(\"textarea\");\n messageInput.className = \"namiru-contact-textarea\";\n messageInput.placeholder = \"How can we help you?\";\n messageInput.rows = 4;\n messageInput.required = true;\n messageInput.setAttribute(\"aria-label\", \"Message\");\n container.appendChild(messageInput);\n\n // Error message\n const errorEl = document.createElement(\"div\");\n errorEl.className = \"namiru-contact-error\";\n errorEl.style.display = \"none\";\n container.appendChild(errorEl);\n\n // Submit button\n const submitBtn = document.createElement(\"button\");\n submitBtn.className = \"namiru-contact-submit\";\n submitBtn.textContent = \"Send Message\";\n submitBtn.disabled = true;\n container.appendChild(submitBtn);\n\n function validate(): boolean {\n const email = emailInput.value.trim();\n const message = messageInput.value.trim();\n const emailValid = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email);\n return emailValid && message.length > 0;\n }\n\n function updateButton(): void {\n submitBtn.disabled = !validate();\n }\n\n emailInput.addEventListener(\"input\", updateButton);\n messageInput.addEventListener(\"input\", updateButton);\n\n function submit(): void {\n if (!validate()) return;\n\n const data = {\n name: nameInput.value.trim(),\n email: emailInput.value.trim(),\n message: messageInput.value.trim(),\n };\n\n // Disable form\n submitBtn.disabled = true;\n submitBtn.textContent = \"Sending...\";\n nameInput.disabled = true;\n emailInput.disabled = true;\n messageInput.disabled = true;\n\n onSubmit(data);\n\n // Show confirmation\n container.textContent = \"\";\n const confirmation = document.createElement(\"div\");\n confirmation.className = \"namiru-contact-confirmation\";\n confirmation.textContent = \"Thanks! We'll get back to you shortly.\";\n container.appendChild(confirmation);\n }\n\n submitBtn.addEventListener(\"click\", submit);\n\n // Allow Enter in inputs (but not textarea) to submit\n emailInput.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n submit();\n }\n });\n nameInput.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n submit();\n }\n });\n\n return container;\n}\n", "export interface LimitOverlayOptions {\n onSubmit: (data: { message: string; visitorEmail?: string }) => void;\n onNewChat?: () => void;\n}\n\nfunction createInfoIcon(): SVGSVGElement {\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.setAttribute(\"width\", \"40\");\n svg.setAttribute(\"height\", \"40\");\n svg.setAttribute(\"viewBox\", \"0 0 256 256\");\n svg.setAttribute(\"fill\", \"none\");\n svg.setAttribute(\"stroke\", \"currentColor\");\n svg.setAttribute(\"stroke-width\", \"16\");\n svg.setAttribute(\"stroke-linecap\", \"round\");\n svg.setAttribute(\"stroke-linejoin\", \"round\");\n\n const circle = document.createElementNS(\"http://www.w3.org/2000/svg\", \"circle\");\n circle.setAttribute(\"cx\", \"128\");\n circle.setAttribute(\"cy\", \"128\");\n circle.setAttribute(\"r\", \"96\");\n svg.appendChild(circle);\n\n const line = document.createElementNS(\"http://www.w3.org/2000/svg\", \"line\");\n line.setAttribute(\"x1\", \"128\");\n line.setAttribute(\"y1\", \"80\");\n line.setAttribute(\"x2\", \"128\");\n line.setAttribute(\"y2\", \"136\");\n svg.appendChild(line);\n\n const dot = document.createElementNS(\"http://www.w3.org/2000/svg\", \"circle\");\n dot.setAttribute(\"cx\", \"128\");\n dot.setAttribute(\"cy\", \"172\");\n dot.setAttribute(\"r\", \"6\");\n dot.setAttribute(\"fill\", \"currentColor\");\n dot.setAttribute(\"stroke\", \"none\");\n svg.appendChild(dot);\n\n return svg;\n}\n\nfunction createCheckIcon(): SVGSVGElement {\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.setAttribute(\"width\", \"40\");\n svg.setAttribute(\"height\", \"40\");\n svg.setAttribute(\"viewBox\", \"0 0 256 256\");\n svg.setAttribute(\"fill\", \"none\");\n svg.setAttribute(\"stroke\", \"currentColor\");\n svg.setAttribute(\"stroke-width\", \"16\");\n svg.setAttribute(\"stroke-linecap\", \"round\");\n svg.setAttribute(\"stroke-linejoin\", \"round\");\n\n const circle = document.createElementNS(\"http://www.w3.org/2000/svg\", \"circle\");\n circle.setAttribute(\"cx\", \"128\");\n circle.setAttribute(\"cy\", \"128\");\n circle.setAttribute(\"r\", \"96\");\n svg.appendChild(circle);\n\n const polyline = document.createElementNS(\"http://www.w3.org/2000/svg\", \"polyline\");\n polyline.setAttribute(\"points\", \"88,136 112,160 168,104\");\n svg.appendChild(polyline);\n\n return svg;\n}\n\nexport function createLimitOverlay(options: LimitOverlayOptions): HTMLElement {\n const { onSubmit, onNewChat } = options;\n\n const container = document.createElement(\"div\");\n container.className = \"namiru-limit-overlay\";\n\n // Icon\n const iconWrap = document.createElement(\"div\");\n iconWrap.className = \"namiru-limit-icon\";\n iconWrap.appendChild(createInfoIcon());\n container.appendChild(iconWrap);\n\n // Heading\n const heading = document.createElement(\"div\");\n heading.className = \"namiru-limit-heading\";\n heading.textContent = \"Conversation limit reached\";\n container.appendChild(heading);\n\n // Subtext\n const subtext = document.createElement(\"div\");\n subtext.className = \"namiru-limit-subtext\";\n subtext.textContent =\n \"AI responses are currently unavailable. Send a message and we'll forward it via email.\";\n container.appendChild(subtext);\n\n // Form container\n const form = document.createElement(\"div\");\n form.className = \"namiru-limit-form\";\n\n // Message textarea\n const messageInput = document.createElement(\"textarea\");\n messageInput.className = \"namiru-limit-textarea\";\n messageInput.placeholder = \"Your message...\";\n messageInput.rows = 4;\n messageInput.setAttribute(\"aria-label\", \"Message\");\n form.appendChild(messageInput);\n\n // Email input (optional)\n const emailInput = document.createElement(\"input\");\n emailInput.className = \"namiru-limit-email\";\n emailInput.type = \"email\";\n emailInput.placeholder = \"Your email (optional, for a reply)\";\n emailInput.setAttribute(\"aria-label\", \"Email address (optional)\");\n form.appendChild(emailInput);\n\n // Submit button\n const submitBtn = document.createElement(\"button\");\n submitBtn.className = \"namiru-limit-submit\";\n submitBtn.textContent = \"Send Message\";\n submitBtn.disabled = true;\n form.appendChild(submitBtn);\n\n container.appendChild(form);\n\n // New Chat button\n if (onNewChat) {\n const newChatBtn = document.createElement(\"button\");\n newChatBtn.className = \"namiru-limit-newchat\";\n newChatBtn.textContent = \"Start New Chat\";\n newChatBtn.addEventListener(\"click\", onNewChat);\n container.appendChild(newChatBtn);\n }\n\n function validate(): boolean {\n return messageInput.value.trim().length > 0;\n }\n\n function updateButton(): void {\n submitBtn.disabled = !validate();\n }\n\n messageInput.addEventListener(\"input\", updateButton);\n\n function submit(): void {\n if (!validate()) return;\n\n const email = emailInput.value.trim();\n const data: { message: string; visitorEmail?: string } = {\n message: messageInput.value.trim(),\n };\n if (email) {\n data.visitorEmail = email;\n }\n\n // Disable form\n submitBtn.disabled = true;\n submitBtn.textContent = \"Sending...\";\n messageInput.disabled = true;\n emailInput.disabled = true;\n\n onSubmit(data);\n\n // Show confirmation\n container.textContent = \"\";\n\n const confirmIcon = document.createElement(\"div\");\n confirmIcon.className = \"namiru-limit-icon namiru-limit-icon--success\";\n confirmIcon.appendChild(createCheckIcon());\n container.appendChild(confirmIcon);\n\n const confirmation = document.createElement(\"div\");\n confirmation.className = \"namiru-limit-confirmation\";\n confirmation.textContent = \"Message sent! The team will get back to you soon.\";\n container.appendChild(confirmation);\n\n // Re-add New Chat button after confirmation\n if (onNewChat) {\n const newChatBtn2 = document.createElement(\"button\");\n newChatBtn2.className = \"namiru-limit-newchat\";\n newChatBtn2.textContent = \"Start New Chat\";\n newChatBtn2.addEventListener(\"click\", onNewChat);\n container.appendChild(newChatBtn2);\n }\n }\n\n submitBtn.addEventListener(\"click\", submit);\n\n return container;\n}\n", "import { ChatStore, type ChatStoreState } from \"../../core/state-machine\";\nimport type { AgentBrandingData, ChatMessage } from \"../../core/types\";\nimport { hasShadowDom } from \"../../core/env\";\nimport { renderMarkdown } from \"../../core/markdown\";\nimport { createChatHeader, showCloseConfirmation } from \"./chat-header\";\nimport { createChatInput } from \"./chat-input\";\nimport { createMessageBubbleFactory } from \"./message-bubble\";\nimport { createPreChatForm } from \"./pre-chat-form\";\nimport { createFeedbackPrompt } from \"./feedback-prompt\";\nimport { createEmailForm } from \"./email-form\";\nimport { createContactForm } from \"./contact-form\";\nimport { createLimitOverlay } from \"./limit-overlay\";\n\nexport interface ChatWindowOptions {\n store: ChatStore;\n branding: AgentBrandingData;\n agentId: string;\n mode: \"button\" | \"inline\";\n position: \"bottom-left\" | \"bottom-right\";\n onSendMessage: (content: string) => void;\n onPreChatSelect: (label: string) => void;\n onFeedback: (rating: \"up\" | \"down\") => void;\n onEscalationEmail: (email: string) => void;\n onTranscriptEmail: (email: string) => void;\n onContactFormSubmit?: (data: { name: string; email: string; message: string }) => void;\n onLimitMessage?: (data: { message: string; visitorEmail?: string }) => void;\n onNewChat?: () => void;\n feedbackEnabled?: boolean;\n}\n\nexport function createChatWindow(options: ChatWindowOptions): HTMLElement {\n const {\n store,\n branding,\n agentId,\n mode,\n position,\n onSendMessage,\n onPreChatSelect,\n onFeedback,\n onEscalationEmail,\n onTranscriptEmail,\n onContactFormSubmit,\n onLimitMessage,\n onNewChat,\n feedbackEnabled,\n } = options;\n\n // Create instance-scoped bubble factory\n const agentAvatarUrl = branding.agentAvatar || branding.logoUrl;\n const bubbles = createMessageBubbleFactory({\n textColor: branding.textColor,\n bubbleStyle: branding.bubbleStyle,\n agentAvatar: agentAvatarUrl,\n presetTheme: branding.presetTheme,\n iconColor: branding.iconColor,\n });\n\n // Container\n const container = document.createElement(\"div\");\n if (mode === \"button\") {\n container.className = `namiru-popup namiru-popup--${position}`;\n } else {\n container.className = \"namiru-inline\";\n }\n\n // Header\n const header = createChatHeader({\n store,\n branding,\n mode,\n ...(mode === 'button' ? {\n onTranscriptClick: () => {\n store.dispatch({ type: \"SET_STATE\", state: \"escalation\" });\n showTranscriptForm();\n },\n onNewChat,\n } : {}),\n feedbackEnabled,\n });\n container.appendChild(header);\n\n // Content area (messages, pre-chat, etc.)\n const content = document.createElement(\"div\");\n content.className = \"namiru-messages\";\n container.appendChild(content);\n\n // Input area (hidden until init completes)\n const inputArea = createChatInput({ onSend: onSendMessage });\n inputArea.style.display = \"none\";\n container.appendChild(inputArea);\n\n // When branding footer is hidden, add bottom padding to the input area\n // so it doesn't sit flush against the container edge\n const showPowered = branding.showPoweredBy !== false;\n if (!showPowered) {\n inputArea.style.paddingBottom = \"12px\";\n }\n\n function createPoweredByEl(): HTMLElement {\n const powered = document.createElement(\"div\");\n powered.className = \"namiru-powered\";\n powered.setAttribute(\"data-namiru-protected\", \"true\");\n const imp = hasShadowDom ? \"\" : \" !important\";\n powered.style.cssText = `display:block${imp};visibility:visible${imp};opacity:1${imp};`;\n const link = document.createElement(\"a\");\n link.href = \"https://namiru.ai\";\n link.target = \"_blank\";\n link.rel = \"noopener noreferrer\";\n link.textContent = \"Namiru.ai\";\n powered.appendChild(document.createTextNode(\"Powered by \"));\n powered.appendChild(link);\n return powered;\n }\n\n if (showPowered) {\n // Store original content from a reference element for tamper detection.\n // This is safe to use with innerHTML because it only contains our own\n // hardcoded static markup (no user input).\n const referenceEl = createPoweredByEl();\n const originalPoweredHTML = referenceEl.innerHTML;\n container.appendChild(createPoweredByEl());\n\n // Anti-tampering: MutationObserver restores the badge instantly if removed, hidden, or content-changed\n let guardPaused = false;\n const poweredByObserver = new MutationObserver(() => {\n if (guardPaused) return;\n guardPaused = true;\n const existing = container.querySelector('.namiru-powered') as HTMLElement | null;\n if (!existing) {\n container.appendChild(createPoweredByEl());\n } else {\n // Restore content if tampered with (innerHTML/textContent changed)\n if (existing.innerHTML !== originalPoweredHTML) {\n // Replace with a fresh element to restore all child nodes\n const fresh = createPoweredByEl();\n existing.replaceWith(fresh);\n } else {\n const s = existing.style;\n const cs = getComputedStyle(existing);\n if (cs.display === 'none' || cs.visibility === 'hidden' || cs.opacity === '0') {\n const imp = hasShadowDom ? \"\" : \" !important\";\n s.cssText = `display:block${imp};visibility:visible${imp};opacity:1${imp};`;\n }\n }\n }\n guardPaused = false;\n });\n poweredByObserver.observe(container, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['style', 'class'],\n characterData: true,\n });\n }\n\n // Apply custom font family to container if provided\n if (branding.fontFamily && branding.fontFamily !== \"system\") {\n container.style.fontFamily = branding.fontFamily;\n }\n\n // Hard message limit per conversation\n const MESSAGE_HARD_LIMIT = 40;\n\n // State tracking\n let renderedMessageCount = 0;\n let streamingBubble: HTMLElement | null = null;\n let loadingEl: HTMLElement | null = null;\n let preChatEl: HTMLElement | null = null;\n let feedbackEl: HTMLElement | null = null;\n let emailFormEl: HTMLElement | null = null;\n let welcomeRendered = false;\n let suggestionsEl: HTMLElement | null = null;\n let contactFormEl: HTMLElement | null = null;\n let limitOverlayEl: HTMLElement | null = null;\n let connectingEl: HTMLElement | null = null;\n\n function showConnectingIndicator(): void {\n if (connectingEl) return;\n connectingEl = document.createElement(\"div\");\n connectingEl.className = \"namiru-connecting\";\n const dots = document.createElement(\"div\");\n dots.className = \"namiru-loading-dots\";\n for (let i = 0; i < 3; i++) {\n const dot = document.createElement(\"span\");\n dot.className = \"namiru-loading-dot\";\n dots.appendChild(dot);\n }\n connectingEl.appendChild(dots);\n content.appendChild(connectingEl);\n }\n\n function removeConnectingIndicator(): void {\n if (connectingEl) {\n connectingEl.remove();\n connectingEl = null;\n }\n }\n\n function clearContent(): void {\n content.textContent = \"\";\n renderedMessageCount = 0;\n streamingBubble = null;\n loadingEl = null;\n preChatEl = null;\n feedbackEl = null;\n emailFormEl = null;\n contactFormEl = null;\n limitOverlayEl = null;\n connectingEl = null;\n welcomeRendered = false;\n suggestionsEl = null;\n }\n\n function renderWelcomeMessage(): void {\n if (welcomeRendered) return;\n welcomeRendered = true;\n\n const welcomeText = branding.welcomeMessage || \"Hello! How can I help you today?\";\n\n // Render welcome as a standard assistant bubble so it matches all other AI messages\n const welcomeMsg: ChatMessage = {\n id: \"welcome\",\n role: \"assistant\",\n content: welcomeText,\n timestamp: Date.now(),\n };\n const row = bubbles.createBubble(welcomeMsg);\n row.classList.add(\"namiru-message-row--welcome\");\n\n content.appendChild(row);\n\n // Render suggested questions if any\n const questions = branding.suggestedQuestions;\n console.log(\"[NamiruChat] renderWelcome suggestedQuestions:\", questions);\n if (questions && questions.length > 0) {\n suggestionsEl = document.createElement(\"div\");\n suggestionsEl.className = \"namiru-suggestions\";\n\n questions.slice(0, 4).forEach((q) => {\n const chip = document.createElement(\"button\");\n chip.className = \"namiru-suggestion-chip\";\n chip.textContent = q;\n chip.addEventListener(\"click\", () => {\n onSendMessage(q);\n // Remove suggestions after click\n if (suggestionsEl) {\n suggestionsEl.remove();\n suggestionsEl = null;\n }\n });\n suggestionsEl!.appendChild(chip);\n });\n\n content.appendChild(suggestionsEl);\n }\n }\n\n function showPreChat(): void {\n const pcConfig = branding.preChatConfig;\n if (!pcConfig || !pcConfig.enabled) return;\n\n // Default templates\n const templates: Record<\n string,\n { question: string; options: { label: string; icon: string }[] }\n > = {\n ecommerce: {\n question: \"What brings you here today?\",\n options: [\n { label: \"Product question\", icon: \"ShoppingBag\" },\n { label: \"Order help\", icon: \"Package\" },\n { label: \"Billing issue\", icon: \"CreditCard\" },\n { label: \"Something else\", icon: \"ChatCircle\" },\n ],\n },\n saas: {\n question: \"What can we help you with?\",\n options: [\n { label: \"Getting started\", icon: \"Rocket\" },\n { label: \"Technical issue\", icon: \"Wrench\" },\n { label: \"Subscription question\", icon: \"CreditCard\" },\n { label: \"Something else\", icon: \"ChatCircle\" },\n ],\n },\n services: {\n question: \"How can we assist you?\",\n options: [\n { label: \"Interested in services\", icon: \"Briefcase\" },\n { label: \"Existing client\", icon: \"UserCircle\" },\n { label: \"General question\", icon: \"ChatCircle\" },\n { label: \"Something else\", icon: \"DotsThree\" },\n ],\n },\n };\n\n let question: string;\n let formOptions: { label: string; icon: string }[];\n\n if (pcConfig.template === \"custom\" && pcConfig.custom) {\n question = pcConfig.custom.question;\n formOptions = pcConfig.custom.options;\n } else if (pcConfig.template && templates[pcConfig.template]) {\n const tmpl = templates[pcConfig.template];\n question = tmpl.question;\n formOptions = tmpl.options;\n } else {\n return;\n }\n\n clearContent();\n inputArea.style.display = \"none\";\n\n preChatEl = createPreChatForm({\n question,\n options: formOptions,\n onSelect: (label) => {\n onPreChatSelect(label);\n inputArea.style.display = \"\";\n },\n });\n content.appendChild(preChatEl);\n }\n\n function showTranscriptForm(): void {\n if (emailFormEl) return;\n emailFormEl = createEmailForm({\n promptText:\n \"Want a copy of this conversation? Handy if you need to reference it later for support.\",\n buttonText: \"Send\",\n onSubmit: (email) => {\n onTranscriptEmail(email);\n emailFormEl = null;\n },\n });\n content.appendChild(emailFormEl);\n scrollToBottom();\n }\n\n function showEscalationForm(): void {\n if (emailFormEl) return;\n emailFormEl = createEmailForm({\n promptText:\n \"We'll connect you with the team. Please share your email and we'll get back to you.\",\n buttonText: \"Submit\",\n onSubmit: (email) => {\n onEscalationEmail(email);\n emailFormEl = null;\n },\n });\n content.appendChild(emailFormEl);\n scrollToBottom();\n }\n\n function showContactForm(): void {\n if (contactFormEl) return;\n clearContent();\n inputArea.style.display = \"none\";\n contactFormEl = createContactForm({\n onSubmit: (data) => {\n if (onContactFormSubmit) {\n onContactFormSubmit(data);\n }\n contactFormEl = null;\n },\n });\n content.appendChild(contactFormEl);\n }\n\n function showLimitOverlay(): void {\n if (limitOverlayEl) return;\n inputArea.style.display = \"none\";\n limitOverlayEl = createLimitOverlay({\n onSubmit: (data) => {\n if (onLimitMessage) {\n onLimitMessage(data);\n }\n limitOverlayEl = null;\n },\n });\n // The overlay is positioned absolute over the messages area\n content.style.position = \"relative\";\n content.appendChild(limitOverlayEl);\n }\n\n function showDomainError(): void {\n // Clear any existing child nodes\n while (content.firstChild) {\n content.removeChild(content.firstChild);\n }\n content.style.position = \"relative\";\n\n const overlay = document.createElement(\"div\");\n overlay.style.cssText = `\n position: absolute; inset: 0; display: flex; flex-direction: column;\n align-items: center; justify-content: center; padding: 2rem; text-align: center;\n background: ${branding.backgroundColor || \"#ffffff\"};\n color: ${branding.textColor || \"#1f2937\"};\n `;\n\n const icon = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n icon.setAttribute(\"viewBox\", \"0 0 256 256\");\n icon.setAttribute(\"width\", \"72\");\n icon.setAttribute(\"height\", \"72\");\n icon.setAttribute(\"fill\", \"#ef4444\");\n icon.style.cssText = \"margin-bottom: 20px; opacity: 0.8;\";\n const path = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n path.setAttribute(\"d\", \"M128,26A102,102,0,1,0,230,128,102.12,102.12,0,0,0,128,26Zm90,102a89.6,89.6,0,0,1-22.29,59.22L68.78,60.29A89.95,89.95,0,0,1,218,128ZM38,128A89.6,89.6,0,0,1,60.29,68.78L187.22,195.71A89.95,89.95,0,0,1,38,128Z\");\n icon.appendChild(path);\n overlay.appendChild(icon);\n\n const title = document.createElement(\"div\");\n title.style.cssText = \"font-size: 18px; font-weight: 600; margin-bottom: 8px;\";\n title.textContent = \"Domain Not Authorized\";\n overlay.appendChild(title);\n\n const msg = document.createElement(\"div\");\n msg.style.cssText = \"font-size: 14px; opacity: 0.7; margin-bottom: 24px; max-width: 300px; line-height: 1.5;\";\n msg.textContent = \"This chat widget is not authorized to run on this domain. Please update the allowed domain in your agent settings.\";\n overlay.appendChild(msg);\n\n const btnRow = document.createElement(\"div\");\n btnRow.style.cssText = \"display: flex; gap: 12px; align-items: center;\";\n\n const settingsLink = document.createElement(\"a\");\n settingsLink.style.cssText = `\n padding: 10px 24px; border-radius: 8px; border: none; cursor: pointer;\n font-size: 14px; font-weight: 500; text-decoration: none;\n display: inline-flex; align-items: center; box-sizing: border-box;\n line-height: 1; background: ${branding.primaryColor || \"#1f2937\"}; color: #fff;\n `;\n settingsLink.textContent = \"Go to Settings\";\n // Resolve the correct dashboard base URL per environment\n const host = window.location.hostname;\n let dashBase = window.location.origin;\n if (host !== \"localhost\" && host !== \"127.0.0.1\") {\n if (host.endsWith(\"namiru.ai\")) {\n dashBase = host.includes(\"test\") ? \"https://test.namiru.ai\" : \"https://namiru.ai\";\n }\n }\n settingsLink.href = `${dashBase}/agent-builder/agent/${agentId}/settings?focus=domain`;\n settingsLink.target = \"_blank\";\n settingsLink.rel = \"noopener\";\n btnRow.appendChild(settingsLink);\n\n const btn = document.createElement(\"button\");\n btn.style.cssText = `\n padding: 10px 24px; border-radius: 8px; cursor: pointer;\n font-size: 14px; font-weight: 500; line-height: 1; box-sizing: border-box;\n background: transparent; color: ${branding.textColor || \"#1f2937\"};\n border: 1px solid ${branding.textColor ? branding.textColor + \"33\" : \"#e5e7eb\"};\n `;\n btn.textContent = \"Reload\";\n btn.addEventListener(\"click\", () => window.location.reload());\n btnRow.appendChild(btn);\n\n overlay.appendChild(btnRow);\n content.appendChild(overlay);\n }\n\n function showFeedback(softPrompt: boolean): void {\n if (feedbackEl) return;\n feedbackEl = createFeedbackPrompt({\n onFeedback: (rating) => {\n onFeedback(rating);\n // After feedback, close immediately\n if (mode === \"button\") {\n setTimeout(() => {\n store.dispatch({ type: \"RESET\" });\n store.dispatch({ type: \"SET_OPEN\", isOpen: false });\n }, 800);\n }\n },\n softPrompt,\n });\n content.appendChild(feedbackEl);\n scrollToBottom();\n }\n\n function scrollToBottom(): void {\n requestAnimationFrame(() => {\n content.scrollTop = content.scrollHeight;\n });\n }\n\n function renderMessages(messages: ChatMessage[]): void {\n // Remove suggestions once user sends a message\n if (suggestionsEl && messages.some((m) => m.role === \"user\")) {\n suggestionsEl.remove();\n suggestionsEl = null;\n }\n\n // Only render new messages\n for (let i = renderedMessageCount; i < messages.length; i++) {\n const bubble = bubbles.createBubble(messages[i]);\n content.appendChild(bubble);\n }\n renderedMessageCount = messages.length;\n scrollToBottom();\n }\n\n function updateStreaming(streamingContent: string): void {\n if (streamingContent) {\n if (!streamingBubble) {\n // Remove loading indicator\n if (loadingEl) {\n loadingEl.remove();\n loadingEl = null;\n }\n streamingBubble = bubbles.createStreaming();\n content.appendChild(streamingBubble);\n }\n // Update inner text element with markdown-rendered HTML.\n // XSS-safe: renderMarkdown() calls escapeHtml() on input before any transforms.\n const textEl = (streamingBubble as any)._namiruTextEl;\n const rendered = renderMarkdown(streamingContent);\n if (textEl) {\n textEl.innerHTML = rendered;\n } else {\n streamingBubble.innerHTML = rendered;\n }\n scrollToBottom();\n } else if (streamingBubble) {\n streamingBubble.remove();\n streamingBubble = null;\n }\n }\n\n function updateLoading(isLoading: boolean): void {\n if (isLoading && !loadingEl && !streamingBubble) {\n loadingEl = bubbles.createLoading();\n content.appendChild(loadingEl);\n scrollToBottom();\n } else if (!isLoading && loadingEl) {\n loadingEl.remove();\n loadingEl = null;\n }\n }\n\n // Subscribe to store changes\n let prevState: ChatStoreState | null = null;\n\n store.subscribe((state) => {\n console.log('[ChatWindow] subscriber:', 'state=' + state.state, 'msgs=' + state.messages.length, 'open=' + state.isOpen, 'input=' + inputArea?.style.display, 'prev=' + (prevState?.state || 'null'));\n\n // Open/close for popup mode\n if (mode === \"button\") {\n if (state.isOpen) {\n container.classList.add(\"namiru-popup--open\");\n } else {\n container.classList.remove(\"namiru-popup--open\");\n }\n }\n\n // State transitions\n if (!prevState || prevState.state !== state.state) {\n switch (state.state) {\n case \"idle\":\n // RESET was dispatched - clear all DOM content for fresh start\n clearContent();\n inputArea.style.display = \"none\";\n removeConnectingIndicator();\n break;\n case \"connecting\":\n inputArea.style.display = \"none\";\n showConnectingIndicator();\n break;\n case \"pre_chat\":\n showPreChat();\n break;\n case \"chatting\":\n removeConnectingIndicator();\n if (prevState?.state === \"pre_chat\") {\n clearContent();\n }\n inputArea.style.display = \"\";\n // Render welcome message when entering chat state\n renderWelcomeMessage();\n break;\n case \"feedback\":\n showFeedback(true);\n break;\n case \"escalation\":\n showEscalationForm();\n break;\n case \"email_fallback\":\n showContactForm();\n break;\n case \"conversation_limit\":\n removeConnectingIndicator();\n inputArea.style.display = \"none\";\n showLimitOverlay();\n break;\n case \"domain_error\":\n removeConnectingIndicator();\n inputArea.style.display = \"none\";\n showDomainError();\n break;\n case \"error\":\n removeConnectingIndicator();\n inputArea.style.display = \"none\";\n break;\n }\n }\n\n // Render messages\n if (\n state.messages.length > renderedMessageCount &&\n state.state !== \"pre_chat\"\n ) {\n renderMessages(state.messages);\n }\n\n // Check per-conversation message limit (count total messages, not just user)\n if (\n state.state === \"chatting\" &&\n state.messages.length >= MESSAGE_HARD_LIMIT\n ) {\n store.dispatch({ type: \"SET_STATE\", state: \"conversation_limit\" });\n }\n\n // Streaming\n if (prevState?.streamingContent !== state.streamingContent) {\n updateStreaming(state.streamingContent);\n }\n\n // Loading\n if (prevState?.isLoading !== state.isLoading) {\n updateLoading(state.isLoading);\n }\n\n prevState = state;\n });\n\n // Expose methods for external triggers\n (container as any)._namiruShowEscalation = showEscalationForm;\n (container as any)._namiruShowFeedback = showFeedback;\n (container as any)._namiruShowTranscript = showTranscriptForm;\n (container as any)._namiruShowContactForm = showContactForm;\n (container as any)._namiruShowLimitOverlay = showLimitOverlay;\n (container as any)._namiruShowCloseConfirmation = () => showCloseConfirmation(header, store);\n\n return container;\n}\n", "import { ChatStore } from \"../../core/state-machine\";\nimport { chatBubbleIcon, closeIcon } from \"../icons\";\n\nexport interface ButtonBubbleOptions {\n position: \"bottom-left\" | \"bottom-right\";\n store: ChatStore;\n welcomeMessage?: string;\n greetingDelay?: number;\n bubbleStyle?: \"modern\" | \"classic\" | \"rounded\" | \"square\";\n onCloseRequest?: () => void;\n}\n\nexport function createButtonBubble(options: ButtonBubbleOptions): HTMLElement {\n const { position, store, welcomeMessage, greetingDelay, bubbleStyle, onCloseRequest } = options;\n\n const wrapper = document.createElement(\"div\");\n\n // Main button\n const button = document.createElement(\"button\");\n button.className = `namiru-button namiru-button--${position}`;\n if (bubbleStyle === \"classic\") {\n button.classList.add(\"namiru-button--classic\");\n }\n button.setAttribute(\"aria-label\", \"Open chat\");\n\n const openSvg = chatBubbleIcon();\n const closeSvg = closeIcon();\n closeSvg.style.display = \"none\";\n\n button.appendChild(openSvg);\n button.appendChild(closeSvg);\n\n button.addEventListener(\"click\", () => {\n const isOpen = store.getState().isOpen;\n if (isOpen && onCloseRequest) {\n onCloseRequest();\n } else {\n store.dispatch({ type: \"SET_OPEN\", isOpen: !isOpen });\n }\n });\n\n wrapper.appendChild(button);\n\n // Greeting bubble\n let greetingEl: HTMLElement | null = null;\n let greetingVisible = false;\n let greetingTimer: ReturnType<typeof setTimeout> | null = null;\n\n if (welcomeMessage) {\n greetingEl = document.createElement(\"div\");\n greetingEl.className = `namiru-greeting namiru-greeting--${position} namiru-greeting--hidden`;\n\n const textNode = document.createTextNode(welcomeMessage);\n greetingEl.appendChild(textNode);\n\n const closeBtn = document.createElement(\"button\");\n closeBtn.className = \"namiru-greeting-close\";\n closeBtn.setAttribute(\"aria-label\", \"Dismiss\");\n closeBtn.textContent = \"\\u00D7\";\n closeBtn.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n hideGreeting();\n });\n greetingEl.appendChild(closeBtn);\n\n greetingEl.addEventListener(\"click\", () => {\n hideGreeting();\n store.dispatch({ type: \"SET_OPEN\", isOpen: true });\n });\n\n wrapper.appendChild(greetingEl);\n\n // Auto-show after delay, auto-hide after 30 seconds\n const delay = greetingDelay ?? 3000;\n greetingTimer = setTimeout(() => {\n if (!store.getState().isOpen && greetingEl) {\n greetingEl.classList.remove(\"namiru-greeting--hidden\");\n greetingVisible = true;\n // Auto-hide after 30 seconds\n setTimeout(() => hideGreeting(), 30000);\n }\n }, delay);\n }\n\n function hideGreeting(): void {\n if (greetingVisible && greetingEl) {\n greetingEl.classList.add(\"namiru-greeting--hidden\");\n greetingVisible = false;\n }\n if (greetingTimer) {\n clearTimeout(greetingTimer);\n greetingTimer = null;\n }\n }\n\n store.subscribe((state) => {\n if (state.isOpen) {\n openSvg.style.display = \"none\";\n closeSvg.style.display = \"\";\n button.setAttribute(\"aria-label\", \"Close chat\");\n hideGreeting();\n } else {\n openSvg.style.display = \"\";\n closeSvg.style.display = \"none\";\n button.setAttribute(\"aria-label\", \"Open chat\");\n }\n });\n\n return wrapper;\n}\n"],
|
|
5
|
-
"mappings": "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AE;AAAA,kBACbA,CAAE;AAAA;AAAA;AAAA;AAAA,uCAImBA,CAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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",
|
|
4
|
+
"sourcesContent": ["export type {\n NamiruChatConfig,\n NamiruChatInstance,\n AgentBrandingData,\n ChatMessage,\n PreChatTemplate,\n PreChatCustomConfig,\n PreChatOption,\n LeadCaptureData,\n} from \"./core/types\";\n\nimport type {\n NamiruChatConfig,\n NamiruChatInstance,\n ChatMessage,\n} from \"./core/types\";\nimport { ChatStore } from \"./core/state-machine\";\nimport { ApiClient } from \"./core/api-client\";\nimport { WebSocketClient } from \"./core/websocket-client\";\nimport { InactivityTimer } from \"./core/inactivity-timer\";\nimport { setHasShadowDom } from \"./core/env\";\nimport { injectStyles, removeStyles } from \"./ui/styles\";\nimport { createChatWindow } from \"./ui/components/chat-window\";\nimport { createButtonBubble } from \"./ui/components/button-bubble\";\n\nfunction mapToWsOrigin(origin: string): string {\n try {\n const url = new URL(origin);\n const wsProtocol = url.protocol === \"https:\" ? \"wss:\" : \"ws:\";\n // Localhost: swap port to 3423 (AI backend WebSocket port)\n if (url.hostname === \"localhost\" || url.hostname === \"127.0.0.1\") {\n url.port = \"3423\";\n url.protocol = wsProtocol;\n return url.origin;\n }\n // Test: test.namiru.ai -> wss://ai-test.namiru.ai\n if (url.hostname === \"test.namiru.ai\") {\n return `${wsProtocol}//ai-test.namiru.ai`;\n }\n // Production: namiru.ai / app.namiru.ai / api.namiru.ai -> wss://ai.namiru.ai\n if (url.hostname === \"namiru.ai\" || url.hostname === \"app.namiru.ai\" || url.hostname === \"api.namiru.ai\") {\n return `${wsProtocol}//ai.namiru.ai`;\n }\n // Fallback: prefix with ai.\n url.protocol = wsProtocol;\n return url.origin;\n } catch {\n const wsProtocol = origin.startsWith(\"https\") ? \"wss\" : \"ws\";\n const host = origin.replace(/^https?:\\/\\//, \"\");\n return `${wsProtocol}://${host}`;\n }\n}\n\nfunction mapToApiOrigin(origin: string): string {\n try {\n const url = new URL(origin);\n // Production: app.namiru.ai -> api.namiru.ai\n if (url.hostname.startsWith(\"app.\")) {\n url.hostname = url.hostname.replace(\"app.\", \"api.\");\n return url.origin;\n }\n // Test/staging: test.namiru.ai -> api-test.namiru.ai\n if (url.hostname === \"test.namiru.ai\") {\n url.hostname = \"api-test.namiru.ai\";\n return url.origin;\n }\n // Bare domain: namiru.ai -> api.namiru.ai\n if (url.hostname === \"namiru.ai\") {\n url.hostname = \"api.namiru.ai\";\n return url.origin;\n }\n // Localhost (any port): map to localhost:3001 (backend-api)\n if (url.hostname === \"localhost\" || url.hostname === \"127.0.0.1\") {\n url.port = \"3001\";\n return url.origin;\n }\n return url.origin;\n } catch {\n return origin;\n }\n}\n\nfunction deriveUrls(config: NamiruChatConfig): {\n apiBase: string;\n wsUrl: string;\n} {\n let apiBase: string;\n let scriptOrigin: string | null = null;\n\n if (config.serverUrl) {\n apiBase = config.serverUrl.replace(/\\/$/, \"\");\n } else {\n // Try to derive from the script src attribute first (takes priority over location.origin)\n const scripts = document.querySelectorAll(\"script[src]\");\n for (let i = scripts.length - 1; i >= 0; i--) {\n const src = (scripts[i] as HTMLScriptElement).src;\n if (src.includes(\"namiru-chat\") || src.includes(\"namiru\")) {\n try {\n const url = new URL(src);\n scriptOrigin = url.origin;\n break;\n } catch {\n // Invalid URL, continue\n }\n }\n }\n // Use script origin if found, otherwise fall back to location.origin\n apiBase = mapToApiOrigin(scriptOrigin || location.origin);\n }\n\n return {\n apiBase,\n wsUrl: config.wsUrl || mapToWsOrigin(scriptOrigin || apiBase),\n };\n}\n\nconst VISITOR_ID_KEY = \"namiru_visitor_id\";\n\nfunction getOrCreateVisitorId(): string {\n try {\n const existing = localStorage.getItem(VISITOR_ID_KEY);\n if (existing) return existing;\n const id = `v_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;\n localStorage.setItem(VISITOR_ID_KEY, id);\n return id;\n } catch {\n // localStorage unavailable (incognito, etc.) - generate ephemeral ID\n return `v_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;\n }\n}\n\nlet messageIdCounter = 0;\n\nfunction createMessageId(): string {\n messageIdCounter++;\n return `msg-${Date.now()}-${messageIdCounter}`;\n}\n\n/**\n * Check if the current page path matches any excluded route pattern.\n * Supports exact match and wildcard suffix (e.g. \"/chat/*\" matches \"/chat/anything\").\n * Empty or missing array means no route exclusions.\n */\nfunction isRouteExcluded(excludedRoutes: string[] | undefined): boolean {\n if (!excludedRoutes || excludedRoutes.length === 0) return false;\n const pathname = window.location.pathname;\n return excludedRoutes.some((pattern) => {\n if (pattern.endsWith('/*')) {\n const prefix = pattern.slice(0, -1); // \"/chat/*\" -> \"/chat/\"\n return pathname.startsWith(prefix) || pathname === prefix.slice(0, -1);\n }\n if (pattern.endsWith('*')) {\n const prefix = pattern.slice(0, -1); // \"/chat*\" -> \"/chat\"\n return pathname.startsWith(prefix);\n }\n return pathname === pattern;\n });\n}\n\n/**\n * Watch for SPA route changes (pushState, replaceState, popstate) and\n * show/hide the widget when navigating to/from excluded routes.\n * Returns a cleanup function that restores the original history methods.\n */\nfunction watchRouteChanges(\n excludedRoutes: string[],\n mountedEl: HTMLElement | null\n): () => void {\n if (!mountedEl) return () => {};\n\n const EVENT_NAME = \"namiru:locationchange\";\n\n const origPushState = history.pushState.bind(history);\n const origReplaceState = history.replaceState.bind(history);\n\n history.pushState = function (...args: Parameters<typeof origPushState>) {\n origPushState(...args);\n window.dispatchEvent(new Event(EVENT_NAME));\n };\n\n history.replaceState = function (...args: Parameters<typeof origReplaceState>) {\n origReplaceState(...args);\n window.dispatchEvent(new Event(EVENT_NAME));\n };\n\n function checkVisibility() {\n if (isRouteExcluded(excludedRoutes)) {\n mountedEl!.style.display = \"none\";\n } else {\n mountedEl!.style.display = \"\";\n }\n }\n\n window.addEventListener(EVENT_NAME, checkVisibility);\n window.addEventListener(\"popstate\", checkVisibility);\n\n return () => {\n history.pushState = origPushState;\n history.replaceState = origReplaceState;\n window.removeEventListener(EVENT_NAME, checkVisibility);\n window.removeEventListener(\"popstate\", checkVisibility);\n };\n}\n\n/**\n * Check if the current hostname matches any of the allowed domains.\n * Supports exact match and subdomain matching.\n * Empty or missing array means no domain restriction.\n */\nfunction isDomainAllowed(allowedDomains: string[] | undefined): boolean {\n if (!allowedDomains || allowedDomains.length === 0) return true;\n const hostname = window.location.hostname.toLowerCase();\n if (hostname === \"localhost\" || hostname === \"127.0.0.1\") return true;\n // Always allow *.namiru.ai and namiru.ai itself\n if (hostname === \"namiru.ai\" || hostname.endsWith(\".namiru.ai\")) return true;\n return allowedDomains.some((domain) => {\n const d = domain.toLowerCase();\n return hostname === d || hostname.endsWith(\".\" + d);\n });\n}\n\nexport function init(config: NamiruChatConfig): NamiruChatInstance {\n if (!config.agentId) {\n throw new Error(\"NamiruChat: agentId is required\");\n }\n\n const mode = config.mode || \"button\";\n const position = config.position || \"bottom-right\";\n const { apiBase, wsUrl } = deriveUrls(config);\n\n // Create core instances\n const store = new ChatStore();\n const apiClient = new ApiClient({ baseUrl: apiBase });\n let wsClient: WebSocketClient | null = null;\n let hostEl: HTMLElement | null = null;\n let shadowRoot: ShadowRoot | null = null;\n let rootEl: HTMLElement | null = null;\n let chatWindowEl: HTMLElement | null = null;\n let buttonEl: HTMLElement | null = null;\n let destroyed = false;\n let lastHandoffReason: string = \"handoff_accepted\";\n let pendingEscalationForm = false;\n let inactivityTimer: InactivityTimer | null = null;\n let feedbackEnabled = false;\n let routeCleanup: (() => void) | null = null;\n\n // Create Shadow DOM host for CSS isolation (with fallback for old browsers)\n hostEl = document.createElement(\"div\");\n hostEl.id = \"namiru-widget-host\";\n\n const supportsShadow = typeof hostEl.attachShadow === \"function\";\n setHasShadowDom(supportsShadow);\n\n if (supportsShadow) {\n // Modern path: Shadow DOM provides full CSS isolation\n hostEl.style.cssText = \"all:initial;position:fixed;top:0;left:0;width:0;height:0;overflow:visible;z-index:2147483646;pointer-events:none;\";\n shadowRoot = hostEl.attachShadow({ mode: \"open\" });\n }\n // else: fallback - hostEl is just a plain container, styles go into document.head\n\n // Create the widget root element\n rootEl = document.createElement(\"div\");\n rootEl.className = \"namiru-widget-root\";\n\n // Render root is the shadow root when available, otherwise the host div itself\n const renderRoot: ShadowRoot | HTMLElement = shadowRoot || hostEl;\n\n if (supportsShadow) {\n // Re-enable pointer events on actual widget content inside shadow DOM\n rootEl.style.pointerEvents = \"auto\";\n }\n renderRoot.appendChild(rootEl);\n\n // Initialize: fetch branding, then render\n async function bootstrap(): Promise<void> {\n try {\n const branding = await apiClient.fetchBranding(config.agentId);\n\n if (destroyed) return;\n\n // Domain locking check using allowedDomains from the public config\n if (!isDomainAllowed(branding.allowedDomains)) {\n console.warn(\n `[Namiru Widget] Domain \"${window.location.hostname}\" is not allowed for this agent. Allowed: ${JSON.stringify(branding.allowedDomains)}`\n );\n return; // Do not render the widget\n }\n\n // Route exclusion check using excludedRoutes from the public config\n if (isRouteExcluded(branding.excludedRoutes)) {\n console.info(\n `[Namiru Widget] Widget hidden on excluded route \"${window.location.pathname}\"`\n );\n return; // Do not render the widget on this route\n }\n\n // Note: Branding properties (colors, fonts, messages) are loaded from server\n // and are no longer configurable via client-side config for consistency\n\n // Inject widget styles into the render root (shadow DOM or document.head fallback)\n injectStyles({\n primaryColor: branding.primaryColor,\n accentColor: branding.accentColor,\n headerColor: branding.headerColor,\n fontFamily: branding.fontFamily,\n presetTheme: branding.presetTheme,\n backgroundColor: branding.backgroundColor,\n textColor: branding.textColor,\n fontSize: branding.fontSize,\n userMessageColor: branding.userMessageColor,\n agentMessageColor: branding.agentMessageColor,\n borderColor: branding.borderColor,\n inputColor: branding.inputColor,\n buttonColor: branding.buttonColor,\n }, renderRoot, !supportsShadow);\n\n // Override suggested questions from init config if provided\n if (config.suggestedQuestions && config.suggestedQuestions.length > 0) {\n branding.suggestedQuestions = config.suggestedQuestions;\n }\n console.log(\"[NamiruChat] suggestedQuestions:\", branding.suggestedQuestions);\n\n // Merge server-side config with local config\n const preChatEnabled =\n config.preChatEnabled ??\n branding.preChatConfig?.enabled ??\n false;\n\n // Ensure branding.preChatConfig reflects widget-level overrides so\n // showPreChat() in chat-window.ts can read it correctly\n if (preChatEnabled) {\n if (!branding.preChatConfig) {\n branding.preChatConfig = {\n enabled: true,\n template: config.preChatTemplate ?? null,\n custom: config.preChatCustom,\n };\n } else {\n branding.preChatConfig.enabled = true;\n if (config.preChatTemplate !== undefined) {\n branding.preChatConfig.template = config.preChatTemplate;\n }\n if (config.preChatCustom) {\n branding.preChatConfig.custom = config.preChatCustom;\n }\n }\n }\n feedbackEnabled = branding.feedbackConfig?.enabled ?? false;\n const feedbackInactivityMinutes =\n branding.feedbackConfig?.inactivityMinutes ?? 3;\n\n // Create inactivity timer for feedback prompt\n if (feedbackEnabled) {\n inactivityTimer = new InactivityTimer(feedbackInactivityMinutes, () => {\n const currentState = store.getState();\n if (\n !currentState.feedbackGiven &&\n currentState.state === \"chatting\" &&\n currentState.messages.length > 0\n ) {\n store.dispatch({ type: \"SET_STATE\", state: \"feedback\" });\n }\n });\n }\n\n // Create chat window\n chatWindowEl = createChatWindow({\n store,\n branding,\n agentId: config.agentId,\n mode,\n position,\n onSendMessage: (content: string) => {\n const userMsg: ChatMessage = {\n id: createMessageId(),\n role: \"user\",\n content,\n timestamp: Date.now(),\n };\n store.dispatch({ type: \"ADD_MESSAGE\", message: userMsg });\n store.dispatch({ type: \"SET_LOADING\", isLoading: true });\n\n if (wsClient) {\n wsClient.sendMessage(content);\n }\n },\n onPreChatSelect: (label: string) => {\n store.dispatch({ type: \"SET_QUALIFICATION\", qualification: label });\n store.dispatch({ type: \"SET_STATE\", state: \"connecting\" });\n connectWebSocket(label);\n },\n onFeedback: (rating: \"up\" | \"down\") => {\n const sessionId = store.getState().sessionId;\n if (sessionId) {\n apiClient\n .submitFeedback(config.agentId, { sessionId, rating })\n .catch((err) =>\n console.error(\"NamiruChat: feedback submit failed\", err)\n );\n }\n store.dispatch({ type: \"SET_FEEDBACK_GIVEN\" });\n inactivityTimer?.stop();\n config.onFeedback?.(rating);\n },\n onEscalationEmail: (email: string) => {\n const sessionId = store.getState().sessionId;\n if (sessionId) {\n apiClient\n .submitEscalation(config.agentId, { sessionId, userEmail: email })\n .catch((err) =>\n console.error(\"NamiruChat: escalation submit failed\", err)\n );\n }\n // Also notify backend-ai via WebSocket to persist customerEmail on the session\n if (wsClient) {\n wsClient.sendEscalationEmail(email);\n }\n config.onLeadCapture?.({\n email,\n sessionId: sessionId || \"\",\n source: \"email_fallback\",\n qualification: store.getState().qualification || undefined,\n });\n },\n onTranscriptEmail: (email: string) => {\n const sessionId = store.getState().sessionId;\n if (sessionId) {\n apiClient\n .requestTranscript(config.agentId, sessionId, { email })\n .catch((err) =>\n console.error(\"NamiruChat: transcript request failed\", err)\n );\n }\n },\n onContactFormSubmit: (data: { name: string; email: string; message: string }) => {\n const visitorId = getOrCreateVisitorId();\n const sessionId = store.getState().sessionId;\n apiClient\n .submitLead({\n agentId: config.agentId,\n name: data.name || undefined,\n email: data.email,\n message: data.message,\n visitorId,\n fallbackReason: lastHandoffReason as \"handoff_accepted\" | \"message_limit\" | \"conversation_limit\",\n conversationId: sessionId || undefined,\n })\n .catch((err) =>\n console.error(\"NamiruChat: lead submit failed\", err)\n );\n // Notify backend-ai to persist handoff metadata on the session\n if (wsClient) {\n wsClient.sendHandoffComplete({\n email: data.email,\n name: data.name || undefined,\n reason: lastHandoffReason,\n });\n }\n config.onLeadCapture?.({\n email: data.email,\n sessionId: sessionId || \"\",\n source: \"email_fallback\",\n qualification: store.getState().qualification || undefined,\n });\n },\n onLimitMessage: (data: { message: string; visitorEmail?: string }) => {\n if (data.visitorEmail) {\n // Contact endpoint sends email AND persists lead -- no need\n // to also call limit-message (which would duplicate the email).\n apiClient\n .submitContactMessage(config.agentId, {\n email: data.visitorEmail,\n message: data.message,\n visitorId: getOrCreateVisitorId(),\n })\n .catch((err) =>\n console.error(\"NamiruChat: contact message submit failed\", err)\n );\n } else {\n // No email provided -- limit-message is the only way to\n // notify the owner.\n apiClient\n .submitLimitMessage({\n agentId: config.agentId,\n message: data.message,\n })\n .catch((err) =>\n console.error(\"NamiruChat: limit message submit failed\", err)\n );\n }\n },\n feedbackEnabled,\n onNewChat: () => {\n // Disconnect existing WebSocket\n if (wsClient) {\n wsClient.disconnect();\n wsClient = null;\n }\n // Stop inactivity timer for the old session\n inactivityTimer?.stop();\n // Reset store state (clears messages, session, etc.)\n store.dispatch({ type: \"RESET\" });\n // Keep widget open and show connecting state\n store.dispatch({ type: \"SET_OPEN\", isOpen: true });\n store.dispatch({ type: \"SET_STATE\", state: \"connecting\" });\n connectWebSocket();\n },\n });\n\n rootEl!.appendChild(chatWindowEl);\n\n // Button mode: create the floating bubble\n if (mode === \"button\") {\n buttonEl = createButtonBubble({\n position,\n store,\n welcomeMessage: branding.bubbleGreeting || undefined,\n greetingDelay: config.greetingDelay,\n bubbleStyle: branding.bubbleStyle,\n onCloseRequest: () => {\n const currentState = store.getState();\n // Same logic as X button in chat-header\n if (\n feedbackEnabled &&\n !currentState.feedbackGiven &&\n currentState.state === \"chatting\" &&\n currentState.messages.length > 0\n ) {\n store.dispatch({ type: \"SET_STATE\", state: \"feedback\" });\n return;\n }\n if (currentState.messages.length === 0) {\n store.dispatch({ type: \"SET_OPEN\", isOpen: false });\n return;\n }\n // Show confirmation modal\n const showConfirm = (chatWindowEl as any)?._namiruShowCloseConfirmation;\n if (typeof showConfirm === \"function\") {\n showConfirm();\n } else {\n store.dispatch({ type: \"SET_OPEN\", isOpen: false });\n }\n },\n });\n rootEl!.appendChild(buttonEl);\n }\n\n // Apply fixed dimensions for inline mode\n if (mode === \"inline\" && chatWindowEl) {\n const w = config.width || \"100%\";\n const h = config.height || \"100%\";\n chatWindowEl.style.width = w;\n chatWindowEl.style.height = h;\n chatWindowEl.style.maxHeight = h;\n // Ensure height propagates through the DOM chain\n rootEl!.style.height = \"100%\";\n }\n\n // Mount to DOM\n if (supportsShadow) {\n // Shadow DOM path: mount the host element (which contains the shadow root)\n if (mode === \"inline\" && config.container) {\n hostEl!.style.cssText = \"all:initial;display:block;height:100%;\";\n config.container.appendChild(hostEl!);\n } else {\n document.body.appendChild(hostEl!);\n }\n } else {\n // Fallback path: mount rootEl directly (old behavior)\n if (mode === \"inline\" && config.container) {\n config.container.appendChild(rootEl!);\n } else {\n document.body.appendChild(rootEl!);\n }\n }\n\n // Determine initial state\n // Usage limits are checked by backend-ai during WebSocket init.\n // If limit is reached, backend-ai sends a 'usage_limit' event instead of 'agent_initialized'.\n if (preChatEnabled) {\n store.dispatch({ type: \"SET_STATE\", state: \"pre_chat\" });\n } else {\n store.dispatch({ type: \"SET_STATE\", state: \"connecting\" });\n connectWebSocket();\n }\n\n // Auto-open in inline mode\n if (mode === \"inline\") {\n store.dispatch({ type: \"SET_OPEN\", isOpen: true });\n }\n\n // Watch for SPA route changes to re-evaluate excluded routes\n if (branding.excludedRoutes && branding.excludedRoutes.length > 0) {\n const mountedEl = supportsShadow ? hostEl : rootEl;\n routeCleanup = watchRouteChanges(branding.excludedRoutes, mountedEl);\n }\n } catch (err) {\n console.error(\"NamiruChat: initialization failed\", err);\n store.dispatch({\n type: \"SET_ERROR\",\n error: \"Failed to load chat. Please try again later.\",\n });\n }\n }\n\n function maybeShowPendingEscalation(): void {\n if (!pendingEscalationForm) return;\n pendingEscalationForm = false;\n // Directly call the escalation form display after a short delay\n // to ensure the AI message renders first\n if (chatWindowEl) {\n setTimeout(() => {\n const showFn = (chatWindowEl as any)?._namiruShowEscalation;\n if (typeof showFn === \"function\") {\n showFn();\n }\n }, 100);\n }\n }\n\n function connectWebSocket(qualification?: string): void {\n if (wsClient || destroyed) return;\n\n wsClient = new WebSocketClient({\n url: wsUrl,\n agentId: config.agentId,\n visitorId: getOrCreateVisitorId(),\n });\n\n // Wire WebSocket events to store\n wsClient.on(\"connected\", () => {\n // Connection established, waiting for agent_initialized\n });\n\n wsClient.on(\"agent_initialized\", (event) => {\n store.dispatch({ type: \"SET_STATE\", state: \"chatting\" });\n store.dispatch({ type: \"SET_LOADING\", isLoading: false });\n\n if (event.data.sessionId) {\n store.dispatch({\n type: \"SET_SESSION_ID\",\n sessionId: event.data.sessionId,\n });\n config.onSessionStart?.(event.data.sessionId);\n }\n\n // Send qualification as first message context if present\n if (qualification) {\n wsClient?.sendMessage(\n `[User selected: ${qualification}]`\n );\n }\n\n });\n\n wsClient.on(\"stream_token\", (event) => {\n store.dispatch({ type: \"APPEND_STREAMING\", token: event.data.token });\n });\n\n wsClient.on(\"final_response\", (event) => {\n store.dispatch({ type: \"CLEAR_STREAMING\" });\n const assistantMsg: ChatMessage = {\n id: createMessageId(),\n role: \"assistant\",\n content: event.data.content || event.data.response || \"\",\n timestamp: Date.now(),\n };\n store.dispatch({ type: \"ADD_MESSAGE\", message: assistantMsg });\n store.dispatch({ type: \"SET_LOADING\", isLoading: false });\n\n // Show pending escalation form after the message renders\n maybeShowPendingEscalation();\n\n // If AI signals the conversation may have ended, show feedback immediately\n if (\n feedbackEnabled &&\n event.data.conversationMayHaveEnded &&\n !store.getState().feedbackGiven\n ) {\n // Short delay so the final message renders before feedback appears\n setTimeout(() => {\n const currentState = store.getState();\n if (\n !currentState.feedbackGiven &&\n currentState.state === \"chatting\" &&\n currentState.messages.length > 0\n ) {\n store.dispatch({ type: \"SET_STATE\", state: \"feedback\" });\n }\n }, 800);\n inactivityTimer?.stop();\n } else if (inactivityTimer && !store.getState().feedbackGiven) {\n // Reset inactivity timer after each assistant response\n inactivityTimer.reset();\n }\n });\n\n wsClient.on(\"stream_end\", () => {\n const streamingContent = store.getState().streamingContent;\n if (streamingContent) {\n store.dispatch({ type: \"CLEAR_STREAMING\" });\n const assistantMsg: ChatMessage = {\n id: createMessageId(),\n role: \"assistant\",\n content: streamingContent,\n timestamp: Date.now(),\n };\n store.dispatch({ type: \"ADD_MESSAGE\", message: assistantMsg });\n }\n store.dispatch({ type: \"SET_LOADING\", isLoading: false });\n\n // Show pending escalation form after the message renders\n maybeShowPendingEscalation();\n\n // Reset inactivity timer after each streamed response\n if (inactivityTimer && !store.getState().feedbackGiven) {\n inactivityTimer.reset();\n }\n });\n\n wsClient.on(\"tool_start\", () => {\n store.dispatch({ type: \"SET_LOADING\", isLoading: true });\n });\n\n wsClient.on(\"tool_end\", () => {\n // Loading continues until final_response or stream_end\n });\n\n wsClient.on(\"kit_trigger\", (event) => {\n const trigger = event.data;\n if (\n trigger === \"escalation_email_form\" ||\n trigger?.type === \"escalation_email_form\"\n ) {\n // Set flag so the form is shown AFTER the bot's final response renders\n pendingEscalationForm = true;\n }\n });\n\n // Handle handoff_active event - a human operator is handling this conversation\n wsClient.on(\"handoff_active\", (event) => {\n const msg: ChatMessage = {\n id: createMessageId(),\n role: \"assistant\",\n content: event.data?.message || \"A human operator is currently handling this conversation. Please wait for their response.\",\n timestamp: Date.now(),\n };\n store.dispatch({ type: \"ADD_MESSAGE\", message: msg });\n store.dispatch({ type: \"SET_LOADING\", isLoading: false });\n });\n\n // Handle show_handoff_form event from backend - triggers email fallback form\n wsClient.on(\"show_handoff_form\", (event) => {\n lastHandoffReason = event.data?.reason || \"handoff_accepted\";\n store.dispatch({ type: \"SET_STATE\", state: \"email_fallback\" });\n store.dispatch({ type: \"SET_LOADING\", isLoading: false });\n });\n\n wsClient.on(\"error\", (event) => {\n // If this is a usage limit error, switch to email fallback instead of showing error\n if (event.data?.type === \"usage_limit\" || event.data?.usage_limit) {\n store.dispatch({ type: \"SET_STATE\", state: \"conversation_limit\" });\n store.dispatch({ type: \"SET_LOADING\", isLoading: false });\n return;\n }\n // Domain not authorized - show dedicated error, no reconnect\n if (event.data?.message === \"Domain not authorized\") {\n store.dispatch({ type: \"SET_STATE\", state: \"domain_error\" });\n store.dispatch({ type: \"SET_LOADING\", isLoading: false });\n return;\n }\n console.error(\"NamiruChat: WebSocket error\", event.data);\n store.dispatch({\n type: \"SET_ERROR\",\n error: event.data?.message || \"Connection error. Please try again.\",\n });\n store.dispatch({ type: \"SET_LOADING\", isLoading: false });\n });\n\n wsClient.on(\"disconnected\", () => {\n // Reconnection is handled by WebSocketClient internally\n });\n\n wsClient.connect();\n }\n\n // Start initialization\n bootstrap();\n\n // Track open/close transitions to manage WS lifecycle\n // RESET is dispatched by close handlers BEFORE SET_OPEN:false, not here.\n let prevIsOpen = false;\n let lifecycleGuard = false;\n store.subscribe((state) => {\n if (destroyed || lifecycleGuard) return;\n\n // Close transition\n if (prevIsOpen && !state.isOpen) {\n prevIsOpen = false;\n lifecycleGuard = true;\n if (wsClient) {\n wsClient.disconnect();\n wsClient = null;\n }\n inactivityTimer?.stop();\n lifecycleGuard = false;\n return;\n }\n\n // Reopen transition (only reconnect if WS was disconnected)\n if (!prevIsOpen && state.isOpen && !wsClient) {\n prevIsOpen = true;\n lifecycleGuard = true;\n store.dispatch({ type: \"SET_STATE\", state: \"connecting\" });\n connectWebSocket();\n lifecycleGuard = false;\n return;\n }\n\n prevIsOpen = state.isOpen;\n });\n\n // Return the public API\n return {\n open: () => {\n if (!destroyed) {\n store.dispatch({ type: \"SET_OPEN\", isOpen: true });\n }\n },\n close: () => {\n if (!destroyed) {\n store.dispatch({ type: \"SET_OPEN\", isOpen: false });\n }\n },\n toggle: () => {\n if (!destroyed) {\n const isOpen = store.getState().isOpen;\n store.dispatch({ type: \"SET_OPEN\", isOpen: !isOpen });\n }\n },\n destroy: () => {\n if (destroyed) return;\n destroyed = true;\n\n routeCleanup?.();\n routeCleanup = null;\n wsClient?.disconnect();\n inactivityTimer?.stop();\n removeStyles();\n\n // Remove the mounted element (hostEl for shadow DOM, rootEl for fallback)\n const mountedEl = supportsShadow ? hostEl : rootEl;\n if (mountedEl && mountedEl.parentNode) {\n mountedEl.parentNode.removeChild(mountedEl);\n }\n\n const sessionId = store.getState().sessionId;\n if (sessionId) {\n config.onSessionEnd?.(sessionId);\n }\n\n store.dispatch({ type: \"RESET\" });\n\n hostEl = null;\n shadowRoot = null;\n rootEl = null;\n chatWindowEl = null;\n buttonEl = null;\n wsClient = null;\n },\n updateConfig: (partial: Partial<NamiruChatConfig>) => {\n if (destroyed) return;\n Object.assign(config, partial);\n },\n };\n}\n\n// Auto-init from script tag data attributes for backward compatibility\n// Supports: <script src=\".../widget.js\" data-agent-id=\"xxx\"></script>\nif (typeof document !== \"undefined\" && document.currentScript) {\n const scriptEl = document.currentScript as HTMLScriptElement;\n const agentId = scriptEl.getAttribute(\"data-agent-id\");\n\n if (agentId) {\n const mode =\n (scriptEl.getAttribute(\"data-mode\") as \"button\" | \"inline\") || \"button\";\n const serverUrl = scriptEl.getAttribute(\"data-server-url\") || undefined;\n const containerId = scriptEl.getAttribute(\"data-container-id\");\n\n init({\n agentId,\n mode,\n serverUrl,\n container: containerId\n ? document.getElementById(containerId) || undefined\n : undefined,\n });\n }\n}\n", "import type { ChatMessage } from \"./types\";\n\nexport type ChatState =\n | \"idle\"\n | \"pre_chat\"\n | \"connecting\"\n | \"chatting\"\n | \"feedback\"\n | \"escalation\"\n | \"email_fallback\"\n | \"conversation_limit\"\n | \"domain_error\"\n | \"error\";\n\nexport interface ChatStoreState {\n state: ChatState;\n messages: ChatMessage[];\n isOpen: boolean;\n isLoading: boolean;\n streamingContent: string;\n qualification: string | null;\n feedbackGiven: boolean;\n sessionId: string | null;\n error: string | null;\n}\n\nexport type ChatAction =\n | { type: \"SET_STATE\"; state: ChatState }\n | { type: \"SET_OPEN\"; isOpen: boolean }\n | { type: \"SET_LOADING\"; isLoading: boolean }\n | { type: \"ADD_MESSAGE\"; message: ChatMessage }\n | { type: \"APPEND_STREAMING\"; token: string }\n | { type: \"CLEAR_STREAMING\" }\n | { type: \"SET_QUALIFICATION\"; qualification: string }\n | { type: \"SET_FEEDBACK_GIVEN\" }\n | { type: \"SET_SESSION_ID\"; sessionId: string }\n | { type: \"SET_ERROR\"; error: string | null }\n | { type: \"RESET\" };\n\nexport type StoreSubscriber = (state: ChatStoreState) => void;\n\nfunction createInitialState(): ChatStoreState {\n return {\n state: \"idle\",\n messages: [],\n isOpen: false,\n isLoading: false,\n streamingContent: \"\",\n qualification: null,\n feedbackGiven: false,\n sessionId: null,\n error: null,\n };\n}\n\nfunction reducer(state: ChatStoreState, action: ChatAction): ChatStoreState {\n switch (action.type) {\n case \"SET_STATE\":\n return { ...state, state: action.state, error: null };\n\n case \"SET_OPEN\":\n return { ...state, isOpen: action.isOpen };\n\n case \"SET_LOADING\":\n return { ...state, isLoading: action.isLoading };\n\n case \"ADD_MESSAGE\":\n return { ...state, messages: [...state.messages, action.message] };\n\n case \"APPEND_STREAMING\":\n return {\n ...state,\n streamingContent: state.streamingContent + action.token,\n };\n\n case \"CLEAR_STREAMING\":\n return { ...state, streamingContent: \"\" };\n\n case \"SET_QUALIFICATION\":\n return { ...state, qualification: action.qualification };\n\n case \"SET_FEEDBACK_GIVEN\":\n return { ...state, feedbackGiven: true };\n\n case \"SET_SESSION_ID\":\n return { ...state, sessionId: action.sessionId };\n\n case \"SET_ERROR\":\n return {\n ...state,\n error: action.error,\n state: action.error ? \"error\" : state.state,\n };\n\n case \"RESET\":\n return createInitialState();\n\n default:\n return state;\n }\n}\n\nexport class ChatStore {\n private state: ChatStoreState;\n private subscribers: Set<StoreSubscriber> = new Set();\n\n constructor() {\n this.state = createInitialState();\n }\n\n getState(): ChatStoreState {\n return this.state;\n }\n\n dispatch(action: ChatAction): void {\n const prevState = this.state;\n this.state = reducer(prevState, action);\n if (this.state !== prevState) {\n this.notify();\n }\n }\n\n subscribe(subscriber: StoreSubscriber): () => void {\n this.subscribers.add(subscriber);\n return () => {\n this.subscribers.delete(subscriber);\n };\n }\n\n private notify(): void {\n const snapshot = this.state;\n this.subscribers.forEach((subscriber) => {\n try {\n subscriber(snapshot);\n } catch (err) {\n console.error(\"NamiruChat: error in store subscriber\", err);\n }\n });\n }\n}\n", "import type { AgentBrandingData } from \"./types\";\n\nexport interface ApiClientConfig {\n baseUrl: string;\n}\n\nexport interface FeedbackPayload {\n sessionId: string;\n rating: \"up\" | \"down\";\n comment?: string;\n}\n\nexport interface EscalationPayload {\n sessionId: string;\n userEmail: string;\n}\n\nexport interface TranscriptPayload {\n email: string;\n}\n\nexport interface TranscriptResponse {\n success: boolean;\n}\n\nexport interface LimitMessagePayload {\n agentId: string;\n message: string;\n visitorEmail?: string;\n}\n\nexport interface LeadSubmitPayload {\n agentId: string;\n name?: string;\n email: string;\n message: string;\n visitorId?: string;\n fallbackReason?: \"handoff_accepted\" | \"message_limit\" | \"conversation_limit\";\n conversationId?: string;\n}\n\nexport class ApiClient {\n private baseUrl: string;\n\n constructor(config: ApiClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, \"\");\n }\n\n async fetchBranding(agentId: string): Promise<AgentBrandingData> {\n const response = await fetch(\n `${this.baseUrl}/api/public/agents/${encodeURIComponent(agentId)}/branding`\n );\n\n if (!response.ok) {\n throw new Error(`Failed to fetch agent branding: ${response.status}`);\n }\n\n const data = await response.json();\n\n // Check for a branding sub-object (backward compat with old widget API)\n const branding = data.branding || {};\n\n function validHex(val: unknown, fallback: string): string {\n if (typeof val === \"string\" && /^#[0-9a-fA-F]{3,8}$/.test(val)) return val;\n return fallback;\n }\n\n // Parse suggested questions from JSON string or array\n let suggestedQuestions: string[] = [];\n if (Array.isArray(branding.suggestedQuestions)) {\n suggestedQuestions = branding.suggestedQuestions;\n } else if (typeof branding.suggestedQuestions === \"string\") {\n try {\n const parsed = JSON.parse(branding.suggestedQuestions);\n if (Array.isArray(parsed)) suggestedQuestions = parsed;\n } catch {\n // ignore parse errors\n }\n }\n\n return {\n agentId: data.id,\n name: branding.agentDisplayName || data.name,\n primaryColor: validHex(branding.primaryColor, \"#1f2937\"),\n accentColor: validHex(branding.accentColor, \"#21DFFB\"),\n logoUrl: branding.agentAvatar || branding.logoUrl || undefined,\n agentAvatar: branding.agentAvatar || branding.logoUrl || undefined,\n welcomeMessage: branding.welcomeMessage || undefined,\n showPoweredBy: branding.showPoweredBy ?? true,\n showHeader: branding.showHeader ?? true,\n headerColor: validHex(branding.headerColor, \"\") || undefined,\n headerTitle: branding.headerTitle || undefined,\n headerSubtitle: branding.headerSubtitle || undefined,\n presetTheme: branding.presetTheme || \"light\",\n backgroundColor: validHex(branding.backgroundColor, \"\") || undefined,\n textColor: validHex(branding.textColor, \"\") || undefined,\n bubbleStyle: branding.bubbleStyle || \"modern\",\n fontFamily: branding.fontFamily || \"system\",\n fontSize: branding.fontSize || \"medium\",\n userMessageColor: branding.userMessageColor === '' ? '' : (validHex(branding.userMessageColor, \"\") || undefined),\n agentMessageColor: branding.agentMessageColor === '' ? '' : (validHex(branding.agentMessageColor, \"\") || undefined),\n iconColor: validHex(branding.iconColor, \"\") || undefined,\n borderColor: validHex(branding.borderColor, \"\") || undefined,\n inputColor: validHex(branding.inputColor, \"\") || undefined,\n buttonColor: validHex(branding.buttonColor, \"\") || undefined,\n bubbleGreeting: branding.bubbleGreeting || undefined,\n suggestedQuestions,\n preChatConfig: data.preChatConfig\n ? {\n enabled: data.preChatConfig.enabled,\n template: data.preChatConfig.template,\n custom:\n data.preChatConfig.template === \"custom\" &&\n data.preChatConfig.customQuestion\n ? {\n question: data.preChatConfig.customQuestion,\n options: data.preChatConfig.customOptions || [],\n }\n : undefined,\n }\n : undefined,\n feedbackConfig: data.feedbackConfig ?? undefined,\n escalationConfig: data.escalationConfig\n ? {\n enabled:\n data.escalationConfig.emailFallbackEnabled ||\n data.escalationConfig.liveChatEnabled ||\n false,\n emailFallbackEnabled: data.escalationConfig.emailFallbackEnabled,\n customReplyMessage: data.escalationConfig.customReplyMessage,\n liveChatEnabled: data.escalationConfig.liveChatEnabled,\n }\n : undefined,\n allowedDomains: Array.isArray(data.allowedDomains) ? data.allowedDomains : undefined,\n excludedRoutes: Array.isArray(data.excludedRoutes) ? data.excludedRoutes : undefined,\n };\n }\n\n async submitFeedback(\n agentId: string,\n payload: FeedbackPayload\n ): Promise<void> {\n const response = await fetch(\n `${this.baseUrl}/api/public/agents/${encodeURIComponent(agentId)}/feedback`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n }\n );\n\n if (!response.ok) {\n throw new Error(`Failed to submit feedback: ${response.status}`);\n }\n }\n\n async submitEscalation(\n agentId: string,\n payload: EscalationPayload\n ): Promise<void> {\n const response = await fetch(\n `${this.baseUrl}/api/public/agents/${encodeURIComponent(agentId)}/escalate`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n }\n );\n\n if (!response.ok) {\n throw new Error(`Failed to submit escalation: ${response.status}`);\n }\n }\n\n async requestTranscript(\n agentId: string,\n sessionId: string,\n payload: TranscriptPayload\n ): Promise<TranscriptResponse> {\n const response = await fetch(\n `${this.baseUrl}/api/public/agents/${encodeURIComponent(agentId)}/sessions/${encodeURIComponent(sessionId)}/transcript`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n }\n );\n\n if (!response.ok) {\n throw new Error(`Failed to request transcript: ${response.status}`);\n }\n\n return response.json();\n }\n\n async submitLimitMessage(payload: LimitMessagePayload): Promise<{ success: boolean }> {\n const response = await fetch(`${this.baseUrl}/api/leads/limit-message`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to submit limit message: ${response.status}`);\n }\n\n return response.json();\n }\n\n async submitContactMessage(\n agentId: string,\n payload: { email: string; message: string; visitorId?: string }\n ): Promise<{ success: boolean }> {\n const response = await fetch(\n `${this.baseUrl}/api/public/agents/${encodeURIComponent(agentId)}/contact`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n }\n );\n\n if (!response.ok) {\n throw new Error(`Failed to submit contact message: ${response.status}`);\n }\n\n return response.json();\n }\n\n async submitLead(payload: LeadSubmitPayload): Promise<{ success: boolean }> {\n const response = await fetch(`${this.baseUrl}/api/leads`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to submit lead: ${response.status}`);\n }\n\n return response.json();\n }\n}\n", "export type WebSocketEventType =\n | \"connected\"\n | \"disconnected\"\n | \"agent_initialized\"\n | \"stream_token\"\n | \"final_response\"\n | \"stream_end\"\n | \"tool_start\"\n | \"tool_end\"\n | \"kit_trigger\"\n | \"usage_limit\"\n | \"show_handoff_form\"\n | \"handoff_active\"\n | \"error\"\n | \"status\";\n\nexport interface WebSocketEvent {\n type: WebSocketEventType;\n data: any;\n}\n\nexport type WebSocketEventHandler = (event: WebSocketEvent) => void;\n\nexport interface WebSocketClientConfig {\n url: string;\n agentId: string;\n token?: string;\n visitorId?: string;\n maxReconnectAttempts?: number;\n}\n\nconst MAX_RECONNECT_ATTEMPTS_DEFAULT = 3;\nconst RECONNECT_BASE_DELAY_MS = 1000;\n\nexport class WebSocketClient {\n private ws: WebSocket | null = null;\n private config: WebSocketClientConfig;\n private listeners: Map<WebSocketEventType, Set<WebSocketEventHandler>> =\n new Map();\n private reconnectAttempts = 0;\n private maxReconnectAttempts: number;\n private isDestroyed = false;\n private isInitialized = false;\n\n constructor(config: WebSocketClientConfig) {\n this.config = config;\n this.maxReconnectAttempts =\n config.maxReconnectAttempts ?? MAX_RECONNECT_ATTEMPTS_DEFAULT;\n }\n\n connect(): void {\n if (this.isDestroyed) return;\n\n try {\n this.ws = new WebSocket(this.config.url);\n this.ws.onopen = this.handleOpen.bind(this);\n this.ws.onmessage = this.handleMessage.bind(this);\n this.ws.onclose = this.handleClose.bind(this);\n this.ws.onerror = this.handleError.bind(this);\n } catch (err) {\n this.emit(\"error\", {\n message: err instanceof Error ? err.message : \"WebSocket connection failed\",\n });\n }\n }\n\n disconnect(): void {\n this.isDestroyed = true;\n if (this.ws) {\n this.ws.onclose = null;\n this.ws.close();\n this.ws = null;\n }\n }\n\n sendMessage(content: string): void {\n this.send({ type: \"message\", content });\n }\n\n sendHandoffComplete(data: { email: string; name?: string; reason: string }): void {\n this.send({ type: \"handoff_complete\", ...data });\n }\n\n sendEscalationEmail(email: string): void {\n this.send({ type: \"escalation_email\", email });\n }\n\n on(type: WebSocketEventType, handler: WebSocketEventHandler): () => void {\n if (!this.listeners.has(type)) {\n this.listeners.set(type, new Set());\n }\n this.listeners.get(type)!.add(handler);\n\n return () => {\n this.listeners.get(type)?.delete(handler);\n };\n }\n\n private send(data: Record<string, unknown>): void {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.send(JSON.stringify(data));\n }\n }\n\n private emit(type: WebSocketEventType, data: any = {}): void {\n const event: WebSocketEvent = { type, data };\n this.listeners.get(type)?.forEach((handler) => {\n try {\n handler(event);\n } catch (err) {\n console.error(`NamiruChat: error in ${type} handler`, err);\n }\n });\n }\n\n private handleOpen(): void {\n this.reconnectAttempts = 0;\n this.emit(\"connected\", {});\n\n // Send init_agent on first connection\n if (!this.isInitialized) {\n this.send({\n type: \"init_agent\",\n agentId: this.config.agentId,\n token: this.config.token || \"\",\n visitorId: this.config.visitorId || \"\",\n });\n }\n }\n\n private handleMessage(event: MessageEvent): void {\n let data: any;\n try {\n data = JSON.parse(event.data);\n } catch {\n return;\n }\n\n const type = data.type as WebSocketEventType;\n\n switch (type) {\n case \"agent_initialized\":\n this.isInitialized = true;\n this.emit(\"agent_initialized\", data);\n break;\n\n case \"stream_token\":\n this.emit(\"stream_token\", data);\n break;\n\n case \"final_response\":\n this.emit(\"final_response\", data);\n break;\n\n case \"stream_end\":\n this.emit(\"stream_end\", data);\n break;\n\n case \"tool_start\":\n this.emit(\"tool_start\", data);\n break;\n\n case \"tool_end\":\n // Check for kit triggers in tool output\n this.handleToolEnd(data);\n break;\n\n case \"usage_limit\":\n this.emit(\"usage_limit\", data);\n // Also emit as error so the widget can handle it\n this.emit(\"error\", { ...data, usage_limit: true });\n break;\n\n case \"show_handoff_form\":\n this.emit(\"show_handoff_form\", data);\n break;\n\n case \"handoff_active\":\n this.emit(\"handoff_active\", data);\n break;\n\n case \"error\":\n this.emit(\"error\", data);\n break;\n\n case \"status\":\n this.emit(\"status\", data);\n break;\n\n default:\n // Forward any unhandled types\n break;\n }\n }\n\n private handleToolEnd(data: any): void {\n this.emit(\"tool_end\", data);\n\n // Parse tool output for kit triggers (e.g. escalation_email_form)\n if (data.output) {\n try {\n const output =\n typeof data.output === \"string\" ? JSON.parse(data.output) : data.output;\n if (output.kitTrigger) {\n this.emit(\"kit_trigger\", output.kitTrigger);\n }\n } catch {\n // Not JSON, ignore\n }\n }\n }\n\n private handleClose(event: CloseEvent): void {\n // Close code 1008 = policy violation (e.g. domain not authorized) - do not reconnect\n if (event.code === 1008) {\n this.isDestroyed = true;\n this.emit(\"disconnected\", { code: event.code, reason: event.reason, permanent: true });\n return;\n }\n\n this.emit(\"disconnected\", { code: event.code, reason: event.reason });\n\n if (!this.isDestroyed && this.reconnectAttempts < this.maxReconnectAttempts) {\n this.reconnectAttempts++;\n const delay = RECONNECT_BASE_DELAY_MS * Math.pow(2, this.reconnectAttempts - 1);\n setTimeout(() => this.connect(), delay);\n }\n }\n\n private handleError(): void {\n // The close event will fire after this, triggering reconnection logic\n this.emit(\"error\", { message: \"WebSocket connection error\" });\n }\n}\n", "export class InactivityTimer {\n private timerId: ReturnType<typeof setTimeout> | null = null;\n private minutes: number;\n private callback: () => void;\n\n constructor(minutes: number, callback: () => void) {\n this.minutes = minutes;\n this.callback = callback;\n }\n\n reset(): void {\n this.stop();\n this.timerId = setTimeout(() => {\n this.callback();\n }, this.minutes * 60 * 1000);\n }\n\n stop(): void {\n if (this.timerId !== null) {\n clearTimeout(this.timerId);\n this.timerId = null;\n }\n }\n\n updateMinutes(minutes: number): void {\n this.minutes = minutes;\n // If timer is already running, restart with new duration\n if (this.timerId !== null) {\n this.reset();\n }\n }\n}\n", "/**\n * Shared runtime flag indicating whether the widget is rendered inside Shadow DOM.\n * When false the widget falls back to direct DOM injection and needs !important\n * declarations to resist host-page CSS bleed-through.\n */\nexport let hasShadowDom = false;\n\nexport function setHasShadowDom(value: boolean): void {\n hasShadowDom = value;\n}\n", "export interface StyleOptions {\n primaryColor: string;\n accentColor?: string;\n headerColor?: string;\n fontFamily?: string;\n presetTheme?: \"light\" | \"dark\" | \"custom\";\n backgroundColor?: string;\n textColor?: string;\n fontSize?: \"small\" | \"medium\" | \"large\";\n userMessageColor?: string;\n agentMessageColor?: string;\n borderColor?: string;\n inputColor?: string;\n buttonColor?: string;\n}\n\nlet styleEl: HTMLStyleElement | null = null;\n\n/**\n * Inject widget styles into the given render root (Shadow DOM or fallback element).\n * When `useImportant` is true (fallback mode), key properties get !important\n * to resist host-page CSS bleed-through.\n */\nexport function injectStyles(\n options: string | StyleOptions,\n renderRoot: ShadowRoot | HTMLElement,\n useImportant?: boolean,\n): void {\n const opts: StyleOptions =\n typeof options === \"string\" ? { primaryColor: options } : options;\n\n const style = document.createElement(\"style\");\n style.setAttribute(\"data-namiru\", \"true\");\n\n style.textContent = getStyles(opts, useImportant);\n\n if (renderRoot instanceof ShadowRoot || renderRoot.shadowRoot) {\n renderRoot.appendChild(style);\n } else {\n // Fallback: inject into document.head like original behavior\n document.head.appendChild(style);\n }\n styleEl = style;\n}\n\nexport function removeStyles(): void {\n if (styleEl) {\n styleEl.remove();\n styleEl = null;\n }\n}\n\n\nfunction resolveFontFamily(font?: string): string {\n if (!font || font === \"system\") {\n return '\"Inter\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif';\n }\n if (font === \"modern\") return '\"Inter\", sans-serif';\n if (font === \"classic\") return '\"Georgia\", serif';\n return font;\n}\n\nfunction resolveFontSize(size?: string): string {\n if (size === \"small\") return \"13px\";\n if (size === \"large\") return \"17px\";\n return \"15px\";\n}\n\nfunction isLightColor(hex: string): boolean {\n let c = hex.replace(\"#\", \"\");\n if (c.length === 3) c = c[0] + c[0] + c[1] + c[1] + c[2] + c[2];\n if (c.length < 6 || !/^[0-9a-fA-F]{6}/.test(c)) return false;\n const r = parseInt(c.substring(0, 2), 16);\n const g = parseInt(c.substring(2, 4), 16);\n const b = parseInt(c.substring(4, 6), 16);\n return (r * 299 + g * 587 + b * 114) / 1000 > 150;\n}\n\nfunction getStyles(opts: StyleOptions, useImportant?: boolean): string {\n // Shorthand: appended to property values that host CSS commonly overrides.\n // Empty string when inside Shadow DOM (no need), \" !important\" in fallback mode.\n const _i = useImportant ? \" !important\" : \"\";\n const primary = opts.primaryColor;\n const accent = opts.accentColor || \"#21DFFB\";\n const fontStack = resolveFontFamily(opts.fontFamily);\n const fontSize = resolveFontSize(opts.fontSize);\n\n const isDark = opts.presetTheme === \"dark\";\n const bgColor = opts.backgroundColor || (isDark ? \"#0f0f1a\" : \"#ffffff\");\n const txtColor = opts.textColor || (isDark ? \"#ffffff\" : \"#1f2937\");\n // Use actual background luminance for derived colors (handles custom themes with dark bg)\n const isDarkBg = !isLightColor(bgColor);\n const borderColor = opts.borderColor || (isDarkBg ? \"rgba(255,255,255,0.15)\" : \"rgba(0,0,0,0.1)\");\n const bgSecondary = opts.inputColor || (isDarkBg ? \"rgba(255,255,255,0.08)\" : \"rgba(0,0,0,0.02)\");\n const txtSecondary = isDarkBg ? \"rgba(255,255,255,0.6)\" : \"rgba(0,0,0,0.45)\";\n const scrollThumb = isDarkBg ? \"rgba(255,255,255,0.2)\" : \"rgba(0,0,0,0.12)\";\n // Header background matches the chat background (like the Live Preview),\n // unless the user explicitly set a custom headerColor.\n const headerBg = opts.headerColor || bgColor;\n const headerTextColor = opts.headerColor\n ? (isLightColor(headerBg) ? \"#1f2937\" : \"#ffffff\")\n : txtColor;\n const headerTextSecondary = opts.headerColor\n ? (isLightColor(headerBg) ? \"rgba(0,0,0,0.5)\" : \"rgba(255,255,255,0.7)\")\n : txtSecondary;\n // Button background: custom buttonColor takes priority, then dark bg uses #0f0f1a, light bg uses primary color\n const buttonBg = opts.buttonColor || (isDarkBg ? \"#0f0f1a\" : primary);\n const buttonBgHover = adjustBrightness(buttonBg, -15);\n // User message bg: undefined = not set (use primary), '' = cleared (transparent), '#hex' = custom\n const userMsgBgVal = opts.userMessageColor !== undefined ? (opts.userMessageColor || \"transparent\") : primary;\n // User message text: contrast-aware based on bubble background luminance\n const userMsgText = userMsgBgVal === \"transparent\"\n ? txtColor\n : (isLightColor(userMsgBgVal) ? \"#1f2937\" : \"#ffffff\");\n\n return `\n/* Namiru Chat Widget Styles */\n.namiru-widget-root {\n --namiru-primary: ${primary};\n --namiru-primary-hover: ${adjustBrightness(primary, -15)};\n --namiru-accent: ${accent};\n --namiru-header-bg: ${headerBg};\n --namiru-header-text: ${headerTextColor};\n --namiru-header-text-secondary: ${headerTextSecondary};\n --namiru-bg: ${bgColor};\n --namiru-bg-secondary: ${bgSecondary};\n --namiru-text: ${txtColor};\n --namiru-text-secondary: ${txtSecondary};\n --namiru-border: ${borderColor};\n --namiru-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);\n --namiru-radius: 12px;\n --namiru-font: ${fontStack};\n --namiru-font-size: ${fontSize};\n --namiru-scroll-thumb: ${scrollThumb};\n --namiru-user-msg-bg: ${userMsgBgVal};\n --namiru-user-msg-text: ${userMsgText};\n --namiru-agent-msg-bg: ${opts.agentMessageColor || \"transparent\"};\n --namiru-button-bg: ${buttonBg};\n --namiru-button-bg-hover: ${buttonBgHover};\n font-family: var(--namiru-font)${_i};\n font-size: var(--namiru-font-size)${_i};\n color: var(--namiru-text)${_i};\n line-height: 1.5${_i};\n box-sizing: border-box${_i};\n}\n\n.namiru-widget-root *, .namiru-widget-root *::before, .namiru-widget-root *::after {\n box-sizing: border-box${_i};\n margin: 0;\n padding: 0;\n}\n\n/* Button bubble (floating launcher) */\n.namiru-button {\n position: fixed;\n width: 56px;\n height: 56px;\n border-radius: 50%;\n background: #0f0f1a;\n border: 1px solid var(--namiru-border);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: var(--namiru-shadow);\n transition: transform 0.2s ease, background 0.2s ease;\n z-index: 2147483646;\n color: #ffffff;\n}\n\n.namiru-button:hover {\n transform: scale(1.08);\n background: #1a1a2e;\n}\n\n.namiru-button--bottom-right {\n bottom: 20px;\n right: 20px;\n}\n\n.namiru-button--bottom-left {\n bottom: 20px;\n left: 20px;\n}\n\n.namiru-button svg {\n width: 24px;\n height: 24px;\n fill: currentColor;\n}\n\n/* Chat popup */\n.namiru-popup {\n position: fixed;\n width: 440px;\n height: 600px;\n border-radius: var(--namiru-radius);\n background: var(--namiru-bg);\n border: 1px solid var(--namiru-border);\n box-shadow: var(--namiru-shadow);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n z-index: 2147483647;\n opacity: 0;\n transform: scale(0.95) translateY(10px);\n transition: opacity 0.2s ease, transform 0.2s ease;\n pointer-events: none;\n}\n\n.namiru-popup--open {\n opacity: 1;\n transform: scale(1) translateY(0);\n pointer-events: auto;\n}\n\n.namiru-popup--bottom-right {\n bottom: 88px;\n right: 20px;\n}\n\n.namiru-popup--bottom-left {\n bottom: 88px;\n left: 20px;\n}\n\n/* Inline mode */\n.namiru-inline {\n width: 100%;\n height: 100%;\n border-radius: var(--namiru-radius);\n background: var(--namiru-bg);\n border: 1px solid var(--namiru-border);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n/* Header */\n.namiru-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n background: var(--namiru-header-bg);\n border-bottom: 1px solid var(--namiru-border);\n min-height: 52px;\n flex-shrink: 0;\n}\n\n.namiru-header-left {\n display: flex;\n align-items: center;\n gap: 12px;\n min-width: 0;\n}\n\n.namiru-header-avatar {\n width: 36px;\n height: 36px;\n border-radius: 10px;\n object-fit: cover;\n flex-shrink: 0;\n}\n\n.namiru-header-avatar-fallback {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.namiru-header-info {\n min-width: 0;\n}\n\n.namiru-header-name {\n font-weight: 600;\n font-size: 14px;\n color: var(--namiru-header-text);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.namiru-header-subtitle {\n font-size: 12px;\n color: var(--namiru-header-text-secondary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.namiru-header-actions {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.namiru-header-btn {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--namiru-header-text-secondary);\n padding: 4px;\n border-radius: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: color 0.15s, background 0.15s;\n}\n\n.namiru-header-btn:hover {\n color: var(--namiru-header-text);\n background: var(--namiru-bg-secondary);\n}\n\n.namiru-header-btn svg {\n width: 18px;\n height: 18px;\n}\n\n/* Messages area */\n.namiru-messages {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n padding: 16px calc(max(16px, (100% - 540px) / 2));\n display: flex;\n flex-direction: column;\n gap: 16px;\n background: var(--namiru-bg);\n}\n\n.namiru-messages::-webkit-scrollbar {\n width: 4px;\n}\n\n.namiru-messages::-webkit-scrollbar-thumb {\n background: var(--namiru-scroll-thumb);\n border-radius: 2px;\n}\n\n/* Message rows */\n.namiru-message-row {\n display: flex;\n gap: 12px;\n max-width: 100%;\n}\n\n.namiru-message-row--user {\n justify-content: flex-end;\n}\n\n.namiru-message-row--assistant {\n justify-content: flex-start;\n gap: 6px;\n}\n\n.namiru-message-icon {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: flex-end;\n justify-content: center;\n flex-shrink: 0;\n margin-top: 4px;\n}\n\n.namiru-message-icon svg {\n width: 20px;\n height: 20px;\n margin-top: 3px;\n}\n\n.namiru-message-avatar-img {\n width: 24px;\n height: 24px;\n border-radius: 6px;\n object-fit: cover;\n}\n\n/* Message bubbles */\n.namiru-message {\n max-width: 75%;\n font-size: var(--namiru-font-size);\n line-height: 1.6;\n word-wrap: break-word;\n white-space: pre-wrap;\n}\n\n.namiru-message--user {\n padding: 10px 16px;\n background: var(--namiru-user-msg-bg);\n color: var(--namiru-user-msg-text);\n border-radius: 1.25rem 1.25rem 0.25rem 1.25rem;\n}\n\n.namiru-message--user.namiru-bubble--rounded {\n border-radius: 1rem;\n}\n\n.namiru-message--user.namiru-bubble--square {\n border-radius: 0.25rem;\n}\n\n.namiru-message--assistant {\n color: var(--namiru-text)${_i};\n background: var(--namiru-agent-msg-bg)${_i};\n padding: 10px 8px${_i};\n border-radius: 0.75rem${_i};\n margin-top: 0${_i};\n}\n\n.namiru-message-row--welcome .namiru-message--assistant {\n margin-top: 4px${_i};\n}\n\n/* Input area - rounded pill style */\n.namiru-input-area {\n padding: 12px calc(max(10px, (100% - 540px) / 2)) 8px;\n flex-shrink: 0;\n background: var(--namiru-bg);\n}\n\n.namiru-input-row {\n display: flex;\n align-items: center;\n gap: 8px;\n border-radius: 9999px;\n border: 1px solid var(--namiru-border);\n background: var(--namiru-bg-secondary);\n padding: 6px 6px 6px 16px;\n}\n\n.namiru-input {\n flex: 1;\n border: none${_i};\n background: transparent${_i};\n font-size: 14px${_i};\n font-family: var(--namiru-font)${_i};\n outline: none${_i};\n resize: none${_i};\n max-height: 100px;\n line-height: 1.4${_i};\n color: var(--namiru-text)${_i};\n padding: 4px 0${_i};\n}\n\n.namiru-input::placeholder {\n color: var(--namiru-text-secondary)${_i};\n}\n\n.namiru-send-btn {\n width: 28px;\n height: 28px;\n border-radius: 50%;\n background: var(--namiru-button-bg);\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #ffffff;\n flex-shrink: 0;\n transition: background 0.15s, opacity 0.15s;\n}\n\n.namiru-send-btn:hover {\n background: var(--namiru-button-bg-hover);\n}\n\n.namiru-send-btn:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.namiru-send-btn svg {\n width: 14px;\n height: 14px;\n}\n\n/* Suggested questions */\n.namiru-suggestions {\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n max-width: 70%;\n margin-left: auto;\n gap: 8px;\n padding: 4px 0;\n}\n\n.namiru-suggestion-chip {\n font-size: 12px;\n padding: 6px 12px;\n border-radius: 9999px;\n border: 1px solid var(--namiru-border);\n background: var(--namiru-bg-secondary);\n color: var(--namiru-text);\n cursor: pointer;\n white-space: normal;\n font-family: var(--namiru-font);\n transition: border-color 0.15s, background 0.15s;\n text-align: right;\n}\n\n.namiru-suggestion-chip:hover {\n border-color: var(--namiru-primary);\n background: var(--namiru-bg);\n}\n\n/* Pre-chat form */\n.namiru-prechat {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 24px 20px;\n gap: 20px;\n}\n\n.namiru-prechat-question {\n font-size: 16px;\n font-weight: 600;\n text-align: center;\n color: var(--namiru-text);\n}\n\n.namiru-prechat-options {\n display: flex;\n flex-direction: column;\n gap: 10px;\n width: 100%;\n max-width: 300px;\n}\n\n.namiru-prechat-option {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n border: 1px solid var(--namiru-border);\n border-radius: 10px;\n background: var(--namiru-bg);\n cursor: pointer;\n font-size: 14px;\n font-family: var(--namiru-font);\n color: var(--namiru-text);\n transition: border-color 0.15s, background 0.15s;\n text-align: left;\n width: 100%;\n}\n\n.namiru-prechat-option:hover {\n border-color: var(--namiru-primary);\n background: var(--namiru-bg-secondary);\n}\n\n.namiru-prechat-option svg {\n width: 20px;\n height: 20px;\n flex-shrink: 0;\n color: var(--namiru-primary);\n}\n\n/* Feedback prompt */\n.namiru-feedback {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 10px;\n padding: 20px 20px 12px;\n margin: 12px auto;\n max-width: 540px;\n background: none;\n border: none;\n border-top: 1px solid var(--namiru-border);\n border-radius: 0;\n box-shadow: none;\n}\n\n.namiru-feedback-label {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: var(--namiru-text);\n opacity: 0.85;\n}\n\n.namiru-feedback-text {\n font-size: 13px;\n color: var(--namiru-text-secondary);\n text-align: center;\n line-height: 1.5;\n}\n\n.namiru-feedback-buttons {\n display: flex;\n gap: 12px;\n}\n\n.namiru-feedback-btn {\n width: 40px;\n height: 40px;\n border-radius: 10px;\n border: 1.5px solid var(--namiru-text-secondary);\n background: var(--namiru-bg);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.15s, border-color 0.15s, color 0.15s;\n color: var(--namiru-text-secondary);\n}\n\n.namiru-feedback-btn-up:hover {\n border-color: #22c55e;\n color: #22c55e;\n}\n\n.namiru-feedback-btn-down:hover {\n border-color: #ef4444;\n color: #ef4444;\n}\n\n.namiru-feedback-btn svg {\n width: 20px;\n height: 20px;\n}\n\n.namiru-feedback-thanks {\n font-size: 14px;\n color: var(--namiru-text);\n font-weight: 600;\n padding: 4px 0;\n}\n\n\n/* Email form */\n.namiru-email-form {\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding: 14px;\n margin: 8px 0;\n background: var(--namiru-bg-secondary);\n border-radius: 12px;\n}\n\n.namiru-email-form-text {\n font-size: 13px;\n color: var(--namiru-text-secondary);\n}\n\n.namiru-email-form-row {\n display: flex;\n gap: 8px;\n}\n\n.namiru-email-input {\n flex: 1;\n border: 1px solid var(--namiru-border);\n border-radius: 8px;\n padding: 8px 12px;\n font-size: 13px;\n font-family: var(--namiru-font);\n outline: none;\n background: var(--namiru-bg);\n color: var(--namiru-text);\n}\n\n.namiru-email-input:focus {\n border-color: var(--namiru-primary);\n}\n\n.namiru-email-submit {\n padding: 8px 16px;\n border: none;\n border-radius: 8px;\n background: var(--namiru-primary);\n color: #ffffff;\n font-size: 13px;\n font-family: var(--namiru-font);\n cursor: pointer;\n white-space: nowrap;\n transition: background 0.15s;\n}\n\n.namiru-email-submit:hover {\n background: var(--namiru-primary-hover);\n}\n\n.namiru-email-submit:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.namiru-email-sent {\n font-size: 13px;\n color: var(--namiru-primary);\n font-weight: 500;\n text-align: center;\n padding: 8px;\n}\n\n/* Loading dots */\n.namiru-loading {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 13px 8px;\n align-self: center;\n}\n\n.namiru-loading-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--namiru-text-secondary);\n animation: namiru-bounce 1.4s infinite ease-in-out;\n}\n\n.namiru-loading-dot:nth-child(1) { animation-delay: 0s; }\n.namiru-loading-dot:nth-child(2) { animation-delay: 0.16s; }\n.namiru-loading-dot:nth-child(3) { animation-delay: 0.32s; }\n\n@keyframes namiru-bounce {\n 0%, 80%, 100% { transform: scale(0); }\n 40% { transform: scale(1); }\n}\n\n/* Connecting indicator */\n.namiru-connecting {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1;\n min-height: 80px;\n}\n\n.namiru-loading-dots {\n display: flex;\n gap: 4px;\n}\n\n/* Powered by */\n.namiru-powered {\n text-align: center;\n padding: 4px 6px 12px;\n font-size: 10px;\n color: var(--namiru-text-secondary);\n flex-shrink: 0;\n background: var(--namiru-bg);\n}\n\n.namiru-powered a {\n color: var(--namiru-primary);\n text-decoration: none;\n font-weight: 600;\n}\n\n.namiru-powered a:hover {\n text-decoration: underline;\n}\n\n/* Greeting bubble */\n.namiru-greeting {\n position: fixed;\n background: var(--namiru-bg);\n color: var(--namiru-text);\n padding: 12px 36px 12px 16px;\n border-radius: 12px;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12), 0 1px 4px rgba(0, 0, 0, 0.08);\n border: 1px solid var(--namiru-border);\n max-width: 240px;\n font-family: var(--namiru-font);\n font-size: 14px;\n line-height: 1.4;\n z-index: 2147483647;\n cursor: pointer;\n transition: opacity 0.2s ease, transform 0.2s ease;\n}\n\n.namiru-greeting--bottom-right {\n bottom: 84px;\n right: 20px;\n}\n\n.namiru-greeting--bottom-left {\n bottom: 84px;\n left: 20px;\n}\n\n.namiru-greeting--hidden {\n opacity: 0;\n transform: translateY(4px);\n pointer-events: none;\n}\n\n.namiru-greeting-close {\n position: absolute;\n top: 6px;\n right: 8px;\n width: 20px;\n height: 20px;\n border: none;\n background: transparent;\n cursor: pointer;\n color: var(--namiru-text-secondary);\n font-size: 14px;\n line-height: 1;\n padding: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n}\n\n.namiru-greeting-close:hover {\n color: var(--namiru-text);\n background: var(--namiru-bg-secondary);\n}\n\n/* Classic bubble style */\n.namiru-button--classic {\n border-radius: 16px;\n width: 60px;\n height: 48px;\n}\n\n/* Contact form (email fallback) */\n.namiru-contact-form {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 20px;\n flex: 1;\n overflow-y: auto;\n}\n\n.namiru-contact-heading {\n font-size: 15px;\n font-weight: 500;\n color: var(--namiru-text);\n line-height: 1.5;\n text-align: center;\n padding-bottom: 4px;\n}\n\n.namiru-contact-label {\n font-size: 12px;\n font-weight: 500;\n color: var(--namiru-text-secondary);\n}\n\n.namiru-contact-input {\n border: 1px solid var(--namiru-border);\n border-radius: 8px;\n padding: 10px 12px;\n font-size: 14px;\n font-family: var(--namiru-font);\n outline: none;\n background: var(--namiru-bg);\n color: var(--namiru-text);\n width: 100%;\n}\n\n.namiru-contact-input:focus {\n border-color: var(--namiru-primary);\n}\n\n.namiru-contact-textarea {\n border: 1px solid var(--namiru-border);\n border-radius: 8px;\n padding: 10px 12px;\n font-size: 14px;\n font-family: var(--namiru-font);\n outline: none;\n background: var(--namiru-bg);\n color: var(--namiru-text);\n width: 100%;\n resize: vertical;\n min-height: 80px;\n}\n\n.namiru-contact-textarea:focus {\n border-color: var(--namiru-primary);\n}\n\n.namiru-contact-error {\n font-size: 12px;\n color: #ef4444;\n}\n\n.namiru-contact-submit {\n padding: 10px 20px;\n border: none;\n border-radius: 8px;\n background: var(--namiru-primary);\n color: #ffffff;\n font-size: 14px;\n font-weight: 500;\n font-family: var(--namiru-font);\n cursor: pointer;\n transition: background 0.15s;\n width: 100%;\n}\n\n.namiru-contact-submit:hover {\n background: var(--namiru-primary-hover);\n}\n\n.namiru-contact-submit:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.namiru-contact-confirmation {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1;\n font-size: 15px;\n font-weight: 500;\n color: var(--namiru-primary);\n text-align: center;\n padding: 20px;\n}\n\n/* Limit overlay */\n.namiru-limit-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 24px 20px;\n gap: 12px;\n background: var(--namiru-bg);\n z-index: 10;\n}\n\n.namiru-limit-icon {\n color: var(--namiru-text-secondary);\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.namiru-limit-icon--success {\n color: var(--namiru-primary);\n}\n\n.namiru-limit-heading {\n font-size: 16px;\n font-weight: 600;\n color: var(--namiru-text);\n text-align: center;\n}\n\n.namiru-limit-subtext {\n font-size: 13px;\n color: var(--namiru-text-secondary);\n text-align: center;\n line-height: 1.5;\n max-width: 280px;\n}\n\n.namiru-limit-form {\n display: flex;\n flex-direction: column;\n gap: 10px;\n width: 100%;\n max-width: 300px;\n margin-top: 4px;\n}\n\n.namiru-limit-textarea {\n border: 1px solid var(--namiru-border);\n border-radius: 8px;\n padding: 10px 12px;\n font-size: 14px;\n font-family: var(--namiru-font);\n outline: none;\n background: var(--namiru-bg-secondary);\n color: var(--namiru-text);\n width: 100%;\n resize: vertical;\n min-height: 80px;\n}\n\n.namiru-limit-textarea::placeholder {\n color: var(--namiru-text-secondary);\n}\n\n.namiru-limit-textarea:focus {\n border-color: var(--namiru-primary);\n}\n\n.namiru-limit-email {\n border: 1px solid var(--namiru-border);\n border-radius: 8px;\n padding: 10px 12px;\n font-size: 14px;\n font-family: var(--namiru-font);\n outline: none;\n background: var(--namiru-bg-secondary);\n color: var(--namiru-text);\n width: 100%;\n}\n\n.namiru-limit-email::placeholder {\n color: var(--namiru-text-secondary);\n}\n\n.namiru-limit-email:focus {\n border-color: var(--namiru-primary);\n}\n\n.namiru-limit-submit {\n padding: 10px 20px;\n border: none;\n border-radius: 8px;\n background: var(--namiru-primary);\n color: #ffffff;\n font-size: 14px;\n font-weight: 500;\n font-family: var(--namiru-font);\n cursor: pointer;\n transition: background 0.15s;\n width: 100%;\n}\n\n.namiru-limit-submit:hover {\n background: var(--namiru-primary-hover);\n}\n\n.namiru-limit-submit:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.namiru-limit-confirmation {\n font-size: 15px;\n font-weight: 500;\n color: var(--namiru-primary);\n text-align: center;\n padding: 8px;\n line-height: 1.5;\n}\n\n.namiru-limit-newchat {\n padding: 10px 20px;\n border: 1px solid var(--namiru-border);\n border-radius: 8px;\n background: transparent;\n color: var(--namiru-text);\n font-size: 14px;\n font-weight: 500;\n font-family: var(--namiru-font);\n cursor: pointer;\n transition: background 0.15s;\n width: 100%;\n max-width: 300px;\n margin-top: 4px;\n}\n\n.namiru-limit-newchat:hover {\n background: var(--namiru-bg-secondary);\n}\n\n/* Mobile responsive */\n@media (max-width: 480px) {\n .namiru-popup {\n width: 100vw;\n height: 100vh;\n bottom: 0${_i};\n right: 0${_i};\n left: 0${_i};\n border-radius: 0;\n }\n .namiru-button {\n width: 48px;\n height: 48px;\n }\n .namiru-greeting {\n max-width: calc(100vw - 80px);\n }\n .namiru-greeting--bottom-right,\n .namiru-greeting--bottom-left {\n bottom: 76px;\n }\n}\n\n/* ---- Markdown styles for bot messages ---- */\n.namiru-md,\n.namiru-md *,\n.namiru-md p,\n.namiru-md span,\n.namiru-md li {\n color: var(--namiru-text)${_i};\n}\n\n.namiru-md p {\n margin: 0 0 0.5em 0${_i};\n display: block${_i};\n visibility: visible${_i};\n}\n.namiru-md p:last-child {\n margin-bottom: 0;\n}\n.namiru-md strong {\n font-weight: 700${_i};\n display: inline${_i};\n visibility: visible${_i};\n font-size: inherit${_i};\n opacity: 1${_i};\n}\n.namiru-md em {\n font-style: italic${_i};\n display: inline${_i};\n visibility: visible${_i};\n font-size: inherit${_i};\n opacity: 1${_i};\n}\n.namiru-md a.namiru-md-link {\n color: var(--namiru-primary)${_i};\n text-decoration: underline${_i};\n display: inline${_i};\n visibility: visible${_i};\n}\n.namiru-md a.namiru-md-link:hover {\n opacity: 0.8;\n}\n.namiru-md .namiru-md-code {\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 0.9em;\n background: rgba(0, 0, 0, 0.06);\n padding: 0.15em 0.4em;\n border-radius: 0.25rem;\n}\n.namiru-md .namiru-md-pre {\n background: #1e1e2e;\n color: #cdd6f4;\n padding: 0.75rem 1rem;\n border-radius: 0.5rem;\n overflow-x: auto;\n margin: 0.5em 0;\n font-size: 0.85em;\n}\n.namiru-md .namiru-md-pre code {\n background: transparent;\n padding: 0;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n}\n.namiru-md .namiru-md-ul,\n.namiru-md .namiru-md-ol {\n margin: 0.4em 0;\n padding-left: 1.5em;\n}\n.namiru-md .namiru-md-ul {\n list-style: disc;\n}\n.namiru-md .namiru-md-ol {\n list-style: decimal;\n}\n.namiru-md li {\n margin: 0.2em 0;\n display: list-item${_i};\n visibility: visible${_i};\n}\n.namiru-md .namiru-md-hr {\n border: none;\n border-top: 1px solid rgba(0,0,0,0.1);\n margin: 0.6em 0;\n}\n`;\n}\n\nfunction adjustBrightness(hex: string, amount: number): string {\n const cleaned = hex.replace(\"#\", \"\");\n const num = parseInt(cleaned, 16);\n if (isNaN(num) || cleaned.length < 6) return hex;\n const r = Math.max(0, Math.min(255, ((num >> 16) & 0xff) + amount));\n const g = Math.max(0, Math.min(255, ((num >> 8) & 0xff) + amount));\n const b = Math.max(0, Math.min(255, (num & 0xff) + amount));\n return `#${((r << 16) | (g << 8) | b).toString(16).padStart(6, \"0\")}`;\n}", "import { hasShadowDom } from \"./env\";\n\n/**\n * Lightweight markdown-to-HTML converter for the embeddable chat widget.\n *\n * Supports: **bold**, *italic*, `inline code`, ```code blocks```,\n * [links](url), unordered lists (- / *), ordered lists (1.), and line breaks.\n *\n * Bot messages only -- user messages should remain plain text.\n *\n * Security: output is set via innerHTML so we escape all HTML entities first,\n * then apply markdown transformations on the escaped string.\n */\n\nfunction escapeHtml(text: string): string {\n return text\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\");\n}\n\nexport function renderMarkdown(raw: string): string {\n // Escape HTML entities first to prevent XSS\n let text = escapeHtml(raw);\n\n // Replace em dashes with commas\n text = text.replace(/\\u2014/g, \", \");\n\n // Fenced code blocks: ```lang\\n...\\n```\n text = text.replace(\n /```(?:\\w*)\\n([\\s\\S]*?)```/g,\n '<pre class=\"namiru-md-pre\"><code>$1</code></pre>',\n );\n\n // Inline code: `code`\n text = text.replace(\n /`([^`\\n]+)`/g,\n '<code class=\"namiru-md-code\">$1</code>',\n );\n\n // Bold + italic: ***text*** or ___text___\n text = text.replace(\n /\\*\\*\\*(.+?)\\*\\*\\*/g,\n \"<strong><em>$1</em></strong>\",\n );\n\n // Bold: **text** or __text__\n text = text.replace(/\\*\\*(.+?)\\*\\*/g, \"<strong>$1</strong>\");\n text = text.replace(/__(.+?)__/g, \"<strong>$1</strong>\");\n\n // Italic: *text* or _text_ (but not inside words for _)\n text = text.replace(/\\*(.+?)\\*/g, \"<em>$1</em>\");\n text = text.replace(/(^|[\\s(])_(.+?)_([\\s).,!?]|$)/gm, \"$1<em>$2</em>$3\");\n\n // Links: [text](url)\n text = text.replace(\n /\\[([^\\]]+)\\]\\(([^)]+)\\)/g,\n '<a href=\"$2\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"namiru-md-link\">$1</a>',\n );\n\n // Horizontal rules: ---, ***, ___ (3+ chars, optionally with spaces)\n // Convert to a subtle visual break\n text = text.replace(/^[ \\t]*([-*_])\\s*\\1\\s*\\1[\\s\\-*_]*$/gm, '<hr class=\"namiru-md-hr\">');\n\n // Process line-by-line for lists and paragraphs\n const lines = text.split(\"\\n\");\n const result: string[] = [];\n let inUl = false;\n let inOl = false;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n\n // Skip already-converted horizontal rules (treat as block element)\n if (line.includes('<hr class=\"namiru-md-hr\">')) {\n if (inUl) { result.push(\"</ul>\"); inUl = false; }\n if (inOl) { result.push(\"</ol>\"); inOl = false; }\n result.push(line);\n continue;\n }\n\n const ulMatch = line.match(/^(\\s*)[-*]\\s+(.*)/);\n const olMatch = line.match(/^(\\s*)\\d+\\.\\s+(.*)/);\n\n if (ulMatch) {\n if (!inUl) {\n if (inOl) { result.push(\"</ol>\"); inOl = false; }\n result.push('<ul class=\"namiru-md-ul\">');\n inUl = true;\n }\n result.push(`<li>${ulMatch[2]}</li>`);\n } else if (olMatch) {\n if (!inOl) {\n if (inUl) { result.push(\"</ul>\"); inUl = false; }\n result.push('<ol class=\"namiru-md-ol\">');\n inOl = true;\n }\n result.push(`<li>${olMatch[2]}</li>`);\n } else {\n if (inUl) { result.push(\"</ul>\"); inUl = false; }\n if (inOl) { result.push(\"</ol>\"); inOl = false; }\n\n // Skip empty lines but preserve spacing\n if (line.trim() === \"\") {\n result.push(\"\");\n } else {\n result.push(line);\n }\n }\n }\n\n if (inUl) result.push(\"</ul>\");\n if (inOl) result.push(\"</ol>\");\n\n // Build HTML from result blocks, avoiding <br> inside lists\n let html = \"\";\n let insideList = false;\n\n for (const item of result) {\n if (item.includes(\"<hr\")) {\n html += item;\n } else if (item.startsWith(\"<ul\") || item.startsWith(\"<ol\")) {\n insideList = true;\n html += item;\n } else if (item === \"</ul>\" || item === \"</ol>\") {\n insideList = false;\n html += item;\n } else if (item.startsWith(\"<li>\")) {\n html += item;\n } else if (item.trim() === \"\") {\n // Empty line = paragraph break (only outside lists)\n if (!insideList) html += \"</p><p>\";\n } else {\n // Regular text line\n if (html.length > 0 && !insideList && !html.endsWith(\"<p>\") && !html.endsWith(\"</ul>\") && !html.endsWith(\"</ol>\") && !html.endsWith(\"</pre>\")) {\n html += \"<br>\";\n }\n html += item;\n }\n }\n\n // Wrap in paragraph if not starting with a block element\n if (!html.startsWith(\"<ul\") && !html.startsWith(\"<ol\") && !html.startsWith(\"<pre\")) {\n html = `<p>${html}</p>`;\n }\n\n // Clean up empty paragraphs\n html = html.replace(/<p>\\s*<\\/p>/g, \"\");\n\n // Clean up paragraphs wrapping block elements\n html = html.replace(/<p>(<(?:ul|ol|pre|hr)[^>]*>)/g, \"$1\");\n html = html.replace(/(<\\/(?:ul|ol|pre)>)<\\/p>/g, \"$1\");\n html = html.replace(/(<hr[^>]*>)<\\/p>/g, \"$1\");\n\n // When inside Shadow DOM, plain styles suffice. In fallback mode, !important\n // is needed to resist host-page CSS bleed-through.\n const i = hasShadowDom ? \"\" : \" !important\";\n html = html.replace(/<p>/g, `<p style=\"color: var(--namiru-text)${i}; margin: 0 0 0.5em 0${i}; max-width: 100%${i}; word-wrap: break-word${i}; display: block${i}; visibility: visible${i};\">`);\n html = html.replace(/<li>/g, `<li style=\"color: var(--namiru-text)${i}; margin: 0.2em 0${i}; display: list-item${i}; visibility: visible${i};\">`);\n html = html.replace(/<strong>/g, `<strong style=\"color: var(--namiru-text)${i}; font-weight: 700${i}; display: inline${i}; visibility: visible${i}; font-size: inherit${i}; opacity: 1${i};\">`);\n html = html.replace(/<em>/g, `<em style=\"color: var(--namiru-text)${i}; font-style: italic${i}; display: inline${i}; visibility: visible${i}; font-size: inherit${i}; opacity: 1${i};\">`);\n html = html.replace(/<a href=/g, `<a style=\"color: var(--namiru-primary)${i}; text-decoration: underline${i}; display: inline${i}; visibility: visible${i};\" href=`);\n\n return html;\n}\n", "// SVG icons created via DOM API (Phosphor-style)\n// Never uses innerHTML for security\n\nfunction createSvg(paths: string[], viewBox = \"0 0 256 256\"): SVGElement {\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.setAttribute(\"viewBox\", viewBox);\n svg.setAttribute(\"fill\", \"currentColor\");\n svg.setAttribute(\"xmlns\", \"http://www.w3.org/2000/svg\");\n\n for (const d of paths) {\n const path = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n path.setAttribute(\"d\", d);\n svg.appendChild(path);\n }\n\n return svg;\n}\n\nexport function headerBotIcon(fill?: string): SVGElement {\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.setAttribute(\"viewBox\", \"0 0 256 256\");\n svg.setAttribute(\"xmlns\", \"http://www.w3.org/2000/svg\");\n svg.setAttribute(\"width\", \"18\");\n svg.setAttribute(\"height\", \"18\");\n if (fill) svg.setAttribute(\"fill\", fill);\n else svg.setAttribute(\"fill\", \"currentColor\");\n\n // Phosphor Headset icon\n const path = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n path.setAttribute(\n \"d\",\n \"M201.89,54.66A103.43,103.43,0,0,0,128.79,24H128A104,104,0,0,0,24,128v56a24,24,0,0,0,24,24H64a24,24,0,0,0,24-24V144a24,24,0,0,0-24-24H40.36A88,88,0,0,1,128,40h.67a87.71,87.71,0,0,1,87,80H192a24,24,0,0,0-24,24v40a24,24,0,0,0,24,24h8a8,8,0,0,0,0-16h-8a8,8,0,0,1-8-8V144a8,8,0,0,1,8-8h24a8,8,0,0,1,8,8v56a40,40,0,0,1-40,40H152a8,8,0,0,0,0,16h32a56.06,56.06,0,0,0,56-56V128A103.41,103.41,0,0,0,201.89,54.66ZM64,136a8,8,0,0,1,8,8v40a8,8,0,0,1-8,8H48a8,8,0,0,1-8-8V136Z\"\n );\n svg.appendChild(path);\n return svg;\n}\n\nexport function namiruBirdIcon(fill?: string): SVGElement {\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.setAttribute(\"viewBox\", \"0 0 256 256\");\n svg.setAttribute(\"xmlns\", \"http://www.w3.org/2000/svg\");\n svg.setAttribute(\"width\", \"20\");\n svg.setAttribute(\"height\", \"20\");\n if (fill) svg.setAttribute(\"fill\", fill);\n else svg.setAttribute(\"fill\", \"currentColor\");\n\n // Phosphor Headset icon (same as headerBotIcon)\n const path = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n path.setAttribute(\n \"d\",\n \"M201.89,54.66A103.43,103.43,0,0,0,128.79,24H128A104,104,0,0,0,24,128v56a24,24,0,0,0,24,24H64a24,24,0,0,0,24-24V144a24,24,0,0,0-24-24H40.36A88,88,0,0,1,128,40h.67a87.71,87.71,0,0,1,87,80H192a24,24,0,0,0-24,24v40a24,24,0,0,0,24,24h8a8,8,0,0,0,0-16h-8a8,8,0,0,1-8-8V144a8,8,0,0,1,8-8h24a8,8,0,0,1,8,8v56a40,40,0,0,1-40,40H152a8,8,0,0,0,0,16h32a56.06,56.06,0,0,0,56-56V128A103.41,103.41,0,0,0,201.89,54.66ZM64,136a8,8,0,0,1,8,8v40a8,8,0,0,1-8,8H48a8,8,0,0,1-8-8V136Z\"\n );\n svg.appendChild(path);\n return svg;\n}\n\nexport function paperPlaneIcon(): SVGElement {\n return createSvg([\n \"M236.2,218.31A8,8,0,0,1,228,224a7.8,7.8,0,0,1-2.31-.34L160,205.42l-65.69,18.24a7.8,7.8,0,0,1-2.31.34,8,8,0,0,1-7.26-4.67,7.82,7.82,0,0,1-.58-1.39L32.76,72.8l0-.13A16,16,0,0,1,55.39,56.32l0,.13L236.54,210a8,8,0,0,1-.34,8.31ZM55.08,63.83,160,186.17V136L63.77,57Z\",\n ]);\n}\n\nexport function chatBubbleIcon(): SVGElement {\n return createSvg([\n \"M128,24A104,104,0,0,0,36.18,176.88L24.83,210.93a16,16,0,0,0,20.24,20.24l34.05-11.35A104,104,0,1,0,128,24Zm0,192a88.11,88.11,0,0,1-44.06-11.81,8,8,0,0,0-4-1.08,7.85,7.85,0,0,0-2.53.42L40,216l12.47-37.41a8,8,0,0,0-.66-6.54A88,88,0,1,1,128,216Z\",\n ]);\n}\n\nexport function closeIcon(): SVGElement {\n return createSvg([\n \"M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z\",\n ]);\n}\n\nexport function sendIcon(): SVGElement {\n // Phosphor PaperPlaneRight fill - matches preview PaperPlaneRight weight=\"fill\"\n return createSvg([\n \"M240,127.89a16,16,0,0,1-8.18,14L63.9,237.9A16.15,16.15,0,0,1,56,240a16,16,0,0,1-15-21.33l27-79.95A4,4,0,0,1,71.72,136H144a8,8,0,0,0,8-8.53,8.19,8.19,0,0,0-8.26-7.47h-72a4,4,0,0,1-3.79-2.72l-27-79.94A16,16,0,0,1,63.84,18.07l168,95.89A16,16,0,0,1,240,127.89Z\",\n ]);\n}\n\nexport function thumbsUpIcon(): SVGElement {\n return createSvg([\n \"M234,80.12A24,24,0,0,0,216,72H160V56a40,40,0,0,0-40-40,8,8,0,0,0-7.16,4.42L75.06,96H32a16,16,0,0,0-16,16v88a16,16,0,0,0,16,16H204a24,24,0,0,0,23.82-21.12l12-96A24,24,0,0,0,234,80.12ZM32,112H72v88H32ZM223.94,97l-12,96a8,8,0,0,1-7.94,7H88V105.89l36.71-73.43A24,24,0,0,1,144,56V80a8,8,0,0,0,8,8h64a8,8,0,0,1,7.94,9Z\",\n ]);\n}\n\nexport function thumbsDownIcon(): SVGElement {\n return createSvg([\n \"M239.82,157l-12-96A24,24,0,0,0,204,40H32A16,16,0,0,0,16,56v88a16,16,0,0,0,16,16H75.06l37.78,75.58A8,8,0,0,0,120,240a40,40,0,0,0,40-40V184h56a24,24,0,0,0,23.82-27ZM72,144H32V56H72Zm150,21.29a8,8,0,0,1-6,2.71H152a8,8,0,0,0-8,8v24a24,24,0,0,1-19.29,23.54L88,150.11V56H204a8,8,0,0,1,7.94,7l12,96A8,8,0,0,1,222,165.29Z\",\n ]);\n}\n\nexport function emailIcon(): SVGElement {\n return createSvg([\n \"M224,48H32a8,8,0,0,0-8,8V192a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A8,8,0,0,0,224,48ZM203.43,64,128,133.15,52.57,64ZM216,192H40V74.19l82.59,75.71a8,8,0,0,0,10.82,0L216,74.19V192Z\",\n ]);\n}\n\nexport function shoppingBagIcon(): SVGElement {\n return createSvg([\n \"M216,64H176a48,48,0,0,0-96,0H40A16,16,0,0,0,24,80V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V80A16,16,0,0,0,216,64ZM128,32a32,32,0,0,1,32,32H96A32,32,0,0,1,128,32Zm88,168H40V80H80V96a8,8,0,0,0,16,0V80h64V96a8,8,0,0,0,16,0V80h40Z\",\n ]);\n}\n\nexport function packageIcon(): SVGElement {\n return createSvg([\n \"M223.68,66.15,135.68,18a15.88,15.88,0,0,0-15.36,0l-88,48.17a16,16,0,0,0-8.32,14v95.64a16,16,0,0,0,8.32,14l88,48.17a15.88,15.88,0,0,0,15.36,0l88-48.17a16,16,0,0,0,8.32-14V80.18A16,16,0,0,0,223.68,66.15ZM128,32l80.34,44-29.77,16.3-80.35-44ZM128,120,47.66,76l33.9-18.56,80.34,44ZM40,90l80,43.78v85.79L40,175.82Zm96,129.57V133.82L216,90v85.78Z\",\n ]);\n}\n\nexport function creditCardIcon(): SVGElement {\n return createSvg([\n \"M224,48H32A16,16,0,0,0,16,64V192a16,16,0,0,0,16,16H224a16,16,0,0,0,16-16V64A16,16,0,0,0,224,48Zm0,16V88H32V64ZM32,192V104H224v88Zm16-24a8,8,0,0,1,8-8H96a8,8,0,0,1,0,16H56A8,8,0,0,1,48,168Zm0-32a8,8,0,0,1,8-8h64a8,8,0,0,1,0,16H56A8,8,0,0,1,48,136Z\",\n ]);\n}\n\nexport function chatCircleIcon(): SVGElement {\n return createSvg([\n \"M128,24A104,104,0,0,0,36.18,176.88L24.83,210.93a16,16,0,0,0,20.24,20.24l34.05-11.35A104,104,0,1,0,128,24Zm0,192a88.11,88.11,0,0,1-44.06-11.81,8,8,0,0,0-4-1.08,7.85,7.85,0,0,0-2.53.42L40,216l12.47-37.41a8,8,0,0,0-.66-6.54A88,88,0,1,1,128,216Z\",\n ]);\n}\n\nexport function rocketIcon(): SVGElement {\n return createSvg([\n \"M152,224a8,8,0,0,1-8,8H112a8,8,0,0,1,0-16h32A8,8,0,0,1,152,224Zm73.69-142.23-21.34-21.35C183.42,39.49,156.58,24,128,24s-55.42,15.49-76.35,36.42L30.31,81.77a16,16,0,0,0,0,22.63L64,138.09V184a16,16,0,0,0,4.69,11.31l24,24A16,16,0,0,0,104,224h48a16,16,0,0,0,11.31-4.69l24-24A16,16,0,0,0,192,184V138.09l33.69-33.69A16,16,0,0,0,225.69,81.77ZM128,40c22.59,0,43.85,12.28,60,32H68C84.15,52.28,105.41,40,128,40Zm48,144-24,24H104L80,184V88H176Zm36.28-79.6L192,172.69V88h17.94l4.34,4.34A.64.64,0,0,1,212.28,104.4ZM64,172.69,45.66,104.4a.64.64,0,0,1-2,0L48,100H64Z\",\n ]);\n}\n\nexport function wrenchIcon(): SVGElement {\n return createSvg([\n \"M226.76,69a8,8,0,0,0-12.84-2.88l-40.3,37.19-17.23-3.7-3.7-17.23,37.19-40.3A8,8,0,0,0,187,29.24,72,72,0,0,0,88,96c0,1.3,0,2.6.1,3.89L33.19,147.68a27.7,27.7,0,0,0,0,39.37l36.76,36.76a27.7,27.7,0,0,0,39.37,0l47.79-54.91c1.29.06,2.59.1,3.89.1a72,72,0,0,0,66.76-99ZM148.49,212.49a11.7,11.7,0,0,1-16.57,0L95.16,175.73a8,8,0,0,0-11.58.28L44.49,220.49a11.7,11.7,0,0,1-16.57,0L44.49,204a11.69,11.69,0,0,1,0-16.57l44.48-39.09a8,8,0,0,0,.28-11.58L52.49,100.05a56,56,0,0,1,89.36-63.58l-31.41,34a8,8,0,0,0-1.8,6.49l6,27.92a8,8,0,0,0,6.13,6.13l27.92,6a8,8,0,0,0,6.49-1.8l34-31.41A56,56,0,0,1,148.49,212.49Z\",\n ]);\n}\n\nexport function briefcaseIcon(): SVGElement {\n return createSvg([\n \"M216,56H176V48a24,24,0,0,0-24-24H104A24,24,0,0,0,80,48v8H40A16,16,0,0,0,24,72V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V72A16,16,0,0,0,216,56ZM96,48a8,8,0,0,1,8-8h48a8,8,0,0,1,8,8v8H96ZM216,72v72H40V72Zm0,128H40V160H216v40Z\",\n ]);\n}\n\nexport function userCircleIcon(): SVGElement {\n return createSvg([\n \"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24ZM74.08,197.5a64,64,0,0,1,107.84,0,87.83,87.83,0,0,1-107.84,0ZM96,120a32,32,0,1,1,32,32A32,32,0,0,1,96,120Zm97.76,66.41a79.66,79.66,0,0,0-36.06-28.75,48,48,0,1,0-59.4,0,79.66,79.66,0,0,0-36.06,28.75,88,88,0,1,1,131.52,0Z\",\n ]);\n}\n\nexport function dotsThreeIcon(): SVGElement {\n return createSvg([\n \"M140,128a12,12,0,1,1-12-12A12,12,0,0,1,140,128Zm56-12a12,12,0,1,0,12,12A12,12,0,0,0,196,116ZM60,116a12,12,0,1,0,12,12A12,12,0,0,0,60,116Z\",\n ]);\n}\n\nexport function transcriptIcon(): SVGElement {\n return createSvg([\n \"M213.66,82.34l-56-56A8,8,0,0,0,152,24H56A16,16,0,0,0,40,40V216a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V88A8,8,0,0,0,213.66,82.34ZM160,51.31,188.69,80H160ZM200,216H56V40h88V88a8,8,0,0,0,8,8h48V216Zm-32-80a8,8,0,0,1-8,8H96a8,8,0,0,1,0-16h64A8,8,0,0,1,168,136Zm0,32a8,8,0,0,1-8,8H96a8,8,0,0,1,0-16h64A8,8,0,0,1,168,168Z\",\n ]);\n}\n\nexport function newChatIcon(): SVGElement {\n // Chat bubble with a plus sign (Phosphor ChatPlus style)\n return createSvg([\n \"M216,48H40A16,16,0,0,0,24,64V224a15.84,15.84,0,0,0,9.25,14.5A16.05,16.05,0,0,0,40,240a15.89,15.89,0,0,0,10.25-3.78.69.69,0,0,0,.13-.11L92.69,200H216a16,16,0,0,0,16-16V64A16,16,0,0,0,216,48ZM216,184H92.69a15.86,15.86,0,0,0-10.31,3.78l-.12.11L40,224V64H216ZM152,128a8,8,0,0,1-8,8H136v8a8,8,0,0,1-16,0v-8H112a8,8,0,0,1,0-16h8v-8a8,8,0,0,1,16,0v8h8A8,8,0,0,1,152,128Z\",\n ]);\n}\n\nexport function openInNewWindowIcon(): SVGElement {\n // ArrowSquareOut (Phosphor) - open in new window\n return createSvg([\n \"M224,104a8,8,0,0,1-16,0V59.32l-66.33,66.34a8,8,0,0,1-11.32-11.32L196.68,48H152a8,8,0,0,1,0-16h64a8,8,0,0,1,8,8Zm-40,24a8,8,0,0,0-8,8v72H48V80h72a8,8,0,0,0,0-16H48A16,16,0,0,0,32,80V208a16,16,0,0,0,16,16H176a16,16,0,0,0,16-16V136A8,8,0,0,0,184,128Z\",\n ]);\n}\n\n// Map icon name strings to icon functions\nconst iconMap: Record<string, () => SVGElement> = {\n ShoppingBag: shoppingBagIcon,\n Package: packageIcon,\n CreditCard: creditCardIcon,\n ChatCircle: chatCircleIcon,\n Rocket: rocketIcon,\n Wrench: wrenchIcon,\n Briefcase: briefcaseIcon,\n UserCircle: userCircleIcon,\n DotsThree: dotsThreeIcon,\n};\n\nexport function getIconByName(name: string): SVGElement {\n const factory = iconMap[name];\n if (factory) return factory();\n return chatCircleIcon();\n}\n", "import { ChatStore } from \"../../core/state-machine\";\nimport type { AgentBrandingData } from \"../../core/types\";\nimport { closeIcon, transcriptIcon, headerBotIcon, newChatIcon, openInNewWindowIcon } from \"../icons\";\n\nexport interface ChatHeaderOptions {\n store: ChatStore;\n branding: AgentBrandingData;\n mode: \"button\" | \"inline\";\n onTranscriptClick?: () => void;\n onNewChat?: () => void;\n feedbackEnabled?: boolean;\n}\n\nfunction hexToRgb(hex: string): string {\n let c = hex.replace(\"#\", \"\");\n if (c.length === 3) {\n c = c[0] + c[0] + c[1] + c[1] + c[2] + c[2];\n }\n if (c.length < 6 || !/^[0-9a-fA-F]{6}/.test(c)) return \"74, 127, 255\";\n const r = parseInt(c.substring(0, 2), 16);\n const g = parseInt(c.substring(2, 4), 16);\n const b = parseInt(c.substring(4, 6), 16);\n return `${r}, ${g}, ${b}`;\n}\n\nexport function createChatHeader(options: ChatHeaderOptions): HTMLElement {\n const { store, branding, mode, onTranscriptClick, onNewChat, feedbackEnabled } = options;\n\n // If showHeader is explicitly false, return an empty hidden element\n if (branding.showHeader === false) {\n const empty = document.createElement(\"div\");\n empty.style.display = \"none\";\n return empty;\n }\n\n const header = document.createElement(\"div\");\n header.className = \"namiru-header\";\n\n // Left side: avatar + name/subtitle\n const left = document.createElement(\"div\");\n left.className = \"namiru-header-left\";\n\n const primaryRgb = hexToRgb(branding.primaryColor);\n\n if (branding.agentAvatar || branding.logoUrl) {\n const avatar = document.createElement(\"img\");\n avatar.className = \"namiru-header-avatar\";\n avatar.src = (branding.agentAvatar || branding.logoUrl)!;\n avatar.alt = branding.name;\n left.appendChild(avatar);\n } else {\n // Fallback: headset icon in a tinted box\n const fallback = document.createElement(\"div\");\n fallback.className = \"namiru-header-avatar-fallback\";\n fallback.style.background = `rgba(${primaryRgb}, 0.06)`;\n fallback.style.border = `none`;\n // Use custom iconColor if set, otherwise derive from theme\n const isDark = branding.presetTheme === \"dark\";\n const iconFill = branding.iconColor || (isDark ? \"#ffffff\" : branding.primaryColor);\n const icon = headerBotIcon(iconFill);\n fallback.appendChild(icon);\n left.appendChild(fallback);\n }\n\n const info = document.createElement(\"div\");\n info.className = \"namiru-header-info\";\n\n const name = document.createElement(\"div\");\n name.className = \"namiru-header-name\";\n name.textContent = branding.headerTitle || branding.name;\n info.appendChild(name);\n\n if (branding.headerSubtitle) {\n const subtitle = document.createElement(\"div\");\n subtitle.className = \"namiru-header-subtitle\";\n subtitle.textContent = branding.headerSubtitle;\n info.appendChild(subtitle);\n }\n\n left.appendChild(info);\n header.appendChild(left);\n\n // Right side: actions\n const actions = document.createElement(\"div\");\n actions.className = \"namiru-header-actions\";\n\n // Close button (only in button/popup mode)\n if (mode === \"button\") {\n const closeBtn = document.createElement(\"button\");\n closeBtn.className = \"namiru-header-btn\";\n closeBtn.setAttribute(\"aria-label\", \"Close chat\");\n closeBtn.appendChild(closeIcon());\n closeBtn.addEventListener(\"click\", () => {\n const currentState = store.getState();\n // Show feedback prompt on close if enabled, not yet given, and conversation happened\n if (\n feedbackEnabled &&\n !currentState.feedbackGiven &&\n currentState.state === \"chatting\" &&\n currentState.messages.length > 0\n ) {\n store.dispatch({ type: \"SET_STATE\", state: \"feedback\" });\n return;\n }\n // No messages yet: close immediately without confirmation\n if (currentState.messages.length === 0) {\n store.dispatch({ type: \"SET_OPEN\", isOpen: false });\n return;\n }\n // Has messages: show confirmation modal\n showCloseConfirmation(header, store);\n });\n actions.appendChild(closeBtn);\n }\n\n header.appendChild(actions);\n\n return header;\n}\n\nexport function showCloseConfirmation(headerEl: HTMLElement, store: ChatStore): void {\n // Find the chat window container (parent of header)\n const container = headerEl.parentElement;\n if (!container) {\n store.dispatch({ type: \"SET_OPEN\", isOpen: false });\n return;\n }\n\n // Prevent duplicate modals\n if (container.querySelector(\".namiru-close-confirm-overlay\")) return;\n\n const overlay = document.createElement(\"div\");\n overlay.className = \"namiru-close-confirm-overlay\";\n overlay.style.cssText =\n \"position:absolute;inset:0;z-index:50;display:flex;align-items:center;justify-content:center;padding:16px;background:rgba(0,0,0,0.35);backdrop-filter:blur(2px);animation:namiruConfirmFade 0.15s ease-out;\";\n\n const card = document.createElement(\"div\");\n card.style.cssText =\n \"background:var(--namiru-bg,#fff);border-radius:8px;border:1px solid var(--namiru-border,#e5e7eb);box-shadow:0 8px 24px rgba(0,0,0,0.12);padding:20px;width:100%;max-width:280px;animation:namiruConfirmSlide 0.2s cubic-bezier(0.16,1,0.3,1);\";\n\n const title = document.createElement(\"div\");\n title.style.cssText = \"font-size:14px;font-weight:600;color:var(--namiru-text,#1f2937);margin-bottom:4px;\";\n title.textContent = \"End conversation?\";\n card.appendChild(title);\n\n const subtitle = document.createElement(\"div\");\n subtitle.style.cssText = \"font-size:13px;color:var(--namiru-text-secondary,#6b7280);line-height:1.4;margin-bottom:16px;\";\n subtitle.textContent = \"We've received your message. Your chat history will not be saved.\";\n card.appendChild(subtitle);\n\n const btnRow = document.createElement(\"div\");\n btnRow.style.cssText = \"display:flex;gap:8px;\";\n\n const cancelBtn = document.createElement(\"button\");\n cancelBtn.style.cssText =\n \"flex:1;padding:8px 12px;border-radius:6px;font-size:13px;font-weight:500;cursor:pointer;border:1px solid var(--namiru-border,#e5e7eb);background:var(--namiru-bg,#fff);color:var(--namiru-text,#1f2937);transition:background 0.15s;\";\n cancelBtn.textContent = \"Cancel\";\n cancelBtn.addEventListener(\"mouseenter\", () => {\n cancelBtn.style.background = \"var(--namiru-bg-secondary,#f3f4f6)\";\n });\n cancelBtn.addEventListener(\"mouseleave\", () => {\n cancelBtn.style.background = \"var(--namiru-bg,#fff)\";\n });\n cancelBtn.addEventListener(\"click\", () => overlay.remove());\n\n const endBtn = document.createElement(\"button\");\n endBtn.style.cssText =\n \"flex:1;padding:8px 12px;border-radius:6px;font-size:13px;font-weight:500;cursor:pointer;border:none;background:var(--namiru-text,#1f2937);color:var(--namiru-bg,#fff);transition:opacity 0.15s;\";\n endBtn.textContent = \"End chat\";\n endBtn.addEventListener(\"mouseenter\", () => {\n endBtn.style.opacity = \"0.85\";\n });\n endBtn.addEventListener(\"mouseleave\", () => {\n endBtn.style.opacity = \"1\";\n });\n endBtn.addEventListener(\"click\", () => {\n overlay.remove();\n store.dispatch({ type: \"RESET\" });\n store.dispatch({ type: \"SET_OPEN\", isOpen: false });\n });\n\n btnRow.appendChild(cancelBtn);\n btnRow.appendChild(endBtn);\n card.appendChild(btnRow);\n overlay.appendChild(card);\n\n // Click backdrop to cancel\n overlay.addEventListener(\"click\", (e) => {\n if (e.target === overlay) overlay.remove();\n });\n\n // Inject keyframe animations\n if (!container.querySelector(\"style[data-namiru-confirm]\")) {\n const style = document.createElement(\"style\");\n style.setAttribute(\"data-namiru-confirm\", \"\");\n style.textContent = `\n @keyframes namiruConfirmFade { from { opacity: 0; } to { opacity: 1; } }\n @keyframes namiruConfirmSlide { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }\n `;\n container.appendChild(style);\n }\n\n container.appendChild(overlay);\n}\n", "import { hasShadowDom } from \"../../core/env\";\nimport { sendIcon } from \"../icons\";\n\nexport interface ChatInputOptions {\n onSend: (content: string) => void;\n}\n\nexport function createChatInput(options: ChatInputOptions): HTMLElement {\n const { onSend } = options;\n\n const area = document.createElement(\"div\");\n area.className = \"namiru-input-area\";\n\n const row = document.createElement(\"div\");\n row.className = \"namiru-input-row\";\n\n const input = document.createElement(\"textarea\");\n input.className = \"namiru-input\";\n input.placeholder = \"Type your message...\";\n input.rows = 1;\n input.setAttribute(\"aria-label\", \"Chat message\");\n if (hasShadowDom) {\n input.style.color = \"var(--namiru-text)\";\n } else {\n input.style.setProperty(\"color\", \"var(--namiru-text)\", \"important\");\n }\n\n const sendBtn = document.createElement(\"button\");\n sendBtn.className = \"namiru-send-btn\";\n sendBtn.setAttribute(\"aria-label\", \"Send message\");\n sendBtn.disabled = true;\n sendBtn.appendChild(sendIcon());\n\n function submit(): void {\n const value = input.value.trim();\n if (!value) return;\n onSend(value);\n input.value = \"\";\n input.style.height = \"auto\";\n sendBtn.disabled = true;\n }\n\n input.addEventListener(\"input\", () => {\n sendBtn.disabled = !input.value.trim();\n // Auto-resize\n input.style.height = \"auto\";\n input.style.height = Math.min(input.scrollHeight, 100) + \"px\";\n });\n\n input.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n submit();\n }\n });\n\n sendBtn.addEventListener(\"click\", submit);\n\n row.appendChild(input);\n row.appendChild(sendBtn);\n area.appendChild(row);\n\n return area;\n}\n", "import type { ChatMessage } from \"../../core/types\";\nimport { renderMarkdown } from \"../../core/markdown\";\nimport { namiruBirdIcon } from \"../icons\";\n\nexport interface MessageBubbleOptions {\n textColor?: string;\n bubbleStyle?: \"modern\" | \"rounded\" | \"square\" | \"classic\";\n agentAvatar?: string;\n presetTheme?: \"light\" | \"dark\" | \"custom\";\n iconColor?: string;\n}\n\nfunction createAvatarElement(opts: MessageBubbleOptions): HTMLElement {\n if (opts.agentAvatar) {\n const img = document.createElement(\"img\");\n img.src = opts.agentAvatar;\n img.alt = \"Agent\";\n img.className = \"namiru-message-avatar-img\";\n return img;\n }\n const span = document.createElement(\"span\");\n const isDark = opts.presetTheme === \"dark\";\n const iconFill = opts.iconColor || (isDark ? \"#ffffff\" : opts.textColor);\n span.appendChild(namiruBirdIcon(iconFill));\n return span;\n}\n\nexport function createMessageBubbleFactory(opts: MessageBubbleOptions) {\n return {\n createBubble(message: ChatMessage): HTMLElement {\n if (message.role === \"user\") {\n return createUserBubble(message, opts);\n }\n return createAssistantBubble(message, opts);\n },\n createStreaming(): HTMLElement {\n return createStreamingBubble(opts);\n },\n createLoading(): HTMLElement {\n return createLoadingIndicator(opts);\n },\n };\n}\n\nfunction createUserBubble(\n message: ChatMessage,\n opts: MessageBubbleOptions,\n): HTMLElement {\n const row = document.createElement(\"div\");\n row.className = \"namiru-message-row namiru-message-row--user\";\n\n const bubble = document.createElement(\"div\");\n let cls = \"namiru-message namiru-message--user\";\n if (opts.bubbleStyle === \"rounded\") cls += \" namiru-bubble--rounded\";\n else if (opts.bubbleStyle === \"square\") cls += \" namiru-bubble--square\";\n bubble.className = cls;\n bubble.textContent = message.content;\n\n row.appendChild(bubble);\n return row;\n}\n\nfunction createAssistantBubble(\n message: ChatMessage,\n opts: MessageBubbleOptions,\n): HTMLElement {\n const row = document.createElement(\"div\");\n row.className = \"namiru-message-row namiru-message-row--assistant\";\n\n // Agent avatar or bird icon\n const iconWrap = document.createElement(\"div\");\n iconWrap.className = \"namiru-message-icon\";\n iconWrap.appendChild(createAvatarElement(opts));\n row.appendChild(iconWrap);\n\n // Text (no bubble background, matches AgentChat) - render markdown for bot messages\n // Safe: renderMarkdown() escapes all HTML entities before applying markdown transforms\n const textEl = document.createElement(\"div\");\n textEl.className = \"namiru-message namiru-message--assistant namiru-md\";\n textEl.innerHTML = renderMarkdown(message.content);\n\n row.appendChild(textEl);\n return row;\n}\n\nfunction createStreamingBubble(opts: MessageBubbleOptions): HTMLElement {\n const row = document.createElement(\"div\");\n row.className = \"namiru-message-row namiru-message-row--assistant\";\n\n // Agent avatar or bird icon\n const iconWrap = document.createElement(\"div\");\n iconWrap.className = \"namiru-message-icon\";\n iconWrap.appendChild(createAvatarElement(opts));\n row.appendChild(iconWrap);\n\n const textEl = document.createElement(\"div\");\n textEl.className =\n \"namiru-message namiru-message--assistant namiru-md\";\n textEl.textContent = \"\";\n\n row.appendChild(textEl);\n\n // Expose the text element for content updates\n (row as any)._namiruTextEl = textEl;\n\n return row;\n}\n\nfunction createLoadingIndicator(opts: MessageBubbleOptions): HTMLElement {\n const row = document.createElement(\"div\");\n row.className = \"namiru-message-row namiru-message-row--assistant\";\n\n // Agent avatar or bird icon\n const iconWrap = document.createElement(\"div\");\n iconWrap.className = \"namiru-message-icon\";\n iconWrap.appendChild(createAvatarElement(opts));\n row.appendChild(iconWrap);\n\n const el = document.createElement(\"div\");\n el.className = \"namiru-loading\";\n for (let i = 0; i < 3; i++) {\n const dot = document.createElement(\"div\");\n dot.className = \"namiru-loading-dot\";\n el.appendChild(dot);\n }\n row.appendChild(el);\n return row;\n}\n", "import type { PreChatOption } from \"../../core/types\";\nimport { getIconByName } from \"../icons\";\n\nexport interface PreChatFormOptions {\n question: string;\n options: PreChatOption[];\n onSelect: (label: string) => void;\n}\n\nexport function createPreChatForm(options: PreChatFormOptions): HTMLElement {\n const { question, options: opts, onSelect } = options;\n\n const container = document.createElement(\"div\");\n container.className = \"namiru-prechat\";\n\n const questionEl = document.createElement(\"div\");\n questionEl.className = \"namiru-prechat-question\";\n questionEl.textContent = question;\n container.appendChild(questionEl);\n\n const optionsList = document.createElement(\"div\");\n optionsList.className = \"namiru-prechat-options\";\n\n for (const opt of opts) {\n const btn = document.createElement(\"button\");\n btn.className = \"namiru-prechat-option\";\n\n const icon = getIconByName(opt.icon);\n btn.appendChild(icon);\n\n const label = document.createElement(\"span\");\n label.textContent = opt.label;\n btn.appendChild(label);\n\n btn.addEventListener(\"click\", () => onSelect(opt.label));\n optionsList.appendChild(btn);\n }\n\n container.appendChild(optionsList);\n return container;\n}\n", "import { thumbsUpIcon, thumbsDownIcon } from \"../icons\";\n\nexport interface FeedbackPromptOptions {\n onFeedback: (rating: \"up\" | \"down\") => void;\n softPrompt?: boolean;\n}\n\nexport function createFeedbackPrompt(\n options: FeedbackPromptOptions\n): HTMLElement {\n const { onFeedback, softPrompt } = options;\n\n const container = document.createElement(\"div\");\n container.className = \"namiru-feedback\";\n\n const label = document.createElement(\"div\");\n label.className = \"namiru-feedback-label\";\n label.textContent = \"Feedback\";\n container.appendChild(label);\n\n const text = document.createElement(\"div\");\n text.className = \"namiru-feedback-text\";\n text.textContent = softPrompt\n ? \"How did it go? Your feedback helps us improve.\"\n : \"How was your experience?\";\n container.appendChild(text);\n\n const buttons = document.createElement(\"div\");\n buttons.className = \"namiru-feedback-buttons\";\n\n const upBtn = document.createElement(\"button\");\n upBtn.className = \"namiru-feedback-btn namiru-feedback-btn-up\";\n upBtn.setAttribute(\"aria-label\", \"Thumbs up\");\n upBtn.appendChild(thumbsUpIcon());\n\n const downBtn = document.createElement(\"button\");\n downBtn.className = \"namiru-feedback-btn namiru-feedback-btn-down\";\n downBtn.setAttribute(\"aria-label\", \"Thumbs down\");\n downBtn.appendChild(thumbsDownIcon());\n\n function handleFeedback(rating: \"up\" | \"down\"): void {\n onFeedback(rating);\n // Replace all content with thanks message\n while (container.firstChild) {\n container.removeChild(container.firstChild);\n }\n const thanks = document.createElement(\"div\");\n thanks.className = \"namiru-feedback-thanks\";\n thanks.textContent = \"Thanks for your feedback!\";\n container.appendChild(thanks);\n }\n\n upBtn.addEventListener(\"click\", () => handleFeedback(\"up\"));\n downBtn.addEventListener(\"click\", () => handleFeedback(\"down\"));\n\n buttons.appendChild(upBtn);\n buttons.appendChild(downBtn);\n container.appendChild(buttons);\n\n return container;\n}\n", "export interface EmailFormOptions {\n promptText: string;\n buttonText: string;\n onSubmit: (email: string) => void;\n}\n\nexport function createEmailForm(options: EmailFormOptions): HTMLElement {\n const { promptText, buttonText, onSubmit } = options;\n\n const container = document.createElement(\"div\");\n container.className = \"namiru-email-form\";\n\n const text = document.createElement(\"div\");\n text.className = \"namiru-email-form-text\";\n text.textContent = promptText;\n container.appendChild(text);\n\n const row = document.createElement(\"div\");\n row.className = \"namiru-email-form-row\";\n\n const input = document.createElement(\"input\");\n input.className = \"namiru-email-input\";\n input.type = \"email\";\n input.placeholder = \"your@email.com\";\n input.setAttribute(\"aria-label\", \"Email address\");\n\n const submitBtn = document.createElement(\"button\");\n submitBtn.className = \"namiru-email-submit\";\n submitBtn.textContent = buttonText;\n submitBtn.disabled = true;\n\n input.addEventListener(\"input\", () => {\n submitBtn.disabled = !isValidEmail(input.value);\n });\n\n function submit(): void {\n const email = input.value.trim();\n if (!isValidEmail(email)) return;\n\n onSubmit(email);\n\n // Replace form with confirmation\n row.remove();\n text.remove();\n const sent = document.createElement(\"div\");\n sent.className = \"namiru-email-sent\";\n sent.textContent = \"Thanks, we'll be in touch\";\n container.appendChild(sent);\n }\n\n input.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n submit();\n }\n });\n\n submitBtn.addEventListener(\"click\", submit);\n\n row.appendChild(input);\n row.appendChild(submitBtn);\n container.appendChild(row);\n\n return container;\n}\n\nfunction isValidEmail(email: string): boolean {\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email.trim());\n}\n", "export interface ContactFormOptions {\n onSubmit: (data: { name: string; email: string; message: string }) => void;\n}\n\nexport function createContactForm(options: ContactFormOptions): HTMLElement {\n const { onSubmit } = options;\n\n const container = document.createElement(\"div\");\n container.className = \"namiru-contact-form\";\n\n const heading = document.createElement(\"div\");\n heading.className = \"namiru-contact-heading\";\n heading.textContent =\n \"Our team is here to help! Leave your message and we'll get back to you.\";\n container.appendChild(heading);\n\n // Name field (optional)\n const nameLabel = document.createElement(\"label\");\n nameLabel.className = \"namiru-contact-label\";\n nameLabel.textContent = \"Name (optional)\";\n container.appendChild(nameLabel);\n\n const nameInput = document.createElement(\"input\");\n nameInput.className = \"namiru-contact-input\";\n nameInput.type = \"text\";\n nameInput.placeholder = \"Your name\";\n nameInput.setAttribute(\"aria-label\", \"Name\");\n container.appendChild(nameInput);\n\n // Email field (required)\n const emailLabel = document.createElement(\"label\");\n emailLabel.className = \"namiru-contact-label\";\n emailLabel.textContent = \"Email *\";\n container.appendChild(emailLabel);\n\n const emailInput = document.createElement(\"input\");\n emailInput.className = \"namiru-contact-input\";\n emailInput.type = \"email\";\n emailInput.placeholder = \"your@email.com\";\n emailInput.required = true;\n emailInput.setAttribute(\"aria-label\", \"Email address\");\n container.appendChild(emailInput);\n\n // Message field (required)\n const msgLabel = document.createElement(\"label\");\n msgLabel.className = \"namiru-contact-label\";\n msgLabel.textContent = \"Message *\";\n container.appendChild(msgLabel);\n\n const messageInput = document.createElement(\"textarea\");\n messageInput.className = \"namiru-contact-textarea\";\n messageInput.placeholder = \"How can we help you?\";\n messageInput.rows = 4;\n messageInput.required = true;\n messageInput.setAttribute(\"aria-label\", \"Message\");\n container.appendChild(messageInput);\n\n // Error message\n const errorEl = document.createElement(\"div\");\n errorEl.className = \"namiru-contact-error\";\n errorEl.style.display = \"none\";\n container.appendChild(errorEl);\n\n // Submit button\n const submitBtn = document.createElement(\"button\");\n submitBtn.className = \"namiru-contact-submit\";\n submitBtn.textContent = \"Send Message\";\n submitBtn.disabled = true;\n container.appendChild(submitBtn);\n\n function validate(): boolean {\n const email = emailInput.value.trim();\n const message = messageInput.value.trim();\n const emailValid = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email);\n return emailValid && message.length > 0;\n }\n\n function updateButton(): void {\n submitBtn.disabled = !validate();\n }\n\n emailInput.addEventListener(\"input\", updateButton);\n messageInput.addEventListener(\"input\", updateButton);\n\n function submit(): void {\n if (!validate()) return;\n\n const data = {\n name: nameInput.value.trim(),\n email: emailInput.value.trim(),\n message: messageInput.value.trim(),\n };\n\n // Disable form\n submitBtn.disabled = true;\n submitBtn.textContent = \"Sending...\";\n nameInput.disabled = true;\n emailInput.disabled = true;\n messageInput.disabled = true;\n\n onSubmit(data);\n\n // Show confirmation\n container.textContent = \"\";\n const confirmation = document.createElement(\"div\");\n confirmation.className = \"namiru-contact-confirmation\";\n confirmation.textContent = \"Thanks! We'll get back to you shortly.\";\n container.appendChild(confirmation);\n }\n\n submitBtn.addEventListener(\"click\", submit);\n\n // Allow Enter in inputs (but not textarea) to submit\n emailInput.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n submit();\n }\n });\n nameInput.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n submit();\n }\n });\n\n return container;\n}\n", "export interface LimitOverlayOptions {\n onSubmit: (data: { message: string; visitorEmail?: string }) => void;\n onNewChat?: () => void;\n}\n\nfunction createInfoIcon(): SVGSVGElement {\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.setAttribute(\"width\", \"40\");\n svg.setAttribute(\"height\", \"40\");\n svg.setAttribute(\"viewBox\", \"0 0 256 256\");\n svg.setAttribute(\"fill\", \"none\");\n svg.setAttribute(\"stroke\", \"currentColor\");\n svg.setAttribute(\"stroke-width\", \"16\");\n svg.setAttribute(\"stroke-linecap\", \"round\");\n svg.setAttribute(\"stroke-linejoin\", \"round\");\n\n const circle = document.createElementNS(\"http://www.w3.org/2000/svg\", \"circle\");\n circle.setAttribute(\"cx\", \"128\");\n circle.setAttribute(\"cy\", \"128\");\n circle.setAttribute(\"r\", \"96\");\n svg.appendChild(circle);\n\n const line = document.createElementNS(\"http://www.w3.org/2000/svg\", \"line\");\n line.setAttribute(\"x1\", \"128\");\n line.setAttribute(\"y1\", \"80\");\n line.setAttribute(\"x2\", \"128\");\n line.setAttribute(\"y2\", \"136\");\n svg.appendChild(line);\n\n const dot = document.createElementNS(\"http://www.w3.org/2000/svg\", \"circle\");\n dot.setAttribute(\"cx\", \"128\");\n dot.setAttribute(\"cy\", \"172\");\n dot.setAttribute(\"r\", \"6\");\n dot.setAttribute(\"fill\", \"currentColor\");\n dot.setAttribute(\"stroke\", \"none\");\n svg.appendChild(dot);\n\n return svg;\n}\n\nfunction createCheckIcon(): SVGSVGElement {\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.setAttribute(\"width\", \"40\");\n svg.setAttribute(\"height\", \"40\");\n svg.setAttribute(\"viewBox\", \"0 0 256 256\");\n svg.setAttribute(\"fill\", \"none\");\n svg.setAttribute(\"stroke\", \"currentColor\");\n svg.setAttribute(\"stroke-width\", \"16\");\n svg.setAttribute(\"stroke-linecap\", \"round\");\n svg.setAttribute(\"stroke-linejoin\", \"round\");\n\n const circle = document.createElementNS(\"http://www.w3.org/2000/svg\", \"circle\");\n circle.setAttribute(\"cx\", \"128\");\n circle.setAttribute(\"cy\", \"128\");\n circle.setAttribute(\"r\", \"96\");\n svg.appendChild(circle);\n\n const polyline = document.createElementNS(\"http://www.w3.org/2000/svg\", \"polyline\");\n polyline.setAttribute(\"points\", \"88,136 112,160 168,104\");\n svg.appendChild(polyline);\n\n return svg;\n}\n\nexport function createLimitOverlay(options: LimitOverlayOptions): HTMLElement {\n const { onSubmit, onNewChat } = options;\n\n const container = document.createElement(\"div\");\n container.className = \"namiru-limit-overlay\";\n\n // Icon\n const iconWrap = document.createElement(\"div\");\n iconWrap.className = \"namiru-limit-icon\";\n iconWrap.appendChild(createInfoIcon());\n container.appendChild(iconWrap);\n\n // Heading\n const heading = document.createElement(\"div\");\n heading.className = \"namiru-limit-heading\";\n heading.textContent = \"Conversation limit reached\";\n container.appendChild(heading);\n\n // Subtext\n const subtext = document.createElement(\"div\");\n subtext.className = \"namiru-limit-subtext\";\n subtext.textContent =\n \"AI responses are currently unavailable. Send a message and we'll forward it via email.\";\n container.appendChild(subtext);\n\n // Form container\n const form = document.createElement(\"div\");\n form.className = \"namiru-limit-form\";\n\n // Message textarea\n const messageInput = document.createElement(\"textarea\");\n messageInput.className = \"namiru-limit-textarea\";\n messageInput.placeholder = \"Your message...\";\n messageInput.rows = 4;\n messageInput.setAttribute(\"aria-label\", \"Message\");\n form.appendChild(messageInput);\n\n // Email input (optional)\n const emailInput = document.createElement(\"input\");\n emailInput.className = \"namiru-limit-email\";\n emailInput.type = \"email\";\n emailInput.placeholder = \"Your email (optional, for a reply)\";\n emailInput.setAttribute(\"aria-label\", \"Email address (optional)\");\n form.appendChild(emailInput);\n\n // Submit button\n const submitBtn = document.createElement(\"button\");\n submitBtn.className = \"namiru-limit-submit\";\n submitBtn.textContent = \"Send Message\";\n submitBtn.disabled = true;\n form.appendChild(submitBtn);\n\n container.appendChild(form);\n\n // New Chat button\n if (onNewChat) {\n const newChatBtn = document.createElement(\"button\");\n newChatBtn.className = \"namiru-limit-newchat\";\n newChatBtn.textContent = \"Start New Chat\";\n newChatBtn.addEventListener(\"click\", onNewChat);\n container.appendChild(newChatBtn);\n }\n\n function validate(): boolean {\n return messageInput.value.trim().length > 0;\n }\n\n function updateButton(): void {\n submitBtn.disabled = !validate();\n }\n\n messageInput.addEventListener(\"input\", updateButton);\n\n function submit(): void {\n if (!validate()) return;\n\n const email = emailInput.value.trim();\n const data: { message: string; visitorEmail?: string } = {\n message: messageInput.value.trim(),\n };\n if (email) {\n data.visitorEmail = email;\n }\n\n // Disable form\n submitBtn.disabled = true;\n submitBtn.textContent = \"Sending...\";\n messageInput.disabled = true;\n emailInput.disabled = true;\n\n onSubmit(data);\n\n // Show confirmation\n container.textContent = \"\";\n\n const confirmIcon = document.createElement(\"div\");\n confirmIcon.className = \"namiru-limit-icon namiru-limit-icon--success\";\n confirmIcon.appendChild(createCheckIcon());\n container.appendChild(confirmIcon);\n\n const confirmation = document.createElement(\"div\");\n confirmation.className = \"namiru-limit-confirmation\";\n confirmation.textContent = \"Message sent! The team will get back to you soon.\";\n container.appendChild(confirmation);\n\n // Re-add New Chat button after confirmation\n if (onNewChat) {\n const newChatBtn2 = document.createElement(\"button\");\n newChatBtn2.className = \"namiru-limit-newchat\";\n newChatBtn2.textContent = \"Start New Chat\";\n newChatBtn2.addEventListener(\"click\", onNewChat);\n container.appendChild(newChatBtn2);\n }\n }\n\n submitBtn.addEventListener(\"click\", submit);\n\n return container;\n}\n", "import { ChatStore, type ChatStoreState } from \"../../core/state-machine\";\nimport type { AgentBrandingData, ChatMessage } from \"../../core/types\";\nimport { hasShadowDom } from \"../../core/env\";\nimport { renderMarkdown } from \"../../core/markdown\";\nimport { createChatHeader, showCloseConfirmation } from \"./chat-header\";\nimport { createChatInput } from \"./chat-input\";\nimport { createMessageBubbleFactory } from \"./message-bubble\";\nimport { createPreChatForm } from \"./pre-chat-form\";\nimport { createFeedbackPrompt } from \"./feedback-prompt\";\nimport { createEmailForm } from \"./email-form\";\nimport { createContactForm } from \"./contact-form\";\nimport { createLimitOverlay } from \"./limit-overlay\";\n\nexport interface ChatWindowOptions {\n store: ChatStore;\n branding: AgentBrandingData;\n agentId: string;\n mode: \"button\" | \"inline\";\n position: \"bottom-left\" | \"bottom-right\";\n onSendMessage: (content: string) => void;\n onPreChatSelect: (label: string) => void;\n onFeedback: (rating: \"up\" | \"down\") => void;\n onEscalationEmail: (email: string) => void;\n onTranscriptEmail: (email: string) => void;\n onContactFormSubmit?: (data: { name: string; email: string; message: string }) => void;\n onLimitMessage?: (data: { message: string; visitorEmail?: string }) => void;\n onNewChat?: () => void;\n feedbackEnabled?: boolean;\n}\n\nexport function createChatWindow(options: ChatWindowOptions): HTMLElement {\n const {\n store,\n branding,\n agentId,\n mode,\n position,\n onSendMessage,\n onPreChatSelect,\n onFeedback,\n onEscalationEmail,\n onTranscriptEmail,\n onContactFormSubmit,\n onLimitMessage,\n onNewChat,\n feedbackEnabled,\n } = options;\n\n // Create instance-scoped bubble factory\n const agentAvatarUrl = branding.agentAvatar || branding.logoUrl;\n const bubbles = createMessageBubbleFactory({\n textColor: branding.textColor,\n bubbleStyle: branding.bubbleStyle,\n agentAvatar: agentAvatarUrl,\n presetTheme: branding.presetTheme,\n iconColor: branding.iconColor,\n });\n\n // Container\n const container = document.createElement(\"div\");\n if (mode === \"button\") {\n container.className = `namiru-popup namiru-popup--${position}`;\n } else {\n container.className = \"namiru-inline\";\n }\n\n // Header\n const header = createChatHeader({\n store,\n branding,\n mode,\n ...(mode === 'button' ? {\n onTranscriptClick: () => {\n store.dispatch({ type: \"SET_STATE\", state: \"escalation\" });\n showTranscriptForm();\n },\n onNewChat,\n } : {}),\n feedbackEnabled,\n });\n container.appendChild(header);\n\n // Content area (messages, pre-chat, etc.)\n const content = document.createElement(\"div\");\n content.className = \"namiru-messages\";\n container.appendChild(content);\n\n // Input area (hidden until init completes)\n const inputArea = createChatInput({ onSend: onSendMessage });\n inputArea.style.display = \"none\";\n container.appendChild(inputArea);\n\n // When branding footer is hidden, add bottom padding to the input area\n // so it doesn't sit flush against the container edge\n const showPowered = branding.showPoweredBy !== false;\n if (!showPowered) {\n inputArea.style.paddingBottom = \"12px\";\n }\n\n function createPoweredByEl(): HTMLElement {\n const powered = document.createElement(\"div\");\n powered.className = \"namiru-powered\";\n powered.setAttribute(\"data-namiru-protected\", \"true\");\n const imp = hasShadowDom ? \"\" : \" !important\";\n powered.style.cssText = `display:block${imp};visibility:visible${imp};opacity:1${imp};`;\n const link = document.createElement(\"a\");\n link.href = \"https://namiru.ai\";\n link.target = \"_blank\";\n link.rel = \"noopener noreferrer\";\n link.textContent = \"Namiru.ai\";\n powered.appendChild(document.createTextNode(\"Powered by \"));\n powered.appendChild(link);\n return powered;\n }\n\n if (showPowered) {\n // Store original content from a reference element for tamper detection.\n // This is safe to use with innerHTML because it only contains our own\n // hardcoded static markup (no user input).\n const referenceEl = createPoweredByEl();\n const originalPoweredHTML = referenceEl.innerHTML;\n container.appendChild(createPoweredByEl());\n\n // Anti-tampering: MutationObserver restores the badge instantly if removed, hidden, or content-changed\n let guardPaused = false;\n const poweredByObserver = new MutationObserver(() => {\n if (guardPaused) return;\n guardPaused = true;\n const existing = container.querySelector('.namiru-powered') as HTMLElement | null;\n if (!existing) {\n container.appendChild(createPoweredByEl());\n } else {\n // Restore content if tampered with (innerHTML/textContent changed)\n if (existing.innerHTML !== originalPoweredHTML) {\n // Replace with a fresh element to restore all child nodes\n const fresh = createPoweredByEl();\n existing.replaceWith(fresh);\n } else {\n const s = existing.style;\n const cs = getComputedStyle(existing);\n if (cs.display === 'none' || cs.visibility === 'hidden' || cs.opacity === '0') {\n const imp = hasShadowDom ? \"\" : \" !important\";\n s.cssText = `display:block${imp};visibility:visible${imp};opacity:1${imp};`;\n }\n }\n }\n guardPaused = false;\n });\n poweredByObserver.observe(container, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['style', 'class'],\n characterData: true,\n });\n }\n\n // Apply custom font family to container if provided\n if (branding.fontFamily && branding.fontFamily !== \"system\") {\n container.style.fontFamily = branding.fontFamily;\n }\n\n // Hard message limit per conversation\n const MESSAGE_HARD_LIMIT = 40;\n\n // State tracking\n let renderedMessageCount = 0;\n let streamingBubble: HTMLElement | null = null;\n let loadingEl: HTMLElement | null = null;\n let preChatEl: HTMLElement | null = null;\n let feedbackEl: HTMLElement | null = null;\n let emailFormEl: HTMLElement | null = null;\n let welcomeRendered = false;\n let suggestionsEl: HTMLElement | null = null;\n let contactFormEl: HTMLElement | null = null;\n let limitOverlayEl: HTMLElement | null = null;\n let connectingEl: HTMLElement | null = null;\n\n function showConnectingIndicator(): void {\n if (connectingEl) return;\n connectingEl = document.createElement(\"div\");\n connectingEl.className = \"namiru-connecting\";\n const dots = document.createElement(\"div\");\n dots.className = \"namiru-loading-dots\";\n for (let i = 0; i < 3; i++) {\n const dot = document.createElement(\"span\");\n dot.className = \"namiru-loading-dot\";\n dots.appendChild(dot);\n }\n connectingEl.appendChild(dots);\n content.appendChild(connectingEl);\n }\n\n function removeConnectingIndicator(): void {\n if (connectingEl) {\n connectingEl.remove();\n connectingEl = null;\n }\n }\n\n function clearContent(): void {\n content.textContent = \"\";\n renderedMessageCount = 0;\n streamingBubble = null;\n loadingEl = null;\n preChatEl = null;\n feedbackEl = null;\n emailFormEl = null;\n contactFormEl = null;\n limitOverlayEl = null;\n connectingEl = null;\n welcomeRendered = false;\n suggestionsEl = null;\n }\n\n function renderWelcomeMessage(): void {\n if (welcomeRendered) return;\n welcomeRendered = true;\n\n const welcomeText = branding.welcomeMessage || \"Hello! How can I help you today?\";\n\n // Render welcome as a standard assistant bubble so it matches all other AI messages\n const welcomeMsg: ChatMessage = {\n id: \"welcome\",\n role: \"assistant\",\n content: welcomeText,\n timestamp: Date.now(),\n };\n const row = bubbles.createBubble(welcomeMsg);\n row.classList.add(\"namiru-message-row--welcome\");\n\n content.appendChild(row);\n\n // Render suggested questions if any\n const questions = branding.suggestedQuestions;\n console.log(\"[NamiruChat] renderWelcome suggestedQuestions:\", questions);\n if (questions && questions.length > 0) {\n suggestionsEl = document.createElement(\"div\");\n suggestionsEl.className = \"namiru-suggestions\";\n\n questions.slice(0, 4).forEach((q) => {\n const chip = document.createElement(\"button\");\n chip.className = \"namiru-suggestion-chip\";\n chip.textContent = q;\n chip.addEventListener(\"click\", () => {\n onSendMessage(q);\n // Remove suggestions after click\n if (suggestionsEl) {\n suggestionsEl.remove();\n suggestionsEl = null;\n }\n });\n suggestionsEl!.appendChild(chip);\n });\n\n content.appendChild(suggestionsEl);\n }\n }\n\n function showPreChat(): void {\n const pcConfig = branding.preChatConfig;\n if (!pcConfig || !pcConfig.enabled) return;\n\n // Default templates\n const templates: Record<\n string,\n { question: string; options: { label: string; icon: string }[] }\n > = {\n ecommerce: {\n question: \"What brings you here today?\",\n options: [\n { label: \"Product question\", icon: \"ShoppingBag\" },\n { label: \"Order help\", icon: \"Package\" },\n { label: \"Billing issue\", icon: \"CreditCard\" },\n { label: \"Something else\", icon: \"ChatCircle\" },\n ],\n },\n saas: {\n question: \"What can we help you with?\",\n options: [\n { label: \"Getting started\", icon: \"Rocket\" },\n { label: \"Technical issue\", icon: \"Wrench\" },\n { label: \"Subscription question\", icon: \"CreditCard\" },\n { label: \"Something else\", icon: \"ChatCircle\" },\n ],\n },\n services: {\n question: \"How can we assist you?\",\n options: [\n { label: \"Interested in services\", icon: \"Briefcase\" },\n { label: \"Existing client\", icon: \"UserCircle\" },\n { label: \"General question\", icon: \"ChatCircle\" },\n { label: \"Something else\", icon: \"DotsThree\" },\n ],\n },\n };\n\n let question: string;\n let formOptions: { label: string; icon: string }[];\n\n if (pcConfig.template === \"custom\" && pcConfig.custom) {\n question = pcConfig.custom.question;\n formOptions = pcConfig.custom.options;\n } else if (pcConfig.template && templates[pcConfig.template]) {\n const tmpl = templates[pcConfig.template];\n question = tmpl.question;\n formOptions = tmpl.options;\n } else {\n return;\n }\n\n clearContent();\n inputArea.style.display = \"none\";\n\n preChatEl = createPreChatForm({\n question,\n options: formOptions,\n onSelect: (label) => {\n onPreChatSelect(label);\n inputArea.style.display = \"\";\n },\n });\n content.appendChild(preChatEl);\n }\n\n function showTranscriptForm(): void {\n if (emailFormEl) return;\n emailFormEl = createEmailForm({\n promptText:\n \"Want a copy of this conversation? Handy if you need to reference it later for support.\",\n buttonText: \"Send\",\n onSubmit: (email) => {\n onTranscriptEmail(email);\n emailFormEl = null;\n },\n });\n content.appendChild(emailFormEl);\n scrollToBottom();\n }\n\n function showEscalationForm(): void {\n if (emailFormEl) return;\n emailFormEl = createEmailForm({\n promptText:\n \"We'll connect you with the team. Please share your email and we'll get back to you.\",\n buttonText: \"Submit\",\n onSubmit: (email) => {\n onEscalationEmail(email);\n emailFormEl = null;\n },\n });\n content.appendChild(emailFormEl);\n scrollToBottom();\n }\n\n function showContactForm(): void {\n if (contactFormEl) return;\n clearContent();\n inputArea.style.display = \"none\";\n contactFormEl = createContactForm({\n onSubmit: (data) => {\n if (onContactFormSubmit) {\n onContactFormSubmit(data);\n }\n contactFormEl = null;\n },\n });\n content.appendChild(contactFormEl);\n }\n\n function showLimitOverlay(): void {\n if (limitOverlayEl) return;\n inputArea.style.display = \"none\";\n limitOverlayEl = createLimitOverlay({\n onSubmit: (data) => {\n if (onLimitMessage) {\n onLimitMessage(data);\n }\n limitOverlayEl = null;\n },\n });\n // The overlay is positioned absolute over the messages area\n content.style.position = \"relative\";\n content.appendChild(limitOverlayEl);\n }\n\n function showDomainError(): void {\n // Clear any existing child nodes\n while (content.firstChild) {\n content.removeChild(content.firstChild);\n }\n content.style.position = \"relative\";\n\n const overlay = document.createElement(\"div\");\n overlay.style.cssText = `\n position: absolute; inset: 0; display: flex; flex-direction: column;\n align-items: center; justify-content: center; padding: 2rem; text-align: center;\n background: ${branding.backgroundColor || \"#ffffff\"};\n color: ${branding.textColor || \"#1f2937\"};\n `;\n\n const icon = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n icon.setAttribute(\"viewBox\", \"0 0 256 256\");\n icon.setAttribute(\"width\", \"72\");\n icon.setAttribute(\"height\", \"72\");\n icon.setAttribute(\"fill\", \"#ef4444\");\n icon.style.cssText = \"margin-bottom: 20px; opacity: 0.8;\";\n const path = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n path.setAttribute(\"d\", \"M128,26A102,102,0,1,0,230,128,102.12,102.12,0,0,0,128,26Zm90,102a89.6,89.6,0,0,1-22.29,59.22L68.78,60.29A89.95,89.95,0,0,1,218,128ZM38,128A89.6,89.6,0,0,1,60.29,68.78L187.22,195.71A89.95,89.95,0,0,1,38,128Z\");\n icon.appendChild(path);\n overlay.appendChild(icon);\n\n const title = document.createElement(\"div\");\n title.style.cssText = \"font-size: 18px; font-weight: 600; margin-bottom: 8px;\";\n title.textContent = \"Domain Not Authorized\";\n overlay.appendChild(title);\n\n const msg = document.createElement(\"div\");\n msg.style.cssText = \"font-size: 14px; opacity: 0.7; margin-bottom: 24px; max-width: 300px; line-height: 1.5;\";\n msg.textContent = \"This chat widget is not authorized to run on this domain. Please update the allowed domain in your agent settings.\";\n overlay.appendChild(msg);\n\n const btnRow = document.createElement(\"div\");\n btnRow.style.cssText = \"display: flex; gap: 12px; align-items: center;\";\n\n const settingsLink = document.createElement(\"a\");\n settingsLink.style.cssText = `\n padding: 10px 24px; border-radius: 8px; border: none; cursor: pointer;\n font-size: 14px; font-weight: 500; text-decoration: none;\n display: inline-flex; align-items: center; box-sizing: border-box;\n line-height: 1; background: ${branding.primaryColor || \"#1f2937\"}; color: #fff;\n `;\n settingsLink.textContent = \"Go to Settings\";\n // Resolve the correct dashboard base URL per environment\n const host = window.location.hostname;\n let dashBase = window.location.origin;\n if (host !== \"localhost\" && host !== \"127.0.0.1\") {\n if (host.endsWith(\"namiru.ai\")) {\n dashBase = host.includes(\"test\") ? \"https://test.namiru.ai\" : \"https://namiru.ai\";\n }\n }\n settingsLink.href = `${dashBase}/agent-builder/agent/${agentId}/settings?focus=domain`;\n settingsLink.target = \"_blank\";\n settingsLink.rel = \"noopener\";\n btnRow.appendChild(settingsLink);\n\n const btn = document.createElement(\"button\");\n btn.style.cssText = `\n padding: 10px 24px; border-radius: 8px; cursor: pointer;\n font-size: 14px; font-weight: 500; line-height: 1; box-sizing: border-box;\n background: transparent; color: ${branding.textColor || \"#1f2937\"};\n border: 1px solid ${branding.textColor ? branding.textColor + \"33\" : \"#e5e7eb\"};\n `;\n btn.textContent = \"Reload\";\n btn.addEventListener(\"click\", () => window.location.reload());\n btnRow.appendChild(btn);\n\n overlay.appendChild(btnRow);\n content.appendChild(overlay);\n }\n\n function showFeedback(softPrompt: boolean): void {\n if (feedbackEl) return;\n feedbackEl = createFeedbackPrompt({\n onFeedback: (rating) => {\n onFeedback(rating);\n // After feedback, close immediately\n if (mode === \"button\") {\n setTimeout(() => {\n store.dispatch({ type: \"RESET\" });\n store.dispatch({ type: \"SET_OPEN\", isOpen: false });\n }, 800);\n }\n },\n softPrompt,\n });\n content.appendChild(feedbackEl);\n scrollToBottom();\n }\n\n function scrollToBottom(): void {\n requestAnimationFrame(() => {\n content.scrollTop = content.scrollHeight;\n });\n }\n\n function renderMessages(messages: ChatMessage[]): void {\n // Remove suggestions once user sends a message\n if (suggestionsEl && messages.some((m) => m.role === \"user\")) {\n suggestionsEl.remove();\n suggestionsEl = null;\n }\n\n // Only render new messages\n for (let i = renderedMessageCount; i < messages.length; i++) {\n const bubble = bubbles.createBubble(messages[i]);\n content.appendChild(bubble);\n }\n renderedMessageCount = messages.length;\n scrollToBottom();\n }\n\n function updateStreaming(streamingContent: string): void {\n if (streamingContent) {\n if (!streamingBubble) {\n // Remove loading indicator\n if (loadingEl) {\n loadingEl.remove();\n loadingEl = null;\n }\n streamingBubble = bubbles.createStreaming();\n content.appendChild(streamingBubble);\n }\n // Update inner text element with markdown-rendered HTML.\n // XSS-safe: renderMarkdown() calls escapeHtml() on input before any transforms.\n const textEl = (streamingBubble as any)._namiruTextEl;\n const rendered = renderMarkdown(streamingContent);\n if (textEl) {\n textEl.innerHTML = rendered;\n } else {\n streamingBubble.innerHTML = rendered;\n }\n scrollToBottom();\n } else if (streamingBubble) {\n streamingBubble.remove();\n streamingBubble = null;\n }\n }\n\n function updateLoading(isLoading: boolean): void {\n if (isLoading && !loadingEl && !streamingBubble) {\n loadingEl = bubbles.createLoading();\n content.appendChild(loadingEl);\n scrollToBottom();\n } else if (!isLoading && loadingEl) {\n loadingEl.remove();\n loadingEl = null;\n }\n }\n\n // Subscribe to store changes\n let prevState: ChatStoreState | null = null;\n\n store.subscribe((state) => {\n console.log('[ChatWindow] subscriber:', 'state=' + state.state, 'msgs=' + state.messages.length, 'open=' + state.isOpen, 'input=' + inputArea?.style.display, 'prev=' + (prevState?.state || 'null'));\n\n // Open/close for popup mode\n if (mode === \"button\") {\n if (state.isOpen) {\n container.classList.add(\"namiru-popup--open\");\n } else {\n container.classList.remove(\"namiru-popup--open\");\n }\n }\n\n // State transitions\n if (!prevState || prevState.state !== state.state) {\n switch (state.state) {\n case \"idle\":\n // RESET was dispatched - clear all DOM content for fresh start\n clearContent();\n inputArea.style.display = \"none\";\n removeConnectingIndicator();\n break;\n case \"connecting\":\n inputArea.style.display = \"none\";\n showConnectingIndicator();\n break;\n case \"pre_chat\":\n showPreChat();\n break;\n case \"chatting\":\n removeConnectingIndicator();\n if (prevState?.state === \"pre_chat\") {\n clearContent();\n }\n inputArea.style.display = \"\";\n // Render welcome message when entering chat state\n renderWelcomeMessage();\n break;\n case \"feedback\":\n showFeedback(true);\n break;\n case \"escalation\":\n showEscalationForm();\n break;\n case \"email_fallback\":\n showContactForm();\n break;\n case \"conversation_limit\":\n removeConnectingIndicator();\n inputArea.style.display = \"none\";\n showLimitOverlay();\n break;\n case \"domain_error\":\n removeConnectingIndicator();\n inputArea.style.display = \"none\";\n showDomainError();\n break;\n case \"error\":\n removeConnectingIndicator();\n inputArea.style.display = \"none\";\n break;\n }\n }\n\n // Render messages\n if (\n state.messages.length > renderedMessageCount &&\n state.state !== \"pre_chat\"\n ) {\n renderMessages(state.messages);\n }\n\n // Check per-conversation message limit (count total messages, not just user)\n if (\n state.state === \"chatting\" &&\n state.messages.length >= MESSAGE_HARD_LIMIT\n ) {\n store.dispatch({ type: \"SET_STATE\", state: \"conversation_limit\" });\n }\n\n // Streaming\n if (prevState?.streamingContent !== state.streamingContent) {\n updateStreaming(state.streamingContent);\n }\n\n // Loading\n if (prevState?.isLoading !== state.isLoading) {\n updateLoading(state.isLoading);\n }\n\n prevState = state;\n });\n\n // Expose methods for external triggers\n (container as any)._namiruShowEscalation = showEscalationForm;\n (container as any)._namiruShowFeedback = showFeedback;\n (container as any)._namiruShowTranscript = showTranscriptForm;\n (container as any)._namiruShowContactForm = showContactForm;\n (container as any)._namiruShowLimitOverlay = showLimitOverlay;\n (container as any)._namiruShowCloseConfirmation = () => showCloseConfirmation(header, store);\n\n return container;\n}\n", "import { ChatStore } from \"../../core/state-machine\";\nimport { chatBubbleIcon, closeIcon } from \"../icons\";\n\nexport interface ButtonBubbleOptions {\n position: \"bottom-left\" | \"bottom-right\";\n store: ChatStore;\n welcomeMessage?: string;\n greetingDelay?: number;\n bubbleStyle?: \"modern\" | \"classic\" | \"rounded\" | \"square\";\n onCloseRequest?: () => void;\n}\n\nexport function createButtonBubble(options: ButtonBubbleOptions): HTMLElement {\n const { position, store, welcomeMessage, greetingDelay, bubbleStyle, onCloseRequest } = options;\n\n const wrapper = document.createElement(\"div\");\n\n // Main button\n const button = document.createElement(\"button\");\n button.className = `namiru-button namiru-button--${position}`;\n if (bubbleStyle === \"classic\") {\n button.classList.add(\"namiru-button--classic\");\n }\n button.setAttribute(\"aria-label\", \"Open chat\");\n\n const openSvg = chatBubbleIcon();\n const closeSvg = closeIcon();\n closeSvg.style.display = \"none\";\n\n button.appendChild(openSvg);\n button.appendChild(closeSvg);\n\n button.addEventListener(\"click\", () => {\n const isOpen = store.getState().isOpen;\n if (isOpen && onCloseRequest) {\n onCloseRequest();\n } else {\n store.dispatch({ type: \"SET_OPEN\", isOpen: !isOpen });\n }\n });\n\n wrapper.appendChild(button);\n\n // Greeting bubble\n let greetingEl: HTMLElement | null = null;\n let greetingVisible = false;\n let greetingTimer: ReturnType<typeof setTimeout> | null = null;\n\n if (welcomeMessage) {\n greetingEl = document.createElement(\"div\");\n greetingEl.className = `namiru-greeting namiru-greeting--${position} namiru-greeting--hidden`;\n\n const textNode = document.createTextNode(welcomeMessage);\n greetingEl.appendChild(textNode);\n\n const closeBtn = document.createElement(\"button\");\n closeBtn.className = \"namiru-greeting-close\";\n closeBtn.setAttribute(\"aria-label\", \"Dismiss\");\n closeBtn.textContent = \"\\u00D7\";\n closeBtn.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n hideGreeting();\n });\n greetingEl.appendChild(closeBtn);\n\n greetingEl.addEventListener(\"click\", () => {\n hideGreeting();\n store.dispatch({ type: \"SET_OPEN\", isOpen: true });\n });\n\n wrapper.appendChild(greetingEl);\n\n // Auto-show after delay, auto-hide after 30 seconds\n const delay = greetingDelay ?? 3000;\n greetingTimer = setTimeout(() => {\n if (!store.getState().isOpen && greetingEl) {\n greetingEl.classList.remove(\"namiru-greeting--hidden\");\n greetingVisible = true;\n // Auto-hide after 30 seconds\n setTimeout(() => hideGreeting(), 30000);\n }\n }, delay);\n }\n\n function hideGreeting(): void {\n if (greetingVisible && greetingEl) {\n greetingEl.classList.add(\"namiru-greeting--hidden\");\n greetingVisible = false;\n }\n if (greetingTimer) {\n clearTimeout(greetingTimer);\n greetingTimer = null;\n }\n }\n\n store.subscribe((state) => {\n if (state.isOpen) {\n openSvg.style.display = \"none\";\n closeSvg.style.display = \"\";\n button.setAttribute(\"aria-label\", \"Close chat\");\n hideGreeting();\n } else {\n openSvg.style.display = \"\";\n closeSvg.style.display = \"none\";\n button.setAttribute(\"aria-label\", \"Open chat\");\n }\n });\n\n return wrapper;\n}\n"],
|
|
5
|
+
"mappings": "4cAAA,IAAAA,GAAA,GAAAC,GAAAD,GAAA,UAAAE,KCyCA,SAASC,IAAqC,CAC5C,MAAO,CACL,MAAO,OACP,SAAU,CAAC,EACX,OAAQ,GACR,UAAW,GACX,iBAAkB,GAClB,cAAe,KACf,cAAe,GACf,UAAW,KACX,MAAO,IACT,CACF,CAEA,SAASC,GAAQC,EAAuBC,EAAoC,CAC1E,OAAQA,EAAO,KAAM,CACnB,IAAK,YACH,MAAO,CAAE,GAAGD,EAAO,MAAOC,EAAO,MAAO,MAAO,IAAK,EAEtD,IAAK,WACH,MAAO,CAAE,GAAGD,EAAO,OAAQC,EAAO,MAAO,EAE3C,IAAK,cACH,MAAO,CAAE,GAAGD,EAAO,UAAWC,EAAO,SAAU,EAEjD,IAAK,cACH,MAAO,CAAE,GAAGD,EAAO,SAAU,CAAC,GAAGA,EAAM,SAAUC,EAAO,OAAO,CAAE,EAEnE,IAAK,mBACH,MAAO,CACL,GAAGD,EACH,iBAAkBA,EAAM,iBAAmBC,EAAO,KACpD,EAEF,IAAK,kBACH,MAAO,CAAE,GAAGD,EAAO,iBAAkB,EAAG,EAE1C,IAAK,oBACH,MAAO,CAAE,GAAGA,EAAO,cAAeC,EAAO,aAAc,EAEzD,IAAK,qBACH,MAAO,CAAE,GAAGD,EAAO,cAAe,EAAK,EAEzC,IAAK,iBACH,MAAO,CAAE,GAAGA,EAAO,UAAWC,EAAO,SAAU,EAEjD,IAAK,YACH,MAAO,CACL,GAAGD,EACH,MAAOC,EAAO,MACd,MAAOA,EAAO,MAAQ,QAAUD,EAAM,KACxC,EAEF,IAAK,QACH,OAAOF,GAAmB,EAE5B,QACE,OAAOE,CACX,CACF,CAEO,IAAME,EAAN,KAAgB,CAIrB,aAAc,CAFd,KAAQ,YAAoC,IAAI,IAG9C,KAAK,MAAQJ,GAAmB,CAClC,CAEA,UAA2B,CACzB,OAAO,KAAK,KACd,CAEA,SAASG,EAA0B,CACjC,IAAME,EAAY,KAAK,MACvB,KAAK,MAAQJ,GAAQI,EAAWF,CAAM,EAClC,KAAK,QAAUE,GACjB,KAAK,OAAO,CAEhB,CAEA,UAAUC,EAAyC,CACjD,YAAK,YAAY,IAAIA,CAAU,EACxB,IAAM,CACX,KAAK,YAAY,OAAOA,CAAU,CACpC,CACF,CAEQ,QAAe,CACrB,IAAMC,EAAW,KAAK,MACtB,KAAK,YAAY,QAASD,GAAe,CACvC,GAAI,CACFA,EAAWC,CAAQ,CACrB,OAASC,EAAK,CACZ,QAAQ,MAAM,wCAAyCA,CAAG,CAC5D,CACF,CAAC,CACH,CACF,EClGO,IAAMC,EAAN,KAAgB,CAGrB,YAAYC,EAAyB,CACnC,KAAK,QAAUA,EAAO,QAAQ,QAAQ,MAAO,EAAE,CACjD,CAEA,MAAM,cAAcC,EAA6C,CAC/D,IAAMC,EAAW,MAAM,MACrB,GAAG,KAAK,OAAO,sBAAsB,mBAAmBD,CAAO,CAAC,WAClE,EAEA,GAAI,CAACC,EAAS,GACZ,MAAM,IAAI,MAAM,mCAAmCA,EAAS,MAAM,EAAE,EAGtE,IAAMC,EAAO,MAAMD,EAAS,KAAK,EAG3BE,EAAWD,EAAK,UAAY,CAAC,EAEnC,SAASE,EAASC,EAAcC,EAA0B,CACxD,OAAI,OAAOD,GAAQ,UAAY,sBAAsB,KAAKA,CAAG,EAAUA,EAChEC,CACT,CAGA,IAAIC,EAA+B,CAAC,EACpC,GAAI,MAAM,QAAQJ,EAAS,kBAAkB,EAC3CI,EAAqBJ,EAAS,2BACrB,OAAOA,EAAS,oBAAuB,SAChD,GAAI,CACF,IAAMK,EAAS,KAAK,MAAML,EAAS,kBAAkB,EACjD,MAAM,QAAQK,CAAM,IAAGD,EAAqBC,EAClD,MAAQ,CAER,CAGF,MAAO,CACL,QAASN,EAAK,GACd,KAAMC,EAAS,kBAAoBD,EAAK,KACxC,aAAcE,EAASD,EAAS,aAAc,SAAS,EACvD,YAAaC,EAASD,EAAS,YAAa,SAAS,EACrD,QAASA,EAAS,aAAeA,EAAS,SAAW,OACrD,YAAaA,EAAS,aAAeA,EAAS,SAAW,OACzD,eAAgBA,EAAS,gBAAkB,OAC3C,cAAeA,EAAS,eAAiB,GACzC,WAAYA,EAAS,YAAc,GACnC,YAAaC,EAASD,EAAS,YAAa,EAAE,GAAK,OACnD,YAAaA,EAAS,aAAe,OACrC,eAAgBA,EAAS,gBAAkB,OAC3C,YAAaA,EAAS,aAAe,QACrC,gBAAiBC,EAASD,EAAS,gBAAiB,EAAE,GAAK,OAC3D,UAAWC,EAASD,EAAS,UAAW,EAAE,GAAK,OAC/C,YAAaA,EAAS,aAAe,SACrC,WAAYA,EAAS,YAAc,SACnC,SAAUA,EAAS,UAAY,SAC/B,iBAAkBA,EAAS,mBAAqB,GAAK,GAAMC,EAASD,EAAS,iBAAkB,EAAE,GAAK,OACtG,kBAAmBA,EAAS,oBAAsB,GAAK,GAAMC,EAASD,EAAS,kBAAmB,EAAE,GAAK,OACzG,UAAWC,EAASD,EAAS,UAAW,EAAE,GAAK,OAC/C,YAAaC,EAASD,EAAS,YAAa,EAAE,GAAK,OACnD,WAAYC,EAASD,EAAS,WAAY,EAAE,GAAK,OACjD,YAAaC,EAASD,EAAS,YAAa,EAAE,GAAK,OACnD,eAAgBA,EAAS,gBAAkB,OAC3C,mBAAAI,EACA,cAAeL,EAAK,cAChB,CACE,QAASA,EAAK,cAAc,QAC5B,SAAUA,EAAK,cAAc,SAC7B,OACEA,EAAK,cAAc,WAAa,UAChCA,EAAK,cAAc,eACf,CACE,SAAUA,EAAK,cAAc,eAC7B,QAASA,EAAK,cAAc,eAAiB,CAAC,CAChD,EACA,MACR,EACA,OACJ,eAAgBA,EAAK,gBAAkB,OACvC,iBAAkBA,EAAK,iBACnB,CACE,QACEA,EAAK,iBAAiB,sBACtBA,EAAK,iBAAiB,iBACtB,GACF,qBAAsBA,EAAK,iBAAiB,qBAC5C,mBAAoBA,EAAK,iBAAiB,mBAC1C,gBAAiBA,EAAK,iBAAiB,eACzC,EACA,OACJ,eAAgB,MAAM,QAAQA,EAAK,cAAc,EAAIA,EAAK,eAAiB,OAC3E,eAAgB,MAAM,QAAQA,EAAK,cAAc,EAAIA,EAAK,eAAiB,MAC7E,CACF,CAEA,MAAM,eACJF,EACAS,EACe,CACf,IAAMR,EAAW,MAAM,MACrB,GAAG,KAAK,OAAO,sBAAsB,mBAAmBD,CAAO,CAAC,YAChE,CACE,OAAQ,OACR,QAAS,CAAE,eAAgB,kBAAmB,EAC9C,KAAM,KAAK,UAAUS,CAAO,CAC9B,CACF,EAEA,GAAI,CAACR,EAAS,GACZ,MAAM,IAAI,MAAM,8BAA8BA,EAAS,MAAM,EAAE,CAEnE,CAEA,MAAM,iBACJD,EACAS,EACe,CACf,IAAMR,EAAW,MAAM,MACrB,GAAG,KAAK,OAAO,sBAAsB,mBAAmBD,CAAO,CAAC,YAChE,CACE,OAAQ,OACR,QAAS,CAAE,eAAgB,kBAAmB,EAC9C,KAAM,KAAK,UAAUS,CAAO,CAC9B,CACF,EAEA,GAAI,CAACR,EAAS,GACZ,MAAM,IAAI,MAAM,gCAAgCA,EAAS,MAAM,EAAE,CAErE,CAEA,MAAM,kBACJD,EACAU,EACAD,EAC6B,CAC7B,IAAMR,EAAW,MAAM,MACrB,GAAG,KAAK,OAAO,sBAAsB,mBAAmBD,CAAO,CAAC,aAAa,mBAAmBU,CAAS,CAAC,cAC1G,CACE,OAAQ,OACR,QAAS,CAAE,eAAgB,kBAAmB,EAC9C,KAAM,KAAK,UAAUD,CAAO,CAC9B,CACF,EAEA,GAAI,CAACR,EAAS,GACZ,MAAM,IAAI,MAAM,iCAAiCA,EAAS,MAAM,EAAE,EAGpE,OAAOA,EAAS,KAAK,CACvB,CAEA,MAAM,mBAAmBQ,EAA6D,CACpF,IAAMR,EAAW,MAAM,MAAM,GAAG,KAAK,OAAO,2BAA4B,CACtE,OAAQ,OACR,QAAS,CAAE,eAAgB,kBAAmB,EAC9C,KAAM,KAAK,UAAUQ,CAAO,CAC9B,CAAC,EAED,GAAI,CAACR,EAAS,GACZ,MAAM,IAAI,MAAM,mCAAmCA,EAAS,MAAM,EAAE,EAGtE,OAAOA,EAAS,KAAK,CACvB,CAEA,MAAM,qBACJD,EACAS,EAC+B,CAC/B,IAAMR,EAAW,MAAM,MACrB,GAAG,KAAK,OAAO,sBAAsB,mBAAmBD,CAAO,CAAC,WAChE,CACE,OAAQ,OACR,QAAS,CAAE,eAAgB,kBAAmB,EAC9C,KAAM,KAAK,UAAUS,CAAO,CAC9B,CACF,EAEA,GAAI,CAACR,EAAS,GACZ,MAAM,IAAI,MAAM,qCAAqCA,EAAS,MAAM,EAAE,EAGxE,OAAOA,EAAS,KAAK,CACvB,CAEA,MAAM,WAAWQ,EAA2D,CAC1E,IAAMR,EAAW,MAAM,MAAM,GAAG,KAAK,OAAO,aAAc,CACxD,OAAQ,OACR,QAAS,CAAE,eAAgB,kBAAmB,EAC9C,KAAM,KAAK,UAAUQ,CAAO,CAC9B,CAAC,EAED,GAAI,CAACR,EAAS,GACZ,MAAM,IAAI,MAAM,0BAA0BA,EAAS,MAAM,EAAE,EAG7D,OAAOA,EAAS,KAAK,CACvB,CACF,EChNO,IAAMU,EAAN,KAAsB,CAU3B,YAAYC,EAA+B,CAT3C,KAAQ,GAAuB,KAE/B,KAAQ,UACN,IAAI,IACN,KAAQ,kBAAoB,EAE5B,KAAQ,YAAc,GACtB,KAAQ,cAAgB,GAGtB,KAAK,OAASA,EACd,KAAK,qBACHA,EAAO,sBAAwB,CACnC,CAEA,SAAgB,CACd,GAAI,MAAK,YAET,GAAI,CACF,KAAK,GAAK,IAAI,UAAU,KAAK,OAAO,GAAG,EACvC,KAAK,GAAG,OAAS,KAAK,WAAW,KAAK,IAAI,EAC1C,KAAK,GAAG,UAAY,KAAK,cAAc,KAAK,IAAI,EAChD,KAAK,GAAG,QAAU,KAAK,YAAY,KAAK,IAAI,EAC5C,KAAK,GAAG,QAAU,KAAK,YAAY,KAAK,IAAI,CAC9C,OAASC,EAAK,CACZ,KAAK,KAAK,QAAS,CACjB,QAASA,aAAe,MAAQA,EAAI,QAAU,6BAChD,CAAC,CACH,CACF,CAEA,YAAmB,CACjB,KAAK,YAAc,GACf,KAAK,KACP,KAAK,GAAG,QAAU,KAClB,KAAK,GAAG,MAAM,EACd,KAAK,GAAK,KAEd,CAEA,YAAYC,EAAuB,CACjC,KAAK,KAAK,CAAE,KAAM,UAAW,QAAAA,CAAQ,CAAC,CACxC,CAEA,oBAAoBC,EAA8D,CAChF,KAAK,KAAK,CAAE,KAAM,mBAAoB,GAAGA,CAAK,CAAC,CACjD,CAEA,oBAAoBC,EAAqB,CACvC,KAAK,KAAK,CAAE,KAAM,mBAAoB,MAAAA,CAAM,CAAC,CAC/C,CAEA,GAAGC,EAA0BC,EAA4C,CACvE,OAAK,KAAK,UAAU,IAAID,CAAI,GAC1B,KAAK,UAAU,IAAIA,EAAM,IAAI,GAAK,EAEpC,KAAK,UAAU,IAAIA,CAAI,EAAG,IAAIC,CAAO,EAE9B,IAAM,CACX,KAAK,UAAU,IAAID,CAAI,GAAG,OAAOC,CAAO,CAC1C,CACF,CAEQ,KAAKH,EAAqC,CAC5C,KAAK,IAAM,KAAK,GAAG,aAAe,UAAU,MAC9C,KAAK,GAAG,KAAK,KAAK,UAAUA,CAAI,CAAC,CAErC,CAEQ,KAAKE,EAA0BF,EAAY,CAAC,EAAS,CAC3D,IAAMI,EAAwB,CAAE,KAAAF,EAAM,KAAAF,CAAK,EAC3C,KAAK,UAAU,IAAIE,CAAI,GAAG,QAASC,GAAY,CAC7C,GAAI,CACFA,EAAQC,CAAK,CACf,OAASN,EAAK,CACZ,QAAQ,MAAM,wBAAwBI,CAAI,WAAYJ,CAAG,CAC3D,CACF,CAAC,CACH,CAEQ,YAAmB,CACzB,KAAK,kBAAoB,EACzB,KAAK,KAAK,YAAa,CAAC,CAAC,EAGpB,KAAK,eACR,KAAK,KAAK,CACR,KAAM,aACN,QAAS,KAAK,OAAO,QACrB,MAAO,KAAK,OAAO,OAAS,GAC5B,UAAW,KAAK,OAAO,WAAa,EACtC,CAAC,CAEL,CAEQ,cAAcM,EAA2B,CAC/C,IAAIJ,EACJ,GAAI,CACFA,EAAO,KAAK,MAAMI,EAAM,IAAI,CAC9B,MAAQ,CACN,MACF,CAIA,OAFaJ,EAAK,KAEJ,CACZ,IAAK,oBACH,KAAK,cAAgB,GACrB,KAAK,KAAK,oBAAqBA,CAAI,EACnC,MAEF,IAAK,eACH,KAAK,KAAK,eAAgBA,CAAI,EAC9B,MAEF,IAAK,iBACH,KAAK,KAAK,iBAAkBA,CAAI,EAChC,MAEF,IAAK,aACH,KAAK,KAAK,aAAcA,CAAI,EAC5B,MAEF,IAAK,aACH,KAAK,KAAK,aAAcA,CAAI,EAC5B,MAEF,IAAK,WAEH,KAAK,cAAcA,CAAI,EACvB,MAEF,IAAK,cACH,KAAK,KAAK,cAAeA,CAAI,EAE7B,KAAK,KAAK,QAAS,CAAE,GAAGA,EAAM,YAAa,EAAK,CAAC,EACjD,MAEF,IAAK,oBACH,KAAK,KAAK,oBAAqBA,CAAI,EACnC,MAEF,IAAK,iBACH,KAAK,KAAK,iBAAkBA,CAAI,EAChC,MAEF,IAAK,QACH,KAAK,KAAK,QAASA,CAAI,EACvB,MAEF,IAAK,SACH,KAAK,KAAK,SAAUA,CAAI,EACxB,MAEF,QAEE,KACJ,CACF,CAEQ,cAAcA,EAAiB,CAIrC,GAHA,KAAK,KAAK,WAAYA,CAAI,EAGtBA,EAAK,OACP,GAAI,CACF,IAAMK,EACJ,OAAOL,EAAK,QAAW,SAAW,KAAK,MAAMA,EAAK,MAAM,EAAIA,EAAK,OAC/DK,EAAO,YACT,KAAK,KAAK,cAAeA,EAAO,UAAU,CAE9C,MAAQ,CAER,CAEJ,CAEQ,YAAYD,EAAyB,CAE3C,GAAIA,EAAM,OAAS,KAAM,CACvB,KAAK,YAAc,GACnB,KAAK,KAAK,eAAgB,CAAE,KAAMA,EAAM,KAAM,OAAQA,EAAM,OAAQ,UAAW,EAAK,CAAC,EACrF,MACF,CAIA,GAFA,KAAK,KAAK,eAAgB,CAAE,KAAMA,EAAM,KAAM,OAAQA,EAAM,MAAO,CAAC,EAEhE,CAAC,KAAK,aAAe,KAAK,kBAAoB,KAAK,qBAAsB,CAC3E,KAAK,oBACL,IAAME,EAAQ,IAA0B,KAAK,IAAI,EAAG,KAAK,kBAAoB,CAAC,EAC9E,WAAW,IAAM,KAAK,QAAQ,EAAGA,CAAK,CACxC,CACF,CAEQ,aAAoB,CAE1B,KAAK,KAAK,QAAS,CAAE,QAAS,4BAA6B,CAAC,CAC9D,CACF,ECzOO,IAAMC,EAAN,KAAsB,CAK3B,YAAYC,EAAiBC,EAAsB,CAJnD,KAAQ,QAAgD,KAKtD,KAAK,QAAUD,EACf,KAAK,SAAWC,CAClB,CAEA,OAAc,CACZ,KAAK,KAAK,EACV,KAAK,QAAU,WAAW,IAAM,CAC9B,KAAK,SAAS,CAChB,EAAG,KAAK,QAAU,GAAK,GAAI,CAC7B,CAEA,MAAa,CACP,KAAK,UAAY,OACnB,aAAa,KAAK,OAAO,EACzB,KAAK,QAAU,KAEnB,CAEA,cAAcD,EAAuB,CACnC,KAAK,QAAUA,EAEX,KAAK,UAAY,MACnB,KAAK,MAAM,CAEf,CACF,EC1BO,IAAIE,EAAe,GAEnB,SAASC,GAAgBC,EAAsB,CACpDF,EAAeE,CACjB,CCOA,IAAIC,GAAmC,KAOhC,SAASC,GACdC,EACAC,EACAC,EACM,CACN,IAAMC,EACJ,OAAOH,GAAY,SAAW,CAAE,aAAcA,CAAQ,EAAIA,EAEtDI,EAAQ,SAAS,cAAc,OAAO,EAC5CA,EAAM,aAAa,cAAe,MAAM,EAExCA,EAAM,YAAcC,GAAUF,EAAMD,CAAY,EAE5CD,aAAsB,YAAcA,EAAW,WACjDA,EAAW,YAAYG,CAAK,EAG5B,SAAS,KAAK,YAAYA,CAAK,EAEjCN,GAAUM,CACZ,CAEO,SAASE,IAAqB,CAC/BR,KACFA,GAAQ,OAAO,EACfA,GAAU,KAEd,CAGA,SAASS,GAAkBC,EAAuB,CAChD,MAAI,CAACA,GAAQA,IAAS,SACb,+FAELA,IAAS,SAAiB,sBAC1BA,IAAS,UAAkB,mBACxBA,CACT,CAEA,SAASC,GAAgBC,EAAuB,CAC9C,OAAIA,IAAS,QAAgB,OACzBA,IAAS,QAAgB,OACtB,MACT,CAEA,SAASC,GAAaC,EAAsB,CAC1C,IAAIC,EAAID,EAAI,QAAQ,IAAK,EAAE,EAE3B,GADIC,EAAE,SAAW,IAAGA,EAAIA,EAAE,CAAC,EAAIA,EAAE,CAAC,EAAIA,EAAE,CAAC,EAAIA,EAAE,CAAC,EAAIA,EAAE,CAAC,EAAIA,EAAE,CAAC,GAC1DA,EAAE,OAAS,GAAK,CAAC,kBAAkB,KAAKA,CAAC,EAAG,MAAO,GACvD,IAAMC,EAAI,SAASD,EAAE,UAAU,EAAG,CAAC,EAAG,EAAE,EAClCE,EAAI,SAASF,EAAE,UAAU,EAAG,CAAC,EAAG,EAAE,EAClCG,EAAI,SAASH,EAAE,UAAU,EAAG,CAAC,EAAG,EAAE,EACxC,OAAQC,EAAI,IAAMC,EAAI,IAAMC,EAAI,KAAO,IAAO,GAChD,CAEA,SAASX,GAAUF,EAAoBD,EAAgC,CAGrE,IAAMe,EAAKf,EAAe,cAAgB,GACpCgB,EAAUf,EAAK,aACfgB,EAAShB,EAAK,aAAe,UAC7BiB,EAAYb,GAAkBJ,EAAK,UAAU,EAC7CkB,EAAWZ,GAAgBN,EAAK,QAAQ,EAExCmB,EAASnB,EAAK,cAAgB,OAC9BoB,EAAUpB,EAAK,kBAAoBmB,EAAS,UAAY,WACxDE,EAAWrB,EAAK,YAAcmB,EAAS,UAAY,WAEnDG,EAAW,CAACd,GAAaY,CAAO,EAChCG,EAAcvB,EAAK,cAAgBsB,EAAW,yBAA2B,mBACzEE,EAAcxB,EAAK,aAAesB,EAAW,yBAA2B,oBACxEG,EAAeH,EAAW,wBAA0B,mBACpDI,EAAcJ,EAAW,wBAA0B,mBAGnDK,EAAW3B,EAAK,aAAeoB,EAC/BQ,EAAkB5B,EAAK,YACxBQ,GAAamB,CAAQ,EAAI,UAAY,UACtCN,EACEQ,EAAsB7B,EAAK,YAC5BQ,GAAamB,CAAQ,EAAI,kBAAoB,wBAC9CF,EAEEK,EAAW9B,EAAK,cAAgBsB,EAAW,UAAYP,GACvDgB,EAAgBC,GAAiBF,EAAU,GAAG,EAE9CG,EAAejC,EAAK,mBAAqB,OAAaA,EAAK,kBAAoB,cAAiBe,EAEhGmB,EAAcD,IAAiB,cACjCZ,EACCb,GAAayB,CAAY,EAAI,UAAY,UAE9C,MAAO;AAAA;AAAA;AAAA,sBAGalB,CAAO;AAAA,4BACDiB,GAAiBjB,EAAS,GAAG,CAAC;AAAA,qBACrCC,CAAM;AAAA,wBACHW,CAAQ;AAAA,0BACNC,CAAe;AAAA,oCACLC,CAAmB;AAAA,iBACtCT,CAAO;AAAA,2BACGI,CAAW;AAAA,mBACnBH,CAAQ;AAAA,6BACEI,CAAY;AAAA,qBACpBF,CAAW;AAAA;AAAA;AAAA,mBAGbN,CAAS;AAAA,wBACJC,CAAQ;AAAA,2BACLQ,CAAW;AAAA,0BACZO,CAAY;AAAA,4BACVC,CAAW;AAAA,2BACZlC,EAAK,mBAAqB,aAAa;AAAA,wBAC1C8B,CAAQ;AAAA,8BACFC,CAAa;AAAA,mCACRjB,CAAE;AAAA,sCACCA,CAAE;AAAA,6BACXA,CAAE;AAAA,oBACXA,CAAE;AAAA,0BACIA,CAAE;AAAA;AAAA;AAAA;AAAA,0BAIFA,CAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,6BAuQCA,CAAE;AAAA,0CACWA,CAAE;AAAA,qBACvBA,CAAE;AAAA,0BACGA,CAAE;AAAA,iBACXA,CAAE;AAAA;AAAA;AAAA;AAAA,mBAIAA,CAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAsBLA,CAAE;AAAA,2BACSA,CAAE;AAAA,mBACVA,CAAE;AAAA,mCACcA,CAAE;AAAA,iBACpBA,CAAE;AAAA,gBACHA,CAAE;AAAA;AAAA,oBAEEA,CAAE;AAAA,6BACOA,CAAE;AAAA,kBACbA,CAAE;AAAA;AAAA;AAAA;AAAA,uCAImBA,CAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAynB1BA,CAAE;AAAA,cACHA,CAAE;AAAA,aACHA,CAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,6BAsBcA,CAAE;AAAA;AAAA;AAAA;AAAA,uBAIRA,CAAE;AAAA,kBACPA,CAAE;AAAA,uBACGA,CAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAMLA,CAAE;AAAA,mBACHA,CAAE;AAAA,uBACEA,CAAE;AAAA,sBACHA,CAAE;AAAA,cACVA,CAAE;AAAA;AAAA;AAAA,sBAGMA,CAAE;AAAA,mBACLA,CAAE;AAAA,uBACEA,CAAE;AAAA,sBACHA,CAAE;AAAA,cACVA,CAAE;AAAA;AAAA;AAAA,gCAGgBA,CAAE;AAAA,8BACJA,CAAE;AAAA,mBACbA,CAAE;AAAA,uBACEA,CAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAuCHA,CAAE;AAAA,uBACDA,CAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAQzB,CAEA,SAASkB,GAAiBvB,EAAa0B,EAAwB,CAC7D,IAAMC,EAAU3B,EAAI,QAAQ,IAAK,EAAE,EAC7B4B,EAAM,SAASD,EAAS,EAAE,EAChC,GAAI,MAAMC,CAAG,GAAKD,EAAQ,OAAS,EAAG,OAAO3B,EAC7C,IAAME,EAAI,KAAK,IAAI,EAAG,KAAK,IAAI,KAAO0B,GAAO,GAAM,KAAQF,CAAM,CAAC,EAC5DvB,EAAI,KAAK,IAAI,EAAG,KAAK,IAAI,KAAOyB,GAAO,EAAK,KAAQF,CAAM,CAAC,EAC3DtB,EAAI,KAAK,IAAI,EAAG,KAAK,IAAI,KAAMwB,EAAM,KAAQF,CAAM,CAAC,EAC1D,MAAO,KAAMxB,GAAK,GAAOC,GAAK,EAAKC,GAAG,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,CAAC,EACrE,CC/pCA,SAASyB,GAAWC,EAAsB,CACxC,OAAOA,EACJ,QAAQ,KAAM,OAAO,EACrB,QAAQ,KAAM,MAAM,EACpB,QAAQ,KAAM,MAAM,EACpB,QAAQ,KAAM,QAAQ,CAC3B,CAEO,SAASC,GAAeC,EAAqB,CAElD,IAAIF,EAAOD,GAAWG,CAAG,EAGzBF,EAAOA,EAAK,QAAQ,UAAW,IAAI,EAGnCA,EAAOA,EAAK,QACV,6BACA,kDACF,EAGAA,EAAOA,EAAK,QACV,eACA,wCACF,EAGAA,EAAOA,EAAK,QACV,qBACA,8BACF,EAGAA,EAAOA,EAAK,QAAQ,iBAAkB,qBAAqB,EAC3DA,EAAOA,EAAK,QAAQ,aAAc,qBAAqB,EAGvDA,EAAOA,EAAK,QAAQ,aAAc,aAAa,EAC/CA,EAAOA,EAAK,QAAQ,kCAAmC,iBAAiB,EAGxEA,EAAOA,EAAK,QACV,2BACA,sFACF,EAIAA,EAAOA,EAAK,QAAQ,uCAAwC,2BAA2B,EAGvF,IAAMG,EAAQH,EAAK,MAAM;AAAA,CAAI,EACvBI,EAAmB,CAAC,EACtBC,EAAO,GACPC,EAAO,GAEX,QAASC,EAAI,EAAGA,EAAIJ,EAAM,OAAQI,IAAK,CACrC,IAAMC,EAAOL,EAAMI,CAAC,EAGpB,GAAIC,EAAK,SAAS,2BAA2B,EAAG,CAC1CH,IAAQD,EAAO,KAAK,OAAO,EAAGC,EAAO,IACrCC,IAAQF,EAAO,KAAK,OAAO,EAAGE,EAAO,IACzCF,EAAO,KAAKI,CAAI,EAChB,QACF,CAEA,IAAMC,EAAUD,EAAK,MAAM,mBAAmB,EACxCE,EAAUF,EAAK,MAAM,oBAAoB,EAE3CC,GACGJ,IACCC,IAAQF,EAAO,KAAK,OAAO,EAAGE,EAAO,IACzCF,EAAO,KAAK,2BAA2B,EACvCC,EAAO,IAETD,EAAO,KAAK,OAAOK,EAAQ,CAAC,CAAC,OAAO,GAC3BC,GACJJ,IACCD,IAAQD,EAAO,KAAK,OAAO,EAAGC,EAAO,IACzCD,EAAO,KAAK,2BAA2B,EACvCE,EAAO,IAETF,EAAO,KAAK,OAAOM,EAAQ,CAAC,CAAC,OAAO,IAEhCL,IAAQD,EAAO,KAAK,OAAO,EAAGC,EAAO,IACrCC,IAAQF,EAAO,KAAK,OAAO,EAAGE,EAAO,IAGrCE,EAAK,KAAK,IAAM,GAClBJ,EAAO,KAAK,EAAE,EAEdA,EAAO,KAAKI,CAAI,EAGtB,CAEIH,GAAMD,EAAO,KAAK,OAAO,EACzBE,GAAMF,EAAO,KAAK,OAAO,EAG7B,IAAIO,EAAO,GACPC,EAAa,GAEjB,QAAWC,KAAQT,EACbS,EAAK,SAAS,KAAK,EACrBF,GAAQE,EACCA,EAAK,WAAW,KAAK,GAAKA,EAAK,WAAW,KAAK,GACxDD,EAAa,GACbD,GAAQE,GACCA,IAAS,SAAWA,IAAS,SACtCD,EAAa,GACbD,GAAQE,GACCA,EAAK,WAAW,MAAM,EAC/BF,GAAQE,EACCA,EAAK,KAAK,IAAM,GAEpBD,IAAYD,GAAQ,YAGrBA,EAAK,OAAS,GAAK,CAACC,GAAc,CAACD,EAAK,SAAS,KAAK,GAAK,CAACA,EAAK,SAAS,OAAO,GAAK,CAACA,EAAK,SAAS,OAAO,GAAK,CAACA,EAAK,SAAS,QAAQ,IAC1IA,GAAQ,QAEVA,GAAQE,GAKR,CAACF,EAAK,WAAW,KAAK,GAAK,CAACA,EAAK,WAAW,KAAK,GAAK,CAACA,EAAK,WAAW,MAAM,IAC/EA,EAAO,MAAMA,CAAI,QAInBA,EAAOA,EAAK,QAAQ,eAAgB,EAAE,EAGtCA,EAAOA,EAAK,QAAQ,gCAAiC,IAAI,EACzDA,EAAOA,EAAK,QAAQ,4BAA6B,IAAI,EACrDA,EAAOA,EAAK,QAAQ,oBAAqB,IAAI,EAI7C,IAAMJ,EAAIO,EAAe,GAAK,cAC9B,OAAAH,EAAOA,EAAK,QAAQ,OAAQ,sCAAsCJ,CAAC,wBAAwBA,CAAC,oBAAoBA,CAAC,0BAA0BA,CAAC,mBAAmBA,CAAC,wBAAwBA,CAAC,KAAK,EAC9LI,EAAOA,EAAK,QAAQ,QAAS,uCAAuCJ,CAAC,oBAAoBA,CAAC,uBAAuBA,CAAC,wBAAwBA,CAAC,KAAK,EAChJI,EAAOA,EAAK,QAAQ,YAAa,2CAA2CJ,CAAC,qBAAqBA,CAAC,oBAAoBA,CAAC,wBAAwBA,CAAC,uBAAuBA,CAAC,eAAeA,CAAC,KAAK,EAC9LI,EAAOA,EAAK,QAAQ,QAAS,uCAAuCJ,CAAC,uBAAuBA,CAAC,oBAAoBA,CAAC,wBAAwBA,CAAC,uBAAuBA,CAAC,eAAeA,CAAC,KAAK,EACxLI,EAAOA,EAAK,QAAQ,YAAa,yCAAyCJ,CAAC,+BAA+BA,CAAC,oBAAoBA,CAAC,wBAAwBA,CAAC,UAAU,EAE5JI,CACT,CClKA,SAASI,EAAUC,EAAiBC,EAAU,cAA2B,CACvE,IAAMC,EAAM,SAAS,gBAAgB,6BAA8B,KAAK,EACxEA,EAAI,aAAa,UAAWD,CAAO,EACnCC,EAAI,aAAa,OAAQ,cAAc,EACvCA,EAAI,aAAa,QAAS,4BAA4B,EAEtD,QAAWC,KAAKH,EAAO,CACrB,IAAMI,EAAO,SAAS,gBAAgB,6BAA8B,MAAM,EAC1EA,EAAK,aAAa,IAAKD,CAAC,EACxBD,EAAI,YAAYE,CAAI,CACtB,CAEA,OAAOF,CACT,CAEO,SAASG,GAAcC,EAA2B,CACvD,IAAMJ,EAAM,SAAS,gBAAgB,6BAA8B,KAAK,EACxEA,EAAI,aAAa,UAAW,aAAa,EACzCA,EAAI,aAAa,QAAS,4BAA4B,EACtDA,EAAI,aAAa,QAAS,IAAI,EAC9BA,EAAI,aAAa,SAAU,IAAI,EAC3BI,EAAMJ,EAAI,aAAa,OAAQI,CAAI,EAClCJ,EAAI,aAAa,OAAQ,cAAc,EAG5C,IAAME,EAAO,SAAS,gBAAgB,6BAA8B,MAAM,EAC1E,OAAAA,EAAK,aACH,IACA,gdACF,EACAF,EAAI,YAAYE,CAAI,EACbF,CACT,CAEO,SAASK,GAAeD,EAA2B,CACxD,IAAMJ,EAAM,SAAS,gBAAgB,6BAA8B,KAAK,EACxEA,EAAI,aAAa,UAAW,aAAa,EACzCA,EAAI,aAAa,QAAS,4BAA4B,EACtDA,EAAI,aAAa,QAAS,IAAI,EAC9BA,EAAI,aAAa,SAAU,IAAI,EAC3BI,EAAMJ,EAAI,aAAa,OAAQI,CAAI,EAClCJ,EAAI,aAAa,OAAQ,cAAc,EAG5C,IAAME,EAAO,SAAS,gBAAgB,6BAA8B,MAAM,EAC1E,OAAAA,EAAK,aACH,IACA,gdACF,EACAF,EAAI,YAAYE,CAAI,EACbF,CACT,CAQO,SAASM,IAA6B,CAC3C,OAAOC,EAAU,CACf,mPACF,CAAC,CACH,CAEO,SAASC,IAAwB,CACtC,OAAOD,EAAU,CACf,0LACF,CAAC,CACH,CAEO,SAASE,IAAuB,CAErC,OAAOF,EAAU,CACf,kQACF,CAAC,CACH,CAEO,SAASG,IAA2B,CACzC,OAAOH,EAAU,CACf,0TACF,CAAC,CACH,CAEO,SAASI,IAA6B,CAC3C,OAAOJ,EAAU,CACf,2TACF,CAAC,CACH,CAQO,SAASK,IAA8B,CAC5C,OAAOC,EAAU,CACf,uOACF,CAAC,CACH,CAEO,SAASC,IAA0B,CACxC,OAAOD,EAAU,CACf,qVACF,CAAC,CACH,CAEO,SAASE,IAA6B,CAC3C,OAAOF,EAAU,CACf,wPACF,CAAC,CACH,CAEO,SAASG,IAA6B,CAC3C,OAAOH,EAAU,CACf,mPACF,CAAC,CACH,CAEO,SAASI,IAAyB,CACvC,OAAOJ,EAAU,CACf,yiBACF,CAAC,CACH,CAEO,SAASK,IAAyB,CACvC,OAAOL,EAAU,CACf,klBACF,CAAC,CACH,CAEO,SAASM,IAA4B,CAC1C,OAAON,EAAU,CACf,mOACF,CAAC,CACH,CAEO,SAASO,IAA6B,CAC3C,OAAOP,EAAU,CACf,sRACF,CAAC,CACH,CAEO,SAASQ,IAA4B,CAC1C,OAAOR,EAAU,CACf,2IACF,CAAC,CACH,CAuBA,IAAMS,GAA4C,CAChD,YAAaC,GACb,QAASC,GACT,WAAYC,GACZ,WAAYC,GACZ,OAAQC,GACR,OAAQC,GACR,UAAWC,GACX,WAAYC,GACZ,UAAWC,EACb,EAEO,SAASC,GAAcC,EAA0B,CACtD,IAAMC,EAAUZ,GAAQW,CAAI,EAC5B,OAAIC,EAAgBA,EAAQ,EACrBR,GAAe,CACxB,CCjLA,SAASS,GAASC,EAAqB,CACrC,IAAIC,EAAID,EAAI,QAAQ,IAAK,EAAE,EAI3B,GAHIC,EAAE,SAAW,IACfA,EAAIA,EAAE,CAAC,EAAIA,EAAE,CAAC,EAAIA,EAAE,CAAC,EAAIA,EAAE,CAAC,EAAIA,EAAE,CAAC,EAAIA,EAAE,CAAC,GAExCA,EAAE,OAAS,GAAK,CAAC,kBAAkB,KAAKA,CAAC,EAAG,MAAO,eACvD,IAAMC,EAAI,SAASD,EAAE,UAAU,EAAG,CAAC,EAAG,EAAE,EAClCE,EAAI,SAASF,EAAE,UAAU,EAAG,CAAC,EAAG,EAAE,EAClCG,EAAI,SAASH,EAAE,UAAU,EAAG,CAAC,EAAG,EAAE,EACxC,MAAO,GAAGC,CAAC,KAAKC,CAAC,KAAKC,CAAC,EACzB,CAEO,SAASC,GAAiBC,EAAyC,CACxE,GAAM,CAAE,MAAAC,EAAO,SAAAC,EAAU,KAAAC,EAAM,kBAAAC,EAAmB,UAAAC,EAAW,gBAAAC,CAAgB,EAAIN,EAGjF,GAAIE,EAAS,aAAe,GAAO,CACjC,IAAMK,EAAQ,SAAS,cAAc,KAAK,EAC1C,OAAAA,EAAM,MAAM,QAAU,OACfA,CACT,CAEA,IAAMC,EAAS,SAAS,cAAc,KAAK,EAC3CA,EAAO,UAAY,gBAGnB,IAAMC,EAAO,SAAS,cAAc,KAAK,EACzCA,EAAK,UAAY,qBAEjB,IAAMC,EAAajB,GAASS,EAAS,YAAY,EAEjD,GAAIA,EAAS,aAAeA,EAAS,QAAS,CAC5C,IAAMS,EAAS,SAAS,cAAc,KAAK,EAC3CA,EAAO,UAAY,uBACnBA,EAAO,IAAOT,EAAS,aAAeA,EAAS,QAC/CS,EAAO,IAAMT,EAAS,KACtBO,EAAK,YAAYE,CAAM,CACzB,KAAO,CAEL,IAAMC,EAAW,SAAS,cAAc,KAAK,EAC7CA,EAAS,UAAY,gCACrBA,EAAS,MAAM,WAAa,QAAQF,CAAU,UAC9CE,EAAS,MAAM,OAAS,OAExB,IAAMC,EAASX,EAAS,cAAgB,OAClCY,EAAWZ,EAAS,YAAcW,EAAS,UAAYX,EAAS,cAChEa,EAAOC,GAAcF,CAAQ,EACnCF,EAAS,YAAYG,CAAI,EACzBN,EAAK,YAAYG,CAAQ,CAC3B,CAEA,IAAMK,EAAO,SAAS,cAAc,KAAK,EACzCA,EAAK,UAAY,qBAEjB,IAAMC,EAAO,SAAS,cAAc,KAAK,EAKzC,GAJAA,EAAK,UAAY,qBACjBA,EAAK,YAAchB,EAAS,aAAeA,EAAS,KACpDe,EAAK,YAAYC,CAAI,EAEjBhB,EAAS,eAAgB,CAC3B,IAAMiB,EAAW,SAAS,cAAc,KAAK,EAC7CA,EAAS,UAAY,yBACrBA,EAAS,YAAcjB,EAAS,eAChCe,EAAK,YAAYE,CAAQ,CAC3B,CAEAV,EAAK,YAAYQ,CAAI,EACrBT,EAAO,YAAYC,CAAI,EAGvB,IAAMW,EAAU,SAAS,cAAc,KAAK,EAI5C,GAHAA,EAAQ,UAAY,wBAGhBjB,IAAS,SAAU,CACrB,IAAMkB,EAAW,SAAS,cAAc,QAAQ,EAChDA,EAAS,UAAY,oBACrBA,EAAS,aAAa,aAAc,YAAY,EAChDA,EAAS,YAAYC,GAAU,CAAC,EAChCD,EAAS,iBAAiB,QAAS,IAAM,CACvC,IAAME,EAAetB,EAAM,SAAS,EAEpC,GACEK,GACA,CAACiB,EAAa,eACdA,EAAa,QAAU,YACvBA,EAAa,SAAS,OAAS,EAC/B,CACAtB,EAAM,SAAS,CAAE,KAAM,YAAa,MAAO,UAAW,CAAC,EACvD,MACF,CAEA,GAAIsB,EAAa,SAAS,SAAW,EAAG,CACtCtB,EAAM,SAAS,CAAE,KAAM,WAAY,OAAQ,EAAM,CAAC,EAClD,MACF,CAEAuB,GAAsBhB,EAAQP,CAAK,CACrC,CAAC,EACDmB,EAAQ,YAAYC,CAAQ,CAC9B,CAEA,OAAAb,EAAO,YAAYY,CAAO,EAEnBZ,CACT,CAEO,SAASgB,GAAsBC,EAAuBxB,EAAwB,CAEnF,IAAMyB,EAAYD,EAAS,cAC3B,GAAI,CAACC,EAAW,CACdzB,EAAM,SAAS,CAAE,KAAM,WAAY,OAAQ,EAAM,CAAC,EAClD,MACF,CAGA,GAAIyB,EAAU,cAAc,+BAA+B,EAAG,OAE9D,IAAMC,EAAU,SAAS,cAAc,KAAK,EAC5CA,EAAQ,UAAY,+BACpBA,EAAQ,MAAM,QACZ,6MAEF,IAAMC,EAAO,SAAS,cAAc,KAAK,EACzCA,EAAK,MAAM,QACT,gPAEF,IAAMC,EAAQ,SAAS,cAAc,KAAK,EAC1CA,EAAM,MAAM,QAAU,qFACtBA,EAAM,YAAc,oBACpBD,EAAK,YAAYC,CAAK,EAEtB,IAAMV,EAAW,SAAS,cAAc,KAAK,EAC7CA,EAAS,MAAM,QAAU,gGACzBA,EAAS,YAAc,oEACvBS,EAAK,YAAYT,CAAQ,EAEzB,IAAMW,EAAS,SAAS,cAAc,KAAK,EAC3CA,EAAO,MAAM,QAAU,wBAEvB,IAAMC,EAAY,SAAS,cAAc,QAAQ,EACjDA,EAAU,MAAM,QACd,uOACFA,EAAU,YAAc,SACxBA,EAAU,iBAAiB,aAAc,IAAM,CAC7CA,EAAU,MAAM,WAAa,oCAC/B,CAAC,EACDA,EAAU,iBAAiB,aAAc,IAAM,CAC7CA,EAAU,MAAM,WAAa,uBAC/B,CAAC,EACDA,EAAU,iBAAiB,QAAS,IAAMJ,EAAQ,OAAO,CAAC,EAE1D,IAAMK,EAAS,SAAS,cAAc,QAAQ,EA2B9C,GA1BAA,EAAO,MAAM,QACX,kMACFA,EAAO,YAAc,WACrBA,EAAO,iBAAiB,aAAc,IAAM,CAC1CA,EAAO,MAAM,QAAU,MACzB,CAAC,EACDA,EAAO,iBAAiB,aAAc,IAAM,CAC1CA,EAAO,MAAM,QAAU,GACzB,CAAC,EACDA,EAAO,iBAAiB,QAAS,IAAM,CACrCL,EAAQ,OAAO,EACf1B,EAAM,SAAS,CAAE,KAAM,OAAQ,CAAC,EAChCA,EAAM,SAAS,CAAE,KAAM,WAAY,OAAQ,EAAM,CAAC,CACpD,CAAC,EAED6B,EAAO,YAAYC,CAAS,EAC5BD,EAAO,YAAYE,CAAM,EACzBJ,EAAK,YAAYE,CAAM,EACvBH,EAAQ,YAAYC,CAAI,EAGxBD,EAAQ,iBAAiB,QAAUM,GAAM,CACnCA,EAAE,SAAWN,GAASA,EAAQ,OAAO,CAC3C,CAAC,EAGG,CAACD,EAAU,cAAc,4BAA4B,EAAG,CAC1D,IAAMQ,EAAQ,SAAS,cAAc,OAAO,EAC5CA,EAAM,aAAa,sBAAuB,EAAE,EAC5CA,EAAM,YAAc;AAAA;AAAA;AAAA,MAIpBR,EAAU,YAAYQ,CAAK,CAC7B,CAEAR,EAAU,YAAYC,CAAO,CAC/B,CCpMO,SAASQ,GAAgBC,EAAwC,CACtE,GAAM,CAAE,OAAAC,CAAO,EAAID,EAEbE,EAAO,SAAS,cAAc,KAAK,EACzCA,EAAK,UAAY,oBAEjB,IAAMC,EAAM,SAAS,cAAc,KAAK,EACxCA,EAAI,UAAY,mBAEhB,IAAMC,EAAQ,SAAS,cAAc,UAAU,EAC/CA,EAAM,UAAY,eAClBA,EAAM,YAAc,uBACpBA,EAAM,KAAO,EACbA,EAAM,aAAa,aAAc,cAAc,EAC3CC,EACFD,EAAM,MAAM,MAAQ,qBAEpBA,EAAM,MAAM,YAAY,QAAS,qBAAsB,WAAW,EAGpE,IAAME,EAAU,SAAS,cAAc,QAAQ,EAC/CA,EAAQ,UAAY,kBACpBA,EAAQ,aAAa,aAAc,cAAc,EACjDA,EAAQ,SAAW,GACnBA,EAAQ,YAAYC,GAAS,CAAC,EAE9B,SAASC,GAAe,CACtB,IAAMC,EAAQL,EAAM,MAAM,KAAK,EAC1BK,IACLR,EAAOQ,CAAK,EACZL,EAAM,MAAQ,GACdA,EAAM,MAAM,OAAS,OACrBE,EAAQ,SAAW,GACrB,CAEA,OAAAF,EAAM,iBAAiB,QAAS,IAAM,CACpCE,EAAQ,SAAW,CAACF,EAAM,MAAM,KAAK,EAErCA,EAAM,MAAM,OAAS,OACrBA,EAAM,MAAM,OAAS,KAAK,IAAIA,EAAM,aAAc,GAAG,EAAI,IAC3D,CAAC,EAEDA,EAAM,iBAAiB,UAAYM,GAAM,CACnCA,EAAE,MAAQ,SAAW,CAACA,EAAE,WAC1BA,EAAE,eAAe,EACjBF,EAAO,EAEX,CAAC,EAEDF,EAAQ,iBAAiB,QAASE,CAAM,EAExCL,EAAI,YAAYC,CAAK,EACrBD,EAAI,YAAYG,CAAO,EACvBJ,EAAK,YAAYC,CAAG,EAEbD,CACT,CCnDA,SAASS,GAAoBC,EAAyC,CACpE,GAAIA,EAAK,YAAa,CACpB,IAAMC,EAAM,SAAS,cAAc,KAAK,EACxC,OAAAA,EAAI,IAAMD,EAAK,YACfC,EAAI,IAAM,QACVA,EAAI,UAAY,4BACTA,CACT,CACA,IAAMC,EAAO,SAAS,cAAc,MAAM,EACpCC,EAASH,EAAK,cAAgB,OAC9BI,EAAWJ,EAAK,YAAcG,EAAS,UAAYH,EAAK,WAC9D,OAAAE,EAAK,YAAYG,GAAeD,CAAQ,CAAC,EAClCF,CACT,CAEO,SAASI,GAA2BN,EAA4B,CACrE,MAAO,CACL,aAAaO,EAAmC,CAC9C,OAAIA,EAAQ,OAAS,OACZC,GAAiBD,EAASP,CAAI,EAEhCS,GAAsBF,EAASP,CAAI,CAC5C,EACA,iBAA+B,CAC7B,OAAOU,GAAsBV,CAAI,CACnC,EACA,eAA6B,CAC3B,OAAOW,GAAuBX,CAAI,CACpC,CACF,CACF,CAEA,SAASQ,GACPD,EACAP,EACa,CACb,IAAMY,EAAM,SAAS,cAAc,KAAK,EACxCA,EAAI,UAAY,8CAEhB,IAAMC,EAAS,SAAS,cAAc,KAAK,EACvCC,EAAM,sCACV,OAAId,EAAK,cAAgB,UAAWc,GAAO,0BAClCd,EAAK,cAAgB,WAAUc,GAAO,0BAC/CD,EAAO,UAAYC,EACnBD,EAAO,YAAcN,EAAQ,QAE7BK,EAAI,YAAYC,CAAM,EACfD,CACT,CAEA,SAASH,GACPF,EACAP,EACa,CACb,IAAMY,EAAM,SAAS,cAAc,KAAK,EACxCA,EAAI,UAAY,mDAGhB,IAAMG,EAAW,SAAS,cAAc,KAAK,EAC7CA,EAAS,UAAY,sBACrBA,EAAS,YAAYhB,GAAoBC,CAAI,CAAC,EAC9CY,EAAI,YAAYG,CAAQ,EAIxB,IAAMC,EAAS,SAAS,cAAc,KAAK,EAC3C,OAAAA,EAAO,UAAY,qDACnBA,EAAO,UAAYC,GAAeV,EAAQ,OAAO,EAEjDK,EAAI,YAAYI,CAAM,EACfJ,CACT,CAEA,SAASF,GAAsBV,EAAyC,CACtE,IAAMY,EAAM,SAAS,cAAc,KAAK,EACxCA,EAAI,UAAY,mDAGhB,IAAMG,EAAW,SAAS,cAAc,KAAK,EAC7CA,EAAS,UAAY,sBACrBA,EAAS,YAAYhB,GAAoBC,CAAI,CAAC,EAC9CY,EAAI,YAAYG,CAAQ,EAExB,IAAMC,EAAS,SAAS,cAAc,KAAK,EAC3C,OAAAA,EAAO,UACL,qDACFA,EAAO,YAAc,GAErBJ,EAAI,YAAYI,CAAM,EAGrBJ,EAAY,cAAgBI,EAEtBJ,CACT,CAEA,SAASD,GAAuBX,EAAyC,CACvE,IAAMY,EAAM,SAAS,cAAc,KAAK,EACxCA,EAAI,UAAY,mDAGhB,IAAMG,EAAW,SAAS,cAAc,KAAK,EAC7CA,EAAS,UAAY,sBACrBA,EAAS,YAAYhB,GAAoBC,CAAI,CAAC,EAC9CY,EAAI,YAAYG,CAAQ,EAExB,IAAMG,EAAK,SAAS,cAAc,KAAK,EACvCA,EAAG,UAAY,iBACf,QAAS,EAAI,EAAG,EAAI,EAAG,IAAK,CAC1B,IAAMC,EAAM,SAAS,cAAc,KAAK,EACxCA,EAAI,UAAY,qBAChBD,EAAG,YAAYC,CAAG,CACpB,CACA,OAAAP,EAAI,YAAYM,CAAE,EACXN,CACT,CCtHO,SAASQ,GAAkBC,EAA0C,CAC1E,GAAM,CAAE,SAAAC,EAAU,QAASC,EAAM,SAAAC,CAAS,EAAIH,EAExCI,EAAY,SAAS,cAAc,KAAK,EAC9CA,EAAU,UAAY,iBAEtB,IAAMC,EAAa,SAAS,cAAc,KAAK,EAC/CA,EAAW,UAAY,0BACvBA,EAAW,YAAcJ,EACzBG,EAAU,YAAYC,CAAU,EAEhC,IAAMC,EAAc,SAAS,cAAc,KAAK,EAChDA,EAAY,UAAY,yBAExB,QAAWC,KAAOL,EAAM,CACtB,IAAMM,EAAM,SAAS,cAAc,QAAQ,EAC3CA,EAAI,UAAY,wBAEhB,IAAMC,EAAOC,GAAcH,EAAI,IAAI,EACnCC,EAAI,YAAYC,CAAI,EAEpB,IAAME,EAAQ,SAAS,cAAc,MAAM,EAC3CA,EAAM,YAAcJ,EAAI,MACxBC,EAAI,YAAYG,CAAK,EAErBH,EAAI,iBAAiB,QAAS,IAAML,EAASI,EAAI,KAAK,CAAC,EACvDD,EAAY,YAAYE,CAAG,CAC7B,CAEA,OAAAJ,EAAU,YAAYE,CAAW,EAC1BF,CACT,CCjCO,SAASQ,GACdC,EACa,CACb,GAAM,CAAE,WAAAC,EAAY,WAAAC,CAAW,EAAIF,EAE7BG,EAAY,SAAS,cAAc,KAAK,EAC9CA,EAAU,UAAY,kBAEtB,IAAMC,EAAQ,SAAS,cAAc,KAAK,EAC1CA,EAAM,UAAY,wBAClBA,EAAM,YAAc,WACpBD,EAAU,YAAYC,CAAK,EAE3B,IAAMC,EAAO,SAAS,cAAc,KAAK,EACzCA,EAAK,UAAY,uBACjBA,EAAK,YAAcH,EACf,iDACA,2BACJC,EAAU,YAAYE,CAAI,EAE1B,IAAMC,EAAU,SAAS,cAAc,KAAK,EAC5CA,EAAQ,UAAY,0BAEpB,IAAMC,EAAQ,SAAS,cAAc,QAAQ,EAC7CA,EAAM,UAAY,6CAClBA,EAAM,aAAa,aAAc,WAAW,EAC5CA,EAAM,YAAYC,GAAa,CAAC,EAEhC,IAAMC,EAAU,SAAS,cAAc,QAAQ,EAC/CA,EAAQ,UAAY,+CACpBA,EAAQ,aAAa,aAAc,aAAa,EAChDA,EAAQ,YAAYC,GAAe,CAAC,EAEpC,SAASC,EAAeC,EAA6B,CAGnD,IAFAX,EAAWW,CAAM,EAEVT,EAAU,YACfA,EAAU,YAAYA,EAAU,UAAU,EAE5C,IAAMU,EAAS,SAAS,cAAc,KAAK,EAC3CA,EAAO,UAAY,yBACnBA,EAAO,YAAc,4BACrBV,EAAU,YAAYU,CAAM,CAC9B,CAEA,OAAAN,EAAM,iBAAiB,QAAS,IAAMI,EAAe,IAAI,CAAC,EAC1DF,EAAQ,iBAAiB,QAAS,IAAME,EAAe,MAAM,CAAC,EAE9DL,EAAQ,YAAYC,CAAK,EACzBD,EAAQ,YAAYG,CAAO,EAC3BN,EAAU,YAAYG,CAAO,EAEtBH,CACT,CCtDO,SAASW,GAAgBC,EAAwC,CACtE,GAAM,CAAE,WAAAC,EAAY,WAAAC,EAAY,SAAAC,CAAS,EAAIH,EAEvCI,EAAY,SAAS,cAAc,KAAK,EAC9CA,EAAU,UAAY,oBAEtB,IAAMC,EAAO,SAAS,cAAc,KAAK,EACzCA,EAAK,UAAY,yBACjBA,EAAK,YAAcJ,EACnBG,EAAU,YAAYC,CAAI,EAE1B,IAAMC,EAAM,SAAS,cAAc,KAAK,EACxCA,EAAI,UAAY,wBAEhB,IAAMC,EAAQ,SAAS,cAAc,OAAO,EAC5CA,EAAM,UAAY,qBAClBA,EAAM,KAAO,QACbA,EAAM,YAAc,iBACpBA,EAAM,aAAa,aAAc,eAAe,EAEhD,IAAMC,EAAY,SAAS,cAAc,QAAQ,EACjDA,EAAU,UAAY,sBACtBA,EAAU,YAAcN,EACxBM,EAAU,SAAW,GAErBD,EAAM,iBAAiB,QAAS,IAAM,CACpCC,EAAU,SAAW,CAACC,GAAaF,EAAM,KAAK,CAChD,CAAC,EAED,SAASG,GAAe,CACtB,IAAMC,EAAQJ,EAAM,MAAM,KAAK,EAC/B,GAAI,CAACE,GAAaE,CAAK,EAAG,OAE1BR,EAASQ,CAAK,EAGdL,EAAI,OAAO,EACXD,EAAK,OAAO,EACZ,IAAMO,EAAO,SAAS,cAAc,KAAK,EACzCA,EAAK,UAAY,oBACjBA,EAAK,YAAc,4BACnBR,EAAU,YAAYQ,CAAI,CAC5B,CAEA,OAAAL,EAAM,iBAAiB,UAAYM,GAAM,CACnCA,EAAE,MAAQ,UACZA,EAAE,eAAe,EACjBH,EAAO,EAEX,CAAC,EAEDF,EAAU,iBAAiB,QAASE,CAAM,EAE1CJ,EAAI,YAAYC,CAAK,EACrBD,EAAI,YAAYE,CAAS,EACzBJ,EAAU,YAAYE,CAAG,EAElBF,CACT,CAEA,SAASK,GAAaE,EAAwB,CAC5C,MAAO,6BAA6B,KAAKA,EAAM,KAAK,CAAC,CACvD,CChEO,SAASG,GAAkBC,EAA0C,CAC1E,GAAM,CAAE,SAAAC,CAAS,EAAID,EAEfE,EAAY,SAAS,cAAc,KAAK,EAC9CA,EAAU,UAAY,sBAEtB,IAAMC,EAAU,SAAS,cAAc,KAAK,EAC5CA,EAAQ,UAAY,yBACpBA,EAAQ,YACN,0EACFD,EAAU,YAAYC,CAAO,EAG7B,IAAMC,EAAY,SAAS,cAAc,OAAO,EAChDA,EAAU,UAAY,uBACtBA,EAAU,YAAc,kBACxBF,EAAU,YAAYE,CAAS,EAE/B,IAAMC,EAAY,SAAS,cAAc,OAAO,EAChDA,EAAU,UAAY,uBACtBA,EAAU,KAAO,OACjBA,EAAU,YAAc,YACxBA,EAAU,aAAa,aAAc,MAAM,EAC3CH,EAAU,YAAYG,CAAS,EAG/B,IAAMC,EAAa,SAAS,cAAc,OAAO,EACjDA,EAAW,UAAY,uBACvBA,EAAW,YAAc,UACzBJ,EAAU,YAAYI,CAAU,EAEhC,IAAMC,EAAa,SAAS,cAAc,OAAO,EACjDA,EAAW,UAAY,uBACvBA,EAAW,KAAO,QAClBA,EAAW,YAAc,iBACzBA,EAAW,SAAW,GACtBA,EAAW,aAAa,aAAc,eAAe,EACrDL,EAAU,YAAYK,CAAU,EAGhC,IAAMC,EAAW,SAAS,cAAc,OAAO,EAC/CA,EAAS,UAAY,uBACrBA,EAAS,YAAc,YACvBN,EAAU,YAAYM,CAAQ,EAE9B,IAAMC,EAAe,SAAS,cAAc,UAAU,EACtDA,EAAa,UAAY,0BACzBA,EAAa,YAAc,uBAC3BA,EAAa,KAAO,EACpBA,EAAa,SAAW,GACxBA,EAAa,aAAa,aAAc,SAAS,EACjDP,EAAU,YAAYO,CAAY,EAGlC,IAAMC,EAAU,SAAS,cAAc,KAAK,EAC5CA,EAAQ,UAAY,uBACpBA,EAAQ,MAAM,QAAU,OACxBR,EAAU,YAAYQ,CAAO,EAG7B,IAAMC,EAAY,SAAS,cAAc,QAAQ,EACjDA,EAAU,UAAY,wBACtBA,EAAU,YAAc,eACxBA,EAAU,SAAW,GACrBT,EAAU,YAAYS,CAAS,EAE/B,SAASC,GAAoB,CAC3B,IAAMC,EAAQN,EAAW,MAAM,KAAK,EAC9BO,EAAUL,EAAa,MAAM,KAAK,EAExC,MADmB,6BAA6B,KAAKI,CAAK,GACrCC,EAAQ,OAAS,CACxC,CAEA,SAASC,GAAqB,CAC5BJ,EAAU,SAAW,CAACC,EAAS,CACjC,CAEAL,EAAW,iBAAiB,QAASQ,CAAY,EACjDN,EAAa,iBAAiB,QAASM,CAAY,EAEnD,SAASC,GAAe,CACtB,GAAI,CAACJ,EAAS,EAAG,OAEjB,IAAMK,EAAO,CACX,KAAMZ,EAAU,MAAM,KAAK,EAC3B,MAAOE,EAAW,MAAM,KAAK,EAC7B,QAASE,EAAa,MAAM,KAAK,CACnC,EAGAE,EAAU,SAAW,GACrBA,EAAU,YAAc,aACxBN,EAAU,SAAW,GACrBE,EAAW,SAAW,GACtBE,EAAa,SAAW,GAExBR,EAASgB,CAAI,EAGbf,EAAU,YAAc,GACxB,IAAMgB,EAAe,SAAS,cAAc,KAAK,EACjDA,EAAa,UAAY,8BACzBA,EAAa,YAAc,yCAC3BhB,EAAU,YAAYgB,CAAY,CACpC,CAEA,OAAAP,EAAU,iBAAiB,QAASK,CAAM,EAG1CT,EAAW,iBAAiB,UAAYY,GAAM,CACxCA,EAAE,MAAQ,UACZA,EAAE,eAAe,EACjBH,EAAO,EAEX,CAAC,EACDX,EAAU,iBAAiB,UAAYc,GAAM,CACvCA,EAAE,MAAQ,UACZA,EAAE,eAAe,EACjBH,EAAO,EAEX,CAAC,EAEMd,CACT,CC1HA,SAASkB,IAAgC,CACvC,IAAMC,EAAM,SAAS,gBAAgB,6BAA8B,KAAK,EACxEA,EAAI,aAAa,QAAS,IAAI,EAC9BA,EAAI,aAAa,SAAU,IAAI,EAC/BA,EAAI,aAAa,UAAW,aAAa,EACzCA,EAAI,aAAa,OAAQ,MAAM,EAC/BA,EAAI,aAAa,SAAU,cAAc,EACzCA,EAAI,aAAa,eAAgB,IAAI,EACrCA,EAAI,aAAa,iBAAkB,OAAO,EAC1CA,EAAI,aAAa,kBAAmB,OAAO,EAE3C,IAAMC,EAAS,SAAS,gBAAgB,6BAA8B,QAAQ,EAC9EA,EAAO,aAAa,KAAM,KAAK,EAC/BA,EAAO,aAAa,KAAM,KAAK,EAC/BA,EAAO,aAAa,IAAK,IAAI,EAC7BD,EAAI,YAAYC,CAAM,EAEtB,IAAMC,EAAO,SAAS,gBAAgB,6BAA8B,MAAM,EAC1EA,EAAK,aAAa,KAAM,KAAK,EAC7BA,EAAK,aAAa,KAAM,IAAI,EAC5BA,EAAK,aAAa,KAAM,KAAK,EAC7BA,EAAK,aAAa,KAAM,KAAK,EAC7BF,EAAI,YAAYE,CAAI,EAEpB,IAAMC,EAAM,SAAS,gBAAgB,6BAA8B,QAAQ,EAC3E,OAAAA,EAAI,aAAa,KAAM,KAAK,EAC5BA,EAAI,aAAa,KAAM,KAAK,EAC5BA,EAAI,aAAa,IAAK,GAAG,EACzBA,EAAI,aAAa,OAAQ,cAAc,EACvCA,EAAI,aAAa,SAAU,MAAM,EACjCH,EAAI,YAAYG,CAAG,EAEZH,CACT,CAEA,SAASI,IAAiC,CACxC,IAAMJ,EAAM,SAAS,gBAAgB,6BAA8B,KAAK,EACxEA,EAAI,aAAa,QAAS,IAAI,EAC9BA,EAAI,aAAa,SAAU,IAAI,EAC/BA,EAAI,aAAa,UAAW,aAAa,EACzCA,EAAI,aAAa,OAAQ,MAAM,EAC/BA,EAAI,aAAa,SAAU,cAAc,EACzCA,EAAI,aAAa,eAAgB,IAAI,EACrCA,EAAI,aAAa,iBAAkB,OAAO,EAC1CA,EAAI,aAAa,kBAAmB,OAAO,EAE3C,IAAMC,EAAS,SAAS,gBAAgB,6BAA8B,QAAQ,EAC9EA,EAAO,aAAa,KAAM,KAAK,EAC/BA,EAAO,aAAa,KAAM,KAAK,EAC/BA,EAAO,aAAa,IAAK,IAAI,EAC7BD,EAAI,YAAYC,CAAM,EAEtB,IAAMI,EAAW,SAAS,gBAAgB,6BAA8B,UAAU,EAClF,OAAAA,EAAS,aAAa,SAAU,wBAAwB,EACxDL,EAAI,YAAYK,CAAQ,EAEjBL,CACT,CAEO,SAASM,GAAmBC,EAA2C,CAC5E,GAAM,CAAE,SAAAC,EAAU,UAAAC,CAAU,EAAIF,EAE1BG,EAAY,SAAS,cAAc,KAAK,EAC9CA,EAAU,UAAY,uBAGtB,IAAMC,EAAW,SAAS,cAAc,KAAK,EAC7CA,EAAS,UAAY,oBACrBA,EAAS,YAAYZ,GAAe,CAAC,EACrCW,EAAU,YAAYC,CAAQ,EAG9B,IAAMC,EAAU,SAAS,cAAc,KAAK,EAC5CA,EAAQ,UAAY,uBACpBA,EAAQ,YAAc,6BACtBF,EAAU,YAAYE,CAAO,EAG7B,IAAMC,EAAU,SAAS,cAAc,KAAK,EAC5CA,EAAQ,UAAY,uBACpBA,EAAQ,YACN,yFACFH,EAAU,YAAYG,CAAO,EAG7B,IAAMC,EAAO,SAAS,cAAc,KAAK,EACzCA,EAAK,UAAY,oBAGjB,IAAMC,EAAe,SAAS,cAAc,UAAU,EACtDA,EAAa,UAAY,wBACzBA,EAAa,YAAc,kBAC3BA,EAAa,KAAO,EACpBA,EAAa,aAAa,aAAc,SAAS,EACjDD,EAAK,YAAYC,CAAY,EAG7B,IAAMC,EAAa,SAAS,cAAc,OAAO,EACjDA,EAAW,UAAY,qBACvBA,EAAW,KAAO,QAClBA,EAAW,YAAc,qCACzBA,EAAW,aAAa,aAAc,0BAA0B,EAChEF,EAAK,YAAYE,CAAU,EAG3B,IAAMC,EAAY,SAAS,cAAc,QAAQ,EASjD,GARAA,EAAU,UAAY,sBACtBA,EAAU,YAAc,eACxBA,EAAU,SAAW,GACrBH,EAAK,YAAYG,CAAS,EAE1BP,EAAU,YAAYI,CAAI,EAGtBL,EAAW,CACb,IAAMS,EAAa,SAAS,cAAc,QAAQ,EAClDA,EAAW,UAAY,uBACvBA,EAAW,YAAc,iBACzBA,EAAW,iBAAiB,QAAST,CAAS,EAC9CC,EAAU,YAAYQ,CAAU,CAClC,CAEA,SAASC,GAAoB,CAC3B,OAAOJ,EAAa,MAAM,KAAK,EAAE,OAAS,CAC5C,CAEA,SAASK,GAAqB,CAC5BH,EAAU,SAAW,CAACE,EAAS,CACjC,CAEAJ,EAAa,iBAAiB,QAASK,CAAY,EAEnD,SAASC,GAAe,CACtB,GAAI,CAACF,EAAS,EAAG,OAEjB,IAAMG,EAAQN,EAAW,MAAM,KAAK,EAC9BO,EAAmD,CACvD,QAASR,EAAa,MAAM,KAAK,CACnC,EACIO,IACFC,EAAK,aAAeD,GAItBL,EAAU,SAAW,GACrBA,EAAU,YAAc,aACxBF,EAAa,SAAW,GACxBC,EAAW,SAAW,GAEtBR,EAASe,CAAI,EAGbb,EAAU,YAAc,GAExB,IAAMc,EAAc,SAAS,cAAc,KAAK,EAChDA,EAAY,UAAY,+CACxBA,EAAY,YAAYpB,GAAgB,CAAC,EACzCM,EAAU,YAAYc,CAAW,EAEjC,IAAMC,EAAe,SAAS,cAAc,KAAK,EAMjD,GALAA,EAAa,UAAY,4BACzBA,EAAa,YAAc,oDAC3Bf,EAAU,YAAYe,CAAY,EAG9BhB,EAAW,CACb,IAAMiB,EAAc,SAAS,cAAc,QAAQ,EACnDA,EAAY,UAAY,uBACxBA,EAAY,YAAc,iBAC1BA,EAAY,iBAAiB,QAASjB,CAAS,EAC/CC,EAAU,YAAYgB,CAAW,CACnC,CACF,CAEA,OAAAT,EAAU,iBAAiB,QAASI,CAAM,EAEnCX,CACT,CCxJO,SAASiB,GAAiBC,EAAyC,CACxE,GAAM,CACJ,MAAAC,EACA,SAAAC,EACA,QAAAC,EACA,KAAAC,EACA,SAAAC,EACA,cAAAC,EACA,gBAAAC,EACA,WAAAC,EACA,kBAAAC,EACA,kBAAAC,EACA,oBAAAC,EACA,eAAAC,EACA,UAAAC,EACA,gBAAAC,CACF,EAAId,EAGEe,EAAiBb,EAAS,aAAeA,EAAS,QAClDc,EAAUC,GAA2B,CACzC,UAAWf,EAAS,UACpB,YAAaA,EAAS,YACtB,YAAaa,EACb,YAAab,EAAS,YACtB,UAAWA,EAAS,SACtB,CAAC,EAGKgB,EAAY,SAAS,cAAc,KAAK,EAC1Cd,IAAS,SACXc,EAAU,UAAY,8BAA8Bb,CAAQ,GAE5Da,EAAU,UAAY,gBAIxB,IAAMC,EAASC,GAAiB,CAC9B,MAAAnB,EACA,SAAAC,EACA,KAAAE,EACA,GAAIA,IAAS,SAAW,CACtB,kBAAmB,IAAM,CACvBH,EAAM,SAAS,CAAE,KAAM,YAAa,MAAO,YAAa,CAAC,EACzDoB,GAAmB,CACrB,EACA,UAAAR,CACF,EAAI,CAAC,EACL,gBAAAC,CACF,CAAC,EACDI,EAAU,YAAYC,CAAM,EAG5B,IAAMG,EAAU,SAAS,cAAc,KAAK,EAC5CA,EAAQ,UAAY,kBACpBJ,EAAU,YAAYI,CAAO,EAG7B,IAAMC,EAAYC,GAAgB,CAAE,OAAQlB,CAAc,CAAC,EAC3DiB,EAAU,MAAM,QAAU,OAC1BL,EAAU,YAAYK,CAAS,EAI/B,IAAME,EAAcvB,EAAS,gBAAkB,GAC1CuB,IACHF,EAAU,MAAM,cAAgB,QAGlC,SAASG,GAAiC,CACxC,IAAMC,EAAU,SAAS,cAAc,KAAK,EAC5CA,EAAQ,UAAY,iBACpBA,EAAQ,aAAa,wBAAyB,MAAM,EACpD,IAAMC,EAAMC,EAAe,GAAK,cAChCF,EAAQ,MAAM,QAAU,gBAAgBC,CAAG,sBAAsBA,CAAG,aAAaA,CAAG,IACpF,IAAME,EAAO,SAAS,cAAc,GAAG,EACvC,OAAAA,EAAK,KAAO,oBACZA,EAAK,OAAS,SACdA,EAAK,IAAM,sBACXA,EAAK,YAAc,YACnBH,EAAQ,YAAY,SAAS,eAAe,aAAa,CAAC,EAC1DA,EAAQ,YAAYG,CAAI,EACjBH,CACT,CAEA,GAAIF,EAAa,CAKf,IAAMM,EADcL,EAAkB,EACE,UACxCR,EAAU,YAAYQ,EAAkB,CAAC,EAGzC,IAAIM,EAAc,GACQ,IAAI,iBAAiB,IAAM,CACnD,GAAIA,EAAa,OACjBA,EAAc,GACd,IAAMC,EAAWf,EAAU,cAAc,iBAAiB,EAC1D,GAAI,CAACe,EACHf,EAAU,YAAYQ,EAAkB,CAAC,UAGrCO,EAAS,YAAcF,EAAqB,CAE9C,IAAMG,EAAQR,EAAkB,EAChCO,EAAS,YAAYC,CAAK,CAC5B,KAAO,CACL,IAAMC,EAAIF,EAAS,MACbG,EAAK,iBAAiBH,CAAQ,EACpC,GAAIG,EAAG,UAAY,QAAUA,EAAG,aAAe,UAAYA,EAAG,UAAY,IAAK,CAC7E,IAAMR,EAAMC,EAAe,GAAK,cAChCM,EAAE,QAAU,gBAAgBP,CAAG,sBAAsBA,CAAG,aAAaA,CAAG,GAC1E,CACF,CAEFI,EAAc,EAChB,CAAC,EACiB,QAAQd,EAAW,CACnC,UAAW,GACX,QAAS,GACT,WAAY,GACZ,gBAAiB,CAAC,QAAS,OAAO,EAClC,cAAe,EACjB,CAAC,CACH,CAGIhB,EAAS,YAAcA,EAAS,aAAe,WACjDgB,EAAU,MAAM,WAAahB,EAAS,YAIxC,IAAMmC,EAAqB,GAGvBC,EAAuB,EACvBC,EAAsC,KACtCC,EAAgC,KAChCC,EAAgC,KAChCC,EAAiC,KACjCC,EAAkC,KAClCC,EAAkB,GAClBC,EAAoC,KACpCC,EAAoC,KACpCC,EAAqC,KACrCC,EAAmC,KAEvC,SAASC,IAAgC,CACvC,GAAID,EAAc,OAClBA,EAAe,SAAS,cAAc,KAAK,EAC3CA,EAAa,UAAY,oBACzB,IAAME,EAAO,SAAS,cAAc,KAAK,EACzCA,EAAK,UAAY,sBACjB,QAASC,EAAI,EAAGA,EAAI,EAAGA,IAAK,CAC1B,IAAMC,EAAM,SAAS,cAAc,MAAM,EACzCA,EAAI,UAAY,qBAChBF,EAAK,YAAYE,CAAG,CACtB,CACAJ,EAAa,YAAYE,CAAI,EAC7B5B,EAAQ,YAAY0B,CAAY,CAClC,CAEA,SAASK,GAAkC,CACrCL,IACFA,EAAa,OAAO,EACpBA,EAAe,KAEnB,CAEA,SAASM,GAAqB,CAC5BhC,EAAQ,YAAc,GACtBgB,EAAuB,EACvBC,EAAkB,KAClBC,EAAY,KACZC,EAAY,KACZC,EAAa,KACbC,EAAc,KACdG,EAAgB,KAChBC,EAAiB,KACjBC,EAAe,KACfJ,EAAkB,GAClBC,EAAgB,IAClB,CAEA,SAASU,IAA6B,CACpC,GAAIX,EAAiB,OACrBA,EAAkB,GAKlB,IAAMY,EAA0B,CAC9B,GAAI,UACJ,KAAM,YACN,QANkBtD,EAAS,gBAAkB,mCAO7C,UAAW,KAAK,IAAI,CACtB,EACMuD,EAAMzC,EAAQ,aAAawC,CAAU,EAC3CC,EAAI,UAAU,IAAI,6BAA6B,EAE/CnC,EAAQ,YAAYmC,CAAG,EAGvB,IAAMC,EAAYxD,EAAS,mBAC3B,QAAQ,IAAI,iDAAkDwD,CAAS,EACnEA,GAAaA,EAAU,OAAS,IAClCb,EAAgB,SAAS,cAAc,KAAK,EAC5CA,EAAc,UAAY,qBAE1Ba,EAAU,MAAM,EAAG,CAAC,EAAE,QAASC,GAAM,CACnC,IAAMC,EAAO,SAAS,cAAc,QAAQ,EAC5CA,EAAK,UAAY,yBACjBA,EAAK,YAAcD,EACnBC,EAAK,iBAAiB,QAAS,IAAM,CACnCtD,EAAcqD,CAAC,EAEXd,IACFA,EAAc,OAAO,EACrBA,EAAgB,KAEpB,CAAC,EACDA,EAAe,YAAYe,CAAI,CACjC,CAAC,EAEDtC,EAAQ,YAAYuB,CAAa,EAErC,CAEA,SAASgB,IAAoB,CAC3B,IAAMC,EAAW5D,EAAS,cAC1B,GAAI,CAAC4D,GAAY,CAACA,EAAS,QAAS,OAGpC,IAAMC,EAGF,CACF,UAAW,CACT,SAAU,8BACV,QAAS,CACP,CAAE,MAAO,mBAAoB,KAAM,aAAc,EACjD,CAAE,MAAO,aAAc,KAAM,SAAU,EACvC,CAAE,MAAO,gBAAiB,KAAM,YAAa,EAC7C,CAAE,MAAO,iBAAkB,KAAM,YAAa,CAChD,CACF,EACA,KAAM,CACJ,SAAU,6BACV,QAAS,CACP,CAAE,MAAO,kBAAmB,KAAM,QAAS,EAC3C,CAAE,MAAO,kBAAmB,KAAM,QAAS,EAC3C,CAAE,MAAO,wBAAyB,KAAM,YAAa,EACrD,CAAE,MAAO,iBAAkB,KAAM,YAAa,CAChD,CACF,EACA,SAAU,CACR,SAAU,yBACV,QAAS,CACP,CAAE,MAAO,yBAA0B,KAAM,WAAY,EACrD,CAAE,MAAO,kBAAmB,KAAM,YAAa,EAC/C,CAAE,MAAO,mBAAoB,KAAM,YAAa,EAChD,CAAE,MAAO,iBAAkB,KAAM,WAAY,CAC/C,CACF,CACF,EAEIC,EACAC,EAEJ,GAAIH,EAAS,WAAa,UAAYA,EAAS,OAC7CE,EAAWF,EAAS,OAAO,SAC3BG,EAAcH,EAAS,OAAO,gBACrBA,EAAS,UAAYC,EAAUD,EAAS,QAAQ,EAAG,CAC5D,IAAMI,EAAOH,EAAUD,EAAS,QAAQ,EACxCE,EAAWE,EAAK,SAChBD,EAAcC,EAAK,OACrB,KACE,QAGFZ,EAAa,EACb/B,EAAU,MAAM,QAAU,OAE1BkB,EAAY0B,GAAkB,CAC5B,SAAAH,EACA,QAASC,EACT,SAAWG,GAAU,CACnB7D,EAAgB6D,CAAK,EACrB7C,EAAU,MAAM,QAAU,EAC5B,CACF,CAAC,EACDD,EAAQ,YAAYmB,CAAS,CAC/B,CAEA,SAASpB,IAA2B,CAC9BsB,IACJA,EAAc0B,GAAgB,CAC5B,WACE,yFACF,WAAY,OACZ,SAAWC,GAAU,CACnB5D,EAAkB4D,CAAK,EACvB3B,EAAc,IAChB,CACF,CAAC,EACDrB,EAAQ,YAAYqB,CAAW,EAC/B4B,EAAe,EACjB,CAEA,SAASC,IAA2B,CAC9B7B,IACJA,EAAc0B,GAAgB,CAC5B,WACE,sFACF,WAAY,SACZ,SAAWC,GAAU,CACnB7D,EAAkB6D,CAAK,EACvB3B,EAAc,IAChB,CACF,CAAC,EACDrB,EAAQ,YAAYqB,CAAW,EAC/B4B,EAAe,EACjB,CAEA,SAASE,IAAwB,CAC3B3B,IACJQ,EAAa,EACb/B,EAAU,MAAM,QAAU,OAC1BuB,EAAgB4B,GAAkB,CAChC,SAAWC,GAAS,CACdhE,GACFA,EAAoBgE,CAAI,EAE1B7B,EAAgB,IAClB,CACF,CAAC,EACDxB,EAAQ,YAAYwB,CAAa,EACnC,CAEA,SAAS8B,IAAyB,CAC5B7B,IACJxB,EAAU,MAAM,QAAU,OAC1BwB,EAAiB8B,GAAmB,CAClC,SAAWF,GAAS,CACd/D,GACFA,EAAe+D,CAAI,EAErB5B,EAAiB,IACnB,CACF,CAAC,EAEDzB,EAAQ,MAAM,SAAW,WACzBA,EAAQ,YAAYyB,CAAc,EACpC,CAEA,SAAS+B,IAAwB,CAE/B,KAAOxD,EAAQ,YACbA,EAAQ,YAAYA,EAAQ,UAAU,EAExCA,EAAQ,MAAM,SAAW,WAEzB,IAAMyD,EAAU,SAAS,cAAc,KAAK,EAC5CA,EAAQ,MAAM,QAAU;AAAA;AAAA;AAAA,oBAGR7E,EAAS,iBAAmB,SAAS;AAAA,eAC1CA,EAAS,WAAa,SAAS;AAAA,MAG1C,IAAM8E,EAAO,SAAS,gBAAgB,6BAA8B,KAAK,EACzEA,EAAK,aAAa,UAAW,aAAa,EAC1CA,EAAK,aAAa,QAAS,IAAI,EAC/BA,EAAK,aAAa,SAAU,IAAI,EAChCA,EAAK,aAAa,OAAQ,SAAS,EACnCA,EAAK,MAAM,QAAU,qCACrB,IAAMC,EAAO,SAAS,gBAAgB,6BAA8B,MAAM,EAC1EA,EAAK,aAAa,IAAK,gNAAgN,EACvOD,EAAK,YAAYC,CAAI,EACrBF,EAAQ,YAAYC,CAAI,EAExB,IAAME,EAAQ,SAAS,cAAc,KAAK,EAC1CA,EAAM,MAAM,QAAU,yDACtBA,EAAM,YAAc,wBACpBH,EAAQ,YAAYG,CAAK,EAEzB,IAAMC,EAAM,SAAS,cAAc,KAAK,EACxCA,EAAI,MAAM,QAAU,0FACpBA,EAAI,YAAc,qHAClBJ,EAAQ,YAAYI,CAAG,EAEvB,IAAMC,EAAS,SAAS,cAAc,KAAK,EAC3CA,EAAO,MAAM,QAAU,iDAEvB,IAAMC,EAAe,SAAS,cAAc,GAAG,EAC/CA,EAAa,MAAM,QAAU;AAAA;AAAA;AAAA;AAAA,oCAIGnF,EAAS,cAAgB,SAAS;AAAA,MAElEmF,EAAa,YAAc,iBAE3B,IAAMC,EAAO,OAAO,SAAS,SACzBC,GAAW,OAAO,SAAS,OAC3BD,IAAS,aAAeA,IAAS,aAC/BA,EAAK,SAAS,WAAW,IAC3BC,GAAWD,EAAK,SAAS,MAAM,EAAI,yBAA2B,qBAGlED,EAAa,KAAO,GAAGE,EAAQ,wBAAwBpF,CAAO,yBAC9DkF,EAAa,OAAS,SACtBA,EAAa,IAAM,WACnBD,EAAO,YAAYC,CAAY,EAE/B,IAAMG,EAAM,SAAS,cAAc,QAAQ,EAC3CA,EAAI,MAAM,QAAU;AAAA;AAAA;AAAA,wCAGgBtF,EAAS,WAAa,SAAS;AAAA,0BAC7CA,EAAS,UAAYA,EAAS,UAAY,KAAO,SAAS;AAAA,MAEhFsF,EAAI,YAAc,SAClBA,EAAI,iBAAiB,QAAS,IAAM,OAAO,SAAS,OAAO,CAAC,EAC5DJ,EAAO,YAAYI,CAAG,EAEtBT,EAAQ,YAAYK,CAAM,EAC1B9D,EAAQ,YAAYyD,CAAO,CAC7B,CAEA,SAASU,GAAaC,EAA2B,CAC3ChD,IACJA,EAAaiD,GAAqB,CAChC,WAAaC,GAAW,CACtBpF,EAAWoF,CAAM,EAEbxF,IAAS,UACX,WAAW,IAAM,CACfH,EAAM,SAAS,CAAE,KAAM,OAAQ,CAAC,EAChCA,EAAM,SAAS,CAAE,KAAM,WAAY,OAAQ,EAAM,CAAC,CACpD,EAAG,GAAG,CAEV,EACA,WAAAyF,CACF,CAAC,EACDpE,EAAQ,YAAYoB,CAAU,EAC9B6B,EAAe,EACjB,CAEA,SAASA,GAAuB,CAC9B,sBAAsB,IAAM,CAC1BjD,EAAQ,UAAYA,EAAQ,YAC9B,CAAC,CACH,CAEA,SAASuE,GAAeC,EAA+B,CAEjDjD,GAAiBiD,EAAS,KAAMC,GAAMA,EAAE,OAAS,MAAM,IACzDlD,EAAc,OAAO,EACrBA,EAAgB,MAIlB,QAASM,EAAIb,EAAsBa,EAAI2C,EAAS,OAAQ3C,IAAK,CAC3D,IAAM6C,EAAShF,EAAQ,aAAa8E,EAAS3C,CAAC,CAAC,EAC/C7B,EAAQ,YAAY0E,CAAM,CAC5B,CACA1D,EAAuBwD,EAAS,OAChCvB,EAAe,CACjB,CAEA,SAAS0B,GAAgBC,EAAgC,CACvD,GAAIA,EAAkB,CACf3D,IAECC,IACFA,EAAU,OAAO,EACjBA,EAAY,MAEdD,EAAkBvB,EAAQ,gBAAgB,EAC1CM,EAAQ,YAAYiB,CAAe,GAIrC,IAAM4D,EAAU5D,EAAwB,cAClC6D,EAAWC,GAAeH,CAAgB,EAC5CC,EACFA,EAAO,UAAYC,EAEnB7D,EAAgB,UAAY6D,EAE9B7B,EAAe,CACjB,MAAWhC,IACTA,EAAgB,OAAO,EACvBA,EAAkB,KAEtB,CAEA,SAAS+D,GAAcC,EAA0B,CAC3CA,GAAa,CAAC/D,GAAa,CAACD,GAC9BC,EAAYxB,EAAQ,cAAc,EAClCM,EAAQ,YAAYkB,CAAS,EAC7B+B,EAAe,GACN,CAACgC,GAAa/D,IACvBA,EAAU,OAAO,EACjBA,EAAY,KAEhB,CAGA,IAAIgE,EAAmC,KAEvC,OAAAvG,EAAM,UAAWwG,GAAU,CAazB,GAZA,QAAQ,IAAI,2BAA4B,SAAWA,EAAM,MAAO,QAAUA,EAAM,SAAS,OAAQ,QAAUA,EAAM,OAAQ,SAAWlF,GAAW,MAAM,QAAS,SAAWiF,GAAW,OAAS,OAAO,EAGhMpG,IAAS,WACPqG,EAAM,OACRvF,EAAU,UAAU,IAAI,oBAAoB,EAE5CA,EAAU,UAAU,OAAO,oBAAoB,GAK/C,CAACsF,GAAaA,EAAU,QAAUC,EAAM,MAC1C,OAAQA,EAAM,MAAO,CACnB,IAAK,OAEHnD,EAAa,EACb/B,EAAU,MAAM,QAAU,OAC1B8B,EAA0B,EAC1B,MACF,IAAK,aACH9B,EAAU,MAAM,QAAU,OAC1B0B,GAAwB,EACxB,MACF,IAAK,WACHY,GAAY,EACZ,MACF,IAAK,WACHR,EAA0B,EACtBmD,GAAW,QAAU,YACvBlD,EAAa,EAEf/B,EAAU,MAAM,QAAU,GAE1BgC,GAAqB,EACrB,MACF,IAAK,WACHkC,GAAa,EAAI,EACjB,MACF,IAAK,aACHjB,GAAmB,EACnB,MACF,IAAK,iBACHC,GAAgB,EAChB,MACF,IAAK,qBACHpB,EAA0B,EAC1B9B,EAAU,MAAM,QAAU,OAC1BqD,GAAiB,EACjB,MACF,IAAK,eACHvB,EAA0B,EAC1B9B,EAAU,MAAM,QAAU,OAC1BuD,GAAgB,EAChB,MACF,IAAK,QACHzB,EAA0B,EAC1B9B,EAAU,MAAM,QAAU,OAC1B,KACJ,CAKAkF,EAAM,SAAS,OAASnE,GACxBmE,EAAM,QAAU,YAEhBZ,GAAeY,EAAM,QAAQ,EAK7BA,EAAM,QAAU,YAChBA,EAAM,SAAS,QAAUpE,GAEzBpC,EAAM,SAAS,CAAE,KAAM,YAAa,MAAO,oBAAqB,CAAC,EAI/DuG,GAAW,mBAAqBC,EAAM,kBACxCR,GAAgBQ,EAAM,gBAAgB,EAIpCD,GAAW,YAAcC,EAAM,WACjCH,GAAcG,EAAM,SAAS,EAG/BD,EAAYC,CACd,CAAC,EAGAvF,EAAkB,sBAAwBsD,GAC1CtD,EAAkB,oBAAsBuE,GACxCvE,EAAkB,sBAAwBG,GAC1CH,EAAkB,uBAAyBuD,GAC3CvD,EAAkB,wBAA0B0D,GAC5C1D,EAAkB,6BAA+B,IAAMwF,GAAsBvF,EAAQlB,CAAK,EAEpFiB,CACT,CCxnBO,SAASyF,GAAmBC,EAA2C,CAC5E,GAAM,CAAE,SAAAC,EAAU,MAAAC,EAAO,eAAAC,EAAgB,cAAAC,EAAe,YAAAC,EAAa,eAAAC,CAAe,EAAIN,EAElFO,EAAU,SAAS,cAAc,KAAK,EAGtCC,EAAS,SAAS,cAAc,QAAQ,EAC9CA,EAAO,UAAY,gCAAgCP,CAAQ,GACvDI,IAAgB,WAClBG,EAAO,UAAU,IAAI,wBAAwB,EAE/CA,EAAO,aAAa,aAAc,WAAW,EAE7C,IAAMC,EAAUC,GAAe,EACzBC,EAAWC,GAAU,EAC3BD,EAAS,MAAM,QAAU,OAEzBH,EAAO,YAAYC,CAAO,EAC1BD,EAAO,YAAYG,CAAQ,EAE3BH,EAAO,iBAAiB,QAAS,IAAM,CACrC,IAAMK,EAASX,EAAM,SAAS,EAAE,OAC5BW,GAAUP,EACZA,EAAe,EAEfJ,EAAM,SAAS,CAAE,KAAM,WAAY,OAAQ,CAACW,CAAO,CAAC,CAExD,CAAC,EAEDN,EAAQ,YAAYC,CAAM,EAG1B,IAAIM,EAAiC,KACjCC,EAAkB,GAClBC,EAAsD,KAE1D,GAAIb,EAAgB,CAClBW,EAAa,SAAS,cAAc,KAAK,EACzCA,EAAW,UAAY,oCAAoCb,CAAQ,2BAEnE,IAAMgB,EAAW,SAAS,eAAed,CAAc,EACvDW,EAAW,YAAYG,CAAQ,EAE/B,IAAMC,EAAW,SAAS,cAAc,QAAQ,EAChDA,EAAS,UAAY,wBACrBA,EAAS,aAAa,aAAc,SAAS,EAC7CA,EAAS,YAAc,OACvBA,EAAS,iBAAiB,QAAUC,GAAM,CACxCA,EAAE,gBAAgB,EAClBC,EAAa,CACf,CAAC,EACDN,EAAW,YAAYI,CAAQ,EAE/BJ,EAAW,iBAAiB,QAAS,IAAM,CACzCM,EAAa,EACblB,EAAM,SAAS,CAAE,KAAM,WAAY,OAAQ,EAAK,CAAC,CACnD,CAAC,EAEDK,EAAQ,YAAYO,CAAU,EAI9BE,EAAgB,WAAW,IAAM,CAC3B,CAACd,EAAM,SAAS,EAAE,QAAUY,IAC9BA,EAAW,UAAU,OAAO,yBAAyB,EACrDC,EAAkB,GAElB,WAAW,IAAMK,EAAa,EAAG,GAAK,EAE1C,EARchB,GAAiB,GAQvB,CACV,CAEA,SAASgB,GAAqB,CACxBL,GAAmBD,IACrBA,EAAW,UAAU,IAAI,yBAAyB,EAClDC,EAAkB,IAEhBC,IACF,aAAaA,CAAa,EAC1BA,EAAgB,KAEpB,CAEA,OAAAd,EAAM,UAAWmB,GAAU,CACrBA,EAAM,QACRZ,EAAQ,MAAM,QAAU,OACxBE,EAAS,MAAM,QAAU,GACzBH,EAAO,aAAa,aAAc,YAAY,EAC9CY,EAAa,IAEbX,EAAQ,MAAM,QAAU,GACxBE,EAAS,MAAM,QAAU,OACzBH,EAAO,aAAa,aAAc,WAAW,EAEjD,CAAC,EAEMD,CACT,ClBpFA,SAASe,GAAcC,EAAwB,CAC7C,GAAI,CACF,IAAMC,EAAM,IAAI,IAAID,CAAM,EACpBE,EAAaD,EAAI,WAAa,SAAW,OAAS,MAExD,OAAIA,EAAI,WAAa,aAAeA,EAAI,WAAa,aACnDA,EAAI,KAAO,OACXA,EAAI,SAAWC,EACRD,EAAI,QAGTA,EAAI,WAAa,iBACZ,GAAGC,CAAU,sBAGlBD,EAAI,WAAa,aAAeA,EAAI,WAAa,iBAAmBA,EAAI,WAAa,gBAChF,GAAGC,CAAU,kBAGtBD,EAAI,SAAWC,EACRD,EAAI,OACb,MAAQ,CACN,IAAMC,EAAaF,EAAO,WAAW,OAAO,EAAI,MAAQ,KAClDG,EAAOH,EAAO,QAAQ,eAAgB,EAAE,EAC9C,MAAO,GAAGE,CAAU,MAAMC,CAAI,EAChC,CACF,CAEA,SAASC,GAAeJ,EAAwB,CAC9C,GAAI,CACF,IAAMC,EAAM,IAAI,IAAID,CAAM,EAE1B,OAAIC,EAAI,SAAS,WAAW,MAAM,GAChCA,EAAI,SAAWA,EAAI,SAAS,QAAQ,OAAQ,MAAM,EAC3CA,EAAI,QAGTA,EAAI,WAAa,kBACnBA,EAAI,SAAW,qBACRA,EAAI,QAGTA,EAAI,WAAa,aACnBA,EAAI,SAAW,gBACRA,EAAI,UAGTA,EAAI,WAAa,aAAeA,EAAI,WAAa,eACnDA,EAAI,KAAO,QACJA,EAAI,OAGf,MAAQ,CACN,OAAOD,CACT,CACF,CAEA,SAASK,GAAWC,EAGlB,CACA,IAAIC,EACAC,EAA8B,KAElC,GAAIF,EAAO,UACTC,EAAUD,EAAO,UAAU,QAAQ,MAAO,EAAE,MACvC,CAEL,IAAMG,EAAU,SAAS,iBAAiB,aAAa,EACvD,QAAS,EAAIA,EAAQ,OAAS,EAAG,GAAK,EAAG,IAAK,CAC5C,IAAMC,EAAOD,EAAQ,CAAC,EAAwB,IAC9C,GAAIC,EAAI,SAAS,aAAa,GAAKA,EAAI,SAAS,QAAQ,EACtD,GAAI,CAEFF,EADY,IAAI,IAAIE,CAAG,EACJ,OACnB,KACF,MAAQ,CAER,CAEJ,CAEAH,EAAUH,GAAeI,GAAgB,SAAS,MAAM,CAC1D,CAEA,MAAO,CACL,QAAAD,EACA,MAAOD,EAAO,OAASP,GAAcS,GAAgBD,CAAO,CAC9D,CACF,CAEA,IAAMI,GAAiB,oBAEvB,SAASC,IAA+B,CACtC,GAAI,CACF,IAAMC,EAAW,aAAa,QAAQF,EAAc,EACpD,GAAIE,EAAU,OAAOA,EACrB,IAAMC,EAAK,KAAK,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,EAAG,EAAE,CAAC,GACzE,oBAAa,QAAQH,GAAgBG,CAAE,EAChCA,CACT,MAAQ,CAEN,MAAO,KAAK,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,EAAG,EAAE,CAAC,EACvE,CACF,CAEA,IAAIC,GAAmB,EAEvB,SAASC,IAA0B,CACjC,OAAAD,KACO,OAAO,KAAK,IAAI,CAAC,IAAIA,EAAgB,EAC9C,CAOA,SAASE,GAAgBC,EAA+C,CACtE,GAAI,CAACA,GAAkBA,EAAe,SAAW,EAAG,MAAO,GAC3D,IAAMC,EAAW,OAAO,SAAS,SACjC,OAAOD,EAAe,KAAME,GAAY,CACtC,GAAIA,EAAQ,SAAS,IAAI,EAAG,CAC1B,IAAMC,EAASD,EAAQ,MAAM,EAAG,EAAE,EAClC,OAAOD,EAAS,WAAWE,CAAM,GAAKF,IAAaE,EAAO,MAAM,EAAG,EAAE,CACvE,CACA,GAAID,EAAQ,SAAS,GAAG,EAAG,CACzB,IAAMC,EAASD,EAAQ,MAAM,EAAG,EAAE,EAClC,OAAOD,EAAS,WAAWE,CAAM,CACnC,CACA,OAAOF,IAAaC,CACtB,CAAC,CACH,CAOA,SAASE,GACPJ,EACAK,EACY,CACZ,GAAI,CAACA,EAAW,MAAO,IAAM,CAAC,EAE9B,IAAMC,EAAa,wBAEbC,EAAgB,QAAQ,UAAU,KAAK,OAAO,EAC9CC,EAAmB,QAAQ,aAAa,KAAK,OAAO,EAE1D,QAAQ,UAAY,YAAaC,EAAwC,CACvEF,EAAc,GAAGE,CAAI,EACrB,OAAO,cAAc,IAAI,MAAMH,CAAU,CAAC,CAC5C,EAEA,QAAQ,aAAe,YAAaG,EAA2C,CAC7ED,EAAiB,GAAGC,CAAI,EACxB,OAAO,cAAc,IAAI,MAAMH,CAAU,CAAC,CAC5C,EAEA,SAASI,GAAkB,CACrBX,GAAgBC,CAAc,EAChCK,EAAW,MAAM,QAAU,OAE3BA,EAAW,MAAM,QAAU,EAE/B,CAEA,cAAO,iBAAiBC,EAAYI,CAAe,EACnD,OAAO,iBAAiB,WAAYA,CAAe,EAE5C,IAAM,CACX,QAAQ,UAAYH,EACpB,QAAQ,aAAeC,EACvB,OAAO,oBAAoBF,EAAYI,CAAe,EACtD,OAAO,oBAAoB,WAAYA,CAAe,CACxD,CACF,CAOA,SAASC,GAAgBC,EAA+C,CACtE,GAAI,CAACA,GAAkBA,EAAe,SAAW,EAAG,MAAO,GAC3D,IAAMC,EAAW,OAAO,SAAS,SAAS,YAAY,EAGtD,OAFIA,IAAa,aAAeA,IAAa,aAEzCA,IAAa,aAAeA,EAAS,SAAS,YAAY,EAAU,GACjED,EAAe,KAAME,GAAW,CACrC,IAAMC,EAAID,EAAO,YAAY,EAC7B,OAAOD,IAAaE,GAAKF,EAAS,SAAS,IAAME,CAAC,CACpD,CAAC,CACH,CAEO,SAASC,GAAK5B,EAA8C,CACjE,GAAI,CAACA,EAAO,QACV,MAAM,IAAI,MAAM,iCAAiC,EAGnD,IAAM6B,EAAO7B,EAAO,MAAQ,SACtB8B,EAAW9B,EAAO,UAAY,eAC9B,CAAE,QAAAC,EAAS,MAAA8B,CAAM,EAAIhC,GAAWC,CAAM,EAGtCgC,EAAQ,IAAIC,EACZC,EAAY,IAAIC,EAAU,CAAE,QAASlC,CAAQ,CAAC,EAChDmC,EAAmC,KACnCC,EAA6B,KAC7BC,EAAgC,KAChCC,EAA6B,KAC7BC,EAAmC,KACnCC,EAA+B,KAC/BC,EAAY,GACZC,EAA4B,mBAC5BC,EAAwB,GACxBC,EAA0C,KAC1CC,EAAkB,GAClBC,EAAoC,KAGxCV,EAAS,SAAS,cAAc,KAAK,EACrCA,EAAO,GAAK,qBAEZ,IAAMW,EAAiB,OAAOX,EAAO,cAAiB,WACtDY,GAAgBD,CAAc,EAE1BA,IAEFX,EAAO,MAAM,QAAU,oHACvBC,EAAaD,EAAO,aAAa,CAAE,KAAM,MAAO,CAAC,GAKnDE,EAAS,SAAS,cAAc,KAAK,EACrCA,EAAO,UAAY,qBAGnB,IAAMW,EAAuCZ,GAAcD,EAEvDW,IAEFT,EAAO,MAAM,cAAgB,QAE/BW,EAAW,YAAYX,CAAM,EAG7B,eAAeY,GAA2B,CACxC,GAAI,CACF,IAAMC,EAAW,MAAMlB,EAAU,cAAclC,EAAO,OAAO,EAE7D,GAAI0C,EAAW,OAGf,GAAI,CAACnB,GAAgB6B,EAAS,cAAc,EAAG,CAC7C,QAAQ,KACN,2BAA2B,OAAO,SAAS,QAAQ,6CAA6C,KAAK,UAAUA,EAAS,cAAc,CAAC,EACzI,EACA,MACF,CAGA,GAAIzC,GAAgByC,EAAS,cAAc,EAAG,CAC5C,QAAQ,KACN,oDAAoD,OAAO,SAAS,QAAQ,GAC9E,EACA,MACF,CAMAC,GAAa,CACX,aAAcD,EAAS,aACvB,YAAaA,EAAS,YACtB,YAAaA,EAAS,YACtB,WAAYA,EAAS,WACrB,YAAaA,EAAS,YACtB,gBAAiBA,EAAS,gBAC1B,UAAWA,EAAS,UACpB,SAAUA,EAAS,SACnB,iBAAkBA,EAAS,iBAC3B,kBAAmBA,EAAS,kBAC5B,YAAaA,EAAS,YACtB,WAAYA,EAAS,WACrB,YAAaA,EAAS,WACxB,EAAGF,EAAY,CAACF,CAAc,EAG1BhD,EAAO,oBAAsBA,EAAO,mBAAmB,OAAS,IAClEoD,EAAS,mBAAqBpD,EAAO,oBAEvC,QAAQ,IAAI,mCAAoCoD,EAAS,kBAAkB,EAG3E,IAAME,EACJtD,EAAO,gBACPoD,EAAS,eAAe,SACxB,GAIEE,IACGF,EAAS,eAOZA,EAAS,cAAc,QAAU,GAC7BpD,EAAO,kBAAoB,SAC7BoD,EAAS,cAAc,SAAWpD,EAAO,iBAEvCA,EAAO,gBACToD,EAAS,cAAc,OAASpD,EAAO,gBAXzCoD,EAAS,cAAgB,CACvB,QAAS,GACT,SAAUpD,EAAO,iBAAmB,KACpC,OAAQA,EAAO,aACjB,GAWJ8C,EAAkBM,EAAS,gBAAgB,SAAW,GACtD,IAAMG,EACJH,EAAS,gBAAgB,mBAAqB,EAuMhD,GApMIN,IACFD,EAAkB,IAAIW,EAAgBD,EAA2B,IAAM,CACrE,IAAME,EAAezB,EAAM,SAAS,EAElC,CAACyB,EAAa,eACdA,EAAa,QAAU,YACvBA,EAAa,SAAS,OAAS,GAE/BzB,EAAM,SAAS,CAAE,KAAM,YAAa,MAAO,UAAW,CAAC,CAE3D,CAAC,GAIHQ,EAAekB,GAAiB,CAC9B,MAAA1B,EACA,SAAAoB,EACA,QAASpD,EAAO,QAChB,KAAA6B,EACA,SAAAC,EACA,cAAgB6B,GAAoB,CAClC,IAAMC,EAAuB,CAC3B,GAAIlD,GAAgB,EACpB,KAAM,OACN,QAAAiD,EACA,UAAW,KAAK,IAAI,CACtB,EACA3B,EAAM,SAAS,CAAE,KAAM,cAAe,QAAS4B,CAAQ,CAAC,EACxD5B,EAAM,SAAS,CAAE,KAAM,cAAe,UAAW,EAAK,CAAC,EAEnDI,GACFA,EAAS,YAAYuB,CAAO,CAEhC,EACA,gBAAkBE,GAAkB,CAClC7B,EAAM,SAAS,CAAE,KAAM,oBAAqB,cAAe6B,CAAM,CAAC,EAClE7B,EAAM,SAAS,CAAE,KAAM,YAAa,MAAO,YAAa,CAAC,EACzD8B,EAAiBD,CAAK,CACxB,EACA,WAAaE,GAA0B,CACrC,IAAMC,EAAYhC,EAAM,SAAS,EAAE,UAC/BgC,GACF9B,EACG,eAAelC,EAAO,QAAS,CAAE,UAAAgE,EAAW,OAAAD,CAAO,CAAC,EACpD,MAAOE,GACN,QAAQ,MAAM,qCAAsCA,CAAG,CACzD,EAEJjC,EAAM,SAAS,CAAE,KAAM,oBAAqB,CAAC,EAC7Ca,GAAiB,KAAK,EACtB7C,EAAO,aAAa+D,CAAM,CAC5B,EACA,kBAAoBG,GAAkB,CACpC,IAAMF,EAAYhC,EAAM,SAAS,EAAE,UAC/BgC,GACF9B,EACG,iBAAiBlC,EAAO,QAAS,CAAE,UAAAgE,EAAW,UAAWE,CAAM,CAAC,EAChE,MAAOD,GACN,QAAQ,MAAM,uCAAwCA,CAAG,CAC3D,EAGA7B,GACFA,EAAS,oBAAoB8B,CAAK,EAEpClE,EAAO,gBAAgB,CACrB,MAAAkE,EACA,UAAWF,GAAa,GACxB,OAAQ,iBACR,cAAehC,EAAM,SAAS,EAAE,eAAiB,MACnD,CAAC,CACH,EACA,kBAAoBkC,GAAkB,CACpC,IAAMF,EAAYhC,EAAM,SAAS,EAAE,UAC/BgC,GACF9B,EACG,kBAAkBlC,EAAO,QAASgE,EAAW,CAAE,MAAAE,CAAM,CAAC,EACtD,MAAOD,GACN,QAAQ,MAAM,wCAAyCA,CAAG,CAC5D,CAEN,EACA,oBAAsBE,GAA2D,CAC/E,IAAMC,EAAY9D,GAAqB,EACjC0D,EAAYhC,EAAM,SAAS,EAAE,UACnCE,EACG,WAAW,CACV,QAASlC,EAAO,QAChB,KAAMmE,EAAK,MAAQ,OACnB,MAAOA,EAAK,MACZ,QAASA,EAAK,QACd,UAAAC,EACA,eAAgBzB,EAChB,eAAgBqB,GAAa,MAC/B,CAAC,EACA,MAAOC,GACN,QAAQ,MAAM,iCAAkCA,CAAG,CACrD,EAEE7B,GACFA,EAAS,oBAAoB,CAC3B,MAAO+B,EAAK,MACZ,KAAMA,EAAK,MAAQ,OACnB,OAAQxB,CACV,CAAC,EAEH3C,EAAO,gBAAgB,CACrB,MAAOmE,EAAK,MACZ,UAAWH,GAAa,GACxB,OAAQ,iBACR,cAAehC,EAAM,SAAS,EAAE,eAAiB,MACnD,CAAC,CACH,EACA,eAAiBmC,GAAqD,CAChEA,EAAK,aAGPjC,EACG,qBAAqBlC,EAAO,QAAS,CACpC,MAAOmE,EAAK,aACZ,QAASA,EAAK,QACd,UAAW7D,GAAqB,CAClC,CAAC,EACA,MAAO2D,GACN,QAAQ,MAAM,4CAA6CA,CAAG,CAChE,EAIF/B,EACG,mBAAmB,CAClB,QAASlC,EAAO,QAChB,QAASmE,EAAK,OAChB,CAAC,EACA,MAAOF,GACN,QAAQ,MAAM,0CAA2CA,CAAG,CAC9D,CAEN,EACA,gBAAAnB,EACA,UAAW,IAAM,CAEXV,IACFA,EAAS,WAAW,EACpBA,EAAW,MAGbS,GAAiB,KAAK,EAEtBb,EAAM,SAAS,CAAE,KAAM,OAAQ,CAAC,EAEhCA,EAAM,SAAS,CAAE,KAAM,WAAY,OAAQ,EAAK,CAAC,EACjDA,EAAM,SAAS,CAAE,KAAM,YAAa,MAAO,YAAa,CAAC,EACzD8B,EAAiB,CACnB,CACF,CAAC,EAEDvB,EAAQ,YAAYC,CAAY,EAG5BX,IAAS,WACXY,EAAW4B,GAAmB,CAC5B,SAAAvC,EACA,MAAAE,EACA,eAAgBoB,EAAS,gBAAkB,OAC3C,cAAepD,EAAO,cACtB,YAAaoD,EAAS,YACtB,eAAgB,IAAM,CACpB,IAAMK,EAAezB,EAAM,SAAS,EAEpC,GACEc,GACA,CAACW,EAAa,eACdA,EAAa,QAAU,YACvBA,EAAa,SAAS,OAAS,EAC/B,CACAzB,EAAM,SAAS,CAAE,KAAM,YAAa,MAAO,UAAW,CAAC,EACvD,MACF,CACA,GAAIyB,EAAa,SAAS,SAAW,EAAG,CACtCzB,EAAM,SAAS,CAAE,KAAM,WAAY,OAAQ,EAAM,CAAC,EAClD,MACF,CAEA,IAAMsC,EAAe9B,GAAsB,6BACvC,OAAO8B,GAAgB,WACzBA,EAAY,EAEZtC,EAAM,SAAS,CAAE,KAAM,WAAY,OAAQ,EAAM,CAAC,CAEtD,CACF,CAAC,EACDO,EAAQ,YAAYE,CAAQ,GAI1BZ,IAAS,UAAYW,EAAc,CACrC,IAAM+B,EAAIvE,EAAO,OAAS,OACpBwE,EAAIxE,EAAO,QAAU,OAC3BwC,EAAa,MAAM,MAAQ+B,EAC3B/B,EAAa,MAAM,OAASgC,EAC5BhC,EAAa,MAAM,UAAYgC,EAE/BjC,EAAQ,MAAM,OAAS,MACzB,CAoCA,GAjCIS,EAEEnB,IAAS,UAAY7B,EAAO,WAC9BqC,EAAQ,MAAM,QAAU,yCACxBrC,EAAO,UAAU,YAAYqC,CAAO,GAEpC,SAAS,KAAK,YAAYA,CAAO,EAI/BR,IAAS,UAAY7B,EAAO,UAC9BA,EAAO,UAAU,YAAYuC,CAAO,EAEpC,SAAS,KAAK,YAAYA,CAAO,EAOjCe,EACFtB,EAAM,SAAS,CAAE,KAAM,YAAa,MAAO,UAAW,CAAC,GAEvDA,EAAM,SAAS,CAAE,KAAM,YAAa,MAAO,YAAa,CAAC,EACzD8B,EAAiB,GAIfjC,IAAS,UACXG,EAAM,SAAS,CAAE,KAAM,WAAY,OAAQ,EAAK,CAAC,EAI/CoB,EAAS,gBAAkBA,EAAS,eAAe,OAAS,EAAG,CACjE,IAAMnC,EAAY+B,EAAiBX,EAASE,EAC5CQ,EAAe/B,GAAkBoC,EAAS,eAAgBnC,CAAS,CACrE,CACF,OAASgD,EAAK,CACZ,QAAQ,MAAM,oCAAqCA,CAAG,EACtDjC,EAAM,SAAS,CACb,KAAM,YACN,MAAO,8CACT,CAAC,CACH,CACF,CAEA,SAASyC,GAAmC,CACrC7B,IACLA,EAAwB,GAGpBJ,GACF,WAAW,IAAM,CACf,IAAMkC,EAAUlC,GAAsB,sBAClC,OAAOkC,GAAW,YACpBA,EAAO,CAEX,EAAG,GAAG,EAEV,CAEA,SAASZ,EAAiBa,EAA8B,CAClDvC,GAAYM,IAEhBN,EAAW,IAAIwC,EAAgB,CAC7B,IAAK7C,EACL,QAAS/B,EAAO,QAChB,UAAWM,GAAqB,CAClC,CAAC,EAGD8B,EAAS,GAAG,YAAa,IAAM,CAE/B,CAAC,EAEDA,EAAS,GAAG,oBAAsByC,GAAU,CAC1C7C,EAAM,SAAS,CAAE,KAAM,YAAa,MAAO,UAAW,CAAC,EACvDA,EAAM,SAAS,CAAE,KAAM,cAAe,UAAW,EAAM,CAAC,EAEpD6C,EAAM,KAAK,YACb7C,EAAM,SAAS,CACb,KAAM,iBACN,UAAW6C,EAAM,KAAK,SACxB,CAAC,EACD7E,EAAO,iBAAiB6E,EAAM,KAAK,SAAS,GAI1CF,GACFvC,GAAU,YACR,mBAAmBuC,CAAa,GAClC,CAGJ,CAAC,EAEDvC,EAAS,GAAG,eAAiByC,GAAU,CACrC7C,EAAM,SAAS,CAAE,KAAM,mBAAoB,MAAO6C,EAAM,KAAK,KAAM,CAAC,CACtE,CAAC,EAEDzC,EAAS,GAAG,iBAAmByC,GAAU,CACvC7C,EAAM,SAAS,CAAE,KAAM,iBAAkB,CAAC,EAC1C,IAAM8C,EAA4B,CAChC,GAAIpE,GAAgB,EACpB,KAAM,YACN,QAASmE,EAAM,KAAK,SAAWA,EAAM,KAAK,UAAY,GACtD,UAAW,KAAK,IAAI,CACtB,EACA7C,EAAM,SAAS,CAAE,KAAM,cAAe,QAAS8C,CAAa,CAAC,EAC7D9C,EAAM,SAAS,CAAE,KAAM,cAAe,UAAW,EAAM,CAAC,EAGxDyC,EAA2B,EAIzB3B,GACA+B,EAAM,KAAK,0BACX,CAAC7C,EAAM,SAAS,EAAE,eAGlB,WAAW,IAAM,CACf,IAAMyB,EAAezB,EAAM,SAAS,EAElC,CAACyB,EAAa,eACdA,EAAa,QAAU,YACvBA,EAAa,SAAS,OAAS,GAE/BzB,EAAM,SAAS,CAAE,KAAM,YAAa,MAAO,UAAW,CAAC,CAE3D,EAAG,GAAG,EACNa,GAAiB,KAAK,GACbA,GAAmB,CAACb,EAAM,SAAS,EAAE,eAE9Ca,EAAgB,MAAM,CAE1B,CAAC,EAEDT,EAAS,GAAG,aAAc,IAAM,CAC9B,IAAM2C,EAAmB/C,EAAM,SAAS,EAAE,iBAC1C,GAAI+C,EAAkB,CACpB/C,EAAM,SAAS,CAAE,KAAM,iBAAkB,CAAC,EAC1C,IAAM8C,EAA4B,CAChC,GAAIpE,GAAgB,EACpB,KAAM,YACN,QAASqE,EACT,UAAW,KAAK,IAAI,CACtB,EACA/C,EAAM,SAAS,CAAE,KAAM,cAAe,QAAS8C,CAAa,CAAC,CAC/D,CACA9C,EAAM,SAAS,CAAE,KAAM,cAAe,UAAW,EAAM,CAAC,EAGxDyC,EAA2B,EAGvB5B,GAAmB,CAACb,EAAM,SAAS,EAAE,eACvCa,EAAgB,MAAM,CAE1B,CAAC,EAEDT,EAAS,GAAG,aAAc,IAAM,CAC9BJ,EAAM,SAAS,CAAE,KAAM,cAAe,UAAW,EAAK,CAAC,CACzD,CAAC,EAEDI,EAAS,GAAG,WAAY,IAAM,CAE9B,CAAC,EAEDA,EAAS,GAAG,cAAgByC,GAAU,CACpC,IAAMG,EAAUH,EAAM,MAEpBG,IAAY,yBACZA,GAAS,OAAS,2BAGlBpC,EAAwB,GAE5B,CAAC,EAGDR,EAAS,GAAG,iBAAmByC,GAAU,CACvC,IAAMI,EAAmB,CACvB,GAAIvE,GAAgB,EACpB,KAAM,YACN,QAASmE,EAAM,MAAM,SAAW,4FAChC,UAAW,KAAK,IAAI,CACtB,EACA7C,EAAM,SAAS,CAAE,KAAM,cAAe,QAASiD,CAAI,CAAC,EACpDjD,EAAM,SAAS,CAAE,KAAM,cAAe,UAAW,EAAM,CAAC,CAC1D,CAAC,EAGDI,EAAS,GAAG,oBAAsByC,GAAU,CAC1ClC,EAAoBkC,EAAM,MAAM,QAAU,mBAC1C7C,EAAM,SAAS,CAAE,KAAM,YAAa,MAAO,gBAAiB,CAAC,EAC7DA,EAAM,SAAS,CAAE,KAAM,cAAe,UAAW,EAAM,CAAC,CAC1D,CAAC,EAEDI,EAAS,GAAG,QAAUyC,GAAU,CAE9B,GAAIA,EAAM,MAAM,OAAS,eAAiBA,EAAM,MAAM,YAAa,CACjE7C,EAAM,SAAS,CAAE,KAAM,YAAa,MAAO,oBAAqB,CAAC,EACjEA,EAAM,SAAS,CAAE,KAAM,cAAe,UAAW,EAAM,CAAC,EACxD,MACF,CAEA,GAAI6C,EAAM,MAAM,UAAY,wBAAyB,CACnD7C,EAAM,SAAS,CAAE,KAAM,YAAa,MAAO,cAAe,CAAC,EAC3DA,EAAM,SAAS,CAAE,KAAM,cAAe,UAAW,EAAM,CAAC,EACxD,MACF,CACA,QAAQ,MAAM,8BAA+B6C,EAAM,IAAI,EACvD7C,EAAM,SAAS,CACb,KAAM,YACN,MAAO6C,EAAM,MAAM,SAAW,qCAChC,CAAC,EACD7C,EAAM,SAAS,CAAE,KAAM,cAAe,UAAW,EAAM,CAAC,CAC1D,CAAC,EAEDI,EAAS,GAAG,eAAgB,IAAM,CAElC,CAAC,EAEDA,EAAS,QAAQ,EACnB,CAGAe,EAAU,EAIV,IAAI+B,EAAa,GACbC,EAAiB,GACrB,OAAAnD,EAAM,UAAWoD,GAAU,CACzB,GAAI,EAAA1C,GAAayC,GAGjB,IAAID,GAAc,CAACE,EAAM,OAAQ,CAC/BF,EAAa,GACbC,EAAiB,GACb/C,IACFA,EAAS,WAAW,EACpBA,EAAW,MAEbS,GAAiB,KAAK,EACtBsC,EAAiB,GACjB,MACF,CAGA,GAAI,CAACD,GAAcE,EAAM,QAAU,CAAChD,EAAU,CAC5C8C,EAAa,GACbC,EAAiB,GACjBnD,EAAM,SAAS,CAAE,KAAM,YAAa,MAAO,YAAa,CAAC,EACzD8B,EAAiB,EACjBqB,EAAiB,GACjB,MACF,CAEAD,EAAaE,EAAM,OACrB,CAAC,EAGM,CACL,KAAM,IAAM,CACL1C,GACHV,EAAM,SAAS,CAAE,KAAM,WAAY,OAAQ,EAAK,CAAC,CAErD,EACA,MAAO,IAAM,CACNU,GACHV,EAAM,SAAS,CAAE,KAAM,WAAY,OAAQ,EAAM,CAAC,CAEtD,EACA,OAAQ,IAAM,CACZ,GAAI,CAACU,EAAW,CACd,IAAM2C,EAASrD,EAAM,SAAS,EAAE,OAChCA,EAAM,SAAS,CAAE,KAAM,WAAY,OAAQ,CAACqD,CAAO,CAAC,CACtD,CACF,EACA,QAAS,IAAM,CACb,GAAI3C,EAAW,OACfA,EAAY,GAEZK,IAAe,EACfA,EAAe,KACfX,GAAU,WAAW,EACrBS,GAAiB,KAAK,EACtByC,GAAa,EAGb,IAAMrE,EAAY+B,EAAiBX,EAASE,EACxCtB,GAAaA,EAAU,YACzBA,EAAU,WAAW,YAAYA,CAAS,EAG5C,IAAM+C,EAAYhC,EAAM,SAAS,EAAE,UAC/BgC,GACFhE,EAAO,eAAegE,CAAS,EAGjChC,EAAM,SAAS,CAAE,KAAM,OAAQ,CAAC,EAEhCK,EAAS,KACTC,EAAa,KACbC,EAAS,KACTC,EAAe,KACfC,EAAW,KACXL,EAAW,IACb,EACA,aAAemD,GAAuC,CAChD7C,GACJ,OAAO,OAAO1C,EAAQuF,CAAO,CAC/B,CACF,CACF,CAIA,GAAI,OAAO,SAAa,KAAe,SAAS,cAAe,CAC7D,IAAMC,EAAW,SAAS,cACpBC,EAAUD,EAAS,aAAa,eAAe,EAErD,GAAIC,EAAS,CACX,IAAM5D,EACH2D,EAAS,aAAa,WAAW,GAA6B,SAC3DE,EAAYF,EAAS,aAAa,iBAAiB,GAAK,OACxDG,EAAcH,EAAS,aAAa,mBAAmB,EAE7D5D,GAAK,CACH,QAAA6D,EACA,KAAA5D,EACA,UAAA6D,EACA,UAAWC,GACP,SAAS,eAAeA,CAAW,GAAK,MAE9C,CAAC,CACH,CACF",
|
|
6
6
|
"names": ["src_exports", "__export", "init", "createInitialState", "reducer", "state", "action", "ChatStore", "prevState", "subscriber", "snapshot", "err", "ApiClient", "config", "agentId", "response", "data", "branding", "validHex", "val", "fallback", "suggestedQuestions", "parsed", "payload", "sessionId", "WebSocketClient", "config", "err", "content", "data", "email", "type", "handler", "event", "output", "delay", "InactivityTimer", "minutes", "callback", "hasShadowDom", "setHasShadowDom", "value", "styleEl", "injectStyles", "options", "renderRoot", "useImportant", "opts", "style", "getStyles", "removeStyles", "resolveFontFamily", "font", "resolveFontSize", "size", "isLightColor", "hex", "c", "r", "g", "b", "_i", "primary", "accent", "fontStack", "fontSize", "isDark", "bgColor", "txtColor", "isDarkBg", "borderColor", "bgSecondary", "txtSecondary", "scrollThumb", "headerBg", "headerTextColor", "headerTextSecondary", "buttonBg", "buttonBgHover", "adjustBrightness", "userMsgBgVal", "userMsgText", "amount", "cleaned", "num", "escapeHtml", "text", "renderMarkdown", "raw", "lines", "result", "inUl", "inOl", "i", "line", "ulMatch", "olMatch", "html", "insideList", "item", "hasShadowDom", "createSvg", "paths", "viewBox", "svg", "d", "path", "headerBotIcon", "fill", "namiruBirdIcon", "chatBubbleIcon", "createSvg", "closeIcon", "sendIcon", "thumbsUpIcon", "thumbsDownIcon", "shoppingBagIcon", "createSvg", "packageIcon", "creditCardIcon", "chatCircleIcon", "rocketIcon", "wrenchIcon", "briefcaseIcon", "userCircleIcon", "dotsThreeIcon", "iconMap", "shoppingBagIcon", "packageIcon", "creditCardIcon", "chatCircleIcon", "rocketIcon", "wrenchIcon", "briefcaseIcon", "userCircleIcon", "dotsThreeIcon", "getIconByName", "name", "factory", "hexToRgb", "hex", "c", "r", "g", "b", "createChatHeader", "options", "store", "branding", "mode", "onTranscriptClick", "onNewChat", "feedbackEnabled", "empty", "header", "left", "primaryRgb", "avatar", "fallback", "isDark", "iconFill", "icon", "headerBotIcon", "info", "name", "subtitle", "actions", "closeBtn", "closeIcon", "currentState", "showCloseConfirmation", "headerEl", "container", "overlay", "card", "title", "btnRow", "cancelBtn", "endBtn", "e", "style", "createChatInput", "options", "onSend", "area", "row", "input", "hasShadowDom", "sendBtn", "sendIcon", "submit", "value", "e", "createAvatarElement", "opts", "img", "span", "isDark", "iconFill", "namiruBirdIcon", "createMessageBubbleFactory", "message", "createUserBubble", "createAssistantBubble", "createStreamingBubble", "createLoadingIndicator", "row", "bubble", "cls", "iconWrap", "textEl", "renderMarkdown", "el", "dot", "createPreChatForm", "options", "question", "opts", "onSelect", "container", "questionEl", "optionsList", "opt", "btn", "icon", "getIconByName", "label", "createFeedbackPrompt", "options", "onFeedback", "softPrompt", "container", "label", "text", "buttons", "upBtn", "thumbsUpIcon", "downBtn", "thumbsDownIcon", "handleFeedback", "rating", "thanks", "createEmailForm", "options", "promptText", "buttonText", "onSubmit", "container", "text", "row", "input", "submitBtn", "isValidEmail", "submit", "email", "sent", "e", "createContactForm", "options", "onSubmit", "container", "heading", "nameLabel", "nameInput", "emailLabel", "emailInput", "msgLabel", "messageInput", "errorEl", "submitBtn", "validate", "email", "message", "updateButton", "submit", "data", "confirmation", "e", "createInfoIcon", "svg", "circle", "line", "dot", "createCheckIcon", "polyline", "createLimitOverlay", "options", "onSubmit", "onNewChat", "container", "iconWrap", "heading", "subtext", "form", "messageInput", "emailInput", "submitBtn", "newChatBtn", "validate", "updateButton", "submit", "email", "data", "confirmIcon", "confirmation", "newChatBtn2", "createChatWindow", "options", "store", "branding", "agentId", "mode", "position", "onSendMessage", "onPreChatSelect", "onFeedback", "onEscalationEmail", "onTranscriptEmail", "onContactFormSubmit", "onLimitMessage", "onNewChat", "feedbackEnabled", "agentAvatarUrl", "bubbles", "createMessageBubbleFactory", "container", "header", "createChatHeader", "showTranscriptForm", "content", "inputArea", "createChatInput", "showPowered", "createPoweredByEl", "powered", "imp", "hasShadowDom", "link", "originalPoweredHTML", "guardPaused", "existing", "fresh", "s", "cs", "MESSAGE_HARD_LIMIT", "renderedMessageCount", "streamingBubble", "loadingEl", "preChatEl", "feedbackEl", "emailFormEl", "welcomeRendered", "suggestionsEl", "contactFormEl", "limitOverlayEl", "connectingEl", "showConnectingIndicator", "dots", "i", "dot", "removeConnectingIndicator", "clearContent", "renderWelcomeMessage", "welcomeMsg", "row", "questions", "q", "chip", "showPreChat", "pcConfig", "templates", "question", "formOptions", "tmpl", "createPreChatForm", "label", "createEmailForm", "email", "scrollToBottom", "showEscalationForm", "showContactForm", "createContactForm", "data", "showLimitOverlay", "createLimitOverlay", "showDomainError", "overlay", "icon", "path", "title", "msg", "btnRow", "settingsLink", "host", "dashBase", "btn", "showFeedback", "softPrompt", "createFeedbackPrompt", "rating", "renderMessages", "messages", "m", "bubble", "updateStreaming", "streamingContent", "textEl", "rendered", "renderMarkdown", "updateLoading", "isLoading", "prevState", "state", "showCloseConfirmation", "createButtonBubble", "options", "position", "store", "welcomeMessage", "greetingDelay", "bubbleStyle", "onCloseRequest", "wrapper", "button", "openSvg", "chatBubbleIcon", "closeSvg", "closeIcon", "isOpen", "greetingEl", "greetingVisible", "greetingTimer", "textNode", "closeBtn", "e", "hideGreeting", "state", "mapToWsOrigin", "origin", "url", "wsProtocol", "host", "mapToApiOrigin", "deriveUrls", "config", "apiBase", "scriptOrigin", "scripts", "src", "VISITOR_ID_KEY", "getOrCreateVisitorId", "existing", "id", "messageIdCounter", "createMessageId", "isRouteExcluded", "excludedRoutes", "pathname", "pattern", "prefix", "watchRouteChanges", "mountedEl", "EVENT_NAME", "origPushState", "origReplaceState", "args", "checkVisibility", "isDomainAllowed", "allowedDomains", "hostname", "domain", "d", "init", "mode", "position", "wsUrl", "store", "ChatStore", "apiClient", "ApiClient", "wsClient", "hostEl", "shadowRoot", "rootEl", "chatWindowEl", "buttonEl", "destroyed", "lastHandoffReason", "pendingEscalationForm", "inactivityTimer", "feedbackEnabled", "routeCleanup", "supportsShadow", "setHasShadowDom", "renderRoot", "bootstrap", "branding", "injectStyles", "preChatEnabled", "feedbackInactivityMinutes", "InactivityTimer", "currentState", "createChatWindow", "content", "userMsg", "label", "connectWebSocket", "rating", "sessionId", "err", "email", "data", "visitorId", "createButtonBubble", "showConfirm", "w", "h", "maybeShowPendingEscalation", "showFn", "qualification", "WebSocketClient", "event", "assistantMsg", "streamingContent", "trigger", "msg", "prevIsOpen", "lifecycleGuard", "state", "isOpen", "removeStyles", "partial", "scriptEl", "agentId", "serverUrl", "containerId"]
|
|
7
7
|
}
|