@chatwidgetai/chat-widget 0.3.0 → 0.3.6

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 +1903 -437
  2. package/dist/ai-chat-widget.umd.js.map +1 -1
  3. package/dist/api/client.d.ts +11 -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 +1 -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} +4 -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 +2 -0
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.esm.js +1904 -438
  30. package/dist/index.esm.js.map +1 -1
  31. package/dist/index.js +1904 -437
  32. package/dist/index.js.map +1 -1
  33. package/dist/types/index.d.ts +22 -0
  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');
@@ -226,6 +237,33 @@ class WidgetApiClient {
226
237
  return typeof data === 'object' && data !== null && 'type' in data;
227
238
  });
228
239
  }
240
+ async *dismissAgentMessageStream(conversationId, toolCallId, signal) {
241
+ const headers = {
242
+ 'Content-Type': 'application/json',
243
+ };
244
+ if (this.config.currentRoute) {
245
+ headers['X-Current-Route'] = this.config.currentRoute;
246
+ }
247
+ const response = await fetch(`${this.config.apiUrl}/api/widget/${this.config.widgetId}/agent/dismiss`, {
248
+ method: 'POST',
249
+ headers,
250
+ body: JSON.stringify({
251
+ conversationId: conversationId,
252
+ toolCallId,
253
+ reason: "user",
254
+ }),
255
+ signal,
256
+ });
257
+ if (response.status === 204) {
258
+ return;
259
+ }
260
+ if (!response.ok) {
261
+ throw await buildApiError(response, 'Failed to dismiss action');
262
+ }
263
+ yield* parseSSEStream(response, (data) => {
264
+ return typeof data === 'object' && data !== null && 'type' in data;
265
+ });
266
+ }
229
267
  /**
230
268
  * Submit feedback for a message
231
269
  */
@@ -288,6 +326,27 @@ class WidgetApiClient {
288
326
  return [];
289
327
  }
290
328
  }
329
+ /**
330
+ * Create a demo conversation with preset messages
331
+ * Used when demo animation completes to persist the demo conversation to the database
332
+ */
333
+ async createDemoConversation(userMessage, assistantMessage) {
334
+ const response = await fetch(`${this.config.apiUrl}/api/widget/${this.config.widgetId}/demo-conversation`, {
335
+ method: 'POST',
336
+ headers: {
337
+ 'Content-Type': 'application/json',
338
+ },
339
+ body: JSON.stringify({
340
+ userMessage,
341
+ assistantMessage,
342
+ timeZone: this.getTimeZone(),
343
+ }),
344
+ });
345
+ if (!response.ok) {
346
+ throw await buildApiError(response, 'Failed to create demo conversation');
347
+ }
348
+ return response.json();
349
+ }
291
350
  /**
292
351
  * Validate widget access
293
352
  */
@@ -27118,22 +27177,19 @@ function ScrollButton({ onClick, visible, className = '' }) {
27118
27177
  const formatToolName = (name) => {
27119
27178
  return name
27120
27179
  .replace(/^(action_|tool_)/, '')
27180
+ .replace(/-/g, '_')
27121
27181
  .split('_')
27122
27182
  .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
27123
27183
  .join(' ');
27124
27184
  };
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
27185
  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))) })] }));
27186
+ 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
27187
  }
27132
27188
 
27133
27189
  // SVG Icon components
27134
27190
  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
27191
  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" }) }));
27192
+ 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
27193
  const FeedbackButtons = ({ messageId, currentFeedback, onFeedback, }) => {
27138
27194
  const [isSubmitting, setIsSubmitting] = React.useState(false);
27139
27195
  const [submitted, setSubmitted] = React.useState(false);
@@ -27154,10 +27210,10 @@ const FeedbackButtons = ({ messageId, currentFeedback, onFeedback, }) => {
27154
27210
  setIsSubmitting(false);
27155
27211
  }
27156
27212
  };
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" })] }))] }));
27213
+ 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" })] }))] }));
27158
27214
  };
27159
27215
 
27160
- const Message = ({ message, showTimestamp = true, enableFeedback = true, onFeedback, getActionRenderer, accentColor, }) => {
27216
+ const Message = ({ message, showTimestamp = true, enableFeedback = true, onFeedback, }) => {
27161
27217
  const formatTime = (timestamp) => {
27162
27218
  const date = typeof timestamp === 'string' ? new Date(timestamp) : timestamp;
27163
27219
  return date.toLocaleTimeString('en-US', {
@@ -27177,15 +27233,15 @@ const Message = ({ message, showTimestamp = true, enableFeedback = true, onFeedb
27177
27233
  return null;
27178
27234
  }
27179
27235
  // AI message rendering
27236
+ // Note: Actions are rendered by ToolMessageGroup for tool messages, not here
27180
27237
  if (isAssistant) {
27181
27238
  const aiContent = message.message.content || '';
27182
27239
  const hasContent = aiContent.trim().length > 0;
27183
27240
  if (!hasContent)
27184
27241
  return null;
27185
- const actionRenderer = message.action && getActionRenderer
27186
- ? getActionRenderer(message.action.implementation)
27187
- : undefined;
27188
- 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, accentColor), 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 }))] }))] }));
27242
+ 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: {
27243
+ table: ({ children, ...props }) => (jsxRuntime.jsx("div", { className: "table-wrapper", children: jsxRuntime.jsx("div", { className: "table-scroll", children: jsxRuntime.jsx("table", { ...props, children: children }) }) })),
27244
+ }, 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 }))] }))] }));
27189
27245
  }
27190
27246
  // System message rendering
27191
27247
  if (isSystem) {
@@ -27199,35 +27255,86 @@ const Message = ({ message, showTimestamp = true, enableFeedback = true, onFeedb
27199
27255
  return null;
27200
27256
  };
27201
27257
 
27202
- const ToolMessageGroup = ({ messages, getActionRenderer, showToolIndicator = true, accentColor }) => {
27203
- const actionMessages = messages.filter(message => message.action);
27258
+ // Centralized action state logic
27259
+ function isActionComplete(state) {
27260
+ if (!state)
27261
+ return false;
27262
+ const TERMINAL_STATUSES = [
27263
+ 'completed', 'booked', 'scheduled', 'cancelled', 'failed', 'error',
27264
+ 'displaying', 'clicked', 'contacted', 'submitted', 'sent'
27265
+ ];
27266
+ const status = state.status;
27267
+ if (typeof status === 'string' && TERMINAL_STATUSES.includes(status)) {
27268
+ return true;
27269
+ }
27270
+ // For non-halting actions (query_contact_directory, etc.) with results/success
27271
+ if (!status && (state.success !== undefined || state.results !== undefined)) {
27272
+ return true;
27273
+ }
27274
+ return false;
27275
+ }
27276
+ function isActionLoading(message) {
27277
+ if (!message.action)
27278
+ return false;
27279
+ if (message.action.done)
27280
+ return false;
27281
+ if (message.isStreaming)
27282
+ return true;
27283
+ const state = message.action.state;
27284
+ return !isActionComplete(state);
27285
+ }
27286
+ const ToolMessageGroup = ({ messages, getActionRenderer, showToolIndicator = true, accentColor, variant, onActionDismiss, }) => {
27287
+ const visibleMessages = messages.filter(message => !message.action?.hidden);
27288
+ const actionMessages = visibleMessages.filter(message => message.action);
27289
+ // Debug logging
27290
+ console.log('[DEBUG ToolMessageGroup] ========================================');
27291
+ console.log('[DEBUG ToolMessageGroup] Total messages:', messages.length);
27292
+ console.log('[DEBUG ToolMessageGroup] Messages with action:', actionMessages.length);
27293
+ console.log('[DEBUG ToolMessageGroup] hasGetActionRenderer:', !!getActionRenderer);
27294
+ messages.forEach((msg, i) => {
27295
+ console.log(`[DEBUG ToolMessageGroup] Message ${i}:`, {
27296
+ id: msg.id,
27297
+ role: msg.message.role,
27298
+ hasAction: !!msg.action,
27299
+ actionImpl: msg.action?.implementation,
27300
+ toolExecuting: msg.toolExecuting,
27301
+ });
27302
+ });
27303
+ actionMessages.forEach((msg, i) => {
27304
+ const impl = msg.action?.implementation || '';
27305
+ const renderer = getActionRenderer?.(impl);
27306
+ console.log(`[DEBUG ToolMessageGroup] Action ${i}:`, {
27307
+ implementation: impl,
27308
+ hasRenderer: !!renderer,
27309
+ rendererType: renderer ? typeof renderer : 'undefined',
27310
+ state: msg.action?.state,
27311
+ });
27312
+ });
27204
27313
  // If tool indicator is hidden AND there are no action cards to render, don't render anything
27205
- // This prevents empty wrapper divs that cause layout jumping
27206
27314
  if (!showToolIndicator && actionMessages.length === 0) {
27207
27315
  return null;
27208
27316
  }
27209
- const badges = messages.map((message) => {
27317
+ const badges = visibleMessages.map((message) => {
27210
27318
  const toolName = message.toolExecuting || message.message.name || 'Tool';
27211
27319
  const hasError = message.isError || false;
27212
- const actionState = message.action?.state;
27213
- const actionStatus = actionState?.status;
27214
- const terminalStatuses = ['completed', 'booked', 'scheduled', 'failed', 'cancelled', 'displaying', 'clicked'];
27215
- const isTerminalStatus = actionStatus && terminalStatuses.includes(actionStatus);
27216
- const isDone = message.action ? (message.action.done ?? isTerminalStatus ?? false) : !message.isStreaming;
27217
- const isLoading = !isDone;
27320
+ const loading = isActionLoading(message);
27218
27321
  return {
27219
27322
  id: message.id,
27220
27323
  name: toolName,
27221
- status: isLoading ? 'loading' : hasError ? 'error' : 'completed',
27324
+ status: loading ? 'loading' : hasError ? 'error' : 'completed',
27222
27325
  };
27223
27326
  });
27224
27327
  return (jsxRuntime.jsxs("div", { className: "ai-chat-message tool", children: [showToolIndicator && jsxRuntime.jsx(ToolIndicator, { badges: badges }), actionMessages.map((message) => {
27225
- if (!message.action || !getActionRenderer)
27328
+ if (!message.action || !getActionRenderer) {
27329
+ console.log('[ToolMessageGroup] Skipping - no action or renderer:', { hasAction: !!message.action, hasGetRenderer: !!getActionRenderer });
27226
27330
  return null;
27331
+ }
27227
27332
  const renderer = getActionRenderer(message.action.implementation);
27228
- if (!renderer)
27333
+ if (!renderer) {
27334
+ console.log('[ToolMessageGroup] No renderer for:', message.action.implementation);
27229
27335
  return null;
27230
- return (jsxRuntime.jsx("div", { className: "ai-chat-tool-action", children: renderer(message, accentColor) }, `action-${message.id}`));
27336
+ }
27337
+ return (jsxRuntime.jsx("div", { className: "ai-chat-tool-action", children: renderer(message, accentColor, variant, onActionDismiss) }, `action-${message.id}`));
27231
27338
  })] }));
27232
27339
  };
27233
27340
 
@@ -27289,12 +27396,17 @@ const FollowUpSuggestions = ({ suggestions, onQuestionClick, onActionClick, acce
27289
27396
  };
27290
27397
 
27291
27398
  const MessageList = (props) => {
27292
- const { messages, isTyping = false, showTypingIndicator = true, showTimestamps = true, showToolCalls = false, enableFeedback = true, welcomeTitle, welcomeMessage, suggestedQuestions, accentColor, onSuggestedQuestionClick, onActionClick, onFeedback, onScrollStateChange, getActionRenderer, } = props;
27399
+ const { messages, isTyping = false, showTypingIndicator = true, showTimestamps = true, showToolCalls = false, enableFeedback = true, welcomeTitle, welcomeMessage, suggestedQuestions, accentColor, onSuggestedQuestionClick, onActionClick, onActionDismiss, onFeedback, onScrollStateChange, getActionRenderer, variant, } = props;
27293
27400
  const containerRef = React.useRef(null);
27294
27401
  const messagesEndRef = React.useRef(null);
27295
27402
  const [showScrollButton, setShowScrollButton] = React.useState(false);
27296
27403
  const prevMessageCountRef = React.useRef(0);
27297
- const hasActiveAction = React.useMemo(() => messages.some(msg => msg.action?.state?.status && !['completed', 'booked', 'failed'].includes(msg.action.state.status)), [messages]);
27404
+ const visibleMessages = React.useMemo(() => messages.filter((message) => !message.action?.hidden), [messages]);
27405
+ const hasActiveAction = React.useMemo(() => {
27406
+ // Find the last tool message and check if its action is still active (not done)
27407
+ const lastToolMsg = [...visibleMessages].reverse().find(msg => msg.message.role === 'tool');
27408
+ return lastToolMsg?.action && lastToolMsg.action.done !== true;
27409
+ }, [visibleMessages]);
27298
27410
  const checkScrollPosition = React.useCallback(() => {
27299
27411
  const c = containerRef.current;
27300
27412
  if (!c)
@@ -27317,7 +27429,7 @@ const MessageList = (props) => {
27317
27429
  const c = containerRef.current;
27318
27430
  if (!c)
27319
27431
  return;
27320
- const count = messages.length;
27432
+ const count = visibleMessages.length;
27321
27433
  const isNew = count > prevMessageCountRef.current;
27322
27434
  prevMessageCountRef.current = count;
27323
27435
  if (count === 0) {
@@ -27328,17 +27440,33 @@ const MessageList = (props) => {
27328
27440
  messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
27329
27441
  }
27330
27442
  checkScrollPosition();
27331
- }, [messages, isTyping, checkScrollPosition]);
27443
+ }, [visibleMessages, isTyping, checkScrollPosition]);
27332
27444
  const groupedMessages = React.useMemo(() => {
27445
+ console.log('[DEBUG MessageList] ========================================');
27446
+ console.log('[DEBUG MessageList] Processing messages:', visibleMessages.length);
27447
+ visibleMessages.forEach((m, i) => {
27448
+ console.log(`[DEBUG MessageList] Message ${i}:`, {
27449
+ id: m.id,
27450
+ role: m.message.role,
27451
+ hasAction: !!m.action,
27452
+ actionImpl: m.action?.implementation,
27453
+ content: (m.message.content || '').substring(0, 50),
27454
+ });
27455
+ });
27333
27456
  const result = [];
27334
27457
  let toolGroup = [];
27335
- const flush = () => { if (toolGroup.length) {
27336
- result.push({ type: 'tool-group', messages: [...toolGroup] });
27337
- toolGroup = [];
27338
- } };
27339
- for (const m of messages) {
27340
- if (m.message.role === 'tool')
27458
+ const flush = () => {
27459
+ if (toolGroup.length) {
27460
+ console.log('[DEBUG MessageList] Flushing tool group with', toolGroup.length, 'messages');
27461
+ result.push({ type: 'tool-group', messages: [...toolGroup] });
27462
+ toolGroup = [];
27463
+ }
27464
+ };
27465
+ for (const m of visibleMessages) {
27466
+ if (m.message.role === 'tool') {
27467
+ console.log('[DEBUG MessageList] Adding to tool group:', m.id);
27341
27468
  toolGroup.push(m);
27469
+ }
27342
27470
  else if (m.message.role === 'user') {
27343
27471
  flush();
27344
27472
  result.push({ type: 'message', message: m });
@@ -27350,6 +27478,7 @@ const MessageList = (props) => {
27350
27478
  flush();
27351
27479
  result.push({ type: 'message', message: m });
27352
27480
  }
27481
+ // Don't flush on empty assistant messages - let tools continue grouping
27353
27482
  }
27354
27483
  else {
27355
27484
  flush();
@@ -27357,18 +27486,27 @@ const MessageList = (props) => {
27357
27486
  }
27358
27487
  }
27359
27488
  flush();
27489
+ console.log('[DEBUG MessageList] Final grouped result:', result.length, 'items');
27490
+ result.forEach((item, i) => {
27491
+ if (item.type === 'tool-group') {
27492
+ console.log(`[DEBUG MessageList] Group ${i}: tool-group with ${item.messages.length} messages`);
27493
+ }
27494
+ else {
27495
+ console.log(`[DEBUG MessageList] Group ${i}: message (${item.message.message.role})`);
27496
+ }
27497
+ });
27360
27498
  return result;
27361
- }, [messages]);
27362
- const hasSuggestions = messages.length === 0 && onSuggestedQuestionClick && suggestedQuestions?.length;
27499
+ }, [visibleMessages]);
27500
+ const hasSuggestions = visibleMessages.length === 0 && onSuggestedQuestionClick && suggestedQuestions?.length;
27363
27501
  const showWelcome = welcomeTitle || welcomeMessage || hasSuggestions;
27364
27502
  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) => {
27365
27503
  if (item.type === 'tool-group') {
27366
- return jsxRuntime.jsx(ToolMessageGroup, { messages: item.messages, getActionRenderer: getActionRenderer, showToolIndicator: showToolCalls, accentColor: accentColor }, `tg-${i}`);
27504
+ return (jsxRuntime.jsx(ToolMessageGroup, { messages: item.messages, getActionRenderer: getActionRenderer, showToolIndicator: showToolCalls, accentColor: accentColor, variant: variant, onActionDismiss: onActionDismiss }, `tg-${i}`));
27367
27505
  }
27368
27506
  const isLast = i === groupedMessages.length - 1;
27369
27507
  const hasFollowUp = item.message.message.role === 'assistant' && item.message.suggestions?.length && isLast && !isTyping;
27370
27508
  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));
27371
- }), isTyping && showTypingIndicator && !hasActiveAction && messages.length > 0 && jsxRuntime.jsx(TypingIndicator, {}), jsxRuntime.jsx("div", { ref: messagesEndRef })] }));
27509
+ }), isTyping && showTypingIndicator && !hasActiveAction && visibleMessages.length > 0 && jsxRuntime.jsx(TypingIndicator, {}), jsxRuntime.jsx("div", { ref: messagesEndRef })] }));
27372
27510
  };
27373
27511
 
27374
27512
  const ALLOWED_EXTENSIONS = ['.pdf', '.doc', '.docx', '.txt', '.md', '.csv'];
@@ -27382,7 +27520,7 @@ const formatFileSize = (bytes) => {
27382
27520
  return (bytes / 1024).toFixed(1) + ' KB';
27383
27521
  return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
27384
27522
  };
27385
- const MessageInput = ({ onSend, placeholder = 'Type your message...', disabled = false, enableFileUpload = false, separateFromChat = true, }) => {
27523
+ const MessageInput = ({ onSend, placeholder = 'Type your message...', disabled = false, enableFileUpload = false, separateFromChat = true, showDataPolicy = true, onDataPolicyClick, }) => {
27386
27524
  const [value, setValue] = React.useState('');
27387
27525
  const [selectedFiles, setSelectedFiles] = React.useState([]);
27388
27526
  const textareaRef = React.useRef(null);
@@ -27417,10 +27555,14 @@ const MessageInput = ({ onSend, placeholder = 'Type your message...', disabled =
27417
27555
  }
27418
27556
  };
27419
27557
  const canSend = value.trim() || selectedFiles.length > 0;
27420
- 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" })] }) })] })] }));
27558
+ 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: "AI-generated responses may be inaccurate." }), onDataPolicyClick && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [' ', jsxRuntime.jsx("button", { type: "button", className: "ai-chat-data-policy-link", onClick: onDataPolicyClick, children: "Privacy Notice" })] }))] }))] }));
27421
27559
  };
27422
27560
 
