@chatwidgetai/chat-widget 0.2.9 → 0.3.1

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.
Files changed (37) hide show
  1. package/dist/ai-chat-widget.umd.js +1546 -331
  2. package/dist/ai-chat-widget.umd.js.map +1 -1
  3. package/dist/api/client.d.ts +2 -2
  4. package/dist/api/client.d.ts.map +1 -1
  5. package/dist/components/ChatWidget.d.ts +2 -1
  6. package/dist/components/ChatWidget.d.ts.map +1 -1
  7. package/dist/components/ChatWindow.d.ts +0 -1
  8. package/dist/components/ChatWindow.d.ts.map +1 -1
  9. package/dist/components/DataPolicyView.d.ts +14 -0
  10. package/dist/components/DataPolicyView.d.ts.map +1 -0
  11. package/dist/hooks/useChat/action-handler.d.ts +6 -0
  12. package/dist/hooks/useChat/action-handler.d.ts.map +1 -0
  13. package/dist/hooks/useChat/action-lifecycle.d.ts +19 -0
  14. package/dist/hooks/useChat/action-lifecycle.d.ts.map +1 -0
  15. package/dist/hooks/useChat/error-utils.d.ts +7 -0
  16. package/dist/hooks/useChat/error-utils.d.ts.map +1 -0
  17. package/dist/hooks/{useChat.d.ts → useChat/index.d.ts} +2 -2
  18. package/dist/hooks/useChat/index.d.ts.map +1 -0
  19. package/dist/hooks/useChat/message-hydration.d.ts +4 -0
  20. package/dist/hooks/useChat/message-hydration.d.ts.map +1 -0
  21. package/dist/hooks/useChat/stream-handlers.d.ts +27 -0
  22. package/dist/hooks/useChat/stream-handlers.d.ts.map +1 -0
  23. package/dist/hooks/useChat/stream-state.d.ts +8 -0
  24. package/dist/hooks/useChat/stream-state.d.ts.map +1 -0
  25. package/dist/hooks/useChat/types.d.ts +26 -0
  26. package/dist/hooks/useChat/types.d.ts.map +1 -0
  27. package/dist/index.d.ts +1 -1
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.esm.js +1546 -331
  30. package/dist/index.esm.js.map +1 -1
  31. package/dist/index.js +1546 -331
  32. package/dist/index.js.map +1 -1
  33. package/dist/types/index.d.ts +10 -3
  34. package/dist/types/index.d.ts.map +1 -1
  35. package/dist/utils/sse-parser.d.ts.map +1 -1
  36. package/package.json +7 -3
  37. package/dist/hooks/useChat.d.ts.map +0 -1
package/dist/index.js CHANGED
@@ -10,11 +10,14 @@ async function* parseSSEStream(response, validator) {
10
10
  const reader = response.body.getReader();
11
11
  const decoder = new TextDecoder();
12
12
  let buffer = "";
13
+ let eventCount = 0;
13
14
  try {
14
15
  while (true) {
15
16
  const { done, value } = await reader.read();
16
- if (done)
17
+ if (done) {
18
+ console.log(`[SSE Parser] Stream ended normally after ${eventCount} events`);
17
19
  break;
20
+ }
18
21
  buffer += decoder.decode(value, { stream: true });
19
22
  const chunks = buffer.split("\n\n");
20
23
  buffer = chunks.pop() || "";
@@ -26,6 +29,7 @@ async function* parseSSEStream(response, validator) {
26
29
  const data = JSON.parse(line.slice(6));
27
30
  if (validator) {
28
31
  if (validator(data)) {
32
+ eventCount++;
29
33
  yield data;
30
34
  }
31
35
  else {
@@ -33,6 +37,7 @@ async function* parseSSEStream(response, validator) {
33
37
  }
34
38
  }
35
39
  else {
40
+ eventCount++;
36
41
  yield data;
37
42
  }
38
43
  }
@@ -45,6 +50,10 @@ async function* parseSSEStream(response, validator) {
45
50
  }
46
51
  }
47
52
  }
53
+ catch (error) {
54
+ console.error(`[SSE Parser] Stream error after ${eventCount} events:`, error);
55
+ throw error;
56
+ }
48
57
  finally {
49
58
  reader.releaseLock();
50
59
  }
@@ -178,7 +187,7 @@ class WidgetApiClient {
178
187
  const result = await response.json();
179
188
  return result.file;
180
189
  }
181
- async *sendAgentMessageStream(conversationId, message, fileIds) {
190
+ async *sendAgentMessageStream(conversationId, message, fileIds, signal) {
182
191
  const headers = {
183
192
  'Content-Type': 'application/json',
184
193
  };
@@ -194,6 +203,7 @@ class WidgetApiClient {
194
203
  fileIds,
195
204
  timeZone: this.getTimeZone(),
196
205
  }),
206
+ signal,
197
207
  });
198
208
  if (!response.ok) {
199
209
  throw await buildApiError(response, 'Failed to send agent message');
@@ -202,7 +212,7 @@ class WidgetApiClient {
202
212
  return typeof data === 'object' && data !== null && 'type' in data;
203
213
  });
204
214
  }
205
- async *continueAgentMessageStream(conversationId, toolCallId, state) {
215
+ async *continueAgentMessageStream(conversationId, toolCallId, state, signal) {
206
216
  const headers = {
207
217
  'Content-Type': 'application/json',
208
218
  };
@@ -218,6 +228,7 @@ class WidgetApiClient {
218
228
  state,
219
229
  timeZone: this.getTimeZone(),
220
230
  }),
231
+ signal,
221
232
  });
222
233
  if (!response.ok) {
223
234
  throw await buildApiError(response, 'Failed to continue agent');
@@ -27122,18 +27133,14 @@ const formatToolName = (name) => {
27122
27133
  .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
27123
27134
  .join(' ');
27124
27135
  };
27125
- const GearIcon = ({ spinning = false }) => (jsxRuntime.jsxs("svg", { className: `ai-chat-tool-gear ${spinning ? 'spinning' : ''}`, width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntime.jsx("path", { d: "M12 20a8 8 0 1 0 0-16 8 8 0 0 0 0 16Z" }), jsxRuntime.jsx("path", { d: "M12 14a2 2 0 1 0 0-4 2 2 0 0 0 0 4Z" }), jsxRuntime.jsx("path", { d: "M12 2v2" }), jsxRuntime.jsx("path", { d: "M12 22v-2" }), jsxRuntime.jsx("path", { d: "m17 20.66-1-1.73" }), jsxRuntime.jsx("path", { d: "M11 10.27 7 3.34" }), jsxRuntime.jsx("path", { d: "m20.66 17-1.73-1" }), jsxRuntime.jsx("path", { d: "m3.34 7 1.73 1" }), jsxRuntime.jsx("path", { d: "M14 12h8" }), jsxRuntime.jsx("path", { d: "M2 12h2" }), jsxRuntime.jsx("path", { d: "m20.66 7-1.73 1" }), jsxRuntime.jsx("path", { d: "m3.34 17 1.73-1" }), jsxRuntime.jsx("path", { d: "m17 3.34-1 1.73" }), jsxRuntime.jsx("path", { d: "m11 13.73-4 6.93" })] }));
27126
- const CheckIcon$2 = () => (jsxRuntime.jsx("svg", { className: "ai-chat-tool-check", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntime.jsx("polyline", { points: "20 6 9 17 4 12" }) }));
27127
- const ErrorIcon = () => (jsxRuntime.jsx("svg", { className: "ai-chat-tool-error", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntime.jsx("path", { d: "M18 6L6 18M6 6l12 12" }) }));
27128
27136
  function ToolIndicator({ badges, className = '' }) {
27129
- const isAnyLoading = badges.some(b => b.status === 'loading');
27130
- return (jsxRuntime.jsxs("div", { className: `ai-chat-tool-row ${className}`, children: [jsxRuntime.jsx(GearIcon, { spinning: isAnyLoading }), jsxRuntime.jsx("div", { className: "ai-chat-tool-badges", children: badges.map((badge) => (jsxRuntime.jsxs("div", { className: `ai-chat-tool-badge ${badge.status}`, children: [badge.status !== 'loading' && (badge.status === 'error' ? jsxRuntime.jsx(ErrorIcon, {}) : jsxRuntime.jsx(CheckIcon$2, {})), jsxRuntime.jsx("span", { className: "tool-name", children: formatToolName(badge.name) })] }, badge.id))) })] }));
27137
+ return (jsxRuntime.jsx("div", { className: `ai-chat-tool-row ${className}`, children: jsxRuntime.jsx("div", { className: "ai-chat-tool-badges", children: badges.map((badge) => (jsxRuntime.jsx("div", { className: `ai-chat-tool-badge ${badge.status}`, children: jsxRuntime.jsx("span", { className: "tool-name", children: formatToolName(badge.name) }) }, badge.id))) }) }));
27131
27138
  }
27132
27139
 
27133
27140
  // SVG Icon components
27134
27141
  const ThumbsUpIcon = () => (jsxRuntime.jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntime.jsx("path", { d: "M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3" }) }));
27135
27142
  const ThumbsDownIcon = () => (jsxRuntime.jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntime.jsx("path", { d: "M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17" }) }));
27136
- const CheckIcon$1 = () => (jsxRuntime.jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntime.jsx("polyline", { points: "20 6 9 17 4 12" }) }));
27143
+ const CheckIcon$2 = () => (jsxRuntime.jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntime.jsx("polyline", { points: "20 6 9 17 4 12" }) }));
27137
27144
  const FeedbackButtons = ({ messageId, currentFeedback, onFeedback, }) => {
27138
27145
  const [isSubmitting, setIsSubmitting] = React.useState(false);
27139
27146
  const [submitted, setSubmitted] = React.useState(false);
@@ -27154,17 +27161,10 @@ const FeedbackButtons = ({ messageId, currentFeedback, onFeedback, }) => {
27154
27161
  setIsSubmitting(false);
27155
27162
  }
27156
27163
  };
27157
- return (jsxRuntime.jsxs("div", { className: `ai-chat-feedback ${submitted ? 'submitted' : ''}`, children: [jsxRuntime.jsxs("div", { className: "ai-chat-feedback-buttons", children: [jsxRuntime.jsx("button", { className: `ai-chat-feedback-button ${currentFeedback === 'positive' ? 'active' : ''}`, onClick: () => handleFeedback('positive'), disabled: isDisabled, "aria-label": "Helpful", title: "This was helpful", children: jsxRuntime.jsx(ThumbsUpIcon, {}) }), jsxRuntime.jsx("button", { className: `ai-chat-feedback-button ${currentFeedback === 'negative' ? 'active' : ''}`, onClick: () => handleFeedback('negative'), disabled: isDisabled, "aria-label": "Not helpful", title: "This was not helpful", children: jsxRuntime.jsx(ThumbsDownIcon, {}) })] }), submitted && (jsxRuntime.jsxs("div", { className: "ai-chat-feedback-message", "aria-live": "polite", children: [jsxRuntime.jsx("span", { className: "ai-chat-feedback-checkmark", children: jsxRuntime.jsx(CheckIcon$1, {}) }), jsxRuntime.jsx("span", { className: "ai-chat-feedback-text", children: "Thanks for feedback" })] }))] }));
27158
- };
27159
-
27160
- const Sources = ({ sources, displayMode = 'with-score' }) => {
27161
- const [isExpanded, setIsExpanded] = React.useState(false);
27162
- if (!sources || sources.length === 0 || displayMode === 'none')
27163
- return null;
27164
- return (jsxRuntime.jsxs("div", { className: "ai-chat-sources", children: [jsxRuntime.jsxs("button", { className: "ai-chat-sources-toggle", onClick: () => setIsExpanded(!isExpanded), "aria-expanded": isExpanded, children: [jsxRuntime.jsx("span", { className: "ai-chat-sources-icon", children: isExpanded ? '▼' : '▶' }), jsxRuntime.jsxs("span", { className: "ai-chat-sources-title", children: [sources.length, " source", sources.length > 1 ? 's' : ''] })] }), isExpanded && displayMode !== 'minimal' && (jsxRuntime.jsx("div", { className: "ai-chat-sources-list", children: sources.map((source, index) => (jsxRuntime.jsxs("div", { className: "ai-chat-source-item", children: [jsxRuntime.jsxs("div", { className: "ai-chat-source-number", children: [index + 1, "."] }), jsxRuntime.jsxs("div", { className: "ai-chat-source-details", children: [displayMode === 'with-score' && source.score && (jsxRuntime.jsxs("div", { className: "ai-chat-source-score", children: ["Score: ", (source.score * 100).toFixed(0), "%"] })), (displayMode === 'with-content' || displayMode === 'full') && source.doc.pageContent && (jsxRuntime.jsxs("div", { className: "ai-chat-source-content", children: [source.doc.pageContent.substring(0, 100), source.doc.pageContent.length > 100 ? '...' : ''] })), displayMode === 'full' && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [source.score && (jsxRuntime.jsxs("div", { className: "ai-chat-source-score", children: ["Score: ", (source.score * 100).toFixed(0), "%"] })), source.doc.metadata && Object.keys(source.doc.metadata).length > 0 && (jsxRuntime.jsx("div", { className: "ai-chat-source-metadata", children: Object.entries(source.doc.metadata).map(([key, value]) => (jsxRuntime.jsxs("span", { className: "ai-chat-source-meta-item", children: [key, ": ", String(value)] }, key))) }))] }))] })] }, `${source.kbId}-${source.doc.id}-${index}`))) }))] }));
27164
+ return (jsxRuntime.jsxs("div", { className: `ai-chat-feedback ${submitted ? 'submitted' : ''}`, children: [jsxRuntime.jsxs("div", { className: "ai-chat-feedback-buttons", children: [jsxRuntime.jsx("button", { className: `ai-chat-feedback-button ${currentFeedback === 'positive' ? 'active' : ''}`, onClick: () => handleFeedback('positive'), disabled: isDisabled, "aria-label": "Helpful", title: "This was helpful", children: jsxRuntime.jsx(ThumbsUpIcon, {}) }), jsxRuntime.jsx("button", { className: `ai-chat-feedback-button ${currentFeedback === 'negative' ? 'active' : ''}`, onClick: () => handleFeedback('negative'), disabled: isDisabled, "aria-label": "Not helpful", title: "This was not helpful", children: jsxRuntime.jsx(ThumbsDownIcon, {}) })] }), submitted && (jsxRuntime.jsxs("div", { className: "ai-chat-feedback-message", "aria-live": "polite", children: [jsxRuntime.jsx("span", { className: "ai-chat-feedback-checkmark", children: jsxRuntime.jsx(CheckIcon$2, {}) }), jsxRuntime.jsx("span", { className: "ai-chat-feedback-text", children: "Thanks for feedback" })] }))] }));
27165
27165
  };
27166
27166
 
27167
- const Message = ({ message, showTimestamp = true, enableFeedback = true, showSources = true, sourceDisplayMode = 'with-score', onFeedback, getActionRenderer, }) => {
27167
+ const Message = ({ message, showTimestamp = true, enableFeedback = true, onFeedback, }) => {
27168
27168
  const formatTime = (timestamp) => {
27169
27169
  const date = typeof timestamp === 'string' ? new Date(timestamp) : timestamp;
27170
27170
  return date.toLocaleTimeString('en-US', {
@@ -27184,15 +27184,15 @@ const Message = ({ message, showTimestamp = true, enableFeedback = true, showSou
27184
27184
  return null;
27185
27185
  }
27186
27186
  // AI message rendering
27187
+ // Note: Actions are rendered by ToolMessageGroup for tool messages, not here
27187
27188
  if (isAssistant) {
27188
27189
  const aiContent = message.message.content || '';
27189
27190
  const hasContent = aiContent.trim().length > 0;
27190
27191
  if (!hasContent)
27191
27192
  return null;
27192
- const actionRenderer = message.action && getActionRenderer
27193
- ? getActionRenderer(message.action.implementation)
27194
- : undefined;
27195
- return (jsxRuntime.jsxs("div", { className: `ai-chat-message assistant ${isError ? 'error' : ''}`, children: [jsxRuntime.jsxs("div", { className: "ai-chat-message-content", children: [isError && (jsxRuntime.jsxs("div", { className: "ai-chat-error-indicator", children: [jsxRuntime.jsx("span", { className: "error-icon", children: "\u26A0\uFE0F" }), jsxRuntime.jsx("span", { className: "error-text", children: "Error" })] })), jsxRuntime.jsx(Markdown, { remarkPlugins: [remarkGfm], children: aiContent })] }), actionRenderer && message.action && actionRenderer(message), showTimestamp && (jsxRuntime.jsxs("div", { className: "ai-chat-message-meta", children: [jsxRuntime.jsx("span", { className: "ai-chat-message-timestamp", children: formatTime(message.timestamp) }), enableFeedback && onFeedback && (jsxRuntime.jsx(FeedbackButtons, { messageId: message.id, currentFeedback: message.feedback, onFeedback: onFeedback }))] })), showSources && message.sources?.length > 0 && (jsxRuntime.jsx(Sources, { sources: message.sources, displayMode: sourceDisplayMode }))] }));
27193
+ return (jsxRuntime.jsxs("div", { className: `ai-chat-message assistant ${isError ? 'error' : ''}`, children: [jsxRuntime.jsx("div", { className: "ai-chat-message-content", children: jsxRuntime.jsx(Markdown, { remarkPlugins: [remarkGfm], components: {
27194
+ table: ({ children, ...props }) => (jsxRuntime.jsx("div", { className: "table-wrapper", children: jsxRuntime.jsx("div", { className: "table-scroll", children: jsxRuntime.jsx("table", { ...props, children: children }) }) })),
27195
+ }, children: aiContent }) }), showTimestamp && (jsxRuntime.jsxs("div", { className: "ai-chat-message-meta", children: [jsxRuntime.jsx("span", { className: "ai-chat-message-timestamp", children: formatTime(message.timestamp) }), enableFeedback && onFeedback && (jsxRuntime.jsx(FeedbackButtons, { messageId: message.id, currentFeedback: message.feedback, onFeedback: onFeedback }))] }))] }));
27196
27196
  }
27197
27197
  // System message rendering
27198
27198
  if (isSystem) {
@@ -27206,30 +27206,85 @@ const Message = ({ message, showTimestamp = true, enableFeedback = true, showSou
27206
27206
  return null;
27207
27207
  };
27208
27208
 
27209
- const ToolMessageGroup = ({ messages, getActionRenderer }) => {
27209
+ // Centralized action state logic
27210
+ function isActionComplete(state) {
27211
+ if (!state)
27212
+ return false;
27213
+ const TERMINAL_STATUSES = [
27214
+ 'completed', 'booked', 'scheduled', 'cancelled', 'failed', 'error',
27215
+ 'displaying', 'clicked', 'contacted', 'submitted', 'sent'
27216
+ ];
27217
+ const status = state.status;
27218
+ if (typeof status === 'string' && TERMINAL_STATUSES.includes(status)) {
27219
+ return true;
27220
+ }
27221
+ // For non-halting actions (query_contact_directory, etc.) with results/success
27222
+ if (!status && (state.success !== undefined || state.results !== undefined)) {
27223
+ return true;
27224
+ }
27225
+ return false;
27226
+ }
27227
+ function isActionLoading(message) {
27228
+ if (!message.action)
27229
+ return false;
27230
+ if (message.action.done)
27231
+ return false;
27232
+ if (message.isStreaming)
27233
+ return true;
27234
+ const state = message.action.state;
27235
+ return !isActionComplete(state);
27236
+ }
27237
+ const ToolMessageGroup = ({ messages, getActionRenderer, showToolIndicator = true, accentColor, variant }) => {
27210
27238
  const actionMessages = messages.filter(message => message.action);
27239
+ // Debug logging
27240
+ console.log('[DEBUG ToolMessageGroup] ========================================');
27241
+ console.log('[DEBUG ToolMessageGroup] Total messages:', messages.length);
27242
+ console.log('[DEBUG ToolMessageGroup] Messages with action:', actionMessages.length);
27243
+ console.log('[DEBUG ToolMessageGroup] hasGetActionRenderer:', !!getActionRenderer);
27244
+ messages.forEach((msg, i) => {
27245
+ console.log(`[DEBUG ToolMessageGroup] Message ${i}:`, {
27246
+ id: msg.id,
27247
+ role: msg.message.role,
27248
+ hasAction: !!msg.action,
27249
+ actionImpl: msg.action?.implementation,
27250
+ toolExecuting: msg.toolExecuting,
27251
+ });
27252
+ });
27253
+ actionMessages.forEach((msg, i) => {
27254
+ const impl = msg.action?.implementation || '';
27255
+ const renderer = getActionRenderer?.(impl);
27256
+ console.log(`[DEBUG ToolMessageGroup] Action ${i}:`, {
27257
+ implementation: impl,
27258
+ hasRenderer: !!renderer,
27259
+ rendererType: renderer ? typeof renderer : 'undefined',
27260
+ state: msg.action?.state,
27261
+ });
27262
+ });
27263
+ // If tool indicator is hidden AND there are no action cards to render, don't render anything
27264
+ if (!showToolIndicator && actionMessages.length === 0) {
27265
+ return null;
27266
+ }
27211
27267
  const badges = messages.map((message) => {
27212
27268
  const toolName = message.toolExecuting || message.message.name || 'Tool';
27213
27269
  const hasError = message.isError || false;
27214
- const actionState = message.action?.state;
27215
- const actionStatus = actionState?.status;
27216
- const terminalStatuses = ['completed', 'booked', 'scheduled', 'failed', 'cancelled'];
27217
- const isTerminalStatus = actionStatus && terminalStatuses.includes(actionStatus);
27218
- const isDone = message.action ? (message.action.done ?? isTerminalStatus ?? false) : !message.isStreaming;
27219
- const isLoading = !isDone;
27270
+ const loading = isActionLoading(message);
27220
27271
  return {
27221
27272
  id: message.id,
27222
27273
  name: toolName,
27223
- status: isLoading ? 'loading' : hasError ? 'error' : 'completed',
27274
+ status: loading ? 'loading' : hasError ? 'error' : 'completed',
27224
27275
  };
27225
27276
  });
27226
- return (jsxRuntime.jsxs("div", { className: "ai-chat-message tool", children: [jsxRuntime.jsx(ToolIndicator, { badges: badges }), actionMessages.map((message) => {
27227
- if (!message.action || !getActionRenderer)
27277
+ return (jsxRuntime.jsxs("div", { className: "ai-chat-message tool", children: [showToolIndicator && jsxRuntime.jsx(ToolIndicator, { badges: badges }), actionMessages.map((message) => {
27278
+ if (!message.action || !getActionRenderer) {
27279
+ console.log('[ToolMessageGroup] Skipping - no action or renderer:', { hasAction: !!message.action, hasGetRenderer: !!getActionRenderer });
27228
27280
  return null;
27281
+ }
27229
27282
  const renderer = getActionRenderer(message.action.implementation);
27230
- if (!renderer)
27283
+ if (!renderer) {
27284
+ console.log('[ToolMessageGroup] No renderer for:', message.action.implementation);
27231
27285
  return null;
27232
- return (jsxRuntime.jsx("div", { className: "ai-chat-tool-action", children: renderer(message) }, `action-${message.id}`));
27286
+ }
27287
+ return (jsxRuntime.jsx("div", { className: "ai-chat-tool-action", children: renderer(message, accentColor, variant) }, `action-${message.id}`));
27233
27288
  })] }));
27234
27289
  };
27235
27290
 
@@ -27291,12 +27346,16 @@ const FollowUpSuggestions = ({ suggestions, onQuestionClick, onActionClick, acce
27291
27346
  };
27292
27347
 
27293
27348
  const MessageList = (props) => {
27294
- const { messages, isTyping = false, showTypingIndicator = true, showTimestamps = true, enableFeedback = true, showSources = true, sourceDisplayMode = 'with-score', welcomeTitle, welcomeMessage, suggestedQuestions, accentColor, onSuggestedQuestionClick, onActionClick, onFeedback, onScrollStateChange, getActionRenderer, } = props;
27349
+ const { messages, isTyping = false, showTypingIndicator = true, showTimestamps = true, showToolCalls = false, enableFeedback = true, welcomeTitle, welcomeMessage, suggestedQuestions, accentColor, onSuggestedQuestionClick, onActionClick, onFeedback, onScrollStateChange, getActionRenderer, variant, } = props;
27295
27350
  const containerRef = React.useRef(null);
27296
27351
  const messagesEndRef = React.useRef(null);
27297
27352
  const [showScrollButton, setShowScrollButton] = React.useState(false);
27298
27353
  const prevMessageCountRef = React.useRef(0);
27299
- const hasActiveAction = React.useMemo(() => messages.some(msg => msg.action?.state?.status && !['completed', 'booked', 'failed'].includes(msg.action.state.status)), [messages]);
27354
+ const hasActiveAction = React.useMemo(() => {
27355
+ // Find the last tool message and check if its action is still active (not done)
27356
+ const lastToolMsg = [...messages].reverse().find(msg => msg.message.role === 'tool');
27357
+ return lastToolMsg?.action && lastToolMsg.action.done !== true;
27358
+ }, [messages]);
27300
27359
  const checkScrollPosition = React.useCallback(() => {
27301
27360
  const c = containerRef.current;
27302
27361
  if (!c)
@@ -27332,39 +27391,70 @@ const MessageList = (props) => {
27332
27391
  checkScrollPosition();
27333
27392
  }, [messages, isTyping, checkScrollPosition]);
27334
27393
  const groupedMessages = React.useMemo(() => {
27394
+ console.log('[DEBUG MessageList] ========================================');
27395
+ console.log('[DEBUG MessageList] Processing messages:', messages.length);
27396
+ messages.forEach((m, i) => {
27397
+ console.log(`[DEBUG MessageList] Message ${i}:`, {
27398
+ id: m.id,
27399
+ role: m.message.role,
27400
+ hasAction: !!m.action,
27401
+ actionImpl: m.action?.implementation,
27402
+ content: (m.message.content || '').substring(0, 50),
27403
+ });
27404
+ });
27335
27405
  const result = [];
27336
27406
  let toolGroup = [];
27337
- const flush = () => { if (toolGroup.length) {
27338
- result.push({ type: 'tool-group', messages: [...toolGroup] });
27339
- toolGroup = [];
27340
- } };
27407
+ const flush = () => {
27408
+ if (toolGroup.length) {
27409
+ console.log('[DEBUG MessageList] Flushing tool group with', toolGroup.length, 'messages');
27410
+ result.push({ type: 'tool-group', messages: [...toolGroup] });
27411
+ toolGroup = [];
27412
+ }
27413
+ };
27341
27414
  for (const m of messages) {
27342
- if (m.message.role === 'tool')
27415
+ if (m.message.role === 'tool') {
27416
+ console.log('[DEBUG MessageList] Adding to tool group:', m.id);
27343
27417
  toolGroup.push(m);
27418
+ }
27344
27419
  else if (m.message.role === 'user') {
27345
27420
  flush();
27346
27421
  result.push({ type: 'message', message: m });
27347
27422
  }
27348
- else if (m.message.role === 'assistant' && (m.message.content || '').trim()) {
27349
- flush();
27350
- result.push({ type: 'message', message: m });
27423
+ else if (m.message.role === 'assistant') {
27424
+ // Include assistant messages if they have content OR are still streaming (content may arrive)
27425
+ const hasContent = (m.message.content || '').trim().length > 0;
27426
+ if (hasContent || m.isStreaming) {
27427
+ flush();
27428
+ result.push({ type: 'message', message: m });
27429
+ }
27430
+ // Don't flush on empty assistant messages - let tools continue grouping
27351
27431
  }
27352
- else if (m.message.role !== 'assistant') {
27432
+ else {
27353
27433
  flush();
27354
27434
  result.push({ type: 'message', message: m });
27355
27435
  }
27356
27436
  }
27357
27437
  flush();
27438
+ console.log('[DEBUG MessageList] Final grouped result:', result.length, 'items');
27439
+ result.forEach((item, i) => {
27440
+ if (item.type === 'tool-group') {
27441
+ console.log(`[DEBUG MessageList] Group ${i}: tool-group with ${item.messages.length} messages`);
27442
+ }
27443
+ else {
27444
+ console.log(`[DEBUG MessageList] Group ${i}: message (${item.message.message.role})`);
27445
+ }
27446
+ });
27358
27447
  return result;
27359
27448
  }, [messages]);
27360
27449
  const hasSuggestions = messages.length === 0 && onSuggestedQuestionClick && suggestedQuestions?.length;
27361
27450
  const showWelcome = welcomeTitle || welcomeMessage || hasSuggestions;
27362
27451
  return (jsxRuntime.jsxs("div", { ref: containerRef, className: "ai-chat-messages", role: "log", "aria-live": "polite", children: [showWelcome && (jsxRuntime.jsxs("div", { className: "ai-chat-welcome", children: [welcomeTitle && jsxRuntime.jsx("div", { className: "ai-chat-welcome-title", children: welcomeTitle }), welcomeMessage && jsxRuntime.jsx("div", { className: "ai-chat-welcome-text", children: welcomeMessage }), hasSuggestions && jsxRuntime.jsx(SuggestedQuestions, { questions: suggestedQuestions, onQuestionClick: onSuggestedQuestionClick })] })), groupedMessages.map((item, i) => {
27363
- if (item.type === 'tool-group')
27364
- return jsxRuntime.jsx(ToolMessageGroup, { messages: item.messages, getActionRenderer: getActionRenderer }, `tg-${i}`);
27452
+ if (item.type === 'tool-group') {
27453
+ return jsxRuntime.jsx(ToolMessageGroup, { messages: item.messages, getActionRenderer: getActionRenderer, showToolIndicator: showToolCalls, accentColor: accentColor, variant: variant }, `tg-${i}`);
27454
+ }
27365
27455
  const isLast = i === groupedMessages.length - 1;
27366
27456
  const hasFollowUp = item.message.message.role === 'assistant' && item.message.suggestions?.length && isLast && !isTyping;
27367
- return (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsx(Message, { message: item.message, showTimestamp: showTimestamps, enableFeedback: enableFeedback, showSources: showSources, sourceDisplayMode: sourceDisplayMode, onFeedback: onFeedback, getActionRenderer: getActionRenderer }), hasFollowUp && onSuggestedQuestionClick && jsxRuntime.jsx(FollowUpSuggestions, { suggestions: item.message.suggestions, onQuestionClick: onSuggestedQuestionClick, onActionClick: onActionClick, accentColor: accentColor })] }, item.message.id));
27457
+ return (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsx(Message, { message: item.message, showTimestamp: showTimestamps, onFeedback: onFeedback, getActionRenderer: getActionRenderer, accentColor: accentColor }), hasFollowUp && onSuggestedQuestionClick && jsxRuntime.jsx(FollowUpSuggestions, { suggestions: item.message.suggestions, onQuestionClick: onSuggestedQuestionClick, onActionClick: onActionClick, accentColor: accentColor })] }, item.message.id));
27368
27458
  }), isTyping && showTypingIndicator && !hasActiveAction && messages.length > 0 && jsxRuntime.jsx(TypingIndicator, {}), jsxRuntime.jsx("div", { ref: messagesEndRef })] }));
27369
27459
  };
27370
27460
 
@@ -27379,7 +27469,7 @@ const formatFileSize = (bytes) => {
27379
27469
  return (bytes / 1024).toFixed(1) + ' KB';
27380
27470
  return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
27381
27471
  };
27382
- const MessageInput = ({ onSend, placeholder = 'Type your message...', disabled = false, enableFileUpload = false, separateFromChat = true, }) => {
27472
+ const MessageInput = ({ onSend, placeholder = 'Type your message...', disabled = false, enableFileUpload = false, separateFromChat = true, showDataPolicy = true, onDataPolicyClick, }) => {
27383
27473
  const [value, setValue] = React.useState('');
27384
27474
  const [selectedFiles, setSelectedFiles] = React.useState([]);
27385
27475
  const textareaRef = React.useRef(null);
@@ -27414,10 +27504,10 @@ const MessageInput = ({ onSend, placeholder = 'Type your message...', disabled =
27414
27504
  }
27415
27505
  };
27416
27506
  const canSend = value.trim() || selectedFiles.length > 0;
27417
- return (jsxRuntime.jsxs("div", { className: `ai-chat-input-container ${separateFromChat ? 'separate' : 'integrated'}`, children: [selectedFiles.length > 0 && (jsxRuntime.jsx("div", { className: "ai-chat-file-list", children: selectedFiles.map((file, index) => (jsxRuntime.jsxs("div", { className: "ai-chat-file-item", children: [jsxRuntime.jsx("span", { className: "ai-chat-file-extension", children: getFileExtension(file.name) }), jsxRuntime.jsxs("div", { className: "ai-chat-file-info", children: [jsxRuntime.jsx("span", { className: "ai-chat-file-name", children: file.name }), jsxRuntime.jsx("span", { className: "ai-chat-file-size", children: formatFileSize(file.size) })] }), jsxRuntime.jsx("button", { className: "ai-chat-file-remove", onClick: () => handleRemoveFile(index), "aria-label": "Remove file", children: jsxRuntime.jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: jsxRuntime.jsx("path", { d: "M18 6L6 18M6 6l12 12" }) }) })] }, index))) })), jsxRuntime.jsxs("div", { className: "ai-chat-input-wrapper", children: [enableFileUpload && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("input", { ref: fileInputRef, type: "file", onChange: handleFileSelect, style: { display: 'none' }, multiple: true, accept: ALLOWED_EXTENSIONS.join(',') }), jsxRuntime.jsx("button", { className: "ai-chat-file-button", onClick: () => fileInputRef.current?.click(), disabled: disabled, "aria-label": "Attach file", children: jsxRuntime.jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: jsxRuntime.jsx("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" }) }) })] })), jsxRuntime.jsx("textarea", { ref: textareaRef, className: "ai-chat-input", value: value, onChange: (e) => setValue(e.target.value), onKeyDown: handleKeyDown, placeholder: placeholder, disabled: disabled, rows: 2, wrap: "soft", "aria-label": "Message input" }), jsxRuntime.jsx("button", { className: `ai-chat-send-button ${canSend ? 'active' : ''}`, onClick: handleSend, disabled: disabled || !canSend, "aria-label": "Send message", children: jsxRuntime.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: [jsxRuntime.jsx("path", { d: "M12 19V5" }), jsxRuntime.jsx("path", { d: "M5 12l7-7 7 7" })] }) })] })] }));
27507
+ return (jsxRuntime.jsxs("div", { className: `ai-chat-input-container ${separateFromChat ? 'separate' : 'integrated'}`, children: [selectedFiles.length > 0 && (jsxRuntime.jsx("div", { className: "ai-chat-file-list", children: selectedFiles.map((file, index) => (jsxRuntime.jsxs("div", { className: "ai-chat-file-item", children: [jsxRuntime.jsx("span", { className: "ai-chat-file-extension", children: getFileExtension(file.name) }), jsxRuntime.jsxs("div", { className: "ai-chat-file-info", children: [jsxRuntime.jsx("span", { className: "ai-chat-file-name", children: file.name }), jsxRuntime.jsx("span", { className: "ai-chat-file-size", children: formatFileSize(file.size) })] }), jsxRuntime.jsx("button", { className: "ai-chat-file-remove", onClick: () => handleRemoveFile(index), "aria-label": "Remove file", children: jsxRuntime.jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: jsxRuntime.jsx("path", { d: "M18 6L6 18M6 6l12 12" }) }) })] }, index))) })), jsxRuntime.jsxs("div", { className: "ai-chat-input-wrapper", children: [enableFileUpload && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("input", { ref: fileInputRef, type: "file", onChange: handleFileSelect, style: { display: 'none' }, multiple: true, accept: ALLOWED_EXTENSIONS.join(',') }), jsxRuntime.jsx("button", { className: "ai-chat-file-button", onClick: () => fileInputRef.current?.click(), disabled: disabled, "aria-label": "Attach file", children: jsxRuntime.jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: jsxRuntime.jsx("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" }) }) })] })), jsxRuntime.jsx("textarea", { ref: textareaRef, className: "ai-chat-input", value: value, onChange: (e) => setValue(e.target.value), onKeyDown: handleKeyDown, placeholder: placeholder, disabled: disabled, rows: 2, wrap: "soft", "aria-label": "Message input" }), jsxRuntime.jsx("button", { className: `ai-chat-send-button ${canSend ? 'active' : ''}`, onClick: handleSend, disabled: disabled || !canSend, "aria-label": "Send message", children: jsxRuntime.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: [jsxRuntime.jsx("path", { d: "M12 19V5" }), jsxRuntime.jsx("path", { d: "M5 12l7-7 7 7" })] }) })] }), showDataPolicy && (jsxRuntime.jsxs("div", { className: "ai-chat-data-policy", children: [jsxRuntime.jsx("span", { children: "KI-generierte Antworten k\u00F6nnen unzutreffend sein." }), onDataPolicyClick && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [' ', jsxRuntime.jsx("button", { type: "button", className: "ai-chat-data-policy-link", onClick: onDataPolicyClick, children: "Datenschutzhinweis" })] }))] }))] }));
27418
27508
  };
27419
27509
 
27420
- function groupSlotsByDate(slots) {
27510
+ function groupSlotsByDate$1(slots) {
27421
27511
  const grouped = new Map();
27422
27512
  for (const slot of slots) {
27423
27513
  if (!slot || typeof slot !== 'object' || !slot.startTime || typeof slot.startTime !== 'string') {
@@ -27431,7 +27521,7 @@ function groupSlotsByDate(slots) {
27431
27521
  }
27432
27522
  return grouped;
27433
27523
  }
27434
- function formatDate(dateStr) {
27524
+ function formatDate$1(dateStr) {
27435
27525
  try {
27436
27526
  const date = new Date(dateStr);
27437
27527
  return new Intl.DateTimeFormat("en-US", {
@@ -27444,16 +27534,16 @@ function formatDate(dateStr) {
27444
27534
  return dateStr;
27445
27535
  }
27446
27536
  }
27447
- function CalendarIcon() {
27537
+ function CalendarIcon$1() {
27448
27538
  return (jsxRuntime.jsx("svg", { className: "ai-chat-action-icon", viewBox: "0 0 20 20", fill: "currentColor", children: jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z", clipRule: "evenodd" }) }));
27449
27539
  }
27450
- function CheckIcon() {
27540
+ function CheckIcon$1() {
27451
27541
  return (jsxRuntime.jsx("svg", { className: "ai-chat-action-icon-success", viewBox: "0 0 20 20", fill: "currentColor", children: jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z", clipRule: "evenodd" }) }));
27452
27542
  }
27453
- function ExternalLinkIcon() {
27543
+ function ExternalLinkIcon$2() {
27454
27544
  return (jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntime.jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }), jsxRuntime.jsx("polyline", { points: "15 3 21 3 21 9" }), jsxRuntime.jsx("line", { x1: "10", y1: "14", x2: "21", y2: "3" })] }));
27455
27545
  }
27456
- function Skeleton({ width, height, borderRadius = '4px' }) {
27546
+ function Skeleton$1({ width, height, borderRadius = '4px' }) {
27457
27547
  return (jsxRuntime.jsx("div", { className: "ai-chat-action-skeleton-item", style: { width, height, borderRadius } }));
27458
27548
  }
27459
27549
  function GoogleCalendarCard({ action, onComplete, accentColor, className = '' }) {
@@ -27470,13 +27560,12 @@ function GoogleCalendarCard({ action, onComplete, accentColor, className = '' })
27470
27560
  : [];
27471
27561
  const allowTopic = state.allowTopic !== false;
27472
27562
  const isBooked = state.status === "booked";
27473
- const slotsByDate = groupSlotsByDate(availableSlots);
27563
+ const slotsByDate = groupSlotsByDate$1(availableSlots);
27474
27564
  const dates = Array.from(slotsByDate.keys()).sort();
27475
27565
  const [selectedDate, setSelectedDate] = React.useState(dates[0] ?? "");
27476
27566
  const [selectedSlot, setSelectedSlot] = React.useState(null);
27477
27567
  const [topic, setTopic] = React.useState("");
27478
27568
  const [error, setError] = React.useState(null);
27479
- const [isSubmitting, setIsSubmitting] = React.useState(false);
27480
27569
  const slotsForSelectedDate = selectedDate ? slotsByDate.get(selectedDate) ?? [] : [];
27481
27570
  const accentStyle = accentColor ? { '--action-accent': accentColor } : {};
27482
27571
  const onConfirm = () => {
@@ -27489,8 +27578,245 @@ function GoogleCalendarCard({ action, onComplete, accentColor, className = '' })
27489
27578
  return;
27490
27579
  }
27491
27580
  setError(null);
27581
+ onComplete?.(action.toolCallId, {
27582
+ ...action.state,
27583
+ selectedSlot: {
27584
+ startTime: selectedSlot.startTime,
27585
+ endTime: selectedSlot.endTime,
27586
+ },
27587
+ topic: allowTopic ? topic.trim() : null,
27588
+ });
27589
+ };
27590
+ // Booked state
27591
+ if (isBooked) {
27592
+ const bookedSlot = state.selectedSlot;
27593
+ const bookedTopic = state.topic;
27594
+ const eventLink = state.bookedEventLink;
27595
+ return (jsxRuntime.jsxs("div", { className: `ai-chat-action-card ai-chat-action-booked ${className}`, style: accentStyle, children: [jsxRuntime.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntime.jsx("div", { className: "ai-chat-action-success-icon-wrapper", children: jsxRuntime.jsx(CheckIcon$1, {}) }), "Appointment Confirmed"] }), jsxRuntime.jsxs("div", { className: "ai-chat-action-body", children: [bookedTopic && (jsxRuntime.jsxs("div", { className: "ai-chat-action-detail-box", children: [jsxRuntime.jsx("span", { className: "ai-chat-action-label-small", children: "TOPIC" }), jsxRuntime.jsx("span", { className: "ai-chat-action-value-large", children: bookedTopic })] })), bookedSlot && bookedSlot.startTime && (jsxRuntime.jsxs("div", { className: "ai-chat-action-detail-box", children: [jsxRuntime.jsx("span", { className: "ai-chat-action-label-small", children: "TIME" }), jsxRuntime.jsx("span", { className: "ai-chat-action-value-large", children: bookedSlot.displayTime || new Date(bookedSlot.startTime).toLocaleString() })] })), eventLink && (jsxRuntime.jsxs("a", { href: eventLink, target: "_blank", rel: "noopener noreferrer", className: "ai-chat-action-link-button", children: ["View in Google Calendar", jsxRuntime.jsx(ExternalLinkIcon$2, {})] }))] })] }));
27596
+ }
27597
+ // Skeleton loading state - show when waiting for backend after user confirms
27598
+ const isWaitingForBackend = !action.done && state.selectedSlot && !isBooked;
27599
+ if (isWaitingForBackend) {
27600
+ return (jsxRuntime.jsx("div", { className: `ai-chat-action-card ai-chat-action-skeleton ${className}`, style: accentStyle, children: jsxRuntime.jsxs("div", { className: "ai-chat-action-skeleton-content", children: [jsxRuntime.jsxs("div", { className: "ai-chat-action-skeleton-header", children: [jsxRuntime.jsx(Skeleton$1, { width: "28px", height: "28px", borderRadius: "50%" }), jsxRuntime.jsx(Skeleton$1, { width: "180px", height: "20px", borderRadius: "4px" })] }), jsxRuntime.jsxs("div", { className: "ai-chat-action-skeleton-box", children: [jsxRuntime.jsx(Skeleton$1, { width: "60px", height: "12px", borderRadius: "4px" }), jsxRuntime.jsx(Skeleton$1, { width: "120px", height: "18px", borderRadius: "4px" })] }), jsxRuntime.jsxs("div", { className: "ai-chat-action-skeleton-box", children: [jsxRuntime.jsx(Skeleton$1, { width: "50px", height: "12px", borderRadius: "4px" }), jsxRuntime.jsx(Skeleton$1, { width: "200px", height: "18px", borderRadius: "4px" })] }), jsxRuntime.jsx(Skeleton$1, { width: "100%", height: "44px", borderRadius: "999px" })] }) }));
27601
+ }
27602
+ // Booking form
27603
+ return (jsxRuntime.jsxs("div", { className: `ai-chat-action-card ai-chat-google-calendar ${className}`, style: accentStyle, children: [jsxRuntime.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntime.jsx(CalendarIcon$1, {}), "Schedule an Appointment"] }), jsxRuntime.jsxs("div", { className: "ai-chat-action-body", children: [allowTopic && (jsxRuntime.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntime.jsx("label", { htmlFor: `topic-${action.toolCallId}`, className: "ai-chat-action-label", children: "Meeting Topic" }), jsxRuntime.jsx("input", { id: `topic-${action.toolCallId}`, type: "text", className: "ai-chat-action-input", placeholder: "e.g., Product Demo", value: topic, onChange: (e) => setTopic(e.target.value) })] })), jsxRuntime.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntime.jsx("label", { className: "ai-chat-action-label", children: "Select Date" }), jsxRuntime.jsx("div", { className: "ai-chat-action-date-grid", children: dates.slice(0, 7).map((date) => (jsxRuntime.jsx("button", { type: "button", className: `ai-chat-action-date-btn ${selectedDate === date ? "active" : ""}`, onClick: () => {
27604
+ setSelectedDate(date);
27605
+ setSelectedSlot(null);
27606
+ }, children: formatDate$1(date) }, date))) })] }), selectedDate && slotsForSelectedDate.length > 0 && (jsxRuntime.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntime.jsx("label", { className: "ai-chat-action-label", children: "Select Time" }), jsxRuntime.jsx("div", { className: "ai-chat-action-time-grid", children: slotsForSelectedDate.map((slot) => (jsxRuntime.jsx("button", { type: "button", className: `ai-chat-action-time-btn ${selectedSlot?.startTime === slot.startTime ? "active" : ""}`, onClick: () => setSelectedSlot(slot), children: slot.displayTime || new Date(slot.startTime).toLocaleTimeString([], { hour: "numeric", minute: "2-digit" }) }, slot.startTime))) })] })), error && jsxRuntime.jsx("div", { className: "ai-chat-action-error", children: error }), jsxRuntime.jsx("button", { className: "ai-chat-action-button", type: "button", onClick: onConfirm, disabled: !selectedSlot, children: "Confirm Appointment" }), availableSlots.length === 0 && (jsxRuntime.jsx("div", { className: "ai-chat-action-hint", children: "No available time slots found." }))] })] }));
27607
+ }
27608
+
27609
+ function groupSlotsByDate(slots) {
27610
+ const grouped = new Map();
27611
+ for (const slot of slots) {
27612
+ if (!slot || typeof slot !== 'object' || !slot.startTime || typeof slot.startTime !== 'string') {
27613
+ continue;
27614
+ }
27615
+ const date = slot.startTime.slice(0, 10);
27616
+ if (!grouped.has(date)) {
27617
+ grouped.set(date, []);
27618
+ }
27619
+ grouped.get(date).push(slot);
27620
+ }
27621
+ return grouped;
27622
+ }
27623
+ function formatDate(dateStr) {
27624
+ try {
27625
+ const date = new Date(dateStr);
27626
+ return new Intl.DateTimeFormat("en-US", {
27627
+ weekday: "short",
27628
+ month: "short",
27629
+ day: "numeric",
27630
+ }).format(date);
27631
+ }
27632
+ catch {
27633
+ return dateStr;
27634
+ }
27635
+ }
27636
+ function CalendarIcon() {
27637
+ return (jsxRuntime.jsx("svg", { className: "ai-chat-action-icon", viewBox: "0 0 20 20", fill: "currentColor", children: jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z", clipRule: "evenodd" }) }));
27638
+ }
27639
+ function MailIcon() {
27640
+ return (jsxRuntime.jsxs("svg", { className: "ai-chat-action-icon", viewBox: "0 0 20 20", fill: "currentColor", children: [jsxRuntime.jsx("path", { d: "M2.003 5.884L10 9.882l7.997-3.998A2 2 0 0016 4H4a2 2 0 00-1.997 1.884z" }), jsxRuntime.jsx("path", { d: "M18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z" })] }));
27641
+ }
27642
+ function CheckIcon() {
27643
+ return (jsxRuntime.jsx("svg", { className: "ai-chat-action-icon-success", viewBox: "0 0 20 20", fill: "currentColor", children: jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z", clipRule: "evenodd" }) }));
27644
+ }
27645
+ function ErrorIcon() {
27646
+ return (jsxRuntime.jsx("svg", { className: "ai-chat-action-icon-error", viewBox: "0 0 20 20", fill: "currentColor", children: jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z", clipRule: "evenodd" }) }));
27647
+ }
27648
+ function ExternalLinkIcon$1() {
27649
+ return (jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntime.jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }), jsxRuntime.jsx("polyline", { points: "15 3 21 3 21 9" }), jsxRuntime.jsx("line", { x1: "10", y1: "14", x2: "21", y2: "3" })] }));
27650
+ }
27651
+ function Skeleton({ width, height, borderRadius = '4px' }) {
27652
+ return (jsxRuntime.jsx("div", { className: "ai-chat-action-skeleton-item", style: { width, height, borderRadius } }));
27653
+ }
27654
+ function PinInputGroup({ values, onChange, disabled }) {
27655
+ const inputRefs = React.useRef([]);
27656
+ const handleChange = (index, value) => {
27657
+ // Only allow digits
27658
+ const digit = value.replace(/[^0-9]/g, '');
27659
+ const newValues = [...values];
27660
+ newValues[index] = digit.slice(-1);
27661
+ onChange(newValues);
27662
+ // Auto-focus next input
27663
+ if (digit && index < 5) {
27664
+ inputRefs.current[index + 1]?.focus();
27665
+ }
27666
+ };
27667
+ const handleKeyDown = (index, e) => {
27668
+ if (e.key === 'Backspace' && !values[index] && index > 0) {
27669
+ inputRefs.current[index - 1]?.focus();
27670
+ }
27671
+ };
27672
+ const handlePaste = (e) => {
27673
+ e.preventDefault();
27674
+ const pastedData = e.clipboardData.getData('text').replace(/[^0-9]/g, '').slice(0, 6);
27675
+ const newValues = pastedData.split('').concat(Array(6 - pastedData.length).fill(''));
27676
+ onChange(newValues);
27677
+ // Focus the next empty input or the last one
27678
+ const nextIndex = Math.min(pastedData.length, 5);
27679
+ inputRefs.current[nextIndex]?.focus();
27680
+ };
27681
+ return (jsxRuntime.jsx("div", { className: "ai-chat-pin-input-group", children: values.map((value, index) => (jsxRuntime.jsx("input", { ref: (el) => {
27682
+ inputRefs.current[index] = el;
27683
+ }, type: "text", inputMode: "numeric", maxLength: 1, className: "ai-chat-pin-input", value: value, onChange: (e) => handleChange(index, e.target.value), onKeyDown: (e) => handleKeyDown(index, e), onPaste: handlePaste, disabled: disabled, autoFocus: index === 0 }, index))) }));
27684
+ }
27685
+ function MicrosoftCalendarCard({ action, onComplete, accentColor, className = '' }) {
27686
+ const state = action.state;
27687
+ const phase = state.phase || "awaiting_email";
27688
+ const allowTopic = state.allowTopic !== false;
27689
+ const accentStyle = accentColor ? { '--action-accent': accentColor } : {};
27690
+ // Debug: Log state changes
27691
+ const prevStateRef = React.useRef(null);
27692
+ React.useEffect(() => {
27693
+ if (JSON.stringify(prevStateRef.current) !== JSON.stringify(state)) {
27694
+ console.log('[MicrosoftCalendarCard] State updated:', {
27695
+ phase: state.phase,
27696
+ hasError: !!state.errorMessage,
27697
+ error: state.errorMessage,
27698
+ slotsCount: state.availableSlots?.length || 0
27699
+ });
27700
+ prevStateRef.current = state;
27701
+ }
27702
+ }, [state]);
27703
+ // Email phase state
27704
+ const [email, setEmail] = React.useState("");
27705
+ const [emailError, setEmailError] = React.useState(null);
27706
+ // OTP phase state
27707
+ const [otpValues, setOtpValues] = React.useState(Array(6).fill(''));
27708
+ const [otpError, setOtpError] = React.useState(null);
27709
+ // Loading states
27710
+ const [isSubmitting, setIsSubmitting] = React.useState(false);
27711
+ // Reset loading state when phase changes (backend has responded)
27712
+ // Use useEffect for reliable re-rendering
27713
+ React.useEffect(() => {
27714
+ console.log('[MicrosoftCalendarCard] Phase changed to:', phase);
27715
+ setIsSubmitting(false);
27716
+ // Clear errors when transitioning to new phase
27717
+ if (phase === "awaiting_email") {
27718
+ setEmailError(null);
27719
+ setOtpError(null);
27720
+ setSelectionError(null);
27721
+ }
27722
+ else if (phase === "awaiting_otp") {
27723
+ setOtpError(state.errorMessage || null);
27724
+ setEmailError(null);
27725
+ setSelectionError(null);
27726
+ // Clear OTP input for fresh attempt
27727
+ setOtpValues(Array(6).fill(''));
27728
+ }
27729
+ else if (phase === "awaiting_options") {
27730
+ setEmailError(null);
27731
+ setOtpError(null);
27732
+ setSelectionError(null);
27733
+ }
27734
+ else if (phase === "awaiting_booking") {
27735
+ setSelectionError(state.errorMessage || null);
27736
+ setEmailError(null);
27737
+ setOtpError(null);
27738
+ }
27739
+ else if (phase === "booked" || phase === "cancelled" || phase === "error") {
27740
+ setEmailError(null);
27741
+ setOtpError(null);
27742
+ setSelectionError(null);
27743
+ setSelectedId(null); // Reset selection
27744
+ }
27745
+ }, [phase, state.errorMessage]);
27746
+ // Selection phase state
27747
+ const rawSlots = state.availableSlots;
27748
+ const availableSlots = Array.isArray(rawSlots)
27749
+ ? rawSlots.filter((slot) => slot !== null &&
27750
+ slot !== undefined &&
27751
+ typeof slot === "object" &&
27752
+ "startTime" in slot &&
27753
+ "endTime" in slot &&
27754
+ typeof slot.startTime === "string" &&
27755
+ typeof slot.endTime === "string")
27756
+ : [];
27757
+ const slotsByDate = groupSlotsByDate(availableSlots);
27758
+ const dates = Array.from(slotsByDate.keys()).sort();
27759
+ const [selectedDate, setSelectedDate] = React.useState(dates[0] ?? "");
27760
+ const [selectedSlot, setSelectedSlot] = React.useState(null);
27761
+ const [topic, setTopic] = React.useState("");
27762
+ const [selectionError, setSelectionError] = React.useState(null);
27763
+ // Cancellation phase state
27764
+ const [selectedId, setSelectedId] = React.useState(null);
27765
+ const slotsForSelectedDate = selectedDate ? slotsByDate.get(selectedDate) ?? [] : [];
27766
+ // Phase 1: Email Input
27767
+ const handleEmailSubmit = () => {
27768
+ const trimmedEmail = email.trim();
27769
+ if (!trimmedEmail) {
27770
+ setEmailError("Please enter your email address");
27771
+ return;
27772
+ }
27773
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(trimmedEmail)) {
27774
+ setEmailError("Please enter a valid email address");
27775
+ return;
27776
+ }
27777
+ setEmailError(null);
27778
+ setIsSubmitting(true);
27779
+ console.log('[MicrosoftCalendarCard] Submitting email:', trimmedEmail);
27780
+ setTimeout(() => {
27781
+ onComplete?.(action.toolCallId, {
27782
+ ...action.state,
27783
+ email: trimmedEmail,
27784
+ });
27785
+ }, 50);
27786
+ };
27787
+ // Phase 2: OTP Verification
27788
+ const handleOtpSubmit = () => {
27789
+ const otpCode = otpValues.join('');
27790
+ if (otpCode.length !== 6) {
27791
+ setOtpError("Please enter the 6-digit code");
27792
+ return;
27793
+ }
27794
+ setOtpError(null);
27795
+ setIsSubmitting(true);
27796
+ console.log('[MicrosoftCalendarCard] Submitting OTP code');
27797
+ setTimeout(() => {
27798
+ onComplete?.(action.toolCallId, {
27799
+ ...action.state,
27800
+ otpCode,
27801
+ });
27802
+ }, 50);
27803
+ };
27804
+ // Phase 3: Appointment Selection
27805
+ const handleAppointmentConfirm = () => {
27806
+ if (!selectedSlot) {
27807
+ setSelectionError("Please select a time slot");
27808
+ return;
27809
+ }
27810
+ if (allowTopic && !topic.trim()) {
27811
+ setSelectionError("Please enter a meeting topic");
27812
+ return;
27813
+ }
27814
+ setSelectionError(null);
27492
27815
  setIsSubmitting(true);
27493
- // Small delay to ensure UI updates
27816
+ console.log('[MicrosoftCalendarCard] Confirming appointment:', {
27817
+ slot: selectedSlot,
27818
+ topic: topic.trim()
27819
+ });
27494
27820
  setTimeout(() => {
27495
27821
  onComplete?.(action.toolCallId, {
27496
27822
  ...action.state,
@@ -27502,22 +27828,566 @@ function GoogleCalendarCard({ action, onComplete, accentColor, className = '' })
27502
27828
  });
27503
27829
  }, 50);
27504
27830
  };
27505
- // Booked state
27506
- if (isBooked) {
27831
+ // Handle "Use different email" button
27832
+ const handleUseDifferentEmail = () => {
27833
+ setEmail("");
27834
+ setEmailError(null);
27835
+ setOtpValues(Array(6).fill(''));
27836
+ setOtpError(null);
27837
+ onComplete?.(action.toolCallId, {
27838
+ phase: "awaiting_email",
27839
+ email: null,
27840
+ otpVerified: false,
27841
+ otpAttempts: 0,
27842
+ availableSlots: [],
27843
+ selectedSlot: null,
27844
+ topic: null,
27845
+ bookedEventId: null,
27846
+ bookedEventLink: null,
27847
+ allowTopic,
27848
+ errorMessage: null,
27849
+ });
27850
+ };
27851
+ // Phase 5: Booked Confirmation
27852
+ if (phase === "booked") {
27507
27853
  const bookedSlot = state.selectedSlot;
27508
27854
  const bookedTopic = state.topic;
27509
27855
  const eventLink = state.bookedEventLink;
27510
- return (jsxRuntime.jsxs("div", { className: `ai-chat-action-card ai-chat-action-booked ${className}`, style: accentStyle, children: [jsxRuntime.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntime.jsx("div", { className: "ai-chat-action-success-icon-wrapper", children: jsxRuntime.jsx(CheckIcon, {}) }), "Appointment Confirmed"] }), jsxRuntime.jsxs("div", { className: "ai-chat-action-body", children: [bookedTopic && (jsxRuntime.jsxs("div", { className: "ai-chat-action-detail-box", children: [jsxRuntime.jsx("span", { className: "ai-chat-action-label-small", children: "TOPIC" }), jsxRuntime.jsx("span", { className: "ai-chat-action-value-large", children: bookedTopic })] })), bookedSlot && bookedSlot.startTime && (jsxRuntime.jsxs("div", { className: "ai-chat-action-detail-box", children: [jsxRuntime.jsx("span", { className: "ai-chat-action-label-small", children: "TIME" }), jsxRuntime.jsx("span", { className: "ai-chat-action-value-large", children: bookedSlot.displayTime || new Date(bookedSlot.startTime).toLocaleString() })] })), eventLink && (jsxRuntime.jsxs("a", { href: eventLink, target: "_blank", rel: "noopener noreferrer", className: "ai-chat-action-link-button", children: ["View in Google Calendar", jsxRuntime.jsx(ExternalLinkIcon, {})] }))] })] }));
27511
- }
27512
- // Skeleton loading state
27856
+ const bookedEmail = state.email;
27857
+ return (jsxRuntime.jsxs("div", { className: `ai-chat-action-card ai-chat-action-booked ${className}`, style: accentStyle, children: [jsxRuntime.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntime.jsx("div", { className: "ai-chat-action-success-icon-wrapper", children: jsxRuntime.jsx(CheckIcon, {}) }), "Appointment Confirmed"] }), jsxRuntime.jsxs("div", { className: "ai-chat-action-body", children: [bookedTopic && (jsxRuntime.jsxs("div", { className: "ai-chat-action-detail-box", children: [jsxRuntime.jsx("span", { className: "ai-chat-action-label-small", children: "TOPIC" }), jsxRuntime.jsx("span", { className: "ai-chat-action-value-large", children: bookedTopic })] })), bookedSlot && bookedSlot.startTime && (jsxRuntime.jsxs("div", { className: "ai-chat-action-detail-box", children: [jsxRuntime.jsx("span", { className: "ai-chat-action-label-small", children: "TIME" }), jsxRuntime.jsx("span", { className: "ai-chat-action-value-large", children: bookedSlot.displayTime || new Date(bookedSlot.startTime).toLocaleString() })] })), bookedEmail && (jsxRuntime.jsxs("div", { className: "ai-chat-action-hint", children: ["A calendar invitation has been sent to ", bookedEmail] })), eventLink && (jsxRuntime.jsxs("a", { href: eventLink, target: "_blank", rel: "noopener noreferrer", className: "ai-chat-action-link-button", children: ["View in Outlook Calendar", jsxRuntime.jsx(ExternalLinkIcon$1, {})] }))] })] }));
27858
+ }
27859
+ // Phase 6: Cancelled Confirmation
27860
+ if (phase === "cancelled") {
27861
+ const cancelledSubject = state.cancelledEventSubject;
27862
+ const userEmail = state.email;
27863
+ return (jsxRuntime.jsxs("div", { className: `ai-chat-action-card ai-chat-action-booked ${className}`, style: accentStyle, children: [jsxRuntime.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntime.jsx("div", { className: "ai-chat-action-success-icon-wrapper", children: jsxRuntime.jsx(CheckIcon, {}) }), "Appointment Cancelled"] }), jsxRuntime.jsxs("div", { className: "ai-chat-action-body", children: [cancelledSubject && (jsxRuntime.jsxs("div", { className: "ai-chat-action-detail-box", children: [jsxRuntime.jsx("span", { className: "ai-chat-action-label-small", children: "CANCELLED" }), jsxRuntime.jsx("span", { className: "ai-chat-action-value-large", children: cancelledSubject })] })), userEmail && (jsxRuntime.jsxs("div", { className: "ai-chat-action-hint", children: ["A cancellation notice has been sent to ", userEmail] }))] })] }));
27864
+ }
27865
+ // Error State
27866
+ if (phase === "error") {
27867
+ return (jsxRuntime.jsxs("div", { className: `ai-chat-action-card ai-chat-action-error ${className}`, style: accentStyle, children: [jsxRuntime.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntime.jsx(ErrorIcon, {}), "Error"] }), jsxRuntime.jsxs("div", { className: "ai-chat-action-body", children: [jsxRuntime.jsx("div", { className: "ai-chat-action-error-message", children: state.errorMessage || "An error occurred. Please try again." }), jsxRuntime.jsx("button", { className: "ai-chat-action-button-secondary", type: "button", onClick: () => {
27868
+ setEmail("");
27869
+ setEmailError(null);
27870
+ setOtpValues(Array(6).fill(''));
27871
+ setOtpError(null);
27872
+ onComplete?.(action.toolCallId, {
27873
+ phase: "awaiting_email",
27874
+ email: null,
27875
+ otpVerified: false,
27876
+ otpAttempts: 0,
27877
+ availableSlots: [],
27878
+ selectedSlot: null,
27879
+ topic: null,
27880
+ bookedEventId: null,
27881
+ bookedEventLink: null,
27882
+ allowTopic,
27883
+ errorMessage: null,
27884
+ });
27885
+ }, children: "Start Over" })] })] }));
27886
+ }
27887
+ // Loading State
27513
27888
  if (isSubmitting) {
27514
- return (jsxRuntime.jsx("div", { className: `ai-chat-action-card ai-chat-action-skeleton ${className}`, style: accentStyle, children: jsxRuntime.jsxs("div", { className: "ai-chat-action-skeleton-content", children: [jsxRuntime.jsxs("div", { className: "ai-chat-action-skeleton-header", children: [jsxRuntime.jsx(Skeleton, { width: "28px", height: "28px", borderRadius: "50%" }), jsxRuntime.jsx(Skeleton, { width: "180px", height: "20px", borderRadius: "4px" })] }), jsxRuntime.jsxs("div", { className: "ai-chat-action-skeleton-box", children: [jsxRuntime.jsx(Skeleton, { width: "60px", height: "12px", borderRadius: "4px" }), jsxRuntime.jsx(Skeleton, { width: "120px", height: "18px", borderRadius: "4px" })] }), jsxRuntime.jsxs("div", { className: "ai-chat-action-skeleton-box", children: [jsxRuntime.jsx(Skeleton, { width: "50px", height: "12px", borderRadius: "4px" }), jsxRuntime.jsx(Skeleton, { width: "200px", height: "18px", borderRadius: "4px" })] }), jsxRuntime.jsx(Skeleton, { width: "100%", height: "44px", borderRadius: "999px" })] }) }));
27889
+ return (jsxRuntime.jsx("div", { className: `ai-chat-action-card ai-chat-action-skeleton ${className}`, style: accentStyle, children: jsxRuntime.jsxs("div", { className: "ai-chat-action-skeleton-content", children: [jsxRuntime.jsxs("div", { className: "ai-chat-action-skeleton-header", children: [jsxRuntime.jsx(Skeleton, { width: "28px", height: "28px", borderRadius: "50%" }), jsxRuntime.jsx(Skeleton, { width: "180px", height: "20px", borderRadius: "4px" })] }), jsxRuntime.jsxs("div", { className: "ai-chat-action-skeleton-box", children: [jsxRuntime.jsx(Skeleton, { width: "60px", height: "12px", borderRadius: "4px" }), jsxRuntime.jsx(Skeleton, { width: "120px", height: "18px", borderRadius: "4px" })] }), jsxRuntime.jsx(Skeleton, { width: "100%", height: "44px", borderRadius: "999px" })] }) }));
27890
+ }
27891
+ // Phase 1: Email Input
27892
+ if (phase === "awaiting_email") {
27893
+ const displayError = state.errorMessage || emailError;
27894
+ return (jsxRuntime.jsxs("div", { className: `ai-chat-action-card ${className}`, style: accentStyle, children: [jsxRuntime.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntime.jsx(CalendarIcon, {}), "Schedule an Appointment"] }), jsxRuntime.jsxs("div", { className: "ai-chat-action-body", children: [jsxRuntime.jsx("div", { className: "ai-chat-action-hint", children: "We'll send a verification code to your email" }), jsxRuntime.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntime.jsx("label", { htmlFor: `email-${action.toolCallId}`, className: "ai-chat-action-label", children: "Email Address" }), jsxRuntime.jsx("input", { id: `email-${action.toolCallId}`, type: "email", className: "ai-chat-action-input", placeholder: "your@email.com", value: email, onChange: (e) => {
27895
+ setEmail(e.target.value);
27896
+ setEmailError(null);
27897
+ }, onKeyPress: (e) => {
27898
+ if (e.key === 'Enter') {
27899
+ handleEmailSubmit();
27900
+ }
27901
+ }, autoFocus: true })] }), displayError && (jsxRuntime.jsx("div", { className: "ai-chat-action-error", children: displayError })), jsxRuntime.jsx("button", { className: "ai-chat-action-button", type: "button", onClick: handleEmailSubmit, children: "Continue" })] })] }));
27902
+ }
27903
+ // Phase 2: OTP Input
27904
+ if (phase === "awaiting_otp") {
27905
+ const displayError = state.errorMessage || otpError;
27906
+ const userEmail = state.email;
27907
+ return (jsxRuntime.jsxs("div", { className: `ai-chat-action-card ${className}`, style: accentStyle, children: [jsxRuntime.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntime.jsx(MailIcon, {}), "Verify Your Email"] }), jsxRuntime.jsxs("div", { className: "ai-chat-action-body", children: [jsxRuntime.jsxs("div", { className: "ai-chat-action-hint", children: ["We sent a 6-digit code to ", jsxRuntime.jsx("strong", { children: userEmail })] }), jsxRuntime.jsx(PinInputGroup, { values: otpValues, onChange: (newValues) => {
27908
+ setOtpValues(newValues);
27909
+ setOtpError(null);
27910
+ // Auto-submit when all 6 digits are entered
27911
+ if (newValues.every(v => v.length === 1)) {
27912
+ console.log('[MicrosoftCalendarCard] Auto-submitting OTP (all 6 digits entered)');
27913
+ setIsSubmitting(true);
27914
+ const code = newValues.join('');
27915
+ setTimeout(() => {
27916
+ onComplete?.(action.toolCallId, {
27917
+ ...action.state,
27918
+ otpCode: code,
27919
+ });
27920
+ }, 100);
27921
+ }
27922
+ }, disabled: isSubmitting }), displayError && (jsxRuntime.jsx("div", { className: "ai-chat-action-error", children: displayError })), jsxRuntime.jsx("button", { className: "ai-chat-action-button", type: "button", onClick: handleOtpSubmit, disabled: otpValues.join('').length !== 6, children: "Verify Code" }), jsxRuntime.jsx("button", { className: "ai-chat-action-button-secondary", type: "button", onClick: handleUseDifferentEmail, children: "Use different email" })] })] }));
27923
+ }
27924
+ // Phase 3: Options Menu (with inline cancel buttons and confirmation)
27925
+ if (phase === "awaiting_options") {
27926
+ const userAppointments = state.userAppointments || [];
27927
+ const maxAppointments = state.maxAppointmentsPerUser || 3;
27928
+ const appointmentCount = userAppointments.length;
27929
+ const canBook = appointmentCount < maxAppointments;
27930
+ const hasAppointments = appointmentCount > 0;
27931
+ const displayError = state.errorMessage || selectionError;
27932
+ // If confirming cancellation, show confirmation dialog
27933
+ if (selectedId) {
27934
+ const appointmentToCancel = userAppointments.find(appt => appt.id === selectedId);
27935
+ if (!appointmentToCancel) {
27936
+ setSelectedId(null); // Reset if appointment not found
27937
+ }
27938
+ else {
27939
+ return (jsxRuntime.jsxs("div", { className: `ai-chat-action-card ${className}`, style: accentStyle, children: [jsxRuntime.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntime.jsx(CalendarIcon, {}), "Confirm Cancellation"] }), jsxRuntime.jsxs("div", { className: "ai-chat-action-body", children: [jsxRuntime.jsx("div", { className: "ai-chat-action-hint", children: "Are you sure you want to cancel this appointment?" }), jsxRuntime.jsx("div", { className: "ai-chat-action-appointment-item", style: { marginBottom: '16px' }, children: jsxRuntime.jsxs("div", { className: "ai-chat-action-appointment-info", children: [jsxRuntime.jsx("div", { className: "ai-chat-action-appointment-subject", children: appointmentToCancel.subject }), jsxRuntime.jsx("div", { className: "ai-chat-action-appointment-time", children: appointmentToCancel.displayTime })] }) }), displayError && (jsxRuntime.jsx("div", { className: "ai-chat-action-error", children: displayError })), jsxRuntime.jsxs("div", { className: "ai-chat-action-button-group", children: [jsxRuntime.jsx("button", { className: "ai-chat-action-button", type: "button", onClick: () => {
27940
+ setIsSubmitting(true);
27941
+ onComplete?.(action.toolCallId, {
27942
+ ...action.state,
27943
+ selectedOption: "cancel",
27944
+ selectedAppointmentId: selectedId,
27945
+ });
27946
+ }, disabled: isSubmitting, children: isSubmitting ? 'Cancelling...' : 'Confirm Cancellation' }), jsxRuntime.jsx("button", { className: "ai-chat-action-button-secondary", type: "button", onClick: () => {
27947
+ setSelectedId(null);
27948
+ setSelectionError(null);
27949
+ }, disabled: isSubmitting, children: "Go Back" })] })] })] }));
27950
+ }
27951
+ }
27952
+ // Normal view with inline cancel buttons
27953
+ return (jsxRuntime.jsxs("div", { className: `ai-chat-action-card ${className}`, style: accentStyle, children: [jsxRuntime.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntime.jsx(CalendarIcon, {}), "Manage Your Appointments"] }), jsxRuntime.jsxs("div", { className: "ai-chat-action-body", children: [jsxRuntime.jsxs("div", { className: "ai-chat-action-hint", children: ["You have ", appointmentCount, " active appointment", appointmentCount !== 1 ? 's' : '', canBook && ` (${maxAppointments - appointmentCount} slot${maxAppointments - appointmentCount !== 1 ? 's' : ''} remaining)`] }), hasAppointments && (jsxRuntime.jsxs("div", { className: "ai-chat-action-appointment-list", children: [jsxRuntime.jsx("div", { className: "ai-chat-action-label", children: "Your Upcoming Appointments" }), userAppointments.map((appt) => (jsxRuntime.jsxs("div", { className: "ai-chat-action-appointment-item", children: [jsxRuntime.jsxs("div", { className: "ai-chat-action-appointment-info", children: [jsxRuntime.jsx("div", { className: "ai-chat-action-appointment-subject", children: appt.subject }), jsxRuntime.jsx("div", { className: "ai-chat-action-appointment-time", children: appt.displayTime })] }), jsxRuntime.jsx("button", { className: "ai-chat-action-button-secondary", type: "button", onClick: () => {
27954
+ setSelectedId(appt.id);
27955
+ setSelectionError(null);
27956
+ }, children: "Cancel" })] }, appt.id)))] })), displayError && (jsxRuntime.jsx("div", { className: "ai-chat-action-error", children: displayError })), canBook && (jsxRuntime.jsx("button", { className: "ai-chat-action-button", type: "button", onClick: () => {
27957
+ setIsSubmitting(true);
27958
+ onComplete?.(action.toolCallId, {
27959
+ ...action.state,
27960
+ selectedOption: "book",
27961
+ });
27962
+ }, disabled: isSubmitting, children: isSubmitting ? 'Loading...' : 'Book New Appointment' })), !canBook && !hasAppointments && (jsxRuntime.jsx("div", { className: "ai-chat-action-hint", children: "No appointments found." }))] })] }));
27963
+ }
27964
+ // Phase 4: Appointment Selection (Booking)
27965
+ if (phase === "awaiting_booking") {
27966
+ const displayError = state.errorMessage || selectionError;
27967
+ return (jsxRuntime.jsxs("div", { className: `ai-chat-action-card ${className}`, style: accentStyle, children: [jsxRuntime.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntime.jsx(CalendarIcon, {}), "Select Appointment Time"] }), jsxRuntime.jsxs("div", { className: "ai-chat-action-body", children: [allowTopic && (jsxRuntime.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntime.jsx("label", { htmlFor: `topic-${action.toolCallId}`, className: "ai-chat-action-label", children: "Meeting Topic" }), jsxRuntime.jsx("input", { id: `topic-${action.toolCallId}`, type: "text", className: "ai-chat-action-input", placeholder: "e.g., Product Demo", value: topic, onChange: (e) => setTopic(e.target.value) })] })), jsxRuntime.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntime.jsx("label", { className: "ai-chat-action-label", children: "Select Date" }), jsxRuntime.jsx("div", { className: "ai-chat-action-date-grid", children: dates.slice(0, 7).map((date) => (jsxRuntime.jsx("button", { type: "button", className: `ai-chat-action-date-btn ${selectedDate === date ? "active" : ""}`, onClick: () => {
27968
+ setSelectedDate(date);
27969
+ setSelectedSlot(null);
27970
+ }, children: formatDate(date) }, date))) })] }), selectedDate && slotsForSelectedDate.length > 0 && (jsxRuntime.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntime.jsx("label", { className: "ai-chat-action-label", children: "Select Time" }), jsxRuntime.jsx("div", { className: "ai-chat-action-time-grid", children: slotsForSelectedDate.map((slot) => (jsxRuntime.jsx("button", { type: "button", className: `ai-chat-action-time-btn ${selectedSlot?.startTime === slot.startTime ? "active" : ""}`, onClick: () => setSelectedSlot(slot), children: slot.displayTime || new Date(slot.startTime).toLocaleTimeString([], { hour: "numeric", minute: "2-digit" }) }, slot.startTime))) })] })), displayError && (jsxRuntime.jsx("div", { className: "ai-chat-action-error", children: displayError })), jsxRuntime.jsx("button", { className: "ai-chat-action-button", type: "button", onClick: handleAppointmentConfirm, disabled: !selectedSlot, children: "Confirm Appointment" }), availableSlots.length === 0 && (jsxRuntime.jsx("div", { className: "ai-chat-action-hint", children: "No available time slots found." }))] })] }));
27971
+ }
27972
+ // Fallback
27973
+ return null;
27974
+ }
27975
+
27976
+ function truncate(text, maxLength) {
27977
+ if (text.length <= maxLength)
27978
+ return text;
27979
+ return text.slice(0, maxLength).trim() + '...';
27980
+ }
27981
+ function ExternalLinkIcon() {
27982
+ return (jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntime.jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }), jsxRuntime.jsx("polyline", { points: "15 3 21 3 21 9" }), jsxRuntime.jsx("line", { x1: "10", y1: "14", x2: "21", y2: "3" })] }));
27983
+ }
27984
+ function SingleLinkPreview({ link, onLinkClick, accentColor }) {
27985
+ const domain = (() => {
27986
+ if (!link.url)
27987
+ return '';
27988
+ try {
27989
+ return new URL(link.url).hostname.replace('www.', '');
27990
+ }
27991
+ catch {
27992
+ return link.url;
27993
+ }
27994
+ })();
27995
+ const style = accentColor ? { '--action-accent': accentColor } : undefined;
27996
+ return (jsxRuntime.jsxs("div", { className: "ai-chat-action-card ai-chat-link-preview", onClick: onLinkClick, style: style, role: "link", tabIndex: 0, onKeyDown: (e) => e.key === 'Enter' && onLinkClick(), children: [link.image && (jsxRuntime.jsx("div", { className: "ai-chat-link-preview__image", children: jsxRuntime.jsx("img", { src: link.image, alt: link.title, onError: (e) => {
27997
+ e.currentTarget.parentElement.style.display = 'none';
27998
+ } }) })), jsxRuntime.jsxs("div", { className: "ai-chat-link-preview__content", children: [jsxRuntime.jsxs("div", { className: "ai-chat-link-preview__site", children: [link.favicon && (jsxRuntime.jsx("img", { src: link.favicon, alt: "", className: "ai-chat-link-preview__favicon", onError: (e) => {
27999
+ e.currentTarget.style.display = 'none';
28000
+ } })), jsxRuntime.jsx("span", { className: "ai-chat-link-preview__domain", children: link.siteName || domain })] }), jsxRuntime.jsx("h4", { className: "ai-chat-link-preview__title", children: link.title }), link.description && (jsxRuntime.jsx("p", { className: "ai-chat-link-preview__description", children: truncate(link.description, 120) }))] }), jsxRuntime.jsx("div", { className: "ai-chat-link-preview__arrow", children: jsxRuntime.jsx(ExternalLinkIcon, {}) })] }));
28001
+ }
28002
+ function LinkPreviewCard({ action, onComplete, accentColor }) {
28003
+ const rawState = action.state;
28004
+ const hasCompletedRef = React.useRef(false);
28005
+ // Provide safe defaults if state is missing
28006
+ const state = {
28007
+ links: rawState?.links || [],
28008
+ context: rawState?.context,
28009
+ status: rawState?.status || 'displaying',
28010
+ error: rawState?.error,
28011
+ };
28012
+ const isError = state.status === 'error';
28013
+ // Auto-complete on mount so AI can continue generating text response
28014
+ React.useEffect(() => {
28015
+ if (!action.done && !hasCompletedRef.current && onComplete && state.links.length > 0) {
28016
+ hasCompletedRef.current = true;
28017
+ // Signal completion immediately - the card is displayed, AI can continue
28018
+ onComplete(action.toolCallId, { ...state, status: 'displaying' });
28019
+ }
28020
+ }, [action.done, action.toolCallId, onComplete, state]);
28021
+ const handleLinkClick = (url) => {
28022
+ if (url) {
28023
+ window.open(url, '_blank', 'noopener,noreferrer');
28024
+ }
28025
+ onComplete?.(action.toolCallId, { ...state, status: 'clicked' });
28026
+ };
28027
+ if (isError) {
28028
+ return (jsxRuntime.jsx("div", { className: "ai-chat-action-card ai-chat-link-preview ai-chat-link-preview--error", children: jsxRuntime.jsx("div", { className: "ai-chat-link-preview__content", children: jsxRuntime.jsx("p", { className: "ai-chat-link-preview__error-text", children: state.error || 'Failed to load preview' }) }) }));
27515
28029
  }
27516
- // Booking form
27517
- return (jsxRuntime.jsxs("div", { className: `ai-chat-action-card ${className}`, style: accentStyle, children: [jsxRuntime.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntime.jsx(CalendarIcon, {}), "Schedule an Appointment"] }), jsxRuntime.jsxs("div", { className: "ai-chat-action-body", children: [allowTopic && (jsxRuntime.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntime.jsx("label", { htmlFor: `topic-${action.toolCallId}`, className: "ai-chat-action-label", children: "Meeting Topic" }), jsxRuntime.jsx("input", { id: `topic-${action.toolCallId}`, type: "text", className: "ai-chat-action-input", placeholder: "e.g., Product Demo", value: topic, onChange: (e) => setTopic(e.target.value) })] })), jsxRuntime.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntime.jsx("label", { className: "ai-chat-action-label", children: "Select Date" }), jsxRuntime.jsx("div", { className: "ai-chat-action-date-grid", children: dates.slice(0, 7).map((date) => (jsxRuntime.jsx("button", { type: "button", className: `ai-chat-action-date-btn ${selectedDate === date ? "active" : ""}`, onClick: () => {
27518
- setSelectedDate(date);
27519
- setSelectedSlot(null);
27520
- }, children: formatDate(date) }, date))) })] }), selectedDate && slotsForSelectedDate.length > 0 && (jsxRuntime.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntime.jsx("label", { className: "ai-chat-action-label", children: "Select Time" }), jsxRuntime.jsx("div", { className: "ai-chat-action-time-grid", children: slotsForSelectedDate.map((slot) => (jsxRuntime.jsx("button", { type: "button", className: `ai-chat-action-time-btn ${selectedSlot?.startTime === slot.startTime ? "active" : ""}`, onClick: () => setSelectedSlot(slot), children: slot.displayTime || new Date(slot.startTime).toLocaleTimeString([], { hour: "numeric", minute: "2-digit" }) }, slot.startTime))) })] })), error && jsxRuntime.jsx("div", { className: "ai-chat-action-error", children: error }), jsxRuntime.jsx("button", { className: "ai-chat-action-button", type: "button", onClick: onConfirm, disabled: !selectedSlot, children: "Confirm Appointment" }), availableSlots.length === 0 && (jsxRuntime.jsx("div", { className: "ai-chat-action-hint", children: "No available time slots found." }))] })] }));
28030
+ if (state.links.length === 0) {
28031
+ return null;
28032
+ }
28033
+ return (jsxRuntime.jsxs("div", { className: "ai-chat-link-preview-container", children: [state.context && (jsxRuntime.jsx("p", { className: "ai-chat-link-preview__context", style: { marginBottom: '8px', fontSize: '0.9em', color: 'var(--ai-chat-fg-muted)' }, children: state.context })), jsxRuntime.jsx("div", { className: "ai-chat-link-preview-grid", style: {
28034
+ display: 'grid',
28035
+ gridTemplateColumns: state.links.length === 1 ? '1fr' : state.links.length === 2 ? 'repeat(2, 1fr)' : 'repeat(3, 1fr)',
28036
+ gap: '12px',
28037
+ }, children: state.links.map((link, index) => (jsxRuntime.jsx(SingleLinkPreview, { link: link, onLinkClick: () => handleLinkClick(link.url), accentColor: accentColor }, index))) })] }));
28038
+ }
28039
+
28040
+ function PlayIcon() {
28041
+ return (jsxRuntime.jsx("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "currentColor", stroke: "none", children: jsxRuntime.jsx("path", { d: "M8 5v14l11-7z" }) }));
28042
+ }
28043
+ function getProviderLabel(provider) {
28044
+ switch (provider) {
28045
+ case 'youtube':
28046
+ return 'YouTube';
28047
+ case 'vimeo':
28048
+ return 'Vimeo';
28049
+ case 'loom':
28050
+ return 'Loom';
28051
+ case 'direct':
28052
+ return 'Video';
28053
+ default:
28054
+ return 'Video';
28055
+ }
28056
+ }
28057
+ function VideoPlayerCard({ action, onComplete, accentColor }) {
28058
+ const rawState = action.state;
28059
+ const hasCompletedRef = React.useRef(false);
28060
+ const [isPlaying, setIsPlaying] = React.useState(false);
28061
+ // Provide safe defaults if state is missing
28062
+ const state = {
28063
+ url: rawState?.url || '',
28064
+ title: rawState?.title,
28065
+ context: rawState?.context,
28066
+ provider: rawState?.provider || 'direct',
28067
+ embedUrl: rawState?.embedUrl || '',
28068
+ thumbnailUrl: rawState?.thumbnailUrl,
28069
+ videoId: rawState?.videoId,
28070
+ status: rawState?.status || 'displaying',
28071
+ error: rawState?.error,
28072
+ };
28073
+ const isError = state.status === 'error';
28074
+ // Auto-complete on mount so AI can continue generating text response
28075
+ React.useEffect(() => {
28076
+ if (!action.done && !hasCompletedRef.current && onComplete && state.embedUrl) {
28077
+ hasCompletedRef.current = true;
28078
+ onComplete(action.toolCallId, { ...state, status: 'displaying' });
28079
+ }
28080
+ }, [action.done, action.toolCallId, onComplete, state]);
28081
+ const handlePlay = () => {
28082
+ setIsPlaying(true);
28083
+ onComplete?.(action.toolCallId, { ...state, status: 'played' });
28084
+ };
28085
+ const style = accentColor ? { '--action-accent': accentColor } : undefined;
28086
+ // Build embed URL with autoplay when playing
28087
+ const getEmbedSrc = () => {
28088
+ if (!isPlaying)
28089
+ return '';
28090
+ let src = state.embedUrl;
28091
+ const separator = src.includes('?') ? '&' : '?';
28092
+ switch (state.provider) {
28093
+ case 'youtube':
28094
+ return `${src}${separator}autoplay=1&rel=0`;
28095
+ case 'vimeo':
28096
+ return `${src}${separator}autoplay=1`;
28097
+ case 'loom':
28098
+ return `${src}${separator}autoplay=1`;
28099
+ default:
28100
+ return src;
28101
+ }
28102
+ };
28103
+ return (jsxRuntime.jsxs("div", { className: "ai-chat-action-card ai-chat-video-player", style: style, children: [jsxRuntime.jsx("div", { className: "ai-chat-video-player__container", children: isError ? (jsxRuntime.jsx("div", { className: "ai-chat-video-player__error", children: jsxRuntime.jsx("span", { children: state.error || 'Could not load video' }) })) : !isPlaying && state.thumbnailUrl ? (jsxRuntime.jsxs("div", { className: "ai-chat-video-player__thumbnail", onClick: handlePlay, children: [jsxRuntime.jsx("img", { src: state.thumbnailUrl, alt: state.title || 'Video thumbnail' }), jsxRuntime.jsx("button", { className: "ai-chat-video-player__play-btn", "aria-label": "Play video", children: jsxRuntime.jsx(PlayIcon, {}) }), jsxRuntime.jsx("div", { className: "ai-chat-video-player__provider-badge", children: getProviderLabel(state.provider) })] })) : !isPlaying ? (jsxRuntime.jsxs("div", { className: "ai-chat-video-player__placeholder", onClick: handlePlay, children: [jsxRuntime.jsx("button", { className: "ai-chat-video-player__play-btn", "aria-label": "Play video", children: jsxRuntime.jsx(PlayIcon, {}) }), jsxRuntime.jsx("span", { className: "ai-chat-video-player__click-text", children: "Click to play" }), jsxRuntime.jsx("div", { className: "ai-chat-video-player__provider-badge", children: getProviderLabel(state.provider) })] })) : state.provider === 'direct' ? (jsxRuntime.jsx("video", { src: state.embedUrl, controls: true, autoPlay: true, className: "ai-chat-video-player__video" })) : (jsxRuntime.jsx("iframe", { src: getEmbedSrc(), className: "ai-chat-video-player__iframe", allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share", allowFullScreen: true, title: state.title || 'Video player' })) }), state.context && (jsxRuntime.jsx("div", { className: "ai-chat-video-player__context", children: state.context }))] }));
28104
+ }
28105
+
28106
+ function MapPinIcon() {
28107
+ return (jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntime.jsx("path", { d: "M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z" }), jsxRuntime.jsx("circle", { cx: "12", cy: "10", r: "3" })] }));
28108
+ }
28109
+ function PhoneIcon() {
28110
+ return (jsxRuntime.jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntime.jsx("path", { d: "M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z" }) }));
28111
+ }
28112
+ function ClockIcon() {
28113
+ return (jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10" }), jsxRuntime.jsx("polyline", { points: "12 6 12 12 16 14" })] }));
28114
+ }
28115
+ function NavigationIcon() {
28116
+ return (jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntime.jsx("polygon", { points: "3 11 22 2 13 21 11 13 3 11" }) }));
28117
+ }
28118
+ function GlobeIcon() {
28119
+ return (jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10" }), jsxRuntime.jsx("line", { x1: "2", y1: "12", x2: "22", y2: "12" }), jsxRuntime.jsx("path", { d: "M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" })] }));
28120
+ }
28121
+ function ChevronIcon({ direction }) {
28122
+ return (jsxRuntime.jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", style: { transform: direction === 'up' ? 'rotate(180deg)' : 'none' }, children: jsxRuntime.jsx("polyline", { points: "6 9 12 15 18 9" }) }));
28123
+ }
28124
+ function getOpenStatus(hours) {
28125
+ if (!hours || hours.length === 0)
28126
+ return null;
28127
+ const now = new Date();
28128
+ const dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
28129
+ const today = dayNames[now.getDay()];
28130
+ const todayHours = hours.find(h => h.day === today);
28131
+ if (!todayHours || todayHours.closed)
28132
+ return false;
28133
+ const currentTime = now.getHours() * 100 + now.getMinutes();
28134
+ const openTime = parseInt(todayHours.open.replace(':', ''));
28135
+ const closeTime = parseInt(todayHours.close.replace(':', ''));
28136
+ return currentTime >= openTime && currentTime < closeTime;
28137
+ }
28138
+ function HoursDisplay({ hours, compact = false }) {
28139
+ const [expanded, setExpanded] = React.useState(false);
28140
+ const dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
28141
+ const today = dayNames[new Date().getDay()];
28142
+ const todayHours = hours.find(h => h.day === today);
28143
+ if (compact && !expanded) {
28144
+ return (jsxRuntime.jsxs("div", { className: "ai-chat-location-card__hours", children: [jsxRuntime.jsx(ClockIcon, {}), jsxRuntime.jsx("span", { children: todayHours?.closed ? 'Closed today' : `${todayHours?.open} - ${todayHours?.close}` })] }));
28145
+ }
28146
+ return (jsxRuntime.jsxs("div", { className: "ai-chat-location-card__hours", children: [jsxRuntime.jsx(ClockIcon, {}), jsxRuntime.jsxs("div", { className: "ai-chat-location-card__hours-list", children: [jsxRuntime.jsxs("button", { type: "button", onClick: () => setExpanded(!expanded), className: "ai-chat-location-card__hours-toggle", children: ["Today: ", todayHours?.closed ? 'Closed' : `${todayHours?.open} - ${todayHours?.close}`, jsxRuntime.jsx(ChevronIcon, { direction: expanded ? 'up' : 'down' })] }), expanded && (jsxRuntime.jsx("ul", { className: "ai-chat-location-card__hours-full", children: hours.map(h => (jsxRuntime.jsxs("li", { className: h.day === today ? 'ai-chat-location-card__hours-today' : '', children: [jsxRuntime.jsx("span", { children: h.day }), jsxRuntime.jsx("span", { children: h.closed ? 'Closed' : `${h.open} - ${h.close}` })] }, h.day))) }))] })] }));
28147
+ }
28148
+ function LocationItem({ location, settings, accentColor, onDirections, showMap = true, compact = false, }) {
28149
+ const openStatus = getOpenStatus(location.hours);
28150
+ const mapHeight = settings.mapHeight || 180;
28151
+ const mapZoom = settings.mapZoom || 15;
28152
+ const getMapEmbedUrl = () => {
28153
+ const query = location.lat && location.lng
28154
+ ? `${location.lat},${location.lng}`
28155
+ : encodeURIComponent(location.address);
28156
+ return `https://www.google.com/maps/embed/v1/place?key=AIzaSyBFw0Qbyq9zTFTd-tUY6dZWTgaQzuU17R8&q=${query}&zoom=${mapZoom}`;
28157
+ };
28158
+ const handleCall = () => {
28159
+ if (location.phone) {
28160
+ window.location.href = `tel:${location.phone}`;
28161
+ }
28162
+ };
28163
+ const style = accentColor ? { '--action-accent': accentColor } : undefined;
28164
+ // Use smaller map height in compact mode
28165
+ const effectiveMapHeight = compact ? Math.min(mapHeight, 140) : mapHeight;
28166
+ return (jsxRuntime.jsxs("div", { className: `ai-chat-action-card ai-chat-location-card ${compact ? 'ai-chat-location-card--compact' : ''}`, style: style, children: [showMap && settings.showMap !== false && (jsxRuntime.jsx("div", { className: "ai-chat-location-card__map", style: { height: effectiveMapHeight }, children: jsxRuntime.jsx("iframe", { src: getMapEmbedUrl(), allowFullScreen: true, loading: "lazy", referrerPolicy: "no-referrer-when-downgrade", title: `Map of ${location.name}` }) })), jsxRuntime.jsxs("div", { className: "ai-chat-location-card__content", children: [jsxRuntime.jsxs("div", { className: "ai-chat-location-card__header", children: [jsxRuntime.jsx("h4", { className: "ai-chat-location-card__name", children: location.name }), location.type && (jsxRuntime.jsx("span", { className: "ai-chat-location-card__type", children: location.type })), openStatus !== null && (jsxRuntime.jsx("span", { className: `ai-chat-location-card__status ai-chat-location-card__status--${openStatus ? 'open' : 'closed'}`, children: openStatus ? 'Open' : 'Closed' }))] }), jsxRuntime.jsxs("p", { className: "ai-chat-location-card__address", children: [jsxRuntime.jsx(MapPinIcon, {}), location.address] }), location.description && (jsxRuntime.jsx("p", { className: "ai-chat-location-card__description", children: location.description })), settings.showHours !== false && location.hours && location.hours.length > 0 && (jsxRuntime.jsx(HoursDisplay, { hours: location.hours, compact: compact })), settings.showPhone !== false && location.phone && (jsxRuntime.jsxs("button", { type: "button", className: "ai-chat-location-card__phone", onClick: handleCall, children: [jsxRuntime.jsx(PhoneIcon, {}), location.phone] })), jsxRuntime.jsxs("div", { className: "ai-chat-location-card__actions", children: [settings.showDirectionsButton !== false && (jsxRuntime.jsxs("button", { type: "button", className: "ai-chat-location-card__button", style: accentColor ? { backgroundColor: accentColor } : undefined, onClick: onDirections, children: [jsxRuntime.jsx(NavigationIcon, {}), compact ? 'Directions' : 'Get Directions'] })), !compact && location.website && (jsxRuntime.jsxs("a", { href: location.website, target: "_blank", rel: "noopener noreferrer", className: "ai-chat-location-card__link", children: [jsxRuntime.jsx(GlobeIcon, {}), "Website"] }))] })] })] }));
28167
+ }
28168
+ function LocationCard({ action, onComplete, accentColor, maxColumns = 3 }) {
28169
+ const rawState = action.state;
28170
+ const hasCompletedRef = React.useRef(false);
28171
+ const state = {
28172
+ locations: rawState?.locations || [],
28173
+ settings: rawState?.settings || {},
28174
+ matchInfo: rawState?.matchInfo,
28175
+ status: rawState?.status || 'displaying',
28176
+ };
28177
+ const { locations, settings } = state;
28178
+ const layout = settings.multiLocationLayout || 'stack';
28179
+ const isSingleLocation = locations.length === 1;
28180
+ const stackColumns = Math.min(Math.max(locations.length, 1), maxColumns);
28181
+ React.useEffect(() => {
28182
+ if (!action.done && !hasCompletedRef.current && onComplete && locations.length > 0) {
28183
+ hasCompletedRef.current = true;
28184
+ onComplete(action.toolCallId, { ...state, status: 'displaying' });
28185
+ }
28186
+ }, [action.done, action.toolCallId, onComplete, state, locations.length]);
28187
+ const handleDirections = (location) => {
28188
+ const url = location.lat && location.lng
28189
+ ? `https://www.google.com/maps/dir/?api=1&destination=${location.lat},${location.lng}`
28190
+ : `https://www.google.com/maps/dir/?api=1&destination=${encodeURIComponent(location.address)}`;
28191
+ window.open(url, '_blank', 'noopener,noreferrer');
28192
+ onComplete?.(action.toolCallId, { ...state, status: 'directions_opened' });
28193
+ };
28194
+ if (locations.length === 0) {
28195
+ return (jsxRuntime.jsx("div", { className: "ai-chat-location-card ai-chat-location-card--error", children: jsxRuntime.jsx("p", { children: "No locations to display" }) }));
28196
+ }
28197
+ if (isSingleLocation) {
28198
+ return (jsxRuntime.jsx(LocationItem, { location: locations[0], settings: settings, accentColor: accentColor, onDirections: () => handleDirections(locations[0]), showMap: true }));
28199
+ }
28200
+ return (jsxRuntime.jsxs("div", { className: `ai-chat-location-card-list ai-chat-location-card-list--${layout}`, children: [jsxRuntime.jsxs("div", { className: "ai-chat-location-card-list__header", children: [jsxRuntime.jsx(MapPinIcon, {}), jsxRuntime.jsxs("span", { children: [locations.length, " Locations"] })] }), layout === 'stack' && (jsxRuntime.jsx("div", { className: `ai-chat-location-card-list__stack ai-chat-location-card-list__stack--cols-${stackColumns}`, children: locations.map((location) => (jsxRuntime.jsx(LocationItem, { location: location, settings: settings, accentColor: accentColor, onDirections: () => handleDirections(location), showMap: settings.showMap !== false, compact: locations.length > 2 }, location.id))) })), layout === 'grid' && (jsxRuntime.jsx("div", { className: "ai-chat-location-card-list__grid", children: locations.map((location) => (jsxRuntime.jsx(LocationItem, { location: location, settings: settings, accentColor: accentColor, onDirections: () => handleDirections(location), showMap: false, compact: true }, location.id))) })), layout === 'carousel' && (jsxRuntime.jsx("div", { className: "ai-chat-location-card-list__carousel", children: locations.map((location) => (jsxRuntime.jsx(LocationItem, { location: location, settings: settings, accentColor: accentColor, onDirections: () => handleDirections(location), showMap: true, compact: false }, location.id))) }))] }));
28201
+ }
28202
+
28203
+ function UsersIcon() {
28204
+ return (jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntime.jsx("path", { d: "M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" }), jsxRuntime.jsx("circle", { cx: "9", cy: "7", r: "4" }), jsxRuntime.jsx("path", { d: "M22 21v-2a4 4 0 0 0-3-3.87" }), jsxRuntime.jsx("path", { d: "M16 3.13a4 4 0 0 1 0 7.75" })] }));
28205
+ }
28206
+ const AVATAR_COLORS = [
28207
+ { bg: '#E8F5E9', text: '#2E7D32' }, // Green
28208
+ { bg: '#E3F2FD', text: '#1565C0' }, // Blue
28209
+ { bg: '#FFF3E0', text: '#E65100' }, // Orange
28210
+ { bg: '#F3E5F5', text: '#7B1FA2' }, // Purple
28211
+ { bg: '#FFEBEE', text: '#C62828' }, // Red
28212
+ { bg: '#E0F7FA', text: '#00838F' }, // Cyan
28213
+ { bg: '#FFF8E1', text: '#F9A825' }, // Amber
28214
+ { bg: '#FCE4EC', text: '#AD1457' }, // Pink
28215
+ ];
28216
+ function getInitials(name) {
28217
+ const parts = name.trim().split(/\s+/);
28218
+ if (parts.length === 1) {
28219
+ return parts[0].substring(0, 2).toUpperCase();
28220
+ }
28221
+ return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
28222
+ }
28223
+ function getColorFromName(name) {
28224
+ let hash = 0;
28225
+ for (let i = 0; i < name.length; i++) {
28226
+ hash = name.charCodeAt(i) + ((hash << 5) - hash);
28227
+ }
28228
+ return AVATAR_COLORS[Math.abs(hash) % AVATAR_COLORS.length];
28229
+ }
28230
+ function ContactItem({ contact, settings, accentColor, onEmail, onPhone, compact = false, layout = 'vertical', }) {
28231
+ const style = accentColor ? { '--action-accent': accentColor } : undefined;
28232
+ const layoutClass = layout === 'horizontal'
28233
+ ? 'ai-chat-contact-card--horizontal'
28234
+ : 'ai-chat-contact-card--vertical';
28235
+ return (jsxRuntime.jsxs("div", { className: `ai-chat-action-card ai-chat-contact-card ${layoutClass} ${compact ? 'ai-chat-contact-card--compact' : ''}`, style: style, children: [jsxRuntime.jsxs("div", { className: "ai-chat-contact-card__image-section", children: [contact.profilePictureUrl ? (jsxRuntime.jsx("img", { src: contact.profilePictureUrl, alt: contact.name, className: "ai-chat-contact-card__image", onError: (e) => {
28236
+ e.currentTarget.style.display = 'none';
28237
+ const placeholder = e.currentTarget.parentElement?.querySelector('.ai-chat-contact-card__initials');
28238
+ if (placeholder) {
28239
+ placeholder.style.display = 'flex';
28240
+ }
28241
+ } })) : null, (() => {
28242
+ const colors = getColorFromName(contact.name);
28243
+ return (jsxRuntime.jsx("div", { className: "ai-chat-contact-card__initials", style: {
28244
+ display: contact.profilePictureUrl ? 'none' : 'flex',
28245
+ backgroundColor: colors.bg,
28246
+ color: colors.text,
28247
+ }, children: getInitials(contact.name) }));
28248
+ })()] }), jsxRuntime.jsxs("div", { className: "ai-chat-contact-card__info", children: [jsxRuntime.jsx("h4", { className: "ai-chat-contact-card__name", children: contact.name }), settings.showRole !== false && contact.role && (jsxRuntime.jsx("p", { className: "ai-chat-contact-card__role", children: contact.role })), jsxRuntime.jsxs("div", { className: "ai-chat-contact-card__details", children: [settings.showEmail !== false && contact.email && (jsxRuntime.jsx("a", { href: `mailto:${contact.email}`, className: "ai-chat-contact-card__detail", onClick: onEmail, children: contact.email })), settings.showPhone !== false && contact.phone && (jsxRuntime.jsx("a", { href: `tel:${contact.phone}`, className: "ai-chat-contact-card__detail", onClick: onPhone, children: contact.phone }))] }), settings.showResponsibilities !== false && contact.responsibilities && contact.responsibilities.length > 0 && !compact && (jsxRuntime.jsxs("div", { className: "ai-chat-contact-card__responsibilities", children: [contact.responsibilities.slice(0, 3).map((resp, idx) => (jsxRuntime.jsx("span", { className: "ai-chat-contact-card__responsibility-tag", children: resp }, idx))), contact.responsibilities.length > 3 && (jsxRuntime.jsxs("span", { className: "ai-chat-contact-card__responsibility-more", children: ["+", contact.responsibilities.length - 3, " more"] }))] }))] })] }));
28249
+ }
28250
+ function ContactCard({ action, onComplete, accentColor, maxColumns = 3 }) {
28251
+ const rawState = action.state;
28252
+ const hasCompletedRef = React.useRef(false);
28253
+ const state = {
28254
+ contacts: rawState?.contacts || [],
28255
+ settings: rawState?.settings || {},
28256
+ query: rawState?.query,
28257
+ status: rawState?.status || 'displaying',
28258
+ };
28259
+ const { contacts, settings } = state;
28260
+ const isSingleContact = contacts.length === 1;
28261
+ const stackColumns = Math.min(Math.max(contacts.length, 1), maxColumns);
28262
+ React.useEffect(() => {
28263
+ if (!action.done && !hasCompletedRef.current && onComplete) {
28264
+ hasCompletedRef.current = true;
28265
+ onComplete(action.toolCallId, { ...state, status: 'displaying' });
28266
+ }
28267
+ }, [action.done, action.toolCallId, onComplete, state]);
28268
+ const handleContact = () => {
28269
+ onComplete?.(action.toolCallId, { ...state, status: 'contacted' });
28270
+ };
28271
+ if (contacts.length === 0) {
28272
+ return (jsxRuntime.jsxs("div", { className: "ai-chat-contact-card ai-chat-contact-card--empty", children: [jsxRuntime.jsx("div", { className: "ai-chat-contact-card__empty-icon", children: jsxRuntime.jsx(UsersIcon, {}) }), jsxRuntime.jsxs("p", { className: "ai-chat-contact-card__empty-text", children: ["No contacts found", state.query ? ` for "${state.query}"` : ''] })] }));
28273
+ }
28274
+ if (isSingleContact) {
28275
+ return (jsxRuntime.jsx(ContactItem, { contact: contacts[0], settings: settings, accentColor: accentColor, onEmail: handleContact, onPhone: handleContact, layout: settings.layout || 'horizontal' }));
28276
+ }
28277
+ const isWidget = maxColumns === 1;
28278
+ const stackClassName = isWidget
28279
+ ? 'ai-chat-contact-card-list__stack ai-chat-contact-card-list__stack--widget'
28280
+ : 'ai-chat-contact-card-list__stack';
28281
+ return (jsxRuntime.jsxs("div", { className: "ai-chat-contact-card-list", style: { containerType: 'inline-size' }, children: [jsxRuntime.jsxs("div", { className: "ai-chat-contact-card-list__header", children: [jsxRuntime.jsx(UsersIcon, {}), jsxRuntime.jsxs("span", { children: [contacts.length, " Contacts"] })] }), jsxRuntime.jsx("div", { className: stackClassName, style: isWidget ? undefined : {
28282
+ gridTemplateColumns: `repeat(${stackColumns}, minmax(0, 1fr))`,
28283
+ }, children: contacts.map((contact) => (jsxRuntime.jsx(ContactItem, { contact: contact, settings: settings, accentColor: accentColor, onEmail: handleContact, onPhone: handleContact, compact: true, layout: settings.layout || 'vertical' }, contact.id))) })] }));
28284
+ }
28285
+
28286
+ function FormCard({ action, onComplete, accentColor }) {
28287
+ const state = action.state;
28288
+ const [currentStep, setCurrentStep] = React.useState(0);
28289
+ const [answers, setAnswers] = React.useState({});
28290
+ const [isSubmitting, setIsSubmitting] = React.useState(false);
28291
+ const questions = state.questions || [];
28292
+ const currentQuestion = questions[currentStep];
28293
+ const totalQuestions = questions.length;
28294
+ const handleAnswerChange = (questionId, value) => {
28295
+ setAnswers((prev) => ({ ...prev, [questionId]: value }));
28296
+ };
28297
+ const handleNext = () => {
28298
+ if (currentStep < totalQuestions - 1) {
28299
+ setCurrentStep((prev) => prev + 1);
28300
+ }
28301
+ };
28302
+ const handlePrev = () => {
28303
+ if (currentStep > 0) {
28304
+ setCurrentStep((prev) => prev - 1);
28305
+ }
28306
+ };
28307
+ const handleSubmit = () => {
28308
+ if (!onComplete)
28309
+ return;
28310
+ setIsSubmitting(true);
28311
+ const formattedAnswers = Object.entries(answers).map(([questionId, value]) => ({
28312
+ questionId,
28313
+ value,
28314
+ }));
28315
+ onComplete(action.toolCallId, {
28316
+ ...state,
28317
+ status: 'submitted',
28318
+ answers: formattedAnswers,
28319
+ });
28320
+ };
28321
+ const handleSkip = () => {
28322
+ if (!onComplete || !state.settings.allowSkip)
28323
+ return;
28324
+ onComplete(action.toolCallId, {
28325
+ ...state,
28326
+ status: 'skipped',
28327
+ });
28328
+ };
28329
+ const isCurrentAnswered = () => {
28330
+ if (!currentQuestion)
28331
+ return false;
28332
+ const answer = answers[currentQuestion.id];
28333
+ if (!answer)
28334
+ return !currentQuestion.required;
28335
+ if (Array.isArray(answer))
28336
+ return answer.length > 0 || !currentQuestion.required;
28337
+ return answer.trim() !== '' || !currentQuestion.required;
28338
+ };
28339
+ const canSubmit = () => {
28340
+ return questions.every((q) => {
28341
+ const answer = answers[q.id];
28342
+ if (!q.required)
28343
+ return true;
28344
+ if (!answer)
28345
+ return false;
28346
+ if (Array.isArray(answer))
28347
+ return answer.length > 0;
28348
+ return answer.trim() !== '';
28349
+ });
28350
+ };
28351
+ // Error state
28352
+ if (state.status === 'error') {
28353
+ return (jsxRuntime.jsxs("div", { className: "ai-chat-form-card ai-chat-form-card--error", children: [jsxRuntime.jsxs("div", { className: "ai-chat-form-card__header", children: [jsxRuntime.jsx("span", { className: "ai-chat-form-card__icon", children: "\u26A0\uFE0F" }), jsxRuntime.jsx("span", { className: "ai-chat-form-card__title", children: "Form Error" })] }), jsxRuntime.jsx("p", { className: "ai-chat-form-card__error", children: state.error || 'Could not load form' })] }));
28354
+ }
28355
+ // Submitted state
28356
+ if (state.status === 'submitted' || action.done) {
28357
+ return (jsxRuntime.jsxs("div", { className: "ai-chat-form-card ai-chat-form-card--submitted", children: [jsxRuntime.jsxs("div", { className: "ai-chat-form-card__header", children: [jsxRuntime.jsx("span", { className: "ai-chat-form-card__icon", children: "\u2713" }), jsxRuntime.jsx("span", { className: "ai-chat-form-card__title", children: state.title })] }), jsxRuntime.jsx("p", { className: "ai-chat-form-card__success", children: state.settings.successMessage || 'Thank you for your response!' })] }));
28358
+ }
28359
+ // Skipped state
28360
+ if (state.status === 'skipped') {
28361
+ return (jsxRuntime.jsxs("div", { className: "ai-chat-form-card ai-chat-form-card--skipped", children: [jsxRuntime.jsxs("div", { className: "ai-chat-form-card__header", children: [jsxRuntime.jsx("span", { className: "ai-chat-form-card__icon", children: "\u21B7" }), jsxRuntime.jsx("span", { className: "ai-chat-form-card__title", children: state.title })] }), jsxRuntime.jsx("p", { className: "ai-chat-form-card__skipped-text", children: "Form skipped" })] }));
28362
+ }
28363
+ // No questions
28364
+ if (totalQuestions === 0) {
28365
+ return (jsxRuntime.jsxs("div", { className: "ai-chat-form-card ai-chat-form-card--empty", children: [jsxRuntime.jsxs("div", { className: "ai-chat-form-card__header", children: [jsxRuntime.jsx("span", { className: "ai-chat-form-card__icon", children: "\uD83D\uDCCB" }), jsxRuntime.jsx("span", { className: "ai-chat-form-card__title", children: state.title })] }), jsxRuntime.jsx("p", { className: "ai-chat-form-card__empty-text", children: "This form has no questions." })] }));
28366
+ }
28367
+ return (jsxRuntime.jsxs("div", { className: "ai-chat-form-card", children: [jsxRuntime.jsxs("div", { className: "ai-chat-form-card__header", children: [jsxRuntime.jsx("span", { className: "ai-chat-form-card__icon", children: "\uD83D\uDCCB" }), jsxRuntime.jsx("span", { className: "ai-chat-form-card__title", children: state.title })] }), state.description && (jsxRuntime.jsx("p", { className: "ai-chat-form-card__description", children: state.description })), state.context && (jsxRuntime.jsx("p", { className: "ai-chat-form-card__context", children: state.context })), state.settings.showProgress && (jsxRuntime.jsxs("div", { className: "ai-chat-form-card__progress", children: [jsxRuntime.jsx("div", { className: "ai-chat-form-card__progress-bar", style: {
28368
+ width: `${((currentStep + 1) / totalQuestions) * 100}%`,
28369
+ backgroundColor: accentColor || 'var(--ai-chat-accent-color, #3b82f6)',
28370
+ } }), jsxRuntime.jsxs("span", { className: "ai-chat-form-card__progress-text", children: [currentStep + 1, " of ", totalQuestions] })] })), jsxRuntime.jsxs("div", { className: "ai-chat-form-card__question", children: [jsxRuntime.jsxs("p", { className: "ai-chat-form-card__question-text", children: [currentQuestion.text, currentQuestion.required && jsxRuntime.jsx("span", { className: "ai-chat-form-card__required", children: "*" })] }), jsxRuntime.jsxs("div", { className: "ai-chat-form-card__answer", children: [currentQuestion.type === 'text' && (jsxRuntime.jsx("textarea", { className: "ai-chat-form-card__textarea", placeholder: currentQuestion.placeholder || 'Type your answer...', value: answers[currentQuestion.id] || '', onChange: (e) => handleAnswerChange(currentQuestion.id, e.target.value), rows: 3 })), currentQuestion.type === 'single_choice' && currentQuestion.options && (jsxRuntime.jsx("div", { className: "ai-chat-form-card__options", children: currentQuestion.options.map((option) => (jsxRuntime.jsxs("label", { className: "ai-chat-form-card__option", children: [jsxRuntime.jsx("input", { type: "radio", name: currentQuestion.id, value: option.value, checked: answers[currentQuestion.id] === option.value, onChange: () => handleAnswerChange(currentQuestion.id, option.value) }), jsxRuntime.jsx("span", { className: "ai-chat-form-card__option-text", children: option.text })] }, option.id))) })), currentQuestion.type === 'multiple_choice' && currentQuestion.options && (jsxRuntime.jsx("div", { className: "ai-chat-form-card__options", children: currentQuestion.options.map((option) => {
28371
+ const currentAnswers = answers[currentQuestion.id] || [];
28372
+ const isChecked = currentAnswers.includes(option.value);
28373
+ return (jsxRuntime.jsxs("label", { className: "ai-chat-form-card__option", children: [jsxRuntime.jsx("input", { type: "checkbox", value: option.value, checked: isChecked, onChange: () => {
28374
+ const newAnswers = isChecked
28375
+ ? currentAnswers.filter((v) => v !== option.value)
28376
+ : [...currentAnswers, option.value];
28377
+ handleAnswerChange(currentQuestion.id, newAnswers);
28378
+ } }), jsxRuntime.jsx("span", { className: "ai-chat-form-card__option-text", children: option.text })] }, option.id));
28379
+ }) })), currentQuestion.type === 'rating' && (jsxRuntime.jsx("div", { className: "ai-chat-form-card__rating", children: Array.from({ length: (currentQuestion.maxRating || 5) - (currentQuestion.minRating || 1) + 1 }, (_, i) => (currentQuestion.minRating || 1) + i).map((rating) => (jsxRuntime.jsx("button", { type: "button", className: `ai-chat-form-card__rating-btn ${answers[currentQuestion.id] === String(rating) ? 'ai-chat-form-card__rating-btn--selected' : ''}`, onClick: () => handleAnswerChange(currentQuestion.id, String(rating)), style: {
28380
+ borderColor: answers[currentQuestion.id] === String(rating)
28381
+ ? (accentColor || 'var(--ai-chat-accent-color, #3b82f6)')
28382
+ : undefined,
28383
+ backgroundColor: answers[currentQuestion.id] === String(rating)
28384
+ ? (accentColor || 'var(--ai-chat-accent-color, #3b82f6)')
28385
+ : undefined,
28386
+ }, children: rating }, rating))) }))] })] }), jsxRuntime.jsxs("div", { className: "ai-chat-form-card__actions", children: [currentStep > 0 && (jsxRuntime.jsx("button", { type: "button", className: "ai-chat-form-card__btn ai-chat-form-card__btn--secondary", onClick: handlePrev, children: "Back" })), state.settings.allowSkip && currentStep === 0 && (jsxRuntime.jsx("button", { type: "button", className: "ai-chat-form-card__btn ai-chat-form-card__btn--ghost", onClick: handleSkip, children: "Skip" })), jsxRuntime.jsx("div", { className: "ai-chat-form-card__actions-spacer" }), currentStep < totalQuestions - 1 ? (jsxRuntime.jsx("button", { type: "button", className: "ai-chat-form-card__btn ai-chat-form-card__btn--primary", onClick: handleNext, disabled: !isCurrentAnswered(), style: {
28387
+ backgroundColor: accentColor || 'var(--ai-chat-accent-color, #3b82f6)',
28388
+ }, children: "Next" })) : (jsxRuntime.jsx("button", { type: "button", className: "ai-chat-form-card__btn ai-chat-form-card__btn--primary", onClick: handleSubmit, disabled: !canSubmit() || isSubmitting, style: {
28389
+ backgroundColor: accentColor || 'var(--ai-chat-accent-color, #3b82f6)',
28390
+ }, children: isSubmitting ? 'Submitting...' : (state.settings.submitButtonText || 'Submit') }))] })] }));
27521
28391
  }
27522
28392
 
27523
28393
  const pendingResolvers = new Map();
@@ -27530,12 +28400,6 @@ function getFrontendActionHandler(implementation) {
27530
28400
  function getActionRenderer(implementation) {
27531
28401
  return actionRenderers[implementation];
27532
28402
  }
27533
- function getActionPrompt(implementation) {
27534
- if (implementation === "google-calendar-appointment") {
27535
- return "Select a date to continue.";
27536
- }
27537
- return "Action input required.";
27538
- }
27539
28403
  function waitForActionState(toolCallId) {
27540
28404
  return new Promise((resolve) => {
27541
28405
  pendingResolvers.set(toolCallId, resolve);
@@ -27562,26 +28426,272 @@ function unregisterActionResumeCallback(toolCallId) {
27562
28426
  resumeCallbacks.delete(toolCallId);
27563
28427
  }
27564
28428
 
27565
- frontendActionHandlers["google-calendar-appointment"] = async (_input, _state, context) => {
27566
- return waitForActionState(context.toolCallId);
27567
- };
28429
+ function registerGoogleCalendarHandler() {
28430
+ frontendActionHandlers["google-calendar-appointment"] = async (_input, _state, context) => {
28431
+ return waitForActionState(context.toolCallId);
28432
+ };
28433
+ }
27568
28434
 
27569
- actionRenderers["google-calendar-appointment"] = (message) => {
27570
- const action = message.action;
27571
- if (!action)
27572
- return null;
27573
- const handleComplete = (toolCallId, newState) => {
27574
- resolveActionState(toolCallId, newState);
28435
+ /**
28436
+ * Register google-calendar-appointment action handler and renderer.
28437
+ * Called by initializeActionHandlers to prevent tree-shaking.
28438
+ */
28439
+ function registerGoogleCalendarAction() {
28440
+ // Register the handler
28441
+ registerGoogleCalendarHandler();
28442
+ // Register the renderer
28443
+ actionRenderers["google-calendar-appointment"] = (message, accentColor) => {
28444
+ const action = message.action;
28445
+ if (!action)
28446
+ return null;
28447
+ const handleComplete = (toolCallId, newState) => {
28448
+ resolveActionState(toolCallId, newState);
28449
+ };
28450
+ return (jsxRuntime.jsx(GoogleCalendarCard, { action: {
28451
+ implementation: action.implementation,
28452
+ toolCallId: action.toolCallId,
28453
+ actionId: action.actionId,
28454
+ input: action.input,
28455
+ state: action.state,
28456
+ done: action.done ?? false,
28457
+ }, onComplete: handleComplete, accentColor: accentColor }));
27575
28458
  };
27576
- return (jsxRuntime.jsx(GoogleCalendarCard, { action: {
27577
- implementation: action.implementation,
27578
- toolCallId: action.toolCallId,
27579
- actionId: action.actionId,
27580
- input: action.input,
27581
- state: action.state,
27582
- done: action.done ?? false,
27583
- }, onComplete: handleComplete }));
27584
- };
28459
+ }
28460
+
28461
+ function registerMicrosoftCalendarHandler() {
28462
+ frontendActionHandlers["microsoft-calendar-appointment"] = async (_input, _state, context) => {
28463
+ return waitForActionState(context.toolCallId);
28464
+ };
28465
+ }
28466
+
28467
+ /**
28468
+ * Register microsoft-calendar-appointment action handler and renderer.
28469
+ * Called by initializeActionHandlers to prevent tree-shaking.
28470
+ */
28471
+ function registerMicrosoftCalendarAction() {
28472
+ // Register the handler
28473
+ registerMicrosoftCalendarHandler();
28474
+ // Register the renderer
28475
+ actionRenderers["microsoft-calendar-appointment"] = (message, accentColor) => {
28476
+ const action = message.action;
28477
+ if (!action)
28478
+ return null;
28479
+ const handleComplete = (toolCallId, newState) => {
28480
+ resolveActionState(toolCallId, newState);
28481
+ };
28482
+ return (jsxRuntime.jsx(MicrosoftCalendarCard, { action: {
28483
+ implementation: action.implementation,
28484
+ toolCallId: action.toolCallId,
28485
+ actionId: action.actionId,
28486
+ input: action.input,
28487
+ state: action.state,
28488
+ done: action.done ?? false,
28489
+ }, onComplete: handleComplete, accentColor: accentColor }));
28490
+ };
28491
+ }
28492
+
28493
+ /**
28494
+ * Register link-preview action handler and renderer.
28495
+ * Called by initializeActionHandlers to prevent tree-shaking.
28496
+ */
28497
+ function registerLinkPreviewAction() {
28498
+ // Handler - auto-completes immediately since no user input is needed
28499
+ frontendActionHandlers["link-preview"] = async (_input, state, _context) => {
28500
+ return { ...state, status: "displaying" };
28501
+ };
28502
+ // Renderer - displays the link preview card
28503
+ actionRenderers["link-preview"] = (message, accentColor) => {
28504
+ const action = message.action;
28505
+ if (!action)
28506
+ return null;
28507
+ const handleComplete = (toolCallId, newState) => {
28508
+ resolveActionState(toolCallId, newState);
28509
+ };
28510
+ // Check if action state indicates it's already complete (displaying or clicked)
28511
+ const state = action.state;
28512
+ const status = state?.status;
28513
+ const isDone = action.done || status === "displaying" || status === "clicked";
28514
+ return (jsxRuntime.jsx(LinkPreviewCard, { action: {
28515
+ implementation: action.implementation,
28516
+ toolCallId: action.toolCallId,
28517
+ actionId: action.actionId,
28518
+ input: action.input,
28519
+ state: action.state,
28520
+ done: isDone,
28521
+ }, onComplete: handleComplete, accentColor: accentColor }));
28522
+ };
28523
+ }
28524
+
28525
+ /**
28526
+ * Register video-player action handler and renderer.
28527
+ * Called by initializeActionHandlers to prevent tree-shaking.
28528
+ */
28529
+ function registerVideoPlayerAction() {
28530
+ // Handler - auto-completes immediately since no user input is needed
28531
+ frontendActionHandlers["video-player"] = async (_input, state, _context) => {
28532
+ return { ...state, status: "displaying" };
28533
+ };
28534
+ // Renderer - displays the embedded video player card
28535
+ actionRenderers["video-player"] = (message, accentColor) => {
28536
+ const action = message.action;
28537
+ if (!action)
28538
+ return null;
28539
+ const handleComplete = (toolCallId, newState) => {
28540
+ resolveActionState(toolCallId, newState);
28541
+ };
28542
+ // Check if action state indicates it's already complete (displaying or played)
28543
+ const state = action.state;
28544
+ const status = state?.status;
28545
+ const isDone = action.done || status === "displaying" || status === "played";
28546
+ return (jsxRuntime.jsx(VideoPlayerCard, { action: {
28547
+ implementation: action.implementation,
28548
+ toolCallId: action.toolCallId,
28549
+ actionId: action.actionId,
28550
+ input: action.input,
28551
+ state: action.state,
28552
+ done: isDone,
28553
+ }, onComplete: handleComplete, accentColor: accentColor }));
28554
+ };
28555
+ }
28556
+
28557
+ /**
28558
+ * Register location-card action handler and renderer.
28559
+ * Called by initializeActionHandlers to prevent tree-shaking.
28560
+ */
28561
+ function registerLocationCardAction() {
28562
+ // Handler - auto-completes immediately since no user input is needed
28563
+ frontendActionHandlers["location-card"] = async (_input, state, _context) => {
28564
+ return { ...state, status: "displaying" };
28565
+ };
28566
+ // Renderer - displays the location card
28567
+ actionRenderers["location-card"] = (message, accentColor, variant) => {
28568
+ const action = message.action;
28569
+ if (!action)
28570
+ return null;
28571
+ const handleComplete = (toolCallId, newState) => {
28572
+ resolveActionState(toolCallId, newState);
28573
+ };
28574
+ // Check if action state indicates it's already complete
28575
+ const state = action.state;
28576
+ const status = state?.status;
28577
+ const isDone = action.done || status === "displaying" || status === "directions_opened";
28578
+ return (jsxRuntime.jsx(LocationCard, { action: {
28579
+ implementation: action.implementation,
28580
+ toolCallId: action.toolCallId,
28581
+ actionId: action.actionId,
28582
+ input: action.input,
28583
+ state: action.state,
28584
+ done: isDone,
28585
+ }, onComplete: handleComplete, accentColor: accentColor, maxColumns: variant === 'fullpage' ? 3 : 1 }));
28586
+ };
28587
+ }
28588
+
28589
+ function registerContactCardAction() {
28590
+ // Handler - auto-completes immediately since no user input is needed
28591
+ frontendActionHandlers['contact-card'] = async (_input, state, _context) => {
28592
+ return { ...state, status: 'displaying' };
28593
+ };
28594
+ // Renderer - displays the contact card
28595
+ actionRenderers['contact-card'] = (message, accentColor, variant) => {
28596
+ const action = message.action;
28597
+ if (!action)
28598
+ return null;
28599
+ const handleComplete = (toolCallId, newState) => {
28600
+ resolveActionState(toolCallId, newState);
28601
+ };
28602
+ // Check if action state indicates it's already complete
28603
+ const state = action.state;
28604
+ const status = state?.status;
28605
+ const isDone = action.done || status === 'displaying' || status === 'contacted';
28606
+ return (jsxRuntime.jsx(ContactCard, { action: {
28607
+ implementation: action.implementation,
28608
+ toolCallId: action.toolCallId,
28609
+ actionId: action.actionId,
28610
+ input: action.input,
28611
+ state: action.state,
28612
+ done: isDone,
28613
+ }, onComplete: handleComplete, accentColor: accentColor, maxColumns: variant === 'fullpage' ? 3 : 1 }));
28614
+ };
28615
+ }
28616
+
28617
+ function registerQueryContactDirectoryAction() {
28618
+ // Handler - auto-completes immediately since no user input is needed
28619
+ frontendActionHandlers['query-contact-directory'] = async (_input, state, _context) => {
28620
+ return { ...state, status: 'displaying' };
28621
+ };
28622
+ // Renderer - displays the contact card with search results
28623
+ actionRenderers['query-contact-directory'] = (message, accentColor, variant) => {
28624
+ const action = message.action;
28625
+ if (!action)
28626
+ return null;
28627
+ // Handle completion - triggers agent to continue with text response
28628
+ const handleComplete = (toolCallId, newState) => {
28629
+ resolveActionState(toolCallId, newState);
28630
+ };
28631
+ // Check if action state indicates it's already complete
28632
+ const state = action.state;
28633
+ const status = state?.status;
28634
+ const isDone = action.done || status === 'displaying' || status === 'contacted';
28635
+ return (jsxRuntime.jsx(ContactCard, { action: {
28636
+ implementation: action.implementation,
28637
+ toolCallId: action.toolCallId,
28638
+ actionId: action.actionId,
28639
+ input: action.input,
28640
+ state: action.state,
28641
+ done: isDone,
28642
+ }, onComplete: handleComplete, accentColor: accentColor, maxColumns: variant === 'fullpage' ? 3 : 1 }));
28643
+ };
28644
+ }
28645
+
28646
+ function registerDisplayFormAction() {
28647
+ // Handler - handles form submission and state updates
28648
+ frontendActionHandlers['display-form'] = async (_input, _state, context) => {
28649
+ return waitForActionState(context.toolCallId);
28650
+ };
28651
+ // Renderer - displays the form card
28652
+ actionRenderers['display-form'] = (message, accentColor, variant) => {
28653
+ const action = message.action;
28654
+ if (!action)
28655
+ return null;
28656
+ const handleComplete = (toolCallId, newState) => {
28657
+ resolveActionState(toolCallId, newState);
28658
+ };
28659
+ // Check if action state indicates it's already complete
28660
+ const state = action.state;
28661
+ const status = state?.status;
28662
+ const isDone = action.done || status === 'completed' || status === 'submitted';
28663
+ return (jsxRuntime.jsx(FormCard, { action: {
28664
+ implementation: action.implementation,
28665
+ toolCallId: action.toolCallId,
28666
+ actionId: action.actionId,
28667
+ input: action.input,
28668
+ state: action.state,
28669
+ done: isDone,
28670
+ }, onComplete: handleComplete, accentColor: accentColor }));
28671
+ };
28672
+ }
28673
+
28674
+ // Track if handlers have been initialized
28675
+ let initialized = false;
28676
+ /**
28677
+ * Initialize all action handlers.
28678
+ * Call this to ensure handlers are registered (prevents tree-shaking in production builds).
28679
+ * Safe to call multiple times - will only register once.
28680
+ */
28681
+ function initializeActionHandlers() {
28682
+ if (initialized)
28683
+ return;
28684
+ initialized = true;
28685
+ // Explicitly call each registration function to prevent tree-shaking
28686
+ registerGoogleCalendarAction();
28687
+ registerMicrosoftCalendarAction();
28688
+ registerLinkPreviewAction();
28689
+ registerVideoPlayerAction();
28690
+ registerLocationCardAction();
28691
+ registerQueryContactDirectoryAction();
28692
+ registerContactCardAction();
28693
+ registerDisplayFormAction();
28694
+ }
27585
28695
 
27586
28696
  /**
27587
28697
  * Local Storage Utilities
@@ -27800,10 +28910,6 @@ function isStorageAvailable() {
27800
28910
  }
27801
28911
  }
27802
28912
 
27803
- /**
27804
- * useChat Hook
27805
- * Main state management for chat functionality
27806
- */
27807
28913
  function hydrateToolNames(messages) {
27808
28914
  const toolCallNameById = new Map();
27809
28915
  for (const entry of messages) {
@@ -27847,81 +28953,77 @@ function hydrateToolNames(messages) {
27847
28953
  };
27848
28954
  });
27849
28955
  }
27850
- function hydrateActionContent(messages) {
27851
- return messages.map((entry) => {
27852
- if (entry.message.role !== "assistant" || !entry.action) {
27853
- return entry;
27854
- }
27855
- const content = typeof entry.message.content === "string" ? entry.message.content : "";
27856
- if (content.trim().length > 0) {
27857
- return entry;
27858
- }
27859
- return {
27860
- ...entry,
27861
- message: { ...entry.message, content: getActionPrompt(entry.action.implementation) },
27862
- };
27863
- });
27864
- }
27865
28956
  function hydrateMessages(messages) {
27866
- return hydrateActionContent(hydrateToolNames(messages));
28957
+ return hydrateToolNames(messages);
27867
28958
  }
27868
- function setupActionResumeCallbacks(messages, client, conversationId, setState, onMessageUpdate) {
27869
- // Find all incomplete actions and register resume callbacks
27870
- for (const message of messages) {
27871
- if (message.action && !message.action.done) {
27872
- const toolCallId = message.action.toolCallId;
27873
- const toolName = message.message.name || message.toolExecuting || "tool";
27874
- registerActionResumeCallback(toolCallId, async (newState) => {
27875
- // When user interacts with the action after reload, continue the stream
27876
- try {
27877
- // Update the action message with the new state
27878
- setState(prev => ({
27879
- ...prev,
27880
- messages: prev.messages.map(m => m.action?.toolCallId === toolCallId
27881
- ? {
27882
- ...m,
27883
- action: m.action ? { ...m.action, state: newState } : undefined,
27884
- }
27885
- : m),
27886
- isTyping: true,
27887
- }));
27888
- const streamState = createStreamState();
27889
- // Continue the agent stream with the new state
27890
- for await (const event of client.continueAgentMessageStream(conversationId, toolCallId, newState)) {
27891
- if (event.type === "done") {
27892
- finalizeToolMessage(streamState, setState, toolCallId, toolName);
27893
- streamState.sources = event.sources;
27894
- streamState.toolCallToActionId = event.tool_call_to_action_id;
27895
- finalizeStreamMessages(setState, streamState.newMessageIds, event.sources, event.tool_call_to_action_id, event.suggestions);
27896
- continue;
27897
- }
27898
- if (event.type === "error") {
27899
- const errorMessage = {
27900
- id: generateMessageId(),
27901
- message: {
27902
- role: "assistant",
27903
- content: "Sorry, an error occurred. Please try again later.",
27904
- },
27905
- timestamp: new Date().toISOString(),
27906
- sources: [],
27907
- isError: true,
27908
- };
27909
- upsertMessage(setState, errorMessage, false);
27910
- setState(prev => ({ ...prev, isTyping: false }));
27911
- return;
27912
- }
27913
- handleStreamEvent(event, streamState, onMessageUpdate, setState);
27914
- }
27915
- setState(prev => ({ ...prev, isTyping: false }));
28959
+
28960
+ function deriveErrorInfo(error) {
28961
+ if (error instanceof ApiError) {
28962
+ const retryAfterSeconds = typeof error.retryAfterMs === 'number'
28963
+ ? Math.max(1, Math.ceil(error.retryAfterMs / 1000))
28964
+ : undefined;
28965
+ const lowerMessage = (error.message || '').toLowerCase();
28966
+ let message;
28967
+ switch (error.status) {
28968
+ case 429: {
28969
+ const isPerUser = lowerMessage.includes('user');
28970
+ const base = isPerUser
28971
+ ? 'You have reached the per-user rate limit.'
28972
+ : 'This widget has received too many requests.';
28973
+ if (retryAfterSeconds) {
28974
+ message = `${base} Please wait ${retryAfterSeconds} second${retryAfterSeconds === 1 ? '' : 's'} before trying again.`;
27916
28975
  }
27917
- catch (error) {
27918
- console.error("[Action Resume] Failed to continue stream:", error);
27919
- setState(prev => ({ ...prev, isTyping: false }));
28976
+ else {
28977
+ message = `${base} Please wait a moment and try again.`;
28978
+ }
28979
+ break;
28980
+ }
28981
+ case 401:
28982
+ message = 'Authentication failed. Please refresh the page or verify your API key.';
28983
+ break;
28984
+ case 403:
28985
+ message = 'Access to this widget is restricted. Please contact the site owner if you believe this is an error.';
28986
+ break;
28987
+ case 404:
28988
+ if (lowerMessage.includes('not active')) {
28989
+ message = 'This widget is currently inactive. Please contact the site owner.';
28990
+ }
28991
+ else {
28992
+ message = 'We could not find this widget. It may have been removed.';
28993
+ }
28994
+ break;
28995
+ default:
28996
+ if (error.status >= 500) {
28997
+ message = 'The server encountered an error. Please try again shortly.';
28998
+ }
28999
+ else if (error.status > 0) {
29000
+ message = error.message || 'Something went wrong. Please try again.';
29001
+ }
29002
+ else {
29003
+ message = error.message || 'Unable to connect to the server. Please check your internet connection.';
27920
29004
  }
27921
- });
27922
29005
  }
29006
+ return { message, retryAfterSeconds, status: error.status };
27923
29007
  }
29008
+ if (error instanceof Error) {
29009
+ const lower = error.message.toLowerCase();
29010
+ if (lower.includes('network')) {
29011
+ return { message: 'Unable to connect to the server. Please check your internet connection.' };
29012
+ }
29013
+ if (lower.includes('timeout')) {
29014
+ return { message: 'The request timed out. Please try again.' };
29015
+ }
29016
+ if (lower.includes('unauthorized') || lower.includes('401')) {
29017
+ return { message: 'Authentication failed. Please refresh the page or verify your API key.' };
29018
+ }
29019
+ if (lower.includes('internal server error') || lower.includes('500')) {
29020
+ return { message: 'The server encountered an error. Please try again shortly.' };
29021
+ }
29022
+ return { message: error.message || 'Something went wrong. Please try again.' };
29023
+ }
29024
+ return { message: 'Something went wrong. Please try again.' };
27924
29025
  }
29026
+
27925
29027
  function createStreamState() {
27926
29028
  return {
27927
29029
  currentContent: "",
@@ -27930,6 +29032,7 @@ function createStreamState() {
27930
29032
  newMessageIds: new Set(),
27931
29033
  sources: [],
27932
29034
  toolCallToActionId: {},
29035
+ requestId: generateMessageId(),
27933
29036
  };
27934
29037
  }
27935
29038
  function upsertMessage(setState, message, isTyping) {
@@ -27965,15 +29068,40 @@ function finalizeStreamMessages(setState, messageIds, sources, toolCallToActionI
27965
29068
  return msg;
27966
29069
  }
27967
29070
  // Attach suggestions only to the last assistant message
27968
- if (index === lastAssistantIndex && suggestions && suggestions.length > 0) {
27969
- return { ...msg, sources, toolCallToActionId, suggestions };
27970
- }
27971
- return { ...msg, sources, toolCallToActionId };
29071
+ const withSuggestions = index === lastAssistantIndex && suggestions && suggestions.length > 0
29072
+ ? { suggestions }
29073
+ : {};
29074
+ return { ...msg, sources, toolCallToActionId, ...withSuggestions };
27972
29075
  }),
27973
29076
  isTyping: false,
27974
29077
  };
27975
29078
  });
27976
29079
  }
29080
+ function finalizeToolMessage(streamState, setState, toolCallId, toolName) {
29081
+ setState(prev => {
29082
+ const messages = prev.messages.map((entry) => {
29083
+ const matchesToolCall = entry.message.role === "tool" && entry.message.tool_call_id === toolCallId;
29084
+ if (!matchesToolCall) {
29085
+ return entry;
29086
+ }
29087
+ const existingName = entry.message.name || toolName;
29088
+ return {
29089
+ ...entry,
29090
+ message: {
29091
+ role: "tool",
29092
+ content: typeof entry.message.content === "string" ? entry.message.content : "",
29093
+ tool_call_id: toolCallId,
29094
+ name: existingName,
29095
+ },
29096
+ isStreaming: false,
29097
+ toolExecuting: existingName,
29098
+ };
29099
+ });
29100
+ return { ...prev, messages, isTyping: false, isLoading: false };
29101
+ });
29102
+ streamState.activeToolCallCount = Math.max(0, streamState.activeToolCallCount - 1);
29103
+ }
29104
+
27977
29105
  function handleContentEvent(event, streamState, onMessageUpdate, setState) {
27978
29106
  streamState.currentContent += event.content;
27979
29107
  const assistantMessage = {
@@ -28020,8 +29148,6 @@ function handleToolStartEvent(event, streamState, onMessageUpdate, setState) {
28020
29148
  }
28021
29149
  function handleToolEndEvent(event, streamState, _onMessageUpdate, setState) {
28022
29150
  streamState.activeToolCallCount = Math.max(0, streamState.activeToolCallCount - 1);
28023
- // Update state and mark action as done in a single setState call
28024
- // Keep isTyping: true because the agent may continue generating content after tool completion
28025
29151
  setState(prev => {
28026
29152
  const messages = prev.messages.map((msg) => {
28027
29153
  const matchesToolCall = msg.message.role === "tool" && msg.message.tool_call_id === event.tool_call_id;
@@ -28029,7 +29155,26 @@ function handleToolEndEvent(event, streamState, _onMessageUpdate, setState) {
28029
29155
  return msg;
28030
29156
  }
28031
29157
  const existingName = msg.message.name || event.tool_name;
28032
- return {
29158
+ let action = msg.action;
29159
+ if (event.action_id && event.implementation) {
29160
+ action = {
29161
+ implementation: event.implementation,
29162
+ toolCallId: event.tool_call_id,
29163
+ actionId: event.action_id,
29164
+ input: (event.input || {}),
29165
+ state: (event.state || {}),
29166
+ done: event.done,
29167
+ };
29168
+ }
29169
+ else if (action) {
29170
+ action = {
29171
+ ...action,
29172
+ input: event.input ? event.input : action.input,
29173
+ state: event.state ? event.state : action.state,
29174
+ done: event.done,
29175
+ };
29176
+ }
29177
+ const updatedMsg = {
28033
29178
  ...msg,
28034
29179
  message: {
28035
29180
  role: "tool",
@@ -28039,14 +29184,10 @@ function handleToolEndEvent(event, streamState, _onMessageUpdate, setState) {
28039
29184
  },
28040
29185
  isStreaming: false,
28041
29186
  toolExecuting: existingName,
28042
- action: msg.action ? {
28043
- ...msg.action,
28044
- state: event.state || msg.action.state,
28045
- done: true, // Mark action as completed
28046
- } : undefined,
29187
+ action,
28047
29188
  };
29189
+ return updatedMsg;
28048
29190
  });
28049
- // Keep typing indicator visible - it will be hidden by done/finalizeStreamMessages
28050
29191
  return { ...prev, messages, isTyping: true, isLoading: false };
28051
29192
  });
28052
29193
  }
@@ -28078,34 +29219,6 @@ function handleToolErrorEvent(event, streamState, _onMessageUpdate, setState) {
28078
29219
  return { ...prev, messages, isTyping: true, isLoading: false };
28079
29220
  });
28080
29221
  }
28081
- function finalizeToolMessage(streamState, setState, toolCallId, toolName) {
28082
- setState(prev => {
28083
- const messages = prev.messages.map((entry) => {
28084
- const matchesToolCall = entry.message.role === "tool" && entry.message.tool_call_id === toolCallId;
28085
- if (!matchesToolCall) {
28086
- return entry;
28087
- }
28088
- const existingName = entry.message.name || toolName;
28089
- return {
28090
- ...entry,
28091
- message: {
28092
- role: "tool",
28093
- content: typeof entry.message.content === "string" ? entry.message.content : "",
28094
- tool_call_id: toolCallId,
28095
- name: existingName,
28096
- },
28097
- isStreaming: false,
28098
- toolExecuting: existingName,
28099
- action: entry.action ? {
28100
- ...entry.action,
28101
- done: true, // Mark action as completed
28102
- } : undefined,
28103
- };
28104
- });
28105
- return { ...prev, messages, isTyping: false, isLoading: false };
28106
- });
28107
- streamState.activeToolCallCount = Math.max(0, streamState.activeToolCallCount - 1);
28108
- }
28109
29222
  function handleDoneEvent(event, streamState, _onMessageUpdate, setState) {
28110
29223
  streamState.sources = event.sources;
28111
29224
  streamState.toolCallToActionId = event.tool_call_to_action_id;
@@ -28164,6 +29277,7 @@ function handleStreamEvent(event, streamState, onMessageUpdate, setState) {
28164
29277
  console.warn('[Chat] Unknown event type:', event.type);
28165
29278
  }
28166
29279
  }
29280
+
28167
29281
  async function handleActionLoop(client, initialEvent, streamState, onMessageUpdate, setState, widgetId, conversationId, getMessages) {
28168
29282
  let pendingEvent = initialEvent;
28169
29283
  while (pendingEvent) {
@@ -28190,7 +29304,7 @@ async function handleActionLoop(client, initialEvent, streamState, onMessageUpda
28190
29304
  actionId: pendingEvent.action_id,
28191
29305
  input: pendingEvent.input,
28192
29306
  state: pendingEvent.state,
28193
- done: false, // Action not yet completed
29307
+ done: pendingEvent.done ?? false,
28194
29308
  },
28195
29309
  };
28196
29310
  if (streamState.activeToolCallCount === 0) {
@@ -28204,7 +29318,7 @@ async function handleActionLoop(client, initialEvent, streamState, onMessageUpda
28204
29318
  id: generateMessageId(),
28205
29319
  message: {
28206
29320
  role: "assistant",
28207
- content: "Sorry, an error occurred. Please try again later.",
29321
+ content: "Sorry, an error occurred.",
28208
29322
  },
28209
29323
  timestamp: new Date().toISOString(),
28210
29324
  sources: [],
@@ -28228,7 +29342,7 @@ async function handleActionLoop(client, initialEvent, streamState, onMessageUpda
28228
29342
  console.error("[Widget] Frontend action failed:", error);
28229
29343
  const errorMessageEntry = {
28230
29344
  id: generateMessageId(),
28231
- message: { role: "assistant", content: "Sorry, an error occurred. Please try again later." },
29345
+ message: { role: "assistant", content: "Sorry, an error occurred." },
28232
29346
  timestamp: new Date().toISOString(),
28233
29347
  sources: [],
28234
29348
  isError: true,
@@ -28240,12 +29354,7 @@ async function handleActionLoop(client, initialEvent, streamState, onMessageUpda
28240
29354
  pendingEvent = null;
28241
29355
  const updatedToolMessage = {
28242
29356
  ...toolMessage,
28243
- action: toolMessage.action
28244
- ? {
28245
- ...toolMessage.action,
28246
- state: nextState,
28247
- }
28248
- : undefined,
29357
+ action: toolMessage.action ? { ...toolMessage.action, state: nextState } : toolMessage.action,
28249
29358
  };
28250
29359
  upsertMessage(setState, updatedToolMessage, true);
28251
29360
  let streamEnded = false;
@@ -28255,22 +29364,20 @@ async function handleActionLoop(client, initialEvent, streamState, onMessageUpda
28255
29364
  break;
28256
29365
  }
28257
29366
  if (event.type === "done") {
28258
- // Don't extract and update state from done event - the state was already
28259
- // updated by tool_end event or by the user's frontend action.
29367
+ // Finalize tool message and stream messages
28260
29368
  finalizeToolMessage(streamState, setState, resumeToolCallId, toolName);
28261
- // Handle the done event but skip the tool finalization part since we already did it
28262
29369
  streamState.sources = event.sources;
28263
29370
  streamState.toolCallToActionId = event.tool_call_to_action_id;
28264
29371
  finalizeStreamMessages(setState, streamState.newMessageIds, event.sources, event.tool_call_to_action_id, event.suggestions);
28265
29372
  streamEnded = true;
28266
- continue; // Skip handleStreamEvent for done events to avoid state conflicts
29373
+ continue;
28267
29374
  }
28268
29375
  if (event.type === "error") {
28269
29376
  const errorMessage = {
28270
29377
  id: generateMessageId(),
28271
29378
  message: {
28272
29379
  role: "assistant",
28273
- content: "Sorry, an error occurred. Please try again later.",
29380
+ content: "Sorry, an error occurred.",
28274
29381
  },
28275
29382
  timestamp: new Date().toISOString(),
28276
29383
  sources: [],
@@ -28281,73 +29388,79 @@ async function handleActionLoop(client, initialEvent, streamState, onMessageUpda
28281
29388
  }
28282
29389
  handleStreamEvent(event, streamState, onMessageUpdate, setState);
28283
29390
  }
28284
- // If stream ended without a done event (e.g., only tool_end was sent), finalize the tool message
29391
+ // If stream ended without a done event, finalize the tool message
28285
29392
  if (!streamEnded && !pendingEvent) {
28286
29393
  finalizeToolMessage(streamState, setState, resumeToolCallId, toolName);
28287
29394
  }
28288
29395
  }
28289
29396
  }
28290
- function deriveErrorInfo(error) {
28291
- if (error instanceof ApiError) {
28292
- const retryAfterSeconds = typeof error.retryAfterMs === 'number'
28293
- ? Math.max(1, Math.ceil(error.retryAfterMs / 1000))
28294
- : undefined;
28295
- const lowerMessage = (error.message || '').toLowerCase();
28296
- let message;
28297
- switch (error.status) {
28298
- case 429: {
28299
- const isPerUser = lowerMessage.includes('user');
28300
- const base = isPerUser
28301
- ? 'You have reached the per-user rate limit.'
28302
- : 'This widget has received too many requests.';
28303
- if (retryAfterSeconds) {
28304
- message = `${base} Please wait ${retryAfterSeconds} second${retryAfterSeconds === 1 ? '' : 's'} before trying again.`;
28305
- }
28306
- else {
28307
- message = `${base} Please wait a moment and try again.`;
28308
- }
28309
- break;
28310
- }
28311
- case 401:
28312
- message = 'Authentication failed. Please refresh the page or verify your API key.';
28313
- break;
28314
- case 403:
28315
- message = 'Access to this widget is restricted. Please contact the site owner if you believe this is an error.';
28316
- break;
28317
- case 404:
28318
- message = 'We could not find this widget. It may have been removed.';
28319
- break;
28320
- default:
28321
- if (error.status >= 500) {
28322
- message = 'The server encountered an error. Please try again shortly.';
28323
- }
28324
- else if (error.status > 0) {
28325
- message = error.message || 'Something went wrong. Please try again.';
29397
+ function setupActionResumeCallbacks(messages, client, conversationId, setState, onMessageUpdate, createStreamState, registerCallback) {
29398
+ // Find all incomplete actions and register resume callbacks
29399
+ for (const message of messages) {
29400
+ if (message.action && !message.action.done) {
29401
+ const toolCallId = message.action.toolCallId;
29402
+ const toolName = message.message.name || message.toolExecuting || "tool";
29403
+ registerCallback(toolCallId, async (newState) => {
29404
+ // When user interacts with the action after reload, continue the stream
29405
+ try {
29406
+ // Update the action message with the new state and check completion
29407
+ setState(prev => ({
29408
+ ...prev,
29409
+ messages: prev.messages.map(m => {
29410
+ if (m.action?.toolCallId !== toolCallId) {
29411
+ return m;
29412
+ }
29413
+ if (!m.action) {
29414
+ return m;
29415
+ }
29416
+ return { ...m, action: { ...m.action, state: newState } };
29417
+ }),
29418
+ isTyping: true,
29419
+ }));
29420
+ const streamState = createStreamState();
29421
+ // Continue the agent stream with the new state
29422
+ for await (const event of client.continueAgentMessageStream(conversationId, toolCallId, newState)) {
29423
+ if (event.type === "done") {
29424
+ finalizeToolMessage(streamState, setState, toolCallId, toolName);
29425
+ streamState.sources = event.sources;
29426
+ streamState.toolCallToActionId = event.tool_call_to_action_id;
29427
+ finalizeStreamMessages(setState, streamState.newMessageIds, event.sources, event.tool_call_to_action_id, event.suggestions);
29428
+ continue;
29429
+ }
29430
+ if (event.type === "error") {
29431
+ const errorMessage = {
29432
+ id: generateMessageId(),
29433
+ message: {
29434
+ role: "assistant",
29435
+ content: "Sorry, an error occurred. Please try again later.",
29436
+ },
29437
+ timestamp: new Date().toISOString(),
29438
+ sources: [],
29439
+ isError: true,
29440
+ };
29441
+ upsertMessage(setState, errorMessage, false);
29442
+ setState(prev => ({ ...prev, isTyping: false }));
29443
+ return;
29444
+ }
29445
+ handleStreamEvent(event, streamState, onMessageUpdate, setState);
29446
+ }
29447
+ setState(prev => ({ ...prev, isTyping: false }));
28326
29448
  }
28327
- else {
28328
- message = error.message || 'Unable to connect to the server. Please check your internet connection.';
29449
+ catch (error) {
29450
+ console.error("[Action Resume] Failed to continue stream:", error);
29451
+ setState(prev => ({ ...prev, isTyping: false }));
28329
29452
  }
29453
+ });
28330
29454
  }
28331
- return { message, retryAfterSeconds, status: error.status };
28332
- }
28333
- if (error instanceof Error) {
28334
- const lower = error.message.toLowerCase();
28335
- if (lower.includes('network')) {
28336
- return { message: 'Unable to connect to the server. Please check your internet connection.' };
28337
- }
28338
- if (lower.includes('timeout')) {
28339
- return { message: 'The request timed out. Please try again.' };
28340
- }
28341
- if (lower.includes('unauthorized') || lower.includes('401')) {
28342
- return { message: 'Authentication failed. Please refresh the page or verify your API key.' };
28343
- }
28344
- if (lower.includes('internal server error') || lower.includes('500')) {
28345
- return { message: 'The server encountered an error. Please try again shortly.' };
28346
- }
28347
- return { message: error.message || 'Something went wrong. Please try again.' };
28348
29455
  }
28349
- return { message: 'Something went wrong. Please try again.' };
28350
29456
  }
29457
+
29458
+ /**
29459
+ * useChat Hook
29460
+ * Main state management for chat functionality
29461
+ */
29462
+ // Initialize action handlers immediately to prevent tree-shaking
29463
+ initializeActionHandlers();
28351
29464
  function useChat(options) {
28352
29465
  const { widgetId, apiUrl, currentRoute, onMessage, onError, skipInitialization = false, } = options;
28353
29466
  const [state, setState] = React.useState({
@@ -28356,23 +29469,24 @@ function useChat(options) {
28356
29469
  isLoading: false,
28357
29470
  isTyping: false,
28358
29471
  error: null,
28359
- conversationId: '', // Will be set after loading conversation
29472
+ conversationId: '',
28360
29473
  config: null,
28361
29474
  });
28362
29475
  const stateRef = React.useRef(state);
28363
29476
  React.useEffect(() => {
28364
29477
  stateRef.current = state;
28365
29478
  }, [state]);
28366
- // Chat history state
28367
29479
  const [conversations, setConversations] = React.useState([]);
29480
+ const abortControllerRef = React.useRef(null);
29481
+ const currentRequestIdRef = React.useRef(null);
29482
+ const lastNewChatTimeRef = React.useRef(0);
29483
+ const NEW_CHAT_COOLDOWN_MS = 5000;
28368
29484
  const apiClient = React.useRef(new WidgetApiClient({ widgetId, apiUrl, currentRoute }));
28369
- // Update API client when currentRoute changes
28370
29485
  React.useEffect(() => {
28371
29486
  apiClient.current = new WidgetApiClient({ widgetId, apiUrl, currentRoute });
28372
29487
  }, [widgetId, apiUrl, currentRoute]);
28373
29488
  // Load configuration on mount and hydrate with existing conversation if available
28374
29489
  React.useEffect(() => {
28375
- // Skip initialization in preview mode
28376
29490
  if (skipInitialization) {
28377
29491
  return;
28378
29492
  }
@@ -28409,7 +29523,7 @@ function useChat(options) {
28409
29523
  }));
28410
29524
  // Setup resume callbacks for incomplete actions
28411
29525
  if (conversationId) {
28412
- setupActionResumeCallbacks(hydratedMessages, apiClient.current, conversationId, setState, onMessage ?? (() => { }));
29526
+ setupActionResumeCallbacks(hydratedMessages, apiClient.current, conversationId, setState, onMessage ?? (() => { }), createStreamState, registerActionResumeCallback);
28413
29527
  }
28414
29528
  }
28415
29529
  catch (error) {
@@ -28426,7 +29540,6 @@ function useChat(options) {
28426
29540
  initialize();
28427
29541
  return () => {
28428
29542
  isMounted = false;
28429
- // Cleanup resume callbacks
28430
29543
  state.messages.forEach(message => {
28431
29544
  if (message.action?.toolCallId) {
28432
29545
  unregisterActionResumeCallback(message.action.toolCallId);
@@ -28449,7 +29562,15 @@ function useChat(options) {
28449
29562
  const hasFiles = !!files && files.length > 0;
28450
29563
  if (!trimmedContent && !hasFiles)
28451
29564
  return;
28452
- // Strip [EXECUTE_ACTION:...] prefix from displayed message (but keep for API)
29565
+ if (stateRef.current.isTyping) {
29566
+ console.warn('[Widget] Cannot send message while streaming is in progress');
29567
+ return;
29568
+ }
29569
+ if (abortControllerRef.current) {
29570
+ abortControllerRef.current.abort();
29571
+ abortControllerRef.current = null;
29572
+ }
29573
+ abortControllerRef.current = new AbortController();
28453
29574
  const displayContent = trimmedContent.replace(/^\[EXECUTE_ACTION:[^\]]+\]\s*/, '');
28454
29575
  const userMessage = {
28455
29576
  id: generateMessageId(),
@@ -28460,12 +29581,11 @@ function useChat(options) {
28460
29581
  timestamp: new Date().toISOString(),
28461
29582
  sources: [],
28462
29583
  };
28463
- // Add user message immediately
28464
29584
  setState(prev => ({
28465
29585
  ...prev,
28466
29586
  messages: [...prev.messages, userMessage],
28467
- isLoading: false, // Don't show loading, will show typing when stream starts
28468
- isTyping: true, // Show typing indicator immediately
29587
+ isLoading: false,
29588
+ isTyping: true,
28469
29589
  error: null,
28470
29590
  }));
28471
29591
  onMessage?.(userMessage);
@@ -28505,16 +29625,29 @@ function useChat(options) {
28505
29625
  }
28506
29626
  catch (uploadError) {
28507
29627
  console.error('Failed to upload file:', uploadError);
28508
- // Continue with other files
28509
29628
  }
28510
29629
  }
28511
29630
  }
28512
- // Stream the response
28513
29631
  let lastStreamedMessage = null;
28514
29632
  const streamState = createStreamState();
28515
- const stream = apiClient.current.sendAgentMessageStream(conversationId, trimmedContent, fileIds);
29633
+ currentRequestIdRef.current = streamState.requestId;
29634
+ const currentAbortController = abortControllerRef.current;
29635
+ const streamConversationId = conversationId;
29636
+ const streamRequestId = streamState.requestId;
29637
+ const stream = apiClient.current.sendAgentMessageStream(conversationId, trimmedContent, fileIds, currentAbortController?.signal);
28516
29638
  for await (const event of stream) {
29639
+ if (currentAbortController?.signal.aborted ||
29640
+ stateRef.current.conversationId !== streamConversationId ||
29641
+ currentRequestIdRef.current !== streamRequestId) {
29642
+ console.log('[Widget] Stream aborted, conversation changed, or superseded by new request');
29643
+ break;
29644
+ }
28517
29645
  if (event.type === "action_request") {
29646
+ if (currentAbortController?.signal.aborted ||
29647
+ stateRef.current.conversationId !== streamConversationId ||
29648
+ currentRequestIdRef.current !== streamRequestId) {
29649
+ break;
29650
+ }
28518
29651
  await handleActionLoop(apiClient.current, event, streamState, (message) => {
28519
29652
  lastStreamedMessage = message;
28520
29653
  }, setState, widgetId, conversationId, () => stateRef.current.messages);
@@ -28524,25 +29657,26 @@ function useChat(options) {
28524
29657
  lastStreamedMessage = message;
28525
29658
  }, setState);
28526
29659
  }
28527
- // Stream completed - finalize state
29660
+ if (currentAbortController?.signal.aborted ||
29661
+ stateRef.current.conversationId !== streamConversationId ||
29662
+ currentRequestIdRef.current !== streamRequestId) {
29663
+ console.log('[Widget] Stream was aborted or superseded, skipping finalization');
29664
+ return;
29665
+ }
28528
29666
  setState(prev => ({
28529
29667
  ...prev,
28530
29668
  isLoading: false,
28531
29669
  isTyping: false,
28532
29670
  }));
28533
- // Notify about final message
28534
29671
  if (lastStreamedMessage) {
28535
29672
  onMessage?.(lastStreamedMessage);
28536
29673
  }
28537
- // Generate follow-up suggestions asynchronously
28538
29674
  const enableFollowUps = state.config?.settings.enableFollowUpSuggestions !== false;
28539
29675
  const actionIds = state.config?.actions || [];
28540
29676
  if (enableFollowUps) {
28541
- // Don't await - let it run in background
28542
29677
  apiClient.current.generateFollowUps(stateRef.current.messages, actionIds)
28543
29678
  .then(suggestions => {
28544
29679
  if (suggestions.length > 0) {
28545
- // Attach suggestions to the last assistant message
28546
29680
  setState(prev => {
28547
29681
  const messages = [...prev.messages];
28548
29682
  for (let i = messages.length - 1; i >= 0; i--) {
@@ -28571,7 +29705,7 @@ function useChat(options) {
28571
29705
  },
28572
29706
  timestamp: new Date().toISOString(),
28573
29707
  sources: [],
28574
- isError: !fallbackMessage, // Only mark as error if using default message
29708
+ isError: !fallbackMessage,
28575
29709
  };
28576
29710
  setState(prev => ({
28577
29711
  ...prev,
@@ -28583,9 +29717,6 @@ function useChat(options) {
28583
29717
  onError?.(err);
28584
29718
  }
28585
29719
  }, [state.conversationId, state.config, state.messages, onMessage, onError]);
28586
- /**
28587
- * Clear all messages
28588
- */
28589
29720
  const clearMessages = React.useCallback(() => {
28590
29721
  setState(prev => ({
28591
29722
  ...prev,
@@ -28598,9 +29729,6 @@ function useChat(options) {
28598
29729
  clearConversation(widgetId);
28599
29730
  }
28600
29731
  }, [widgetId, state.config?.settings.persistConversation]);
28601
- /**
28602
- * Submit feedback for a message
28603
- */
28604
29732
  const submitFeedback = React.useCallback(async (messageId, feedback) => {
28605
29733
  try {
28606
29734
  const message = state.messages.find(msg => msg.id === messageId);
@@ -28610,7 +29738,6 @@ function useChat(options) {
28610
29738
  : undefined;
28611
29739
  console.log('Submitting feedback:', { conversationId: state.conversationId, messageId, feedback });
28612
29740
  await apiClient.current.submitFeedback(state.conversationId, messageId, feedback, meta);
28613
- // Update message with feedback
28614
29741
  setState(prev => ({
28615
29742
  ...prev,
28616
29743
  messages: prev.messages.map(msg => msg.id === messageId
@@ -28625,9 +29752,6 @@ function useChat(options) {
28625
29752
  onError?.(err);
28626
29753
  }
28627
29754
  }, [state.conversationId, onError]);
28628
- /**
28629
- * Load conversation history list from localStorage
28630
- */
28631
29755
  const loadConversations = React.useCallback(() => {
28632
29756
  const persistConversation = state.config?.settings.persistConversation ?? true;
28633
29757
  if (!persistConversation || !isStorageAvailable()) {
@@ -28644,8 +29768,11 @@ function useChat(options) {
28644
29768
  })));
28645
29769
  }, [widgetId, state.config?.settings.persistConversation]);
28646
29770
  const switchConversation = React.useCallback(async (conversationId) => {
29771
+ if (abortControllerRef.current) {
29772
+ abortControllerRef.current.abort();
29773
+ abortControllerRef.current = null;
29774
+ }
28647
29775
  const persistConversation = state.config?.settings.persistConversation ?? true;
28648
- // First try to load from localStorage
28649
29776
  if (persistConversation && isStorageAvailable()) {
28650
29777
  const stored = loadConversationById(widgetId, conversationId);
28651
29778
  if (stored) {
@@ -28653,16 +29780,17 @@ function useChat(options) {
28653
29780
  ...prev,
28654
29781
  conversationId: stored.conversationId,
28655
29782
  messages: hydrateMessages(stored.messages),
29783
+ isTyping: false,
29784
+ isLoading: false,
28656
29785
  }));
28657
29786
  setActiveConversation(widgetId, conversationId);
28658
29787
  return;
28659
29788
  }
28660
29789
  }
28661
- setState(prev => ({ ...prev, isLoading: true, error: null }));
29790
+ setState(prev => ({ ...prev, isLoading: true, isTyping: false, error: null }));
28662
29791
  try {
28663
29792
  const conversation = await apiClient.current.getOrCreateConversation(conversationId);
28664
29793
  const hydratedMessages = hydrateMessages(conversation.messages);
28665
- // Clear old resume callbacks
28666
29794
  state.messages.forEach(message => {
28667
29795
  if (message.action?.toolCallId) {
28668
29796
  unregisterActionResumeCallback(message.action.toolCallId);
@@ -28674,9 +29802,7 @@ function useChat(options) {
28674
29802
  messages: hydratedMessages,
28675
29803
  isLoading: false,
28676
29804
  }));
28677
- // Setup new resume callbacks
28678
- setupActionResumeCallbacks(hydratedMessages, apiClient.current, conversation.id, setState, onMessage ?? (() => { }));
28679
- // Save to local storage
29805
+ setupActionResumeCallbacks(hydratedMessages, apiClient.current, conversation.id, setState, onMessage ?? (() => { }), createStreamState, registerActionResumeCallback);
28680
29806
  if (persistConversation && isStorageAvailable()) {
28681
29807
  saveConversation(widgetId, conversation.id, hydratedMessages);
28682
29808
  }
@@ -28687,11 +29813,23 @@ function useChat(options) {
28687
29813
  }
28688
29814
  }, [widgetId, state.config?.settings.persistConversation]);
28689
29815
  const startNewConversation = React.useCallback(() => {
29816
+ const now = Date.now();
29817
+ if (now - lastNewChatTimeRef.current < NEW_CHAT_COOLDOWN_MS) {
29818
+ console.warn('[Widget] New chat rate limited - please wait');
29819
+ return;
29820
+ }
29821
+ lastNewChatTimeRef.current = now;
29822
+ if (abortControllerRef.current) {
29823
+ abortControllerRef.current.abort();
29824
+ abortControllerRef.current = null;
29825
+ }
28690
29826
  setState(prev => ({
28691
29827
  ...prev,
28692
29828
  messages: [],
28693
29829
  conversationId: '',
28694
29830
  error: null,
29831
+ isTyping: false,
29832
+ isLoading: false,
28695
29833
  }));
28696
29834
  const persistConversation = state.config?.settings.persistConversation ?? true;
28697
29835
  if (persistConversation && isStorageAvailable()) {
@@ -28703,11 +29841,8 @@ function useChat(options) {
28703
29841
  if (!persistConversation || !isStorageAvailable()) {
28704
29842
  return;
28705
29843
  }
28706
- // Delete from storage
28707
29844
  deleteConversation(widgetId, conversationId);
28708
- // Update local state
28709
29845
  setConversations(prev => prev.filter(c => c.id !== conversationId));
28710
- // If we deleted the current conversation, clear it
28711
29846
  if (state.conversationId === conversationId) {
28712
29847
  setState(prev => ({
28713
29848
  ...prev,
@@ -28727,7 +29862,6 @@ function useChat(options) {
28727
29862
  sendMessage,
28728
29863
  clearMessages,
28729
29864
  submitFeedback,
28730
- // Chat history features
28731
29865
  conversations,
28732
29866
  loadConversations,
28733
29867
  switchConversation,
@@ -28736,11 +29870,20 @@ function useChat(options) {
28736
29870
  };
28737
29871
  }
28738
29872
 
29873
+ const ShieldIcon = () => (jsxRuntime.jsxs("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntime.jsx("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" }), jsxRuntime.jsx("path", { d: "M9 12l2 2 4-4" })] }));
29874
+ const DataPolicyView = ({ config, widgetName, }) => {
29875
+ const headerTitle = widgetName || config?.appearance?.headerTitle || 'AI Assistant';
29876
+ const hasFileUpload = config?.settings?.enableFileUpload ?? false;
29877
+ const persistsConversation = config?.settings?.persistConversation ?? true;
29878
+ return (jsxRuntime.jsx("div", { className: "ai-chat-data-policy-view", children: jsxRuntime.jsxs("div", { className: "ai-chat-data-policy-content", children: [jsxRuntime.jsxs("div", { className: "ai-chat-data-policy-intro", children: [jsxRuntime.jsx("div", { className: "ai-chat-data-policy-icon", children: jsxRuntime.jsx(ShieldIcon, {}) }), jsxRuntime.jsxs("p", { children: ["Dieser Datenschutzhinweis informiert dich gem\u00E4\u00DF Art. 13 DSGVO dar\u00FCber, wie ", jsxRuntime.jsx("strong", { children: headerTitle }), " Daten verarbeitet, wenn du diesen Chat nutzt. Bitte beachte, dass der konkrete Umfang der Verarbeitung vom Betreiber dieser Website/Anwendung (dem Verantwortlichen) sowie von den jeweils aktivierten Funktionen abh\u00E4ngt."] })] }), jsxRuntime.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntime.jsx("h3", { children: "Verantwortlicher / Kontakt" }), jsxRuntime.jsx("p", { children: "Verantwortlicher im Sinne von Art. 4 Nr. 7 DSGVO ist der Betreiber dieser Website/Anwendung. Die Kontaktdaten (und ggf. die Kontaktdaten eines Datenschutzbeauftragten) findest du in der Datenschutzerkl\u00E4rung bzw. im Impressum der Website, in die dieses Chat-Widget eingebunden ist." })] }), jsxRuntime.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntime.jsx("h3", { children: "Verarbeitete Daten (Kategorien)" }), jsxRuntime.jsxs("ul", { children: [jsxRuntime.jsxs("li", { children: [jsxRuntime.jsx("strong", { children: "Chat-Inhalte:" }), " Nachrichten (Text) sowie ggf. Kontextinformationen, die du im Chat angibst. Diese Inhalte werden verarbeitet, um Antworten zu generieren und die Unterhaltung bereitzustellen."] }), hasFileUpload && (jsxRuntime.jsxs("li", { children: [jsxRuntime.jsx("strong", { children: "Hochgeladene Dateien:" }), " Dateien, die du an den Chat \u00FCbermittelst, werden zur Bearbeitung des Anliegens verarbeitet. Die Verarbeitung kann das Extrahieren von Text/Informationen umfassen."] })), jsxRuntime.jsxs("li", { children: [jsxRuntime.jsx("strong", { children: "Technische Nutzungsdaten:" }), " z.B. Zeitstempel, Sitzungs-/Request-Informationen sowie technische Metadaten, die f\u00FCr den Betrieb, die Sicherheit (Missbrauchspr\u00E4vention) und Fehleranalyse erforderlich sind."] })] })] }), jsxRuntime.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntime.jsx("h3", { children: "Zwecke und Rechtsgrundlagen" }), jsxRuntime.jsxs("ul", { children: [jsxRuntime.jsxs("li", { children: [jsxRuntime.jsx("strong", { children: "Bereitstellung des Chats und Beantwortung von Anfragen" }), " (Art. 6 Abs. 1 lit. b DSGVO, soweit Vertrags-/vorvertragliche Ma\u00DFnahmen; andernfalls Art. 6 Abs. 1 lit. f DSGVO \u2013 berechtigtes Interesse an effizienter Kommunikation und Support)."] }), jsxRuntime.jsxs("li", { children: [jsxRuntime.jsx("strong", { children: "Qualit\u00E4tssicherung, Betrieb und Sicherheit" }), " (Art. 6 Abs. 1 lit. f DSGVO), z.B. zur Stabilit\u00E4t, Missbrauchserkennung und Fehlerbehebung."] }), jsxRuntime.jsxs("li", { children: [jsxRuntime.jsx("strong", { children: "Einwilligungsbasierte Verarbeitung" }), " kann erfolgen, sofern der Betreiber dies vorsieht (Art. 6 Abs. 1 lit. a DSGVO)."] })] })] }), jsxRuntime.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntime.jsx("h3", { children: "Empf\u00E4nger und Auftragsverarbeiter" }), jsxRuntime.jsxs("ul", { children: [jsxRuntime.jsxs("li", { children: [jsxRuntime.jsx("strong", { children: "Hosting/IT-Dienstleister:" }), " Der Betreiber kann Dienstleister f\u00FCr Hosting, Logging, Monitoring und Infrastruktur einsetzen."] }), jsxRuntime.jsxs("li", { children: [jsxRuntime.jsx("strong", { children: "KI-Dienstleister:" }), " Zur Generierung von Antworten k\u00F6nnen Chat-Inhalte an KI-Modelle bzw. Anbieter von KI-Infrastruktur \u00FCbertragen werden. Soweit erforderlich, erfolgt dies auf Grundlage eines Auftragsverarbeitungsvertrags (Art. 28 DSGVO)."] }), jsxRuntime.jsxs("li", { children: [jsxRuntime.jsx("strong", { children: "Drittlandtransfer:" }), " Falls Empf\u00E4nger au\u00DFerhalb der EU/des EWR sitzen, kann ein Transfer in Drittl\u00E4nder stattfinden. In diesem Fall werden geeignete Garantien (z.B. EU-Standardvertragsklauseln) eingesetzt, soweit erforderlich."] })] })] }), jsxRuntime.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntime.jsx("h3", { children: "Speicherdauer" }), jsxRuntime.jsxs("ul", { children: [persistsConversation ? (jsxRuntime.jsxs("li", { children: [jsxRuntime.jsx("strong", { children: "Chatverlauf:" }), " Der Chatverlauf kann gespeichert werden, um die Unterhaltung \u00FCber mehrere Sitzungen hinweg fortzusetzen."] })) : (jsxRuntime.jsxs("li", { children: [jsxRuntime.jsx("strong", { children: "Chatverlauf:" }), " Der Chatverlauf wird nicht dauerhaft gespeichert und wird beim Schlie\u00DFen des Chats beendet."] })), hasFileUpload && (jsxRuntime.jsxs("li", { children: [jsxRuntime.jsx("strong", { children: "Dateien:" }), " Hochgeladene Dateien werden nur so lange verarbeitet, wie dies f\u00FCr die Bearbeitung erforderlich ist, und anschlie\u00DFend gel\u00F6scht, sofern keine l\u00E4ngere Speicherung gesetzlich erforderlich ist."] })), jsxRuntime.jsxs("li", { children: [jsxRuntime.jsx("strong", { children: "Technische Protokolle:" }), " Technische Logdaten k\u00F6nnen f\u00FCr einen begrenzten Zeitraum gespeichert werden, um den sicheren Betrieb zu gew\u00E4hrleisten."] })] })] }), jsxRuntime.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntime.jsx("h3", { children: "Deine Rechte (Betroffenenrechte)" }), jsxRuntime.jsxs("ul", { children: [jsxRuntime.jsxs("li", { children: [jsxRuntime.jsx("strong", { children: "Auskunft" }), " (Art. 15 DSGVO)"] }), jsxRuntime.jsxs("li", { children: [jsxRuntime.jsx("strong", { children: "Berichtigung" }), " (Art. 16 DSGVO)"] }), jsxRuntime.jsxs("li", { children: [jsxRuntime.jsx("strong", { children: "L\u00F6schung" }), " (Art. 17 DSGVO) und ", jsxRuntime.jsx("strong", { children: "Einschr\u00E4nkung der Verarbeitung" }), " (Art. 18 DSGVO)"] }), jsxRuntime.jsxs("li", { children: [jsxRuntime.jsx("strong", { children: "Daten\u00FCbertragbarkeit" }), " (Art. 20 DSGVO), soweit anwendbar"] }), jsxRuntime.jsxs("li", { children: [jsxRuntime.jsx("strong", { children: "Widerspruch" }), " gegen Verarbeitungen auf Grundlage berechtigter Interessen (Art. 21 DSGVO)"] }), jsxRuntime.jsxs("li", { children: [jsxRuntime.jsx("strong", { children: "Beschwerderecht" }), " bei einer Datenschutzaufsichtsbeh\u00F6rde (Art. 77 DSGVO)"] })] }), jsxRuntime.jsx("p", { children: "Hinweis: Ohne eindeutige Identifikationsmerkmale kann der Betreiber einzelne Chatverl\u00E4ufe ggf. nicht einer Person zuordnen. F\u00FCr Anfragen wende dich bitte an den Betreiber dieser Website/Anwendung." })] }), jsxRuntime.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntime.jsx("h3", { children: "Wichtiger Hinweis" }), jsxRuntime.jsx("p", { className: "ai-chat-data-policy-warning", children: "Bitte gib keine besonderen Kategorien personenbezogener Daten (z.B. Gesundheitsdaten), Passw\u00F6rter, Kreditkarten-/Bankdaten oder vertrauliche Gesch\u00E4ftsgeheimnisse in den Chat ein. KI-generierte Antworten k\u00F6nnen unzutreffend sein und sollten vor einer Nutzung eigenverantwortlich gepr\u00FCft werden." })] })] }) }));
29879
+ };
29880
+
28739
29881
  const MenuIcon = () => (jsxRuntime.jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntime.jsx("line", { x1: "4", y1: "10", x2: "20", y2: "10" }), jsxRuntime.jsx("line", { x1: "10", y1: "14", x2: "20", y2: "14" })] }));
28740
29882
  const PlusIcon = () => (jsxRuntime.jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntime.jsx("line", { x1: "12", y1: "5", x2: "12", y2: "19" }), jsxRuntime.jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" })] }));
28741
29883
  const TrashIcon = () => (jsxRuntime.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntime.jsx("path", { d: "M3 6h18" }), jsxRuntime.jsx("path", { d: "M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" }), jsxRuntime.jsx("path", { d: "M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" })] }));
28742
29884
  const CloseIcon = () => (jsxRuntime.jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntime.jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), jsxRuntime.jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }));
28743
- const ChatWindow = ({ messages, isLoading, isTyping, error, config, onSendMessage, onClose: _onClose, onFeedback, onActionClick,
29885
+ const BackIcon = () => (jsxRuntime.jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntime.jsx("path", { d: "M19 12H5" }), jsxRuntime.jsx("path", { d: "M12 19l-7-7 7-7" })] }));
29886
+ const ChatWindow = ({ messages, isLoading, isTyping, config, onSendMessage, onClose: _onClose, onFeedback, onActionClick,
28744
29887
  // Chat history props (only active when persistConversation is true)
28745
29888
  conversations = [], onLoadConversations, onSwitchConversation, onStartNewConversation, onDeleteConversation, currentConversationId,
28746
29889
  // Override props for live preview
@@ -28757,6 +29900,8 @@ headerTitleOverride, welcomeTitleOverride, welcomeMessageOverride, placeholderOv
28757
29900
  const inputPlaceholder = placeholderOverride ?? appearance?.placeholder ?? 'Ask me anything...';
28758
29901
  // Track if history panel is open
28759
29902
  const [showHistory, setShowHistory] = React.useState(false);
29903
+ // Track if data policy view is open
29904
+ const [showDataPolicy, setShowDataPolicy] = React.useState(false);
28760
29905
  // Scroll button state (managed by MessageList)
28761
29906
  const [showScrollButton, setShowScrollButton] = React.useState(false);
28762
29907
  const [scrollToBottom, setScrollToBottom] = React.useState(null);
@@ -28766,6 +29911,13 @@ headerTitleOverride, welcomeTitleOverride, welcomeMessageOverride, placeholderOv
28766
29911
  }, []);
28767
29912
  // History exit animation when starting a new chat from overview
28768
29913
  const [isHistoryExiting, setIsHistoryExiting] = React.useState(false);
29914
+ // Handle data policy click
29915
+ const handleDataPolicyClick = React.useCallback(() => {
29916
+ setShowDataPolicy(true);
29917
+ }, []);
29918
+ const handleDataPolicyBack = React.useCallback(() => {
29919
+ setShowDataPolicy(false);
29920
+ }, []);
28769
29921
  // Load conversations when history panel opens
28770
29922
  const handleOpenHistory = () => {
28771
29923
  setShowHistory(true);
@@ -28813,10 +29965,22 @@ headerTitleOverride, welcomeTitleOverride, welcomeMessageOverride, placeholderOv
28813
29965
  // The backend will detect and trigger the action based on the message
28814
29966
  onSendMessage(question);
28815
29967
  };
28816
- return (jsxRuntime.jsxs("div", { className: `ai-chat-window size-${size}`, role: "dialog", "aria-label": "Chat window", children: [jsxRuntime.jsx("div", { className: `ai-chat-header ${showHistory ? 'is-history' : ''}`, children: showHistory ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: "ai-chat-title", children: headerTitle }), jsxRuntime.jsx("button", { className: "ai-chat-header-button", onClick: handleNewConversation, "aria-label": "New chat", children: jsxRuntime.jsx(PlusIcon, {}) })] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: "ai-chat-header-content", children: [appearance?.logo && (jsxRuntime.jsx("img", { src: appearance.logo, alt: "Logo", className: "ai-chat-logo" })), jsxRuntime.jsx("div", { className: "ai-chat-title", children: headerTitle })] }), jsxRuntime.jsxs("div", { className: "ai-chat-header-actions", children: [canShowHistory && (jsxRuntime.jsx("button", { className: "ai-chat-header-button", onClick: handleOpenHistory, "aria-label": "Chat overview", children: jsxRuntime.jsx(MenuIcon, {}) })), jsxRuntime.jsx("button", { className: "ai-chat-close-button header-close-button", onClick: _onClose, "aria-label": "Close chat", children: jsxRuntime.jsx(CloseIcon, {}) })] })] })) }), showHistory ? (jsxRuntime.jsxs("div", { className: "ai-chat-history-panel", children: [conversations.length === 0 ? (jsxRuntime.jsx("div", { className: "ai-chat-history-empty", children: "No previous conversations" })) : (jsxRuntime.jsx("div", { className: `ai-chat-history-list ${isHistoryExiting ? 'exiting' : ''}`, children: conversations.map((conv) => (jsxRuntime.jsx("div", { className: `ai-chat-history-item ${conv.id === currentConversationId ? 'active' : ''}`, onClick: () => handleSelectConversation(conv.id), children: jsxRuntime.jsxs("div", { className: "ai-chat-history-item-content", children: [jsxRuntime.jsx("div", { className: "ai-chat-history-item-preview", children: conv.preview }), onDeleteConversation && (jsxRuntime.jsx("button", { className: "ai-chat-history-item-delete", onClick: (e) => {
29968
+ return (jsxRuntime.jsxs("div", { className: `ai-chat-window size-${size}`, role: "dialog", "aria-label": "Chat window", children: [jsxRuntime.jsx("div", { className: `ai-chat-header ${showHistory ? 'is-history' : ''} ${showDataPolicy ? 'is-data-policy' : ''}`, children: showDataPolicy ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("button", { className: "ai-chat-header-button", onClick: handleDataPolicyBack, "aria-label": "Back to chat", children: jsxRuntime.jsx(BackIcon, {}) }), jsxRuntime.jsx("div", { className: "ai-chat-title", children: "Datenschutzhinweis" })] })) : showHistory ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: "ai-chat-title", children: headerTitle }), jsxRuntime.jsx("button", { className: "ai-chat-header-button", onClick: handleNewConversation, "aria-label": "New chat", children: jsxRuntime.jsx(PlusIcon, {}) })] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: "ai-chat-header-content", children: [appearance?.logo && (jsxRuntime.jsx("img", { src: appearance.logo, alt: "Logo", className: "ai-chat-logo" })), jsxRuntime.jsx("div", { className: "ai-chat-title", children: headerTitle })] }), jsxRuntime.jsxs("div", { className: "ai-chat-header-actions", children: [canShowHistory && (jsxRuntime.jsx("button", { className: "ai-chat-header-button", onClick: handleOpenHistory, "aria-label": "Chat overview", children: jsxRuntime.jsx(MenuIcon, {}) })), jsxRuntime.jsx("button", { className: "ai-chat-close-button header-close-button", onClick: _onClose, "aria-label": "Close chat", children: jsxRuntime.jsx(CloseIcon, {}) })] })] })) }), showDataPolicy ? (jsxRuntime.jsx(DataPolicyView, { config: config, onBack: handleDataPolicyBack, widgetName: headerTitle })) : showHistory ? (
29969
+ /* History Panel */
29970
+ jsxRuntime.jsxs("div", { className: "ai-chat-history-panel", children: [conversations.length === 0 ? (jsxRuntime.jsx("div", { className: "ai-chat-history-empty", children: "No previous conversations" })) : (jsxRuntime.jsx("div", { className: `ai-chat-history-list ${isHistoryExiting ? 'exiting' : ''}`, children: conversations.map((conv) => (jsxRuntime.jsx("div", { className: `ai-chat-history-item ${conv.id === currentConversationId ? 'active' : ''}`, onClick: () => handleSelectConversation(conv.id), children: jsxRuntime.jsxs("div", { className: "ai-chat-history-item-content", children: [jsxRuntime.jsx("div", { className: "ai-chat-history-item-preview", children: conv.preview }), onDeleteConversation && (jsxRuntime.jsx("button", { className: "ai-chat-history-item-delete", onClick: (e) => {
28817
29971
  e.stopPropagation();
28818
29972
  onDeleteConversation(conv.id);
28819
- }, "aria-label": "Delete conversation", children: jsxRuntime.jsx(TrashIcon, {}) }))] }) }, conv.id))) })), jsxRuntime.jsx(MessageInput, { onSend: (text) => handleSendFromOverview(text), placeholder: inputPlaceholder, disabled: isLoading, enableFileUpload: settings?.enableFileUpload })] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [error && (jsxRuntime.jsx("div", { className: "ai-chat-error", role: "alert", children: error })), maxMessages && userMessageCount >= maxMessages - 2 && !isLimitReached && (jsxRuntime.jsxs("div", { className: "ai-chat-warning", role: "alert", children: [maxMessages - userMessageCount, " message", maxMessages - userMessageCount !== 1 ? 's' : '', " remaining"] })), isLimitReached && (jsxRuntime.jsx("div", { className: "ai-chat-error", role: "alert", children: "Message limit reached. Please start a new conversation." })), jsxRuntime.jsx(MessageList, { messages: messages, isTyping: isTyping, showTypingIndicator: settings?.showTypingIndicator, showTimestamps: settings?.showTimestamps, enableFeedback: settings?.enableFeedback, showSources: settings?.showSources, sourceDisplayMode: settings?.sourceDisplayMode, welcomeTitle: welcomeTitle || 'Welcome Message', welcomeMessage: welcomeMessage, suggestedQuestions: suggestedQuestionsOverride ?? settings?.suggestedQuestions, accentColor: appearance?.primaryColor, onSuggestedQuestionClick: handleQuestionClick, onActionClick: onActionClick, onFeedback: onFeedback, onScrollStateChange: handleScrollStateChange, getActionRenderer: getActionRenderer }), jsxRuntime.jsx(ScrollButton, { onClick: () => scrollToBottom?.(), visible: showScrollButton }), jsxRuntime.jsx(MessageInput, { onSend: onSendMessage, placeholder: isLimitReached ? 'Message limit reached' : inputPlaceholder, disabled: isLoading || isLimitReached, enableFileUpload: settings?.enableFileUpload })] }))] }));
29973
+ }, "aria-label": "Delete conversation", children: jsxRuntime.jsx(TrashIcon, {}) }))] }) }, conv.id))) })), jsxRuntime.jsx(MessageInput, { onSend: (text) => handleSendFromOverview(text), placeholder: inputPlaceholder, disabled: isLoading, enableFileUpload: settings?.enableFileUpload, showDataPolicy: settings?.showDataPolicy ?? true, onDataPolicyClick: handleDataPolicyClick })] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [maxMessages && userMessageCount >= maxMessages - 2 && !isLimitReached && (jsxRuntime.jsxs("div", { className: "ai-chat-warning", role: "alert", children: [maxMessages - userMessageCount, " message", maxMessages - userMessageCount !== 1 ? 's' : '', " remaining"] })), isLimitReached && (jsxRuntime.jsx("div", { className: "ai-chat-error", role: "alert", children: "Message limit reached. Please start a new conversation." })), (() => {
29974
+ console.log('[DEBUG ChatWindow] Rendering MessageList with', messages.length, 'messages');
29975
+ messages.forEach((m, i) => {
29976
+ console.log(`[DEBUG ChatWindow] msg ${i}:`, { role: m.message.role, hasAction: !!m.action, impl: m.action?.implementation });
29977
+ });
29978
+ console.log('[DEBUG ChatWindow] getActionRenderer available:', !!getActionRenderer);
29979
+ if (getActionRenderer) {
29980
+ console.log('[DEBUG ChatWindow] Testing renderer for query-contact-directory:', !!getActionRenderer('query-contact-directory'));
29981
+ }
29982
+ return null;
29983
+ })(), jsxRuntime.jsx(MessageList, { messages: messages, isTyping: isTyping, showTypingIndicator: settings?.showTypingIndicator, showTimestamps: settings?.showTimestamps, showToolCalls: settings?.showToolCalls, enableFeedback: settings?.enableFeedback, welcomeTitle: welcomeTitle || 'Welcome Message', welcomeMessage: welcomeMessage, suggestedQuestions: suggestedQuestionsOverride ?? settings?.suggestedQuestions, accentColor: appearance?.primaryColor, onSuggestedQuestionClick: handleQuestionClick, onActionClick: onActionClick, onFeedback: onFeedback, onScrollStateChange: handleScrollStateChange, getActionRenderer: getActionRenderer }), jsxRuntime.jsx(ScrollButton, { onClick: () => scrollToBottom?.(), visible: showScrollButton }), jsxRuntime.jsx(MessageInput, { onSend: onSendMessage, placeholder: isLimitReached ? 'Message limit reached' : (isTyping ? 'Waiting for response...' : inputPlaceholder), disabled: isLoading || isTyping || isLimitReached, enableFileUpload: settings?.enableFileUpload, showDataPolicy: settings?.showDataPolicy ?? true, onDataPolicyClick: handleDataPolicyClick })] }))] }));
28820
29984
  };
28821
29985
 
28822
29986
  /**
@@ -29222,7 +30386,7 @@ function styleInject(css, ref) {
29222
30386
  if ( ref === void 0 ) ref = {};
29223
30387
  var insertAt = ref.insertAt;
29224
30388
 
29225
- if (typeof document === 'undefined') { return; }
30389
+ if (!css || typeof document === 'undefined') { return; }
29226
30390
 
29227
30391
  var head = document.head || document.getElementsByTagName('head')[0];
29228
30392
  var style = document.createElement('style');
@@ -29245,7 +30409,10 @@ function styleInject(css, ref) {
29245
30409
  }
29246
30410
  }
29247
30411
 
29248
- var css_248z = ".ai-chat-message{animation:ai-chat-message-appear .2s var(--chat-ease-bounce);max-width:85%}.ai-chat-message-content{border-radius:var(--chat-radius-bubble,14px);font-size:var(--chat-text-md,15px);line-height:var(--chat-line-relaxed,1.6);padding:var(--chat-space-sm,8px) var(--chat-space-md,16px)}.ai-chat-message.user .ai-chat-message-content{background:var(--chat-user-bg,#f4f3f0);border-bottom-right-radius:var(--chat-radius-sm,4px);color:var(--chat-user-text,#000)}.ai-chat-message.assistant .ai-chat-message-content{background:var(--chat-assistant-bg,transparent);color:var(--chat-assistant-text,#000)}.ai-chat-message-timestamp{color:var(--chat-text-muted,#71717a);font-size:var(--chat-text-xs,12px);margin-top:var(--chat-space-xs,4px);padding:0 var(--chat-space-xs,4px)}.ai-chat-message.streaming .ai-chat-message-content:after{animation:ai-chat-cursor-blink .8s infinite;content:\"▋\";margin-left:2px;opacity:.7}@keyframes ai-chat-message-appear{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}@keyframes ai-chat-cursor-blink{0%,50%{opacity:1}51%,to{opacity:0}}.ai-chat-message.fullpage .ai-chat-message-content{font-size:var(--chat-text-lg,18px);padding:var(--chat-space-md,16px) var(--chat-space-lg,24px)}.ai-chat-typing{gap:var(--chat-space-xs,4px);padding:var(--chat-space-sm,8px) var(--chat-space-md,16px)}.ai-chat-typing-dot{background:var(--chat-text-muted,#71717a)}.ai-chat-tool-gear{color:var(--text-primary,#3e3e3e)}.ai-chat-tool-gear.spinning{animation:ai-chat-spin 1.5s linear infinite}.ai-chat-tool-badge{border-radius:8px}.ai-chat-tool-badge.loading{background:#e5e7eb;border:1px solid #d1d5db;color:#1f2937}.ai-chat-tool-badge.error{background:rgba(239,68,68,.1);color:#ef4444}.ai-chat-tool-check{color:#22c55e;flex-shrink:0}.ai-chat-tool-error{color:#ef4444;flex-shrink:0}.ai-chat-tool-badge .tool-name{max-width:150px;overflow:hidden;text-overflow:ellipsis}.ai-chat-widget.dark .ai-chat-tool-gear,.ai-chat-widget[data-theme=dark] .ai-chat-tool-gear,.dark .ai-chat-tool-gear,[data-theme=dark] .ai-chat-tool-gear{color:#fff}.ai-chat-widget.dark .ai-chat-tool-badge,.ai-chat-widget[data-theme=dark] .ai-chat-tool-badge,.dark .ai-chat-tool-badge,[data-theme=dark] .ai-chat-tool-badge{background:hsla(0,0%,100%,.12);border:1px solid hsla(0,0%,100%,.2);color:hsla(0,0%,100%,.9)}.ai-chat-widget.dark .ai-chat-tool-badge.error,.ai-chat-widget[data-theme=dark] .ai-chat-tool-badge.error,.dark .ai-chat-tool-badge.error,[data-theme=dark] .ai-chat-tool-badge.error{background:rgba(239,68,68,.2);color:#f87171}.chakra-ui-dark .ai-chat-tool-gear,html.dark .ai-chat-tool-gear{color:#fff}.chakra-ui-dark .ai-chat-tool-badge,html.dark .ai-chat-tool-badge{background:hsla(0,0%,100%,.12);border:1px solid hsla(0,0%,100%,.2);color:hsla(0,0%,100%,.9)}.chakra-ui-dark .ai-chat-tool-badge.error,html.dark .ai-chat-tool-badge.error{background:rgba(239,68,68,.2);color:#f87171}@keyframes ai-chat-skeleton-pulse{0%,to{opacity:.4}50%{opacity:.7}}.ai-chat-action-skeleton-item{animation:ai-chat-skeleton-pulse 1.5s ease-in-out infinite;background:var(--bg-secondary,#e5e7eb)}.ai-chat-widget.dark .ai-chat-action-skeleton-item,.chakra-ui-dark .ai-chat-action-skeleton-item,.dark .ai-chat-action-skeleton-item,[data-theme=dark] .ai-chat-action-skeleton-item{background:hsla(0,0%,100%,.1)}.ai-chat-action-skeleton-content{display:flex;flex-direction:column;gap:16px}.ai-chat-action-skeleton-header{align-items:center;display:flex;gap:10px}.ai-chat-action-skeleton-box{background:rgba(0,0,0,.08);border-radius:10px;display:flex;flex-direction:column;gap:8px;padding:14px}.ai-chat-widget.dark .ai-chat-action-skeleton-box,.chakra-ui-dark .ai-chat-action-skeleton-box,.dark .ai-chat-action-skeleton-box,[data-theme=dark] .ai-chat-action-skeleton-box{background:rgba(0,0,0,.25)}.ai-chat-action-card{--action-accent:var(--primary-color,#3b82f6);background:var(--bg-secondary,#f4f4f4);border:none;border-radius:var(--radius-lg,12px);box-sizing:border-box;margin-top:var(--space-sm,8px);max-width:100%;padding:var(--space-md,16px);transition:all var(--duration-normal,.25s) ease;width:100%}.ai-chat-widget.dark .ai-chat-action-card,.chakra-ui-dark .ai-chat-action-card,.dark .ai-chat-action-card,[data-theme=dark] .ai-chat-action-card{background:var(--bg-secondary,#3a3a3a)}.ai-chat-action-booked{background:var(--bg-secondary,#f4f4f4);border:none}.ai-chat-widget.dark .ai-chat-action-booked,.chakra-ui-dark .ai-chat-action-booked,.dark .ai-chat-action-booked,[data-theme=dark] .ai-chat-action-booked{background:var(--bg-secondary,#3a3a3a)}.ai-chat-action-header{align-items:center;color:var(--text-primary,#3e3e3e);display:flex;font-size:var(--text-md,15px);font-weight:var(--font-weight-semibold,600);gap:var(--space-sm,8px);margin-bottom:var(--space-md,16px)}.ai-chat-widget.dark .ai-chat-action-header,.chakra-ui-dark .ai-chat-action-header,.dark .ai-chat-action-header,[data-theme=dark] .ai-chat-action-header{color:var(--text-primary,#fff)}.ai-chat-action-icon{color:var(--action-accent,var(--primary-color,#3b82f6));flex-shrink:0;height:20px;width:20px}.ai-chat-action-success-icon-wrapper{align-items:center;background:var(--action-accent,var(--primary-color,#22c55e));border-radius:50%;color:#fff;display:flex;flex-shrink:0;height:24px;justify-content:center;width:24px}.ai-chat-action-icon-success{color:currentColor;height:14px;width:14px}.ai-chat-action-detail-box{background:var(--bg-primary,#fff);border:1px solid var(--border-subtle,rgba(0,0,0,.08));border-radius:var(--radius-md,8px);display:flex;flex-direction:column;gap:4px;padding:12px 16px}.ai-chat-widget.dark .ai-chat-action-detail-box,.chakra-ui-dark .ai-chat-action-detail-box,.dark .ai-chat-action-detail-box,[data-theme=dark] .ai-chat-action-detail-box{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.05)}.ai-chat-action-label-small{color:var(--text-muted,#71717a);font-size:11px;font-weight:600;letter-spacing:.5px;text-transform:uppercase}.ai-chat-action-value-large{color:var(--text-primary,#3e3e3e);font-size:15px;font-weight:500}.ai-chat-widget.dark .ai-chat-action-value-large,.chakra-ui-dark .ai-chat-action-value-large,.dark .ai-chat-action-value-large,[data-theme=dark] .ai-chat-action-value-large{color:#fff}.ai-chat-action-link-button{align-items:center;background:var(--action-accent,var(--primary-color,#3b82f6));border:none;border-radius:9999px;box-sizing:border-box;color:#fff;display:flex;font-size:14px;font-weight:600;gap:6px;justify-content:center;margin-top:8px;padding:12px;text-decoration:none;transition:all .2s ease;width:100%}.ai-chat-action-link-button:hover{opacity:.9;transform:translateY(-1px)}.ai-chat-action-body{display:flex;flex-direction:column;gap:var(--space-md,16px)}.ai-chat-action-field{display:flex;flex-direction:column;gap:var(--space-xs,6px)}.ai-chat-action-label{color:var(--text-secondary,#6b7280);font-size:var(--text-sm,13px);font-weight:var(--font-weight-medium,500)}.ai-chat-widget.dark .ai-chat-action-label,.chakra-ui-dark .ai-chat-action-label,.dark .ai-chat-action-label,[data-theme=dark] .ai-chat-action-label{color:var(--text-secondary,#a1a1aa)}.ai-chat-action-input{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);color:var(--text-primary,#3e3e3e);font-size:var(--text-sm,13px);outline:none;padding:10px 12px;transition:border-color .2s ease,box-shadow .2s ease}.ai-chat-action-input:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.1)}.ai-chat-action-input::placeholder{color:var(--text-muted,#9ca3af)}.ai-chat-widget.dark .ai-chat-action-input,.chakra-ui-dark .ai-chat-action-input,.dark .ai-chat-action-input,[data-theme=dark] .ai-chat-action-input{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-action-input:focus,.chakra-ui-dark .ai-chat-action-input:focus,.dark .ai-chat-action-input:focus,[data-theme=dark] .ai-chat-action-input:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.2)}.ai-chat-action-date-grid{display:grid;gap:var(--space-xs,6px);grid-template-columns:repeat(auto-fill,minmax(90px,1fr))}.ai-chat-action-date-btn{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);color:var(--text-primary,#3e3e3e);cursor:pointer;font-size:var(--text-xs,12px);font-weight:var(--font-weight-medium,500);padding:8px 10px;text-align:center;transition:all .15s ease}.ai-chat-action-date-btn:hover{background:rgba(59,130,246,.05);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-action-date-btn.active{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-widget.dark .ai-chat-action-date-btn,.chakra-ui-dark .ai-chat-action-date-btn,.dark .ai-chat-action-date-btn,[data-theme=dark] .ai-chat-action-date-btn{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-action-date-btn:hover,.chakra-ui-dark .ai-chat-action-date-btn:hover,.dark .ai-chat-action-date-btn:hover,[data-theme=dark] .ai-chat-action-date-btn:hover{background:rgba(59,130,246,.15);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-action-date-btn.active,.chakra-ui-dark .ai-chat-action-date-btn.active,.dark .ai-chat-action-date-btn.active,[data-theme=dark] .ai-chat-action-date-btn.active{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-action-time-grid{display:grid;gap:var(--space-xs,6px);grid-template-columns:repeat(auto-fill,minmax(100px,1fr))}.ai-chat-action-time-btn{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);color:var(--text-primary,#3e3e3e);cursor:pointer;font-size:var(--text-xs,12px);font-weight:var(--font-weight-medium,500);padding:8px 10px;text-align:center;transition:all .15s ease}.ai-chat-action-time-btn:hover{background:rgba(59,130,246,.05);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-action-time-btn.active{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-widget.dark .ai-chat-action-time-btn,.chakra-ui-dark .ai-chat-action-time-btn,.dark .ai-chat-action-time-btn,[data-theme=dark] .ai-chat-action-time-btn{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-action-time-btn:hover,.chakra-ui-dark .ai-chat-action-time-btn:hover,.dark .ai-chat-action-time-btn:hover,[data-theme=dark] .ai-chat-action-time-btn:hover{background:rgba(59,130,246,.15);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-action-time-btn.active,.chakra-ui-dark .ai-chat-action-time-btn.active,.dark .ai-chat-action-time-btn.active,[data-theme=dark] .ai-chat-action-time-btn.active{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-action-button{background:var(--action-accent,var(--primary-color,#3b82f6));border:none;border-radius:9999px;color:#fff;cursor:pointer;font-size:var(--text-sm,13px);font-weight:var(--font-weight-semibold,600);padding:12px 16px;transition:all .2s ease;width:100%}.ai-chat-action-button:hover:not(:disabled){opacity:.9;transform:translateY(-1px)}.ai-chat-action-button:disabled{cursor:not-allowed;opacity:.5}.ai-chat-action-error{background:rgba(239,68,68,.1);border-radius:var(--radius-md,8px);color:#dc2626;font-size:var(--text-sm,13px);padding:10px 12px}.ai-chat-widget.dark .ai-chat-action-error,.chakra-ui-dark .ai-chat-action-error,.dark .ai-chat-action-error,[data-theme=dark] .ai-chat-action-error{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-action-hint{color:var(--text-muted,#9ca3af);font-size:var(--text-sm,13px);padding:var(--space-sm,8px);text-align:center}.ai-chat-widget,.chat-ui{--radius-sm:4px;--radius-md:8px;--radius-lg:12px;--radius-xl:16px;--radius-2xl:18px;--radius-pill:9999px;--radius-window-top:22px;--radius-window-bottom:44px;--radius-window-gutter:16px;--radius-chat-bubble:14px;--radius-preset-badge:13px;--radius-history-item:14px;--radius-action-badge:8px;--radius-input:62px;--space-xs:4px;--space-sm:8px;--space-md:16px;--space-lg:24px;--space-xl:32px;--text-xs:12px;--text-sm:14px;--text-md:15px;--text-lg:18px;--text-xl:22px;--text-2xl:28px;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--line-height-tight:1.3;--line-height-normal:1.4;--line-height-relaxed:1.6;--bg-primary:#fff;--bg-secondary:#f4f4f4;--bg-tertiary:#e5e7eb;--bg-hover:#e5e7eb;--text-primary:#3e3e3e;--text-secondary:#000;--text-muted:#71717a;--text-placeholder:#a1a1aa;--border-default:#d3d3d3;--border-subtle:#e5e7eb;--border-muted:#f4f4f5;--user-bg:#f4f3f0;--user-text:#000;--user-bg-hover:#e8e7e4;--agent-bg:transparent;--agent-text:#000;--input-bg:#f4f4f4;--input-border:#d3d3d3;--input-text:#000;--btn-primary-bg:#151515;--btn-primary-text:#f4f4f4;--btn-secondary-bg:transparent;--btn-secondary-text:#71717a;--spring-bounce:cubic-bezier(0.34,1.56,0.64,1);--spring-smooth:cubic-bezier(0.4,0,0.2,1);--spring-snappy:cubic-bezier(0.2,0,0,1);--duration-fast:0.15s;--duration-normal:0.25s;--duration-slow:0.35s;--shadow-sm:0 1px 2px rgba(0,0,0,.05);--shadow-md:0 2px 8px rgba(0,0,0,.1);--shadow-lg:0 4px 16px rgba(0,0,0,.12);--shadow-window:0px 0px 15px 9px rgba(0,0,0,.1);--shadow-button:0px 0px 15px 9px rgba(0,0,0,.03)}.ai-chat-widget.dark,.chat-ui.dark{--bg-primary:#282625;--bg-secondary:#4a4846;--bg-tertiary:#484848;--bg-hover:#484848;--text-primary:#fff;--text-secondary:#fff;--text-muted:#a1a1aa;--text-placeholder:#71717a;--border-default:#5d5b5b;--border-subtle:#5d5b5b;--border-muted:#5d5b5b;--user-bg:#484848;--user-text:#fff;--user-bg-hover:#5a5a5a;--agent-bg:transparent;--agent-text:#fff;--input-bg:#4a4846;--input-border:#5d5b5b;--input-text:#fff;--btn-primary-bg:#fff;--btn-primary-text:#312f2d;--btn-secondary-bg:transparent;--btn-secondary-text:#a1a1aa;--shadow-window:0px 0px 15px 9px rgba(0,0,0,.2);--shadow-button:0px 0px 15px 9px rgba(0,0,0,.03);--shadow-input:0px 0px 10px rgba(0,0,0,.15)}.ai-chat-widget,.chat-ui{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}.ai-chat-widget-container{font-size:var(--text-sm);line-height:1.5;position:fixed;z-index:9999}.ai-chat-widget-container.bottom-right{bottom:20px;right:20px}.ai-chat-widget-container.bottom-left{bottom:20px;left:20px}.ai-chat-widget-container.top-right{right:20px;top:20px}.ai-chat-widget-container.top-left{left:20px;top:20px}@keyframes ai-chat-window-open{0%{opacity:0;transform:scale(.9) translateY(20px)}to{opacity:1;transform:scale(1) translateY(0)}}@keyframes ai-chat-window-close{0%{opacity:1;transform:scale(1) translateY(0)}to{opacity:0;transform:scale(.9) translateY(20px)}}@keyframes ai-chat-message-slide-in{0%{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}@keyframes ai-chat-welcome-fade-in{0%{opacity:0;transform:translateY(16px)}to{opacity:1;transform:translateY(0)}}@keyframes ai-chat-typing-pulse{0%,60%,to{opacity:.4;transform:translateY(0) scale(1)}30%{opacity:1;transform:translateY(-4px) scale(1.1)}}@keyframes ai-chat-gear-spin{to{transform:rotate(1turn)}}@keyframes ai-chat-tool-active{0%,to{background:var(--bg-secondary);opacity:1}50%{background:var(--bg-tertiary);opacity:1}}@keyframes ai-chat-feedback-morph{0%{opacity:.5;transform:scale(.8)}to{opacity:1;transform:scale(1)}}@keyframes ai-chat-checkmark-pop{0%{opacity:0;transform:scale(0) rotate(-45deg)}50%{transform:scale(1.3) rotate(0deg)}to{opacity:1;transform:scale(1) rotate(0deg)}}@keyframes ai-chat-history-exit{to{opacity:0;transform:translateY(-18px)}}@keyframes ai-chat-tool-gradient{0%{background-position:200% 0}to{background-position:-200% 0}}@media (max-width:480px){.ai-chat-widget-container.is-open{height:100vh!important;inset:0!important;width:100vw!important}.ai-chat-widget-container.is-open .ai-chat-window{animation:none!important;border-radius:0!important;height:100%!important;inset:0!important;max-height:100%!important;max-width:100%!important;position:absolute!important;width:100%!important}.ai-chat-widget-container.is-open .ai-chat-button{display:none!important;visibility:hidden!important}.ai-chat-header{padding-top:max(16px,env(safe-area-inset-top))}.ai-chat-input-container{padding-bottom:max(20px,env(safe-area-inset-bottom))}}.ai-chat-window{animation:ai-chat-window-open var(--duration-slow,.35s) var(--spring-bounce);background:var(--bg-primary,#fff);border:1px solid var(--border-default,#d3d3d3);border-radius:var(--radius-window-top,22px) var(--radius-window-top,22px) var(--radius-window-bottom,44px) var(--radius-window-bottom,44px);box-shadow:var(--shadow-window,0 0 15px 5px rgba(0,0,0,.08));display:flex;flex-direction:column;overflow:hidden;position:absolute;transform-origin:bottom right;z-index:2}.ai-chat-widget.dark .ai-chat-window{background:var(--bg-primary,#282625);border-color:var(--border-default,#5d5b5b);border-width:.7px}.ai-chat-window.closing{animation:ai-chat-window-close var(--duration-normal) var(--spring-smooth) forwards}.ai-chat-window.size-small{height:500px;width:380px}.ai-chat-window.size-medium,.ai-chat-window.size-small{max-height:calc(100vh - 100px);max-width:calc(100vw - 40px)}.ai-chat-window.size-medium{height:600px;width:420px}.ai-chat-window.size-large{height:700px;max-height:calc(100vh - 100px);max-width:calc(100vw - 40px);width:480px}.ai-chat-widget-container.bottom-right .ai-chat-window{bottom:calc(var(--button-size, 56px) + 8px);right:0}.ai-chat-widget-container.bottom-left .ai-chat-window{bottom:calc(var(--button-size, 56px) + 8px);left:0}.ai-chat-widget-container.top-right .ai-chat-window{right:0;top:calc(var(--button-size, 56px) + 8px)}.ai-chat-widget-container.top-left .ai-chat-window{left:0;top:calc(var(--button-size, 56px) + 8px)}.ai-chat-header{align-items:center;background:var(--bg-primary,#fff);border-bottom:1px solid var(--border-default,#d3d3d3);border-radius:var(--radius-window-top,22px) var(--radius-window-top,22px) 0 0;display:flex;justify-content:space-between;padding:18px var(--space-md,16px);position:relative;z-index:10}.ai-chat-widget.dark .ai-chat-header{background:var(--bg-primary,#282625);border-bottom-color:var(--border-default,#5d5b5b);border-bottom-width:.7px}.ai-chat-header.is-history{padding-left:var(--space-md)}.ai-chat-header.is-history .ai-chat-title{flex:1;min-width:0;overflow:hidden;padding-right:var(--space-lg);text-overflow:ellipsis;white-space:nowrap}.ai-chat-header-content{align-items:center;display:flex;flex:1;gap:var(--space-lg)}.ai-chat-header-actions{align-items:center;display:flex;gap:var(--space-sm)}.ai-chat-logo{border-radius:10px;height:36px;object-fit:cover;width:36px}.ai-chat-title{color:var(--text-primary,#3e3e3e);font-size:var(--text-xl,22px);font-weight:var(--font-weight-bold,700);letter-spacing:-.02em}.ai-chat-widget.dark .ai-chat-title{color:var(--text-primary,#fff)}.ai-chat-close-button,.ai-chat-header-button{align-items:center;background:transparent;border:none;border-radius:var(--radius-md);color:var(--text-muted);cursor:pointer;display:flex;height:32px;justify-content:center;padding:0;transition:color var(--duration-fast) ease;width:32px}.ai-chat-close-button:hover,.ai-chat-header-button:hover{color:var(--text-primary)}.ai-chat-close-button:active,.ai-chat-header-button:active{transform:scale(.95)}.ai-chat-close-button svg,.ai-chat-header-button svg{height:22px;width:22px}.ai-chat-button{align-items:center;background:var(--button-color,var(--btn-primary-bg));border:1px solid var(--border-default,#d3d3d3);border-radius:50%;box-shadow:var(--shadow-button,0 0 15px 9px rgba(0,0,0,.03));color:var(--button-icon-color,var(--btn-primary-text));cursor:pointer;display:flex;height:var(--button-size,56px);justify-content:center;overflow:hidden;position:relative;transition:opacity var(--duration-fast) ease;width:var(--button-size,56px);z-index:1}.ai-chat-button:hover{opacity:.9}.ai-chat-button:active{opacity:.8}.ai-chat-button-svg{height:50%;min-height:24px;min-width:24px;transition:transform var(--duration-fast) ease;width:50%}.ai-chat-button.is-open .ai-chat-button-svg{transform:rotate(0deg)}.ai-chat-button-icon{font-size:1.5em;line-height:1}.ai-chat-input-container{background:linear-gradient(to bottom,transparent 0,var(--bg-primary,#fff) 50%,var(--bg-primary,#fff) 100%);bottom:0;left:0;padding-top:30px;position:absolute;right:0;z-index:10}.ai-chat-widget.dark .ai-chat-input-container{background:linear-gradient(to bottom,transparent 0,var(--bg-primary,#282625) 50%,var(--bg-primary,#282625) 100%)}.ai-chat-input-container.separate{padding:0 var(--radius-window-gutter,16px) var(--radius-window-gutter,16px);padding-top:30px}.ai-chat-input-wrapper{align-items:flex-end;background:var(--input-bg,#f4f4f4);border:1px solid var(--input-border,#d3d3d3);border-radius:var(--radius-input,62px);box-sizing:border-box;display:flex;gap:0;height:52px;overflow:hidden;padding:6px 6px 6px 16px;position:relative;transition:all var(--duration-fast,.15s) ease;z-index:5}.ai-chat-input-wrapper.multiline{border-radius:14px!important;min-height:64px;padding:10px 10px 10px 14px}.ai-chat-widget.dark .ai-chat-input-wrapper{background:var(--input-bg,#4a4846);border-color:var(--input-border,#5d5b5b);border-width:.7px;box-shadow:var(--shadow-input,0 0 10px rgba(0,0,0,.15))}.ai-chat-input-wrapper:focus-within{border-color:var(--text-muted,#a1a1aa)}.ai-chat-input{word-wrap:break-word!important;background:transparent!important;border:none!important;border-radius:0!important;box-shadow:none!important;box-sizing:border-box!important;color:var(--input-text,#000)!important;flex:1!important;font-family:inherit!important;font-size:var(--text-md,15px)!important;height:40px!important;line-height:20px!important;margin:0!important;max-height:40px!important;min-height:40px!important;min-width:0!important;outline:none!important;overflow-wrap:anywhere!important;overflow-x:hidden!important;overflow-y:auto!important;padding:10px var(--space-sm,8px)!important;resize:none!important;white-space:pre-wrap!important;width:0!important;word-break:break-word!important}.ai-chat-widget.dark .ai-chat-input{color:var(--input-text,#fff)}.ai-chat-input::placeholder{color:var(--text-placeholder,#a1a1aa)}.ai-chat-widget.dark .ai-chat-input::placeholder{color:var(--text-placeholder,#52525b)}.ai-chat-file-button{align-items:center;align-self:center;background:transparent;border:none;color:var(--text-placeholder);cursor:pointer;display:flex;flex-shrink:0;height:28px;justify-content:center;padding:0;transition:color var(--duration-fast) ease;width:28px}.ai-chat-file-button:hover{color:var(--text-secondary)}.ai-chat-file-button:disabled{cursor:not-allowed;opacity:.5}.ai-chat-send-button{align-items:center;align-self:center;background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#151515))));border:none;border-radius:50%;color:var(--button-icon-color,var(--btn-primary-text,#f4f4f4));cursor:pointer;display:flex;flex-shrink:0;height:40px;justify-content:center;min-height:40px;min-width:40px;padding:0;transition:all var(--duration-fast,.15s) ease;width:40px}.ai-chat-widget.dark .ai-chat-send-button{background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#fff))));color:var(--button-icon-color,var(--btn-primary-text,#312f2d))}.ai-chat-send-button.active{background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#151515))));color:var(--button-icon-color,var(--btn-primary-text,#f4f4f4))}.ai-chat-widget.dark .ai-chat-send-button.active{background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#fff))));color:var(--button-icon-color,var(--btn-primary-text,#312f2d))}.ai-chat-send-button:hover:not(:disabled){opacity:.8}.ai-chat-send-button:active:not(:disabled){transform:scale(.95)}.ai-chat-send-button:disabled{cursor:not-allowed;opacity:.3}.ai-chat-file-list{display:flex;flex-wrap:wrap;gap:var(--space-sm);padding:var(--space-sm) var(--space-sm)}.ai-chat-file-item{align-items:center;background:rgba(0,0,0,.05);border-radius:6px;display:flex;font-size:var(--text-xs);gap:var(--space-sm);padding:6px 10px}.ai-chat-file-extension{background:var(--btn-primary-bg);border-radius:3px;color:var(--btn-primary-text);display:inline-block;font-size:10px;font-weight:var(--font-weight-semibold);min-width:40px;padding:2px 6px;text-align:center;text-transform:uppercase}.ai-chat-file-info{display:flex;flex:1;flex-direction:column;gap:2px;min-width:0}.ai-chat-file-name{font-weight:var(--font-weight-medium);max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-file-size{color:var(--text-muted);font-size:10px;opacity:.7}.ai-chat-file-remove{align-items:center;background:none;border:none;color:inherit;cursor:pointer;display:flex;justify-content:center;opacity:.5;padding:var(--space-xs);transition:opacity var(--duration-fast) ease}.ai-chat-file-remove:hover{opacity:1}.ai-chat-messages{-webkit-overflow-scrolling:touch;-ms-overflow-style:none;align-items:stretch;background:var(--bg-primary,#fff);display:flex;flex:1;flex-direction:column;gap:var(--space-md,16px);justify-content:flex-start;overflow-x:hidden;overflow-y:auto;padding:var(--space-lg,24px) var(--space-md,16px) 100px;position:relative;scroll-behavior:smooth;scrollbar-width:none}.ai-chat-widget.dark .ai-chat-messages{background:var(--bg-primary,#18181b)}.ai-chat-messages::-webkit-scrollbar{display:none}.ai-chat-message{animation:ai-chat-message-slide-in .2s var(--spring-bounce);display:flex;flex-direction:column;max-width:90%}.ai-chat-message.user{align-items:flex-end;align-self:flex-end}.ai-chat-message.assistant{align-items:flex-start;align-self:flex-start;max-width:100%}.ai-chat-message.tool{align-self:flex-start;margin:0 -16px;max-width:100%;padding:0;width:calc(100% + 32px)}.ai-chat-message-content{word-wrap:break-word;border-radius:18px;font-size:var(--text-md,15px);line-height:var(--line-height-relaxed,1.6);overflow-wrap:break-word;padding:8px 14px}.ai-chat-message.user .ai-chat-message-content{background:var(--user-bg,#f4f3f0);border-radius:18px;color:var(--user-text,#000)}.ai-chat-widget.dark .ai-chat-message.user .ai-chat-message-content{background:var(--user-bg,#484848);color:var(--user-text,#fff)}.ai-chat-message.assistant .ai-chat-message-content{background:var(--agent-bg,transparent);color:var(--agent-text,#000);padding:0}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content{color:var(--agent-text,#fff)}.ai-chat-message-timestamp{color:var(--text-muted,#71717a);font-size:var(--text-xs,12px);margin-top:var(--space-xs,4px);padding:0 var(--space-xs,4px)}.ai-chat-welcome{animation:ai-chat-welcome-fade-in .3s var(--spring-smooth);display:flex;flex-direction:column;gap:var(--space-md,16px);padding:var(--space-lg,24px) 0}.ai-chat-welcome-title{color:var(--text-primary,#3e3e3e);font-size:var(--text-2xl,28px);font-weight:var(--font-weight-bold,700);line-height:var(--line-height-tight,1.3)}.ai-chat-widget.dark .ai-chat-welcome-title{color:var(--text-primary,#fff)}.ai-chat-welcome-text{color:var(--text-secondary,#000);font-size:var(--text-md,15px);line-height:var(--line-height-relaxed,1.6);max-width:100%}.ai-chat-widget.dark .ai-chat-welcome-text{color:var(--text-secondary,#fff)}.ai-chat-typing{align-items:center;display:flex;gap:var(--space-xs,4px);padding:var(--space-sm,8px) var(--space-md,16px)}.ai-chat-typing-dot{animation:ai-chat-typing-bounce 1.4s ease-in-out infinite both;background:var(--text-muted,#71717a);border-radius:50%;height:8px;width:8px}.ai-chat-typing-dot:first-child{animation-delay:-.32s}.ai-chat-typing-dot:nth-child(2){animation-delay:-.16s}.ai-chat-typing-dot:nth-child(3){animation-delay:0s}@keyframes ai-chat-typing-bounce{0%,80%,to{opacity:.4;transform:scale(.6)}40%{opacity:1;transform:scale(1)}}.ai-chat-scroll-button{align-items:center;background:var(--bg-secondary,#f4f4f5);border:1px solid var(--border-subtle,rgba(0,0,0,.1));border-radius:50%;bottom:80px;box-shadow:0 2px 8px rgba(0,0,0,.1);color:var(--text-secondary,#71717a);cursor:pointer;display:flex;height:36px;justify-content:center;left:50%;opacity:0;pointer-events:none;position:absolute;transform:translateX(-50%);transition:background .15s ease,box-shadow .15s ease,opacity .15s ease,visibility .15s ease;visibility:hidden;width:36px;z-index:15}.ai-chat-scroll-button.visible{opacity:1;pointer-events:auto;visibility:visible}.ai-chat-scroll-button:hover{background:var(--bg-tertiary,#e4e4e7);box-shadow:0 4px 12px rgba(0,0,0,.15)}.ai-chat-scroll-button:active{background:var(--bg-tertiary,#d4d4d8)}.ai-chat-widget.dark .ai-chat-scroll-button{background:var(--bg-secondary,#3f3f46);border-color:var(--border-subtle,hsla(0,0%,100%,.1));box-shadow:0 2px 8px rgba(0,0,0,.3);color:var(--text-secondary,#a1a1aa)}.ai-chat-widget.dark .ai-chat-scroll-button:hover{background:var(--bg-tertiary,#52525b);box-shadow:0 4px 12px rgba(0,0,0,.4)}.ai-chat-error{background:var(--bg-secondary);border-radius:var(--radius-chat-bubble);color:var(--text-primary);font-size:var(--text-md);margin:0 auto;padding:10px var(--space-md)}.ai-chat-message.assistant .ai-chat-message-content p{margin:0 0 var(--space-sm) 0}.ai-chat-message.assistant .ai-chat-message-content p:last-child{margin-bottom:0}.ai-chat-message.assistant .ai-chat-message-content ol,.ai-chat-message.assistant .ai-chat-message-content ul{margin:var(--space-sm) 0;padding-left:var(--space-lg)}.ai-chat-message.assistant .ai-chat-message-content li{margin-bottom:var(--space-xs)}.ai-chat-message.assistant .ai-chat-message-content code{background:rgba(0,0,0,.05);border-radius:var(--radius-sm);font-family:SF Mono,Monaco,Cascadia Code,monospace;font-size:.9em;padding:2px 6px}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content code{background:hsla(0,0%,100%,.1)}.ai-chat-message.assistant .ai-chat-message-content pre{background:rgba(0,0,0,.05);border-radius:var(--radius-md);margin:var(--space-sm) 0;overflow-x:auto;padding:var(--space-sm)}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content pre{background:hsla(0,0%,100%,.05)}.ai-chat-message.assistant .ai-chat-message-content pre code{background:transparent;padding:0}.ai-chat-message.assistant .ai-chat-message-content a{color:var(--btn-primary-bg);text-decoration:underline}.ai-chat-message.assistant .ai-chat-message-content strong{font-weight:var(--font-weight-semibold)}.ai-chat-message.assistant .ai-chat-message-content blockquote{border-left:3px solid var(--border-default);color:var(--text-muted);margin:var(--space-sm) 0;padding-left:var(--space-md)}.ai-chat-message.assistant .ai-chat-message-content hr{border:none;border-top:1px solid var(--border-subtle,rgba(0,0,0,.1));margin:var(--space-lg,24px) 0}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content hr{border-top-color:var(--border-subtle,hsla(0,0%,100%,.1))}.ai-chat-message.assistant .ai-chat-message-content table{border-collapse:collapse;font-size:var(--text-sm);margin:var(--space-sm) 0;width:100%}.ai-chat-message.assistant .ai-chat-message-content td,.ai-chat-message.assistant .ai-chat-message-content th{border:1px solid var(--border-subtle);padding:var(--space-sm);text-align:left}.ai-chat-message.assistant .ai-chat-message-content th{font-weight:var(--font-weight-semibold);white-space:nowrap}.ai-chat-message.assistant .ai-chat-message-content tbody tr:nth-child(2n){background:rgba(0,0,0,.02)}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content tbody tr:nth-child(2n){background:hsla(0,0%,100%,.03)}.ai-chat-suggested-questions{align-self:flex-end;margin:0;padding:16px 0 0;width:100%}.ai-chat-suggested-questions-list{align-items:center;display:flex;flex-wrap:wrap;gap:6px;justify-content:flex-end}.ai-chat-suggested-question{align-items:center;background:transparent;border:1px solid var(--border-default,#d4d4d8);border-radius:var(--radius-preset-badge,18px);color:var(--text-primary,#18181b);cursor:pointer;display:inline-flex;font-size:14px;font-weight:400;gap:6px;justify-content:center;line-height:1.3;max-width:100%;overflow:hidden;padding:8px 14px;text-overflow:ellipsis;transition:background .15s ease,border-color .15s ease,transform .1s ease;white-space:nowrap}.ai-chat-widget.dark .ai-chat-suggested-question{background:transparent;border-color:var(--border-subtle,#52525b);color:var(--text-primary,#fafafa)}.ai-chat-suggested-question-text{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-suggested-question:hover{background:var(--bg-hover,#f4f4f5);border-color:var(--border-default,#d4d4d8)}.ai-chat-widget.dark .ai-chat-suggested-question:hover{background:var(--bg-hover,#3f3f46);border-color:var(--border-subtle,#52525b)}.ai-chat-suggested-question:active{transform:scale(.98)}.ai-chat-suggested-question.action-type{border:none}.ai-chat-suggested-question.action-type,.ai-chat-widget.dark .ai-chat-suggested-question.action-type{background:var(--primary-color,var(--button-color,#ef4444));color:var(--button-icon-color,#fff)}.ai-chat-suggested-question.action-type:hover{background:var(--primary-color,var(--button-color,#ef4444));opacity:.9}.ai-chat-suggested-question-icon{align-items:center;display:flex;flex-shrink:0;justify-content:center}.ai-chat-suggested-question:not(.action-type) .ai-chat-suggested-question-icon{display:none}.ai-chat-follow-up-suggestions{box-sizing:border-box;margin:0;padding:8px 16px 0;width:100%}.ai-chat-follow-up-list{align-items:flex-end;display:flex;flex-direction:column;gap:6px}.ai-chat-follow-up-item{align-items:center;border:none;border-radius:var(--radius-preset-badge,18px);cursor:pointer;display:inline-flex;font-size:14px;font-weight:400;gap:6px;justify-content:center;line-height:1.3;max-width:100%;overflow:hidden;padding:8px 14px;text-overflow:ellipsis;transition:opacity .15s ease,transform .1s ease;white-space:nowrap}.ai-chat-follow-up-item,.ai-chat-widget.dark .ai-chat-follow-up-item{background:var(--primary-color,var(--button-color,#07f));color:var(--button-icon-color,#fff)}.ai-chat-follow-up-item:hover{opacity:.9}.ai-chat-follow-up-item:active{transform:scale(.98)}.ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-default,#d4d4d8);color:var(--text-primary,#18181b)}.ai-chat-widget.dark .ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-subtle,#52525b);color:var(--text-primary,#fafafa)}.ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#f4f4f5);opacity:1}.ai-chat-widget.dark .ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#3f3f46);opacity:1}.ai-chat-follow-up-item.action-type{background:var(--primary-color,var(--button-color,#07f));border:none;color:var(--button-icon-color,#fff)}.ai-chat-follow-up-icon{align-items:center;display:flex;flex-shrink:0;justify-content:center}.ai-chat-follow-up-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-feedback-buttons{align-items:center;display:flex;gap:var(--space-xs)}.ai-chat-feedback{align-items:center;display:inline-flex;gap:0;height:20px}.ai-chat-feedback-button{align-items:center;background:transparent!important;border:none;border-radius:var(--radius-sm);color:var(--text-placeholder);cursor:pointer;display:flex;font-size:var(--text-sm);height:20px;justify-content:center;padding:var(--space-xs);transition:all var(--duration-fast) var(--spring-bounce)}.ai-chat-feedback-button:hover:not(:disabled){background:none!important;color:var(--text-secondary)}.ai-chat-feedback-button:active:not(:disabled){transform:scale(.9)}.ai-chat-feedback-button:disabled{cursor:not-allowed;opacity:.4}.ai-chat-feedback-button.active{background:none!important;color:var(--text-primary)}.ai-chat-feedback.submitted{align-items:center;animation:ai-chat-feedback-morph .3s var(--spring-bounce);gap:var(--space-xs)}.ai-chat-feedback-message{align-items:center;display:flex;gap:4px;margin-left:var(--space-xxs)}.ai-chat-feedback-checkmark{animation:ai-chat-checkmark-pop .3s var(--spring-bounce);color:#10b981;font-size:var(--text-md);font-weight:700}.ai-chat-feedback-text{color:#10b981;font-size:var(--text-xs);font-weight:var(--font-weight-medium)}.ai-chat-history-panel{background:var(--bg-primary,#fff);display:flex;flex:1;flex-direction:column;overflow:hidden}.ai-chat-widget.dark .ai-chat-history-panel{background:var(--bg-primary,#18181b)}.ai-chat-history-empty,.ai-chat-history-loading{align-items:center;color:var(--text-muted);display:flex;flex:1;font-size:var(--text-sm);justify-content:center;padding:var(--space-lg);text-align:center}.ai-chat-history-list{-ms-overflow-style:none;display:flex;flex:1;flex-direction:column;gap:var(--space-sm);overflow-y:auto;padding:var(--space-md) var(--space-md) 120px;scrollbar-width:none}.ai-chat-history-list::-webkit-scrollbar{display:none}.ai-chat-history-list.exiting{animation:ai-chat-history-exit .22s var(--spring-smooth) forwards}.ai-chat-history-item{align-items:center;background:var(--user-bg,#f4f4f5);border-radius:var(--radius-history-item,15px);display:flex;flex:0 0 auto;flex-direction:row;height:var(--history-item-height,44px);margin:0;overflow:hidden;transition:background var(--duration-fast,.15s) ease;width:100%}.ai-chat-history-item-content{align-items:center;background:transparent;border:none;cursor:pointer;display:flex;flex:1;flex-direction:row;height:100%;min-width:0;padding:0 var(--space-xs,16px);text-align:left}.ai-chat-widget.dark .ai-chat-history-item{background:var(--user-bg,#27272a)}.ai-chat-history-item:hover{background:var(--user-bg-hover,#e5e7eb)}.ai-chat-widget.dark .ai-chat-history-item:hover{background:var(--user-bg-hover,#3f3f46)}.ai-chat-history-item.active{background:var(--user-bg-hover,#e5e7eb)}.ai-chat-widget.dark .ai-chat-history-item.active{background:var(--user-bg-hover,#3f3f46)}.ai-chat-history-item-preview{color:var(--text-primary,#18181b);flex:1;font-size:var(--text-sm,14px);font-weight:var(--font-weight-medium,500);line-height:var(--line-height-normal,1.4);margin-bottom:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-widget.dark .ai-chat-history-item-preview{color:var(--text-primary,#fafafa)}.ai-chat-history-item.active .ai-chat-history-item-preview{font-weight:var(--font-weight-medium)}.ai-chat-history-item-meta{display:none}.ai-chat-history-item-delete{align-items:center;background:transparent;border:none;border-radius:var(--radius-sm,8px);color:var(--text-muted,#71717a);cursor:pointer;display:flex;flex-shrink:0;height:32px;justify-content:center;margin-left:auto;margin-right:var(--space-2xs,2px);opacity:0;transition:opacity var(--duration-fast,.15s) ease,background var(--duration-fast,.15s) ease,color var(--duration-fast,.15s) ease;width:32px}.ai-chat-history-item:hover .ai-chat-history-item-delete{opacity:1}.ai-chat-history-item-delete:hover{background:rgba(239,68,68,.1);color:#ef4444}.ai-chat-widget.dark .ai-chat-history-item-delete:hover{background:rgba(239,68,68,.2);color:#f87171}.ai-chat-tool-row{align-items:center;display:flex;gap:10px;margin:2px 0;padding:0 16px}.ai-chat-tool-gear{color:#1f2937;flex-shrink:0;height:20px;width:20px}.ai-chat-tool-gear.spinning{animation:ai-chat-gear-spin 1.5s linear infinite}.ai-chat-tool-badges{align-items:center;display:flex;flex-wrap:wrap;gap:8px}.ai-chat-tool-badge{align-items:center;background:#e5e7eb;border:1px solid #d1d5db;border-radius:var(--radius-action-badge,8px);color:#1f2937;display:inline-flex;font-size:12px;font-weight:500;gap:4px;line-height:1.2;padding:5px 12px;transition:all .2s ease;white-space:nowrap}.ai-chat-tool-badge.loading{animation:ai-chat-tool-gradient 2s linear infinite;background:linear-gradient(90deg,var(--tool-loading-bg-1,#e0e0e0) 0,var(--tool-loading-bg-2,#f0f0f0) 25%,var(--tool-loading-bg-3,#fff) 50%,var(--tool-loading-bg-2,#f0f0f0) 75%,var(--tool-loading-bg-1,#e0e0e0) 100%);background-size:200% 100%;color:var(--tool-loading-text,#1a1a1a);position:relative}.ai-chat-widget:not(.dark) .ai-chat-tool-badge.loading{--tool-loading-bg-1:#2a2a2a;--tool-loading-bg-2:#3a3a3a;--tool-loading-bg-3:#4a4a4a;--tool-loading-text:#fff}.ai-chat-tool-badge.completed{background:#e5e7eb;border:1px solid #d1d5db;color:#1f2937}.ai-chat-widget.dark .ai-chat-tool-badge,.ai-chat-widget[data-theme=dark] .ai-chat-tool-badge,.chakra-ui-dark .ai-chat-tool-badge,.dark .ai-chat-tool-badge,[data-theme=dark] .ai-chat-tool-badge,html.dark .ai-chat-tool-badge{background:hsla(0,0%,100%,.12);border:1px solid hsla(0,0%,100%,.2);color:hsla(0,0%,100%,.9)}.ai-chat-widget.dark .ai-chat-tool-gear,.ai-chat-widget[data-theme=dark] .ai-chat-tool-gear,.chakra-ui-dark .ai-chat-tool-gear,.dark .ai-chat-tool-gear,[data-theme=dark] .ai-chat-tool-gear,html.dark .ai-chat-tool-gear{color:#fff}.ai-chat-tool-badge.error{background:var(--tool-error-bg,rgba(239,68,68,.15));color:var(--tool-error-text,#ef4444)}.ai-chat-tool-badge .ai-chat-tool-check{color:#22c55e;flex-shrink:0}.ai-chat-tool-badge .ai-chat-tool-error{color:#ef4444;flex-shrink:0}.tool-name{font-weight:500;line-height:1.2;white-space:nowrap}.ai-chat-tool-action{box-sizing:border-box;padding:0 16px;width:100%}.ai-chat-sources{background:rgba(0,0,0,.02);border-radius:6px;font-size:var(--text-xs);margin-top:var(--space-sm);overflow:hidden}.ai-chat-sources-toggle{align-items:center;background:none;border:none;cursor:pointer;display:flex;gap:6px;padding:var(--space-sm) 10px;text-align:left;transition:background var(--duration-fast) ease;width:100%}.ai-chat-sources-toggle:hover{background:rgba(0,0,0,.03)}.ai-chat-sources-icon{color:var(--text-muted);font-size:10px;transition:transform var(--duration-fast) ease}.ai-chat-sources-title{color:var(--text-primary);flex:1;font-size:11px;font-weight:var(--font-weight-semibold);letter-spacing:.5px;text-transform:uppercase}.ai-chat-source-item{border-top:1px solid rgba(0,0,0,.05);color:var(--text-muted);display:flex;gap:var(--space-sm);padding:var(--space-sm) 10px}.ai-chat-source-item:last-child{border-bottom:none}.ai-chat-source-number{color:var(--btn-primary-bg);flex-shrink:0;font-weight:var(--font-weight-semibold)}.ai-chat-source-details{display:flex;flex:1;flex-direction:column;gap:var(--space-xs)}.ai-chat-source-score{color:var(--text-placeholder);font-size:11px}.ai-chat-source-content{color:var(--text-muted);font-size:11px;font-style:italic;line-height:var(--line-height-normal)}.ai-chat-source-metadata{display:flex;flex-wrap:wrap;gap:6px;margin-top:2px}.ai-chat-source-meta-item{background:rgba(0,0,0,.05);border-radius:3px;color:var(--text-muted);font-size:10px;padding:2px 6px}";
30412
+ var css_248z$1 = ".ai-chat-message{animation:ai-chat-message-appear .2s var(--chat-ease-bounce);max-width:85%}.ai-chat-message-content{border-radius:var(--chat-radius-bubble,14px);font-size:var(--chat-text-md,15px);line-height:var(--chat-line-relaxed,1.6);padding:var(--chat-space-sm,8px) var(--chat-space-md,16px)}.ai-chat-message.user .ai-chat-message-content{background:var(--chat-user-bg,#f4f3f0);border-bottom-right-radius:var(--chat-radius-sm,4px);color:var(--chat-user-text,#000)}.ai-chat-message.assistant .ai-chat-message-content{background:var(--chat-assistant-bg,transparent);color:var(--chat-assistant-text,#000)}.ai-chat-message-timestamp{color:var(--chat-text-muted,#71717a);font-size:var(--chat-text-xs,12px);margin-top:var(--chat-space-xs,4px);padding:0 var(--chat-space-xs,4px)}.ai-chat-message.streaming .ai-chat-message-content:after{animation:ai-chat-cursor-blink .8s infinite;content:\"▋\";margin-left:2px;opacity:.7}@keyframes ai-chat-message-appear{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}@keyframes ai-chat-cursor-blink{0%,50%{opacity:1}51%,to{opacity:0}}.ai-chat-message.fullpage .ai-chat-message-content{font-size:var(--chat-text-lg,18px);padding:var(--chat-space-md,16px) var(--chat-space-lg,24px)}.ai-chat-typing{gap:var(--chat-space-xs,4px);padding:var(--chat-space-sm,8px) var(--chat-space-md,16px)}.ai-chat-typing-dot{background:var(--chat-text-muted,#71717a)}.ai-chat-tool-row{padding:0 16px}.ai-chat-tool-gear{color:var(--text-primary,#3e3e3e)}.ai-chat-tool-badge{border-radius:8px}.ai-chat-tool-badge.loading{background:#e5e7eb;border:1px solid #d1d5db;color:#1f2937}.ai-chat-tool-badge.error{background:rgba(239,68,68,.1);color:#ef4444}.ai-chat-tool-check{color:#22c55e;flex-shrink:0}.ai-chat-tool-error{color:#ef4444;flex-shrink:0}.ai-chat-tool-badge .tool-name{max-width:150px;overflow:hidden;text-overflow:ellipsis}.ai-chat-widget.dark .ai-chat-tool-gear,.ai-chat-widget[data-theme=dark] .ai-chat-tool-gear,.dark .ai-chat-tool-gear,[data-theme=dark] .ai-chat-tool-gear{color:#fff}.ai-chat-widget.dark .ai-chat-tool-badge,.ai-chat-widget[data-theme=dark] .ai-chat-tool-badge,.dark .ai-chat-tool-badge,[data-theme=dark] .ai-chat-tool-badge{background:hsla(0,0%,100%,.12);border:1px solid hsla(0,0%,100%,.2);color:hsla(0,0%,100%,.9)}.ai-chat-widget.dark .ai-chat-tool-badge.error,.ai-chat-widget[data-theme=dark] .ai-chat-tool-badge.error,.dark .ai-chat-tool-badge.error,[data-theme=dark] .ai-chat-tool-badge.error{background:rgba(239,68,68,.2);color:#f87171}.chakra-ui-dark .ai-chat-tool-gear,html.dark .ai-chat-tool-gear{color:#fff}.chakra-ui-dark .ai-chat-tool-badge,html.dark .ai-chat-tool-badge{background:hsla(0,0%,100%,.12);border:1px solid hsla(0,0%,100%,.2);color:hsla(0,0%,100%,.9)}.chakra-ui-dark .ai-chat-tool-badge.error,html.dark .ai-chat-tool-badge.error{background:rgba(239,68,68,.2);color:#f87171}.ai-chat-pin-input-group{align-items:center;display:flex;flex-wrap:nowrap;gap:8px;justify-content:center;margin:4px 0 8px}.ai-chat-pin-input{align-items:center;appearance:none;background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);box-sizing:border-box;color:var(--text-primary,#3e3e3e);display:inline-flex;flex:0 0 42px;font-family:inherit;font-size:18px;font-weight:600;height:46px;justify-content:center;line-height:1;max-width:42px;min-width:42px;outline:none;padding:0;text-align:center;transition:border-color .2s ease,box-shadow .2s ease;width:42px}.ai-chat-pin-input:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.1)}.ai-chat-pin-input:disabled{cursor:not-allowed;opacity:.6}.ai-chat-widget.dark .ai-chat-pin-input,.chakra-ui-dark .ai-chat-pin-input,.dark .ai-chat-pin-input,[data-theme=dark] .ai-chat-pin-input{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-pin-input:focus,.chakra-ui-dark .ai-chat-pin-input:focus,.dark .ai-chat-pin-input:focus,[data-theme=dark] .ai-chat-pin-input:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.2)}.ai-chat-action-button-secondary{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:9999px;color:var(--text-secondary,#6b7280);cursor:pointer;font-size:var(--text-sm,13px);font-weight:var(--font-weight-medium,500);padding:10px 16px;transition:all .2s ease;width:100%}.ai-chat-action-button-secondary:hover:not(:disabled){background:rgba(59,130,246,.05);border-color:var(--action-accent,var(--primary-color,#3b82f6));color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-action-button-secondary:disabled{cursor:not-allowed;opacity:.5}.ai-chat-widget.dark .ai-chat-action-button-secondary,.chakra-ui-dark .ai-chat-action-button-secondary,.dark .ai-chat-action-button-secondary,[data-theme=dark] .ai-chat-action-button-secondary{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#e5e7eb}.ai-chat-widget.dark .ai-chat-action-button-secondary:hover:not(:disabled),.chakra-ui-dark .ai-chat-action-button-secondary:hover:not(:disabled),.dark .ai-chat-action-button-secondary:hover:not(:disabled),[data-theme=dark] .ai-chat-action-button-secondary:hover:not(:disabled){background:rgba(59,130,246,.2);border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-action-appointment-list,.ai-chat-action-button-group{display:flex;flex-direction:column;gap:8px}.ai-chat-action-appointment-item{align-items:center;background:var(--bg-primary,#fff);border:1px solid var(--border-subtle,rgba(0,0,0,.08));border-radius:var(--radius-md,8px);display:flex;gap:12px;justify-content:space-between;padding:10px 12px}.ai-chat-widget.dark .ai-chat-action-appointment-item,.chakra-ui-dark .ai-chat-action-appointment-item,.dark .ai-chat-action-appointment-item,[data-theme=dark] .ai-chat-action-appointment-item{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.08)}.ai-chat-action-appointment-info{display:flex;flex-direction:column;gap:2px;min-width:0}.ai-chat-action-appointment-subject{color:var(--text-primary,#3e3e3e);font-size:14px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-widget.dark .ai-chat-action-appointment-subject,.chakra-ui-dark .ai-chat-action-appointment-subject,.dark .ai-chat-action-appointment-subject,[data-theme=dark] .ai-chat-action-appointment-subject{color:#fff}.ai-chat-action-appointment-time{color:var(--text-muted,#71717a);font-size:12px}.ai-chat-action-appointment-item .ai-chat-action-button-secondary{font-size:12px;padding:6px 12px;width:auto}.ai-chat-action-error-message{background:rgba(239,68,68,.1);border-radius:var(--radius-md,8px);color:#dc2626;font-size:var(--text-sm,13px);padding:12px}.ai-chat-widget.dark .ai-chat-action-error-message,.chakra-ui-dark .ai-chat-action-error-message,.dark .ai-chat-action-error-message,[data-theme=dark] .ai-chat-action-error-message{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-widget,.chat-ui{--radius-sm:4px;--radius-md:8px;--radius-lg:12px;--radius-xl:16px;--radius-2xl:18px;--radius-pill:9999px;--radius-window-top:22px;--radius-window-bottom:44px;--radius-window-gutter:16px;--radius-chat-bubble:14px;--radius-preset-badge:13px;--radius-history-item:14px;--radius-action-badge:8px;--radius-input:62px;--space-xs:4px;--space-sm:8px;--space-md:16px;--space-lg:24px;--space-xl:32px;--text-xs:12px;--text-sm:14px;--text-md:15px;--text-lg:18px;--text-xl:22px;--text-2xl:28px;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--line-height-tight:1.3;--line-height-normal:1.4;--line-height-relaxed:1.6;--bg-primary:#fff;--bg-secondary:#f4f4f4;--bg-tertiary:#e5e7eb;--bg-hover:#e5e7eb;--text-primary:#3e3e3e;--text-secondary:#000;--text-muted:#71717a;--text-placeholder:#a1a1aa;--border-default:#d3d3d3;--border-subtle:#e5e7eb;--border-muted:#f4f4f5;--user-bg:#f4f3f0;--user-text:#000;--user-bg-hover:#e8e7e4;--agent-bg:transparent;--agent-text:#000;--input-bg:#f4f4f4;--input-border:#d3d3d3;--input-text:#000;--btn-primary-bg:#151515;--btn-primary-text:#f4f4f4;--btn-secondary-bg:transparent;--btn-secondary-text:#71717a;--spring-bounce:cubic-bezier(0.34,1.56,0.64,1);--spring-smooth:cubic-bezier(0.4,0,0.2,1);--spring-snappy:cubic-bezier(0.2,0,0,1);--duration-fast:0.15s;--duration-normal:0.25s;--duration-slow:0.35s;--shadow-sm:0 1px 2px rgba(0,0,0,.05);--shadow-md:0 2px 8px rgba(0,0,0,.1);--shadow-lg:0 4px 16px rgba(0,0,0,.12);--shadow-window:0px 0px 15px 9px rgba(0,0,0,.1);--shadow-button:0px 0px 15px 9px rgba(0,0,0,.03)}.ai-chat-widget.dark,.chat-ui.dark{--bg-primary:#282625;--bg-secondary:#4a4846;--bg-tertiary:#484848;--bg-hover:#484848;--text-primary:#fff;--text-secondary:#fff;--text-muted:#a1a1aa;--text-placeholder:#71717a;--border-default:#5d5b5b;--border-subtle:#5d5b5b;--border-muted:#5d5b5b;--user-bg:#484848;--user-text:#fff;--user-bg-hover:#5a5a5a;--agent-bg:transparent;--agent-text:#fff;--input-bg:#4a4846;--input-border:#5d5b5b;--input-text:#fff;--btn-primary-bg:#fff;--btn-primary-text:#312f2d;--btn-secondary-bg:transparent;--btn-secondary-text:#a1a1aa;--shadow-window:0px 0px 15px 9px rgba(0,0,0,.2);--shadow-button:0px 0px 15px 9px rgba(0,0,0,.03);--shadow-input:0px 0px 10px rgba(0,0,0,.15)}.ai-chat-widget,.chat-ui{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}.ai-chat-widget-container{font-size:var(--text-sm);line-height:1.5;position:fixed;z-index:var(--widget-z-index,2147483647)}.ai-chat-widget-container.bottom-right{bottom:20px;right:20px}.ai-chat-widget-container.bottom-left{bottom:20px;left:20px}.ai-chat-widget-container.top-right{right:20px;top:20px}.ai-chat-widget-container.top-left{left:20px;top:20px}.ai-chat-widget-container.container-mode{position:absolute}@keyframes ai-chat-window-open{0%{opacity:0;transform:scale(.9) translateY(20px)}to{opacity:1;transform:scale(1) translateY(0)}}@keyframes ai-chat-window-close{0%{opacity:1;transform:scale(1) translateY(0)}to{opacity:0;transform:scale(.9) translateY(20px)}}@keyframes ai-chat-message-slide-in{0%{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}@keyframes ai-chat-welcome-fade-in{0%{opacity:0;transform:translateY(16px)}to{opacity:1;transform:translateY(0)}}@keyframes ai-chat-typing-pulse{0%,60%,to{opacity:.4;transform:translateY(0) scale(1)}30%{opacity:1;transform:translateY(-4px) scale(1.1)}}@keyframes ai-chat-gear-spin{to{transform:rotate(1turn)}}@keyframes ai-chat-tool-active{0%,to{background:var(--bg-secondary);opacity:1}50%{background:var(--bg-tertiary);opacity:1}}@keyframes ai-chat-feedback-morph{0%{opacity:.5;transform:scale(.8)}to{opacity:1;transform:scale(1)}}@keyframes ai-chat-checkmark-pop{0%{opacity:0;transform:scale(0) rotate(-45deg)}50%{transform:scale(1.3) rotate(0deg)}to{opacity:1;transform:scale(1) rotate(0deg)}}@keyframes ai-chat-history-exit{to{opacity:0;transform:translateY(-18px)}}@keyframes ai-chat-tool-gradient{0%{background-position:200% 0}to{background-position:-200% 0}}.ai-chat-window{animation:ai-chat-window-open var(--duration-slow,.35s) var(--spring-bounce);background:var(--bg-primary,#fff);border:1px solid var(--border-default,#d3d3d3);border-radius:var(--radius-window-top,22px) var(--radius-window-top,22px) var(--radius-window-bottom,44px) var(--radius-window-bottom,44px);box-shadow:var(--shadow-window,0 0 15px 5px rgba(0,0,0,.08));display:flex;flex-direction:column;overflow:hidden;position:absolute;transform-origin:bottom right;z-index:2}.ai-chat-widget.dark .ai-chat-window{background:var(--bg-primary,#282625);border-color:var(--border-default,#5d5b5b);border-width:.7px}.ai-chat-window.closing{animation:ai-chat-window-close var(--duration-normal) var(--spring-smooth) forwards}.ai-chat-window.size-small{height:500px;width:380px}.ai-chat-window.size-medium,.ai-chat-window.size-small{max-height:calc(100vh - 100px);max-width:calc(100vw - 40px)}.ai-chat-window.size-medium{height:600px;width:420px}.ai-chat-window.size-large{height:700px;max-height:calc(100vh - 100px);max-width:calc(100vw - 40px);width:480px}.ai-chat-widget-container.bottom-right .ai-chat-window{bottom:calc(var(--button-size, 56px) + 8px);right:0}.ai-chat-widget-container.bottom-left .ai-chat-window{bottom:calc(var(--button-size, 56px) + 8px);left:0}.ai-chat-widget-container.top-right .ai-chat-window{right:0;top:calc(var(--button-size, 56px) + 8px)}.ai-chat-widget-container.top-left .ai-chat-window{left:0;top:calc(var(--button-size, 56px) + 8px)}.ai-chat-header{align-items:center;background:var(--bg-primary,#fff);border-bottom:1px solid var(--border-default,#d3d3d3);border-radius:var(--radius-window-top,22px) var(--radius-window-top,22px) 0 0;display:flex;justify-content:space-between;padding:12px var(--space-md,16px);position:relative;z-index:10}.ai-chat-widget.dark .ai-chat-header{background:var(--bg-primary,#282625);border-bottom-color:var(--border-default,#5d5b5b);border-bottom-width:.7px}.ai-chat-header.is-history{padding-left:var(--space-md)}.ai-chat-header.is-history .ai-chat-title{flex:1;min-width:0;overflow:hidden;padding-right:var(--space-lg);text-overflow:ellipsis;white-space:nowrap}.ai-chat-header-content{align-items:center;display:flex;flex:1;gap:var(--space-lg)}.ai-chat-header-actions{align-items:center;display:flex;gap:var(--space-sm)}.ai-chat-logo{border-radius:10px;height:36px;object-fit:cover;width:36px}.ai-chat-title{color:var(--text-primary,#3e3e3e);font-size:var(--text-xl,22px);font-weight:var(--font-weight-bold,700);letter-spacing:-.02em}.ai-chat-widget.dark .ai-chat-title{color:var(--text-primary,#fff)}.ai-chat-close-button,.ai-chat-header-button{align-items:center;background:transparent;border:none;border-radius:var(--radius-md);color:var(--text-muted);cursor:pointer;display:flex;height:32px;justify-content:center;padding:0;transition:color var(--duration-fast) ease;width:32px}.ai-chat-close-button:hover,.ai-chat-header-button:hover{color:var(--text-primary)}.ai-chat-close-button:active,.ai-chat-header-button:active{transform:scale(.95)}.ai-chat-close-button svg,.ai-chat-header-button svg{height:22px;width:22px}.ai-chat-button{align-items:center;background:var(--button-color,var(--btn-primary-bg));border:1px solid var(--border-default,#d3d3d3);border-radius:50%;box-shadow:var(--shadow-button,0 0 15px 9px rgba(0,0,0,.03));color:var(--button-icon-color,var(--btn-primary-text));cursor:pointer;display:flex;height:var(--button-size,56px);justify-content:center;overflow:hidden;position:relative;transition:opacity var(--duration-fast) ease;width:var(--button-size,56px);z-index:1}.ai-chat-button:hover{opacity:.9}.ai-chat-button:active{opacity:.8}.ai-chat-button-svg{height:50%;min-height:24px;min-width:24px;transition:transform var(--duration-fast) ease;width:50%}.ai-chat-button.is-open .ai-chat-button-svg{transform:rotate(0deg)}.ai-chat-button-icon{font-size:1.5em;line-height:1}.ai-chat-welcome-bubble{animation:ai-chat-bubble-fade-in .3s ease-out;background:var(--button-color,var(--btn-primary-bg,#07f));border:none;border-radius:12px;box-shadow:0 4px 12px rgba(0,0,0,.15);color:var(--button-icon-color,var(--btn-primary-text,#fff));cursor:pointer;font-size:14px;font-weight:500;line-height:1.4;padding:12px 16px;position:absolute;width:200px;z-index:0}.ai-chat-widget-container.bottom-right .ai-chat-welcome-bubble{bottom:68px;right:0;text-align:right}.ai-chat-widget-container.bottom-left .ai-chat-welcome-bubble{bottom:68px;left:0;right:auto;text-align:left}.ai-chat-widget-container.top-right .ai-chat-welcome-bubble{right:0;text-align:right;top:68px}.ai-chat-widget-container.top-left .ai-chat-welcome-bubble{left:0;right:auto;text-align:left;top:68px}.ai-chat-welcome-bubble:hover{filter:brightness(1.1)}@keyframes ai-chat-bubble-fade-in{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.ai-chat-widget-container.top-left .ai-chat-welcome-bubble,.ai-chat-widget-container.top-right .ai-chat-welcome-bubble{animation-name:ai-chat-bubble-fade-in-down}@keyframes ai-chat-bubble-fade-in-down{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}.ai-chat-input-container{background:var(--bg-primary,#fff);bottom:0;left:0;padding:8px 0 16px;position:absolute;right:0;z-index:10}.ai-chat-widget.dark .ai-chat-input-container{background:var(--bg-primary,#282625)}.ai-chat-input-container.separate{padding:0 var(--radius-window-gutter,16px) var(--radius-window-gutter,16px)}.ai-chat-input-wrapper{align-items:flex-end;background:var(--input-bg,#f4f4f4);border:1px solid var(--input-border,#d3d3d3);border-radius:var(--radius-input,62px);box-sizing:border-box;display:flex;gap:0;height:52px;overflow:hidden;padding:6px 6px 6px 16px;position:relative;transition:all var(--duration-fast,.15s) ease;z-index:5}.ai-chat-input-wrapper.multiline{border-radius:14px!important;min-height:64px;padding:10px 10px 10px 14px}.ai-chat-widget.dark .ai-chat-input-wrapper{background:var(--input-bg,#4a4846);border-color:var(--input-border,#5d5b5b);border-width:.7px;box-shadow:var(--shadow-input,0 0 10px rgba(0,0,0,.15))}.ai-chat-input-wrapper:focus-within{border-color:var(--text-muted,#a1a1aa)}.ai-chat-input{word-wrap:break-word!important;background:transparent!important;border:none!important;border-radius:0!important;box-shadow:none!important;box-sizing:border-box!important;color:var(--input-text,#000)!important;flex:1!important;font-family:inherit!important;font-size:var(--text-md,15px)!important;height:40px!important;line-height:20px!important;margin:0!important;max-height:40px!important;min-height:40px!important;min-width:0!important;outline:none!important;overflow-wrap:anywhere!important;overflow-x:hidden!important;overflow-y:auto!important;padding:10px var(--space-sm,8px)!important;resize:none!important;white-space:pre-wrap!important;width:0!important;word-break:break-word!important}.ai-chat-widget.dark .ai-chat-input{color:var(--input-text,#fff)}.ai-chat-input::placeholder{color:var(--text-placeholder,#a1a1aa)}.ai-chat-widget.dark .ai-chat-input::placeholder{color:var(--text-placeholder,#52525b)}.ai-chat-file-button{align-items:center;align-self:center;background:transparent;border:none;color:var(--text-placeholder);cursor:pointer;display:flex;flex-shrink:0;height:28px;justify-content:center;padding:0;transition:color var(--duration-fast) ease;width:28px}.ai-chat-file-button:hover{color:var(--text-secondary)}.ai-chat-file-button:disabled{cursor:not-allowed;opacity:.5}.ai-chat-send-button{align-items:center;align-self:center;background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#151515))));border:none;border-radius:50%;color:var(--button-icon-color,var(--btn-primary-text,#f4f4f4));cursor:pointer;display:flex;flex-shrink:0;height:40px;justify-content:center;min-height:40px;min-width:40px;padding:0;transition:all var(--duration-fast,.15s) ease;width:40px}.ai-chat-widget.dark .ai-chat-send-button{background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#fff))));color:var(--button-icon-color,var(--btn-primary-text,#312f2d))}.ai-chat-send-button.active{background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#151515))));color:var(--button-icon-color,var(--btn-primary-text,#f4f4f4))}.ai-chat-widget.dark .ai-chat-send-button.active{background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#fff))));color:var(--button-icon-color,var(--btn-primary-text,#312f2d))}.ai-chat-send-button:hover:not(:disabled){opacity:.8}.ai-chat-send-button:active:not(:disabled){transform:scale(.95)}.ai-chat-send-button:disabled{cursor:not-allowed;opacity:.3}.ai-chat-file-list{display:flex;flex-wrap:wrap;gap:var(--space-sm);padding:var(--space-sm) var(--space-sm)}.ai-chat-file-item{align-items:center;background:rgba(0,0,0,.05);border-radius:6px;display:flex;font-size:var(--text-xs);gap:var(--space-sm);padding:6px 10px}.ai-chat-file-extension{background:var(--btn-primary-bg);border-radius:3px;color:var(--btn-primary-text);display:inline-block;font-size:10px;font-weight:var(--font-weight-semibold);min-width:40px;padding:2px 6px;text-align:center;text-transform:uppercase}.ai-chat-file-info{display:flex;flex:1;flex-direction:column;gap:2px;min-width:0}.ai-chat-file-name{font-weight:var(--font-weight-medium);max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-file-size{color:var(--text-muted);font-size:10px;opacity:.7}.ai-chat-file-remove{align-items:center;background:none;border:none;color:inherit;cursor:pointer;display:flex;justify-content:center;opacity:.5;padding:var(--space-xs);transition:opacity var(--duration-fast) ease}.ai-chat-file-remove:hover{opacity:1}.ai-chat-data-policy{bottom:2px;color:var(--text-muted,#71717a);font-size:9px;left:0;line-height:1.4;opacity:.5;pointer-events:auto;position:absolute;right:0;text-align:center}.ai-chat-widget.dark .ai-chat-data-policy{color:var(--text-muted,#a1a1aa)}.ai-chat-data-policy-link{background:none;border:none;color:var(--text-muted,#71717a);cursor:pointer;font-family:inherit;font-size:inherit;margin:0;padding:0;text-decoration:underline;text-underline-offset:2px;transition:color .15s ease}.ai-chat-data-policy-link:hover{color:var(--text-secondary,#52525b)}.ai-chat-widget.dark .ai-chat-data-policy-link{color:var(--text-muted,#a1a1aa)}.ai-chat-widget.dark .ai-chat-data-policy-link:hover{color:var(--text-secondary,#d4d4d8)}.ai-chat-messages{-webkit-overflow-scrolling:touch;-ms-overflow-style:none;align-items:stretch;background:var(--bg-primary,#fff);display:flex;flex:1;flex-direction:column;gap:var(--space-md,16px);justify-content:flex-start;overflow-x:hidden;overflow-y:auto;padding:0 var(--space-md,16px) 100px;position:relative;scroll-behavior:smooth;scrollbar-width:none}.ai-chat-widget.dark .ai-chat-messages{background:var(--bg-primary,#18181b)}.ai-chat-messages::-webkit-scrollbar{display:none}.ai-chat-message{animation:ai-chat-message-slide-in .2s var(--spring-bounce);display:flex;flex-direction:column;max-width:90%}.ai-chat-message.user{align-items:flex-end;align-self:flex-end}.ai-chat-message.assistant{align-items:flex-start;align-self:flex-start;max-width:100%;width:100%}.ai-chat-message.tool{align-self:stretch;max-width:none;padding:0}.ai-chat-message-content{word-wrap:break-word;border-radius:18px;font-size:var(--text-md,15px);line-height:var(--line-height-relaxed,1.6);overflow-wrap:break-word;padding:8px 14px}.ai-chat-message.user .ai-chat-message-content{background:var(--user-bg,#f4f3f0);border-radius:18px;color:var(--user-text,#000)}.ai-chat-widget.dark .ai-chat-message.user .ai-chat-message-content{background:var(--user-bg,#484848);color:var(--user-text,#fff)}.ai-chat-message.assistant .ai-chat-message-content{background:var(--agent-bg,transparent);box-sizing:border-box;color:var(--agent-text,#000);padding:0;width:100%}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content{color:var(--agent-text,#fff)}.ai-chat-message-timestamp{color:var(--text-muted,#71717a);font-size:var(--text-xs,12px);margin-top:var(--space-xs,4px);padding:0 var(--space-xs,4px)}.ai-chat-welcome{animation:ai-chat-welcome-fade-in .3s var(--spring-smooth);display:flex;flex-direction:column;gap:var(--space-md,16px);padding:var(--space-lg,24px) 0}.ai-chat-welcome-title{color:var(--text-primary,#3e3e3e);font-size:var(--text-2xl,28px);font-weight:var(--font-weight-bold,700);line-height:var(--line-height-tight,1.3)}.ai-chat-widget.dark .ai-chat-welcome-title{color:var(--text-primary,#fff)}.ai-chat-welcome-text{color:var(--text-secondary,#000);font-size:var(--text-md,15px);line-height:var(--line-height-relaxed,1.6);max-width:100%}.ai-chat-widget.dark .ai-chat-welcome-text{color:var(--text-secondary,#fff)}.ai-chat-typing{align-items:center;display:flex;gap:var(--space-xs,4px);padding:var(--space-sm,8px) var(--space-md,16px)}.ai-chat-typing-dot{animation:ai-chat-typing-bounce 1.4s ease-in-out infinite both;background:var(--text-muted,#71717a);border-radius:50%;height:8px;width:8px}.ai-chat-typing-dot:first-child{animation-delay:-.32s}.ai-chat-typing-dot:nth-child(2){animation-delay:-.16s}.ai-chat-typing-dot:nth-child(3){animation-delay:0s}@keyframes ai-chat-typing-bounce{0%,80%,to{opacity:.4;transform:scale(.6)}40%{opacity:1;transform:scale(1)}}.ai-chat-scroll-button{align-items:center;background:var(--bg-secondary,#f4f4f5);border:1px solid var(--border-subtle,rgba(0,0,0,.1));border-radius:50%;bottom:80px;box-shadow:0 2px 8px rgba(0,0,0,.1);color:var(--text-secondary,#71717a);cursor:pointer;display:flex;height:36px;justify-content:center;left:50%;opacity:0;pointer-events:none;position:absolute;transform:translateX(-50%);transition:background .15s ease,box-shadow .15s ease,opacity .15s ease,visibility .15s ease;visibility:hidden;width:36px;z-index:15}.ai-chat-scroll-button.visible{opacity:1;pointer-events:auto;visibility:visible}.ai-chat-scroll-button:hover{background:var(--bg-tertiary,#e4e4e7);box-shadow:0 4px 12px rgba(0,0,0,.15)}.ai-chat-scroll-button:active{background:var(--bg-tertiary,#d4d4d8)}.ai-chat-widget.dark .ai-chat-scroll-button{background:var(--bg-secondary,#3f3f46);border-color:var(--border-subtle,hsla(0,0%,100%,.1));box-shadow:0 2px 8px rgba(0,0,0,.3);color:var(--text-secondary,#a1a1aa)}.ai-chat-widget.dark .ai-chat-scroll-button:hover{background:var(--bg-tertiary,#52525b);box-shadow:0 4px 12px rgba(0,0,0,.4)}.ai-chat-error{background:var(--bg-secondary);border-radius:var(--radius-chat-bubble);color:var(--text-primary);font-size:var(--text-md);margin:0 auto;padding:10px var(--space-md)}.ai-chat-message.assistant .ai-chat-message-content p{margin:0 0 var(--space-sm) 0}.ai-chat-message.assistant .ai-chat-message-content p:last-child{margin-bottom:0}.ai-chat-message.assistant .ai-chat-message-content ol,.ai-chat-message.assistant .ai-chat-message-content ul{margin:var(--space-sm) 0;padding-left:var(--space-lg)}.ai-chat-message.assistant .ai-chat-message-content li{margin-bottom:var(--space-xs)}.ai-chat-message.assistant .ai-chat-message-content code{background:rgba(0,0,0,.05);border-radius:var(--radius-sm);font-family:SF Mono,Monaco,Cascadia Code,monospace;font-size:.9em;padding:2px 6px}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content code{background:hsla(0,0%,100%,.1)}.ai-chat-message.assistant .ai-chat-message-content pre{background:rgba(0,0,0,.05);border-radius:var(--radius-md);margin:var(--space-sm) 0;overflow-x:auto;padding:var(--space-sm)}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content pre{background:hsla(0,0%,100%,.05)}.ai-chat-message.assistant .ai-chat-message-content pre code{background:transparent;padding:0}.ai-chat-message.assistant .ai-chat-message-content a{color:var(--btn-primary-bg);text-decoration:underline}.ai-chat-message.assistant .ai-chat-message-content strong{font-weight:var(--font-weight-semibold)}.ai-chat-message.assistant .ai-chat-message-content blockquote{border-left:3px solid var(--border-default);color:var(--text-muted);margin:var(--space-sm) 0;padding-left:var(--space-md)}.ai-chat-message.assistant .ai-chat-message-content hr{border:none;border-top:1px solid var(--border-subtle,rgba(0,0,0,.1));margin:var(--space-lg,24px) 0}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content hr{border-top-color:var(--border-subtle,hsla(0,0%,100%,.1))}.ai-chat-message.assistant .ai-chat-message-content .table-wrapper{border:1px solid var(--border-subtle,rgba(0,0,0,.1));border-radius:var(--radius-md,8px);box-sizing:border-box;display:block;margin:var(--space-sm) var(--space-sm);max-width:100%;overflow:hidden;width:auto}.ai-chat-message.assistant .ai-chat-message-content .table-scroll{max-width:100%;overflow-x:auto;overflow-y:hidden;width:100%}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content .table-wrapper{border-color:var(--border-subtle,hsla(0,0%,100%,.1))}.ai-chat-message.assistant .ai-chat-message-content table{border-collapse:collapse;font-size:var(--text-sm);min-width:100%;width:max-content}.ai-chat-message.assistant .ai-chat-message-content td,.ai-chat-message.assistant .ai-chat-message-content th{border-bottom:1px solid var(--border-subtle,rgba(0,0,0,.1));border-right:1px solid var(--border-subtle,rgba(0,0,0,.1));padding:var(--space-sm);text-align:left}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content td,.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content th{border-color:var(--border-subtle,hsla(0,0%,100%,.1))}.ai-chat-message.assistant .ai-chat-message-content td:last-child,.ai-chat-message.assistant .ai-chat-message-content th:last-child{border-right:none}.ai-chat-message.assistant .ai-chat-message-content tr:last-child td{border-bottom:none}.ai-chat-message.assistant .ai-chat-message-content th{background:rgba(0,0,0,.03);font-weight:var(--font-weight-semibold);white-space:nowrap}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content th{background:hsla(0,0%,100%,.05)}.ai-chat-message.assistant .ai-chat-message-content tbody tr:nth-child(2n){background:rgba(0,0,0,.02)}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content tbody tr:nth-child(2n){background:hsla(0,0%,100%,.03)}.ai-chat-suggested-questions{align-self:flex-end;margin:0;padding:16px 0 0;width:100%}.ai-chat-suggested-questions-list{align-items:center;display:flex;flex-wrap:wrap;gap:6px;justify-content:flex-end}.ai-chat-suggested-question{align-items:center;background:transparent;border:1px solid var(--border-default,#d4d4d8);border-radius:var(--radius-preset-badge,18px);color:var(--text-primary,#18181b);cursor:pointer;display:inline-flex;font-size:14px;font-weight:400;gap:6px;justify-content:center;line-height:1.3;max-width:100%;overflow:hidden;padding:8px 14px;text-overflow:ellipsis;transition:background .15s ease,border-color .15s ease,transform .1s ease;white-space:nowrap}.ai-chat-widget.dark .ai-chat-suggested-question{background:transparent;border-color:var(--border-subtle,#52525b);color:var(--text-primary,#fafafa)}.ai-chat-suggested-question-text{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-suggested-question:hover{background:var(--bg-hover,#f4f4f5);border-color:var(--border-default,#d4d4d8)}.ai-chat-widget.dark .ai-chat-suggested-question:hover{background:var(--bg-hover,#3f3f46);border-color:var(--border-subtle,#52525b)}.ai-chat-suggested-question:active{transform:scale(.98)}.ai-chat-suggested-question.action-type{border:none}.ai-chat-suggested-question.action-type,.ai-chat-widget.dark .ai-chat-suggested-question.action-type{background:var(--primary-color,var(--button-color,#ef4444));color:var(--button-icon-color,#fff)}.ai-chat-suggested-question.action-type:hover{background:var(--primary-color,var(--button-color,#ef4444));opacity:.9}.ai-chat-suggested-question-icon{align-items:center;display:flex;flex-shrink:0;justify-content:center}.ai-chat-suggested-question:not(.action-type) .ai-chat-suggested-question-icon{display:none}.ai-chat-follow-up-suggestions{box-sizing:border-box;margin:0;padding:8px 16px 0;width:100%}.ai-chat-follow-up-list{align-items:flex-end;display:flex;flex-direction:column;gap:6px}.ai-chat-follow-up-item{align-items:center;border:none;border-radius:var(--radius-preset-badge,18px);cursor:pointer;display:inline-flex;font-size:14px;font-weight:400;gap:6px;justify-content:center;line-height:1.3;max-width:100%;overflow:hidden;padding:8px 14px;text-overflow:ellipsis;transition:opacity .15s ease,transform .1s ease;white-space:nowrap}.ai-chat-follow-up-item,.ai-chat-widget.dark .ai-chat-follow-up-item{background:var(--primary-color,var(--button-color,#07f));color:var(--button-icon-color,#fff)}.ai-chat-follow-up-item:hover{opacity:.9}.ai-chat-follow-up-item:active{transform:scale(.98)}.ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-default,#d4d4d8);color:var(--text-primary,#18181b)}.ai-chat-widget.dark .ai-chat-follow-up-item.question-type,.dark .ai-chat-follow-up-item.question-type,[data-color-mode=dark] .ai-chat-follow-up-item.question-type,[data-theme=dark] .ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-subtle,#52525b);color:var(--text-primary,#fafafa)}@media (prefers-color-scheme:dark){.ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-subtle,#52525b);color:var(--text-primary,#fafafa)}}.ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#f4f4f5);opacity:1}.ai-chat-widget.dark .ai-chat-follow-up-item.question-type:hover,.dark .ai-chat-follow-up-item.question-type:hover,[data-color-mode=dark] .ai-chat-follow-up-item.question-type:hover,[data-theme=dark] .ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#3f3f46);opacity:1}@media (prefers-color-scheme:dark){.ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#3f3f46);opacity:1}}.ai-chat-follow-up-item.action-type{background:var(--primary-color,var(--button-color,#07f));border:none;color:var(--button-icon-color,#fff)}.ai-chat-follow-up-icon{align-items:center;display:flex;flex-shrink:0;justify-content:center}.ai-chat-follow-up-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-feedback-buttons{align-items:center;display:flex;gap:var(--space-xs)}.ai-chat-feedback{align-items:center;display:inline-flex;gap:0;height:20px}.ai-chat-feedback-button{align-items:center;background:transparent!important;border:none;border-radius:var(--radius-sm);color:var(--text-placeholder);cursor:pointer;display:flex;font-size:var(--text-sm);height:20px;justify-content:center;padding:var(--space-xs);transition:all var(--duration-fast) var(--spring-bounce)}.ai-chat-feedback-button:hover:not(:disabled){background:none!important;color:var(--text-secondary)}.ai-chat-feedback-button:active:not(:disabled){transform:scale(.9)}.ai-chat-feedback-button:disabled{cursor:not-allowed;opacity:.4}.ai-chat-feedback-button.active{background:none!important;color:var(--text-primary)}.ai-chat-feedback.submitted{align-items:center;animation:ai-chat-feedback-morph .3s var(--spring-bounce);gap:var(--space-xs)}.ai-chat-feedback-message{align-items:center;display:flex;gap:4px;margin-left:var(--space-xxs)}.ai-chat-feedback-checkmark{animation:ai-chat-checkmark-pop .3s var(--spring-bounce);color:#10b981;font-size:var(--text-md);font-weight:700}.ai-chat-feedback-text{color:#10b981;font-size:var(--text-xs);font-weight:var(--font-weight-medium)}.ai-chat-history-panel{background:var(--bg-primary,#fff);display:flex;flex:1;flex-direction:column;overflow:hidden}.ai-chat-widget.dark .ai-chat-history-panel{background:var(--bg-primary,#18181b)}.ai-chat-history-empty,.ai-chat-history-loading{align-items:center;color:var(--text-muted);display:flex;flex:1;font-size:var(--text-sm);justify-content:center;padding:var(--space-lg);text-align:center}.ai-chat-history-list{-ms-overflow-style:none;display:flex;flex:1;flex-direction:column;gap:var(--space-sm);overflow-y:auto;padding:var(--space-xs) var(--space-md) 120px;scrollbar-width:none}.ai-chat-history-list::-webkit-scrollbar{display:none}.ai-chat-history-list.exiting{animation:ai-chat-history-exit .22s var(--spring-smooth) forwards}.ai-chat-history-item{align-items:center;background:var(--user-bg,#f4f4f5);border-radius:var(--radius-history-item,15px);display:flex;flex:0 0 auto;flex-direction:row;height:var(--history-item-height,36px);margin:0;overflow:hidden;transition:background var(--duration-fast,.15s) ease;width:100%}.ai-chat-history-item-content{align-items:center;background:transparent;border:none;cursor:pointer;display:flex;flex:1;flex-direction:row;height:100%;min-width:0;padding:0 var(--space-xs,4px) 0 var(--space-md,16px);text-align:left}.ai-chat-widget.dark .ai-chat-history-item{background:var(--user-bg,#27272a)}.ai-chat-history-item:hover{background:var(--user-bg-hover,#e5e7eb)}.ai-chat-widget.dark .ai-chat-history-item:hover{background:var(--user-bg-hover,#3f3f46)}.ai-chat-history-item.active{background:var(--user-bg-hover,#e5e7eb)}.ai-chat-widget.dark .ai-chat-history-item.active{background:var(--user-bg-hover,#3f3f46)}.ai-chat-history-item-preview{color:var(--text-primary,#18181b);flex:1;font-size:var(--text-sm,14px);font-weight:var(--font-weight-medium,500);line-height:var(--line-height-normal,1.4);margin-bottom:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-widget.dark .ai-chat-history-item-preview{color:var(--text-primary,#fafafa)}.ai-chat-history-item.active .ai-chat-history-item-preview{font-weight:var(--font-weight-medium)}.ai-chat-history-item-meta{display:none}.ai-chat-history-item-delete{align-items:center;background:transparent;border:none;border-radius:var(--radius-sm,6px);color:var(--text-muted,#71717a);cursor:pointer;display:flex;flex-shrink:0;height:24px;justify-content:center;margin-left:auto;margin-right:var(--space-xs,4px);opacity:0;transition:opacity var(--duration-fast,.15s) ease,background var(--duration-fast,.15s) ease,color var(--duration-fast,.15s) ease;width:24px}.ai-chat-history-item-delete svg{height:14px;width:14px}.ai-chat-history-item:hover .ai-chat-history-item-delete{opacity:1}.ai-chat-history-item-delete:hover{background:rgba(239,68,68,.1);color:#ef4444}.ai-chat-widget.dark .ai-chat-history-item-delete:hover{background:rgba(239,68,68,.2);color:#f87171}.ai-chat-tool-row{align-items:center;display:flex;gap:10px;margin:2px 0;padding:0}.ai-chat-tool-gear{color:#1f2937;flex-shrink:0;height:20px;width:20px}.ai-chat-tool-gear.spinning{animation:ai-chat-gear-spin 1.5s linear infinite}.ai-chat-tool-badges{align-items:center;display:flex;flex-wrap:wrap;gap:8px}.ai-chat-tool-badge{align-items:center;background:#e5e7eb;border:1px solid #d1d5db;border-radius:var(--radius-action-badge,8px);color:#1f2937;display:inline-flex;font-size:12px;font-weight:500;gap:4px;line-height:1.2;padding:5px 12px;transition:all .2s ease;white-space:nowrap}.ai-chat-tool-badge.loading{animation:ai-chat-tool-gradient 2s linear infinite;background:linear-gradient(90deg,var(--tool-loading-bg-1,#e0e0e0) 0,var(--tool-loading-bg-2,#f0f0f0) 25%,var(--tool-loading-bg-3,#fff) 50%,var(--tool-loading-bg-2,#f0f0f0) 75%,var(--tool-loading-bg-1,#e0e0e0) 100%);background-size:200% 100%;color:var(--tool-loading-text,#1a1a1a);position:relative}.ai-chat-widget:not(.dark) .ai-chat-tool-badge.loading{--tool-loading-bg-1:#2a2a2a;--tool-loading-bg-2:#3a3a3a;--tool-loading-bg-3:#4a4a4a;--tool-loading-text:#fff}.ai-chat-tool-badge.completed{background:#e5e7eb;border:1px solid #d1d5db;color:#1f2937}.ai-chat-widget.dark .ai-chat-tool-badge,.ai-chat-widget[data-theme=dark] .ai-chat-tool-badge,.chakra-ui-dark .ai-chat-tool-badge,.dark .ai-chat-tool-badge,[data-theme=dark] .ai-chat-tool-badge,html.dark .ai-chat-tool-badge{background:hsla(0,0%,100%,.12);border:1px solid hsla(0,0%,100%,.2);color:hsla(0,0%,100%,.9)}.ai-chat-widget.dark .ai-chat-tool-gear,.ai-chat-widget[data-theme=dark] .ai-chat-tool-gear,.chakra-ui-dark .ai-chat-tool-gear,.dark .ai-chat-tool-gear,[data-theme=dark] .ai-chat-tool-gear,html.dark .ai-chat-tool-gear{color:#fff}.ai-chat-tool-badge.error{background:var(--tool-error-bg,rgba(239,68,68,.15));color:var(--tool-error-text,#ef4444)}.ai-chat-tool-badge .ai-chat-tool-check{color:#fff;flex-shrink:0}.ai-chat-tool-badge .ai-chat-tool-error{color:#ef4444;flex-shrink:0}.tool-name{font-weight:500;line-height:1.2;white-space:nowrap}.ai-chat-tool-action{box-sizing:border-box;padding:0;width:100%}@keyframes ai-chat-skeleton-pulse{0%,to{opacity:.4}50%{opacity:.7}}.ai-chat-action-skeleton-item{animation:ai-chat-skeleton-pulse 1.5s ease-in-out infinite;background:var(--bg-secondary,#e5e7eb)}.ai-chat-widget.dark .ai-chat-action-skeleton-item,.chakra-ui-dark .ai-chat-action-skeleton-item,.dark .ai-chat-action-skeleton-item,[data-theme=dark] .ai-chat-action-skeleton-item{background:hsla(0,0%,100%,.1)}.ai-chat-action-skeleton-content{display:flex;flex-direction:column;gap:16px}.ai-chat-action-skeleton-header{align-items:center;display:flex;gap:10px}.ai-chat-action-skeleton-box{background:rgba(0,0,0,.08);border-radius:10px;display:flex;flex-direction:column;gap:8px;padding:14px}.ai-chat-widget.dark .ai-chat-action-skeleton-box,.chakra-ui-dark .ai-chat-action-skeleton-box,.dark .ai-chat-action-skeleton-box,[data-theme=dark] .ai-chat-action-skeleton-box{background:rgba(0,0,0,.25)}.ai-chat-action-card{--action-accent:var(--primary-color,#3b82f6);background:var(--bg-secondary,#f9fafb);border:1px solid var(--border-subtle,rgba(0,0,0,.06));border-radius:12px;box-sizing:border-box;margin-top:4px;padding:16px;transition:all .2s ease;width:100%}.ai-chat-widget.dark .ai-chat-action-card,.chakra-ui-dark .ai-chat-action-card,.dark .ai-chat-action-card,[data-theme=dark] .ai-chat-action-card{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1)}.ai-chat-action-booked{background:var(--bg-secondary,#f9fafb);border:1px solid var(--border-subtle,rgba(0,0,0,.06))}.ai-chat-widget.dark .ai-chat-action-booked,.chakra-ui-dark .ai-chat-action-booked,.dark .ai-chat-action-booked,[data-theme=dark] .ai-chat-action-booked{background:var(--bg-secondary,#3a3a3a)}.ai-chat-action-header{align-items:center;color:var(--text-primary,#3e3e3e);display:flex;font-size:var(--text-md,15px);font-weight:var(--font-weight-semibold,600);gap:var(--space-sm,8px);margin-bottom:var(--space-md,16px)}.ai-chat-widget.dark .ai-chat-action-header,.chakra-ui-dark .ai-chat-action-header,.dark .ai-chat-action-header,[data-theme=dark] .ai-chat-action-header{color:var(--text-primary,#fff)}.ai-chat-action-icon{color:var(--action-accent,var(--primary-color,#3b82f6));flex-shrink:0;height:20px;width:20px}.ai-chat-action-success-icon-wrapper{align-items:center;background:var(--action-accent,var(--primary-color,#22c55e));border-radius:50%;color:#fff;display:flex;flex-shrink:0;height:24px;justify-content:center;width:24px}.ai-chat-action-icon-success{color:currentColor;height:14px;width:14px}.ai-chat-action-detail-box{background:var(--bg-primary,#fff);border:1px solid var(--border-subtle,rgba(0,0,0,.08));border-radius:var(--radius-md,8px);display:flex;flex-direction:column;gap:4px;padding:12px 16px}.ai-chat-widget.dark .ai-chat-action-detail-box,.chakra-ui-dark .ai-chat-action-detail-box,.dark .ai-chat-action-detail-box,[data-theme=dark] .ai-chat-action-detail-box{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.05)}.ai-chat-action-label-small{color:var(--text-muted,#71717a);font-size:11px;font-weight:600;letter-spacing:.5px;text-transform:uppercase}.ai-chat-action-value-large{color:var(--text-primary,#3e3e3e);font-size:15px;font-weight:500}.ai-chat-widget.dark .ai-chat-action-value-large,.chakra-ui-dark .ai-chat-action-value-large,.dark .ai-chat-action-value-large,[data-theme=dark] .ai-chat-action-value-large{color:#fff}.ai-chat-action-body{display:flex;flex-direction:column;gap:var(--space-md,16px)}.ai-chat-action-field{display:flex;flex-direction:column;gap:var(--space-xs,6px)}.ai-chat-action-label{color:var(--text-secondary,#6b7280);font-size:var(--text-sm,13px);font-weight:var(--font-weight-medium,500)}.ai-chat-widget.dark .ai-chat-action-label,.chakra-ui-dark .ai-chat-action-label,.dark .ai-chat-action-label,[data-theme=dark] .ai-chat-action-label{color:var(--text-secondary,#a1a1aa)}.ai-chat-action-input{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);color:var(--text-primary,#3e3e3e);font-size:var(--text-sm,13px);outline:none;padding:10px 12px;transition:border-color .2s ease,box-shadow .2s ease}.ai-chat-action-input:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.1)}.ai-chat-action-input::placeholder{color:var(--text-muted,#9ca3af)}.ai-chat-widget.dark .ai-chat-action-input,.chakra-ui-dark .ai-chat-action-input,.dark .ai-chat-action-input,[data-theme=dark] .ai-chat-action-input{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-action-input:focus,.chakra-ui-dark .ai-chat-action-input:focus,.dark .ai-chat-action-input:focus,[data-theme=dark] .ai-chat-action-input:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.2)}.ai-chat-action-button{background:var(--action-accent,var(--primary-color,#3b82f6));border:none;border-radius:9999px;color:#fff;cursor:pointer;font-size:var(--text-sm,13px);font-weight:var(--font-weight-semibold,600);padding:12px 16px;transition:all .2s ease;width:100%}.ai-chat-action-button:hover:not(:disabled){opacity:.9;transform:translateY(-1px)}.ai-chat-action-button:disabled{cursor:not-allowed;opacity:.5}.ai-chat-action-link-button{align-items:center;background:var(--action-accent,var(--primary-color,#3b82f6));border:none;border-radius:9999px;box-sizing:border-box;color:#fff;display:flex;font-size:14px;font-weight:600;gap:6px;justify-content:center;margin-top:8px;padding:12px;text-decoration:none;transition:all .2s ease;width:100%}.ai-chat-action-link-button:hover{opacity:.9;transform:translateY(-1px)}.ai-chat-action-error{background:rgba(239,68,68,.1);border-radius:var(--radius-md,8px);color:#dc2626;font-size:var(--text-sm,13px);padding:10px 12px}.ai-chat-widget.dark .ai-chat-action-error,.chakra-ui-dark .ai-chat-action-error,.dark .ai-chat-action-error,[data-theme=dark] .ai-chat-action-error{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-action-hint{color:var(--text-muted,#9ca3af);font-size:var(--text-sm,13px);padding:var(--space-sm,8px);text-align:center}.ai-chat-action-date-grid{display:grid;gap:var(--space-xs,6px);grid-template-columns:repeat(auto-fill,minmax(90px,1fr))}.ai-chat-action-date-btn{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);color:var(--text-primary,#3e3e3e);cursor:pointer;font-size:var(--text-xs,12px);font-weight:var(--font-weight-medium,500);padding:8px 10px;text-align:center;transition:all .15s ease}.ai-chat-action-date-btn:hover{background:rgba(59,130,246,.05);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-action-date-btn.active{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-widget.dark .ai-chat-action-date-btn,.chakra-ui-dark .ai-chat-action-date-btn,.dark .ai-chat-action-date-btn,[data-theme=dark] .ai-chat-action-date-btn{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-action-date-btn:hover,.chakra-ui-dark .ai-chat-action-date-btn:hover,.dark .ai-chat-action-date-btn:hover,[data-theme=dark] .ai-chat-action-date-btn:hover{background:rgba(59,130,246,.15);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-action-date-btn.active,.chakra-ui-dark .ai-chat-action-date-btn.active,.dark .ai-chat-action-date-btn.active,[data-theme=dark] .ai-chat-action-date-btn.active{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-action-time-grid{display:grid;gap:var(--space-xs,6px);grid-template-columns:repeat(auto-fill,minmax(100px,1fr))}.ai-chat-action-time-btn{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);color:var(--text-primary,#3e3e3e);cursor:pointer;font-size:var(--text-xs,12px);font-weight:var(--font-weight-medium,500);padding:8px 10px;text-align:center;transition:all .15s ease}.ai-chat-action-time-btn:hover{background:rgba(59,130,246,.05);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-action-time-btn.active{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-widget.dark .ai-chat-action-time-btn,.chakra-ui-dark .ai-chat-action-time-btn,.dark .ai-chat-action-time-btn,[data-theme=dark] .ai-chat-action-time-btn{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-action-time-btn:hover,.chakra-ui-dark .ai-chat-action-time-btn:hover,.dark .ai-chat-action-time-btn:hover,[data-theme=dark] .ai-chat-action-time-btn:hover{background:rgba(59,130,246,.15);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-action-time-btn.active,.chakra-ui-dark .ai-chat-action-time-btn.active,.dark .ai-chat-action-time-btn.active,[data-theme=dark] .ai-chat-action-time-btn.active{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-link-preview{--action-accent:var(--primary-color,#3b82f6);background:var(--bg-secondary,#f4f4f4);border:1px solid var(--border-subtle,rgba(0,0,0,.08));border-radius:var(--radius-lg,12px);cursor:pointer;display:flex;flex-direction:column;margin-top:4px;overflow:hidden;padding:0!important;position:relative;transition:border-color .2s,box-shadow .2s,transform .2s}.ai-chat-link-preview:hover{border-color:var(--action-accent);box-shadow:0 2px 8px rgba(0,0,0,.1);transform:translateY(-1px)}.ai-chat-link-preview:focus{border-color:var(--action-accent);box-shadow:0 0 0 2px rgba(59,130,246,.2);outline:none}.ai-chat-widget.dark .ai-chat-link-preview,.chakra-ui-dark .ai-chat-link-preview,.dark .ai-chat-link-preview,[data-theme=dark] .ai-chat-link-preview{background:var(--bg-secondary,#3a3a3a);border-color:hsla(0,0%,100%,.08)}.ai-chat-widget.dark .ai-chat-link-preview:hover,.chakra-ui-dark .ai-chat-link-preview:hover,.dark .ai-chat-link-preview:hover,[data-theme=dark] .ai-chat-link-preview:hover{border-color:var(--action-accent);box-shadow:0 2px 12px rgba(0,0,0,.3)}.ai-chat-link-preview__image{aspect-ratio:1.91/1;background:var(--bg-muted,#e5e7eb);overflow:hidden;width:100%}.ai-chat-widget.dark .ai-chat-link-preview__image,.chakra-ui-dark .ai-chat-link-preview__image,.dark .ai-chat-link-preview__image,[data-theme=dark] .ai-chat-link-preview__image{background:hsla(0,0%,100%,.05)}.ai-chat-link-preview__image img{height:100%;object-fit:cover;width:100%}.ai-chat-link-preview__content{flex:1;padding:8px 10px}.ai-chat-link-preview__site{align-items:center;display:flex;gap:6px;margin-bottom:6px}.ai-chat-link-preview__favicon{border-radius:2px;flex-shrink:0;height:16px;width:16px}.ai-chat-link-preview__domain{color:var(--text-muted,#71717a);font-size:12px;letter-spacing:.5px;overflow:hidden;text-overflow:ellipsis;text-transform:uppercase;white-space:nowrap}.ai-chat-link-preview__title{-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;color:var(--text-primary,#3e3e3e);display:-webkit-box;font-size:15px;font-weight:600;line-height:1.3;margin:0 0 4px;overflow:hidden}.ai-chat-widget.dark .ai-chat-link-preview__title,.chakra-ui-dark .ai-chat-link-preview__title,.dark .ai-chat-link-preview__title,[data-theme=dark] .ai-chat-link-preview__title{color:#fff}.ai-chat-link-preview__description{-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;color:var(--text-muted,#71717a);display:-webkit-box;font-size:13px;line-height:1.4;margin:0;overflow:hidden}.ai-chat-link-preview__context{border-top:1px solid var(--border-subtle,rgba(0,0,0,.08));color:var(--text-muted,#71717a);font-size:12px;font-style:italic;margin:8px 0 0;padding-top:8px}.ai-chat-widget.dark .ai-chat-link-preview__context,.chakra-ui-dark .ai-chat-link-preview__context,.dark .ai-chat-link-preview__context,[data-theme=dark] .ai-chat-link-preview__context{border-color:hsla(0,0%,100%,.08)}.ai-chat-link-preview__arrow{align-items:center;background:var(--bg-primary,#fff);border-radius:50%;box-shadow:0 1px 3px rgba(0,0,0,.1);color:var(--text-muted,#71717a);display:flex;height:28px;justify-content:center;opacity:0;position:absolute;right:12px;top:12px;transition:opacity .2s,background .2s;width:28px}.ai-chat-link-preview:hover .ai-chat-link-preview__arrow{opacity:1}.ai-chat-widget.dark .ai-chat-link-preview__arrow,.chakra-ui-dark .ai-chat-link-preview__arrow,.dark .ai-chat-link-preview__arrow,[data-theme=dark] .ai-chat-link-preview__arrow{background:hsla(0,0%,100%,.1);color:#fff}.ai-chat-link-preview--error{border-color:rgba(239,68,68,.3)}.ai-chat-link-preview--error:hover{border-color:rgba(239,68,68,.5)}.ai-chat-link-preview__error-text{color:#dc2626;font-size:12px;margin:4px 0 0}.ai-chat-widget.dark .ai-chat-link-preview__error-text,.chakra-ui-dark .ai-chat-link-preview__error-text,.dark .ai-chat-link-preview__error-text,[data-theme=dark] .ai-chat-link-preview__error-text{color:#fca5a5}.ai-chat-video-player{--action-accent:var(--primary-color,#3b82f6);background:var(--bg-secondary,#f4f4f4);border-radius:var(--radius-lg,12px);display:flex;flex-direction:column;gap:0;margin-top:4px;overflow:hidden;padding:0!important}.ai-chat-widget.dark .ai-chat-video-player,.chakra-ui-dark .ai-chat-video-player,.dark .ai-chat-video-player,[data-theme=dark] .ai-chat-video-player{background:var(--bg-secondary,#3a3a3a)}.ai-chat-video-player__header{align-items:center;color:var(--action-accent,var(--primary-color,#3b82f6));display:flex;gap:8px}.ai-chat-video-player__title{color:var(--text-primary,#3e3e3e);font-size:14px;font-weight:600}.ai-chat-widget.dark .ai-chat-video-player__title,.chakra-ui-dark .ai-chat-video-player__title,.dark .ai-chat-video-player__title,[data-theme=dark] .ai-chat-video-player__title{color:#fff}.ai-chat-video-player__container{aspect-ratio:16/9;background:#000;border-radius:8px;overflow:hidden;position:relative;width:100%}.ai-chat-video-player__thumbnail{cursor:pointer;height:100%;position:relative;width:100%}.ai-chat-video-player__thumbnail img{height:100%;object-fit:cover;width:100%}.ai-chat-video-player__placeholder{align-items:center;background:linear-gradient(135deg,#1a1a2e,#16213e);cursor:pointer;display:flex;flex-direction:column;gap:8px;height:100%;justify-content:center;position:relative;width:100%}.ai-chat-video-player__click-text{color:hsla(0,0%,100%,.7);font-size:13px}.ai-chat-video-player__play-btn{align-items:center;background:rgba(0,0,0,.7);border:none;border-radius:50%;color:#fff;cursor:pointer;display:flex;height:64px;justify-content:center;left:50%;position:absolute;top:50%;transform:translate(-50%,-50%);transition:background .2s,transform .2s;width:64px}.ai-chat-video-player__placeholder .ai-chat-video-player__play-btn{left:auto;position:relative;top:auto;transform:none}.ai-chat-video-player__play-btn:hover{background:rgba(0,0,0,.9);transform:translate(-50%,-50%) scale(1.05)}.ai-chat-video-player__placeholder .ai-chat-video-player__play-btn:hover{transform:scale(1.05)}.ai-chat-video-player__provider-badge{background:rgba(0,0,0,.8);border-radius:4px;bottom:8px;color:#fff;font-size:11px;font-weight:600;letter-spacing:.5px;padding:4px 8px;position:absolute;right:8px;text-transform:uppercase}.ai-chat-video-player__iframe,.ai-chat-video-player__video{border:none;height:100%;left:0;position:absolute;top:0;width:100%}.ai-chat-video-player__error{align-items:center;background:rgba(239,68,68,.1);color:#dc2626;display:flex;font-size:13px;height:100%;justify-content:center;padding:16px;text-align:center;width:100%}.ai-chat-widget.dark .ai-chat-video-player__error,.chakra-ui-dark .ai-chat-video-player__error,.dark .ai-chat-video-player__error,[data-theme=dark] .ai-chat-video-player__error{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-video-player__context{border-top:1px solid var(--border-subtle,rgba(0,0,0,.08));color:var(--text-muted,#71717a);font-size:12px;font-style:italic;margin-top:4px;padding-top:8px}.ai-chat-widget.dark .ai-chat-video-player__context,.chakra-ui-dark .ai-chat-video-player__context,.dark .ai-chat-video-player__context,[data-theme=dark] .ai-chat-video-player__context{border-color:hsla(0,0%,100%,.08)}.ai-chat-location-card{background:var(--bg-secondary,#fff);border:1px solid var(--border-subtle,rgba(0,0,0,.08));border-radius:12px;overflow:hidden;padding:0}.ai-chat-widget.dark .ai-chat-location-card,.chakra-ui-dark .ai-chat-location-card,.dark .ai-chat-location-card,[data-theme=dark] .ai-chat-location-card{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1)}.ai-chat-location-card--compact{border-radius:10px}.ai-chat-location-card--error{color:var(--text-muted,#71717a);padding:16px;text-align:center}.ai-chat-location-card__map{background:var(--bg-muted,#f4f4f5);position:relative;width:100%}.ai-chat-widget.dark .ai-chat-location-card__map,.chakra-ui-dark .ai-chat-location-card__map,.dark .ai-chat-location-card__map,[data-theme=dark] .ai-chat-location-card__map{background:rgba(0,0,0,.2)}.ai-chat-location-card__map iframe{border:none;display:block;height:100%;width:100%}.ai-chat-location-card__content{padding:12px}.ai-chat-location-card--compact .ai-chat-location-card__content{padding:10px}.ai-chat-location-card__header{align-items:center;display:flex;flex-wrap:wrap;gap:8px;margin-bottom:8px}.ai-chat-location-card__name{color:var(--text-primary,#18181b);flex:1;font-size:16px;font-weight:600;margin:0;min-width:0}.ai-chat-widget.dark .ai-chat-location-card__name,.chakra-ui-dark .ai-chat-location-card__name,.dark .ai-chat-location-card__name,[data-theme=dark] .ai-chat-location-card__name{color:#fff}.ai-chat-location-card--compact .ai-chat-location-card__name{font-size:14px}.ai-chat-location-card__type{background:var(--bg-muted,#f4f4f5);border-radius:10px;color:var(--text-muted,#71717a);font-size:11px;font-weight:500;letter-spacing:.5px;padding:2px 8px;text-transform:uppercase}.ai-chat-widget.dark .ai-chat-location-card__type,.chakra-ui-dark .ai-chat-location-card__type,.dark .ai-chat-location-card__type,[data-theme=dark] .ai-chat-location-card__type{background:hsla(0,0%,100%,.1);color:hsla(0,0%,100%,.7)}.ai-chat-location-card__status{border-radius:12px;font-size:12px;font-weight:500;padding:2px 8px}.ai-chat-location-card__status--open{background:#dcfce7;color:#16a34a}.ai-chat-location-card__status--closed{background:#fef2f2;color:#dc2626}.ai-chat-widget.dark .ai-chat-location-card__status--open,.chakra-ui-dark .ai-chat-location-card__status--open,.dark .ai-chat-location-card__status--open,[data-theme=dark] .ai-chat-location-card__status--open{background:rgba(34,197,94,.2);color:#4ade80}.ai-chat-widget.dark .ai-chat-location-card__status--closed,.chakra-ui-dark .ai-chat-location-card__status--closed,.dark .ai-chat-location-card__status--closed,[data-theme=dark] .ai-chat-location-card__status--closed{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-location-card__address{align-items:flex-start;color:var(--text-muted,#71717a);display:flex;font-size:13px;gap:6px;line-height:1.4;margin:0 0 8px}.ai-chat-location-card__address svg{flex-shrink:0;margin-top:2px}.ai-chat-location-card__description{color:var(--text-muted,#71717a);font-size:13px;line-height:1.4;margin:0 0 8px}.ai-chat-location-card__hours{align-items:flex-start;color:var(--text-muted,#71717a);display:flex;font-size:13px;gap:6px;margin-bottom:8px}.ai-chat-location-card__hours svg{flex-shrink:0;margin-top:2px}.ai-chat-location-card__hours-list{flex:1}.ai-chat-location-card__hours-toggle{align-items:center;background:none;border:none;color:inherit;cursor:pointer;display:flex;font:inherit;gap:4px;padding:0}.ai-chat-location-card__hours-toggle:hover{text-decoration:underline}.ai-chat-location-card__hours-full{list-style:none;margin:8px 0 0;padding:0}.ai-chat-location-card__hours-full li{display:flex;font-size:12px;justify-content:space-between;padding:4px 0}.ai-chat-location-card__hours-today{color:var(--text-primary,#18181b);font-weight:600}.ai-chat-widget.dark .ai-chat-location-card__hours-today,.chakra-ui-dark .ai-chat-location-card__hours-today,.dark .ai-chat-location-card__hours-today,[data-theme=dark] .ai-chat-location-card__hours-today{color:#fff}.ai-chat-location-card__phone{align-items:center;background:none;border:none;color:var(--action-accent,#3b82f6);cursor:pointer;display:flex;font-size:13px;gap:6px;margin-bottom:12px;padding:0}.ai-chat-location-card__phone:hover{text-decoration:underline}.ai-chat-location-card__actions{display:flex;gap:8px;justify-content:flex-start;width:100%}.ai-chat-location-card__button{align-items:center;background:var(--action-accent,#3b82f6);border:none;border-radius:20px;color:#fff;cursor:pointer;display:flex;flex:1;font-size:13px;font-weight:500;gap:6px;justify-content:center;padding:10px 16px;transition:opacity .2s}.ai-chat-location-card__button:hover{opacity:.9}.ai-chat-location-card--compact .ai-chat-location-card__button{font-size:12px;padding:8px 12px}.ai-chat-location-card__link{align-items:center;background:var(--bg-secondary,#fff);border:1px solid var(--border-subtle,rgba(0,0,0,.08));border-radius:20px;color:var(--text-primary,#18181b);display:flex;font-size:13px;gap:6px;padding:10px 16px;text-decoration:none;transition:border-color .2s}.ai-chat-widget.dark .ai-chat-location-card__link,.chakra-ui-dark .ai-chat-location-card__link,.dark .ai-chat-location-card__link,[data-theme=dark] .ai-chat-location-card__link{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-location-card__link:hover{border-color:var(--action-accent,#3b82f6)}.ai-chat-location-card-list{display:flex;flex-direction:column;gap:8px}.ai-chat-location-card-list__header{align-items:center;color:var(--text-muted,#71717a);display:flex;font-size:13px;font-weight:500;gap:6px;margin-bottom:4px;padding:0 4px}.ai-chat-location-card-list__stack{display:grid;gap:12px;grid-template-columns:1fr}.ai-chat-location-card-list__stack--cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.ai-chat-location-card-list__stack--cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}@media (max-width:1000px){.ai-chat-location-card-list__stack--cols-3{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (max-width:640px){.ai-chat-location-card-list__stack--cols-2,.ai-chat-location-card-list__stack--cols-3{grid-template-columns:1fr}}.ai-chat-location-card-list__grid{display:grid;gap:8px;grid-template-columns:repeat(2,1fr)}@media (max-width:400px){.ai-chat-location-card-list__grid{grid-template-columns:1fr}}.ai-chat-location-card-list__carousel{-webkit-overflow-scrolling:touch;-ms-overflow-style:none;display:flex;gap:8px;overflow-x:auto;padding-bottom:4px;scroll-snap-type:x mandatory;scrollbar-width:none}.ai-chat-location-card-list__carousel::-webkit-scrollbar{display:none}.ai-chat-location-card-list__carousel>.ai-chat-location-card{flex:0 0 280px;scroll-snap-align:start}.ai-chat-contact-card{background:#fff;border:1px solid rgba(0,0,0,.08);border-radius:16px;overflow:hidden;padding:0;position:relative}.ai-chat-widget.dark .ai-chat-contact-card,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card,.chakra-ui-dark .ai-chat-contact-card,.dark .ai-chat-contact-card,[data-theme=dark] .ai-chat-contact-card,html.dark .ai-chat-contact-card{background:#4a4a4a;border-color:hsla(0,0%,100%,.08)}.ai-chat-contact-card-list{gap:12px;width:100%}.ai-chat-contact-card--compact{border-radius:12px}.ai-chat-contact-card--empty{align-items:center;background:var(--bg-secondary,#f4f4f5);display:flex;flex-direction:column;gap:8px;justify-content:center;padding:24px 16px;text-align:center}.ai-chat-widget.dark .ai-chat-contact-card--empty,.chakra-ui-dark .ai-chat-contact-card--empty,.dark .ai-chat-contact-card--empty,[data-theme=dark] .ai-chat-contact-card--empty{background:#3a3a3a}.ai-chat-contact-card__empty-icon{color:var(--text-muted,#71717a);opacity:.6}.ai-chat-contact-card__empty-text{color:var(--text-muted,#71717a);font-size:14px;margin:0}.ai-chat-contact-card--vertical{display:flex;flex-direction:column}.ai-chat-contact-card--vertical .ai-chat-contact-card__image-section{aspect-ratio:3/2;overflow:hidden;width:100%}.ai-chat-contact-card--vertical .ai-chat-contact-card__image{height:100%;object-fit:cover;width:100%}.ai-chat-contact-card--vertical .ai-chat-contact-card__image-placeholder{align-items:center;background:linear-gradient(135deg,#5a5a5a,#3a3a3a);color:hsla(0,0%,100%,.5);display:flex;height:100%;justify-content:center;width:100%}.ai-chat-contact-card--vertical .ai-chat-contact-card__image-placeholder svg{height:48px;width:48px}.ai-chat-contact-card--vertical .ai-chat-contact-card__info{padding:16px;text-align:center}.ai-chat-contact-card--horizontal{display:flex;flex-direction:row}.ai-chat-contact-card--horizontal .ai-chat-contact-card__image-section{height:160px;min-width:140px;overflow:hidden;width:140px}.ai-chat-contact-card--horizontal.ai-chat-contact-card--compact .ai-chat-contact-card__image-section{height:120px;min-width:100px;width:100px}.ai-chat-contact-card--horizontal .ai-chat-contact-card__image{height:100%;object-fit:cover;width:100%}.ai-chat-contact-card--horizontal .ai-chat-contact-card__image-placeholder{align-items:center;background:linear-gradient(135deg,#5a5a5a,#3a3a3a);color:hsla(0,0%,100%,.5);display:flex;height:100%;justify-content:center;width:100%}.ai-chat-contact-card--horizontal .ai-chat-contact-card__image-placeholder svg{height:36px;width:36px}.ai-chat-contact-card--horizontal .ai-chat-contact-card__info{display:flex;flex:1;flex-direction:column;justify-content:center;padding:16px}.ai-chat-contact-card__name{color:var(--action-accent,#ef4444);font-size:18px;font-weight:600;line-height:1.3;margin:0}.ai-chat-contact-card--compact .ai-chat-contact-card__name{font-size:15px}.ai-chat-contact-card__role{color:rgba(0,0,0,.7);font-size:14px;font-weight:400;margin:2px 0 0}.ai-chat-widget.dark .ai-chat-contact-card__role,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card__role,.chakra-ui-dark .ai-chat-contact-card__role,.dark .ai-chat-contact-card__role,[data-theme=dark] .ai-chat-contact-card__role,html.dark .ai-chat-contact-card__role{color:hsla(0,0%,100%,.9)}.ai-chat-contact-card--compact .ai-chat-contact-card__role{font-size:13px}.ai-chat-contact-card__details{display:flex;flex-direction:column;gap:2px;margin-top:12px}.ai-chat-contact-card__detail{color:rgba(0,0,0,.6);display:block;font-size:14px;line-height:1.5;margin:0;text-decoration:none}.ai-chat-contact-card__detail:hover{color:#000;text-decoration:underline}.ai-chat-widget.dark .ai-chat-contact-card__detail,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card__detail,.chakra-ui-dark .ai-chat-contact-card__detail,.dark .ai-chat-contact-card__detail,[data-theme=dark] .ai-chat-contact-card__detail,html.dark .ai-chat-contact-card__detail{color:hsla(0,0%,100%,.7)}.ai-chat-widget.dark .ai-chat-contact-card__detail:hover,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card__detail:hover,.chakra-ui-dark .ai-chat-contact-card__detail:hover,.dark .ai-chat-contact-card__detail:hover,[data-theme=dark] .ai-chat-contact-card__detail:hover,html.dark .ai-chat-contact-card__detail:hover{color:#fff}.ai-chat-contact-card--compact .ai-chat-contact-card__detail{font-size:13px}.ai-chat-contact-card__responsibilities{display:flex;flex-wrap:wrap;gap:4px;margin-top:8px}.ai-chat-contact-card__responsibility-tag{background:rgba(0,0,0,.08);border-radius:10px;color:rgba(0,0,0,.8);font-size:11px;font-weight:500;padding:3px 10px}.ai-chat-widget.dark .ai-chat-contact-card__responsibility-tag,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card__responsibility-tag,.chakra-ui-dark .ai-chat-contact-card__responsibility-tag,.dark .ai-chat-contact-card__responsibility-tag,[data-theme=dark] .ai-chat-contact-card__responsibility-tag,html.dark .ai-chat-contact-card__responsibility-tag{background:hsla(0,0%,100%,.15);color:hsla(0,0%,100%,.9)}.ai-chat-contact-card__responsibility-more{color:rgba(0,0,0,.5);font-size:11px;padding:3px 4px}.ai-chat-widget.dark .ai-chat-contact-card__responsibility-more,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card__responsibility-more,.chakra-ui-dark .ai-chat-contact-card__responsibility-more,.dark .ai-chat-contact-card__responsibility-more,[data-theme=dark] .ai-chat-contact-card__responsibility-more,html.dark .ai-chat-contact-card__responsibility-more{color:hsla(0,0%,100%,.5)}.ai-chat-contact-card__actions{display:flex;gap:8px;padding:0 12px 12px}.ai-chat-contact-card--compact .ai-chat-contact-card__actions{gap:6px;padding:0 10px 10px}.ai-chat-contact-card__button{align-items:center;border:none;border-radius:9999px;cursor:pointer;display:flex;font-size:14px;font-weight:600;gap:8px;justify-content:center;padding:12px 20px;transition:all .15s ease;white-space:nowrap}.ai-chat-contact-card--compact .ai-chat-contact-card__button{font-size:13px;padding:10px 16px}.ai-chat-contact-card__button:hover{box-shadow:0 4px 12px rgba(0,0,0,.15);transform:translateY(-1px)}.ai-chat-contact-card__button:active{transform:translateY(0)}.ai-chat-contact-card__button--primary{background:var(--action-accent,#3b82f6);color:#fff;flex:1}.ai-chat-contact-card__button--primary:hover{background:color-mix(in srgb,var(--action-accent,#3b82f6) 90%,#000)}.ai-chat-contact-card__button--secondary{background:var(--bg-muted,#f4f4f5);border:1px solid var(--border-subtle,rgba(0,0,0,.08));color:var(--text-primary,#18181b);flex:1}.ai-chat-contact-card__button--secondary:hover{background:var(--bg-hover,#e4e4e7)}.ai-chat-widget.dark .ai-chat-contact-card__button--secondary,.chakra-ui-dark .ai-chat-contact-card__button--secondary,.dark .ai-chat-contact-card__button--secondary,[data-theme=dark] .ai-chat-contact-card__button--secondary{background:hsla(0,0%,100%,.1);border-color:hsla(0,0%,100%,.15);color:#fff}.ai-chat-widget.dark .ai-chat-contact-card__button--secondary:hover,.chakra-ui-dark .ai-chat-contact-card__button--secondary:hover,.dark .ai-chat-contact-card__button--secondary:hover,[data-theme=dark] .ai-chat-contact-card__button--secondary:hover{background:hsla(0,0%,100%,.15)}.ai-chat-contact-card-list{display:flex;flex-direction:column;gap:8px}.ai-chat-contact-card-list__header{align-items:center;color:var(--text-muted,#71717a);display:flex;font-size:13px;font-weight:500;gap:6px;margin-bottom:2px;margin-top:8px;padding:0 4px}.ai-chat-contact-card-list__stack{display:grid;gap:12px;grid-template-columns:repeat(3,minmax(0,1fr))}@media (max-width:900px){.ai-chat-contact-card-list__stack{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (max-width:600px){.ai-chat-contact-card-list__stack{grid-template-columns:1fr}}.ai-chat-contact-card-list__stack--widget{grid-template-columns:1fr}@container (min-width: 380px){.ai-chat-contact-card-list__stack--widget{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (max-width:520px){.ai-chat-contact-card-list__stack{grid-template-columns:1fr!important}.ai-chat-contact-card--horizontal{flex-direction:column}.ai-chat-contact-card--horizontal .ai-chat-contact-card__image-section{aspect-ratio:3/2;height:auto;min-width:100%;width:100%}}.ai-chat-contact-card__initials{align-items:center;display:flex;font-size:48px;font-weight:600;height:100%;justify-content:center;letter-spacing:.05em;text-transform:uppercase;width:100%}.ai-chat-contact-card--compact .ai-chat-contact-card__initials{font-size:32px}.ai-chat-contact-card--horizontal .ai-chat-contact-card__initials{font-size:28px}.ai-chat-contact-card--horizontal.ai-chat-contact-card--compact .ai-chat-contact-card__initials{font-size:22px}.ai-chat-form-card{--action-accent:var(--primary-color,#3b82f6);background:var(--bg-secondary,#f9fafb);border:1px solid var(--border-subtle,rgba(0,0,0,.06));border-radius:12px;box-sizing:border-box;margin:6px 0;overflow:hidden;padding:16px;width:100%}.ai-chat-widget.dark .ai-chat-form-card,.chakra-ui-dark .ai-chat-form-card,.dark .ai-chat-form-card,[data-theme=dark] .ai-chat-form-card{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1)}.ai-chat-form-card--empty,.ai-chat-form-card--error,.ai-chat-form-card--skipped,.ai-chat-form-card--submitted{padding:12px 16px}.ai-chat-form-card__header{align-items:center;display:flex;gap:8px;margin-bottom:12px}.ai-chat-form-card__icon{font-size:18px}.ai-chat-form-card__title{color:var(--text-primary,#3e3e3e);font-size:15px;font-weight:600}.ai-chat-widget.dark .ai-chat-form-card__title,.chakra-ui-dark .ai-chat-form-card__title,.dark .ai-chat-form-card__title,[data-theme=dark] .ai-chat-form-card__title{color:#fff}.ai-chat-form-card__description{color:var(--text-muted,#71717a);font-size:13px;line-height:1.4;margin:0 0 12px}.ai-chat-form-card__context{color:var(--text-muted,#71717a);font-size:12px;font-style:italic;margin:0 0 12px}.ai-chat-form-card__error{color:#dc2626;font-size:13px;margin:0}.ai-chat-widget.dark .ai-chat-form-card__error,.chakra-ui-dark .ai-chat-form-card__error,.dark .ai-chat-form-card__error,[data-theme=dark] .ai-chat-form-card__error{color:#fca5a5}.ai-chat-form-card__success{color:#16a34a;font-size:13px;margin:0}.ai-chat-widget.dark .ai-chat-form-card__success,.chakra-ui-dark .ai-chat-form-card__success,.dark .ai-chat-form-card__success,[data-theme=dark] .ai-chat-form-card__success{color:#4ade80}.ai-chat-form-card__empty-text,.ai-chat-form-card__skipped-text{color:var(--text-muted,#71717a);font-size:13px;margin:0}.ai-chat-form-card__progress{align-items:center;display:flex;gap:12px;margin-bottom:16px}.ai-chat-form-card__progress-bar{background:var(--action-accent,var(--primary-color,#3b82f6));border-radius:2px;flex:1;height:4px;transition:width .3s ease}.ai-chat-form-card__progress-text{color:var(--text-muted,#71717a);font-size:12px;white-space:nowrap}.ai-chat-form-card__question{margin-bottom:16px}.ai-chat-form-card__question-text{color:var(--text-primary,#3e3e3e);font-size:14px;font-weight:500;line-height:1.4;margin:0 0 12px}.ai-chat-widget.dark .ai-chat-form-card__question-text,.chakra-ui-dark .ai-chat-form-card__question-text,.dark .ai-chat-form-card__question-text,[data-theme=dark] .ai-chat-form-card__question-text{color:#fff}.ai-chat-form-card__required{color:#dc2626;margin-left:2px}.ai-chat-form-card__answer{margin-top:8px}.ai-chat-form-card__textarea{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);box-sizing:border-box;color:var(--text-primary,#3e3e3e);font-family:inherit;font-size:14px;min-height:80px;outline:none;padding:10px 12px;resize:vertical;transition:border-color .2s ease,box-shadow .2s ease;width:100%}.ai-chat-form-card__textarea:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.1)}.ai-chat-form-card__textarea::placeholder{color:var(--text-muted,#9ca3af)}.ai-chat-widget.dark .ai-chat-form-card__textarea,.chakra-ui-dark .ai-chat-form-card__textarea,.dark .ai-chat-form-card__textarea,[data-theme=dark] .ai-chat-form-card__textarea{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-form-card__textarea:focus,.chakra-ui-dark .ai-chat-form-card__textarea:focus,.dark .ai-chat-form-card__textarea:focus,[data-theme=dark] .ai-chat-form-card__textarea:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.2)}.ai-chat-form-card__options{display:flex;flex-direction:column;gap:8px}.ai-chat-form-card__option{align-items:center;background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);cursor:pointer;display:flex;gap:10px;padding:10px 12px;transition:border-color .15s,background .15s}.ai-chat-form-card__option:hover{background:rgba(59,130,246,.05);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-form-card__option,.chakra-ui-dark .ai-chat-form-card__option,.dark .ai-chat-form-card__option,[data-theme=dark] .ai-chat-form-card__option{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1)}.ai-chat-widget.dark .ai-chat-form-card__option:hover,.chakra-ui-dark .ai-chat-form-card__option:hover,.dark .ai-chat-form-card__option:hover,[data-theme=dark] .ai-chat-form-card__option:hover{background:rgba(59,130,246,.15);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-form-card__option input{accent-color:var(--action-accent,var(--primary-color,#3b82f6));margin:0}.ai-chat-form-card__option-text{color:var(--text-primary,#3e3e3e);font-size:14px}.ai-chat-widget.dark .ai-chat-form-card__option-text,.chakra-ui-dark .ai-chat-form-card__option-text,.dark .ai-chat-form-card__option-text,[data-theme=dark] .ai-chat-form-card__option-text{color:#fff}.ai-chat-form-card__rating{display:flex;flex-wrap:wrap;gap:8px}.ai-chat-form-card__rating-btn{align-items:center;background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);color:var(--text-primary,#3e3e3e);cursor:pointer;display:flex;font-size:14px;font-weight:500;height:40px;justify-content:center;transition:all .15s ease;width:40px}.ai-chat-form-card__rating-btn--selected,.ai-chat-form-card__rating-btn:hover{border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-form-card__rating-btn--selected{background:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-widget.dark .ai-chat-form-card__rating-btn,.chakra-ui-dark .ai-chat-form-card__rating-btn,.dark .ai-chat-form-card__rating-btn,[data-theme=dark] .ai-chat-form-card__rating-btn{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-form-card__rating-btn:hover,.chakra-ui-dark .ai-chat-form-card__rating-btn:hover,.dark .ai-chat-form-card__rating-btn:hover,[data-theme=dark] .ai-chat-form-card__rating-btn:hover{border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-form-card__rating-btn--selected,.chakra-ui-dark .ai-chat-form-card__rating-btn--selected,.dark .ai-chat-form-card__rating-btn--selected,[data-theme=dark] .ai-chat-form-card__rating-btn--selected{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-form-card__actions{align-items:center;border-top:1px solid var(--border-subtle,rgba(0,0,0,.08));display:flex;gap:8px;margin-top:16px;padding-top:16px}.ai-chat-widget.dark .ai-chat-form-card__actions,.chakra-ui-dark .ai-chat-form-card__actions,.dark .ai-chat-form-card__actions,[data-theme=dark] .ai-chat-form-card__actions{border-color:hsla(0,0%,100%,.08)}.ai-chat-form-card__actions-spacer{flex:1}.ai-chat-form-card__btn{border:none;border-radius:9999px;cursor:pointer;font-family:inherit;font-size:13px;font-weight:500;padding:8px 16px;transition:all .2s ease}.ai-chat-form-card__btn:disabled{cursor:not-allowed;opacity:.5}.ai-chat-form-card__btn--primary{background:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-form-card__btn--primary:hover:not(:disabled){opacity:.9;transform:translateY(-1px)}.ai-chat-form-card__btn--secondary{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);color:var(--text-primary,#3e3e3e)}.ai-chat-form-card__btn--secondary:hover:not(:disabled){border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-form-card__btn--secondary,.chakra-ui-dark .ai-chat-form-card__btn--secondary,.dark .ai-chat-form-card__btn--secondary,[data-theme=dark] .ai-chat-form-card__btn--secondary{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-form-card__btn--ghost{background:transparent;color:var(--text-muted,#71717a)}.ai-chat-form-card__btn--ghost:hover:not(:disabled){background:rgba(0,0,0,.05);color:var(--text-primary,#3e3e3e)}.ai-chat-widget.dark .ai-chat-form-card__btn--ghost:hover:not(:disabled),.chakra-ui-dark .ai-chat-form-card__btn--ghost:hover:not(:disabled),.dark .ai-chat-form-card__btn--ghost:hover:not(:disabled),[data-theme=dark] .ai-chat-form-card__btn--ghost:hover:not(:disabled){background:hsla(0,0%,100%,.05);color:#fff}.chat-fullpage{--fp-max-width:800px;--fp-padding-x:16px;--fp-padding-top-mobile:64px;--fp-padding-top-desktop:16px;--fp-padding-bottom:200px;--fp-input-bottom:0}.chat-fullpage .ai-chat-messages{background:transparent;height:100%;margin:0 auto;max-width:var(--fp-max-width);padding:var(--fp-padding-top-desktop) var(--fp-padding-x) var(--fp-padding-bottom)}@media (max-width:768px){.chat-fullpage .ai-chat-messages{padding-top:var(--fp-padding-top-mobile)}}.chat-fullpage .ai-chat-message{animation:none}.chat-fullpage .ai-chat-message.user{max-width:85%}.chat-fullpage .ai-chat-message.user .ai-chat-message-content{background:var(--bg-muted,#f4f4f5);border-radius:24px;color:#000;padding:8px 16px}.chat-fullpage.dark .ai-chat-message.user .ai-chat-message-content{background:var(--bg-muted,#27272a);color:#fff}.chat-fullpage .ai-chat-message.assistant{width:100%}.chat-fullpage .ai-chat-message.assistant .ai-chat-message-content{color:#000;padding:8px 16px}.chat-fullpage.dark .ai-chat-message.assistant .ai-chat-message-content{color:#fff}.chat-fullpage .ai-chat-message.tool{margin:0;padding:0;width:100%}.chat-fullpage .ai-chat-welcome{align-items:center;display:flex;flex-direction:column;gap:24px;justify-content:center;min-height:60vh;padding:24px;text-align:center}.chat-fullpage .ai-chat-welcome-title{font-size:32px;font-weight:600}.chat-fullpage .ai-chat-welcome-text{color:var(--text-muted,#71717a);font-size:18px;max-width:400px}.chat-fullpage .ai-chat-input-container{background:transparent;bottom:0;left:0;padding:16px 16px calc(16px + env(safe-area-inset-bottom));position:fixed;right:0;z-index:20}.chat-fullpage .ai-chat-input-container:after{background:var(--bg-primary,#fff);bottom:0;content:\"\";height:calc(40% + 16px);left:0;pointer-events:none;position:absolute;right:0;z-index:-1}.chat-fullpage.dark .ai-chat-input-container:after{background:var(--bg-primary,#18181b)}@media (min-width:769px){.chat-fullpage .ai-chat-input-container{background:transparent;bottom:var(--fp-input-bottom);left:50%;max-width:var(--fp-max-width);padding:0;position:absolute;right:auto;transform:translateX(-50%);width:100%}}.chat-fullpage .ai-chat-input-wrapper{background:var(--bg-muted,#f4f4f5);border:1px solid var(--border-muted,#e4e4e7);border-radius:24px;box-shadow:0 1px 8px rgba(0,0,0,.06);margin:0 auto;max-width:var(--fp-max-width)}.chat-fullpage.dark .ai-chat-input-wrapper{background:var(--bg-muted,#27272a);border-color:var(--border-muted,#3f3f46);box-shadow:0 1px 12px rgba(0,0,0,.25)}.chat-fullpage .ai-chat-scroll-button{bottom:100px}@media (min-width:769px){.chat-fullpage .ai-chat-scroll-button{bottom:90px}}.chat-fullpage .ai-chat-suggested-questions{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;max-width:600px}.chat-fullpage .ai-chat-suggested-question{border-radius:9999px;font-size:14px;padding:8px 16px}.chat-fullpage .ai-chat-follow-up-suggestions{margin-top:12px}.chat-fullpage .ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-default,#d4d4d8);color:#000}.chat-fullpage .ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#f4f4f5)}.chat-fullpage.dark .ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-subtle,#52525b);color:#fff}.chat-fullpage.dark .ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#3f3f46)}.chat-fullpage .ai-chat-typing{padding:8px 16px}@media (max-width:480px){body.ai-chat-widget-open{height:100%!important;overflow:hidden!important;position:fixed!important;touch-action:none!important;width:100%!important}.ai-chat-widget-container.is-open{height:100vh!important;height:100dvh!important;width:100vw!important;z-index:var(--widget-z-index,2147483647)!important}.ai-chat-widget-container.is-open,.ai-chat-widget-container.is-open .ai-chat-window{bottom:0!important;left:0!important;position:fixed!important;right:0!important;top:0!important}.ai-chat-widget-container.is-open .ai-chat-window{animation:none!important;border:none!important;border-radius:0!important;box-shadow:none!important;height:100%!important;max-height:100%!important;max-width:100%!important;outline:none!important;transform:none!important;width:100%!important}.ai-chat-widget-container.is-open .ai-chat-button{display:none!important;pointer-events:none!important;visibility:hidden!important}.ai-chat-widget-container.is-open .ai-chat-header{border-radius:0!important;flex-shrink:0;padding-left:max(16px,env(safe-area-inset-left));padding-right:max(16px,env(safe-area-inset-right));padding-top:max(12px,env(safe-area-inset-top));position:relative;z-index:100}.ai-chat-widget-container.is-open .ai-chat-messages{-webkit-overflow-scrolling:touch;flex:1;overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain;padding-bottom:120px;padding-left:max(16px,env(safe-area-inset-left));padding-right:max(16px,env(safe-area-inset-right));touch-action:pan-y}.ai-chat-widget-container.is-open .ai-chat-input-container{background:var(--bg-primary,#fff);bottom:0!important;left:0!important;padding:8px max(12px,env(safe-area-inset-right)) max(16px,calc(env(safe-area-inset-bottom) + 8px)) max(12px,env(safe-area-inset-left));position:fixed!important;right:0!important;z-index:100}.ai-chat-widget.dark .ai-chat-widget-container.is-open .ai-chat-input-container{background:var(--bg-primary,#282625)}.ai-chat-widget-container.is-open .ai-chat-input-container:after{display:none}.ai-chat-widget-container.is-open .ai-chat-input-wrapper{margin:0;max-width:100%}.ai-chat-widget-container.is-open .ai-chat-scroll-button{bottom:calc(80px + env(safe-area-inset-bottom))}.ai-chat-widget-container.is-open .ai-chat-welcome{padding:16px 0}.ai-chat-widget-container.is-open .ai-chat-welcome-title{font-size:24px}.ai-chat-widget-container.is-open .ai-chat-suggested-questions{align-items:stretch;flex-direction:column}.ai-chat-widget-container.is-open .ai-chat-suggested-question{text-align:center;width:100%}}@media (min-width:481px) and (max-width:768px){.ai-chat-widget-container.is-open .ai-chat-window{border-radius:22px 22px 44px 44px;max-height:calc(100vh - 100px);max-width:calc(100vw - 32px)}}";
30413
+ styleInject(css_248z$1);
30414
+
30415
+ var css_248z = ".ai-chat-data-policy-view{display:flex;flex:1;flex-direction:column;min-height:0;overflow:hidden}.ai-chat-data-policy-content{-webkit-overflow-scrolling:touch;flex:1;overflow-y:auto;padding:20px 16px 40px}.ai-chat-data-policy-intro{align-items:center;background:var(--bg-subtle,rgba(0,0,0,.02));border-radius:12px;display:flex;flex-direction:column;margin-bottom:20px;padding:16px;text-align:center}.ai-chat-widget.dark .ai-chat-data-policy-intro{background:var(--bg-subtle,hsla(0,0%,100%,.04))}.ai-chat-data-policy-icon{align-items:center;background:var(--primary-color,#07f);border-radius:12px;color:#fff;display:flex;height:48px;justify-content:center;margin-bottom:12px;width:48px}.ai-chat-data-policy-intro p{color:var(--text-secondary,#52525b);font-size:13px;line-height:1.5;margin:0}.ai-chat-widget.dark .ai-chat-data-policy-intro p{color:var(--text-secondary,#a1a1aa)}.ai-chat-data-policy-intro strong{color:var(--text-primary,#18181b)}.ai-chat-widget.dark .ai-chat-data-policy-intro strong{color:var(--text-primary,#fafafa)}.ai-chat-data-policy-section{margin-bottom:20px}.ai-chat-data-policy-section h3{color:var(--text-primary,#18181b);font-size:13px;font-weight:600;letter-spacing:.02em;margin:0 0 8px;text-transform:uppercase}.ai-chat-widget.dark .ai-chat-data-policy-section h3{color:var(--text-primary,#fafafa)}.ai-chat-data-policy-section ul{list-style:none;margin:0;padding:0}.ai-chat-data-policy-section li{color:var(--text-secondary,#52525b);font-size:12px;line-height:1.5;padding:8px 0 8px 16px;position:relative}.ai-chat-widget.dark .ai-chat-data-policy-section li{color:var(--text-secondary,#a1a1aa)}.ai-chat-data-policy-section li:before{background:var(--text-muted,#a1a1aa);border-radius:50%;content:\"\";height:4px;left:0;position:absolute;top:14px;width:4px}.ai-chat-data-policy-section li strong{color:var(--text-primary,#18181b)}.ai-chat-widget.dark .ai-chat-data-policy-section li strong{color:var(--text-primary,#fafafa)}.ai-chat-data-policy-section p{color:var(--text-secondary,#52525b);font-size:12px;line-height:1.5;margin:0}.ai-chat-widget.dark .ai-chat-data-policy-section p{color:var(--text-secondary,#a1a1aa)}.ai-chat-data-policy-warning{background:rgba(234,179,8,.1);border:1px solid rgba(234,179,8,.3);border-radius:8px;color:#92400e!important;padding:12px}.ai-chat-widget.dark .ai-chat-data-policy-warning{background:rgba(234,179,8,.15);border-color:rgba(234,179,8,.25);color:#fbbf24!important}";
29249
30416
  styleInject(css_248z);
29250
30417
 
29251
30418
  // Icon components mapping
@@ -29253,9 +30420,10 @@ const iconComponents = {
29253
30420
  FiMessageCircle: () => (jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntime.jsx("path", { d: "M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" }) })),
29254
30421
  FiChevronDown: () => (jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntime.jsx("polyline", { points: "6 9 12 15 18 9" }) })),
29255
30422
  };
29256
- const ChatWidget = ({ widgetId, apiUrl = window.location.origin, previewMode = false, previewConfig, position = 'bottom-right', primaryColor, size, headerTitle, welcomeTitle, welcomeMessage, placeholder, theme, suggestedQuestions, customStyles, currentRoute, defaultOpen = false, zIndex, onOpen, onClose, onMessage, onError, mode = 'bubble', }) => {
30423
+ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, previewMode = false, previewConfig, position = 'bottom-right', primaryColor, size, headerTitle, welcomeTitle, welcomeMessage, placeholder, welcomeBubbleText, theme, suggestedQuestions, customStyles, currentRoute, defaultOpen = false, zIndex, containerMode = false, onOpen, onClose, onMessage, onError, mode = 'bubble', }) => {
29257
30424
  const [isOpen, setIsOpen] = React.useState(defaultOpen);
29258
30425
  const [autoDetectedTheme, setAutoDetectedTheme] = React.useState('light');
30426
+ const [showWelcomeBubble, setShowWelcomeBubble] = React.useState(false);
29259
30427
  const widgetRef = React.useRef(null);
29260
30428
  const containerRef = React.useRef(null);
29261
30429
  // Determine mode
@@ -29277,10 +30445,9 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, previewMode = f
29277
30445
  showChatHistory: true,
29278
30446
  showTimestamps: true,
29279
30447
  showTypingIndicator: true,
30448
+ showToolCalls: false,
29280
30449
  enableFileUpload: false,
29281
30450
  enableFeedback: true,
29282
- showSources: false,
29283
- sourceDisplayMode: 'none',
29284
30451
  },
29285
30452
  behavior: {
29286
30453
  agentic: false,
@@ -29317,7 +30484,6 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, previewMode = f
29317
30484
  const messages = previewMode ? [] : chatHook.messages;
29318
30485
  const isLoading = previewMode ? false : chatHook.isLoading;
29319
30486
  const isTyping = previewMode ? false : chatHook.isTyping;
29320
- const error = previewMode ? null : chatHook.error;
29321
30487
  const config = previewMode ? mergedPreviewConfig : chatHook.config;
29322
30488
  const sendMessage = previewMode ? (() => Promise.resolve()) : chatHook.sendMessage;
29323
30489
  const submitFeedback = previewMode ? (() => Promise.resolve()) : chatHook.submitFeedback;
@@ -29352,8 +30518,13 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, previewMode = f
29352
30518
  mediaQuery.removeEventListener('change', handleMediaChange);
29353
30519
  };
29354
30520
  }, [config]);
29355
- // Handle auto-open (only for bubble mode)
30521
+ // Check if device is mobile
30522
+ const isMobile = typeof window !== 'undefined' && window.innerWidth <= 480;
30523
+ // Handle auto-open (only for bubble mode, disabled on mobile)
29356
30524
  React.useEffect(() => {
30525
+ // Never auto-open on mobile devices
30526
+ if (isMobile)
30527
+ return undefined;
29357
30528
  if (!isEmbedded && config?.settings.autoOpen) {
29358
30529
  const delay = config.settings.autoOpenDelay || 0;
29359
30530
  const timer = setTimeout(() => {
@@ -29363,7 +30534,7 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, previewMode = f
29363
30534
  return () => clearTimeout(timer);
29364
30535
  }
29365
30536
  return undefined;
29366
- }, [config, onOpen, isEmbedded]);
30537
+ }, [config, onOpen, isEmbedded, isMobile]);
29367
30538
  // Handle close on Escape key (only for bubble mode)
29368
30539
  React.useEffect(() => {
29369
30540
  if (!isOpen || isEmbedded)
@@ -29377,6 +30548,37 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, previewMode = f
29377
30548
  document.addEventListener('keydown', handleEscapeKey);
29378
30549
  return () => document.removeEventListener('keydown', handleEscapeKey);
29379
30550
  }, [isOpen, onClose, isEmbedded]);
30551
+ // Handle body scroll lock on mobile when widget is open
30552
+ React.useEffect(() => {
30553
+ if (!isOpen || isEmbedded)
30554
+ return;
30555
+ // Only apply scroll lock on mobile
30556
+ const checkMobile = window.innerWidth <= 480;
30557
+ if (!checkMobile)
30558
+ return;
30559
+ // Add class to body to lock scrolling
30560
+ document.body.classList.add('ai-chat-widget-open');
30561
+ return () => {
30562
+ document.body.classList.remove('ai-chat-widget-open');
30563
+ };
30564
+ }, [isOpen, isEmbedded]);
30565
+ // Handle welcome bubble visibility per session
30566
+ // Shows on each new session if welcomeBubbleText is configured
30567
+ React.useEffect(() => {
30568
+ if (isEmbedded || previewMode)
30569
+ return;
30570
+ const bubbleText = welcomeBubbleText ?? config?.appearance?.welcomeBubbleText;
30571
+ if (!bubbleText) {
30572
+ setShowWelcomeBubble(false);
30573
+ return;
30574
+ }
30575
+ // Check if bubble was already dismissed this session
30576
+ const storageKey = `ai-chat-bubble-dismissed-${widgetId || 'default'}`;
30577
+ const wasDismissed = sessionStorage.getItem(storageKey) === 'true';
30578
+ if (!wasDismissed && !isOpen) {
30579
+ setShowWelcomeBubble(true);
30580
+ }
30581
+ }, [widgetId, welcomeBubbleText, config, isOpen, isEmbedded, previewMode]);
29380
30582
  // Determine theme - use prop override if provided, otherwise auto-detect
29381
30583
  const appearanceConfig = config?.appearance;
29382
30584
  const effectiveTheme = theme ?? autoDetectedTheme;
@@ -29390,6 +30592,7 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, previewMode = f
29390
30592
  const effectiveWelcomeTitle = welcomeTitle ?? appearanceConfig?.welcomeTitle ?? '';
29391
30593
  const effectiveWelcomeMessage = welcomeMessage ?? appearanceConfig?.welcomeMessage ?? '';
29392
30594
  const effectivePlaceholder = placeholder ?? appearanceConfig?.placeholder ?? '';
30595
+ const effectiveWelcomeBubbleText = welcomeBubbleText ?? appearanceConfig?.welcomeBubbleText ?? '';
29393
30596
  // Generate styles using simplified theme system
29394
30597
  const simpleAppearance = {
29395
30598
  accentColor};
@@ -29411,6 +30614,18 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, previewMode = f
29411
30614
  return;
29412
30615
  const newState = !isOpen;
29413
30616
  setIsOpen(newState);
30617
+ // Dismiss welcome bubble when chat is opened
30618
+ if (newState && showWelcomeBubble) {
30619
+ setShowWelcomeBubble(false);
30620
+ // Store in sessionStorage so it doesn't show again this session
30621
+ const storageKey = `ai-chat-bubble-dismissed-${widgetId || 'default'}`;
30622
+ try {
30623
+ sessionStorage.setItem(storageKey, 'true');
30624
+ }
30625
+ catch {
30626
+ // Ignore storage errors
30627
+ }
30628
+ }
29414
30629
  if (newState) {
29415
30630
  onOpen?.();
29416
30631
  }
@@ -29441,13 +30656,13 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, previewMode = f
29441
30656
  const IconComponent = isOpen ? iconComponents.FiChevronDown : iconComponents.FiMessageCircle;
29442
30657
  // Embedded mode renders directly without wrapper positioning
29443
30658
  if (isEmbedded) {
29444
- return (jsxRuntime.jsx("div", { ref: containerRef, className: `ai-chat-widget ai-chat-widget-embedded ${effectiveTheme}`, style: { ...mergedStyles, width: '100%', height: '100%' }, children: jsxRuntime.jsx(ChatWindow, { messages: messages, isLoading: isLoading, isTyping: isTyping, error: error, config: config, onSendMessage: sendMessage, onClose: () => { }, onFeedback: handleFeedback, onActionClick: handleActionClick, conversations: conversations, onLoadConversations: loadConversations, onSwitchConversation: switchConversation, onStartNewConversation: startNewConversation, onDeleteConversation: deleteConversation, currentConversationId: conversationId, headerTitleOverride: effectiveHeaderTitle, welcomeTitleOverride: effectiveWelcomeTitle, welcomeMessageOverride: effectiveWelcomeMessage, placeholderOverride: effectivePlaceholder, suggestedQuestionsOverride: suggestedQuestions }) }));
30659
+ return (jsxRuntime.jsx("div", { ref: containerRef, className: `ai-chat-widget ai-chat-widget-embedded ${effectiveTheme}`, style: { ...mergedStyles, width: '100%', height: '100%' }, children: jsxRuntime.jsx(ChatWindow, { messages: messages, isLoading: isLoading, isTyping: isTyping, config: config, onSendMessage: sendMessage, onClose: () => { }, onFeedback: handleFeedback, onActionClick: handleActionClick, conversations: conversations, onLoadConversations: loadConversations, onSwitchConversation: switchConversation, onStartNewConversation: startNewConversation, onDeleteConversation: deleteConversation, currentConversationId: conversationId, headerTitleOverride: effectiveHeaderTitle, welcomeTitleOverride: effectiveWelcomeTitle, welcomeMessageOverride: effectiveWelcomeMessage, placeholderOverride: effectivePlaceholder, suggestedQuestionsOverride: suggestedQuestions }) }));
29445
30660
  }
29446
- return (jsxRuntime.jsx("div", { ref: containerRef, className: `ai-chat-widget ${effectiveTheme}`, style: mergedStyles, children: jsxRuntime.jsxs("div", { ref: widgetRef, className: `ai-chat-widget-container ${effectivePosition} ${isOpen ? 'is-open' : ''}`, children: [isOpen && (jsxRuntime.jsx(ChatWindow, { messages: messages, isLoading: isLoading, isTyping: isTyping, error: error, config: config, onSendMessage: sendMessage, onClose: handleToggle, onFeedback: handleFeedback, onActionClick: handleActionClick,
30661
+ return (jsxRuntime.jsx("div", { ref: containerRef, className: `ai-chat-widget ${effectiveTheme}`, style: mergedStyles, children: jsxRuntime.jsxs("div", { ref: widgetRef, className: `ai-chat-widget-container ${effectivePosition} ${isOpen ? 'is-open' : ''} ${containerMode ? 'container-mode' : ''}`, children: [isOpen && (jsxRuntime.jsx(ChatWindow, { messages: messages, isLoading: isLoading, isTyping: isTyping, config: config, onSendMessage: sendMessage, onClose: handleToggle, onFeedback: handleFeedback, onActionClick: handleActionClick,
29447
30662
  // Chat history props (only active when persistConversation is true)
29448
30663
  conversations: conversations, onLoadConversations: loadConversations, onSwitchConversation: switchConversation, onStartNewConversation: startNewConversation, onDeleteConversation: deleteConversation, currentConversationId: conversationId,
29449
30664
  // Override props for live preview
29450
- headerTitleOverride: effectiveHeaderTitle, welcomeTitleOverride: effectiveWelcomeTitle, welcomeMessageOverride: effectiveWelcomeMessage, placeholderOverride: effectivePlaceholder, suggestedQuestionsOverride: suggestedQuestions })), jsxRuntime.jsx("button", { className: `ai-chat-button ${isOpen ? 'is-open' : ''}`, onClick: handleToggle, "aria-label": isOpen ? "Minimize chat" : "Open chat", children: jsxRuntime.jsx("div", { className: "ai-chat-button-svg", children: jsxRuntime.jsx(IconComponent, {}) }) })] }) }));
30665
+ headerTitleOverride: effectiveHeaderTitle, welcomeTitleOverride: effectiveWelcomeTitle, welcomeMessageOverride: effectiveWelcomeMessage, placeholderOverride: effectivePlaceholder, suggestedQuestionsOverride: suggestedQuestions })), !isOpen && effectiveWelcomeBubbleText && (previewMode || showWelcomeBubble) && (jsxRuntime.jsx("div", { className: "ai-chat-welcome-bubble", onClick: handleToggle, children: jsxRuntime.jsx("span", { children: effectiveWelcomeBubbleText }) })), jsxRuntime.jsx("button", { className: `ai-chat-button ${isOpen ? 'is-open' : ''}`, onClick: handleToggle, "aria-label": isOpen ? "Minimize chat" : "Open chat", children: jsxRuntime.jsx("div", { className: "ai-chat-button-svg", children: jsxRuntime.jsx(IconComponent, {}) }) })] }) }));
29451
30666
  };
29452
30667
 
29453
30668
  exports.ApiError = ApiError;