@chatwidgetai/chat-widget 0.3.6 → 0.3.8

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 (44) hide show
  1. package/dist/ai-chat-widget.umd.js +1562 -1380
  2. package/dist/ai-chat-widget.umd.js.map +1 -1
  3. package/dist/api/client.d.ts +12 -2
  4. package/dist/api/client.d.ts.map +1 -1
  5. package/dist/components/ChatWidget/hooks/useWidgetAppearance.d.ts +37 -0
  6. package/dist/components/ChatWidget/hooks/useWidgetAppearance.d.ts.map +1 -0
  7. package/dist/components/ChatWidget/icons.d.ts +2 -0
  8. package/dist/components/ChatWidget/icons.d.ts.map +1 -0
  9. package/dist/components/ChatWidget/parts/WidgetTriggers.d.ts +25 -0
  10. package/dist/components/ChatWidget/parts/WidgetTriggers.d.ts.map +1 -0
  11. package/dist/components/ChatWidget.d.ts.map +1 -1
  12. package/dist/components/ChatWindow.d.ts +4 -1
  13. package/dist/components/ChatWindow.d.ts.map +1 -1
  14. package/dist/components/WelcomeBubble.d.ts +12 -0
  15. package/dist/components/WelcomeBubble.d.ts.map +1 -0
  16. package/dist/components/icons.d.ts +21 -0
  17. package/dist/components/icons.d.ts.map +1 -0
  18. package/dist/components/triggers/ButtonTrigger.d.ts +11 -0
  19. package/dist/components/triggers/ButtonTrigger.d.ts.map +1 -0
  20. package/dist/components/triggers/InputBarTrigger.d.ts +18 -0
  21. package/dist/components/triggers/InputBarTrigger.d.ts.map +1 -0
  22. package/dist/components/triggers/PillTrigger.d.ts +12 -0
  23. package/dist/components/triggers/PillTrigger.d.ts.map +1 -0
  24. package/dist/components/triggers/index.d.ts +8 -0
  25. package/dist/components/triggers/index.d.ts.map +1 -0
  26. package/dist/hooks/useChat/action-handler.d.ts +17 -1
  27. package/dist/hooks/useChat/action-handler.d.ts.map +1 -1
  28. package/dist/hooks/useChat/index.d.ts +5 -0
  29. package/dist/hooks/useChat/index.d.ts.map +1 -1
  30. package/dist/hooks/useChat/message-hydration.d.ts.map +1 -1
  31. package/dist/hooks/useChat/stream-buffer.d.ts +18 -0
  32. package/dist/hooks/useChat/stream-buffer.d.ts.map +1 -0
  33. package/dist/hooks/useChat/stream-handlers.d.ts +3 -3
  34. package/dist/hooks/useChat/stream-handlers.d.ts.map +1 -1
  35. package/dist/hooks/useChat/stream-state.d.ts.map +1 -1
  36. package/dist/hooks/useChat/types.d.ts +2 -0
  37. package/dist/hooks/useChat/types.d.ts.map +1 -1
  38. package/dist/index.esm.js +1562 -1380
  39. package/dist/index.esm.js.map +1 -1
  40. package/dist/index.js +1562 -1380
  41. package/dist/index.js.map +1 -1
  42. package/dist/types/index.d.ts +5 -92
  43. package/dist/types/index.d.ts.map +1 -1
  44. package/package.json +1 -1
@@ -16898,58 +16898,83 @@
16898
16898
  return typeof data === 'object' && data !== null && 'type' in data;
16899
16899
  });
16900
16900
  }
16901
- async *continueAgentMessageStream(conversationId, toolCallId, state, signal) {
16901
+ async *dismissAgentMessageStream(conversationId, toolCallId, signal) {
16902
16902
  const headers = {
16903
16903
  'Content-Type': 'application/json',
16904
16904
  };
16905
16905
  if (this.config.currentRoute) {
16906
16906
  headers['X-Current-Route'] = this.config.currentRoute;
16907
16907
  }
16908
- const response = await fetch(`${this.config.apiUrl}/api/widget/${this.config.widgetId}/agent/continue`, {
16908
+ const response = await fetch(`${this.config.apiUrl}/api/widget/${this.config.widgetId}/agent/dismiss`, {
16909
16909
  method: 'POST',
16910
16910
  headers,
16911
16911
  body: JSON.stringify({
16912
16912
  conversationId: conversationId,
16913
16913
  toolCallId,
16914
- state,
16915
- timeZone: this.getTimeZone(),
16914
+ reason: "user",
16916
16915
  }),
16917
16916
  signal,
16918
16917
  });
16918
+ if (response.status === 204) {
16919
+ return;
16920
+ }
16919
16921
  if (!response.ok) {
16920
- throw await buildApiError(response, 'Failed to continue agent');
16922
+ throw await buildApiError(response, 'Failed to dismiss action');
16921
16923
  }
16922
16924
  yield* parseSSEStream(response, (data) => {
16923
16925
  return typeof data === 'object' && data !== null && 'type' in data;
16924
16926
  });
16925
16927
  }
16926
- async *dismissAgentMessageStream(conversationId, toolCallId, signal) {
16928
+ /**
16929
+ * Continue agent after halting action completes
16930
+ * Call this when frontend completes an action and wants to pass result back to agent
16931
+ */
16932
+ async *continueAgentAction(conversationId, toolCallId, body, signal) {
16927
16933
  const headers = {
16928
16934
  'Content-Type': 'application/json',
16929
16935
  };
16930
16936
  if (this.config.currentRoute) {
16931
16937
  headers['X-Current-Route'] = this.config.currentRoute;
16932
16938
  }
16933
- const response = await fetch(`${this.config.apiUrl}/api/widget/${this.config.widgetId}/agent/dismiss`, {
16939
+ const response = await fetch(`${this.config.apiUrl}/api/widget/${this.config.widgetId}/agent/continue`, {
16934
16940
  method: 'POST',
16935
16941
  headers,
16936
16942
  body: JSON.stringify({
16937
- conversationId: conversationId,
16943
+ conversationId,
16938
16944
  toolCallId,
16939
- reason: "user",
16945
+ body,
16946
+ timeZone: this.getTimeZone(),
16940
16947
  }),
16941
16948
  signal,
16942
16949
  });
16943
- if (response.status === 204) {
16944
- return;
16945
- }
16946
16950
  if (!response.ok) {
16947
- throw await buildApiError(response, 'Failed to dismiss action');
16951
+ throw await buildApiError(response, 'Failed to continue agent action');
16948
16952
  }
16949
16953
  yield* parseSSEStream(response, (data) => {
16950
16954
  return typeof data === 'object' && data !== null && 'type' in data;
16951
16955
  });
16952
16956
  }
16957
+ /**
16958
+ * NEW: Call action endpoint (frontend-owned flow)
16959
+ * Used for multi-step actions like booking appointments
16960
+ */
16961
+ async callActionEndpoint(actionId, endpoint, input, token) {
16962
+ const headers = {
16963
+ 'Content-Type': 'application/json',
16964
+ };
16965
+ if (token) {
16966
+ headers['Authorization'] = `Bearer ${token}`;
16967
+ }
16968
+ const response = await fetch(`${this.config.apiUrl}/api/widget/${this.config.widgetId}/actions/${actionId}/${endpoint}`, {
16969
+ method: 'POST',
16970
+ headers,
16971
+ body: JSON.stringify(input),
16972
+ });
16973
+ if (!response.ok) {
16974
+ throw await buildApiError(response, `Action endpoint '${endpoint}' failed`);
16975
+ }
16976
+ return response.json();
16977
+ }
16953
16978
  /**
16954
16979
  * Submit feedback for a message
16955
16980
  */
@@ -16980,7 +17005,8 @@
16980
17005
  }
16981
17006
  /**
16982
17007
  * Generate follow-up suggestions based on conversation context and available actions.
16983
- * Called by the frontend after receiving a "done" event from the agent.
17008
+ * @deprecated Follow-ups are now generated server-side in parallel and included in the done event.
17009
+ * This method is kept for backwards compatibility but is no longer called by the widget.
16984
17010
  */
16985
17011
  async generateFollowUps(messages, actionIds) {
16986
17012
  try {
@@ -43844,7 +43870,7 @@
43844
43870
  }
43845
43871
 
43846
43872
  // Styles are provided by global messages.css - no component-specific CSS needed
43847
- function ChevronDownIcon() {
43873
+ function ChevronDownIcon$1() {
43848
43874
  return (jsxRuntimeExports.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("polyline", { points: "6 9 12 15 18 9" }) }));
43849
43875
  }
43850
43876
  function ScrollButton({ onClick, visible, className = '' }) {
@@ -43853,7 +43879,7 @@
43853
43879
  visible && 'visible',
43854
43880
  className,
43855
43881
  ].filter(Boolean).join(' ');
43856
- return (jsxRuntimeExports.jsx("button", { type: "button", className: classes, onClick: onClick, "aria-label": "Scroll to bottom", children: jsxRuntimeExports.jsx(ChevronDownIcon, {}) }));
43882
+ return (jsxRuntimeExports.jsx("button", { type: "button", className: classes, onClick: onClick, "aria-label": "Scroll to bottom", children: jsxRuntimeExports.jsx(ChevronDownIcon$1, {}) }));
43857
43883
  }
43858
43884
 
43859
43885
  const formatToolName = (name) => {
@@ -43865,13 +43891,23 @@
43865
43891
  .join(' ');
43866
43892
  };
43867
43893
  function ToolIndicator({ badges, className = '' }) {
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))) }) }));
43894
+ // Consolidate multiple badges into a single status indicator
43895
+ const hasLoading = badges.some(b => b.status === 'loading');
43896
+ const hasError = badges.some(b => b.status === 'error');
43897
+ const status = hasLoading ? 'loading' : hasError ? 'error' : 'completed';
43898
+ // Show only the most relevant badge name, or count if multiple
43899
+ const displayName = badges.length === 1
43900
+ ? formatToolName(badges[0].name)
43901
+ : badges.length > 1
43902
+ ? `${badges.length} actions`
43903
+ : 'Processing';
43904
+ return (jsxRuntimeExports.jsx("div", { className: `ai-chat-tool-row ${className}`, children: jsxRuntimeExports.jsx("div", { className: "ai-chat-tool-badges", children: jsxRuntimeExports.jsx("div", { className: `ai-chat-tool-badge ${status}`, children: jsxRuntimeExports.jsx("span", { className: "tool-name", children: displayName }) }) }) }));
43869
43905
  }
43870
43906
 
43871
43907
  // SVG Icon components
43872
43908
  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" }) }));
43873
43909
  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" }) }));
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" }) }));
43910
+ 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" }) }));
43875
43911
  const FeedbackButtons = ({ messageId, currentFeedback, onFeedback, }) => {
43876
43912
  const [isSubmitting, setIsSubmitting] = reactExports.useState(false);
43877
43913
  const [submitted, setSubmitted] = reactExports.useState(false);
@@ -43892,7 +43928,7 @@
43892
43928
  setIsSubmitting(false);
43893
43929
  }
43894
43930
  };
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" })] }))] }));
43931
+ 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" })] }))] }));
43896
43932
  };
43897
43933
 