27423
- function groupSlotsByDate(slots) {
27561
+ const CloseButton = ({ onClick, className = "", ariaLabel = "Close", }) => {
27562
+ return (jsxRuntime.jsx("button", { type: "button", className: `ai-chat-action-close-btn ${className}`, onClick: onClick, "aria-label": ariaLabel, children: jsxRuntime.jsx("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "2", children: jsxRuntime.jsx("path", { d: "M1 1L13 13M1 13L13 1" }) }) }));
27563
+ };
27564
+
27565
+ function groupSlotsByDate$1(slots) {
27424
27566
  const grouped = new Map();
27425
27567
  for (const slot of slots) {
27426
27568
  if (!slot || typeof slot !== 'object' || !slot.startTime || typeof slot.startTime !== 'string') {
@@ -27434,7 +27576,7 @@ function groupSlotsByDate(slots) {
27434
27576
  }
27435
27577
  return grouped;
27436
27578
  }
27437
- function formatDate(dateStr) {
27579
+ function formatDate$1(dateStr) {
27438
27580
  try {
27439
27581
  const date = new Date(dateStr);
27440
27582
  return new Intl.DateTimeFormat("en-US", {
@@ -27447,19 +27589,19 @@ function formatDate(dateStr) {
27447
27589
  return dateStr;
27448
27590
  }
27449
27591
  }
27450
- function CalendarIcon() {
27592
+ function CalendarIcon$1() {
27451
27593
  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" }) }));
27452
27594
  }
27453
- function CheckIcon() {
27595
+ function CheckIcon$1() {
27454
27596
  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" }) }));
27455
27597
  }
27456
- function ExternalLinkIcon$1() {
27598
+ function ExternalLinkIcon$2() {
27457
27599
  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" })] }));
27458
27600
  }
27459
- function Skeleton({ width, height, borderRadius = '4px' }) {
27601
+ function Skeleton$2({ width, height, borderRadius = '4px' }) {
27460
27602
  return (jsxRuntime.jsx("div", { className: "ai-chat-action-skeleton-item", style: { width, height, borderRadius } }));
27461
27603
  }
27462
- function GoogleCalendarCard({ action, onComplete, accentColor, className = '' }) {
27604
+ function GoogleCalendarCard({ action, onComplete, onDismiss, accentColor, className = '' }) {
27463
27605
  const state = action.state;
27464
27606
  const rawSlots = state.availableSlots;
27465
27607
  const availableSlots = Array.isArray(rawSlots)
@@ -27473,13 +27615,12 @@ function GoogleCalendarCard({ action, onComplete, accentColor, className = '' })
27473
27615
  : [];
27474
27616
  const allowTopic = state.allowTopic !== false;
27475
27617
  const isBooked = state.status === "booked";
27476
- const slotsByDate = groupSlotsByDate(availableSlots);
27618
+ const slotsByDate = groupSlotsByDate$1(availableSlots);
27477
27619
  const dates = Array.from(slotsByDate.keys()).sort();
27478
27620
  const [selectedDate, setSelectedDate] = React.useState(dates[0] ?? "");
27479
27621
  const [selectedSlot, setSelectedSlot] = React.useState(null);
27480
27622
  const [topic, setTopic] = React.useState("");
27481
27623
  const [error, setError] = React.useState(null);
27482
- const [isSubmitting, setIsSubmitting] = React.useState(false);
27483
27624
  const slotsForSelectedDate = selectedDate ? slotsByDate.get(selectedDate) ?? [] : [];
27484
27625
  const accentStyle = accentColor ? { '--action-accent': accentColor } : {};
27485
27626
  const onConfirm = () => {
@@ -27492,8 +27633,252 @@ function GoogleCalendarCard({ action, onComplete, accentColor, className = '' })
27492
27633
  return;
27493
27634
  }
27494
27635
  setError(null);
27636
+ onComplete?.(action.toolCallId, {
27637
+ ...action.state,
27638
+ selectedSlot: {
27639
+ startTime: selectedSlot.startTime,
27640
+ endTime: selectedSlot.endTime,
27641
+ },
27642
+ topic: allowTopic ? topic.trim() : null,
27643
+ });
27644
+ };
27645
+ const handleDismiss = () => {
27646
+ onDismiss?.(action.toolCallId);
27647
+ };
27648
+ // Booked state
27649
+ if (isBooked) {
27650
+ const bookedSlot = state.selectedSlot;
27651
+ const bookedTopic = state.topic;
27652
+ const eventLink = state.bookedEventLink;
27653
+ 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, {})] }))] })] }));
27654
+ }
27655
+ // Skeleton loading state - show when waiting for backend after user confirms
27656
+ const isWaitingForBackend = !action.done && state.selectedSlot && !isBooked;
27657
+ if (isWaitingForBackend) {
27658
+ 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$2, { width: "28px", height: "28px", borderRadius: "50%" }), jsxRuntime.jsx(Skeleton$2, { width: "180px", height: "20px", borderRadius: "4px" })] }), jsxRuntime.jsxs("div", { className: "ai-chat-action-skeleton-box", children: [jsxRuntime.jsx(Skeleton$2, { width: "60px", height: "12px", borderRadius: "4px" }), jsxRuntime.jsx(Skeleton$2, { width: "120px", height: "18px", borderRadius: "4px" })] }), jsxRuntime.jsxs("div", { className: "ai-chat-action-skeleton-box", children: [jsxRuntime.jsx(Skeleton$2, { width: "50px", height: "12px", borderRadius: "4px" }), jsxRuntime.jsx(Skeleton$2, { width: "200px", height: "18px", borderRadius: "4px" })] }), jsxRuntime.jsx(Skeleton$2, { width: "100%", height: "44px", borderRadius: "999px" })] }) }));
27659
+ }
27660
+ // Booking form
27661
+ return (jsxRuntime.jsxs("div", { className: `ai-chat-action-card ai-chat-action-card--closable ai-chat-google-calendar ${className}`, style: accentStyle, children: [jsxRuntime.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntime.jsx(CalendarIcon$1, {}), "Schedule an Appointment", onDismiss && (jsxRuntime.jsx(CloseButton, { onClick: handleDismiss, ariaLabel: "Cancel appointment booking" }))] }), 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: () => {
27662
+ setSelectedDate(date);
27663
+ setSelectedSlot(null);
27664
+ }, 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." }))] })] }));
27665
+ }
27666
+
27667
+ function groupSlotsByDate(slots) {
27668
+ const grouped = new Map();
27669
+ for (const slot of slots) {
27670
+ if (!slot || typeof slot !== 'object' || !slot.startTime || typeof slot.startTime !== 'string') {
27671
+ continue;
27672
+ }
27673
+ const date = slot.startTime.slice(0, 10);
27674
+ if (!grouped.has(date)) {
27675
+ grouped.set(date, []);
27676
+ }
27677
+ grouped.get(date).push(slot);
27678
+ }
27679
+ return grouped;
27680
+ }
27681
+ function formatDate(dateStr) {
27682
+ try {
27683
+ const date = new Date(dateStr);
27684
+ return new Intl.DateTimeFormat("en-US", {
27685
+ weekday: "short",
27686
+ month: "short",
27687
+ day: "numeric",
27688
+ }).format(date);
27689
+ }
27690
+ catch {
27691
+ return dateStr;
27692
+ }
27693
+ }
27694
+ function CalendarIcon() {
27695
+ 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" }) }));
27696
+ }
27697
+ function MailIcon() {
27698
+ 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" })] }));
27699
+ }
27700
+ function CheckIcon() {
27701
+ 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" }) }));
27702
+ }
27703
+ function ErrorIcon() {
27704
+ 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" }) }));
27705
+ }
27706
+ function ExternalLinkIcon$1() {
27707
+ 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" })] }));
27708
+ }
27709
+ function Skeleton$1({ width, height, borderRadius = '4px' }) {
27710
+ return (jsxRuntime.jsx("div", { className: "ai-chat-action-skeleton-item", style: { width, height, borderRadius } }));
27711
+ }
27712
+ function PinInputGroup$1({ values, onChange, disabled }) {
27713
+ const inputRefs = React.useRef([]);
27714
+ const handleChange = (index, value) => {
27715
+ // Only allow digits
27716
+ const digit = value.replace(/[^0-9]/g, '');
27717
+ const newValues = [...values];
27718
+ newValues[index] = digit.slice(-1);
27719
+ onChange(newValues);
27720
+ // Auto-focus next input
27721
+ if (digit && index < 5) {
27722
+ inputRefs.current[index + 1]?.focus();
27723
+ }
27724
+ };
27725
+ const handleKeyDown = (index, e) => {
27726
+ if (e.key === 'Backspace' && !values[index] && index > 0) {
27727
+ inputRefs.current[index - 1]?.focus();
27728
+ }
27729
+ };
27730
+ const handlePaste = (e) => {
27731
+ e.preventDefault();
27732
+ const pastedData = e.clipboardData.getData('text').replace(/[^0-9]/g, '').slice(0, 6);
27733
+ const newValues = pastedData.split('').concat(Array(6 - pastedData.length).fill(''));
27734
+ onChange(newValues);
27735
+ // Focus the next empty input or the last one
27736
+ const nextIndex = Math.min(pastedData.length, 5);
27737
+ inputRefs.current[nextIndex]?.focus();
27738
+ };
27739
+ return (jsxRuntime.jsx("div", { className: "ai-chat-pin-input-group", children: values.map((value, index) => (jsxRuntime.jsx("input", { ref: (el) => {
27740
+ inputRefs.current[index] = el;
27741
+ }, 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))) }));
27742
+ }
27743
+ function MicrosoftCalendarCard({ action, onComplete, onDismiss, accentColor, className = '' }) {
27744
+ const state = action.state;
27745
+ const phase = state.phase || "awaiting_email";
27746
+ const allowTopic = state.allowTopic !== false;
27747
+ const accentStyle = accentColor ? { '--action-accent': accentColor } : {};
27748
+ const handleDismiss = () => {
27749
+ onDismiss?.(action.toolCallId);
27750
+ };
27751
+ const showCloseButton = Boolean(onDismiss);
27752
+ // Debug: Log state changes
27753
+ const prevStateRef = React.useRef(null);
27754
+ React.useEffect(() => {
27755
+ if (JSON.stringify(prevStateRef.current) !== JSON.stringify(state)) {
27756
+ console.log('[MicrosoftCalendarCard] State updated:', {
27757
+ phase: state.phase,
27758
+ hasError: !!state.errorMessage,
27759
+ error: state.errorMessage,
27760
+ slotsCount: state.availableSlots?.length || 0
27761
+ });
27762
+ prevStateRef.current = state;
27763
+ }
27764
+ }, [state]);
27765
+ // Email phase state
27766
+ const [email, setEmail] = React.useState("");
27767
+ const [emailError, setEmailError] = React.useState(null);
27768
+ // OTP phase state
27769
+ const [otpValues, setOtpValues] = React.useState(Array(6).fill(''));
27770
+ const [otpError, setOtpError] = React.useState(null);
27771
+ // Loading states
27772
+ const [isSubmitting, setIsSubmitting] = React.useState(false);
27773
+ // Reset loading state when phase changes (backend has responded)
27774
+ // Use useEffect for reliable re-rendering
27775
+ React.useEffect(() => {
27776
+ console.log('[MicrosoftCalendarCard] Phase changed to:', phase);
27777
+ setIsSubmitting(false);
27778
+ // Clear errors when transitioning to new phase
27779
+ if (phase === "awaiting_email") {
27780
+ setEmailError(null);
27781
+ setOtpError(null);
27782
+ setSelectionError(null);
27783
+ }
27784
+ else if (phase === "awaiting_otp") {
27785
+ setOtpError(state.errorMessage || null);
27786
+ setEmailError(null);
27787
+ setSelectionError(null);
27788
+ // Clear OTP input for fresh attempt
27789
+ setOtpValues(Array(6).fill(''));
27790
+ }
27791
+ else if (phase === "awaiting_options") {
27792
+ setEmailError(null);
27793
+ setOtpError(null);
27794
+ setSelectionError(null);
27795
+ }
27796
+ else if (phase === "awaiting_booking") {
27797
+ setSelectionError(state.errorMessage || null);
27798
+ setEmailError(null);
27799
+ setOtpError(null);
27800
+ }
27801
+ else if (phase === "booked" || phase === "cancelled" || phase === "error") {
27802
+ setEmailError(null);
27803
+ setOtpError(null);
27804
+ setSelectionError(null);
27805
+ setSelectedId(null); // Reset selection
27806
+ }
27807
+ }, [phase, state.errorMessage]);
27808
+ // Selection phase state
27809
+ const rawSlots = state.availableSlots;
27810
+ const availableSlots = Array.isArray(rawSlots)
27811
+ ? rawSlots.filter((slot) => slot !== null &&
27812
+ slot !== undefined &&
27813
+ typeof slot === "object" &&
27814
+ "startTime" in slot &&
27815
+ "endTime" in slot &&
27816
+ typeof slot.startTime === "string" &&
27817
+ typeof slot.endTime === "string")
27818
+ : [];
27819
+ const slotsByDate = groupSlotsByDate(availableSlots);
27820
+ const dates = Array.from(slotsByDate.keys()).sort();
27821
+ const [selectedDate, setSelectedDate] = React.useState(dates[0] ?? "");
27822
+ const [selectedSlot, setSelectedSlot] = React.useState(null);
27823
+ const [topic, setTopic] = React.useState("");
27824
+ const [selectionError, setSelectionError] = React.useState(null);
27825
+ // Cancellation phase state
27826
+ const [selectedId, setSelectedId] = React.useState(null);
27827
+ const slotsForSelectedDate = selectedDate ? slotsByDate.get(selectedDate) ?? [] : [];
27828
+ // Phase 1: Email Input
27829
+ const handleEmailSubmit = () => {
27830
+ const trimmedEmail = email.trim();
27831
+ if (!trimmedEmail) {
27832
+ setEmailError("Please enter your email address");
27833
+ return;
27834
+ }
27835
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(trimmedEmail)) {
27836
+ setEmailError("Please enter a valid email address");
27837
+ return;
27838
+ }
27839
+ setEmailError(null);
27840
+ setIsSubmitting(true);
27841
+ console.log('[MicrosoftCalendarCard] Submitting email:', trimmedEmail);
27842
+ setTimeout(() => {
27843
+ onComplete?.(action.toolCallId, {
27844
+ ...action.state,
27845
+ email: trimmedEmail,
27846
+ });
27847
+ }, 50);
27848
+ };
27849
+ // Phase 2: OTP Verification
27850
+ const handleOtpSubmit = () => {
27851
+ const otpCode = otpValues.join('');
27852
+ if (otpCode.length !== 6) {
27853
+ setOtpError("Please enter the 6-digit code");
27854
+ return;
27855
+ }
27856
+ setOtpError(null);
27857
+ setIsSubmitting(true);
27858
+ console.log('[MicrosoftCalendarCard] Submitting OTP code');
27859
+ setTimeout(() => {
27860
+ onComplete?.(action.toolCallId, {
27861
+ ...action.state,
27862
+ otpCode,
27863
+ });
27864
+ }, 50);
27865
+ };
27866
+ // Phase 3: Appointment Selection
27867
+ const handleAppointmentConfirm = () => {
27868
+ if (!selectedSlot) {
27869
+ setSelectionError("Please select a time slot");
27870
+ return;
27871
+ }
27872
+ if (allowTopic && !topic.trim()) {
27873
+ setSelectionError("Please enter a meeting topic");
27874
+ return;
27875
+ }
27876
+ setSelectionError(null);
27495
27877
  setIsSubmitting(true);
27496
- // Small delay to ensure UI updates
27878
+ console.log('[MicrosoftCalendarCard] Confirming appointment:', {
27879
+ slot: selectedSlot,
27880
+ topic: topic.trim()
27881
+ });
27497
27882
  setTimeout(() => {
27498
27883
  onComplete?.(action.toolCallId, {
27499
27884
  ...action.state,
@@ -27505,22 +27890,149 @@ function GoogleCalendarCard({ action, onComplete, accentColor, className = '' })
27505
27890
  });
27506
27891
  }, 50);
27507
27892
  };
27508
- // Booked state
27509
- if (isBooked) {
27893
+ // Handle "Use different email" button
27894
+ const handleUseDifferentEmail = () => {
27895
+ setEmail("");
27896
+ setEmailError(null);
27897
+ setOtpValues(Array(6).fill(''));
27898
+ setOtpError(null);
27899
+ onComplete?.(action.toolCallId, {
27900
+ phase: "awaiting_email",
27901
+ email: null,
27902
+ otpVerified: false,
27903
+ otpAttempts: 0,
27904
+ availableSlots: [],
27905
+ selectedSlot: null,
27906
+ topic: null,
27907
+ bookedEventId: null,
27908
+ bookedEventLink: null,
27909
+ allowTopic,
27910
+ errorMessage: null,
27911
+ });
27912
+ };
27913
+ // Phase 5: Booked Confirmation
27914
+ if (phase === "booked") {
27510
27915
  const bookedSlot = state.selectedSlot;
27511
27916
  const bookedTopic = state.topic;
27512
27917
  const eventLink = state.bookedEventLink;
27513
- 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$1, {})] }))] })] }));
27514
- }
27515
- // Skeleton loading state
27918
+ const bookedEmail = state.email;
27919
+ 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, {})] }))] })] }));
27920
+ }
27921
+ // Phase 6: Cancelled Confirmation
27922
+ if (phase === "cancelled") {
27923
+ const cancelledSubject = state.cancelledEventSubject;
27924
+ const userEmail = state.email;
27925
+ 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] }))] })] }));
27926
+ }
27927
+ // Error State
27928
+ if (phase === "error") {
27929
+ 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: () => {
27930
+ setEmail("");
27931
+ setEmailError(null);
27932
+ setOtpValues(Array(6).fill(''));
27933
+ setOtpError(null);
27934
+ onComplete?.(action.toolCallId, {
27935
+ phase: "awaiting_email",
27936
+ email: null,
27937
+ otpVerified: false,
27938
+ otpAttempts: 0,
27939
+ availableSlots: [],
27940
+ selectedSlot: null,
27941
+ topic: null,
27942
+ bookedEventId: null,
27943
+ bookedEventLink: null,
27944
+ allowTopic,
27945
+ errorMessage: null,
27946
+ });
27947
+ }, children: "Start Over" })] })] }));
27948
+ }
27949
+ // Loading State
27516
27950
  if (isSubmitting) {
27517
- 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" })] }) }));
27518
- }
27519
- // Booking form
27520
- 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: () => {
27521
- setSelectedDate(date);
27522
- setSelectedSlot(null);
27523
- }, 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." }))] })] }));
27951
+ 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.jsx(Skeleton$1, { width: "100%", height: "44px", borderRadius: "999px" })] }) }));
27952
+ }
27953
+ // Phase 1: Email Input
27954
+ if (phase === "awaiting_email") {
27955
+ const displayError = state.errorMessage || emailError;
27956
+ return (jsxRuntime.jsxs("div", { className: `ai-chat-action-card ai-chat-action-card--closable ${className}`, style: accentStyle, children: [jsxRuntime.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntime.jsx(CalendarIcon, {}), "Schedule an Appointment", showCloseButton && (jsxRuntime.jsx(CloseButton, { onClick: handleDismiss, ariaLabel: "Cancel appointment booking" }))] }), 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) => {
27957
+ setEmail(e.target.value);
27958
+ setEmailError(null);
27959
+ }, onKeyPress: (e) => {
27960
+ if (e.key === 'Enter') {
27961
+ handleEmailSubmit();
27962
+ }
27963
+ }, 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" })] })] }));
27964
+ }
27965
+ // Phase 2: OTP Input
27966
+ if (phase === "awaiting_otp") {
27967
+ const displayError = state.errorMessage || otpError;
27968
+ const userEmail = state.email;
27969
+ return (jsxRuntime.jsxs("div", { className: `ai-chat-action-card ai-chat-action-card--closable ${className}`, style: accentStyle, children: [jsxRuntime.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntime.jsx(MailIcon, {}), "Verify Your Email", showCloseButton && (jsxRuntime.jsx(CloseButton, { onClick: handleDismiss, ariaLabel: "Cancel appointment booking" }))] }), 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$1, { values: otpValues, onChange: (newValues) => {
27970
+ setOtpValues(newValues);
27971
+ setOtpError(null);
27972
+ // Auto-submit when all 6 digits are entered
27973
+ if (newValues.every(v => v.length === 1)) {
27974
+ console.log('[MicrosoftCalendarCard] Auto-submitting OTP (all 6 digits entered)');
27975
+ setIsSubmitting(true);
27976
+ const code = newValues.join('');
27977
+ setTimeout(() => {
27978
+ onComplete?.(action.toolCallId, {
27979
+ ...action.state,
27980
+ otpCode: code,
27981
+ });
27982
+ }, 100);
27983
+ }
27984
+ }, 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" })] })] }));
27985
+ }
27986
+ // Phase 3: Options Menu (with inline cancel buttons and confirmation)
27987
+ if (phase === "awaiting_options") {
27988
+ const userAppointments = state.userAppointments || [];
27989
+ const maxAppointments = state.maxAppointmentsPerUser || 3;
27990
+ const appointmentCount = userAppointments.length;
27991
+ const canBook = appointmentCount < maxAppointments;
27992
+ const hasAppointments = appointmentCount > 0;
27993
+ const displayError = state.errorMessage || selectionError;
27994
+ // If confirming cancellation, show confirmation dialog
27995
+ if (selectedId) {
27996
+ const appointmentToCancel = userAppointments.find(appt => appt.id === selectedId);
27997
+ if (!appointmentToCancel) {
27998
+ setSelectedId(null); // Reset if appointment not found
27999
+ }
28000
+ else {
28001
+ return (jsxRuntime.jsxs("div", { className: `ai-chat-action-card ai-chat-action-card--closable ${className}`, style: accentStyle, children: [jsxRuntime.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntime.jsx(CalendarIcon, {}), "Confirm Cancellation", showCloseButton && (jsxRuntime.jsx(CloseButton, { onClick: handleDismiss, ariaLabel: "Cancel appointment booking" }))] }), 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: () => {
28002
+ setIsSubmitting(true);
28003
+ onComplete?.(action.toolCallId, {
28004
+ ...action.state,
28005
+ selectedOption: "cancel",
28006
+ selectedAppointmentId: selectedId,
28007
+ });
28008
+ }, disabled: isSubmitting, children: isSubmitting ? 'Cancelling...' : 'Confirm Cancellation' }), jsxRuntime.jsx("button", { className: "ai-chat-action-button-secondary", type: "button", onClick: () => {
28009
+ setSelectedId(null);
28010
+ setSelectionError(null);
28011
+ }, disabled: isSubmitting, children: "Go Back" })] })] })] }));
28012
+ }
28013
+ }
28014
+ // Normal view with inline cancel buttons
28015
+ return (jsxRuntime.jsxs("div", { className: `ai-chat-action-card ai-chat-action-card--closable ${className}`, style: accentStyle, children: [jsxRuntime.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntime.jsx(CalendarIcon, {}), "Manage Your Appointments", showCloseButton && (jsxRuntime.jsx(CloseButton, { onClick: handleDismiss, ariaLabel: "Cancel appointment booking" }))] }), 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: () => {
28016
+ setSelectedId(appt.id);
28017
+ setSelectionError(null);
28018
+ }, 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: () => {
28019
+ setIsSubmitting(true);
28020
+ onComplete?.(action.toolCallId, {
28021
+ ...action.state,
28022
+ selectedOption: "book",
28023
+ });
28024
+ }, disabled: isSubmitting, children: isSubmitting ? 'Loading...' : 'Book New Appointment' })), !canBook && !hasAppointments && (jsxRuntime.jsx("div", { className: "ai-chat-action-hint", children: "No appointments found." }))] })] }));
28025
+ }
28026
+ // Phase 4: Appointment Selection (Booking)
28027
+ if (phase === "awaiting_booking") {
28028
+ const displayError = state.errorMessage || selectionError;
28029
+ return (jsxRuntime.jsxs("div", { className: `ai-chat-action-card ai-chat-action-card--closable ${className}`, style: accentStyle, children: [jsxRuntime.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntime.jsx(CalendarIcon, {}), "Select Appointment Time", showCloseButton && (jsxRuntime.jsx(CloseButton, { onClick: handleDismiss, ariaLabel: "Cancel appointment booking" }))] }), 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: () => {
28030
+ setSelectedDate(date);
28031
+ setSelectedSlot(null);
28032
+ }, 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." }))] })] }));
28033
+ }
28034
+ // Fallback
28035
+ return null;
27524
28036
  }
27525
28037
 
27526
28038
  function truncate(text, maxLength) {
@@ -27531,17 +28043,30 @@ function truncate(text, maxLength) {
27531
28043
  function ExternalLinkIcon() {
27532
28044
  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" })] }));
27533
28045
  }
28046
+ function SingleLinkPreview({ link, onLinkClick, accentColor }) {
28047
+ const domain = (() => {
28048
+ if (!link.url)
28049
+ return '';
28050
+ try {
28051
+ return new URL(link.url).hostname.replace('www.', '');
28052
+ }
28053
+ catch {
28054
+ return link.url;
28055
+ }
28056
+ })();
28057
+ const style = accentColor ? { '--action-accent': accentColor } : undefined;
28058
+ 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) => {
28059
+ e.currentTarget.parentElement.style.display = 'none';
28060
+ } }) })), 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) => {
28061
+ e.currentTarget.style.display = 'none';
28062
+ } })), 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, {}) })] }));
28063
+ }
27534
28064
  function LinkPreviewCard({ action, onComplete, accentColor }) {
27535
28065
  const rawState = action.state;
27536
28066
  const hasCompletedRef = React.useRef(false);
27537
28067
  // Provide safe defaults if state is missing
27538
28068
  const state = {
27539
- url: rawState?.url || '',
27540
- title: rawState?.title || 'Link',
27541
- description: rawState?.description,
27542
- image: rawState?.image,
27543
- siteName: rawState?.siteName,
27544
- favicon: rawState?.favicon,
28069
+ links: rawState?.links || [],
27545
28070
  context: rawState?.context,
27546
28071
  status: rawState?.status || 'displaying',
27547
28072
  error: rawState?.error,
@@ -27549,34 +28074,29 @@ function LinkPreviewCard({ action, onComplete, accentColor }) {
27549
28074
  const isError = state.status === 'error';
27550
28075
  // Auto-complete on mount so AI can continue generating text response
27551
28076
  React.useEffect(() => {
27552
- if (!action.done && !hasCompletedRef.current && onComplete && state.url) {
28077
+ if (!action.done && !hasCompletedRef.current && onComplete && state.links.length > 0) {
27553
28078
  hasCompletedRef.current = true;
27554
28079
  // Signal completion immediately - the card is displayed, AI can continue
27555
28080
  onComplete(action.toolCallId, { ...state, status: 'displaying' });
27556
28081
  }
27557
28082
  }, [action.done, action.toolCallId, onComplete, state]);
27558
- const handleClick = () => {
27559
- if (state.url) {
27560
- window.open(state.url, '_blank', 'noopener,noreferrer');
28083
+ const handleLinkClick = (url) => {
28084
+ if (url) {
28085
+ window.open(url, '_blank', 'noopener,noreferrer');
27561
28086
  }
27562
28087
  onComplete?.(action.toolCallId, { ...state, status: 'clicked' });
27563
28088
  };
27564
- const domain = (() => {
27565
- if (!state.url)
27566
- return '';
27567
- try {
27568
- return new URL(state.url).hostname.replace('www.', '');
27569
- }
27570
- catch {
27571
- return state.url;
27572
- }
27573
- })();
27574
- const style = accentColor ? { '--action-accent': accentColor } : undefined;
27575
- return (jsxRuntime.jsxs("div", { className: `ai-chat-link-preview ${isError ? 'ai-chat-link-preview--error' : ''}`, onClick: handleClick, style: style, role: "link", tabIndex: 0, onKeyDown: (e) => e.key === 'Enter' && handleClick(), children: [state.image && !isError && (jsxRuntime.jsx("div", { className: "ai-chat-link-preview__image", children: jsxRuntime.jsx("img", { src: state.image, alt: state.title, onError: (e) => {
27576
- e.currentTarget.parentElement.style.display = 'none';
27577
- } }) })), jsxRuntime.jsxs("div", { className: "ai-chat-link-preview__content", children: [jsxRuntime.jsxs("div", { className: "ai-chat-link-preview__site", children: [state.favicon && (jsxRuntime.jsx("img", { src: state.favicon, alt: "", className: "ai-chat-link-preview__favicon", onError: (e) => {
27578
- e.currentTarget.style.display = 'none';
27579
- } })), jsxRuntime.jsx("span", { className: "ai-chat-link-preview__domain", children: state.siteName || domain })] }), jsxRuntime.jsx("h4", { className: "ai-chat-link-preview__title", children: state.title }), state.description && (jsxRuntime.jsx("p", { className: "ai-chat-link-preview__description", children: truncate(state.description, 120) })), state.context && (jsxRuntime.jsx("p", { className: "ai-chat-link-preview__context", children: state.context })), isError && state.error && (jsxRuntime.jsx("p", { className: "ai-chat-link-preview__error-text", children: state.error }))] }), jsxRuntime.jsx("div", { className: "ai-chat-link-preview__arrow", children: jsxRuntime.jsx(ExternalLinkIcon, {}) })] }));
28089
+ if (isError) {
28090
+ 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' }) }) }));
28091
+ }
28092
+ if (state.links.length === 0) {
28093
+ return null;
28094
+ }
28095
+ 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: {
28096
+ display: 'grid',
28097
+ gridTemplateColumns: state.links.length === 1 ? '1fr' : state.links.length === 2 ? 'repeat(2, 1fr)' : 'repeat(3, 1fr)',
28098
+ gap: '12px',
28099
+ }, children: state.links.map((link, index) => (jsxRuntime.jsx(SingleLinkPreview, { link: link, onLinkClick: () => handleLinkClick(link.url), accentColor: accentColor }, index))) })] }));
27580
28100
  }
27581
28101
 
27582
28102
  function PlayIcon() {
@@ -27642,7 +28162,7 @@ function VideoPlayerCard({ action, onComplete, accentColor }) {
27642
28162
  return src;
27643
28163
  }
27644
28164
  };
27645
- return (jsxRuntime.jsxs("div", { className: "ai-chat-video-player", style: style, children: [state.title && (jsxRuntime.jsx("div", { className: "ai-chat-video-player__header", children: jsxRuntime.jsx("span", { className: "ai-chat-video-player__title", children: state.title }) })), 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 }))] }));
28165
+ 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 }))] }));
27646
28166
  }
27647
28167
 
27648
28168
  function MapPinIcon() {
@@ -27703,7 +28223,9 @@ function LocationItem({ location, settings, accentColor, onDirections, showMap =
27703
28223
  }
27704
28224
  };
27705
28225
  const style = accentColor ? { '--action-accent': accentColor } : undefined;
27706
- return (jsxRuntime.jsxs("div", { className: `ai-chat-location-card ${compact ? 'ai-chat-location-card--compact' : ''}`, style: style, children: [showMap && !compact && settings.showMap !== false && (jsxRuntime.jsx("div", { className: "ai-chat-location-card__map", style: { height: mapHeight }, 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"] }))] })] })] }));
28226
+ // Use smaller map height in compact mode
28227
+ const effectiveMapHeight = compact ? Math.min(mapHeight, 140) : mapHeight;
28228
+ 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"] }))] })] })] }));
27707
28229
  }
27708
28230
  function LocationCard({ action, onComplete, accentColor, maxColumns = 3 }) {
27709
28231
  const rawState = action.state;
@@ -27737,40 +28259,443 @@ function LocationCard({ action, onComplete, accentColor, maxColumns = 3 }) {
27737
28259
  if (isSingleLocation) {
27738
28260
  return (jsxRuntime.jsx(LocationItem, { location: locations[0], settings: settings, accentColor: accentColor, onDirections: () => handleDirections(locations[0]), showMap: true }));
27739
28261
  }
27740
- 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", style: {
27741
- gridTemplateColumns: `repeat(${stackColumns}, minmax(0, 1fr))`,
27742
- }, 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))) }))] }));
28262
+ 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))) }))] }));
27743
28263
  }
27744
28264
 
