@chatwidgetai/chat-widget 0.3.1 → 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 (48) hide show
  1. package/dist/ai-chat-widget.umd.js +1890 -1018
  2. package/dist/ai-chat-widget.umd.js.map +1 -1
  3. package/dist/api/client.d.ts +21 -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 +5 -1
  13. package/dist/components/ChatWindow.d.ts.map +1 -1
  14. package/dist/components/DataPolicyView.d.ts.map +1 -1
  15. package/dist/components/WelcomeBubble.d.ts +12 -0
  16. package/dist/components/WelcomeBubble.d.ts.map +1 -0
  17. package/dist/components/icons.d.ts +21 -0
  18. package/dist/components/icons.d.ts.map +1 -0
  19. package/dist/components/triggers/ButtonTrigger.d.ts +11 -0
  20. package/dist/components/triggers/ButtonTrigger.d.ts.map +1 -0
  21. package/dist/components/triggers/InputBarTrigger.d.ts +18 -0
  22. package/dist/components/triggers/InputBarTrigger.d.ts.map +1 -0
  23. package/dist/components/triggers/PillTrigger.d.ts +12 -0
  24. package/dist/components/triggers/PillTrigger.d.ts.map +1 -0
  25. package/dist/components/triggers/index.d.ts +8 -0
  26. package/dist/components/triggers/index.d.ts.map +1 -0
  27. package/dist/hooks/useChat/action-handler.d.ts +17 -1
  28. package/dist/hooks/useChat/action-handler.d.ts.map +1 -1
  29. package/dist/hooks/useChat/action-lifecycle.d.ts.map +1 -1
  30. package/dist/hooks/useChat/index.d.ts +7 -0
  31. package/dist/hooks/useChat/index.d.ts.map +1 -1
  32. package/dist/hooks/useChat/message-hydration.d.ts.map +1 -1
  33. package/dist/hooks/useChat/stream-buffer.d.ts +18 -0
  34. package/dist/hooks/useChat/stream-buffer.d.ts.map +1 -0
  35. package/dist/hooks/useChat/stream-handlers.d.ts +3 -3
  36. package/dist/hooks/useChat/stream-handlers.d.ts.map +1 -1
  37. package/dist/hooks/useChat/stream-state.d.ts.map +1 -1
  38. package/dist/hooks/useChat/types.d.ts +2 -0
  39. package/dist/hooks/useChat/types.d.ts.map +1 -1
  40. package/dist/index.d.ts +2 -0
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.esm.js +1891 -1019
  43. package/dist/index.esm.js.map +1 -1
  44. package/dist/index.js +1891 -1018
  45. package/dist/index.js.map +1 -1
  46. package/dist/types/index.d.ts +12 -85
  47. package/dist/types/index.d.ts.map +1 -1
  48. package/package.json +1 -1
@@ -16898,31 +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,
16914
+ reason: "user",
16915
+ }),
16916
+ signal,
16917
+ });
16918
+ if (response.status === 204) {
16919
+ return;
16920
+ }
16921
+ if (!response.ok) {
16922
+ throw await buildApiError(response, 'Failed to dismiss action');
16923
+ }
16924
+ yield* parseSSEStream(response, (data) => {
16925
+ return typeof data === 'object' && data !== null && 'type' in data;
16926
+ });
16927
+ }
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) {
16933
+ const headers = {
16934
+ 'Content-Type': 'application/json',
16935
+ };
16936
+ if (this.config.currentRoute) {
16937
+ headers['X-Current-Route'] = this.config.currentRoute;
16938
+ }
16939
+ const response = await fetch(`${this.config.apiUrl}/api/widget/${this.config.widgetId}/agent/continue`, {
16940
+ method: 'POST',
16941
+ headers,
16942
+ body: JSON.stringify({
16943
+ conversationId,
16944
+ toolCallId,
16945
+ body,
16915
16946
  timeZone: this.getTimeZone(),
16916
16947
  }),
16917
16948
  signal,
16918
16949
  });
16919
16950
  if (!response.ok) {
16920
- throw await buildApiError(response, 'Failed to continue agent');
16951
+ throw await buildApiError(response, 'Failed to continue agent action');
16921
16952
  }
16922
16953
  yield* parseSSEStream(response, (data) => {
16923
16954
  return typeof data === 'object' && data !== null && 'type' in data;
16924
16955
  });
16925
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
+ }
16926
16978
  /**
16927
16979
  * Submit feedback for a message
16928
16980
  */
@@ -16953,7 +17005,8 @@
16953
17005
  }
16954
17006
  /**
16955
17007
  * Generate follow-up suggestions based on conversation context and available actions.
16956
- * 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.
16957
17010
  */
16958
17011
  async generateFollowUps(messages, actionIds) {
16959
17012
  try {
@@ -16985,6 +17038,27 @@
16985
17038
  return [];
16986
17039
  }
16987
17040
  }
17041
+ /**
17042
+ * Create a demo conversation with preset messages
17043
+ * Used when demo animation completes to persist the demo conversation to the database
17044
+ */
17045
+ async createDemoConversation(userMessage, assistantMessage) {
17046
+ const response = await fetch(`${this.config.apiUrl}/api/widget/${this.config.widgetId}/demo-conversation`, {
17047
+ method: 'POST',
17048
+ headers: {
17049
+ 'Content-Type': 'application/json',
17050
+ },
17051
+ body: JSON.stringify({
17052
+ userMessage,
17053
+ assistantMessage,
17054
+ timeZone: this.getTimeZone(),
17055
+ }),
17056
+ });
17057
+ if (!response.ok) {
17058
+ throw await buildApiError(response, 'Failed to create demo conversation');
17059
+ }
17060
+ return response.json();
17061
+ }
16988
17062
  /**
16989
17063
  * Validate widget access
16990
17064
  */
@@ -43796,7 +43870,7 @@
43796
43870
  }
43797
43871
 
43798
43872
  // Styles are provided by global messages.css - no component-specific CSS needed
43799
- function ChevronDownIcon() {
43873
+ function ChevronDownIcon$1() {
43800
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" }) }));
43801
43875
  }
43802
43876
  function ScrollButton({ onClick, visible, className = '' }) {
@@ -43805,24 +43879,35 @@
43805
43879
  visible && 'visible',
43806
43880
  className,
43807
43881
  ].filter(Boolean).join(' ');
43808
- 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, {}) }));
43809
43883
  }
43810
43884
 
43811
43885
  const formatToolName = (name) => {
43812
43886
  return name
43813
43887
  .replace(/^(action_|tool_)/, '')
43888
+ .replace(/-/g, '_')
43814
43889
  .split('_')
43815
43890
  .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
43816
43891
  .join(' ');
43817
43892
  };
43818
43893
  function ToolIndicator({ badges, className = '' }) {
43819
- 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 }) }) }) }));
43820
43905
  }
43821
43906
 
43822
43907
  // SVG Icon components
43823
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" }) }));
43824
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" }) }));
43825
- 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" }) }));
43826
43911
  const FeedbackButtons = ({ messageId, currentFeedback, onFeedback, }) => {
43827
43912
  const [isSubmitting, setIsSubmitting] = reactExports.useState(false);
43828
43913
  const [submitted, setSubmitted] = reactExports.useState(false);
@@ -43843,7 +43928,7 @@
43843
43928
  setIsSubmitting(false);
43844
43929
  }
43845
43930
  };
43846
- 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" })] }))] }));
43847
43932
  };
43848
43933
 
43849
43934
  const Message = ({ message, showTimestamp = true, enableFeedback = true, onFeedback, }) => {
@@ -43872,9 +43957,11 @@
43872
43957
  const hasContent = aiContent.trim().length > 0;
43873
43958
  if (!hasContent)
43874
43959
  return null;
43875
- 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: {
43876
43963
  table: ({ children, ...props }) => (jsxRuntimeExports.jsx("div", { className: "table-wrapper", children: jsxRuntimeExports.jsx("div", { className: "table-scroll", children: jsxRuntimeExports.jsx("table", { ...props, children: children }) }) })),
43877
- }, 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 }))] }))] }));
43878
43965
  }
43879
43966
  // System message rendering
43880
43967
  if (isSystem) {
@@ -43894,7 +43981,7 @@
43894
43981
  return false;
43895
43982
  const TERMINAL_STATUSES = [
43896
43983
  'completed', 'booked', 'scheduled', 'cancelled', 'failed', 'error',
43897
- 'displaying', 'clicked', 'contacted', 'submitted', 'sent'
43984
+ 'displaying', 'displayed', 'clicked', 'contacted', 'submitted', 'sent'
43898
43985
  ];
43899
43986
  const status = state.status;
43900
43987
  if (typeof status === 'string' && TERMINAL_STATUSES.includes(status)) {
@@ -43913,11 +44000,12 @@
43913
44000
  return false;
43914
44001
  if (message.isStreaming)
43915
44002
  return true;
43916
- const state = message.action.state;
43917
- return !isActionComplete(state);
44003
+ const input = message.action.input;
44004
+ return !isActionComplete(input);
43918
44005
  }
43919
- const ToolMessageGroup = ({ messages, getActionRenderer, showToolIndicator = true, accentColor, variant }) => {
43920
- const actionMessages = messages.filter(message => message.action);
44006
+ const ToolMessageGroup = ({ messages, getActionRenderer, showToolIndicator = true, accentColor, variant, onActionDismiss, onCallEndpoint, }) => {
44007
+ const visibleMessages = messages.filter(message => !message.action?.hidden);
44008
+ const actionMessages = visibleMessages.filter(message => message.action);
43921
44009
  // Debug logging
43922
44010
  console.log('[DEBUG ToolMessageGroup] ========================================');
43923
44011
  console.log('[DEBUG ToolMessageGroup] Total messages:', messages.length);
@@ -43939,14 +44027,14 @@
43939
44027
  implementation: impl,
43940
44028
  hasRenderer: !!renderer,
43941
44029
  rendererType: renderer ? typeof renderer : 'undefined',
43942
- state: msg.action?.state,
44030
+ input: msg.action?.input,
43943
44031
  });
43944
44032
  });
43945
44033
  // If tool indicator is hidden AND there are no action cards to render, don't render anything
43946
44034
  if (!showToolIndicator && actionMessages.length === 0) {
43947
44035
  return null;
43948
44036
  }
43949
- const badges = messages.map((message) => {
44037
+ const badges = visibleMessages.map((message) => {
43950
44038
  const toolName = message.toolExecuting || message.message.name || 'Tool';
43951
44039
  const hasError = message.isError || false;
43952
44040
  const loading = isActionLoading(message);
@@ -43966,7 +44054,7 @@
43966
44054
  console.log('[ToolMessageGroup] No renderer for:', message.action.implementation);
43967
44055
  return null;
43968
44056
  }
43969
- return (jsxRuntimeExports.jsx("div", { className: "ai-chat-tool-action", children: renderer(message, accentColor, variant) }, `action-${message.id}`));
44057
+ return (jsxRuntimeExports.jsx("div", { className: "ai-chat-tool-action", children: renderer(message, accentColor, variant, onActionDismiss, onCallEndpoint) }, `action-${message.id}`));
43970
44058
  })] }));
43971
44059
  };
43972
44060
 
@@ -44000,12 +44088,29 @@
44000
44088
  };
44001
44089
 
44002
44090
  const MAX_TEXT_LENGTH = 40;
44091
+ const STAGGER_DELAY_MS = 200; // Delay between each suggestion appearing
44003
44092
  const FollowUpSuggestions = ({ suggestions, onQuestionClick, onActionClick, accentColor, }) => {
44004
- if (!suggestions || suggestions.length === 0) {
44005
- return null;
44006
- }
44093
+ const [visibleIndices, setVisibleIndices] = reactExports.useState(new Set());
44007
44094
  // Filter out empty suggestions
44008
- 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
44009
44114
  if (validSuggestions.length === 0) {
44010
44115
  return null;
44011
44116
  }
@@ -44013,8 +44118,12 @@
44013
44118
  ? { "--primary-color": accentColor }
44014
44119
  : undefined;
44015
44120
  const trimText = (text) => text.length > MAX_TEXT_LENGTH ? `${text.slice(0, MAX_TEXT_LENGTH)}...` : text;
44016
- 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) => {
44017
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;
44018
44127
  const className = `ai-chat-follow-up-item ${isActionSuggestion ? 'action-type' : 'question-type'}`;
44019
44128
  const handleClick = () => {
44020
44129
  if (isActionSuggestion && onActionClick) {
@@ -44028,39 +44137,47 @@
44028
44137
  };
44029
44138
 
44030
44139
  const MessageList = (props) => {
44031
- const { messages, isTyping = false, showTypingIndicator = true, showTimestamps = true, showToolCalls = false, enableFeedback = true, welcomeTitle, welcomeMessage, suggestedQuestions, accentColor, onSuggestedQuestionClick, onActionClick, 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;
44032
44141
  const containerRef = reactExports.useRef(null);
44033
44142
  const messagesEndRef = reactExports.useRef(null);
44034
44143
  const [showScrollButton, setShowScrollButton] = reactExports.useState(false);
44035
44144
  const prevMessageCountRef = reactExports.useRef(0);
44145
+ const visibleMessages = reactExports.useMemo(() => messages.filter((message) => !message.action?.hidden), [messages]);
44036
44146
  const hasActiveAction = reactExports.useMemo(() => {
44037
44147
  // Find the last tool message and check if its action is still active (not done)
44038
- const lastToolMsg = [...messages].reverse().find(msg => msg.message.role === 'tool');
44148
+ const lastToolMsg = [...visibleMessages].reverse().find(msg => msg.message.role === 'tool');
44039
44149
  return lastToolMsg?.action && lastToolMsg.action.done !== true;
44040
- }, [messages]);
44041
- const checkScrollPosition = reactExports.useCallback(() => {
44042
- const c = containerRef.current;
44043
- if (!c)
44044
- return;
44045
- const pb = parseInt(getComputedStyle(c).paddingBottom || '0', 10);
44046
- setShowScrollButton(c.scrollHeight - c.scrollTop - c.clientHeight - pb > 24);
44047
- }, []);
44150
+ }, [visibleMessages]);
44048
44151
  const scrollToBottom = reactExports.useCallback(() => {
44049
44152
  messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
44050
44153
  }, []);
44051
- 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
44052
44156
  reactExports.useEffect(() => {
44053
- const c = containerRef.current;
44054
- if (!c)
44157
+ const endMarker = messagesEndRef.current;
44158
+ const container = containerRef.current;
44159
+ if (!endMarker || !container)
44055
44160
  return;
44056
- c.addEventListener('scroll', checkScrollPosition);
44057
- return () => c.removeEventListener('scroll', checkScrollPosition);
44058
- }, [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]);
44059
44176
  reactExports.useEffect(() => {
44060
44177
  const c = containerRef.current;
44061
44178
  if (!c)
44062
44179
  return;
44063
- const count = messages.length;
44180
+ const count = visibleMessages.length;
44064
44181
  const isNew = count > prevMessageCountRef.current;
44065
44182
  prevMessageCountRef.current = count;
44066
44183
  if (count === 0) {
@@ -44070,32 +44187,18 @@
44070
44187
  if ((isNew || isTyping) && c.scrollHeight - c.scrollTop - c.clientHeight < 150) {
44071
44188
  messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
44072
44189
  }
44073
- checkScrollPosition();
44074
- }, [messages, isTyping, checkScrollPosition]);
44190
+ }, [visibleMessages, isTyping]);
44075
44191
  const groupedMessages = reactExports.useMemo(() => {
44076
- console.log('[DEBUG MessageList] ========================================');
44077
- console.log('[DEBUG MessageList] Processing messages:', messages.length);
44078
- messages.forEach((m, i) => {
44079
- console.log(`[DEBUG MessageList] Message ${i}:`, {
44080
- id: m.id,
44081
- role: m.message.role,
44082
- hasAction: !!m.action,
44083
- actionImpl: m.action?.implementation,
44084
- content: (m.message.content || '').substring(0, 50),
44085
- });
44086
- });
44087
44192
  const result = [];
44088
44193
  let toolGroup = [];
44089
44194
  const flush = () => {
44090
44195
  if (toolGroup.length) {
44091
- console.log('[DEBUG MessageList] Flushing tool group with', toolGroup.length, 'messages');
44092
44196
  result.push({ type: 'tool-group', messages: [...toolGroup] });
44093
44197
  toolGroup = [];
44094
44198
  }
44095
44199
  };
44096
- for (const m of messages) {
44200
+ for (const m of visibleMessages) {
44097
44201
  if (m.message.role === 'tool') {
44098
- console.log('[DEBUG MessageList] Adding to tool group:', m.id);
44099
44202
  toolGroup.push(m);
44100
44203
  }
44101
44204
  else if (m.message.role === 'user') {
@@ -44117,27 +44220,26 @@
44117
44220
  }
44118
44221
  }
44119
44222
  flush();
44120
- console.log('[DEBUG MessageList] Final grouped result:', result.length, 'items');
44121
- result.forEach((item, i) => {
44122
- if (item.type === 'tool-group') {
44123
- console.log(`[DEBUG MessageList] Group ${i}: tool-group with ${item.messages.length} messages`);
44124
- }
44125
- else {
44126
- console.log(`[DEBUG MessageList] Group ${i}: message (${item.message.message.role})`);
44127
- }
44128
- });
44129
44223
  return result;
44130
- }, [messages]);
44131
- const hasSuggestions = messages.length === 0 && onSuggestedQuestionClick && suggestedQuestions?.length;
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]);
44235
+ const hasSuggestions = visibleMessages.length === 0 && onSuggestedQuestionClick && suggestedQuestions?.length;
44132
44236
  const showWelcome = welcomeTitle || welcomeMessage || hasSuggestions;
44133
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) => {
44134
44238
  if (item.type === 'tool-group') {
44135
- return jsxRuntimeExports.jsx(ToolMessageGroup, { messages: item.messages, getActionRenderer: getActionRenderer, showToolIndicator: showToolCalls, accentColor: accentColor, variant: variant }, `tg-${i}`);
44239
+ return (jsxRuntimeExports.jsx(ToolMessageGroup, { messages: item.messages, getActionRenderer: getActionRenderer, showToolIndicator: showToolCalls, accentColor: accentColor, variant: variant, onActionDismiss: onActionDismiss, onCallEndpoint: onCallEndpoint }, `tg-${i}`));
44136
44240
  }
44137
- const isLast = i === groupedMessages.length - 1;
44138
- const hasFollowUp = item.message.message.role === 'assistant' && item.message.suggestions?.length && isLast && !isTyping;
44139
- 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));
44140
- }), isTyping && showTypingIndicator && !hasActiveAction && messages.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 })] }));
44141
44243
  };
44142
44244
 
44143
44245
  const ALLOWED_EXTENSIONS = ['.pdf', '.doc', '.docx', '.txt', '.md', '.csv'];
@@ -44151,7 +44253,7 @@
44151
44253
  return (bytes / 1024).toFixed(1) + ' KB';
44152
44254
  return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
44153
44255
  };
44154
- 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, }) => {
44155
44257
  const [value, setValue] = reactExports.useState('');
44156
44258
  const [selectedFiles, setSelectedFiles] = reactExports.useState([]);
44157
44259
  const textareaRef = reactExports.useRef(null);
@@ -44186,481 +44288,15 @@
44186
44288
  }
44187
44289
  };
44188
44290
  const canSend = value.trim() || selectedFiles.length > 0;
44189
- 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: "KI-generierte Antworten k\u00F6nnen unzutreffend sein." }), onDataPolicyClick && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [' ', jsxRuntimeExports.jsx("button", { type: "button", className: "ai-chat-data-policy-link", onClick: onDataPolicyClick, children: "Datenschutzhinweis" })] }))] }))] }));
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" })] }))] }))] }));
44190
44292
  };
44191
44293
 