43898
43934
  const Message = ({ message, showTimestamp = true, enableFeedback = true, onFeedback, }) => {
@@ -43921,9 +43957,11 @@
43921
43957
  const hasContent = aiContent.trim().length > 0;
43922
43958
  if (!hasContent)
43923
43959
  return null;
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: {
43960
+ // Only show timestamp and feedback when message is complete (not streaming)
43961
+ const isComplete = !message.isStreaming;
43962
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-message assistant ${isError ? 'error' : ''} ${message.isStreaming ? 'streaming' : ''}`, children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-message-content", children: jsxRuntimeExports.jsx(Markdown, { remarkPlugins: [remarkGfm], components: {
43925
43963
  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 }))] }))] }));
43964
+ }, children: aiContent }) }), showTimestamp && isComplete && (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 }))] }))] }));
43927
43965
  }
43928
43966
  // System message rendering
43929
43967
  if (isSystem) {
@@ -43943,7 +43981,7 @@
43943
43981
  return false;
43944
43982
  const TERMINAL_STATUSES = [
43945
43983
  'completed', 'booked', 'scheduled', 'cancelled', 'failed', 'error',
43946
- 'displaying', 'clicked', 'contacted', 'submitted', 'sent'
43984
+ 'displaying', 'displayed', 'clicked', 'contacted', 'submitted', 'sent'
43947
43985
  ];
43948
43986
  const status = state.status;
43949
43987
  if (typeof status === 'string' && TERMINAL_STATUSES.includes(status)) {
@@ -43962,10 +44000,10 @@
43962
44000
  return false;
43963
44001
  if (message.isStreaming)
43964
44002
  return true;
43965
- const state = message.action.state;
43966
- return !isActionComplete(state);
44003
+ const input = message.action.input;
44004
+ return !isActionComplete(input);
43967
44005
  }
43968
- const ToolMessageGroup = ({ messages, getActionRenderer, showToolIndicator = true, accentColor, variant, onActionDismiss, }) => {
44006
+ const ToolMessageGroup = ({ messages, getActionRenderer, showToolIndicator = true, accentColor, variant, onActionDismiss, onCallEndpoint, }) => {
43969
44007
  const visibleMessages = messages.filter(message => !message.action?.hidden);
43970
44008
  const actionMessages = visibleMessages.filter(message => message.action);
43971
44009
  // Debug logging
@@ -43989,7 +44027,7 @@
43989
44027
  implementation: impl,
43990
44028
  hasRenderer: !!renderer,
43991
44029
  rendererType: renderer ? typeof renderer : 'undefined',
43992
- state: msg.action?.state,
44030
+ input: msg.action?.input,
43993
44031
  });
43994
44032
  });
43995
44033
  // If tool indicator is hidden AND there are no action cards to render, don't render anything
@@ -44016,7 +44054,7 @@
44016
44054
  console.log('[ToolMessageGroup] No renderer for:', message.action.implementation);
44017
44055
  return null;
44018
44056
  }
44019
- return (jsxRuntimeExports.jsx("div", { className: "ai-chat-tool-action", children: renderer(message, accentColor, variant, onActionDismiss) }, `action-${message.id}`));
44057
+ return (jsxRuntimeExports.jsx("div", { className: "ai-chat-tool-action", children: renderer(message, accentColor, variant, onActionDismiss, onCallEndpoint) }, `action-${message.id}`));
44020
44058
  })] }));
44021
44059
  };
44022
44060
 
@@ -44050,12 +44088,29 @@
44050
44088
  };
44051
44089
 
44052
44090
  const MAX_TEXT_LENGTH = 40;
44091
+ const STAGGER_DELAY_MS = 200; // Delay between each suggestion appearing
44053
44092
  const FollowUpSuggestions = ({ suggestions, onQuestionClick, onActionClick, accentColor, }) => {
44054
- if (!suggestions || suggestions.length === 0) {
44055
- return null;
44056
- }
44093
+ const [visibleIndices, setVisibleIndices] = reactExports.useState(new Set());
44057
44094
  // Filter out empty suggestions
44058
- const validSuggestions = suggestions.filter(s => s && s.text && s.text.trim());
44095
+ const validSuggestions = suggestions?.filter(s => s && s.text && s.text.trim()) || [];
44096
+ // Create a stable key for the current suggestions set
44097
+ const suggestionsKey = validSuggestions.map(s => s.id).join(',');
44098
+ // Stagger reveal each suggestion one at a time
44099
+ reactExports.useEffect(() => {
44100
+ // Reset when suggestions change
44101
+ setVisibleIndices(new Set());
44102
+ if (validSuggestions.length === 0)
44103
+ return;
44104
+ const timers = [];
44105
+ // Reveal each suggestion one by one
44106
+ validSuggestions.slice(0, 5).forEach((_, index) => {
44107
+ const timer = setTimeout(() => {
44108
+ setVisibleIndices(prev => new Set([...prev, index]));
44109
+ }, (index + 1) * STAGGER_DELAY_MS);
44110
+ timers.push(timer);
44111
+ });
44112
+ return () => timers.forEach(t => clearTimeout(t));
44113
+ }, [suggestionsKey]); // eslint-disable-line react-hooks/exhaustive-deps
44059
44114
  if (validSuggestions.length === 0) {
44060
44115
  return null;
44061
44116
  }
@@ -44063,8 +44118,12 @@
44063
44118
  ? { "--primary-color": accentColor }
44064
44119
  : undefined;
44065
44120
  const trimText = (text) => text.length > MAX_TEXT_LENGTH ? `${text.slice(0, MAX_TEXT_LENGTH)}...` : text;
44066
- return (jsxRuntimeExports.jsx("div", { className: "ai-chat-follow-up-suggestions", style: containerStyle, children: jsxRuntimeExports.jsx("div", { className: "ai-chat-follow-up-list", children: validSuggestions.slice(0, 5).map((suggestion) => {
44121
+ return (jsxRuntimeExports.jsx("div", { className: "ai-chat-follow-up-suggestions", style: containerStyle, children: jsxRuntimeExports.jsx("div", { className: "ai-chat-follow-up-list", children: validSuggestions.slice(0, 5).map((suggestion, index) => {
44067
44122
  const isActionSuggestion = suggestion.type === 'action';
44123
+ const isVisible = visibleIndices.has(index);
44124
+ // Only render if visible - this adds items one by one instead of showing all at once
44125
+ if (!isVisible)
44126
+ return null;
44068
44127
  const className = `ai-chat-follow-up-item ${isActionSuggestion ? 'action-type' : 'question-type'}`;
44069
44128
  const handleClick = () => {
44070
44129
  if (isActionSuggestion && onActionClick) {
@@ -44078,7 +44137,7 @@
44078
44137
  };
44079
44138
 
44080
44139
  const MessageList = (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;
44140
+ const { messages, isTyping = false, showTypingIndicator = true, showTimestamps = true, showToolCalls = false, enableFeedback = true, welcomeTitle, welcomeMessage, suggestedQuestions, accentColor, onSuggestedQuestionClick, onActionClick, onActionDismiss, onFeedback, onScrollStateChange, getActionRenderer, onCallEndpoint, variant, } = props;
44082
44141
  const containerRef = reactExports.useRef(null);
44083
44142
  const messagesEndRef = reactExports.useRef(null);
44084
44143
  const [showScrollButton, setShowScrollButton] = reactExports.useState(false);
@@ -44089,24 +44148,31 @@
44089
44148
  const lastToolMsg = [...visibleMessages].reverse().find(msg => msg.message.role === 'tool');
44090
44149
  return lastToolMsg?.action && lastToolMsg.action.done !== true;
44091
44150
  }, [visibleMessages]);
44092
- const checkScrollPosition = reactExports.useCallback(() => {
44093
- const c = containerRef.current;
44094
- if (!c)
44095
- return;
44096
- const pb = parseInt(getComputedStyle(c).paddingBottom || '0', 10);
44097
- setShowScrollButton(c.scrollHeight - c.scrollTop - c.clientHeight - pb > 24);
44098
- }, []);
44099
44151
  const scrollToBottom = reactExports.useCallback(() => {
44100
44152
  messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
44101
44153
  }, []);
44102
- reactExports.useEffect(() => { onScrollStateChange?.(showScrollButton, scrollToBottom); }, [showScrollButton, scrollToBottom, onScrollStateChange]);
44154
+ // Use IntersectionObserver to detect when the end marker is visible
44155
+ // This is more reliable than scroll position calculations
44103
44156
  reactExports.useEffect(() => {
44104
- const c = containerRef.current;
44105
- if (!c)
44157
+ const endMarker = messagesEndRef.current;
44158
+ const container = containerRef.current;
44159
+ if (!endMarker || !container)
44106
44160
  return;
44107
- c.addEventListener('scroll', checkScrollPosition);
44108
- return () => c.removeEventListener('scroll', checkScrollPosition);
44109
- }, [checkScrollPosition]);
44161
+ const observer = new IntersectionObserver((entries) => {
44162
+ // If the end marker is intersecting (visible), hide the button
44163
+ // If it's not visible, show the button
44164
+ const isAtBottom = entries[0]?.isIntersecting ?? false;
44165
+ setShowScrollButton(!isAtBottom);
44166
+ }, {
44167
+ root: container,
44168
+ // rootMargin adds extra space - if end marker is within 100px of viewport, consider it "visible"
44169
+ rootMargin: '0px 0px 100px 0px',
44170
+ threshold: 0,
44171
+ });
44172
+ observer.observe(endMarker);
44173
+ return () => observer.disconnect();
44174
+ }, []);
44175
+ reactExports.useEffect(() => { onScrollStateChange?.(showScrollButton, scrollToBottom); }, [showScrollButton, scrollToBottom, onScrollStateChange]);
44110
44176
  reactExports.useEffect(() => {
44111
44177
  const c = containerRef.current;
44112
44178
  if (!c)
@@ -44121,32 +44187,18 @@
44121
44187
  if ((isNew || isTyping) && c.scrollHeight - c.scrollTop - c.clientHeight < 150) {
44122
44188
  messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
44123
44189
  }
44124
- checkScrollPosition();
44125
- }, [visibleMessages, isTyping, checkScrollPosition]);
44190
+ }, [visibleMessages, isTyping]);
44126
44191
  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
- });
44138
44192
  const result = [];
44139
44193
  let toolGroup = [];
44140
44194
  const flush = () => {
44141
44195
  if (toolGroup.length) {
44142
- console.log('[DEBUG MessageList] Flushing tool group with', toolGroup.length, 'messages');
44143
44196
  result.push({ type: 'tool-group', messages: [...toolGroup] });
44144
44197
  toolGroup = [];
44145
44198
  }
44146
44199
  };
44147
44200
  for (const m of visibleMessages) {
44148
44201
  if (m.message.role === 'tool') {
44149
- console.log('[DEBUG MessageList] Adding to tool group:', m.id);
44150
44202
  toolGroup.push(m);
44151
44203
  }
44152
44204
  else if (m.message.role === 'user') {
@@ -44168,27 +44220,26 @@
44168
44220
  }
44169
44221
  }
44170
44222
  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
- });
44180
44223
  return result;
44181
44224
  }, [visibleMessages]);
44225
+ // Get the last assistant message's suggestions for rendering at the end
44226
+ const lastAssistantSuggestions = reactExports.useMemo(() => {
44227
+ for (let i = groupedMessages.length - 1; i >= 0; i--) {
44228
+ const item = groupedMessages[i];
44229
+ if (item.type === 'message' && item.message.message.role === 'assistant') {
44230
+ return item.message.suggestions;
44231
+ }
44232
+ }
44233
+ return undefined;
44234
+ }, [groupedMessages]);
44182
44235
  const hasSuggestions = visibleMessages.length === 0 && onSuggestedQuestionClick && suggestedQuestions?.length;
44183
44236
  const showWelcome = welcomeTitle || welcomeMessage || hasSuggestions;
44184
44237
  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) => {
44185
44238
  if (item.type === 'tool-group') {
44186
- return (jsxRuntimeExports.jsx(ToolMessageGroup, { messages: item.messages, getActionRenderer: getActionRenderer, showToolIndicator: showToolCalls, accentColor: accentColor, variant: variant, onActionDismiss: onActionDismiss }, `tg-${i}`));
44239
+ return (jsxRuntimeExports.jsx(ToolMessageGroup, { messages: item.messages, getActionRenderer: getActionRenderer, showToolIndicator: showToolCalls, accentColor: accentColor, variant: variant, onActionDismiss: onActionDismiss, onCallEndpoint: onCallEndpoint }, `tg-${i}`));
44187
44240
  }
44188
- const isLast = i === groupedMessages.length - 1;
44189
- const hasFollowUp = item.message.message.role === 'assistant' && item.message.suggestions?.length && isLast && !isTyping;
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));
44191
- }), isTyping && showTypingIndicator && !hasActiveAction && visibleMessages.length > 0 && jsxRuntimeExports.jsx(TypingIndicator, {}), jsxRuntimeExports.jsx("div", { ref: messagesEndRef })] }));
44241
+ return (jsxRuntimeExports.jsx(Message, { message: item.message, showTimestamp: showTimestamps, enableFeedback: enableFeedback, onFeedback: onFeedback, getActionRenderer: getActionRenderer, accentColor: accentColor }, item.message.id));
44242
+ }), !isTyping && lastAssistantSuggestions?.length && onSuggestedQuestionClick && (jsxRuntimeExports.jsx(FollowUpSuggestions, { suggestions: lastAssistantSuggestions, onQuestionClick: onSuggestedQuestionClick, onActionClick: onActionClick, accentColor: accentColor })), isTyping && showTypingIndicator && !hasActiveAction && visibleMessages.length > 0 && jsxRuntimeExports.jsx(TypingIndicator, {}), jsxRuntimeExports.jsx("div", { ref: messagesEndRef })] }));
44192
44243
  };
44193
44244
 
44194
44245
  const ALLOWED_EXTENSIONS = ['.pdf', '.doc', '.docx', '.txt', '.md', '.csv'];
@@ -44202,7 +44253,7 @@
44202
44253
  return (bytes / 1024).toFixed(1) + ' KB';
44203
44254
  return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
44204
44255
  };
44205
- const MessageInput = ({ onSend, placeholder = 'Type your message...', disabled = false, enableFileUpload = false, separateFromChat = true, showDataPolicy = true, onDataPolicyClick, }) => {
44256
+ const MessageInput = ({ onSend, placeholder = 'Type your message...', disabled = false, enableFileUpload = false, separateFromChat = true, showDataPolicy = true, onDataPolicyClick, onInputFocus, }) => {
44206
44257
  const [value, setValue] = reactExports.useState('');
44207
44258
  const [selectedFiles, setSelectedFiles] = reactExports.useState([]);
44208
44259
  const textareaRef = reactExports.useRef(null);
@@ -44237,492 +44288,15 @@
44237
44288
  }
44238
44289
  };
44239
44290
  const canSend = value.trim() || selectedFiles.length > 0;
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" })] }))] }))] }));
44241
- };
44242
-
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" }) }) }));
44291
+ 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, onFocus: onInputFocus, 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" })] }))] }))] }));
44245
44292
  };
44246
44293
 
44247
- function groupSlotsByDate$1(slots) {
44248
- const grouped = new Map();
44249
- for (const slot of slots) {
44250
- if (!slot || typeof slot !== 'object' || !slot.startTime || typeof slot.startTime !== 'string') {
44251
- continue;
44252
- }
44253
- const date = slot.startTime.slice(0, 10);
44254
- if (!grouped.has(date)) {
44255
- grouped.set(date, []);
44256
- }
44257
- grouped.get(date).push(slot);
44258
- }
44259
- return grouped;
44260
- }
44261
- function formatDate$1(dateStr) {
44262
- try {
44263
- const date = new Date(dateStr);
44264
- return new Intl.DateTimeFormat("en-US", {
44265
- weekday: "short",
44266
- month: "short",
44267
- day: "numeric",
44268
- }).format(date);
44269
- }
44270
- catch {
44271
- return dateStr;
44272
- }
44273
- }
44274
- function CalendarIcon$1() {
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" }) }));
44276
- }
44277
- function CheckIcon$1() {
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" }) }));
44279
- }
44280
- function ExternalLinkIcon$2() {
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" })] }));
44282
- }
44283
- function Skeleton$2({ width, height, borderRadius = '4px' }) {
44284
- return (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-skeleton-item", style: { width, height, borderRadius } }));
44285
- }
44286
- function GoogleCalendarCard({ action, onComplete, onDismiss, accentColor, className = '' }) {
44287
- const state = action.state;
44288
- const rawSlots = state.availableSlots;
44289
- const availableSlots = Array.isArray(rawSlots)
44290
- ? rawSlots.filter((slot) => slot !== null &&
44291
- slot !== undefined &&
44292
- typeof slot === "object" &&
44293
- "startTime" in slot &&
44294
- "endTime" in slot &&
44295
- typeof slot.startTime === "string" &&
44296
- typeof slot.endTime === "string")
44297
- : [];
44298
- const allowTopic = state.allowTopic !== false;
44299
- const isBooked = state.status === "booked";
44300
- const slotsByDate = groupSlotsByDate$1(availableSlots);
44301
- const dates = Array.from(slotsByDate.keys()).sort();
44302
- const [selectedDate, setSelectedDate] = reactExports.useState(dates[0] ?? "");
44303
- const [selectedSlot, setSelectedSlot] = reactExports.useState(null);
44304
- const [topic, setTopic] = reactExports.useState("");
44305
- const [error, setError] = reactExports.useState(null);
44306
- const slotsForSelectedDate = selectedDate ? slotsByDate.get(selectedDate) ?? [] : [];
44307
- const accentStyle = accentColor ? { '--action-accent': accentColor } : {};
44308
- const onConfirm = () => {
44309
- if (!selectedSlot) {
44310
- setError("Please select a time slot.");
44311
- return;
44312
- }
44313
- if (allowTopic && !topic.trim()) {
44314
- setError("Please enter a topic for the meeting.");
44315
- return;
44316
- }
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);
44559
- setIsSubmitting(true);
44560
- console.log('[MicrosoftCalendarCard] Confirming appointment:', {
44561
- slot: selectedSlot,
44562
- topic: topic.trim()
44563
- });
44564
- setTimeout(() => {
44565
- onComplete?.(action.toolCallId, {
44566
- ...action.state,
44567
- selectedSlot: {
44568
- startTime: selectedSlot.startTime,
44569
- endTime: selectedSlot.endTime,
44570
- },
44571
- topic: allowTopic ? topic.trim() : null,
44572
- });
44573
- }, 50);
44574
- };
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") {
44597
- const bookedSlot = state.selectedSlot;
44598
- const bookedTopic = state.topic;
44599
- const eventLink = state.bookedEventLink;
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
44632
- if (isSubmitting) {
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;
44718
- }
44719
-
44720
- function truncate(text, maxLength) {
44294
+ function truncate$1(text, maxLength) {
44721
44295
  if (text.length <= maxLength)
44722
44296
  return text;
44723
44297
  return text.slice(0, maxLength).trim() + '...';
44724
44298
  }
44725
- function ExternalLinkIcon() {
44299
+ function ExternalLinkIcon$2() {
44726
44300
  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" })] }));
44727
44301
  }
44728
44302
  function SingleLinkPreview({ link, onLinkClick, accentColor }) {
@@ -44741,10 +44315,10 @@
44741
44315
  e.currentTarget.parentElement.style.display = 'none';
44742
44316
  } }) })), 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
44317
  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, {}) })] }));
44318
+ } })), 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$1(link.description, 120) }))] }), jsxRuntimeExports.jsx("div", { className: "ai-chat-link-preview__arrow", children: jsxRuntimeExports.jsx(ExternalLinkIcon$2, {}) })] }));
44745
44319
  }
44746
44320
  function LinkPreviewCard({ action, onComplete, accentColor }) {
44747
- const rawState = action.state;
44321
+ const rawState = action.input;
44748
44322
  const hasCompletedRef = reactExports.useRef(false);
44749
44323
  // Provide safe defaults if state is missing
44750
44324
  const state = {
@@ -44774,11 +44348,12 @@
44774
44348
  if (state.links.length === 0) {
44775
44349
  return null;
44776
44350
  }
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))) })] }));
44351
+ const gridClass = state.links.length === 1
44352
+ ? 'ai-chat-link-preview-grid ai-chat-link-preview-grid--single'
44353
+ : state.links.length === 2
44354
+ ? 'ai-chat-link-preview-grid ai-chat-link-preview-grid--double'
44355
+ : 'ai-chat-link-preview-grid ai-chat-link-preview-grid--triple';
44356
+ 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: gridClass, children: state.links.map((link, index) => (jsxRuntimeExports.jsx(SingleLinkPreview, { link: link, onLinkClick: () => handleLinkClick(link.url), accentColor: accentColor }, index))) })] }));
44782
44357
  }
44783
44358
 
44784
44359
  function PlayIcon() {
@@ -44799,7 +44374,7 @@
44799
44374
  }
44800
44375
  }
44801
44376
  function VideoPlayerCard({ action, onComplete, accentColor }) {
44802
- const rawState = action.state;
44377
+ const rawState = action.input;
44803
44378
  const hasCompletedRef = reactExports.useRef(false);
44804
44379
  const [isPlaying, setIsPlaying] = reactExports.useState(false);
44805
44380
  // Provide safe defaults if state is missing
@@ -44910,7 +44485,7 @@
44910
44485
  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"] }))] })] })] }));
44911
44486
  }
44912
44487
  function LocationCard({ action, onComplete, accentColor, maxColumns = 3 }) {
44913
- const rawState = action.state;
44488
+ const rawState = action.input;
44914
44489
  const hasCompletedRef = reactExports.useRef(false);
44915
44490
  const state = {
44916
44491
  locations: rawState?.locations || [],
@@ -44992,7 +44567,7 @@
44992
44567
  })()] }), 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
44568
  }
44994
44569
  function ContactCard({ action, onComplete, accentColor, maxColumns = 3 }) {
44995
- const rawState = action.state;
44570
+ const rawState = action.input;
44996
44571
  const hasCompletedRef = reactExports.useRef(false);
44997
44572
  const state = {
44998
44573
  contacts: rawState?.contacts || [],
@@ -45027,11 +44602,37 @@
45027
44602
  }, 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
44603
  }
45029
44604
 
44605
+ const CloseButton = ({ onClick, className = "", ariaLabel = "Close", }) => {
44606
+ 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" }) }) }));
44607
+ };
44608
+
44609
+ function FormIcon(props) {
44610
+ return (jsxRuntimeExports.jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", ...props, children: [jsxRuntimeExports.jsx("path", { d: "M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z" }), jsxRuntimeExports.jsx("polyline", { points: "14,2 14,8 20,8" }), jsxRuntimeExports.jsx("line", { x1: "16", y1: "13", x2: "8", y2: "13" }), jsxRuntimeExports.jsx("line", { x1: "16", y1: "17", x2: "8", y2: "17" }), jsxRuntimeExports.jsx("line", { x1: "10", y1: "9", x2: "8", y2: "9" })] }));
44611
+ }
44612
+ function CheckIcon(props) {
44613
+ return (jsxRuntimeExports.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", ...props, children: jsxRuntimeExports.jsx("polyline", { points: "20,6 9,17 4,12" }) }));
44614
+ }
44615
+ function WarningIcon(props) {
44616
+ return (jsxRuntimeExports.jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", ...props, children: [jsxRuntimeExports.jsx("path", { d: "M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" }), jsxRuntimeExports.jsx("line", { x1: "12", y1: "9", x2: "12", y2: "13" }), jsxRuntimeExports.jsx("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })] }));
44617
+ }
44618
+ function SkipIcon(props) {
44619
+ return (jsxRuntimeExports.jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", ...props, children: [jsxRuntimeExports.jsx("polygon", { points: "5,4 15,12 5,20 5,4" }), jsxRuntimeExports.jsx("line", { x1: "19", y1: "5", x2: "19", y2: "19" })] }));
44620
+ }
44621
+ function BackArrowIcon(props) {
44622
+ return (jsxRuntimeExports.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", ...props, children: jsxRuntimeExports.jsx("polyline", { points: "15,18 9,12 15,6" }) }));
44623
+ }
44624
+
45030
44625
  function FormCard({ action, onComplete, onDismiss, accentColor }) {
45031
- const state = action.state;
44626
+ const state = action.input;
45032
44627
  const [currentStep, setCurrentStep] = reactExports.useState(0);
45033
44628
  const [answers, setAnswers] = reactExports.useState({});
45034
44629
  const [isSubmitting, setIsSubmitting] = reactExports.useState(false);
44630
+ const [localStatus, setLocalStatus] = reactExports.useState(null);
44631
+ // If action is already done, show simple completion indicator
44632
+ // The agent's response will convey what happened
44633
+ if (action.done) {
44634
+ return (jsxRuntimeExports.jsx("div", { className: "ai-chat-form-card ai-chat-form-card--completed", children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__icon", children: jsxRuntimeExports.jsx(CheckIcon, {}) }), jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__title", children: "Form completed" })] }) }));
44635
+ }
45035
44636
  const questions = state.questions || [];
45036
44637
  const currentQuestion = questions[currentStep];
45037
44638
  const totalQuestions = questions.length;
@@ -45052,6 +44653,7 @@
45052
44653
  if (!onComplete)
45053
44654
  return;
45054
44655
  setIsSubmitting(true);
44656
+ setLocalStatus('submitted');
45055
44657
  const formattedAnswers = Object.entries(answers).map(([questionId, value]) => ({
45056
44658
  questionId,
45057
44659
  value,
@@ -45065,6 +44667,7 @@
45065
44667
  const handleSkip = () => {
45066
44668
  if (!onComplete || !state.settings.allowSkip)
45067
44669
  return;
44670
+ setLocalStatus('skipped');
45068
44671
  onComplete(action.toolCallId, {
45069
44672
  ...state,
45070
44673
  status: 'skipped',
@@ -45095,24 +44698,26 @@
45095
44698
  const handleDismiss = () => {
45096
44699
  onDismiss?.(action.toolCallId);
45097
44700
  };
44701
+ // Use local status if available (for immediate UI feedback), otherwise use state.status
44702
+ const effectiveStatus = localStatus || state.status;
45098
44703
  // 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' })] }));
44704
+ if (effectiveStatus === 'error') {
44705
+ 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: jsxRuntimeExports.jsx(WarningIcon, {}) }), 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
44706
  }
45102
44707
  // 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!' })] }));
44708
+ if (effectiveStatus === 'submitted') {
44709
+ 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: jsxRuntimeExports.jsx(CheckIcon, {}) }), 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
44710
  }
45106
44711
  // 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" })] }));
44712
+ if (effectiveStatus === 'skipped') {
44713
+ 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: jsxRuntimeExports.jsx(SkipIcon, {}) }), 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
44714
  }
45110
44715
  // No questions
45111
44716
  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." })] }));
44717
+ 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: jsxRuntimeExports.jsx(FormIcon, {}) }), 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
44718
  }
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: {
44719
+ const showCloseButton = effectiveStatus === "displaying" && !action.done && Boolean(onDismiss);
44720
+ 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: jsxRuntimeExports.jsx(FormIcon, {}) }), 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
44721
  width: `${((currentStep + 1) / totalQuestions) * 100}%`,
45117
44722
  backgroundColor: accentColor || 'var(--ai-chat-accent-color, #3b82f6)',
45118
44723
  } }), 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) => {
@@ -45138,9 +44743,37 @@
45138
44743
  }, children: isSubmitting ? 'Submitting...' : (state.settings.submitButtonText || 'Submit') }))] })] }));
45139
44744
  }
45140
44745
 
44746
+ function EmailPhase({ accentColor, onDismiss, showCloseButton, onSubmit, isLoading, error, }) {
44747
+ const [emailInput, setEmailInput] = reactExports.useState('');
44748
+ const [localError, setLocalError] = reactExports.useState(null);
44749
+ const handleSubmit = () => {
44750
+ const trimmedEmail = emailInput.trim();
44751
+ if (!trimmedEmail) {
44752
+ setLocalError('Please enter your email address');
44753
+ return;
44754
+ }
44755
+ if (!trimmedEmail.includes('@')) {
44756
+ setLocalError('Please enter a valid email address');
44757
+ return;
44758
+ }
44759
+ setLocalError(null);
44760
+ onSubmit(trimmedEmail);
44761
+ };
44762
+ const displayError = localError || error;
44763
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-booking-card${showCloseButton ? ' ai-chat-booking-card--closable' : ''}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Enter Your Email" }), showCloseButton && onDismiss && jsxRuntimeExports.jsx(CloseButton, { onClick: onDismiss, ariaLabel: "Cancel booking" })] }), 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) => {
44764
+ setEmailInput(e.target.value);
44765
+ setLocalError(null);
44766
+ }, onKeyDown: (e) => {
44767
+ if (e.key === 'Enter' && !isLoading) {
44768
+ handleSubmit();
44769
+ }
44770
+ }, disabled: isLoading }), jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__btn ai-chat-booking-card__btn--primary", onClick: handleSubmit, disabled: !emailInput.trim() || isLoading, children: isLoading ? 'Sending...' : 'Continue' })] })] }));
44771
+ }
44772
+
45141
44773
  function Skeleton({ width, height, borderRadius = '4px' }) {
45142
44774
  return (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-skeleton-item", style: { width, height, borderRadius } }));
45143
44775
  }
44776
+
45144
44777
  function PinInputGroup({ values, onChange, disabled }) {
45145
44778
  const inputRefs = reactExports.useRef([]);
45146
44779
  const handleChange = (index, value) => {
@@ -45172,299 +44805,853 @@
45172
44805
  inputRefs.current[index] = el;
45173
44806
  }, 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
44807
  }
45175
- function BookContactAppointmentCard({ action, onComplete, accentColor }) {
45176
- const state = action.state;
45177
- const [emailInput, setEmailInput] = reactExports.useState('');
44808
+
44809
+ function OtpPhase({ accentColor, onDismiss, showCloseButton, email, onSubmit, onResend, isLoading, error, }) {
45178
44810
  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)
44811
+ const [localError, setLocalError] = reactExports.useState(null);
44812
+ const [isResending, setIsResending] = reactExports.useState(false);
44813
+ const handleSubmit = () => {
44814
+ const code = otpValues.join('');
44815
+ if (code.length !== 6) {
44816
+ setLocalError('Please enter the 6-digit code');
45186
44817
  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
44818
  }
45206
- else {
45207
- setEmailError(null);
45208
- setOtpError(null);
44819
+ setLocalError(null);
44820
+ onSubmit(code);
44821
+ };
44822
+ const handleResend = async () => {
44823
+ setIsResending(true);
44824
+ setLocalError(null);
44825
+ try {
44826
+ await onResend();
45209
44827
  }
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;
44828
+ finally {
44829
+ setIsResending(false);
45218
44830
  }
45219
- setEmailError(null);
45220
- setEmailInput(trimmedEmail);
45221
- handleSubmit({ email: trimmedEmail });
45222
44831
  };
45223
- const handleOtpSubmit = () => {
45224
- const code = otpValues.join('');
45225
- if (code.length !== 6) {
45226
- setOtpError('Please enter the 6-digit code');
44832
+ const displayError = localError || error;
44833
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-booking-card${showCloseButton ? ' ai-chat-booking-card--closable' : ''}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Verify Your Email" }), showCloseButton && onDismiss && jsxRuntimeExports.jsx(CloseButton, { onClick: onDismiss, ariaLabel: "Cancel booking" })] }), 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: email })] }), jsxRuntimeExports.jsx(PinInputGroup, { values: otpValues, onChange: (newValues) => {
44834
+ setOtpValues(newValues);
44835
+ setLocalError(null);
44836
+ // Auto-submit when all 6 digits are entered
44837
+ if (newValues.every((value) => value.length === 1) && !isLoading) {
44838
+ onSubmit(newValues.join(''));
44839
+ }
44840
+ }, disabled: isLoading }), 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: handleSubmit, disabled: otpValues.join('').length !== 6 || isLoading, children: isLoading ? 'Verifying...' : 'Verify' }), jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__btn ai-chat-booking-card__btn--secondary", onClick: handleResend, disabled: isLoading || isResending, children: isResending ? 'Sending...' : 'Resend Code' })] })] }));
44841
+ }
44842
+
44843
+ function ContactSelectionPhase({ accentColor, onDismiss, showCloseButton, contacts, onSelect, }) {
44844
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-booking-card${showCloseButton ? ' ai-chat-booking-card--closable' : ''}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Select Contact" }), showCloseButton && onDismiss && jsxRuntimeExports.jsx(CloseButton, { onClick: onDismiss, ariaLabel: "Cancel booking" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__description", children: "Choose who you would like to book an appointment with:" }), jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__list", children: contacts.map((contact) => (jsxRuntimeExports.jsxs("button", { className: "ai-chat-booking-card__list-item", onClick: () => onSelect(contact.id), children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__list-item-content", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__list-item-name", children: contact.name }), contact.role && (jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__list-item-role", children: contact.role }))] }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__list-item-arrow", "aria-hidden": "true" })] }, contact.id))) })] })] }));
44845
+ }
44846
+
44847
+ // Calendar icon SVG
44848
+ const CalendarIcon = () => (jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2", ry: "2" }), jsxRuntimeExports.jsx("line", { x1: "16", y1: "2", x2: "16", y2: "6" }), jsxRuntimeExports.jsx("line", { x1: "8", y1: "2", x2: "8", y2: "6" }), jsxRuntimeExports.jsx("line", { x1: "3", y1: "10", x2: "21", y2: "10" })] }));
44849
+ // List icon SVG
44850
+ const ListIcon = () => (jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("line", { x1: "8", y1: "6", x2: "21", y2: "6" }), jsxRuntimeExports.jsx("line", { x1: "8", y1: "12", x2: "21", y2: "12" }), jsxRuntimeExports.jsx("line", { x1: "8", y1: "18", x2: "21", y2: "18" }), jsxRuntimeExports.jsx("line", { x1: "3", y1: "6", x2: "3.01", y2: "6" }), jsxRuntimeExports.jsx("line", { x1: "3", y1: "12", x2: "3.01", y2: "12" }), jsxRuntimeExports.jsx("line", { x1: "3", y1: "18", x2: "3.01", y2: "18" })] }));
44851
+ function OptionsPhase({ onDismiss, showCloseButton, appointments, maxAppointments, onBookNew, onViewAppointments, isCancelling, }) {
44852
+ const activeAppointments = appointments.filter(a => a.status !== 'cancelled' && a.status !== 'declined');
44853
+ const canBookNew = activeAppointments.length < maxAppointments;
44854
+ const hasAppointments = appointments.length > 0;
44855
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-booking-card${showCloseButton ? ' ai-chat-booking-card--closable' : ''}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Booking Options" }), showCloseButton && onDismiss && jsxRuntimeExports.jsx(CloseButton, { onClick: onDismiss, ariaLabel: "Cancel booking" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [!canBookNew && (jsxRuntimeExports.jsxs("p", { className: "ai-chat-booking-card__warning", children: ["You have reached the maximum number of appointments (", maxAppointments, "). Please cancel an existing appointment to book a new one."] })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__options", children: [jsxRuntimeExports.jsxs("button", { className: "ai-chat-booking-card__option-btn", onClick: onBookNew, disabled: !canBookNew || isCancelling, children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__option-icon", children: jsxRuntimeExports.jsx(CalendarIcon, {}) }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__option-text", children: "Book New Appointment" })] }), hasAppointments && (jsxRuntimeExports.jsxs("button", { className: "ai-chat-booking-card__option-btn", onClick: onViewAppointments, disabled: isCancelling, children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__option-icon", children: jsxRuntimeExports.jsx(ListIcon, {}) }), jsxRuntimeExports.jsxs("span", { className: "ai-chat-booking-card__option-text", children: ["View My Appointments (", activeAppointments.length, ")"] })] }))] })] })] }));
44856
+ }
44857
+
44858
+ function ViewAppointmentsPhase({ accentColor, onDismiss, showCloseButton, appointments, onBack, onCancelAppointment, isCancelling, }) {
44859
+ const [cancellingId, setCancellingId] = reactExports.useState(null);
44860
+ const handleCancel = async (appointmentId) => {
44861
+ setCancellingId(appointmentId);
44862
+ await onCancelAppointment(appointmentId);
44863
+ setCancellingId(null);
44864
+ };
44865
+ const activeAppointments = appointments.filter(a => a.status !== 'cancelled');
44866
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-booking-card${showCloseButton ? ' ai-chat-booking-card--closable' : ''}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__back-btn", onClick: onBack, children: "Back" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "My Appointments" }), showCloseButton && onDismiss && jsxRuntimeExports.jsx(CloseButton, { onClick: onDismiss, ariaLabel: "Cancel booking" })] }), jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__content", children: activeAppointments.length === 0 ? (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__empty", children: "No appointments found." })) : (jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__appointments", children: activeAppointments.map((apt) => (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__appointment", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__appointment-info", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__appointment-subject", children: apt.subject }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__appointment-contact", children: apt.contactName }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__appointment-time", children: apt.displayTime }), jsxRuntimeExports.jsx("span", { className: `ai-chat-booking-card__appointment-status ai-chat-booking-card__appointment-status--${apt.status}`, children: apt.status === 'pending' ? 'Pending Approval' : apt.status })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__appointment-actions", children: [apt.teamsLink && (jsxRuntimeExports.jsx("a", { href: apt.teamsLink, target: "_blank", rel: "noopener noreferrer", className: "ai-chat-booking-card__appointment-link", children: "Join Meeting" })), apt.googleMeetLink && (jsxRuntimeExports.jsx("a", { href: apt.googleMeetLink, target: "_blank", rel: "noopener noreferrer", className: "ai-chat-booking-card__appointment-link", children: "Join Meeting" })), jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__appointment-cancel", onClick: () => handleCancel(apt.id), disabled: isCancelling || cancellingId === apt.id, children: cancellingId === apt.id ? 'Cancelling...' : 'Cancel' })] })] }, apt.id))) })) })] }));
44867
+ }
44868
+
44869
+ function SlotSelectionPhase({ onDismiss, showCloseButton, slots, contactName, onSelect, onBack, isLoading, error, }) {
44870
+ // Group slots by date
44871
+ const slotsByDate = reactExports.useMemo(() => {
44872
+ const grouped = {};
44873
+ for (const slot of slots) {
44874
+ const date = slot.displayDate;
44875
+ if (!grouped[date]) {
44876
+ grouped[date] = [];
44877
+ }
44878
+ grouped[date].push(slot);
44879
+ }
44880
+ return grouped;
44881
+ }, [slots]);
44882
+ const dates = Object.keys(slotsByDate);
44883
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-booking-card${showCloseButton ? ' ai-chat-booking-card--closable' : ''}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__back-btn", onClick: onBack, children: "Back" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Select Time Slot" }), showCloseButton && onDismiss && jsxRuntimeExports.jsx(CloseButton, { onClick: onDismiss, ariaLabel: "Cancel booking" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [contactName && (jsxRuntimeExports.jsxs("p", { className: "ai-chat-booking-card__description", children: ["Available times for ", jsxRuntimeExports.jsx("strong", { children: contactName }), ":"] })), error && (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__error", children: error })), slots.length === 0 ? (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__empty", children: "No available time slots found. Please try again later." })) : (jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__slots-container", children: dates.map((date) => (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__date-group", children: [jsxRuntimeExports.jsx("h4", { className: "ai-chat-booking-card__date-header", children: date }), jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__slots", children: slotsByDate[date].map((slot) => (jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__slot", onClick: () => onSelect({ startTime: slot.startTime, endTime: slot.endTime }), disabled: isLoading, children: slot.displayTime }, `${slot.startTime}-${slot.endTime}`))) })] }, date))) }))] })] }));
44884
+ }
44885
+
44886
+ function ConfirmationPhase({ onDismiss, showCloseButton, contactName, slotDisplay, subjectMode, predefinedSubjects, onConfirm, onBack, isLoading, error, }) {
44887
+ const [subject, setSubject] = reactExports.useState('');
44888
+ const [selectedPredefined, setSelectedPredefined] = reactExports.useState('');
44889
+ const [localError, setLocalError] = reactExports.useState(null);
44890
+ const handleConfirm = () => {
44891
+ const finalSubject = subjectMode === 'predefined' ? selectedPredefined : subject.trim();
44892
+ if (!finalSubject) {
44893
+ setLocalError('Please enter a subject for your appointment');
45227
44894
  return;
45228
44895
  }
45229
- setOtpError(null);
45230
- const resolvedEmail = state.email || emailInput.trim() || null;
45231
- handleSubmit({ otpCode: code, email: resolvedEmail });
44896
+ setLocalError(null);
44897
+ onConfirm(finalSubject);
45232
44898
  };
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..." }) })] }));
44899
+ const displayError = localError || error;
44900
+ const isValid = subjectMode === 'predefined' ? !!selectedPredefined : !!subject.trim();
44901
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-booking-card${showCloseButton ? ' ai-chat-booking-card--closable' : ''}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__back-btn", onClick: onBack, "aria-label": "Go back", children: jsxRuntimeExports.jsx(BackArrowIcon, {}) }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Confirm Booking" }), showCloseButton && onDismiss && jsxRuntimeExports.jsx(CloseButton, { onClick: onDismiss, ariaLabel: "Cancel booking" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__summary", children: [contactName && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__summary-row", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-label", children: "With:" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-value", children: contactName })] })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__summary-row", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-label", children: "When:" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-value", children: slotDisplay })] })] }), displayError && (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__error", children: displayError })), subjectMode === 'predefined' ? (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__field", children: [jsxRuntimeExports.jsx("label", { className: "ai-chat-booking-card__label", children: "Select a topic:" }), jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__subject-options", children: predefinedSubjects.map((subj) => (jsxRuntimeExports.jsx("button", { className: `ai-chat-booking-card__subject-option ${selectedPredefined === subj ? 'ai-chat-booking-card__subject-option--selected' : ''}`, onClick: () => {
44902
+ setSelectedPredefined(subj);
44903
+ setLocalError(null);
44904
+ }, disabled: isLoading, children: subj }, subj))) })] })) : (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__field", children: [jsxRuntimeExports.jsx("label", { className: "ai-chat-booking-card__label", children: "What would you like to discuss?" }), jsxRuntimeExports.jsx("input", { type: "text", className: "ai-chat-booking-card__input", placeholder: "Enter appointment subject...", value: subject, onChange: (e) => {
44905
+ setSubject(e.target.value);
44906
+ setLocalError(null);
44907
+ }, onKeyDown: (e) => {
44908
+ if (e.key === 'Enter' && isValid && !isLoading) {
44909
+ handleConfirm();
44910
+ }
44911
+ }, disabled: isLoading })] })), jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__btn ai-chat-booking-card__btn--primary", onClick: handleConfirm, disabled: !isValid || isLoading, children: isLoading ? 'Booking...' : 'Confirm Booking' })] })] }));
45356
44912
  }
45357
44913
 
45358
- const pendingResolvers = new Map();
45359
- const resumeCallbacks = new Map();
45360
- const frontendActionHandlers = {};
45361
- const actionRenderers = {};
45362
- function getFrontendActionHandler(implementation) {
45363
- return frontendActionHandlers[implementation];
44914
+ function BookedPhase({ subject, contactName, meetingLink, meetingProvider, }) {
44915
+ return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card ai-chat-booking-card--success", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__header", children: jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Appointment Booked" }) }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__success-icon", "aria-hidden": "true" }), jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__success-message", children: "Your appointment has been successfully scheduled." }), 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: "Subject:" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-value", children: subject })] }), contactName && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__summary-row", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-label", children: "With:" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-value", children: contactName })] }))] }), meetingLink && (jsxRuntimeExports.jsx("a", { href: meetingLink, target: "_blank", rel: "noopener noreferrer", className: "ai-chat-booking-card__btn ai-chat-booking-card__btn--primary", style: {
44916
+ textDecoration: 'none',
44917
+ display: 'inline-block',
44918
+ textAlign: 'center',
44919
+ }, children: meetingProvider === 'google' ? 'Join Google Meet' : 'Join Teams Meeting' }))] })] }));
45364
44920
  }
45365
- function getActionRenderer(implementation) {
45366
- return actionRenderers[implementation];
44921
+
44922
+ function PendingApprovalPhase({ subject, contactName }) {
44923
+ 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__status-icon ai-chat-booking-card__status-icon--pending" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Awaiting Approval" })] }), jsxRuntimeExports.jsxs("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." }), 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: "Subject:" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-value", children: subject })] }), contactName && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__summary-row", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-label", children: "With:" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-value", children: contactName })] }))] })] })] }));
45367
44924
  }
45368
- function waitForActionState(toolCallId) {
45369
- return new Promise((resolve) => {
45370
- pendingResolvers.set(toolCallId, resolve);
45371
- });
44925
+
44926
+ /**
44927
+ * Cancelled Phase Component (terminal state)
44928
+ */
44929
+ function CancelledPhase() {
44930
+ return (jsxRuntimeExports.jsxs("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__status-icon ai-chat-booking-card__status-icon--cancelled" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Appointment Cancelled" })] }), jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__content", children: jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__description", children: "This appointment has been cancelled." }) })] }));
45372
44931
  }
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);
45381
- if (resumeCallback) {
45382
- resumeCallback(state).catch((error) => {
45383
- console.error("[Action] Failed to resume action:", error);
45384
- });
45385
- }
44932
+
44933
+ function ErrorPhase({ error, onRetry }) {
44934
+ 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__status-icon ai-chat-booking-card__status-icon--error" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Booking Error" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__error", children: error }), onRetry && (jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__btn ai-chat-booking-card__btn--secondary", onClick: onRetry, children: "Try Again" }))] })] }));
45386
44935
  }
45387
- function registerActionResumeCallback(toolCallId, callback) {
45388
- resumeCallbacks.set(toolCallId, callback);
44936
+
44937
+ function CompletedPhase() {
44938
+ return (jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card ai-chat-booking-card--completed", children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__completed-indicator", children: [jsxRuntimeExports.jsx(CheckIcon, {}), jsxRuntimeExports.jsx("span", { children: "Booking action completed" })] }) }));
45389
44939
  }
45390
- function unregisterActionResumeCallback(toolCallId) {
45391
- resumeCallbacks.delete(toolCallId);
44940
+
44941
+ function LoadingPhase() {
44942
+ return (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" })] }) }));
45392
44943
  }
45393
44944
 
45394
- function registerGoogleCalendarHandler() {
45395
- frontendActionHandlers["google-calendar-appointment"] = async (_input, _state, context) => {
45396
- return waitForActionState(context.toolCallId);
44945
+ /**
44946
+ * Core action lifecycle handlers for booking flow
44947
+ */
44948
+ function useBookingAction({ onComplete, onDismiss, toolCallId, }) {
44949
+ const handleDismiss = reactExports.useCallback(() => {
44950
+ onDismiss?.(toolCallId);
44951
+ }, [onDismiss, toolCallId]);
44952
+ const finishAction = reactExports.useCallback((body) => {
44953
+ if (!onComplete)
44954
+ return;
44955
+ onComplete(toolCallId, body);
44956
+ }, [onComplete, toolCallId]);
44957
+ return {
44958
+ handleDismiss,
44959
+ finishAction,
45397
44960
  };
45398
44961
  }
45399
44962
 
45400
44963
  /**
45401
- * Register google-calendar-appointment action handler and renderer.
45402
- * Called by initializeActionHandlers to prevent tree-shaking.
44964
+ * Helper functions for accessing booking data
45403
44965
  */
45404
- function registerGoogleCalendarAction() {
45405
- // Register the handler
45406
- registerGoogleCalendarHandler();
45407
- // Register the renderer
45408
- actionRenderers["google-calendar-appointment"] = (message, accentColor, _variant, onActionDismiss) => {
45409
- const action = message.action;
45410
- if (!action)
45411
- return null;
45412
- const handleComplete = (toolCallId, newState) => {
45413
- resolveActionState(toolCallId, newState);
45414
- };
45415
- const handleDismiss = onActionDismiss
45416
- ? (toolCallId) => {
45417
- resolveActionState(toolCallId, { __dismissed: true });
45418
- onActionDismiss(toolCallId);
44966
+ function useBookingHelpers({ contacts, slots, bookingMode, }) {
44967
+ const getContactName = reactExports.useCallback((contactId) => {
44968
+ if (!contactId)
44969
+ return bookingMode === 'general' ? 'Shared Calendar' : null;
44970
+ const contact = contacts.find(c => c.id === contactId);
44971
+ return contact?.name || null;
44972
+ }, [contacts, bookingMode]);
44973
+ const getSlotDisplay = reactExports.useCallback((slot) => {
44974
+ if (!slot)
44975
+ return '';
44976
+ const slotData = slots.find(s => s.startTime === slot.startTime && s.endTime === slot.endTime);
44977
+ return slotData ? `${slotData.displayDate} ${slotData.displayTime}` : '';
44978
+ }, [slots]);
44979
+ return {
44980
+ getContactName,
44981
+ getSlotDisplay,
44982
+ };
44983
+ }
44984
+
44985
+ /**
44986
+ * OTP-related operations for email verification
44987
+ */
44988
+ function useBookingOtp({ onCallEndpoint, state, setState, config, }) {
44989
+ const handleSendOtp = reactExports.useCallback(async (email) => {
44990
+ if (!onCallEndpoint) {
44991
+ setState(prev => ({ ...prev, error: 'Endpoint not available' }));
44992
+ return;
44993
+ }
44994
+ setState(prev => ({ ...prev, isLoading: true, error: null, email }));
44995
+ try {
44996
+ await onCallEndpoint('send-otp', { email });
44997
+ setState(prev => ({ ...prev, isLoading: false, step: 'otp' }));
44998
+ }
44999
+ catch (err) {
45000
+ const message = err instanceof Error ? err.message : 'Failed to send verification code';
45001
+ setState(prev => ({ ...prev, isLoading: false, error: message }));
45002
+ }
45003
+ }, [onCallEndpoint, setState]);
45004
+ const handleVerifyOtp = reactExports.useCallback(async (code) => {
45005
+ if (!onCallEndpoint) {
45006
+ setState(prev => ({ ...prev, error: 'Endpoint not available' }));
45007
+ return;
45008
+ }
45009
+ setState(prev => ({ ...prev, isLoading: true, error: null }));
45010
+ try {
45011
+ const result = await onCallEndpoint('verify-otp', {
45012
+ email: state.email,
45013
+ code,
45014
+ bookingMode: config.bookingMode,
45015
+ timeZone: config.timeZone,
45016
+ });
45017
+ const nextStep = config.bookingMode === 'general'
45018
+ ? 'options'
45019
+ : result.contacts.length === 1
45020
+ ? 'options'
45021
+ : 'contact_selection';
45022
+ setState(prev => ({
45023
+ ...prev,
45024
+ isLoading: false,
45025
+ token: result.token,
45026
+ contacts: result.contacts,
45027
+ appointments: result.appointments,
45028
+ selectedContactId: result.contacts.length === 1 ? result.contacts[0].id : null,
45029
+ step: nextStep,
45030
+ }));
45031
+ }
45032
+ catch (err) {
45033
+ const message = err instanceof Error ? err.message : 'Invalid verification code';
45034
+ setState(prev => ({ ...prev, isLoading: false, error: message }));
45035
+ }
45036
+ }, [onCallEndpoint, state.email, config.bookingMode, config.timeZone, setState]);
45037
+ const handleResendOtp = reactExports.useCallback(async () => {
45038
+ await handleSendOtp(state.email);
45039
+ }, [handleSendOtp, state.email]);
45040
+ return {
45041
+ handleSendOtp,
45042
+ handleVerifyOtp,
45043
+ handleResendOtp,
45044
+ };
45045
+ }
45046
+
45047
+ /**
45048
+ * Navigation and flow control handlers for booking steps
45049
+ */
45050
+ function useBookingNavigation({ onCallEndpoint, state, setState, config, }) {
45051
+ const handleSelectContact = reactExports.useCallback((contactId) => {
45052
+ setState(prev => ({
45053
+ ...prev,
45054
+ selectedContactId: contactId,
45055
+ step: 'options',
45056
+ }));
45057
+ }, [setState]);
45058
+ const handleBookNew = reactExports.useCallback(async () => {
45059
+ if (!onCallEndpoint || !state.token) {
45060
+ setState(prev => ({ ...prev, error: 'Not authenticated' }));
45061
+ return;
45062
+ }
45063
+ setState(prev => ({ ...prev, isLoading: true, error: null }));
45064
+ try {
45065
+ const result = await onCallEndpoint('get-slots', {
45066
+ contactId: state.selectedContactId,
45067
+ daysAhead: config.daysAhead,
45068
+ timeZone: config.timeZone,
45069
+ }, { token: state.token });
45070
+ setState(prev => ({
45071
+ ...prev,
45072
+ isLoading: false,
45073
+ slots: result.slots,
45074
+ step: 'slot_selection',
45075
+ }));
45076
+ }
45077
+ catch (err) {
45078
+ const message = err instanceof Error ? err.message : 'Failed to load available slots';
45079
+ setState(prev => ({ ...prev, isLoading: false, error: message }));
45080
+ }
45081
+ }, [onCallEndpoint, state.token, state.selectedContactId, config.daysAhead, config.timeZone, setState]);
45082
+ const handleViewAppointments = reactExports.useCallback(() => {
45083
+ setState(prev => ({ ...prev, step: 'view_appointments' }));
45084
+ }, [setState]);
45085
+ const handleBackToOptions = reactExports.useCallback(() => {
45086
+ setState(prev => ({ ...prev, step: 'options', error: null }));
45087
+ }, [setState]);
45088
+ const handleSelectSlot = reactExports.useCallback((slot) => {
45089
+ setState(prev => ({
45090
+ ...prev,
45091
+ selectedSlot: slot,
45092
+ step: 'confirmation',
45093
+ }));
45094
+ }, [setState]);
45095
+ const handleBackToSlots = reactExports.useCallback(() => {
45096
+ setState(prev => ({ ...prev, step: 'slot_selection', error: null }));
45097
+ }, [setState]);
45098
+ return {
45099
+ handleSelectContact,
45100
+ handleBookNew,
45101
+ handleViewAppointments,
45102
+ handleBackToOptions,
45103
+ handleSelectSlot,
45104
+ handleBackToSlots,
45105
+ };
45106
+ }
45107
+
45108
+ /**
45109
+ * Core booking operations (confirm and cancel)
45110
+ */
45111
+ function useBookingOperations({ onCallEndpoint, state, setState, config, getContactName, finishAction, }) {
45112
+ const [isCancelling, setIsCancelling] = reactExports.useState(false);
45113
+ const handleConfirmBooking = reactExports.useCallback(async (subject) => {
45114
+ if (!onCallEndpoint || !state.token || !state.selectedSlot) {
45115
+ setState(prev => ({ ...prev, error: 'Missing required data' }));
45116
+ return;
45117
+ }
45118
+ setState(prev => ({ ...prev, isLoading: true, error: null, subject }));
45119
+ try {
45120
+ const result = await onCallEndpoint('book', {
45121
+ contactId: state.selectedContactId,
45122
+ slot: state.selectedSlot,
45123
+ subject,
45124
+ timeZone: config.timeZone,
45125
+ }, { token: state.token });
45126
+ const contactName = getContactName(state.selectedContactId);
45127
+ if (result.status === 'pending_approval') {
45128
+ setState(prev => ({
45129
+ ...prev,
45130
+ isLoading: false,
45131
+ step: 'pending_approval',
45132
+ }));
45133
+ // Finish with pending status
45134
+ finishAction({
45135
+ status: 'pending_approval',
45136
+ subject,
45137
+ contactName,
45138
+ message: `Appointment request "${subject}" submitted and awaiting approval.`,
45139
+ });
45419
45140
  }
45420
- : undefined;
45421
- return (jsxRuntimeExports.jsx(GoogleCalendarCard, { action: {
45422
- implementation: action.implementation,
45423
- toolCallId: action.toolCallId,
45424
- actionId: action.actionId,
45425
- input: action.input,
45426
- state: action.state,
45427
- done: action.done ?? false,
45428
- }, onComplete: handleComplete, onDismiss: handleDismiss, accentColor: accentColor }));
45141
+ else {
45142
+ setState(prev => ({
45143
+ ...prev,
45144
+ isLoading: false,
45145
+ bookedMeetingLink: result.meetingLink || null,
45146
+ bookedMeetingProvider: result.meetingProvider || null,
45147
+ step: 'booked',
45148
+ }));
45149
+ // Finish with booked status
45150
+ finishAction({
45151
+ status: 'booked',
45152
+ subject,
45153
+ contactName,
45154
+ meetingLink: result.meetingLink,
45155
+ message: `Successfully booked appointment "${subject}"${contactName ? ` with ${contactName}` : ''}.`,
45156
+ });
45157
+ }
45158
+ }
45159
+ catch (err) {
45160
+ const message = err instanceof Error ? err.message : 'Failed to book appointment';
45161
+ setState(prev => ({ ...prev, isLoading: false, error: message }));
45162
+ }
45163
+ }, [onCallEndpoint, state.token, state.selectedSlot, state.selectedContactId, config.timeZone, getContactName, finishAction, setState]);
45164
+ const handleCancelAppointment = reactExports.useCallback(async (appointmentId) => {
45165
+ if (!onCallEndpoint || !state.token) {
45166
+ setState(prev => ({ ...prev, error: 'Not authenticated' }));
45167
+ return;
45168
+ }
45169
+ setIsCancelling(true);
45170
+ try {
45171
+ await onCallEndpoint('cancel', { appointmentId }, { token: state.token });
45172
+ // Update local appointments list
45173
+ setState(prev => ({
45174
+ ...prev,
45175
+ appointments: prev.appointments.map(apt => apt.id === appointmentId ? { ...apt, status: 'cancelled' } : apt),
45176
+ }));
45177
+ }
45178
+ catch (err) {
45179
+ const message = err instanceof Error ? err.message : 'Failed to cancel appointment';
45180
+ setState(prev => ({ ...prev, error: message }));
45181
+ }
45182
+ finally {
45183
+ setIsCancelling(false);
45184
+ }
45185
+ }, [onCallEndpoint, state.token, setState]);
45186
+ return {
45187
+ handleConfirmBooking,
45188
+ handleCancelAppointment,
45189
+ isCancelling,
45429
45190
  };
45430
45191
  }
45431
45192
 
45432
- function registerMicrosoftCalendarHandler() {
45433
- frontendActionHandlers["microsoft-calendar-appointment"] = async (_input, _state, context) => {
45434
- return waitForActionState(context.toolCallId);
45193
+ // Default config values
45194
+ const DEFAULT_CONFIG = {
45195
+ bookingMode: 'per-contact',
45196
+ timeZone: 'UTC',
45197
+ maxAppointmentsPerUser: 3,
45198
+ daysAhead: 14,
45199
+ subjectMode: 'user_defined',
45200
+ predefinedSubjects: [],
45201
+ };
45202
+ // Initial UI state
45203
+ const createInitialState = () => ({
45204
+ step: 'email',
45205
+ email: '',
45206
+ selectedContactId: null,
45207
+ selectedSlot: null,
45208
+ subject: '',
45209
+ token: null,
45210
+ contacts: [],
45211
+ appointments: [],
45212
+ slots: [],
45213
+ bookedMeetingLink: null,
45214
+ bookedMeetingProvider: null,
45215
+ isLoading: false,
45216
+ error: null,
45217
+ });
45218
+ function BookContactAppointmentCard({ action, onComplete, onDismiss, onCallEndpoint, accentColor, }) {
45219
+ // Parse config from input (from getInitialClientState)
45220
+ const initialState = action.input;
45221
+ const config = {
45222
+ bookingMode: initialState.bookingMode || DEFAULT_CONFIG.bookingMode,
45223
+ timeZone: initialState.timeZone || DEFAULT_CONFIG.timeZone,
45224
+ maxAppointmentsPerUser: initialState.maxAppointmentsPerUser || DEFAULT_CONFIG.maxAppointmentsPerUser,
45225
+ daysAhead: initialState.daysAhead || DEFAULT_CONFIG.daysAhead,
45226
+ subjectMode: initialState.subjectMode || DEFAULT_CONFIG.subjectMode,
45227
+ predefinedSubjects: initialState.predefinedSubjects || DEFAULT_CONFIG.predefinedSubjects,
45228
+ };
45229
+ // Local UI state
45230
+ const [state, setState] = reactExports.useState(createInitialState);
45231
+ // Check if action is already done (from server state)
45232
+ const isDone = action.done;
45233
+ // Determine if dismiss should be available
45234
+ const isInteractiveStep = ['email', 'otp', 'contact_selection', 'options', 'view_appointments', 'slot_selection', 'confirmation'].includes(state.step);
45235
+ const showCloseButton = !isDone && isInteractiveStep && Boolean(onDismiss);
45236
+ // =========================================================================
45237
+ // Custom Hooks
45238
+ // =========================================================================
45239
+ // Core action lifecycle
45240
+ const { handleDismiss, finishAction } = useBookingAction({
45241
+ onComplete,
45242
+ onDismiss,
45243
+ toolCallId: action.toolCallId,
45244
+ });
45245
+ // Helper functions
45246
+ const { getContactName, getSlotDisplay } = useBookingHelpers({
45247
+ contacts: state.contacts,
45248
+ slots: state.slots,
45249
+ bookingMode: config.bookingMode,
45250
+ });
45251
+ // OTP operations
45252
+ const { handleSendOtp, handleVerifyOtp, handleResendOtp, } = useBookingOtp({
45253
+ onCallEndpoint,
45254
+ state: { email: state.email },
45255
+ setState,
45256
+ config: {
45257
+ bookingMode: config.bookingMode,
45258
+ timeZone: config.timeZone,
45259
+ },
45260
+ });
45261
+ // Navigation handlers
45262
+ const { handleSelectContact, handleBookNew, handleViewAppointments, handleBackToOptions, handleSelectSlot, handleBackToSlots, } = useBookingNavigation({
45263
+ onCallEndpoint,
45264
+ state,
45265
+ setState,
45266
+ config: {
45267
+ daysAhead: config.daysAhead,
45268
+ timeZone: config.timeZone,
45269
+ },
45270
+ });
45271
+ // Booking operations
45272
+ const { handleConfirmBooking, handleCancelAppointment, isCancelling, } = useBookingOperations({
45273
+ onCallEndpoint,
45274
+ state,
45275
+ setState,
45276
+ config: {
45277
+ timeZone: config.timeZone,
45278
+ },
45279
+ getContactName,
45280
+ finishAction,
45281
+ });
45282
+ // =========================================================================
45283
+ // Render
45284
+ // =========================================================================
45285
+ // If action is already done, show a simple completion indicator
45286
+ // The agent's response will convey what happened - no need to reconstruct terminal state
45287
+ if (isDone) {
45288
+ return jsxRuntimeExports.jsx(CompletedPhase, {});
45289
+ }
45290
+ // Show loading when making API calls
45291
+ if (state.isLoading) {
45292
+ return jsxRuntimeExports.jsx(LoadingPhase, {});
45293
+ }
45294
+ // Render based on current step
45295
+ switch (state.step) {
45296
+ case 'email':
45297
+ return (jsxRuntimeExports.jsx(EmailPhase, { accentColor: accentColor, onDismiss: handleDismiss, showCloseButton: showCloseButton, onSubmit: handleSendOtp, isLoading: state.isLoading, error: state.error }));
45298
+ case 'otp':
45299
+ return (jsxRuntimeExports.jsx(OtpPhase, { accentColor: accentColor, onDismiss: handleDismiss, showCloseButton: showCloseButton, email: state.email, onSubmit: handleVerifyOtp, onResend: handleResendOtp, isLoading: state.isLoading, error: state.error }));
45300
+ case 'contact_selection':
45301
+ return (jsxRuntimeExports.jsx(ContactSelectionPhase, { accentColor: accentColor, onDismiss: handleDismiss, showCloseButton: showCloseButton, contacts: state.contacts, onSelect: handleSelectContact }));
45302
+ case 'options':
45303
+ return (jsxRuntimeExports.jsx(OptionsPhase, { accentColor: accentColor, onDismiss: handleDismiss, showCloseButton: showCloseButton, appointments: state.appointments.filter(a => a.status !== 'cancelled'), maxAppointments: config.maxAppointmentsPerUser, onBookNew: handleBookNew, onViewAppointments: handleViewAppointments, onCancelAppointment: handleCancelAppointment, isCancelling: isCancelling }));
45304
+ case 'view_appointments':
45305
+ return (jsxRuntimeExports.jsx(ViewAppointmentsPhase, { accentColor: accentColor, onDismiss: handleDismiss, showCloseButton: showCloseButton, appointments: state.appointments, onBack: handleBackToOptions, onCancelAppointment: handleCancelAppointment, isCancelling: isCancelling }));
45306
+ case 'slot_selection':
45307
+ return (jsxRuntimeExports.jsx(SlotSelectionPhase, { accentColor: accentColor, onDismiss: handleDismiss, showCloseButton: showCloseButton, slots: state.slots, contactName: getContactName(state.selectedContactId), onSelect: handleSelectSlot, onBack: handleBackToOptions, isLoading: state.isLoading, error: state.error }));
45308
+ case 'confirmation':
45309
+ return (jsxRuntimeExports.jsx(ConfirmationPhase, { accentColor: accentColor, onDismiss: handleDismiss, showCloseButton: showCloseButton, contactName: getContactName(state.selectedContactId), slot: state.selectedSlot, slotDisplay: getSlotDisplay(state.selectedSlot), subjectMode: config.subjectMode, predefinedSubjects: config.predefinedSubjects, onConfirm: handleConfirmBooking, onBack: handleBackToSlots, isLoading: state.isLoading, error: state.error }));
45310
+ case 'booked':
45311
+ return (jsxRuntimeExports.jsx(BookedPhase, { subject: state.subject, contactName: getContactName(state.selectedContactId), meetingLink: state.bookedMeetingLink, meetingProvider: state.bookedMeetingProvider }));
45312
+ case 'pending_approval':
45313
+ return (jsxRuntimeExports.jsx(PendingApprovalPhase, { subject: state.subject, contactName: getContactName(state.selectedContactId) }));
45314
+ case 'cancelled':
45315
+ return jsxRuntimeExports.jsx(CancelledPhase, {});
45316
+ case 'error':
45317
+ return jsxRuntimeExports.jsx(ErrorPhase, { error: state.error || 'An error occurred' });
45318
+ default:
45319
+ return jsxRuntimeExports.jsx(ErrorPhase, { error: "Unknown state" });
45320
+ }
45321
+ }
45322
+
45323
+ function ExternalLinkIcon$1() {
45324
+ return (jsxRuntimeExports.jsxs("svg", { width: "14", height: "14", 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" })] }));
45325
+ }
45326
+ function ImageCard({ item, accentColor, showOverlay = true, onClick, onLinkClick }) {
45327
+ const [imageError, setImageError] = reactExports.useState(false);
45328
+ const style = accentColor ? { '--action-accent': accentColor } : undefined;
45329
+ const hasMetadata = item.title || item.description || item.link;
45330
+ const handleLinkClick = (e) => {
45331
+ e.stopPropagation();
45332
+ if (item.link) {
45333
+ onLinkClick?.(item.link);
45334
+ window.open(item.link, '_blank', 'noopener,noreferrer');
45335
+ }
45336
+ };
45337
+ const handleImageClick = () => {
45338
+ if (onClick) {
45339
+ onClick();
45340
+ }
45435
45341
  };
45342
+ return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-image-card", style: style, onClick: handleImageClick, children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-image-card__media", children: !imageError ? (jsxRuntimeExports.jsx("img", { src: item.url, alt: item.alt || item.title || 'Image', className: "ai-chat-image-card__image", onError: () => setImageError(true) })) : (jsxRuntimeExports.jsx("div", { className: "ai-chat-image-card__image-error", children: jsxRuntimeExports.jsx("span", { children: "Failed to load image" }) })) }), hasMetadata && showOverlay && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-image-card__content", children: [item.title && (jsxRuntimeExports.jsx("h4", { className: "ai-chat-image-card__title", children: item.title })), item.description && (jsxRuntimeExports.jsx("p", { className: "ai-chat-image-card__description", children: item.description })), item.link && (jsxRuntimeExports.jsxs("button", { className: "ai-chat-image-card__link-btn", onClick: handleLinkClick, children: [item.linkText || 'View More', jsxRuntimeExports.jsx(ExternalLinkIcon$1, {})] }))] }))] }));
45343
+ }
45344
+
45345
+ function ImageGallery({ items, columns = 2, accentColor }) {
45346
+ const [imageErrors, setImageErrors] = reactExports.useState(new Set());
45347
+ const imageItems = items;
45348
+ if (imageItems.length === 0)
45349
+ return null;
45350
+ // Determine if first item should span full width (for odd counts > 1)
45351
+ const itemCount = imageItems.length;
45352
+ const isOddCount = itemCount > 1 && itemCount % 2 === 1;
45353
+ const style = {
45354
+ ...(accentColor ? { '--action-accent': accentColor } : {}),
45355
+ '--gallery-item-count': itemCount,
45356
+ };
45357
+ const handleImageError = (index) => {
45358
+ setImageErrors(prev => new Set(prev).add(index));
45359
+ };
45360
+ return (jsxRuntimeExports.jsx("div", { className: "ai-chat-image-gallery", style: style, "data-item-count": itemCount, children: jsxRuntimeExports.jsx("div", { className: `ai-chat-image-gallery__grid ${isOddCount ? 'odd-count' : ''}`, "data-count": itemCount, children: imageItems.map((item, index) => (jsxRuntimeExports.jsx("div", { className: `ai-chat-image-gallery__item ${isOddCount && index === 0 ? 'span-full' : ''}`, children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-image-gallery__item-media", children: [!imageErrors.has(index) ? (jsxRuntimeExports.jsx("img", { src: item.url, alt: item.alt || item.title || `Image ${index + 1}`, onError: () => handleImageError(index) })) : (jsxRuntimeExports.jsx("div", { className: "ai-chat-image-gallery__error", children: jsxRuntimeExports.jsx("span", { children: "Failed to load" }) })), item.title && (jsxRuntimeExports.jsx("div", { className: "ai-chat-image-gallery__item-overlay", children: jsxRuntimeExports.jsx("span", { className: "ai-chat-image-gallery__item-title", children: item.title }) }))] }) }, index))) }) }));
45361
+ }
45362
+
45363
+ function ExternalLinkIcon() {
45364
+ return (jsxRuntimeExports.jsxs("svg", { width: "14", height: "14", 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" })] }));
45365
+ }
45366
+ function truncate(text, maxLength) {
45367
+ if (text.length <= maxLength)
45368
+ return text;
45369
+ return text.slice(0, maxLength).trim() + '...';
45370
+ }
45371
+ function ProjectCard({ item, accentColor, onLinkClick, variant }) {
45372
+ const [imageError, setImageError] = reactExports.useState(false);
45373
+ const style = accentColor ? { '--action-accent': accentColor } : undefined;
45374
+ const imageUrl = item.url;
45375
+ // Determine variant based on content if not specified
45376
+ const hasTextContent = item.title || item.description;
45377
+ const effectiveVariant = variant || (hasTextContent ? 'full' : 'image-only');
45378
+ const handleCardClick = () => {
45379
+ if (item.link) {
45380
+ onLinkClick?.(item.link);
45381
+ window.open(item.link, '_blank', 'noopener,noreferrer');
45382
+ }
45383
+ };
45384
+ // Image-only variant - just the image with optional hover effect
45385
+ if (effectiveVariant === 'image-only') {
45386
+ return (jsxRuntimeExports.jsx("div", { className: `ai-chat-project-card ai-chat-project-card--image-only ${item.link ? 'clickable' : ''}`, style: style, onClick: item.link ? handleCardClick : undefined, role: item.link ? 'link' : undefined, tabIndex: item.link ? 0 : undefined, onKeyDown: (e) => e.key === 'Enter' && item.link && handleCardClick(), children: jsxRuntimeExports.jsx("div", { className: "ai-chat-project-card__media", children: imageUrl && !imageError ? (jsxRuntimeExports.jsx("img", { src: imageUrl, alt: item.alt || 'Image', onError: () => setImageError(true) })) : (jsxRuntimeExports.jsx("div", { className: "ai-chat-project-card__placeholder", children: imageError ? 'Failed to load' : 'No image' })) }) }));
45387
+ }
45388
+ // Overlay variant - title overlaid on image
45389
+ if (effectiveVariant === 'overlay') {
45390
+ return (jsxRuntimeExports.jsx("div", { className: `ai-chat-project-card ai-chat-project-card--overlay ${item.link ? 'clickable' : ''}`, style: style, onClick: item.link ? handleCardClick : undefined, role: item.link ? 'link' : undefined, tabIndex: item.link ? 0 : undefined, onKeyDown: (e) => e.key === 'Enter' && item.link && handleCardClick(), children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-project-card__media", children: [imageUrl && !imageError ? (jsxRuntimeExports.jsx("img", { src: imageUrl, alt: item.alt || item.title || 'Image', onError: () => setImageError(true) })) : (jsxRuntimeExports.jsx("div", { className: "ai-chat-project-card__placeholder", children: imageError ? 'Failed to load' : 'No image' })), item.title && (jsxRuntimeExports.jsx("div", { className: "ai-chat-project-card__overlay", children: jsxRuntimeExports.jsx("h4", { className: "ai-chat-project-card__overlay-title", children: truncate(item.title, 50) }) }))] }) }));
45391
+ }
45392
+ // Full variant - image with separate content section below
45393
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-project-card ai-chat-project-card--full ${item.link ? 'clickable' : ''}`, style: style, onClick: item.link ? handleCardClick : undefined, role: item.link ? 'link' : undefined, tabIndex: item.link ? 0 : undefined, onKeyDown: (e) => e.key === 'Enter' && item.link && handleCardClick(), children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-project-card__media", children: imageUrl && !imageError ? (jsxRuntimeExports.jsx("img", { src: imageUrl, alt: item.alt || item.title || 'Project image', onError: () => setImageError(true) })) : (jsxRuntimeExports.jsx("div", { className: "ai-chat-project-card__placeholder", children: imageError ? 'Failed to load' : 'No image' })) }), hasTextContent && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-project-card__content", children: [item.title && (jsxRuntimeExports.jsx("h4", { className: "ai-chat-project-card__title", children: truncate(item.title, 60) })), item.description && (jsxRuntimeExports.jsx("p", { className: "ai-chat-project-card__description", children: truncate(item.description, 120) })), item.link && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-project-card__link", children: [jsxRuntimeExports.jsx("span", { children: item.linkText || 'View' }), jsxRuntimeExports.jsx(ExternalLinkIcon, {})] }))] }))] }));
45436
45394
  }
45437
45395
 
45438
45396
  /**
45439
- * Register microsoft-calendar-appointment action handler and renderer.
45440
- * Called by initializeActionHandlers to prevent tree-shaking.
45397
+ * URL validation utilities for images, cards, and links
45398
+ * Prevents 404 errors by validating URLs before display
45441
45399
  */
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);
45400
+ /**
45401
+ * Validate a single URL by attempting to load it
45402
+ */
45403
+ /**
45404
+ * Validate an image URL by attempting to load it as an Image
45405
+ */
45406
+ async function validateImageUrl(url, timeout = 5000) {
45407
+ if (!url || typeof url !== 'string') {
45408
+ return { isValid: false, error: 'Invalid URL format' };
45409
+ }
45410
+ try {
45411
+ new URL(url);
45412
+ }
45413
+ catch (e) {
45414
+ return { isValid: false, error: 'Invalid URL structure' };
45415
+ }
45416
+ return new Promise((resolve) => {
45417
+ const img = new Image();
45418
+ const timeoutId = setTimeout(() => {
45419
+ img.src = '';
45420
+ resolve({ isValid: false, error: 'Image load timeout' });
45421
+ }, timeout);
45422
+ img.onload = () => {
45423
+ clearTimeout(timeoutId);
45424
+ resolve({ isValid: true });
45452
45425
  };
45453
- const handleDismiss = onActionDismiss
45454
- ? (toolCallId) => {
45455
- resolveActionState(toolCallId, { __dismissed: true });
45456
- onActionDismiss(toolCallId);
45426
+ img.onerror = () => {
45427
+ clearTimeout(timeoutId);
45428
+ resolve({ isValid: false, error: 'Failed to load image' });
45429
+ };
45430
+ img.src = url;
45431
+ });
45432
+ }
45433
+ /**
45434
+ * Validate multiple image URLs concurrently
45435
+ */
45436
+ async function validateImageUrls(urls, timeout = 5000, maxConcurrent = 10) {
45437
+ const results = new Map();
45438
+ // Process in batches to limit concurrent requests
45439
+ for (let i = 0; i < urls.length; i += maxConcurrent) {
45440
+ const batch = urls.slice(i, i + maxConcurrent);
45441
+ const batchResults = await Promise.all(batch.map(async (url) => {
45442
+ const result = await validateImageUrl(url, timeout);
45443
+ return { url, result };
45444
+ }));
45445
+ batchResults.forEach(({ url, result }) => {
45446
+ results.set(url, result);
45447
+ });
45448
+ }
45449
+ return results;
45450
+ }
45451
+ /**
45452
+ * Validate image items and separate valid from invalid
45453
+ */
45454
+ async function validateImageItems(items, timeout = 5000) {
45455
+ const urls = items.map(item => item.url).filter(Boolean);
45456
+ if (urls.length === 0) {
45457
+ return { validItems: [], invalidItems: items };
45458
+ }
45459
+ const validationResults = await validateImageUrls(urls, timeout);
45460
+ const validItems = [];
45461
+ const invalidItems = [];
45462
+ items.forEach(item => {
45463
+ if (!item.url) {
45464
+ invalidItems.push({
45465
+ ...item,
45466
+ isValid: false,
45467
+ validationError: 'Missing URL',
45468
+ });
45469
+ return;
45470
+ }
45471
+ const result = validationResults.get(item.url);
45472
+ if (result?.isValid) {
45473
+ validItems.push({
45474
+ ...item,
45475
+ isValid: true,
45476
+ });
45477
+ }
45478
+ else {
45479
+ invalidItems.push({
45480
+ ...item,
45481
+ isValid: false,
45482
+ validationError: result?.error || 'Unknown error',
45483
+ });
45484
+ }
45485
+ });
45486
+ return { validItems, invalidItems };
45487
+ }
45488
+ /**
45489
+ * Preload and validate images before rendering
45490
+ * Returns items with validation status
45491
+ */
45492
+ async function preloadAndValidateImages(items, timeout = 5000) {
45493
+ const { validItems, invalidItems } = await validateImageItems(items, timeout);
45494
+ if (invalidItems.length > 0) {
45495
+ console.warn('[URLValidator] Invalid image URLs detected:', invalidItems.map(i => ({
45496
+ url: i.url,
45497
+ error: i.validationError,
45498
+ })));
45499
+ }
45500
+ return [...validItems, ...invalidItems];
45501
+ }
45502
+
45503
+ function determineLayout(items, requestedLayout) {
45504
+ // Single item always uses single layout
45505
+ if (items.length === 1) {
45506
+ return 'single';
45507
+ }
45508
+ // For multiple items, use gallery (which now supports overlay titles)
45509
+ // Cards and gallery are now visually the same - 2-column grid with overlay titles
45510
+ return 'gallery';
45511
+ }
45512
+ function determineColumns(itemCount, maxColumns = 2) {
45513
+ if (itemCount === 1)
45514
+ return 1;
45515
+ return Math.min(2, maxColumns);
45516
+ }
45517
+ function StructuredImageDisplay({ action, onComplete, accentColor, maxColumns = 3 }) {
45518
+ const rawState = action.input;
45519
+ const hasCompletedRef = reactExports.useRef(false);
45520
+ const [validatedItems, setValidatedItems] = reactExports.useState([]);
45521
+ const [isValidating, setIsValidating] = reactExports.useState(true);
45522
+ const [validationErrors, setValidationErrors] = reactExports.useState([]);
45523
+ // Provide safe defaults if state is missing
45524
+ const state = {
45525
+ items: rawState?.items || [],
45526
+ layout: rawState?.layout || 'single',
45527
+ context: rawState?.context,
45528
+ columns: rawState?.columns,
45529
+ status: rawState?.status || 'displaying',
45530
+ error: rawState?.error,
45531
+ };
45532
+ const isError = state.status === 'error';
45533
+ // Validate URLs before displaying
45534
+ reactExports.useEffect(() => {
45535
+ if (state.items.length === 0) {
45536
+ setIsValidating(false);
45537
+ return;
45538
+ }
45539
+ let isMounted = true;
45540
+ const validateItems = async () => {
45541
+ try {
45542
+ const validated = await preloadAndValidateImages(state.items, 3000);
45543
+ if (!isMounted)
45544
+ return;
45545
+ const valid = validated.filter(item => item.isValid !== false);
45546
+ const invalid = validated.filter(item => item.isValid === false);
45547
+ setValidatedItems(valid);
45548
+ if (invalid.length > 0) {
45549
+ const errors = invalid.map(item => `${item.url}: ${item.validationError || 'Failed to load'}`);
45550
+ setValidationErrors(errors);
45551
+ console.warn('[StructuredImageDisplay] Filtered invalid URLs:', errors);
45552
+ }
45457
45553
  }
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 }));
45554
+ catch (error) {
45555
+ console.error('[StructuredImageDisplay] Validation error:', error);
45556
+ // Fallback to unvalidated items on error
45557
+ if (isMounted) {
45558
+ setValidatedItems(state.items);
45559
+ }
45560
+ }
45561
+ finally {
45562
+ if (isMounted) {
45563
+ setIsValidating(false);
45564
+ }
45565
+ }
45566
+ };
45567
+ validateItems();
45568
+ return () => {
45569
+ isMounted = false;
45570
+ };
45571
+ }, [state.items]);
45572
+ // Auto-complete on mount so AI can continue generating text response
45573
+ reactExports.useEffect(() => {
45574
+ if (!action.done && !hasCompletedRef.current && onComplete && state.items.length > 0) {
45575
+ hasCompletedRef.current = true;
45576
+ onComplete(action.toolCallId, { ...state, status: 'displaying' });
45577
+ }
45578
+ }, [action.done, action.toolCallId, onComplete, state]);
45579
+ const handleInteraction = () => {
45580
+ onComplete?.(action.toolCallId, { ...state, status: 'interacted' });
45581
+ };
45582
+ const handleLinkClick = (url) => {
45583
+ handleInteraction();
45584
+ };
45585
+ const style = accentColor ? { '--action-accent': accentColor } : undefined;
45586
+ // Error state
45587
+ if (isError) {
45588
+ return (jsxRuntimeExports.jsx("div", { className: "ai-chat-structured-image ai-chat-structured-image--error", style: style, children: jsxRuntimeExports.jsx("div", { className: "ai-chat-structured-image__error", children: state.error || 'Failed to load media' }) }));
45589
+ }
45590
+ // Loading state
45591
+ if (isValidating) {
45592
+ return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-structured-image", style: style, children: [state.context && (jsxRuntimeExports.jsx("p", { className: "ai-chat-structured-image__context", children: state.context })), jsxRuntimeExports.jsx("div", { className: "ai-chat-structured-image__loading", children: "Validating images..." })] }));
45593
+ }
45594
+ // No valid items after validation
45595
+ if (validatedItems.length === 0) {
45596
+ return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-structured-image", style: style, children: [state.context && (jsxRuntimeExports.jsx("p", { className: "ai-chat-structured-image__context", children: state.context })), validationErrors.length > 0 && (jsxRuntimeExports.jsx("div", { className: "ai-chat-structured-image__error", children: "All images failed to load. Please check the URLs." }))] }));
45597
+ }
45598
+ const layout = determineLayout(validatedItems, state.layout);
45599
+ const columns = state.columns || determineColumns(validatedItems.length, maxColumns);
45600
+ return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-structured-image", style: style, children: [state.context && (jsxRuntimeExports.jsx("p", { className: "ai-chat-structured-image__context", children: state.context })), validationErrors.length > 0 && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-structured-image__warning", children: [validationErrors.length, " image(s) could not be loaded and were filtered."] })), layout === 'single' && validatedItems[0] && (jsxRuntimeExports.jsx(ImageCard, { item: validatedItems[0], accentColor: accentColor, onLinkClick: handleLinkClick })), layout === 'gallery' && (jsxRuntimeExports.jsx(ImageGallery, { items: validatedItems, columns: columns, accentColor: accentColor, maxColumns: maxColumns })), layout === 'cards' && (jsxRuntimeExports.jsx("div", { className: "ai-chat-structured-image__cards", style: { '--card-columns': validatedItems.length === 1 ? 1 : 2 }, children: validatedItems.map((item, index) => (jsxRuntimeExports.jsx(ProjectCard, { item: item, accentColor: accentColor, onLinkClick: handleLinkClick, variant: "overlay" }, index))) })), layout === 'carousel' && (jsxRuntimeExports.jsx(ImageCarousel, { items: validatedItems, accentColor: accentColor, onLinkClick: handleLinkClick }))] }));
45601
+ }
45602
+ function ChevronLeftIcon() {
45603
+ return (jsxRuntimeExports.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("polyline", { points: "15 18 9 12 15 6" }) }));
45604
+ }
45605
+ function ChevronRightIcon() {
45606
+ return (jsxRuntimeExports.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("polyline", { points: "9 18 15 12 9 6" }) }));
45607
+ }
45608
+ function ImageCarousel({ items, accentColor, onLinkClick }) {
45609
+ const [currentIndex, setCurrentIndex] = React.useState(0);
45610
+ const containerRef = reactExports.useRef(null);
45611
+ const goToPrevious = () => {
45612
+ setCurrentIndex(prev => prev === 0 ? items.length - 1 : prev - 1);
45467
45613
  };
45614
+ const goToNext = () => {
45615
+ setCurrentIndex(prev => prev === items.length - 1 ? 0 : prev + 1);
45616
+ };
45617
+ const style = accentColor ? { '--action-accent': accentColor } : undefined;
45618
+ return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-image-carousel", style: style, ref: containerRef, children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-image-carousel__track", style: { transform: `translateX(-${currentIndex * 100}%)` }, children: items.map((item, index) => (jsxRuntimeExports.jsx("div", { className: "ai-chat-image-carousel__slide", children: jsxRuntimeExports.jsx(ProjectCard, { item: item, accentColor: accentColor, onLinkClick: onLinkClick }) }, index))) }), items.length > 1 && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("button", { className: "ai-chat-image-carousel__nav prev", onClick: goToPrevious, "aria-label": "Previous", children: jsxRuntimeExports.jsx(ChevronLeftIcon, {}) }), jsxRuntimeExports.jsx("button", { className: "ai-chat-image-carousel__nav next", onClick: goToNext, "aria-label": "Next", children: jsxRuntimeExports.jsx(ChevronRightIcon, {}) }), jsxRuntimeExports.jsx("div", { className: "ai-chat-image-carousel__dots", children: items.map((_, index) => (jsxRuntimeExports.jsx("button", { className: `ai-chat-image-carousel__dot ${index === currentIndex ? 'active' : ''}`, onClick: () => setCurrentIndex(index), "aria-label": `Go to slide ${index + 1}` }, index))) })] }))] }));
45619
+ }
45620
+
45621
+ const pendingResolvers = new Map();
45622
+ const resumeCallbacks = new Map();
45623
+ const frontendActionHandlers = {};
45624
+ const actionRenderers = {};
45625
+ function getFrontendActionHandler(implementation) {
45626
+ return frontendActionHandlers[implementation];
45627
+ }
45628
+ function getActionRenderer(implementation) {
45629
+ return actionRenderers[implementation];
45630
+ }
45631
+ function waitForActionState(toolCallId) {
45632
+ return new Promise((resolve) => {
45633
+ pendingResolvers.set(toolCallId, resolve);
45634
+ });
45635
+ }
45636
+ function resolveActionState(toolCallId, state) {
45637
+ const resolver = pendingResolvers.get(toolCallId);
45638
+ if (resolver) {
45639
+ pendingResolvers.delete(toolCallId);
45640
+ resolver(state);
45641
+ return;
45642
+ }
45643
+ const resumeCallback = resumeCallbacks.get(toolCallId);
45644
+ if (resumeCallback) {
45645
+ resumeCallback(state).catch((error) => {
45646
+ console.error("[Action] Failed to resume action:", error);
45647
+ });
45648
+ }
45649
+ }
45650
+ function registerActionResumeCallback(toolCallId, callback) {
45651
+ resumeCallbacks.set(toolCallId, callback);
45652
+ }
45653
+ function unregisterActionResumeCallback(toolCallId) {
45654
+ resumeCallbacks.delete(toolCallId);
45468
45655
  }