27745
- const pendingResolvers = new Map();
27746
- const resumeCallbacks = new Map();
27747
- const frontendActionHandlers = {};
27748
- const actionRenderers = {};
27749
- function getFrontendActionHandler(implementation) {
27750
- return frontendActionHandlers[implementation];
28265
+ function UsersIcon() {
28266
+ 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" })] }));
27751
28267
  }
27752
- function getActionRenderer(implementation) {
27753
- return actionRenderers[implementation];
27754
- }
27755
- function getActionPrompt(implementation) {
27756
- if (implementation === "google-calendar-appointment") {
27757
- return "Select a date to continue.";
28268
+ const AVATAR_COLORS = [
28269
+ { bg: '#E8F5E9', text: '#2E7D32' }, // Green
28270
+ { bg: '#E3F2FD', text: '#1565C0' }, // Blue
28271
+ { bg: '#FFF3E0', text: '#E65100' }, // Orange
28272
+ { bg: '#F3E5F5', text: '#7B1FA2' }, // Purple
28273
+ { bg: '#FFEBEE', text: '#C62828' }, // Red
28274
+ { bg: '#E0F7FA', text: '#00838F' }, // Cyan
28275
+ { bg: '#FFF8E1', text: '#F9A825' }, // Amber
28276
+ { bg: '#FCE4EC', text: '#AD1457' }, // Pink
28277
+ ];
28278
+ function getInitials(name) {
28279
+ const parts = name.trim().split(/\s+/);
28280
+ if (parts.length === 1) {
28281
+ return parts[0].substring(0, 2).toUpperCase();
27758
28282
  }
27759
- return "Action input required.";
27760
- }
27761
- function waitForActionState(toolCallId) {
27762
- return new Promise((resolve) => {
27763
- pendingResolvers.set(toolCallId, resolve);
27764
- });
28283
+ return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
27765
28284
  }
27766
- function resolveActionState(toolCallId, state) {
27767
- const resolver = pendingResolvers.get(toolCallId);
27768
- if (resolver) {
27769
- pendingResolvers.delete(toolCallId);
27770
- resolver(state);
27771
- return;
28285
+ function getColorFromName(name) {
28286
+ let hash = 0;
28287
+ for (let i = 0; i < name.length; i++) {
28288
+ hash = name.charCodeAt(i) + ((hash << 5) - hash);
27772
28289
  }
27773
- const resumeCallback = resumeCallbacks.get(toolCallId);
28290
+ return AVATAR_COLORS[Math.abs(hash) % AVATAR_COLORS.length];
28291
+ }
28292
+ function ContactItem({ contact, settings, accentColor, onEmail, onPhone, compact = false, layout = 'vertical', }) {
28293
+ const style = accentColor ? { '--action-accent': accentColor } : undefined;
28294
+ const layoutClass = layout === 'horizontal'
28295
+ ? 'ai-chat-contact-card--horizontal'
28296
+ : 'ai-chat-contact-card--vertical';
28297
+ 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) => {
28298
+ e.currentTarget.style.display = 'none';
28299
+ const placeholder = e.currentTarget.parentElement?.querySelector('.ai-chat-contact-card__initials');
28300
+ if (placeholder) {
28301
+ placeholder.style.display = 'flex';
28302
+ }
28303
+ } })) : null, (() => {
28304
+ const colors = getColorFromName(contact.name);
28305
+ return (jsxRuntime.jsx("div", { className: "ai-chat-contact-card__initials", style: {
28306
+ display: contact.profilePictureUrl ? 'none' : 'flex',
28307
+ backgroundColor: colors.bg,
28308
+ color: colors.text,
28309
+ }, children: getInitials(contact.name) }));
28310
+ })()] }), 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"] }))] }))] })] }));
28311
+ }
28312
+ function ContactCard({ action, onComplete, accentColor, maxColumns = 3 }) {
28313
+ const rawState = action.state;
28314
+ const hasCompletedRef = React.useRef(false);
28315
+ const state = {
28316
+ contacts: rawState?.contacts || [],
28317
+ settings: rawState?.settings || {},
28318
+ query: rawState?.query,
28319
+ status: rawState?.status || 'displaying',
28320
+ };
28321
+ const { contacts, settings } = state;
28322
+ const isSingleContact = contacts.length === 1;
28323
+ const stackColumns = Math.min(Math.max(contacts.length, 1), maxColumns);
28324
+ React.useEffect(() => {
28325
+ if (!action.done && !hasCompletedRef.current && onComplete) {
28326
+ hasCompletedRef.current = true;
28327
+ onComplete(action.toolCallId, { ...state, status: 'displaying' });
28328
+ }
28329
+ }, [action.done, action.toolCallId, onComplete, state]);
28330
+ const handleContact = () => {
28331
+ onComplete?.(action.toolCallId, { ...state, status: 'contacted' });
28332
+ };
28333
+ if (contacts.length === 0) {
28334
+ 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}"` : ''] })] }));
28335
+ }
28336
+ if (isSingleContact) {
28337
+ return (jsxRuntime.jsx(ContactItem, { contact: contacts[0], settings: settings, accentColor: accentColor, onEmail: handleContact, onPhone: handleContact, layout: settings.layout || 'horizontal' }));
28338
+ }
28339
+ const isWidget = maxColumns === 1;
28340
+ const stackClassName = isWidget
28341
+ ? 'ai-chat-contact-card-list__stack ai-chat-contact-card-list__stack--widget'
28342
+ : 'ai-chat-contact-card-list__stack';
28343
+ 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 : {
28344
+ gridTemplateColumns: `repeat(${stackColumns}, minmax(0, 1fr))`,
28345
+ }, 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))) })] }));
28346
+ }
28347
+
28348
+ function FormCard({ action, onComplete, onDismiss, accentColor }) {
28349
+ const state = action.state;
28350
+ const [currentStep, setCurrentStep] = React.useState(0);
28351
+ const [answers, setAnswers] = React.useState({});
28352
+ const [isSubmitting, setIsSubmitting] = React.useState(false);
28353
+ const questions = state.questions || [];
28354
+ const currentQuestion = questions[currentStep];
28355
+ const totalQuestions = questions.length;
28356
+ const handleAnswerChange = (questionId, value) => {
28357
+ setAnswers((prev) => ({ ...prev, [questionId]: value }));
28358
+ };
28359
+ const handleNext = () => {
28360
+ if (currentStep < totalQuestions - 1) {
28361
+ setCurrentStep((prev) => prev + 1);
28362
+ }
28363
+ };
28364
+ const handlePrev = () => {
28365
+ if (currentStep > 0) {
28366
+ setCurrentStep((prev) => prev - 1);
28367
+ }
28368
+ };
28369
+ const handleSubmit = () => {
28370
+ if (!onComplete)
28371
+ return;
28372
+ setIsSubmitting(true);
28373
+ const formattedAnswers = Object.entries(answers).map(([questionId, value]) => ({
28374
+ questionId,
28375
+ value,
28376
+ }));
28377
+ onComplete(action.toolCallId, {
28378
+ ...state,
28379
+ status: 'submitted',
28380
+ answers: formattedAnswers,
28381
+ });
28382
+ };
28383
+ const handleSkip = () => {
28384
+ if (!onComplete || !state.settings.allowSkip)
28385
+ return;
28386
+ onComplete(action.toolCallId, {
28387
+ ...state,
28388
+ status: 'skipped',
28389
+ });
28390
+ };
28391
+ const isCurrentAnswered = () => {
28392
+ if (!currentQuestion)
28393
+ return false;
28394
+ const answer = answers[currentQuestion.id];
28395
+ if (!answer)
28396
+ return !currentQuestion.required;
28397
+ if (Array.isArray(answer))
28398
+ return answer.length > 0 || !currentQuestion.required;
28399
+ return answer.trim() !== '' || !currentQuestion.required;
28400
+ };
28401
+ const canSubmit = () => {
28402
+ return questions.every((q) => {
28403
+ const answer = answers[q.id];
28404
+ if (!q.required)
28405
+ return true;
28406
+ if (!answer)
28407
+ return false;
28408
+ if (Array.isArray(answer))
28409
+ return answer.length > 0;
28410
+ return answer.trim() !== '';
28411
+ });
28412
+ };
28413
+ const handleDismiss = () => {
28414
+ onDismiss?.(action.toolCallId);
28415
+ };
28416
+ // Error state
28417
+ if (state.status === 'error') {
28418
+ 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' })] }));
28419
+ }
28420
+ // Submitted state
28421
+ if (state.status === 'submitted' || action.done) {
28422
+ 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!' })] }));
28423
+ }
28424
+ // Skipped state
28425
+ if (state.status === 'skipped') {
28426
+ 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" })] }));
28427
+ }
28428
+ // No questions
28429
+ if (totalQuestions === 0) {
28430
+ 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." })] }));
28431
+ }
28432
+ const showCloseButton = state.status === "displaying" && !action.done && Boolean(onDismiss);
28433
+ return (jsxRuntime.jsxs("div", { className: `ai-chat-form-card${showCloseButton ? " ai-chat-form-card--closable" : ""}`, 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 }), showCloseButton && (jsxRuntime.jsx(CloseButton, { onClick: handleDismiss, ariaLabel: "Close form" }))] }), 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: {
28434
+ width: `${((currentStep + 1) / totalQuestions) * 100}%`,
28435
+ backgroundColor: accentColor || 'var(--ai-chat-accent-color, #3b82f6)',
28436
+ } }), 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) => {
28437
+ const currentAnswers = answers[currentQuestion.id] || [];
28438
+ const isChecked = currentAnswers.includes(option.value);
28439
+ return (jsxRuntime.jsxs("label", { className: "ai-chat-form-card__option", children: [jsxRuntime.jsx("input", { type: "checkbox", value: option.value, checked: isChecked, onChange: () => {
28440
+ const newAnswers = isChecked
28441
+ ? currentAnswers.filter((v) => v !== option.value)
28442
+ : [...currentAnswers, option.value];
28443
+ handleAnswerChange(currentQuestion.id, newAnswers);
28444
+ } }), jsxRuntime.jsx("span", { className: "ai-chat-form-card__option-text", children: option.text })] }, option.id));
28445
+ }) })), 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: {
28446
+ borderColor: answers[currentQuestion.id] === String(rating)
28447
+ ? (accentColor || 'var(--ai-chat-accent-color, #3b82f6)')
28448
+ : undefined,
28449
+ backgroundColor: answers[currentQuestion.id] === String(rating)
28450
+ ? (accentColor || 'var(--ai-chat-accent-color, #3b82f6)')
28451
+ : undefined,
28452
+ }, 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: {
28453
+ backgroundColor: accentColor || 'var(--ai-chat-accent-color, #3b82f6)',
28454
+ }, 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: {
28455
+ backgroundColor: accentColor || 'var(--ai-chat-accent-color, #3b82f6)',
28456
+ }, children: isSubmitting ? 'Submitting...' : (state.settings.submitButtonText || 'Submit') }))] })] }));
28457
+ }
28458
+
28459
+ function Skeleton({ width, height, borderRadius = '4px' }) {
28460
+ return (jsxRuntime.jsx("div", { className: "ai-chat-action-skeleton-item", style: { width, height, borderRadius } }));
28461
+ }
28462
+ function PinInputGroup({ values, onChange, disabled }) {
28463
+ const inputRefs = React.useRef([]);
28464
+ const handleChange = (index, value) => {
28465
+ // Only allow digits
28466
+ const digit = value.replace(/[^0-9]/g, '');
28467
+ const newValues = [...values];
28468
+ newValues[index] = digit.slice(-1);
28469
+ onChange(newValues);
28470
+ // Auto-focus next input
28471
+ if (digit && index < 5) {
28472
+ inputRefs.current[index + 1]?.focus();
28473
+ }
28474
+ };
28475
+ const handleKeyDown = (index, e) => {
28476
+ if (e.key === 'Backspace' && !values[index] && index > 0) {
28477
+ inputRefs.current[index - 1]?.focus();
28478
+ }
28479
+ };
28480
+ const handlePaste = (e) => {
28481
+ e.preventDefault();
28482
+ const pastedData = e.clipboardData.getData('text').replace(/[^0-9]/g, '').slice(0, 6);
28483
+ const newValues = pastedData.split('').concat(Array(6 - pastedData.length).fill(''));
28484
+ onChange(newValues);
28485
+ // Focus the next empty input or the last one
28486
+ const nextIndex = Math.min(pastedData.length, 5);
28487
+ inputRefs.current[nextIndex]?.focus();
28488
+ };
28489
+ return (jsxRuntime.jsx("div", { className: "ai-chat-pin-input-group", children: values.map((value, index) => (jsxRuntime.jsx("input", { ref: (el) => {
28490
+ inputRefs.current[index] = el;
28491
+ }, 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))) }));
28492
+ }
28493
+ function BookContactAppointmentCard({ action, onComplete, accentColor }) {
28494
+ const state = action.state;
28495
+ const [emailInput, setEmailInput] = React.useState('');
28496
+ const [otpValues, setOtpValues] = React.useState(Array(6).fill(''));
28497
+ const [subjectInput, setSubjectInput] = React.useState(state.subject || '');
28498
+ const [isSubmitting, setIsSubmitting] = React.useState(false);
28499
+ const [emailError, setEmailError] = React.useState(null);
28500
+ const [otpError, setOtpError] = React.useState(null);
28501
+ const phase = state.phase || 'awaiting_email';
28502
+ const handleSubmit = (newState, delay = 50) => {
28503
+ if (!onComplete)
28504
+ return;
28505
+ setIsSubmitting(true);
28506
+ setTimeout(() => {
28507
+ onComplete(action.toolCallId, { ...state, ...newState, errorMessage: null });
28508
+ }, delay);
28509
+ };
28510
+ React.useEffect(() => {
28511
+ setIsSubmitting(false);
28512
+ if (phase === 'awaiting_email') {
28513
+ setEmailError(null);
28514
+ setOtpError(null);
28515
+ }
28516
+ else if (phase === 'awaiting_otp') {
28517
+ setOtpError(state.errorMessage || null);
28518
+ setEmailError(null);
28519
+ setOtpValues(Array(6).fill(''));
28520
+ if (state.email) {
28521
+ setEmailInput(state.email);
28522
+ }
28523
+ }
28524
+ else {
28525
+ setEmailError(null);
28526
+ setOtpError(null);
28527
+ }
28528
+ }, [phase, state.errorMessage]);
28529
+ const isWaitingForBackend = !action.done && Boolean(state.confirmed) && phase === 'awaiting_confirmation';
28530
+ const renderSkeleton = () => (jsxRuntime.jsx("div", { className: "ai-chat-booking-card", 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" })] }) }));
28531
+ const handleEmailSubmit = () => {
28532
+ const trimmedEmail = emailInput.trim();
28533
+ if (!trimmedEmail) {
28534
+ setEmailError('Please enter your email address');
28535
+ return;
28536
+ }
28537
+ setEmailError(null);
28538
+ setEmailInput(trimmedEmail);
28539
+ handleSubmit({ email: trimmedEmail });
28540
+ };
28541
+ const handleOtpSubmit = () => {
28542
+ const code = otpValues.join('');
28543
+ if (code.length !== 6) {
28544
+ setOtpError('Please enter the 6-digit code');
28545
+ return;
28546
+ }
28547
+ setOtpError(null);
28548
+ const resolvedEmail = state.email || emailInput.trim() || null;
28549
+ handleSubmit({ otpCode: code, email: resolvedEmail });
28550
+ };
28551
+ // ========================================
28552
+ // Terminal States
28553
+ // ========================================
28554
+ if (phase === 'booked') {
28555
+ return (jsxRuntime.jsxs("div", { className: "ai-chat-booking-card ai-chat-booking-card--success", children: [jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntime.jsx("span", { className: "ai-chat-booking-card__icon", children: "\u2713" }), jsxRuntime.jsx("span", { className: "ai-chat-booking-card__title", children: "Appointment Booked" })] }), state.bookedTeamsLink && (jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__content", children: [jsxRuntime.jsx("p", { className: "ai-chat-booking-card__success-text", children: "Your appointment has been confirmed. You can join via Microsoft Teams." }), jsxRuntime.jsx("a", { href: state.bookedTeamsLink, target: "_blank", rel: "noopener noreferrer", className: "ai-chat-booking-card__link", style: { color: accentColor }, children: "Join Teams Meeting \u2192" })] }))] }));
28556
+ }
28557
+ if (phase === 'pending_approval') {
28558
+ return (jsxRuntime.jsxs("div", { className: "ai-chat-booking-card ai-chat-booking-card--pending", children: [jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntime.jsx("span", { className: "ai-chat-booking-card__icon", children: "\u23F3" }), jsxRuntime.jsx("span", { className: "ai-chat-booking-card__title", children: "Awaiting Approval" })] }), jsxRuntime.jsx("div", { className: "ai-chat-booking-card__content", children: jsxRuntime.jsx("p", { className: "ai-chat-booking-card__pending-text", children: "Your appointment request has been sent and is awaiting approval from the contact." }) })] }));
28559
+ }
28560
+ if (phase === 'cancelled') {
28561
+ return (jsxRuntime.jsx("div", { className: "ai-chat-booking-card ai-chat-booking-card--cancelled", children: jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntime.jsx("span", { className: "ai-chat-booking-card__icon", children: "\u2715" }), jsxRuntime.jsx("span", { className: "ai-chat-booking-card__title", children: "Appointment Cancelled" })] }) }));
28562
+ }
28563
+ if (phase === 'error') {
28564
+ return (jsxRuntime.jsxs("div", { className: "ai-chat-booking-card ai-chat-booking-card--error", children: [jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntime.jsx("span", { className: "ai-chat-booking-card__icon", children: "\u26A0\uFE0F" }), jsxRuntime.jsx("span", { className: "ai-chat-booking-card__title", children: "Booking Error" })] }), state.errorMessage && (jsxRuntime.jsx("p", { className: "ai-chat-booking-card__error", children: state.errorMessage }))] }));
28565
+ }
28566
+ if (isSubmitting || isWaitingForBackend) {
28567
+ return renderSkeleton();
28568
+ }
28569
+ // ========================================
28570
+ // Phase: Email Collection
28571
+ // ========================================
28572
+ if (phase === 'awaiting_email') {
28573
+ const displayError = emailError || state.errorMessage;
28574
+ return (jsxRuntime.jsxs("div", { className: "ai-chat-booking-card", children: [jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntime.jsx("span", { className: "ai-chat-booking-card__icon", children: "\uD83D\uDCE7" }), jsxRuntime.jsx("span", { className: "ai-chat-booking-card__title", children: "Enter Your Email" })] }), jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__content", children: [jsxRuntime.jsx("p", { className: "ai-chat-booking-card__description", children: "Please enter your email address to start the booking process." }), displayError && (jsxRuntime.jsx("p", { className: "ai-chat-booking-card__error", children: displayError })), jsxRuntime.jsx("input", { type: "email", className: "ai-chat-booking-card__input", placeholder: "your@email.com", value: emailInput, onChange: (e) => {
28575
+ setEmailInput(e.target.value);
28576
+ setEmailError(null);
28577
+ }, onKeyDown: (e) => {
28578
+ if (e.key === 'Enter') {
28579
+ handleEmailSubmit();
28580
+ }
28581
+ } }), jsxRuntime.jsx("button", { className: "ai-chat-booking-card__btn ai-chat-booking-card__btn--primary", onClick: handleEmailSubmit, disabled: !emailInput.trim(), style: {
28582
+ backgroundColor: accentColor || undefined,
28583
+ borderColor: accentColor || undefined,
28584
+ }, children: "Continue" })] })] }));
28585
+ }
28586
+ // ========================================
28587
+ // Phase: OTP Verification
28588
+ // ========================================
28589
+ if (phase === 'awaiting_otp') {
28590
+ const displayError = otpError || state.errorMessage;
28591
+ return (jsxRuntime.jsxs("div", { className: "ai-chat-booking-card", children: [jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntime.jsx("span", { className: "ai-chat-booking-card__icon", children: "\uD83D\uDD10" }), jsxRuntime.jsx("span", { className: "ai-chat-booking-card__title", children: "Verify Your Email" })] }), jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__content", children: [jsxRuntime.jsxs("p", { className: "ai-chat-booking-card__description", children: ["Enter the verification code sent to ", jsxRuntime.jsx("strong", { children: state.email })] }), jsxRuntime.jsx(PinInputGroup, { values: otpValues, onChange: (newValues) => {
28592
+ setOtpValues(newValues);
28593
+ setOtpError(null);
28594
+ if (newValues.every((value) => value.length === 1) && !isSubmitting) {
28595
+ const resolvedEmail = state.email || emailInput.trim() || null;
28596
+ handleSubmit({ otpCode: newValues.join(''), email: resolvedEmail }, 100);
28597
+ }
28598
+ }, disabled: isSubmitting }), displayError && (jsxRuntime.jsx("p", { className: "ai-chat-booking-card__error", children: displayError })), jsxRuntime.jsx("button", { className: "ai-chat-booking-card__btn ai-chat-booking-card__btn--primary", onClick: handleOtpSubmit, disabled: otpValues.join('').length !== 6, style: {
28599
+ backgroundColor: accentColor || undefined,
28600
+ borderColor: accentColor || undefined,
28601
+ }, children: "Verify" })] })] }));
28602
+ }
28603
+ // ========================================
28604
+ // Phase: Contact Selection
28605
+ // ========================================
28606
+ if (phase === 'awaiting_contact_selection') {
28607
+ return (jsxRuntime.jsxs("div", { className: "ai-chat-booking-card", children: [jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntime.jsx("span", { className: "ai-chat-booking-card__icon", children: "\uD83D\uDC65" }), jsxRuntime.jsx("span", { className: "ai-chat-booking-card__title", children: "Select a Contact" })] }), jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__content", children: [state.errorMessage && (jsxRuntime.jsx("p", { className: "ai-chat-booking-card__error", children: state.errorMessage })), state.bookableContacts.length === 0 ? (jsxRuntime.jsx("p", { className: "ai-chat-booking-card__empty", children: "No contacts available for booking." })) : (jsxRuntime.jsx("div", { className: "ai-chat-booking-card__grid", children: state.bookableContacts.map((contact) => (jsxRuntime.jsxs("button", { className: `ai-chat-booking-card__contact ${state.selectedContactId === contact.id ? 'ai-chat-booking-card__contact--selected' : ''}`, onClick: () => handleSubmit({ selectedContactId: contact.id }), style: {
28608
+ borderColor: state.selectedContactId === contact.id
28609
+ ? accentColor || undefined
28610
+ : undefined,
28611
+ backgroundColor: state.selectedContactId === contact.id
28612
+ ? `${accentColor || '#3b82f6'}15`
28613
+ : undefined,
28614
+ }, children: [jsxRuntime.jsx("div", { className: "ai-chat-booking-card__contact-name", children: contact.name }), contact.role && (jsxRuntime.jsx("div", { className: "ai-chat-booking-card__contact-role", children: contact.role }))] }, contact.id))) }))] })] }));
28615
+ }
28616
+ // ========================================
28617
+ // Phase: Options Selection
28618
+ // ========================================
28619
+ if (phase === 'awaiting_options') {
28620
+ const selectedContact = state.bookableContacts.find((c) => c.id === state.selectedContactId);
28621
+ return (jsxRuntime.jsxs("div", { className: "ai-chat-booking-card", children: [jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntime.jsx("span", { className: "ai-chat-booking-card__icon", children: "\uD83D\uDCC5" }), jsxRuntime.jsxs("span", { className: "ai-chat-booking-card__title", children: ["Book with ", selectedContact?.name] })] }), jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__content", children: [state.errorMessage && (jsxRuntime.jsx("p", { className: "ai-chat-booking-card__error", children: state.errorMessage })), jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__options", children: [jsxRuntime.jsxs("button", { className: "ai-chat-booking-card__option-btn", onClick: () => handleSubmit({ selectedOption: 'book_new' }), children: [jsxRuntime.jsx("span", { className: "ai-chat-booking-card__option-icon", children: "\u2795" }), jsxRuntime.jsx("span", { className: "ai-chat-booking-card__option-text", children: "Book New Appointment" })] }), state.userAppointments.length > 0 && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("button", { className: "ai-chat-booking-card__option-btn", onClick: () => handleSubmit({ selectedOption: 'view_existing' }), children: [jsxRuntime.jsx("span", { className: "ai-chat-booking-card__option-icon", children: "\uD83D\uDCCB" }), jsxRuntime.jsx("span", { className: "ai-chat-booking-card__option-text", children: "View Appointments" })] }), jsxRuntime.jsxs("button", { className: "ai-chat-booking-card__option-btn", onClick: () => handleSubmit({ selectedOption: 'cancel_existing' }), children: [jsxRuntime.jsx("span", { className: "ai-chat-booking-card__option-icon", children: "\u2715" }), jsxRuntime.jsx("span", { className: "ai-chat-booking-card__option-text", children: "Cancel Appointment" })] })] }))] })] })] }));
28622
+ }
28623
+ // ========================================
28624
+ // Phase: View Existing Appointments
28625
+ // ========================================
28626
+ if (state.phase === 'awaiting_options' && state.selectedOption === 'view_existing') {
28627
+ return (jsxRuntime.jsxs("div", { className: "ai-chat-booking-card", children: [jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntime.jsx("span", { className: "ai-chat-booking-card__icon", children: "\uD83D\uDCCB" }), jsxRuntime.jsx("span", { className: "ai-chat-booking-card__title", children: "Your Appointments" })] }), jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__content", children: [state.userAppointments.length === 0 ? (jsxRuntime.jsx("p", { className: "ai-chat-booking-card__empty", children: "You have no appointments yet." })) : (jsxRuntime.jsx("div", { className: "ai-chat-booking-card__appointments", children: state.userAppointments.map((apt) => (jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__appointment", children: [jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__appointment-header", children: [jsxRuntime.jsx("span", { className: "ai-chat-booking-card__appointment-subject", children: apt.subject }), jsxRuntime.jsx("span", { className: `ai-chat-booking-card__appointment-status ai-chat-booking-card__appointment-status--${apt.status}`, children: apt.status })] }), jsxRuntime.jsx("div", { className: "ai-chat-booking-card__appointment-time", children: apt.displayTime }), jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__appointment-contact", children: ["with ", apt.contactName] }), apt.teamsLink && (jsxRuntime.jsx("a", { href: apt.teamsLink, target: "_blank", rel: "noopener noreferrer", className: "ai-chat-booking-card__link", style: { color: accentColor }, children: "Join Teams Meeting \u2192" }))] }, apt.id))) })), jsxRuntime.jsx("button", { className: "ai-chat-booking-card__btn ai-chat-booking-card__btn--secondary", onClick: () => handleSubmit({ selectedOption: undefined }), children: "Back" })] })] }));
28628
+ }
28629
+ // ========================================
28630
+ // Phase: Cancel Appointment
28631
+ // ========================================
28632
+ if (state.phase === 'awaiting_options' && state.selectedOption === 'cancel_existing') {
28633
+ const activeAppointments = state.userAppointments.filter((a) => a.status !== 'cancelled' && a.status !== 'declined');
28634
+ return (jsxRuntime.jsxs("div", { className: "ai-chat-booking-card", children: [jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntime.jsx("span", { className: "ai-chat-booking-card__icon", children: "\u2715" }), jsxRuntime.jsx("span", { className: "ai-chat-booking-card__title", children: "Cancel Appointment" })] }), jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__content", children: [state.errorMessage && (jsxRuntime.jsx("p", { className: "ai-chat-booking-card__error", children: state.errorMessage })), activeAppointments.length === 0 ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("p", { className: "ai-chat-booking-card__empty", children: "No active appointments to cancel." }), jsxRuntime.jsx("button", { className: "ai-chat-booking-card__btn ai-chat-booking-card__btn--secondary", onClick: () => handleSubmit({ selectedOption: undefined }), children: "Back" })] })) : (jsxRuntime.jsx("div", { className: "ai-chat-booking-card__appointments", children: activeAppointments.map((apt) => (jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__appointment", children: [jsxRuntime.jsx("div", { className: "ai-chat-booking-card__appointment-header", children: jsxRuntime.jsx("span", { className: "ai-chat-booking-card__appointment-subject", children: apt.subject }) }), jsxRuntime.jsx("div", { className: "ai-chat-booking-card__appointment-time", children: apt.displayTime }), jsxRuntime.jsx("button", { className: "ai-chat-booking-card__btn ai-chat-booking-card__btn--danger", onClick: () => handleSubmit({ selectedAppointmentId: apt.id, confirmCancel: true }), children: "Cancel This Appointment" })] }, apt.id))) }))] })] }));
28635
+ }
28636
+ // ========================================
28637
+ // Phase: Slot Selection
28638
+ // ========================================
28639
+ if (phase === 'awaiting_slot_selection') {
28640
+ const groupedSlots = state.availableSlots.reduce((acc, slot) => {
28641
+ if (!acc[slot.displayDate]) {
28642
+ acc[slot.displayDate] = [];
28643
+ }
28644
+ acc[slot.displayDate].push(slot);
28645
+ return acc;
28646
+ }, {});
28647
+ return (jsxRuntime.jsxs("div", { className: "ai-chat-booking-card", children: [jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntime.jsx("span", { className: "ai-chat-booking-card__icon", children: "\uD83D\uDD50" }), jsxRuntime.jsx("span", { className: "ai-chat-booking-card__title", children: "Select a Time Slot" })] }), jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__content", children: [jsxRuntime.jsxs("p", { className: "ai-chat-booking-card__description", children: ["Available times in ", state.timeZone] }), state.errorMessage && (jsxRuntime.jsx("p", { className: "ai-chat-booking-card__error", children: state.errorMessage })), Object.entries(groupedSlots).map(([date, slots]) => (jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__date-group", children: [jsxRuntime.jsx("div", { className: "ai-chat-booking-card__date-header", children: date }), jsxRuntime.jsx("div", { className: "ai-chat-booking-card__slots", children: slots.map((slot, idx) => {
28648
+ const isSelected = state.selectedSlot?.startTime === slot.startTime &&
28649
+ state.selectedSlot?.endTime === slot.endTime;
28650
+ return (jsxRuntime.jsx("button", { className: `ai-chat-booking-card__slot ${isSelected ? 'ai-chat-booking-card__slot--selected' : ''}`, onClick: () => handleSubmit({
28651
+ selectedSlot: { startTime: slot.startTime, endTime: slot.endTime },
28652
+ }), style: {
28653
+ borderColor: isSelected ? accentColor || undefined : undefined,
28654
+ backgroundColor: isSelected ? `${accentColor || '#3b82f6'}15` : undefined,
28655
+ }, children: slot.displayTime }, `${slot.startTime}-${idx}`));
28656
+ }) })] }, date))), state.availableSlots.length === 0 && (jsxRuntime.jsx("p", { className: "ai-chat-booking-card__empty", children: "No available time slots." }))] })] }));
28657
+ }
28658
+ // ========================================
28659
+ // Phase: Confirmation
28660
+ // ========================================
28661
+ if (phase === 'awaiting_confirmation') {
28662
+ const selectedContact = state.bookableContacts.find((c) => c.id === state.selectedContactId);
28663
+ const selectedSlot = state.availableSlots.find((s) => s.startTime === state.selectedSlot?.startTime && s.endTime === state.selectedSlot?.endTime);
28664
+ return (jsxRuntime.jsxs("div", { className: "ai-chat-booking-card", children: [jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntime.jsx("span", { className: "ai-chat-booking-card__icon", children: "\u2713" }), jsxRuntime.jsx("span", { className: "ai-chat-booking-card__title", children: "Confirm Booking" })] }), jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__content", children: [state.errorMessage && (jsxRuntime.jsx("p", { className: "ai-chat-booking-card__error", children: state.errorMessage })), jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__summary", children: [jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__summary-row", children: [jsxRuntime.jsx("span", { className: "ai-chat-booking-card__summary-label", children: "Contact:" }), jsxRuntime.jsx("span", { className: "ai-chat-booking-card__summary-value", children: selectedContact?.name })] }), jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__summary-row", children: [jsxRuntime.jsx("span", { className: "ai-chat-booking-card__summary-label", children: "Date:" }), jsxRuntime.jsx("span", { className: "ai-chat-booking-card__summary-value", children: selectedSlot?.displayDate })] }), jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__summary-row", children: [jsxRuntime.jsx("span", { className: "ai-chat-booking-card__summary-label", children: "Time:" }), jsxRuntime.jsx("span", { className: "ai-chat-booking-card__summary-value", children: selectedSlot?.displayTime })] })] }), state.allowCustomSubject && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("label", { className: "ai-chat-booking-card__label", children: "Subject (optional):" }), jsxRuntime.jsx("input", { type: "text", className: "ai-chat-booking-card__input", placeholder: "Meeting subject", value: subjectInput, onChange: (e) => setSubjectInput(e.target.value) })] })), jsxRuntime.jsx("button", { className: "ai-chat-booking-card__btn ai-chat-booking-card__btn--primary", onClick: () => handleSubmit({
28665
+ subject: state.allowCustomSubject ? subjectInput || undefined : undefined,
28666
+ confirmed: true,
28667
+ }), style: {
28668
+ backgroundColor: accentColor || undefined,
28669
+ borderColor: accentColor || undefined,
28670
+ }, children: "Confirm Booking" })] })] }));
28671
+ }
28672
+ // Fallback for unknown states
28673
+ return (jsxRuntime.jsxs("div", { className: "ai-chat-booking-card", children: [jsxRuntime.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntime.jsx("span", { className: "ai-chat-booking-card__icon", children: "\uD83D\uDCC5" }), jsxRuntime.jsx("span", { className: "ai-chat-booking-card__title", children: "Booking" })] }), jsxRuntime.jsx("div", { className: "ai-chat-booking-card__content", children: jsxRuntime.jsx("p", { className: "ai-chat-booking-card__description", children: "Loading booking options..." }) })] }));
28674
+ }
28675
+
28676
+ const pendingResolvers = new Map();
28677
+ const resumeCallbacks = new Map();
28678
+ const frontendActionHandlers = {};
28679
+ const actionRenderers = {};
28680
+ function getFrontendActionHandler(implementation) {
28681
+ return frontendActionHandlers[implementation];
28682
+ }
28683
+ function getActionRenderer(implementation) {
28684
+ return actionRenderers[implementation];
28685
+ }
28686
+ function waitForActionState(toolCallId) {
28687
+ return new Promise((resolve) => {
28688
+ pendingResolvers.set(toolCallId, resolve);
28689
+ });
28690
+ }
28691
+ function resolveActionState(toolCallId, state) {
28692
+ const resolver = pendingResolvers.get(toolCallId);
28693
+ if (resolver) {
28694
+ pendingResolvers.delete(toolCallId);
28695
+ resolver(state);
28696
+ return;
28697
+ }
28698
+ const resumeCallback = resumeCallbacks.get(toolCallId);
27774
28699
  if (resumeCallback) {
27775
28700
  resumeCallback(state).catch((error) => {
27776
28701
  console.error("[Action] Failed to resume action:", error);
@@ -27798,13 +28723,19 @@ function registerGoogleCalendarAction() {
27798
28723
  // Register the handler
27799
28724
  registerGoogleCalendarHandler();
27800
28725
  // Register the renderer
27801
- actionRenderers["google-calendar-appointment"] = (message) => {
28726
+ actionRenderers["google-calendar-appointment"] = (message, accentColor, _variant, onActionDismiss) => {
27802
28727
  const action = message.action;
27803
28728
  if (!action)
27804
28729
  return null;
27805
28730
  const handleComplete = (toolCallId, newState) => {
27806
28731
  resolveActionState(toolCallId, newState);
27807
28732
  };
28733
+ const handleDismiss = onActionDismiss
28734
+ ? (toolCallId) => {
28735
+ resolveActionState(toolCallId, { __dismissed: true });
28736
+ onActionDismiss(toolCallId);
28737
+ }
28738
+ : undefined;
27808
28739
  return (jsxRuntime.jsx(GoogleCalendarCard, { action: {
27809
28740
  implementation: action.implementation,
27810
28741
  toolCallId: action.toolCallId,
@@ -27812,7 +28743,45 @@ function registerGoogleCalendarAction() {
27812
28743
  input: action.input,
27813
28744
  state: action.state,
27814
28745
  done: action.done ?? false,
27815
- }, onComplete: handleComplete }));
28746
+ }, onComplete: handleComplete, onDismiss: handleDismiss, accentColor: accentColor }));
28747
+ };
28748
+ }
28749
+
28750
+ function registerMicrosoftCalendarHandler() {
28751
+ frontendActionHandlers["microsoft-calendar-appointment"] = async (_input, _state, context) => {
28752
+ return waitForActionState(context.toolCallId);
28753
+ };
28754
+ }
28755
+
28756
+ /**
28757
+ * Register microsoft-calendar-appointment action handler and renderer.
28758
+ * Called by initializeActionHandlers to prevent tree-shaking.
28759
+ */
28760
+ function registerMicrosoftCalendarAction() {
28761
+ // Register the handler
28762
+ registerMicrosoftCalendarHandler();
28763
+ // Register the renderer
28764
+ actionRenderers["microsoft-calendar-appointment"] = (message, accentColor, _variant, onActionDismiss) => {
28765
+ const action = message.action;
28766
+ if (!action)
28767
+ return null;
28768
+ const handleComplete = (toolCallId, newState) => {
28769
+ resolveActionState(toolCallId, newState);
28770
+ };
28771
+ const handleDismiss = onActionDismiss
28772
+ ? (toolCallId) => {
28773
+ resolveActionState(toolCallId, { __dismissed: true });
28774
+ onActionDismiss(toolCallId);
28775
+ }
28776
+ : undefined;
28777
+ return (jsxRuntime.jsx(MicrosoftCalendarCard, { action: {
28778
+ implementation: action.implementation,
28779
+ toolCallId: action.toolCallId,
28780
+ actionId: action.actionId,
28781
+ input: action.input,
28782
+ state: action.state,
28783
+ done: action.done ?? false,
28784
+ }, onComplete: handleComplete, onDismiss: handleDismiss, accentColor: accentColor }));
27816
28785
  };
27817
28786
  }
27818
28787
 
@@ -27826,7 +28795,7 @@ function registerLinkPreviewAction() {
27826
28795
  return { ...state, status: "displaying" };
27827
28796
  };
27828
28797
  // Renderer - displays the link preview card
27829
- actionRenderers["link-preview"] = (message) => {
28798
+ actionRenderers["link-preview"] = (message, accentColor) => {
27830
28799
  const action = message.action;
27831
28800
  if (!action)
27832
28801
  return null;
@@ -27844,7 +28813,7 @@ function registerLinkPreviewAction() {
27844
28813
  input: action.input,
27845
28814
  state: action.state,
27846
28815
  done: isDone,
27847
- }, onComplete: handleComplete }));
28816
+ }, onComplete: handleComplete, accentColor: accentColor }));
27848
28817
  };