44192
- function groupSlotsByDate$1(slots) {
44193
- const grouped = new Map();
44194
- for (const slot of slots) {
44195
- if (!slot || typeof slot !== 'object' || !slot.startTime || typeof slot.startTime !== 'string') {
44196
- continue;
44197
- }
44198
- const date = slot.startTime.slice(0, 10);
44199
- if (!grouped.has(date)) {
44200
- grouped.set(date, []);
44201
- }
44202
- grouped.get(date).push(slot);
44203
- }
44204
- return grouped;
44205
- }
44206
- function formatDate$1(dateStr) {
44207
- try {
44208
- const date = new Date(dateStr);
44209
- return new Intl.DateTimeFormat("en-US", {
44210
- weekday: "short",
44211
- month: "short",
44212
- day: "numeric",
44213
- }).format(date);
44214
- }
44215
- catch {
44216
- return dateStr;
44217
- }
44218
- }
44219
- function CalendarIcon$1() {
44220
- 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" }) }));
44221
- }
44222
- function CheckIcon$1() {
44223
- 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" }) }));
44224
- }
44225
- function ExternalLinkIcon$2() {
44226
- 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" })] }));
44227
- }
44228
- function Skeleton$1({ width, height, borderRadius = '4px' }) {
44229
- return (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-skeleton-item", style: { width, height, borderRadius } }));
44230
- }
44231
- function GoogleCalendarCard({ action, onComplete, accentColor, className = '' }) {
44232
- const state = action.state;
44233
- const rawSlots = state.availableSlots;
44234
- const availableSlots = Array.isArray(rawSlots)
44235
- ? rawSlots.filter((slot) => slot !== null &&
44236
- slot !== undefined &&
44237
- typeof slot === "object" &&
44238
- "startTime" in slot &&
44239
- "endTime" in slot &&
44240
- typeof slot.startTime === "string" &&
44241
- typeof slot.endTime === "string")
44242
- : [];
44243
- const allowTopic = state.allowTopic !== false;
44244
- const isBooked = state.status === "booked";
44245
- const slotsByDate = groupSlotsByDate$1(availableSlots);
44246
- const dates = Array.from(slotsByDate.keys()).sort();
44247
- const [selectedDate, setSelectedDate] = reactExports.useState(dates[0] ?? "");
44248
- const [selectedSlot, setSelectedSlot] = reactExports.useState(null);
44249
- const [topic, setTopic] = reactExports.useState("");
44250
- const [error, setError] = reactExports.useState(null);
44251
- const slotsForSelectedDate = selectedDate ? slotsByDate.get(selectedDate) ?? [] : [];
44252
- const accentStyle = accentColor ? { '--action-accent': accentColor } : {};
44253
- const onConfirm = () => {
44254
- if (!selectedSlot) {
44255
- setError("Please select a time slot.");
44256
- return;
44257
- }
44258
- if (allowTopic && !topic.trim()) {
44259
- setError("Please enter a topic for the meeting.");
44260
- return;
44261
- }
44262
- setError(null);
44263
- onComplete?.(action.toolCallId, {
44264
- ...action.state,
44265
- selectedSlot: {
44266
- startTime: selectedSlot.startTime,
44267
- endTime: selectedSlot.endTime,
44268
- },
44269
- topic: allowTopic ? topic.trim() : null,
44270
- });
44271
- };
44272
- // Booked state
44273
- if (isBooked) {
44274
- const bookedSlot = state.selectedSlot;
44275
- const bookedTopic = state.topic;
44276
- const eventLink = state.bookedEventLink;
44277
- 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, {})] }))] })] }));
44278
- }
44279
- // Skeleton loading state - show when waiting for backend after user confirms
44280
- const isWaitingForBackend = !action.done && state.selectedSlot && !isBooked;
44281
- if (isWaitingForBackend) {
44282
- 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.jsxs("div", { className: "ai-chat-action-skeleton-box", children: [jsxRuntimeExports.jsx(Skeleton$1, { width: "50px", height: "12px", borderRadius: "4px" }), jsxRuntimeExports.jsx(Skeleton$1, { width: "200px", height: "18px", borderRadius: "4px" })] }), jsxRuntimeExports.jsx(Skeleton$1, { width: "100%", height: "44px", borderRadius: "999px" })] }) }));
44283
- }
44284
- // Booking form
44285
- return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-google-calendar ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx(CalendarIcon$1, {}), "Schedule an Appointment"] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [allowTopic && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntimeExports.jsx("label", { htmlFor: `topic-${action.toolCallId}`, className: "ai-chat-action-label", children: "Meeting Topic" }), jsxRuntimeExports.jsx("input", { id: `topic-${action.toolCallId}`, type: "text", className: "ai-chat-action-input", placeholder: "e.g., Product Demo", value: topic, onChange: (e) => setTopic(e.target.value) })] })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntimeExports.jsx("label", { className: "ai-chat-action-label", children: "Select Date" }), jsxRuntimeExports.jsx("div", { className: "ai-chat-action-date-grid", children: dates.slice(0, 7).map((date) => (jsxRuntimeExports.jsx("button", { type: "button", className: `ai-chat-action-date-btn ${selectedDate === date ? "active" : ""}`, onClick: () => {
44286
- setSelectedDate(date);
44287
- setSelectedSlot(null);
44288
- }, 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." }))] })] }));
44289
- }
44290
-
44291
- function groupSlotsByDate(slots) {
44292
- const grouped = new Map();
44293
- for (const slot of slots) {
44294
- if (!slot || typeof slot !== 'object' || !slot.startTime || typeof slot.startTime !== 'string') {
44295
- continue;
44296
- }
44297
- const date = slot.startTime.slice(0, 10);
44298
- if (!grouped.has(date)) {
44299
- grouped.set(date, []);
44300
- }
44301
- grouped.get(date).push(slot);
44302
- }
44303
- return grouped;
44304
- }
44305
- function formatDate(dateStr) {
44306
- try {
44307
- const date = new Date(dateStr);
44308
- return new Intl.DateTimeFormat("en-US", {
44309
- weekday: "short",
44310
- month: "short",
44311
- day: "numeric",
44312
- }).format(date);
44313
- }
44314
- catch {
44315
- return dateStr;
44316
- }
44317
- }
44318
- function CalendarIcon() {
44319
- 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" }) }));
44320
- }
44321
- function MailIcon() {
44322
- 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" })] }));
44323
- }
44324
- function CheckIcon() {
44325
- 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" }) }));
44326
- }
44327
- function ErrorIcon() {
44328
- 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" }) }));
44329
- }
44330
- function ExternalLinkIcon$1() {
44331
- 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" })] }));
44332
- }
44333
- function Skeleton({ width, height, borderRadius = '4px' }) {
44334
- return (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-skeleton-item", style: { width, height, borderRadius } }));
44335
- }
44336
- function PinInputGroup({ values, onChange, disabled }) {
44337
- const inputRefs = reactExports.useRef([]);
44338
- const handleChange = (index, value) => {
44339
- // Only allow digits
44340
- const digit = value.replace(/[^0-9]/g, '');
44341
- const newValues = [...values];
44342
- newValues[index] = digit.slice(-1);
44343
- onChange(newValues);
44344
- // Auto-focus next input
44345
- if (digit && index < 5) {
44346
- inputRefs.current[index + 1]?.focus();
44347
- }
44348
- };
44349
- const handleKeyDown = (index, e) => {
44350
- if (e.key === 'Backspace' && !values[index] && index > 0) {
44351
- inputRefs.current[index - 1]?.focus();
44352
- }
44353
- };
44354
- const handlePaste = (e) => {
44355
- e.preventDefault();
44356
- const pastedData = e.clipboardData.getData('text').replace(/[^0-9]/g, '').slice(0, 6);
44357
- const newValues = pastedData.split('').concat(Array(6 - pastedData.length).fill(''));
44358
- onChange(newValues);
44359
- // Focus the next empty input or the last one
44360
- const nextIndex = Math.min(pastedData.length, 5);
44361
- inputRefs.current[nextIndex]?.focus();
44362
- };
44363
- return (jsxRuntimeExports.jsx("div", { className: "ai-chat-pin-input-group", children: values.map((value, index) => (jsxRuntimeExports.jsx("input", { ref: (el) => {
44364
- inputRefs.current[index] = el;
44365
- }, 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))) }));
44366
- }
44367
- function MicrosoftCalendarCard({ action, onComplete, accentColor, className = '' }) {
44368
- const state = action.state;
44369
- const phase = state.phase || "awaiting_email";
44370
- const allowTopic = state.allowTopic !== false;
44371
- const accentStyle = accentColor ? { '--action-accent': accentColor } : {};
44372
- // Debug: Log state changes
44373
- const prevStateRef = reactExports.useRef(null);
44374
- reactExports.useEffect(() => {
44375
- if (JSON.stringify(prevStateRef.current) !== JSON.stringify(state)) {
44376
- console.log('[MicrosoftCalendarCard] State updated:', {
44377
- phase: state.phase,
44378
- hasError: !!state.errorMessage,
44379
- error: state.errorMessage,
44380
- slotsCount: state.availableSlots?.length || 0
44381
- });
44382
- prevStateRef.current = state;
44383
- }
44384
- }, [state]);
44385
- // Email phase state
44386
- const [email, setEmail] = reactExports.useState("");
44387
- const [emailError, setEmailError] = reactExports.useState(null);
44388
- // OTP phase state
44389
- const [otpValues, setOtpValues] = reactExports.useState(Array(6).fill(''));
44390
- const [otpError, setOtpError] = reactExports.useState(null);
44391
- // Loading states
44392
- const [isSubmitting, setIsSubmitting] = reactExports.useState(false);
44393
- // Reset loading state when phase changes (backend has responded)
44394
- // Use useEffect for reliable re-rendering
44395
- reactExports.useEffect(() => {
44396
- console.log('[MicrosoftCalendarCard] Phase changed to:', phase);
44397
- setIsSubmitting(false);
44398
- // Clear errors when transitioning to new phase
44399
- if (phase === "awaiting_email") {
44400
- setEmailError(null);
44401
- setOtpError(null);
44402
- setSelectionError(null);
44403
- }
44404
- else if (phase === "awaiting_otp") {
44405
- setOtpError(state.errorMessage || null);
44406
- setEmailError(null);
44407
- setSelectionError(null);
44408
- // Clear OTP input for fresh attempt
44409
- setOtpValues(Array(6).fill(''));
44410
- }
44411
- else if (phase === "awaiting_options") {
44412
- setEmailError(null);
44413
- setOtpError(null);
44414
- setSelectionError(null);
44415
- }
44416
- else if (phase === "awaiting_booking") {
44417
- setSelectionError(state.errorMessage || null);
44418
- setEmailError(null);
44419
- setOtpError(null);
44420
- }
44421
- else if (phase === "booked" || phase === "cancelled" || phase === "error") {
44422
- setEmailError(null);
44423
- setOtpError(null);
44424
- setSelectionError(null);
44425
- setSelectedId(null); // Reset selection
44426
- }
44427
- }, [phase, state.errorMessage]);
44428
- // Selection phase state
44429
- const rawSlots = state.availableSlots;
44430
- const availableSlots = Array.isArray(rawSlots)
44431
- ? rawSlots.filter((slot) => slot !== null &&
44432
- slot !== undefined &&
44433
- typeof slot === "object" &&
44434
- "startTime" in slot &&
44435
- "endTime" in slot &&
44436
- typeof slot.startTime === "string" &&
44437
- typeof slot.endTime === "string")
44438
- : [];
44439
- const slotsByDate = groupSlotsByDate(availableSlots);
44440
- const dates = Array.from(slotsByDate.keys()).sort();
44441
- const [selectedDate, setSelectedDate] = reactExports.useState(dates[0] ?? "");
44442
- const [selectedSlot, setSelectedSlot] = reactExports.useState(null);
44443
- const [topic, setTopic] = reactExports.useState("");
44444
- const [selectionError, setSelectionError] = reactExports.useState(null);
44445
- // Cancellation phase state
44446
- const [selectedId, setSelectedId] = reactExports.useState(null);
44447
- const slotsForSelectedDate = selectedDate ? slotsByDate.get(selectedDate) ?? [] : [];
44448
- // Phase 1: Email Input
44449
- const handleEmailSubmit = () => {
44450
- const trimmedEmail = email.trim();
44451
- if (!trimmedEmail) {
44452
- setEmailError("Please enter your email address");
44453
- return;
44454
- }
44455
- if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(trimmedEmail)) {
44456
- setEmailError("Please enter a valid email address");
44457
- return;
44458
- }
44459
- setEmailError(null);
44460
- setIsSubmitting(true);
44461
- console.log('[MicrosoftCalendarCard] Submitting email:', trimmedEmail);
44462
- setTimeout(() => {
44463
- onComplete?.(action.toolCallId, {
44464
- ...action.state,
44465
- email: trimmedEmail,
44466
- });
44467
- }, 50);
44468
- };
44469
- // Phase 2: OTP Verification
44470
- const handleOtpSubmit = () => {
44471
- const otpCode = otpValues.join('');
44472
- if (otpCode.length !== 6) {
44473
- setOtpError("Please enter the 6-digit code");
44474
- return;
44475
- }
44476
- setOtpError(null);
44477
- setIsSubmitting(true);
44478
- console.log('[MicrosoftCalendarCard] Submitting OTP code');
44479
- setTimeout(() => {
44480
- onComplete?.(action.toolCallId, {
44481
- ...action.state,
44482
- otpCode,
44483
- });
44484
- }, 50);
44485
- };
44486
- // Phase 3: Appointment Selection
44487
- const handleAppointmentConfirm = () => {
44488
- if (!selectedSlot) {
44489
- setSelectionError("Please select a time slot");
44490
- return;
44491
- }
44492
- if (allowTopic && !topic.trim()) {
44493
- setSelectionError("Please enter a meeting topic");
44494
- return;
44495
- }
44496
- setSelectionError(null);
44497
- setIsSubmitting(true);
44498
- console.log('[MicrosoftCalendarCard] Confirming appointment:', {
44499
- slot: selectedSlot,
44500
- topic: topic.trim()
44501
- });
44502
- setTimeout(() => {
44503
- onComplete?.(action.toolCallId, {
44504
- ...action.state,
44505
- selectedSlot: {
44506
- startTime: selectedSlot.startTime,
44507
- endTime: selectedSlot.endTime,
44508
- },
44509
- topic: allowTopic ? topic.trim() : null,
44510
- });
44511
- }, 50);
44512
- };
44513
- // Handle "Use different email" button
44514
- const handleUseDifferentEmail = () => {
44515
- setEmail("");
44516
- setEmailError(null);
44517
- setOtpValues(Array(6).fill(''));
44518
- setOtpError(null);
44519
- onComplete?.(action.toolCallId, {
44520
- phase: "awaiting_email",
44521
- email: null,
44522
- otpVerified: false,
44523
- otpAttempts: 0,
44524
- availableSlots: [],
44525
- selectedSlot: null,
44526
- topic: null,
44527
- bookedEventId: null,
44528
- bookedEventLink: null,
44529
- allowTopic,
44530
- errorMessage: null,
44531
- });
44532
- };
44533
- // Phase 5: Booked Confirmation
44534
- if (phase === "booked") {
44535
- const bookedSlot = state.selectedSlot;
44536
- const bookedTopic = state.topic;
44537
- const eventLink = state.bookedEventLink;
44538
- const bookedEmail = state.email;
44539
- 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, {})] }))] })] }));
44540
- }
44541
- // Phase 6: Cancelled Confirmation
44542
- if (phase === "cancelled") {
44543
- const cancelledSubject = state.cancelledEventSubject;
44544
- const userEmail = state.email;
44545
- 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] }))] })] }));
44546
- }
44547
- // Error State
44548
- if (phase === "error") {
44549
- 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: () => {
44550
- setEmail("");
44551
- setEmailError(null);
44552
- setOtpValues(Array(6).fill(''));
44553
- setOtpError(null);
44554
- onComplete?.(action.toolCallId, {
44555
- phase: "awaiting_email",
44556
- email: null,
44557
- otpVerified: false,
44558
- otpAttempts: 0,
44559
- availableSlots: [],
44560
- selectedSlot: null,
44561
- topic: null,
44562
- bookedEventId: null,
44563
- bookedEventLink: null,
44564
- allowTopic,
44565
- errorMessage: null,
44566
- });
44567
- }, children: "Start Over" })] })] }));
44568
- }
44569
- // Loading State
44570
- if (isSubmitting) {
44571
- return (jsxRuntimeExports.jsx("div", { className: `ai-chat-action-card ai-chat-action-skeleton ${className}`, style: accentStyle, children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-content", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-header", children: [jsxRuntimeExports.jsx(Skeleton, { width: "28px", height: "28px", borderRadius: "50%" }), jsxRuntimeExports.jsx(Skeleton, { width: "180px", height: "20px", borderRadius: "4px" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-box", children: [jsxRuntimeExports.jsx(Skeleton, { width: "60px", height: "12px", borderRadius: "4px" }), jsxRuntimeExports.jsx(Skeleton, { width: "120px", height: "18px", borderRadius: "4px" })] }), jsxRuntimeExports.jsx(Skeleton, { width: "100%", height: "44px", borderRadius: "999px" })] }) }));
44572
- }
44573
- // Phase 1: Email Input
44574
- if (phase === "awaiting_email") {
44575
- const displayError = state.errorMessage || emailError;
44576
- return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx(CalendarIcon, {}), "Schedule an Appointment"] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [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) => {
44577
- setEmail(e.target.value);
44578
- setEmailError(null);
44579
- }, onKeyPress: (e) => {
44580
- if (e.key === 'Enter') {
44581
- handleEmailSubmit();
44582
- }
44583
- }, 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" })] })] }));
44584
- }
44585
- // Phase 2: OTP Input
44586
- if (phase === "awaiting_otp") {
44587
- const displayError = state.errorMessage || otpError;
44588
- const userEmail = state.email;
44589
- return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx(MailIcon, {}), "Verify Your Email"] }), 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, { values: otpValues, onChange: (newValues) => {
44590
- setOtpValues(newValues);
44591
- setOtpError(null);
44592
- // Auto-submit when all 6 digits are entered
44593
- if (newValues.every(v => v.length === 1)) {
44594
- console.log('[MicrosoftCalendarCard] Auto-submitting OTP (all 6 digits entered)');
44595
- setIsSubmitting(true);
44596
- const code = newValues.join('');
44597
- setTimeout(() => {
44598
- onComplete?.(action.toolCallId, {
44599
- ...action.state,
44600
- otpCode: code,
44601
- });
44602
- }, 100);
44603
- }
44604
- }, 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" })] })] }));
44605
- }
44606
- // Phase 3: Options Menu (with inline cancel buttons and confirmation)
44607
- if (phase === "awaiting_options") {
44608
- const userAppointments = state.userAppointments || [];
44609
- const maxAppointments = state.maxAppointmentsPerUser || 3;
44610
- const appointmentCount = userAppointments.length;
44611
- const canBook = appointmentCount < maxAppointments;
44612
- const hasAppointments = appointmentCount > 0;
44613
- const displayError = state.errorMessage || selectionError;
44614
- // If confirming cancellation, show confirmation dialog
44615
- if (selectedId) {
44616
- const appointmentToCancel = userAppointments.find(appt => appt.id === selectedId);
44617
- if (!appointmentToCancel) {
44618
- setSelectedId(null); // Reset if appointment not found
44619
- }
44620
- else {
44621
- return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx(CalendarIcon, {}), "Confirm Cancellation"] }), 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: () => {
44622
- setIsSubmitting(true);
44623
- onComplete?.(action.toolCallId, {
44624
- ...action.state,
44625
- selectedOption: "cancel",
44626
- selectedAppointmentId: selectedId,
44627
- });
44628
- }, disabled: isSubmitting, children: isSubmitting ? 'Cancelling...' : 'Confirm Cancellation' }), jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button-secondary", type: "button", onClick: () => {
44629
- setSelectedId(null);
44630
- setSelectionError(null);
44631
- }, disabled: isSubmitting, children: "Go Back" })] })] })] }));
44632
- }
44633
- }
44634
- // Normal view with inline cancel buttons
44635
- return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx(CalendarIcon, {}), "Manage Your Appointments"] }), 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: () => {
44636
- setSelectedId(appt.id);
44637
- setSelectionError(null);
44638
- }, 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: () => {
44639
- setIsSubmitting(true);
44640
- onComplete?.(action.toolCallId, {
44641
- ...action.state,
44642
- selectedOption: "book",
44643
- });
44644
- }, disabled: isSubmitting, children: isSubmitting ? 'Loading...' : 'Book New Appointment' })), !canBook && !hasAppointments && (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-hint", children: "No appointments found." }))] })] }));
44645
- }
44646
- // Phase 4: Appointment Selection (Booking)
44647
- if (phase === "awaiting_booking") {
44648
- const displayError = state.errorMessage || selectionError;
44649
- return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx(CalendarIcon, {}), "Select Appointment Time"] }), 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: () => {
44650
- setSelectedDate(date);
44651
- setSelectedSlot(null);
44652
- }, 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." }))] })] }));
44653
- }
44654
- // Fallback
44655
- return null;
44656
- }
44657
-
44658
- function truncate(text, maxLength) {
44294
+ function truncate$1(text, maxLength) {
44659
44295
  if (text.length <= maxLength)
44660
44296
  return text;
44661
44297
  return text.slice(0, maxLength).trim() + '...';
44662
44298
  }
44663
- function ExternalLinkIcon() {
44299
+ function ExternalLinkIcon$2() {
44664
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" })] }));
44665
44301
  }
44666
44302
  function SingleLinkPreview({ link, onLinkClick, accentColor }) {
@@ -44679,10 +44315,10 @@
44679
44315
  e.currentTarget.parentElement.style.display = 'none';
44680
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) => {
44681
44317
  e.currentTarget.style.display = 'none';
44682
- } })), 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, {}) })] }));
44683
44319
  }
44684
44320
  function LinkPreviewCard({ action, onComplete, accentColor }) {
44685
- const rawState = action.state;
44321
+ const rawState = action.input;
44686
44322
  const hasCompletedRef = reactExports.useRef(false);
44687
44323
  // Provide safe defaults if state is missing
44688
44324
  const state = {
@@ -44712,11 +44348,12 @@
44712
44348
  if (state.links.length === 0) {
44713
44349
  return null;
44714
44350
  }
44715
- 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: {
44716
- display: 'grid',
44717
- gridTemplateColumns: state.links.length === 1 ? '1fr' : state.links.length === 2 ? 'repeat(2, 1fr)' : 'repeat(3, 1fr)',
44718
- gap: '12px',
44719
- }, 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))) })] }));
44720
44357
  }
44721
44358
 
44722
44359
  function PlayIcon() {
@@ -44737,7 +44374,7 @@
44737
44374
  }
44738
44375
  }
44739
44376
  function VideoPlayerCard({ action, onComplete, accentColor }) {
44740
- const rawState = action.state;
44377
+ const rawState = action.input;
44741
44378
  const hasCompletedRef = reactExports.useRef(false);
44742
44379
  const [isPlaying, setIsPlaying] = reactExports.useState(false);
44743
44380
  // Provide safe defaults if state is missing
@@ -44848,7 +44485,7 @@
44848
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"] }))] })] })] }));
44849
44486
  }
44850
44487
  function LocationCard({ action, onComplete, accentColor, maxColumns = 3 }) {
44851
- const rawState = action.state;
44488
+ const rawState = action.input;
44852
44489
  const hasCompletedRef = reactExports.useRef(false);
44853
44490
  const state = {
44854
44491
  locations: rawState?.locations || [],
@@ -44930,7 +44567,7 @@
44930
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"] }))] }))] })] }));
44931
44568
  }
44932
44569
  function ContactCard({ action, onComplete, accentColor, maxColumns = 3 }) {
44933
- const rawState = action.state;
44570
+ const rawState = action.input;
44934
44571
  const hasCompletedRef = reactExports.useRef(false);
44935
44572
  const state = {
44936
44573
  contacts: rawState?.contacts || [],
@@ -44965,11 +44602,37 @@
44965
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))) })] }));
44966
44603
  }
44967
44604
 
44968
- function FormCard({ action, onComplete, accentColor }) {
44969
- const state = action.state;
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
+
44625
+ function FormCard({ action, onComplete, onDismiss, accentColor }) {
44626
+ const state = action.input;
44970
44627
  const [currentStep, setCurrentStep] = reactExports.useState(0);
44971
44628
  const [answers, setAnswers] = reactExports.useState({});
44972
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
+ }
44973
44636
  const questions = state.questions || [];
44974
44637
  const currentQuestion = questions[currentStep];
44975
44638
  const totalQuestions = questions.length;
@@ -44990,6 +44653,7 @@
44990
44653
  if (!onComplete)
44991
44654
  return;
44992
44655
  setIsSubmitting(true);
44656
+ setLocalStatus('submitted');
44993
44657
  const formattedAnswers = Object.entries(answers).map(([questionId, value]) => ({
44994
44658
  questionId,
44995
44659
  value,
@@ -45003,6 +44667,7 @@
45003
44667
  const handleSkip = () => {
45004
44668
  if (!onComplete || !state.settings.allowSkip)
45005
44669
  return;
44670
+ setLocalStatus('skipped');
45006
44671
  onComplete(action.toolCallId, {
45007
44672
  ...state,
45008
44673
  status: 'skipped',
@@ -45030,23 +44695,29 @@
45030
44695
  return answer.trim() !== '';
45031
44696
  });
45032
44697
  };
44698
+ const handleDismiss = () => {
44699
+ onDismiss?.(action.toolCallId);
44700
+ };
44701
+ // Use local status if available (for immediate UI feedback), otherwise use state.status
44702
+ const effectiveStatus = localStatus || state.status;
45033
44703
  // Error state
45034
- if (state.status === 'error') {
45035
- 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' })] }));
45036
44706
  }
45037
44707
  // Submitted state
45038
- if (state.status === 'submitted' || action.done) {
45039
- 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!' })] }));
45040
44710
  }
45041
44711
  // Skipped state
45042
- if (state.status === 'skipped') {
45043
- 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" })] }));
45044
44714
  }
45045
44715
  // No questions
45046
44716
  if (totalQuestions === 0) {
45047
- 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." })] }));
45048
44718
  }
45049
- return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card", 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 })] }), 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: {
45050
44721
  width: `${((currentStep + 1) / totalQuestions) * 100}%`,
45051
44722
  backgroundColor: accentColor || 'var(--ai-chat-accent-color, #3b82f6)',
45052
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) => {
@@ -45072,104 +44743,915 @@
45072
44743
  }, children: isSubmitting ? 'Submitting...' : (state.settings.submitButtonText || 'Submit') }))] })] }));
45073
44744
  }
45074
44745
 
45075
- const pendingResolvers = new Map();
45076
- const resumeCallbacks = new Map();
45077
- const frontendActionHandlers = {};
45078
- const actionRenderers = {};
45079
- function getFrontendActionHandler(implementation) {
45080
- return frontendActionHandlers[implementation];
45081
- }
45082
- function getActionRenderer(implementation) {
45083
- return actionRenderers[implementation];
45084
- }
45085
- function waitForActionState(toolCallId) {
45086
- return new Promise((resolve) => {
45087
- pendingResolvers.set(toolCallId, resolve);
45088
- });
45089
- }
45090
- function resolveActionState(toolCallId, state) {
45091
- const resolver = pendingResolvers.get(toolCallId);
45092
- if (resolver) {
45093
- pendingResolvers.delete(toolCallId);
45094
- resolver(state);
45095
- return;
45096
- }
45097
- const resumeCallback = resumeCallbacks.get(toolCallId);
45098
- if (resumeCallback) {
45099
- resumeCallback(state).catch((error) => {
45100
- console.error("[Action] Failed to resume action:", error);
45101
- });
45102
- }
45103
- }
45104
- function registerActionResumeCallback(toolCallId, callback) {
45105
- resumeCallbacks.set(toolCallId, callback);
45106
- }
45107
- function unregisterActionResumeCallback(toolCallId) {
45108
- resumeCallbacks.delete(toolCallId);
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' })] })] }));
45109
44771
  }
45110
44772
 
45111
- function registerGoogleCalendarHandler() {
45112
- frontendActionHandlers["google-calendar-appointment"] = async (_input, _state, context) => {
45113
- return waitForActionState(context.toolCallId);
44773
+ function Skeleton({ width, height, borderRadius = '4px' }) {
44774
+ return (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-skeleton-item", style: { width, height, borderRadius } }));
44775
+ }
44776
+
44777
+ function PinInputGroup({ values, onChange, disabled }) {
44778
+ const inputRefs = reactExports.useRef([]);
44779
+ const handleChange = (index, value) => {
44780
+ // Only allow digits
44781
+ const digit = value.replace(/[^0-9]/g, '');
44782
+ const newValues = [...values];
44783
+ newValues[index] = digit.slice(-1);
44784
+ onChange(newValues);
44785
+ // Auto-focus next input
44786
+ if (digit && index < 5) {
44787
+ inputRefs.current[index + 1]?.focus();
44788
+ }
44789
+ };
44790
+ const handleKeyDown = (index, e) => {
44791
+ if (e.key === 'Backspace' && !values[index] && index > 0) {
44792
+ inputRefs.current[index - 1]?.focus();
44793
+ }
44794
+ };
44795
+ const handlePaste = (e) => {
44796
+ e.preventDefault();
44797
+ const pastedData = e.clipboardData.getData('text').replace(/[^0-9]/g, '').slice(0, 6);
44798
+ const newValues = pastedData.split('').concat(Array(6 - pastedData.length).fill(''));
44799
+ onChange(newValues);
44800
+ // Focus the next empty input or the last one
44801
+ const nextIndex = Math.min(pastedData.length, 5);
44802
+ inputRefs.current[nextIndex]?.focus();
44803
+ };
44804
+ return (jsxRuntimeExports.jsx("div", { className: "ai-chat-pin-input-group", children: values.map((value, index) => (jsxRuntimeExports.jsx("input", { ref: (el) => {
44805
+ inputRefs.current[index] = el;
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))) }));
44807
+ }
44808
+
44809
+ function OtpPhase({ accentColor, onDismiss, showCloseButton, email, onSubmit, onResend, isLoading, error, }) {
44810
+ const [otpValues, setOtpValues] = reactExports.useState(Array(6).fill(''));
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');
44817
+ return;
44818
+ }
44819
+ setLocalError(null);
44820
+ onSubmit(code);
44821
+ };
44822
+ const handleResend = async () => {
44823
+ setIsResending(true);
44824
+ setLocalError(null);
44825
+ try {
44826
+ await onResend();
44827
+ }
44828
+ finally {
44829
+ setIsResending(false);
44830
+ }
45114
44831
  };
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');
44894
+ return;
44895
+ }
44896
+ setLocalError(null);
44897
+ onConfirm(finalSubject);
44898
+ };
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' })] })] }));
44912
+ }
44913
+
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' }))] })] }));
44920
+ }
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 })] }))] })] })] }));
45115
44924
  }
45116
44925
 
45117
44926
  /**
45118
- * Register google-calendar-appointment action handler and renderer.
45119
- * Called by initializeActionHandlers to prevent tree-shaking.
44927
+ * Cancelled Phase Component (terminal state)
45120
44928
  */
45121
- function registerGoogleCalendarAction() {
45122
- // Register the handler
45123
- registerGoogleCalendarHandler();
45124
- // Register the renderer
45125
- actionRenderers["google-calendar-appointment"] = (message, accentColor) => {
45126
- const action = message.action;
45127
- if (!action)
45128
- return null;
45129
- const handleComplete = (toolCallId, newState) => {
45130
- resolveActionState(toolCallId, newState);
45131
- };
45132
- return (jsxRuntimeExports.jsx(GoogleCalendarCard, { action: {
45133
- implementation: action.implementation,
45134
- toolCallId: action.toolCallId,
45135
- actionId: action.actionId,
45136
- input: action.input,
45137
- state: action.state,
45138
- done: action.done ?? false,
45139
- }, onComplete: handleComplete, accentColor: accentColor }));
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." }) })] }));
44931
+ }
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" }))] })] }));
44935
+ }
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" })] }) }));
44939
+ }
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" })] }) }));
44943
+ }
44944
+
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,
45140
44960
  };
45141
44961
  }
45142
44962
 
45143
- function registerMicrosoftCalendarHandler() {
45144
- frontendActionHandlers["microsoft-calendar-appointment"] = async (_input, _state, context) => {
45145
- return waitForActionState(context.toolCallId);
44963
+ /**
44964
+ * Helper functions for accessing booking data
44965
+ */
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,
45146
44982
  };
45147
44983
  }
45148
44984
 
45149
44985
  /**
45150
- * Register microsoft-calendar-appointment action handler and renderer.
45151
- * Called by initializeActionHandlers to prevent tree-shaking.
44986
+ * OTP-related operations for email verification
45152
44987
  */
45153
- function registerMicrosoftCalendarAction() {
45154
- // Register the handler
45155
- registerMicrosoftCalendarHandler();
45156
- // Register the renderer
45157
- actionRenderers["microsoft-calendar-appointment"] = (message, accentColor) => {
45158
- const action = message.action;
45159
- if (!action)
45160
- return null;
45161
- const handleComplete = (toolCallId, newState) => {
45162
- resolveActionState(toolCallId, newState);
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
+ });
45140
+ }
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,
45190
+ };
45191
+ }
45192
+
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
+ }
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, {})] }))] }))] }));
45394
+ }
45395
+
45396
+ /**
45397
+ * URL validation utilities for images, cards, and links
45398
+ * Prevents 404 errors by validating URLs before display
45399
+ */
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 });
45163
45425
  };
45164
- return (jsxRuntimeExports.jsx(MicrosoftCalendarCard, { action: {
45165
- implementation: action.implementation,
45166
- toolCallId: action.toolCallId,
45167
- actionId: action.actionId,
45168
- input: action.input,
45169
- state: action.state,
45170
- done: action.done ?? false,
45171
- }, onComplete: handleComplete, accentColor: accentColor }));
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,
45172
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
+ }
45553
+ }
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);
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);
45173
45655
  }
45174
45656
 
45175
45657
  /**
@@ -45177,9 +45659,15 @@
45177
45659
  * Called by initializeActionHandlers to prevent tree-shaking.
45178
45660
  */
45179
45661
  function registerLinkPreviewAction() {
45180
- // Handler - auto-completes immediately since no user input is needed
45662
+ // Handler - auto-completes immediately, returns body for agent
45181
45663
  frontendActionHandlers["link-preview"] = async (_input, state, _context) => {
45182
- 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
+ };
45183
45671
  };
45184
45672
  // Renderer - displays the link preview card
45185
45673
  actionRenderers["link-preview"] = (message, accentColor) => {
@@ -45189,16 +45677,15 @@
45189
45677
  const handleComplete = (toolCallId, newState) => {
45190
45678
  resolveActionState(toolCallId, newState);
45191
45679
  };
45192
- // Check if action state indicates it's already complete (displaying or clicked)
45193
- const state = action.state;
45194
- const status = state?.status;
45195
- 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";
45196
45684
  return (jsxRuntimeExports.jsx(LinkPreviewCard, { action: {
45197
45685
  implementation: action.implementation,
45198
45686
  toolCallId: action.toolCallId,
45199
45687
  actionId: action.actionId,
45200
45688
  input: action.input,
45201
- state: action.state,
45202
45689
  done: isDone,
45203
45690
  }, onComplete: handleComplete, accentColor: accentColor }));
45204
45691
  };
@@ -45209,9 +45696,15 @@
45209
45696
  * Called by initializeActionHandlers to prevent tree-shaking.
45210
45697
  */
45211
45698
  function registerVideoPlayerAction() {
45212
- // Handler - auto-completes immediately since no user input is needed
45699
+ // Handler - auto-completes immediately, returns body for agent
45213
45700
  frontendActionHandlers["video-player"] = async (_input, state, _context) => {
45214
- 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
+ };
45215
45708
  };