45469
45656
 
45470
45657
  /**
@@ -45472,9 +45659,15 @@
45472
45659
  * Called by initializeActionHandlers to prevent tree-shaking.
45473
45660
  */
45474
45661
  function registerLinkPreviewAction() {
45475
- // Handler - auto-completes immediately since no user input is needed
45662
+ // Handler - auto-completes immediately, returns body for agent
45476
45663
  frontendActionHandlers["link-preview"] = async (_input, state, _context) => {
45477
- return { ...state, status: "displaying" };
45664
+ const links = state?.links || [];
45665
+ // Return body directly - sent to backend via continueAgentAction
45666
+ return {
45667
+ status: "displayed",
45668
+ linkCount: links.length,
45669
+ message: `Displayed ${links.length} link preview${links.length > 1 ? 's' : ''}.`,
45670
+ };
45478
45671
  };
45479
45672
  // Renderer - displays the link preview card
45480
45673
  actionRenderers["link-preview"] = (message, accentColor) => {
@@ -45484,16 +45677,15 @@
45484
45677
  const handleComplete = (toolCallId, newState) => {
45485
45678
  resolveActionState(toolCallId, newState);
45486
45679
  };
45487
- // Check if action state indicates it's already complete (displaying or clicked)
45488
- const state = action.state;
45489
- const status = state?.status;
45490
- const isDone = action.done || status === "displaying" || status === "clicked";
45680
+ // Check if action input indicates it's already complete (displaying or clicked)
45681
+ const input = action.input;
45682
+ const status = input?.status;
45683
+ const isDone = action.done || status === "displaying" || status === "displayed" || status === "clicked";
45491
45684
  return (jsxRuntimeExports.jsx(LinkPreviewCard, { action: {
45492
45685
  implementation: action.implementation,
45493
45686
  toolCallId: action.toolCallId,
45494
45687
  actionId: action.actionId,
45495
45688
  input: action.input,
45496
- state: action.state,
45497
45689
  done: isDone,
45498
45690
  }, onComplete: handleComplete, accentColor: accentColor }));
45499
45691
  };
@@ -45504,9 +45696,15 @@
45504
45696
  * Called by initializeActionHandlers to prevent tree-shaking.
45505
45697
  */
45506
45698
  function registerVideoPlayerAction() {
45507
- // Handler - auto-completes immediately since no user input is needed
45699
+ // Handler - auto-completes immediately, returns body for agent
45508
45700
  frontendActionHandlers["video-player"] = async (_input, state, _context) => {
45509
- return { ...state, status: "displaying" };
45701
+ const videos = state?.videos || [];
45702
+ // Return body directly - sent to backend via continueAgentAction
45703
+ return {
45704
+ status: "displayed",
45705
+ videoCount: videos.length,
45706
+ message: `Displayed ${videos.length} video${videos.length !== 1 ? 's' : ''}.`,
45707
+ };
45510
45708
  };
45511
45709
  // Renderer - displays the embedded video player card
45512
45710
  actionRenderers["video-player"] = (message, accentColor) => {
@@ -45516,16 +45714,15 @@
45516
45714
  const handleComplete = (toolCallId, newState) => {
45517
45715
  resolveActionState(toolCallId, newState);
45518
45716
  };
45519
- // Check if action state indicates it's already complete (displaying or played)
45520
- const state = action.state;
45521
- const status = state?.status;
45522
- const isDone = action.done || status === "displaying" || status === "played";
45717
+ // Check if action input indicates it's already complete (displaying or played)
45718
+ const input = action.input;
45719
+ const status = input?.status;
45720
+ const isDone = action.done || status === "displaying" || status === "displayed" || status === "played";
45523
45721
  return (jsxRuntimeExports.jsx(VideoPlayerCard, { action: {
45524
45722
  implementation: action.implementation,
45525
45723
  toolCallId: action.toolCallId,
45526
45724
  actionId: action.actionId,
45527
45725
  input: action.input,
45528
- state: action.state,
45529
45726
  done: isDone,
45530
45727
  }, onComplete: handleComplete, accentColor: accentColor }));
45531
45728
  };
@@ -45536,9 +45733,15 @@
45536
45733
  * Called by initializeActionHandlers to prevent tree-shaking.
45537
45734
  */
45538
45735
  function registerLocationCardAction() {
45539
- // Handler - auto-completes immediately since no user input is needed
45736
+ // Handler - auto-completes immediately, returns body for agent
45540
45737
  frontendActionHandlers["location-card"] = async (_input, state, _context) => {
45541
- return { ...state, status: "displaying" };
45738
+ const locations = state?.locations || [];
45739
+ // Return body directly - sent to backend via continueAgentAction
45740
+ return {
45741
+ status: "displayed",
45742
+ locationCount: locations.length,
45743
+ message: `Displayed ${locations.length} location${locations.length !== 1 ? 's' : ''}.`,
45744
+ };
45542
45745
  };
45543
45746
  // Renderer - displays the location card
45544
45747
  actionRenderers["location-card"] = (message, accentColor, variant) => {
@@ -45548,25 +45751,30 @@
45548
45751
  const handleComplete = (toolCallId, newState) => {
45549
45752
  resolveActionState(toolCallId, newState);
45550
45753
  };
45551
- // Check if action state indicates it's already complete
45552
- const state = action.state;
45553
- const status = state?.status;
45554
- const isDone = action.done || status === "displaying" || status === "directions_opened";
45754
+ // Check if action input indicates it's already complete
45755
+ const input = action.input;
45756
+ const status = input?.status;
45757
+ const isDone = action.done || status === "displaying" || status === "displayed" || status === "directions_opened";
45555
45758
  return (jsxRuntimeExports.jsx(LocationCard, { action: {
45556
45759
  implementation: action.implementation,
45557
45760
  toolCallId: action.toolCallId,
45558
45761
  actionId: action.actionId,
45559
45762
  input: action.input,
45560
- state: action.state,
45561
45763
  done: isDone,
45562
45764
  }, onComplete: handleComplete, accentColor: accentColor, maxColumns: variant === 'fullpage' ? 3 : 1 }));
45563
45765
  };
45564
45766
  }
45565
45767
 
45566
45768
  function registerContactCardAction() {
45567
- // Handler - auto-completes immediately since no user input is needed
45769
+ // Handler - auto-completes immediately, returns body for agent
45568
45770
  frontendActionHandlers['contact-card'] = async (_input, state, _context) => {
45569
- return { ...state, status: 'displaying' };
45771
+ const contacts = state?.contacts || [];
45772
+ // Return body directly - sent to backend via continueAgentAction
45773
+ return {
45774
+ status: 'displayed',
45775
+ contactCount: contacts.length,
45776
+ message: `Displayed ${contacts.length} contact${contacts.length !== 1 ? 's' : ''}.`,
45777
+ };
45570
45778
  };
45571
45779
  // Renderer - displays the contact card
45572
45780
  actionRenderers['contact-card'] = (message, accentColor, variant) => {
@@ -45576,16 +45784,15 @@
45576
45784
  const handleComplete = (toolCallId, newState) => {
45577
45785
  resolveActionState(toolCallId, newState);
45578
45786
  };
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';
45787
+ // Check if action input indicates it's already complete
45788
+ const input = action.input;
45789
+ const status = input?.status;
45790
+ const isDone = action.done || status === 'displaying' || status === 'displayed' || status === 'contacted';
45583
45791
  return (jsxRuntimeExports.jsx(ContactCard, { action: {
45584
45792
  implementation: action.implementation,
45585
45793
  toolCallId: action.toolCallId,
45586
45794
  actionId: action.actionId,
45587
45795
  input: action.input,
45588
- state: action.state,
45589
45796
  done: isDone,
45590
45797
  }, onComplete: handleComplete, accentColor: accentColor, maxColumns: variant === 'fullpage' ? 3 : 1 }));
45591
45798
  };
@@ -45605,16 +45812,15 @@
45605
45812
  const handleComplete = (toolCallId, newState) => {
45606
45813
  resolveActionState(toolCallId, newState);
45607
45814
  };
45608
- // Check if action state indicates it's already complete
45609
- const state = action.state;
45610
- const status = state?.status;
45815
+ // Check if action input indicates it's already complete
45816
+ const input = action.input;
45817
+ const status = input?.status;
45611
45818
  const isDone = action.done || status === 'displaying' || status === 'contacted';
45612
45819
  return (jsxRuntimeExports.jsx(ContactCard, { action: {
45613
45820
  implementation: action.implementation,
45614
45821
  toolCallId: action.toolCallId,
45615
45822
  actionId: action.actionId,
45616
45823
  input: action.input,
45617
- state: action.state,
45618
45824
  done: isDone,
45619
45825
  }, onComplete: handleComplete, accentColor: accentColor, maxColumns: variant === 'fullpage' ? 3 : 1 }));
45620
45826
  };
@@ -45626,7 +45832,9 @@
45626
45832
  return waitForActionState(context.toolCallId);
45627
45833
  };
45628
45834
  // Renderer - displays the form card
45629
- actionRenderers['display-form'] = (message, accentColor, variant, onActionDismiss) => {
45835
+ // Rendering is based only on action.input and action.done
45836
+ // When done=true, FormCard shows a simple completion indicator
45837
+ actionRenderers['display-form'] = (message, accentColor, _variant, onActionDismiss) => {
45630
45838
  const action = message.action;
45631
45839
  if (!action)
45632
45840
  return null;
@@ -45634,22 +45842,14 @@
45634
45842
  resolveActionState(toolCallId, newState);
45635
45843
  };
45636
45844
  const handleDismiss = onActionDismiss
45637
- ? (toolCallId) => {
45638
- resolveActionState(toolCallId, { __dismissed: true });
45639
- onActionDismiss(toolCallId);
45640
- }
45845
+ ? (toolCallId) => onActionDismiss(toolCallId)
45641
45846
  : 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
45847
  return (jsxRuntimeExports.jsx(FormCard, { action: {
45647
45848
  implementation: action.implementation,
45648
45849
  toolCallId: action.toolCallId,
45649
45850
  actionId: action.actionId,
45650
45851
  input: action.input,
45651
- state: action.state,
45652
- done: isDone,
45852
+ done: action.done ?? false,
45653
45853
  }, onComplete: handleComplete, onDismiss: handleDismiss, accentColor: accentColor }));
45654
45854
  };
45655
45855
  }
