@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
@@ -16696,11 +16696,14 @@
16696
16696
  const reader = response.body.getReader();
16697
16697
  const decoder = new TextDecoder();
16698
16698
  let buffer = "";
16699
+ let eventCount = 0;
16699
16700
  try {
16700
16701
  while (true) {
16701
16702
  const { done, value } = await reader.read();
16702
- if (done)
16703
+ if (done) {
16704
+ console.log(`[SSE Parser] Stream ended normally after ${eventCount} events`);
16703
16705
  break;
16706
+ }
16704
16707
  buffer += decoder.decode(value, { stream: true });
16705
16708
  const chunks = buffer.split("\n\n");
16706
16709
  buffer = chunks.pop() || "";
@@ -16712,6 +16715,7 @@
16712
16715
  const data = JSON.parse(line.slice(6));
16713
16716
  if (validator) {
16714
16717
  if (validator(data)) {
16718
+ eventCount++;
16715
16719
  yield data;
16716
16720
  }
16717
16721
  else {
@@ -16719,6 +16723,7 @@
16719
16723
  }
16720
16724
  }
16721
16725
  else {
16726
+ eventCount++;
16722
16727
  yield data;
16723
16728
  }
16724
16729
  }
@@ -16731,6 +16736,10 @@
16731
16736
  }
16732
16737
  }
16733
16738
  }
16739
+ catch (error) {
16740
+ console.error(`[SSE Parser] Stream error after ${eventCount} events:`, error);
16741
+ throw error;
16742
+ }
16734
16743
  finally {
16735
16744
  reader.releaseLock();
16736
16745
  }
@@ -16864,7 +16873,7 @@
16864
16873
  const result = await response.json();
16865
16874
  return result.file;
16866
16875
  }
16867
- async *sendAgentMessageStream(conversationId, message, fileIds) {
16876
+ async *sendAgentMessageStream(conversationId, message, fileIds, signal) {
16868
16877
  const headers = {
16869
16878
  'Content-Type': 'application/json',
16870
16879
  };
@@ -16880,6 +16889,7 @@
16880
16889
  fileIds,
16881
16890
  timeZone: this.getTimeZone(),
16882
16891
  }),
16892
+ signal,
16883
16893
  });
16884
16894
  if (!response.ok) {
16885
16895
  throw await buildApiError(response, 'Failed to send agent message');
@@ -16888,7 +16898,7 @@
16888
16898
  return typeof data === 'object' && data !== null && 'type' in data;
16889
16899
  });
16890
16900
  }
16891
- async *continueAgentMessageStream(conversationId, toolCallId, state) {
16901
+ async *continueAgentMessageStream(conversationId, toolCallId, state, signal) {
16892
16902
  const headers = {
16893
16903
  'Content-Type': 'application/json',
16894
16904
  };
@@ -16904,6 +16914,7 @@
16904
16914
  state,
16905
16915
  timeZone: this.getTimeZone(),
16906
16916
  }),
16917
+ signal,
16907
16918
  });
16908
16919
  if (!response.ok) {
16909
16920
  throw await buildApiError(response, 'Failed to continue agent');
@@ -16912,6 +16923,33 @@
16912
16923
  return typeof data === 'object' && data !== null && 'type' in data;
16913
16924
  });
16914
16925
  }
16926
+ async *dismissAgentMessageStream(conversationId, toolCallId, signal) {
16927
+ const headers = {
16928
+ 'Content-Type': 'application/json',
16929
+ };
16930
+ if (this.config.currentRoute) {
16931
+ headers['X-Current-Route'] = this.config.currentRoute;
16932
+ }
16933
+ const response = await fetch(`${this.config.apiUrl}/api/widget/${this.config.widgetId}/agent/dismiss`, {
16934
+ method: 'POST',
16935
+ headers,
16936
+ body: JSON.stringify({
16937
+ conversationId: conversationId,
16938
+ toolCallId,
16939
+ reason: "user",
16940
+ }),
16941
+ signal,
16942
+ });
16943
+ if (response.status === 204) {
16944
+ return;
16945
+ }
16946
+ if (!response.ok) {
16947
+ throw await buildApiError(response, 'Failed to dismiss action');
16948
+ }
16949
+ yield* parseSSEStream(response, (data) => {
16950
+ return typeof data === 'object' && data !== null && 'type' in data;
16951
+ });
16952
+ }
16915
16953
  /**
16916
16954
  * Submit feedback for a message
16917
16955
  */
@@ -16974,6 +17012,27 @@
16974
17012
  return [];
16975
17013
  }
16976
17014
  }
17015
+ /**
17016
+ * Create a demo conversation with preset messages
17017
+ * Used when demo animation completes to persist the demo conversation to the database
17018
+ */
17019
+ async createDemoConversation(userMessage, assistantMessage) {
17020
+ const response = await fetch(`${this.config.apiUrl}/api/widget/${this.config.widgetId}/demo-conversation`, {
17021
+ method: 'POST',
17022
+ headers: {
17023
+ 'Content-Type': 'application/json',
17024
+ },
17025
+ body: JSON.stringify({
17026
+ userMessage,
17027
+ assistantMessage,
17028
+ timeZone: this.getTimeZone(),
17029
+ }),
17030
+ });
17031
+ if (!response.ok) {
17032
+ throw await buildApiError(response, 'Failed to create demo conversation');
17033
+ }
17034
+ return response.json();
17035
+ }
16977
17036
  /**
16978
17037
  * Validate widget access
16979
17038
  */
@@ -43800,22 +43859,19 @@
43800
43859
  const formatToolName = (name) => {
43801
43860
  return name
43802
43861
  .replace(/^(action_|tool_)/, '')
43862
+ .replace(/-/g, '_')
43803
43863
  .split('_')
43804
43864
  .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
43805
43865
  .join(' ');
43806
43866
  };
43807
- const GearIcon = ({ spinning = false }) => (jsxRuntimeExports.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: [jsxRuntimeExports.jsx("path", { d: "M12 20a8 8 0 1 0 0-16 8 8 0 0 0 0 16Z" }), jsxRuntimeExports.jsx("path", { d: "M12 14a2 2 0 1 0 0-4 2 2 0 0 0 0 4Z" }), jsxRuntimeExports.jsx("path", { d: "M12 2v2" }), jsxRuntimeExports.jsx("path", { d: "M12 22v-2" }), jsxRuntimeExports.jsx("path", { d: "m17 20.66-1-1.73" }), jsxRuntimeExports.jsx("path", { d: "M11 10.27 7 3.34" }), jsxRuntimeExports.jsx("path", { d: "m20.66 17-1.73-1" }), jsxRuntimeExports.jsx("path", { d: "m3.34 7 1.73 1" }), jsxRuntimeExports.jsx("path", { d: "M14 12h8" }), jsxRuntimeExports.jsx("path", { d: "M2 12h2" }), jsxRuntimeExports.jsx("path", { d: "m20.66 7-1.73 1" }), jsxRuntimeExports.jsx("path", { d: "m3.34 17 1.73-1" }), jsxRuntimeExports.jsx("path", { d: "m17 3.34-1 1.73" }), jsxRuntimeExports.jsx("path", { d: "m11 13.73-4 6.93" })] }));
43808
- const CheckIcon$2 = () => (jsxRuntimeExports.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: jsxRuntimeExports.jsx("polyline", { points: "20 6 9 17 4 12" }) }));
43809
- const ErrorIcon = () => (jsxRuntimeExports.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: jsxRuntimeExports.jsx("path", { d: "M18 6L6 18M6 6l12 12" }) }));
43810
43867
  function ToolIndicator({ badges, className = '' }) {
43811
- const isAnyLoading = badges.some(b => b.status === 'loading');
43812
- return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-tool-row ${className}`, children: [jsxRuntimeExports.jsx(GearIcon, { spinning: isAnyLoading }), jsxRuntimeExports.jsx("div", { className: "ai-chat-tool-badges", children: badges.map((badge) => (jsxRuntimeExports.jsxs("div", { className: `ai-chat-tool-badge ${badge.status}`, children: [badge.status !== 'loading' && (badge.status === 'error' ? jsxRuntimeExports.jsx(ErrorIcon, {}) : jsxRuntimeExports.jsx(CheckIcon$2, {})), jsxRuntimeExports.jsx("span", { className: "tool-name", children: formatToolName(badge.name) })] }, badge.id))) })] }));
43868
+ return (jsxRuntimeExports.jsx("div", { className: `ai-chat-tool-row ${className}`, children: jsxRuntimeExports.jsx("div", { className: "ai-chat-tool-badges", children: badges.map((badge) => (jsxRuntimeExports.jsx("div", { className: `ai-chat-tool-badge ${badge.status}`, children: jsxRuntimeExports.jsx("span", { className: "tool-name", children: formatToolName(badge.name) }) }, badge.id))) }) }));
43813
43869
  }
43814
43870
 
43815
43871
  // SVG Icon components
43816
43872
  const ThumbsUpIcon = () => (jsxRuntimeExports.jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.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" }) }));
43817
43873
  const ThumbsDownIcon = () => (jsxRuntimeExports.jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.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" }) }));
43818
- const CheckIcon$1 = () => (jsxRuntimeExports.jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("polyline", { points: "20 6 9 17 4 12" }) }));
43874
+ const CheckIcon$2 = () => (jsxRuntimeExports.jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("polyline", { points: "20 6 9 17 4 12" }) }));
43819
43875
  const FeedbackButtons = ({ messageId, currentFeedback, onFeedback, }) => {
43820
43876
  const [isSubmitting, setIsSubmitting] = reactExports.useState(false);
43821
43877
  const [submitted, setSubmitted] = reactExports.useState(false);
@@ -43836,10 +43892,10 @@
43836
43892
  setIsSubmitting(false);
43837
43893
  }
43838
43894
  };
43839
- return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-feedback ${submitted ? 'submitted' : ''}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-feedback-buttons", children: [jsxRuntimeExports.jsx("button", { className: `ai-chat-feedback-button ${currentFeedback === 'positive' ? 'active' : ''}`, onClick: () => handleFeedback('positive'), disabled: isDisabled, "aria-label": "Helpful", title: "This was helpful", children: jsxRuntimeExports.jsx(ThumbsUpIcon, {}) }), jsxRuntimeExports.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: jsxRuntimeExports.jsx(ThumbsDownIcon, {}) })] }), submitted && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-feedback-message", "aria-live": "polite", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-feedback-checkmark", children: jsxRuntimeExports.jsx(CheckIcon$1, {}) }), jsxRuntimeExports.jsx("span", { className: "ai-chat-feedback-text", children: "Thanks for feedback" })] }))] }));
43895
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-feedback ${submitted ? 'submitted' : ''}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-feedback-buttons", children: [jsxRuntimeExports.jsx("button", { className: `ai-chat-feedback-button ${currentFeedback === 'positive' ? 'active' : ''}`, onClick: () => handleFeedback('positive'), disabled: isDisabled, "aria-label": "Helpful", title: "This was helpful", children: jsxRuntimeExports.jsx(ThumbsUpIcon, {}) }), jsxRuntimeExports.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: jsxRuntimeExports.jsx(ThumbsDownIcon, {}) })] }), submitted && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-feedback-message", "aria-live": "polite", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-feedback-checkmark", children: jsxRuntimeExports.jsx(CheckIcon$2, {}) }), jsxRuntimeExports.jsx("span", { className: "ai-chat-feedback-text", children: "Thanks for feedback" })] }))] }));
43840
43896
  };
43841
43897
 
43842
- const Message = ({ message, showTimestamp = true, enableFeedback = true, onFeedback, getActionRenderer, accentColor, }) => {
43898
+ const Message = ({ message, showTimestamp = true, enableFeedback = true, onFeedback, }) => {
43843
43899
  const formatTime = (timestamp) => {
43844
43900
  const date = typeof timestamp === 'string' ? new Date(timestamp) : timestamp;
43845
43901
  return date.toLocaleTimeString('en-US', {
@@ -43859,15 +43915,15 @@
43859
43915
  return null;
43860
43916
  }
43861
43917
  // AI message rendering
43918
+ // Note: Actions are rendered by ToolMessageGroup for tool messages, not here
43862
43919
  if (isAssistant) {
43863
43920
  const aiContent = message.message.content || '';
43864
43921
  const hasContent = aiContent.trim().length > 0;
43865
43922
  if (!hasContent)
43866
43923
  return null;
43867
- const actionRenderer = message.action && getActionRenderer
43868
- ? getActionRenderer(message.action.implementation)
43869
- : undefined;
43870
- return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-message assistant ${isError ? 'error' : ''}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-message-content", children: [isError && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-error-indicator", children: [jsxRuntimeExports.jsx("span", { className: "error-icon", children: "\u26A0\uFE0F" }), jsxRuntimeExports.jsx("span", { className: "error-text", children: "Error" })] })), jsxRuntimeExports.jsx(Markdown, { remarkPlugins: [remarkGfm], children: aiContent })] }), actionRenderer && message.action && actionRenderer(message, accentColor), showTimestamp && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-message-meta", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-message-timestamp", children: formatTime(message.timestamp) }), enableFeedback && onFeedback && (jsxRuntimeExports.jsx(FeedbackButtons, { messageId: message.id, currentFeedback: message.feedback, onFeedback: onFeedback }))] }))] }));
43924
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-message assistant ${isError ? 'error' : ''}`, children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-message-content", children: jsxRuntimeExports.jsx(Markdown, { remarkPlugins: [remarkGfm], components: {
43925
+ table: ({ children, ...props }) => (jsxRuntimeExports.jsx("div", { className: "table-wrapper", children: jsxRuntimeExports.jsx("div", { className: "table-scroll", children: jsxRuntimeExports.jsx("table", { ...props, children: children }) }) })),
43926
+ }, children: aiContent }) }), showTimestamp && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-message-meta", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-message-timestamp", children: formatTime(message.timestamp) }), enableFeedback && onFeedback && (jsxRuntimeExports.jsx(FeedbackButtons, { messageId: message.id, currentFeedback: message.feedback, onFeedback: onFeedback }))] }))] }));
43871
43927
  }
43872
43928
  // System message rendering
43873
43929
  if (isSystem) {
@@ -43881,35 +43937,86 @@
43881
43937
  return null;
43882
43938
  };
43883
43939
 
43884
- const ToolMessageGroup = ({ messages, getActionRenderer, showToolIndicator = true, accentColor }) => {
43885
- const actionMessages = messages.filter(message => message.action);
43940
+ // Centralized action state logic
43941
+ function isActionComplete(state) {
43942
+ if (!state)
43943
+ return false;
43944
+ const TERMINAL_STATUSES = [
43945
+ 'completed', 'booked', 'scheduled', 'cancelled', 'failed', 'error',
43946
+ 'displaying', 'clicked', 'contacted', 'submitted', 'sent'
43947
+ ];
43948
+ const status = state.status;
43949
+ if (typeof status === 'string' && TERMINAL_STATUSES.includes(status)) {
43950
+ return true;
43951
+ }
43952
+ // For non-halting actions (query_contact_directory, etc.) with results/success
43953
+ if (!status && (state.success !== undefined || state.results !== undefined)) {
43954
+ return true;
43955
+ }
43956
+ return false;
43957
+ }
43958
+ function isActionLoading(message) {
43959
+ if (!message.action)
43960
+ return false;
43961
+ if (message.action.done)
43962
+ return false;
43963
+ if (message.isStreaming)
43964
+ return true;
43965
+ const state = message.action.state;
43966
+ return !isActionComplete(state);
43967
+ }
43968
+ const ToolMessageGroup = ({ messages, getActionRenderer, showToolIndicator = true, accentColor, variant, onActionDismiss, }) => {
43969
+ const visibleMessages = messages.filter(message => !message.action?.hidden);
43970
+ const actionMessages = visibleMessages.filter(message => message.action);
43971
+ // Debug logging
43972
+ console.log('[DEBUG ToolMessageGroup] ========================================');
43973
+ console.log('[DEBUG ToolMessageGroup] Total messages:', messages.length);
43974
+ console.log('[DEBUG ToolMessageGroup] Messages with action:', actionMessages.length);
43975
+ console.log('[DEBUG ToolMessageGroup] hasGetActionRenderer:', !!getActionRenderer);
43976
+ messages.forEach((msg, i) => {
43977
+ console.log(`[DEBUG ToolMessageGroup] Message ${i}:`, {
43978
+ id: msg.id,
43979
+ role: msg.message.role,
43980
+ hasAction: !!msg.action,
43981
+ actionImpl: msg.action?.implementation,
43982
+ toolExecuting: msg.toolExecuting,
43983
+ });
43984
+ });
43985
+ actionMessages.forEach((msg, i) => {
43986
+ const impl = msg.action?.implementation || '';
43987
+ const renderer = getActionRenderer?.(impl);
43988
+ console.log(`[DEBUG ToolMessageGroup] Action ${i}:`, {
43989
+ implementation: impl,
43990
+ hasRenderer: !!renderer,
43991
+ rendererType: renderer ? typeof renderer : 'undefined',
43992
+ state: msg.action?.state,
43993
+ });
43994
+ });
43886
43995
  // If tool indicator is hidden AND there are no action cards to render, don't render anything
43887
- // This prevents empty wrapper divs that cause layout jumping
43888
43996
  if (!showToolIndicator && actionMessages.length === 0) {
43889
43997
  return null;
43890
43998
  }
43891
- const badges = messages.map((message) => {
43999
+ const badges = visibleMessages.map((message) => {
43892
44000
  const toolName = message.toolExecuting || message.message.name || 'Tool';
43893
44001
  const hasError = message.isError || false;
43894
- const actionState = message.action?.state;
43895
- const actionStatus = actionState?.status;
43896
- const terminalStatuses = ['completed', 'booked', 'scheduled', 'failed', 'cancelled', 'displaying', 'clicked'];
43897
- const isTerminalStatus = actionStatus && terminalStatuses.includes(actionStatus);
43898
- const isDone = message.action ? (message.action.done ?? isTerminalStatus ?? false) : !message.isStreaming;
43899
- const isLoading = !isDone;
44002
+ const loading = isActionLoading(message);
43900
44003
  return {
43901
44004
  id: message.id,
43902
44005
  name: toolName,
43903
- status: isLoading ? 'loading' : hasError ? 'error' : 'completed',
44006
+ status: loading ? 'loading' : hasError ? 'error' : 'completed',
43904
44007
  };
43905
44008
  });
43906
44009
  return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-message tool", children: [showToolIndicator && jsxRuntimeExports.jsx(ToolIndicator, { badges: badges }), actionMessages.map((message) => {
43907
- if (!message.action || !getActionRenderer)
44010
+ if (!message.action || !getActionRenderer) {
44011
+ console.log('[ToolMessageGroup] Skipping - no action or renderer:', { hasAction: !!message.action, hasGetRenderer: !!getActionRenderer });
43908
44012
  return null;
44013
+ }
43909
44014
  const renderer = getActionRenderer(message.action.implementation);
43910
- if (!renderer)
44015
+ if (!renderer) {
44016
+ console.log('[ToolMessageGroup] No renderer for:', message.action.implementation);
43911
44017
  return null;
43912
- return (jsxRuntimeExports.jsx("div", { className: "ai-chat-tool-action", children: renderer(message, accentColor) }, `action-${message.id}`));
44018
+ }
44019
+ return (jsxRuntimeExports.jsx("div", { className: "ai-chat-tool-action", children: renderer(message, accentColor, variant, onActionDismiss) }, `action-${message.id}`));
43913
44020
  })] }));
43914
44021
  };
43915
44022
 
@@ -43971,12 +44078,17 @@
43971
44078
  };
43972
44079
 
43973
44080
  const MessageList = (props) => {
43974
- const { messages, isTyping = false, showTypingIndicator = true, showTimestamps = true, showToolCalls = false, enableFeedback = true, welcomeTitle, welcomeMessage, suggestedQuestions, accentColor, onSuggestedQuestionClick, onActionClick, onFeedback, onScrollStateChange, getActionRenderer, } = props;
44081
+ const { messages, isTyping = false, showTypingIndicator = true, showTimestamps = true, showToolCalls = false, enableFeedback = true, welcomeTitle, welcomeMessage, suggestedQuestions, accentColor, onSuggestedQuestionClick, onActionClick, onActionDismiss, onFeedback, onScrollStateChange, getActionRenderer, variant, } = props;
43975
44082
  const containerRef = reactExports.useRef(null);
43976
44083
  const messagesEndRef = reactExports.useRef(null);
43977
44084
  const [showScrollButton, setShowScrollButton] = reactExports.useState(false);
43978
44085
  const prevMessageCountRef = reactExports.useRef(0);
43979
- const hasActiveAction = reactExports.useMemo(() => messages.some(msg => msg.action?.state?.status && !['completed', 'booked', 'failed'].includes(msg.action.state.status)), [messages]);
44086
+ const visibleMessages = reactExports.useMemo(() => messages.filter((message) => !message.action?.hidden), [messages]);
44087
+ const hasActiveAction = reactExports.useMemo(() => {
44088
+ // Find the last tool message and check if its action is still active (not done)
44089
+ const lastToolMsg = [...visibleMessages].reverse().find(msg => msg.message.role === 'tool');
44090
+ return lastToolMsg?.action && lastToolMsg.action.done !== true;
44091
+ }, [visibleMessages]);
43980
44092
  const checkScrollPosition = reactExports.useCallback(() => {
43981
44093
  const c = containerRef.current;
43982
44094
  if (!c)
@@ -43999,7 +44111,7 @@
43999
44111
  const c = containerRef.current;
44000
44112
  if (!c)
44001
44113
  return;
44002
- const count = messages.length;
44114
+ const count = visibleMessages.length;
44003
44115
  const isNew = count > prevMessageCountRef.current;
44004
44116
  prevMessageCountRef.current = count;
44005
44117
  if (count === 0) {
@@ -44010,17 +44122,33 @@
44010
44122
  messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
44011
44123
  }
44012
44124
  checkScrollPosition();
44013
- }, [messages, isTyping, checkScrollPosition]);
44125
+ }, [visibleMessages, isTyping, checkScrollPosition]);
44014
44126
  const groupedMessages = reactExports.useMemo(() => {
44127
+ console.log('[DEBUG MessageList] ========================================');
44128
+ console.log('[DEBUG MessageList] Processing messages:', visibleMessages.length);
44129
+ visibleMessages.forEach((m, i) => {
44130
+ console.log(`[DEBUG MessageList] Message ${i}:`, {
44131
+ id: m.id,
44132
+ role: m.message.role,
44133
+ hasAction: !!m.action,
44134
+ actionImpl: m.action?.implementation,
44135
+ content: (m.message.content || '').substring(0, 50),
44136
+ });
44137
+ });
44015
44138
  const result = [];
44016
44139
  let toolGroup = [];
44017
- const flush = () => { if (toolGroup.length) {
44018
- result.push({ type: 'tool-group', messages: [...toolGroup] });
44019
- toolGroup = [];
44020
- } };
44021
- for (const m of messages) {
44022
- if (m.message.role === 'tool')
44140
+ const flush = () => {
44141
+ if (toolGroup.length) {
44142
+ console.log('[DEBUG MessageList] Flushing tool group with', toolGroup.length, 'messages');
44143
+ result.push({ type: 'tool-group', messages: [...toolGroup] });
44144
+ toolGroup = [];
44145
+ }
44146
+ };
44147
+ for (const m of visibleMessages) {
44148
+ if (m.message.role === 'tool') {
44149
+ console.log('[DEBUG MessageList] Adding to tool group:', m.id);
44023
44150
  toolGroup.push(m);
44151
+ }
44024
44152
  else if (m.message.role === 'user') {
44025
44153
  flush();
44026
44154
  result.push({ type: 'message', message: m });
@@ -44032,6 +44160,7 @@
44032
44160
  flush();
44033
44161
  result.push({ type: 'message', message: m });
44034
44162
  }
44163
+ // Don't flush on empty assistant messages - let tools continue grouping
44035
44164
  }
44036
44165
  else {
44037
44166
  flush();
@@ -44039,18 +44168,27 @@
44039
44168
  }
44040
44169
  }
44041
44170
  flush();
44171
+ console.log('[DEBUG MessageList] Final grouped result:', result.length, 'items');
44172
+ result.forEach((item, i) => {
44173
+ if (item.type === 'tool-group') {
44174
+ console.log(`[DEBUG MessageList] Group ${i}: tool-group with ${item.messages.length} messages`);
44175
+ }
44176
+ else {
44177
+ console.log(`[DEBUG MessageList] Group ${i}: message (${item.message.message.role})`);
44178
+ }
44179
+ });
44042
44180
  return result;
44043
- }, [messages]);
44044
- const hasSuggestions = messages.length === 0 && onSuggestedQuestionClick && suggestedQuestions?.length;
44181
+ }, [visibleMessages]);
44182
+ const hasSuggestions = visibleMessages.length === 0 && onSuggestedQuestionClick && suggestedQuestions?.length;
44045
44183
  const showWelcome = welcomeTitle || welcomeMessage || hasSuggestions;
44046
44184
  return (jsxRuntimeExports.jsxs("div", { ref: containerRef, className: "ai-chat-messages", role: "log", "aria-live": "polite", children: [showWelcome && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-welcome", children: [welcomeTitle && jsxRuntimeExports.jsx("div", { className: "ai-chat-welcome-title", children: welcomeTitle }), welcomeMessage && jsxRuntimeExports.jsx("div", { className: "ai-chat-welcome-text", children: welcomeMessage }), hasSuggestions && jsxRuntimeExports.jsx(SuggestedQuestions, { questions: suggestedQuestions, onQuestionClick: onSuggestedQuestionClick })] })), groupedMessages.map((item, i) => {
44047
44185
  if (item.type === 'tool-group') {
44048
- return jsxRuntimeExports.jsx(ToolMessageGroup, { messages: item.messages, getActionRenderer: getActionRenderer, showToolIndicator: showToolCalls, accentColor: accentColor }, `tg-${i}`);
44186
+ return (jsxRuntimeExports.jsx(ToolMessageGroup, { messages: item.messages, getActionRenderer: getActionRenderer, showToolIndicator: showToolCalls, accentColor: accentColor, variant: variant, onActionDismiss: onActionDismiss }, `tg-${i}`));
44049
44187
  }
44050
44188
  const isLast = i === groupedMessages.length - 1;
44051
44189
  const hasFollowUp = item.message.message.role === 'assistant' && item.message.suggestions?.length && isLast && !isTyping;
44052
44190
  return (jsxRuntimeExports.jsxs(React.Fragment, { children: [jsxRuntimeExports.jsx(Message, { message: item.message, showTimestamp: showTimestamps, onFeedback: onFeedback, getActionRenderer: getActionRenderer, accentColor: accentColor }), hasFollowUp && onSuggestedQuestionClick && jsxRuntimeExports.jsx(FollowUpSuggestions, { suggestions: item.message.suggestions, onQuestionClick: onSuggestedQuestionClick, onActionClick: onActionClick, accentColor: accentColor })] }, item.message.id));
44053
- }), isTyping && showTypingIndicator && !hasActiveAction && messages.length > 0 && jsxRuntimeExports.jsx(TypingIndicator, {}), jsxRuntimeExports.jsx("div", { ref: messagesEndRef })] }));
44191
+ }), isTyping && showTypingIndicator && !hasActiveAction && visibleMessages.length > 0 && jsxRuntimeExports.jsx(TypingIndicator, {}), jsxRuntimeExports.jsx("div", { ref: messagesEndRef })] }));
44054
44192
  };