45216
45709
  // Renderer - displays the embedded video player card
45217
45710
  actionRenderers["video-player"] = (message, accentColor) => {
@@ -45221,16 +45714,15 @@
45221
45714
  const handleComplete = (toolCallId, newState) => {
45222
45715
  resolveActionState(toolCallId, newState);
45223
45716
  };
45224
- // Check if action state indicates it's already complete (displaying or played)
45225
- const state = action.state;
45226
- const status = state?.status;
45227
- 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";
45228
45721
  return (jsxRuntimeExports.jsx(VideoPlayerCard, { action: {
45229
45722
  implementation: action.implementation,
45230
45723
  toolCallId: action.toolCallId,
45231
45724
  actionId: action.actionId,
45232
45725
  input: action.input,
45233
- state: action.state,
45234
45726
  done: isDone,
45235
45727
  }, onComplete: handleComplete, accentColor: accentColor }));
45236
45728
  };
@@ -45241,9 +45733,15 @@
45241
45733
  * Called by initializeActionHandlers to prevent tree-shaking.
45242
45734
  */
45243
45735
  function registerLocationCardAction() {
45244
- // Handler - auto-completes immediately since no user input is needed
45736
+ // Handler - auto-completes immediately, returns body for agent
45245
45737
  frontendActionHandlers["location-card"] = async (_input, state, _context) => {
45246
- 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
+ };
45247
45745
  };
45248
45746
  // Renderer - displays the location card
45249
45747
  actionRenderers["location-card"] = (message, accentColor, variant) => {
@@ -45253,25 +45751,30 @@
45253
45751
  const handleComplete = (toolCallId, newState) => {
45254
45752
  resolveActionState(toolCallId, newState);
45255
45753
  };
45256
- // Check if action state indicates it's already complete
45257
- const state = action.state;
45258
- const status = state?.status;
45259
- 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";
45260
45758
  return (jsxRuntimeExports.jsx(LocationCard, { action: {
45261
45759
  implementation: action.implementation,
45262
45760
  toolCallId: action.toolCallId,
45263
45761
  actionId: action.actionId,
45264
45762
  input: action.input,
45265
- state: action.state,
45266
45763
  done: isDone,
45267
45764
  }, onComplete: handleComplete, accentColor: accentColor, maxColumns: variant === 'fullpage' ? 3 : 1 }));
45268
45765
  };
45269
45766
  }
45270
45767
 
45271
45768
  function registerContactCardAction() {
45272
- // Handler - auto-completes immediately since no user input is needed
45769
+ // Handler - auto-completes immediately, returns body for agent
45273
45770
  frontendActionHandlers['contact-card'] = async (_input, state, _context) => {
45274
- 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
+ };
45275
45778
  };
45276
45779
  // Renderer - displays the contact card
45277
45780
  actionRenderers['contact-card'] = (message, accentColor, variant) => {
@@ -45281,16 +45784,15 @@
45281
45784
  const handleComplete = (toolCallId, newState) => {
45282
45785
  resolveActionState(toolCallId, newState);
45283
45786
  };
45284
- // Check if action state indicates it's already complete
45285
- const state = action.state;
45286
- const status = state?.status;
45287
- 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';
45288
45791
  return (jsxRuntimeExports.jsx(ContactCard, { action: {
45289
45792
  implementation: action.implementation,
45290
45793
  toolCallId: action.toolCallId,
45291
45794
  actionId: action.actionId,
45292
45795
  input: action.input,
45293
- state: action.state,
45294
45796
  done: isDone,
45295
45797
  }, onComplete: handleComplete, accentColor: accentColor, maxColumns: variant === 'fullpage' ? 3 : 1 }));
45296
45798
  };
@@ -45301,55 +45803,133 @@
45301
45803
  frontendActionHandlers['query-contact-directory'] = async (_input, state, _context) => {
45302
45804
  return { ...state, status: 'displaying' };
45303
45805
  };
45304
- // Renderer - displays the contact card with search results
45305
- actionRenderers['query-contact-directory'] = (message, accentColor, variant) => {
45806
+ // Renderer - displays the contact card with search results
45807
+ actionRenderers['query-contact-directory'] = (message, accentColor, variant) => {
45808
+ const action = message.action;
45809
+ if (!action)
45810
+ return null;
45811
+ // Handle completion - triggers agent to continue with text response
45812
+ const handleComplete = (toolCallId, newState) => {
45813
+ resolveActionState(toolCallId, newState);
45814
+ };
45815
+ // Check if action input indicates it's already complete
45816
+ const input = action.input;
45817
+ const status = input?.status;
45818
+ const isDone = action.done || status === 'displaying' || status === 'contacted';
45819
+ return (jsxRuntimeExports.jsx(ContactCard, { action: {
45820
+ implementation: action.implementation,
45821
+ toolCallId: action.toolCallId,
45822
+ actionId: action.actionId,
45823
+ input: action.input,
45824
+ done: isDone,
45825
+ }, onComplete: handleComplete, accentColor: accentColor, maxColumns: variant === 'fullpage' ? 3 : 1 }));
45826
+ };
45827
+ }
45828
+
45829
+ function registerDisplayFormAction() {
45830
+ // Handler - handles form submission and state updates
45831
+ frontendActionHandlers['display-form'] = async (_input, _state, context) => {
45832
+ return waitForActionState(context.toolCallId);
45833
+ };
45834
+ // Renderer - displays the form card
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) => {
45838
+ const action = message.action;
45839
+ if (!action)
45840
+ return null;
45841
+ const handleComplete = (toolCallId, newState) => {
45842
+ resolveActionState(toolCallId, newState);
45843
+ };
45844
+ const handleDismiss = onActionDismiss
45845
+ ? (toolCallId) => onActionDismiss(toolCallId)
45846
+ : undefined;
45847
+ return (jsxRuntimeExports.jsx(FormCard, { action: {
45848
+ implementation: action.implementation,
45849
+ toolCallId: action.toolCallId,
45850
+ actionId: action.actionId,
45851
+ input: action.input,
45852
+ done: action.done ?? false,
45853
+ }, onComplete: handleComplete, onDismiss: handleDismiss, accentColor: accentColor }));
45854
+ };
45855
+ }
45856
+
45857
+ /**
45858
+ * Book Contact Appointment Handler
45859
+ * Frontend action handler that waits for action completion
45860
+ */
45861
+ function registerBookContactAppointmentHandler() {
45862
+ frontendActionHandlers["book-contact-appointment"] = async (_input, _state, context) => {
45863
+ return waitForActionState(context.toolCallId);
45864
+ };
45865
+ }
45866
+
45867
+ /**
45868
+ * Register book-contact-appointment action handler and renderer.
45869
+ * Called by initializeActionHandlers to prevent tree-shaking.
45870
+ */
45871
+ function registerBookContactAppointmentAction() {
45872
+ // Register the handler
45873
+ registerBookContactAppointmentHandler();
45874
+ // Register the renderer
45875
+ actionRenderers['book-contact-appointment'] = (message, accentColor, _variant, _onActionDismiss, onCallEndpoint) => {
45306
45876
  const action = message.action;
45307
45877
  if (!action)
45308
45878
  return null;
45309
- // Handle completion - triggers agent to continue with text response
45310
45879
  const handleComplete = (toolCallId, newState) => {
45311
45880
  resolveActionState(toolCallId, newState);
45312
45881
  };
45313
- // Check if action state indicates it's already complete
45314
- const state = action.state;
45315
- const status = state?.status;
45316
- const isDone = action.done || status === 'displaying' || status === 'contacted';
45317
- return (jsxRuntimeExports.jsx(ContactCard, { action: {
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;
45893
+ return (jsxRuntimeExports.jsx(BookContactAppointmentCard, { action: {
45318
45894
  implementation: action.implementation,
45319
45895
  toolCallId: action.toolCallId,
45320
45896
  actionId: action.actionId,
45321
45897
  input: action.input,
45322
- state: action.state,
45323
- done: isDone,
45324
- }, onComplete: handleComplete, accentColor: accentColor, maxColumns: variant === 'fullpage' ? 3 : 1 }));
45898
+ done: action.done ?? false,
45899
+ }, onComplete: handleComplete, onDismiss: handleDismiss, onCallEndpoint: handleCallEndpoint, accentColor: accentColor }));
45325
45900
  };
45326
45901
  }
45327
45902
 
45328
- function registerDisplayFormAction() {
45329
- // Handler - handles form submission and state updates
45330
- frontendActionHandlers['display-form'] = async (_input, _state, context) => {
45331
- return waitForActionState(context.toolCallId);
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
+ };
45332
45913
  };
45333
- // Renderer - displays the form card
45334
- actionRenderers['display-form'] = (message, accentColor, variant) => {
45914
+ // Renderer - displays the image content
45915
+ actionRenderers['structured-image'] = (message, accentColor, variant, onActionDismiss) => {
45335
45916
  const action = message.action;
45336
45917
  if (!action)
45337
45918
  return null;
45338
45919
  const handleComplete = (toolCallId, newState) => {
45339
45920
  resolveActionState(toolCallId, newState);
45340
45921
  };
45341
- // Check if action state indicates it's already complete
45342
- const state = action.state;
45343
- const status = state?.status;
45344
- const isDone = action.done || status === 'completed' || status === 'submitted';
45345
- return (jsxRuntimeExports.jsx(FormCard, { action: {
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: {
45346
45927
  implementation: action.implementation,
45347
45928
  toolCallId: action.toolCallId,
45348
45929
  actionId: action.actionId,
45349
45930
  input: action.input,
45350
- state: action.state,
45351
45931
  done: isDone,
45352
- }, onComplete: handleComplete, accentColor: accentColor }));
45932
+ }, onComplete: handleComplete, onDismiss: onActionDismiss ? () => onActionDismiss(action.toolCallId) : undefined, accentColor: accentColor, maxColumns: variant === 'fullpage' ? 3 : 2 }));
45353
45933
  };
45354
45934
  }
45355
45935
 
@@ -45365,14 +45945,14 @@
45365
45945
  return;
45366
45946
  initialized = true;
45367
45947
  // Explicitly call each registration function to prevent tree-shaking
45368
- registerGoogleCalendarAction();
45369
- registerMicrosoftCalendarAction();
45370
45948
  registerLinkPreviewAction();
45371
45949
  registerVideoPlayerAction();
45372
45950
  registerLocationCardAction();
45373
45951
  registerQueryContactDirectoryAction();
45374
45952
  registerContactCardAction();
45375
45953
  registerDisplayFormAction();
45954
+ registerBookContactAppointmentAction();
45955
+ registerStructuredImageAction();
45376
45956
  }
45377
45957
 
45378
45958
  /**
@@ -45635,8 +46215,49 @@
45635
46215
  };
45636
46216
  });
45637
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
+ }
45638
46257
  function hydrateMessages(messages) {
45639
- return hydrateToolNames(messages);
46258
+ const visibleMessages = messages.filter((message) => !message.action?.hidden);
46259
+ const cleanedMessages = cleanupInterruptedMessages(visibleMessages);
46260
+ return hydrateToolNames(cleanedMessages);
45640
46261
  }
45641
46262
 
45642
46263
  function deriveErrorInfo(error) {
@@ -45706,6 +46327,75 @@
45706
46327
  return { message: 'Something went wrong. Please try again.' };
45707
46328
  }
45708
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
+
45709
46399
  function createStreamState() {
45710
46400
  return {
45711
46401
  currentContent: "",
@@ -45715,6 +46405,7 @@
45715
46405
  sources: [],
45716
46406
  toolCallToActionId: {},
45717
46407
  requestId: generateMessageId(),
46408
+ buffer: createStreamBuffer(),
45718
46409
  };
45719
46410
  }
45720
46411
  function upsertMessage(setState, message, isTyping) {
@@ -45777,6 +46468,8 @@
45777
46468
  },
45778
46469
  isStreaming: false,
45779
46470
  toolExecuting: existingName,
46471
+ // Mark action as done when tool message is finalized
46472
+ action: entry.action ? { ...entry.action, done: true } : undefined,
45780
46473
  };
45781
46474
  });
45782
46475
  return { ...prev, messages, isTyping: false, isLoading: false };
@@ -45785,26 +46478,34 @@
45785
46478
  }
45786
46479
 
45787
46480
  function handleContentEvent(event, streamState, onMessageUpdate, setState) {
46481
+ // Track full content for finalization
45788
46482
  streamState.currentContent += event.content;
45789
- const assistantMessage = {
45790
- id: streamState.currentMessageId,
45791
- message: { role: "assistant", content: streamState.currentContent },
45792
- timestamp: new Date().toISOString(),
45793
- sources: streamState.sources,
45794
- isStreaming: true,
45795
- };
45796
- streamState.newMessageIds.add(assistantMessage.id);
45797
- onMessageUpdate(assistantMessage);
45798
- const hasContent = assistantMessage.message.content?.trim().length || 0 > 0;
45799
- const isToolExecuting = streamState.activeToolCallCount > 0;
45800
- const isTyping = (!hasContent && assistantMessage.isStreaming) || isToolExecuting;
45801
- 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
+ });
45802
46501
  }
45803
46502
  function handleToolStartEvent(event, streamState, onMessageUpdate, setState) {
45804
- if (streamState.currentContent.trim()) {
46503
+ // Flush buffer before tool starts
46504
+ const flushedContent = flushBuffer(streamState.buffer);
46505
+ if (flushedContent.trim()) {
45805
46506
  const finalAssistant = {
45806
46507
  id: streamState.currentMessageId,
45807
- message: { role: "assistant", content: streamState.currentContent },
46508
+ message: { role: "assistant", content: flushedContent },
45808
46509
  timestamp: new Date().toISOString(),
45809
46510
  sources: streamState.sources,
45810
46511
  isStreaming: false,
@@ -45815,6 +46516,8 @@
45815
46516
  streamState.currentContent = "";
45816
46517
  streamState.currentMessageId = generateMessageId();
45817
46518
  }
46519
+ // Reset buffer for post-tool content
46520
+ resetBuffer(streamState.buffer);
45818
46521
  const toolMessageId = event.tool_call_id;
45819
46522
  streamState.activeToolCallCount += 1;
45820
46523
  streamState.newMessageIds.add(toolMessageId);
@@ -45832,43 +46535,22 @@
45832
46535
  streamState.activeToolCallCount = Math.max(0, streamState.activeToolCallCount - 1);
45833
46536
  setState(prev => {
45834
46537
  const messages = prev.messages.map((msg) => {
45835
- const matchesToolCall = msg.message.role === "tool" && msg.message.tool_call_id === event.tool_call_id;
45836
- if (!matchesToolCall) {
46538
+ if (msg.message.role !== "tool" || msg.message.tool_call_id !== event.tool_call_id) {
45837
46539
  return msg;
45838
46540
  }
45839
- const existingName = msg.message.name || event.tool_name;
45840
- let action = msg.action;
45841
- if (event.action_id && event.implementation) {
45842
- action = {
45843
- implementation: event.implementation,
45844
- toolCallId: event.tool_call_id,
45845
- actionId: event.action_id,
45846
- input: (event.input || {}),
45847
- state: (event.state || {}),
45848
- done: event.done,
45849
- };
45850
- }
45851
- else if (action) {
45852
- action = {
45853
- ...action,
45854
- input: event.input ? event.input : action.input,
45855
- state: event.state ? event.state : action.state,
45856
- done: event.done,
45857
- };
45858
- }
45859
- 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 {
45860
46548
  ...msg,
45861
- message: {
45862
- role: "tool",
45863
- content: event.state ? JSON.stringify(event.state) : (typeof msg.message.content === "string" ? msg.message.content : ""),
45864
- tool_call_id: event.tool_call_id,
45865
- name: existingName,
45866
- },
46549
+ message: { ...msg.message, name: toolName },
45867
46550
  isStreaming: false,
45868
- toolExecuting: existingName,
46551
+ toolExecuting: toolName,
45869
46552
  action,
45870
46553
  };
45871
- return updatedMsg;
45872
46554
  });
45873
46555
  return { ...prev, messages, isTyping: true, isLoading: false };
45874
46556
  });
@@ -45901,11 +46583,6 @@
45901
46583
  return { ...prev, messages, isTyping: true, isLoading: false };
45902
46584
  });
45903
46585
  }
45904
- function handleDoneEvent(event, streamState, _onMessageUpdate, setState) {
45905
- streamState.sources = event.sources;
45906
- streamState.toolCallToActionId = event.tool_call_to_action_id;
45907
- finalizeStreamMessages(setState, streamState.newMessageIds, event.sources, event.tool_call_to_action_id, event.suggestions);
45908
- }
45909
46586
  function handleHaltEvent(event, _streamState, onMessageUpdate, setState) {
45910
46587
  const toolNames = event.tool_calls.map(call => call.name).join(", ");
45911
46588
  const notice = toolNames
@@ -45920,7 +46597,8 @@
45920
46597
  };
45921
46598
  onMessageUpdate(haltMessage);
45922
46599
  upsertMessage(setState, haltMessage, false);
45923
- 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." }));
45924
46602
  }
45925
46603
  function handleErrorEvent(_event, _streamState, onMessageUpdate, setState) {
45926
46604
  const errorMessage = {
@@ -45932,6 +46610,8 @@
45932
46610
  };
45933
46611
  onMessageUpdate(errorMessage);
45934
46612
  upsertMessage(setState, errorMessage, false);
46613
+ // Stop loading/typing state on error
46614
+ setState(prev => ({ ...prev, isLoading: false, isTyping: false }));
45935
46615
  }
45936
46616
  const eventHandlers = {
45937
46617
  content: handleContentEvent,
@@ -45959,7 +46639,37 @@
45959
46639
  console.warn('[Chat] Unknown event type:', event.type);
45960
46640
  }
45961
46641
  }
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);
46661
+ }
45962
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
+ */
45963
46673
  async function handleActionLoop(client, initialEvent, streamState, onMessageUpdate, setState, widgetId, conversationId, getMessages) {
45964
46674
  let pendingEvent = initialEvent;
45965
46675
  while (pendingEvent) {
@@ -45985,7 +46695,6 @@
45985
46695
  toolCallId: pendingEvent.tool_call_id,
45986
46696
  actionId: pendingEvent.action_id,
45987
46697
  input: pendingEvent.input,
45988
- state: pendingEvent.state,
45989
46698
  done: pendingEvent.done ?? false,
45990
46699
  },
45991
46700
  };
@@ -46010,9 +46719,13 @@
46010
46719
  upsertMessage(setState, errorMessage, false);
46011
46720
  return;
46012
46721
  }
46013
- 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;
46014
46726
  try {
46015
- 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
+ {
46016
46729
  widgetId,
46017
46730
  conversationId,
46018
46731
  toolCallId: pendingEvent.tool_call_id,
@@ -46034,19 +46747,16 @@
46034
46747
  return;
46035
46748
  }
46036
46749
  pendingEvent = null;
46037
- const updatedToolMessage = {
46038
- ...toolMessage,
46039
- action: toolMessage.action ? { ...toolMessage.action, state: nextState } : toolMessage.action,
46040
- };
46041
- upsertMessage(setState, updatedToolMessage, true);
46750
+ // Send body to backend and continue agent
46751
+ // No need to update message - input is immutable and already contains display data
46042
46752
  let streamEnded = false;
46043
- for await (const event of client.continueAgentMessageStream(conversationId, resumeToolCallId, nextState)) {
46753
+ for await (const event of client.continueAgentAction(conversationId, resumeToolCallId, body)) {
46044
46754
  if (event.type === "action_request") {
46755
+ // Chained action - continue the loop
46045
46756
  pendingEvent = event;
46046
46757
  break;
46047
46758
  }
46048
46759
  if (event.type === "done") {
46049
- // Finalize tool message and stream messages
46050
46760
  finalizeToolMessage(streamState, setState, resumeToolCallId, toolName);
46051
46761
  streamState.sources = event.sources;
46052
46762
  streamState.toolCallToActionId = event.tool_call_to_action_id;
@@ -46076,57 +46786,118 @@
46076
46786
  }
46077
46787
  }
46078
46788
  }
46079
- 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) {
46080
46796
  // Find all incomplete actions and register resume callbacks
46081
46797
  for (const message of messages) {
46082
- if (message.action && !message.action.done) {
46083
- const toolCallId = message.action.toolCallId;
46084
- const toolName = message.message.name || message.toolExecuting || "tool";
46085
- registerCallback(toolCallId, async (newState) => {
46086
- // When user interacts with the action after reload, continue the stream
46798
+ if (message.action && !message.action.done && !message.action.hidden) {
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
46087
46803
  try {
46088
- // Update the action message with the new state and check completion
46089
46804
  setState(prev => ({
46090
46805
  ...prev,
46091
- messages: prev.messages.map(m => {
46092
- if (m.action?.toolCallId !== toolCallId) {
46093
- return m;
46094
- }
46095
- if (!m.action) {
46096
- return m;
46097
- }
46098
- return { ...m, action: { ...m.action, state: newState } };
46099
- }),
46100
46806
  isTyping: true,
46101
46807
  }));
46102
46808
  const streamState = createStreamState();
46103
- // Continue the agent stream with the new state
46104
- for await (const event of client.continueAgentMessageStream(conversationId, toolCallId, newState)) {
46105
- if (event.type === "done") {
46106
- finalizeToolMessage(streamState, setState, toolCallId, toolName);
46107
- streamState.sources = event.sources;
46108
- streamState.toolCallToActionId = event.tool_call_to_action_id;
46109
- finalizeStreamMessages(setState, streamState.newMessageIds, event.sources, event.tool_call_to_action_id, event.suggestions);
46110
- 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;
46111
46851
  }
46112
- if (event.type === "error") {
46113
- const errorMessage = {
46114
- id: generateMessageId(),
46115
- message: {
46116
- role: "assistant",
46117
- content: "Sorry, an error occurred. Please try again later.",
46118
- },
46119
- timestamp: new Date().toISOString(),
46120
- sources: [],
46121
- isError: true,
46122
- };
46123
- upsertMessage(setState, errorMessage, false);
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
+ });
46891
+ }
46892
+ catch (handlerError) {
46893
+ console.error("[Action Resume] Handler failed:", handlerError);
46124
46894
  setState(prev => ({ ...prev, isTyping: false }));
46125
46895
  return;
46126
46896
  }
46127
- handleStreamEvent(event, streamState, onMessageUpdate, setState);
46897
+ // Continue loop with new body
46898
+ currentToolCallId = nextActionRequest.tool_call_id;
46899
+ currentBody = handlerResult;
46128
46900
  }
46129
- setState(prev => ({ ...prev, isTyping: false }));
46130
46901
  }
46131
46902
  catch (error) {
46132
46903
  console.error("[Action Resume] Failed to continue stream:", error);
@@ -46205,7 +46976,7 @@
46205
46976
  }));
46206
46977
  // Setup resume callbacks for incomplete actions
46207
46978
  if (conversationId) {
46208
- setupActionResumeCallbacks(hydratedMessages, apiClient.current, conversationId, setState, onMessage ?? (() => { }), createStreamState, registerActionResumeCallback);
46979
+ setupActionResumeCallbacks(hydratedMessages, apiClient.current, conversationId, widgetId, setState, onMessage ?? (() => { }), createStreamState, registerActionResumeCallback);
46209
46980
  }
46210
46981
  }
46211
46982
  catch (error) {
@@ -46228,7 +46999,7 @@
46228
46999
  }
46229
47000
  });
46230
47001
  };
46231
- }, [widgetId, apiUrl, onError]);
47002
+ }, [widgetId, apiUrl, onError, skipInitialization]);
46232
47003
  // Save conversation when messages change
46233
47004
  reactExports.useEffect(() => {
46234
47005
  const persistConversation = state.config?.settings.persistConversation ?? true;
@@ -46239,6 +47010,21 @@
46239
47010
  saveConversation(widgetId, state.conversationId, state.messages);
46240
47011
  }
46241
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]);
46242
47028
  const sendMessage = reactExports.useCallback(async (content, files) => {
46243
47029
  const trimmedContent = content.trim();
46244
47030
  const hasFiles = !!files && files.length > 0;
@@ -46322,12 +47108,14 @@
46322
47108
  stateRef.current.conversationId !== streamConversationId ||
46323
47109
  currentRequestIdRef.current !== streamRequestId) {
46324
47110
  console.log('[Widget] Stream aborted, conversation changed, or superseded by new request');
47111
+ cancelBuffer(streamState.buffer);
46325
47112
  break;
46326
47113
  }
46327
47114
  if (event.type === "action_request") {
46328
47115
  if (currentAbortController?.signal.aborted ||
46329
47116
  stateRef.current.conversationId !== streamConversationId ||
46330
47117
  currentRequestIdRef.current !== streamRequestId) {
47118
+ cancelBuffer(streamState.buffer);
46331
47119
  break;
46332
47120
  }
46333
47121
  await handleActionLoop(apiClient.current, event, streamState, (message) => {
@@ -46353,26 +47141,8 @@
46353
47141
  if (lastStreamedMessage) {
46354
47142
  onMessage?.(lastStreamedMessage);
46355
47143
  }
46356
- const enableFollowUps = state.config?.settings.enableFollowUpSuggestions !== false;
46357
- const actionIds = state.config?.actions || [];
46358
- if (enableFollowUps) {
46359
- apiClient.current.generateFollowUps(stateRef.current.messages, actionIds)
46360
- .then(suggestions => {
46361
- if (suggestions.length > 0) {
46362
- setState(prev => {
46363
- const messages = [...prev.messages];
46364
- for (let i = messages.length - 1; i >= 0; i--) {
46365
- if (messages[i].message.role === 'assistant' && !messages[i].isError) {
46366
- messages[i] = { ...messages[i], suggestions };
46367
- break;
46368
- }
46369
- }
46370
- return { ...prev, messages };
46371
- });
46372
- }
46373
- })
46374
- .catch(err => console.warn('[Widget] Follow-up generation failed:', err));
46375
- }
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()
46376
47146
  }
46377
47147
  catch (error) {
46378
47148
  console.error("[Widget] sendMessage error:", error);
@@ -46434,6 +47204,51 @@
46434
47204
  onError?.(err);
46435
47205
  }
46436
47206
  }, [state.conversationId, onError]);
47207
+ const dismissAction = reactExports.useCallback(async (toolCallId) => {
47208
+ if (!toolCallId)
47209
+ return;
47210
+ const dismissedAt = new Date().toISOString();
47211
+ setState(prev => ({
47212
+ ...prev,
47213
+ messages: prev.messages.map((message) => {
47214
+ if (message.action?.toolCallId !== toolCallId) {
47215
+ return message;
47216
+ }
47217
+ if (!message.action) {
47218
+ return message;
47219
+ }
47220
+ return {
47221
+ ...message,
47222
+ action: {
47223
+ ...message.action,
47224
+ hidden: true,
47225
+ dismissedAt,
47226
+ dismissedBy: "user",
47227
+ done: true,
47228
+ },
47229
+ };
47230
+ }),
47231
+ isTyping: true,
47232
+ isLoading: false,
47233
+ }));
47234
+ unregisterActionResumeCallback(toolCallId);
47235
+ const conversationId = stateRef.current.conversationId;
47236
+ if (!conversationId) {
47237
+ setState(prev => ({ ...prev, isTyping: false }));
47238
+ return;
47239
+ }
47240
+ try {
47241
+ const streamState = createStreamState();
47242
+ for await (const event of apiClient.current.dismissAgentMessageStream(conversationId, toolCallId)) {
47243
+ handleStreamEvent(event, streamState, onMessage ?? (() => { }), setState);
47244
+ }
47245
+ setState(prev => ({ ...prev, isTyping: false, isLoading: false }));
47246
+ }
47247
+ catch (error) {
47248
+ console.error("[Widget] dismissAction error:", error);
47249
+ setState(prev => ({ ...prev, isTyping: false, isLoading: false }));
47250
+ }
47251
+ }, [onMessage]);
46437
47252
  const loadConversations = reactExports.useCallback(() => {
46438
47253
  const persistConversation = state.config?.settings.persistConversation ?? true;
46439
47254
  if (!persistConversation || !isStorageAvailable()) {
@@ -46484,7 +47299,7 @@
46484
47299
  messages: hydratedMessages,
46485
47300
  isLoading: false,
46486
47301
  }));
46487
- setupActionResumeCallbacks(hydratedMessages, apiClient.current, conversation.id, setState, onMessage ?? (() => { }), createStreamState, registerActionResumeCallback);
47302
+ setupActionResumeCallbacks(hydratedMessages, apiClient.current, conversation.id, widgetId, setState, onMessage ?? (() => { }), createStreamState, registerActionResumeCallback);
46488
47303
  if (persistConversation && isStorageAvailable()) {
46489
47304
  saveConversation(widgetId, conversation.id, hydratedMessages);
46490
47305
  }
@@ -46534,6 +47349,53 @@
46534
47349
  }));