27849
28818
  }
27850
28819
 
@@ -27858,7 +28827,7 @@ function registerVideoPlayerAction() {
27858
28827
  return { ...state, status: "displaying" };
27859
28828
  };
27860
28829
  // Renderer - displays the embedded video player card
27861
- actionRenderers["video-player"] = (message) => {
28830
+ actionRenderers["video-player"] = (message, accentColor) => {
27862
28831
  const action = message.action;
27863
28832
  if (!action)
27864
28833
  return null;
@@ -27876,7 +28845,7 @@ function registerVideoPlayerAction() {
27876
28845
  input: action.input,
27877
28846
  state: action.state,
27878
28847
  done: isDone,
27879
- }, onComplete: handleComplete }));
28848
+ }, onComplete: handleComplete, accentColor: accentColor }));
27880
28849
  };
27881
28850
  }
27882
28851
 
@@ -27890,7 +28859,7 @@ function registerLocationCardAction() {
27890
28859
  return { ...state, status: "displaying" };
27891
28860
  };
27892
28861
  // Renderer - displays the location card
27893
- actionRenderers["location-card"] = (message, accentColor) => {
28862
+ actionRenderers["location-card"] = (message, accentColor, variant) => {
27894
28863
  const action = message.action;
27895
28864
  if (!action)
27896
28865
  return null;
@@ -27908,7 +28877,134 @@ function registerLocationCardAction() {
27908
28877
  input: action.input,
27909
28878
  state: action.state,
27910
28879
  done: isDone,
27911
- }, onComplete: handleComplete, accentColor: accentColor, maxColumns: 1 }));
28880
+ }, onComplete: handleComplete, accentColor: accentColor, maxColumns: variant === 'fullpage' ? 3 : 1 }));
28881
+ };
28882
+ }
28883
+
28884
+ function registerContactCardAction() {
28885
+ // Handler - auto-completes immediately since no user input is needed
28886
+ frontendActionHandlers['contact-card'] = async (_input, state, _context) => {
28887
+ return { ...state, status: 'displaying' };
28888
+ };
28889
+ // Renderer - displays the contact card
28890
+ actionRenderers['contact-card'] = (message, accentColor, variant) => {
28891
+ const action = message.action;
28892
+ if (!action)
28893
+ return null;
28894
+ const handleComplete = (toolCallId, newState) => {
28895
+ resolveActionState(toolCallId, newState);
28896
+ };
28897
+ // Check if action state indicates it's already complete
28898
+ const state = action.state;
28899
+ const status = state?.status;
28900
+ const isDone = action.done || status === 'displaying' || status === 'contacted';
28901
+ return (jsxRuntime.jsx(ContactCard, { action: {
28902
+ implementation: action.implementation,
28903
+ toolCallId: action.toolCallId,
28904
+ actionId: action.actionId,
28905
+ input: action.input,
28906
+ state: action.state,
28907
+ done: isDone,
28908
+ }, onComplete: handleComplete, accentColor: accentColor, maxColumns: variant === 'fullpage' ? 3 : 1 }));
28909
+ };
28910
+ }
28911
+
28912
+ function registerQueryContactDirectoryAction() {
28913
+ // Handler - auto-completes immediately since no user input is needed
28914
+ frontendActionHandlers['query-contact-directory'] = async (_input, state, _context) => {
28915
+ return { ...state, status: 'displaying' };
28916
+ };
28917
+ // Renderer - displays the contact card with search results
28918
+ actionRenderers['query-contact-directory'] = (message, accentColor, variant) => {
28919
+ const action = message.action;
28920
+ if (!action)
28921
+ return null;
28922
+ // Handle completion - triggers agent to continue with text response
28923
+ const handleComplete = (toolCallId, newState) => {
28924
+ resolveActionState(toolCallId, newState);
28925
+ };
28926
+ // Check if action state indicates it's already complete
28927
+ const state = action.state;
28928
+ const status = state?.status;
28929
+ const isDone = action.done || status === 'displaying' || status === 'contacted';
28930
+ return (jsxRuntime.jsx(ContactCard, { action: {
28931
+ implementation: action.implementation,
28932
+ toolCallId: action.toolCallId,
28933
+ actionId: action.actionId,
28934
+ input: action.input,
28935
+ state: action.state,
28936
+ done: isDone,
28937
+ }, onComplete: handleComplete, accentColor: accentColor, maxColumns: variant === 'fullpage' ? 3 : 1 }));
28938
+ };
28939
+ }
28940
+
28941
+ function registerDisplayFormAction() {
28942
+ // Handler - handles form submission and state updates
28943
+ frontendActionHandlers['display-form'] = async (_input, _state, context) => {
28944
+ return waitForActionState(context.toolCallId);
28945
+ };
28946
+ // Renderer - displays the form card
28947
+ actionRenderers['display-form'] = (message, accentColor, variant, onActionDismiss) => {
28948
+ const action = message.action;
28949
+ if (!action)
28950
+ return null;
28951
+ const handleComplete = (toolCallId, newState) => {
28952
+ resolveActionState(toolCallId, newState);
28953
+ };
28954
+ const handleDismiss = onActionDismiss
28955
+ ? (toolCallId) => {
28956
+ resolveActionState(toolCallId, { __dismissed: true });
28957
+ onActionDismiss(toolCallId);
28958
+ }
28959
+ : undefined;
28960
+ // Check if action state indicates it's already complete
28961
+ const state = action.state;
28962
+ const status = state?.status;
28963
+ const isDone = action.done || status === 'completed' || status === 'submitted';
28964
+ return (jsxRuntime.jsx(FormCard, { action: {
28965
+ implementation: action.implementation,
28966
+ toolCallId: action.toolCallId,
28967
+ actionId: action.actionId,
28968
+ input: action.input,
28969
+ state: action.state,
28970
+ done: isDone,
28971
+ }, onComplete: handleComplete, onDismiss: handleDismiss, accentColor: accentColor }));
28972
+ };
28973
+ }
28974
+
28975
+ /**
28976
+ * Book Contact Appointment Handler
28977
+ * Frontend action handler that waits for action completion
28978
+ */
28979
+ function registerBookContactAppointmentHandler() {
28980
+ frontendActionHandlers["book-contact-appointment"] = async (_input, _state, context) => {
28981
+ return waitForActionState(context.toolCallId);
28982
+ };
28983
+ }
28984
+
28985
+ /**
28986
+ * Register book-contact-appointment action handler and renderer.
28987
+ * Called by initializeActionHandlers to prevent tree-shaking.
28988
+ */
28989
+ function registerBookContactAppointmentAction() {
28990
+ // Register the handler
28991
+ registerBookContactAppointmentHandler();
28992
+ // Register the renderer
28993
+ actionRenderers['book-contact-appointment'] = (message, accentColor) => {
28994
+ const action = message.action;
28995
+ if (!action)
28996
+ return null;
28997
+ const handleComplete = (toolCallId, newState) => {
28998
+ resolveActionState(toolCallId, newState);
28999
+ };
29000
+ return (jsxRuntime.jsx(BookContactAppointmentCard, { action: {
29001
+ implementation: action.implementation,
29002
+ toolCallId: action.toolCallId,
29003
+ actionId: action.actionId,
29004
+ input: action.input,
29005
+ state: action.state,
29006
+ done: action.done ?? false,
29007
+ }, onComplete: handleComplete, accentColor: accentColor }));
27912
29008
  };
27913
29009
  }
27914
29010
 
@@ -27925,9 +29021,14 @@ function initializeActionHandlers() {
27925
29021
  initialized = true;
27926
29022
  // Explicitly call each registration function to prevent tree-shaking
27927
29023
  registerGoogleCalendarAction();
29024
+ registerMicrosoftCalendarAction();
27928
29025
  registerLinkPreviewAction();
27929
29026
  registerVideoPlayerAction();
27930
29027
  registerLocationCardAction();
29028
+ registerQueryContactDirectoryAction();
29029
+ registerContactCardAction();
29030
+ registerDisplayFormAction();
29031
+ registerBookContactAppointmentAction();
27931
29032
  }
27932
29033
 
27933
29034
  /**
@@ -28147,12 +29248,6 @@ function isStorageAvailable() {
28147
29248
  }
28148
29249
  }
28149
29250
 
28150
- /**
28151
- * useChat Hook
28152
- * Main state management for chat functionality
28153
- */
28154
- // Initialize action handlers immediately to prevent tree-shaking
28155
- initializeActionHandlers();
28156
29251
  function hydrateToolNames(messages) {
28157
29252
  const toolCallNameById = new Map();
28158
29253
  for (const entry of messages) {
@@ -28196,118 +29291,78 @@ function hydrateToolNames(messages) {
28196
29291
  };
28197
29292
  });
28198
29293
  }