44055
44193
 
44056
44194
  const ALLOWED_EXTENSIONS = ['.pdf', '.doc', '.docx', '.txt', '.md', '.csv'];
@@ -44064,7 +44202,7 @@
44064
44202
  return (bytes / 1024).toFixed(1) + ' KB';
44065
44203
  return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
44066
44204
  };
44067
- const MessageInput = ({ onSend, placeholder = 'Type your message...', disabled = false, enableFileUpload = false, separateFromChat = true, }) => {
44205
+ const MessageInput = ({ onSend, placeholder = 'Type your message...', disabled = false, enableFileUpload = false, separateFromChat = true, showDataPolicy = true, onDataPolicyClick, }) => {
44068
44206
  const [value, setValue] = reactExports.useState('');
44069
44207
  const [selectedFiles, setSelectedFiles] = reactExports.useState([]);
44070
44208
  const textareaRef = reactExports.useRef(null);
@@ -44099,10 +44237,14 @@
44099
44237
  }
44100
44238
  };
44101
44239
  const canSend = value.trim() || selectedFiles.length > 0;
44102
- return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-input-container ${separateFromChat ? 'separate' : 'integrated'}`, children: [selectedFiles.length > 0 && (jsxRuntimeExports.jsx("div", { className: "ai-chat-file-list", children: selectedFiles.map((file, index) => (jsxRuntimeExports.jsxs("div", { className: "ai-chat-file-item", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-file-extension", children: getFileExtension(file.name) }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-file-info", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-file-name", children: file.name }), jsxRuntimeExports.jsx("span", { className: "ai-chat-file-size", children: formatFileSize(file.size) })] }), jsxRuntimeExports.jsx("button", { className: "ai-chat-file-remove", onClick: () => handleRemoveFile(index), "aria-label": "Remove file", children: jsxRuntimeExports.jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: jsxRuntimeExports.jsx("path", { d: "M18 6L6 18M6 6l12 12" }) }) })] }, index))) })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-input-wrapper", children: [enableFileUpload && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("input", { ref: fileInputRef, type: "file", onChange: handleFileSelect, style: { display: 'none' }, multiple: true, accept: ALLOWED_EXTENSIONS.join(',') }), jsxRuntimeExports.jsx("button", { className: "ai-chat-file-button", onClick: () => fileInputRef.current?.click(), disabled: disabled, "aria-label": "Attach file", children: jsxRuntimeExports.jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: jsxRuntimeExports.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" }) }) })] })), jsxRuntimeExports.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" }), jsxRuntimeExports.jsx("button", { className: `ai-chat-send-button ${canSend ? 'active' : ''}`, onClick: handleSend, disabled: disabled || !canSend, "aria-label": "Send message", children: jsxRuntimeExports.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: [jsxRuntimeExports.jsx("path", { d: "M12 19V5" }), jsxRuntimeExports.jsx("path", { d: "M5 12l7-7 7 7" })] }) })] })] }));
44240
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-input-container ${separateFromChat ? 'separate' : 'integrated'}`, children: [selectedFiles.length > 0 && (jsxRuntimeExports.jsx("div", { className: "ai-chat-file-list", children: selectedFiles.map((file, index) => (jsxRuntimeExports.jsxs("div", { className: "ai-chat-file-item", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-file-extension", children: getFileExtension(file.name) }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-file-info", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-file-name", children: file.name }), jsxRuntimeExports.jsx("span", { className: "ai-chat-file-size", children: formatFileSize(file.size) })] }), jsxRuntimeExports.jsx("button", { className: "ai-chat-file-remove", onClick: () => handleRemoveFile(index), "aria-label": "Remove file", children: jsxRuntimeExports.jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: jsxRuntimeExports.jsx("path", { d: "M18 6L6 18M6 6l12 12" }) }) })] }, index))) })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-input-wrapper", children: [enableFileUpload && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("input", { ref: fileInputRef, type: "file", onChange: handleFileSelect, style: { display: 'none' }, multiple: true, accept: ALLOWED_EXTENSIONS.join(',') }), jsxRuntimeExports.jsx("button", { className: "ai-chat-file-button", onClick: () => fileInputRef.current?.click(), disabled: disabled, "aria-label": "Attach file", children: jsxRuntimeExports.jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: jsxRuntimeExports.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" }) }) })] })), jsxRuntimeExports.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" }), jsxRuntimeExports.jsx("button", { className: `ai-chat-send-button ${canSend ? 'active' : ''}`, onClick: handleSend, disabled: disabled || !canSend, "aria-label": "Send message", children: jsxRuntimeExports.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: [jsxRuntimeExports.jsx("path", { d: "M12 19V5" }), jsxRuntimeExports.jsx("path", { d: "M5 12l7-7 7 7" })] }) })] }), showDataPolicy && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy", children: [jsxRuntimeExports.jsx("span", { children: "AI-generated responses may be inaccurate." }), onDataPolicyClick && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [' ', jsxRuntimeExports.jsx("button", { type: "button", className: "ai-chat-data-policy-link", onClick: onDataPolicyClick, children: "Privacy Notice" })] }))] }))] }));
44103
44241
  };
44104
44242
 
44105
- function groupSlotsByDate(slots) {
44243
+ const CloseButton = ({ onClick, className = "", ariaLabel = "Close", }) => {
44244
+ return (jsxRuntimeExports.jsx("button", { type: "button", className: `ai-chat-action-close-btn ${className}`, onClick: onClick, "aria-label": ariaLabel, children: jsxRuntimeExports.jsx("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "2", children: jsxRuntimeExports.jsx("path", { d: "M1 1L13 13M1 13L13 1" }) }) }));
44245
+ };
44246
+
44247
+ function groupSlotsByDate$1(slots) {
44106
44248
  const grouped = new Map();
44107
44249
  for (const slot of slots) {
44108
44250
  if (!slot || typeof slot !== 'object' || !slot.startTime || typeof slot.startTime !== 'string') {
@@ -44116,7 +44258,7 @@
44116
44258
  }
44117
44259
  return grouped;
44118
44260
  }
44119
- function formatDate(dateStr) {
44261
+ function formatDate$1(dateStr) {
44120
44262
  try {
44121
44263
  const date = new Date(dateStr);
44122
44264
  return new Intl.DateTimeFormat("en-US", {
@@ -44129,19 +44271,19 @@
44129
44271
  return dateStr;
44130
44272
  }
44131
44273
  }
44132
- function CalendarIcon() {
44274
+ function CalendarIcon$1() {
44133
44275
  return (jsxRuntimeExports.jsx("svg", { className: "ai-chat-action-icon", viewBox: "0 0 20 20", fill: "currentColor", children: jsxRuntimeExports.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" }) }));
44134
44276
  }
44135
- function CheckIcon() {
44277
+ function CheckIcon$1() {
44136
44278
  return (jsxRuntimeExports.jsx("svg", { className: "ai-chat-action-icon-success", viewBox: "0 0 20 20", fill: "currentColor", children: jsxRuntimeExports.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" }) }));
44137
44279
  }
44138
- function ExternalLinkIcon$1() {
44280
+ function ExternalLinkIcon$2() {
44139
44281
  return (jsxRuntimeExports.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }), jsxRuntimeExports.jsx("polyline", { points: "15 3 21 3 21 9" }), jsxRuntimeExports.jsx("line", { x1: "10", y1: "14", x2: "21", y2: "3" })] }));
44140
44282
  }
44141
- function Skeleton({ width, height, borderRadius = '4px' }) {
44283
+ function Skeleton$2({ width, height, borderRadius = '4px' }) {
44142
44284
  return (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-skeleton-item", style: { width, height, borderRadius } }));
44143
44285
  }
44144
- function GoogleCalendarCard({ action, onComplete, accentColor, className = '' }) {
44286
+ function GoogleCalendarCard({ action, onComplete, onDismiss, accentColor, className = '' }) {
44145
44287
  const state = action.state;
44146
44288
  const rawSlots = state.availableSlots;
44147
44289
  const availableSlots = Array.isArray(rawSlots)
@@ -44155,13 +44297,12 @@
44155
44297
  : [];
44156
44298
  const allowTopic = state.allowTopic !== false;
44157
44299
  const isBooked = state.status === "booked";
44158
- const slotsByDate = groupSlotsByDate(availableSlots);
44300
+ const slotsByDate = groupSlotsByDate$1(availableSlots);
44159
44301
  const dates = Array.from(slotsByDate.keys()).sort();
44160
44302
  const [selectedDate, setSelectedDate] = reactExports.useState(dates[0] ?? "");
44161
44303
  const [selectedSlot, setSelectedSlot] = reactExports.useState(null);
44162
44304
  const [topic, setTopic] = reactExports.useState("");
44163
44305
  const [error, setError] = reactExports.useState(null);
44164
- const [isSubmitting, setIsSubmitting] = reactExports.useState(false);
44165
44306
  const slotsForSelectedDate = selectedDate ? slotsByDate.get(selectedDate) ?? [] : [];
44166
44307
  const accentStyle = accentColor ? { '--action-accent': accentColor } : {};
44167
44308
  const onConfirm = () => {
@@ -44174,8 +44315,252 @@
44174
44315
  return;
44175
44316
  }
44176
44317
  setError(null);
44318
+ onComplete?.(action.toolCallId, {
44319
+ ...action.state,
44320
+ selectedSlot: {
44321
+ startTime: selectedSlot.startTime,
44322
+ endTime: selectedSlot.endTime,
44323
+ },
44324
+ topic: allowTopic ? topic.trim() : null,
44325
+ });
44326
+ };
44327
+ const handleDismiss = () => {
44328
+ onDismiss?.(action.toolCallId);
44329
+ };
44330
+ // Booked state
44331
+ if (isBooked) {
44332
+ const bookedSlot = state.selectedSlot;
44333
+ const bookedTopic = state.topic;
44334
+ const eventLink = state.bookedEventLink;
44335
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-action-booked ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-action-success-icon-wrapper", children: jsxRuntimeExports.jsx(CheckIcon$1, {}) }), "Appointment Confirmed"] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [bookedTopic && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-detail-box", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-action-label-small", children: "TOPIC" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-action-value-large", children: bookedTopic })] })), bookedSlot && bookedSlot.startTime && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-detail-box", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-action-label-small", children: "TIME" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-action-value-large", children: bookedSlot.displayTime || new Date(bookedSlot.startTime).toLocaleString() })] })), eventLink && (jsxRuntimeExports.jsxs("a", { href: eventLink, target: "_blank", rel: "noopener noreferrer", className: "ai-chat-action-link-button", children: ["View in Google Calendar", jsxRuntimeExports.jsx(ExternalLinkIcon$2, {})] }))] })] }));
44336
+ }
44337
+ // Skeleton loading state - show when waiting for backend after user confirms
44338
+ const isWaitingForBackend = !action.done && state.selectedSlot && !isBooked;
44339
+ if (isWaitingForBackend) {
44340
+ return (jsxRuntimeExports.jsx("div", { className: `ai-chat-action-card ai-chat-action-skeleton ${className}`, style: accentStyle, children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-content", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-header", children: [jsxRuntimeExports.jsx(Skeleton$2, { width: "28px", height: "28px", borderRadius: "50%" }), jsxRuntimeExports.jsx(Skeleton$2, { width: "180px", height: "20px", borderRadius: "4px" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-box", children: [jsxRuntimeExports.jsx(Skeleton$2, { width: "60px", height: "12px", borderRadius: "4px" }), jsxRuntimeExports.jsx(Skeleton$2, { width: "120px", height: "18px", borderRadius: "4px" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-box", children: [jsxRuntimeExports.jsx(Skeleton$2, { width: "50px", height: "12px", borderRadius: "4px" }), jsxRuntimeExports.jsx(Skeleton$2, { width: "200px", height: "18px", borderRadius: "4px" })] }), jsxRuntimeExports.jsx(Skeleton$2, { width: "100%", height: "44px", borderRadius: "999px" })] }) }));
44341
+ }
44342
+ // Booking form
44343
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-action-card--closable ai-chat-google-calendar ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx(CalendarIcon$1, {}), "Schedule an Appointment", onDismiss && (jsxRuntimeExports.jsx(CloseButton, { onClick: handleDismiss, ariaLabel: "Cancel appointment booking" }))] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [allowTopic && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntimeExports.jsx("label", { htmlFor: `topic-${action.toolCallId}`, className: "ai-chat-action-label", children: "Meeting Topic" }), jsxRuntimeExports.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) })] })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntimeExports.jsx("label", { className: "ai-chat-action-label", children: "Select Date" }), jsxRuntimeExports.jsx("div", { className: "ai-chat-action-date-grid", children: dates.slice(0, 7).map((date) => (jsxRuntimeExports.jsx("button", { type: "button", className: `ai-chat-action-date-btn ${selectedDate === date ? "active" : ""}`, onClick: () => {
44344
+ setSelectedDate(date);
44345
+ setSelectedSlot(null);
44346
+ }, children: formatDate$1(date) }, date))) })] }), selectedDate && slotsForSelectedDate.length > 0 && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntimeExports.jsx("label", { className: "ai-chat-action-label", children: "Select Time" }), jsxRuntimeExports.jsx("div", { className: "ai-chat-action-time-grid", children: slotsForSelectedDate.map((slot) => (jsxRuntimeExports.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 && jsxRuntimeExports.jsx("div", { className: "ai-chat-action-error", children: error }), jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button", type: "button", onClick: onConfirm, disabled: !selectedSlot, children: "Confirm Appointment" }), availableSlots.length === 0 && (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-hint", children: "No available time slots found." }))] })] }));
44347
+ }
44348
+
44349
+ function groupSlotsByDate(slots) {
44350
+ const grouped = new Map();
44351
+ for (const slot of slots) {
44352
+ if (!slot || typeof slot !== 'object' || !slot.startTime || typeof slot.startTime !== 'string') {
44353
+ continue;
44354
+ }
44355
+ const date = slot.startTime.slice(0, 10);
44356
+ if (!grouped.has(date)) {
44357
+ grouped.set(date, []);
44358
+ }
44359
+ grouped.get(date).push(slot);
44360
+ }
44361
+ return grouped;
44362
+ }
44363
+ function formatDate(dateStr) {
44364
+ try {
44365
+ const date = new Date(dateStr);
44366
+ return new Intl.DateTimeFormat("en-US", {
44367
+ weekday: "short",
44368
+ month: "short",
44369
+ day: "numeric",
44370
+ }).format(date);
44371
+ }
44372
+ catch {
44373
+ return dateStr;
44374
+ }
44375
+ }
44376
+ function CalendarIcon() {
44377
+ return (jsxRuntimeExports.jsx("svg", { className: "ai-chat-action-icon", viewBox: "0 0 20 20", fill: "currentColor", children: jsxRuntimeExports.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" }) }));
44378
+ }
44379
+ function MailIcon() {
44380
+ return (jsxRuntimeExports.jsxs("svg", { className: "ai-chat-action-icon", viewBox: "0 0 20 20", fill: "currentColor", children: [jsxRuntimeExports.jsx("path", { d: "M2.003 5.884L10 9.882l7.997-3.998A2 2 0 0016 4H4a2 2 0 00-1.997 1.884z" }), jsxRuntimeExports.jsx("path", { d: "M18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z" })] }));
44381
+ }
44382
+ function CheckIcon() {
44383
+ return (jsxRuntimeExports.jsx("svg", { className: "ai-chat-action-icon-success", viewBox: "0 0 20 20", fill: "currentColor", children: jsxRuntimeExports.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" }) }));
44384
+ }
44385
+ function ErrorIcon() {
44386
+ return (jsxRuntimeExports.jsx("svg", { className: "ai-chat-action-icon-error", viewBox: "0 0 20 20", fill: "currentColor", children: jsxRuntimeExports.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" }) }));
44387
+ }
44388
+ function ExternalLinkIcon$1() {
44389
+ return (jsxRuntimeExports.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }), jsxRuntimeExports.jsx("polyline", { points: "15 3 21 3 21 9" }), jsxRuntimeExports.jsx("line", { x1: "10", y1: "14", x2: "21", y2: "3" })] }));
44390
+ }
44391
+ function Skeleton$1({ width, height, borderRadius = '4px' }) {
44392
+ return (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-skeleton-item", style: { width, height, borderRadius } }));
44393
+ }
44394
+ function PinInputGroup$1({ values, onChange, disabled }) {
44395
+ const inputRefs = reactExports.useRef([]);
44396
+ const handleChange = (index, value) => {
44397
+ // Only allow digits
44398
+ const digit = value.replace(/[^0-9]/g, '');
44399
+ const newValues = [...values];
44400
+ newValues[index] = digit.slice(-1);
44401
+ onChange(newValues);
44402
+ // Auto-focus next input
44403
+ if (digit && index < 5) {
44404
+ inputRefs.current[index + 1]?.focus();
44405
+ }
44406
+ };
44407
+ const handleKeyDown = (index, e) => {
44408
+ if (e.key === 'Backspace' && !values[index] && index > 0) {
44409
+ inputRefs.current[index - 1]?.focus();
44410
+ }
44411
+ };
44412
+ const handlePaste = (e) => {
44413
+ e.preventDefault();
44414
+ const pastedData = e.clipboardData.getData('text').replace(/[^0-9]/g, '').slice(0, 6);
44415
+ const newValues = pastedData.split('').concat(Array(6 - pastedData.length).fill(''));
44416
+ onChange(newValues);
44417
+ // Focus the next empty input or the last one
44418
+ const nextIndex = Math.min(pastedData.length, 5);
44419
+ inputRefs.current[nextIndex]?.focus();
44420
+ };
44421
+ return (jsxRuntimeExports.jsx("div", { className: "ai-chat-pin-input-group", children: values.map((value, index) => (jsxRuntimeExports.jsx("input", { ref: (el) => {
44422
+ inputRefs.current[index] = el;
44423
+ }, 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))) }));
44424
+ }
44425
+ function MicrosoftCalendarCard({ action, onComplete, onDismiss, accentColor, className = '' }) {
44426
+ const state = action.state;
44427
+ const phase = state.phase || "awaiting_email";
44428
+ const allowTopic = state.allowTopic !== false;
44429
+ const accentStyle = accentColor ? { '--action-accent': accentColor } : {};
44430
+ const handleDismiss = () => {
44431
+ onDismiss?.(action.toolCallId);
44432
+ };
44433
+ const showCloseButton = Boolean(onDismiss);
44434
+ // Debug: Log state changes
44435
+ const prevStateRef = reactExports.useRef(null);
44436
+ reactExports.useEffect(() => {
44437
+ if (JSON.stringify(prevStateRef.current) !== JSON.stringify(state)) {
44438
+ console.log('[MicrosoftCalendarCard] State updated:', {
44439
+ phase: state.phase,
44440
+ hasError: !!state.errorMessage,
44441
+ error: state.errorMessage,
44442
+ slotsCount: state.availableSlots?.length || 0
44443
+ });
44444
+ prevStateRef.current = state;
44445
+ }
44446
+ }, [state]);
44447
+ // Email phase state
44448
+ const [email, setEmail] = reactExports.useState("");
44449
+ const [emailError, setEmailError] = reactExports.useState(null);
44450
+ // OTP phase state
44451
+ const [otpValues, setOtpValues] = reactExports.useState(Array(6).fill(''));
44452
+ const [otpError, setOtpError] = reactExports.useState(null);
44453
+ // Loading states
44454
+ const [isSubmitting, setIsSubmitting] = reactExports.useState(false);
44455
+ // Reset loading state when phase changes (backend has responded)
44456
+ // Use useEffect for reliable re-rendering
44457
+ reactExports.useEffect(() => {
44458
+ console.log('[MicrosoftCalendarCard] Phase changed to:', phase);
44459
+ setIsSubmitting(false);
44460
+ // Clear errors when transitioning to new phase
44461
+ if (phase === "awaiting_email") {
44462
+ setEmailError(null);
44463
+ setOtpError(null);
44464
+ setSelectionError(null);
44465
+ }
44466
+ else if (phase === "awaiting_otp") {
44467
+ setOtpError(state.errorMessage || null);
44468
+ setEmailError(null);
44469
+ setSelectionError(null);
44470
+ // Clear OTP input for fresh attempt
44471
+ setOtpValues(Array(6).fill(''));
44472
+ }
44473
+ else if (phase === "awaiting_options") {
44474
+ setEmailError(null);
44475
+ setOtpError(null);
44476
+ setSelectionError(null);
44477
+ }
44478
+ else if (phase === "awaiting_booking") {
44479
+ setSelectionError(state.errorMessage || null);
44480
+ setEmailError(null);
44481
+ setOtpError(null);
44482
+ }
44483
+ else if (phase === "booked" || phase === "cancelled" || phase === "error") {
44484
+ setEmailError(null);
44485
+ setOtpError(null);
44486
+ setSelectionError(null);
44487
+ setSelectedId(null); // Reset selection
44488
+ }
44489
+ }, [phase, state.errorMessage]);
44490
+ // Selection phase state
44491
+ const rawSlots = state.availableSlots;
44492
+ const availableSlots = Array.isArray(rawSlots)
44493
+ ? rawSlots.filter((slot) => slot !== null &&
44494
+ slot !== undefined &&
44495
+ typeof slot === "object" &&
44496
+ "startTime" in slot &&
44497
+ "endTime" in slot &&
44498
+ typeof slot.startTime === "string" &&
44499
+ typeof slot.endTime === "string")
44500
+ : [];
44501
+ const slotsByDate = groupSlotsByDate(availableSlots);
44502
+ const dates = Array.from(slotsByDate.keys()).sort();
44503
+ const [selectedDate, setSelectedDate] = reactExports.useState(dates[0] ?? "");
44504
+ const [selectedSlot, setSelectedSlot] = reactExports.useState(null);
44505
+ const [topic, setTopic] = reactExports.useState("");
44506
+ const [selectionError, setSelectionError] = reactExports.useState(null);
44507
+ // Cancellation phase state
44508
+ const [selectedId, setSelectedId] = reactExports.useState(null);
44509
+ const slotsForSelectedDate = selectedDate ? slotsByDate.get(selectedDate) ?? [] : [];
44510
+ // Phase 1: Email Input
44511
+ const handleEmailSubmit = () => {
44512
+ const trimmedEmail = email.trim();
44513
+ if (!trimmedEmail) {
44514
+ setEmailError("Please enter your email address");
44515
+ return;
44516
+ }
44517
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(trimmedEmail)) {
44518
+ setEmailError("Please enter a valid email address");
44519
+ return;
44520
+ }
44521
+ setEmailError(null);
44522
+ setIsSubmitting(true);
44523
+ console.log('[MicrosoftCalendarCard] Submitting email:', trimmedEmail);
44524
+ setTimeout(() => {
44525
+ onComplete?.(action.toolCallId, {
44526
+ ...action.state,
44527
+ email: trimmedEmail,
44528
+ });
44529
+ }, 50);
44530
+ };
44531
+ // Phase 2: OTP Verification
44532
+ const handleOtpSubmit = () => {
44533
+ const otpCode = otpValues.join('');
44534
+ if (otpCode.length !== 6) {
44535
+ setOtpError("Please enter the 6-digit code");
44536
+ return;
44537
+ }
44538
+ setOtpError(null);
44539
+ setIsSubmitting(true);
44540
+ console.log('[MicrosoftCalendarCard] Submitting OTP code');
44541
+ setTimeout(() => {
44542
+ onComplete?.(action.toolCallId, {
44543
+ ...action.state,
44544
+ otpCode,
44545
+ });
44546
+ }, 50);
44547
+ };
44548
+ // Phase 3: Appointment Selection
44549
+ const handleAppointmentConfirm = () => {
44550
+ if (!selectedSlot) {
44551
+ setSelectionError("Please select a time slot");
44552
+ return;
44553
+ }
44554
+ if (allowTopic && !topic.trim()) {
44555
+ setSelectionError("Please enter a meeting topic");
44556
+ return;
44557
+ }
44558
+ setSelectionError(null);
44177
44559
  setIsSubmitting(true);
44178
- // Small delay to ensure UI updates
44560
+ console.log('[MicrosoftCalendarCard] Confirming appointment:', {
44561
+ slot: selectedSlot,
44562
+ topic: topic.trim()
44563
+ });
44179
44564
  setTimeout(() => {
44180
44565
  onComplete?.(action.toolCallId, {
44181
44566
  ...action.state,
@@ -44187,22 +44572,149 @@
44187
44572
  });
44188
44573
  }, 50);
44189
44574
  };
44190
- // Booked state
44191
- if (isBooked) {
44575
+ // Handle "Use different email" button
44576
+ const handleUseDifferentEmail = () => {
44577
+ setEmail("");
44578
+ setEmailError(null);
44579
+ setOtpValues(Array(6).fill(''));
44580
+ setOtpError(null);
44581
+ onComplete?.(action.toolCallId, {
44582
+ phase: "awaiting_email",
44583
+ email: null,
44584
+ otpVerified: false,
44585
+ otpAttempts: 0,
44586
+ availableSlots: [],
44587
+ selectedSlot: null,
44588
+ topic: null,
44589
+ bookedEventId: null,
44590
+ bookedEventLink: null,
44591
+ allowTopic,
44592
+ errorMessage: null,
44593
+ });
44594
+ };
44595
+ // Phase 5: Booked Confirmation
44596
+ if (phase === "booked") {
44192
44597
  const bookedSlot = state.selectedSlot;
44193
44598
  const bookedTopic = state.topic;
44194
44599
  const eventLink = state.bookedEventLink;
44195
- return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-action-booked ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-action-success-icon-wrapper", children: jsxRuntimeExports.jsx(CheckIcon, {}) }), "Appointment Confirmed"] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [bookedTopic && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-detail-box", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-action-label-small", children: "TOPIC" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-action-value-large", children: bookedTopic })] })), bookedSlot && bookedSlot.startTime && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-detail-box", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-action-label-small", children: "TIME" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-action-value-large", children: bookedSlot.displayTime || new Date(bookedSlot.startTime).toLocaleString() })] })), eventLink && (jsxRuntimeExports.jsxs("a", { href: eventLink, target: "_blank", rel: "noopener noreferrer", className: "ai-chat-action-link-button", children: ["View in Google Calendar", jsxRuntimeExports.jsx(ExternalLinkIcon$1, {})] }))] })] }));
44196
- }
44197
- // Skeleton loading state
44600
+ const bookedEmail = state.email;
44601
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-action-booked ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-action-success-icon-wrapper", children: jsxRuntimeExports.jsx(CheckIcon, {}) }), "Appointment Confirmed"] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [bookedTopic && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-detail-box", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-action-label-small", children: "TOPIC" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-action-value-large", children: bookedTopic })] })), bookedSlot && bookedSlot.startTime && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-detail-box", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-action-label-small", children: "TIME" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-action-value-large", children: bookedSlot.displayTime || new Date(bookedSlot.startTime).toLocaleString() })] })), bookedEmail && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-hint", children: ["A calendar invitation has been sent to ", bookedEmail] })), eventLink && (jsxRuntimeExports.jsxs("a", { href: eventLink, target: "_blank", rel: "noopener noreferrer", className: "ai-chat-action-link-button", children: ["View in Outlook Calendar", jsxRuntimeExports.jsx(ExternalLinkIcon$1, {})] }))] })] }));
44602
+ }
44603
+ // Phase 6: Cancelled Confirmation
44604
+ if (phase === "cancelled") {
44605
+ const cancelledSubject = state.cancelledEventSubject;
44606
+ const userEmail = state.email;
44607
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-action-booked ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-action-success-icon-wrapper", children: jsxRuntimeExports.jsx(CheckIcon, {}) }), "Appointment Cancelled"] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [cancelledSubject && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-detail-box", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-action-label-small", children: "CANCELLED" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-action-value-large", children: cancelledSubject })] })), userEmail && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-hint", children: ["A cancellation notice has been sent to ", userEmail] }))] })] }));
44608
+ }
44609
+ // Error State
44610
+ if (phase === "error") {
44611
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-action-error ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx(ErrorIcon, {}), "Error"] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-action-error-message", children: state.errorMessage || "An error occurred. Please try again." }), jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button-secondary", type: "button", onClick: () => {
44612
+ setEmail("");
44613
+ setEmailError(null);
44614
+ setOtpValues(Array(6).fill(''));
44615
+ setOtpError(null);
44616
+ onComplete?.(action.toolCallId, {
44617
+ phase: "awaiting_email",
44618
+ email: null,
44619
+ otpVerified: false,
44620
+ otpAttempts: 0,
44621
+ availableSlots: [],
44622
+ selectedSlot: null,
44623
+ topic: null,
44624
+ bookedEventId: null,
44625
+ bookedEventLink: null,
44626
+ allowTopic,
44627
+ errorMessage: null,
44628
+ });
44629
+ }, children: "Start Over" })] })] }));
44630
+ }
44631
+ // Loading State
44198
44632
  if (isSubmitting) {
44199
- return (jsxRuntimeExports.jsx("div", { className: `ai-chat-action-card ai-chat-action-skeleton ${className}`, style: accentStyle, children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-content", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-header", children: [jsxRuntimeExports.jsx(Skeleton, { width: "28px", height: "28px", borderRadius: "50%" }), jsxRuntimeExports.jsx(Skeleton, { width: "180px", height: "20px", borderRadius: "4px" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-box", children: [jsxRuntimeExports.jsx(Skeleton, { width: "60px", height: "12px", borderRadius: "4px" }), jsxRuntimeExports.jsx(Skeleton, { width: "120px", height: "18px", borderRadius: "4px" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-box", children: [jsxRuntimeExports.jsx(Skeleton, { width: "50px", height: "12px", borderRadius: "4px" }), jsxRuntimeExports.jsx(Skeleton, { width: "200px", height: "18px", borderRadius: "4px" })] }), jsxRuntimeExports.jsx(Skeleton, { width: "100%", height: "44px", borderRadius: "999px" })] }) }));
44200
- }
44201
- // Booking form
44202
- return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx(CalendarIcon, {}), "Schedule an Appointment"] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [allowTopic && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntimeExports.jsx("label", { htmlFor: `topic-${action.toolCallId}`, className: "ai-chat-action-label", children: "Meeting Topic" }), jsxRuntimeExports.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) })] })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntimeExports.jsx("label", { className: "ai-chat-action-label", children: "Select Date" }), jsxRuntimeExports.jsx("div", { className: "ai-chat-action-date-grid", children: dates.slice(0, 7).map((date) => (jsxRuntimeExports.jsx("button", { type: "button", className: `ai-chat-action-date-btn ${selectedDate === date ? "active" : ""}`, onClick: () => {
44203
- setSelectedDate(date);
44204
- setSelectedSlot(null);
44205
- }, children: formatDate(date) }, date))) })] }), selectedDate && slotsForSelectedDate.length > 0 && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntimeExports.jsx("label", { className: "ai-chat-action-label", children: "Select Time" }), jsxRuntimeExports.jsx("div", { className: "ai-chat-action-time-grid", children: slotsForSelectedDate.map((slot) => (jsxRuntimeExports.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 && jsxRuntimeExports.jsx("div", { className: "ai-chat-action-error", children: error }), jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button", type: "button", onClick: onConfirm, disabled: !selectedSlot, children: "Confirm Appointment" }), availableSlots.length === 0 && (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-hint", children: "No available time slots found." }))] })] }));
44633
+ return (jsxRuntimeExports.jsx("div", { className: `ai-chat-action-card ai-chat-action-skeleton ${className}`, style: accentStyle, children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-content", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-header", children: [jsxRuntimeExports.jsx(Skeleton$1, { width: "28px", height: "28px", borderRadius: "50%" }), jsxRuntimeExports.jsx(Skeleton$1, { width: "180px", height: "20px", borderRadius: "4px" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-box", children: [jsxRuntimeExports.jsx(Skeleton$1, { width: "60px", height: "12px", borderRadius: "4px" }), jsxRuntimeExports.jsx(Skeleton$1, { width: "120px", height: "18px", borderRadius: "4px" })] }), jsxRuntimeExports.jsx(Skeleton$1, { width: "100%", height: "44px", borderRadius: "999px" })] }) }));
44634
+ }
44635
+ // Phase 1: Email Input
44636
+ if (phase === "awaiting_email") {
44637
+ const displayError = state.errorMessage || emailError;
44638
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-action-card--closable ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx(CalendarIcon, {}), "Schedule an Appointment", showCloseButton && (jsxRuntimeExports.jsx(CloseButton, { onClick: handleDismiss, ariaLabel: "Cancel appointment booking" }))] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-action-hint", children: "We'll send a verification code to your email" }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntimeExports.jsx("label", { htmlFor: `email-${action.toolCallId}`, className: "ai-chat-action-label", children: "Email Address" }), jsxRuntimeExports.jsx("input", { id: `email-${action.toolCallId}`, type: "email", className: "ai-chat-action-input", placeholder: "your@email.com", value: email, onChange: (e) => {
44639
+ setEmail(e.target.value);
44640
+ setEmailError(null);
44641
+ }, onKeyPress: (e) => {
44642
+ if (e.key === 'Enter') {
44643
+ handleEmailSubmit();
44644
+ }
44645
+ }, autoFocus: true })] }), displayError && (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-error", children: displayError })), jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button", type: "button", onClick: handleEmailSubmit, children: "Continue" })] })] }));
44646
+ }
44647
+ // Phase 2: OTP Input
44648
+ if (phase === "awaiting_otp") {
44649
+ const displayError = state.errorMessage || otpError;
44650
+ const userEmail = state.email;
44651
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-action-card--closable ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx(MailIcon, {}), "Verify Your Email", showCloseButton && (jsxRuntimeExports.jsx(CloseButton, { onClick: handleDismiss, ariaLabel: "Cancel appointment booking" }))] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-hint", children: ["We sent a 6-digit code to ", jsxRuntimeExports.jsx("strong", { children: userEmail })] }), jsxRuntimeExports.jsx(PinInputGroup$1, { values: otpValues, onChange: (newValues) => {
44652
+ setOtpValues(newValues);
44653
+ setOtpError(null);
44654
+ // Auto-submit when all 6 digits are entered
44655
+ if (newValues.every(v => v.length === 1)) {
44656
+ console.log('[MicrosoftCalendarCard] Auto-submitting OTP (all 6 digits entered)');
44657
+ setIsSubmitting(true);
44658
+ const code = newValues.join('');
44659
+ setTimeout(() => {
44660
+ onComplete?.(action.toolCallId, {
44661
+ ...action.state,
44662
+ otpCode: code,
44663
+ });
44664
+ }, 100);
44665
+ }
44666
+ }, disabled: isSubmitting }), displayError && (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-error", children: displayError })), jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button", type: "button", onClick: handleOtpSubmit, disabled: otpValues.join('').length !== 6, children: "Verify Code" }), jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button-secondary", type: "button", onClick: handleUseDifferentEmail, children: "Use different email" })] })] }));
44667
+ }
44668
+ // Phase 3: Options Menu (with inline cancel buttons and confirmation)
44669
+ if (phase === "awaiting_options") {
44670
+ const userAppointments = state.userAppointments || [];
44671
+ const maxAppointments = state.maxAppointmentsPerUser || 3;
44672
+ const appointmentCount = userAppointments.length;
44673
+ const canBook = appointmentCount < maxAppointments;
44674
+ const hasAppointments = appointmentCount > 0;
44675
+ const displayError = state.errorMessage || selectionError;
44676
+ // If confirming cancellation, show confirmation dialog
44677
+ if (selectedId) {
44678
+ const appointmentToCancel = userAppointments.find(appt => appt.id === selectedId);
44679
+ if (!appointmentToCancel) {
44680
+ setSelectedId(null); // Reset if appointment not found
44681
+ }
44682
+ else {
44683
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-action-card--closable ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx(CalendarIcon, {}), "Confirm Cancellation", showCloseButton && (jsxRuntimeExports.jsx(CloseButton, { onClick: handleDismiss, ariaLabel: "Cancel appointment booking" }))] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-action-hint", children: "Are you sure you want to cancel this appointment?" }), jsxRuntimeExports.jsx("div", { className: "ai-chat-action-appointment-item", style: { marginBottom: '16px' }, children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-appointment-info", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-action-appointment-subject", children: appointmentToCancel.subject }), jsxRuntimeExports.jsx("div", { className: "ai-chat-action-appointment-time", children: appointmentToCancel.displayTime })] }) }), displayError && (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-error", children: displayError })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-button-group", children: [jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button", type: "button", onClick: () => {
44684
+ setIsSubmitting(true);
44685
+ onComplete?.(action.toolCallId, {
44686
+ ...action.state,
44687
+ selectedOption: "cancel",
44688
+ selectedAppointmentId: selectedId,
44689
+ });
44690
+ }, disabled: isSubmitting, children: isSubmitting ? 'Cancelling...' : 'Confirm Cancellation' }), jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button-secondary", type: "button", onClick: () => {
44691
+ setSelectedId(null);
44692
+ setSelectionError(null);
44693
+ }, disabled: isSubmitting, children: "Go Back" })] })] })] }));
44694
+ }
44695
+ }
44696
+ // Normal view with inline cancel buttons
44697
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-action-card--closable ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx(CalendarIcon, {}), "Manage Your Appointments", showCloseButton && (jsxRuntimeExports.jsx(CloseButton, { onClick: handleDismiss, ariaLabel: "Cancel appointment booking" }))] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [jsxRuntimeExports.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 && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-appointment-list", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-action-label", children: "Your Upcoming Appointments" }), userAppointments.map((appt) => (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-appointment-item", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-appointment-info", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-action-appointment-subject", children: appt.subject }), jsxRuntimeExports.jsx("div", { className: "ai-chat-action-appointment-time", children: appt.displayTime })] }), jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button-secondary", type: "button", onClick: () => {
44698
+ setSelectedId(appt.id);
44699
+ setSelectionError(null);
44700
+ }, children: "Cancel" })] }, appt.id)))] })), displayError && (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-error", children: displayError })), canBook && (jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button", type: "button", onClick: () => {
44701
+ setIsSubmitting(true);
44702
+ onComplete?.(action.toolCallId, {
44703
+ ...action.state,
44704
+ selectedOption: "book",
44705
+ });
44706
+ }, disabled: isSubmitting, children: isSubmitting ? 'Loading...' : 'Book New Appointment' })), !canBook && !hasAppointments && (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-hint", children: "No appointments found." }))] })] }));
44707
+ }
44708
+ // Phase 4: Appointment Selection (Booking)
44709
+ if (phase === "awaiting_booking") {
44710
+ const displayError = state.errorMessage || selectionError;
44711
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-action-card--closable ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx(CalendarIcon, {}), "Select Appointment Time", showCloseButton && (jsxRuntimeExports.jsx(CloseButton, { onClick: handleDismiss, ariaLabel: "Cancel appointment booking" }))] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [allowTopic && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntimeExports.jsx("label", { htmlFor: `topic-${action.toolCallId}`, className: "ai-chat-action-label", children: "Meeting Topic" }), jsxRuntimeExports.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) })] })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntimeExports.jsx("label", { className: "ai-chat-action-label", children: "Select Date" }), jsxRuntimeExports.jsx("div", { className: "ai-chat-action-date-grid", children: dates.slice(0, 7).map((date) => (jsxRuntimeExports.jsx("button", { type: "button", className: `ai-chat-action-date-btn ${selectedDate === date ? "active" : ""}`, onClick: () => {
44712
+ setSelectedDate(date);
44713
+ setSelectedSlot(null);
44714
+ }, children: formatDate(date) }, date))) })] }), selectedDate && slotsForSelectedDate.length > 0 && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntimeExports.jsx("label", { className: "ai-chat-action-label", children: "Select Time" }), jsxRuntimeExports.jsx("div", { className: "ai-chat-action-time-grid", children: slotsForSelectedDate.map((slot) => (jsxRuntimeExports.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 && (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-error", children: displayError })), jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button", type: "button", onClick: handleAppointmentConfirm, disabled: !selectedSlot, children: "Confirm Appointment" }), availableSlots.length === 0 && (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-hint", children: "No available time slots found." }))] })] }));
44715
+ }
44716
+ // Fallback
44717
+ return null;
44206
44718
  }
44207
44719
 
44208
44720
  function truncate(text, maxLength) {
@@ -44213,17 +44725,30 @@
44213
44725
  function ExternalLinkIcon() {
44214
44726
  return (jsxRuntimeExports.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }), jsxRuntimeExports.jsx("polyline", { points: "15 3 21 3 21 9" }), jsxRuntimeExports.jsx("line", { x1: "10", y1: "14", x2: "21", y2: "3" })] }));