46535
47350
  }
46536
47351
  }, [widgetId, state.config?.settings.persistConversation, state.conversationId]);
47352
+ const createDemoConversation = reactExports.useCallback(async (userMessage, assistantMessage) => {
47353
+ try {
47354
+ const result = await apiClient.current.createDemoConversation(userMessage, assistantMessage);
47355
+ if (result.success && result.id) {
47356
+ // Update state with the new conversation ID
47357
+ setState(prev => ({
47358
+ ...prev,
47359
+ conversationId: result.id,
47360
+ }));
47361
+ // Save to local storage if persistence is enabled
47362
+ const persistConversation = state.config?.settings.persistConversation ?? true;
47363
+ if (persistConversation && isStorageAvailable()) {
47364
+ const demoMessages = [
47365
+ {
47366
+ id: generateMessageId(),
47367
+ message: { role: 'user', content: userMessage },
47368
+ timestamp: new Date().toISOString(),
47369
+ sources: [],
47370
+ },
47371
+ {
47372
+ id: generateMessageId(),
47373
+ message: { role: 'assistant', content: assistantMessage },
47374
+ timestamp: new Date(Date.now() + 1000).toISOString(),
47375
+ sources: [],
47376
+ },
47377
+ ];
47378
+ saveConversation(widgetId, result.id, demoMessages);
47379
+ }
47380
+ return result.id;
47381
+ }
47382
+ return null;
47383
+ }
47384
+ catch (error) {
47385
+ console.error('[useChat] Failed to create demo conversation:', error);
47386
+ return null;
47387
+ }
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]);
46537
47399
  return {
46538
47400
  messages: state.messages,
46539
47401
  isLoading: state.isLoading,
@@ -46544,20 +47406,22 @@
46544
47406
  sendMessage,
46545
47407
  clearMessages,
46546
47408
  submitFeedback,
47409
+ dismissAction,
46547
47410
  conversations,
46548
47411
  loadConversations,
46549
47412
  switchConversation,
46550
47413
  startNewConversation,
46551
47414
  deleteConversation: deleteConversation$1,
47415
+ createDemoConversation,
47416
+ callActionEndpoint,
46552
47417
  };
46553
47418
  }
46554
47419
 
46555
- const ShieldIcon = () => (jsxRuntimeExports.jsxs("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" }), jsxRuntimeExports.jsx("path", { d: "M9 12l2 2 4-4" })] }));
46556
47420
  const DataPolicyView = ({ config, widgetName, }) => {
46557
47421
  const headerTitle = widgetName || config?.appearance?.headerTitle || 'AI Assistant';
46558
47422
  const hasFileUpload = config?.settings?.enableFileUpload ?? false;
46559
47423
  const persistsConversation = config?.settings?.persistConversation ?? true;
46560
- return (jsxRuntimeExports.jsx("div", { className: "ai-chat-data-policy-view", children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-content", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-intro", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-data-policy-icon", children: jsxRuntimeExports.jsx(ShieldIcon, {}) }), jsxRuntimeExports.jsxs("p", { children: ["Dieser Datenschutzhinweis informiert dich gem\u00E4\u00DF Art. 13 DSGVO dar\u00FCber, wie ", jsxRuntimeExports.jsx("strong", { children: headerTitle }), " Daten verarbeitet, wenn du diesen Chat nutzt. Bitte beachte, dass der konkrete Umfang der Verarbeitung vom Betreiber dieser Website/Anwendung (dem Verantwortlichen) sowie von den jeweils aktivierten Funktionen abh\u00E4ngt."] })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntimeExports.jsx("h3", { children: "Verantwortlicher / Kontakt" }), jsxRuntimeExports.jsx("p", { children: "Verantwortlicher im Sinne von Art. 4 Nr. 7 DSGVO ist der Betreiber dieser Website/Anwendung. Die Kontaktdaten (und ggf. die Kontaktdaten eines Datenschutzbeauftragten) findest du in der Datenschutzerkl\u00E4rung bzw. im Impressum der Website, in die dieses Chat-Widget eingebunden ist." })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntimeExports.jsx("h3", { children: "Verarbeitete Daten (Kategorien)" }), jsxRuntimeExports.jsxs("ul", { children: [jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Chat-Inhalte:" }), " Nachrichten (Text) sowie ggf. Kontextinformationen, die du im Chat angibst. Diese Inhalte werden verarbeitet, um Antworten zu generieren und die Unterhaltung bereitzustellen."] }), hasFileUpload && (jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Hochgeladene Dateien:" }), " Dateien, die du an den Chat \u00FCbermittelst, werden zur Bearbeitung des Anliegens verarbeitet. Die Verarbeitung kann das Extrahieren von Text/Informationen umfassen."] })), jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Technische Nutzungsdaten:" }), " z.B. Zeitstempel, Sitzungs-/Request-Informationen sowie technische Metadaten, die f\u00FCr den Betrieb, die Sicherheit (Missbrauchspr\u00E4vention) und Fehleranalyse erforderlich sind."] })] })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntimeExports.jsx("h3", { children: "Zwecke und Rechtsgrundlagen" }), jsxRuntimeExports.jsxs("ul", { children: [jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Bereitstellung des Chats und Beantwortung von Anfragen" }), " (Art. 6 Abs. 1 lit. b DSGVO, soweit Vertrags-/vorvertragliche Ma\u00DFnahmen; andernfalls Art. 6 Abs. 1 lit. f DSGVO \u2013 berechtigtes Interesse an effizienter Kommunikation und Support)."] }), jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Qualit\u00E4tssicherung, Betrieb und Sicherheit" }), " (Art. 6 Abs. 1 lit. f DSGVO), z.B. zur Stabilit\u00E4t, Missbrauchserkennung und Fehlerbehebung."] }), jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Einwilligungsbasierte Verarbeitung" }), " kann erfolgen, sofern der Betreiber dies vorsieht (Art. 6 Abs. 1 lit. a DSGVO)."] })] })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntimeExports.jsx("h3", { children: "Empf\u00E4nger und Auftragsverarbeiter" }), jsxRuntimeExports.jsxs("ul", { children: [jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Hosting/IT-Dienstleister:" }), " Der Betreiber kann Dienstleister f\u00FCr Hosting, Logging, Monitoring und Infrastruktur einsetzen."] }), jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "KI-Dienstleister:" }), " Zur Generierung von Antworten k\u00F6nnen Chat-Inhalte an KI-Modelle bzw. Anbieter von KI-Infrastruktur \u00FCbertragen werden. Soweit erforderlich, erfolgt dies auf Grundlage eines Auftragsverarbeitungsvertrags (Art. 28 DSGVO)."] }), jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Drittlandtransfer:" }), " Falls Empf\u00E4nger au\u00DFerhalb der EU/des EWR sitzen, kann ein Transfer in Drittl\u00E4nder stattfinden. In diesem Fall werden geeignete Garantien (z.B. EU-Standardvertragsklauseln) eingesetzt, soweit erforderlich."] })] })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntimeExports.jsx("h3", { children: "Speicherdauer" }), jsxRuntimeExports.jsxs("ul", { children: [persistsConversation ? (jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Chatverlauf:" }), " Der Chatverlauf kann gespeichert werden, um die Unterhaltung \u00FCber mehrere Sitzungen hinweg fortzusetzen."] })) : (jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Chatverlauf:" }), " Der Chatverlauf wird nicht dauerhaft gespeichert und wird beim Schlie\u00DFen des Chats beendet."] })), hasFileUpload && (jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Dateien:" }), " Hochgeladene Dateien werden nur so lange verarbeitet, wie dies f\u00FCr die Bearbeitung erforderlich ist, und anschlie\u00DFend gel\u00F6scht, sofern keine l\u00E4ngere Speicherung gesetzlich erforderlich ist."] })), jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Technische Protokolle:" }), " Technische Logdaten k\u00F6nnen f\u00FCr einen begrenzten Zeitraum gespeichert werden, um den sicheren Betrieb zu gew\u00E4hrleisten."] })] })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntimeExports.jsx("h3", { children: "Deine Rechte (Betroffenenrechte)" }), jsxRuntimeExports.jsxs("ul", { children: [jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Auskunft" }), " (Art. 15 DSGVO)"] }), jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Berichtigung" }), " (Art. 16 DSGVO)"] }), jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "L\u00F6schung" }), " (Art. 17 DSGVO) und ", jsxRuntimeExports.jsx("strong", { children: "Einschr\u00E4nkung der Verarbeitung" }), " (Art. 18 DSGVO)"] }), jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Daten\u00FCbertragbarkeit" }), " (Art. 20 DSGVO), soweit anwendbar"] }), jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Widerspruch" }), " gegen Verarbeitungen auf Grundlage berechtigter Interessen (Art. 21 DSGVO)"] }), jsxRuntimeExports.jsxs("li", { children: [jsxRuntimeExports.jsx("strong", { children: "Beschwerderecht" }), " bei einer Datenschutzaufsichtsbeh\u00F6rde (Art. 77 DSGVO)"] })] }), jsxRuntimeExports.jsx("p", { children: "Hinweis: Ohne eindeutige Identifikationsmerkmale kann der Betreiber einzelne Chatverl\u00E4ufe ggf. nicht einer Person zuordnen. F\u00FCr Anfragen wende dich bitte an den Betreiber dieser Website/Anwendung." })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntimeExports.jsx("h3", { children: "Wichtiger Hinweis" }), jsxRuntimeExports.jsx("p", { className: "ai-chat-data-policy-warning", children: "Bitte gib keine besonderen Kategorien personenbezogener Daten (z.B. Gesundheitsdaten), Passw\u00F6rter, Kreditkarten-/Bankdaten oder vertrauliche Gesch\u00E4ftsgeheimnisse in den Chat ein. KI-generierte Antworten k\u00F6nnen unzutreffend sein und sollten vor einer Nutzung eigenverantwortlich gepr\u00FCft werden." })] })] }) }));
47424
+ return (jsxRuntimeExports.jsx("div", { className: "ai-chat-data-policy-view", children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-content", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-data-policy-intro", children: jsxRuntimeExports.jsxs("p", { children: ["This privacy notice informs you pursuant to Art. 13 GDPR about how ", jsxRuntimeExports.jsx("strong", { children: headerTitle }), " processes data when you use this chat. Please note that the specific scope of processing depends on the operator of this website/application (the controller) and on the respective activated functions."] }) }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntimeExports.jsx("h3", { children: "Controller / Contact" }), jsxRuntimeExports.jsx("p", { children: "The controller within the meaning of Art. 4 No. 7 GDPR is the operator of this website/application. The contact details (and, if applicable, the contact details of a data protection officer) can be found in the privacy policy or in the legal notice of the website into which this chat widget is embedded." })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntimeExports.jsx("h3", { children: "Processed Data" }), jsxRuntimeExports.jsxs("p", { children: ["The chat processes the following categories of data. ", jsxRuntimeExports.jsx("strong", { children: "Chat Content" }), " comprises messages (text) and, if applicable, context information that you provide in the chat. This content is processed to generate responses and provide the conversation."] }), hasFileUpload && (jsxRuntimeExports.jsxs("p", { children: [jsxRuntimeExports.jsx("strong", { children: "Uploaded Files" }), " that you transmit to the chat are processed to handle your request. Processing may include extracting text or information."] })), jsxRuntimeExports.jsxs("p", { children: [jsxRuntimeExports.jsx("strong", { children: "Technical Usage Data" }), " includes timestamps, session or request information, as well as technical metadata required for operation, security (abuse prevention), and error analysis."] }), jsxRuntimeExports.jsx("p", { children: "Please do not enter special categories of personal data (e.g., health data), passwords, credit card or bank data, or confidential business secrets in the chat. AI-generated responses may be inaccurate and should be checked independently before use." })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntimeExports.jsx("h3", { children: "Purposes and Legal Bases" }), jsxRuntimeExports.jsxs("p", { children: [jsxRuntimeExports.jsx("strong", { children: "Provision of the chat and answering of inquiries" }), " is based on Art. 6 Para. 1 lit. b GDPR, insofar as contractual or pre-contractual measures apply; otherwise on Art. 6 Para. 1 lit. f GDPR (legitimate interest in efficient communication and support)."] }), jsxRuntimeExports.jsxs("p", { children: [jsxRuntimeExports.jsx("strong", { children: "Quality assurance, operation and security" }), " are based on Art. 6 Para. 1 lit. f GDPR, for example for stability, abuse detection, and troubleshooting."] }), jsxRuntimeExports.jsxs("p", { children: [jsxRuntimeExports.jsx("strong", { children: "Consent-based processing" }), " may occur if the operator provides for this (Art. 6 Para. 1 lit. a GDPR)."] })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntimeExports.jsx("h3", { children: "Recipients and Processors" }), jsxRuntimeExports.jsxs("p", { children: [jsxRuntimeExports.jsx("strong", { children: "Hosting/IT Service Providers" }), " may be used by the operator for hosting, logging, monitoring, and infrastructure."] }), jsxRuntimeExports.jsxs("p", { children: [jsxRuntimeExports.jsx("strong", { children: "AI Service Providers" }), " may receive chat content to generate responses. Where required, this is done on the basis of a data processing agreement (Art. 28 GDPR)."] }), jsxRuntimeExports.jsxs("p", { children: [jsxRuntimeExports.jsx("strong", { children: "Third-Country Transfer" }), " may occur if recipients are located outside the EU/EEA. In this case, appropriate safeguards (e.g., EU Standard Contractual Clauses) are used where required."] })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntimeExports.jsx("h3", { children: "Retention Period" }), persistsConversation ? (jsxRuntimeExports.jsxs("p", { children: [jsxRuntimeExports.jsx("strong", { children: "Chat History" }), " may be stored to continue the conversation across multiple sessions."] })) : (jsxRuntimeExports.jsxs("p", { children: [jsxRuntimeExports.jsx("strong", { children: "Chat History" }), " is not permanently stored and ends when the chat is closed."] })), hasFileUpload && (jsxRuntimeExports.jsxs("p", { children: [jsxRuntimeExports.jsx("strong", { children: "Files" }), " are processed only as long as necessary to handle the request and are then deleted, unless longer retention is legally required."] })), jsxRuntimeExports.jsxs("p", { children: [jsxRuntimeExports.jsx("strong", { children: "Technical Logs" }), " may be stored for a limited period to ensure secure operation."] })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy-section", children: [jsxRuntimeExports.jsx("h3", { children: "Your Rights (Data Subject Rights)" }), jsxRuntimeExports.jsx("p", { children: "You have the following rights under the GDPR: Right to Information (Art. 15), Right to Rectification (Art. 16), Right to Erasure (Art. 17) and Restriction of Processing (Art. 18), Right to Data Portability (Art. 20), Right to Objection to processing based on legitimate interests (Art. 21), and Right to Complain to a supervisory authority (Art. 77)." }), jsxRuntimeExports.jsx("p", { children: "Note: Without clear identification features, the operator may not be able to assign individual chat histories to a person. For inquiries, please contact the operator of this website/application." })] })] }) }));
46561
47425
  };
46562
47426
 
46563
47427
  const MenuIcon = () => (jsxRuntimeExports.jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("line", { x1: "4", y1: "10", x2: "20", y2: "10" }), jsxRuntimeExports.jsx("line", { x1: "10", y1: "14", x2: "20", y2: "14" })] }));
@@ -46565,17 +47429,19 @@
46565
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" })] }));
46566
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" })] }));
46567
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" })] }));
46568
- const ChatWindow = ({ messages, isLoading, isTyping, config, onSendMessage, onClose: _onClose, onFeedback, onActionClick,
47432
+ const ChatWindow = ({ messages, isLoading, isTyping, config, onSendMessage, onClose: _onClose, onFeedback, onActionClick, onActionDismiss, onCallEndpoint,
46569
47433
  // Chat history props (only active when persistConversation is true)
46570
47434
  conversations = [], onLoadConversations, onSwitchConversation, onStartNewConversation, onDeleteConversation, currentConversationId,
46571
47435
  // Override props for live preview
46572
- headerTitleOverride, welcomeTitleOverride, welcomeMessageOverride, placeholderOverride, suggestedQuestionsOverride, }) => {
47436
+ sizeOverride, headerTitleOverride, welcomeTitleOverride, welcomeMessageOverride, placeholderOverride, suggestedQuestionsOverride,
47437
+ // Demo mode
47438
+ onInputFocus, }) => {
46573
47439
  const appearance = config?.appearance;
46574
47440
  const settings = config?.settings;
46575
47441
  // Check if chat history should be shown (requires both persistConversation AND showChatHistory)
46576
47442
  const canShowHistory = (settings?.persistConversation ?? true) && (settings?.showChatHistory ?? true);
46577
47443
  // Apply overrides for live preview (overrides take priority over saved config)
46578
- const size = appearance?.size || 'medium';
47444
+ const size = sizeOverride ?? appearance?.size ?? 'medium';
46579
47445
  const headerTitle = headerTitleOverride ?? appearance?.headerTitle ?? 'AI Assistant';
46580
47446
  const welcomeTitle = welcomeTitleOverride ?? appearance?.welcomeTitle ?? '';
46581
47447
  const welcomeMessage = welcomeMessageOverride ?? appearance?.welcomeMessage ?? '';
@@ -46647,12 +47513,12 @@
46647
47513
  // The backend will detect and trigger the action based on the message
46648
47514
  onSendMessage(question);
46649
47515
  };
46650
- return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-window size-${size}`, role: "dialog", "aria-label": "Chat window", children: [jsxRuntimeExports.jsx("div", { className: `ai-chat-header ${showHistory ? 'is-history' : ''} ${showDataPolicy ? 'is-data-policy' : ''}`, children: showDataPolicy ? (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("button", { className: "ai-chat-header-button", onClick: handleDataPolicyBack, "aria-label": "Back to chat", children: jsxRuntimeExports.jsx(BackIcon, {}) }), jsxRuntimeExports.jsx("div", { className: "ai-chat-title", children: "Datenschutzhinweis" })] })) : showHistory ? (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-title", children: headerTitle }), jsxRuntimeExports.jsx("button", { className: "ai-chat-header-button", onClick: handleNewConversation, "aria-label": "New chat", children: jsxRuntimeExports.jsx(PlusIcon, {}) })] })) : (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-header-content", children: [appearance?.logo && (jsxRuntimeExports.jsx("img", { src: appearance.logo, alt: "Logo", className: "ai-chat-logo" })), jsxRuntimeExports.jsx("div", { className: "ai-chat-title", children: headerTitle })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-header-actions", children: [canShowHistory && (jsxRuntimeExports.jsx("button", { className: "ai-chat-header-button", onClick: handleOpenHistory, "aria-label": "Chat overview", children: jsxRuntimeExports.jsx(MenuIcon, {}) })), jsxRuntimeExports.jsx("button", { className: "ai-chat-close-button header-close-button", onClick: _onClose, "aria-label": "Close chat", children: jsxRuntimeExports.jsx(CloseIcon, {}) })] })] })) }), showDataPolicy ? (jsxRuntimeExports.jsx(DataPolicyView, { config: config, onBack: handleDataPolicyBack, widgetName: headerTitle })) : showHistory ? (
47516
+ return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-window size-${size}`, role: "dialog", "aria-label": "Chat window", children: [jsxRuntimeExports.jsx("div", { className: `ai-chat-header ${showHistory ? 'is-history' : ''} ${showDataPolicy ? 'is-data-policy' : ''}`, children: showDataPolicy ? (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("button", { className: "ai-chat-header-button", onClick: handleDataPolicyBack, "aria-label": "Back to chat", children: jsxRuntimeExports.jsx(BackIcon, {}) }), jsxRuntimeExports.jsx("div", { className: "ai-chat-title", children: "Privacy Notice" })] })) : showHistory ? (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-title", children: headerTitle }), jsxRuntimeExports.jsx("button", { className: "ai-chat-header-button", onClick: handleNewConversation, "aria-label": "New chat", children: jsxRuntimeExports.jsx(PlusIcon, {}) })] })) : (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-header-content", children: [appearance?.logo && (jsxRuntimeExports.jsx("img", { src: appearance.logo, alt: "Logo", className: "ai-chat-logo" })), jsxRuntimeExports.jsx("div", { className: "ai-chat-title", children: headerTitle })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-header-actions", children: [canShowHistory && (jsxRuntimeExports.jsx("button", { className: "ai-chat-header-button", onClick: handleOpenHistory, "aria-label": "Chat overview", children: jsxRuntimeExports.jsx(MenuIcon, {}) })), jsxRuntimeExports.jsx("button", { className: "ai-chat-close-button header-close-button", onClick: _onClose, "aria-label": "Close chat", children: jsxRuntimeExports.jsx(CloseIcon, {}) })] })] })) }), showDataPolicy ? (jsxRuntimeExports.jsx(DataPolicyView, { config: config, onBack: handleDataPolicyBack, widgetName: headerTitle })) : showHistory ? (
46651
47517
  /* History Panel */
46652
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) => {
46653
47519
  e.stopPropagation();
46654
47520
  onDeleteConversation(conv.id);
46655
- }, "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." })), (() => {
46656
47522
  console.log('[DEBUG ChatWindow] Rendering MessageList with', messages.length, 'messages');
46657
47523
  messages.forEach((m, i) => {
46658
47524
  console.log(`[DEBUG ChatWindow] msg ${i}:`, { role: m.message.role, hasAction: !!m.action, impl: m.action?.implementation });
@@ -46662,7 +47528,15 @@
46662
47528
  console.log('[DEBUG ChatWindow] Testing renderer for query-contact-directory:', !!getActionRenderer('query-contact-directory'));
46663
47529
  }
46664
47530
  return null;
46665
- })(), jsxRuntimeExports.jsx(MessageList, { messages: messages, isTyping: isTyping, showTypingIndicator: settings?.showTypingIndicator, showTimestamps: settings?.showTimestamps, showToolCalls: settings?.showToolCalls, enableFeedback: settings?.enableFeedback, welcomeTitle: welcomeTitle || 'Welcome Message', welcomeMessage: welcomeMessage, suggestedQuestions: suggestedQuestionsOverride ?? settings?.suggestedQuestions, accentColor: appearance?.primaryColor, onSuggestedQuestionClick: handleQuestionClick, onActionClick: onActionClick, onFeedback: onFeedback, onScrollStateChange: handleScrollStateChange, getActionRenderer: getActionRenderer }), jsxRuntimeExports.jsx(ScrollButton, { onClick: () => scrollToBottom?.(), visible: showScrollButton }), jsxRuntimeExports.jsx(MessageInput, { onSend: onSendMessage, placeholder: isLimitReached ? 'Message limit reached' : (isTyping ? 'Waiting for response...' : inputPlaceholder), disabled: isLoading || isTyping || isLimitReached, enableFileUpload: settings?.enableFileUpload, 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,
46666
47540
  };
46667
47541
 
46668
47542
  /**
@@ -46960,108 +47834,60 @@
46960
47834
  return styles;
46961
47835
  }
46962
47836
 
46963
- /**
46964
- * Auto Theme Detector
46965
- * Detects whether the widget should use light or dark mode
46966
- * based on the background behind it
46967
- */
46968
- /**
46969
- * Sample the background color behind an element
46970
- * Uses multiple sampling points for accuracy
46971
- */
46972
- function sampleBackgroundColor(element) {
46973
- const rect = element.getBoundingClientRect();
46974
- const centerX = rect.left + rect.width / 2;
46975
- const centerY = rect.top + rect.height / 2;
46976
- // Try to get the element behind our widget
46977
- // Temporarily hide the element to sample what's behind
46978
- const originalVisibility = element.style.visibility;
46979
- element.style.visibility = 'hidden';
46980
- // Sample the center point
46981
- const elementBehind = document.elementFromPoint(centerX, centerY);
46982
- // Restore visibility
46983
- element.style.visibility = originalVisibility;
46984
- if (!elementBehind) {
46985
- return '#ffffff'; // Default to white
46986
- }
46987
- // Get computed background color
46988
- const computedStyle = window.getComputedStyle(elementBehind);
46989
- let bgColor = computedStyle.backgroundColor;
46990
- // If transparent, walk up the DOM tree
46991
- if (bgColor === 'rgba(0, 0, 0, 0)' || bgColor === 'transparent') {
46992
- let parent = elementBehind.parentElement;
46993
- while (parent) {
46994
- const parentStyle = window.getComputedStyle(parent);
46995
- bgColor = parentStyle.backgroundColor;
46996
- if (bgColor !== 'rgba(0, 0, 0, 0)' && bgColor !== 'transparent') {
46997
- break;
46998
- }
46999
- parent = parent.parentElement;
47000
- }
47001
- }
47002
- // If still transparent, check body/html
47003
- if (bgColor === 'rgba(0, 0, 0, 0)' || bgColor === 'transparent') {
47004
- const bodyStyle = window.getComputedStyle(document.body);
47005
- bgColor = bodyStyle.backgroundColor;
47006
- if (bgColor === 'rgba(0, 0, 0, 0)' || bgColor === 'transparent') {
47007
- 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);
47008
47844
  }
47009
- }
47010
- return rgbaToHex(bgColor);
47011
- }
47012
- /**
47013
- * Convert rgba/rgb string to hex
47014
- */
47015
- function rgbaToHex(rgba) {
47016
- // Handle rgb(r, g, b) or rgba(r, g, b, a)
47017
- const match = rgba.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
47018
- if (!match)
47019
- return '#ffffff';
47020
- const r = parseInt(match[1]);
47021
- const g = parseInt(match[2]);
47022
- const b = parseInt(match[3]);
47023
- return '#' + [r, g, b].map(x => {
47024
- const hex = x.toString(16);
47025
- return hex.length === 1 ? '0' + hex : hex;
47026
- }).join('');
47027
- }
47028
- /**
47029
- * Determine if the background is dark
47030
- */
47031
- function isBackgroundDark(backgroundColor) {
47032
- const luminance = getLuminance(backgroundColor);
47033
- return luminance < 0.5;
47034
- }
47035
- /**
47036
- * Auto-detect theme based on background
47037
- */
47038
- function detectTheme(element) {
47039
- const bgColor = sampleBackgroundColor(element);
47040
- 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
+ };
47041
47884
  }
47042
- /**
47043
- * Create a MutationObserver to watch for theme changes
47044
- */
47045
- function createThemeObserver(element, callback) {
47046
- let lastTheme = detectTheme(element);
47047
- const observer = new MutationObserver(() => {
47048
- const theme = detectTheme(element);
47049
- if (theme !== lastTheme) {
47050
- lastTheme = theme;
47051
- callback(theme);
47052
- }
47053
- });
47054
- // Observe body for class/style changes (common for theme switching)
47055
- observer.observe(document.body, {
47056
- attributes: true,
47057
- attributeFilter: ['class', 'style', 'data-theme', 'data-bs-theme'],
47058
- });
47059
- // Also observe html element
47060
- observer.observe(document.documentElement, {
47061
- attributes: true,
47062
- attributeFilter: ['class', 'style', 'data-theme', 'data-bs-theme'],
47063
- });
47064
- 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" }) }) })] })) }))] }));
47065
47891
  }