28199
- function hydrateActionContent(messages) {
28200
- return messages.map((entry) => {
28201
- if (entry.message.role !== "assistant" || !entry.action) {
28202
- return entry;
28203
- }
28204
- const content = typeof entry.message.content === "string" ? entry.message.content : "";
28205
- if (content.trim().length > 0) {
28206
- return entry;
28207
- }
28208
- return {
28209
- ...entry,
28210
- message: { ...entry.message, content: getActionPrompt(entry.action.implementation) },
28211
- };
28212
- });
29294
+ function hydrateMessages(messages) {
29295
+ const visibleMessages = messages.filter((message) => !message.action?.hidden);
29296
+ return hydrateToolNames(visibleMessages);
28213
29297
  }
28214
- function hydrateActionDoneStatus(messages) {
28215
- return messages.map((entry) => {
28216
- if (!entry.action) {
28217
- return entry;
28218
- }
28219
- // If action already marked done, skip
28220
- if (entry.action.done) {
28221
- return entry;
29298
+
29299
+ function deriveErrorInfo(error) {
29300
+ if (error instanceof ApiError) {
29301
+ const retryAfterSeconds = typeof error.retryAfterMs === 'number'
29302
+ ? Math.max(1, Math.ceil(error.retryAfterMs / 1000))
29303
+ : undefined;
29304
+ const lowerMessage = (error.message || '').toLowerCase();
29305
+ let message;
29306
+ switch (error.status) {
29307
+ case 429: {
29308
+ const isPerUser = lowerMessage.includes('user');
29309
+ const base = isPerUser
29310
+ ? 'You have reached the per-user rate limit.'
29311
+ : 'This widget has received too many requests.';
29312
+ if (retryAfterSeconds) {
29313
+ message = `${base} Please wait ${retryAfterSeconds} second${retryAfterSeconds === 1 ? '' : 's'} before trying again.`;
29314
+ }
29315
+ else {
29316
+ message = `${base} Please wait a moment and try again.`;
29317
+ }
29318
+ break;
29319
+ }
29320
+ case 401:
29321
+ message = 'Authentication failed. Please refresh the page or verify your API key.';
29322
+ break;
29323
+ case 403:
29324
+ message = 'Access to this widget is restricted. Please contact the site owner if you believe this is an error.';
29325
+ break;
29326
+ case 404:
29327
+ if (lowerMessage.includes('not active')) {
29328
+ message = 'This widget is currently inactive. Please contact the site owner.';
29329
+ }
29330
+ else {
29331
+ message = 'We could not find this widget. It may have been removed.';
29332
+ }
29333
+ break;
29334
+ default:
29335
+ if (error.status >= 500) {
29336
+ message = 'The server encountered an error. Please try again shortly.';
29337
+ }
29338
+ else if (error.status > 0) {
29339
+ message = error.message || 'Something went wrong. Please try again.';
29340
+ }
29341
+ else {
29342
+ message = error.message || 'Unable to connect to the server. Please check your internet connection.';
29343
+ }
28222
29344
  }
28223
- // Check if action state indicates completion
28224
- const state = entry.action.state;
28225
- if (!state) {
28226
- return entry;
29345
+ return { message, retryAfterSeconds, status: error.status };
29346
+ }
29347
+ if (error instanceof Error) {
29348
+ const lower = error.message.toLowerCase();
29349
+ if (lower.includes('network')) {
29350
+ return { message: 'Unable to connect to the server. Please check your internet connection.' };
28227
29351
  }
28228
- // Link-preview: done if status is "displaying" or "clicked"
28229
- if (entry.action.implementation === "link-preview") {
28230
- const status = state.status;
28231
- if (status === "displaying" || status === "clicked") {
28232
- return {
28233
- ...entry,
28234
- action: { ...entry.action, done: true },
28235
- };
28236
- }
29352
+ if (lower.includes('timeout')) {
29353
+ return { message: 'The request timed out. Please try again.' };
28237
29354
  }
28238
- // Google Calendar: done if status indicates completion
28239
- if (entry.action.implementation === "google-calendar-appointment") {
28240
- const status = state.status;
28241
- if (status === "booked" || status === "cancelled" || status === "error") {
28242
- return {
28243
- ...entry,
28244
- action: { ...entry.action, done: true },
28245
- };
28246
- }
29355
+ if (lower.includes('unauthorized') || lower.includes('401')) {
29356
+ return { message: 'Authentication failed. Please refresh the page or verify your API key.' };
28247
29357
  }
28248
- return entry;
28249
- });
28250
- }
28251
- function hydrateMessages(messages) {
28252
- return hydrateActionDoneStatus(hydrateActionContent(hydrateToolNames(messages)));
28253
- }
28254
- function setupActionResumeCallbacks(messages, client, conversationId, setState, onMessageUpdate) {
28255
- // Find all incomplete actions and register resume callbacks
28256
- for (const message of messages) {
28257
- if (message.action && !message.action.done) {
28258
- const toolCallId = message.action.toolCallId;
28259
- const toolName = message.message.name || message.toolExecuting || "tool";
28260
- registerActionResumeCallback(toolCallId, async (newState) => {
28261
- // When user interacts with the action after reload, continue the stream
28262
- try {
28263
- // Update the action message with the new state
28264
- setState(prev => ({
28265
- ...prev,
28266
- messages: prev.messages.map(m => m.action?.toolCallId === toolCallId
28267
- ? {
28268
- ...m,
28269
- action: m.action ? { ...m.action, state: newState } : undefined,
28270
- }
28271
- : m),
28272
- isTyping: true,
28273
- }));
28274
- const streamState = createStreamState();
28275
- // Continue the agent stream with the new state
28276
- for await (const event of client.continueAgentMessageStream(conversationId, toolCallId, newState)) {
28277
- if (event.type === "done") {
28278
- finalizeToolMessage(streamState, setState, toolCallId, toolName);
28279
- streamState.sources = event.sources;
28280
- streamState.toolCallToActionId = event.tool_call_to_action_id;
28281
- finalizeStreamMessages(setState, streamState.newMessageIds, event.sources, event.tool_call_to_action_id, event.suggestions);
28282
- continue;
28283
- }
28284
- if (event.type === "error") {
28285
- const errorMessage = {
28286
- id: generateMessageId(),
28287
- message: {
28288
- role: "assistant",
28289
- content: "Sorry, an error occurred. Please try again later.",
28290
- },
28291
- timestamp: new Date().toISOString(),
28292
- sources: [],
28293
- isError: true,
28294
- };
28295
- upsertMessage(setState, errorMessage, false);
28296
- setState(prev => ({ ...prev, isTyping: false }));
28297
- return;
28298
- }
28299
- handleStreamEvent(event, streamState, onMessageUpdate, setState);
28300
- }
28301
- setState(prev => ({ ...prev, isTyping: false }));
28302
- }
28303
- catch (error) {
28304
- console.error("[Action Resume] Failed to continue stream:", error);
28305
- setState(prev => ({ ...prev, isTyping: false }));
28306
- }
28307
- });
29358
+ if (lower.includes('internal server error') || lower.includes('500')) {
29359
+ return { message: 'The server encountered an error. Please try again shortly.' };
28308
29360
  }
29361
+ return { message: error.message || 'Something went wrong. Please try again.' };
28309
29362
  }
29363
+ return { message: 'Something went wrong. Please try again.' };
28310
29364
  }
29365
+
28311
29366
  function createStreamState() {
28312
29367
  return {
28313
29368
  currentContent: "",
@@ -28316,6 +29371,7 @@ function createStreamState() {
28316
29371
  newMessageIds: new Set(),
28317
29372
  sources: [],
28318
29373
  toolCallToActionId: {},
29374
+ requestId: generateMessageId(),
28319
29375
  };
28320
29376
  }
28321
29377
  function upsertMessage(setState, message, isTyping) {
@@ -28351,15 +29407,40 @@ function finalizeStreamMessages(setState, messageIds, sources, toolCallToActionI
28351
29407
  return msg;
28352
29408
  }
28353
29409
  // Attach suggestions only to the last assistant message
28354
- if (index === lastAssistantIndex && suggestions && suggestions.length > 0) {
28355
- return { ...msg, sources, toolCallToActionId, suggestions };
28356
- }
28357
- return { ...msg, sources, toolCallToActionId };
29410
+ const withSuggestions = index === lastAssistantIndex && suggestions && suggestions.length > 0
29411
+ ? { suggestions }
29412
+ : {};
29413
+ return { ...msg, sources, toolCallToActionId, ...withSuggestions };
28358
29414
  }),
28359
29415
  isTyping: false,
28360
29416
  };
28361
29417
  });
28362
29418
  }
29419
+ function finalizeToolMessage(streamState, setState, toolCallId, toolName) {
29420
+ setState(prev => {
29421
+ const messages = prev.messages.map((entry) => {
29422
+ const matchesToolCall = entry.message.role === "tool" && entry.message.tool_call_id === toolCallId;
29423
+ if (!matchesToolCall) {
29424
+ return entry;
29425
+ }
29426
+ const existingName = entry.message.name || toolName;
29427
+ return {
29428
+ ...entry,
29429
+ message: {
29430
+ role: "tool",
29431
+ content: typeof entry.message.content === "string" ? entry.message.content : "",
29432
+ tool_call_id: toolCallId,
29433
+ name: existingName,
29434
+ },
29435
+ isStreaming: false,
29436
+ toolExecuting: existingName,
29437
+ };
29438
+ });
29439
+ return { ...prev, messages, isTyping: false, isLoading: false };
29440
+ });
29441
+ streamState.activeToolCallCount = Math.max(0, streamState.activeToolCallCount - 1);
29442
+ }
29443
+
28363
29444
  function handleContentEvent(event, streamState, onMessageUpdate, setState) {
28364
29445
  streamState.currentContent += event.content;
28365
29446
  const assistantMessage = {
@@ -28406,8 +29487,6 @@ function handleToolStartEvent(event, streamState, onMessageUpdate, setState) {
28406
29487
  }
28407
29488
  function handleToolEndEvent(event, streamState, _onMessageUpdate, setState) {
28408
29489
  streamState.activeToolCallCount = Math.max(0, streamState.activeToolCallCount - 1);
28409
- // Update state and mark action as done in a single setState call
28410
- // Keep isTyping: true because the agent may continue generating content after tool completion
28411
29490
  setState(prev => {
28412
29491
  const messages = prev.messages.map((msg) => {
28413
29492
  const matchesToolCall = msg.message.role === "tool" && msg.message.tool_call_id === event.tool_call_id;
@@ -28415,7 +29494,27 @@ function handleToolEndEvent(event, streamState, _onMessageUpdate, setState) {
28415
29494
  return msg;
28416
29495
  }
28417
29496
  const existingName = msg.message.name || event.tool_name;
28418
- return {
29497
+ let action = msg.action;
29498
+ if (event.action_id && event.implementation) {
29499
+ action = {
29500
+ ...action,
29501
+ implementation: event.implementation,
29502
+ toolCallId: event.tool_call_id,
29503
+ actionId: event.action_id,
29504
+ input: (event.input || {}),
29505
+ state: (event.state || {}),
29506
+ done: event.done,
29507
+ };
29508
+ }
29509
+ else if (action) {
29510
+ action = {
29511
+ ...action,
29512
+ input: event.input ? event.input : action.input,
29513
+ state: event.state ? event.state : action.state,
29514
+ done: event.done,
29515
+ };
29516
+ }
29517
+ const updatedMsg = {
28419
29518
  ...msg,
28420
29519
  message: {
28421
29520
  role: "tool",
@@ -28425,14 +29524,10 @@ function handleToolEndEvent(event, streamState, _onMessageUpdate, setState) {
28425
29524
  },
28426
29525
  isStreaming: false,
28427
29526
  toolExecuting: existingName,
28428
- action: msg.action ? {
28429
- ...msg.action,
28430
- state: event.state || msg.action.state,
28431
- done: true, // Mark action as completed
28432
- } : undefined,
29527
+ action,
28433
29528
  };
29529
+ return updatedMsg;
28434
29530
  });
28435
- // Keep typing indicator visible - it will be hidden by done/finalizeStreamMessages
28436
29531
  return { ...prev, messages, isTyping: true, isLoading: false };
28437
29532
  });
28438
29533
  }
@@ -28464,34 +29559,6 @@ function handleToolErrorEvent(event, streamState, _onMessageUpdate, setState) {
28464
29559
  return { ...prev, messages, isTyping: true, isLoading: false };
28465
29560
  });
28466
29561
  }
28467
- function finalizeToolMessage(streamState, setState, toolCallId, toolName) {
28468
- setState(prev => {
28469
- const messages = prev.messages.map((entry) => {
28470
- const matchesToolCall = entry.message.role === "tool" && entry.message.tool_call_id === toolCallId;
28471
- if (!matchesToolCall) {
28472
- return entry;
28473
- }
28474
- const existingName = entry.message.name || toolName;
28475
- return {
28476
- ...entry,
28477
- message: {
28478
- role: "tool",
28479
- content: typeof entry.message.content === "string" ? entry.message.content : "",
28480
- tool_call_id: toolCallId,
28481
- name: existingName,
28482
- },
28483
- isStreaming: false,
28484
- toolExecuting: existingName,
28485
- action: entry.action ? {
28486
- ...entry.action,
28487
- done: true, // Mark action as completed
28488
- } : undefined,
28489
- };
28490
- });
28491
- return { ...prev, messages, isTyping: false, isLoading: false };
28492
- });
28493
- streamState.activeToolCallCount = Math.max(0, streamState.activeToolCallCount - 1);
28494
- }
28495
29562
  function handleDoneEvent(event, streamState, _onMessageUpdate, setState) {
28496
29563
  streamState.sources = event.sources;
28497
29564
  streamState.toolCallToActionId = event.tool_call_to_action_id;
@@ -28550,6 +29617,10 @@ function handleStreamEvent(event, streamState, onMessageUpdate, setState) {
28550
29617
  console.warn('[Chat] Unknown event type:', event.type);
28551
29618
  }
28552
29619
  }
29620
+
29621
+ function isDismissedState(state) {
29622
+ return Boolean(state.__dismissed);
29623
+ }
28553
29624
  async function handleActionLoop(client, initialEvent, streamState, onMessageUpdate, setState, widgetId, conversationId, getMessages) {
28554
29625
  let pendingEvent = initialEvent;
28555
29626
  while (pendingEvent) {
@@ -28576,7 +29647,7 @@ async function handleActionLoop(client, initialEvent, streamState, onMessageUpda
28576
29647
  actionId: pendingEvent.action_id,
28577
29648
  input: pendingEvent.input,
28578
29649
  state: pendingEvent.state,
28579
- done: false, // Action not yet completed
29650
+ done: pendingEvent.done ?? false,
28580
29651
  },
28581
29652
  };
28582
29653
  if (streamState.activeToolCallCount === 0) {
@@ -28590,7 +29661,7 @@ async function handleActionLoop(client, initialEvent, streamState, onMessageUpda
28590
29661
  id: generateMessageId(),
28591
29662
  message: {
28592
29663
  role: "assistant",
28593
- content: "Sorry, an error occurred. Please try again later.",
29664
+ content: "Sorry, an error occurred.",
28594
29665
  },
28595
29666
  timestamp: new Date().toISOString(),
28596
29667
  sources: [],
@@ -28614,7 +29685,7 @@ async function handleActionLoop(client, initialEvent, streamState, onMessageUpda
28614
29685
  console.error("[Widget] Frontend action failed:", error);
28615
29686
  const errorMessageEntry = {
28616
29687
  id: generateMessageId(),
28617
- message: { role: "assistant", content: "Sorry, an error occurred. Please try again later." },
29688
+ message: { role: "assistant", content: "Sorry, an error occurred." },
28618
29689
  timestamp: new Date().toISOString(),
28619
29690
  sources: [],
28620
29691
  isError: true,
@@ -28624,16 +29695,17 @@ async function handleActionLoop(client, initialEvent, streamState, onMessageUpda
28624
29695
  return;
28625
29696
  }
28626
29697
  pendingEvent = null;
28627
- const updatedToolMessage = {
28628
- ...toolMessage,
28629
- action: toolMessage.action
28630
- ? {
28631
- ...toolMessage.action,
28632
- state: nextState,
28633
- }
28634
- : undefined,
28635
- };
28636
- upsertMessage(setState, updatedToolMessage, true);
29698
+ const dismissed = isDismissedState(nextState);
29699
+ if (!dismissed) {
29700
+ const updatedToolMessage = {
29701
+ ...toolMessage,
29702
+ action: toolMessage.action ? { ...toolMessage.action, state: nextState } : toolMessage.action,
29703
+ };
29704
+ upsertMessage(setState, updatedToolMessage, true);
29705
+ }
29706
+ if (dismissed) {
29707
+ return;
29708
+ }
28637
29709
  let streamEnded = false;
28638
29710
  for await (const event of client.continueAgentMessageStream(conversationId, resumeToolCallId, nextState)) {
28639
29711
  if (event.type === "action_request") {
@@ -28641,22 +29713,20 @@ async function handleActionLoop(client, initialEvent, streamState, onMessageUpda
28641
29713
  break;
28642
29714
  }
28643
29715
  if (event.type === "done") {
28644
- // Don't extract and update state from done event - the state was already
28645
- // updated by tool_end event or by the user's frontend action.
29716
+ // Finalize tool message and stream messages
28646
29717
  finalizeToolMessage(streamState, setState, resumeToolCallId, toolName);
28647
- // Handle the done event but skip the tool finalization part since we already did it
28648
29718
  streamState.sources = event.sources;
28649
29719
  streamState.toolCallToActionId = event.tool_call_to_action_id;
28650
29720
  finalizeStreamMessages(setState, streamState.newMessageIds, event.sources, event.tool_call_to_action_id, event.suggestions);
28651
29721
  streamEnded = true;
28652
- continue; // Skip handleStreamEvent for done events to avoid state conflicts
29722
+ continue;
28653
29723
  }
28654
29724
  if (event.type === "error") {
28655
29725
  const errorMessage = {
28656
29726
  id: generateMessageId(),
28657
29727
  message: {
28658
29728
  role: "assistant",
28659
- content: "Sorry, an error occurred. Please try again later.",
29729
+ content: "Sorry, an error occurred.",
28660
29730
  },
28661
29731
  timestamp: new Date().toISOString(),
28662
29732
  sources: [],
@@ -28667,73 +29737,83 @@ async function handleActionLoop(client, initialEvent, streamState, onMessageUpda
28667
29737
  }
28668
29738
  handleStreamEvent(event, streamState, onMessageUpdate, setState);
28669
29739
  }
28670
- // If stream ended without a done event (e.g., only tool_end was sent), finalize the tool message
29740
+ // If stream ended without a done event, finalize the tool message
28671
29741
  if (!streamEnded && !pendingEvent) {
28672
29742
  finalizeToolMessage(streamState, setState, resumeToolCallId, toolName);
28673
29743
  }
28674
29744
  }
28675
29745
  }
28676
- function deriveErrorInfo(error) {
28677
- if (error instanceof ApiError) {
28678
- const retryAfterSeconds = typeof error.retryAfterMs === 'number'
28679
- ? Math.max(1, Math.ceil(error.retryAfterMs / 1000))
28680
- : undefined;
28681
- const lowerMessage = (error.message || '').toLowerCase();
28682
- let message;
28683
- switch (error.status) {
28684
- case 429: {
28685
- const isPerUser = lowerMessage.includes('user');
28686
- const base = isPerUser
28687
- ? 'You have reached the per-user rate limit.'
28688
- : 'This widget has received too many requests.';
28689
- if (retryAfterSeconds) {
28690
- message = `${base} Please wait ${retryAfterSeconds} second${retryAfterSeconds === 1 ? '' : 's'} before trying again.`;
28691
- }
28692
- else {
28693
- message = `${base} Please wait a moment and try again.`;
28694
- }
28695
- break;
28696
- }
28697
- case 401:
28698
- message = 'Authentication failed. Please refresh the page or verify your API key.';
28699
- break;
28700
- case 403:
28701
- message = 'Access to this widget is restricted. Please contact the site owner if you believe this is an error.';
28702
- break;
28703
- case 404:
28704
- message = 'We could not find this widget. It may have been removed.';
28705
- break;
28706
- default:
28707
- if (error.status >= 500) {
28708
- message = 'The server encountered an error. Please try again shortly.';
28709
- }
28710
- else if (error.status > 0) {
28711
- message = error.message || 'Something went wrong. Please try again.';
29746
+ function setupActionResumeCallbacks(messages, client, conversationId, setState, onMessageUpdate, createStreamState, registerCallback) {
29747
+ // Find all incomplete actions and register resume callbacks
29748
+ for (const message of messages) {
29749
+ if (message.action && !message.action.done && !message.action.hidden) {
29750
+ const toolCallId = message.action.toolCallId;
29751
+ const toolName = message.message.name || message.toolExecuting || "tool";
29752
+ registerCallback(toolCallId, async (newState) => {
29753
+ // When user interacts with the action after reload, continue the stream
29754
+ try {
29755
+ // Update the action message with the new state and check completion
29756
+ if (isDismissedState(newState)) {
29757
+ setState(prev => ({ ...prev, isTyping: false }));
29758
+ return;
29759
+ }
29760
+ setState(prev => ({
29761
+ ...prev,
29762
+ messages: prev.messages.map(m => {
29763
+ if (m.action?.toolCallId !== toolCallId) {
29764
+ return m;
29765
+ }
29766
+ if (!m.action) {
29767
+ return m;
29768
+ }
29769
+ return { ...m, action: { ...m.action, state: newState } };
29770
+ }),
29771
+ isTyping: true,
29772
+ }));
29773
+ const streamState = createStreamState();
29774
+ // Continue the agent stream with the new state
29775
+ for await (const event of client.continueAgentMessageStream(conversationId, toolCallId, newState)) {
29776
+ if (event.type === "done") {
29777
+ finalizeToolMessage(streamState, setState, toolCallId, toolName);
29778
+ streamState.sources = event.sources;
29779
+ streamState.toolCallToActionId = event.tool_call_to_action_id;
29780
+ finalizeStreamMessages(setState, streamState.newMessageIds, event.sources, event.tool_call_to_action_id, event.suggestions);
29781
+ continue;
29782
+ }
29783
+ if (event.type === "error") {
29784
+ const errorMessage = {
29785
+ id: generateMessageId(),
29786
+ message: {
29787
+ role: "assistant",
29788
+ content: "Sorry, an error occurred. Please try again later.",
29789
+ },
29790
+ timestamp: new Date().toISOString(),
29791
+ sources: [],
29792
+ isError: true,
29793
+ };
29794
+ upsertMessage(setState, errorMessage, false);
29795
+ setState(prev => ({ ...prev, isTyping: false }));
29796
+ return;
29797
+ }
29798
+ handleStreamEvent(event, streamState, onMessageUpdate, setState);
29799
+ }
29800
+ setState(prev => ({ ...prev, isTyping: false }));
28712
29801
  }
28713
- else {
28714
- message = error.message || 'Unable to connect to the server. Please check your internet connection.';
29802
+ catch (error) {
29803
+ console.error("[Action Resume] Failed to continue stream:", error);
29804
+ setState(prev => ({ ...prev, isTyping: false }));
28715
29805
  }
29806
+ });
28716
29807
  }
28717
- return { message, retryAfterSeconds, status: error.status };
28718
- }
28719
- if (error instanceof Error) {
28720
- const lower = error.message.toLowerCase();
28721
- if (lower.includes('network')) {
28722
- return { message: 'Unable to connect to the server. Please check your internet connection.' };
28723
- }
28724
- if (lower.includes('timeout')) {
28725
- return { message: 'The request timed out. Please try again.' };
28726
- }
28727
- if (lower.includes('unauthorized') || lower.includes('401')) {
28728
- return { message: 'Authentication failed. Please refresh the page or verify your API key.' };
28729
- }
28730
- if (lower.includes('internal server error') || lower.includes('500')) {
28731
- return { message: 'The server encountered an error. Please try again shortly.' };
28732
- }
28733
- return { message: error.message || 'Something went wrong. Please try again.' };
28734
29808
  }
28735
- return { message: 'Something went wrong. Please try again.' };
28736
29809
  }
29810
+
29811
+ /**
29812
+ * useChat Hook
29813
+ * Main state management for chat functionality
29814
+ */
29815
+ // Initialize action handlers immediately to prevent tree-shaking
29816
+ initializeActionHandlers();
28737
29817
  function useChat(options) {
28738
29818
  const { widgetId, apiUrl, currentRoute, onMessage, onError, skipInitialization = false, } = options;
28739
29819
  const [state, setState] = React.useState({
@@ -28742,27 +29822,24 @@ function useChat(options) {
28742
29822
  isLoading: false,
28743
29823
  isTyping: false,
28744
29824
  error: null,
28745
- conversationId: '', // Will be set after loading conversation
29825
+ conversationId: '',
28746
29826
  config: null,
28747
29827
  });
28748
29828
  const stateRef = React.useRef(state);
28749
29829
  React.useEffect(() => {
28750
29830
  stateRef.current = state;
28751
29831
  }, [state]);
28752
- // Chat history state
28753
29832
  const [conversations, setConversations] = React.useState([]);
28754
- // Stream cancellation and rate limiting
28755
29833
  const abortControllerRef = React.useRef(null);
29834
+ const currentRequestIdRef = React.useRef(null);
28756
29835
  const lastNewChatTimeRef = React.useRef(0);
28757
- const NEW_CHAT_COOLDOWN_MS = 5000; // 2 second cooldown between new chats
29836
+ const NEW_CHAT_COOLDOWN_MS = 5000;
28758
29837
  const apiClient = React.useRef(new WidgetApiClient({ widgetId, apiUrl, currentRoute }));
28759
- // Update API client when currentRoute changes
28760
29838
  React.useEffect(() => {
28761
29839
  apiClient.current = new WidgetApiClient({ widgetId, apiUrl, currentRoute });
28762
29840
  }, [widgetId, apiUrl, currentRoute]);
28763
29841
  // Load configuration on mount and hydrate with existing conversation if available
28764
29842
  React.useEffect(() => {
28765
- // Skip initialization in preview mode
28766
29843
  if (skipInitialization) {
28767
29844
  return;
28768
29845
  }
@@ -28799,7 +29876,7 @@ function useChat(options) {
28799
29876
  }));
28800
29877
  // Setup resume callbacks for incomplete actions
28801
29878
  if (conversationId) {
28802
- setupActionResumeCallbacks(hydratedMessages, apiClient.current, conversationId, setState, onMessage ?? (() => { }));
29879
+ setupActionResumeCallbacks(hydratedMessages, apiClient.current, conversationId, setState, onMessage ?? (() => { }), createStreamState, registerActionResumeCallback);
28803
29880
  }
28804
29881
  }
28805
29882
  catch (error) {
@@ -28816,14 +29893,13 @@ function useChat(options) {
28816
29893
  initialize();
28817
29894
  return () => {
28818
29895
  isMounted = false;
28819
- // Cleanup resume callbacks
28820
29896
  state.messages.forEach(message => {
28821
29897
  if (message.action?.toolCallId) {
28822
29898
  unregisterActionResumeCallback(message.action.toolCallId);
28823
29899
  }
28824
29900
  });
28825
29901
  };
28826
- }, [widgetId, apiUrl, onError]);
29902
+ }, [widgetId, apiUrl, onError, skipInitialization]);
28827
29903
  // Save conversation when messages change
28828
29904
  React.useEffect(() => {
28829
29905
  const persistConversation = state.config?.settings.persistConversation ?? true;
@@ -28839,19 +29915,15 @@ function useChat(options) {
28839
29915
  const hasFiles = !!files && files.length > 0;
28840
29916
  if (!trimmedContent && !hasFiles)
28841
29917
  return;
28842
- // Block parallel streams - don't allow sending while already streaming
28843
29918
  if (stateRef.current.isTyping) {
28844
29919
  console.warn('[Widget] Cannot send message while streaming is in progress');
28845
29920
  return;
28846
29921
  }
28847
- // Cancel any existing stream before starting new one
28848
29922
  if (abortControllerRef.current) {
28849
29923
  abortControllerRef.current.abort();
28850
29924
  abortControllerRef.current = null;
28851
29925
  }
28852
- // Create new abort controller for this stream
28853
29926
  abortControllerRef.current = new AbortController();
28854
- // Strip [EXECUTE_ACTION:...] prefix from displayed message (but keep for API)
28855
29927
  const displayContent = trimmedContent.replace(/^\[EXECUTE_ACTION:[^\]]+\]\s*/, '');
28856
29928
  const userMessage = {
28857
29929
  id: generateMessageId(),
@@ -28862,12 +29934,11 @@ function useChat(options) {
28862
29934
  timestamp: new Date().toISOString(),
28863
29935
  sources: [],
28864
29936
  };
28865
- // Add user message immediately
28866
29937
  setState(prev => ({
28867
29938
  ...prev,
28868
29939
  messages: [...prev.messages, userMessage],
28869
- isLoading: false, // Don't show loading, will show typing when stream starts
28870
- isTyping: true, // Show typing indicator immediately
29940
+ isLoading: false,
29941
+ isTyping: true,
28871
29942
  error: null,
28872
29943
  }));
28873
29944
  onMessage?.(userMessage);
@@ -28907,26 +29978,27 @@ function useChat(options) {
28907
29978
  }
28908
29979
  catch (uploadError) {
28909
29980
  console.error('Failed to upload file:', uploadError);
28910
- // Continue with other files
28911
29981
  }
28912
29982
  }
28913
29983
  }
28914
- // Stream the response
28915
29984
  let lastStreamedMessage = null;
28916
29985
  const streamState = createStreamState();
28917
- // Capture the abort controller and conversation ID for this specific stream
29986
+ currentRequestIdRef.current = streamState.requestId;
28918
29987
  const currentAbortController = abortControllerRef.current;
28919
29988
  const streamConversationId = conversationId;
28920
- const stream = apiClient.current.sendAgentMessageStream(conversationId, trimmedContent, fileIds);
29989
+ const streamRequestId = streamState.requestId;
29990
+ const stream = apiClient.current.sendAgentMessageStream(conversationId, trimmedContent, fileIds, currentAbortController?.signal);
28921
29991
  for await (const event of stream) {
28922
- // Check if stream was aborted or conversation changed
28923
- if (currentAbortController?.signal.aborted || stateRef.current.conversationId !== streamConversationId) {
28924
- console.log('[Widget] Stream aborted or conversation changed, stopping event processing');
29992
+ if (currentAbortController?.signal.aborted ||
29993
+ stateRef.current.conversationId !== streamConversationId ||
29994
+ currentRequestIdRef.current !== streamRequestId) {
29995
+ console.log('[Widget] Stream aborted, conversation changed, or superseded by new request');
28925
29996
  break;
28926
29997
  }
28927
29998
  if (event.type === "action_request") {
28928
- // Check again before expensive operation
28929
- if (currentAbortController?.signal.aborted || stateRef.current.conversationId !== streamConversationId) {
29999
+ if (currentAbortController?.signal.aborted ||
30000
+ stateRef.current.conversationId !== streamConversationId ||
30001
+ currentRequestIdRef.current !== streamRequestId) {
28930
30002
  break;
28931
30003
  }
28932
30004
  await handleActionLoop(apiClient.current, event, streamState, (message) => {
@@ -28938,30 +30010,26 @@ function useChat(options) {
28938
30010
  lastStreamedMessage = message;
28939
30011
  }, setState);
28940
30012
  }
28941
- // Only finalize if this stream wasn't aborted
28942
- if (currentAbortController?.signal.aborted || stateRef.current.conversationId !== streamConversationId) {
28943
- console.log('[Widget] Stream was aborted, skipping finalization');
30013
+ if (currentAbortController?.signal.aborted ||
30014
+ stateRef.current.conversationId !== streamConversationId ||
30015
+ currentRequestIdRef.current !== streamRequestId) {
30016
+ console.log('[Widget] Stream was aborted or superseded, skipping finalization');
28944
30017
  return;
28945
30018
  }
28946
- // Stream completed - finalize state
28947
30019
  setState(prev => ({
28948
30020
  ...prev,
28949
30021
  isLoading: false,
28950
30022
  isTyping: false,
28951
30023
  }));
28952
- // Notify about final message
28953
30024
  if (lastStreamedMessage) {
28954
30025
  onMessage?.(lastStreamedMessage);
28955
30026
  }
28956
- // Generate follow-up suggestions asynchronously
28957
30027
  const enableFollowUps = state.config?.settings.enableFollowUpSuggestions !== false;
28958
30028
  const actionIds = state.config?.actions || [];
28959
30029
  if (enableFollowUps) {
28960
- // Don't await - let it run in background
28961
30030
  apiClient.current.generateFollowUps(stateRef.current.messages, actionIds)
28962
30031
  .then(suggestions => {
28963
30032
  if (suggestions.length > 0) {
28964
- // Attach suggestions to the last assistant message
28965
30033
  setState(prev => {
28966
30034
  const messages = [...prev.messages];
28967
30035
  for (let i = messages.length - 1; i >= 0; i--) {
@@ -28990,7 +30058,7 @@ function useChat(options) {
28990
30058
  },
28991
30059
  timestamp: new Date().toISOString(),
28992
30060
  sources: [],
28993
- isError: !fallbackMessage, // Only mark as error if using default message
30061
+ isError: !fallbackMessage,
28994
30062
  };
28995
30063
  setState(prev => ({
28996
30064
  ...prev,
@@ -29002,9 +30070,6 @@ function useChat(options) {
29002
30070
  onError?.(err);
29003
30071
  }
29004
30072
  }, [state.conversationId, state.config, state.messages, onMessage, onError]);
29005
- /**
29006
- * Clear all messages
29007
- */
29008
30073
  const clearMessages = React.useCallback(() => {
29009
30074
  setState(prev => ({
29010
30075
  ...prev,
@@ -29017,9 +30082,6 @@ function useChat(options) {
29017
30082
  clearConversation(widgetId);
29018
30083
  }
29019
30084
  }, [widgetId, state.config?.settings.persistConversation]);
29020
- /**
29021
- * Submit feedback for a message
29022
- */
29023
30085
  const submitFeedback = React.useCallback(async (messageId, feedback) => {
29024
30086
  try {
29025
30087
  const message = state.messages.find(msg => msg.id === messageId);
@@ -29029,7 +30091,6 @@ function useChat(options) {
29029
30091
  : undefined;
29030
30092
  console.log('Submitting feedback:', { conversationId: state.conversationId, messageId, feedback });
29031
30093
  await apiClient.current.submitFeedback(state.conversationId, messageId, feedback, meta);
29032
- // Update message with feedback
29033
30094
  setState(prev => ({
29034
30095
  ...prev,
29035
30096
  messages: prev.messages.map(msg => msg.id === messageId
@@ -29044,9 +30105,51 @@ function useChat(options) {
29044
30105
  onError?.(err);
29045
30106
  }
29046
30107
  }, [state.conversationId, onError]);
29047
- /**
29048
- * Load conversation history list from localStorage
29049
- */
30108
+ const dismissAction = React.useCallback(async (toolCallId) => {
30109
+ if (!toolCallId)
30110
+ return;
30111
+ const dismissedAt = new Date().toISOString();
30112
+ setState(prev => ({
30113
+ ...prev,
30114
+ messages: prev.messages.map((message) => {
30115
+ if (message.action?.toolCallId !== toolCallId) {
30116
+ return message;
30117
+ }
30118
+ if (!message.action) {
30119
+ return message;
30120
+ }
30121
+ return {
30122
+ ...message,
30123
+ action: {
30124
+ ...message.action,
30125
+ hidden: true,
30126
+ dismissedAt,
30127
+ dismissedBy: "user",
30128
+ done: true,
30129
+ },
30130
+ };
30131
+ }),
30132
+ isTyping: true,
30133
+ isLoading: false,
30134
+ }));
30135
+ unregisterActionResumeCallback(toolCallId);
30136
+ const conversationId = stateRef.current.conversationId;
30137
+ if (!conversationId) {
30138
+ setState(prev => ({ ...prev, isTyping: false }));
30139
+ return;
30140
+ }
30141
+ try {
30142
+ const streamState = createStreamState();
30143
+ for await (const event of apiClient.current.dismissAgentMessageStream(conversationId, toolCallId)) {
30144
+ handleStreamEvent(event, streamState, onMessage ?? (() => { }), setState);
30145
+ }
30146
+ setState(prev => ({ ...prev, isTyping: false, isLoading: false }));
30147
+ }
30148
+ catch (error) {
30149
+ console.error("[Widget] dismissAction error:", error);
30150
+ setState(prev => ({ ...prev, isTyping: false, isLoading: false }));
30151
+ }
30152
+ }, [onMessage]);
29050
30153
  const loadConversations = React.useCallback(() => {
29051
30154
  const persistConversation = state.config?.settings.persistConversation ?? true;
29052
30155
  if (!persistConversation || !isStorageAvailable()) {
@@ -29063,13 +30166,11 @@ function useChat(options) {
29063
30166
  })));
29064
30167
  }, [widgetId, state.config?.settings.persistConversation]);
29065
30168
  const switchConversation = React.useCallback(async (conversationId) => {
29066
- // Cancel any active stream before switching conversations
29067
30169
  if (abortControllerRef.current) {
29068
30170
  abortControllerRef.current.abort();
29069
30171
  abortControllerRef.current = null;
29070
30172
  }
29071
30173
  const persistConversation = state.config?.settings.persistConversation ?? true;
29072
- // First try to load from localStorage
29073
30174
  if (persistConversation && isStorageAvailable()) {
29074
30175
  const stored = loadConversationById(widgetId, conversationId);
29075
30176
  if (stored) {
@@ -29088,7 +30189,6 @@ function useChat(options) {
29088
30189
  try {
29089
30190
  const conversation = await apiClient.current.getOrCreateConversation(conversationId);
29090
30191
  const hydratedMessages = hydrateMessages(conversation.messages);
29091
- // Clear old resume callbacks
29092
30192
  state.messages.forEach(message => {
29093
30193
  if (message.action?.toolCallId) {
29094
30194
  unregisterActionResumeCallback(message.action.toolCallId);
@@ -29100,9 +30200,7 @@ function useChat(options) {
29100
30200
  messages: hydratedMessages,
29101
30201
  isLoading: false,
29102
30202
  }));
29103
- // Setup new resume callbacks
29104
- setupActionResumeCallbacks(hydratedMessages, apiClient.current, conversation.id, setState, onMessage ?? (() => { }));
29105
- // Save to local storage
30203
+ setupActionResumeCallbacks(hydratedMessages, apiClient.current, conversation.id, setState, onMessage ?? (() => { }), createStreamState, registerActionResumeCallback);
29106
30204
  if (persistConversation && isStorageAvailable()) {
29107
30205
  saveConversation(widgetId, conversation.id, hydratedMessages);
29108
30206
  }
@@ -29113,19 +30211,16 @@ function useChat(options) {
29113
30211
  }
29114
30212
  }, [widgetId, state.config?.settings.persistConversation]);
29115
30213
  const startNewConversation = React.useCallback(() => {
29116
- // Rate limiting - prevent spamming new chats
29117
30214
  const now = Date.now();
29118
30215
  if (now - lastNewChatTimeRef.current < NEW_CHAT_COOLDOWN_MS) {
29119
30216
  console.warn('[Widget] New chat rate limited - please wait');
29120
30217
  return;
29121
30218
  }
29122
30219
  lastNewChatTimeRef.current = now;
29123
- // Cancel any active stream before starting new conversation
29124
30220
  if (abortControllerRef.current) {
29125
30221
  abortControllerRef.current.abort();
29126
30222
  abortControllerRef.current = null;
29127
30223
  }
29128
- // Reset typing state if stream was active
29129
30224
  setState(prev => ({
29130
30225
  ...prev,
29131
30226
  messages: [],
@@ -29144,11 +30239,8 @@ function useChat(options) {
29144
30239
  if (!persistConversation || !isStorageAvailable()) {
29145
30240
  return;
29146
30241
  }
29147
- // Delete from storage
29148
30242
  deleteConversation(widgetId, conversationId);
29149
- // Update local state
29150
30243
  setConversations(prev => prev.filter(c => c.id !== conversationId));
29151
- // If we deleted the current conversation, clear it
29152
30244
  if (state.conversationId === conversationId) {
29153
30245
  setState(prev => ({
29154
30246
  ...prev,
@@ -29158,6 +30250,43 @@ function useChat(options) {
29158
30250
  }));
29159
30251
  }
29160
30252
  }, [widgetId, state.config?.settings.persistConversation, state.conversationId]);
30253
+ const createDemoConversation = React.useCallback(async (userMessage, assistantMessage) => {
30254
+ try {
30255
+ const result = await apiClient.current.createDemoConversation(userMessage, assistantMessage);
30256
+ if (result.success && result.id) {
30257
+ // Update state with the new conversation ID
30258
+ setState(prev => ({
30259
+ ...prev,
30260
+ conversationId: result.id,
30261
+ }));
30262
+ // Save to local storage if persistence is enabled
30263
+ const persistConversation = state.config?.settings.persistConversation ?? true;
30264
+ if (persistConversation && isStorageAvailable()) {
30265
+ const demoMessages = [
30266
+ {
30267
+ id: generateMessageId(),
30268
+ message: { role: 'user', content: userMessage },
30269
+ timestamp: new Date().toISOString(),
30270
+ sources: [],
30271
+ },
30272
+ {
30273
+ id: generateMessageId(),
30274
+ message: { role: 'assistant', content: assistantMessage },
30275
+ timestamp: new Date(Date.now() + 1000).toISOString(),
30276
+ sources: [],
30277
+ },
30278
+ ];
30279
+ saveConversation(widgetId, result.id, demoMessages);
30280
+ }
30281
+ return result.id;
30282
+ }
30283
+ return null;
30284
+ }
30285
+ catch (error) {
30286
+ console.error('[useChat] Failed to create demo conversation:', error);
30287
+ return null;
30288
+ }
30289
+ }, [widgetId, state.config?.settings.persistConversation]);
29161
30290
  return {
29162
30291
  messages: state.messages,
29163
30292
  isLoading: state.isLoading,
@@ -29168,20 +30297,29 @@ function useChat(options) {
29168
30297
  sendMessage,
29169
30298
  clearMessages,
29170
30299
  submitFeedback,
29171
- // Chat history features
30300
+ dismissAction,
29172
30301
  conversations,
29173
30302
  loadConversations,
29174
30303
  switchConversation,
29175
30304
  startNewConversation,
29176
30305
  deleteConversation: deleteConversation$1,
30306
+ createDemoConversation,
29177
30307
  };
29178
30308
  }
29179
30309
 
30310
+ const DataPolicyView = ({ config, widgetName, }) => {
30311
+ const headerTitle = widgetName || config?.appearance?.headerTitle || 'AI Assistant';
30312
+ const hasFileUpload = config?.settings?.enableFileUpload ?? false;
30313
+ const persistsConversation = config?.settings?.persistConversation ?? true;
30314
+ return (jsxRuntime.jsx("div", { className: "ai-chat-data-policy-view", children: jsxRuntime.jsxs("div", { className: "ai-chat-data-policy-content", children: [jsxRuntime.jsx("div", { className: "ai-chat-data-policy-intro", children: jsxRuntime.jsxs("p", { children: ["This privacy notice informs you pursuant to Art. 13 GDPR about how ", jsxRuntime.jsx("strong", { children: headerTitle }), " processes data when you use this chat. Please note that the specific scope of processing depends on the operator of this website/application (the controller) and on the respective activated functions."] }) }), jsxRuntime.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntime.jsx("h3", { children: "Controller / Contact" }), jsxRuntime.jsx("p", { children: "The controller within the meaning of Art. 4 No. 7 GDPR is the operator of this website/application. The contact details (and, if applicable, the contact details of a data protection officer) can be found in the privacy policy or in the legal notice of the website into which this chat widget is embedded." })] }), jsxRuntime.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntime.jsx("h3", { children: "Processed Data" }), jsxRuntime.jsxs("p", { children: ["The chat processes the following categories of data. ", jsxRuntime.jsx("strong", { children: "Chat Content" }), " comprises messages (text) and, if applicable, context information that you provide in the chat. This content is processed to generate responses and provide the conversation."] }), hasFileUpload && (jsxRuntime.jsxs("p", { children: [jsxRuntime.jsx("strong", { children: "Uploaded Files" }), " that you transmit to the chat are processed to handle your request. Processing may include extracting text or information."] })), jsxRuntime.jsxs("p", { children: [jsxRuntime.jsx("strong", { children: "Technical Usage Data" }), " includes timestamps, session or request information, as well as technical metadata required for operation, security (abuse prevention), and error analysis."] }), jsxRuntime.jsx("p", { children: "Please do not enter special categories of personal data (e.g., health data), passwords, credit card or bank data, or confidential business secrets in the chat. AI-generated responses may be inaccurate and should be checked independently before use." })] }), jsxRuntime.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntime.jsx("h3", { children: "Purposes and Legal Bases" }), jsxRuntime.jsxs("p", { children: [jsxRuntime.jsx("strong", { children: "Provision of the chat and answering of inquiries" }), " is based on Art. 6 Para. 1 lit. b GDPR, insofar as contractual or pre-contractual measures apply; otherwise on Art. 6 Para. 1 lit. f GDPR (legitimate interest in efficient communication and support)."] }), jsxRuntime.jsxs("p", { children: [jsxRuntime.jsx("strong", { children: "Quality assurance, operation and security" }), " are based on Art. 6 Para. 1 lit. f GDPR, for example for stability, abuse detection, and troubleshooting."] }), jsxRuntime.jsxs("p", { children: [jsxRuntime.jsx("strong", { children: "Consent-based processing" }), " may occur if the operator provides for this (Art. 6 Para. 1 lit. a GDPR)."] })] }), jsxRuntime.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntime.jsx("h3", { children: "Recipients and Processors" }), jsxRuntime.jsxs("p", { children: [jsxRuntime.jsx("strong", { children: "Hosting/IT Service Providers" }), " may be used by the operator for hosting, logging, monitoring, and infrastructure."] }), jsxRuntime.jsxs("p", { children: [jsxRuntime.jsx("strong", { children: "AI Service Providers" }), " may receive chat content to generate responses. Where required, this is done on the basis of a data processing agreement (Art. 28 GDPR)."] }), jsxRuntime.jsxs("p", { children: [jsxRuntime.jsx("strong", { children: "Third-Country Transfer" }), " may occur if recipients are located outside the EU/EEA. In this case, appropriate safeguards (e.g., EU Standard Contractual Clauses) are used where required."] })] }), jsxRuntime.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntime.jsx("h3", { children: "Retention Period" }), persistsConversation ? (jsxRuntime.jsxs("p", { children: [jsxRuntime.jsx("strong", { children: "Chat History" }), " may be stored to continue the conversation across multiple sessions."] })) : (jsxRuntime.jsxs("p", { children: [jsxRuntime.jsx("strong", { children: "Chat History" }), " is not permanently stored and ends when the chat is closed."] })), hasFileUpload && (jsxRuntime.jsxs("p", { children: [jsxRuntime.jsx("strong", { children: "Files" }), " are processed only as long as necessary to handle the request and are then deleted, unless longer retention is legally required."] })), jsxRuntime.jsxs("p", { children: [jsxRuntime.jsx("strong", { children: "Technical Logs" }), " may be stored for a limited period to ensure secure operation."] })] }), jsxRuntime.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntime.jsx("h3", { children: "Your Rights (Data Subject Rights)" }), jsxRuntime.jsx("p", { children: "You have the following rights under the GDPR: Right to Information (Art. 15), Right to Rectification (Art. 16), Right to Erasure (Art. 17) and Restriction of Processing (Art. 18), Right to Data Portability (Art. 20), Right to Objection to processing based on legitimate interests (Art. 21), and Right to Complain to a supervisory authority (Art. 77)." }), jsxRuntime.jsx("p", { children: "Note: Without clear identification features, the operator may not be able to assign individual chat histories to a person. For inquiries, please contact the operator of this website/application." })] })] }) }));
30315
+ };
30316
+
29180
30317
  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" })] }));
29181
30318
  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" })] }));
29182
30319
  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" })] }));
29183
30320
  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" })] }));
29184
- const ChatWindow = ({ messages, isLoading, isTyping, error, config, onSendMessage, onClose: _onClose, onFeedback, onActionClick,
30321
+ 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" })] }));
30322
+ const ChatWindow = ({ messages, isLoading, isTyping, config, onSendMessage, onClose: _onClose, onFeedback, onActionClick, onActionDismiss,
29185
30323
  // Chat history props (only active when persistConversation is true)
29186
30324
  conversations = [], onLoadConversations, onSwitchConversation, onStartNewConversation, onDeleteConversation, currentConversationId,
29187
30325
  // Override props for live preview
@@ -29198,6 +30336,8 @@ headerTitleOverride, welcomeTitleOverride, welcomeMessageOverride, placeholderOv
29198
30336
  const inputPlaceholder = placeholderOverride ?? appearance?.placeholder ?? 'Ask me anything...';
29199
30337
  // Track if history panel is open
29200
30338
  const [showHistory, setShowHistory] = React.useState(false);
30339
+ // Track if data policy view is open
30340
+ const [showDataPolicy, setShowDataPolicy] = React.useState(false);
29201
30341
  // Scroll button state (managed by MessageList)
29202
30342
  const [showScrollButton, setShowScrollButton] = React.useState(false);
29203
30343
  const [scrollToBottom, setScrollToBottom] = React.useState(null);
@@ -29207,6 +30347,13 @@ headerTitleOverride, welcomeTitleOverride, welcomeMessageOverride, placeholderOv
29207
30347
  }, []);
29208
30348
  // History exit animation when starting a new chat from overview
29209
30349
  const [isHistoryExiting, setIsHistoryExiting] = React.useState(false);
30350
+ // Handle data policy click
30351
+ const handleDataPolicyClick = React.useCallback(() => {
30352
+ setShowDataPolicy(true);
30353
+ }, []);
30354
+ const handleDataPolicyBack = React.useCallback(() => {
30355
+ setShowDataPolicy(false);
30356
+ }, []);
29210
30357
  // Load conversations when history panel opens
29211
30358
  const handleOpenHistory = () => {
29212
30359
  setShowHistory(true);
@@ -29254,10 +30401,22 @@ headerTitleOverride, welcomeTitleOverride, welcomeMessageOverride, placeholderOv
29254
30401
  // The backend will detect and trigger the action based on the message
29255
30402
  onSendMessage(question);
29256
30403
  };
29257
- 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) => {
30404
+ 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: "Privacy Notice" })] })) : 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 ? (
30405
+ /* History Panel */
30406
+ 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) => {
29258
30407
  e.stopPropagation();
29259
30408
  onDeleteConversation(conv.id);
29260
- }, "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, 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 })] }))] }));
30409
+ }, "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." })), (() => {
30410
+ console.log('[DEBUG ChatWindow] Rendering MessageList with', messages.length, 'messages');
30411
+ messages.forEach((m, i) => {
30412
+ console.log(`[DEBUG ChatWindow] msg ${i}:`, { role: m.message.role, hasAction: !!m.action, impl: m.action?.implementation });
30413
+ });
30414
+ console.log('[DEBUG ChatWindow] getActionRenderer available:', !!getActionRenderer);
30415
+ if (getActionRenderer) {
30416
+ console.log('[DEBUG ChatWindow] Testing renderer for query-contact-directory:', !!getActionRenderer('query-contact-directory'));
30417
+ }
30418
+ return null;
30419
+ })(), 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, onActionDismiss: onActionDismiss, onFeedback: onFeedback, onScrollStateChange: handleScrollStateChange, getActionRenderer: getActionRenderer }), settings?.showDataPolicy && (jsxRuntime.jsxs("div", { className: "ai-chat-page-disclaimer", children: [jsxRuntime.jsx("span", { children: "AI-generated responses may be inaccurate." }), jsxRuntime.jsx("button", { type: "button", className: "ai-chat-page-disclaimer-link", onClick: handleDataPolicyClick, children: "Privacy Notice" })] })), 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 })] }))] }));
29261
30420
  };
29262
30421
 
29263
30422
  /**
@@ -29663,7 +30822,7 @@ function styleInject(css, ref) {
29663
30822
  if ( ref === void 0 ) ref = {};
29664
30823
  var insertAt = ref.insertAt;
29665
30824
 
29666
- if (typeof document === 'undefined') { return; }
30825
+ if (!css || typeof document === 'undefined') { return; }
29667
30826
 
29668
30827
  var head = document.head || document.getElementsByTagName('head')[0];
29669
30828
  var style = document.createElement('style');
@@ -29686,7 +30845,10 @@ function styleInject(css, ref) {
29686
30845
  }
29687
30846
  }
29688
30847
 
29689
- 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-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:var(--space-sm,8px);overflow:hidden;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:12px}.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;margin-top:var(--space-sm,8px);overflow:hidden}.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;padding:12px 12px 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;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;padding:10px 12px}.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}.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:14px}.ai-chat-location-card--compact .ai-chat-location-card__content{padding:12px}.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:repeat(3,minmax(0,1fr))}@media (max-width:1200px){.ai-chat-location-card-list__stack{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (max-width:768px){.ai-chat-location-card-list__stack{grid-template-columns:1fr}}@media (max-width:520px){.ai-chat-location-card-list__stack{grid-template-columns:1fr!important}}@media (min-width:521px) and (max-width:900px){.ai-chat-location-card-list__stack{grid-template-columns:repeat(2,minmax(0,1fr))!important}}.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-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,.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-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 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:#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 16px;width:100%}";
30848
+ 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:transform var(--duration-fast) ease;width:var(--button-size,56px);z-index:1}.ai-chat-button:hover{transform:scale(1.05)}.ai-chat-button:active{transform:scale(.98)}.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:16px;box-shadow:none;box-sizing:border-box;color:var(--button-icon-color,var(--btn-primary-text,#fff));cursor:pointer;font-size:13px;font-weight:500;line-height:1.5;max-width:min(420px,90vw);padding:12px 32px 12px 16px;position:absolute;text-align:left;white-space:normal;width:auto;z-index:0}.ai-chat-welcome-bubble-close{align-items:center;background:transparent;border:none;border-radius:50%;color:inherit;cursor:pointer;display:flex;height:20px;justify-content:center;opacity:.8;padding:0;position:absolute;right:8px;top:8px;transition:opacity .15s ease,background .15s ease;width:20px}.ai-chat-welcome-bubble-close:hover{background:hsla(0,0%,100%,.2);opacity:1}.ai-chat-welcome-bubble-close svg{height:12px;width:12px}.ai-chat-welcome-bubble-arrow{border-bottom:8px solid transparent;border-top:8px solid transparent;height:0;position:absolute;width:0}.ai-chat-widget-container.bottom-right .ai-chat-welcome-bubble{bottom:50%;right:calc(100% + 12px);text-align:left;transform:translateY(50%)}.ai-chat-widget-container.bottom-left .ai-chat-welcome-bubble{bottom:50%;left:calc(100% + 12px);text-align:left;transform:translateY(50%)}.ai-chat-widget-container.top-right .ai-chat-welcome-bubble{right:calc(100% + 12px);text-align:left;top:50%;transform:translateY(-50%)}.ai-chat-widget-container.top-left .ai-chat-welcome-bubble{left:calc(100% + 12px);text-align:left;top:50%;transform:translateY(-50%)}.ai-chat-widget-container.bottom-right .ai-chat-welcome-bubble-arrow{border-left:8px solid var(--button-color,var(--btn-primary-bg,#07f));right:-8px;top:50%;transform:translateY(-50%)}.ai-chat-widget-container.bottom-left .ai-chat-welcome-bubble-arrow{border-right:8px solid var(--button-color,var(--btn-primary-bg,#07f));left:-8px;top:50%;transform:translateY(-50%)}.ai-chat-widget-container.top-right .ai-chat-welcome-bubble-arrow{border-left:8px solid var(--button-color,var(--btn-primary-bg,#07f));right:-8px;top:50%;transform:translateY(-50%)}.ai-chat-widget-container.top-left .ai-chat-welcome-bubble-arrow{border-right:8px solid var(--button-color,var(--btn-primary-bg,#07f));left:-8px;top:50%;transform:translateY(-50%)}.ai-chat-welcome-bubble:hover{filter:brightness(1.1)}.ai-chat-widget-container.bottom-right .ai-chat-welcome-bubble{animation-name:ai-chat-bubble-fade-in-bottom-right}@keyframes ai-chat-bubble-fade-in-bottom-right{0%{opacity:0;transform:translateY(50%) translateX(8px)}to{opacity:1;transform:translateY(50%) translateX(0)}}.ai-chat-widget-container.bottom-left .ai-chat-welcome-bubble{animation-name:ai-chat-bubble-fade-in-bottom-left}@keyframes ai-chat-bubble-fade-in-bottom-left{0%{opacity:0;transform:translateY(50%) translateX(-8px)}to{opacity:1;transform:translateY(50%) translateX(0)}}.ai-chat-widget-container.top-right .ai-chat-welcome-bubble{animation-name:ai-chat-bubble-fade-in-top-right}@keyframes ai-chat-bubble-fade-in-top-right{0%{opacity:0;transform:translateY(-50%) translateX(8px)}to{opacity:1;transform:translateY(-50%) translateX(0)}}.ai-chat-widget-container.top-left .ai-chat-welcome-bubble{animation-name:ai-chat-bubble-fade-in-top-left}@keyframes ai-chat-bubble-fade-in-top-left{0%{opacity:0;transform:translateY(-50%) translateX(-8px)}to{opacity:1;transform:translateY(-50%) translateX(0)}}.ai-chat-trigger-pill{align-items:center;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);background:hsla(0,0%,100%,.08);border:1px solid hsla(0,0%,100%,.15);border-radius:9999px;color:var(--text-primary,#fff);cursor:pointer;display:flex;font-size:13px;font-weight:500;gap:8px;height:40px;justify-content:center;padding:0 20px;position:relative;transition:all .3s ease;white-space:nowrap;z-index:1}.ai-chat-trigger-pill.is-open{background:var(--button-color,var(--btn-primary-bg));border-color:var(--border-default,#d3d3d3);box-shadow:var(--shadow-button,0 0 15px 9px rgba(0,0,0,.03));height:56px;padding:0;width:56px}.ai-chat-trigger-pill.is-open .ai-chat-trigger-pill-icon{height:24px;width:24px}.ai-chat-trigger-pill:hover:not(.is-open){background:hsla(0,0%,100%,.12);border-color:hsla(0,0%,100%,.25)}.ai-chat-trigger-pill.is-open:hover{transform:scale(1.05)}.ai-chat-trigger-pill:active{transform:scale(.98)}.ai-chat-trigger-pill-icon{flex-shrink:0;height:16px;transition:all .3s ease;width:16px}.ai-chat-widget.light .ai-chat-trigger-pill{background:rgba(0,0,0,.04);border-color:rgba(0,0,0,.12);color:var(--text-primary,#1a1a1a)}.ai-chat-widget.light .ai-chat-trigger-pill:hover:not(.is-open){background:rgba(0,0,0,.08);border-color:rgba(0,0,0,.2)}.ai-chat-trigger-input-container{align-items:flex-end;display:flex;flex-direction:column;gap:8px}.ai-chat-widget-container.bottom-left .ai-chat-trigger-input-container,.ai-chat-widget-container.top-left .ai-chat-trigger-input-container{align-items:flex-start}.ai-chat-trigger-input-expand{align-items:center;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);background:hsla(0,0%,100%,.1);border:1px solid hsla(0,0%,100%,.15);border-radius:50%;color:hsla(0,0%,100%,.7);cursor:pointer;display:flex;height:32px;justify-content:center;padding:0;transition:all .2s ease;width:32px}.ai-chat-trigger-input-expand:hover{background:hsla(0,0%,100%,.15);color:hsla(0,0%,100%,.9);transform:translateY(-2px)}.ai-chat-trigger-input-expand:active{transform:translateY(0)}.ai-chat-trigger-input-expand svg{height:16px;width:16px}.ai-chat-widget.light .ai-chat-trigger-input-expand{background:rgba(0,0,0,.05);border:1px solid rgba(0,0,0,.1);color:rgba(0,0,0,.5)}.ai-chat-widget.light .ai-chat-trigger-input-expand:hover{background:rgba(0,0,0,.1);color:rgba(0,0,0,.7)}.ai-chat-trigger-input-wrapper{max-width:calc(100vw - 40px);position:relative;z-index:1}.ai-chat-widget-container.trigger-input-bar .ai-chat-trigger-input-wrapper{width:348px}.ai-chat-widget-container.trigger-input-bar.size-medium .ai-chat-trigger-input-wrapper{width:388px}.ai-chat-widget-container.trigger-input-bar.size-large .ai-chat-trigger-input-wrapper{width:448px}.ai-chat-trigger-input{backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);background:hsla(0,0%,100%,.08);border:1px solid hsla(0,0%,100%,.12);border-radius:var(--radius-input,62px);box-shadow:0 4px 24px rgba(0,0,0,.15);box-sizing:border-box;color:var(--input-text,#fff);font-size:var(--text-md,15px);height:52px;outline:none;padding:6px 52px 6px 16px;transition:all .2s ease;width:100%}.ai-chat-trigger-input::placeholder{color:var(--text-placeholder,hsla(0,0%,100%,.5))}.ai-chat-trigger-input:focus{background:hsla(0,0%,100%,.12);border-color:hsla(0,0%,100%,.25)}.ai-chat-trigger-input-btn{align-items:center;background:var(--primary-color,var(--button-color,#07f));border:none;border-radius:50%;box-shadow:0 2px 8px rgba(0,119,255,.3);color:#fff;cursor:pointer;display:flex;height:40px;justify-content:center;position:absolute;right:6px;top:50%;transform:translateY(-50%);transition:all .2s ease;width:40px}.ai-chat-trigger-input-btn:hover:not(:disabled){box-shadow:0 4px 12px rgba(0,119,255,.4);transform:translateY(-50%) scale(1.05)}.ai-chat-trigger-input-btn:active:not(:disabled){transform:translateY(-50%) scale(.95)}.ai-chat-trigger-input-btn:disabled{box-shadow:none;cursor:not-allowed;opacity:.4}.ai-chat-trigger-input-btn svg{height:18px;width:18px}.ai-chat-widget.light .ai-chat-trigger-input{backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);background:hsla(0,0%,100%,.7);border:1px solid rgba(0,0,0,.1);box-shadow:0 4px 24px rgba(0,0,0,.08);color:var(--input-text,#1a1a1a)}.ai-chat-widget.light .ai-chat-trigger-input::placeholder{color:var(--text-placeholder,rgba(0,0,0,.4))}.ai-chat-widget.light .ai-chat-trigger-input:focus{background:hsla(0,0%,100%,.85);border-color:rgba(0,0,0,.2)}.ai-chat-widget.light .ai-chat-trigger-input-btn{background:var(--primary-color,var(--button-color,#07f));box-shadow:0 2px 8px rgba(0,119,255,.25);color:#fff}.ai-chat-widget.light .ai-chat-trigger-input-btn:hover:not(:disabled){box-shadow:0 4px 12px rgba(0,119,255,.35)}.ai-chat-widget-container.trigger-input-bar{align-items:flex-end;display:flex;flex-direction:column;gap:12px}.ai-chat-widget-container.trigger-input-bar.bottom-left,.ai-chat-widget-container.trigger-input-bar.top-left{align-items:flex-start}.ai-chat-widget-container.trigger-input-bar .ai-chat-window{bottom:auto;left:auto;order:-1;position:relative;right:auto;top:auto;width:100%}.ai-chat-widget-container.trigger-input-bar .ai-chat-window.size-small{max-width:calc(100vw - 40px);width:380px}.ai-chat-widget-container.trigger-input-bar .ai-chat-window.size-medium{max-width:calc(100vw - 40px);width:420px}.ai-chat-widget-container.trigger-input-bar .ai-chat-window.size-large{max-width:calc(100vw - 40px);width:480px}.ai-chat-widget-container.trigger-input-bar .ai-chat-button,.ai-chat-widget-container.trigger-pill-text .ai-chat-button{display:none}.ai-chat-widget-container.trigger-pill-text.is-open{gap:8px}.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-page-disclaimer{align-items:center;color:var(--text-muted,#71717a);display:flex;font-size:10px;gap:4px;justify-content:center;line-height:1.4;opacity:.7;padding:8px 16px;text-align:center}.ai-chat-widget.dark .ai-chat-page-disclaimer{color:var(--text-muted,#a1a1aa)}.ai-chat-page-disclaimer-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-page-disclaimer-link:hover{color:var(--text-secondary,#52525b)}.ai-chat-widget.dark .ai-chat-page-disclaimer-link{color:var(--text-muted,#a1a1aa)}.ai-chat-widget.dark .ai-chat-page-disclaimer-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 h1{font-size:1.5em}.ai-chat-message.assistant .ai-chat-message-content h1,.ai-chat-message.assistant .ai-chat-message-content h2{color:var(--text-primary,#3e3e3e);font-weight:var(--font-weight-bold,700);line-height:var(--line-height-tight,1.3);margin:var(--space-md,16px) 0 var(--space-sm,8px) 0}.ai-chat-message.assistant .ai-chat-message-content h2{font-size:1.3em}.ai-chat-message.assistant .ai-chat-message-content h3{color:var(--text-primary,#3e3e3e);font-size:1.15em;font-weight:var(--font-weight-semibold,600);line-height:var(--line-height-tight,1.3);margin:var(--space-sm,8px) 0 var(--space-xs,4px) 0}.ai-chat-message.assistant .ai-chat-message-content h4,.ai-chat-message.assistant .ai-chat-message-content h5,.ai-chat-message.assistant .ai-chat-message-content h6{color:var(--text-primary,#3e3e3e);font-size:1em;font-weight:var(--font-weight-semibold,600);line-height:var(--line-height-tight,1.3);margin:var(--space-sm,8px) 0 var(--space-xs,4px) 0}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content h1,.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content h2,.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content h3,.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content h4,.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content h5,.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content h6{color:var(--text-primary,#fff)}.ai-chat-message.assistant .ai-chat-message-content>h1:first-child,.ai-chat-message.assistant .ai-chat-message-content>h2:first-child,.ai-chat-message.assistant .ai-chat-message-content>h3:first-child,.ai-chat-message.assistant .ai-chat-message-content>h4:first-child,.ai-chat-message.assistant .ai-chat-message-content>h5:first-child,.ai-chat-message.assistant .ai-chat-message-content>h6:first-child{margin-top:0}.ai-chat-message.assistant .ai-chat-message-content ul{list-style-type:disc;margin:var(--space-sm,8px) 0;padding-left:var(--space-lg,24px)}.ai-chat-message.assistant .ai-chat-message-content ul ul{list-style-type:circle;margin:var(--space-xs,4px) 0}.ai-chat-message.assistant .ai-chat-message-content ul ul ul{list-style-type:square}.ai-chat-message.assistant .ai-chat-message-content ol{list-style-type:decimal;margin:var(--space-sm,8px) 0;padding-left:var(--space-lg,24px)}.ai-chat-message.assistant .ai-chat-message-content ol ol{list-style-type:lower-alpha;margin:var(--space-xs,4px) 0}.ai-chat-message.assistant .ai-chat-message-content ol ol ol{list-style-type:lower-roman}.ai-chat-message.assistant .ai-chat-message-content li{margin-bottom:var(--space-xs,4px);padding-left:var(--space-xs,4px)}.ai-chat-message.assistant .ai-chat-message-content li:last-child{margin-bottom:0}.ai-chat-message.assistant .ai-chat-message-content li>ol,.ai-chat-message.assistant .ai-chat-message-content li>ul{margin-top:var(--space-xs,4px)}.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-close-btn{align-items:center;background:transparent;border:none;border-radius:6px;color:var(--ai-chat-fg-muted,#6b7280);cursor:pointer;display:flex;height:28px;justify-content:center;padding:0;position:absolute;right:12px;top:12px;transition:all .15s ease;width:28px;z-index:10}.ai-chat-action-close-btn:hover{background:var(--ai-chat-bg-muted,#f3f4f6);color:var(--ai-chat-fg,#1f2937)}.ai-chat-action-close-btn:active{transform:scale(.95)}.ai-chat-action-close-btn:focus-visible{outline:2px solid var(--ai-chat-accent,#2563eb);outline-offset:2px}.ai-chat-action-card--closable,.ai-chat-form-card--closable{position:relative}.ai-chat-action-card--closable .ai-chat-action-header,.ai-chat-form-card--closable .ai-chat-form-card__header{padding-right:40px}.ai-chat-widget.dark .ai-chat-action-close-btn:hover,.chakra-ui-dark .ai-chat-action-close-btn:hover,.dark .ai-chat-action-close-btn:hover,[data-theme=dark] .ai-chat-action-close-btn:hover{background:hsla(0,0%,100%,.1);color:var(--ai-chat-fg,#f3f4f6)}.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{color:var(--text-muted,#71717a);font-size:12px;font-style:italic;margin-top:4px;padding:8px 12px 12px}.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}.ai-chat-booking-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;padding:16px;width:100%}.ai-chat-widget.dark .ai-chat-booking-card,.chakra-ui-dark .ai-chat-booking-card,.dark .ai-chat-booking-card,[data-theme=dark] .ai-chat-booking-card{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1)}.ai-chat-booking-card__header{align-items:center;display:flex;gap:8px;margin-bottom:12px}.ai-chat-booking-card__icon{flex-shrink:0;font-size:18px}.ai-chat-booking-card__title{color:var(--text-primary,#3e3e3e);font-size:15px;font-weight:600}.ai-chat-widget.dark .ai-chat-booking-card__title,.chakra-ui-dark .ai-chat-booking-card__title,.dark .ai-chat-booking-card__title,[data-theme=dark] .ai-chat-booking-card__title{color:#fff}.ai-chat-booking-card__content{display:flex;flex-direction:column;gap:12px}.ai-chat-booking-card__description{color:var(--text-muted,#71717a);font-size:13px;line-height:1.4;margin:0}.ai-chat-booking-card__empty{color:var(--text-muted,#71717a);font-size:13px;padding:16px;text-align:center}.ai-chat-booking-card__input{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:8px;box-sizing:border-box;color:var(--text-primary,#3e3e3e);font-family:inherit;font-size:14px;outline:none;padding:10px 12px;transition:border-color .2s ease,box-shadow .2s ease;width:100%}.ai-chat-booking-card__input:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.1)}.ai-chat-booking-card__input::placeholder{color:var(--text-muted,#9ca3af)}.ai-chat-widget.dark .ai-chat-booking-card__input,.chakra-ui-dark .ai-chat-booking-card__input,.dark .ai-chat-booking-card__input,[data-theme=dark] .ai-chat-booking-card__input{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-booking-card__input:focus,.chakra-ui-dark .ai-chat-booking-card__input:focus,.dark .ai-chat-booking-card__input:focus,[data-theme=dark] .ai-chat-booking-card__input:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.2)}.ai-chat-booking-card__label{color:var(--text-secondary,#6b7280);display:block;font-size:13px;font-weight:500;margin-bottom:4px}.ai-chat-widget.dark .ai-chat-booking-card__label,.chakra-ui-dark .ai-chat-booking-card__label,.dark .ai-chat-booking-card__label,[data-theme=dark] .ai-chat-booking-card__label{color:var(--text-secondary,#a1a1aa)}.ai-chat-booking-card__btn{border:none;border-radius:9999px;box-sizing:border-box;cursor:pointer;font-family:inherit;font-size:13px;font-weight:500;padding:10px 16px;transition:all .2s ease;width:100%}.ai-chat-booking-card__btn:disabled{cursor:not-allowed;opacity:.5}.ai-chat-booking-card__btn--primary{background:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-booking-card__btn--primary:hover:not(:disabled){opacity:.9;transform:translateY(-1px)}.ai-chat-booking-card__btn--secondary{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);color:var(--text-primary,#3e3e3e)}.ai-chat-booking-card__btn--secondary:hover:not(:disabled){border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-booking-card__btn--secondary,.chakra-ui-dark .ai-chat-booking-card__btn--secondary,.dark .ai-chat-booking-card__btn--secondary,[data-theme=dark] .ai-chat-booking-card__btn--secondary{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-booking-card__btn--danger{background:rgba(220,38,38,.1);border:1px solid rgba(220,38,38,.2);color:#dc2626}.ai-chat-booking-card__btn--danger:hover:not(:disabled){background:rgba(220,38,38,.15)}.ai-chat-widget.dark .ai-chat-booking-card__btn--danger,.chakra-ui-dark .ai-chat-booking-card__btn--danger,.dark .ai-chat-booking-card__btn--danger,[data-theme=dark] .ai-chat-booking-card__btn--danger{background:rgba(239,68,68,.2);border-color:rgba(239,68,68,.3);color:#fca5a5}.ai-chat-booking-card__grid{display:grid;gap:10px;grid-template-columns:repeat(auto-fill,minmax(200px,1fr))}.ai-chat-booking-card__contact{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:8px;cursor:pointer;display:flex;flex-direction:column;font-family:inherit;padding:12px;text-align:left;transition:all .2s ease}.ai-chat-booking-card__contact:hover{background:rgba(59,130,246,.05);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-booking-card__contact--selected{border-width:2px}.ai-chat-widget.dark .ai-chat-booking-card__contact,.chakra-ui-dark .ai-chat-booking-card__contact,.dark .ai-chat-booking-card__contact,[data-theme=dark] .ai-chat-booking-card__contact{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1)}.ai-chat-widget.dark .ai-chat-booking-card__contact--selected,.chakra-ui-dark .ai-chat-booking-card__contact--selected,.dark .ai-chat-booking-card__contact--selected,[data-theme=dark] .ai-chat-booking-card__contact--selected{background:rgba(59,130,246,.15)}.ai-chat-booking-card__contact-name{color:var(--text-primary,#3e3e3e);font-size:14px;font-weight:500}.ai-chat-widget.dark .ai-chat-booking-card__contact-name,.chakra-ui-dark .ai-chat-booking-card__contact-name,.dark .ai-chat-booking-card__contact-name,[data-theme=dark] .ai-chat-booking-card__contact-name{color:#fff}.ai-chat-booking-card__contact-role{color:var(--text-muted,#71717a);font-size:12px;margin-top:2px}.ai-chat-booking-card__options{display:flex;flex-direction:column;gap:8px}.ai-chat-booking-card__option-btn{align-items:center;background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:8px;box-sizing:border-box;cursor:pointer;display:flex;font-family:inherit;gap:12px;padding:12px;text-align:left;transition:all .2s ease;width:100%}.ai-chat-booking-card__option-btn:hover{background:rgba(59,130,246,.05);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-booking-card__option-btn,.chakra-ui-dark .ai-chat-booking-card__option-btn,.dark .ai-chat-booking-card__option-btn,[data-theme=dark] .ai-chat-booking-card__option-btn{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1)}.ai-chat-booking-card__option-icon{flex-shrink:0;font-size:18px}.ai-chat-booking-card__option-text{color:var(--text-primary,#3e3e3e);font-size:14px;font-weight:500}.ai-chat-widget.dark .ai-chat-booking-card__option-text,.chakra-ui-dark .ai-chat-booking-card__option-text,.dark .ai-chat-booking-card__option-text,[data-theme=dark] .ai-chat-booking-card__option-text{color:#fff}.ai-chat-booking-card__date-group{margin-bottom:12px}.ai-chat-booking-card__date-header{color:var(--text-muted,#71717a);font-size:12px;font-weight:600;letter-spacing:.5px;margin-bottom:8px;text-transform:uppercase}.ai-chat-booking-card__slots{display:grid;gap:8px;grid-template-columns:repeat(auto-fill,minmax(120px,1fr))}.ai-chat-booking-card__slot{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:8px;color:var(--text-primary,#3e3e3e);cursor:pointer;font-family:inherit;font-size:13px;font-weight:500;padding:10px 12px;transition:all .2s ease}.ai-chat-booking-card__slot:hover{background:rgba(59,130,246,.05);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-booking-card__slot--selected{border-width:2px}.ai-chat-widget.dark .ai-chat-booking-card__slot,.chakra-ui-dark .ai-chat-booking-card__slot,.dark .ai-chat-booking-card__slot,[data-theme=dark] .ai-chat-booking-card__slot{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-booking-card__slot--selected,.chakra-ui-dark .ai-chat-booking-card__slot--selected,.dark .ai-chat-booking-card__slot--selected,[data-theme=dark] .ai-chat-booking-card__slot--selected{background:rgba(59,130,246,.15)}.ai-chat-booking-card__appointments{display:flex;flex-direction:column;gap:10px}.ai-chat-booking-card__appointment{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:8px;padding:12px}.ai-chat-widget.dark .ai-chat-booking-card__appointment,.chakra-ui-dark .ai-chat-booking-card__appointment,.dark .ai-chat-booking-card__appointment,[data-theme=dark] .ai-chat-booking-card__appointment{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1)}.ai-chat-booking-card__appointment-header{align-items:center;display:flex;gap:8px;justify-content:space-between;margin-bottom:6px}.ai-chat-booking-card__appointment-subject{color:var(--text-primary,#3e3e3e);font-size:14px;font-weight:500}.ai-chat-widget.dark .ai-chat-booking-card__appointment-subject,.chakra-ui-dark .ai-chat-booking-card__appointment-subject,.dark .ai-chat-booking-card__appointment-subject,[data-theme=dark] .ai-chat-booking-card__appointment-subject{color:#fff}.ai-chat-booking-card__appointment-status{border-radius:4px;font-size:11px;font-weight:600;padding:2px 6px;text-transform:uppercase}.ai-chat-booking-card__appointment-status--confirmed,.ai-chat-booking-card__appointment-status--pending{background:rgba(34,197,94,.1);color:#16a34a}.ai-chat-widget.dark .ai-chat-booking-card__appointment-status--confirmed,.ai-chat-widget.dark .ai-chat-booking-card__appointment-status--pending,.chakra-ui-dark .ai-chat-booking-card__appointment-status--confirmed,.chakra-ui-dark .ai-chat-booking-card__appointment-status--pending,.dark .ai-chat-booking-card__appointment-status--confirmed,.dark .ai-chat-booking-card__appointment-status--pending,[data-theme=dark] .ai-chat-booking-card__appointment-status--confirmed,[data-theme=dark] .ai-chat-booking-card__appointment-status--pending{background:rgba(34,197,94,.2);color:#4ade80}.ai-chat-booking-card__appointment-status--cancelled{background:hsla(220,9%,46%,.1);color:#6b7280}.ai-chat-booking-card__appointment-time{color:var(--text-secondary,#6b7280);font-size:13px;margin-bottom:4px}.ai-chat-widget.dark .ai-chat-booking-card__appointment-time,.chakra-ui-dark .ai-chat-booking-card__appointment-time,.dark .ai-chat-booking-card__appointment-time,[data-theme=dark] .ai-chat-booking-card__appointment-time{color:var(--text-secondary,#a1a1aa)}.ai-chat-booking-card__appointment-contact{color:var(--text-muted,#71717a);font-size:12px}.ai-chat-booking-card__summary{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:8px;margin-bottom:12px;padding:12px}.ai-chat-widget.dark .ai-chat-booking-card__summary,.chakra-ui-dark .ai-chat-booking-card__summary,.dark .ai-chat-booking-card__summary,[data-theme=dark] .ai-chat-booking-card__summary{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1)}.ai-chat-booking-card__summary-row{align-items:center;display:flex;justify-content:space-between;padding:6px 0}.ai-chat-booking-card__summary-row:not(:last-child){border-bottom:1px solid var(--border-subtle,rgba(0,0,0,.06))}.ai-chat-widget.dark .ai-chat-booking-card__summary-row:not(:last-child),.chakra-ui-dark .ai-chat-booking-card__summary-row:not(:last-child),.dark .ai-chat-booking-card__summary-row:not(:last-child),[data-theme=dark] .ai-chat-booking-card__summary-row:not(:last-child){border-bottom-color:hsla(0,0%,100%,.08)}.ai-chat-booking-card__summary-label{color:var(--text-muted,#71717a);font-size:12px;font-weight:600;letter-spacing:.5px;text-transform:uppercase}.ai-chat-booking-card__summary-value{color:var(--text-primary,#3e3e3e);font-size:14px;font-weight:500;text-align:right}.ai-chat-widget.dark .ai-chat-booking-card__summary-value,.chakra-ui-dark .ai-chat-booking-card__summary-value,.dark .ai-chat-booking-card__summary-value,[data-theme=dark] .ai-chat-booking-card__summary-value{color:#fff}.ai-chat-booking-card__link{display:inline-block;font-size:13px;font-weight:500;margin-top:8px;text-decoration:none;transition:opacity .2s ease}.ai-chat-booking-card__link:hover{opacity:.8;text-decoration:underline}.ai-chat-booking-card--success{background:rgba(34,197,94,.05);border-color:rgba(34,197,94,.2)}.ai-chat-widget.dark .ai-chat-booking-card--success,.chakra-ui-dark .ai-chat-booking-card--success,.dark .ai-chat-booking-card--success,[data-theme=dark] .ai-chat-booking-card--success{background:rgba(34,197,94,.1);border-color:rgba(34,197,94,.3)}.ai-chat-booking-card--pending{background:rgba(234,179,8,.05);border-color:rgba(234,179,8,.2)}.ai-chat-widget.dark .ai-chat-booking-card--pending,.chakra-ui-dark .ai-chat-booking-card--pending,.dark .ai-chat-booking-card--pending,[data-theme=dark] .ai-chat-booking-card--pending{background:rgba(234,179,8,.1);border-color:rgba(234,179,8,.3)}.ai-chat-booking-card--cancelled{background:hsla(220,9%,46%,.05);border-color:hsla(220,9%,46%,.2)}.ai-chat-widget.dark .ai-chat-booking-card--cancelled,.chakra-ui-dark .ai-chat-booking-card--cancelled,.dark .ai-chat-booking-card--cancelled,[data-theme=dark] .ai-chat-booking-card--cancelled{background:hsla(220,9%,46%,.1);border-color:hsla(220,9%,46%,.3)}.ai-chat-booking-card--error{background:rgba(239,68,68,.05);border-color:rgba(239,68,68,.2)}.ai-chat-widget.dark .ai-chat-booking-card--error,.chakra-ui-dark .ai-chat-booking-card--error,.dark .ai-chat-booking-card--error,[data-theme=dark] .ai-chat-booking-card--error{background:rgba(239,68,68,.1);border-color:rgba(239,68,68,.3)}.ai-chat-booking-card__pending-text,.ai-chat-booking-card__success-text{color:var(--text-secondary,#6b7280);font-size:13px;margin:0}.ai-chat-widget.dark .ai-chat-booking-card__pending-text,.ai-chat-widget.dark .ai-chat-booking-card__success-text,.chakra-ui-dark .ai-chat-booking-card__pending-text,.chakra-ui-dark .ai-chat-booking-card__success-text,.dark .ai-chat-booking-card__pending-text,.dark .ai-chat-booking-card__success-text,[data-theme=dark] .ai-chat-booking-card__pending-text,[data-theme=dark] .ai-chat-booking-card__success-text{color:var(--text-secondary,#a1a1aa)}.ai-chat-booking-card__error{color:#dc2626;font-size:13px;margin:0}.ai-chat-widget.dark .ai-chat-booking-card__error,.chakra-ui-dark .ai-chat-booking-card__error,.dark .ai-chat-booking-card__error,[data-theme=dark] .ai-chat-booking-card__error{color:#fca5a5}.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)}}";
30849
+ styleInject(css_248z$1);
30850
+
30851
+ 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{margin-bottom:24px}.ai-chat-data-policy-intro p{color:var(--text-primary,#18181b);font-size:13px;line-height:1.6;margin:0;text-align:left}.ai-chat-widget.dark .ai-chat-data-policy-intro p{color:var(--text-primary,#fafafa)}.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:14px;font-weight:600;margin:0 0 12px}.ai-chat-widget.dark .ai-chat-data-policy-section h3{color:var(--text-primary,#fafafa)}.ai-chat-data-policy-section p{color:var(--text-secondary,#52525b);font-size:12px;line-height:1.6;margin:0 0 12px;text-align:justify;text-justify:inter-word}.ai-chat-widget.dark .ai-chat-data-policy-section p{color:var(--text-secondary,#a1a1aa)}.ai-chat-data-policy-section p strong{color:var(--text-primary,#18181b)}.ai-chat-widget.dark .ai-chat-data-policy-section p strong{color:var(--text-primary,#fafafa)}.ai-chat-data-policy-section p:last-child{margin-bottom:0}";
29690
30852
  styleInject(css_248z);
29691
30853
 
29692
30854
  // Icon components mapping
@@ -29694,11 +30856,23 @@ const iconComponents = {
29694
30856
  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" }) })),
29695
30857
  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" }) })),
29696
30858
  };
29697
- 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', }) => {
30859
+ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, previewMode = false, previewConfig, demoMode = false, demoInput, demoOutput, onDemoComplete, position = 'bottom-right', primaryColor, size, headerTitle, welcomeTitle, welcomeMessage, placeholder, welcomeBubbleText, triggerType, triggerText, theme, suggestedQuestions, customStyles, currentRoute, defaultOpen = false, zIndex, containerMode = false, onOpen, onClose, onMessage, onError, mode = 'bubble', }) => {
29698
30860
  const [isOpen, setIsOpen] = React.useState(defaultOpen);
30861
+ const [inputBarValue, setInputBarValue] = React.useState('');
29699
30862
  const [autoDetectedTheme, setAutoDetectedTheme] = React.useState('light');
30863
+ const [showWelcomeBubble, setShowWelcomeBubble] = React.useState(false);
29700
30864
  const widgetRef = React.useRef(null);
29701
30865
  const containerRef = React.useRef(null);
30866
+ // Demo mode state - track whether demo has been activated and completed
30867
+ const [demoMessages, setDemoMessages] = React.useState([]);
30868
+ const [isDemoComplete, setIsDemoComplete] = React.useState(false);
30869
+ const [isDemoTyping, setIsDemoTyping] = React.useState(false);
30870
+ const [demoInputBarText, setDemoInputBarText] = React.useState(''); // For animating text in input bar
30871
+ const [isDemoAnimatingInput, setIsDemoAnimatingInput] = React.useState(false); // True while typing into input bar
30872
+ const [isDemoActive, setIsDemoActive] = React.useState(false); // True when demo animation is running
30873
+ const demoStartedRef = React.useRef(false);
30874
+ // Track if user has sent a real message (transitions from demo to real chat)
30875
+ const [userSentRealMessage, setUserSentRealMessage] = React.useState(false);
29702
30876
  // Determine mode
29703
30877
  const isEmbedded = mode === 'embedded';
29704
30878
  // Default config for preview mode
@@ -29718,6 +30892,7 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, previewMode = f
29718
30892
  showChatHistory: true,
29719
30893
  showTimestamps: true,
29720
30894
  showTypingIndicator: true,
30895
+ showToolCalls: false,
29721
30896
  enableFileUpload: false,
29722
30897
  enableFeedback: true,
29723
30898
  },
@@ -29743,29 +30918,54 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, previewMode = f
29743
30918
  ...previewConfig?.behavior,
29744
30919
  },
29745
30920
  };
29746
- // Always call useChat hook (React rules), but skip initialization in preview mode
30921
+ // Always call useChat hook (React rules), but skip initialization in preview mode or during demo
30922
+ // Skip initialization during demo to prevent loading old conversations
30923
+ // Note: We still pass the real widgetId so createDemoConversation works correctly
30924
+ const shouldSkipInit = previewMode || (demoMode && !userSentRealMessage);
29747
30925
  const chatHook = useChat({
29748
30926
  widgetId: previewMode ? '__preview__' : (widgetId || '__preview__'),
29749
30927
  apiUrl,
29750
30928
  currentRoute,
29751
- onMessage: previewMode ? undefined : onMessage,
29752
- onError: previewMode ? undefined : onError,
29753
- skipInitialization: previewMode, // Don't make API calls in preview mode
30929
+ onMessage: shouldSkipInit ? undefined : onMessage,
30930
+ onError: shouldSkipInit ? undefined : onError,
30931
+ skipInitialization: shouldSkipInit, // Don't make API calls in preview mode or during demo
29754
30932
  });
29755
30933
  // Extract values from hook or use preview defaults
29756
- const messages = previewMode ? [] : chatHook.messages;
29757
- const isLoading = previewMode ? false : chatHook.isLoading;
29758
- const isTyping = previewMode ? false : chatHook.isTyping;
29759
- const error = previewMode ? null : chatHook.error;
30934
+ const hookMessages = previewMode ? [] : chatHook.messages;
30935
+ const hookIsLoading = previewMode ? false : chatHook.isLoading;
30936
+ const hookIsTyping = previewMode ? false : chatHook.isTyping;
29760
30937
  const config = previewMode ? mergedPreviewConfig : chatHook.config;
29761
- const sendMessage = previewMode ? (() => Promise.resolve()) : chatHook.sendMessage;
30938
+ const hookSendMessage = previewMode ? (() => Promise.resolve()) : chatHook.sendMessage;
29762
30939
  const submitFeedback = previewMode ? (() => Promise.resolve()) : chatHook.submitFeedback;
30940
+ const dismissAction = previewMode ? (() => Promise.resolve()) : chatHook.dismissAction;
29763
30941
  const conversations = previewMode ? [] : chatHook.conversations;
29764
30942
  const loadConversations = previewMode ? (() => { }) : chatHook.loadConversations;
29765
30943
  const switchConversation = previewMode ? (() => Promise.resolve()) : chatHook.switchConversation;
29766
30944
  const startNewConversation = previewMode ? (() => { }) : chatHook.startNewConversation;
29767
30945
  const deleteConversation = previewMode ? (() => { }) : chatHook.deleteConversation;
30946
+ const createDemoConversation = previewMode ? (() => Promise.resolve(null)) : chatHook.createDemoConversation;
29768
30947
  const conversationId = previewMode ? '' : chatHook.conversationId;
30948
+ // Message display logic:
30949
+ // - During demo (before user sends real message): show demoMessages
30950
+ // - After user sends real message: show hookMessages
30951
+ const showDemoMessages = demoMode && demoMessages.length > 0 && !userSentRealMessage;
30952
+ const messages = showDemoMessages ? demoMessages : hookMessages;
30953
+ const isLoading = showDemoMessages ? false : hookIsLoading;
30954
+ const isTyping = showDemoMessages ? isDemoTyping : hookIsTyping;
30955
+ // Send message handler - transitions from demo to real chat when user sends first message
30956
+ const sendMessage = React.useCallback((content) => {
30957
+ if (demoMode && isDemoActive && !isDemoComplete) {
30958
+ // Demo animation is still running - ignore user input
30959
+ return Promise.resolve();
30960
+ }
30961
+ // User is sending a real message - transition to real chat
30962
+ if (demoMode && !userSentRealMessage) {
30963
+ setUserSentRealMessage(true);
30964
+ // Clear demo messages so hook messages take over
30965
+ setDemoMessages([]);
30966
+ }
30967
+ return hookSendMessage(content);
30968
+ }, [demoMode, isDemoActive, isDemoComplete, userSentRealMessage, hookSendMessage]);
29769
30969
  // Auto-detect theme from background
29770
30970
  React.useEffect(() => {
29771
30971
  if (!containerRef.current)
@@ -29791,8 +30991,16 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, previewMode = f
29791
30991
  mediaQuery.removeEventListener('change', handleMediaChange);
29792
30992
  };
29793
30993
  }, [config]);
29794
- // Handle auto-open (only for bubble mode)
30994
+ // Check if device is mobile
30995
+ const isMobile = typeof window !== 'undefined' && window.innerWidth <= 480;
30996
+ // Handle auto-open (only for bubble mode, disabled on mobile)
29795
30997
  React.useEffect(() => {
30998
+ // Never auto-open on mobile devices
30999
+ if (isMobile)
31000
+ return undefined;
31001
+ // Don't auto-open if demo mode is active - let demo animation control opening
31002
+ if (demoMode && !isDemoComplete)
31003
+ return undefined;
29796
31004
  if (!isEmbedded && config?.settings.autoOpen) {
29797
31005
  const delay = config.settings.autoOpenDelay || 0;
29798
31006
  const timer = setTimeout(() => {
@@ -29802,7 +31010,7 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, previewMode = f
29802
31010
  return () => clearTimeout(timer);
29803
31011
  }
29804
31012
  return undefined;
29805
- }, [config, onOpen, isEmbedded]);
31013
+ }, [config, onOpen, isEmbedded, isMobile, demoMode, isDemoComplete]);
29806
31014
  // Handle close on Escape key (only for bubble mode)
29807
31015
  React.useEffect(() => {
29808
31016
  if (!isOpen || isEmbedded)
@@ -29816,6 +31024,203 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, previewMode = f
29816
31024
  document.addEventListener('keydown', handleEscapeKey);
29817
31025
  return () => document.removeEventListener('keydown', handleEscapeKey);
29818
31026
  }, [isOpen, onClose, isEmbedded]);
31027
+ // Handle body scroll lock on mobile when widget is open
31028
+ React.useEffect(() => {
31029
+ if (!isOpen || isEmbedded)
31030
+ return;
31031
+ // Only apply scroll lock on mobile
31032
+ const checkMobile = window.innerWidth <= 480;
31033
+ if (!checkMobile)
31034
+ return;
31035
+ // Add class to body to lock scrolling
31036
+ document.body.classList.add('ai-chat-widget-open');
31037
+ return () => {
31038
+ document.body.classList.remove('ai-chat-widget-open');
31039
+ };
31040
+ }, [isOpen, isEmbedded]);
31041
+ // Handle welcome bubble visibility based on frequency setting
31042
+ // Frequency options: 'always' (every page visit), 'session', 'weekly', 'monthly'
31043
+ React.useEffect(() => {
31044
+ if (isEmbedded || previewMode)
31045
+ return;
31046
+ const bubbleText = welcomeBubbleText ?? config?.appearance?.welcomeBubbleText;
31047
+ if (!bubbleText) {
31048
+ setShowWelcomeBubble(false);
31049
+ return;
31050
+ }
31051
+ const frequency = config?.appearance?.welcomeBubbleFrequency ?? 'session';
31052
+ const storageKey = `ai-chat-bubble-dismissed-${widgetId || 'default'}`;
31053
+ // Check if bubble should be shown based on frequency
31054
+ const shouldShowBubble = () => {
31055
+ if (frequency === 'always') {
31056
+ // Always show on every page visit (no storage check)
31057
+ return true;
31058
+ }
31059
+ if (frequency === 'session') {
31060
+ // Show once per session
31061
+ return sessionStorage.getItem(storageKey) !== 'true';
31062
+ }
31063
+ // For weekly/monthly, use localStorage with timestamp
31064
+ try {
31065
+ const stored = localStorage.getItem(storageKey);
31066
+ if (!stored)
31067
+ return true;
31068
+ const dismissedAt = parseInt(stored, 10);
31069
+ if (isNaN(dismissedAt))
31070
+ return true;
31071
+ const now = Date.now();
31072
+ const weekMs = 7 * 24 * 60 * 60 * 1000;
31073
+ const monthMs = 30 * 24 * 60 * 60 * 1000;
31074
+ if (frequency === 'weekly') {
31075
+ return now - dismissedAt > weekMs;
31076
+ }
31077
+ if (frequency === 'monthly') {
31078
+ return now - dismissedAt > monthMs;
31079
+ }
31080
+ }
31081
+ catch {
31082
+ return true;
31083
+ }
31084
+ return true;
31085
+ };
31086
+ if (shouldShowBubble() && !isOpen) {
31087
+ setShowWelcomeBubble(true);
31088
+ }
31089
+ }, [widgetId, welcomeBubbleText, config, isOpen, isEmbedded, previewMode]);
31090
+ // Demo mode: animate typing into input bar, then open widget with conversation
31091
+ // This shows the widget in action without making expensive AI calls
31092
+ React.useEffect(() => {
31093
+ // Determine trigger type early (from prop or config)
31094
+ // IMPORTANT: For demo mode, we need config to be loaded to know the trigger type
31095
+ // If config is not loaded yet, wait for it (unless triggerType prop is provided)
31096
+ const effectiveTriggerTypeForDemo = triggerType ?? config?.appearance?.triggerType ?? 'button';
31097
+ const isInputBarTrigger = effectiveTriggerTypeForDemo === 'input-bar';
31098
+ // Debug logging
31099
+ console.log('[Widget] Demo effect check:', {
31100
+ demoMode,
31101
+ isDemoComplete,
31102
+ demoStartedRef: demoStartedRef.current,
31103
+ hasDemoInput: !!demoInput,
31104
+ hasDemoOutput: !!demoOutput,
31105
+ triggerType: effectiveTriggerTypeForDemo,
31106
+ isInputBar: isInputBarTrigger,
31107
+ isOpen,
31108
+ });
31109
+ // Start demo when demoMode is enabled and we have input/output
31110
+ const shouldStartDemo = demoMode && !isDemoComplete && !demoStartedRef.current && demoInput && demoOutput;
31111
+ if (!shouldStartDemo) {
31112
+ console.log('[Widget] Demo not starting:', { shouldStartDemo, reason: !demoMode ? 'demoMode false' : !demoInput ? 'no demoInput' : !demoOutput ? 'no demoOutput' : isDemoComplete ? 'already complete' : demoStartedRef.current ? 'already started' : 'unknown' });
31113
+ return;
31114
+ }
31115
+ // Wait for config to load before starting demo (unless triggerType prop is explicitly provided)
31116
+ // This prevents the demo from starting with wrong trigger type
31117
+ if (!triggerType && !config) {
31118
+ console.log('[Widget] Demo waiting for config or triggerType prop');
31119
+ return;
31120
+ }
31121
+ // For input-bar: start immediately (widget closed, type into bar)
31122
+ // For others: wait until widget is open
31123
+ if (!isInputBarTrigger && !isOpen) {
31124
+ console.log('[Widget] Demo waiting for widget to open (non-input-bar trigger)');
31125
+ return;
31126
+ }
31127
+ console.log('[Widget] Starting demo animation...', {
31128
+ triggerType: effectiveTriggerTypeForDemo,
31129
+ isInputBar: isInputBarTrigger,
31130
+ demoInput,
31131
+ demoOutput: demoOutput?.substring(0, 50) + '...',
31132
+ });
31133
+ demoStartedRef.current = true;
31134
+ setIsDemoActive(true);
31135
+ // Use stable IDs to prevent React from remounting components
31136
+ const userMessageId = 'demo-user-message';
31137
+ const assistantMessageId = 'demo-assistant-message';
31138
+ // Helper to create a message with stable ID
31139
+ const createMessage = (id, role, content, isStreaming = false) => ({
31140
+ id,
31141
+ message: { role, content },
31142
+ timestamp: new Date().toISOString(),
31143
+ sources: [],
31144
+ isStreaming,
31145
+ });
31146
+ // Animation sequence - runs to completion even if widget is closed
31147
+ // This ensures conversation is always created and saved consistently
31148
+ const runDemoAnimation = async () => {
31149
+ // STEP 1: Create conversation IMMEDIATELY at the start
31150
+ // This ensures we have a conversation ID before any animation
31151
+ console.log('[Widget] Creating demo conversation at start...');
31152
+ let conversationId = null;
31153
+ try {
31154
+ conversationId = await createDemoConversation(demoInput, demoOutput);
31155
+ if (conversationId) {
31156
+ console.log('[Widget] Demo conversation created:', conversationId);
31157
+ }
31158
+ }
31159
+ catch (err) {
31160
+ console.warn('[Widget] Failed to create demo conversation:', err);
31161
+ }
31162
+ // STEP 2: For input-bar trigger, animate typing into input bar first
31163
+ if (isInputBarTrigger && !isOpen) {
31164
+ setIsDemoAnimatingInput(true);
31165
+ // Wait before starting to type - ensure input bar is fully visible
31166
+ await new Promise(resolve => setTimeout(resolve, 1500));
31167
+ // Type into input bar character by character
31168
+ const inputChars = demoInput.split('');
31169
+ for (let i = 0; i < inputChars.length; i++) {
31170
+ setDemoInputBarText(demoInput.slice(0, i + 1));
31171
+ // Slower typing speed for better visibility
31172
+ const delay = inputChars[i] === ' ' ? 100 : 60 + Math.random() * 40;
31173
+ await new Promise(resolve => setTimeout(resolve, delay));
31174
+ }
31175
+ // Longer pause after typing so user can read the question
31176
+ await new Promise(resolve => setTimeout(resolve, 1000));
31177
+ setIsDemoAnimatingInput(false);
31178
+ setDemoInputBarText('');
31179
+ setIsOpen(true);
31180
+ onOpen?.();
31181
+ // Let widget open animation complete
31182
+ await new Promise(resolve => setTimeout(resolve, 500));
31183
+ }
31184
+ else {
31185
+ // For non-input-bar triggers, just wait for widget to settle
31186
+ await new Promise(resolve => setTimeout(resolve, 800));
31187
+ }
31188
+ // STEP 3: Add user message
31189
+ setDemoMessages([createMessage(userMessageId, 'user', demoInput)]);
31190
+ // Show typing indicator after a pause
31191
+ await new Promise(resolve => setTimeout(resolve, 500));
31192
+ setIsDemoTyping(true);
31193
+ // "Thinking" pause
31194
+ await new Promise(resolve => setTimeout(resolve, 1200));
31195
+ setIsDemoTyping(false);
31196
+ // STEP 4: Stream the response character by character
31197
+ const chars = demoOutput.split('');
31198
+ let currentText = '';
31199
+ // Initial message with empty content
31200
+ setDemoMessages([
31201
+ createMessage(userMessageId, 'user', demoInput),
31202
+ createMessage(assistantMessageId, 'assistant', '', true),
31203
+ ]);
31204
+ await new Promise(resolve => setTimeout(resolve, 100));
31205
+ // Stream characters - continues even if widget is closed
31206
+ for (let i = 0; i < chars.length; i++) {
31207
+ currentText += chars[i];
31208
+ setDemoMessages([
31209
+ createMessage(userMessageId, 'user', demoInput),
31210
+ createMessage(assistantMessageId, 'assistant', currentText, i < chars.length - 1),
31211
+ ]);
31212
+ const delay = chars[i] === ' ' ? 12 : 20;
31213
+ await new Promise(resolve => setTimeout(resolve, delay));
31214
+ }
31215
+ // STEP 5: Mark demo complete
31216
+ await new Promise(resolve => setTimeout(resolve, 500));
31217
+ setIsDemoComplete(true);
31218
+ setIsDemoActive(false);
31219
+ console.log('[Widget] Demo animation complete');
31220
+ onDemoComplete?.();
31221
+ };
31222
+ runDemoAnimation();
31223
+ }, [demoMode, isOpen, isDemoComplete, demoInput, demoOutput, onDemoComplete, triggerType, config?.appearance?.triggerType, onOpen, createDemoConversation]);
29819
31224
  // Determine theme - use prop override if provided, otherwise auto-detect
29820
31225
  const appearanceConfig = config?.appearance;
29821
31226
  const effectiveTheme = theme ?? autoDetectedTheme;
@@ -29824,11 +31229,14 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, previewMode = f
29824
31229
  // Get accent color from prop or config (empty string means no accent color / vanilla mode)
29825
31230
  const accentColor = primaryColor ?? appearanceConfig?.primaryColor ?? '';
29826
31231
  // Apply prop overrides for live preview (props take priority over config)
29827
- size || appearanceConfig?.size || 'small';
31232
+ const effectiveSize = size || appearanceConfig?.size || 'small';
29828
31233
  const effectiveHeaderTitle = headerTitle ?? appearanceConfig?.headerTitle ?? '';
29829
31234
  const effectiveWelcomeTitle = welcomeTitle ?? appearanceConfig?.welcomeTitle ?? '';
29830
31235
  const effectiveWelcomeMessage = welcomeMessage ?? appearanceConfig?.welcomeMessage ?? '';
29831
31236
  const effectivePlaceholder = placeholder ?? appearanceConfig?.placeholder ?? '';
31237
+ const effectiveWelcomeBubbleText = welcomeBubbleText ?? appearanceConfig?.welcomeBubbleText ?? '';
31238
+ const effectiveTriggerType = triggerType ?? appearanceConfig?.triggerType ?? 'button';
31239
+ const effectiveTriggerText = triggerText ?? appearanceConfig?.triggerText ?? 'Chat';
29832
31240
  // Generate styles using simplified theme system
29833
31241
  const simpleAppearance = {
29834
31242
  accentColor};
@@ -29845,18 +31253,65 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, previewMode = f
29845
31253
  ...customStyles,
29846
31254
  ...(zIndex !== undefined ? { '--widget-z-index': String(zIndex) } : {}),
29847
31255
  };
31256
+ // Dismiss bubble and store based on frequency setting
31257
+ const dismissBubble = () => {
31258
+ setShowWelcomeBubble(false);
31259
+ const frequency = config?.appearance?.welcomeBubbleFrequency ?? 'session';
31260
+ const storageKey = `ai-chat-bubble-dismissed-${widgetId || 'default'}`;
31261
+ try {
31262
+ if (frequency === 'always') {
31263
+ // For 'always', use sessionStorage so it only hides until page refresh
31264
+ sessionStorage.setItem(storageKey, 'true');
31265
+ }
31266
+ else if (frequency === 'session') {
31267
+ sessionStorage.setItem(storageKey, 'true');
31268
+ }
31269
+ else {
31270
+ // For weekly/monthly, store timestamp in localStorage
31271
+ localStorage.setItem(storageKey, String(Date.now()));
31272
+ }
31273
+ }
31274
+ catch {
31275
+ // Ignore storage errors
31276
+ }
31277
+ };
29848
31278
  const handleToggle = () => {
29849
31279
  if (isEmbedded)
29850
31280
  return;
29851
31281
  const newState = !isOpen;
29852
31282
  setIsOpen(newState);
31283
+ // Dismiss welcome bubble when chat is opened
31284
+ if (newState && showWelcomeBubble) {
31285
+ dismissBubble();
31286
+ }
29853
31287
  if (newState) {
29854
31288
  onOpen?.();
29855
31289
  }
29856
31290
  else {
31291
+ // Demo animation continues in background when widget is closed
31292
+ // The conversation was already created at the start, so closing is safe
31293
+ // When user reopens, they'll see the current state of the demo animation
29857
31294
  onClose?.();
29858
31295
  }
29859
31296
  };
31297
+ const handleDismissBubble = (e) => {
31298
+ e.stopPropagation();
31299
+ dismissBubble();
31300
+ };
31301
+ // Handle input bar submit - opens widget and sends message
31302
+ const handleInputBarSubmit = React.useCallback((e) => {
31303
+ e.preventDefault();
31304
+ if (!inputBarValue.trim() || previewMode)
31305
+ return;
31306
+ // Open the widget
31307
+ setIsOpen(true);
31308
+ onOpen?.();
31309
+ // Send the message after a brief delay to allow widget to open
31310
+ setTimeout(() => {
31311
+ sendMessage(inputBarValue.trim());
31312
+ setInputBarValue('');
31313
+ }, 100);
31314
+ }, [inputBarValue, previewMode, onOpen, sendMessage]);
29860
31315
  const handleFeedback = async (messageId, feedback) => {
29861
31316
  await submitFeedback(messageId, feedback);
29862
31317
  };
@@ -29872,24 +31327,36 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, previewMode = f
29872
31327
  sendMessage(actionInstruction);
29873
31328
  };
29874
31329
  // Don't render until config is loaded to avoid flash of unstyled content
31330
+ // Exception: If we have essential props (triggerType), allow rendering the trigger immediately
31331
+ // This improves perceived loading speed - users see the trigger while config loads
29875
31332
  // In preview mode, config is always available
29876
- if (!config && !previewMode) {
31333
+ const canRenderWithoutConfig = !!triggerType;
31334
+ if (!config && !previewMode && !canRenderWithoutConfig) {
29877
31335
  return null;
29878
31336
  }
29879
31337
  // Get button icon based on state
29880
31338
  const IconComponent = isOpen ? iconComponents.FiChevronDown : iconComponents.FiMessageCircle;
29881
31339
  // Embedded mode renders directly without wrapper positioning
29882
31340
  if (isEmbedded) {
29883
- 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 }) }));
29884
- }
29885
- 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,
31341
+ 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, onActionDismiss: dismissAction, conversations: conversations, onLoadConversations: loadConversations, onSwitchConversation: switchConversation, onStartNewConversation: startNewConversation, onDeleteConversation: deleteConversation, currentConversationId: conversationId, headerTitleOverride: effectiveHeaderTitle, welcomeTitleOverride: effectiveWelcomeTitle, welcomeMessageOverride: effectiveWelcomeMessage, placeholderOverride: effectivePlaceholder, suggestedQuestionsOverride: suggestedQuestions }) }));
31342
+ }
31343
+ // Determine trigger class for container
31344
+ const triggerClass = effectiveTriggerType === 'pill-text'
31345
+ ? 'trigger-pill-text'
31346
+ : effectiveTriggerType === 'input-bar'
31347
+ ? 'trigger-input-bar'
31348
+ : '';
31349
+ // Size class for CSS targeting (used by input-bar trigger for width matching)
31350
+ const sizeClass = `size-${effectiveSize}`;
31351
+ 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' : ''} ${triggerClass} ${sizeClass}`, children: [isOpen && (jsxRuntime.jsx(ChatWindow, { messages: demoMode && !isDemoComplete ? demoMessages : messages, isLoading: demoMode && !isDemoComplete ? false : isLoading, isTyping: demoMode && !isDemoComplete ? isDemoTyping : isTyping, config: config, onSendMessage: sendMessage, onClose: handleToggle, onFeedback: handleFeedback, onActionClick: handleActionClick, onActionDismiss: dismissAction,
29886
31352
  // Chat history props (only active when persistConversation is true)
29887
31353
  conversations: conversations, onLoadConversations: loadConversations, onSwitchConversation: switchConversation, onStartNewConversation: startNewConversation, onDeleteConversation: deleteConversation, currentConversationId: conversationId,
29888
31354
  // Override props for live preview
29889
- 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, {}) }) })] }) }));
31355
+ headerTitleOverride: effectiveHeaderTitle, welcomeTitleOverride: effectiveWelcomeTitle, welcomeMessageOverride: effectiveWelcomeMessage, placeholderOverride: effectivePlaceholder, suggestedQuestionsOverride: suggestedQuestions })), effectiveTriggerType === 'button' && !isOpen && effectiveWelcomeBubbleText && (previewMode || showWelcomeBubble) && (jsxRuntime.jsxs("div", { className: "ai-chat-welcome-bubble", onClick: handleToggle, children: [jsxRuntime.jsx("span", { children: effectiveWelcomeBubbleText }), jsxRuntime.jsx("button", { className: "ai-chat-welcome-bubble-close", onClick: handleDismissBubble, "aria-label": "Dismiss", children: jsxRuntime.jsxs("svg", { 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" })] }) }), jsxRuntime.jsx("div", { className: "ai-chat-welcome-bubble-arrow" })] })), effectiveTriggerType === 'button' && (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, {}) }) })), effectiveTriggerType === 'pill-text' && (jsxRuntime.jsxs("button", { className: `ai-chat-trigger-pill ${isOpen ? 'is-open' : ''}`, onClick: handleToggle, "aria-label": isOpen ? "Close chat" : "Open chat", children: [jsxRuntime.jsx("div", { className: "ai-chat-trigger-pill-icon", children: jsxRuntime.jsx(IconComponent, {}) }), !isOpen && jsxRuntime.jsx("span", { children: effectiveTriggerText })] })), effectiveTriggerType === 'input-bar' && !isOpen && (jsxRuntime.jsxs("div", { className: "ai-chat-trigger-input-container", children: [jsxRuntime.jsx("button", { type: "button", className: "ai-chat-trigger-input-expand", onClick: handleToggle, "aria-label": "Open chat", children: jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntime.jsx("polyline", { points: "18 15 12 9 6 15" }) }) }), jsxRuntime.jsxs("form", { className: "ai-chat-trigger-input-wrapper", onSubmit: handleInputBarSubmit, children: [jsxRuntime.jsx("input", { type: "text", className: "ai-chat-trigger-input", placeholder: effectivePlaceholder || "Ask me anything...", value: isDemoAnimatingInput ? demoInputBarText : inputBarValue, onChange: (e) => !isDemoAnimatingInput && setInputBarValue(e.target.value), readOnly: isDemoAnimatingInput, "aria-label": "Chat input" }), jsxRuntime.jsx("button", { type: "submit", className: "ai-chat-trigger-input-btn", disabled: isDemoAnimatingInput ? !demoInputBarText.trim() : !inputBarValue.trim(), "aria-label": "Send message", children: jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntime.jsx("line", { x1: "22", y1: "2", x2: "11", y2: "13" }), jsxRuntime.jsx("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })] }) })] })] }))] }) }));
29890
31356
  };
29891
31357
 
29892
31358
  exports.ApiError = ApiError;
29893
31359
  exports.ChatWidget = ChatWidget;
31360
+ exports.DataPolicyView = DataPolicyView;
29894
31361
  exports.useChat = useChat;
29895
31362
  //# sourceMappingURL=index.js.map