44215
44727
  }
44728
+ function SingleLinkPreview({ link, onLinkClick, accentColor }) {
44729
+ const domain = (() => {
44730
+ if (!link.url)
44731
+ return '';
44732
+ try {
44733
+ return new URL(link.url).hostname.replace('www.', '');
44734
+ }
44735
+ catch {
44736
+ return link.url;
44737
+ }
44738
+ })();
44739
+ const style = accentColor ? { '--action-accent': accentColor } : undefined;
44740
+ return (jsxRuntimeExports.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 && (jsxRuntimeExports.jsx("div", { className: "ai-chat-link-preview__image", children: jsxRuntimeExports.jsx("img", { src: link.image, alt: link.title, onError: (e) => {
44741
+ e.currentTarget.parentElement.style.display = 'none';
44742
+ } }) })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-link-preview__content", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-link-preview__site", children: [link.favicon && (jsxRuntimeExports.jsx("img", { src: link.favicon, alt: "", className: "ai-chat-link-preview__favicon", onError: (e) => {
44743
+ e.currentTarget.style.display = 'none';
44744
+ } })), jsxRuntimeExports.jsx("span", { className: "ai-chat-link-preview__domain", children: link.siteName || domain })] }), jsxRuntimeExports.jsx("h4", { className: "ai-chat-link-preview__title", children: link.title }), link.description && (jsxRuntimeExports.jsx("p", { className: "ai-chat-link-preview__description", children: truncate(link.description, 120) }))] }), jsxRuntimeExports.jsx("div", { className: "ai-chat-link-preview__arrow", children: jsxRuntimeExports.jsx(ExternalLinkIcon, {}) })] }));
44745
+ }
44216
44746
  function LinkPreviewCard({ action, onComplete, accentColor }) {
44217
44747
  const rawState = action.state;
44218
44748
  const hasCompletedRef = reactExports.useRef(false);
44219
44749
  // Provide safe defaults if state is missing
44220
44750
  const state = {
44221
- url: rawState?.url || '',
44222
- title: rawState?.title || 'Link',
44223
- description: rawState?.description,
44224
- image: rawState?.image,
44225
- siteName: rawState?.siteName,
44226
- favicon: rawState?.favicon,
44751
+ links: rawState?.links || [],
44227
44752
  context: rawState?.context,
44228
44753
  status: rawState?.status || 'displaying',
44229
44754
  error: rawState?.error,
@@ -44231,34 +44756,29 @@
44231
44756
  const isError = state.status === 'error';
44232
44757
  // Auto-complete on mount so AI can continue generating text response
44233
44758
  reactExports.useEffect(() => {
44234
- if (!action.done && !hasCompletedRef.current && onComplete && state.url) {
44759
+ if (!action.done && !hasCompletedRef.current && onComplete && state.links.length > 0) {
44235
44760
  hasCompletedRef.current = true;
44236
44761
  // Signal completion immediately - the card is displayed, AI can continue
44237
44762
  onComplete(action.toolCallId, { ...state, status: 'displaying' });
44238
44763
  }
44239
44764
  }, [action.done, action.toolCallId, onComplete, state]);
44240
- const handleClick = () => {
44241
- if (state.url) {
44242
- window.open(state.url, '_blank', 'noopener,noreferrer');
44765
+ const handleLinkClick = (url) => {
44766
+ if (url) {
44767
+ window.open(url, '_blank', 'noopener,noreferrer');
44243
44768
  }
44244
44769
  onComplete?.(action.toolCallId, { ...state, status: 'clicked' });
44245
44770
  };
44246
- const domain = (() => {
44247
- if (!state.url)
44248
- return '';
44249
- try {
44250
- return new URL(state.url).hostname.replace('www.', '');
44251
- }
44252
- catch {
44253
- return state.url;
44254
- }
44255
- })();
44256
- const style = accentColor ? { '--action-accent': accentColor } : undefined;
44257
- return (jsxRuntimeExports.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 && (jsxRuntimeExports.jsx("div", { className: "ai-chat-link-preview__image", children: jsxRuntimeExports.jsx("img", { src: state.image, alt: state.title, onError: (e) => {
44258
- e.currentTarget.parentElement.style.display = 'none';
44259
- } }) })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-link-preview__content", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-link-preview__site", children: [state.favicon && (jsxRuntimeExports.jsx("img", { src: state.favicon, alt: "", className: "ai-chat-link-preview__favicon", onError: (e) => {
44260
- e.currentTarget.style.display = 'none';
44261
- } })), jsxRuntimeExports.jsx("span", { className: "ai-chat-link-preview__domain", children: state.siteName || domain })] }), jsxRuntimeExports.jsx("h4", { className: "ai-chat-link-preview__title", children: state.title }), state.description && (jsxRuntimeExports.jsx("p", { className: "ai-chat-link-preview__description", children: truncate(state.description, 120) })), state.context && (jsxRuntimeExports.jsx("p", { className: "ai-chat-link-preview__context", children: state.context })), isError && state.error && (jsxRuntimeExports.jsx("p", { className: "ai-chat-link-preview__error-text", children: state.error }))] }), jsxRuntimeExports.jsx("div", { className: "ai-chat-link-preview__arrow", children: jsxRuntimeExports.jsx(ExternalLinkIcon, {}) })] }));
44771
+ if (isError) {
44772
+ return (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-card ai-chat-link-preview ai-chat-link-preview--error", children: jsxRuntimeExports.jsx("div", { className: "ai-chat-link-preview__content", children: jsxRuntimeExports.jsx("p", { className: "ai-chat-link-preview__error-text", children: state.error || 'Failed to load preview' }) }) }));
44773
+ }
44774
+ if (state.links.length === 0) {
44775
+ return null;
44776
+ }
44777
+ return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-link-preview-container", children: [state.context && (jsxRuntimeExports.jsx("p", { className: "ai-chat-link-preview__context", style: { marginBottom: '8px', fontSize: '0.9em', color: 'var(--ai-chat-fg-muted)' }, children: state.context })), jsxRuntimeExports.jsx("div", { className: "ai-chat-link-preview-grid", style: {
44778
+ display: 'grid',
44779
+ gridTemplateColumns: state.links.length === 1 ? '1fr' : state.links.length === 2 ? 'repeat(2, 1fr)' : 'repeat(3, 1fr)',
44780
+ gap: '12px',
44781
+ }, children: state.links.map((link, index) => (jsxRuntimeExports.jsx(SingleLinkPreview, { link: link, onLinkClick: () => handleLinkClick(link.url), accentColor: accentColor }, index))) })] }));
44262
44782
  }
44263
44783
 
44264
44784
  function PlayIcon() {
@@ -44324,7 +44844,7 @@
44324
44844
  return src;
44325
44845
  }
44326
44846
  };
44327
- return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-video-player", style: style, children: [state.title && (jsxRuntimeExports.jsx("div", { className: "ai-chat-video-player__header", children: jsxRuntimeExports.jsx("span", { className: "ai-chat-video-player__title", children: state.title }) })), jsxRuntimeExports.jsx("div", { className: "ai-chat-video-player__container", children: isError ? (jsxRuntimeExports.jsx("div", { className: "ai-chat-video-player__error", children: jsxRuntimeExports.jsx("span", { children: state.error || 'Could not load video' }) })) : !isPlaying && state.thumbnailUrl ? (jsxRuntimeExports.jsxs("div", { className: "ai-chat-video-player__thumbnail", onClick: handlePlay, children: [jsxRuntimeExports.jsx("img", { src: state.thumbnailUrl, alt: state.title || 'Video thumbnail' }), jsxRuntimeExports.jsx("button", { className: "ai-chat-video-player__play-btn", "aria-label": "Play video", children: jsxRuntimeExports.jsx(PlayIcon, {}) }), jsxRuntimeExports.jsx("div", { className: "ai-chat-video-player__provider-badge", children: getProviderLabel(state.provider) })] })) : !isPlaying ? (jsxRuntimeExports.jsxs("div", { className: "ai-chat-video-player__placeholder", onClick: handlePlay, children: [jsxRuntimeExports.jsx("button", { className: "ai-chat-video-player__play-btn", "aria-label": "Play video", children: jsxRuntimeExports.jsx(PlayIcon, {}) }), jsxRuntimeExports.jsx("span", { className: "ai-chat-video-player__click-text", children: "Click to play" }), jsxRuntimeExports.jsx("div", { className: "ai-chat-video-player__provider-badge", children: getProviderLabel(state.provider) })] })) : state.provider === 'direct' ? (jsxRuntimeExports.jsx("video", { src: state.embedUrl, controls: true, autoPlay: true, className: "ai-chat-video-player__video" })) : (jsxRuntimeExports.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 && (jsxRuntimeExports.jsx("div", { className: "ai-chat-video-player__context", children: state.context }))] }));
44847
+ return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-card ai-chat-video-player", style: style, children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-video-player__container", children: isError ? (jsxRuntimeExports.jsx("div", { className: "ai-chat-video-player__error", children: jsxRuntimeExports.jsx("span", { children: state.error || 'Could not load video' }) })) : !isPlaying && state.thumbnailUrl ? (jsxRuntimeExports.jsxs("div", { className: "ai-chat-video-player__thumbnail", onClick: handlePlay, children: [jsxRuntimeExports.jsx("img", { src: state.thumbnailUrl, alt: state.title || 'Video thumbnail' }), jsxRuntimeExports.jsx("button", { className: "ai-chat-video-player__play-btn", "aria-label": "Play video", children: jsxRuntimeExports.jsx(PlayIcon, {}) }), jsxRuntimeExports.jsx("div", { className: "ai-chat-video-player__provider-badge", children: getProviderLabel(state.provider) })] })) : !isPlaying ? (jsxRuntimeExports.jsxs("div", { className: "ai-chat-video-player__placeholder", onClick: handlePlay, children: [jsxRuntimeExports.jsx("button", { className: "ai-chat-video-player__play-btn", "aria-label": "Play video", children: jsxRuntimeExports.jsx(PlayIcon, {}) }), jsxRuntimeExports.jsx("span", { className: "ai-chat-video-player__click-text", children: "Click to play" }), jsxRuntimeExports.jsx("div", { className: "ai-chat-video-player__provider-badge", children: getProviderLabel(state.provider) })] })) : state.provider === 'direct' ? (jsxRuntimeExports.jsx("video", { src: state.embedUrl, controls: true, autoPlay: true, className: "ai-chat-video-player__video" })) : (jsxRuntimeExports.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 && (jsxRuntimeExports.jsx("div", { className: "ai-chat-video-player__context", children: state.context }))] }));
44328
44848
  }
44329
44849
 
44330
44850
  function MapPinIcon() {
@@ -44385,7 +44905,9 @@
44385
44905
  }
44386
44906
  };
44387
44907
  const style = accentColor ? { '--action-accent': accentColor } : undefined;
44388
- return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-location-card ${compact ? 'ai-chat-location-card--compact' : ''}`, style: style, children: [showMap && !compact && settings.showMap !== false && (jsxRuntimeExports.jsx("div", { className: "ai-chat-location-card__map", style: { height: mapHeight }, children: jsxRuntimeExports.jsx("iframe", { src: getMapEmbedUrl(), allowFullScreen: true, loading: "lazy", referrerPolicy: "no-referrer-when-downgrade", title: `Map of ${location.name}` }) })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-location-card__content", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-location-card__header", children: [jsxRuntimeExports.jsx("h4", { className: "ai-chat-location-card__name", children: location.name }), location.type && (jsxRuntimeExports.jsx("span", { className: "ai-chat-location-card__type", children: location.type })), openStatus !== null && (jsxRuntimeExports.jsx("span", { className: `ai-chat-location-card__status ai-chat-location-card__status--${openStatus ? 'open' : 'closed'}`, children: openStatus ? 'Open' : 'Closed' }))] }), jsxRuntimeExports.jsxs("p", { className: "ai-chat-location-card__address", children: [jsxRuntimeExports.jsx(MapPinIcon, {}), location.address] }), location.description && (jsxRuntimeExports.jsx("p", { className: "ai-chat-location-card__description", children: location.description })), settings.showHours !== false && location.hours && location.hours.length > 0 && (jsxRuntimeExports.jsx(HoursDisplay, { hours: location.hours, compact: compact })), settings.showPhone !== false && location.phone && (jsxRuntimeExports.jsxs("button", { type: "button", className: "ai-chat-location-card__phone", onClick: handleCall, children: [jsxRuntimeExports.jsx(PhoneIcon, {}), location.phone] })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-location-card__actions", children: [settings.showDirectionsButton !== false && (jsxRuntimeExports.jsxs("button", { type: "button", className: "ai-chat-location-card__button", style: accentColor ? { backgroundColor: accentColor } : undefined, onClick: onDirections, children: [jsxRuntimeExports.jsx(NavigationIcon, {}), compact ? 'Directions' : 'Get Directions'] })), !compact && location.website && (jsxRuntimeExports.jsxs("a", { href: location.website, target: "_blank", rel: "noopener noreferrer", className: "ai-chat-location-card__link", children: [jsxRuntimeExports.jsx(GlobeIcon, {}), "Website"] }))] })] })] }));
44908
+ // Use smaller map height in compact mode
44909
+ const effectiveMapHeight = compact ? Math.min(mapHeight, 140) : mapHeight;
44910
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-location-card ${compact ? 'ai-chat-location-card--compact' : ''}`, style: style, children: [showMap && settings.showMap !== false && (jsxRuntimeExports.jsx("div", { className: "ai-chat-location-card__map", style: { height: effectiveMapHeight }, children: jsxRuntimeExports.jsx("iframe", { src: getMapEmbedUrl(), allowFullScreen: true, loading: "lazy", referrerPolicy: "no-referrer-when-downgrade", title: `Map of ${location.name}` }) })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-location-card__content", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-location-card__header", children: [jsxRuntimeExports.jsx("h4", { className: "ai-chat-location-card__name", children: location.name }), location.type && (jsxRuntimeExports.jsx("span", { className: "ai-chat-location-card__type", children: location.type })), openStatus !== null && (jsxRuntimeExports.jsx("span", { className: `ai-chat-location-card__status ai-chat-location-card__status--${openStatus ? 'open' : 'closed'}`, children: openStatus ? 'Open' : 'Closed' }))] }), jsxRuntimeExports.jsxs("p", { className: "ai-chat-location-card__address", children: [jsxRuntimeExports.jsx(MapPinIcon, {}), location.address] }), location.description && (jsxRuntimeExports.jsx("p", { className: "ai-chat-location-card__description", children: location.description })), settings.showHours !== false && location.hours && location.hours.length > 0 && (jsxRuntimeExports.jsx(HoursDisplay, { hours: location.hours, compact: compact })), settings.showPhone !== false && location.phone && (jsxRuntimeExports.jsxs("button", { type: "button", className: "ai-chat-location-card__phone", onClick: handleCall, children: [jsxRuntimeExports.jsx(PhoneIcon, {}), location.phone] })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-location-card__actions", children: [settings.showDirectionsButton !== false && (jsxRuntimeExports.jsxs("button", { type: "button", className: "ai-chat-location-card__button", style: accentColor ? { backgroundColor: accentColor } : undefined, onClick: onDirections, children: [jsxRuntimeExports.jsx(NavigationIcon, {}), compact ? 'Directions' : 'Get Directions'] })), !compact && location.website && (jsxRuntimeExports.jsxs("a", { href: location.website, target: "_blank", rel: "noopener noreferrer", className: "ai-chat-location-card__link", children: [jsxRuntimeExports.jsx(GlobeIcon, {}), "Website"] }))] })] })] }));
44389
44911
  }