47066
47892
 
47067
47893
  function styleInject(css, ref) {
@@ -47091,21 +47917,17 @@
47091
47917
  }
47092
47918
  }
47093
47919
 
47094
- var css_248z$1 = ".ai-chat-message{animation:ai-chat-message-appear .2s var(--chat-ease-bounce);max-width:85%}.ai-chat-message-content{border-radius:var(--chat-radius-bubble,14px);font-size:var(--chat-text-md,15px);line-height:var(--chat-line-relaxed,1.6);padding:var(--chat-space-sm,8px) var(--chat-space-md,16px)}.ai-chat-message.user .ai-chat-message-content{background:var(--chat-user-bg,#f4f3f0);border-bottom-right-radius:var(--chat-radius-sm,4px);color:var(--chat-user-text,#000)}.ai-chat-message.assistant .ai-chat-message-content{background:var(--chat-assistant-bg,transparent);color:var(--chat-assistant-text,#000)}.ai-chat-message-timestamp{color:var(--chat-text-muted,#71717a);font-size:var(--chat-text-xs,12px);margin-top:var(--chat-space-xs,4px);padding:0 var(--chat-space-xs,4px)}.ai-chat-message.streaming .ai-chat-message-content:after{animation:ai-chat-cursor-blink .8s infinite;content:\"▋\";margin-left:2px;opacity:.7}@keyframes ai-chat-message-appear{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}@keyframes ai-chat-cursor-blink{0%,50%{opacity:1}51%,to{opacity:0}}.ai-chat-message.fullpage .ai-chat-message-content{font-size:var(--chat-text-lg,18px);padding:var(--chat-space-md,16px) var(--chat-space-lg,24px)}.ai-chat-typing{gap:var(--chat-space-xs,4px);padding:var(--chat-space-sm,8px) var(--chat-space-md,16px)}.ai-chat-typing-dot{background:var(--chat-text-muted,#71717a)}.ai-chat-tool-row{padding:0 16px}.ai-chat-tool-gear{color:var(--text-primary,#3e3e3e)}.ai-chat-tool-badge{border-radius:8px}.ai-chat-tool-badge.loading{background:#e5e7eb;border:1px solid #d1d5db;color:#1f2937}.ai-chat-tool-badge.error{background:rgba(239,68,68,.1);color:#ef4444}.ai-chat-tool-check{color:#22c55e;flex-shrink:0}.ai-chat-tool-error{color:#ef4444;flex-shrink:0}.ai-chat-tool-badge .tool-name{max-width:150px;overflow:hidden;text-overflow:ellipsis}.ai-chat-widget.dark .ai-chat-tool-gear,.ai-chat-widget[data-theme=dark] .ai-chat-tool-gear,.dark .ai-chat-tool-gear,[data-theme=dark] .ai-chat-tool-gear{color:#fff}.ai-chat-widget.dark .ai-chat-tool-badge,.ai-chat-widget[data-theme=dark] .ai-chat-tool-badge,.dark .ai-chat-tool-badge,[data-theme=dark] .ai-chat-tool-badge{background:hsla(0,0%,100%,.12);border:1px solid hsla(0,0%,100%,.2);color:hsla(0,0%,100%,.9)}.ai-chat-widget.dark .ai-chat-tool-badge.error,.ai-chat-widget[data-theme=dark] .ai-chat-tool-badge.error,.dark .ai-chat-tool-badge.error,[data-theme=dark] .ai-chat-tool-badge.error{background:rgba(239,68,68,.2);color:#f87171}.chakra-ui-dark .ai-chat-tool-gear,html.dark .ai-chat-tool-gear{color:#fff}.chakra-ui-dark .ai-chat-tool-badge,html.dark .ai-chat-tool-badge{background:hsla(0,0%,100%,.12);border:1px solid hsla(0,0%,100%,.2);color:hsla(0,0%,100%,.9)}.chakra-ui-dark .ai-chat-tool-badge.error,html.dark .ai-chat-tool-badge.error{background:rgba(239,68,68,.2);color:#f87171}.ai-chat-pin-input-group{align-items:center;display:flex;flex-wrap:nowrap;gap:8px;justify-content:center;margin:4px 0 8px}.ai-chat-pin-input{align-items:center;appearance:none;background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);box-sizing:border-box;color:var(--text-primary,#3e3e3e);display:inline-flex;flex:0 0 42px;font-family:inherit;font-size:18px;font-weight:600;height:46px;justify-content:center;line-height:1;max-width:42px;min-width:42px;outline:none;padding:0;text-align:center;transition:border-color .2s ease,box-shadow .2s ease;width:42px}.ai-chat-pin-input:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.1)}.ai-chat-pin-input:disabled{cursor:not-allowed;opacity:.6}.ai-chat-widget.dark .ai-chat-pin-input,.chakra-ui-dark .ai-chat-pin-input,.dark .ai-chat-pin-input,[data-theme=dark] .ai-chat-pin-input{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-pin-input:focus,.chakra-ui-dark .ai-chat-pin-input:focus,.dark .ai-chat-pin-input:focus,[data-theme=dark] .ai-chat-pin-input:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.2)}.ai-chat-action-button-secondary{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:9999px;color:var(--text-secondary,#6b7280);cursor:pointer;font-size:var(--text-sm,13px);font-weight:var(--font-weight-medium,500);padding:10px 16px;transition:all .2s ease;width:100%}.ai-chat-action-button-secondary:hover:not(:disabled){background:rgba(59,130,246,.05);border-color:var(--action-accent,var(--primary-color,#3b82f6));color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-action-button-secondary:disabled{cursor:not-allowed;opacity:.5}.ai-chat-widget.dark .ai-chat-action-button-secondary,.chakra-ui-dark .ai-chat-action-button-secondary,.dark .ai-chat-action-button-secondary,[data-theme=dark] .ai-chat-action-button-secondary{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#e5e7eb}.ai-chat-widget.dark .ai-chat-action-button-secondary:hover:not(:disabled),.chakra-ui-dark .ai-chat-action-button-secondary:hover:not(:disabled),.dark .ai-chat-action-button-secondary:hover:not(:disabled),[data-theme=dark] .ai-chat-action-button-secondary:hover:not(:disabled){background:rgba(59,130,246,.2);border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-action-appointment-list,.ai-chat-action-button-group{display:flex;flex-direction:column;gap:8px}.ai-chat-action-appointment-item{align-items:center;background:var(--bg-primary,#fff);border:1px solid var(--border-subtle,rgba(0,0,0,.08));border-radius:var(--radius-md,8px);display:flex;gap:12px;justify-content:space-between;padding:10px 12px}.ai-chat-widget.dark .ai-chat-action-appointment-item,.chakra-ui-dark .ai-chat-action-appointment-item,.dark .ai-chat-action-appointment-item,[data-theme=dark] .ai-chat-action-appointment-item{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.08)}.ai-chat-action-appointment-info{display:flex;flex-direction:column;gap:2px;min-width:0}.ai-chat-action-appointment-subject{color:var(--text-primary,#3e3e3e);font-size:14px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-widget.dark .ai-chat-action-appointment-subject,.chakra-ui-dark .ai-chat-action-appointment-subject,.dark .ai-chat-action-appointment-subject,[data-theme=dark] .ai-chat-action-appointment-subject{color:#fff}.ai-chat-action-appointment-time{color:var(--text-muted,#71717a);font-size:12px}.ai-chat-action-appointment-item .ai-chat-action-button-secondary{font-size:12px;padding:6px 12px;width:auto}.ai-chat-action-error-message{background:rgba(239,68,68,.1);border-radius:var(--radius-md,8px);color:#dc2626;font-size:var(--text-sm,13px);padding:12px}.ai-chat-widget.dark .ai-chat-action-error-message,.chakra-ui-dark .ai-chat-action-error-message,.dark .ai-chat-action-error-message,[data-theme=dark] .ai-chat-action-error-message{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-widget,.chat-ui{--radius-sm:4px;--radius-md:8px;--radius-lg:12px;--radius-xl:16px;--radius-2xl:18px;--radius-pill:9999px;--radius-window-top:22px;--radius-window-bottom:44px;--radius-window-gutter:16px;--radius-chat-bubble:14px;--radius-preset-badge:13px;--radius-history-item:14px;--radius-action-badge:8px;--radius-input:62px;--space-xs:4px;--space-sm:8px;--space-md:16px;--space-lg:24px;--space-xl:32px;--text-xs:12px;--text-sm:14px;--text-md:15px;--text-lg:18px;--text-xl:22px;--text-2xl:28px;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--line-height-tight:1.3;--line-height-normal:1.4;--line-height-relaxed:1.6;--bg-primary:#fff;--bg-secondary:#f4f4f4;--bg-tertiary:#e5e7eb;--bg-hover:#e5e7eb;--text-primary:#3e3e3e;--text-secondary:#000;--text-muted:#71717a;--text-placeholder:#a1a1aa;--border-default:#d3d3d3;--border-subtle:#e5e7eb;--border-muted:#f4f4f5;--user-bg:#f4f3f0;--user-text:#000;--user-bg-hover:#e8e7e4;--agent-bg:transparent;--agent-text:#000;--input-bg:#f4f4f4;--input-border:#d3d3d3;--input-text:#000;--btn-primary-bg:#151515;--btn-primary-text:#f4f4f4;--btn-secondary-bg:transparent;--btn-secondary-text:#71717a;--spring-bounce:cubic-bezier(0.34,1.56,0.64,1);--spring-smooth:cubic-bezier(0.4,0,0.2,1);--spring-snappy:cubic-bezier(0.2,0,0,1);--duration-fast:0.15s;--duration-normal:0.25s;--duration-slow:0.35s;--shadow-sm:0 1px 2px rgba(0,0,0,.05);--shadow-md:0 2px 8px rgba(0,0,0,.1);--shadow-lg:0 4px 16px rgba(0,0,0,.12);--shadow-window:0px 0px 15px 9px rgba(0,0,0,.1);--shadow-button:0px 0px 15px 9px rgba(0,0,0,.03)}.ai-chat-widget.dark,.chat-ui.dark{--bg-primary:#282625;--bg-secondary:#4a4846;--bg-tertiary:#484848;--bg-hover:#484848;--text-primary:#fff;--text-secondary:#fff;--text-muted:#a1a1aa;--text-placeholder:#71717a;--border-default:#5d5b5b;--border-subtle:#5d5b5b;--border-muted:#5d5b5b;--user-bg:#484848;--user-text:#fff;--user-bg-hover:#5a5a5a;--agent-bg:transparent;--agent-text:#fff;--input-bg:#4a4846;--input-border:#5d5b5b;--input-text:#fff;--btn-primary-bg:#fff;--btn-primary-text:#312f2d;--btn-secondary-bg:transparent;--btn-secondary-text:#a1a1aa;--shadow-window:0px 0px 15px 9px rgba(0,0,0,.2);--shadow-button:0px 0px 15px 9px rgba(0,0,0,.03);--shadow-input:0px 0px 10px rgba(0,0,0,.15)}.ai-chat-widget,.chat-ui{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}.ai-chat-widget-container{font-size:var(--text-sm);line-height:1.5;position:fixed;z-index:var(--widget-z-index,2147483647)}.ai-chat-widget-container.bottom-right{bottom:20px;right:20px}.ai-chat-widget-container.bottom-left{bottom:20px;left:20px}.ai-chat-widget-container.top-right{right:20px;top:20px}.ai-chat-widget-container.top-left{left:20px;top:20px}.ai-chat-widget-container.container-mode{position:absolute}@keyframes ai-chat-window-open{0%{opacity:0;transform:scale(.9) translateY(20px)}to{opacity:1;transform:scale(1) translateY(0)}}@keyframes ai-chat-window-close{0%{opacity:1;transform:scale(1) translateY(0)}to{opacity:0;transform:scale(.9) translateY(20px)}}@keyframes ai-chat-message-slide-in{0%{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}@keyframes ai-chat-welcome-fade-in{0%{opacity:0;transform:translateY(16px)}to{opacity:1;transform:translateY(0)}}@keyframes ai-chat-typing-pulse{0%,60%,to{opacity:.4;transform:translateY(0) scale(1)}30%{opacity:1;transform:translateY(-4px) scale(1.1)}}@keyframes ai-chat-gear-spin{to{transform:rotate(1turn)}}@keyframes ai-chat-tool-active{0%,to{background:var(--bg-secondary);opacity:1}50%{background:var(--bg-tertiary);opacity:1}}@keyframes ai-chat-feedback-morph{0%{opacity:.5;transform:scale(.8)}to{opacity:1;transform:scale(1)}}@keyframes ai-chat-checkmark-pop{0%{opacity:0;transform:scale(0) rotate(-45deg)}50%{transform:scale(1.3) rotate(0deg)}to{opacity:1;transform:scale(1) rotate(0deg)}}@keyframes ai-chat-history-exit{to{opacity:0;transform:translateY(-18px)}}@keyframes ai-chat-tool-gradient{0%{background-position:200% 0}to{background-position:-200% 0}}.ai-chat-window{animation:ai-chat-window-open var(--duration-slow,.35s) var(--spring-bounce);background:var(--bg-primary,#fff);border:1px solid var(--border-default,#d3d3d3);border-radius:var(--radius-window-top,22px) var(--radius-window-top,22px) var(--radius-window-bottom,44px) var(--radius-window-bottom,44px);box-shadow:var(--shadow-window,0 0 15px 5px rgba(0,0,0,.08));display:flex;flex-direction:column;overflow:hidden;position:absolute;transform-origin:bottom right;z-index:2}.ai-chat-widget.dark .ai-chat-window{background:var(--bg-primary,#282625);border-color:var(--border-default,#5d5b5b);border-width:.7px}.ai-chat-window.closing{animation:ai-chat-window-close var(--duration-normal) var(--spring-smooth) forwards}.ai-chat-window.size-small{height:500px;width:380px}.ai-chat-window.size-medium,.ai-chat-window.size-small{max-height:calc(100vh - 100px);max-width:calc(100vw - 40px)}.ai-chat-window.size-medium{height:600px;width:420px}.ai-chat-window.size-large{height:700px;max-height:calc(100vh - 100px);max-width:calc(100vw - 40px);width:480px}.ai-chat-widget-container.bottom-right .ai-chat-window{bottom:calc(var(--button-size, 56px) + 8px);right:0}.ai-chat-widget-container.bottom-left .ai-chat-window{bottom:calc(var(--button-size, 56px) + 8px);left:0}.ai-chat-widget-container.top-right .ai-chat-window{right:0;top:calc(var(--button-size, 56px) + 8px)}.ai-chat-widget-container.top-left .ai-chat-window{left:0;top:calc(var(--button-size, 56px) + 8px)}.ai-chat-header{align-items:center;background:var(--bg-primary,#fff);border-bottom:1px solid var(--border-default,#d3d3d3);border-radius:var(--radius-window-top,22px) var(--radius-window-top,22px) 0 0;display:flex;justify-content:space-between;padding:12px var(--space-md,16px);position:relative;z-index:10}.ai-chat-widget.dark .ai-chat-header{background:var(--bg-primary,#282625);border-bottom-color:var(--border-default,#5d5b5b);border-bottom-width:.7px}.ai-chat-header.is-history{padding-left:var(--space-md)}.ai-chat-header.is-history .ai-chat-title{flex:1;min-width:0;overflow:hidden;padding-right:var(--space-lg);text-overflow:ellipsis;white-space:nowrap}.ai-chat-header-content{align-items:center;display:flex;flex:1;gap:var(--space-lg)}.ai-chat-header-actions{align-items:center;display:flex;gap:var(--space-sm)}.ai-chat-logo{border-radius:10px;height:36px;object-fit:cover;width:36px}.ai-chat-title{color:var(--text-primary,#3e3e3e);font-size:var(--text-xl,22px);font-weight:var(--font-weight-bold,700);letter-spacing:-.02em}.ai-chat-widget.dark .ai-chat-title{color:var(--text-primary,#fff)}.ai-chat-close-button,.ai-chat-header-button{align-items:center;background:transparent;border:none;border-radius:var(--radius-md);color:var(--text-muted);cursor:pointer;display:flex;height:32px;justify-content:center;padding:0;transition:color var(--duration-fast) ease;width:32px}.ai-chat-close-button:hover,.ai-chat-header-button:hover{color:var(--text-primary)}.ai-chat-close-button:active,.ai-chat-header-button:active{transform:scale(.95)}.ai-chat-close-button svg,.ai-chat-header-button svg{height:22px;width:22px}.ai-chat-button{align-items:center;background:var(--button-color,var(--btn-primary-bg));border:1px solid var(--border-default,#d3d3d3);border-radius:50%;box-shadow:var(--shadow-button,0 0 15px 9px rgba(0,0,0,.03));color:var(--button-icon-color,var(--btn-primary-text));cursor:pointer;display:flex;height:var(--button-size,56px);justify-content:center;overflow:hidden;position:relative;transition:opacity var(--duration-fast) ease;width:var(--button-size,56px);z-index:1}.ai-chat-button:hover{opacity:.9}.ai-chat-button:active{opacity:.8}.ai-chat-button-svg{height:50%;min-height:24px;min-width:24px;transition:transform var(--duration-fast) ease;width:50%}.ai-chat-button.is-open .ai-chat-button-svg{transform:rotate(0deg)}.ai-chat-button-icon{font-size:1.5em;line-height:1}.ai-chat-welcome-bubble{animation:ai-chat-bubble-fade-in .3s ease-out;background:var(--button-color,var(--btn-primary-bg,#07f));border:none;border-radius:12px;box-shadow:0 4px 12px rgba(0,0,0,.15);color:var(--button-icon-color,var(--btn-primary-text,#fff));cursor:pointer;font-size:14px;font-weight:500;line-height:1.4;padding:12px 16px;position:absolute;width:200px;z-index:0}.ai-chat-widget-container.bottom-right .ai-chat-welcome-bubble{bottom:68px;right:0;text-align:right}.ai-chat-widget-container.bottom-left .ai-chat-welcome-bubble{bottom:68px;left:0;right:auto;text-align:left}.ai-chat-widget-container.top-right .ai-chat-welcome-bubble{right:0;text-align:right;top:68px}.ai-chat-widget-container.top-left .ai-chat-welcome-bubble{left:0;right:auto;text-align:left;top:68px}.ai-chat-welcome-bubble:hover{filter:brightness(1.1)}@keyframes ai-chat-bubble-fade-in{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.ai-chat-widget-container.top-left .ai-chat-welcome-bubble,.ai-chat-widget-container.top-right .ai-chat-welcome-bubble{animation-name:ai-chat-bubble-fade-in-down}@keyframes ai-chat-bubble-fade-in-down{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}.ai-chat-input-container{background:var(--bg-primary,#fff);bottom:0;left:0;padding:8px 0 16px;position:absolute;right:0;z-index:10}.ai-chat-widget.dark .ai-chat-input-container{background:var(--bg-primary,#282625)}.ai-chat-input-container.separate{padding:0 var(--radius-window-gutter,16px) var(--radius-window-gutter,16px)}.ai-chat-input-wrapper{align-items:flex-end;background:var(--input-bg,#f4f4f4);border:1px solid var(--input-border,#d3d3d3);border-radius:var(--radius-input,62px);box-sizing:border-box;display:flex;gap:0;height:52px;overflow:hidden;padding:6px 6px 6px 16px;position:relative;transition:all var(--duration-fast,.15s) ease;z-index:5}.ai-chat-input-wrapper.multiline{border-radius:14px!important;min-height:64px;padding:10px 10px 10px 14px}.ai-chat-widget.dark .ai-chat-input-wrapper{background:var(--input-bg,#4a4846);border-color:var(--input-border,#5d5b5b);border-width:.7px;box-shadow:var(--shadow-input,0 0 10px rgba(0,0,0,.15))}.ai-chat-input-wrapper:focus-within{border-color:var(--text-muted,#a1a1aa)}.ai-chat-input{word-wrap:break-word!important;background:transparent!important;border:none!important;border-radius:0!important;box-shadow:none!important;box-sizing:border-box!important;color:var(--input-text,#000)!important;flex:1!important;font-family:inherit!important;font-size:var(--text-md,15px)!important;height:40px!important;line-height:20px!important;margin:0!important;max-height:40px!important;min-height:40px!important;min-width:0!important;outline:none!important;overflow-wrap:anywhere!important;overflow-x:hidden!important;overflow-y:auto!important;padding:10px var(--space-sm,8px)!important;resize:none!important;white-space:pre-wrap!important;width:0!important;word-break:break-word!important}.ai-chat-widget.dark .ai-chat-input{color:var(--input-text,#fff)}.ai-chat-input::placeholder{color:var(--text-placeholder,#a1a1aa)}.ai-chat-widget.dark .ai-chat-input::placeholder{color:var(--text-placeholder,#52525b)}.ai-chat-file-button{align-items:center;align-self:center;background:transparent;border:none;color:var(--text-placeholder);cursor:pointer;display:flex;flex-shrink:0;height:28px;justify-content:center;padding:0;transition:color var(--duration-fast) ease;width:28px}.ai-chat-file-button:hover{color:var(--text-secondary)}.ai-chat-file-button:disabled{cursor:not-allowed;opacity:.5}.ai-chat-send-button{align-items:center;align-self:center;background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#151515))));border:none;border-radius:50%;color:var(--button-icon-color,var(--btn-primary-text,#f4f4f4));cursor:pointer;display:flex;flex-shrink:0;height:40px;justify-content:center;min-height:40px;min-width:40px;padding:0;transition:all var(--duration-fast,.15s) ease;width:40px}.ai-chat-widget.dark .ai-chat-send-button{background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#fff))));color:var(--button-icon-color,var(--btn-primary-text,#312f2d))}.ai-chat-send-button.active{background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#151515))));color:var(--button-icon-color,var(--btn-primary-text,#f4f4f4))}.ai-chat-widget.dark .ai-chat-send-button.active{background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#fff))));color:var(--button-icon-color,var(--btn-primary-text,#312f2d))}.ai-chat-send-button:hover:not(:disabled){opacity:.8}.ai-chat-send-button:active:not(:disabled){transform:scale(.95)}.ai-chat-send-button:disabled{cursor:not-allowed;opacity:.3}.ai-chat-file-list{display:flex;flex-wrap:wrap;gap:var(--space-sm);padding:var(--space-sm) var(--space-sm)}.ai-chat-file-item{align-items:center;background:rgba(0,0,0,.05);border-radius:6px;display:flex;font-size:var(--text-xs);gap:var(--space-sm);padding:6px 10px}.ai-chat-file-extension{background:var(--btn-primary-bg);border-radius:3px;color:var(--btn-primary-text);display:inline-block;font-size:10px;font-weight:var(--font-weight-semibold);min-width:40px;padding:2px 6px;text-align:center;text-transform:uppercase}.ai-chat-file-info{display:flex;flex:1;flex-direction:column;gap:2px;min-width:0}.ai-chat-file-name{font-weight:var(--font-weight-medium);max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-file-size{color:var(--text-muted);font-size:10px;opacity:.7}.ai-chat-file-remove{align-items:center;background:none;border:none;color:inherit;cursor:pointer;display:flex;justify-content:center;opacity:.5;padding:var(--space-xs);transition:opacity var(--duration-fast) ease}.ai-chat-file-remove:hover{opacity:1}.ai-chat-data-policy{bottom:2px;color:var(--text-muted,#71717a);font-size:9px;left:0;line-height:1.4;opacity:.5;pointer-events:auto;position:absolute;right:0;text-align:center}.ai-chat-widget.dark .ai-chat-data-policy{color:var(--text-muted,#a1a1aa)}.ai-chat-data-policy-link{background:none;border:none;color:var(--text-muted,#71717a);cursor:pointer;font-family:inherit;font-size:inherit;margin:0;padding:0;text-decoration:underline;text-underline-offset:2px;transition:color .15s ease}.ai-chat-data-policy-link:hover{color:var(--text-secondary,#52525b)}.ai-chat-widget.dark .ai-chat-data-policy-link{color:var(--text-muted,#a1a1aa)}.ai-chat-widget.dark .ai-chat-data-policy-link:hover{color:var(--text-secondary,#d4d4d8)}.ai-chat-messages{-webkit-overflow-scrolling:touch;-ms-overflow-style:none;align-items:stretch;background:var(--bg-primary,#fff);display:flex;flex:1;flex-direction:column;gap:var(--space-md,16px);justify-content:flex-start;overflow-x:hidden;overflow-y:auto;padding:0 var(--space-md,16px) 100px;position:relative;scroll-behavior:smooth;scrollbar-width:none}.ai-chat-widget.dark .ai-chat-messages{background:var(--bg-primary,#18181b)}.ai-chat-messages::-webkit-scrollbar{display:none}.ai-chat-message{animation:ai-chat-message-slide-in .2s var(--spring-bounce);display:flex;flex-direction:column;max-width:90%}.ai-chat-message.user{align-items:flex-end;align-self:flex-end}.ai-chat-message.assistant{align-items:flex-start;align-self:flex-start;max-width:100%;width:100%}.ai-chat-message.tool{align-self:stretch;max-width:none;padding:0}.ai-chat-message-content{word-wrap:break-word;border-radius:18px;font-size:var(--text-md,15px);line-height:var(--line-height-relaxed,1.6);overflow-wrap:break-word;padding:8px 14px}.ai-chat-message.user .ai-chat-message-content{background:var(--user-bg,#f4f3f0);border-radius:18px;color:var(--user-text,#000)}.ai-chat-widget.dark .ai-chat-message.user .ai-chat-message-content{background:var(--user-bg,#484848);color:var(--user-text,#fff)}.ai-chat-message.assistant .ai-chat-message-content{background:var(--agent-bg,transparent);box-sizing:border-box;color:var(--agent-text,#000);padding:0;width:100%}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content{color:var(--agent-text,#fff)}.ai-chat-message-timestamp{color:var(--text-muted,#71717a);font-size:var(--text-xs,12px);margin-top:var(--space-xs,4px);padding:0 var(--space-xs,4px)}.ai-chat-welcome{animation:ai-chat-welcome-fade-in .3s var(--spring-smooth);display:flex;flex-direction:column;gap:var(--space-md,16px);padding:var(--space-lg,24px) 0}.ai-chat-welcome-title{color:var(--text-primary,#3e3e3e);font-size:var(--text-2xl,28px);font-weight:var(--font-weight-bold,700);line-height:var(--line-height-tight,1.3)}.ai-chat-widget.dark .ai-chat-welcome-title{color:var(--text-primary,#fff)}.ai-chat-welcome-text{color:var(--text-secondary,#000);font-size:var(--text-md,15px);line-height:var(--line-height-relaxed,1.6);max-width:100%}.ai-chat-widget.dark .ai-chat-welcome-text{color:var(--text-secondary,#fff)}.ai-chat-typing{align-items:center;display:flex;gap:var(--space-xs,4px);padding:var(--space-sm,8px) var(--space-md,16px)}.ai-chat-typing-dot{animation:ai-chat-typing-bounce 1.4s ease-in-out infinite both;background:var(--text-muted,#71717a);border-radius:50%;height:8px;width:8px}.ai-chat-typing-dot:first-child{animation-delay:-.32s}.ai-chat-typing-dot:nth-child(2){animation-delay:-.16s}.ai-chat-typing-dot:nth-child(3){animation-delay:0s}@keyframes ai-chat-typing-bounce{0%,80%,to{opacity:.4;transform:scale(.6)}40%{opacity:1;transform:scale(1)}}.ai-chat-scroll-button{align-items:center;background:var(--bg-secondary,#f4f4f5);border:1px solid var(--border-subtle,rgba(0,0,0,.1));border-radius:50%;bottom:80px;box-shadow:0 2px 8px rgba(0,0,0,.1);color:var(--text-secondary,#71717a);cursor:pointer;display:flex;height:36px;justify-content:center;left:50%;opacity:0;pointer-events:none;position:absolute;transform:translateX(-50%);transition:background .15s ease,box-shadow .15s ease,opacity .15s ease,visibility .15s ease;visibility:hidden;width:36px;z-index:15}.ai-chat-scroll-button.visible{opacity:1;pointer-events:auto;visibility:visible}.ai-chat-scroll-button:hover{background:var(--bg-tertiary,#e4e4e7);box-shadow:0 4px 12px rgba(0,0,0,.15)}.ai-chat-scroll-button:active{background:var(--bg-tertiary,#d4d4d8)}.ai-chat-widget.dark .ai-chat-scroll-button{background:var(--bg-secondary,#3f3f46);border-color:var(--border-subtle,hsla(0,0%,100%,.1));box-shadow:0 2px 8px rgba(0,0,0,.3);color:var(--text-secondary,#a1a1aa)}.ai-chat-widget.dark .ai-chat-scroll-button:hover{background:var(--bg-tertiary,#52525b);box-shadow:0 4px 12px rgba(0,0,0,.4)}.ai-chat-error{background:var(--bg-secondary);border-radius:var(--radius-chat-bubble);color:var(--text-primary);font-size:var(--text-md);margin:0 auto;padding:10px var(--space-md)}.ai-chat-message.assistant .ai-chat-message-content p{margin:0 0 var(--space-sm) 0}.ai-chat-message.assistant .ai-chat-message-content p:last-child{margin-bottom:0}.ai-chat-message.assistant .ai-chat-message-content ol,.ai-chat-message.assistant .ai-chat-message-content ul{margin:var(--space-sm) 0;padding-left:var(--space-lg)}.ai-chat-message.assistant .ai-chat-message-content li{margin-bottom:var(--space-xs)}.ai-chat-message.assistant .ai-chat-message-content code{background:rgba(0,0,0,.05);border-radius:var(--radius-sm);font-family:SF Mono,Monaco,Cascadia Code,monospace;font-size:.9em;padding:2px 6px}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content code{background:hsla(0,0%,100%,.1)}.ai-chat-message.assistant .ai-chat-message-content pre{background:rgba(0,0,0,.05);border-radius:var(--radius-md);margin:var(--space-sm) 0;overflow-x:auto;padding:var(--space-sm)}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content pre{background:hsla(0,0%,100%,.05)}.ai-chat-message.assistant .ai-chat-message-content pre code{background:transparent;padding:0}.ai-chat-message.assistant .ai-chat-message-content a{color:var(--btn-primary-bg);text-decoration:underline}.ai-chat-message.assistant .ai-chat-message-content strong{font-weight:var(--font-weight-semibold)}.ai-chat-message.assistant .ai-chat-message-content blockquote{border-left:3px solid var(--border-default);color:var(--text-muted);margin:var(--space-sm) 0;padding-left:var(--space-md)}.ai-chat-message.assistant .ai-chat-message-content hr{border:none;border-top:1px solid var(--border-subtle,rgba(0,0,0,.1));margin:var(--space-lg,24px) 0}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content hr{border-top-color:var(--border-subtle,hsla(0,0%,100%,.1))}.ai-chat-message.assistant .ai-chat-message-content .table-wrapper{border:1px solid var(--border-subtle,rgba(0,0,0,.1));border-radius:var(--radius-md,8px);box-sizing:border-box;display:block;margin:var(--space-sm) var(--space-sm);max-width:100%;overflow:hidden;width:auto}.ai-chat-message.assistant .ai-chat-message-content .table-scroll{max-width:100%;overflow-x:auto;overflow-y:hidden;width:100%}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content .table-wrapper{border-color:var(--border-subtle,hsla(0,0%,100%,.1))}.ai-chat-message.assistant .ai-chat-message-content table{border-collapse:collapse;font-size:var(--text-sm);min-width:100%;width:max-content}.ai-chat-message.assistant .ai-chat-message-content td,.ai-chat-message.assistant .ai-chat-message-content th{border-bottom:1px solid var(--border-subtle,rgba(0,0,0,.1));border-right:1px solid var(--border-subtle,rgba(0,0,0,.1));padding:var(--space-sm);text-align:left}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content td,.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content th{border-color:var(--border-subtle,hsla(0,0%,100%,.1))}.ai-chat-message.assistant .ai-chat-message-content td:last-child,.ai-chat-message.assistant .ai-chat-message-content th:last-child{border-right:none}.ai-chat-message.assistant .ai-chat-message-content tr:last-child td{border-bottom:none}.ai-chat-message.assistant .ai-chat-message-content th{background:rgba(0,0,0,.03);font-weight:var(--font-weight-semibold);white-space:nowrap}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content th{background:hsla(0,0%,100%,.05)}.ai-chat-message.assistant .ai-chat-message-content tbody tr:nth-child(2n){background:rgba(0,0,0,.02)}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content tbody tr:nth-child(2n){background:hsla(0,0%,100%,.03)}.ai-chat-suggested-questions{align-self:flex-end;margin:0;padding:16px 0 0;width:100%}.ai-chat-suggested-questions-list{align-items:center;display:flex;flex-wrap:wrap;gap:6px;justify-content:flex-end}.ai-chat-suggested-question{align-items:center;background:transparent;border:1px solid var(--border-default,#d4d4d8);border-radius:var(--radius-preset-badge,18px);color:var(--text-primary,#18181b);cursor:pointer;display:inline-flex;font-size:14px;font-weight:400;gap:6px;justify-content:center;line-height:1.3;max-width:100%;overflow:hidden;padding:8px 14px;text-overflow:ellipsis;transition:background .15s ease,border-color .15s ease,transform .1s ease;white-space:nowrap}.ai-chat-widget.dark .ai-chat-suggested-question{background:transparent;border-color:var(--border-subtle,#52525b);color:var(--text-primary,#fafafa)}.ai-chat-suggested-question-text{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-suggested-question:hover{background:var(--bg-hover,#f4f4f5);border-color:var(--border-default,#d4d4d8)}.ai-chat-widget.dark .ai-chat-suggested-question:hover{background:var(--bg-hover,#3f3f46);border-color:var(--border-subtle,#52525b)}.ai-chat-suggested-question:active{transform:scale(.98)}.ai-chat-suggested-question.action-type{border:none}.ai-chat-suggested-question.action-type,.ai-chat-widget.dark .ai-chat-suggested-question.action-type{background:var(--primary-color,var(--button-color,#ef4444));color:var(--button-icon-color,#fff)}.ai-chat-suggested-question.action-type:hover{background:var(--primary-color,var(--button-color,#ef4444));opacity:.9}.ai-chat-suggested-question-icon{align-items:center;display:flex;flex-shrink:0;justify-content:center}.ai-chat-suggested-question:not(.action-type) .ai-chat-suggested-question-icon{display:none}.ai-chat-follow-up-suggestions{box-sizing:border-box;margin:0;padding:8px 16px 0;width:100%}.ai-chat-follow-up-list{align-items:flex-end;display:flex;flex-direction:column;gap:6px}.ai-chat-follow-up-item{align-items:center;border:none;border-radius:var(--radius-preset-badge,18px);cursor:pointer;display:inline-flex;font-size:14px;font-weight:400;gap:6px;justify-content:center;line-height:1.3;max-width:100%;overflow:hidden;padding:8px 14px;text-overflow:ellipsis;transition:opacity .15s ease,transform .1s ease;white-space:nowrap}.ai-chat-follow-up-item,.ai-chat-widget.dark .ai-chat-follow-up-item{background:var(--primary-color,var(--button-color,#07f));color:var(--button-icon-color,#fff)}.ai-chat-follow-up-item:hover{opacity:.9}.ai-chat-follow-up-item:active{transform:scale(.98)}.ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-default,#d4d4d8);color:var(--text-primary,#18181b)}.ai-chat-widget.dark .ai-chat-follow-up-item.question-type,.dark .ai-chat-follow-up-item.question-type,[data-color-mode=dark] .ai-chat-follow-up-item.question-type,[data-theme=dark] .ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-subtle,#52525b);color:var(--text-primary,#fafafa)}@media (prefers-color-scheme:dark){.ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-subtle,#52525b);color:var(--text-primary,#fafafa)}}.ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#f4f4f5);opacity:1}.ai-chat-widget.dark .ai-chat-follow-up-item.question-type:hover,.dark .ai-chat-follow-up-item.question-type:hover,[data-color-mode=dark] .ai-chat-follow-up-item.question-type:hover,[data-theme=dark] .ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#3f3f46);opacity:1}@media (prefers-color-scheme:dark){.ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#3f3f46);opacity:1}}.ai-chat-follow-up-item.action-type{background:var(--primary-color,var(--button-color,#07f));border:none;color:var(--button-icon-color,#fff)}.ai-chat-follow-up-icon{align-items:center;display:flex;flex-shrink:0;justify-content:center}.ai-chat-follow-up-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-feedback-buttons{align-items:center;display:flex;gap:var(--space-xs)}.ai-chat-feedback{align-items:center;display:inline-flex;gap:0;height:20px}.ai-chat-feedback-button{align-items:center;background:transparent!important;border:none;border-radius:var(--radius-sm);color:var(--text-placeholder);cursor:pointer;display:flex;font-size:var(--text-sm);height:20px;justify-content:center;padding:var(--space-xs);transition:all var(--duration-fast) var(--spring-bounce)}.ai-chat-feedback-button:hover:not(:disabled){background:none!important;color:var(--text-secondary)}.ai-chat-feedback-button:active:not(:disabled){transform:scale(.9)}.ai-chat-feedback-button:disabled{cursor:not-allowed;opacity:.4}.ai-chat-feedback-button.active{background:none!important;color:var(--text-primary)}.ai-chat-feedback.submitted{align-items:center;animation:ai-chat-feedback-morph .3s var(--spring-bounce);gap:var(--space-xs)}.ai-chat-feedback-message{align-items:center;display:flex;gap:4px;margin-left:var(--space-xxs)}.ai-chat-feedback-checkmark{animation:ai-chat-checkmark-pop .3s var(--spring-bounce);color:#10b981;font-size:var(--text-md);font-weight:700}.ai-chat-feedback-text{color:#10b981;font-size:var(--text-xs);font-weight:var(--font-weight-medium)}.ai-chat-history-panel{background:var(--bg-primary,#fff);display:flex;flex:1;flex-direction:column;overflow:hidden}.ai-chat-widget.dark .ai-chat-history-panel{background:var(--bg-primary,#18181b)}.ai-chat-history-empty,.ai-chat-history-loading{align-items:center;color:var(--text-muted);display:flex;flex:1;font-size:var(--text-sm);justify-content:center;padding:var(--space-lg);text-align:center}.ai-chat-history-list{-ms-overflow-style:none;display:flex;flex:1;flex-direction:column;gap:var(--space-sm);overflow-y:auto;padding:var(--space-xs) var(--space-md) 120px;scrollbar-width:none}.ai-chat-history-list::-webkit-scrollbar{display:none}.ai-chat-history-list.exiting{animation:ai-chat-history-exit .22s var(--spring-smooth) forwards}.ai-chat-history-item{align-items:center;background:var(--user-bg,#f4f4f5);border-radius:var(--radius-history-item,15px);display:flex;flex:0 0 auto;flex-direction:row;height:var(--history-item-height,36px);margin:0;overflow:hidden;transition:background var(--duration-fast,.15s) ease;width:100%}.ai-chat-history-item-content{align-items:center;background:transparent;border:none;cursor:pointer;display:flex;flex:1;flex-direction:row;height:100%;min-width:0;padding:0 var(--space-xs,4px) 0 var(--space-md,16px);text-align:left}.ai-chat-widget.dark .ai-chat-history-item{background:var(--user-bg,#27272a)}.ai-chat-history-item:hover{background:var(--user-bg-hover,#e5e7eb)}.ai-chat-widget.dark .ai-chat-history-item:hover{background:var(--user-bg-hover,#3f3f46)}.ai-chat-history-item.active{background:var(--user-bg-hover,#e5e7eb)}.ai-chat-widget.dark .ai-chat-history-item.active{background:var(--user-bg-hover,#3f3f46)}.ai-chat-history-item-preview{color:var(--text-primary,#18181b);flex:1;font-size:var(--text-sm,14px);font-weight:var(--font-weight-medium,500);line-height:var(--line-height-normal,1.4);margin-bottom:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-widget.dark .ai-chat-history-item-preview{color:var(--text-primary,#fafafa)}.ai-chat-history-item.active .ai-chat-history-item-preview{font-weight:var(--font-weight-medium)}.ai-chat-history-item-meta{display:none}.ai-chat-history-item-delete{align-items:center;background:transparent;border:none;border-radius:var(--radius-sm,6px);color:var(--text-muted,#71717a);cursor:pointer;display:flex;flex-shrink:0;height:24px;justify-content:center;margin-left:auto;margin-right:var(--space-xs,4px);opacity:0;transition:opacity var(--duration-fast,.15s) ease,background var(--duration-fast,.15s) ease,color var(--duration-fast,.15s) ease;width:24px}.ai-chat-history-item-delete svg{height:14px;width:14px}.ai-chat-history-item:hover .ai-chat-history-item-delete{opacity:1}.ai-chat-history-item-delete:hover{background:rgba(239,68,68,.1);color:#ef4444}.ai-chat-widget.dark .ai-chat-history-item-delete:hover{background:rgba(239,68,68,.2);color:#f87171}.ai-chat-tool-row{align-items:center;display:flex;gap:10px;margin:2px 0;padding:0}.ai-chat-tool-gear{color:#1f2937;flex-shrink:0;height:20px;width:20px}.ai-chat-tool-gear.spinning{animation:ai-chat-gear-spin 1.5s linear infinite}.ai-chat-tool-badges{align-items:center;display:flex;flex-wrap:wrap;gap:8px}.ai-chat-tool-badge{align-items:center;background:#e5e7eb;border:1px solid #d1d5db;border-radius:var(--radius-action-badge,8px);color:#1f2937;display:inline-flex;font-size:12px;font-weight:500;gap:4px;line-height:1.2;padding:5px 12px;transition:all .2s ease;white-space:nowrap}.ai-chat-tool-badge.loading{animation:ai-chat-tool-gradient 2s linear infinite;background:linear-gradient(90deg,var(--tool-loading-bg-1,#e0e0e0) 0,var(--tool-loading-bg-2,#f0f0f0) 25%,var(--tool-loading-bg-3,#fff) 50%,var(--tool-loading-bg-2,#f0f0f0) 75%,var(--tool-loading-bg-1,#e0e0e0) 100%);background-size:200% 100%;color:var(--tool-loading-text,#1a1a1a);position:relative}.ai-chat-widget:not(.dark) .ai-chat-tool-badge.loading{--tool-loading-bg-1:#2a2a2a;--tool-loading-bg-2:#3a3a3a;--tool-loading-bg-3:#4a4a4a;--tool-loading-text:#fff}.ai-chat-tool-badge.completed{background:#e5e7eb;border:1px solid #d1d5db;color:#1f2937}.ai-chat-widget.dark .ai-chat-tool-badge,.ai-chat-widget[data-theme=dark] .ai-chat-tool-badge,.chakra-ui-dark .ai-chat-tool-badge,.dark .ai-chat-tool-badge,[data-theme=dark] .ai-chat-tool-badge,html.dark .ai-chat-tool-badge{background:hsla(0,0%,100%,.12);border:1px solid hsla(0,0%,100%,.2);color:hsla(0,0%,100%,.9)}.ai-chat-widget.dark .ai-chat-tool-gear,.ai-chat-widget[data-theme=dark] .ai-chat-tool-gear,.chakra-ui-dark .ai-chat-tool-gear,.dark .ai-chat-tool-gear,[data-theme=dark] .ai-chat-tool-gear,html.dark .ai-chat-tool-gear{color:#fff}.ai-chat-tool-badge.error{background:var(--tool-error-bg,rgba(239,68,68,.15));color:var(--tool-error-text,#ef4444)}.ai-chat-tool-badge .ai-chat-tool-check{color:#fff;flex-shrink:0}.ai-chat-tool-badge .ai-chat-tool-error{color:#ef4444;flex-shrink:0}.tool-name{font-weight:500;line-height:1.2;white-space:nowrap}.ai-chat-tool-action{box-sizing:border-box;padding:0;width:100%}@keyframes ai-chat-skeleton-pulse{0%,to{opacity:.4}50%{opacity:.7}}.ai-chat-action-skeleton-item{animation:ai-chat-skeleton-pulse 1.5s ease-in-out infinite;background:var(--bg-secondary,#e5e7eb)}.ai-chat-widget.dark .ai-chat-action-skeleton-item,.chakra-ui-dark .ai-chat-action-skeleton-item,.dark .ai-chat-action-skeleton-item,[data-theme=dark] .ai-chat-action-skeleton-item{background:hsla(0,0%,100%,.1)}.ai-chat-action-skeleton-content{display:flex;flex-direction:column;gap:16px}.ai-chat-action-skeleton-header{align-items:center;display:flex;gap:10px}.ai-chat-action-skeleton-box{background:rgba(0,0,0,.08);border-radius:10px;display:flex;flex-direction:column;gap:8px;padding:14px}.ai-chat-widget.dark .ai-chat-action-skeleton-box,.chakra-ui-dark .ai-chat-action-skeleton-box,.dark .ai-chat-action-skeleton-box,[data-theme=dark] .ai-chat-action-skeleton-box{background:rgba(0,0,0,.25)}.ai-chat-action-card{--action-accent:var(--primary-color,#3b82f6);background:var(--bg-secondary,#f9fafb);border:1px solid var(--border-subtle,rgba(0,0,0,.06));border-radius:12px;box-sizing:border-box;margin-top:4px;padding:16px;transition:all .2s ease;width:100%}.ai-chat-widget.dark .ai-chat-action-card,.chakra-ui-dark .ai-chat-action-card,.dark .ai-chat-action-card,[data-theme=dark] .ai-chat-action-card{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1)}.ai-chat-action-booked{background:var(--bg-secondary,#f9fafb);border:1px solid var(--border-subtle,rgba(0,0,0,.06))}.ai-chat-widget.dark .ai-chat-action-booked,.chakra-ui-dark .ai-chat-action-booked,.dark .ai-chat-action-booked,[data-theme=dark] .ai-chat-action-booked{background:var(--bg-secondary,#3a3a3a)}.ai-chat-action-header{align-items:center;color:var(--text-primary,#3e3e3e);display:flex;font-size:var(--text-md,15px);font-weight:var(--font-weight-semibold,600);gap:var(--space-sm,8px);margin-bottom:var(--space-md,16px)}.ai-chat-widget.dark .ai-chat-action-header,.chakra-ui-dark .ai-chat-action-header,.dark .ai-chat-action-header,[data-theme=dark] .ai-chat-action-header{color:var(--text-primary,#fff)}.ai-chat-action-icon{color:var(--action-accent,var(--primary-color,#3b82f6));flex-shrink:0;height:20px;width:20px}.ai-chat-action-success-icon-wrapper{align-items:center;background:var(--action-accent,var(--primary-color,#22c55e));border-radius:50%;color:#fff;display:flex;flex-shrink:0;height:24px;justify-content:center;width:24px}.ai-chat-action-icon-success{color:currentColor;height:14px;width:14px}.ai-chat-action-detail-box{background:var(--bg-primary,#fff);border:1px solid var(--border-subtle,rgba(0,0,0,.08));border-radius:var(--radius-md,8px);display:flex;flex-direction:column;gap:4px;padding:12px 16px}.ai-chat-widget.dark .ai-chat-action-detail-box,.chakra-ui-dark .ai-chat-action-detail-box,.dark .ai-chat-action-detail-box,[data-theme=dark] .ai-chat-action-detail-box{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.05)}.ai-chat-action-label-small{color:var(--text-muted,#71717a);font-size:11px;font-weight:600;letter-spacing:.5px;text-transform:uppercase}.ai-chat-action-value-large{color:var(--text-primary,#3e3e3e);font-size:15px;font-weight:500}.ai-chat-widget.dark .ai-chat-action-value-large,.chakra-ui-dark .ai-chat-action-value-large,.dark .ai-chat-action-value-large,[data-theme=dark] .ai-chat-action-value-large{color:#fff}.ai-chat-action-body{display:flex;flex-direction:column;gap:var(--space-md,16px)}.ai-chat-action-field{display:flex;flex-direction:column;gap:var(--space-xs,6px)}.ai-chat-action-label{color:var(--text-secondary,#6b7280);font-size:var(--text-sm,13px);font-weight:var(--font-weight-medium,500)}.ai-chat-widget.dark .ai-chat-action-label,.chakra-ui-dark .ai-chat-action-label,.dark .ai-chat-action-label,[data-theme=dark] .ai-chat-action-label{color:var(--text-secondary,#a1a1aa)}.ai-chat-action-input{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);color:var(--text-primary,#3e3e3e);font-size:var(--text-sm,13px);outline:none;padding:10px 12px;transition:border-color .2s ease,box-shadow .2s ease}.ai-chat-action-input:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.1)}.ai-chat-action-input::placeholder{color:var(--text-muted,#9ca3af)}.ai-chat-widget.dark .ai-chat-action-input,.chakra-ui-dark .ai-chat-action-input,.dark .ai-chat-action-input,[data-theme=dark] .ai-chat-action-input{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-action-input:focus,.chakra-ui-dark .ai-chat-action-input:focus,.dark .ai-chat-action-input:focus,[data-theme=dark] .ai-chat-action-input:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.2)}.ai-chat-action-button{background:var(--action-accent,var(--primary-color,#3b82f6));border:none;border-radius:9999px;color:#fff;cursor:pointer;font-size:var(--text-sm,13px);font-weight:var(--font-weight-semibold,600);padding:12px 16px;transition:all .2s ease;width:100%}.ai-chat-action-button:hover:not(:disabled){opacity:.9;transform:translateY(-1px)}.ai-chat-action-button:disabled{cursor:not-allowed;opacity:.5}.ai-chat-action-link-button{align-items:center;background:var(--action-accent,var(--primary-color,#3b82f6));border:none;border-radius:9999px;box-sizing:border-box;color:#fff;display:flex;font-size:14px;font-weight:600;gap:6px;justify-content:center;margin-top:8px;padding:12px;text-decoration:none;transition:all .2s ease;width:100%}.ai-chat-action-link-button:hover{opacity:.9;transform:translateY(-1px)}.ai-chat-action-error{background:rgba(239,68,68,.1);border-radius:var(--radius-md,8px);color:#dc2626;font-size:var(--text-sm,13px);padding:10px 12px}.ai-chat-widget.dark .ai-chat-action-error,.chakra-ui-dark .ai-chat-action-error,.dark .ai-chat-action-error,[data-theme=dark] .ai-chat-action-error{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-action-hint{color:var(--text-muted,#9ca3af);font-size:var(--text-sm,13px);padding:var(--space-sm,8px);text-align:center}.ai-chat-action-date-grid{display:grid;gap:var(--space-xs,6px);grid-template-columns:repeat(auto-fill,minmax(90px,1fr))}.ai-chat-action-date-btn{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);color:var(--text-primary,#3e3e3e);cursor:pointer;font-size:var(--text-xs,12px);font-weight:var(--font-weight-medium,500);padding:8px 10px;text-align:center;transition:all .15s ease}.ai-chat-action-date-btn:hover{background:rgba(59,130,246,.05);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-action-date-btn.active{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-widget.dark .ai-chat-action-date-btn,.chakra-ui-dark .ai-chat-action-date-btn,.dark .ai-chat-action-date-btn,[data-theme=dark] .ai-chat-action-date-btn{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-action-date-btn:hover,.chakra-ui-dark .ai-chat-action-date-btn:hover,.dark .ai-chat-action-date-btn:hover,[data-theme=dark] .ai-chat-action-date-btn:hover{background:rgba(59,130,246,.15);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-action-date-btn.active,.chakra-ui-dark .ai-chat-action-date-btn.active,.dark .ai-chat-action-date-btn.active,[data-theme=dark] .ai-chat-action-date-btn.active{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-action-time-grid{display:grid;gap:var(--space-xs,6px);grid-template-columns:repeat(auto-fill,minmax(100px,1fr))}.ai-chat-action-time-btn{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);color:var(--text-primary,#3e3e3e);cursor:pointer;font-size:var(--text-xs,12px);font-weight:var(--font-weight-medium,500);padding:8px 10px;text-align:center;transition:all .15s ease}.ai-chat-action-time-btn:hover{background:rgba(59,130,246,.05);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-action-time-btn.active{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-widget.dark .ai-chat-action-time-btn,.chakra-ui-dark .ai-chat-action-time-btn,.dark .ai-chat-action-time-btn,[data-theme=dark] .ai-chat-action-time-btn{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-action-time-btn:hover,.chakra-ui-dark .ai-chat-action-time-btn:hover,.dark .ai-chat-action-time-btn:hover,[data-theme=dark] .ai-chat-action-time-btn:hover{background:rgba(59,130,246,.15);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-action-time-btn.active,.chakra-ui-dark .ai-chat-action-time-btn.active,.dark .ai-chat-action-time-btn.active,[data-theme=dark] .ai-chat-action-time-btn.active{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-link-preview{--action-accent:var(--primary-color,#3b82f6);background:var(--bg-secondary,#f4f4f4);border:1px solid var(--border-subtle,rgba(0,0,0,.08));border-radius:var(--radius-lg,12px);cursor:pointer;display:flex;flex-direction:column;margin-top:4px;overflow:hidden;padding:0!important;position:relative;transition:border-color .2s,box-shadow .2s,transform .2s}.ai-chat-link-preview:hover{border-color:var(--action-accent);box-shadow:0 2px 8px rgba(0,0,0,.1);transform:translateY(-1px)}.ai-chat-link-preview:focus{border-color:var(--action-accent);box-shadow:0 0 0 2px rgba(59,130,246,.2);outline:none}.ai-chat-widget.dark .ai-chat-link-preview,.chakra-ui-dark .ai-chat-link-preview,.dark .ai-chat-link-preview,[data-theme=dark] .ai-chat-link-preview{background:var(--bg-secondary,#3a3a3a);border-color:hsla(0,0%,100%,.08)}.ai-chat-widget.dark .ai-chat-link-preview:hover,.chakra-ui-dark .ai-chat-link-preview:hover,.dark .ai-chat-link-preview:hover,[data-theme=dark] .ai-chat-link-preview:hover{border-color:var(--action-accent);box-shadow:0 2px 12px rgba(0,0,0,.3)}.ai-chat-link-preview__image{aspect-ratio:1.91/1;background:var(--bg-muted,#e5e7eb);overflow:hidden;width:100%}.ai-chat-widget.dark .ai-chat-link-preview__image,.chakra-ui-dark .ai-chat-link-preview__image,.dark .ai-chat-link-preview__image,[data-theme=dark] .ai-chat-link-preview__image{background:hsla(0,0%,100%,.05)}.ai-chat-link-preview__image img{height:100%;object-fit:cover;width:100%}.ai-chat-link-preview__content{flex:1;padding:8px 10px}.ai-chat-link-preview__site{align-items:center;display:flex;gap:6px;margin-bottom:6px}.ai-chat-link-preview__favicon{border-radius:2px;flex-shrink:0;height:16px;width:16px}.ai-chat-link-preview__domain{color:var(--text-muted,#71717a);font-size:12px;letter-spacing:.5px;overflow:hidden;text-overflow:ellipsis;text-transform:uppercase;white-space:nowrap}.ai-chat-link-preview__title{-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;color:var(--text-primary,#3e3e3e);display:-webkit-box;font-size:15px;font-weight:600;line-height:1.3;margin:0 0 4px;overflow:hidden}.ai-chat-widget.dark .ai-chat-link-preview__title,.chakra-ui-dark .ai-chat-link-preview__title,.dark .ai-chat-link-preview__title,[data-theme=dark] .ai-chat-link-preview__title{color:#fff}.ai-chat-link-preview__description{-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;color:var(--text-muted,#71717a);display:-webkit-box;font-size:13px;line-height:1.4;margin:0;overflow:hidden}.ai-chat-link-preview__context{border-top:1px solid var(--border-subtle,rgba(0,0,0,.08));color:var(--text-muted,#71717a);font-size:12px;font-style:italic;margin:8px 0 0;padding-top:8px}.ai-chat-widget.dark .ai-chat-link-preview__context,.chakra-ui-dark .ai-chat-link-preview__context,.dark .ai-chat-link-preview__context,[data-theme=dark] .ai-chat-link-preview__context{border-color:hsla(0,0%,100%,.08)}.ai-chat-link-preview__arrow{align-items:center;background:var(--bg-primary,#fff);border-radius:50%;box-shadow:0 1px 3px rgba(0,0,0,.1);color:var(--text-muted,#71717a);display:flex;height:28px;justify-content:center;opacity:0;position:absolute;right:12px;top:12px;transition:opacity .2s,background .2s;width:28px}.ai-chat-link-preview:hover .ai-chat-link-preview__arrow{opacity:1}.ai-chat-widget.dark .ai-chat-link-preview__arrow,.chakra-ui-dark .ai-chat-link-preview__arrow,.dark .ai-chat-link-preview__arrow,[data-theme=dark] .ai-chat-link-preview__arrow{background:hsla(0,0%,100%,.1);color:#fff}.ai-chat-link-preview--error{border-color:rgba(239,68,68,.3)}.ai-chat-link-preview--error:hover{border-color:rgba(239,68,68,.5)}.ai-chat-link-preview__error-text{color:#dc2626;font-size:12px;margin:4px 0 0}.ai-chat-widget.dark .ai-chat-link-preview__error-text,.chakra-ui-dark .ai-chat-link-preview__error-text,.dark .ai-chat-link-preview__error-text,[data-theme=dark] .ai-chat-link-preview__error-text{color:#fca5a5}.ai-chat-video-player{--action-accent:var(--primary-color,#3b82f6);background:var(--bg-secondary,#f4f4f4);border-radius:var(--radius-lg,12px);display:flex;flex-direction:column;gap:0;margin-top:4px;overflow:hidden;padding:0!important}.ai-chat-widget.dark .ai-chat-video-player,.chakra-ui-dark .ai-chat-video-player,.dark .ai-chat-video-player,[data-theme=dark] .ai-chat-video-player{background:var(--bg-secondary,#3a3a3a)}.ai-chat-video-player__header{align-items:center;color:var(--action-accent,var(--primary-color,#3b82f6));display:flex;gap:8px}.ai-chat-video-player__title{color:var(--text-primary,#3e3e3e);font-size:14px;font-weight:600}.ai-chat-widget.dark .ai-chat-video-player__title,.chakra-ui-dark .ai-chat-video-player__title,.dark .ai-chat-video-player__title,[data-theme=dark] .ai-chat-video-player__title{color:#fff}.ai-chat-video-player__container{aspect-ratio:16/9;background:#000;border-radius:8px;overflow:hidden;position:relative;width:100%}.ai-chat-video-player__thumbnail{cursor:pointer;height:100%;position:relative;width:100%}.ai-chat-video-player__thumbnail img{height:100%;object-fit:cover;width:100%}.ai-chat-video-player__placeholder{align-items:center;background:linear-gradient(135deg,#1a1a2e,#16213e);cursor:pointer;display:flex;flex-direction:column;gap:8px;height:100%;justify-content:center;position:relative;width:100%}.ai-chat-video-player__click-text{color:hsla(0,0%,100%,.7);font-size:13px}.ai-chat-video-player__play-btn{align-items:center;background:rgba(0,0,0,.7);border:none;border-radius:50%;color:#fff;cursor:pointer;display:flex;height:64px;justify-content:center;left:50%;position:absolute;top:50%;transform:translate(-50%,-50%);transition:background .2s,transform .2s;width:64px}.ai-chat-video-player__placeholder .ai-chat-video-player__play-btn{left:auto;position:relative;top:auto;transform:none}.ai-chat-video-player__play-btn:hover{background:rgba(0,0,0,.9);transform:translate(-50%,-50%) scale(1.05)}.ai-chat-video-player__placeholder .ai-chat-video-player__play-btn:hover{transform:scale(1.05)}.ai-chat-video-player__provider-badge{background:rgba(0,0,0,.8);border-radius:4px;bottom:8px;color:#fff;font-size:11px;font-weight:600;letter-spacing:.5px;padding:4px 8px;position:absolute;right:8px;text-transform:uppercase}.ai-chat-video-player__iframe,.ai-chat-video-player__video{border:none;height:100%;left:0;position:absolute;top:0;width:100%}.ai-chat-video-player__error{align-items:center;background:rgba(239,68,68,.1);color:#dc2626;display:flex;font-size:13px;height:100%;justify-content:center;padding:16px;text-align:center;width:100%}.ai-chat-widget.dark .ai-chat-video-player__error,.chakra-ui-dark .ai-chat-video-player__error,.dark .ai-chat-video-player__error,[data-theme=dark] .ai-chat-video-player__error{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-video-player__context{border-top:1px solid var(--border-subtle,rgba(0,0,0,.08));color:var(--text-muted,#71717a);font-size:12px;font-style:italic;margin-top:4px;padding-top:8px}.ai-chat-widget.dark .ai-chat-video-player__context,.chakra-ui-dark .ai-chat-video-player__context,.dark .ai-chat-video-player__context,[data-theme=dark] .ai-chat-video-player__context{border-color:hsla(0,0%,100%,.08)}.ai-chat-location-card{background:var(--bg-secondary,#fff);border:1px solid var(--border-subtle,rgba(0,0,0,.08));border-radius:12px;overflow:hidden;padding:0}.ai-chat-widget.dark .ai-chat-location-card,.chakra-ui-dark .ai-chat-location-card,.dark .ai-chat-location-card,[data-theme=dark] .ai-chat-location-card{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1)}.ai-chat-location-card--compact{border-radius:10px}.ai-chat-location-card--error{color:var(--text-muted,#71717a);padding:16px;text-align:center}.ai-chat-location-card__map{background:var(--bg-muted,#f4f4f5);position:relative;width:100%}.ai-chat-widget.dark .ai-chat-location-card__map,.chakra-ui-dark .ai-chat-location-card__map,.dark .ai-chat-location-card__map,[data-theme=dark] .ai-chat-location-card__map{background:rgba(0,0,0,.2)}.ai-chat-location-card__map iframe{border:none;display:block;height:100%;width:100%}.ai-chat-location-card__content{padding:12px}.ai-chat-location-card--compact .ai-chat-location-card__content{padding:10px}.ai-chat-location-card__header{align-items:center;display:flex;flex-wrap:wrap;gap:8px;margin-bottom:8px}.ai-chat-location-card__name{color:var(--text-primary,#18181b);flex:1;font-size:16px;font-weight:600;margin:0;min-width:0}.ai-chat-widget.dark .ai-chat-location-card__name,.chakra-ui-dark .ai-chat-location-card__name,.dark .ai-chat-location-card__name,[data-theme=dark] .ai-chat-location-card__name{color:#fff}.ai-chat-location-card--compact .ai-chat-location-card__name{font-size:14px}.ai-chat-location-card__type{background:var(--bg-muted,#f4f4f5);border-radius:10px;color:var(--text-muted,#71717a);font-size:11px;font-weight:500;letter-spacing:.5px;padding:2px 8px;text-transform:uppercase}.ai-chat-widget.dark .ai-chat-location-card__type,.chakra-ui-dark .ai-chat-location-card__type,.dark .ai-chat-location-card__type,[data-theme=dark] .ai-chat-location-card__type{background:hsla(0,0%,100%,.1);color:hsla(0,0%,100%,.7)}.ai-chat-location-card__status{border-radius:12px;font-size:12px;font-weight:500;padding:2px 8px}.ai-chat-location-card__status--open{background:#dcfce7;color:#16a34a}.ai-chat-location-card__status--closed{background:#fef2f2;color:#dc2626}.ai-chat-widget.dark .ai-chat-location-card__status--open,.chakra-ui-dark .ai-chat-location-card__status--open,.dark .ai-chat-location-card__status--open,[data-theme=dark] .ai-chat-location-card__status--open{background:rgba(34,197,94,.2);color:#4ade80}.ai-chat-widget.dark .ai-chat-location-card__status--closed,.chakra-ui-dark .ai-chat-location-card__status--closed,.dark .ai-chat-location-card__status--closed,[data-theme=dark] .ai-chat-location-card__status--closed{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-location-card__address{align-items:flex-start;color:var(--text-muted,#71717a);display:flex;font-size:13px;gap:6px;line-height:1.4;margin:0 0 8px}.ai-chat-location-card__address svg{flex-shrink:0;margin-top:2px}.ai-chat-location-card__description{color:var(--text-muted,#71717a);font-size:13px;line-height:1.4;margin:0 0 8px}.ai-chat-location-card__hours{align-items:flex-start;color:var(--text-muted,#71717a);display:flex;font-size:13px;gap:6px;margin-bottom:8px}.ai-chat-location-card__hours svg{flex-shrink:0;margin-top:2px}.ai-chat-location-card__hours-list{flex:1}.ai-chat-location-card__hours-toggle{align-items:center;background:none;border:none;color:inherit;cursor:pointer;display:flex;font:inherit;gap:4px;padding:0}.ai-chat-location-card__hours-toggle:hover{text-decoration:underline}.ai-chat-location-card__hours-full{list-style:none;margin:8px 0 0;padding:0}.ai-chat-location-card__hours-full li{display:flex;font-size:12px;justify-content:space-between;padding:4px 0}.ai-chat-location-card__hours-today{color:var(--text-primary,#18181b);font-weight:600}.ai-chat-widget.dark .ai-chat-location-card__hours-today,.chakra-ui-dark .ai-chat-location-card__hours-today,.dark .ai-chat-location-card__hours-today,[data-theme=dark] .ai-chat-location-card__hours-today{color:#fff}.ai-chat-location-card__phone{align-items:center;background:none;border:none;color:var(--action-accent,#3b82f6);cursor:pointer;display:flex;font-size:13px;gap:6px;margin-bottom:12px;padding:0}.ai-chat-location-card__phone:hover{text-decoration:underline}.ai-chat-location-card__actions{display:flex;gap:8px;justify-content:flex-start;width:100%}.ai-chat-location-card__button{align-items:center;background:var(--action-accent,#3b82f6);border:none;border-radius:20px;color:#fff;cursor:pointer;display:flex;flex:1;font-size:13px;font-weight:500;gap:6px;justify-content:center;padding:10px 16px;transition:opacity .2s}.ai-chat-location-card__button:hover{opacity:.9}.ai-chat-location-card--compact .ai-chat-location-card__button{font-size:12px;padding:8px 12px}.ai-chat-location-card__link{align-items:center;background:var(--bg-secondary,#fff);border:1px solid var(--border-subtle,rgba(0,0,0,.08));border-radius:20px;color:var(--text-primary,#18181b);display:flex;font-size:13px;gap:6px;padding:10px 16px;text-decoration:none;transition:border-color .2s}.ai-chat-widget.dark .ai-chat-location-card__link,.chakra-ui-dark .ai-chat-location-card__link,.dark .ai-chat-location-card__link,[data-theme=dark] .ai-chat-location-card__link{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-location-card__link:hover{border-color:var(--action-accent,#3b82f6)}.ai-chat-location-card-list{display:flex;flex-direction:column;gap:8px}.ai-chat-location-card-list__header{align-items:center;color:var(--text-muted,#71717a);display:flex;font-size:13px;font-weight:500;gap:6px;margin-bottom:4px;padding:0 4px}.ai-chat-location-card-list__stack{display:grid;gap:12px;grid-template-columns:1fr}.ai-chat-location-card-list__stack--cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.ai-chat-location-card-list__stack--cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}@media (max-width:1000px){.ai-chat-location-card-list__stack--cols-3{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (max-width:640px){.ai-chat-location-card-list__stack--cols-2,.ai-chat-location-card-list__stack--cols-3{grid-template-columns:1fr}}.ai-chat-location-card-list__grid{display:grid;gap:8px;grid-template-columns:repeat(2,1fr)}@media (max-width:400px){.ai-chat-location-card-list__grid{grid-template-columns:1fr}}.ai-chat-location-card-list__carousel{-webkit-overflow-scrolling:touch;-ms-overflow-style:none;display:flex;gap:8px;overflow-x:auto;padding-bottom:4px;scroll-snap-type:x mandatory;scrollbar-width:none}.ai-chat-location-card-list__carousel::-webkit-scrollbar{display:none}.ai-chat-location-card-list__carousel>.ai-chat-location-card{flex:0 0 280px;scroll-snap-align:start}.ai-chat-contact-card{background:#fff;border:1px solid rgba(0,0,0,.08);border-radius:16px;overflow:hidden;padding:0;position:relative}.ai-chat-widget.dark .ai-chat-contact-card,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card,.chakra-ui-dark .ai-chat-contact-card,.dark .ai-chat-contact-card,[data-theme=dark] .ai-chat-contact-card,html.dark .ai-chat-contact-card{background:#4a4a4a;border-color:hsla(0,0%,100%,.08)}.ai-chat-contact-card-list{gap:12px;width:100%}.ai-chat-contact-card--compact{border-radius:12px}.ai-chat-contact-card--empty{align-items:center;background:var(--bg-secondary,#f4f4f5);display:flex;flex-direction:column;gap:8px;justify-content:center;padding:24px 16px;text-align:center}.ai-chat-widget.dark .ai-chat-contact-card--empty,.chakra-ui-dark .ai-chat-contact-card--empty,.dark .ai-chat-contact-card--empty,[data-theme=dark] .ai-chat-contact-card--empty{background:#3a3a3a}.ai-chat-contact-card__empty-icon{color:var(--text-muted,#71717a);opacity:.6}.ai-chat-contact-card__empty-text{color:var(--text-muted,#71717a);font-size:14px;margin:0}.ai-chat-contact-card--vertical{display:flex;flex-direction:column}.ai-chat-contact-card--vertical .ai-chat-contact-card__image-section{aspect-ratio:3/2;overflow:hidden;width:100%}.ai-chat-contact-card--vertical .ai-chat-contact-card__image{height:100%;object-fit:cover;width:100%}.ai-chat-contact-card--vertical .ai-chat-contact-card__image-placeholder{align-items:center;background:linear-gradient(135deg,#5a5a5a,#3a3a3a);color:hsla(0,0%,100%,.5);display:flex;height:100%;justify-content:center;width:100%}.ai-chat-contact-card--vertical .ai-chat-contact-card__image-placeholder svg{height:48px;width:48px}.ai-chat-contact-card--vertical .ai-chat-contact-card__info{padding:16px;text-align:center}.ai-chat-contact-card--horizontal{display:flex;flex-direction:row}.ai-chat-contact-card--horizontal .ai-chat-contact-card__image-section{height:160px;min-width:140px;overflow:hidden;width:140px}.ai-chat-contact-card--horizontal.ai-chat-contact-card--compact .ai-chat-contact-card__image-section{height:120px;min-width:100px;width:100px}.ai-chat-contact-card--horizontal .ai-chat-contact-card__image{height:100%;object-fit:cover;width:100%}.ai-chat-contact-card--horizontal .ai-chat-contact-card__image-placeholder{align-items:center;background:linear-gradient(135deg,#5a5a5a,#3a3a3a);color:hsla(0,0%,100%,.5);display:flex;height:100%;justify-content:center;width:100%}.ai-chat-contact-card--horizontal .ai-chat-contact-card__image-placeholder svg{height:36px;width:36px}.ai-chat-contact-card--horizontal .ai-chat-contact-card__info{display:flex;flex:1;flex-direction:column;justify-content:center;padding:16px}.ai-chat-contact-card__name{color:var(--action-accent,#ef4444);font-size:18px;font-weight:600;line-height:1.3;margin:0}.ai-chat-contact-card--compact .ai-chat-contact-card__name{font-size:15px}.ai-chat-contact-card__role{color:rgba(0,0,0,.7);font-size:14px;font-weight:400;margin:2px 0 0}.ai-chat-widget.dark .ai-chat-contact-card__role,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card__role,.chakra-ui-dark .ai-chat-contact-card__role,.dark .ai-chat-contact-card__role,[data-theme=dark] .ai-chat-contact-card__role,html.dark .ai-chat-contact-card__role{color:hsla(0,0%,100%,.9)}.ai-chat-contact-card--compact .ai-chat-contact-card__role{font-size:13px}.ai-chat-contact-card__details{display:flex;flex-direction:column;gap:2px;margin-top:12px}.ai-chat-contact-card__detail{color:rgba(0,0,0,.6);display:block;font-size:14px;line-height:1.5;margin:0;text-decoration:none}.ai-chat-contact-card__detail:hover{color:#000;text-decoration:underline}.ai-chat-widget.dark .ai-chat-contact-card__detail,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card__detail,.chakra-ui-dark .ai-chat-contact-card__detail,.dark .ai-chat-contact-card__detail,[data-theme=dark] .ai-chat-contact-card__detail,html.dark .ai-chat-contact-card__detail{color:hsla(0,0%,100%,.7)}.ai-chat-widget.dark .ai-chat-contact-card__detail:hover,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card__detail:hover,.chakra-ui-dark .ai-chat-contact-card__detail:hover,.dark .ai-chat-contact-card__detail:hover,[data-theme=dark] .ai-chat-contact-card__detail:hover,html.dark .ai-chat-contact-card__detail:hover{color:#fff}.ai-chat-contact-card--compact .ai-chat-contact-card__detail{font-size:13px}.ai-chat-contact-card__responsibilities{display:flex;flex-wrap:wrap;gap:4px;margin-top:8px}.ai-chat-contact-card__responsibility-tag{background:rgba(0,0,0,.08);border-radius:10px;color:rgba(0,0,0,.8);font-size:11px;font-weight:500;padding:3px 10px}.ai-chat-widget.dark .ai-chat-contact-card__responsibility-tag,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card__responsibility-tag,.chakra-ui-dark .ai-chat-contact-card__responsibility-tag,.dark .ai-chat-contact-card__responsibility-tag,[data-theme=dark] .ai-chat-contact-card__responsibility-tag,html.dark .ai-chat-contact-card__responsibility-tag{background:hsla(0,0%,100%,.15);color:hsla(0,0%,100%,.9)}.ai-chat-contact-card__responsibility-more{color:rgba(0,0,0,.5);font-size:11px;padding:3px 4px}.ai-chat-widget.dark .ai-chat-contact-card__responsibility-more,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card__responsibility-more,.chakra-ui-dark .ai-chat-contact-card__responsibility-more,.dark .ai-chat-contact-card__responsibility-more,[data-theme=dark] .ai-chat-contact-card__responsibility-more,html.dark .ai-chat-contact-card__responsibility-more{color:hsla(0,0%,100%,.5)}.ai-chat-contact-card__actions{display:flex;gap:8px;padding:0 12px 12px}.ai-chat-contact-card--compact .ai-chat-contact-card__actions{gap:6px;padding:0 10px 10px}.ai-chat-contact-card__button{align-items:center;border:none;border-radius:9999px;cursor:pointer;display:flex;font-size:14px;font-weight:600;gap:8px;justify-content:center;padding:12px 20px;transition:all .15s ease;white-space:nowrap}.ai-chat-contact-card--compact .ai-chat-contact-card__button{font-size:13px;padding:10px 16px}.ai-chat-contact-card__button:hover{box-shadow:0 4px 12px rgba(0,0,0,.15);transform:translateY(-1px)}.ai-chat-contact-card__button:active{transform:translateY(0)}.ai-chat-contact-card__button--primary{background:var(--action-accent,#3b82f6);color:#fff;flex:1}.ai-chat-contact-card__button--primary:hover{background:color-mix(in srgb,var(--action-accent,#3b82f6) 90%,#000)}.ai-chat-contact-card__button--secondary{background:var(--bg-muted,#f4f4f5);border:1px solid var(--border-subtle,rgba(0,0,0,.08));color:var(--text-primary,#18181b);flex:1}.ai-chat-contact-card__button--secondary:hover{background:var(--bg-hover,#e4e4e7)}.ai-chat-widget.dark .ai-chat-contact-card__button--secondary,.chakra-ui-dark .ai-chat-contact-card__button--secondary,.dark .ai-chat-contact-card__button--secondary,[data-theme=dark] .ai-chat-contact-card__button--secondary{background:hsla(0,0%,100%,.1);border-color:hsla(0,0%,100%,.15);color:#fff}.ai-chat-widget.dark .ai-chat-contact-card__button--secondary:hover,.chakra-ui-dark .ai-chat-contact-card__button--secondary:hover,.dark .ai-chat-contact-card__button--secondary:hover,[data-theme=dark] .ai-chat-contact-card__button--secondary:hover{background:hsla(0,0%,100%,.15)}.ai-chat-contact-card-list{display:flex;flex-direction:column;gap:8px}.ai-chat-contact-card-list__header{align-items:center;color:var(--text-muted,#71717a);display:flex;font-size:13px;font-weight:500;gap:6px;margin-bottom:2px;margin-top:8px;padding:0 4px}.ai-chat-contact-card-list__stack{display:grid;gap:12px;grid-template-columns:repeat(3,minmax(0,1fr))}@media (max-width:900px){.ai-chat-contact-card-list__stack{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (max-width:600px){.ai-chat-contact-card-list__stack{grid-template-columns:1fr}}.ai-chat-contact-card-list__stack--widget{grid-template-columns:1fr}@container (min-width: 380px){.ai-chat-contact-card-list__stack--widget{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (max-width:520px){.ai-chat-contact-card-list__stack{grid-template-columns:1fr!important}.ai-chat-contact-card--horizontal{flex-direction:column}.ai-chat-contact-card--horizontal .ai-chat-contact-card__image-section{aspect-ratio:3/2;height:auto;min-width:100%;width:100%}}.ai-chat-contact-card__initials{align-items:center;display:flex;font-size:48px;font-weight:600;height:100%;justify-content:center;letter-spacing:.05em;text-transform:uppercase;width:100%}.ai-chat-contact-card--compact .ai-chat-contact-card__initials{font-size:32px}.ai-chat-contact-card--horizontal .ai-chat-contact-card__initials{font-size:28px}.ai-chat-contact-card--horizontal.ai-chat-contact-card--compact .ai-chat-contact-card__initials{font-size:22px}.ai-chat-form-card{--action-accent:var(--primary-color,#3b82f6);background:var(--bg-secondary,#f9fafb);border:1px solid var(--border-subtle,rgba(0,0,0,.06));border-radius:12px;box-sizing:border-box;margin:6px 0;overflow:hidden;padding:16px;width:100%}.ai-chat-widget.dark .ai-chat-form-card,.chakra-ui-dark .ai-chat-form-card,.dark .ai-chat-form-card,[data-theme=dark] .ai-chat-form-card{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1)}.ai-chat-form-card--empty,.ai-chat-form-card--error,.ai-chat-form-card--skipped,.ai-chat-form-card--submitted{padding:12px 16px}.ai-chat-form-card__header{align-items:center;display:flex;gap:8px;margin-bottom:12px}.ai-chat-form-card__icon{font-size:18px}.ai-chat-form-card__title{color:var(--text-primary,#3e3e3e);font-size:15px;font-weight:600}.ai-chat-widget.dark .ai-chat-form-card__title,.chakra-ui-dark .ai-chat-form-card__title,.dark .ai-chat-form-card__title,[data-theme=dark] .ai-chat-form-card__title{color:#fff}.ai-chat-form-card__description{color:var(--text-muted,#71717a);font-size:13px;line-height:1.4;margin:0 0 12px}.ai-chat-form-card__context{color:var(--text-muted,#71717a);font-size:12px;font-style:italic;margin:0 0 12px}.ai-chat-form-card__error{color:#dc2626;font-size:13px;margin:0}.ai-chat-widget.dark .ai-chat-form-card__error,.chakra-ui-dark .ai-chat-form-card__error,.dark .ai-chat-form-card__error,[data-theme=dark] .ai-chat-form-card__error{color:#fca5a5}.ai-chat-form-card__success{color:#16a34a;font-size:13px;margin:0}.ai-chat-widget.dark .ai-chat-form-card__success,.chakra-ui-dark .ai-chat-form-card__success,.dark .ai-chat-form-card__success,[data-theme=dark] .ai-chat-form-card__success{color:#4ade80}.ai-chat-form-card__empty-text,.ai-chat-form-card__skipped-text{color:var(--text-muted,#71717a);font-size:13px;margin:0}.ai-chat-form-card__progress{align-items:center;display:flex;gap:12px;margin-bottom:16px}.ai-chat-form-card__progress-bar{background:var(--action-accent,var(--primary-color,#3b82f6));border-radius:2px;flex:1;height:4px;transition:width .3s ease}.ai-chat-form-card__progress-text{color:var(--text-muted,#71717a);font-size:12px;white-space:nowrap}.ai-chat-form-card__question{margin-bottom:16px}.ai-chat-form-card__question-text{color:var(--text-primary,#3e3e3e);font-size:14px;font-weight:500;line-height:1.4;margin:0 0 12px}.ai-chat-widget.dark .ai-chat-form-card__question-text,.chakra-ui-dark .ai-chat-form-card__question-text,.dark .ai-chat-form-card__question-text,[data-theme=dark] .ai-chat-form-card__question-text{color:#fff}.ai-chat-form-card__required{color:#dc2626;margin-left:2px}.ai-chat-form-card__answer{margin-top:8px}.ai-chat-form-card__textarea{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);box-sizing:border-box;color:var(--text-primary,#3e3e3e);font-family:inherit;font-size:14px;min-height:80px;outline:none;padding:10px 12px;resize:vertical;transition:border-color .2s ease,box-shadow .2s ease;width:100%}.ai-chat-form-card__textarea:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.1)}.ai-chat-form-card__textarea::placeholder{color:var(--text-muted,#9ca3af)}.ai-chat-widget.dark .ai-chat-form-card__textarea,.chakra-ui-dark .ai-chat-form-card__textarea,.dark .ai-chat-form-card__textarea,[data-theme=dark] .ai-chat-form-card__textarea{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-form-card__textarea:focus,.chakra-ui-dark .ai-chat-form-card__textarea:focus,.dark .ai-chat-form-card__textarea:focus,[data-theme=dark] .ai-chat-form-card__textarea:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.2)}.ai-chat-form-card__options{display:flex;flex-direction:column;gap:8px}.ai-chat-form-card__option{align-items:center;background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);cursor:pointer;display:flex;gap:10px;padding:10px 12px;transition:border-color .15s,background .15s}.ai-chat-form-card__option:hover{background:rgba(59,130,246,.05);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-form-card__option,.chakra-ui-dark .ai-chat-form-card__option,.dark .ai-chat-form-card__option,[data-theme=dark] .ai-chat-form-card__option{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1)}.ai-chat-widget.dark .ai-chat-form-card__option:hover,.chakra-ui-dark .ai-chat-form-card__option:hover,.dark .ai-chat-form-card__option:hover,[data-theme=dark] .ai-chat-form-card__option:hover{background:rgba(59,130,246,.15);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-form-card__option input{accent-color:var(--action-accent,var(--primary-color,#3b82f6));margin:0}.ai-chat-form-card__option-text{color:var(--text-primary,#3e3e3e);font-size:14px}.ai-chat-widget.dark .ai-chat-form-card__option-text,.chakra-ui-dark .ai-chat-form-card__option-text,.dark .ai-chat-form-card__option-text,[data-theme=dark] .ai-chat-form-card__option-text{color:#fff}.ai-chat-form-card__rating{display:flex;flex-wrap:wrap;gap:8px}.ai-chat-form-card__rating-btn{align-items:center;background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);color:var(--text-primary,#3e3e3e);cursor:pointer;display:flex;font-size:14px;font-weight:500;height:40px;justify-content:center;transition:all .15s ease;width:40px}.ai-chat-form-card__rating-btn--selected,.ai-chat-form-card__rating-btn:hover{border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-form-card__rating-btn--selected{background:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-widget.dark .ai-chat-form-card__rating-btn,.chakra-ui-dark .ai-chat-form-card__rating-btn,.dark .ai-chat-form-card__rating-btn,[data-theme=dark] .ai-chat-form-card__rating-btn{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-form-card__rating-btn:hover,.chakra-ui-dark .ai-chat-form-card__rating-btn:hover,.dark .ai-chat-form-card__rating-btn:hover,[data-theme=dark] .ai-chat-form-card__rating-btn:hover{border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-form-card__rating-btn--selected,.chakra-ui-dark .ai-chat-form-card__rating-btn--selected,.dark .ai-chat-form-card__rating-btn--selected,[data-theme=dark] .ai-chat-form-card__rating-btn--selected{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-form-card__actions{align-items:center;border-top:1px solid var(--border-subtle,rgba(0,0,0,.08));display:flex;gap:8px;margin-top:16px;padding-top:16px}.ai-chat-widget.dark .ai-chat-form-card__actions,.chakra-ui-dark .ai-chat-form-card__actions,.dark .ai-chat-form-card__actions,[data-theme=dark] .ai-chat-form-card__actions{border-color:hsla(0,0%,100%,.08)}.ai-chat-form-card__actions-spacer{flex:1}.ai-chat-form-card__btn{border:none;border-radius:9999px;cursor:pointer;font-family:inherit;font-size:13px;font-weight:500;padding:8px 16px;transition:all .2s ease}.ai-chat-form-card__btn:disabled{cursor:not-allowed;opacity:.5}.ai-chat-form-card__btn--primary{background:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-form-card__btn--primary:hover:not(:disabled){opacity:.9;transform:translateY(-1px)}.ai-chat-form-card__btn--secondary{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);color:var(--text-primary,#3e3e3e)}.ai-chat-form-card__btn--secondary:hover:not(:disabled){border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-form-card__btn--secondary,.chakra-ui-dark .ai-chat-form-card__btn--secondary,.dark .ai-chat-form-card__btn--secondary,[data-theme=dark] .ai-chat-form-card__btn--secondary{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-form-card__btn--ghost{background:transparent;color:var(--text-muted,#71717a)}.ai-chat-form-card__btn--ghost:hover:not(:disabled){background:rgba(0,0,0,.05);color:var(--text-primary,#3e3e3e)}.ai-chat-widget.dark .ai-chat-form-card__btn--ghost:hover:not(:disabled),.chakra-ui-dark .ai-chat-form-card__btn--ghost:hover:not(:disabled),.dark .ai-chat-form-card__btn--ghost:hover:not(:disabled),[data-theme=dark] .ai-chat-form-card__btn--ghost:hover:not(:disabled){background:hsla(0,0%,100%,.05);color:#fff}.chat-fullpage{--fp-max-width:800px;--fp-padding-x:16px;--fp-padding-top-mobile:64px;--fp-padding-top-desktop:16px;--fp-padding-bottom:200px;--fp-input-bottom:0}.chat-fullpage .ai-chat-messages{background:transparent;height:100%;margin:0 auto;max-width:var(--fp-max-width);padding:var(--fp-padding-top-desktop) var(--fp-padding-x) var(--fp-padding-bottom)}@media (max-width:768px){.chat-fullpage .ai-chat-messages{padding-top:var(--fp-padding-top-mobile)}}.chat-fullpage .ai-chat-message{animation:none}.chat-fullpage .ai-chat-message.user{max-width:85%}.chat-fullpage .ai-chat-message.user .ai-chat-message-content{background:var(--bg-muted,#f4f4f5);border-radius:24px;color:#000;padding:8px 16px}.chat-fullpage.dark .ai-chat-message.user .ai-chat-message-content{background:var(--bg-muted,#27272a);color:#fff}.chat-fullpage .ai-chat-message.assistant{width:100%}.chat-fullpage .ai-chat-message.assistant .ai-chat-message-content{color:#000;padding:8px 16px}.chat-fullpage.dark .ai-chat-message.assistant .ai-chat-message-content{color:#fff}.chat-fullpage .ai-chat-message.tool{margin:0;padding:0;width:100%}.chat-fullpage .ai-chat-welcome{align-items:center;display:flex;flex-direction:column;gap:24px;justify-content:center;min-height:60vh;padding:24px;text-align:center}.chat-fullpage .ai-chat-welcome-title{font-size:32px;font-weight:600}.chat-fullpage .ai-chat-welcome-text{color:var(--text-muted,#71717a);font-size:18px;max-width:400px}.chat-fullpage .ai-chat-input-container{background:transparent;bottom:0;left:0;padding:16px 16px calc(16px + env(safe-area-inset-bottom));position:fixed;right:0;z-index:20}.chat-fullpage .ai-chat-input-container:after{background:var(--bg-primary,#fff);bottom:0;content:\"\";height:calc(40% + 16px);left:0;pointer-events:none;position:absolute;right:0;z-index:-1}.chat-fullpage.dark .ai-chat-input-container:after{background:var(--bg-primary,#18181b)}@media (min-width:769px){.chat-fullpage .ai-chat-input-container{background:transparent;bottom:var(--fp-input-bottom);left:50%;max-width:var(--fp-max-width);padding:0;position:absolute;right:auto;transform:translateX(-50%);width:100%}}.chat-fullpage .ai-chat-input-wrapper{background:var(--bg-muted,#f4f4f5);border:1px solid var(--border-muted,#e4e4e7);border-radius:24px;box-shadow:0 1px 8px rgba(0,0,0,.06);margin:0 auto;max-width:var(--fp-max-width)}.chat-fullpage.dark .ai-chat-input-wrapper{background:var(--bg-muted,#27272a);border-color:var(--border-muted,#3f3f46);box-shadow:0 1px 12px rgba(0,0,0,.25)}.chat-fullpage .ai-chat-scroll-button{bottom:100px}@media (min-width:769px){.chat-fullpage .ai-chat-scroll-button{bottom:90px}}.chat-fullpage .ai-chat-suggested-questions{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;max-width:600px}.chat-fullpage .ai-chat-suggested-question{border-radius:9999px;font-size:14px;padding:8px 16px}.chat-fullpage .ai-chat-follow-up-suggestions{margin-top:12px}.chat-fullpage .ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-default,#d4d4d8);color:#000}.chat-fullpage .ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#f4f4f5)}.chat-fullpage.dark .ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-subtle,#52525b);color:#fff}.chat-fullpage.dark .ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#3f3f46)}.chat-fullpage .ai-chat-typing{padding:8px 16px}@media (max-width:480px){body.ai-chat-widget-open{height:100%!important;overflow:hidden!important;position:fixed!important;touch-action:none!important;width:100%!important}.ai-chat-widget-container.is-open{height:100vh!important;height:100dvh!important;width:100vw!important;z-index:var(--widget-z-index,2147483647)!important}.ai-chat-widget-container.is-open,.ai-chat-widget-container.is-open .ai-chat-window{bottom:0!important;left:0!important;position:fixed!important;right:0!important;top:0!important}.ai-chat-widget-container.is-open .ai-chat-window{animation:none!important;border:none!important;border-radius:0!important;box-shadow:none!important;height:100%!important;max-height:100%!important;max-width:100%!important;outline:none!important;transform:none!important;width:100%!important}.ai-chat-widget-container.is-open .ai-chat-button{display:none!important;pointer-events:none!important;visibility:hidden!important}.ai-chat-widget-container.is-open .ai-chat-header{border-radius:0!important;flex-shrink:0;padding-left:max(16px,env(safe-area-inset-left));padding-right:max(16px,env(safe-area-inset-right));padding-top:max(12px,env(safe-area-inset-top));position:relative;z-index:100}.ai-chat-widget-container.is-open .ai-chat-messages{-webkit-overflow-scrolling:touch;flex:1;overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain;padding-bottom:120px;padding-left:max(16px,env(safe-area-inset-left));padding-right:max(16px,env(safe-area-inset-right));touch-action:pan-y}.ai-chat-widget-container.is-open .ai-chat-input-container{background:var(--bg-primary,#fff);bottom:0!important;left:0!important;padding:8px max(12px,env(safe-area-inset-right)) max(16px,calc(env(safe-area-inset-bottom) + 8px)) max(12px,env(safe-area-inset-left));position:fixed!important;right:0!important;z-index:100}.ai-chat-widget.dark .ai-chat-widget-container.is-open .ai-chat-input-container{background:var(--bg-primary,#282625)}.ai-chat-widget-container.is-open .ai-chat-input-container:after{display:none}.ai-chat-widget-container.is-open .ai-chat-input-wrapper{margin:0;max-width:100%}.ai-chat-widget-container.is-open .ai-chat-scroll-button{bottom:calc(80px + env(safe-area-inset-bottom))}.ai-chat-widget-container.is-open .ai-chat-welcome{padding:16px 0}.ai-chat-widget-container.is-open .ai-chat-welcome-title{font-size:24px}.ai-chat-widget-container.is-open .ai-chat-suggested-questions{align-items:stretch;flex-direction:column}.ai-chat-widget-container.is-open .ai-chat-suggested-question{text-align:center;width:100%}}@media (min-width:481px) and (max-width:768px){.ai-chat-widget-container.is-open .ai-chat-window{border-radius:22px 22px 44px 44px;max-height:calc(100vh - 100px);max-width:calc(100vw - 32px)}}";
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}";
47095
47921
  styleInject(css_248z$1);