@@ -45672,21 +45872,64 @@
45672
45872
  // Register the handler
45673
45873
  registerBookContactAppointmentHandler();
45674
45874
  // Register the renderer
45675
- actionRenderers['book-contact-appointment'] = (message, accentColor) => {
45875
+ actionRenderers['book-contact-appointment'] = (message, accentColor, _variant, _onActionDismiss, onCallEndpoint) => {
45676
45876
  const action = message.action;
45677
45877
  if (!action)
45678
45878
  return null;
45679
45879
  const handleComplete = (toolCallId, newState) => {
45680
45880
  resolveActionState(toolCallId, newState);
45681
45881
  };
45882
+ // Create action-specific endpoint callback
45883
+ // Include toolCallId for done flag enforcement (server rejects calls for completed actions)
45884
+ const handleCallEndpoint = onCallEndpoint
45885
+ ? async (endpoint, input, options) => {
45886
+ return onCallEndpoint(action.actionId, endpoint, input, { ...options, toolCallId: action.toolCallId });
45887
+ }
45888
+ : undefined;
45889
+ // Create dismiss handler
45890
+ const handleDismiss = _onActionDismiss
45891
+ ? (toolCallId) => _onActionDismiss(toolCallId)
45892
+ : undefined;
45682
45893
  return (jsxRuntimeExports.jsx(BookContactAppointmentCard, { action: {
45683
45894
  implementation: action.implementation,
45684
45895
  toolCallId: action.toolCallId,
45685
45896
  actionId: action.actionId,
45686
45897
  input: action.input,
45687
- state: action.state,
45688
45898
  done: action.done ?? false,
45689
- }, onComplete: handleComplete, accentColor: accentColor }));
45899
+ }, onComplete: handleComplete, onDismiss: handleDismiss, onCallEndpoint: handleCallEndpoint, accentColor: accentColor }));
45900
+ };
45901
+ }
45902
+
45903
+ function registerStructuredImageAction() {
45904
+ // Handler - auto-completes immediately, returns body for agent
45905
+ frontendActionHandlers['structured-image'] = async (_input, state, _context) => {
45906
+ const images = state?.images || [];
45907
+ // Return body directly - sent to backend via continueAgentAction
45908
+ return {
45909
+ status: 'displayed',
45910
+ imageCount: images.length,
45911
+ message: `Displayed ${images.length} image${images.length !== 1 ? 's' : ''}.`,
45912
+ };
45913
+ };
45914
+ // Renderer - displays the image content
45915
+ actionRenderers['structured-image'] = (message, accentColor, variant, onActionDismiss) => {
45916
+ const action = message.action;
45917
+ if (!action)
45918
+ return null;
45919
+ const handleComplete = (toolCallId, newState) => {
45920
+ resolveActionState(toolCallId, newState);
45921
+ };
45922
+ // Check if action input indicates it's already complete
45923
+ const input = action.input;
45924
+ const status = input?.status;
45925
+ const isDone = action.done || status === 'displaying' || status === 'displayed' || status === 'interacted';
45926
+ return (jsxRuntimeExports.jsx(StructuredImageDisplay, { action: {
45927
+ implementation: action.implementation,
45928
+ toolCallId: action.toolCallId,
45929
+ actionId: action.actionId,
45930
+ input: action.input,
45931
+ done: isDone,
45932
+ }, onComplete: handleComplete, onDismiss: onActionDismiss ? () => onActionDismiss(action.toolCallId) : undefined, accentColor: accentColor, maxColumns: variant === 'fullpage' ? 3 : 2 }));
45690
45933
  };
45691
45934
  }
45692
45935
 
@@ -45702,8 +45945,6 @@
45702
45945
  return;
45703
45946
  initialized = true;
45704
45947
  // Explicitly call each registration function to prevent tree-shaking
45705
- registerGoogleCalendarAction();
45706
- registerMicrosoftCalendarAction();
45707
45948
  registerLinkPreviewAction();
45708
45949
  registerVideoPlayerAction();
45709
45950
  registerLocationCardAction();
@@ -45711,6 +45952,7 @@
45711
45952
  registerContactCardAction();
45712
45953
  registerDisplayFormAction();
45713
45954
  registerBookContactAppointmentAction();
45955
+ registerStructuredImageAction();
45714
45956
  }
45715
45957
 
45716
45958
  /**
@@ -45973,9 +46215,49 @@
45973
46215
  };
45974
46216
  });
45975
46217
  }
46218
+ /**
46219
+ * Clean up messages that were interrupted during streaming.
46220
+ * - Marks streaming messages as complete
46221
+ * - Removes empty assistant messages
46222
+ * - Marks incomplete tool calls as done
46223
+ */
46224
+ function cleanupInterruptedMessages(messages) {
46225
+ return messages
46226
+ .map((msg) => {
46227
+ // Mark streaming messages as complete
46228
+ if (msg.isStreaming) {
46229
+ msg = { ...msg, isStreaming: false };
46230
+ }
46231
+ // Mark incomplete tool calls as done (they were interrupted)
46232
+ if (msg.message.role === 'tool' && msg.action && !msg.action.done) {
46233
+ msg = {
46234
+ ...msg,
46235
+ action: {
46236
+ ...msg.action,
46237
+ done: true,
46238
+ // Mark as interrupted so UI can show appropriate state
46239
+ input: {
46240
+ ...msg.action.input,
46241
+ _interrupted: true,
46242
+ },
46243
+ },
46244
+ };
46245
+ }
46246
+ return msg;
46247
+ })
46248
+ // Remove empty assistant messages (streaming was interrupted before content)
46249
+ .filter((msg) => {
46250
+ if (msg.message.role === 'assistant') {
46251
+ const content = msg.message.content;
46252
+ return content && typeof content === 'string' && content.trim().length > 0;
46253
+ }
46254
+ return true;
46255
+ });
46256
+ }
45976
46257
  function hydrateMessages(messages) {
45977
46258
  const visibleMessages = messages.filter((message) => !message.action?.hidden);
45978
- return hydrateToolNames(visibleMessages);
46259
+ const cleanedMessages = cleanupInterruptedMessages(visibleMessages);
46260
+ return hydrateToolNames(cleanedMessages);
45979
46261
  }
45980
46262
 
45981
46263
  function deriveErrorInfo(error) {
@@ -46045,6 +46327,75 @@
46045
46327
  return { message: 'Something went wrong. Please try again.' };
46046
46328
  }
46047
46329
 
46330
+ /**
46331
+ * Stream Buffer
46332
+ * Smooths out streaming text rendering by buffering words and draining them
46333
+ * with requestAnimationFrame for a fluid typing effect.
46334
+ */
46335
+ function createStreamBuffer() {
46336
+ return {
46337
+ pendingWords: [],
46338
+ displayedContent: '',
46339
+ streamEnded: false,
46340
+ rafHandle: null,
46341
+ };
46342
+ }
46343
+ function appendToBuffer(buffer, content) {
46344
+ // Split by whitespace while preserving the whitespace characters
46345
+ const words = content.split(/(\s+)/);
46346
+ buffer.pendingWords.push(...words.filter(w => w.length > 0));
46347
+ }
46348
+ function startBufferDrain(buffer, onContentUpdate) {
46349
+ if (buffer.rafHandle !== null) {
46350
+ return; // Already draining
46351
+ }
46352
+ const drainLoop = () => {
46353
+ if (buffer.pendingWords.length === 0) {
46354
+ if (buffer.streamEnded) {
46355
+ buffer.rafHandle = null;
46356
+ return;
46357
+ }
46358
+ // No words to render, wait for more
46359
+ buffer.rafHandle = requestAnimationFrame(drainLoop);
46360
+ return;
46361
+ }
46362
+ // Adaptive: render more words if buffer is filling up
46363
+ const wordsToRender = buffer.pendingWords.length > 20 ? 3 : 1;
46364
+ const chunk = buffer.pendingWords.splice(0, wordsToRender).join('');
46365
+ buffer.displayedContent += chunk;
46366
+ onContentUpdate(buffer.displayedContent);
46367
+ buffer.rafHandle = requestAnimationFrame(drainLoop);
46368
+ };
46369
+ buffer.rafHandle = requestAnimationFrame(drainLoop);
46370
+ }
46371
+ function flushBuffer(buffer) {
46372
+ buffer.streamEnded = true;
46373
+ if (buffer.rafHandle !== null) {
46374
+ cancelAnimationFrame(buffer.rafHandle);
46375
+ buffer.rafHandle = null;
46376
+ }
46377
+ const remaining = buffer.pendingWords.join('');
46378
+ buffer.displayedContent += remaining;
46379
+ buffer.pendingWords = [];
46380
+ return buffer.displayedContent;
46381
+ }
46382
+ function cancelBuffer(buffer) {
46383
+ if (buffer.rafHandle !== null) {
46384
+ cancelAnimationFrame(buffer.rafHandle);
46385
+ buffer.rafHandle = null;
46386
+ }
46387
+ buffer.streamEnded = true;
46388
+ }
46389
+ function resetBuffer(buffer) {
46390
+ if (buffer.rafHandle !== null) {
46391
+ cancelAnimationFrame(buffer.rafHandle);
46392
+ buffer.rafHandle = null;
46393
+ }
46394
+ buffer.pendingWords = [];
46395
+ buffer.displayedContent = '';
46396
+ buffer.streamEnded = false;
46397
+ }
46398
+
46048
46399
  function createStreamState() {
46049
46400
  return {
46050
46401
  currentContent: "",
@@ -46054,6 +46405,7 @@
46054
46405
  sources: [],
46055
46406
  toolCallToActionId: {},
46056
46407
  requestId: generateMessageId(),
46408
+ buffer: createStreamBuffer(),
46057
46409
  };
46058
46410
  }
46059
46411
  function upsertMessage(setState, message, isTyping) {
@@ -46116,6 +46468,8 @@
46116
46468
  },
46117
46469
  isStreaming: false,
46118
46470
  toolExecuting: existingName,
46471
+ // Mark action as done when tool message is finalized
46472
+ action: entry.action ? { ...entry.action, done: true } : undefined,
46119
46473
  };
46120
46474
  });
46121
46475
  return { ...prev, messages, isTyping: false, isLoading: false };
@@ -46124,26 +46478,34 @@
46124
46478
  }
46125
46479
 
46126
46480
  function handleContentEvent(event, streamState, onMessageUpdate, setState) {
46481
+ // Track full content for finalization
46127
46482
  streamState.currentContent += event.content;
46128
- const assistantMessage = {
46129
- id: streamState.currentMessageId,
46130
- message: { role: "assistant", content: streamState.currentContent },
46131
- timestamp: new Date().toISOString(),
46132
- sources: streamState.sources,
46133
- isStreaming: true,
46134
- };
46135
- streamState.newMessageIds.add(assistantMessage.id);
46136
- onMessageUpdate(assistantMessage);
46137
- const hasContent = assistantMessage.message.content?.trim().length || 0 > 0;
46138
- const isToolExecuting = streamState.activeToolCallCount > 0;
46139
- const isTyping = (!hasContent && assistantMessage.isStreaming) || isToolExecuting;
46140
- upsertMessage(setState, assistantMessage, isTyping);
46483
+ // Add to buffer for smooth rendering
46484
+ appendToBuffer(streamState.buffer, event.content);
46485
+ // Start drain loop if not already running
46486
+ startBufferDrain(streamState.buffer, (displayedContent) => {
46487
+ const assistantMessage = {
46488
+ id: streamState.currentMessageId,
46489
+ message: { role: "assistant", content: displayedContent },
46490
+ timestamp: new Date().toISOString(),
46491
+ sources: streamState.sources,
46492
+ isStreaming: true,
46493
+ };
46494
+ streamState.newMessageIds.add(assistantMessage.id);
46495
+ onMessageUpdate(assistantMessage);
46496
+ const hasContent = displayedContent.trim().length > 0;
46497
+ const isToolExecuting = streamState.activeToolCallCount > 0;
46498
+ const isTyping = (!hasContent && assistantMessage.isStreaming) || isToolExecuting;
46499
+ upsertMessage(setState, assistantMessage, isTyping);
46500
+ });
46141
46501
  }
46142
46502
  function handleToolStartEvent(event, streamState, onMessageUpdate, setState) {
46143
- if (streamState.currentContent.trim()) {
46503
+ // Flush buffer before tool starts
46504
+ const flushedContent = flushBuffer(streamState.buffer);
46505
+ if (flushedContent.trim()) {
46144
46506
  const finalAssistant = {
46145
46507
  id: streamState.currentMessageId,
46146
- message: { role: "assistant", content: streamState.currentContent },
46508
+ message: { role: "assistant", content: flushedContent },
46147
46509
  timestamp: new Date().toISOString(),
46148
46510
  sources: streamState.sources,
46149
46511
  isStreaming: false,
@@ -46154,6 +46516,8 @@
46154
46516
  streamState.currentContent = "";
46155
46517
  streamState.currentMessageId = generateMessageId();
46156
46518
  }
46519
+ // Reset buffer for post-tool content
46520
+ resetBuffer(streamState.buffer);
46157
46521
  const toolMessageId = event.tool_call_id;
46158
46522
  streamState.activeToolCallCount += 1;
46159
46523
  streamState.newMessageIds.add(toolMessageId);
@@ -46171,44 +46535,22 @@
46171
46535
  streamState.activeToolCallCount = Math.max(0, streamState.activeToolCallCount - 1);
46172
46536
  setState(prev => {
46173
46537
  const messages = prev.messages.map((msg) => {
46174
- const matchesToolCall = msg.message.role === "tool" && msg.message.tool_call_id === event.tool_call_id;
46175
- if (!matchesToolCall) {
46538
+ if (msg.message.role !== "tool" || msg.message.tool_call_id !== event.tool_call_id) {
46176
46539
  return msg;
46177
46540
  }
46178
- const existingName = msg.message.name || event.tool_name;
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 = {
46541
+ const toolName = msg.message.name || event.tool_name;
46542
+ // For actions: just mark as done, preserve existing input (display data is immutable)
46543
+ // For non-action tools: update normally
46544
+ const action = msg.action
46545
+ ? { ...msg.action, done: event.done }
46546
+ : undefined;
46547
+ return {
46200
46548
  ...msg,
46201
- message: {
46202
- role: "tool",
46203
- content: event.state ? JSON.stringify(event.state) : (typeof msg.message.content === "string" ? msg.message.content : ""),
46204
- tool_call_id: event.tool_call_id,
46205
- name: existingName,
46206
- },
46549
+ message: { ...msg.message, name: toolName },
46207
46550
  isStreaming: false,
46208
- toolExecuting: existingName,
46551
+ toolExecuting: toolName,
46209
46552
  action,
46210
46553
  };
46211
- return updatedMsg;
46212
46554
  });
46213
46555
  return { ...prev, messages, isTyping: true, isLoading: false };
46214
46556
  });
@@ -46241,11 +46583,6 @@
46241
46583
  return { ...prev, messages, isTyping: true, isLoading: false };
46242
46584
  });
46243
46585
  }
46244
- function handleDoneEvent(event, streamState, _onMessageUpdate, setState) {
46245
- streamState.sources = event.sources;
46246
- streamState.toolCallToActionId = event.tool_call_to_action_id;
46247
- finalizeStreamMessages(setState, streamState.newMessageIds, event.sources, event.tool_call_to_action_id, event.suggestions);
46248
- }
46249
46586
  function handleHaltEvent(event, _streamState, onMessageUpdate, setState) {
46250
46587
  const toolNames = event.tool_calls.map(call => call.name).join(", ");
46251
46588
  const notice = toolNames
@@ -46260,7 +46597,8 @@
46260
46597
  };
46261
46598
  onMessageUpdate(haltMessage);
46262
46599
  upsertMessage(setState, haltMessage, false);
46263
- setState(prev => ({ ...prev, error: "Awaiting external tool handling." }));
46600
+ // Stop loading/typing state when halted
46601
+ setState(prev => ({ ...prev, isLoading: false, isTyping: false, error: "Awaiting external tool handling." }));
46264
46602
  }
46265
46603
  function handleErrorEvent(_event, _streamState, onMessageUpdate, setState) {
46266
46604
  const errorMessage = {
@@ -46272,6 +46610,8 @@
46272
46610
  };
46273
46611
  onMessageUpdate(errorMessage);
46274
46612
  upsertMessage(setState, errorMessage, false);
46613
+ // Stop loading/typing state on error
46614
+ setState(prev => ({ ...prev, isLoading: false, isTyping: false }));
46275
46615
  }
46276
46616
  const eventHandlers = {
46277
46617
  content: handleContentEvent,
@@ -46299,10 +46639,37 @@
46299
46639
  console.warn('[Chat] Unknown event type:', event.type);
46300
46640
  }
46301
46641
  }