44390
44912
  function LocationCard({ action, onComplete, accentColor, maxColumns = 3 }) {
44391
44913
  const rawState = action.state;
@@ -44419,40 +44941,443 @@
44419
44941
  if (isSingleLocation) {
44420
44942
  return (jsxRuntimeExports.jsx(LocationItem, { location: locations[0], settings: settings, accentColor: accentColor, onDirections: () => handleDirections(locations[0]), showMap: true }));
44421
44943
  }
44422
- return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-location-card-list ai-chat-location-card-list--${layout}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-location-card-list__header", children: [jsxRuntimeExports.jsx(MapPinIcon, {}), jsxRuntimeExports.jsxs("span", { children: [locations.length, " Locations"] })] }), layout === 'stack' && (jsxRuntimeExports.jsx("div", { className: "ai-chat-location-card-list__stack", style: {
44423
- gridTemplateColumns: `repeat(${stackColumns}, minmax(0, 1fr))`,
44424
- }, children: locations.map((location) => (jsxRuntimeExports.jsx(LocationItem, { location: location, settings: settings, accentColor: accentColor, onDirections: () => handleDirections(location), showMap: settings.showMap !== false, compact: locations.length > 2 }, location.id))) })), layout === 'grid' && (jsxRuntimeExports.jsx("div", { className: "ai-chat-location-card-list__grid", children: locations.map((location) => (jsxRuntimeExports.jsx(LocationItem, { location: location, settings: settings, accentColor: accentColor, onDirections: () => handleDirections(location), showMap: false, compact: true }, location.id))) })), layout === 'carousel' && (jsxRuntimeExports.jsx("div", { className: "ai-chat-location-card-list__carousel", children: locations.map((location) => (jsxRuntimeExports.jsx(LocationItem, { location: location, settings: settings, accentColor: accentColor, onDirections: () => handleDirections(location), showMap: true, compact: false }, location.id))) }))] }));
44944
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-location-card-list ai-chat-location-card-list--${layout}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-location-card-list__header", children: [jsxRuntimeExports.jsx(MapPinIcon, {}), jsxRuntimeExports.jsxs("span", { children: [locations.length, " Locations"] })] }), layout === 'stack' && (jsxRuntimeExports.jsx("div", { className: `ai-chat-location-card-list__stack ai-chat-location-card-list__stack--cols-${stackColumns}`, children: locations.map((location) => (jsxRuntimeExports.jsx(LocationItem, { location: location, settings: settings, accentColor: accentColor, onDirections: () => handleDirections(location), showMap: settings.showMap !== false, compact: locations.length > 2 }, location.id))) })), layout === 'grid' && (jsxRuntimeExports.jsx("div", { className: "ai-chat-location-card-list__grid", children: locations.map((location) => (jsxRuntimeExports.jsx(LocationItem, { location: location, settings: settings, accentColor: accentColor, onDirections: () => handleDirections(location), showMap: false, compact: true }, location.id))) })), layout === 'carousel' && (jsxRuntimeExports.jsx("div", { className: "ai-chat-location-card-list__carousel", children: locations.map((location) => (jsxRuntimeExports.jsx(LocationItem, { location: location, settings: settings, accentColor: accentColor, onDirections: () => handleDirections(location), showMap: true, compact: false }, location.id))) }))] }));
44425
44945
  }
44426
44946
 