47096
47922
 
47097
- var css_248z = ".ai-chat-data-policy-view{display:flex;flex:1;flex-direction:column;min-height:0;overflow:hidden}.ai-chat-data-policy-content{-webkit-overflow-scrolling:touch;flex:1;overflow-y:auto;padding:20px 16px 40px}.ai-chat-data-policy-intro{align-items:center;background:var(--bg-subtle,rgba(0,0,0,.02));border-radius:12px;display:flex;flex-direction:column;margin-bottom:20px;padding:16px;text-align:center}.ai-chat-widget.dark .ai-chat-data-policy-intro{background:var(--bg-subtle,hsla(0,0%,100%,.04))}.ai-chat-data-policy-icon{align-items:center;background:var(--primary-color,#07f);border-radius:12px;color:#fff;display:flex;height:48px;justify-content:center;margin-bottom:12px;width:48px}.ai-chat-data-policy-intro p{color:var(--text-secondary,#52525b);font-size:13px;line-height:1.5;margin:0}.ai-chat-widget.dark .ai-chat-data-policy-intro p{color:var(--text-secondary,#a1a1aa)}.ai-chat-data-policy-intro strong{color:var(--text-primary,#18181b)}.ai-chat-widget.dark .ai-chat-data-policy-intro strong{color:var(--text-primary,#fafafa)}.ai-chat-data-policy-section{margin-bottom:20px}.ai-chat-data-policy-section h3{color:var(--text-primary,#18181b);font-size:13px;font-weight:600;letter-spacing:.02em;margin:0 0 8px;text-transform:uppercase}.ai-chat-widget.dark .ai-chat-data-policy-section h3{color:var(--text-primary,#fafafa)}.ai-chat-data-policy-section ul{list-style:none;margin:0;padding:0}.ai-chat-data-policy-section li{color:var(--text-secondary,#52525b);font-size:12px;line-height:1.5;padding:8px 0 8px 16px;position:relative}.ai-chat-widget.dark .ai-chat-data-policy-section li{color:var(--text-secondary,#a1a1aa)}.ai-chat-data-policy-section li:before{background:var(--text-muted,#a1a1aa);border-radius:50%;content:\"\";height:4px;left:0;position:absolute;top:14px;width:4px}.ai-chat-data-policy-section li strong{color:var(--text-primary,#18181b)}.ai-chat-widget.dark .ai-chat-data-policy-section li strong{color:var(--text-primary,#fafafa)}.ai-chat-data-policy-section p{color:var(--text-secondary,#52525b);font-size:12px;line-height:1.5;margin:0}.ai-chat-widget.dark .ai-chat-data-policy-section p{color:var(--text-secondary,#a1a1aa)}.ai-chat-data-policy-warning{background:rgba(234,179,8,.1);border:1px solid rgba(234,179,8,.3);border-radius:8px;color:#92400e!important;padding:12px}.ai-chat-widget.dark .ai-chat-data-policy-warning{background:rgba(234,179,8,.15);border-color:rgba(234,179,8,.25);color:#fbbf24!important}";
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)}";
47098
47924
  styleInject(css_248z);