46302
-
46303
- function isDismissedState(state) {
46304
- return Boolean(state.__dismissed);
46642
+ function handleDoneEvent(event, streamState, onMessageUpdate, setState) {
46643
+ // Flush any remaining buffered content
46644
+ const flushedContent = flushBuffer(streamState.buffer);
46645
+ // Update the final message with complete content if there was content
46646
+ if (flushedContent.trim()) {
46647
+ const finalMessage = {
46648
+ id: streamState.currentMessageId,
46649
+ message: { role: "assistant", content: flushedContent },
46650
+ timestamp: new Date().toISOString(),
46651
+ sources: event.sources,
46652
+ isStreaming: false,
46653
+ };
46654
+ streamState.newMessageIds.add(finalMessage.id);
46655
+ onMessageUpdate(finalMessage);
46656
+ upsertMessage(setState, finalMessage, false);
46657
+ }
46658
+ streamState.sources = event.sources;
46659
+ streamState.toolCallToActionId = event.tool_call_to_action_id;
46660
+ finalizeStreamMessages(setState, streamState.newMessageIds, event.sources, event.tool_call_to_action_id, event.suggestions);
46305
46661
  }
46662
+
46663
+ /**
46664
+ * Handle the action loop for halting actions.
46665
+ *
46666
+ * Flow:
46667
+ * 1. Display the action in UI
46668
+ * 2. Call the frontend handler (which waits for user interaction or returns immediately for display actions)
46669
+ * 3. Handler returns body when complete
46670
+ * 4. Send body to backend via continueAgentAction
46671
+ * 5. Process any subsequent events (may include new action_request for chained actions)
46672
+ */
46306
46673
  async function handleActionLoop(client, initialEvent, streamState, onMessageUpdate, setState, widgetId, conversationId, getMessages) {
46307
46674
  let pendingEvent = initialEvent;
46308
46675
  while (pendingEvent) {
@@ -46328,7 +46695,6 @@
46328
46695
  toolCallId: pendingEvent.tool_call_id,
46329
46696
  actionId: pendingEvent.action_id,
46330
46697
  input: pendingEvent.input,
46331
- state: pendingEvent.state,
46332
46698
  done: pendingEvent.done ?? false,
46333
46699
  },
46334
46700
  };
@@ -46353,9 +46719,13 @@
46353
46719
  upsertMessage(setState, errorMessage, false);
46354
46720
  return;
46355
46721
  }
46356
- let nextState;
46722
+ // Handler returns body when complete (for display actions this is immediate,
46723
+ // for interactive actions this waits for user completion)
46724
+ // Note: For halting actions, input contains the transformed data from getInitialClientState
46725
+ let body;
46357
46726
  try {
46358
- nextState = await handler(pendingEvent.input, pendingEvent.state, {
46727
+ body = await handler(pendingEvent.input, pendingEvent.input, // Input now contains the display data for halting actions
46728
+ {
46359
46729
  widgetId,
46360
46730
  conversationId,
46361
46731
  toolCallId: pendingEvent.tool_call_id,
@@ -46377,25 +46747,16 @@
46377
46747
  return;
46378
46748
  }
46379
46749
  pendingEvent = null;
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
- }
46750
+ // Send body to backend and continue agent
46751
+ // No need to update message - input is immutable and already contains display data
46391
46752
  let streamEnded = false;
46392
- for await (const event of client.continueAgentMessageStream(conversationId, resumeToolCallId, nextState)) {
46753
+ for await (const event of client.continueAgentAction(conversationId, resumeToolCallId, body)) {
46393
46754
  if (event.type === "action_request") {
46755
+ // Chained action - continue the loop
46394
46756
  pendingEvent = event;
46395
46757
  break;
46396
46758
  }
46397
46759
  if (event.type === "done") {
46398
- // Finalize tool message and stream messages
46399
46760
  finalizeToolMessage(streamState, setState, resumeToolCallId, toolName);
46400
46761
  streamState.sources = event.sources;
46401
46762
  streamState.toolCallToActionId = event.tool_call_to_action_id;
@@ -46425,61 +46786,118 @@
46425
46786
  }
46426
46787
  }
46427
46788
  }
46428
- function setupActionResumeCallbacks(messages, client, conversationId, setState, onMessageUpdate, createStreamState, registerCallback) {
46789
+ /**
46790
+ * Setup resume callbacks for incomplete actions after page reload.
46791
+ *
46792
+ * When a page reloads with an incomplete action, this sets up callbacks
46793
+ * so when the user completes the action, we can continue the agent flow.
46794
+ */
46795
+ function setupActionResumeCallbacks(messages, client, conversationId, widgetId, setState, onMessageUpdate, createStreamState, registerCallback) {
46429
46796
  // Find all incomplete actions and register resume callbacks
46430
46797
  for (const message of messages) {
46431
46798
  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
46799
+ const initialToolCallId = message.action.toolCallId;
46800
+ const initialToolName = message.message.name || message.toolExecuting || "tool";
46801
+ registerCallback(initialToolCallId, async (body) => {
46802
+ // When user completes the action after reload, continue the stream
46436
46803
  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
46804
  setState(prev => ({
46443
46805
  ...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
46806
  isTyping: true,
46454
46807
  }));
46455
46808
  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;
46809
+ let currentToolCallId = initialToolCallId;
46810
+ let currentToolName = initialToolName;
46811
+ let currentBody = body;
46812
+ // Loop to handle chained action_requests
46813
+ while (true) {
46814
+ let nextActionRequest = null;
46815
+ // Continue the agent with the body
46816
+ for await (const event of client.continueAgentAction(conversationId, currentToolCallId, currentBody)) {
46817
+ if (event.type === "action_request") {
46818
+ // Chained action - need to handle the new action request
46819
+ nextActionRequest = event;
46820
+ break;
46821
+ }
46822
+ if (event.type === "done") {
46823
+ finalizeToolMessage(streamState, setState, currentToolCallId, currentToolName);
46824
+ streamState.sources = event.sources;
46825
+ streamState.toolCallToActionId = event.tool_call_to_action_id;
46826
+ finalizeStreamMessages(setState, streamState.newMessageIds, event.sources, event.tool_call_to_action_id, event.suggestions);
46827
+ setState(prev => ({ ...prev, isTyping: false }));
46828
+ return;
46829
+ }
46830
+ if (event.type === "error") {
46831
+ const errorMessage = {
46832
+ id: generateMessageId(),
46833
+ message: {
46834
+ role: "assistant",
46835
+ content: "Sorry, an error occurred. Please try again later.",
46836
+ },
46837
+ timestamp: new Date().toISOString(),
46838
+ sources: [],
46839
+ isError: true,
46840
+ };
46841
+ upsertMessage(setState, errorMessage, false);
46842
+ setState(prev => ({ ...prev, isTyping: false }));
46843
+ return;
46844
+ }
46845
+ handleStreamEvent(event, streamState, onMessageUpdate, setState);
46846
+ }
46847
+ // If no action_request, stream ended normally
46848
+ if (!nextActionRequest) {
46849
+ setState(prev => ({ ...prev, isTyping: false }));
46850
+ return;
46851
+ }
46852
+ // Update UI with new action for the chained action
46853
+ const toolMessage = {
46854
+ id: nextActionRequest.tool_call_id,
46855
+ sources: [],
46856
+ message: {
46857
+ role: "tool",
46858
+ content: "",
46859
+ tool_call_id: nextActionRequest.tool_call_id,
46860
+ name: currentToolName,
46861
+ },
46862
+ timestamp: new Date().toISOString(),
46863
+ isStreaming: true,
46864
+ toolExecuting: currentToolName,
46865
+ action: {
46866
+ implementation: nextActionRequest.implementation,
46867
+ toolCallId: nextActionRequest.tool_call_id,
46868
+ actionId: nextActionRequest.action_id,
46869
+ input: nextActionRequest.input,
46870
+ done: nextActionRequest.done ?? false,
46871
+ },
46872
+ };
46873
+ upsertMessage(setState, toolMessage, true);
46874
+ // Wait for user to complete the chained action
46875
+ const handler = getFrontendActionHandler(nextActionRequest.implementation);
46876
+ if (!handler) {
46877
+ console.error("[Action Resume] No handler for implementation:", nextActionRequest.implementation);
46878
+ setState(prev => ({ ...prev, isTyping: false }));
46879
+ return;
46880
+ }
46881
+ let handlerResult;
46882
+ try {
46883
+ handlerResult = await handler(nextActionRequest.input, nextActionRequest.input, // Input contains display data for halting actions
46884
+ {
46885
+ widgetId,
46886
+ conversationId,
46887
+ toolCallId: nextActionRequest.tool_call_id,
46888
+ actionId: nextActionRequest.action_id,
46889
+ implementation: nextActionRequest.implementation,
46890
+ });
46464
46891
  }
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);
46892
+ catch (handlerError) {
46893
+ console.error("[Action Resume] Handler failed:", handlerError);
46477
46894
  setState(prev => ({ ...prev, isTyping: false }));
46478
46895
  return;
46479
46896
  }
46480
- handleStreamEvent(event, streamState, onMessageUpdate, setState);
46897
+ // Continue loop with new body
46898
+ currentToolCallId = nextActionRequest.tool_call_id;
46899
+ currentBody = handlerResult;
46481
46900
  }
46482
- setState(prev => ({ ...prev, isTyping: false }));
46483
46901
  }
46484
46902
  catch (error) {
46485
46903
  console.error("[Action Resume] Failed to continue stream:", error);
@@ -46558,7 +46976,7 @@
46558
46976
  }));
46559
46977
  // Setup resume callbacks for incomplete actions
46560
46978
  if (conversationId) {
46561
- setupActionResumeCallbacks(hydratedMessages, apiClient.current, conversationId, setState, onMessage ?? (() => { }), createStreamState, registerActionResumeCallback);
46979
+ setupActionResumeCallbacks(hydratedMessages, apiClient.current, conversationId, widgetId, setState, onMessage ?? (() => { }), createStreamState, registerActionResumeCallback);
46562
46980
  }
46563
46981
  }
46564
46982
  catch (error) {
@@ -46592,6 +47010,21 @@
46592
47010
  saveConversation(widgetId, state.conversationId, state.messages);
46593
47011
  }
46594
47012
  }, [widgetId, state.messages, state.conversationId, state.config?.settings.persistConversation]);
47013
+ // Save conversation on page unload to preserve streaming state
47014
+ reactExports.useEffect(() => {
47015
+ const persistConversation = state.config?.settings.persistConversation ?? true;
47016
+ if (!persistConversation || !isStorageAvailable())
47017
+ return;
47018
+ const handleBeforeUnload = () => {
47019
+ const currentState = stateRef.current;
47020
+ if (currentState.messages.length > 0 && currentState.conversationId) {
47021
+ // Force save current state before page closes
47022
+ saveConversation(widgetId, currentState.conversationId, currentState.messages);
47023
+ }
47024
+ };
47025
+ window.addEventListener('beforeunload', handleBeforeUnload);
47026
+ return () => window.removeEventListener('beforeunload', handleBeforeUnload);
47027
+ }, [widgetId, state.config?.settings.persistConversation]);
46595
47028
  const sendMessage = reactExports.useCallback(async (content, files) => {
46596
47029
  const trimmedContent = content.trim();
46597
47030
  const hasFiles = !!files && files.length > 0;
@@ -46675,12 +47108,14 @@
46675
47108
  stateRef.current.conversationId !== streamConversationId ||
46676
47109
  currentRequestIdRef.current !== streamRequestId) {
46677
47110
  console.log('[Widget] Stream aborted, conversation changed, or superseded by new request');
47111
+ cancelBuffer(streamState.buffer);
46678
47112
  break;
46679
47113
  }
46680
47114
  if (event.type === "action_request") {
46681
47115
  if (currentAbortController?.signal.aborted ||
46682
47116
  stateRef.current.conversationId !== streamConversationId ||
46683
47117
  currentRequestIdRef.current !== streamRequestId) {
47118
+ cancelBuffer(streamState.buffer);
46684
47119
  break;
46685
47120
  }
46686
47121
  await handleActionLoop(apiClient.current, event, streamState, (message) => {
@@ -46706,26 +47141,8 @@
46706
47141
  if (lastStreamedMessage) {
46707
47142
  onMessage?.(lastStreamedMessage);
46708
47143
  }
46709
- const enableFollowUps = state.config?.settings.enableFollowUpSuggestions !== false;
46710
- const actionIds = state.config?.actions || [];
46711
- if (enableFollowUps) {
46712
- apiClient.current.generateFollowUps(stateRef.current.messages, actionIds)
46713
- .then(suggestions => {
46714
- if (suggestions.length > 0) {
46715
- setState(prev => {
46716
- const messages = [...prev.messages];
46717
- for (let i = messages.length - 1; i >= 0; i--) {
46718
- if (messages[i].message.role === 'assistant' && !messages[i].isError) {
46719
- messages[i] = { ...messages[i], suggestions };
46720
- break;
46721
- }
46722
- }
46723
- return { ...prev, messages };
46724
- });
46725
- }
46726
- })
46727
- .catch(err => console.warn('[Widget] Follow-up generation failed:', err));
46728
- }
47144
+ // Follow-up suggestions are now generated server-side in parallel and included in the done event
47145
+ // They are automatically attached to the last assistant message by finalizeStreamMessages()
46729
47146
  }
46730
47147
  catch (error) {
46731
47148
  console.error("[Widget] sendMessage error:", error);
@@ -46882,7 +47299,7 @@
46882
47299
  messages: hydratedMessages,
46883
47300
  isLoading: false,
46884
47301
  }));
46885
- setupActionResumeCallbacks(hydratedMessages, apiClient.current, conversation.id, setState, onMessage ?? (() => { }), createStreamState, registerActionResumeCallback);
47302
+ setupActionResumeCallbacks(hydratedMessages, apiClient.current, conversation.id, widgetId, setState, onMessage ?? (() => { }), createStreamState, registerActionResumeCallback);
46886
47303
  if (persistConversation && isStorageAvailable()) {
46887
47304
  saveConversation(widgetId, conversation.id, hydratedMessages);
46888
47305
  }
@@ -46969,6 +47386,16 @@
46969
47386
  return null;
46970
47387
  }
46971
47388
  }, [widgetId, state.config?.settings.persistConversation]);
47389
+ // Call an action endpoint directly (frontend-owned flow)
47390
+ // Auto-injects conversationId and toolCallId for done flag enforcement
47391
+ const callActionEndpoint = reactExports.useCallback(async (actionId, endpoint, input, options) => {
47392
+ const enrichedInput = {
47393
+ ...input,
47394
+ conversationId: state.conversationId,
47395
+ toolCallId: options?.toolCallId,
47396
+ };
47397
+ return apiClient.current.callActionEndpoint(actionId, endpoint, enrichedInput, options?.token);
47398
+ }, [state.conversationId]);
46972
47399
  return {
46973
47400
  messages: state.messages,
46974
47401
  isLoading: state.isLoading,
@@ -46986,6 +47413,7 @@
46986
47413
  startNewConversation,
46987
47414
  deleteConversation: deleteConversation$1,
46988
47415
  createDemoConversation,
47416
+ callActionEndpoint,
46989
47417
  };
46990
47418
  }
46991
47419
 
@@ -47001,17 +47429,19 @@
47001
47429
  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" })] }));
47002
47430
  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" })] }));
47003
47431
  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,
47432
+ const ChatWindow = ({ messages, isLoading, isTyping, config, onSendMessage, onClose: _onClose, onFeedback, onActionClick, onActionDismiss, onCallEndpoint,
47005
47433
  // Chat history props (only active when persistConversation is true)
47006
47434
  conversations = [], onLoadConversations, onSwitchConversation, onStartNewConversation, onDeleteConversation, currentConversationId,
47007
47435
  // Override props for live preview
47008
- headerTitleOverride, welcomeTitleOverride, welcomeMessageOverride, placeholderOverride, suggestedQuestionsOverride, }) => {
47436
+ sizeOverride, headerTitleOverride, welcomeTitleOverride, welcomeMessageOverride, placeholderOverride, suggestedQuestionsOverride,
47437
+ // Demo mode
47438
+ onInputFocus, }) => {
47009
47439
  const appearance = config?.appearance;
47010
47440
  const settings = config?.settings;
47011
47441
  // Check if chat history should be shown (requires both persistConversation AND showChatHistory)
47012
47442
  const canShowHistory = (settings?.persistConversation ?? true) && (settings?.showChatHistory ?? true);
47013
47443
  // Apply overrides for live preview (overrides take priority over saved config)
47014
- const size = appearance?.size || 'medium';
47444
+ const size = sizeOverride ?? appearance?.size ?? 'medium';
47015
47445
  const headerTitle = headerTitleOverride ?? appearance?.headerTitle ?? 'AI Assistant';
47016
47446
  const welcomeTitle = welcomeTitleOverride ?? appearance?.welcomeTitle ?? '';
47017
47447
  const welcomeMessage = welcomeMessageOverride ?? appearance?.welcomeMessage ?? '';
@@ -47088,7 +47518,7 @@
47088
47518
  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) => {
47089
47519
  e.stopPropagation();
47090
47520
  onDeleteConversation(conv.id);
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." })), (() => {
47521
+ }, "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, onInputFocus: onInputFocus })] })) : (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
47522
  console.log('[DEBUG ChatWindow] Rendering MessageList with', messages.length, 'messages');
47093
47523
  messages.forEach((m, i) => {
47094
47524
  console.log(`[DEBUG ChatWindow] msg ${i}:`, { role: m.message.role, hasAction: !!m.action, impl: m.action?.implementation });
@@ -47098,7 +47528,15 @@
47098
47528
  console.log('[DEBUG ChatWindow] Testing renderer for query-contact-directory:', !!getActionRenderer('query-contact-directory'));
47099
47529
  }
47100
47530
  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 })] }))] }));
47531
+ })(), 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, onCallEndpoint: onCallEndpoint }), 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, onInputFocus: onInputFocus })] }))] }));
47532
+ };
47533
+
47534
+ const MessageCircleIcon = () => (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" }) }));
47535
+ const ChevronDownIcon = () => (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" }) }));
47536
+ // Icon components mapping for dynamic lookup
47537
+ const iconComponents = {
47538
+ FiMessageCircle: MessageCircleIcon,
47539
+ FiChevronDown: ChevronDownIcon,
47102
47540
  };
47103
47541
 
47104
47542
  /**
@@ -47396,108 +47834,60 @@
47396
47834
  return styles;
47397
47835
  }
47398
47836
 
47399
- /**
47400
- * Auto Theme Detector
47401
- * Detects whether the widget should use light or dark mode
47402
- * based on the background behind it
47403
- */
47404
- /**
47405
- * Sample the background color behind an element
47406
- * Uses multiple sampling points for accuracy
47407
- */
47408
- function sampleBackgroundColor(element) {
47409
- const rect = element.getBoundingClientRect();
47410
- const centerX = rect.left + rect.width / 2;
47411
- const centerY = rect.top + rect.height / 2;
47412
- // Try to get the element behind our widget
47413
- // Temporarily hide the element to sample what's behind
47414
- const originalVisibility = element.style.visibility;
47415
- element.style.visibility = 'hidden';
47416
- // Sample the center point
47417
- const elementBehind = document.elementFromPoint(centerX, centerY);
47418
- // Restore visibility
47419
- element.style.visibility = originalVisibility;
47420
- if (!elementBehind) {
47421
- return '#ffffff'; // Default to white
47422
- }
47423
- // Get computed background color
47424
- const computedStyle = window.getComputedStyle(elementBehind);
47425
- let bgColor = computedStyle.backgroundColor;
47426
- // If transparent, walk up the DOM tree
47427
- if (bgColor === 'rgba(0, 0, 0, 0)' || bgColor === 'transparent') {
47428
- let parent = elementBehind.parentElement;
47429
- while (parent) {
47430
- const parentStyle = window.getComputedStyle(parent);
47431
- bgColor = parentStyle.backgroundColor;
47432
- if (bgColor !== 'rgba(0, 0, 0, 0)' && bgColor !== 'transparent') {
47433
- break;
47434
- }
47435
- parent = parent.parentElement;
47436
- }
47437
- }
47438
- // If still transparent, check body/html
47439
- if (bgColor === 'rgba(0, 0, 0, 0)' || bgColor === 'transparent') {
47440
- const bodyStyle = window.getComputedStyle(document.body);
47441
- bgColor = bodyStyle.backgroundColor;
47442
- if (bgColor === 'rgba(0, 0, 0, 0)' || bgColor === 'transparent') {
47443
- return '#ffffff'; // Default to white
47837
+ function useWidgetAppearance({ containerRef, config, theme, primaryColor, position, size, headerTitle, welcomeTitle, welcomeMessage, placeholder, welcomeBubbleText, triggerType, triggerText, customStyles, zIndex, previewMode: _previewMode, }) {
47838
+ // Use theme prop directly - no dynamic detection
47839
+ const effectiveTheme = theme ?? "light";
47840
+ // Set data attribute for CSS styling
47841
+ reactExports.useEffect(() => {
47842
+ if (containerRef.current) {
47843
+ containerRef.current.setAttribute('data-theme', effectiveTheme);
47444
47844
  }
47445
- }
47446
- return rgbaToHex(bgColor);
47447
- }
47448
- /**
47449
- * Convert rgba/rgb string to hex
47450
- */
47451
- function rgbaToHex(rgba) {
47452
- // Handle rgb(r, g, b) or rgba(r, g, b, a)
47453
- const match = rgba.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
47454
- if (!match)
47455
- return '#ffffff';
47456
- const r = parseInt(match[1]);
47457
- const g = parseInt(match[2]);
47458
- const b = parseInt(match[3]);
47459
- return '#' + [r, g, b].map(x => {
47460
- const hex = x.toString(16);
47461
- return hex.length === 1 ? '0' + hex : hex;
47462
- }).join('');
47463
- }
47464
- /**
47465
- * Determine if the background is dark
47466
- */
47467
- function isBackgroundDark(backgroundColor) {
47468
- const luminance = getLuminance(backgroundColor);
47469
- return luminance < 0.5;
47470
- }
47471
- /**
47472
- * Auto-detect theme based on background
47473
- */
47474
- function detectTheme(element) {
47475
- const bgColor = sampleBackgroundColor(element);
47476
- return isBackgroundDark(bgColor) ? 'dark' : 'light';
47845
+ }, [effectiveTheme, containerRef]);
47846
+ const appearanceConfig = config?.appearance;
47847
+ const effectivePosition = position || appearanceConfig?.position || "bottom-right";
47848
+ const accentColor = primaryColor !== undefined ? primaryColor : appearanceConfig?.primaryColor ?? "";
47849
+ const effectiveSize = size || appearanceConfig?.size || "small";
47850
+ const effectiveHeaderTitle = headerTitle ?? appearanceConfig?.headerTitle ?? "";
47851
+ const effectiveWelcomeTitle = welcomeTitle ?? appearanceConfig?.welcomeTitle ?? "";
47852
+ const effectiveWelcomeMessage = welcomeMessage ?? appearanceConfig?.welcomeMessage ?? "";
47853
+ const effectivePlaceholder = placeholder ?? appearanceConfig?.placeholder ?? "";
47854
+ const effectiveWelcomeBubbleText = welcomeBubbleText ?? appearanceConfig?.welcomeBubbleText ?? "";
47855
+ const effectiveTriggerType = triggerType ?? appearanceConfig?.triggerType ?? "button";
47856
+ const effectiveTriggerText = triggerText ?? appearanceConfig?.triggerText ?? "Chat";
47857
+ const simpleAppearance = {
47858
+ accentColor};
47859
+ const generatedStyles = generateThemeStyles(simpleAppearance, effectiveTheme);
47860
+ const legacyStyles = appearanceConfig ? applyAppearanceStyles(appearanceConfig) : {};
47861
+ const mergedStyles = {
47862
+ ...legacyStyles,
47863
+ ...generatedStyles,
47864
+ ...customStyles,
47865
+ ...(zIndex !== undefined ? { "--widget-z-index": String(zIndex) } : {}),
47866
+ };
47867
+ // Compute icon contrast color for inline button styling (prevents FOUC)
47868
+ const iconContrastColor = accentColor ? getContrastText(accentColor) : undefined;
47869
+ return {
47870
+ effectiveTheme,
47871
+ effectivePosition,
47872
+ accentColor,
47873
+ iconContrastColor,
47874
+ effectiveSize,
47875
+ effectiveHeaderTitle,
47876
+ effectiveWelcomeTitle,
47877
+ effectiveWelcomeMessage,
47878
+ effectivePlaceholder,
47879
+ effectiveWelcomeBubbleText,
47880
+ effectiveTriggerType,
47881
+ effectiveTriggerText,
47882
+ mergedStyles,
47883
+ };
47477
47884
  }
47478
- /**
47479
- * Create a MutationObserver to watch for theme changes
47480
- */
47481
- function createThemeObserver(element, callback) {
47482
- let lastTheme = detectTheme(element);
47483
- const observer = new MutationObserver(() => {
47484
- const theme = detectTheme(element);
47485
- if (theme !== lastTheme) {
47486
- lastTheme = theme;
47487
- callback(theme);
47488
- }
47489
- });
47490
- // Observe body for class/style changes (common for theme switching)
47491
- observer.observe(document.body, {
47492
- attributes: true,
47493
- attributeFilter: ['class', 'style', 'data-theme', 'data-bs-theme'],
47494
- });
47495
- // Also observe html element
47496
- observer.observe(document.documentElement, {
47497
- attributes: true,
47498
- attributeFilter: ['class', 'style', 'data-theme', 'data-bs-theme'],
47499
- });
47500
- return observer;
47885
+
47886
+ function WidgetTriggers({ triggerType, isOpen, onToggle, triggerText, placeholder, IconComponent, showWelcomeBubble, welcomeBubbleText, previewMode, onDismissBubble, isInputBarCollapsed, setIsInputBarCollapsed, inputBarValue, setInputBarValue, onSubmitInputBar, accentColor, iconColor, }) {
47887
+ // Inline button styles to prevent flash of unstyled content (FOUC)
47888
+ // Applied directly to button elements, bypassing CSS variable cascade timing
47889
+ const buttonStyle = accentColor ? { background: accentColor, color: iconColor } : undefined;
47890
+ return (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [triggerType === "button" && !isOpen && welcomeBubbleText && (previewMode || showWelcomeBubble) && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-welcome-bubble", onClick: onToggle, children: [jsxRuntimeExports.jsx("span", { children: welcomeBubbleText }), jsxRuntimeExports.jsx("button", { className: "ai-chat-welcome-bubble-close", onClick: onDismissBubble, "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" })] })), triggerType === "button" && (jsxRuntimeExports.jsx("button", { className: `ai-chat-button ${isOpen ? "is-open" : ""}`, onClick: onToggle, "aria-label": isOpen ? "Minimize chat" : "Open chat", style: buttonStyle, children: jsxRuntimeExports.jsx("div", { className: "ai-chat-button-svg", children: jsxRuntimeExports.jsx(IconComponent, {}) }) })), triggerType === "pill-text" && (jsxRuntimeExports.jsxs("button", { className: `ai-chat-trigger-pill ${isOpen ? "is-open" : ""}`, onClick: onToggle, "aria-label": isOpen ? "Close chat" : "Open chat", style: isOpen ? buttonStyle : undefined, children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-trigger-pill-icon", children: jsxRuntimeExports.jsx(IconComponent, {}) }), !isOpen && jsxRuntimeExports.jsx("span", { children: triggerText })] })), triggerType === "input-bar" && !isOpen && (jsxRuntimeExports.jsx("div", { className: "ai-chat-trigger-input-container", children: isInputBarCollapsed ? (jsxRuntimeExports.jsxs("div", { className: "ai-chat-trigger-input-row", children: [jsxRuntimeExports.jsx("button", { type: "button", className: "ai-chat-trigger-collapse-toggle", onClick: () => setIsInputBarCollapsed(false), "aria-label": "Expand input bar", children: jsxRuntimeExports.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("polyline", { points: "15 18 9 12 15 6" }) }) }), jsxRuntimeExports.jsx("button", { type: "button", className: "ai-chat-button", onClick: onToggle, "aria-label": "Open chat", style: buttonStyle, children: jsxRuntimeExports.jsx("div", { className: "ai-chat-button-svg", children: jsxRuntimeExports.jsx(IconComponent, {}) }) })] })) : (jsxRuntimeExports.jsxs("div", { className: "ai-chat-trigger-input-row", children: [jsxRuntimeExports.jsx("button", { type: "button", className: "ai-chat-trigger-collapse-toggle", onClick: () => setIsInputBarCollapsed(true), "aria-label": "Collapse input bar", children: jsxRuntimeExports.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("polyline", { points: "9 18 15 12 9 6" }) }) }), jsxRuntimeExports.jsxs("form", { className: "ai-chat-trigger-input-wrapper", onSubmit: onSubmitInputBar, children: [jsxRuntimeExports.jsx("input", { type: "text", className: "ai-chat-trigger-input", placeholder: placeholder || "Ask me anything...", value: inputBarValue, onChange: (event) => setInputBarValue(event.target.value), "aria-label": "Chat input" }), jsxRuntimeExports.jsx("button", { type: "submit", className: "ai-chat-trigger-input-btn", disabled: !inputBarValue.trim(), "aria-label": "Send message", style: buttonStyle, children: jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("line", { x1: "12", y1: "19", x2: "12", y2: "5" }), jsxRuntimeExports.jsx("polyline", { points: "5 12 12 5 19 12" })] }) })] }), jsxRuntimeExports.jsx("button", { type: "button", className: "ai-chat-trigger-input-expand", onClick: onToggle, "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" }) }) })] })) }))] }));
47501
47891
  }
47502
47892
 
47503
47893
  function styleInject(css, ref) {
@@ -47527,34 +47917,19 @@
47527
47917
  }
47528
47918
  }