44427
- const pendingResolvers = new Map();
44428
- const resumeCallbacks = new Map();
44429
- const frontendActionHandlers = {};
44430
- const actionRenderers = {};
44431
- function getFrontendActionHandler(implementation) {
44432
- return frontendActionHandlers[implementation];
44947
+ function UsersIcon() {
44948
+ return (jsxRuntimeExports.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" }), jsxRuntimeExports.jsx("circle", { cx: "9", cy: "7", r: "4" }), jsxRuntimeExports.jsx("path", { d: "M22 21v-2a4 4 0 0 0-3-3.87" }), jsxRuntimeExports.jsx("path", { d: "M16 3.13a4 4 0 0 1 0 7.75" })] }));
44433
44949
  }
44434
- function getActionRenderer(implementation) {
44435
- return actionRenderers[implementation];
44436
- }
44437
- function getActionPrompt(implementation) {
44438
- if (implementation === "google-calendar-appointment") {
44439
- return "Select a date to continue.";
44950
+ const AVATAR_COLORS = [
44951
+ { bg: '#E8F5E9', text: '#2E7D32' }, // Green
44952
+ { bg: '#E3F2FD', text: '#1565C0' }, // Blue
44953
+ { bg: '#FFF3E0', text: '#E65100' }, // Orange
44954
+ { bg: '#F3E5F5', text: '#7B1FA2' }, // Purple
44955
+ { bg: '#FFEBEE', text: '#C62828' }, // Red
44956
+ { bg: '#E0F7FA', text: '#00838F' }, // Cyan
44957
+ { bg: '#FFF8E1', text: '#F9A825' }, // Amber
44958
+ { bg: '#FCE4EC', text: '#AD1457' }, // Pink
44959
+ ];
44960
+ function getInitials(name) {
44961
+ const parts = name.trim().split(/\s+/);
44962
+ if (parts.length === 1) {
44963
+ return parts[0].substring(0, 2).toUpperCase();
44440
44964
  }
44441
- return "Action input required.";
44442
- }
44443
- function waitForActionState(toolCallId) {
44444
- return new Promise((resolve) => {
44445
- pendingResolvers.set(toolCallId, resolve);
44446
- });
44965
+ return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
44447
44966
  }
44448
- function resolveActionState(toolCallId, state) {
44449
- const resolver = pendingResolvers.get(toolCallId);
44450
- if (resolver) {
44451
- pendingResolvers.delete(toolCallId);
44452
- resolver(state);
44453
- return;
44967
+ function getColorFromName(name) {
44968
+ let hash = 0;
44969
+ for (let i = 0; i < name.length; i++) {
44970
+ hash = name.charCodeAt(i) + ((hash << 5) - hash);
44454
44971
  }
44455
- const resumeCallback = resumeCallbacks.get(toolCallId);
44972
+ return AVATAR_COLORS[Math.abs(hash) % AVATAR_COLORS.length];
44973
+ }
44974
+ function ContactItem({ contact, settings, accentColor, onEmail, onPhone, compact = false, layout = 'vertical', }) {
44975
+ const style = accentColor ? { '--action-accent': accentColor } : undefined;
44976
+ const layoutClass = layout === 'horizontal'
44977
+ ? 'ai-chat-contact-card--horizontal'
44978
+ : 'ai-chat-contact-card--vertical';
44979
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-contact-card ${layoutClass} ${compact ? 'ai-chat-contact-card--compact' : ''}`, style: style, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-contact-card__image-section", children: [contact.profilePictureUrl ? (jsxRuntimeExports.jsx("img", { src: contact.profilePictureUrl, alt: contact.name, className: "ai-chat-contact-card__image", onError: (e) => {
44980
+ e.currentTarget.style.display = 'none';
44981
+ const placeholder = e.currentTarget.parentElement?.querySelector('.ai-chat-contact-card__initials');
44982
+ if (placeholder) {
44983
+ placeholder.style.display = 'flex';
44984
+ }
44985
+ } })) : null, (() => {
44986
+ const colors = getColorFromName(contact.name);
44987
+ return (jsxRuntimeExports.jsx("div", { className: "ai-chat-contact-card__initials", style: {
44988
+ display: contact.profilePictureUrl ? 'none' : 'flex',
44989
+ backgroundColor: colors.bg,
44990
+ color: colors.text,
44991
+ }, children: getInitials(contact.name) }));
44992
+ })()] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-contact-card__info", children: [jsxRuntimeExports.jsx("h4", { className: "ai-chat-contact-card__name", children: contact.name }), settings.showRole !== false && contact.role && (jsxRuntimeExports.jsx("p", { className: "ai-chat-contact-card__role", children: contact.role })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-contact-card__details", children: [settings.showEmail !== false && contact.email && (jsxRuntimeExports.jsx("a", { href: `mailto:${contact.email}`, className: "ai-chat-contact-card__detail", onClick: onEmail, children: contact.email })), settings.showPhone !== false && contact.phone && (jsxRuntimeExports.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 && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-contact-card__responsibilities", children: [contact.responsibilities.slice(0, 3).map((resp, idx) => (jsxRuntimeExports.jsx("span", { className: "ai-chat-contact-card__responsibility-tag", children: resp }, idx))), contact.responsibilities.length > 3 && (jsxRuntimeExports.jsxs("span", { className: "ai-chat-contact-card__responsibility-more", children: ["+", contact.responsibilities.length - 3, " more"] }))] }))] })] }));
44993
+ }
44994
+ function ContactCard({ action, onComplete, accentColor, maxColumns = 3 }) {
44995
+ const rawState = action.state;
44996
+ const hasCompletedRef = reactExports.useRef(false);
44997
+ const state = {
44998
+ contacts: rawState?.contacts || [],
44999
+ settings: rawState?.settings || {},
45000
+ query: rawState?.query,
45001
+ status: rawState?.status || 'displaying',
45002
+ };
45003
+ const { contacts, settings } = state;
45004
+ const isSingleContact = contacts.length === 1;
45005
+ const stackColumns = Math.min(Math.max(contacts.length, 1), maxColumns);
45006
+ reactExports.useEffect(() => {
45007
+ if (!action.done && !hasCompletedRef.current && onComplete) {
45008
+ hasCompletedRef.current = true;
45009
+ onComplete(action.toolCallId, { ...state, status: 'displaying' });
45010
+ }
45011
+ }, [action.done, action.toolCallId, onComplete, state]);
45012
+ const handleContact = () => {
45013
+ onComplete?.(action.toolCallId, { ...state, status: 'contacted' });
45014
+ };
45015
+ if (contacts.length === 0) {
45016
+ return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-contact-card ai-chat-contact-card--empty", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-contact-card__empty-icon", children: jsxRuntimeExports.jsx(UsersIcon, {}) }), jsxRuntimeExports.jsxs("p", { className: "ai-chat-contact-card__empty-text", children: ["No contacts found", state.query ? ` for "${state.query}"` : ''] })] }));
45017
+ }
45018
+ if (isSingleContact) {
45019
+ return (jsxRuntimeExports.jsx(ContactItem, { contact: contacts[0], settings: settings, accentColor: accentColor, onEmail: handleContact, onPhone: handleContact, layout: settings.layout || 'horizontal' }));
45020
+ }
45021
+ const isWidget = maxColumns === 1;
45022
+ const stackClassName = isWidget
45023
+ ? 'ai-chat-contact-card-list__stack ai-chat-contact-card-list__stack--widget'
45024
+ : 'ai-chat-contact-card-list__stack';
45025
+ return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-contact-card-list", style: { containerType: 'inline-size' }, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-contact-card-list__header", children: [jsxRuntimeExports.jsx(UsersIcon, {}), jsxRuntimeExports.jsxs("span", { children: [contacts.length, " Contacts"] })] }), jsxRuntimeExports.jsx("div", { className: stackClassName, style: isWidget ? undefined : {
45026
+ gridTemplateColumns: `repeat(${stackColumns}, minmax(0, 1fr))`,
45027
+ }, children: contacts.map((contact) => (jsxRuntimeExports.jsx(ContactItem, { contact: contact, settings: settings, accentColor: accentColor, onEmail: handleContact, onPhone: handleContact, compact: true, layout: settings.layout || 'vertical' }, contact.id))) })] }));
45028
+ }
45029
+
45030
+ function FormCard({ action, onComplete, onDismiss, accentColor }) {
45031
+ const state = action.state;
45032
+ const [currentStep, setCurrentStep] = reactExports.useState(0);
45033
+ const [answers, setAnswers] = reactExports.useState({});
45034
+ const [isSubmitting, setIsSubmitting] = reactExports.useState(false);
45035
+ const questions = state.questions || [];
45036
+ const currentQuestion = questions[currentStep];
45037
+ const totalQuestions = questions.length;
45038
+ const handleAnswerChange = (questionId, value) => {
45039
+ setAnswers((prev) => ({ ...prev, [questionId]: value }));
45040
+ };
45041
+ const handleNext = () => {
45042
+ if (currentStep < totalQuestions - 1) {
45043
+ setCurrentStep((prev) => prev + 1);
45044
+ }
45045
+ };
45046
+ const handlePrev = () => {
45047
+ if (currentStep > 0) {
45048
+ setCurrentStep((prev) => prev - 1);
45049
+ }
45050
+ };
45051
+ const handleSubmit = () => {
45052
+ if (!onComplete)
45053
+ return;
45054
+ setIsSubmitting(true);
45055
+ const formattedAnswers = Object.entries(answers).map(([questionId, value]) => ({
45056
+ questionId,
45057
+ value,
45058
+ }));
45059
+ onComplete(action.toolCallId, {
45060
+ ...state,
45061
+ status: 'submitted',
45062
+ answers: formattedAnswers,
45063
+ });
45064
+ };
45065
+ const handleSkip = () => {
45066
+ if (!onComplete || !state.settings.allowSkip)
45067
+ return;
45068
+ onComplete(action.toolCallId, {
45069
+ ...state,
45070
+ status: 'skipped',
45071
+ });
45072
+ };
45073
+ const isCurrentAnswered = () => {
45074
+ if (!currentQuestion)
45075
+ return false;
45076
+ const answer = answers[currentQuestion.id];
45077
+ if (!answer)
45078
+ return !currentQuestion.required;
45079
+ if (Array.isArray(answer))
45080
+ return answer.length > 0 || !currentQuestion.required;
45081
+ return answer.trim() !== '' || !currentQuestion.required;
45082
+ };
45083
+ const canSubmit = () => {
45084
+ return questions.every((q) => {
45085
+ const answer = answers[q.id];
45086
+ if (!q.required)
45087
+ return true;
45088
+ if (!answer)
45089
+ return false;
45090
+ if (Array.isArray(answer))
45091
+ return answer.length > 0;
45092
+ return answer.trim() !== '';
45093
+ });
45094
+ };
45095
+ const handleDismiss = () => {
45096
+ onDismiss?.(action.toolCallId);
45097
+ };
45098
+ // Error state
45099
+ if (state.status === 'error') {
45100
+ return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card ai-chat-form-card--error", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__icon", children: "\u26A0\uFE0F" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__title", children: "Form Error" })] }), jsxRuntimeExports.jsx("p", { className: "ai-chat-form-card__error", children: state.error || 'Could not load form' })] }));
45101
+ }
45102
+ // Submitted state
45103
+ if (state.status === 'submitted' || action.done) {
45104
+ return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card ai-chat-form-card--submitted", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__icon", children: "\u2713" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__title", children: state.title })] }), jsxRuntimeExports.jsx("p", { className: "ai-chat-form-card__success", children: state.settings.successMessage || 'Thank you for your response!' })] }));
45105
+ }
45106
+ // Skipped state
45107
+ if (state.status === 'skipped') {
45108
+ return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card ai-chat-form-card--skipped", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__icon", children: "\u21B7" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__title", children: state.title })] }), jsxRuntimeExports.jsx("p", { className: "ai-chat-form-card__skipped-text", children: "Form skipped" })] }));
45109
+ }
45110
+ // No questions
45111
+ if (totalQuestions === 0) {
45112
+ return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card ai-chat-form-card--empty", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__icon", children: "\uD83D\uDCCB" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__title", children: state.title })] }), jsxRuntimeExports.jsx("p", { className: "ai-chat-form-card__empty-text", children: "This form has no questions." })] }));
45113
+ }
45114
+ const showCloseButton = state.status === "displaying" && !action.done && Boolean(onDismiss);
45115
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-form-card${showCloseButton ? " ai-chat-form-card--closable" : ""}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__icon", children: "\uD83D\uDCCB" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__title", children: state.title }), showCloseButton && (jsxRuntimeExports.jsx(CloseButton, { onClick: handleDismiss, ariaLabel: "Close form" }))] }), state.description && (jsxRuntimeExports.jsx("p", { className: "ai-chat-form-card__description", children: state.description })), state.context && (jsxRuntimeExports.jsx("p", { className: "ai-chat-form-card__context", children: state.context })), state.settings.showProgress && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__progress", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-form-card__progress-bar", style: {
45116
+ width: `${((currentStep + 1) / totalQuestions) * 100}%`,
45117
+ backgroundColor: accentColor || 'var(--ai-chat-accent-color, #3b82f6)',
45118
+ } }), jsxRuntimeExports.jsxs("span", { className: "ai-chat-form-card__progress-text", children: [currentStep + 1, " of ", totalQuestions] })] })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__question", children: [jsxRuntimeExports.jsxs("p", { className: "ai-chat-form-card__question-text", children: [currentQuestion.text, currentQuestion.required && jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__required", children: "*" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__answer", children: [currentQuestion.type === 'text' && (jsxRuntimeExports.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 && (jsxRuntimeExports.jsx("div", { className: "ai-chat-form-card__options", children: currentQuestion.options.map((option) => (jsxRuntimeExports.jsxs("label", { className: "ai-chat-form-card__option", children: [jsxRuntimeExports.jsx("input", { type: "radio", name: currentQuestion.id, value: option.value, checked: answers[currentQuestion.id] === option.value, onChange: () => handleAnswerChange(currentQuestion.id, option.value) }), jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__option-text", children: option.text })] }, option.id))) })), currentQuestion.type === 'multiple_choice' && currentQuestion.options && (jsxRuntimeExports.jsx("div", { className: "ai-chat-form-card__options", children: currentQuestion.options.map((option) => {
45119
+ const currentAnswers = answers[currentQuestion.id] || [];
45120
+ const isChecked = currentAnswers.includes(option.value);
45121
+ return (jsxRuntimeExports.jsxs("label", { className: "ai-chat-form-card__option", children: [jsxRuntimeExports.jsx("input", { type: "checkbox", value: option.value, checked: isChecked, onChange: () => {
45122
+ const newAnswers = isChecked
45123
+ ? currentAnswers.filter((v) => v !== option.value)
45124
+ : [...currentAnswers, option.value];
45125
+ handleAnswerChange(currentQuestion.id, newAnswers);
45126
+ } }), jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__option-text", children: option.text })] }, option.id));
45127
+ }) })), currentQuestion.type === 'rating' && (jsxRuntimeExports.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) => (jsxRuntimeExports.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: {
45128
+ borderColor: answers[currentQuestion.id] === String(rating)
45129
+ ? (accentColor || 'var(--ai-chat-accent-color, #3b82f6)')
45130
+ : undefined,
45131
+ backgroundColor: answers[currentQuestion.id] === String(rating)
45132
+ ? (accentColor || 'var(--ai-chat-accent-color, #3b82f6)')
45133
+ : undefined,
45134
+ }, children: rating }, rating))) }))] })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__actions", children: [currentStep > 0 && (jsxRuntimeExports.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 && (jsxRuntimeExports.jsx("button", { type: "button", className: "ai-chat-form-card__btn ai-chat-form-card__btn--ghost", onClick: handleSkip, children: "Skip" })), jsxRuntimeExports.jsx("div", { className: "ai-chat-form-card__actions-spacer" }), currentStep < totalQuestions - 1 ? (jsxRuntimeExports.jsx("button", { type: "button", className: "ai-chat-form-card__btn ai-chat-form-card__btn--primary", onClick: handleNext, disabled: !isCurrentAnswered(), style: {
45135
+ backgroundColor: accentColor || 'var(--ai-chat-accent-color, #3b82f6)',
45136
+ }, children: "Next" })) : (jsxRuntimeExports.jsx("button", { type: "button", className: "ai-chat-form-card__btn ai-chat-form-card__btn--primary", onClick: handleSubmit, disabled: !canSubmit() || isSubmitting, style: {
45137
+ backgroundColor: accentColor || 'var(--ai-chat-accent-color, #3b82f6)',
45138
+ }, children: isSubmitting ? 'Submitting...' : (state.settings.submitButtonText || 'Submit') }))] })] }));
45139
+ }
45140
+
45141
+ function Skeleton({ width, height, borderRadius = '4px' }) {
45142
+ return (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-skeleton-item", style: { width, height, borderRadius } }));
45143
+ }
45144
+ function PinInputGroup({ values, onChange, disabled }) {
45145
+ const inputRefs = reactExports.useRef([]);
45146
+ const handleChange = (index, value) => {
45147
+ // Only allow digits
45148
+ const digit = value.replace(/[^0-9]/g, '');
45149
+ const newValues = [...values];
45150
+ newValues[index] = digit.slice(-1);
45151
+ onChange(newValues);
45152
+ // Auto-focus next input
45153
+ if (digit && index < 5) {
45154
+ inputRefs.current[index + 1]?.focus();
45155
+ }
45156
+ };
45157
+ const handleKeyDown = (index, e) => {
45158
+ if (e.key === 'Backspace' && !values[index] && index > 0) {
45159
+ inputRefs.current[index - 1]?.focus();
45160
+ }
45161
+ };
45162
+ const handlePaste = (e) => {
45163
+ e.preventDefault();
45164
+ const pastedData = e.clipboardData.getData('text').replace(/[^0-9]/g, '').slice(0, 6);
45165
+ const newValues = pastedData.split('').concat(Array(6 - pastedData.length).fill(''));
45166
+ onChange(newValues);
45167
+ // Focus the next empty input or the last one
45168
+ const nextIndex = Math.min(pastedData.length, 5);
45169
+ inputRefs.current[nextIndex]?.focus();
45170
+ };
45171
+ return (jsxRuntimeExports.jsx("div", { className: "ai-chat-pin-input-group", children: values.map((value, index) => (jsxRuntimeExports.jsx("input", { ref: (el) => {
45172
+ inputRefs.current[index] = el;
45173
+ }, 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))) }));
45174
+ }
45175
+ function BookContactAppointmentCard({ action, onComplete, accentColor }) {
45176
+ const state = action.state;
45177
+ const [emailInput, setEmailInput] = reactExports.useState('');
45178
+ const [otpValues, setOtpValues] = reactExports.useState(Array(6).fill(''));
45179
+ const [subjectInput, setSubjectInput] = reactExports.useState(state.subject || '');
45180
+ const [isSubmitting, setIsSubmitting] = reactExports.useState(false);
45181
+ const [emailError, setEmailError] = reactExports.useState(null);
45182
+ const [otpError, setOtpError] = reactExports.useState(null);
45183
+ const phase = state.phase || 'awaiting_email';
45184
+ const handleSubmit = (newState, delay = 50) => {
45185
+ if (!onComplete)
45186
+ return;
45187
+ setIsSubmitting(true);
45188
+ setTimeout(() => {
45189
+ onComplete(action.toolCallId, { ...state, ...newState, errorMessage: null });
45190
+ }, delay);
45191
+ };
45192
+ reactExports.useEffect(() => {
45193
+ setIsSubmitting(false);
45194
+ if (phase === 'awaiting_email') {
45195
+ setEmailError(null);
45196
+ setOtpError(null);
45197
+ }
45198
+ else if (phase === 'awaiting_otp') {
45199
+ setOtpError(state.errorMessage || null);
45200
+ setEmailError(null);
45201
+ setOtpValues(Array(6).fill(''));
45202
+ if (state.email) {
45203
+ setEmailInput(state.email);
45204
+ }
45205
+ }
45206
+ else {
45207
+ setEmailError(null);
45208
+ setOtpError(null);
45209
+ }
45210
+ }, [phase, state.errorMessage]);
45211
+ const isWaitingForBackend = !action.done && Boolean(state.confirmed) && phase === 'awaiting_confirmation';
45212
+ const renderSkeleton = () => (jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card", children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-content", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-header", children: [jsxRuntimeExports.jsx(Skeleton, { width: "28px", height: "28px", borderRadius: "50%" }), jsxRuntimeExports.jsx(Skeleton, { width: "180px", height: "20px", borderRadius: "4px" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-box", children: [jsxRuntimeExports.jsx(Skeleton, { width: "60px", height: "12px", borderRadius: "4px" }), jsxRuntimeExports.jsx(Skeleton, { width: "120px", height: "18px", borderRadius: "4px" })] }), jsxRuntimeExports.jsx(Skeleton, { width: "100%", height: "44px", borderRadius: "999px" })] }) }));
45213
+ const handleEmailSubmit = () => {
45214
+ const trimmedEmail = emailInput.trim();
45215
+ if (!trimmedEmail) {
45216
+ setEmailError('Please enter your email address');
45217
+ return;
45218
+ }
45219
+ setEmailError(null);
45220
+ setEmailInput(trimmedEmail);
45221
+ handleSubmit({ email: trimmedEmail });
45222
+ };
45223
+ const handleOtpSubmit = () => {
45224
+ const code = otpValues.join('');
45225
+ if (code.length !== 6) {
45226
+ setOtpError('Please enter the 6-digit code');
45227
+ return;
45228
+ }
45229
+ setOtpError(null);
45230
+ const resolvedEmail = state.email || emailInput.trim() || null;
45231
+ handleSubmit({ otpCode: code, email: resolvedEmail });
45232
+ };
45233
+ // ========================================
45234
+ // Terminal States
45235
+ // ========================================
45236
+ if (phase === 'booked') {
45237
+ return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card ai-chat-booking-card--success", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__icon", children: "\u2713" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Appointment Booked" })] }), state.bookedTeamsLink && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__success-text", children: "Your appointment has been confirmed. You can join via Microsoft Teams." }), jsxRuntimeExports.jsx("a", { href: state.bookedTeamsLink, target: "_blank", rel: "noopener noreferrer", className: "ai-chat-booking-card__link", style: { color: accentColor }, children: "Join Teams Meeting \u2192" })] }))] }));
45238
+ }
45239
+ if (phase === 'pending_approval') {
45240
+ return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card ai-chat-booking-card--pending", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__icon", children: "\u23F3" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Awaiting Approval" })] }), jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__content", children: jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__pending-text", children: "Your appointment request has been sent and is awaiting approval from the contact." }) })] }));
45241
+ }
45242
+ if (phase === 'cancelled') {
45243
+ return (jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card ai-chat-booking-card--cancelled", children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__icon", children: "\u2715" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Appointment Cancelled" })] }) }));
45244
+ }
45245
+ if (phase === 'error') {
45246
+ return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card ai-chat-booking-card--error", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__icon", children: "\u26A0\uFE0F" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Booking Error" })] }), state.errorMessage && (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__error", children: state.errorMessage }))] }));
45247
+ }
45248
+ if (isSubmitting || isWaitingForBackend) {
45249
+ return renderSkeleton();
45250
+ }
45251
+ // ========================================
45252
+ // Phase: Email Collection
45253
+ // ========================================
45254
+ if (phase === 'awaiting_email') {
45255
+ const displayError = emailError || state.errorMessage;
45256
+ return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__icon", children: "\uD83D\uDCE7" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Enter Your Email" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__description", children: "Please enter your email address to start the booking process." }), displayError && (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__error", children: displayError })), jsxRuntimeExports.jsx("input", { type: "email", className: "ai-chat-booking-card__input", placeholder: "your@email.com", value: emailInput, onChange: (e) => {
45257
+ setEmailInput(e.target.value);
45258
+ setEmailError(null);
45259
+ }, onKeyDown: (e) => {
45260
+ if (e.key === 'Enter') {
45261
+ handleEmailSubmit();
45262
+ }
45263
+ } }), jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__btn ai-chat-booking-card__btn--primary", onClick: handleEmailSubmit, disabled: !emailInput.trim(), style: {
45264
+ backgroundColor: accentColor || undefined,
45265
+ borderColor: accentColor || undefined,
45266
+ }, children: "Continue" })] })] }));
45267
+ }
45268
+ // ========================================
45269
+ // Phase: OTP Verification
45270
+ // ========================================
45271
+ if (phase === 'awaiting_otp') {
45272
+ const displayError = otpError || state.errorMessage;
45273
+ return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__icon", children: "\uD83D\uDD10" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Verify Your Email" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [jsxRuntimeExports.jsxs("p", { className: "ai-chat-booking-card__description", children: ["Enter the verification code sent to ", jsxRuntimeExports.jsx("strong", { children: state.email })] }), jsxRuntimeExports.jsx(PinInputGroup, { values: otpValues, onChange: (newValues) => {
45274
+ setOtpValues(newValues);
45275
+ setOtpError(null);
45276
+ if (newValues.every((value) => value.length === 1) && !isSubmitting) {
45277
+ const resolvedEmail = state.email || emailInput.trim() || null;
45278
+ handleSubmit({ otpCode: newValues.join(''), email: resolvedEmail }, 100);
45279
+ }
45280
+ }, disabled: isSubmitting }), displayError && (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__error", children: displayError })), jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__btn ai-chat-booking-card__btn--primary", onClick: handleOtpSubmit, disabled: otpValues.join('').length !== 6, style: {
45281
+ backgroundColor: accentColor || undefined,
45282
+ borderColor: accentColor || undefined,
45283
+ }, children: "Verify" })] })] }));
45284
+ }
45285
+ // ========================================
45286
+ // Phase: Contact Selection
45287
+ // ========================================
45288
+ if (phase === 'awaiting_contact_selection') {
45289
+ return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__icon", children: "\uD83D\uDC65" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Select a Contact" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [state.errorMessage && (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__error", children: state.errorMessage })), state.bookableContacts.length === 0 ? (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__empty", children: "No contacts available for booking." })) : (jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__grid", children: state.bookableContacts.map((contact) => (jsxRuntimeExports.jsxs("button", { className: `ai-chat-booking-card__contact ${state.selectedContactId === contact.id ? 'ai-chat-booking-card__contact--selected' : ''}`, onClick: () => handleSubmit({ selectedContactId: contact.id }), style: {
45290
+ borderColor: state.selectedContactId === contact.id
45291
+ ? accentColor || undefined
45292
+ : undefined,
45293
+ backgroundColor: state.selectedContactId === contact.id
45294
+ ? `${accentColor || '#3b82f6'}15`
45295
+ : undefined,
45296
+ }, children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__contact-name", children: contact.name }), contact.role && (jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__contact-role", children: contact.role }))] }, contact.id))) }))] })] }));
45297
+ }
45298
+ // ========================================
45299
+ // Phase: Options Selection
45300
+ // ========================================
45301
+ if (phase === 'awaiting_options') {
45302
+ const selectedContact = state.bookableContacts.find((c) => c.id === state.selectedContactId);
45303
+ return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__icon", children: "\uD83D\uDCC5" }), jsxRuntimeExports.jsxs("span", { className: "ai-chat-booking-card__title", children: ["Book with ", selectedContact?.name] })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [state.errorMessage && (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__error", children: state.errorMessage })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__options", children: [jsxRuntimeExports.jsxs("button", { className: "ai-chat-booking-card__option-btn", onClick: () => handleSubmit({ selectedOption: 'book_new' }), children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__option-icon", children: "\u2795" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__option-text", children: "Book New Appointment" })] }), state.userAppointments.length > 0 && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsxs("button", { className: "ai-chat-booking-card__option-btn", onClick: () => handleSubmit({ selectedOption: 'view_existing' }), children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__option-icon", children: "\uD83D\uDCCB" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__option-text", children: "View Appointments" })] }), jsxRuntimeExports.jsxs("button", { className: "ai-chat-booking-card__option-btn", onClick: () => handleSubmit({ selectedOption: 'cancel_existing' }), children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__option-icon", children: "\u2715" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__option-text", children: "Cancel Appointment" })] })] }))] })] })] }));
45304
+ }
45305
+ // ========================================
45306
+ // Phase: View Existing Appointments
45307
+ // ========================================
45308
+ if (state.phase === 'awaiting_options' && state.selectedOption === 'view_existing') {
45309
+ return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__icon", children: "\uD83D\uDCCB" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Your Appointments" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [state.userAppointments.length === 0 ? (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__empty", children: "You have no appointments yet." })) : (jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__appointments", children: state.userAppointments.map((apt) => (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__appointment", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__appointment-header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__appointment-subject", children: apt.subject }), jsxRuntimeExports.jsx("span", { className: `ai-chat-booking-card__appointment-status ai-chat-booking-card__appointment-status--${apt.status}`, children: apt.status })] }), jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__appointment-time", children: apt.displayTime }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__appointment-contact", children: ["with ", apt.contactName] }), apt.teamsLink && (jsxRuntimeExports.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))) })), jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__btn ai-chat-booking-card__btn--secondary", onClick: () => handleSubmit({ selectedOption: undefined }), children: "Back" })] })] }));
45310
+ }
45311
+ // ========================================
45312
+ // Phase: Cancel Appointment
45313
+ // ========================================
45314
+ if (state.phase === 'awaiting_options' && state.selectedOption === 'cancel_existing') {
45315
+ const activeAppointments = state.userAppointments.filter((a) => a.status !== 'cancelled' && a.status !== 'declined');
45316
+ return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__icon", children: "\u2715" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Cancel Appointment" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [state.errorMessage && (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__error", children: state.errorMessage })), activeAppointments.length === 0 ? (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__empty", children: "No active appointments to cancel." }), jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__btn ai-chat-booking-card__btn--secondary", onClick: () => handleSubmit({ selectedOption: undefined }), children: "Back" })] })) : (jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__appointments", children: activeAppointments.map((apt) => (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__appointment", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__appointment-header", children: jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__appointment-subject", children: apt.subject }) }), jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__appointment-time", children: apt.displayTime }), jsxRuntimeExports.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))) }))] })] }));
45317
+ }
45318
+ // ========================================
45319
+ // Phase: Slot Selection
45320
+ // ========================================
45321
+ if (phase === 'awaiting_slot_selection') {
45322
+ const groupedSlots = state.availableSlots.reduce((acc, slot) => {
45323
+ if (!acc[slot.displayDate]) {
45324
+ acc[slot.displayDate] = [];
45325
+ }
45326
+ acc[slot.displayDate].push(slot);
45327
+ return acc;
45328
+ }, {});
45329
+ return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__icon", children: "\uD83D\uDD50" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Select a Time Slot" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [jsxRuntimeExports.jsxs("p", { className: "ai-chat-booking-card__description", children: ["Available times in ", state.timeZone] }), state.errorMessage && (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__error", children: state.errorMessage })), Object.entries(groupedSlots).map(([date, slots]) => (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__date-group", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__date-header", children: date }), jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__slots", children: slots.map((slot, idx) => {
45330
+ const isSelected = state.selectedSlot?.startTime === slot.startTime &&
45331
+ state.selectedSlot?.endTime === slot.endTime;
45332
+ return (jsxRuntimeExports.jsx("button", { className: `ai-chat-booking-card__slot ${isSelected ? 'ai-chat-booking-card__slot--selected' : ''}`, onClick: () => handleSubmit({
45333
+ selectedSlot: { startTime: slot.startTime, endTime: slot.endTime },
45334
+ }), style: {
45335
+ borderColor: isSelected ? accentColor || undefined : undefined,
45336
+ backgroundColor: isSelected ? `${accentColor || '#3b82f6'}15` : undefined,
45337
+ }, children: slot.displayTime }, `${slot.startTime}-${idx}`));
45338
+ }) })] }, date))), state.availableSlots.length === 0 && (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__empty", children: "No available time slots." }))] })] }));
45339
+ }
45340
+ // ========================================
45341
+ // Phase: Confirmation
45342
+ // ========================================
45343
+ if (phase === 'awaiting_confirmation') {
45344
+ const selectedContact = state.bookableContacts.find((c) => c.id === state.selectedContactId);
45345
+ const selectedSlot = state.availableSlots.find((s) => s.startTime === state.selectedSlot?.startTime && s.endTime === state.selectedSlot?.endTime);
45346
+ return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__icon", children: "\u2713" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Confirm Booking" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [state.errorMessage && (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__error", children: state.errorMessage })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__summary", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__summary-row", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-label", children: "Contact:" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-value", children: selectedContact?.name })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__summary-row", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-label", children: "Date:" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-value", children: selectedSlot?.displayDate })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__summary-row", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-label", children: "Time:" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-value", children: selectedSlot?.displayTime })] })] }), state.allowCustomSubject && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("label", { className: "ai-chat-booking-card__label", children: "Subject (optional):" }), jsxRuntimeExports.jsx("input", { type: "text", className: "ai-chat-booking-card__input", placeholder: "Meeting subject", value: subjectInput, onChange: (e) => setSubjectInput(e.target.value) })] })), jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__btn ai-chat-booking-card__btn--primary", onClick: () => handleSubmit({
45347
+ subject: state.allowCustomSubject ? subjectInput || undefined : undefined,
45348
+ confirmed: true,
45349
+ }), style: {
45350
+ backgroundColor: accentColor || undefined,
45351
+ borderColor: accentColor || undefined,
45352
+ }, children: "Confirm Booking" })] })] }));
45353
+ }
45354
+ // Fallback for unknown states
45355
+ return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__icon", children: "\uD83D\uDCC5" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Booking" })] }), jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__content", children: jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__description", children: "Loading booking options..." }) })] }));
45356
+ }
45357
+
45358
+ const pendingResolvers = new Map();
45359
+ const resumeCallbacks = new Map();
45360
+ const frontendActionHandlers = {};
45361
+ const actionRenderers = {};
45362
+ function getFrontendActionHandler(implementation) {
45363
+ return frontendActionHandlers[implementation];
45364
+ }
45365
+ function getActionRenderer(implementation) {
45366
+ return actionRenderers[implementation];
45367
+ }
45368
+ function waitForActionState(toolCallId) {
45369
+ return new Promise((resolve) => {
45370
+ pendingResolvers.set(toolCallId, resolve);
45371
+ });
45372
+ }
45373
+ function resolveActionState(toolCallId, state) {
45374
+ const resolver = pendingResolvers.get(toolCallId);
45375
+ if (resolver) {
45376
+ pendingResolvers.delete(toolCallId);
45377
+ resolver(state);
45378
+ return;
45379
+ }
45380
+ const resumeCallback = resumeCallbacks.get(toolCallId);
44456
45381
  if (resumeCallback) {
44457
45382
  resumeCallback(state).catch((error) => {
44458
45383
  console.error("[Action] Failed to resume action:", error);
@@ -44480,13 +45405,19 @@
44480
45405
  // Register the handler
44481
45406
  registerGoogleCalendarHandler();
44482
45407
  // Register the renderer
44483
- actionRenderers["google-calendar-appointment"] = (message) => {
45408
+ actionRenderers["google-calendar-appointment"] = (message, accentColor, _variant, onActionDismiss) => {
44484
45409
  const action = message.action;
44485
45410
  if (!action)
44486
45411
  return null;
44487
45412
  const handleComplete = (toolCallId, newState) => {
44488
45413
  resolveActionState(toolCallId, newState);
44489
45414
  };
45415
+ const handleDismiss = onActionDismiss
45416
+ ? (toolCallId) => {
45417
+ resolveActionState(toolCallId, { __dismissed: true });
45418
+ onActionDismiss(toolCallId);
45419
+ }
45420
+ : undefined;
44490
45421
  return (jsxRuntimeExports.jsx(GoogleCalendarCard, { action: {
44491
45422
  implementation: action.implementation,
44492
45423
  toolCallId: action.toolCallId,
@@ -44494,7 +45425,45 @@
44494
45425
  input: action.input,
44495
45426
  state: action.state,
44496
45427
  done: action.done ?? false,
44497
- }, onComplete: handleComplete }));
45428
+ }, onComplete: handleComplete, onDismiss: handleDismiss, accentColor: accentColor }));
45429
+ };
45430
+ }
45431
+
45432
+ function registerMicrosoftCalendarHandler() {
45433
+ frontendActionHandlers["microsoft-calendar-appointment"] = async (_input, _state, context) => {
45434
+ return waitForActionState(context.toolCallId);
45435
+ };
45436
+ }
45437
+
45438
+ /**
45439
+ * Register microsoft-calendar-appointment action handler and renderer.
45440
+ * Called by initializeActionHandlers to prevent tree-shaking.
45441
+ */
45442
+ function registerMicrosoftCalendarAction() {
45443
+ // Register the handler
45444
+ registerMicrosoftCalendarHandler();
45445
+ // Register the renderer
45446
+ actionRenderers["microsoft-calendar-appointment"] = (message, accentColor, _variant, onActionDismiss) => {
45447
+ const action = message.action;
45448
+ if (!action)
45449
+ return null;
45450
+ const handleComplete = (toolCallId, newState) => {
45451
+ resolveActionState(toolCallId, newState);
45452
+ };
45453
+ const handleDismiss = onActionDismiss
45454
+ ? (toolCallId) => {
45455
+ resolveActionState(toolCallId, { __dismissed: true });
45456
+ onActionDismiss(toolCallId);
45457
+ }
45458
+ : undefined;
45459
+ return (jsxRuntimeExports.jsx(MicrosoftCalendarCard, { action: {
45460
+ implementation: action.implementation,
45461
+ toolCallId: action.toolCallId,
45462
+ actionId: action.actionId,
45463
+ input: action.input,
45464
+ state: action.state,
45465
+ done: action.done ?? false,
45466
+ }, onComplete: handleComplete, onDismiss: handleDismiss, accentColor: accentColor }));
44498
45467
  };
44499
45468
  }
44500
45469
 
@@ -44508,7 +45477,7 @@
44508
45477
  return { ...state, status: "displaying" };
44509
45478
  };
44510
45479
  // Renderer - displays the link preview card
44511
- actionRenderers["link-preview"] = (message) => {
45480
+ actionRenderers["link-preview"] = (message, accentColor) => {
44512
45481
  const action = message.action;
44513
45482
  if (!action)
44514
45483
  return null;
@@ -44526,7 +45495,7 @@
44526
45495
  input: action.input,
44527
45496
  state: action.state,
44528
45497
  done: isDone,
44529
- }, onComplete: handleComplete }));
45498
+ }, onComplete: handleComplete, accentColor: accentColor }));
44530
45499
  };
44531
45500
  }
44532
45501
 
@@ -44540,7 +45509,7 @@
44540
45509
  return { ...state, status: "displaying" };
44541
45510
  };
44542
45511
  // Renderer - displays the embedded video player card
44543
- actionRenderers["video-player"] = (message) => {
45512
+ actionRenderers["video-player"] = (message, accentColor) => {
44544
45513
  const action = message.action;
44545
45514
  if (!action)
44546
45515
  return null;
@@ -44558,7 +45527,7 @@
44558
45527
  input: action.input,
44559
45528
  state: action.state,
44560
45529
  done: isDone,
44561
- }, onComplete: handleComplete }));
45530
+ }, onComplete: handleComplete, accentColor: accentColor }));
44562
45531
  };
44563
45532
  }
44564
45533
 
@@ -44572,7 +45541,7 @@
44572
45541
  return { ...state, status: "displaying" };
44573
45542
  };
44574
45543
  // Renderer - displays the location card
44575
- actionRenderers["location-card"] = (message, accentColor) => {
45544
+ actionRenderers["location-card"] = (message, accentColor, variant) => {
44576
45545
  const action = message.action;
44577
45546
  if (!action)
44578
45547
  return null;
@@ -44590,7 +45559,134 @@
44590
45559
  input: action.input,
44591
45560
  state: action.state,
44592
45561
  done: isDone,
44593
- }, onComplete: handleComplete, accentColor: accentColor, maxColumns: 1 }));
45562
+ }, onComplete: handleComplete, accentColor: accentColor, maxColumns: variant === 'fullpage' ? 3 : 1 }));
45563
+ };
45564
+ }
45565
+
45566
+ function registerContactCardAction() {
45567
+ // Handler - auto-completes immediately since no user input is needed
45568
+ frontendActionHandlers['contact-card'] = async (_input, state, _context) => {
45569
+ return { ...state, status: 'displaying' };
45570
+ };
45571
+ // Renderer - displays the contact card
45572
+ actionRenderers['contact-card'] = (message, accentColor, variant) => {
45573
+ const action = message.action;
45574
+ if (!action)
45575
+ return null;
45576
+ const handleComplete = (toolCallId, newState) => {
45577
+ resolveActionState(toolCallId, newState);
45578
+ };
45579
+ // Check if action state indicates it's already complete
45580
+ const state = action.state;
45581
+ const status = state?.status;
45582
+ const isDone = action.done || status === 'displaying' || status === 'contacted';
45583
+ return (jsxRuntimeExports.jsx(ContactCard, { action: {
45584
+ implementation: action.implementation,
45585
+ toolCallId: action.toolCallId,
45586
+ actionId: action.actionId,
45587
+ input: action.input,
45588
+ state: action.state,
45589
+ done: isDone,
45590
+ }, onComplete: handleComplete, accentColor: accentColor, maxColumns: variant === 'fullpage' ? 3 : 1 }));
45591
+ };
45592
+ }
45593
+
45594
+ function registerQueryContactDirectoryAction() {
45595
+ // Handler - auto-completes immediately since no user input is needed
45596
+ frontendActionHandlers['query-contact-directory'] = async (_input, state, _context) => {
45597
+ return { ...state, status: 'displaying' };
45598
+ };
45599
+ // Renderer - displays the contact card with search results
45600
+ actionRenderers['query-contact-directory'] = (message, accentColor, variant) => {
45601
+ const action = message.action;
45602
+ if (!action)
45603
+ return null;
45604
+ // Handle completion - triggers agent to continue with text response
45605
+ const handleComplete = (toolCallId, newState) => {
45606
+ resolveActionState(toolCallId, newState);
45607
+ };
45608
+ // Check if action state indicates it's already complete
45609
+ const state = action.state;
45610
+ const status = state?.status;
45611
+ const isDone = action.done || status === 'displaying' || status === 'contacted';
45612
+ return (jsxRuntimeExports.jsx(ContactCard, { action: {
45613
+ implementation: action.implementation,
45614
+ toolCallId: action.toolCallId,
45615
+ actionId: action.actionId,
45616
+ input: action.input,
45617
+ state: action.state,
45618
+ done: isDone,
45619
+ }, onComplete: handleComplete, accentColor: accentColor, maxColumns: variant === 'fullpage' ? 3 : 1 }));
45620
+ };
45621
+ }
45622
+
45623
+ function registerDisplayFormAction() {
45624
+ // Handler - handles form submission and state updates
45625
+ frontendActionHandlers['display-form'] = async (_input, _state, context) => {
45626
+ return waitForActionState(context.toolCallId);
45627
+ };
45628
+ // Renderer - displays the form card
45629
+ actionRenderers['display-form'] = (message, accentColor, variant, onActionDismiss) => {
45630
+ const action = message.action;
45631
+ if (!action)
45632
+ return null;
45633
+ const handleComplete = (toolCallId, newState) => {
45634
+ resolveActionState(toolCallId, newState);
45635
+ };
45636
+ const handleDismiss = onActionDismiss
45637
+ ? (toolCallId) => {
45638
+ resolveActionState(toolCallId, { __dismissed: true });
45639
+ onActionDismiss(toolCallId);
45640
+ }
45641
+ : undefined;
45642
+ // Check if action state indicates it's already complete
45643
+ const state = action.state;
45644
+ const status = state?.status;
45645
+ const isDone = action.done || status === 'completed' || status === 'submitted';
45646
+ return (jsxRuntimeExports.jsx(FormCard, { action: {
45647
+ implementation: action.implementation,
45648
+ toolCallId: action.toolCallId,
45649
+ actionId: action.actionId,
45650
+ input: action.input,
45651
+ state: action.state,
45652
+ done: isDone,
45653
+ }, onComplete: handleComplete, onDismiss: handleDismiss, accentColor: accentColor }));
45654
+ };
45655
+ }
45656
+
45657
+ /**
45658
+ * Book Contact Appointment Handler
45659
+ * Frontend action handler that waits for action completion
45660
+ */
45661
+ function registerBookContactAppointmentHandler() {
45662
+ frontendActionHandlers["book-contact-appointment"] = async (_input, _state, context) => {
45663
+ return waitForActionState(context.toolCallId);
45664
+ };
45665
+ }
45666
+
45667
+ /**
45668
+ * Register book-contact-appointment action handler and renderer.
45669
+ * Called by initializeActionHandlers to prevent tree-shaking.
45670
+ */
45671
+ function registerBookContactAppointmentAction() {
45672
+ // Register the handler
45673
+ registerBookContactAppointmentHandler();
45674
+ // Register the renderer
45675
+ actionRenderers['book-contact-appointment'] = (message, accentColor) => {
45676
+ const action = message.action;
45677
+ if (!action)
45678
+ return null;
45679
+ const handleComplete = (toolCallId, newState) => {
45680
+ resolveActionState(toolCallId, newState);
45681
+ };
45682
+ return (jsxRuntimeExports.jsx(BookContactAppointmentCard, { action: {
45683
+ implementation: action.implementation,
45684
+ toolCallId: action.toolCallId,
45685
+ actionId: action.actionId,
45686
+ input: action.input,
45687
+ state: action.state,
45688
+ done: action.done ?? false,
45689
+ }, onComplete: handleComplete, accentColor: accentColor }));
44594
45690
  };
44595
45691
  }
44596
45692
 
@@ -44607,9 +45703,14 @@
44607
45703
  initialized = true;
44608
45704
  // Explicitly call each registration function to prevent tree-shaking
44609
45705
  registerGoogleCalendarAction();
45706
+ registerMicrosoftCalendarAction();
44610
45707
  registerLinkPreviewAction();
44611
45708
  registerVideoPlayerAction();
44612
45709
  registerLocationCardAction();
45710
+ registerQueryContactDirectoryAction();
45711
+ registerContactCardAction();
45712
+ registerDisplayFormAction();
45713
+ registerBookContactAppointmentAction();
44613
45714
  }
44614
45715
 
44615
45716
  /**
@@ -44829,12 +45930,6 @@
44829
45930
  }
44830
45931
  }
44831
45932
 
44832
- /**
44833
- * useChat Hook
44834
- * Main state management for chat functionality
44835
- */
44836
- // Initialize action handlers immediately to prevent tree-shaking
44837
- initializeActionHandlers();
44838
45933
  function hydrateToolNames(messages) {
44839
45934
  const toolCallNameById = new Map();
44840
45935
  for (const entry of messages) {
@@ -44878,118 +45973,78 @@
44878
45973
  };
44879
45974
  });
44880
45975
  }
44881
- function hydrateActionContent(messages) {
44882
- return messages.map((entry) => {
44883
- if (entry.message.role !== "assistant" || !entry.action) {
44884
- return entry;
44885
- }
44886
- const content = typeof entry.message.content === "string" ? entry.message.content : "";
44887
- if (content.trim().length > 0) {
44888
- return entry;
44889
- }
44890
- return {
44891
- ...entry,
44892
- message: { ...entry.message, content: getActionPrompt(entry.action.implementation) },
44893
- };
44894
- });
45976
+ function hydrateMessages(messages) {
45977
+ const visibleMessages = messages.filter((message) => !message.action?.hidden);
45978
+ return hydrateToolNames(visibleMessages);
44895
45979
  }
44896
- function hydrateActionDoneStatus(messages) {
44897
- return messages.map((entry) => {
44898
- if (!entry.action) {
44899
- return entry;
44900
- }
44901
- // If action already marked done, skip
44902
- if (entry.action.done) {
44903
- return entry;
45980
+
45981
+ function deriveErrorInfo(error) {
45982
+ if (error instanceof ApiError) {
45983
+ const retryAfterSeconds = typeof error.retryAfterMs === 'number'
45984
+ ? Math.max(1, Math.ceil(error.retryAfterMs / 1000))
45985
+ : undefined;
45986
+ const lowerMessage = (error.message || '').toLowerCase();
45987
+ let message;
45988
+ switch (error.status) {
45989
+ case 429: {
45990
+ const isPerUser = lowerMessage.includes('user');
45991
+ const base = isPerUser
45992
+ ? 'You have reached the per-user rate limit.'
45993
+ : 'This widget has received too many requests.';
45994
+ if (retryAfterSeconds) {
45995
+ message = `${base} Please wait ${retryAfterSeconds} second${retryAfterSeconds === 1 ? '' : 's'} before trying again.`;
45996
+ }
45997
+ else {
45998
+ message = `${base} Please wait a moment and try again.`;
45999
+ }
46000
+ break;
46001
+ }
46002
+ case 401:
46003
+ message = 'Authentication failed. Please refresh the page or verify your API key.';
46004
+ break;
46005
+ case 403:
46006
+ message = 'Access to this widget is restricted. Please contact the site owner if you believe this is an error.';
46007
+ break;
46008
+ case 404:
46009
+ if (lowerMessage.includes('not active')) {
46010
+ message = 'This widget is currently inactive. Please contact the site owner.';
46011
+ }
46012
+ else {
46013
+ message = 'We could not find this widget. It may have been removed.';
46014
+ }
46015
+ break;
46016
+ default:
46017
+ if (error.status >= 500) {
46018
+ message = 'The server encountered an error. Please try again shortly.';
46019
+ }
46020
+ else if (error.status > 0) {
46021
+ message = error.message || 'Something went wrong. Please try again.';
46022
+ }
46023
+ else {
46024
+ message = error.message || 'Unable to connect to the server. Please check your internet connection.';
46025
+ }
44904
46026
  }
44905
- // Check if action state indicates completion
44906
- const state = entry.action.state;
44907
- if (!state) {
44908
- return entry;
46027
+ return { message, retryAfterSeconds, status: error.status };
46028
+ }
46029
+ if (error instanceof Error) {
46030
+ const lower = error.message.toLowerCase();
46031
+ if (lower.includes('network')) {
46032
+ return { message: 'Unable to connect to the server. Please check your internet connection.' };
44909
46033
  }
44910
- // Link-preview: done if status is "displaying" or "clicked"
44911
- if (entry.action.implementation === "link-preview") {
44912
- const status = state.status;
44913
- if (status === "displaying" || status === "clicked") {
44914
- return {
44915
- ...entry,
44916
- action: { ...entry.action, done: true },
44917
- };
44918
- }
46034
+ if (lower.includes('timeout')) {
46035
+ return { message: 'The request timed out. Please try again.' };
44919
46036
  }
44920
- // Google Calendar: done if status indicates completion
44921
- if (entry.action.implementation === "google-calendar-appointment") {
44922
- const status = state.status;
44923
- if (status === "booked" || status === "cancelled" || status === "error") {
44924
- return {
44925
- ...entry,
44926
- action: { ...entry.action, done: true },
44927
- };
44928
- }
46037
+ if (lower.includes('unauthorized') || lower.includes('401')) {
46038
+ return { message: 'Authentication failed. Please refresh the page or verify your API key.' };
44929
46039
  }
44930
- return entry;
44931
- });
44932
- }
44933
- function hydrateMessages(messages) {
44934
- return hydrateActionDoneStatus(hydrateActionContent(hydrateToolNames(messages)));
44935
- }
44936
- function setupActionResumeCallbacks(messages, client, conversationId, setState, onMessageUpdate) {
44937
- // Find all incomplete actions and register resume callbacks
44938
- for (const message of messages) {
44939
- if (message.action && !message.action.done) {
44940
- const toolCallId = message.action.toolCallId;
44941
- const toolName = message.message.name || message.toolExecuting || "tool";
44942
- registerActionResumeCallback(toolCallId, async (newState) => {
44943
- // When user interacts with the action after reload, continue the stream
44944
- try {
44945
- // Update the action message with the new state
44946
- setState(prev => ({
44947
- ...prev,
44948
- messages: prev.messages.map(m => m.action?.toolCallId === toolCallId
44949
- ? {
44950
- ...m,
44951
- action: m.action ? { ...m.action, state: newState } : undefined,
44952
- }
44953
- : m),
44954
- isTyping: true,
44955
- }));
44956
- const streamState = createStreamState();
44957
- // Continue the agent stream with the new state
44958
- for await (const event of client.continueAgentMessageStream(conversationId, toolCallId, newState)) {
44959
- if (event.type === "done") {
44960
- finalizeToolMessage(streamState, setState, toolCallId, toolName);
44961
- streamState.sources = event.sources;
44962
- streamState.toolCallToActionId = event.tool_call_to_action_id;
44963
- finalizeStreamMessages(setState, streamState.newMessageIds, event.sources, event.tool_call_to_action_id, event.suggestions);
44964
- continue;
44965
- }
44966
- if (event.type === "error") {
44967
- const errorMessage = {
44968
- id: generateMessageId(),
44969
- message: {
44970
- role: "assistant",
44971
- content: "Sorry, an error occurred. Please try again later.",
44972
- },
44973
- timestamp: new Date().toISOString(),
44974
- sources: [],
44975
- isError: true,
44976
- };
44977
- upsertMessage(setState, errorMessage, false);
44978
- setState(prev => ({ ...prev, isTyping: false }));
44979
- return;
44980
- }
44981
- handleStreamEvent(event, streamState, onMessageUpdate, setState);
44982
- }
44983
- setState(prev => ({ ...prev, isTyping: false }));
44984
- }
44985
- catch (error) {
44986
- console.error("[Action Resume] Failed to continue stream:", error);
44987
- setState(prev => ({ ...prev, isTyping: false }));
44988
- }
44989
- });
46040
+ if (lower.includes('internal server error') || lower.includes('500')) {
46041
+ return { message: 'The server encountered an error. Please try again shortly.' };
44990
46042
  }
46043
+ return { message: error.message || 'Something went wrong. Please try again.' };
44991
46044
  }
46045
+ return { message: 'Something went wrong. Please try again.' };
44992
46046
  }
46047
+
44993
46048
  function createStreamState() {
44994
46049
  return {
44995
46050
  currentContent: "",
@@ -44998,6 +46053,7 @@
44998
46053
  newMessageIds: new Set(),
44999
46054
  sources: [],
45000
46055
  toolCallToActionId: {},
46056
+ requestId: generateMessageId(),
45001
46057
  };
45002
46058
  }
45003
46059
  function upsertMessage(setState, message, isTyping) {
@@ -45033,15 +46089,40 @@
45033
46089
  return msg;
45034
46090
  }
45035
46091
  // Attach suggestions only to the last assistant message
45036
- if (index === lastAssistantIndex && suggestions && suggestions.length > 0) {
45037
- return { ...msg, sources, toolCallToActionId, suggestions };
45038
- }
45039
- return { ...msg, sources, toolCallToActionId };
46092
+ const withSuggestions = index === lastAssistantIndex && suggestions && suggestions.length > 0
46093
+ ? { suggestions }
46094
+ : {};
46095
+ return { ...msg, sources, toolCallToActionId, ...withSuggestions };
45040
46096
  }),
45041
46097
  isTyping: false,
45042
46098
  };
45043
46099
  });
45044
46100
  }
46101
+ function finalizeToolMessage(streamState, setState, toolCallId, toolName) {
46102
+ setState(prev => {
46103
+ const messages = prev.messages.map((entry) => {
46104
+ const matchesToolCall = entry.message.role === "tool" && entry.message.tool_call_id === toolCallId;
46105
+ if (!matchesToolCall) {
46106
+ return entry;
46107
+ }
46108
+ const existingName = entry.message.name || toolName;
46109
+ return {
46110
+ ...entry,
46111
+ message: {
46112
+ role: "tool",
46113
+ content: typeof entry.message.content === "string" ? entry.message.content : "",
46114
+ tool_call_id: toolCallId,
46115
+ name: existingName,
46116
+ },
46117
+ isStreaming: false,
46118
+ toolExecuting: existingName,
46119
+ };
46120
+ });
46121
+ return { ...prev, messages, isTyping: false, isLoading: false };
46122
+ });
46123
+ streamState.activeToolCallCount = Math.max(0, streamState.activeToolCallCount - 1);
46124
+ }
46125
+
45045
46126
  function handleContentEvent(event, streamState, onMessageUpdate, setState) {
45046
46127
  streamState.currentContent += event.content;
45047
46128
  const assistantMessage = {
@@ -45088,8 +46169,6 @@
45088
46169
  }
45089
46170
  function handleToolEndEvent(event, streamState, _onMessageUpdate, setState) {
45090
46171
  streamState.activeToolCallCount = Math.max(0, streamState.activeToolCallCount - 1);
45091
- // Update state and mark action as done in a single setState call
45092
- // Keep isTyping: true because the agent may continue generating content after tool completion
45093
46172
  setState(prev => {
45094
46173
  const messages = prev.messages.map((msg) => {
45095
46174
  const matchesToolCall = msg.message.role === "tool" && msg.message.tool_call_id === event.tool_call_id;
@@ -45097,7 +46176,27 @@
45097
46176
  return msg;
45098
46177
  }
45099
46178
  const existingName = msg.message.name || event.tool_name;
45100
- return {
46179
+ let action = msg.action;
46180
+ if (event.action_id && event.implementation) {
46181
+ action = {
46182
+ ...action,
46183
+ implementation: event.implementation,
46184
+ toolCallId: event.tool_call_id,
46185
+ actionId: event.action_id,
46186
+ input: (event.input || {}),
46187
+ state: (event.state || {}),
46188
+ done: event.done,
46189
+ };
46190
+ }
46191
+ else if (action) {
46192
+ action = {
46193
+ ...action,
46194
+ input: event.input ? event.input : action.input,
46195
+ state: event.state ? event.state : action.state,
46196
+ done: event.done,
46197
+ };
46198
+ }
46199
+ const updatedMsg = {
45101
46200
  ...msg,
45102
46201
  message: {
45103
46202
  role: "tool",
@@ -45107,14 +46206,10 @@
45107
46206
  },
45108
46207
  isStreaming: false,
45109
46208
  toolExecuting: existingName,
45110
- action: msg.action ? {
45111
- ...msg.action,
45112
- state: event.state || msg.action.state,
45113
- done: true, // Mark action as completed
45114
- } : undefined,
46209
+ action,
45115
46210
  };
46211
+ return updatedMsg;
45116
46212
  });
45117
- // Keep typing indicator visible - it will be hidden by done/finalizeStreamMessages
45118
46213
  return { ...prev, messages, isTyping: true, isLoading: false };
45119
46214
  });
45120
46215
  }
@@ -45146,34 +46241,6 @@
45146
46241
  return { ...prev, messages, isTyping: true, isLoading: false };
45147
46242
  });
45148
46243
  }
45149
- function finalizeToolMessage(streamState, setState, toolCallId, toolName) {
45150
- setState(prev => {
45151
- const messages = prev.messages.map((entry) => {
45152
- const matchesToolCall = entry.message.role === "tool" && entry.message.tool_call_id === toolCallId;
45153
- if (!matchesToolCall) {
45154
- return entry;
45155
- }
45156
- const existingName = entry.message.name || toolName;
45157
- return {
45158
- ...entry,
45159
- message: {
45160
- role: "tool",
45161
- content: typeof entry.message.content === "string" ? entry.message.content : "",
45162
- tool_call_id: toolCallId,
45163
- name: existingName,
45164
- },
45165
- isStreaming: false,
45166
- toolExecuting: existingName,
45167
- action: entry.action ? {
45168
- ...entry.action,
45169
- done: true, // Mark action as completed
45170
- } : undefined,
45171
- };
45172
- });
45173
- return { ...prev, messages, isTyping: false, isLoading: false };
45174
- });
45175
- streamState.activeToolCallCount = Math.max(0, streamState.activeToolCallCount - 1);
45176
- }
45177
46244
  function handleDoneEvent(event, streamState, _onMessageUpdate, setState) {
45178
46245
  streamState.sources = event.sources;
45179
46246
  streamState.toolCallToActionId = event.tool_call_to_action_id;
@@ -45232,6 +46299,10 @@
45232
46299
  console.warn('[Chat] Unknown event type:', event.type);
45233
46300
  }
45234
46301
  }
46302
+
46303
+ function isDismissedState(state) {
46304
+ return Boolean(state.__dismissed);
46305
+ }
45235
46306
  async function handleActionLoop(client, initialEvent, streamState, onMessageUpdate, setState, widgetId, conversationId, getMessages) {
45236
46307
  let pendingEvent = initialEvent;
45237
46308
  while (pendingEvent) {
@@ -45258,7 +46329,7 @@
45258
46329
  actionId: pendingEvent.action_id,
45259
46330
  input: pendingEvent.input,
45260
46331
  state: pendingEvent.state,
45261
- done: false, // Action not yet completed
46332
+ done: pendingEvent.done ?? false,
45262
46333
  },
45263
46334
  };
45264
46335
  if (streamState.activeToolCallCount === 0) {
@@ -45272,7 +46343,7 @@
45272
46343
  id: generateMessageId(),
45273
46344
  message: {
45274
46345
  role: "assistant",
45275
- content: "Sorry, an error occurred. Please try again later.",
46346
+ content: "Sorry, an error occurred.",
45276
46347
  },
45277
46348
  timestamp: new Date().toISOString(),
45278
46349
  sources: [],
@@ -45296,7 +46367,7 @@
45296
46367
  console.error("[Widget] Frontend action failed:", error);
45297
46368
  const errorMessageEntry = {
45298
46369
  id: generateMessageId(),
45299
- message: { role: "assistant", content: "Sorry, an error occurred. Please try again later." },
46370
+ message: { role: "assistant", content: "Sorry, an error occurred." },
45300
46371
  timestamp: new Date().toISOString(),
45301
46372
  sources: [],
45302
46373
  isError: true,
@@ -45306,16 +46377,17 @@
45306
46377
  return;
45307
46378
  }
45308
46379
  pendingEvent = null;
45309
- const updatedToolMessage = {
45310
- ...toolMessage,
45311
- action: toolMessage.action
45312
- ? {
45313
- ...toolMessage.action,
45314
- state: nextState,
45315
- }
45316
- : undefined,
45317
- };
45318
- upsertMessage(setState, updatedToolMessage, true);
46380
+ const dismissed = isDismissedState(nextState);
46381
+ if (!dismissed) {
46382
+ const updatedToolMessage = {
46383
+ ...toolMessage,
46384
+ action: toolMessage.action ? { ...toolMessage.action, state: nextState } : toolMessage.action,
46385
+ };
46386
+ upsertMessage(setState, updatedToolMessage, true);
46387
+ }
46388
+ if (dismissed) {
46389
+ return;
46390
+ }
45319
46391
  let streamEnded = false;
45320
46392
  for await (const event of client.continueAgentMessageStream(conversationId, resumeToolCallId, nextState)) {
45321
46393
  if (event.type === "action_request") {
@@ -45323,22 +46395,20 @@
45323
46395
  break;
45324
46396
  }
45325
46397
  if (event.type === "done") {
45326
- // Don't extract and update state from done event - the state was already
45327
- // updated by tool_end event or by the user's frontend action.
46398
+ // Finalize tool message and stream messages
45328
46399
  finalizeToolMessage(streamState, setState, resumeToolCallId, toolName);
45329
- // Handle the done event but skip the tool finalization part since we already did it
45330
46400
  streamState.sources = event.sources;
45331
46401
  streamState.toolCallToActionId = event.tool_call_to_action_id;
45332
46402
  finalizeStreamMessages(setState, streamState.newMessageIds, event.sources, event.tool_call_to_action_id, event.suggestions);
45333
46403
  streamEnded = true;
45334
- continue; // Skip handleStreamEvent for done events to avoid state conflicts
46404
+ continue;
45335
46405
  }
45336
46406
  if (event.type === "error") {
45337
46407
  const errorMessage = {
45338
46408
  id: generateMessageId(),
45339
46409
  message: {
45340
46410
  role: "assistant",
45341
- content: "Sorry, an error occurred. Please try again later.",
46411
+ content: "Sorry, an error occurred.",
45342
46412
  },
45343
46413
  timestamp: new Date().toISOString(),
45344
46414
  sources: [],
@@ -45349,73 +46419,83 @@
45349
46419
  }
45350
46420
  handleStreamEvent(event, streamState, onMessageUpdate, setState);
45351
46421
  }
45352
- // If stream ended without a done event (e.g., only tool_end was sent), finalize the tool message
46422
+ // If stream ended without a done event, finalize the tool message
45353
46423
  if (!streamEnded && !pendingEvent) {
45354
46424
  finalizeToolMessage(streamState, setState, resumeToolCallId, toolName);
45355
46425
  }
45356
46426
  }
45357
46427
  }
45358
- function deriveErrorInfo(error) {
45359
- if (error instanceof ApiError) {
45360
- const retryAfterSeconds = typeof error.retryAfterMs === 'number'
45361
- ? Math.max(1, Math.ceil(error.retryAfterMs / 1000))
45362
- : undefined;
45363
- const lowerMessage = (error.message || '').toLowerCase();
45364
- let message;
45365
- switch (error.status) {
45366
- case 429: {
45367
- const isPerUser = lowerMessage.includes('user');
45368
- const base = isPerUser
45369
- ? 'You have reached the per-user rate limit.'
45370
- : 'This widget has received too many requests.';
45371
- if (retryAfterSeconds) {
45372
- message = `${base} Please wait ${retryAfterSeconds} second${retryAfterSeconds === 1 ? '' : 's'} before trying again.`;
45373
- }
45374
- else {
45375
- message = `${base} Please wait a moment and try again.`;
45376
- }
45377
- break;
45378
- }
45379
- case 401:
45380
- message = 'Authentication failed. Please refresh the page or verify your API key.';
45381
- break;
45382
- case 403:
45383
- message = 'Access to this widget is restricted. Please contact the site owner if you believe this is an error.';
45384
- break;
45385
- case 404:
45386
- message = 'We could not find this widget. It may have been removed.';
45387
- break;
45388
- default:
45389
- if (error.status >= 500) {
45390
- message = 'The server encountered an error. Please try again shortly.';
45391
- }
45392
- else if (error.status > 0) {
45393
- message = error.message || 'Something went wrong. Please try again.';
46428
+ function setupActionResumeCallbacks(messages, client, conversationId, setState, onMessageUpdate, createStreamState, registerCallback) {
46429
+ // Find all incomplete actions and register resume callbacks
46430
+ for (const message of messages) {
46431
+ if (message.action && !message.action.done && !message.action.hidden) {
46432
+ const toolCallId = message.action.toolCallId;
46433
+ const toolName = message.message.name || message.toolExecuting || "tool";
46434
+ registerCallback(toolCallId, async (newState) => {
46435
+ // When user interacts with the action after reload, continue the stream
46436
+ try {
46437
+ // Update the action message with the new state and check completion
46438
+ if (isDismissedState(newState)) {
46439
+ setState(prev => ({ ...prev, isTyping: false }));
46440
+ return;
46441
+ }
46442
+ setState(prev => ({
46443
+ ...prev,
46444
+ messages: prev.messages.map(m => {
46445
+ if (m.action?.toolCallId !== toolCallId) {
46446
+ return m;
46447
+ }
46448
+ if (!m.action) {
46449
+ return m;
46450
+ }
46451
+ return { ...m, action: { ...m.action, state: newState } };
46452
+ }),
46453
+ isTyping: true,
46454
+ }));
46455
+ const streamState = createStreamState();
46456
+ // Continue the agent stream with the new state
46457
+ for await (const event of client.continueAgentMessageStream(conversationId, toolCallId, newState)) {
46458
+ if (event.type === "done") {
46459
+ finalizeToolMessage(streamState, setState, toolCallId, toolName);
46460
+ streamState.sources = event.sources;
46461
+ streamState.toolCallToActionId = event.tool_call_to_action_id;
46462
+ finalizeStreamMessages(setState, streamState.newMessageIds, event.sources, event.tool_call_to_action_id, event.suggestions);
46463
+ continue;
46464
+ }
46465
+ if (event.type === "error") {
46466
+ const errorMessage = {
46467
+ id: generateMessageId(),
46468
+ message: {
46469
+ role: "assistant",
46470
+ content: "Sorry, an error occurred. Please try again later.",
46471
+ },
46472
+ timestamp: new Date().toISOString(),
46473
+ sources: [],
46474
+ isError: true,
46475
+ };
46476
+ upsertMessage(setState, errorMessage, false);
46477
+ setState(prev => ({ ...prev, isTyping: false }));
46478
+ return;
46479
+ }
46480
+ handleStreamEvent(event, streamState, onMessageUpdate, setState);
46481
+ }
46482
+ setState(prev => ({ ...prev, isTyping: false }));
45394
46483
  }
45395
- else {
45396
- message = error.message || 'Unable to connect to the server. Please check your internet connection.';
46484
+ catch (error) {
46485
+ console.error("[Action Resume] Failed to continue stream:", error);
46486
+ setState(prev => ({ ...prev, isTyping: false }));
45397
46487
  }
46488
+ });
45398
46489
  }
45399
- return { message, retryAfterSeconds, status: error.status };
45400
- }
45401
- if (error instanceof Error) {
45402
- const lower = error.message.toLowerCase();
45403
- if (lower.includes('network')) {
45404
- return { message: 'Unable to connect to the server. Please check your internet connection.' };
45405
- }
45406
- if (lower.includes('timeout')) {
45407
- return { message: 'The request timed out. Please try again.' };
45408
- }
45409
- if (lower.includes('unauthorized') || lower.includes('401')) {
45410
- return { message: 'Authentication failed. Please refresh the page or verify your API key.' };
45411
- }
45412
- if (lower.includes('internal server error') || lower.includes('500')) {
45413
- return { message: 'The server encountered an error. Please try again shortly.' };
45414
- }
45415
- return { message: error.message || 'Something went wrong. Please try again.' };
45416
46490
  }
45417
- return { message: 'Something went wrong. Please try again.' };
45418
46491
  }
46492
+
46493
+ /**
46494
+ * useChat Hook
46495
+ * Main state management for chat functionality
46496
+ */
46497
+ // Initialize action handlers immediately to prevent tree-shaking
46498
+ initializeActionHandlers();
45419
46499
  function useChat(options) {
45420
46500
  const { widgetId, apiUrl, currentRoute, onMessage, onError, skipInitialization = false, } = options;
45421
46501
  const [state, setState] = reactExports.useState({
@@ -45424,27 +46504,24 @@
45424
46504
  isLoading: false,
45425
46505
  isTyping: false,
45426
46506
  error: null,
45427
- conversationId: '', // Will be set after loading conversation
46507
+ conversationId: '',
45428
46508
  config: null,
45429
46509
  });
45430
46510
  const stateRef = reactExports.useRef(state);
45431
46511
  reactExports.useEffect(() => {
45432
46512
  stateRef.current = state;
45433
46513
  }, [state]);
45434
- // Chat history state
45435
46514
  const [conversations, setConversations] = reactExports.useState([]);
45436
- // Stream cancellation and rate limiting
45437
46515
  const abortControllerRef = reactExports.useRef(null);
46516
+ const currentRequestIdRef = reactExports.useRef(null);
45438
46517
  const lastNewChatTimeRef = reactExports.useRef(0);
45439
- const NEW_CHAT_COOLDOWN_MS = 5000; // 2 second cooldown between new chats
46518
+ const NEW_CHAT_COOLDOWN_MS = 5000;
45440
46519
  const apiClient = reactExports.useRef(new WidgetApiClient({ widgetId, apiUrl, currentRoute }));
45441
- // Update API client when currentRoute changes
45442
46520
  reactExports.useEffect(() => {
45443
46521
  apiClient.current = new WidgetApiClient({ widgetId, apiUrl, currentRoute });
45444
46522
  }, [widgetId, apiUrl, currentRoute]);
45445
46523
  // Load configuration on mount and hydrate with existing conversation if available
45446
46524
  reactExports.useEffect(() => {
45447
- // Skip initialization in preview mode
45448
46525
  if (skipInitialization) {
45449
46526
  return;
45450
46527
  }
@@ -45481,7 +46558,7 @@
45481
46558
  }));
45482
46559
  // Setup resume callbacks for incomplete actions
45483
46560
  if (conversationId) {
45484
- setupActionResumeCallbacks(hydratedMessages, apiClient.current, conversationId, setState, onMessage ?? (() => { }));
46561
+ setupActionResumeCallbacks(hydratedMessages, apiClient.current, conversationId, setState, onMessage ?? (() => { }), createStreamState, registerActionResumeCallback);
45485
46562
  }
45486
46563
  }
45487
46564
  catch (error) {
@@ -45498,14 +46575,13 @@
45498
46575
  initialize();
45499
46576
  return () => {
45500
46577
  isMounted = false;
45501
- // Cleanup resume callbacks
45502
46578
  state.messages.forEach(message => {
45503
46579
  if (message.action?.toolCallId) {
45504
46580
  unregisterActionResumeCallback(message.action.toolCallId);
45505
46581
  }
45506
46582
  });
45507
46583
  };
45508
- }, [widgetId, apiUrl, onError]);
46584
+ }, [widgetId, apiUrl, onError, skipInitialization]);
45509
46585
  // Save conversation when messages change
45510
46586
  reactExports.useEffect(() => {
45511
46587
  const persistConversation = state.config?.settings.persistConversation ?? true;
@@ -45521,19 +46597,15 @@
45521
46597
  const hasFiles = !!files && files.length > 0;
45522
46598
  if (!trimmedContent && !hasFiles)
45523
46599
  return;
45524
- // Block parallel streams - don't allow sending while already streaming
45525
46600
  if (stateRef.current.isTyping) {
45526
46601
  console.warn('[Widget] Cannot send message while streaming is in progress');
45527
46602
  return;
45528
46603
  }
45529
- // Cancel any existing stream before starting new one
45530
46604
  if (abortControllerRef.current) {
45531
46605
  abortControllerRef.current.abort();
45532
46606
  abortControllerRef.current = null;
45533
46607
  }
45534
- // Create new abort controller for this stream
45535
46608
  abortControllerRef.current = new AbortController();
45536
- // Strip [EXECUTE_ACTION:...] prefix from displayed message (but keep for API)
45537
46609
  const displayContent = trimmedContent.replace(/^\[EXECUTE_ACTION:[^\]]+\]\s*/, '');
45538
46610
  const userMessage = {
45539
46611
  id: generateMessageId(),
@@ -45544,12 +46616,11 @@
45544
46616
  timestamp: new Date().toISOString(),
45545
46617
  sources: [],
45546
46618
  };
45547
- // Add user message immediately
45548
46619
  setState(prev => ({
45549
46620
  ...prev,
45550
46621
  messages: [...prev.messages, userMessage],
45551
- isLoading: false, // Don't show loading, will show typing when stream starts
45552
- isTyping: true, // Show typing indicator immediately
46622
+ isLoading: false,
46623
+ isTyping: true,
45553
46624
  error: null,
45554
46625
  }));
45555
46626
  onMessage?.(userMessage);
@@ -45589,26 +46660,27 @@
45589
46660
  }
45590
46661
  catch (uploadError) {
45591
46662
  console.error('Failed to upload file:', uploadError);
45592
- // Continue with other files
45593
46663
  }
45594
46664
  }
45595
46665
  }
45596
- // Stream the response
45597
46666
  let lastStreamedMessage = null;
45598
46667
  const streamState = createStreamState();
45599
- // Capture the abort controller and conversation ID for this specific stream
46668
+ currentRequestIdRef.current = streamState.requestId;
45600
46669
  const currentAbortController = abortControllerRef.current;
45601
46670
  const streamConversationId = conversationId;
45602
- const stream = apiClient.current.sendAgentMessageStream(conversationId, trimmedContent, fileIds);
46671
+ const streamRequestId = streamState.requestId;
46672
+ const stream = apiClient.current.sendAgentMessageStream(conversationId, trimmedContent, fileIds, currentAbortController?.signal);
45603
46673
  for await (const event of stream) {
45604
- // Check if stream was aborted or conversation changed
45605
- if (currentAbortController?.signal.aborted || stateRef.current.conversationId !== streamConversationId) {
45606
- console.log('[Widget] Stream aborted or conversation changed, stopping event processing');
46674
+ if (currentAbortController?.signal.aborted ||
46675
+ stateRef.current.conversationId !== streamConversationId ||
46676
+ currentRequestIdRef.current !== streamRequestId) {
46677
+ console.log('[Widget] Stream aborted, conversation changed, or superseded by new request');
45607
46678
  break;
45608
46679
  }
45609
46680
  if (event.type === "action_request") {
45610
- // Check again before expensive operation
45611
- if (currentAbortController?.signal.aborted || stateRef.current.conversationId !== streamConversationId) {
46681
+ if (currentAbortController?.signal.aborted ||
46682
+ stateRef.current.conversationId !== streamConversationId ||
46683
+ currentRequestIdRef.current !== streamRequestId) {
45612
46684
  break;
45613
46685
  }
45614
46686
  await handleActionLoop(apiClient.current, event, streamState, (message) => {
@@ -45620,30 +46692,26 @@
45620
46692
  lastStreamedMessage = message;
45621
46693
  }, setState);
45622
46694
  }
45623
- // Only finalize if this stream wasn't aborted
45624
- if (currentAbortController?.signal.aborted || stateRef.current.conversationId !== streamConversationId) {
45625
- console.log('[Widget] Stream was aborted, skipping finalization');
46695
+ if (currentAbortController?.signal.aborted ||
46696
+ stateRef.current.conversationId !== streamConversationId ||
46697
+ currentRequestIdRef.current !== streamRequestId) {
46698
+ console.log('[Widget] Stream was aborted or superseded, skipping finalization');
45626
46699
  return;
45627
46700
  }
45628
- // Stream completed - finalize state
45629
46701
  setState(prev => ({
45630
46702
  ...prev,
45631
46703
  isLoading: false,
45632
46704
  isTyping: false,
45633
46705
  }));
45634
- // Notify about final message
45635
46706
  if (lastStreamedMessage) {
45636
46707
  onMessage?.(lastStreamedMessage);
45637
46708
  }
45638
- // Generate follow-up suggestions asynchronously
45639
46709
  const enableFollowUps = state.config?.settings.enableFollowUpSuggestions !== false;
45640
46710
  const actionIds = state.config?.actions || [];
45641
46711
  if (enableFollowUps) {
45642
- // Don't await - let it run in background
45643
46712
  apiClient.current.generateFollowUps(stateRef.current.messages, actionIds)
45644
46713
  .then(suggestions => {
45645
46714
  if (suggestions.length > 0) {
45646
- // Attach suggestions to the last assistant message
45647
46715
  setState(prev => {
45648
46716
  const messages = [...prev.messages];
45649
46717
  for (let i = messages.length - 1; i >= 0; i--) {
@@ -45672,7 +46740,7 @@
45672
46740
  },
45673
46741
  timestamp: new Date().toISOString(),
45674
46742
  sources: [],
45675
- isError: !fallbackMessage, // Only mark as error if using default message
46743
+ isError: !fallbackMessage,
45676
46744
  };
45677
46745
  setState(prev => ({
45678
46746
  ...prev,
@@ -45684,9 +46752,6 @@
45684
46752
  onError?.(err);
45685
46753
  }
45686
46754
  }, [state.conversationId, state.config, state.messages, onMessage, onError]);
45687
- /**
45688
- * Clear all messages
45689
- */
45690
46755
  const clearMessages = reactExports.useCallback(() => {
45691
46756
  setState(prev => ({
45692
46757
  ...prev,
@@ -45699,9 +46764,6 @@
45699
46764
  clearConversation(widgetId);
45700
46765
  }
45701
46766
  }, [widgetId, state.config?.settings.persistConversation]);
45702
- /**
45703
- * Submit feedback for a message
45704
- */
45705
46767
  const submitFeedback = reactExports.useCallback(async (messageId, feedback) => {
45706
46768
  try {
45707
46769
  const message = state.messages.find(msg => msg.id === messageId);
@@ -45711,7 +46773,6 @@
45711
46773
  : undefined;
45712
46774
  console.log('Submitting feedback:', { conversationId: state.conversationId, messageId, feedback });
45713
46775
  await apiClient.current.submitFeedback(state.conversationId, messageId, feedback, meta);
45714
- // Update message with feedback
45715
46776
  setState(prev => ({
45716
46777
  ...prev,
45717
46778
  messages: prev.messages.map(msg => msg.id === messageId
@@ -45726,9 +46787,51 @@
45726
46787
  onError?.(err);
45727
46788
  }
45728
46789
  }, [state.conversationId, onError]);
45729
- /**
45730
- * Load conversation history list from localStorage
45731
- */
46790
+ const dismissAction = reactExports.useCallback(async (toolCallId) => {
46791
+ if (!toolCallId)
46792
+ return;
46793
+ const dismissedAt = new Date().toISOString();
46794
+ setState(prev => ({
46795
+ ...prev,
46796
+ messages: prev.messages.map((message) => {
46797
+ if (message.action?.toolCallId !== toolCallId) {
46798
+ return message;
46799
+ }
46800
+ if (!message.action) {
46801
+ return message;
46802
+ }
46803
+ return {
46804
+ ...message,
46805
+ action: {
46806
+ ...message.action,
46807
+ hidden: true,
46808
+ dismissedAt,
46809
+ dismissedBy: "user",
46810
+ done: true,
46811
+ },
46812
+ };
46813
+ }),
46814
+ isTyping: true,
46815
+ isLoading: false,
46816
+ }));
46817
+ unregisterActionResumeCallback(toolCallId);
46818
+ const conversationId = stateRef.current.conversationId;
46819
+ if (!conversationId) {
46820
+ setState(prev => ({ ...prev, isTyping: false }));
46821
+ return;
46822
+ }
46823
+ try {
46824
+ const streamState = createStreamState();
46825
+ for await (const event of apiClient.current.dismissAgentMessageStream(conversationId, toolCallId)) {
46826
+ handleStreamEvent(event, streamState, onMessage ?? (() => { }), setState);
46827
+ }
46828
+ setState(prev => ({ ...prev, isTyping: false, isLoading: false }));
46829
+ }
46830
+ catch (error) {
46831
+ console.error("[Widget] dismissAction error:", error);
46832
+ setState(prev => ({ ...prev, isTyping: false, isLoading: false }));
46833
+ }
46834
+ }, [onMessage]);
45732
46835
  const loadConversations = reactExports.useCallback(() => {
45733
46836
  const persistConversation = state.config?.settings.persistConversation ?? true;
45734
46837
  if (!persistConversation || !isStorageAvailable()) {
@@ -45745,13 +46848,11 @@
45745
46848
  })));
45746
46849
  }, [widgetId, state.config?.settings.persistConversation]);
45747
46850
  const switchConversation = reactExports.useCallback(async (conversationId) => {
45748
- // Cancel any active stream before switching conversations
45749
46851
  if (abortControllerRef.current) {
45750
46852
  abortControllerRef.current.abort();
45751
46853
  abortControllerRef.current = null;
45752
46854
  }
45753
46855
  const persistConversation = state.config?.settings.persistConversation ?? true;
45754
- // First try to load from localStorage
45755
46856
  if (persistConversation && isStorageAvailable()) {
45756
46857
  const stored = loadConversationById(widgetId, conversationId);
45757
46858
  if (stored) {
@@ -45770,7 +46871,6 @@
45770
46871
  try {
45771
46872
  const conversation = await apiClient.current.getOrCreateConversation(conversationId);
45772
46873
  const hydratedMessages = hydrateMessages(conversation.messages);
45773
- // Clear old resume callbacks
45774
46874
  state.messages.forEach(message => {
45775
46875
  if (message.action?.toolCallId) {
45776
46876
  unregisterActionResumeCallback(message.action.toolCallId);
@@ -45782,9 +46882,7 @@
45782
46882
  messages: hydratedMessages,
45783
46883
  isLoading: false,
45784
46884
  }));
45785
- // Setup new resume callbacks
45786
- setupActionResumeCallbacks(hydratedMessages, apiClient.current, conversation.id, setState, onMessage ?? (() => { }));
45787
- // Save to local storage
46885
+ setupActionResumeCallbacks(hydratedMessages, apiClient.current, conversation.id, setState, onMessage ?? (() => { }), createStreamState, registerActionResumeCallback);
45788
46886
  if (persistConversation && isStorageAvailable()) {
45789
46887
  saveConversation(widgetId, conversation.id, hydratedMessages);
45790
46888
  }
@@ -45795,19 +46893,16 @@
45795
46893
  }
45796
46894
  }, [widgetId, state.config?.settings.persistConversation]);
45797
46895
  const startNewConversation = reactExports.useCallback(() => {
45798
- // Rate limiting - prevent spamming new chats
45799
46896
  const now = Date.now();
45800
46897
  if (now - lastNewChatTimeRef.current < NEW_CHAT_COOLDOWN_MS) {
45801
46898
  console.warn('[Widget] New chat rate limited - please wait');
45802
46899
  return;
45803
46900
  }
45804
46901
  lastNewChatTimeRef.current = now;
45805
- // Cancel any active stream before starting new conversation
45806
46902
  if (abortControllerRef.current) {
45807
46903
  abortControllerRef.current.abort();
45808
46904
  abortControllerRef.current = null;
45809
46905
  }
45810
- // Reset typing state if stream was active
45811
46906
  setState(prev => ({
45812
46907
  ...prev,
45813
46908
  messages: [],
@@ -45826,11 +46921,8 @@
45826
46921
  if (!persistConversation || !isStorageAvailable()) {
45827
46922
  return;
45828
46923
  }
45829
- // Delete from storage
45830
46924
  deleteConversation(widgetId, conversationId);
45831
- // Update local state
45832
46925
  setConversations(prev => prev.filter(c => c.id !== conversationId));
45833
- // If we deleted the current conversation, clear it
45834
46926
  if (state.conversationId === conversationId) {
45835
46927
  setState(prev => ({
45836
46928
  ...prev,
@@ -45840,6 +46932,43 @@
45840
46932
  }));
45841
46933
  }
45842
46934
  }, [widgetId, state.config?.settings.persistConversation, state.conversationId]);
46935
+ const createDemoConversation = reactExports.useCallback(async (userMessage, assistantMessage) => {
46936
+ try {
46937
+ const result = await apiClient.current.createDemoConversation(userMessage, assistantMessage);
46938
+ if (result.success && result.id) {
46939
+ // Update state with the new conversation ID
46940
+ setState(prev => ({
46941
+ ...prev,
46942
+ conversationId: result.id,
46943
+ }));
46944
+ // Save to local storage if persistence is enabled
46945
+ const persistConversation = state.config?.settings.persistConversation ?? true;
46946
+ if (persistConversation && isStorageAvailable()) {
46947
+ const demoMessages = [
46948
+ {
46949
+ id: generateMessageId(),
46950
+ message: { role: 'user', content: userMessage },
46951
+ timestamp: new Date().toISOString(),
46952
+ sources: [],
46953
+ },
46954
+ {
46955
+ id: generateMessageId(),
46956
+ message: { role: 'assistant', content: assistantMessage },
46957
+ timestamp: new Date(Date.now() + 1000).toISOString(),
46958
+ sources: [],
46959
+ },
46960
+ ];
46961
+ saveConversation(widgetId, result.id, demoMessages);
46962
+ }
46963
+ return result.id;
46964
+ }
46965
+ return null;
46966
+ }
46967
+ catch (error) {
46968
+ console.error('[useChat] Failed to create demo conversation:', error);
46969
+ return null;
46970
+ }
46971
+ }, [widgetId, state.config?.settings.persistConversation]);
45843
46972
  return {
45844
46973
  messages: state.messages,
45845
46974
  isLoading: state.isLoading,
@@ -45850,20 +46979,29 @@
45850
46979
  sendMessage,
45851
46980
  clearMessages,
45852
46981
  submitFeedback,
45853
- // Chat history features
46982
+ dismissAction,
45854
46983
  conversations,
45855
46984
  loadConversations,
45856
46985
  switchConversation,
45857
46986
  startNewConversation,
45858
46987
  deleteConversation: deleteConversation$1,
46988
+ createDemoConversation,
45859
46989
  };
45860
46990
  }
45861
46991
 
46992
+ const DataPolicyView = ({ config, widgetName, }) => {
46993
+ const headerTitle = widgetName || config?.appearance?.headerTitle || 'AI Assistant';
46994
+ const hasFileUpload = config?.settings?.enableFileUpload ?? false;
46995
+ const persistsConversation = config?.settings?.persistConversation ?? true;
46996
+ return (jsxRuntimeExports.jsx("div", { className: "ai-chat-data-policy-view", children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-content", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-data-policy-intro", children: jsxRuntimeExports.jsxs("p", { children: ["This privacy notice informs you pursuant to Art. 13 GDPR about how ", jsxRuntimeExports.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."] }) }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntimeExports.jsx("h3", { children: "Controller / Contact" }), jsxRuntimeExports.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." })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntimeExports.jsx("h3", { children: "Processed Data" }), jsxRuntimeExports.jsxs("p", { children: ["The chat processes the following categories of data. ", jsxRuntimeExports.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 && (jsxRuntimeExports.jsxs("p", { children: [jsxRuntimeExports.jsx("strong", { children: "Uploaded Files" }), " that you transmit to the chat are processed to handle your request. Processing may include extracting text or information."] })), jsxRuntimeExports.jsxs("p", { children: [jsxRuntimeExports.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."] }), jsxRuntimeExports.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." })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntimeExports.jsx("h3", { children: "Purposes and Legal Bases" }), jsxRuntimeExports.jsxs("p", { children: [jsxRuntimeExports.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)."] }), jsxRuntimeExports.jsxs("p", { children: [jsxRuntimeExports.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."] }), jsxRuntimeExports.jsxs("p", { children: [jsxRuntimeExports.jsx("strong", { children: "Consent-based processing" }), " may occur if the operator provides for this (Art. 6 Para. 1 lit. a GDPR)."] })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntimeExports.jsx("h3", { children: "Recipients and Processors" }), jsxRuntimeExports.jsxs("p", { children: [jsxRuntimeExports.jsx("strong", { children: "Hosting/IT Service Providers" }), " may be used by the operator for hosting, logging, monitoring, and infrastructure."] }), jsxRuntimeExports.jsxs("p", { children: [jsxRuntimeExports.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)."] }), jsxRuntimeExports.jsxs("p", { children: [jsxRuntimeExports.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."] })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntimeExports.jsx("h3", { children: "Retention Period" }), persistsConversation ? (jsxRuntimeExports.jsxs("p", { children: [jsxRuntimeExports.jsx("strong", { children: "Chat History" }), " may be stored to continue the conversation across multiple sessions."] })) : (jsxRuntimeExports.jsxs("p", { children: [jsxRuntimeExports.jsx("strong", { children: "Chat History" }), " is not permanently stored and ends when the chat is closed."] })), hasFileUpload && (jsxRuntimeExports.jsxs("p", { children: [jsxRuntimeExports.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."] })), jsxRuntimeExports.jsxs("p", { children: [jsxRuntimeExports.jsx("strong", { children: "Technical Logs" }), " may be stored for a limited period to ensure secure operation."] })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntimeExports.jsx("h3", { children: "Your Rights (Data Subject Rights)" }), jsxRuntimeExports.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)." }), jsxRuntimeExports.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." })] })] }) }));
46997
+ };
46998
+
45862
46999
  const MenuIcon = () => (jsxRuntimeExports.jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("line", { x1: "4", y1: "10", x2: "20", y2: "10" }), jsxRuntimeExports.jsx("line", { x1: "10", y1: "14", x2: "20", y2: "14" })] }));
45863
47000
  const PlusIcon = () => (jsxRuntimeExports.jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("line", { x1: "12", y1: "5", x2: "12", y2: "19" }), jsxRuntimeExports.jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" })] }));
45864
47001
  const TrashIcon = () => (jsxRuntimeExports.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M3 6h18" }), jsxRuntimeExports.jsx("path", { d: "M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" }), jsxRuntimeExports.jsx("path", { d: "M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" })] }));
45865
47002
  const CloseIcon = () => (jsxRuntimeExports.jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), jsxRuntimeExports.jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }));
45866
- const ChatWindow = ({ messages, isLoading, isTyping, error, config, onSendMessage, onClose: _onClose, onFeedback, onActionClick,
47003
+ const BackIcon = () => (jsxRuntimeExports.jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M19 12H5" }), jsxRuntimeExports.jsx("path", { d: "M12 19l-7-7 7-7" })] }));
47004
+ const ChatWindow = ({ messages, isLoading, isTyping, config, onSendMessage, onClose: _onClose, onFeedback, onActionClick, onActionDismiss,
45867
47005
  // Chat history props (only active when persistConversation is true)
45868
47006
  conversations = [], onLoadConversations, onSwitchConversation, onStartNewConversation, onDeleteConversation, currentConversationId,
45869
47007
  // Override props for live preview
@@ -45880,6 +47018,8 @@
45880
47018
  const inputPlaceholder = placeholderOverride ?? appearance?.placeholder ?? 'Ask me anything...';
45881
47019
  // Track if history panel is open
45882
47020
  const [showHistory, setShowHistory] = reactExports.useState(false);
47021
+ // Track if data policy view is open
47022
+ const [showDataPolicy, setShowDataPolicy] = reactExports.useState(false);
45883
47023
  // Scroll button state (managed by MessageList)
45884
47024
  const [showScrollButton, setShowScrollButton] = reactExports.useState(false);
45885
47025
  const [scrollToBottom, setScrollToBottom] = reactExports.useState(null);
@@ -45889,6 +47029,13 @@
45889
47029
  }, []);
45890
47030
  // History exit animation when starting a new chat from overview
45891
47031
  const [isHistoryExiting, setIsHistoryExiting] = reactExports.useState(false);
47032
+ // Handle data policy click
47033
+ const handleDataPolicyClick = reactExports.useCallback(() => {
47034
+ setShowDataPolicy(true);
47035
+ }, []);
47036
+ const handleDataPolicyBack = reactExports.useCallback(() => {
47037
+ setShowDataPolicy(false);
47038
+ }, []);
45892
47039
  // Load conversations when history panel opens
45893
47040
  const handleOpenHistory = () => {
45894
47041
  setShowHistory(true);
@@ -45936,10 +47083,22 @@
45936
47083
  // The backend will detect and trigger the action based on the message
45937
47084
  onSendMessage(question);
45938
47085
  };
45939
- return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-window size-${size}`, role: "dialog", "aria-label": "Chat window", children: [jsxRuntimeExports.jsx("div", { className: `ai-chat-header ${showHistory ? 'is-history' : ''}`, children: showHistory ? (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-title", children: headerTitle }), jsxRuntimeExports.jsx("button", { className: "ai-chat-header-button", onClick: handleNewConversation, "aria-label": "New chat", children: jsxRuntimeExports.jsx(PlusIcon, {}) })] })) : (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-header-content", children: [appearance?.logo && (jsxRuntimeExports.jsx("img", { src: appearance.logo, alt: "Logo", className: "ai-chat-logo" })), jsxRuntimeExports.jsx("div", { className: "ai-chat-title", children: headerTitle })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-header-actions", children: [canShowHistory && (jsxRuntimeExports.jsx("button", { className: "ai-chat-header-button", onClick: handleOpenHistory, "aria-label": "Chat overview", children: jsxRuntimeExports.jsx(MenuIcon, {}) })), jsxRuntimeExports.jsx("button", { className: "ai-chat-close-button header-close-button", onClick: _onClose, "aria-label": "Close chat", children: jsxRuntimeExports.jsx(CloseIcon, {}) })] })] })) }), showHistory ? (jsxRuntimeExports.jsxs("div", { className: "ai-chat-history-panel", children: [conversations.length === 0 ? (jsxRuntimeExports.jsx("div", { className: "ai-chat-history-empty", children: "No previous conversations" })) : (jsxRuntimeExports.jsx("div", { className: `ai-chat-history-list ${isHistoryExiting ? 'exiting' : ''}`, children: conversations.map((conv) => (jsxRuntimeExports.jsx("div", { className: `ai-chat-history-item ${conv.id === currentConversationId ? 'active' : ''}`, onClick: () => handleSelectConversation(conv.id), children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-history-item-content", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-history-item-preview", children: conv.preview }), onDeleteConversation && (jsxRuntimeExports.jsx("button", { className: "ai-chat-history-item-delete", onClick: (e) => {
47086
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-window size-${size}`, role: "dialog", "aria-label": "Chat window", children: [jsxRuntimeExports.jsx("div", { className: `ai-chat-header ${showHistory ? 'is-history' : ''} ${showDataPolicy ? 'is-data-policy' : ''}`, children: showDataPolicy ? (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("button", { className: "ai-chat-header-button", onClick: handleDataPolicyBack, "aria-label": "Back to chat", children: jsxRuntimeExports.jsx(BackIcon, {}) }), jsxRuntimeExports.jsx("div", { className: "ai-chat-title", children: "Privacy Notice" })] })) : showHistory ? (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-title", children: headerTitle }), jsxRuntimeExports.jsx("button", { className: "ai-chat-header-button", onClick: handleNewConversation, "aria-label": "New chat", children: jsxRuntimeExports.jsx(PlusIcon, {}) })] })) : (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-header-content", children: [appearance?.logo && (jsxRuntimeExports.jsx("img", { src: appearance.logo, alt: "Logo", className: "ai-chat-logo" })), jsxRuntimeExports.jsx("div", { className: "ai-chat-title", children: headerTitle })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-header-actions", children: [canShowHistory && (jsxRuntimeExports.jsx("button", { className: "ai-chat-header-button", onClick: handleOpenHistory, "aria-label": "Chat overview", children: jsxRuntimeExports.jsx(MenuIcon, {}) })), jsxRuntimeExports.jsx("button", { className: "ai-chat-close-button header-close-button", onClick: _onClose, "aria-label": "Close chat", children: jsxRuntimeExports.jsx(CloseIcon, {}) })] })] })) }), showDataPolicy ? (jsxRuntimeExports.jsx(DataPolicyView, { config: config, onBack: handleDataPolicyBack, widgetName: headerTitle })) : showHistory ? (
47087
+ /* History Panel */
47088
+ jsxRuntimeExports.jsxs("div", { className: "ai-chat-history-panel", children: [conversations.length === 0 ? (jsxRuntimeExports.jsx("div", { className: "ai-chat-history-empty", children: "No previous conversations" })) : (jsxRuntimeExports.jsx("div", { className: `ai-chat-history-list ${isHistoryExiting ? 'exiting' : ''}`, children: conversations.map((conv) => (jsxRuntimeExports.jsx("div", { className: `ai-chat-history-item ${conv.id === currentConversationId ? 'active' : ''}`, onClick: () => handleSelectConversation(conv.id), children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-history-item-content", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-history-item-preview", children: conv.preview }), onDeleteConversation && (jsxRuntimeExports.jsx("button", { className: "ai-chat-history-item-delete", onClick: (e) => {
45940
47089
  e.stopPropagation();
45941
47090
  onDeleteConversation(conv.id);
45942
- }, "aria-label": "Delete conversation", children: jsxRuntimeExports.jsx(TrashIcon, {}) }))] }) }, conv.id))) })), jsxRuntimeExports.jsx(MessageInput, { onSend: (text) => handleSendFromOverview(text), placeholder: inputPlaceholder, disabled: isLoading, enableFileUpload: settings?.enableFileUpload })] })) : (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [error && (jsxRuntimeExports.jsx("div", { className: "ai-chat-error", role: "alert", children: error })), maxMessages && userMessageCount >= maxMessages - 2 && !isLimitReached && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-warning", role: "alert", children: [maxMessages - userMessageCount, " message", maxMessages - userMessageCount !== 1 ? 's' : '', " remaining"] })), isLimitReached && (jsxRuntimeExports.jsx("div", { className: "ai-chat-error", role: "alert", children: "Message limit reached. Please start a new conversation." })), jsxRuntimeExports.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 }), jsxRuntimeExports.jsx(ScrollButton, { onClick: () => scrollToBottom?.(), visible: showScrollButton }), jsxRuntimeExports.jsx(MessageInput, { onSend: onSendMessage, placeholder: isLimitReached ? 'Message limit reached' : (isTyping ? 'Waiting for response...' : inputPlaceholder), disabled: isLoading || isTyping || isLimitReached, enableFileUpload: settings?.enableFileUpload })] }))] }));
47091
+ }, "aria-label": "Delete conversation", children: jsxRuntimeExports.jsx(TrashIcon, {}) }))] }) }, conv.id))) })), jsxRuntimeExports.jsx(MessageInput, { onSend: (text) => handleSendFromOverview(text), placeholder: inputPlaceholder, disabled: isLoading, enableFileUpload: settings?.enableFileUpload, showDataPolicy: settings?.showDataPolicy ?? true, onDataPolicyClick: handleDataPolicyClick })] })) : (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [maxMessages && userMessageCount >= maxMessages - 2 && !isLimitReached && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-warning", role: "alert", children: [maxMessages - userMessageCount, " message", maxMessages - userMessageCount !== 1 ? 's' : '', " remaining"] })), isLimitReached && (jsxRuntimeExports.jsx("div", { className: "ai-chat-error", role: "alert", children: "Message limit reached. Please start a new conversation." })), (() => {
47092
+ console.log('[DEBUG ChatWindow] Rendering MessageList with', messages.length, 'messages');
47093
+ messages.forEach((m, i) => {
47094
+ console.log(`[DEBUG ChatWindow] msg ${i}:`, { role: m.message.role, hasAction: !!m.action, impl: m.action?.implementation });
47095
+ });
47096
+ console.log('[DEBUG ChatWindow] getActionRenderer available:', !!getActionRenderer);
47097
+ if (getActionRenderer) {
47098
+ console.log('[DEBUG ChatWindow] Testing renderer for query-contact-directory:', !!getActionRenderer('query-contact-directory'));
47099
+ }
47100
+ return null;
47101
+ })(), jsxRuntimeExports.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 && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-page-disclaimer", children: [jsxRuntimeExports.jsx("span", { children: "AI-generated responses may be inaccurate." }), jsxRuntimeExports.jsx("button", { type: "button", className: "ai-chat-page-disclaimer-link", onClick: handleDataPolicyClick, children: "Privacy Notice" })] })), jsxRuntimeExports.jsx(ScrollButton, { onClick: () => scrollToBottom?.(), visible: showScrollButton }), jsxRuntimeExports.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 })] }))] }));
45943
47102
  };
45944
47103
 
45945
47104
  /**
@@ -46345,7 +47504,7 @@
46345
47504
  if ( ref === void 0 ) ref = {};
46346
47505
  var insertAt = ref.insertAt;
46347
47506
 
46348
- if (typeof document === 'undefined') { return; }
47507
+ if (!css || typeof document === 'undefined') { return; }
46349
47508
 
46350
47509
  var head = document.head || document.getElementsByTagName('head')[0];
46351
47510
  var style = document.createElement('style');
@@ -46368,7 +47527,10 @@
46368
47527
  }
46369
47528
  }
46370
47529
 
46371
- 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%}";
47530
+ 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)}}";
47531
+ styleInject(css_248z$1);
47532
+
47533
+ 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}";
46372
47534
  styleInject(css_248z);
46373
47535
 
46374
47536
  // Icon components mapping
@@ -46376,11 +47538,23 @@
46376
47538
  FiMessageCircle: () => (jsxRuntimeExports.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.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" }) })),
46377
47539
  FiChevronDown: () => (jsxRuntimeExports.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("polyline", { points: "6 9 12 15 18 9" }) })),
46378
47540
  };
46379
- 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', }) => {
47541
+ 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', }) => {
46380
47542
  const [isOpen, setIsOpen] = reactExports.useState(defaultOpen);
47543
+ const [inputBarValue, setInputBarValue] = reactExports.useState('');
46381
47544
  const [autoDetectedTheme, setAutoDetectedTheme] = reactExports.useState('light');
47545
+ const [showWelcomeBubble, setShowWelcomeBubble] = reactExports.useState(false);
46382
47546
  const widgetRef = reactExports.useRef(null);
46383
47547
  const containerRef = reactExports.useRef(null);
47548
+ // Demo mode state - track whether demo has been activated and completed
47549
+ const [demoMessages, setDemoMessages] = reactExports.useState([]);
47550
+ const [isDemoComplete, setIsDemoComplete] = reactExports.useState(false);
47551
+ const [isDemoTyping, setIsDemoTyping] = reactExports.useState(false);
47552
+ const [demoInputBarText, setDemoInputBarText] = reactExports.useState(''); // For animating text in input bar
47553
+ const [isDemoAnimatingInput, setIsDemoAnimatingInput] = reactExports.useState(false); // True while typing into input bar
47554
+ const [isDemoActive, setIsDemoActive] = reactExports.useState(false); // True when demo animation is running
47555
+ const demoStartedRef = reactExports.useRef(false);
47556
+ // Track if user has sent a real message (transitions from demo to real chat)
47557
+ const [userSentRealMessage, setUserSentRealMessage] = reactExports.useState(false);
46384
47558
  // Determine mode
46385
47559
  const isEmbedded = mode === 'embedded';
46386
47560
  // Default config for preview mode
@@ -46400,6 +47574,7 @@
46400
47574
  showChatHistory: true,
46401
47575
  showTimestamps: true,
46402
47576
  showTypingIndicator: true,
47577
+ showToolCalls: false,
46403
47578
  enableFileUpload: false,
46404
47579
  enableFeedback: true,
46405
47580
  },
@@ -46425,29 +47600,54 @@
46425
47600
  ...previewConfig?.behavior,
46426
47601
  },
46427
47602
  };
46428
- // Always call useChat hook (React rules), but skip initialization in preview mode
47603
+ // Always call useChat hook (React rules), but skip initialization in preview mode or during demo
47604
+ // Skip initialization during demo to prevent loading old conversations
47605
+ // Note: We still pass the real widgetId so createDemoConversation works correctly
47606
+ const shouldSkipInit = previewMode || (demoMode && !userSentRealMessage);
46429
47607
  const chatHook = useChat({
46430
47608
  widgetId: previewMode ? '__preview__' : (widgetId || '__preview__'),
46431
47609
  apiUrl,
46432
47610
  currentRoute,
46433
- onMessage: previewMode ? undefined : onMessage,
46434
- onError: previewMode ? undefined : onError,
46435
- skipInitialization: previewMode, // Don't make API calls in preview mode
47611
+ onMessage: shouldSkipInit ? undefined : onMessage,
47612
+ onError: shouldSkipInit ? undefined : onError,
47613
+ skipInitialization: shouldSkipInit, // Don't make API calls in preview mode or during demo
46436
47614
  });
46437
47615
  // Extract values from hook or use preview defaults
46438
- const messages = previewMode ? [] : chatHook.messages;
46439
- const isLoading = previewMode ? false : chatHook.isLoading;
46440
- const isTyping = previewMode ? false : chatHook.isTyping;
46441
- const error = previewMode ? null : chatHook.error;
47616
+ const hookMessages = previewMode ? [] : chatHook.messages;
47617
+ const hookIsLoading = previewMode ? false : chatHook.isLoading;
47618
+ const hookIsTyping = previewMode ? false : chatHook.isTyping;
46442
47619
  const config = previewMode ? mergedPreviewConfig : chatHook.config;
46443
- const sendMessage = previewMode ? (() => Promise.resolve()) : chatHook.sendMessage;
47620
+ const hookSendMessage = previewMode ? (() => Promise.resolve()) : chatHook.sendMessage;
46444
47621
  const submitFeedback = previewMode ? (() => Promise.resolve()) : chatHook.submitFeedback;
47622
+ const dismissAction = previewMode ? (() => Promise.resolve()) : chatHook.dismissAction;
46445
47623
  const conversations = previewMode ? [] : chatHook.conversations;
46446
47624
  const loadConversations = previewMode ? (() => { }) : chatHook.loadConversations;
46447
47625
  const switchConversation = previewMode ? (() => Promise.resolve()) : chatHook.switchConversation;
46448
47626
  const startNewConversation = previewMode ? (() => { }) : chatHook.startNewConversation;
46449
47627
  const deleteConversation = previewMode ? (() => { }) : chatHook.deleteConversation;
47628
+ const createDemoConversation = previewMode ? (() => Promise.resolve(null)) : chatHook.createDemoConversation;
46450
47629
  const conversationId = previewMode ? '' : chatHook.conversationId;
47630
+ // Message display logic:
47631
+ // - During demo (before user sends real message): show demoMessages
47632
+ // - After user sends real message: show hookMessages
47633
+ const showDemoMessages = demoMode && demoMessages.length > 0 && !userSentRealMessage;
47634
+ const messages = showDemoMessages ? demoMessages : hookMessages;
47635
+ const isLoading = showDemoMessages ? false : hookIsLoading;
47636
+ const isTyping = showDemoMessages ? isDemoTyping : hookIsTyping;
47637
+ // Send message handler - transitions from demo to real chat when user sends first message
47638
+ const sendMessage = reactExports.useCallback((content) => {
47639
+ if (demoMode && isDemoActive && !isDemoComplete) {
47640
+ // Demo animation is still running - ignore user input
47641
+ return Promise.resolve();
47642
+ }
47643
+ // User is sending a real message - transition to real chat
47644
+ if (demoMode && !userSentRealMessage) {
47645
+ setUserSentRealMessage(true);
47646
+ // Clear demo messages so hook messages take over
47647
+ setDemoMessages([]);
47648
+ }
47649
+ return hookSendMessage(content);
47650
+ }, [demoMode, isDemoActive, isDemoComplete, userSentRealMessage, hookSendMessage]);
46451
47651
  // Auto-detect theme from background
46452
47652
  reactExports.useEffect(() => {
46453
47653
  if (!containerRef.current)
@@ -46473,8 +47673,16 @@
46473
47673
  mediaQuery.removeEventListener('change', handleMediaChange);
46474
47674
  };
46475
47675
  }, [config]);
46476
- // Handle auto-open (only for bubble mode)
47676
+ // Check if device is mobile
47677
+ const isMobile = typeof window !== 'undefined' && window.innerWidth <= 480;
47678
+ // Handle auto-open (only for bubble mode, disabled on mobile)
46477
47679
  reactExports.useEffect(() => {
47680
+ // Never auto-open on mobile devices
47681
+ if (isMobile)
47682
+ return undefined;
47683
+ // Don't auto-open if demo mode is active - let demo animation control opening
47684
+ if (demoMode && !isDemoComplete)
47685
+ return undefined;
46478
47686
  if (!isEmbedded && config?.settings.autoOpen) {
46479
47687
  const delay = config.settings.autoOpenDelay || 0;
46480
47688
  const timer = setTimeout(() => {
@@ -46484,7 +47692,7 @@
46484
47692
  return () => clearTimeout(timer);
46485
47693
  }
46486
47694
  return undefined;
46487
- }, [config, onOpen, isEmbedded]);
47695
+ }, [config, onOpen, isEmbedded, isMobile, demoMode, isDemoComplete]);
46488
47696
  // Handle close on Escape key (only for bubble mode)
46489
47697
  reactExports.useEffect(() => {
46490
47698
  if (!isOpen || isEmbedded)
@@ -46498,6 +47706,203 @@
46498
47706
  document.addEventListener('keydown', handleEscapeKey);
46499
47707
  return () => document.removeEventListener('keydown', handleEscapeKey);
46500
47708
  }, [isOpen, onClose, isEmbedded]);
47709
+ // Handle body scroll lock on mobile when widget is open
47710
+ reactExports.useEffect(() => {
47711
+ if (!isOpen || isEmbedded)
47712
+ return;
47713
+ // Only apply scroll lock on mobile
47714
+ const checkMobile = window.innerWidth <= 480;
47715
+ if (!checkMobile)
47716
+ return;
47717
+ // Add class to body to lock scrolling
47718
+ document.body.classList.add('ai-chat-widget-open');
47719
+ return () => {
47720
+ document.body.classList.remove('ai-chat-widget-open');
47721
+ };
47722
+ }, [isOpen, isEmbedded]);
47723
+ // Handle welcome bubble visibility based on frequency setting
47724
+ // Frequency options: 'always' (every page visit), 'session', 'weekly', 'monthly'
47725
+ reactExports.useEffect(() => {
47726
+ if (isEmbedded || previewMode)
47727
+ return;
47728
+ const bubbleText = welcomeBubbleText ?? config?.appearance?.welcomeBubbleText;
47729
+ if (!bubbleText) {
47730
+ setShowWelcomeBubble(false);
47731
+ return;
47732
+ }
47733
+ const frequency = config?.appearance?.welcomeBubbleFrequency ?? 'session';
47734
+ const storageKey = `ai-chat-bubble-dismissed-${widgetId || 'default'}`;
47735
+ // Check if bubble should be shown based on frequency
47736
+ const shouldShowBubble = () => {
47737
+ if (frequency === 'always') {
47738
+ // Always show on every page visit (no storage check)
47739
+ return true;
47740
+ }
47741
+ if (frequency === 'session') {
47742
+ // Show once per session
47743
+ return sessionStorage.getItem(storageKey) !== 'true';
47744
+ }
47745
+ // For weekly/monthly, use localStorage with timestamp
47746
+ try {
47747
+ const stored = localStorage.getItem(storageKey);
47748
+ if (!stored)
47749
+ return true;
47750
+ const dismissedAt = parseInt(stored, 10);
47751
+ if (isNaN(dismissedAt))
47752
+ return true;
47753
+ const now = Date.now();
47754
+ const weekMs = 7 * 24 * 60 * 60 * 1000;
47755
+ const monthMs = 30 * 24 * 60 * 60 * 1000;
47756
+ if (frequency === 'weekly') {
47757
+ return now - dismissedAt > weekMs;
47758
+ }
47759
+ if (frequency === 'monthly') {
47760
+ return now - dismissedAt > monthMs;
47761
+ }
47762
+ }
47763
+ catch {
47764
+ return true;
47765
+ }
47766
+ return true;
47767
+ };
47768
+ if (shouldShowBubble() && !isOpen) {
47769
+ setShowWelcomeBubble(true);
47770
+ }
47771
+ }, [widgetId, welcomeBubbleText, config, isOpen, isEmbedded, previewMode]);
47772
+ // Demo mode: animate typing into input bar, then open widget with conversation
47773
+ // This shows the widget in action without making expensive AI calls
47774
+ reactExports.useEffect(() => {
47775
+ // Determine trigger type early (from prop or config)
47776
+ // IMPORTANT: For demo mode, we need config to be loaded to know the trigger type
47777
+ // If config is not loaded yet, wait for it (unless triggerType prop is provided)
47778
+ const effectiveTriggerTypeForDemo = triggerType ?? config?.appearance?.triggerType ?? 'button';
47779
+ const isInputBarTrigger = effectiveTriggerTypeForDemo === 'input-bar';
47780
+ // Debug logging
47781
+ console.log('[Widget] Demo effect check:', {
47782
+ demoMode,
47783
+ isDemoComplete,
47784
+ demoStartedRef: demoStartedRef.current,
47785
+ hasDemoInput: !!demoInput,
47786
+ hasDemoOutput: !!demoOutput,
47787
+ triggerType: effectiveTriggerTypeForDemo,
47788
+ isInputBar: isInputBarTrigger,
47789
+ isOpen,
47790
+ });
47791
+ // Start demo when demoMode is enabled and we have input/output
47792
+ const shouldStartDemo = demoMode && !isDemoComplete && !demoStartedRef.current && demoInput && demoOutput;
47793
+ if (!shouldStartDemo) {
47794
+ 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' });
47795
+ return;
47796
+ }
47797
+ // Wait for config to load before starting demo (unless triggerType prop is explicitly provided)
47798
+ // This prevents the demo from starting with wrong trigger type
47799
+ if (!triggerType && !config) {
47800
+ console.log('[Widget] Demo waiting for config or triggerType prop');
47801
+ return;
47802
+ }
47803
+ // For input-bar: start immediately (widget closed, type into bar)
47804
+ // For others: wait until widget is open
47805
+ if (!isInputBarTrigger && !isOpen) {
47806
+ console.log('[Widget] Demo waiting for widget to open (non-input-bar trigger)');
47807
+ return;
47808
+ }
47809
+ console.log('[Widget] Starting demo animation...', {
47810
+ triggerType: effectiveTriggerTypeForDemo,
47811
+ isInputBar: isInputBarTrigger,
47812
+ demoInput,
47813
+ demoOutput: demoOutput?.substring(0, 50) + '...',
47814
+ });
47815
+ demoStartedRef.current = true;
47816
+ setIsDemoActive(true);
47817
+ // Use stable IDs to prevent React from remounting components
47818
+ const userMessageId = 'demo-user-message';
47819
+ const assistantMessageId = 'demo-assistant-message';
47820
+ // Helper to create a message with stable ID
47821
+ const createMessage = (id, role, content, isStreaming = false) => ({
47822
+ id,
47823
+ message: { role, content },
47824
+ timestamp: new Date().toISOString(),
47825
+ sources: [],
47826
+ isStreaming,
47827
+ });
47828
+ // Animation sequence - runs to completion even if widget is closed
47829
+ // This ensures conversation is always created and saved consistently
47830
+ const runDemoAnimation = async () => {
47831
+ // STEP 1: Create conversation IMMEDIATELY at the start
47832
+ // This ensures we have a conversation ID before any animation
47833
+ console.log('[Widget] Creating demo conversation at start...');
47834
+ let conversationId = null;
47835
+ try {
47836
+ conversationId = await createDemoConversation(demoInput, demoOutput);
47837
+ if (conversationId) {
47838
+ console.log('[Widget] Demo conversation created:', conversationId);
47839
+ }
47840
+ }
47841
+ catch (err) {
47842
+ console.warn('[Widget] Failed to create demo conversation:', err);
47843
+ }
47844
+ // STEP 2: For input-bar trigger, animate typing into input bar first
47845
+ if (isInputBarTrigger && !isOpen) {
47846
+ setIsDemoAnimatingInput(true);
47847
+ // Wait before starting to type - ensure input bar is fully visible
47848
+ await new Promise(resolve => setTimeout(resolve, 1500));
47849
+ // Type into input bar character by character
47850
+ const inputChars = demoInput.split('');
47851
+ for (let i = 0; i < inputChars.length; i++) {
47852
+ setDemoInputBarText(demoInput.slice(0, i + 1));
47853
+ // Slower typing speed for better visibility
47854
+ const delay = inputChars[i] === ' ' ? 100 : 60 + Math.random() * 40;
47855
+ await new Promise(resolve => setTimeout(resolve, delay));
47856
+ }
47857
+ // Longer pause after typing so user can read the question
47858
+ await new Promise(resolve => setTimeout(resolve, 1000));
47859
+ setIsDemoAnimatingInput(false);
47860
+ setDemoInputBarText('');
47861
+ setIsOpen(true);
47862
+ onOpen?.();
47863
+ // Let widget open animation complete
47864
+ await new Promise(resolve => setTimeout(resolve, 500));
47865
+ }
47866
+ else {
47867
+ // For non-input-bar triggers, just wait for widget to settle
47868
+ await new Promise(resolve => setTimeout(resolve, 800));
47869
+ }
47870
+ // STEP 3: Add user message
47871
+ setDemoMessages([createMessage(userMessageId, 'user', demoInput)]);
47872
+ // Show typing indicator after a pause
47873
+ await new Promise(resolve => setTimeout(resolve, 500));
47874
+ setIsDemoTyping(true);
47875
+ // "Thinking" pause
47876
+ await new Promise(resolve => setTimeout(resolve, 1200));
47877
+ setIsDemoTyping(false);
47878
+ // STEP 4: Stream the response character by character
47879
+ const chars = demoOutput.split('');
47880
+ let currentText = '';
47881
+ // Initial message with empty content
47882
+ setDemoMessages([
47883
+ createMessage(userMessageId, 'user', demoInput),
47884
+ createMessage(assistantMessageId, 'assistant', '', true),
47885
+ ]);
47886
+ await new Promise(resolve => setTimeout(resolve, 100));
47887
+ // Stream characters - continues even if widget is closed
47888
+ for (let i = 0; i < chars.length; i++) {
47889
+ currentText += chars[i];
47890
+ setDemoMessages([
47891
+ createMessage(userMessageId, 'user', demoInput),
47892
+ createMessage(assistantMessageId, 'assistant', currentText, i < chars.length - 1),
47893
+ ]);
47894
+ const delay = chars[i] === ' ' ? 12 : 20;
47895
+ await new Promise(resolve => setTimeout(resolve, delay));
47896
+ }
47897
+ // STEP 5: Mark demo complete
47898
+ await new Promise(resolve => setTimeout(resolve, 500));
47899
+ setIsDemoComplete(true);
47900
+ setIsDemoActive(false);
47901
+ console.log('[Widget] Demo animation complete');
47902
+ onDemoComplete?.();
47903
+ };
47904
+ runDemoAnimation();
47905
+ }, [demoMode, isOpen, isDemoComplete, demoInput, demoOutput, onDemoComplete, triggerType, config?.appearance?.triggerType, onOpen, createDemoConversation]);
46501
47906
  // Determine theme - use prop override if provided, otherwise auto-detect
46502
47907
  const appearanceConfig = config?.appearance;
46503
47908
  const effectiveTheme = theme ?? autoDetectedTheme;
@@ -46506,11 +47911,14 @@
46506
47911
  // Get accent color from prop or config (empty string means no accent color / vanilla mode)
46507
47912
  const accentColor = primaryColor ?? appearanceConfig?.primaryColor ?? '';
46508
47913
  // Apply prop overrides for live preview (props take priority over config)
46509
- size || appearanceConfig?.size || 'small';
47914
+ const effectiveSize = size || appearanceConfig?.size || 'small';
46510
47915
  const effectiveHeaderTitle = headerTitle ?? appearanceConfig?.headerTitle ?? '';
46511
47916
  const effectiveWelcomeTitle = welcomeTitle ?? appearanceConfig?.welcomeTitle ?? '';
46512
47917
  const effectiveWelcomeMessage = welcomeMessage ?? appearanceConfig?.welcomeMessage ?? '';
46513
47918
  const effectivePlaceholder = placeholder ?? appearanceConfig?.placeholder ?? '';
47919
+ const effectiveWelcomeBubbleText = welcomeBubbleText ?? appearanceConfig?.welcomeBubbleText ?? '';
47920
+ const effectiveTriggerType = triggerType ?? appearanceConfig?.triggerType ?? 'button';
47921
+ const effectiveTriggerText = triggerText ?? appearanceConfig?.triggerText ?? 'Chat';
46514
47922
  // Generate styles using simplified theme system
46515
47923
  const simpleAppearance = {
46516
47924
  accentColor};
@@ -46527,18 +47935,65 @@
46527
47935
  ...customStyles,
46528
47936
  ...(zIndex !== undefined ? { '--widget-z-index': String(zIndex) } : {}),
46529
47937
  };
47938
+ // Dismiss bubble and store based on frequency setting
47939
+ const dismissBubble = () => {
47940
+ setShowWelcomeBubble(false);
47941
+ const frequency = config?.appearance?.welcomeBubbleFrequency ?? 'session';
47942
+ const storageKey = `ai-chat-bubble-dismissed-${widgetId || 'default'}`;
47943
+ try {
47944
+ if (frequency === 'always') {
47945
+ // For 'always', use sessionStorage so it only hides until page refresh
47946
+ sessionStorage.setItem(storageKey, 'true');
47947
+ }
47948
+ else if (frequency === 'session') {
47949
+ sessionStorage.setItem(storageKey, 'true');
47950
+ }
47951
+ else {
47952
+ // For weekly/monthly, store timestamp in localStorage
47953
+ localStorage.setItem(storageKey, String(Date.now()));
47954
+ }
47955
+ }
47956
+ catch {
47957
+ // Ignore storage errors
47958
+ }
47959
+ };
46530
47960
  const handleToggle = () => {
46531
47961
  if (isEmbedded)
46532
47962
  return;
46533
47963
  const newState = !isOpen;
46534
47964
  setIsOpen(newState);
47965
+ // Dismiss welcome bubble when chat is opened
47966
+ if (newState && showWelcomeBubble) {
47967
+ dismissBubble();
47968
+ }
46535
47969
  if (newState) {
46536
47970
  onOpen?.();
46537
47971
  }
46538
47972
  else {
47973
+ // Demo animation continues in background when widget is closed
47974
+ // The conversation was already created at the start, so closing is safe
47975
+ // When user reopens, they'll see the current state of the demo animation
46539
47976
  onClose?.();
46540
47977
  }
46541
47978
  };
47979
+ const handleDismissBubble = (e) => {
47980
+ e.stopPropagation();
47981
+ dismissBubble();
47982
+ };
47983
+ // Handle input bar submit - opens widget and sends message
47984
+ const handleInputBarSubmit = reactExports.useCallback((e) => {
47985
+ e.preventDefault();
47986
+ if (!inputBarValue.trim() || previewMode)
47987
+ return;
47988
+ // Open the widget
47989
+ setIsOpen(true);
47990
+ onOpen?.();
47991
+ // Send the message after a brief delay to allow widget to open
47992
+ setTimeout(() => {
47993
+ sendMessage(inputBarValue.trim());
47994
+ setInputBarValue('');
47995
+ }, 100);
47996
+ }, [inputBarValue, previewMode, onOpen, sendMessage]);
46542
47997
  const handleFeedback = async (messageId, feedback) => {
46543
47998
  await submitFeedback(messageId, feedback);
46544
47999
  };
@@ -46554,21 +48009,32 @@
46554
48009
  sendMessage(actionInstruction);
46555
48010
  };
46556
48011
  // Don't render until config is loaded to avoid flash of unstyled content
48012
+ // Exception: If we have essential props (triggerType), allow rendering the trigger immediately
48013
+ // This improves perceived loading speed - users see the trigger while config loads
46557
48014
  // In preview mode, config is always available
46558
- if (!config && !previewMode) {
48015
+ const canRenderWithoutConfig = !!triggerType;
48016
+ if (!config && !previewMode && !canRenderWithoutConfig) {
46559
48017
  return null;
46560
48018
  }
46561
48019
  // Get button icon based on state
46562
48020
  const IconComponent = isOpen ? iconComponents.FiChevronDown : iconComponents.FiMessageCircle;
46563
48021
  // Embedded mode renders directly without wrapper positioning
46564
48022
  if (isEmbedded) {
46565
- return (jsxRuntimeExports.jsx("div", { ref: containerRef, className: `ai-chat-widget ai-chat-widget-embedded ${effectiveTheme}`, style: { ...mergedStyles, width: '100%', height: '100%' }, children: jsxRuntimeExports.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 }) }));
46566
- }
46567
- return (jsxRuntimeExports.jsx("div", { ref: containerRef, className: `ai-chat-widget ${effectiveTheme}`, style: mergedStyles, children: jsxRuntimeExports.jsxs("div", { ref: widgetRef, className: `ai-chat-widget-container ${effectivePosition} ${isOpen ? 'is-open' : ''}`, children: [isOpen && (jsxRuntimeExports.jsx(ChatWindow, { messages: messages, isLoading: isLoading, isTyping: isTyping, error: error, config: config, onSendMessage: sendMessage, onClose: handleToggle, onFeedback: handleFeedback, onActionClick: handleActionClick,
48023
+ return (jsxRuntimeExports.jsx("div", { ref: containerRef, className: `ai-chat-widget ai-chat-widget-embedded ${effectiveTheme}`, style: { ...mergedStyles, width: '100%', height: '100%' }, children: jsxRuntimeExports.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 }) }));
48024
+ }
48025
+ // Determine trigger class for container
48026
+ const triggerClass = effectiveTriggerType === 'pill-text'
48027
+ ? 'trigger-pill-text'
48028
+ : effectiveTriggerType === 'input-bar'
48029
+ ? 'trigger-input-bar'
48030
+ : '';
48031
+ // Size class for CSS targeting (used by input-bar trigger for width matching)
48032
+ const sizeClass = `size-${effectiveSize}`;
48033
+ return (jsxRuntimeExports.jsx("div", { ref: containerRef, className: `ai-chat-widget ${effectiveTheme}`, style: mergedStyles, children: jsxRuntimeExports.jsxs("div", { ref: widgetRef, className: `ai-chat-widget-container ${effectivePosition} ${isOpen ? 'is-open' : ''} ${containerMode ? 'container-mode' : ''} ${triggerClass} ${sizeClass}`, children: [isOpen && (jsxRuntimeExports.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,
46568
48034
  // Chat history props (only active when persistConversation is true)
46569
48035
  conversations: conversations, onLoadConversations: loadConversations, onSwitchConversation: switchConversation, onStartNewConversation: startNewConversation, onDeleteConversation: deleteConversation, currentConversationId: conversationId,
46570
48036
  // Override props for live preview
46571
- headerTitleOverride: effectiveHeaderTitle, welcomeTitleOverride: effectiveWelcomeTitle, welcomeMessageOverride: effectiveWelcomeMessage, placeholderOverride: effectivePlaceholder, suggestedQuestionsOverride: suggestedQuestions })), jsxRuntimeExports.jsx("button", { className: `ai-chat-button ${isOpen ? 'is-open' : ''}`, onClick: handleToggle, "aria-label": isOpen ? "Minimize chat" : "Open chat", children: jsxRuntimeExports.jsx("div", { className: "ai-chat-button-svg", children: jsxRuntimeExports.jsx(IconComponent, {}) }) })] }) }));
48037
+ headerTitleOverride: effectiveHeaderTitle, welcomeTitleOverride: effectiveWelcomeTitle, welcomeMessageOverride: effectiveWelcomeMessage, placeholderOverride: effectivePlaceholder, suggestedQuestionsOverride: suggestedQuestions })), effectiveTriggerType === 'button' && !isOpen && effectiveWelcomeBubbleText && (previewMode || showWelcomeBubble) && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-welcome-bubble", onClick: handleToggle, children: [jsxRuntimeExports.jsx("span", { children: effectiveWelcomeBubbleText }), jsxRuntimeExports.jsx("button", { className: "ai-chat-welcome-bubble-close", onClick: handleDismissBubble, "aria-label": "Dismiss", children: jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), jsxRuntimeExports.jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }) }), jsxRuntimeExports.jsx("div", { className: "ai-chat-welcome-bubble-arrow" })] })), effectiveTriggerType === 'button' && (jsxRuntimeExports.jsx("button", { className: `ai-chat-button ${isOpen ? 'is-open' : ''}`, onClick: handleToggle, "aria-label": isOpen ? "Minimize chat" : "Open chat", children: jsxRuntimeExports.jsx("div", { className: "ai-chat-button-svg", children: jsxRuntimeExports.jsx(IconComponent, {}) }) })), effectiveTriggerType === 'pill-text' && (jsxRuntimeExports.jsxs("button", { className: `ai-chat-trigger-pill ${isOpen ? 'is-open' : ''}`, onClick: handleToggle, "aria-label": isOpen ? "Close chat" : "Open chat", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-trigger-pill-icon", children: jsxRuntimeExports.jsx(IconComponent, {}) }), !isOpen && jsxRuntimeExports.jsx("span", { children: effectiveTriggerText })] })), effectiveTriggerType === 'input-bar' && !isOpen && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-trigger-input-container", children: [jsxRuntimeExports.jsx("button", { type: "button", className: "ai-chat-trigger-input-expand", onClick: handleToggle, "aria-label": "Open chat", children: jsxRuntimeExports.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("polyline", { points: "18 15 12 9 6 15" }) }) }), jsxRuntimeExports.jsxs("form", { className: "ai-chat-trigger-input-wrapper", onSubmit: handleInputBarSubmit, children: [jsxRuntimeExports.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" }), jsxRuntimeExports.jsx("button", { type: "submit", className: "ai-chat-trigger-input-btn", disabled: isDemoAnimatingInput ? !demoInputBarText.trim() : !inputBarValue.trim(), "aria-label": "Send message", children: jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("line", { x1: "22", y1: "2", x2: "11", y2: "13" }), jsxRuntimeExports.jsx("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })] }) })] })] }))] }) }));
46572
48038
  };
46573
48039
 
46574
48040
  /**