47099
47925
 
47100
- // Icon components mapping
47101
- const iconComponents = {
47102
- 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" }) })),
47103
- 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" }) })),
47104
- };
47105
- const ChatWidget = ({ widgetId, apiUrl = window.location.origin, previewMode = false, previewConfig, position = 'bottom-right', primaryColor, size, headerTitle, welcomeTitle, welcomeMessage, placeholder, welcomeBubbleText, theme, suggestedQuestions, customStyles, currentRoute, defaultOpen = false, zIndex, containerMode = false, onOpen, onClose, onMessage, onError, mode = 'bubble', }) => {
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', }) => {
47106
47927
  const [isOpen, setIsOpen] = reactExports.useState(defaultOpen);
47107
- const [autoDetectedTheme, setAutoDetectedTheme] = reactExports.useState('light');
47928
+ const [inputBarValue, setInputBarValue] = reactExports.useState('');
47108
47929
  const [showWelcomeBubble, setShowWelcomeBubble] = reactExports.useState(false);
47930
+ const [isInputBarCollapsed, setIsInputBarCollapsed] = reactExports.useState(false);
47109
47931
  const widgetRef = reactExports.useRef(null);
47110
47932
  const containerRef = reactExports.useRef(null);
47111
47933
  // Determine mode
@@ -47154,13 +47976,14 @@
47154
47976
  },