47529
47919
 
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)}}";
47920
+ 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)}@keyframes ai-chat-message-appear{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(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-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;--breakpoint-mobile:480px;--breakpoint-tablet:768px;--breakpoint-desktop:769px;--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)!important}.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{height:100%;inset:0;pointer-events:none;position:absolute;width:100%}.ai-chat-widget-container.container-mode .ai-chat-button,.ai-chat-widget-container.container-mode .ai-chat-trigger-button,.ai-chat-widget-container.container-mode .ai-chat-trigger-input-container,.ai-chat-widget-container.container-mode .ai-chat-window{pointer-events:auto}.ai-chat-widget-container.container-mode:not(.trigger-input-bar) .ai-chat-button{position:absolute}.ai-chat-widget-container.container-mode:not(.trigger-input-bar).bottom-right .ai-chat-button{bottom:20px;left:auto;right:20px;top:auto}.ai-chat-widget-container.container-mode:not(.trigger-input-bar).bottom-left .ai-chat-button{bottom:20px;left:20px;right:auto;top:auto}.ai-chat-widget-container.container-mode:not(.trigger-input-bar).top-right .ai-chat-button{bottom:auto;left:auto;right:20px;top:20px}.ai-chat-widget-container.container-mode:not(.trigger-input-bar).top-left .ai-chat-button{bottom:auto;left:20px;right:auto;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-user-message-sent{0%{opacity:0;transform:translateX(20px) scale(.95)}60%{opacity:1;transform:translateX(-4px) scale(1.02)}to{opacity:1;transform:translateX(0) scale(1)}}@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{-webkit-font-smoothing:subpixel-antialiased;-moz-osx-font-smoothing:auto;animation:ai-chat-window-open var(--duration-slow,.35s) var(--spring-bounce);-webkit-backface-visibility:hidden;backface-visibility:hidden;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;-webkit-transform:translateZ(0);transform:translateZ(0);transform-origin:bottom right;will-change:transform,opacity;z-index:2147483647!important}.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;max-height:calc(100vh - 100px);max-width:calc(100vw - 40px);min-width:320px;width:380px}.ai-chat-window.size-medium{height:calc(100vh - 140px);max-height:680px;max-width:calc(100vw - 40px);min-width:380px;width:440px}.ai-chat-window.size-large{height:calc(100vh - 48px);max-height:calc(100vh - 48px);max-width:560px;min-width:440px;width:33vw}.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-widget-container.trigger-button.size-large.bottom-left .ai-chat-window,.ai-chat-widget-container.trigger-button.size-large.bottom-right .ai-chat-window{bottom:0}.ai-chat-widget-container.trigger-button.size-large.top-left .ai-chat-window,.ai-chat-widget-container.trigger-button.size-large.top-right .ai-chat-window{top:0}.ai-chat-widget-container.trigger-pill-text.size-large.bottom-left .ai-chat-window,.ai-chat-widget-container.trigger-pill-text.size-large.bottom-right .ai-chat-window{bottom:72px;height:calc(100vh - 120px);max-height:calc(100vh - 120px)}.ai-chat-widget-container.trigger-pill-text.size-large.top-left .ai-chat-window,.ai-chat-widget-container.trigger-pill-text.size-large.top-right .ai-chat-window{height:calc(100vh - 120px);max-height:calc(100vh - 120px);top:72px}.ai-chat-widget-container.trigger-input-bar.size-large.bottom-left .ai-chat-window,.ai-chat-widget-container.trigger-input-bar.size-large.bottom-right .ai-chat-window{bottom:72px;height:calc(100vh - 120px);max-height:calc(100vh - 120px)}.ai-chat-widget-container.trigger-input-bar.size-large.top-left .ai-chat-window,.ai-chat-widget-container.trigger-input-bar.size-large.top-right .ai-chat-window{height:calc(100vh - 120px);max-height:calc(100vh - 120px);top:72px}.ai-chat-widget-container.container-mode.bottom-right .ai-chat-window{bottom:20px;left:auto;right:20px;top:auto}.ai-chat-widget-container.container-mode.bottom-left .ai-chat-window{bottom:20px;left:20px;right:auto;top:auto}.ai-chat-widget-container.container-mode.top-right .ai-chat-window{bottom:auto;left:auto;right:20px;top:20px}.ai-chat-widget-container.container-mode.top-left .ai-chat-window{bottom:auto;left:20px;right:auto;top:20px}.ai-chat-widget-container.container-mode.size-small .ai-chat-window{height:min(500px,50%);max-height:calc(100% - 100px);max-width:calc(100% - 40px);min-height:300px;min-width:280px;width:min(380px,calc(100% - 40px))}.ai-chat-widget-container.container-mode.size-medium .ai-chat-window{height:min(680px,70%);max-height:calc(100% - 80px);max-width:calc(100% - 40px);min-height:400px;min-width:320px;width:min(440px,calc(100% - 40px))}.ai-chat-widget-container.container-mode.size-large .ai-chat-window{height:90%;max-height:calc(100% - 60px);max-width:calc(100% - 40px);min-height:500px;min-width:380px;width:min(560px,calc(100% - 40px))}.ai-chat-widget-container.trigger-button.container-mode.bottom-left .ai-chat-window,.ai-chat-widget-container.trigger-button.container-mode.bottom-right .ai-chat-window{bottom:88px}.ai-chat-widget-container.trigger-pill-text.container-mode.bottom-left .ai-chat-window,.ai-chat-widget-container.trigger-pill-text.container-mode.bottom-right .ai-chat-window{bottom:80px}.ai-chat-widget-container.trigger-button.container-mode.size-medium .ai-chat-window,.ai-chat-widget-container.trigger-button.container-mode.size-small .ai-chat-window,.ai-chat-widget-container.trigger-pill-text.container-mode.size-medium .ai-chat-window,.ai-chat-widget-container.trigger-pill-text.container-mode.size-small .ai-chat-window{max-height:calc(100% - 108px)}.ai-chat-widget-container.trigger-button.container-mode.size-large .ai-chat-window,.ai-chat-widget-container.trigger-pill-text.container-mode.size-large .ai-chat-window{height:calc(100% - 108px);max-height:calc(100% - 108px)}.ai-chat-widget-container.trigger-button.container-mode.top-left .ai-chat-window,.ai-chat-widget-container.trigger-button.container-mode.top-right .ai-chat-window{bottom:auto;top:88px}.ai-chat-widget-container.trigger-pill-text.container-mode.top-left .ai-chat-window,.ai-chat-widget-container.trigger-pill-text.container-mode.top-right .ai-chat-window{bottom:auto;top:80px}.ai-chat-widget-container.container-mode.mobile-mode.is-open{margin:0!important;padding:0!important}.ai-chat-widget-container.container-mode.mobile-mode.is-open,.ai-chat-widget-container.container-mode.mobile-mode.is-open .ai-chat-window{bottom:0!important;height:100%!important;left:0!important;position:absolute!important;right:0!important;top:0!important;width:100%!important}.ai-chat-widget-container.container-mode.mobile-mode.is-open .ai-chat-window{animation:none!important;border:none!important;border-radius:0!important;box-shadow:none!important;max-height:100%!important;max-width:100%!important;min-height:100%!important;min-width:100%!important}.ai-chat-widget-container.container-mode.mobile-mode.is-open .ai-chat-button,.ai-chat-widget-container.container-mode.mobile-mode.is-open .ai-chat-trigger-input-container,.ai-chat-widget-container.container-mode.mobile-mode.is-open .ai-chat-trigger-pill{display:none!important}.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{-webkit-font-smoothing:subpixel-antialiased;-moz-osx-font-smoothing:auto;align-items:center;-webkit-backface-visibility:hidden;backface-visibility:hidden;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;-webkit-transform:translateZ(0);transform:translateZ(0);transition:transform var(--duration-fast) ease;width:var(--button-size,56px);will-change:transform;z-index:2147483647!important}.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:2147483647!important}.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{-webkit-font-smoothing:subpixel-antialiased;-moz-osx-font-smoothing:auto;align-items:center;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);-webkit-backface-visibility:hidden;backface-visibility:hidden;background:var(--trigger-bg,rgba(0,0,0,.04));border:1px solid var(--trigger-border,rgba(0,0,0,.12));border-radius:9999px;box-shadow:0 4px 16px rgba(0,0,0,.12);color:var(--trigger-text,#1a1a1a);cursor:pointer;display:flex;font-size:14px;font-weight:500;gap:10px;height:48px;justify-content:center;padding:0 24px;position:relative;-webkit-transform:translateZ(0);transform:translateZ(0);transition:all .3s ease,color .4s ease,background .4s ease,border-color .4s ease;white-space:nowrap;will-change:transform;z-index:2147483647!important}.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));color:var(--button-icon-color,var(--btn-primary-text));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:var(--trigger-bg-hover,rgba(0,0,0,.08));border-color:var(--trigger-border-hover,rgba(0,0,0,.2))}.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:20px;transition:all .3s ease;width:20px}.ai-chat-widget-container.trigger-pill-text.container-mode .ai-chat-trigger-pill{position:absolute}.ai-chat-widget-container.trigger-pill-text.container-mode.bottom-right .ai-chat-trigger-pill{bottom:20px;left:auto;right:20px;top:auto}.ai-chat-widget-container.trigger-pill-text.container-mode.bottom-left .ai-chat-trigger-pill{bottom:20px;left:20px;right:auto;top:auto}.ai-chat-widget-container.trigger-pill-text.container-mode.top-right .ai-chat-trigger-pill{bottom:auto;left:auto;right:20px;top:20px}.ai-chat-widget-container.trigger-pill-text.container-mode.top-left .ai-chat-trigger-pill{bottom:auto;left:20px;right:auto;top:20px}.ai-chat-widget-container.trigger-pill-text.container-mode .ai-chat-trigger-pill{pointer-events:auto}.ai-chat-trigger-input-container{align-items:flex-end;display:flex;flex-direction:column;gap:8px;z-index:2147483647!important}.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-row{align-items:center;display:flex;gap:8px;transition:gap .4s cubic-bezier(.4,0,.2,1),width .4s cubic-bezier(.4,0,.2,1)}.ai-chat-widget-container.trigger-input-bar.is-collapsed .ai-chat-trigger-input-row{gap:4px}.ai-chat-trigger-input-expand{-webkit-font-smoothing:subpixel-antialiased;-moz-osx-font-smoothing:auto;align-items:center;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);-webkit-backface-visibility:hidden;backface-visibility:hidden;background:var(--trigger-bg,rgba(0,0,0,.04));border:1px solid var(--trigger-border,rgba(0,0,0,.12));border-radius:50%;box-shadow:0 2px 12px rgba(0,0,0,.12);color:var(--trigger-text-muted,rgba(0,0,0,.5));cursor:pointer;display:flex;flex-shrink:0;height:48px;justify-content:center;padding:0;-webkit-transform:translateZ(0);transform:translateZ(0);transition:all .2s ease,color .4s ease,background .4s ease,border-color .4s ease;width:48px;will-change:transform}.ai-chat-trigger-input-expand:hover{background:var(--trigger-bg-hover,rgba(0,0,0,.08));color:var(--trigger-text,#1a1a1a);transform:translateY(-2px)}.ai-chat-trigger-input-expand:active{transform:translateY(0)}.ai-chat-trigger-input-expand svg{stroke-width:2.5;height:20px;width:20px}.ai-chat-trigger-input-wrapper{flex:1;min-width:120px;position:relative;transform-origin:right center;transition:flex .4s cubic-bezier(.4,0,.2,1),width .4s cubic-bezier(.4,0,.2,1),opacity .3s cubic-bezier(.4,0,.2,1),transform .4s cubic-bezier(.4,0,.2,1);z-index:1}.ai-chat-widget-container.bottom-left .ai-chat-trigger-input-wrapper,.ai-chat-widget-container.top-left .ai-chat-trigger-input-wrapper{transform-origin:left center}.ai-chat-trigger-input{-webkit-font-smoothing:subpixel-antialiased;-moz-osx-font-smoothing:auto;backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);-webkit-backface-visibility:hidden;backface-visibility:hidden;background:var(--trigger-bg,rgba(0,0,0,.04));border:1px solid var(--trigger-border,rgba(0,0,0,.12));border-radius:var(--radius-input,62px);box-shadow:0 4px 24px rgba(0,0,0,.15);box-sizing:border-box;color:var(--trigger-text,#1a1a1a);font-size:var(--text-md,15px);height:48px;outline:none;padding:6px 52px 6px 16px;-webkit-transform:translateZ(0);transform:translateZ(0);transition:all .2s ease,color .4s ease,background .4s ease,border-color .4s ease;width:100%}.ai-chat-trigger-input::placeholder{color:var(--trigger-text-muted,rgba(0,0,0,.5))}.ai-chat-trigger-input:focus{background:var(--trigger-bg-hover,rgba(0,0,0,.08));border-color:var(--trigger-border-hover,rgba(0,0,0,.2))}.ai-chat-trigger-input-btn{-webkit-font-smoothing:subpixel-antialiased;-moz-osx-font-smoothing:auto;align-items:center;-webkit-backface-visibility:hidden;backface-visibility:hidden;background:var(--primary-color,var(--button-color,#07f));border:none;border-radius:50%;box-shadow:0 2px 8px rgba(0,119,255,.3);color:var(--send-button-icon-color,var(--button-icon-color,#fff));cursor:pointer;display:flex;height:38px;justify-content:center;position:absolute;right:4px;top:50%;transform:translateY(-50%);transition:all .2s ease;width:38px;will-change:transform}.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-container.trigger-input-bar .ai-chat-trigger-input-row{width:min(380px,calc(100vw - 40px))}.ai-chat-widget-container.trigger-input-bar.size-medium .ai-chat-trigger-input-row{width:min(440px,calc(100vw - 40px))}.ai-chat-widget-container.trigger-input-bar.size-large .ai-chat-trigger-input-row{width:min(560px,calc(100vw - 40px))}.ai-chat-widget-container.trigger-input-bar .ai-chat-trigger-input-wrapper{flex:1;min-width:160px}.ai-chat-widget-container.trigger-input-bar.container-mode .ai-chat-trigger-input-container{position:absolute;width:min(380px,calc(100% - 40px))}.ai-chat-widget-container.trigger-input-bar.container-mode.size-small .ai-chat-trigger-input-container{width:min(380px,calc(100% - 40px))}.ai-chat-widget-container.trigger-input-bar.container-mode.size-medium .ai-chat-trigger-input-container{width:min(440px,calc(100% - 40px))}.ai-chat-widget-container.trigger-input-bar.container-mode.size-large .ai-chat-trigger-input-container{width:min(560px,calc(100% - 40px))}.ai-chat-widget-container.trigger-input-bar.container-mode.bottom-right .ai-chat-trigger-input-container{bottom:20px;left:auto;right:20px;top:auto}.ai-chat-widget-container.trigger-input-bar.container-mode.bottom-left .ai-chat-trigger-input-container{bottom:20px;left:20px;right:auto;top:auto}.ai-chat-widget-container.trigger-input-bar.container-mode.top-right .ai-chat-trigger-input-container{bottom:auto;left:auto;right:20px;top:20px}.ai-chat-widget-container.trigger-input-bar.container-mode.top-left .ai-chat-trigger-input-container{bottom:auto;left:20px;right:auto;top:20px}.ai-chat-widget-container.trigger-input-bar.container-mode .ai-chat-trigger-input-row{width:100%}.ai-chat-widget-container.trigger-input-bar.container-mode .ai-chat-trigger-input-wrapper{flex:1;min-width:120px}.ai-chat-widget-container.trigger-input-bar.is-collapsed .ai-chat-trigger-input-wrapper{opacity:0;overflow:hidden;pointer-events:none;transform:scaleX(0);width:0}.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}.ai-chat-widget-container.trigger-input-bar .ai-chat-window.size-small{max-width:calc(100vw - 40px);min-width:320px;width:380px}.ai-chat-widget-container.trigger-input-bar .ai-chat-window.size-medium{max-width:calc(100vw - 40px);min-width:380px;width:440px}.ai-chat-widget-container.trigger-input-bar .ai-chat-window.size-large{max-width:calc(100vw - 40px);min-width:440px;width:560px}.ai-chat-widget-container.trigger-input-bar.container-mode .ai-chat-window{max-width:calc(100% - 40px);position:absolute}.ai-chat-widget-container.trigger-input-bar.container-mode.bottom-right .ai-chat-window{bottom:20px;left:auto;right:20px;top:auto}.ai-chat-widget-container.trigger-input-bar.container-mode.bottom-left .ai-chat-window{bottom:20px;left:20px;right:auto;top:auto}.ai-chat-widget-container.trigger-input-bar.container-mode.top-right .ai-chat-window{bottom:auto;left:auto;right:20px;top:20px}.ai-chat-widget-container.trigger-input-bar.container-mode.top-left .ai-chat-window{bottom:auto;left:20px;right:auto;top:20px}.ai-chat-widget-container.trigger-input-bar.container-mode.size-small .ai-chat-window{max-width:calc(100% - 40px);width:380px}.ai-chat-widget-container.trigger-input-bar.container-mode.size-medium .ai-chat-window{max-width:calc(100% - 40px);width:440px}.ai-chat-widget-container.trigger-input-bar.container-mode.size-large .ai-chat-window{max-width:calc(100% - 40px);width:560px}.ai-chat-widget-container.trigger-input-bar.mobile-mode .ai-chat-trigger-input-container{width:calc(100% - 40px)}.ai-chat-widget-container.trigger-input-bar.mobile-mode .ai-chat-trigger-input-row{width:100%}.ai-chat-widget-container.trigger-input-bar.mobile-mode .ai-chat-trigger-input-wrapper{flex:1;min-width:120px}.ai-chat-widget-container.trigger-input-bar.mobile-mode.is-collapsed .ai-chat-trigger-input-container{width:auto}.ai-chat-widget-container.trigger-input-bar.mobile-mode.is-collapsed .ai-chat-trigger-input-row{gap:8px;justify-content:flex-end}.ai-chat-trigger-collapse-toggle{align-items:center;background:transparent;border:none;border-radius:50%;color:var(--trigger-text-muted,rgba(0,0,0,.5));cursor:pointer;display:flex;flex-shrink:0;height:24px;justify-content:center;margin-right:-4px;order:-1;padding:0;transition:all .2s ease;width:24px}.ai-chat-trigger-collapse-toggle:hover{color:var(--trigger-text,#1a1a1a)}.ai-chat-trigger-collapse-toggle svg{stroke-width:2.5;height:20px;transition:transform .4s cubic-bezier(.4,0,.2,1);width:20px}.ai-chat-widget-container.trigger-input-bar.bottom-left .ai-chat-trigger-collapse-toggle svg,.ai-chat-widget-container.trigger-input-bar.top-left .ai-chat-trigger-collapse-toggle svg{transform:rotate(180deg)}.ai-chat-trigger-input-expand{margin-left:-4px;order:1;transition:transform .2s ease,opacity .3s ease}.ai-chat-widget-container.container-mode .ai-chat-trigger-input-expand{margin-left:0}.ai-chat-trigger-input-expand svg{transition:transform .4s cubic-bezier(.4,0,.2,1)}.ai-chat-widget-container.trigger-input-bar .ai-chat-trigger-input-expand svg{transform:rotate(0deg)}.ai-chat-widget-container.bottom-left .ai-chat-trigger-collapse-toggle,.ai-chat-widget-container.top-left .ai-chat-trigger-collapse-toggle{margin-left:-4px;margin-right:0;order:1}.ai-chat-widget-container.bottom-left .ai-chat-trigger-input-expand,.ai-chat-widget-container.top-left .ai-chat-trigger-input-expand{margin-left:0;margin-right:-4px;order:-1}.ai-chat-widget-container.trigger-input-bar .ai-chat-trigger-input-row .ai-chat-button{order:1}.ai-chat-widget-container.trigger-input-bar.bottom-left .ai-chat-trigger-input-row .ai-chat-button,.ai-chat-widget-container.trigger-input-bar.top-left .ai-chat-trigger-input-row .ai-chat-button{order:-1}.ai-chat-widget-container.trigger-input-bar.is-collapsed.bottom-right .ai-chat-button,.ai-chat-widget-container.trigger-input-bar.is-collapsed.top-right .ai-chat-button{margin-right:16px}.ai-chat-widget-container.trigger-input-bar.is-collapsed.bottom-left .ai-chat-button,.ai-chat-widget-container.trigger-input-bar.is-collapsed.top-left .ai-chat-button{margin-left:16px}.ai-chat-widget-container.trigger-input-bar.is-collapsed .ai-chat-trigger-input-row{flex-direction:row;justify-content:flex-end}.ai-chat-widget-container.trigger-input-bar.is-collapsed.bottom-left .ai-chat-trigger-input-row,.ai-chat-widget-container.trigger-input-bar.is-collapsed.top-left .ai-chat-trigger-input-row{justify-content:flex-start}.ai-chat-widget-container.trigger-input-bar .ai-chat-button{display:flex;opacity:1;transform:scale(1);transition:transform .4s cubic-bezier(.4,0,.2,1),opacity .3s cubic-bezier(.4,0,.2,1),width .4s cubic-bezier(.4,0,.2,1),height .4s cubic-bezier(.4,0,.2,1)}.ai-chat-widget-container.trigger-input-bar:not(.is-collapsed) .ai-chat-button{border:none;height:0;margin:0;min-width:0;opacity:0;overflow:hidden;padding:0;pointer-events:none;transform:scale(0);width:0}.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-widget.light .ai-chat-trigger-pill:not(.is-open){backdrop-filter:none;-webkit-backdrop-filter:none;background:#fff;border:1px solid rgba(0,0,0,.15);box-shadow:0 2px 8px rgba(0,0,0,.08);color:#18181b}.ai-chat-widget.light .ai-chat-trigger-pill:not(.is-open):hover{background:#fafafa;border-color:rgba(0,0,0,.2)}.ai-chat-widget.light .ai-chat-trigger-input-expand{backdrop-filter:none;-webkit-backdrop-filter:none;background:#fff;border:1px solid rgba(0,0,0,.15);box-shadow:0 2px 8px rgba(0,0,0,.08);color:#52525b}.ai-chat-widget.light .ai-chat-trigger-input-expand:hover{background:#fafafa;color:#18181b}.ai-chat-widget.light .ai-chat-trigger-input{backdrop-filter:none;-webkit-backdrop-filter:none;background:#fff;border:1px solid rgba(0,0,0,.15);box-shadow:0 2px 8px rgba(0,0,0,.08);color:#18181b}.ai-chat-widget.light .ai-chat-trigger-input::placeholder{color:#71717a}.ai-chat-widget.light .ai-chat-trigger-input:focus{background:#fff;border-color:rgba(0,0,0,.25)}.ai-chat-widget.light .ai-chat-trigger-collapse-toggle{color:#71717a}.ai-chat-widget.light .ai-chat-trigger-collapse-toggle:hover{color:#18181b}.ai-chat-widget.dark .ai-chat-trigger-pill:not(.is-open){backdrop-filter:none;-webkit-backdrop-filter:none;background:#27272a;border:1px solid hsla(0,0%,100%,.15);box-shadow:0 2px 8px rgba(0,0,0,.3);color:#fafafa}.ai-chat-widget.dark .ai-chat-trigger-pill:not(.is-open):hover{background:#3f3f46;border-color:hsla(0,0%,100%,.25)}.ai-chat-widget.dark .ai-chat-trigger-input-expand{backdrop-filter:none;-webkit-backdrop-filter:none;background:#27272a;border:1px solid hsla(0,0%,100%,.15);box-shadow:0 2px 8px rgba(0,0,0,.3);color:#a1a1aa}.ai-chat-widget.dark .ai-chat-trigger-input-expand:hover{background:#3f3f46;color:#fafafa}.ai-chat-widget.dark .ai-chat-trigger-input{backdrop-filter:none;-webkit-backdrop-filter:none;background:#27272a;border:1px solid hsla(0,0%,100%,.15);box-shadow:0 2px 8px rgba(0,0,0,.3);color:#fafafa}.ai-chat-widget.dark .ai-chat-trigger-input::placeholder{color:#71717a}.ai-chat-widget.dark .ai-chat-trigger-input:focus{background:#27272a;border-color:hsla(0,0%,100%,.25)}.ai-chat-widget.dark .ai-chat-trigger-collapse-toggle{color:#71717a}.ai-chat-widget.dark .ai-chat-trigger-collapse-toggle:hover{color:#fafafa}.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{-webkit-font-smoothing:subpixel-antialiased;-moz-osx-font-smoothing:auto;align-items:flex-end;-webkit-backface-visibility:hidden;backface-visibility:hidden;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;-webkit-transform:translateZ(0);transform:translateZ(0);transition:all var(--duration-fast,.15s) ease;will-change:transform;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:16px!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{-webkit-font-smoothing:subpixel-antialiased;-moz-osx-font-smoothing:auto;align-items:center;align-self:center;-webkit-backface-visibility:hidden;backface-visibility:hidden;background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#151515))));border:none;border-radius:50%;color:var(--send-button-icon-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;-webkit-transform:translateZ(0);transform:translateZ(0);transition:all var(--duration-fast,.15s) ease;width:40px;will-change:transform,opacity}.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(--send-button-icon-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(--send-button-icon-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(--send-button-icon-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;min-height:0;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;animation:ai-chat-user-message-sent .35s var(--spring-bounce)}.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);max-width:100%;overflow-wrap:break-word;padding:8px 14px;word-break:break-word}.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-meta{align-items:center;display:flex;gap:var(--space-sm,8px);margin-top:var(--space-xs,4px);padding:0 var(--space-xs,4px)}.ai-chat-message.user .ai-chat-message-meta{justify-content:flex-end}.ai-chat-message.assistant .ai-chat-message-meta{justify-content:flex-start}.ai-chat-message-timestamp{color:var(--text-muted,#71717a);font-size:var(--text-xs,12px)}.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-message.assistant.streaming .ai-chat-message-content>ol:last-child>li:last-child,.ai-chat-message.assistant.streaming .ai-chat-message-content>p:last-child,.ai-chat-message.assistant.streaming .ai-chat-message-content>ul:last-child>li:last-child{animation:ai-chat-text-fade-in .3s ease-out}@keyframes ai-chat-text-fade-in{0%{opacity:0}to{opacity:1}}.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-widget-container.container-mode.trigger-input-bar .ai-chat-suggested-questions{box-sizing:border-box;margin:0;padding:16px 0 0;width:100%}.ai-chat-widget-container.container-mode.trigger-input-bar .ai-chat-suggested-questions-list{box-sizing:border-box;display:flex;flex-wrap:wrap;gap:6px}.ai-chat-widget-container.container-mode.trigger-input-bar.bottom-right .ai-chat-suggested-questions-list,.ai-chat-widget-container.container-mode.trigger-input-bar.top-right .ai-chat-suggested-questions-list{justify-content:flex-end;margin-left:auto;margin-right:0;padding-right:0}.ai-chat-widget-container.container-mode.trigger-input-bar.bottom-left .ai-chat-suggested-questions-list,.ai-chat-widget-container.container-mode.trigger-input-bar.top-left .ai-chat-suggested-questions-list{justify-content:flex-start;margin-left:0;margin-right:auto;padding-left:0}.ai-chat-widget-container.container-mode.trigger-input-bar.size-small .ai-chat-suggested-questions-list{max-width:calc(100% - 132px);width:348px}.ai-chat-widget-container.container-mode.trigger-input-bar.size-medium .ai-chat-suggested-questions-list{max-width:calc(100% - 132px);width:408px}.ai-chat-widget-container.container-mode.trigger-input-bar.size-large .ai-chat-suggested-questions-list{max-width:calc(100% - 132px);width:528px}.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;animation:followUpFadeIn .25s ease-out forwards;background:var(--primary-color,var(--button-color,#07f));border:none;border-radius:var(--radius-preset-badge,18px);color:var(--button-icon-color,#fff);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;white-space:nowrap}@keyframes followUpFadeIn{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.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}@media (max-width:480px){.ai-chat-action-card{padding:12px}.ai-chat-action-header{font-size:var(--text-sm,14px);margin-bottom:var(--space-sm,12px)}.ai-chat-action-button{font-size:13px;padding:10px 14px}.ai-chat-action-link-button{font-size:13px;padding:10px}}.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-link-preview-grid{display:grid;gap:12px}.ai-chat-link-preview-grid--single{grid-template-columns:1fr}.ai-chat-link-preview-grid--double{grid-template-columns:repeat(2,1fr)}.ai-chat-link-preview-grid--triple{grid-template-columns:repeat(3,1fr)}@media (max-width:768px){.ai-chat-link-preview-grid--triple{grid-template-columns:repeat(2,1fr)}}@media (max-width:480px){.ai-chat-link-preview-grid--double,.ai-chat-link-preview-grid--triple{grid-template-columns:1fr}}.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}@media (max-width:480px){.ai-chat-video-player__play-btn{height:56px;width:56px}.ai-chat-video-player__provider-badge{font-size:10px;padding:3px 6px}}.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;flex-wrap:wrap;gap:8px;justify-content:flex-start;width:100%}@media (max-width:380px){.ai-chat-location-card__actions{flex-direction:column}.ai-chat-location-card__button,.ai-chat-location-card__link{flex:none;justify-content:center;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}@media (max-width:480px){.ai-chat-location-card__content{padding:10px}.ai-chat-location-card__name{font-size:14px}.ai-chat-location-card__address,.ai-chat-location-card__description,.ai-chat-location-card__hours{font-size:12px}.ai-chat-location-card__button,.ai-chat-location-card__link{font-size:12px;padding:8px 12px}.ai-chat-location-card-list__carousel>.ai-chat-location-card{flex:0 0 240px}}.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;flex-wrap:wrap;gap:8px;padding:0 12px 12px}@media (max-width:380px){.ai-chat-contact-card__actions{flex-direction:column}.ai-chat-contact-card__button{flex:none;width:100%}}.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}@media (max-width:480px){.ai-chat-contact-card__name{font-size:16px}.ai-chat-contact-card__detail,.ai-chat-contact-card__role{font-size:13px}.ai-chat-contact-card__button{font-size:13px;padding:10px 16px}.ai-chat-contact-card--horizontal .ai-chat-contact-card__info,.ai-chat-contact-card--vertical .ai-chat-contact-card__info{padding:12px}}.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--completed,.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--completed .ai-chat-form-card__header{margin-bottom:0}.ai-chat-form-card--completed .ai-chat-form-card__icon svg{color:#10b981}.ai-chat-form-card__header{align-items:center;display:flex;gap:8px;margin-bottom:12px}.ai-chat-form-card__icon{align-items:center;display:inline-flex;justify-content:center}.ai-chat-form-card__icon svg{color:var(--text-primary,#3e3e3e);height:18px;width:18px}.ai-chat-widget.dark .ai-chat-form-card__icon svg,.chakra-ui-dark .ai-chat-form-card__icon svg,.dark .ai-chat-form-card__icon svg,[data-theme=dark] .ai-chat-form-card__icon svg{color:#fff}.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 .ai-chat-form-card__icon svg{color:#dc2626}.ai-chat-form-card--submitted .ai-chat-form-card__icon svg{color:#16a34a}.ai-chat-widget.dark .ai-chat-form-card--error .ai-chat-form-card__icon svg,.chakra-ui-dark .ai-chat-form-card--error .ai-chat-form-card__icon svg,.dark .ai-chat-form-card--error .ai-chat-form-card__icon svg,[data-theme=dark] .ai-chat-form-card--error .ai-chat-form-card__icon svg{color:#fca5a5}.ai-chat-widget.dark .ai-chat-form-card--submitted .ai-chat-form-card__icon svg,.chakra-ui-dark .ai-chat-form-card--submitted .ai-chat-form-card__icon svg,.dark .ai-chat-form-card--submitted .ai-chat-form-card__icon svg,[data-theme=dark] .ai-chat-form-card--submitted .ai-chat-form-card__icon svg{color:#4ade80}.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;justify-content:flex-start}@media (max-width:380px){.ai-chat-form-card__rating{gap:6px}.ai-chat-form-card__rating-btn{font-size:13px;height:36px;width:36px}}.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;flex-wrap:wrap;gap:8px;margin-top:16px;padding-top:16px}@media (max-width:380px){.ai-chat-form-card__actions{align-items:stretch;flex-direction:column}.ai-chat-form-card__actions-spacer{display:none}.ai-chat-form-card__btn{width:100%}}.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}@media (max-width:480px){.ai-chat-form-card{padding:12px}.ai-chat-form-card__title{font-size:14px}.ai-chat-form-card__context,.ai-chat-form-card__description{font-size:12px}.ai-chat-form-card__question-text{font-size:13px}.ai-chat-form-card__textarea{font-size:13px;min-height:70px}.ai-chat-form-card__option{padding:8px 10px}.ai-chat-form-card__option-text{font-size:13px}}.ai-chat-booking-card{--action-accent:var(--primary-color,#3b82f6);background:var(--bg-secondary,#f5f5f5);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%,.06)}.ai-chat-booking-card__header{align-items:center;display:flex;gap:8px;margin-bottom:12px}.ai-chat-booking-card__back-btn{align-items:center;background:rgba(0,0,0,.05);border:none;border-radius:6px;color:var(--text-secondary,#6b7280);cursor:pointer;display:flex;font-family:inherit;font-size:13px;font-weight:500;justify-content:center;padding:6px;transition:background .15s ease,color .15s ease}.ai-chat-booking-card__back-btn svg{height:16px;width:16px}.ai-chat-booking-card__back-btn:hover{background:rgba(0,0,0,.1);color:var(--text-primary,#3e3e3e)}.ai-chat-widget.dark .ai-chat-booking-card__back-btn,.chakra-ui-dark .ai-chat-booking-card__back-btn,.dark .ai-chat-booking-card__back-btn,[data-theme=dark] .ai-chat-booking-card__back-btn{background:hsla(0,0%,100%,.08);color:var(--text-secondary,#a1a1aa)}.ai-chat-widget.dark .ai-chat-booking-card__back-btn:hover,.chakra-ui-dark .ai-chat-booking-card__back-btn:hover,.dark .ai-chat-booking-card__back-btn:hover,[data-theme=dark] .ai-chat-booking-card__back-btn:hover{background:hsla(0,0%,100%,.15);color:#fff}.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__status-icon{align-items:center;border-radius:50%;display:flex;flex-shrink:0;height:20px;justify-content:center;position:relative;width:20px}.ai-chat-booking-card__status-icon--pending{background:#6b7280}.ai-chat-booking-card__status-icon--pending:before{background:#fff;border-radius:1px;content:\"\";height:6px;position:absolute;top:5px;width:2px}.ai-chat-booking-card__status-icon--pending:after{background:#fff;border-radius:1px;content:\"\";height:2px;left:9px;position:absolute;top:9px;width:4px}.ai-chat-booking-card__status-icon--cancelled{background:#6b7280}.ai-chat-booking-card__status-icon--cancelled:after,.ai-chat-booking-card__status-icon--cancelled:before{background:#fff;border-radius:1px;content:\"\";height:2px;position:absolute;width:10px}.ai-chat-booking-card__status-icon--cancelled:before{transform:rotate(45deg)}.ai-chat-booking-card__status-icon--cancelled:after{transform:rotate(-45deg)}.ai-chat-booking-card__status-icon--error{background:#6b7280}.ai-chat-booking-card__status-icon--error:after{color:#fff;content:\"!\";font-size:12px;font-weight:700}.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__warning{background:rgba(0,0,0,.04);border-radius:8px;color:var(--text-secondary,#6b7280);font-size:13px;margin:0;padding:10px 12px}.ai-chat-widget.dark .ai-chat-booking-card__warning,.chakra-ui-dark .ai-chat-booking-card__warning,.dark .ai-chat-booking-card__warning,[data-theme=dark] .ai-chat-booking-card__warning{background:hsla(0,0%,100%,.06);color:var(--text-secondary,#a1a1aa)}.ai-chat-booking-card__input{background:rgba(0,0,0,.05);border:none;border-radius:8px;box-sizing:border-box;color:var(--text-primary,#3e3e3e);font-family:inherit;font-size:14px;outline:none;padding:10px 12px;transition:background .15s ease,box-shadow .15s ease;width:100%}.ai-chat-booking-card__input:focus{background:rgba(0,0,0,.08);box-shadow:0 0 0 2px var(--action-accent,var(--primary-color,#3b82f6))}.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:hsla(0,0%,100%,.08);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{background:hsla(0,0%,100%,.12)}.ai-chat-booking-card__field{display:flex;flex-direction:column;gap:8px}.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 .15s 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){filter:brightness(1.1);transform:translateY(-1px)}.ai-chat-booking-card__btn--secondary{background:rgba(0,0,0,.06);color:var(--text-primary,#3e3e3e)}.ai-chat-booking-card__btn--secondary:hover:not(:disabled){background:rgba(0,0,0,.1)}.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%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-booking-card__btn--secondary:hover:not(:disabled),.chakra-ui-dark .ai-chat-booking-card__btn--secondary:hover:not(:disabled),.dark .ai-chat-booking-card__btn--secondary:hover:not(:disabled),[data-theme=dark] .ai-chat-booking-card__btn--secondary:hover:not(:disabled){background:hsla(0,0%,100%,.15)}.ai-chat-booking-card__btn--danger{background:rgba(220,38,38,.1);color:#dc2626}.ai-chat-booking-card__btn--danger:hover:not(:disabled){background:rgba(220,38,38,.18)}.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);color:#fca5a5}.ai-chat-booking-card__btn--inline{font-size:12px;margin-top:8px;padding:6px 12px;width:auto}.ai-chat-booking-card__options{display:flex;flex-direction:column;gap:8px}.ai-chat-booking-card__option-btn{align-items:center;background:rgba(0,0,0,.04);border:none;border-radius:10px;box-sizing:border-box;cursor:pointer;display:flex;font-family:inherit;gap:12px;padding:14px 16px;text-align:left;transition:background .15s ease;width:100%}.ai-chat-booking-card__option-btn:hover:not(:disabled){background:rgba(0,0,0,.08)}.ai-chat-booking-card__option-btn:disabled{cursor:not-allowed;opacity:.5}.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:hsla(0,0%,100%,.06)}.ai-chat-widget.dark .ai-chat-booking-card__option-btn:hover:not(:disabled),.chakra-ui-dark .ai-chat-booking-card__option-btn:hover:not(:disabled),.dark .ai-chat-booking-card__option-btn:hover:not(:disabled),[data-theme=dark] .ai-chat-booking-card__option-btn:hover:not(:disabled){background:hsla(0,0%,100%,.1)}.ai-chat-booking-card__option-icon{align-items:center;background:var(--action-accent,var(--primary-color,#3b82f6));border-radius:8px;color:#fff;display:flex;flex-shrink:0;height:32px;justify-content:center;width:32px}.ai-chat-booking-card__option-icon svg{height:16px;width:16px}.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__list{display:flex;flex-direction:column;gap:6px}.ai-chat-booking-card__list-item{align-items:center;background:rgba(0,0,0,.04);border:none;border-radius:10px;box-sizing:border-box;cursor:pointer;display:flex;font-family:inherit;justify-content:space-between;padding:12px 14px;text-align:left;transition:background .15s ease;width:100%}.ai-chat-booking-card__list-item:hover{background:rgba(0,0,0,.08)}.ai-chat-widget.dark .ai-chat-booking-card__list-item,.chakra-ui-dark .ai-chat-booking-card__list-item,.dark .ai-chat-booking-card__list-item,[data-theme=dark] .ai-chat-booking-card__list-item{background:hsla(0,0%,100%,.06)}.ai-chat-widget.dark .ai-chat-booking-card__list-item:hover,.chakra-ui-dark .ai-chat-booking-card__list-item:hover,.dark .ai-chat-booking-card__list-item:hover,[data-theme=dark] .ai-chat-booking-card__list-item:hover{background:hsla(0,0%,100%,.1)}.ai-chat-booking-card__list-item-content{display:flex;flex-direction:column;gap:2px}.ai-chat-booking-card__list-item-name{color:var(--text-primary,#3e3e3e);font-size:14px;font-weight:500}.ai-chat-widget.dark .ai-chat-booking-card__list-item-name,.chakra-ui-dark .ai-chat-booking-card__list-item-name,.dark .ai-chat-booking-card__list-item-name,[data-theme=dark] .ai-chat-booking-card__list-item-name{color:#fff}.ai-chat-booking-card__list-item-role{color:var(--text-muted,#71717a);font-size:12px}.ai-chat-booking-card__list-item-arrow{flex-shrink:0;height:16px;position:relative;width:16px}.ai-chat-booking-card__list-item-arrow:before{border-width:medium;border-bottom:2px solid var(--text-muted,#9ca3af);border-left:0 solid var(--text-muted,#9ca3af);border-right:2px solid var(--text-muted,#9ca3af);border-top:0 solid var(--text-muted,#9ca3af);content:\"\";height:6px;left:50%;position:absolute;top:50%;transform:translate(-70%,-50%) rotate(-45deg);width:6px}.ai-chat-booking-card__slots-container{display:flex;flex-direction:column;gap:12px;max-height:280px;overflow-y:auto}.ai-chat-booking-card__date-group{display:flex;flex-direction:column;gap:8px}.ai-chat-booking-card__date-header{color:var(--text-muted,#71717a);font-size:12px;font-weight:600;letter-spacing:.5px;margin:0;padding-left:2px;text-transform:uppercase}.ai-chat-booking-card__slots{display:flex;flex-wrap:wrap;gap:6px}.ai-chat-booking-card__slot{background:rgba(0,0,0,.05);border:none;border-radius:20px;color:var(--text-primary,#3e3e3e);cursor:pointer;flex:0 0 auto;font-family:inherit;font-size:13px;font-weight:500;padding:8px 14px;transition:background .15s ease,transform .1s ease;white-space:nowrap}.ai-chat-booking-card__slot:hover:not(:disabled){background:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-booking-card__slot:active:not(:disabled){transform:scale(.97)}.ai-chat-booking-card__slot:disabled{cursor:not-allowed;opacity:.5}.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:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-booking-card__slot:hover:not(:disabled),.chakra-ui-dark .ai-chat-booking-card__slot:hover:not(:disabled),.dark .ai-chat-booking-card__slot:hover:not(:disabled),[data-theme=dark] .ai-chat-booking-card__slot:hover:not(:disabled){background:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-booking-card__subject-options{display:flex;flex-direction:column;gap:6px}.ai-chat-booking-card__subject-option{background:rgba(0,0,0,.04);border:none;border-radius:10px;color:var(--text-primary,#3e3e3e);cursor:pointer;font-family:inherit;font-size:14px;font-weight:500;padding:12px 14px;text-align:left;transition:background .15s ease,filter .15s ease}.ai-chat-booking-card__subject-option:hover:not(.ai-chat-booking-card__subject-option--selected){background:rgba(0,0,0,.08)}.ai-chat-booking-card__subject-option--selected,.ai-chat-booking-card__subject-option--selected:hover{background:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-booking-card__subject-option--selected:hover{filter:brightness(1.1)}.ai-chat-widget.dark .ai-chat-booking-card__subject-option,.chakra-ui-dark .ai-chat-booking-card__subject-option,.dark .ai-chat-booking-card__subject-option,[data-theme=dark] .ai-chat-booking-card__subject-option{background:hsla(0,0%,100%,.06);color:#fff}.ai-chat-widget.dark .ai-chat-booking-card__subject-option:hover:not(.ai-chat-booking-card__subject-option--selected),.chakra-ui-dark .ai-chat-booking-card__subject-option:hover:not(.ai-chat-booking-card__subject-option--selected),.dark .ai-chat-booking-card__subject-option:hover:not(.ai-chat-booking-card__subject-option--selected),[data-theme=dark] .ai-chat-booking-card__subject-option:hover:not(.ai-chat-booking-card__subject-option--selected){background:hsla(0,0%,100%,.1)}.ai-chat-widget.dark .ai-chat-booking-card__subject-option--selected,.ai-chat-widget.dark .ai-chat-booking-card__subject-option--selected:hover,.chakra-ui-dark .ai-chat-booking-card__subject-option--selected,.chakra-ui-dark .ai-chat-booking-card__subject-option--selected:hover,.dark .ai-chat-booking-card__subject-option--selected,.dark .ai-chat-booking-card__subject-option--selected:hover,[data-theme=dark] .ai-chat-booking-card__subject-option--selected,[data-theme=dark] .ai-chat-booking-card__subject-option--selected:hover{background:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-booking-card__appointments{display:flex;flex-direction:column;gap:8px}.ai-chat-booking-card__appointment{background:rgba(0,0,0,.04);border-radius:10px;padding:12px 14px}.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:hsla(0,0%,100%,.06)}.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:10px;font-size:11px;font-weight:600;padding:3px 8px;text-transform:uppercase}.ai-chat-booking-card__appointment-status--confirmed{background:rgba(59,130,246,.15);color:#3b82f6}.ai-chat-booking-card__appointment-status--pending{background:hsla(220,9%,46%,.15);color:#6b7280}.ai-chat-widget.dark .ai-chat-booking-card__appointment-status--confirmed,.chakra-ui-dark .ai-chat-booking-card__appointment-status--confirmed,.dark .ai-chat-booking-card__appointment-status--confirmed,[data-theme=dark] .ai-chat-booking-card__appointment-status--confirmed{background:rgba(59,130,246,.25);color:#60a5fa}.ai-chat-widget.dark .ai-chat-booking-card__appointment-status--pending,.chakra-ui-dark .ai-chat-booking-card__appointment-status--pending,.dark .ai-chat-booking-card__appointment-status--pending,[data-theme=dark] .ai-chat-booking-card__appointment-status--pending{background:hsla(220,9%,46%,.25);color:#9ca3af}.ai-chat-booking-card__appointment-status--cancelled{background:hsla(220,9%,46%,.15);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__appointment-info{display:flex;flex-direction:column;gap:4px;margin-bottom:10px}.ai-chat-booking-card__appointment-actions{display:flex;flex-wrap:wrap;gap:8px}@media (max-width:380px){.ai-chat-booking-card__appointment-actions{flex-direction:column}.ai-chat-booking-card__appointment-cancel,.ai-chat-booking-card__appointment-link{justify-content:center;text-align:center;width:100%}}.ai-chat-booking-card__appointment-link{background:var(--action-accent,var(--primary-color,#3b82f6));border-radius:6px;color:#fff;display:inline-block;font-size:12px;font-weight:500;padding:6px 12px;text-decoration:none;transition:filter .15s ease}.ai-chat-booking-card__appointment-link:hover{filter:brightness(1.1);text-decoration:none}.ai-chat-booking-card__appointment-cancel{background:rgba(220,38,38,.1);border:none;border-radius:6px;color:#dc2626;cursor:pointer;font-family:inherit;font-size:12px;font-weight:500;padding:6px 12px;transition:background .15s ease}.ai-chat-booking-card__appointment-cancel:hover:not(:disabled){background:rgba(220,38,38,.18)}.ai-chat-booking-card__appointment-cancel:disabled{cursor:not-allowed;opacity:.5}.ai-chat-widget.dark .ai-chat-booking-card__appointment-cancel,.chakra-ui-dark .ai-chat-booking-card__appointment-cancel,.dark .ai-chat-booking-card__appointment-cancel,[data-theme=dark] .ai-chat-booking-card__appointment-cancel{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-booking-card__summary{background:rgba(0,0,0,.04);border-radius:10px;padding:12px 14px}.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:hsla(0,0%,100%,.06)}.ai-chat-booking-card__summary-row{align-items:center;display:flex;gap:8px;justify-content:space-between;padding:6px 0}@media (max-width:380px){.ai-chat-booking-card__summary-row{align-items:flex-start;flex-direction:column;gap:2px}.ai-chat-booking-card__summary-value{text-align:left}}.ai-chat-booking-card__summary-row:not(:last-child){border-bottom:1px solid 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__success-icon{align-items:center;background:var(--action-accent,var(--primary-color,#3b82f6));border-radius:50%;display:flex;height:40px;justify-content:center;margin:0 auto 12px;position:relative;width:40px}.ai-chat-booking-card__success-icon:after{border:solid #fff;border-width:0 3px 3px 0;content:\"\";height:16px;margin-bottom:4px;transform:rotate(45deg);width:10px}.ai-chat-booking-card__success-message{color:var(--text-secondary,#6b7280);font-size:14px;margin:0 0 12px;text-align:center}.ai-chat-widget.dark .ai-chat-booking-card__success-message,.chakra-ui-dark .ai-chat-booking-card__success-message,.dark .ai-chat-booking-card__success-message,[data-theme=dark] .ai-chat-booking-card__success-message{color:var(--text-secondary,#a1a1aa)}.ai-chat-booking-card__link{display:inline-block;font-size:13px;font-weight:500;margin-top:8px;text-decoration:none;transition:opacity .15s ease}.ai-chat-booking-card__link:hover{opacity:.8;text-decoration:underline}.ai-chat-booking-card--success{background:rgba(59,130,246,.08)}.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(59,130,246,.12)}.ai-chat-booking-card--pending{background:hsla(220,9%,46%,.08)}.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:hsla(220,9%,46%,.12)}.ai-chat-booking-card--cancelled{background:hsla(220,9%,46%,.08)}.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%,.12)}.ai-chat-booking-card--error{background:hsla(220,9%,46%,.08)}.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:hsla(220,9%,46%,.12)}.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{background:rgba(220,38,38,.08);border-radius:8px;color:#dc2626;font-size:13px;margin:0;padding:10px 12px}.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,.15);color:#fca5a5}.ai-chat-booking-card--closable{position:relative}.ai-chat-booking-card--closable .ai-chat-booking-card__header{padding-right:40px}.ai-chat-pin-input-group{display:flex;flex-wrap:wrap;gap:8px;justify-content:center}@media (max-width:320px){.ai-chat-pin-input-group{gap:6px}}.ai-chat-pin-input{background:rgba(0,0,0,.05);border:none;border-radius:8px;box-sizing:border-box;color:var(--text-primary,#3e3e3e);font-family:inherit;font-size:20px;font-weight:600;height:48px;outline:none;padding:0;text-align:center;transition:background .15s ease,box-shadow .15s ease;width:42px}@media (max-width:320px){.ai-chat-pin-input{font-size:18px;height:42px;width:36px}}.ai-chat-pin-input:focus{background:rgba(0,0,0,.08);box-shadow:0 0 0 2px var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-pin-input::placeholder{color:var(--text-muted,#9ca3af)}.ai-chat-pin-input:disabled{cursor:not-allowed;opacity:.5}.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:hsla(0,0%,100%,.08);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{background:hsla(0,0%,100%,.12)}@media (max-width:480px){.ai-chat-booking-card{padding:12px}.ai-chat-booking-card__title{font-size:14px}.ai-chat-booking-card__option-btn{padding:12px 14px}.ai-chat-booking-card__option-icon{height:28px;width:28px}.ai-chat-booking-card__option-icon svg{height:14px;width:14px}.ai-chat-booking-card__option-text{font-size:13px}.ai-chat-booking-card__slots-container{max-height:240px}.ai-chat-booking-card__slot{font-size:12px;padding:6px 12px}}.ai-chat-structured-image{--action-accent:var(--primary-color,#3b82f6);display:flex;flex-direction:column;gap:8px;width:100%}.ai-chat-structured-image__context{color:var(--text-primary,#3e3e3e);font-size:13px;line-height:1.4;margin:0 0 4px}.ai-chat-widget.dark .ai-chat-structured-image__context,.chakra-ui-dark .ai-chat-structured-image__context,.dark .ai-chat-structured-image__context,[data-theme=dark] .ai-chat-structured-image__context{color:var(--text-primary,#fff)}.ai-chat-structured-image__error{background:rgba(239,68,68,.1);border-radius:var(--radius-md,8px);color:#dc2626;font-size:13px;padding:12px 16px;text-align:center}.ai-chat-widget.dark .ai-chat-structured-image__error,.chakra-ui-dark .ai-chat-structured-image__error,.dark .ai-chat-structured-image__error,[data-theme=dark] .ai-chat-structured-image__error{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-structured-image__cards{display:grid;gap:8px;grid-template-columns:repeat(2,1fr)}.ai-chat-structured-image__cards:has(.ai-chat-project-card:only-child){grid-template-columns:1fr}@supports not selector(:has(*)){.ai-chat-structured-image__cards{grid-template-columns:repeat(var(--card-columns,2),1fr)}}@media (max-width:480px){.ai-chat-structured-image__cards{grid-template-columns:1fr}}.ai-chat-media-display{--action-accent:var(--primary-color,#3b82f6);display:flex;flex-direction:column;gap:8px;margin-top:4px;padding:0!important}.ai-chat-media-display__context{color:var(--text-muted,#71717a);font-size:13px;margin:0 0 4px;padding:0 4px}.ai-chat-media-display__error{background:rgba(239,68,68,.1);border-radius:var(--radius-lg,12px);color:#dc2626;font-size:13px;padding:16px;text-align:center}.ai-chat-widget.dark .ai-chat-media-display__error,.chakra-ui-dark .ai-chat-media-display__error,.dark .ai-chat-media-display__error,[data-theme=dark] .ai-chat-media-display__error{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-media-display__cards{display:grid;gap:12px;grid-template-columns:repeat(var(--card-columns,1),1fr)}.ai-chat-image-card{--action-accent:var(--primary-color,#3b82f6);background:transparent;display:flex;flex-direction:column}.ai-chat-image-card,.ai-chat-image-card__media{border-radius:var(--radius-lg,12px);overflow:hidden}.ai-chat-image-card__media{position:relative;width:100%}.ai-chat-image-card__image{border-radius:var(--radius-lg,12px);display:block;height:auto;max-height:300px;object-fit:cover;width:100%}.ai-chat-image-card__image-error{align-items:center;background:var(--bg-muted,#e5e7eb);border-radius:var(--radius-lg,12px);color:var(--text-muted,#71717a);display:flex;font-size:13px;height:150px;justify-content:center;width:100%}.ai-chat-image-card__content{padding:10px 0 0}.ai-chat-image-card__title{color:var(--text-primary,#1a1a1a);font-size:14px;font-weight:600;line-height:1.3;margin:0 0 4px}.ai-chat-widget.dark .ai-chat-image-card__title,.dark .ai-chat-image-card__title,[data-theme=dark] .ai-chat-image-card__title{color:#fff}.ai-chat-image-card__description{color:var(--text-muted,#6b7280);font-size:13px;line-height:1.4;margin:0 0 8px}.ai-chat-image-card__link-btn{align-items:center;background:transparent;border:none;color:var(--action-accent);cursor:pointer;display:inline-flex;font-size:13px;font-weight:500;gap:4px;padding:0;transition:opacity .2s}.ai-chat-image-card__link-btn:hover{opacity:.8}.ai-chat-media-card{--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);display:flex;flex-direction:column;overflow:hidden}.ai-chat-widget.dark .ai-chat-media-card,.chakra-ui-dark .ai-chat-media-card,.dark .ai-chat-media-card,[data-theme=dark] .ai-chat-media-card{background:var(--bg-secondary,#3a3a3a);border-color:hsla(0,0%,100%,.08)}.ai-chat-media-card__media{background:#000;position:relative;width:100%}.ai-chat-media-card__media.video{aspect-ratio:16/9}.ai-chat-media-card__media.image{aspect-ratio:auto;max-height:400px}.ai-chat-media-card__image{display:block;height:100%;object-fit:cover;width:100%}.ai-chat-media-card__image-error{align-items:center;background:var(--bg-muted,#e5e7eb);color:var(--text-muted,#71717a);display:flex;font-size:13px;height:200px;justify-content:center;width:100%}.ai-chat-media-card__video-placeholder{cursor:pointer;height:100%;position:relative;width:100%}.ai-chat-media-card__video-placeholder img{height:100%;object-fit:cover;width:100%}.ai-chat-media-card__video-bg{background:linear-gradient(135deg,#1a1a2e,#16213e);height:100%;width:100%}.ai-chat-media-card__play-btn{align-items:center;background:rgba(0,0,0,.7);border:none;border-radius:50%;color:#fff;cursor:pointer;display:flex;height:56px;justify-content:center;left:50%;position:absolute;top:50%;transform:translate(-50%,-50%);transition:background .2s,transform .2s;width:56px}.ai-chat-media-card__play-btn:hover{background:rgba(0,0,0,.9);transform:translate(-50%,-50%) scale(1.05)}.ai-chat-media-card__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-media-card__iframe,.ai-chat-media-card__video{border:none;height:100%;left:0;position:absolute;top:0;width:100%}.ai-chat-media-card__content{padding:12px}.ai-chat-media-card__title{color:var(--text-primary,#3e3e3e);font-size:15px;font-weight:600;line-height:1.3;margin:0 0 4px}.ai-chat-widget.dark .ai-chat-media-card__title,.chakra-ui-dark .ai-chat-media-card__title,.dark .ai-chat-media-card__title,[data-theme=dark] .ai-chat-media-card__title{color:#fff}.ai-chat-media-card__description{color:var(--text-muted,#71717a);font-size:13px;line-height:1.4;margin:0 0 8px}.ai-chat-media-card__link-btn{align-items:center;background:var(--action-accent);border:none;border-radius:6px;color:#fff;cursor:pointer;display:inline-flex;font-size:13px;font-weight:500;gap:6px;padding:6px 12px;transition:opacity .2s}.ai-chat-media-card__link-btn:hover{opacity:.9}.ai-chat-image-gallery{--action-accent:var(--primary-color,#3b82f6)}.ai-chat-image-gallery__grid{display:grid;gap:8px;grid-template-columns:repeat(2,1fr)}@media (max-width:480px){.ai-chat-image-gallery__grid{grid-template-columns:1fr}.ai-chat-image-gallery__grid .ai-chat-image-gallery__item:first-child{grid-column:span 1}}.ai-chat-image-gallery__grid:has(.ai-chat-image-gallery__item:only-child){grid-template-columns:1fr}.ai-chat-image-gallery__grid:has(.ai-chat-image-gallery__item:nth-child(3):last-child) .ai-chat-image-gallery__item:first-child{grid-column:span 2}.ai-chat-image-gallery__grid:has(.ai-chat-image-gallery__item:nth-child(5):last-child) .ai-chat-image-gallery__item:first-child{grid-column:span 2}.ai-chat-image-gallery__grid:has(.ai-chat-image-gallery__item:nth-child(7):last-child) .ai-chat-image-gallery__item:first-child{grid-column:span 2}.ai-chat-image-gallery__item.span-full{grid-column:span 2}.ai-chat-image-gallery[data-item-count=\"1\"] .ai-chat-image-gallery__grid{grid-template-columns:1fr}.ai-chat-image-gallery__item{position:relative}.ai-chat-image-gallery__item-media{aspect-ratio:4/3;background:var(--bg-muted,#e5e7eb);border-radius:var(--radius-lg,12px);overflow:hidden;position:relative}.ai-chat-image-gallery__item-media img{height:100%;object-fit:cover;width:100%}.ai-chat-image-gallery__item-overlay{background:linear-gradient(0deg,rgba(0,0,0,.85) 0,rgba(0,0,0,.4) 60%,transparent);border-radius:0 0 var(--radius-lg,12px) var(--radius-lg,12px);bottom:0;left:0;padding:24px 12px 10px;position:absolute;right:0}.ai-chat-image-gallery__item-title{-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;color:#fff;display:-webkit-box;font-size:12px;font-weight:600;line-height:1.3;margin:0;overflow:hidden;text-shadow:0 1px 3px rgba(0,0,0,.5)}.ai-chat-image-gallery__error{align-items:center;color:var(--text-muted,#71717a);display:flex;font-size:12px;height:100%;justify-content:center;width:100%}.ai-chat-media-gallery{--action-accent:var(--primary-color,#3b82f6)}.ai-chat-media-gallery__grid{display:grid;gap:8px;grid-template-columns:repeat(2,1fr)}.ai-chat-image-gallery__lightbox,.ai-chat-media-gallery__lightbox{align-items:center;background:rgba(0,0,0,.95);bottom:0;display:flex;justify-content:center;left:0;padding:40px;position:fixed;right:0;top:0;z-index:10000}.ai-chat-image-gallery__lightbox-close,.ai-chat-media-gallery__lightbox-close{align-items:center;background:hsla(0,0%,100%,.1);border:none;border-radius:50%;color:#fff;cursor:pointer;display:flex;height:40px;justify-content:center;position:absolute;right:16px;top:16px;transition:background .2s;width:40px}.ai-chat-image-gallery__lightbox-close:hover,.ai-chat-media-gallery__lightbox-close:hover{background:hsla(0,0%,100%,.2)}.ai-chat-image-gallery__lightbox-nav,.ai-chat-media-gallery__lightbox-nav{align-items:center;background:hsla(0,0%,100%,.1);border:none;border-radius:50%;color:#fff;cursor:pointer;display:flex;height:48px;justify-content:center;position:absolute;top:50%;transform:translateY(-50%);transition:background .2s;width:48px}.ai-chat-image-gallery__lightbox-nav:hover,.ai-chat-media-gallery__lightbox-nav:hover{background:hsla(0,0%,100%,.2)}.ai-chat-image-gallery__lightbox-nav.prev,.ai-chat-media-gallery__lightbox-nav.prev{left:16px}.ai-chat-image-gallery__lightbox-nav.next,.ai-chat-media-gallery__lightbox-nav.next{right:16px}.ai-chat-image-gallery__lightbox-content,.ai-chat-media-gallery__lightbox-content{align-items:center;display:flex;flex-direction:column;max-height:80vh;max-width:90vw}.ai-chat-image-gallery__lightbox-content img,.ai-chat-media-gallery__lightbox-content img{border-radius:4px;max-height:70vh;max-width:100%;object-fit:contain}.ai-chat-image-gallery__lightbox-caption,.ai-chat-media-gallery__lightbox-caption{color:#fff;margin-top:16px;text-align:center}.ai-chat-image-gallery__lightbox-caption h4,.ai-chat-media-gallery__lightbox-caption h4{font-size:16px;font-weight:600;margin:0 0 4px}.ai-chat-image-gallery__lightbox-caption p,.ai-chat-media-gallery__lightbox-caption p{color:hsla(0,0%,100%,.7);font-size:14px;margin:0}.ai-chat-image-gallery__lightbox-counter,.ai-chat-media-gallery__lightbox-counter{background:rgba(0,0,0,.6);border-radius:20px;bottom:16px;color:#fff;font-size:13px;left:50%;padding:6px 12px;position:absolute;transform:translateX(-50%)}.ai-chat-project-card{--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);display:flex;flex-direction:column;overflow:hidden;transition:border-color .2s,box-shadow .2s,transform .2s}.ai-chat-project-card.clickable{cursor:pointer}.ai-chat-project-card.clickable:hover{border-color:var(--action-accent);box-shadow:0 4px 12px rgba(0,0,0,.1);transform:translateY(-2px)}.ai-chat-widget.dark .ai-chat-project-card,.chakra-ui-dark .ai-chat-project-card,.dark .ai-chat-project-card,[data-theme=dark] .ai-chat-project-card{background:var(--bg-secondary,#2a2a2a);border-color:hsla(0,0%,100%,.1)}.ai-chat-widget.dark .ai-chat-project-card.clickable:hover,.chakra-ui-dark .ai-chat-project-card.clickable:hover,.dark .ai-chat-project-card.clickable:hover,[data-theme=dark] .ai-chat-project-card.clickable:hover{border-color:var(--action-accent);box-shadow:0 4px 16px rgba(0,0,0,.3)}.ai-chat-project-card--image-only{background:transparent;border:none}.ai-chat-project-card--image-only .ai-chat-project-card__media{aspect-ratio:16/9;border-radius:var(--radius-lg,12px)}.ai-chat-project-card--image-only.clickable:hover{border:none;box-shadow:0 4px 16px rgba(0,0,0,.2)}.ai-chat-project-card--overlay{background:transparent;border:none;border-radius:var(--radius-lg,12px);overflow:hidden}.ai-chat-project-card--overlay .ai-chat-project-card__media{aspect-ratio:4/3;border-radius:var(--radius-lg,12px)}.ai-chat-project-card__overlay{background:linear-gradient(0deg,rgba(0,0,0,.85) 0,rgba(0,0,0,.5) 50%,transparent);border-radius:0 0 var(--radius-lg,12px) var(--radius-lg,12px);bottom:0;left:0;padding:10px 12px;position:absolute;right:0}.ai-chat-project-card__overlay-title{-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;color:#fff;display:-webkit-box;font-size:12px;font-weight:600;line-height:1.3;margin:0;overflow:hidden;text-shadow:0 1px 3px rgba(0,0,0,.5)}.ai-chat-project-card--full .ai-chat-project-card__media{aspect-ratio:16/10;border-bottom:1px solid var(--border-subtle,rgba(0,0,0,.06))}.ai-chat-widget.dark .ai-chat-project-card--full .ai-chat-project-card__media,.chakra-ui-dark .ai-chat-project-card--full .ai-chat-project-card__media,.dark .ai-chat-project-card--full .ai-chat-project-card__media,[data-theme=dark] .ai-chat-project-card--full .ai-chat-project-card__media{border-bottom-color:hsla(0,0%,100%,.08)}.ai-chat-project-card__media{aspect-ratio:16/10;background:var(--bg-muted,#e5e7eb);overflow:hidden;position:relative;width:100%}.ai-chat-widget.dark .ai-chat-project-card__media,.chakra-ui-dark .ai-chat-project-card__media,.dark .ai-chat-project-card__media,[data-theme=dark] .ai-chat-project-card__media{background:hsla(0,0%,100%,.05)}.ai-chat-project-card__media img{height:100%;object-fit:cover;transition:transform .3s ease;width:100%}.ai-chat-project-card.clickable:hover .ai-chat-project-card__media img{transform:scale(1.03)}.ai-chat-project-card__iframe,.ai-chat-project-card__video{border:none;height:100%;left:0;position:absolute;top:0;width:100%}.ai-chat-project-card__placeholder{align-items:center;color:var(--text-muted,#71717a);display:flex;font-size:13px;height:100%;justify-content:center;width:100%}.ai-chat-project-card__play-btn{align-items:center;background:rgba(0,0,0,.7);border:none;border-radius:50%;color:#fff;cursor:pointer;display:flex;height:48px;justify-content:center;left:50%;position:absolute;top:50%;transform:translate(-50%,-50%);transition:background .2s,transform .2s;width:48px}.ai-chat-project-card__play-btn:hover{background:rgba(0,0,0,.9);transform:translate(-50%,-50%) scale(1.1)}.ai-chat-project-card__content{background:var(--bg-secondary,#f4f4f4);padding:12px 14px 14px}.ai-chat-widget.dark .ai-chat-project-card__content,.chakra-ui-dark .ai-chat-project-card__content,.dark .ai-chat-project-card__content,[data-theme=dark] .ai-chat-project-card__content{background:var(--bg-secondary,#2a2a2a)}.ai-chat-project-card__title{color:var(--text-primary,#1a1a1a);font-size:14px;font-weight:600;line-height:1.35;margin:0 0 6px}.ai-chat-widget.dark .ai-chat-project-card__title,.chakra-ui-dark .ai-chat-project-card__title,.dark .ai-chat-project-card__title,[data-theme=dark] .ai-chat-project-card__title{color:#fff}.ai-chat-project-card__description{-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;color:var(--text-muted,#6b7280);display:-webkit-box;font-size:13px;line-height:1.45;margin:0 0 10px;overflow:hidden}.ai-chat-project-card__link{align-items:center;color:var(--action-accent);display:inline-flex;font-size:13px;font-weight:500;gap:4px;transition:opacity .2s}.ai-chat-project-card__link:hover{opacity:.8}.ai-chat-media-carousel{--action-accent:var(--primary-color,#3b82f6);border-radius:var(--radius-lg,12px);overflow:hidden;position:relative}.ai-chat-media-carousel__track{display:flex;transition:transform .3s ease-out}.ai-chat-media-carousel__slide{flex:0 0 100%;min-width:0}.ai-chat-media-carousel__slide .ai-chat-project-card{border-radius:var(--radius-md,8px);margin:0 4px}.ai-chat-media-carousel__nav{align-items:center;background:hsla(0,0%,100%,.9);border:none;border-radius:50%;box-shadow:0 2px 8px rgba(0,0,0,.15);color:#333;cursor:pointer;display:flex;height:32px;justify-content:center;position:absolute;top:50%;transform:translateY(-50%);transition:background .2s;width:32px;z-index:2}.ai-chat-media-carousel__nav:hover{background:#fff}.ai-chat-media-carousel__nav.prev{left:8px}.ai-chat-media-carousel__nav.next{right:8px}.ai-chat-widget.dark .ai-chat-media-carousel__nav,.chakra-ui-dark .ai-chat-media-carousel__nav,.dark .ai-chat-media-carousel__nav,[data-theme=dark] .ai-chat-media-carousel__nav{background:rgba(0,0,0,.7);color:#fff}.ai-chat-widget.dark .ai-chat-media-carousel__nav:hover,.chakra-ui-dark .ai-chat-media-carousel__nav:hover,.dark .ai-chat-media-carousel__nav:hover,[data-theme=dark] .ai-chat-media-carousel__nav:hover{background:rgba(0,0,0,.9)}.ai-chat-media-carousel__dots{display:flex;gap:6px;justify-content:center;padding:12px 0 4px}.ai-chat-media-carousel__dot{background:var(--border-subtle,rgba(0,0,0,.2));border:none;border-radius:50%;cursor:pointer;height:8px;padding:0;transition:background .2s,transform .2s;width:8px}.ai-chat-media-carousel__dot:hover{transform:scale(1.2)}.ai-chat-media-carousel__dot.active{background:var(--action-accent)}.ai-chat-widget.dark .ai-chat-media-carousel__dot,.chakra-ui-dark .ai-chat-media-carousel__dot,.dark .ai-chat-media-carousel__dot,[data-theme=dark] .ai-chat-media-carousel__dot{background:hsla(0,0%,100%,.3)}.ai-chat-widget.dark .ai-chat-media-carousel__dot.active,.chakra-ui-dark .ai-chat-media-carousel__dot.active,.dark .ai-chat-media-carousel__dot.active,[data-theme=dark] .ai-chat-media-carousel__dot.active{background:var(--action-accent)}@media (max-width:480px){.ai-chat-media-carousel__nav{height:28px;width:28px}.ai-chat-media-carousel__nav.prev{left:4px}.ai-chat-media-carousel__nav.next{right:4px}.ai-chat-image-gallery__lightbox-nav,.ai-chat-media-gallery__lightbox-nav{height:40px;width:40px}.ai-chat-image-gallery__lightbox,.ai-chat-media-gallery__lightbox{padding:16px}.ai-chat-project-card__content{padding:10px 12px 12px}.ai-chat-project-card__title{font-size:13px}.ai-chat-project-card__description{font-size:12px}}.chat-fullpage{--fp-max-width:800px;--fp-padding-x:16px;--fp-padding-top-mobile:64px;--fp-padding-top-desktop:24px;--fp-padding-bottom:200px;--fp-input-bottom:0}.chat-fullpage .ai-chat-messages{background:transparent;flex:1 1 auto;height:auto;justify-content:flex-start;margin:0 auto;max-height:none;max-width:var(--fp-max-width);min-height:0!important;overflow-x:hidden!important;overflow-y:scroll!important;padding:var(--fp-padding-top-desktop) var(--fp-padding-x) var(--fp-padding-bottom);position:relative}@media (max-width:767px){.chat-fullpage .ai-chat-messages{padding-top:var(--fp-padding-top-mobile)!important}}@media (max-width:480px){.chat-fullpage .ai-chat-messages{padding-top:calc(var(--fp-padding-top-mobile) + env(safe-area-inset-top, 0px))}}.chat-fullpage .ai-chat-messages>.ai-chat-message:first-child,.chat-fullpage .ai-chat-messages>.ai-chat-welcome:first-child{margin-top:0}.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:12px 0 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:110px}}.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}.chat-fullpage .ai-chat-message-meta{align-items:center;display:flex;gap:8px;margin-top:4px;padding:0 16px}.chat-fullpage .ai-chat-message-timestamp{color:var(--text-muted,#71717a);font-size:12px}.chat-fullpage .ai-chat-feedback{display:inline-flex}.chat-fullpage .ai-chat-feedback-button{display:flex}@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:not(.is-open).bottom-right .ai-chat-button{bottom:12px!important;right:12px!important}.ai-chat-widget-container:not(.is-open).bottom-left .ai-chat-button{bottom:12px!important;left:12px!important}.ai-chat-widget-container:not(.is-open).top-right .ai-chat-button{right:12px!important;top:12px!important}.ai-chat-widget-container:not(.is-open).top-left .ai-chat-button{left:12px!important;top:12px!important}.ai-chat-widget-container.trigger-pill-text.container-mode:not(.is-open).bottom-right .ai-chat-trigger-pill{bottom:12px!important;right:12px!important}.ai-chat-widget-container.trigger-pill-text.container-mode:not(.is-open).bottom-left .ai-chat-trigger-pill{bottom:12px!important;left:12px!important}.ai-chat-widget-container.trigger-pill-text.container-mode:not(.is-open).top-right .ai-chat-trigger-pill{right:12px!important;top:12px!important}.ai-chat-widget-container.trigger-pill-text.container-mode:not(.is-open).top-left .ai-chat-trigger-pill{left:12px!important;top:12px!important}.ai-chat-widget-container.trigger-input-bar.container-mode:not(.is-open) .ai-chat-trigger-input-container{bottom:12px!important;left:12px!important;right:12px!important;width:calc(100% - 24px)!important}.ai-chat-widget-container.trigger-input-bar:not(.is-open) .ai-chat-trigger-input-wrapper{max-width:100%!important;width:100%!important}.ai-chat-widget-container.trigger-input-bar:not(.is-open) .ai-chat-trigger-input-row{display:flex;gap:8px;max-width:calc(100vw - 24px)!important;width:calc(100vw - 24px)!important}.ai-chat-widget-container.trigger-input-bar.is-collapsed:not(.is-open) .ai-chat-trigger-input-container{bottom:12px!important;right:12px!important;width:auto!important}.ai-chat-widget-container.trigger-input-bar.is-collapsed:not(.is-open) .ai-chat-button{margin-left:0!important;margin-right:0!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%}.ai-chat-widget-container.is-open .ai-chat-message-meta{align-items:center;display:flex;gap:8px;margin-top:4px}.ai-chat-widget-container.is-open .ai-chat-message-timestamp{font-size:11px}.ai-chat-widget-container.is-open .ai-chat-feedback{display:inline-flex}.ai-chat-widget-container.is-open .ai-chat-feedback-button{display:flex;padding:4px}.ai-chat-widget-container.is-open .ai-chat-input{font-size:16px!important}}@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)}}.ai-chat-widget-container.desktop-mode.container-mode.is-open{height:100%!important;inset:0!important;position:absolute!important;width:100%!important}.ai-chat-widget-container.desktop-mode.container-mode.is-open .ai-chat-window{border:1px solid var(--border-color,rgba(0,0,0,.08))!important;border-radius:var(--radius-window-top,22px) var(--radius-window-top,22px) var(--radius-window-bottom,44px) var(--radius-window-bottom,44px)!important;box-shadow:var(--window-shadow,0 20px 60px -10px rgba(0,0,0,.25))!important;position:absolute!important}.ai-chat-widget-container.desktop-mode.container-mode.size-small.is-open .ai-chat-window{height:min(500px,calc(100% - 120px))!important;max-height:500px!important;max-width:380px!important;min-height:300px!important;min-width:280px!important;width:min(380px,calc(100% - 40px))!important}.ai-chat-widget-container.desktop-mode.container-mode.size-medium.is-open .ai-chat-window{height:min(65%,calc(100% - 120px))!important;max-height:680px!important;max-width:440px!important;min-height:400px!important;min-width:320px!important;width:min(440px,calc(100% - 40px))!important}.ai-chat-widget-container.desktop-mode.container-mode.size-large.is-open .ai-chat-window{height:calc(100% - 100px)!important;max-height:calc(100% - 100px)!important;max-width:560px!important;min-height:500px!important;min-width:380px!important;width:min(560px,calc(100% - 40px))!important}.ai-chat-widget-container.desktop-mode.container-mode.is-open.bottom-right .ai-chat-window{bottom:88px!important;left:auto!important;right:20px!important;top:auto!important}.ai-chat-widget-container.desktop-mode.container-mode.is-open.bottom-left .ai-chat-window{bottom:88px!important;left:20px!important;right:auto!important;top:auto!important}.ai-chat-widget-container.desktop-mode.container-mode.is-open.top-right .ai-chat-window{bottom:auto!important;left:auto!important;right:20px!important;top:88px!important}.ai-chat-widget-container.desktop-mode.container-mode.is-open.top-left .ai-chat-window{bottom:auto!important;left:20px!important;right:auto!important;top:88px!important}.ai-chat-widget-container.desktop-mode.is-open .ai-chat-button{display:flex!important;opacity:1!important;pointer-events:auto!important;visibility:visible!important}.ai-chat-widget-container.desktop-mode.container-mode:not(.trigger-input-bar).bottom-right .ai-chat-button{bottom:20px!important;left:auto!important;right:20px!important;top:auto!important}.ai-chat-widget-container.desktop-mode.container-mode:not(.trigger-input-bar).bottom-left .ai-chat-button{bottom:20px!important;left:20px!important;right:auto!important;top:auto!important}.ai-chat-widget-container.desktop-mode.container-mode:not(.trigger-input-bar).top-right .ai-chat-button{bottom:auto!important;left:auto!important;right:20px!important;top:20px!important}.ai-chat-widget-container.desktop-mode.container-mode:not(.trigger-input-bar).top-left .ai-chat-button{bottom:auto!important;left:20px!important;right:auto!important;top:20px!important}.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.bottom-right .ai-chat-trigger-input-container{bottom:20px!important;left:auto!important;right:20px!important;top:auto!important}.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.bottom-left .ai-chat-trigger-input-container{bottom:20px!important;left:20px!important;right:auto!important;top:auto!important}.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.top-right .ai-chat-trigger-input-container{bottom:auto!important;left:auto!important;right:20px!important;top:20px!important}.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.top-left .ai-chat-trigger-input-container{bottom:auto!important;left:20px!important;right:auto!important;top:20px!important}.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.size-small .ai-chat-trigger-input-container{width:min(380px,calc(100% - 40px))!important}.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.size-medium .ai-chat-trigger-input-container{width:min(440px,calc(100% - 40px))!important}.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.size-large .ai-chat-trigger-input-container{width:min(560px,calc(100% - 40px))!important}.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.is-open.bottom-left .ai-chat-window,.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.is-open.bottom-right .ai-chat-window{bottom:20px!important}.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.is-open.top-left .ai-chat-window,.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.is-open.top-right .ai-chat-window{top:20px!important}.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.is-open.bottom-right .ai-chat-window,.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.is-open.top-right .ai-chat-window{left:auto!important;right:20px!important}.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.is-open.bottom-left .ai-chat-window,.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.is-open.top-left .ai-chat-window{left:20px!important;right:auto!important}";
47531
47921
  styleInject(css_248z$1);
47532
47922
 
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}";
47923
+ 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}.ai-chat-widget-embedded .ai-chat-data-policy-view{-webkit-overflow-scrolling:touch;overflow-y:auto}.ai-chat-widget-embedded .ai-chat-data-policy-content{margin:0 auto;max-width:640px;overflow-y:visible;padding:32px 24px 60px}.ai-chat-widget-embedded .ai-chat-data-policy-intro p{font-size:14px;line-height:1.7}.ai-chat-widget-embedded .ai-chat-data-policy-section h3{font-size:15px;margin-bottom:14px}.ai-chat-widget-embedded .ai-chat-data-policy-section p{font-size:13px;line-height:1.7}.ai-chat-widget-embedded.dark .ai-chat-data-policy-intro p,.ai-chat-widget-embedded.dark .ai-chat-data-policy-intro strong,.ai-chat-widget-embedded.dark .ai-chat-data-policy-section h3{color:var(--text-primary,#fafafa)}.ai-chat-widget-embedded.dark .ai-chat-data-policy-section p{color:var(--text-secondary,#a1a1aa)}.ai-chat-widget-embedded.dark .ai-chat-data-policy-section p strong{color:var(--text-primary,#fafafa)}";
47534
47924
  styleInject(css_248z);
47535
47925
 
47536
- // Icon components mapping
47537
- const iconComponents = {
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" }) })),
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" }) })),
47540
- };
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', }) => {
47926
+ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, previewMode = false, previewConfig, position = 'bottom-right', primaryColor, size, headerTitle, welcomeTitle, welcomeMessage, placeholder, welcomeBubbleText, triggerType, triggerText, theme, suggestedQuestions, customStyles, currentRoute, defaultOpen = false, zIndex, containerMode = false, mobileMode = false, desktopMode = false, onOpen, onClose, onMessage, onError, mode = 'bubble', }) => {
47542
47927
  const [isOpen, setIsOpen] = reactExports.useState(defaultOpen);
47543
47928
  const [inputBarValue, setInputBarValue] = reactExports.useState('');
47544
- const [autoDetectedTheme, setAutoDetectedTheme] = reactExports.useState('light');
47545
47929
  const [showWelcomeBubble, setShowWelcomeBubble] = reactExports.useState(false);
47930
+ const [isInputBarCollapsed, setIsInputBarCollapsed] = reactExports.useState(false);
47546
47931
  const widgetRef = reactExports.useRef(null);
47547
47932
  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);
47558
47933
  // Determine mode
47559
47934
  const isEmbedded = mode === 'embedded';
47560
47935
  // Default config for preview mode
@@ -47600,24 +47975,22 @@
47600
47975
  ...previewConfig?.behavior,
47601
47976
  },
47602
47977
  };
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);
47978
+ // Always call useChat hook (React rules), but skip initialization in preview mode
47979
+ const shouldSkipInit = previewMode;
47607
47980
  const chatHook = useChat({
47608
47981
  widgetId: previewMode ? '__preview__' : (widgetId || '__preview__'),
47609
47982
  apiUrl,
47610
47983
  currentRoute,
47611
47984
  onMessage: shouldSkipInit ? undefined : onMessage,
47612
47985
  onError: shouldSkipInit ? undefined : onError,
47613
- skipInitialization: shouldSkipInit, // Don't make API calls in preview mode or during demo
47986
+ skipInitialization: shouldSkipInit,
47614
47987
  });
47615
47988
  // Extract values from hook or use preview defaults
47616
- const hookMessages = previewMode ? [] : chatHook.messages;
47617
- const hookIsLoading = previewMode ? false : chatHook.isLoading;
47618
- const hookIsTyping = previewMode ? false : chatHook.isTyping;
47989
+ const messages = previewMode ? [] : chatHook.messages;
47990
+ const isLoading = previewMode ? false : chatHook.isLoading;
47991
+ const isTyping = previewMode ? false : chatHook.isTyping;
47619
47992
  const config = previewMode ? mergedPreviewConfig : chatHook.config;