47155
47977
  };
47156
47978
  // Always call useChat hook (React rules), but skip initialization in preview mode
47979
+ const shouldSkipInit = previewMode;
47157
47980
  const chatHook = useChat({
47158
47981
  widgetId: previewMode ? '__preview__' : (widgetId || '__preview__'),
47159
47982
  apiUrl,
47160
47983
  currentRoute,
47161
- onMessage: previewMode ? undefined : onMessage,
47162
- onError: previewMode ? undefined : onError,
47163
- skipInitialization: previewMode, // Don't make API calls in preview mode
47984
+ onMessage: shouldSkipInit ? undefined : onMessage,
47985
+ onError: shouldSkipInit ? undefined : onError,
47986
+ skipInitialization: shouldSkipInit,
47164
47987
  });
47165
47988
  // Extract values from hook or use preview defaults
47166
47989
  const messages = previewMode ? [] : chatHook.messages;
@@ -47169,37 +47992,32 @@
47169
47992
  const config = previewMode ? mergedPreviewConfig : chatHook.config;
47170
47993
  const sendMessage = previewMode ? (() => Promise.resolve()) : chatHook.sendMessage;
47171
47994
  const submitFeedback = previewMode ? (() => Promise.resolve()) : chatHook.submitFeedback;
47995
+ const dismissAction = previewMode ? (() => Promise.resolve()) : chatHook.dismissAction;
47172
47996
  const conversations = previewMode ? [] : chatHook.conversations;
47173
47997
  const loadConversations = previewMode ? (() => { }) : chatHook.loadConversations;
47174
47998
  const switchConversation = previewMode ? (() => Promise.resolve()) : chatHook.switchConversation;
47175
47999
  const startNewConversation = previewMode ? (() => { }) : chatHook.startNewConversation;
47176
48000
  const deleteConversation = previewMode ? (() => { }) : chatHook.deleteConversation;
47177
48001
  const conversationId = previewMode ? '' : chatHook.conversationId;
47178
- // Auto-detect theme from background
47179
- reactExports.useEffect(() => {
47180
- if (!containerRef.current)
47181
- return;
47182
- // Initial detection
47183
- const detected = detectTheme(containerRef.current);
47184
- setAutoDetectedTheme(detected);
47185
- // Watch for theme changes on the page
47186
- const observer = createThemeObserver(containerRef.current, (newTheme) => {
47187
- setAutoDetectedTheme(newTheme);
47188
- });
47189
- // Also listen for system preference changes
47190
- const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
47191
- const handleMediaChange = () => {
47192
- if (containerRef.current) {
47193
- const detected = detectTheme(containerRef.current);
47194
- setAutoDetectedTheme(detected);
47195
- }
47196
- };
47197
- mediaQuery.addEventListener('change', handleMediaChange);
47198
- return () => {
47199
- observer.disconnect();
47200
- mediaQuery.removeEventListener('change', handleMediaChange);
47201
- };
47202
- }, [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
+ });
47203
48021
  // Check if device is mobile
47204
48022
  const isMobile = typeof window !== 'undefined' && window.innerWidth <= 480;
47205
48023
  // Handle auto-open (only for bubble mode, disabled on mobile)
@@ -47244,8 +48062,8 @@
47244
48062
  document.body.classList.remove('ai-chat-widget-open');
47245
48063
  };
47246
48064
  }, [isOpen, isEmbedded]);
47247
- // Handle welcome bubble visibility per session
47248
- // Shows on each new session if welcomeBubbleText is configured
48065
+ // Handle welcome bubble visibility based on frequency setting
48066
+ // Frequency options: 'always' (every page visit), 'session', 'weekly', 'monthly'
47249
48067
  reactExports.useEffect(() => {
47250
48068
  if (isEmbedded || previewMode)
47251
48069
  return;
@@ -47254,42 +48072,72 @@
47254
48072
  setShowWelcomeBubble(false);
47255
48073
  return;
47256
48074
  }
47257
- // Check if bubble was already dismissed this session
48075
+ const frequency = config?.appearance?.welcomeBubbleFrequency ?? 'session';
47258
48076
  const storageKey = `ai-chat-bubble-dismissed-${widgetId || 'default'}`;
47259
- const wasDismissed = sessionStorage.getItem(storageKey) === 'true';
47260
- if (!wasDismissed && !isOpen) {
48077
+ // Check if bubble should be shown based on frequency
48078
+ const shouldShowBubble = () => {
48079
+ if (frequency === 'always') {
48080
+ // Always show on every page visit (no storage check)
48081
+ return true;
48082
+ }
48083
+ if (frequency === 'session') {
48084
+ // Show once per session
48085
+ return sessionStorage.getItem(storageKey) !== 'true';
48086
+ }
48087
+ // For weekly/monthly, use localStorage with timestamp
48088
+ try {
48089
+ const stored = localStorage.getItem(storageKey);
48090
+ if (!stored)
48091
+ return true;
48092
+ const dismissedAt = parseInt(stored, 10);
48093
+ if (isNaN(dismissedAt))
48094
+ return true;
48095
+ const now = Date.now();
48096
+ const weekMs = 7 * 24 * 60 * 60 * 1000;
48097
+ const monthMs = 30 * 24 * 60 * 60 * 1000;
48098
+ if (frequency === 'weekly') {
48099
+ return now - dismissedAt > weekMs;
48100
+ }
48101
+ if (frequency === 'monthly') {
48102
+ return now - dismissedAt > monthMs;
48103
+ }
48104
+ }
48105
+ catch {
48106
+ return true;
48107
+ }
48108
+ return true;
48109
+ };
48110
+ if (shouldShowBubble() && !isOpen) {
47261
48111
  setShowWelcomeBubble(true);
47262
48112
  }
47263
48113
  }, [widgetId, welcomeBubbleText, config, isOpen, isEmbedded, previewMode]);
47264
- // Determine theme - use prop override if provided, otherwise auto-detect
47265
- const appearanceConfig = config?.appearance;
47266
- const effectiveTheme = theme ?? autoDetectedTheme;
47267
- // Determine position (prop override takes priority for live preview)
47268
- const effectivePosition = position || config?.appearance.position || 'bottom-right';
47269
- // Get accent color from prop or config (empty string means no accent color / vanilla mode)
47270
- const accentColor = primaryColor ?? appearanceConfig?.primaryColor ?? '';
47271
- // Apply prop overrides for live preview (props take priority over config)
47272
- size || appearanceConfig?.size || 'small';
47273
- const effectiveHeaderTitle = headerTitle ?? appearanceConfig?.headerTitle ?? '';
47274
- const effectiveWelcomeTitle = welcomeTitle ?? appearanceConfig?.welcomeTitle ?? '';
47275
- const effectiveWelcomeMessage = welcomeMessage ?? appearanceConfig?.welcomeMessage ?? '';
47276
- const effectivePlaceholder = placeholder ?? appearanceConfig?.placeholder ?? '';
47277
- const effectiveWelcomeBubbleText = welcomeBubbleText ?? appearanceConfig?.welcomeBubbleText ?? '';
47278
- // Generate styles using simplified theme system
47279
- const simpleAppearance = {
47280
- accentColor};
47281
- // Generate theme styles from accent color
47282
- const generatedStyles = generateThemeStyles(simpleAppearance, effectiveTheme);
47283
- // Also apply legacy styles for backward compatibility
47284
- const legacyStyles = appearanceConfig
47285
- ? applyAppearanceStyles(appearanceConfig)
47286
- : {};
47287
- // Merge styles (generated takes priority for new simplified system, then custom overrides)
47288
- const mergedStyles = {
47289
- ...legacyStyles,
47290
- ...generatedStyles,
47291
- ...customStyles,
47292
- ...(zIndex !== undefined ? { '--widget-z-index': String(zIndex) } : {}),
48114
+ const handleStartNewConversation = reactExports.useCallback(() => {
48115
+ startNewConversation();
48116
+ }, [startNewConversation]);
48117
+ const handleSendMessage = reactExports.useCallback((content) => {
48118
+ sendMessage(content);
48119
+ }, [sendMessage]);
48120
+ // Dismiss bubble and store based on frequency setting
48121
+ const dismissBubble = () => {
48122
+ setShowWelcomeBubble(false);
48123
+ const frequency = config?.appearance?.welcomeBubbleFrequency ?? 'session';
48124
+ const storageKey = `ai-chat-bubble-dismissed-${widgetId || 'default'}`;
48125
+ try {
48126
+ if (frequency === 'always') {
48127
+ // For 'always', use sessionStorage so it only hides until page refresh
48128
+ sessionStorage.setItem(storageKey, 'true');
48129
+ }
48130
+ else if (frequency === 'session') {
48131
+ sessionStorage.setItem(storageKey, 'true');
48132
+ }
48133
+ else {
48134
+ // For weekly/monthly, store timestamp in localStorage
48135
+ localStorage.setItem(storageKey, String(Date.now()));
48136
+ }
48137
+ }
48138
+ catch {
48139
+ // Ignore storage errors
48140
+ }
47293
48141
  };
47294
48142
  const handleToggle = () => {
47295
48143
  if (isEmbedded)
@@ -47298,15 +48146,7 @@
47298
48146
  setIsOpen(newState);
47299
48147
  // Dismiss welcome bubble when chat is opened
47300
48148
  if (newState && showWelcomeBubble) {
47301
- setShowWelcomeBubble(false);
47302
- // Store in sessionStorage so it doesn't show again this session
47303
- const storageKey = `ai-chat-bubble-dismissed-${widgetId || 'default'}`;
47304
- try {
47305
- sessionStorage.setItem(storageKey, 'true');
47306
- }
47307
- catch {
47308
- // Ignore storage errors
47309
- }
48149
+ dismissBubble();
47310
48150
  }
47311
48151
  if (newState) {
47312
48152
  onOpen?.();
@@ -47315,6 +48155,24 @@
47315
48155
  onClose?.();
47316
48156
  }
47317
48157
  };
48158
+ const handleDismissBubble = (e) => {
48159
+ e.stopPropagation();
48160
+ dismissBubble();
48161
+ };
48162
+ // Handle input bar submit - opens widget and sends message
48163
+ const handleInputBarSubmit = reactExports.useCallback((e) => {
48164
+ e.preventDefault();
48165
+ if (!inputBarValue.trim() || previewMode)
48166
+ return;
48167
+ // Open the widget
48168
+ setIsOpen(true);
48169
+ onOpen?.();
48170
+ // Send the message after a brief delay to allow widget to open
48171
+ setTimeout(() => {
48172
+ sendMessage(inputBarValue.trim());
48173
+ setInputBarValue('');
48174
+ }, 100);
48175
+ }, [inputBarValue, previewMode, onOpen, sendMessage]);
47318
48176
  const handleFeedback = async (messageId, feedback) => {
47319
48177
  await submitFeedback(messageId, feedback);
47320
48178
  };
@@ -47330,21 +48188,35 @@
47330
48188
  sendMessage(actionInstruction);
47331
48189
  };
47332
48190
  // Don't render until config is loaded to avoid flash of unstyled content
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
47333
48195
  // In preview mode, config is always available
47334
- if (!config && !previewMode) {
48196
+ const hasInitialStyling = !!primaryColor;
48197
+ const canRenderWithoutConfig = !!triggerType || hasInitialStyling;
48198
+ if (!config && !previewMode && !canRenderWithoutConfig) {
47335
48199
  return null;
47336
48200
  }
47337
48201
  // Get button icon based on state
47338
48202
  const IconComponent = isOpen ? iconComponents.FiChevronDown : iconComponents.FiMessageCircle;
47339
48203
  // Embedded mode renders directly without wrapper positioning
47340
48204
  if (isEmbedded) {
47341
- 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, conversations: conversations, onLoadConversations: loadConversations, onSwitchConversation: switchConversation, onStartNewConversation: startNewConversation, onDeleteConversation: deleteConversation, currentConversationId: conversationId, headerTitleOverride: effectiveHeaderTitle, welcomeTitleOverride: effectiveWelcomeTitle, welcomeMessageOverride: effectiveWelcomeMessage, placeholderOverride: effectivePlaceholder, suggestedQuestionsOverride: suggestedQuestions }) }));
47342
- }
47343
- 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' : ''}`, children: [isOpen && (jsxRuntimeExports.jsx(ChatWindow, { messages: messages, isLoading: isLoading, isTyping: isTyping, config: config, onSendMessage: sendMessage, onClose: handleToggle, onFeedback: handleFeedback, onActionClick: handleActionClick,
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 }) }));
48206
+ }
48207
+ // Determine trigger class for container
48208
+ const triggerClass = effectiveTriggerType === 'pill-text'
48209
+ ? 'trigger-pill-text'
48210
+ : effectiveTriggerType === 'input-bar'
48211
+ ? 'trigger-input-bar'
48212
+ : 'trigger-button';
48213
+ // Size class for CSS targeting (used by input-bar trigger for width matching)
48214
+ const sizeClass = `size-${effectiveSize}`;
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,
47344
48218
  // Chat history props (only active when persistConversation is true)
47345
- conversations: conversations, onLoadConversations: loadConversations, onSwitchConversation: switchConversation, onStartNewConversation: startNewConversation, onDeleteConversation: deleteConversation, currentConversationId: conversationId,
47346
- // Override props for live preview
47347
- headerTitleOverride: effectiveHeaderTitle, welcomeTitleOverride: effectiveWelcomeTitle, welcomeMessageOverride: effectiveWelcomeMessage, placeholderOverride: effectivePlaceholder, suggestedQuestionsOverride: suggestedQuestions })), !isOpen && effectiveWelcomeBubbleText && (previewMode || showWelcomeBubble) && (jsxRuntimeExports.jsx("div", { className: "ai-chat-welcome-bubble", onClick: handleToggle, children: jsxRuntimeExports.jsx("span", { children: effectiveWelcomeBubbleText }) })), 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, {}) }) })] }) }));
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 })] }) }));
47348
48220
  };
47349
48221
 
47350
48222
  /**