47620
- const hookSendMessage = previewMode ? (() => Promise.resolve()) : chatHook.sendMessage;
47993
+ const sendMessage = previewMode ? (() => Promise.resolve()) : chatHook.sendMessage;
47621
47994
  const submitFeedback = previewMode ? (() => Promise.resolve()) : chatHook.submitFeedback;
47622
47995
  const dismissAction = previewMode ? (() => Promise.resolve()) : chatHook.dismissAction;
47623
47996
  const conversations = previewMode ? [] : chatHook.conversations;
@@ -47625,54 +47998,26 @@
47625
47998
  const switchConversation = previewMode ? (() => Promise.resolve()) : chatHook.switchConversation;
47626
47999
  const startNewConversation = previewMode ? (() => { }) : chatHook.startNewConversation;
47627
48000
  const deleteConversation = previewMode ? (() => { }) : chatHook.deleteConversation;
47628
- const createDemoConversation = previewMode ? (() => Promise.resolve(null)) : chatHook.createDemoConversation;
47629
48001
  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]);
47651
- // Auto-detect theme from background
47652
- reactExports.useEffect(() => {
47653
- if (!containerRef.current)
47654
- return;
47655
- // Initial detection
47656
- const detected = detectTheme(containerRef.current);
47657
- setAutoDetectedTheme(detected);
47658
- // Watch for theme changes on the page
47659
- const observer = createThemeObserver(containerRef.current, (newTheme) => {
47660
- setAutoDetectedTheme(newTheme);
47661
- });
47662
- // Also listen for system preference changes
47663
- const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
47664
- const handleMediaChange = () => {
47665
- if (containerRef.current) {
47666
- const detected = detectTheme(containerRef.current);
47667
- setAutoDetectedTheme(detected);
47668
- }
47669
- };
47670
- mediaQuery.addEventListener('change', handleMediaChange);
47671
- return () => {
47672
- observer.disconnect();
47673
- mediaQuery.removeEventListener('change', handleMediaChange);
47674
- };
47675
- }, [config]);
48002
+ const callActionEndpoint = previewMode ? (async () => { throw new Error('Not available in preview mode'); }) : chatHook.callActionEndpoint;
48003
+ const { effectiveTheme, effectivePosition, accentColor, iconContrastColor, effectiveSize, effectiveHeaderTitle, effectiveWelcomeTitle, effectiveWelcomeMessage, effectivePlaceholder, effectiveWelcomeBubbleText, effectiveTriggerType, effectiveTriggerText, mergedStyles, } = useWidgetAppearance({
48004
+ containerRef,
48005
+ config,
48006
+ theme,
48007
+ primaryColor,
48008
+ position,
48009
+ size,
48010
+ headerTitle,
48011
+ welcomeTitle,
48012
+ welcomeMessage,
48013
+ placeholder,
48014
+ welcomeBubbleText,
48015
+ triggerType,
48016
+ triggerText,
48017
+ customStyles,
48018
+ zIndex,
48019
+ previewMode,
48020
+ });
47676
48021
  // Check if device is mobile
47677
48022
  const isMobile = typeof window !== 'undefined' && window.innerWidth <= 480;
47678
48023
  // Handle auto-open (only for bubble mode, disabled on mobile)
@@ -47680,9 +48025,6 @@
47680
48025
  // Never auto-open on mobile devices
47681
48026
  if (isMobile)
47682
48027
  return undefined;
47683
- // Don't auto-open if demo mode is active - let demo animation control opening
47684
- if (demoMode && !isDemoComplete)
47685
- return undefined;
47686
48028
  if (!isEmbedded && config?.settings.autoOpen) {
47687
48029
  const delay = config.settings.autoOpenDelay || 0;
47688
48030
  const timer = setTimeout(() => {
@@ -47692,7 +48034,7 @@
47692
48034
  return () => clearTimeout(timer);
47693
48035
  }
47694
48036
  return undefined;
47695
- }, [config, onOpen, isEmbedded, isMobile, demoMode, isDemoComplete]);
48037
+ }, [config, onOpen, isEmbedded, isMobile]);
47696
48038
  // Handle close on Escape key (only for bubble mode)
47697
48039
  reactExports.useEffect(() => {
47698
48040
  if (!isOpen || isEmbedded)
@@ -47769,172 +48111,12 @@
47769
48111
  setShowWelcomeBubble(true);
47770
48112
  }
47771
48113
  }, [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]);
47906
- // Determine theme - use prop override if provided, otherwise auto-detect
47907
- const appearanceConfig = config?.appearance;
47908
- const effectiveTheme = theme ?? autoDetectedTheme;
47909
- // Determine position (prop override takes priority for live preview)
47910
- const effectivePosition = position || config?.appearance.position || 'bottom-right';
47911
- // Get accent color from prop or config (empty string means no accent color / vanilla mode)
47912
- const accentColor = primaryColor ?? appearanceConfig?.primaryColor ?? '';
47913
- // Apply prop overrides for live preview (props take priority over config)
47914
- const effectiveSize = size || appearanceConfig?.size || 'small';
47915
- const effectiveHeaderTitle = headerTitle ?? appearanceConfig?.headerTitle ?? '';
47916
- const effectiveWelcomeTitle = welcomeTitle ?? appearanceConfig?.welcomeTitle ?? '';
47917
- const effectiveWelcomeMessage = welcomeMessage ?? appearanceConfig?.welcomeMessage ?? '';
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';
47922
- // Generate styles using simplified theme system
47923
- const simpleAppearance = {
47924
- accentColor};
47925
- // Generate theme styles from accent color
47926
- const generatedStyles = generateThemeStyles(simpleAppearance, effectiveTheme);
47927
- // Also apply legacy styles for backward compatibility
47928
- const legacyStyles = appearanceConfig
47929
- ? applyAppearanceStyles(appearanceConfig)
47930
- : {};
47931
- // Merge styles (generated takes priority for new simplified system, then custom overrides)
47932
- const mergedStyles = {
47933
- ...legacyStyles,
47934
- ...generatedStyles,
47935
- ...customStyles,
47936
- ...(zIndex !== undefined ? { '--widget-z-index': String(zIndex) } : {}),
47937
- };
48114
+ const handleStartNewConversation = reactExports.useCallback(() => {
48115
+ startNewConversation();
48116
+ }, [startNewConversation]);
48117
+ const handleSendMessage = reactExports.useCallback((content) => {
48118
+ sendMessage(content);
48119
+ }, [sendMessage]);
47938
48120
  // Dismiss bubble and store based on frequency setting
47939
48121
  const dismissBubble = () => {
47940
48122
  setShowWelcomeBubble(false);
@@ -47970,9 +48152,6 @@
47970
48152
  onOpen?.();
47971
48153
  }
47972
48154
  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
47976
48155
  onClose?.();
47977
48156
  }
47978
48157
  };
@@ -48009,10 +48188,13 @@
48009
48188
  sendMessage(actionInstruction);
48010
48189
  };
48011
48190
  // 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
48191
+ // Exceptions that allow immediate rendering:
48192
+ // 1. triggerType prop provided - user wants specific trigger shown immediately
48193
+ // 2. primaryColor prop provided - we have initial styling, no flash will occur
48194
+ // This improves perceived loading speed - users see the correctly styled trigger while config loads
48014
48195
  // In preview mode, config is always available
48015
- const canRenderWithoutConfig = !!triggerType;
48196
+ const hasInitialStyling = !!primaryColor;
48197
+ const canRenderWithoutConfig = !!triggerType || hasInitialStyling;
48016
48198
  if (!config && !previewMode && !canRenderWithoutConfig) {
48017
48199
  return null;
48018
48200
  }
@@ -48020,21 +48202,21 @@
48020
48202
  const IconComponent = isOpen ? iconComponents.FiChevronDown : iconComponents.FiMessageCircle;
48021
48203
  // Embedded mode renders directly without wrapper positioning
48022
48204
  if (isEmbedded) {
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 }) }));
48205
+ 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: handleSendMessage, onClose: () => { }, onFeedback: handleFeedback, onActionClick: handleActionClick, onActionDismiss: dismissAction, onCallEndpoint: callActionEndpoint, conversations: conversations, onLoadConversations: loadConversations, onSwitchConversation: switchConversation, onStartNewConversation: handleStartNewConversation, onDeleteConversation: deleteConversation, currentConversationId: conversationId, sizeOverride: effectiveSize, headerTitleOverride: effectiveHeaderTitle, welcomeTitleOverride: effectiveWelcomeTitle, welcomeMessageOverride: effectiveWelcomeMessage, placeholderOverride: effectivePlaceholder, suggestedQuestionsOverride: suggestedQuestions }) }));
48024
48206
  }
48025
48207
  // Determine trigger class for container
48026
48208
  const triggerClass = effectiveTriggerType === 'pill-text'
48027
48209
  ? 'trigger-pill-text'
48028
48210
  : effectiveTriggerType === 'input-bar'
48029
48211
  ? 'trigger-input-bar'
48030
- : '';
48212
+ : 'trigger-button';
48031
48213
  // Size class for CSS targeting (used by input-bar trigger for width matching)
48032
48214
  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,
48215
+ // Collapsed class for input bar
48216
+ const collapsedClass = isInputBarCollapsed ? 'is-collapsed' : '';
48217
+ 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' : ''} ${mobileMode ? 'mobile-mode' : ''} ${desktopMode ? 'desktop-mode' : ''} ${triggerClass} ${sizeClass} ${collapsedClass}`, children: [isOpen && (jsxRuntimeExports.jsx(ChatWindow, { messages: messages, isLoading: isLoading, isTyping: isTyping, config: config, onSendMessage: handleSendMessage, onClose: handleToggle, onFeedback: handleFeedback, onActionClick: handleActionClick, onActionDismiss: dismissAction, onCallEndpoint: callActionEndpoint,
48034
48218
  // Chat history props (only active when persistConversation is true)
48035
- conversations: conversations, onLoadConversations: loadConversations, onSwitchConversation: switchConversation, onStartNewConversation: startNewConversation, onDeleteConversation: deleteConversation, currentConversationId: conversationId,
48036
- // Override props for live preview
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" })] }) })] })] }))] }) }));
48219
+ conversations: conversations, onLoadConversations: loadConversations, onSwitchConversation: switchConversation, onStartNewConversation: handleStartNewConversation, onDeleteConversation: deleteConversation, currentConversationId: conversationId, sizeOverride: effectiveSize, headerTitleOverride: effectiveHeaderTitle, welcomeTitleOverride: effectiveWelcomeTitle, welcomeMessageOverride: effectiveWelcomeMessage, placeholderOverride: effectivePlaceholder, suggestedQuestionsOverride: suggestedQuestions })), jsxRuntimeExports.jsx(WidgetTriggers, { triggerType: effectiveTriggerType, isOpen: isOpen, onToggle: handleToggle, triggerText: effectiveTriggerText, placeholder: effectivePlaceholder, IconComponent: IconComponent, showWelcomeBubble: showWelcomeBubble, welcomeBubbleText: effectiveWelcomeBubbleText, previewMode: previewMode, onDismissBubble: handleDismissBubble, isInputBarCollapsed: isInputBarCollapsed, setIsInputBarCollapsed: setIsInputBarCollapsed, inputBarValue: inputBarValue, setInputBarValue: setInputBarValue, onSubmitInputBar: handleInputBarSubmit, accentColor: accentColor, iconColor: iconContrastColor })] }) }));
48038
48220
  };
48039
48221
 
48040
48222
  /**