@chatwidgetai/chat-widget 0.3.6 → 0.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-chat-widget.umd.js +1562 -1380
- package/dist/ai-chat-widget.umd.js.map +1 -1
- package/dist/api/client.d.ts +12 -2
- package/dist/api/client.d.ts.map +1 -1
- package/dist/components/ChatWidget/hooks/useWidgetAppearance.d.ts +37 -0
- package/dist/components/ChatWidget/hooks/useWidgetAppearance.d.ts.map +1 -0
- package/dist/components/ChatWidget/icons.d.ts +2 -0
- package/dist/components/ChatWidget/icons.d.ts.map +1 -0
- package/dist/components/ChatWidget/parts/WidgetTriggers.d.ts +25 -0
- package/dist/components/ChatWidget/parts/WidgetTriggers.d.ts.map +1 -0
- package/dist/components/ChatWidget.d.ts.map +1 -1
- package/dist/components/ChatWindow.d.ts +4 -1
- package/dist/components/ChatWindow.d.ts.map +1 -1
- package/dist/components/WelcomeBubble.d.ts +12 -0
- package/dist/components/WelcomeBubble.d.ts.map +1 -0
- package/dist/components/icons.d.ts +21 -0
- package/dist/components/icons.d.ts.map +1 -0
- package/dist/components/triggers/ButtonTrigger.d.ts +11 -0
- package/dist/components/triggers/ButtonTrigger.d.ts.map +1 -0
- package/dist/components/triggers/InputBarTrigger.d.ts +18 -0
- package/dist/components/triggers/InputBarTrigger.d.ts.map +1 -0
- package/dist/components/triggers/PillTrigger.d.ts +12 -0
- package/dist/components/triggers/PillTrigger.d.ts.map +1 -0
- package/dist/components/triggers/index.d.ts +8 -0
- package/dist/components/triggers/index.d.ts.map +1 -0
- package/dist/hooks/useChat/action-handler.d.ts +17 -1
- package/dist/hooks/useChat/action-handler.d.ts.map +1 -1
- package/dist/hooks/useChat/index.d.ts +5 -0
- package/dist/hooks/useChat/index.d.ts.map +1 -1
- package/dist/hooks/useChat/message-hydration.d.ts.map +1 -1
- package/dist/hooks/useChat/stream-buffer.d.ts +18 -0
- package/dist/hooks/useChat/stream-buffer.d.ts.map +1 -0
- package/dist/hooks/useChat/stream-handlers.d.ts +3 -3
- package/dist/hooks/useChat/stream-handlers.d.ts.map +1 -1
- package/dist/hooks/useChat/stream-state.d.ts.map +1 -1
- package/dist/hooks/useChat/types.d.ts +2 -0
- package/dist/hooks/useChat/types.d.ts.map +1 -1
- package/dist/index.esm.js +1562 -1380
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1562 -1380
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.ts +5 -92
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -16898,58 +16898,83 @@
|
|
|
16898
16898
|
return typeof data === 'object' && data !== null && 'type' in data;
|
|
16899
16899
|
});
|
|
16900
16900
|
}
|
|
16901
|
-
async *
|
|
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/
|
|
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
|
-
|
|
16915
|
-
timeZone: this.getTimeZone(),
|
|
16914
|
+
reason: "user",
|
|
16916
16915
|
}),
|
|
16917
16916
|
signal,
|
|
16918
16917
|
});
|
|
16918
|
+
if (response.status === 204) {
|
|
16919
|
+
return;
|
|
16920
|
+
}
|
|
16919
16921
|
if (!response.ok) {
|
|
16920
|
-
throw await buildApiError(response, 'Failed to
|
|
16922
|
+
throw await buildApiError(response, 'Failed to dismiss action');
|
|
16921
16923
|
}
|
|
16922
16924
|
yield* parseSSEStream(response, (data) => {
|
|
16923
16925
|
return typeof data === 'object' && data !== null && 'type' in data;
|
|
16924
16926
|
});
|
|
16925
16927
|
}
|
|
16926
|
-
|
|
16928
|
+
/**
|
|
16929
|
+
* Continue agent after halting action completes
|
|
16930
|
+
* Call this when frontend completes an action and wants to pass result back to agent
|
|
16931
|
+
*/
|
|
16932
|
+
async *continueAgentAction(conversationId, toolCallId, body, signal) {
|
|
16927
16933
|
const headers = {
|
|
16928
16934
|
'Content-Type': 'application/json',
|
|
16929
16935
|
};
|
|
16930
16936
|
if (this.config.currentRoute) {
|
|
16931
16937
|
headers['X-Current-Route'] = this.config.currentRoute;
|
|
16932
16938
|
}
|
|
16933
|
-
const response = await fetch(`${this.config.apiUrl}/api/widget/${this.config.widgetId}/agent/
|
|
16939
|
+
const response = await fetch(`${this.config.apiUrl}/api/widget/${this.config.widgetId}/agent/continue`, {
|
|
16934
16940
|
method: 'POST',
|
|
16935
16941
|
headers,
|
|
16936
16942
|
body: JSON.stringify({
|
|
16937
|
-
conversationId
|
|
16943
|
+
conversationId,
|
|
16938
16944
|
toolCallId,
|
|
16939
|
-
|
|
16945
|
+
body,
|
|
16946
|
+
timeZone: this.getTimeZone(),
|
|
16940
16947
|
}),
|
|
16941
16948
|
signal,
|
|
16942
16949
|
});
|
|
16943
|
-
if (response.status === 204) {
|
|
16944
|
-
return;
|
|
16945
|
-
}
|
|
16946
16950
|
if (!response.ok) {
|
|
16947
|
-
throw await buildApiError(response, 'Failed to
|
|
16951
|
+
throw await buildApiError(response, 'Failed to continue agent action');
|
|
16948
16952
|
}
|
|
16949
16953
|
yield* parseSSEStream(response, (data) => {
|
|
16950
16954
|
return typeof data === 'object' && data !== null && 'type' in data;
|
|
16951
16955
|
});
|
|
16952
16956
|
}
|
|
16957
|
+
/**
|
|
16958
|
+
* NEW: Call action endpoint (frontend-owned flow)
|
|
16959
|
+
* Used for multi-step actions like booking appointments
|
|
16960
|
+
*/
|
|
16961
|
+
async callActionEndpoint(actionId, endpoint, input, token) {
|
|
16962
|
+
const headers = {
|
|
16963
|
+
'Content-Type': 'application/json',
|
|
16964
|
+
};
|
|
16965
|
+
if (token) {
|
|
16966
|
+
headers['Authorization'] = `Bearer ${token}`;
|
|
16967
|
+
}
|
|
16968
|
+
const response = await fetch(`${this.config.apiUrl}/api/widget/${this.config.widgetId}/actions/${actionId}/${endpoint}`, {
|
|
16969
|
+
method: 'POST',
|
|
16970
|
+
headers,
|
|
16971
|
+
body: JSON.stringify(input),
|
|
16972
|
+
});
|
|
16973
|
+
if (!response.ok) {
|
|
16974
|
+
throw await buildApiError(response, `Action endpoint '${endpoint}' failed`);
|
|
16975
|
+
}
|
|
16976
|
+
return response.json();
|
|
16977
|
+
}
|
|
16953
16978
|
/**
|
|
16954
16979
|
* Submit feedback for a message
|
|
16955
16980
|
*/
|
|
@@ -16980,7 +17005,8 @@
|
|
|
16980
17005
|
}
|
|
16981
17006
|
/**
|
|
16982
17007
|
* Generate follow-up suggestions based on conversation context and available actions.
|
|
16983
|
-
*
|
|
17008
|
+
* @deprecated Follow-ups are now generated server-side in parallel and included in the done event.
|
|
17009
|
+
* This method is kept for backwards compatibility but is no longer called by the widget.
|
|
16984
17010
|
*/
|
|
16985
17011
|
async generateFollowUps(messages, actionIds) {
|
|
16986
17012
|
try {
|
|
@@ -43844,7 +43870,7 @@
|
|
|
43844
43870
|
}
|
|
43845
43871
|
|
|
43846
43872
|
// Styles are provided by global messages.css - no component-specific CSS needed
|
|
43847
|
-
function ChevronDownIcon() {
|
|
43873
|
+
function ChevronDownIcon$1() {
|
|
43848
43874
|
return (jsxRuntimeExports.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("polyline", { points: "6 9 12 15 18 9" }) }));
|
|
43849
43875
|
}
|
|
43850
43876
|
function ScrollButton({ onClick, visible, className = '' }) {
|
|
@@ -43853,7 +43879,7 @@
|
|
|
43853
43879
|
visible && 'visible',
|
|
43854
43880
|
className,
|
|
43855
43881
|
].filter(Boolean).join(' ');
|
|
43856
|
-
return (jsxRuntimeExports.jsx("button", { type: "button", className: classes, onClick: onClick, "aria-label": "Scroll to bottom", children: jsxRuntimeExports.jsx(ChevronDownIcon, {}) }));
|
|
43882
|
+
return (jsxRuntimeExports.jsx("button", { type: "button", className: classes, onClick: onClick, "aria-label": "Scroll to bottom", children: jsxRuntimeExports.jsx(ChevronDownIcon$1, {}) }));
|
|
43857
43883
|
}
|
|
43858
43884
|
|
|
43859
43885
|
const formatToolName = (name) => {
|
|
@@ -43865,13 +43891,23 @@
|
|
|
43865
43891
|
.join(' ');
|
|
43866
43892
|
};
|
|
43867
43893
|
function ToolIndicator({ badges, className = '' }) {
|
|
43868
|
-
|
|
43894
|
+
// Consolidate multiple badges into a single status indicator
|
|
43895
|
+
const hasLoading = badges.some(b => b.status === 'loading');
|
|
43896
|
+
const hasError = badges.some(b => b.status === 'error');
|
|
43897
|
+
const status = hasLoading ? 'loading' : hasError ? 'error' : 'completed';
|
|
43898
|
+
// Show only the most relevant badge name, or count if multiple
|
|
43899
|
+
const displayName = badges.length === 1
|
|
43900
|
+
? formatToolName(badges[0].name)
|
|
43901
|
+
: badges.length > 1
|
|
43902
|
+
? `${badges.length} actions`
|
|
43903
|
+
: 'Processing';
|
|
43904
|
+
return (jsxRuntimeExports.jsx("div", { className: `ai-chat-tool-row ${className}`, children: jsxRuntimeExports.jsx("div", { className: "ai-chat-tool-badges", children: jsxRuntimeExports.jsx("div", { className: `ai-chat-tool-badge ${status}`, children: jsxRuntimeExports.jsx("span", { className: "tool-name", children: displayName }) }) }) }));
|
|
43869
43905
|
}
|
|
43870
43906
|
|
|
43871
43907
|
// SVG Icon components
|
|
43872
43908
|
const ThumbsUpIcon = () => (jsxRuntimeExports.jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("path", { d: "M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3" }) }));
|
|
43873
43909
|
const ThumbsDownIcon = () => (jsxRuntimeExports.jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("path", { d: "M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17" }) }));
|
|
43874
|
-
const CheckIcon$
|
|
43910
|
+
const CheckIcon$1 = () => (jsxRuntimeExports.jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("polyline", { points: "20 6 9 17 4 12" }) }));
|
|
43875
43911
|
const FeedbackButtons = ({ messageId, currentFeedback, onFeedback, }) => {
|
|
43876
43912
|
const [isSubmitting, setIsSubmitting] = reactExports.useState(false);
|
|
43877
43913
|
const [submitted, setSubmitted] = reactExports.useState(false);
|
|
@@ -43892,7 +43928,7 @@
|
|
|
43892
43928
|
setIsSubmitting(false);
|
|
43893
43929
|
}
|
|
43894
43930
|
};
|
|
43895
|
-
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-feedback ${submitted ? 'submitted' : ''}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-feedback-buttons", children: [jsxRuntimeExports.jsx("button", { className: `ai-chat-feedback-button ${currentFeedback === 'positive' ? 'active' : ''}`, onClick: () => handleFeedback('positive'), disabled: isDisabled, "aria-label": "Helpful", title: "This was helpful", children: jsxRuntimeExports.jsx(ThumbsUpIcon, {}) }), jsxRuntimeExports.jsx("button", { className: `ai-chat-feedback-button ${currentFeedback === 'negative' ? 'active' : ''}`, onClick: () => handleFeedback('negative'), disabled: isDisabled, "aria-label": "Not helpful", title: "This was not helpful", children: jsxRuntimeExports.jsx(ThumbsDownIcon, {}) })] }), submitted && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-feedback-message", "aria-live": "polite", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-feedback-checkmark", children: jsxRuntimeExports.jsx(CheckIcon$
|
|
43931
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-feedback ${submitted ? 'submitted' : ''}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-feedback-buttons", children: [jsxRuntimeExports.jsx("button", { className: `ai-chat-feedback-button ${currentFeedback === 'positive' ? 'active' : ''}`, onClick: () => handleFeedback('positive'), disabled: isDisabled, "aria-label": "Helpful", title: "This was helpful", children: jsxRuntimeExports.jsx(ThumbsUpIcon, {}) }), jsxRuntimeExports.jsx("button", { className: `ai-chat-feedback-button ${currentFeedback === 'negative' ? 'active' : ''}`, onClick: () => handleFeedback('negative'), disabled: isDisabled, "aria-label": "Not helpful", title: "This was not helpful", children: jsxRuntimeExports.jsx(ThumbsDownIcon, {}) })] }), submitted && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-feedback-message", "aria-live": "polite", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-feedback-checkmark", children: jsxRuntimeExports.jsx(CheckIcon$1, {}) }), jsxRuntimeExports.jsx("span", { className: "ai-chat-feedback-text", children: "Thanks for feedback" })] }))] }));
|
|
43896
43932
|
};
|
|
43897
43933
|
|
|
43898
43934
|
const Message = ({ message, showTimestamp = true, enableFeedback = true, onFeedback, }) => {
|
|
@@ -43921,9 +43957,11 @@
|
|
|
43921
43957
|
const hasContent = aiContent.trim().length > 0;
|
|
43922
43958
|
if (!hasContent)
|
|
43923
43959
|
return null;
|
|
43924
|
-
|
|
43960
|
+
// Only show timestamp and feedback when message is complete (not streaming)
|
|
43961
|
+
const isComplete = !message.isStreaming;
|
|
43962
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-message assistant ${isError ? 'error' : ''} ${message.isStreaming ? 'streaming' : ''}`, children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-message-content", children: jsxRuntimeExports.jsx(Markdown, { remarkPlugins: [remarkGfm], components: {
|
|
43925
43963
|
table: ({ children, ...props }) => (jsxRuntimeExports.jsx("div", { className: "table-wrapper", children: jsxRuntimeExports.jsx("div", { className: "table-scroll", children: jsxRuntimeExports.jsx("table", { ...props, children: children }) }) })),
|
|
43926
|
-
}, children: aiContent }) }), showTimestamp && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-message-meta", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-message-timestamp", children: formatTime(message.timestamp) }), enableFeedback && onFeedback && (jsxRuntimeExports.jsx(FeedbackButtons, { messageId: message.id, currentFeedback: message.feedback, onFeedback: onFeedback }))] }))] }));
|
|
43964
|
+
}, children: aiContent }) }), showTimestamp && isComplete && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-message-meta", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-message-timestamp", children: formatTime(message.timestamp) }), enableFeedback && onFeedback && (jsxRuntimeExports.jsx(FeedbackButtons, { messageId: message.id, currentFeedback: message.feedback, onFeedback: onFeedback }))] }))] }));
|
|
43927
43965
|
}
|
|
43928
43966
|
// System message rendering
|
|
43929
43967
|
if (isSystem) {
|
|
@@ -43943,7 +43981,7 @@
|
|
|
43943
43981
|
return false;
|
|
43944
43982
|
const TERMINAL_STATUSES = [
|
|
43945
43983
|
'completed', 'booked', 'scheduled', 'cancelled', 'failed', 'error',
|
|
43946
|
-
'displaying', 'clicked', 'contacted', 'submitted', 'sent'
|
|
43984
|
+
'displaying', 'displayed', 'clicked', 'contacted', 'submitted', 'sent'
|
|
43947
43985
|
];
|
|
43948
43986
|
const status = state.status;
|
|
43949
43987
|
if (typeof status === 'string' && TERMINAL_STATUSES.includes(status)) {
|
|
@@ -43962,10 +44000,10 @@
|
|
|
43962
44000
|
return false;
|
|
43963
44001
|
if (message.isStreaming)
|
|
43964
44002
|
return true;
|
|
43965
|
-
const
|
|
43966
|
-
return !isActionComplete(
|
|
44003
|
+
const input = message.action.input;
|
|
44004
|
+
return !isActionComplete(input);
|
|
43967
44005
|
}
|
|
43968
|
-
const ToolMessageGroup = ({ messages, getActionRenderer, showToolIndicator = true, accentColor, variant, onActionDismiss, }) => {
|
|
44006
|
+
const ToolMessageGroup = ({ messages, getActionRenderer, showToolIndicator = true, accentColor, variant, onActionDismiss, onCallEndpoint, }) => {
|
|
43969
44007
|
const visibleMessages = messages.filter(message => !message.action?.hidden);
|
|
43970
44008
|
const actionMessages = visibleMessages.filter(message => message.action);
|
|
43971
44009
|
// Debug logging
|
|
@@ -43989,7 +44027,7 @@
|
|
|
43989
44027
|
implementation: impl,
|
|
43990
44028
|
hasRenderer: !!renderer,
|
|
43991
44029
|
rendererType: renderer ? typeof renderer : 'undefined',
|
|
43992
|
-
|
|
44030
|
+
input: msg.action?.input,
|
|
43993
44031
|
});
|
|
43994
44032
|
});
|
|
43995
44033
|
// If tool indicator is hidden AND there are no action cards to render, don't render anything
|
|
@@ -44016,7 +44054,7 @@
|
|
|
44016
44054
|
console.log('[ToolMessageGroup] No renderer for:', message.action.implementation);
|
|
44017
44055
|
return null;
|
|
44018
44056
|
}
|
|
44019
|
-
return (jsxRuntimeExports.jsx("div", { className: "ai-chat-tool-action", children: renderer(message, accentColor, variant, onActionDismiss) }, `action-${message.id}`));
|
|
44057
|
+
return (jsxRuntimeExports.jsx("div", { className: "ai-chat-tool-action", children: renderer(message, accentColor, variant, onActionDismiss, onCallEndpoint) }, `action-${message.id}`));
|
|
44020
44058
|
})] }));
|
|
44021
44059
|
};
|
|
44022
44060
|
|
|
@@ -44050,12 +44088,29 @@
|
|
|
44050
44088
|
};
|
|
44051
44089
|
|
|
44052
44090
|
const MAX_TEXT_LENGTH = 40;
|
|
44091
|
+
const STAGGER_DELAY_MS = 200; // Delay between each suggestion appearing
|
|
44053
44092
|
const FollowUpSuggestions = ({ suggestions, onQuestionClick, onActionClick, accentColor, }) => {
|
|
44054
|
-
|
|
44055
|
-
return null;
|
|
44056
|
-
}
|
|
44093
|
+
const [visibleIndices, setVisibleIndices] = reactExports.useState(new Set());
|
|
44057
44094
|
// Filter out empty suggestions
|
|
44058
|
-
const validSuggestions = suggestions
|
|
44095
|
+
const validSuggestions = suggestions?.filter(s => s && s.text && s.text.trim()) || [];
|
|
44096
|
+
// Create a stable key for the current suggestions set
|
|
44097
|
+
const suggestionsKey = validSuggestions.map(s => s.id).join(',');
|
|
44098
|
+
// Stagger reveal each suggestion one at a time
|
|
44099
|
+
reactExports.useEffect(() => {
|
|
44100
|
+
// Reset when suggestions change
|
|
44101
|
+
setVisibleIndices(new Set());
|
|
44102
|
+
if (validSuggestions.length === 0)
|
|
44103
|
+
return;
|
|
44104
|
+
const timers = [];
|
|
44105
|
+
// Reveal each suggestion one by one
|
|
44106
|
+
validSuggestions.slice(0, 5).forEach((_, index) => {
|
|
44107
|
+
const timer = setTimeout(() => {
|
|
44108
|
+
setVisibleIndices(prev => new Set([...prev, index]));
|
|
44109
|
+
}, (index + 1) * STAGGER_DELAY_MS);
|
|
44110
|
+
timers.push(timer);
|
|
44111
|
+
});
|
|
44112
|
+
return () => timers.forEach(t => clearTimeout(t));
|
|
44113
|
+
}, [suggestionsKey]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
44059
44114
|
if (validSuggestions.length === 0) {
|
|
44060
44115
|
return null;
|
|
44061
44116
|
}
|
|
@@ -44063,8 +44118,12 @@
|
|
|
44063
44118
|
? { "--primary-color": accentColor }
|
|
44064
44119
|
: undefined;
|
|
44065
44120
|
const trimText = (text) => text.length > MAX_TEXT_LENGTH ? `${text.slice(0, MAX_TEXT_LENGTH)}...` : text;
|
|
44066
|
-
return (jsxRuntimeExports.jsx("div", { className: "ai-chat-follow-up-suggestions", style: containerStyle, children: jsxRuntimeExports.jsx("div", { className: "ai-chat-follow-up-list", children: validSuggestions.slice(0, 5).map((suggestion) => {
|
|
44121
|
+
return (jsxRuntimeExports.jsx("div", { className: "ai-chat-follow-up-suggestions", style: containerStyle, children: jsxRuntimeExports.jsx("div", { className: "ai-chat-follow-up-list", children: validSuggestions.slice(0, 5).map((suggestion, index) => {
|
|
44067
44122
|
const isActionSuggestion = suggestion.type === 'action';
|
|
44123
|
+
const isVisible = visibleIndices.has(index);
|
|
44124
|
+
// Only render if visible - this adds items one by one instead of showing all at once
|
|
44125
|
+
if (!isVisible)
|
|
44126
|
+
return null;
|
|
44068
44127
|
const className = `ai-chat-follow-up-item ${isActionSuggestion ? 'action-type' : 'question-type'}`;
|
|
44069
44128
|
const handleClick = () => {
|
|
44070
44129
|
if (isActionSuggestion && onActionClick) {
|
|
@@ -44078,7 +44137,7 @@
|
|
|
44078
44137
|
};
|
|
44079
44138
|
|
|
44080
44139
|
const MessageList = (props) => {
|
|
44081
|
-
const { messages, isTyping = false, showTypingIndicator = true, showTimestamps = true, showToolCalls = false, enableFeedback = true, welcomeTitle, welcomeMessage, suggestedQuestions, accentColor, onSuggestedQuestionClick, onActionClick, onActionDismiss, onFeedback, onScrollStateChange, getActionRenderer, variant, } = props;
|
|
44140
|
+
const { messages, isTyping = false, showTypingIndicator = true, showTimestamps = true, showToolCalls = false, enableFeedback = true, welcomeTitle, welcomeMessage, suggestedQuestions, accentColor, onSuggestedQuestionClick, onActionClick, onActionDismiss, onFeedback, onScrollStateChange, getActionRenderer, onCallEndpoint, variant, } = props;
|
|
44082
44141
|
const containerRef = reactExports.useRef(null);
|
|
44083
44142
|
const messagesEndRef = reactExports.useRef(null);
|
|
44084
44143
|
const [showScrollButton, setShowScrollButton] = reactExports.useState(false);
|
|
@@ -44089,24 +44148,31 @@
|
|
|
44089
44148
|
const lastToolMsg = [...visibleMessages].reverse().find(msg => msg.message.role === 'tool');
|
|
44090
44149
|
return lastToolMsg?.action && lastToolMsg.action.done !== true;
|
|
44091
44150
|
}, [visibleMessages]);
|
|
44092
|
-
const checkScrollPosition = reactExports.useCallback(() => {
|
|
44093
|
-
const c = containerRef.current;
|
|
44094
|
-
if (!c)
|
|
44095
|
-
return;
|
|
44096
|
-
const pb = parseInt(getComputedStyle(c).paddingBottom || '0', 10);
|
|
44097
|
-
setShowScrollButton(c.scrollHeight - c.scrollTop - c.clientHeight - pb > 24);
|
|
44098
|
-
}, []);
|
|
44099
44151
|
const scrollToBottom = reactExports.useCallback(() => {
|
|
44100
44152
|
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
|
|
44101
44153
|
}, []);
|
|
44102
|
-
|
|
44154
|
+
// Use IntersectionObserver to detect when the end marker is visible
|
|
44155
|
+
// This is more reliable than scroll position calculations
|
|
44103
44156
|
reactExports.useEffect(() => {
|
|
44104
|
-
const
|
|
44105
|
-
|
|
44157
|
+
const endMarker = messagesEndRef.current;
|
|
44158
|
+
const container = containerRef.current;
|
|
44159
|
+
if (!endMarker || !container)
|
|
44106
44160
|
return;
|
|
44107
|
-
|
|
44108
|
-
|
|
44109
|
-
|
|
44161
|
+
const observer = new IntersectionObserver((entries) => {
|
|
44162
|
+
// If the end marker is intersecting (visible), hide the button
|
|
44163
|
+
// If it's not visible, show the button
|
|
44164
|
+
const isAtBottom = entries[0]?.isIntersecting ?? false;
|
|
44165
|
+
setShowScrollButton(!isAtBottom);
|
|
44166
|
+
}, {
|
|
44167
|
+
root: container,
|
|
44168
|
+
// rootMargin adds extra space - if end marker is within 100px of viewport, consider it "visible"
|
|
44169
|
+
rootMargin: '0px 0px 100px 0px',
|
|
44170
|
+
threshold: 0,
|
|
44171
|
+
});
|
|
44172
|
+
observer.observe(endMarker);
|
|
44173
|
+
return () => observer.disconnect();
|
|
44174
|
+
}, []);
|
|
44175
|
+
reactExports.useEffect(() => { onScrollStateChange?.(showScrollButton, scrollToBottom); }, [showScrollButton, scrollToBottom, onScrollStateChange]);
|
|
44110
44176
|
reactExports.useEffect(() => {
|
|
44111
44177
|
const c = containerRef.current;
|
|
44112
44178
|
if (!c)
|
|
@@ -44121,32 +44187,18 @@
|
|
|
44121
44187
|
if ((isNew || isTyping) && c.scrollHeight - c.scrollTop - c.clientHeight < 150) {
|
|
44122
44188
|
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
|
|
44123
44189
|
}
|
|
44124
|
-
|
|
44125
|
-
}, [visibleMessages, isTyping, checkScrollPosition]);
|
|
44190
|
+
}, [visibleMessages, isTyping]);
|
|
44126
44191
|
const groupedMessages = reactExports.useMemo(() => {
|
|
44127
|
-
console.log('[DEBUG MessageList] ========================================');
|
|
44128
|
-
console.log('[DEBUG MessageList] Processing messages:', visibleMessages.length);
|
|
44129
|
-
visibleMessages.forEach((m, i) => {
|
|
44130
|
-
console.log(`[DEBUG MessageList] Message ${i}:`, {
|
|
44131
|
-
id: m.id,
|
|
44132
|
-
role: m.message.role,
|
|
44133
|
-
hasAction: !!m.action,
|
|
44134
|
-
actionImpl: m.action?.implementation,
|
|
44135
|
-
content: (m.message.content || '').substring(0, 50),
|
|
44136
|
-
});
|
|
44137
|
-
});
|
|
44138
44192
|
const result = [];
|
|
44139
44193
|
let toolGroup = [];
|
|
44140
44194
|
const flush = () => {
|
|
44141
44195
|
if (toolGroup.length) {
|
|
44142
|
-
console.log('[DEBUG MessageList] Flushing tool group with', toolGroup.length, 'messages');
|
|
44143
44196
|
result.push({ type: 'tool-group', messages: [...toolGroup] });
|
|
44144
44197
|
toolGroup = [];
|
|
44145
44198
|
}
|
|
44146
44199
|
};
|
|
44147
44200
|
for (const m of visibleMessages) {
|
|
44148
44201
|
if (m.message.role === 'tool') {
|
|
44149
|
-
console.log('[DEBUG MessageList] Adding to tool group:', m.id);
|
|
44150
44202
|
toolGroup.push(m);
|
|
44151
44203
|
}
|
|
44152
44204
|
else if (m.message.role === 'user') {
|
|
@@ -44168,27 +44220,26 @@
|
|
|
44168
44220
|
}
|
|
44169
44221
|
}
|
|
44170
44222
|
flush();
|
|
44171
|
-
console.log('[DEBUG MessageList] Final grouped result:', result.length, 'items');
|
|
44172
|
-
result.forEach((item, i) => {
|
|
44173
|
-
if (item.type === 'tool-group') {
|
|
44174
|
-
console.log(`[DEBUG MessageList] Group ${i}: tool-group with ${item.messages.length} messages`);
|
|
44175
|
-
}
|
|
44176
|
-
else {
|
|
44177
|
-
console.log(`[DEBUG MessageList] Group ${i}: message (${item.message.message.role})`);
|
|
44178
|
-
}
|
|
44179
|
-
});
|
|
44180
44223
|
return result;
|
|
44181
44224
|
}, [visibleMessages]);
|
|
44225
|
+
// Get the last assistant message's suggestions for rendering at the end
|
|
44226
|
+
const lastAssistantSuggestions = reactExports.useMemo(() => {
|
|
44227
|
+
for (let i = groupedMessages.length - 1; i >= 0; i--) {
|
|
44228
|
+
const item = groupedMessages[i];
|
|
44229
|
+
if (item.type === 'message' && item.message.message.role === 'assistant') {
|
|
44230
|
+
return item.message.suggestions;
|
|
44231
|
+
}
|
|
44232
|
+
}
|
|
44233
|
+
return undefined;
|
|
44234
|
+
}, [groupedMessages]);
|
|
44182
44235
|
const hasSuggestions = visibleMessages.length === 0 && onSuggestedQuestionClick && suggestedQuestions?.length;
|
|
44183
44236
|
const showWelcome = welcomeTitle || welcomeMessage || hasSuggestions;
|
|
44184
44237
|
return (jsxRuntimeExports.jsxs("div", { ref: containerRef, className: "ai-chat-messages", role: "log", "aria-live": "polite", children: [showWelcome && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-welcome", children: [welcomeTitle && jsxRuntimeExports.jsx("div", { className: "ai-chat-welcome-title", children: welcomeTitle }), welcomeMessage && jsxRuntimeExports.jsx("div", { className: "ai-chat-welcome-text", children: welcomeMessage }), hasSuggestions && jsxRuntimeExports.jsx(SuggestedQuestions, { questions: suggestedQuestions, onQuestionClick: onSuggestedQuestionClick })] })), groupedMessages.map((item, i) => {
|
|
44185
44238
|
if (item.type === 'tool-group') {
|
|
44186
|
-
return (jsxRuntimeExports.jsx(ToolMessageGroup, { messages: item.messages, getActionRenderer: getActionRenderer, showToolIndicator: showToolCalls, accentColor: accentColor, variant: variant, onActionDismiss: onActionDismiss }, `tg-${i}`));
|
|
44239
|
+
return (jsxRuntimeExports.jsx(ToolMessageGroup, { messages: item.messages, getActionRenderer: getActionRenderer, showToolIndicator: showToolCalls, accentColor: accentColor, variant: variant, onActionDismiss: onActionDismiss, onCallEndpoint: onCallEndpoint }, `tg-${i}`));
|
|
44187
44240
|
}
|
|
44188
|
-
|
|
44189
|
-
|
|
44190
|
-
return (jsxRuntimeExports.jsxs(React.Fragment, { children: [jsxRuntimeExports.jsx(Message, { message: item.message, showTimestamp: showTimestamps, onFeedback: onFeedback, getActionRenderer: getActionRenderer, accentColor: accentColor }), hasFollowUp && onSuggestedQuestionClick && jsxRuntimeExports.jsx(FollowUpSuggestions, { suggestions: item.message.suggestions, onQuestionClick: onSuggestedQuestionClick, onActionClick: onActionClick, accentColor: accentColor })] }, item.message.id));
|
|
44191
|
-
}), isTyping && showTypingIndicator && !hasActiveAction && visibleMessages.length > 0 && jsxRuntimeExports.jsx(TypingIndicator, {}), jsxRuntimeExports.jsx("div", { ref: messagesEndRef })] }));
|
|
44241
|
+
return (jsxRuntimeExports.jsx(Message, { message: item.message, showTimestamp: showTimestamps, enableFeedback: enableFeedback, onFeedback: onFeedback, getActionRenderer: getActionRenderer, accentColor: accentColor }, item.message.id));
|
|
44242
|
+
}), !isTyping && lastAssistantSuggestions?.length && onSuggestedQuestionClick && (jsxRuntimeExports.jsx(FollowUpSuggestions, { suggestions: lastAssistantSuggestions, onQuestionClick: onSuggestedQuestionClick, onActionClick: onActionClick, accentColor: accentColor })), isTyping && showTypingIndicator && !hasActiveAction && visibleMessages.length > 0 && jsxRuntimeExports.jsx(TypingIndicator, {}), jsxRuntimeExports.jsx("div", { ref: messagesEndRef })] }));
|
|
44192
44243
|
};
|
|
44193
44244
|
|
|
44194
44245
|
const ALLOWED_EXTENSIONS = ['.pdf', '.doc', '.docx', '.txt', '.md', '.csv'];
|
|
@@ -44202,7 +44253,7 @@
|
|
|
44202
44253
|
return (bytes / 1024).toFixed(1) + ' KB';
|
|
44203
44254
|
return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
|
|
44204
44255
|
};
|
|
44205
|
-
const MessageInput = ({ onSend, placeholder = 'Type your message...', disabled = false, enableFileUpload = false, separateFromChat = true, showDataPolicy = true, onDataPolicyClick, }) => {
|
|
44256
|
+
const MessageInput = ({ onSend, placeholder = 'Type your message...', disabled = false, enableFileUpload = false, separateFromChat = true, showDataPolicy = true, onDataPolicyClick, onInputFocus, }) => {
|
|
44206
44257
|
const [value, setValue] = reactExports.useState('');
|
|
44207
44258
|
const [selectedFiles, setSelectedFiles] = reactExports.useState([]);
|
|
44208
44259
|
const textareaRef = reactExports.useRef(null);
|
|
@@ -44237,492 +44288,15 @@
|
|
|
44237
44288
|
}
|
|
44238
44289
|
};
|
|
44239
44290
|
const canSend = value.trim() || selectedFiles.length > 0;
|
|
44240
|
-
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-input-container ${separateFromChat ? 'separate' : 'integrated'}`, children: [selectedFiles.length > 0 && (jsxRuntimeExports.jsx("div", { className: "ai-chat-file-list", children: selectedFiles.map((file, index) => (jsxRuntimeExports.jsxs("div", { className: "ai-chat-file-item", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-file-extension", children: getFileExtension(file.name) }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-file-info", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-file-name", children: file.name }), jsxRuntimeExports.jsx("span", { className: "ai-chat-file-size", children: formatFileSize(file.size) })] }), jsxRuntimeExports.jsx("button", { className: "ai-chat-file-remove", onClick: () => handleRemoveFile(index), "aria-label": "Remove file", children: jsxRuntimeExports.jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: jsxRuntimeExports.jsx("path", { d: "M18 6L6 18M6 6l12 12" }) }) })] }, index))) })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-input-wrapper", children: [enableFileUpload && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("input", { ref: fileInputRef, type: "file", onChange: handleFileSelect, style: { display: 'none' }, multiple: true, accept: ALLOWED_EXTENSIONS.join(',') }), jsxRuntimeExports.jsx("button", { className: "ai-chat-file-button", onClick: () => fileInputRef.current?.click(), disabled: disabled, "aria-label": "Attach file", children: jsxRuntimeExports.jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: jsxRuntimeExports.jsx("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" }) }) })] })), jsxRuntimeExports.jsx("textarea", { ref: textareaRef, className: "ai-chat-input", value: value, onChange: (e) => setValue(e.target.value), onKeyDown: handleKeyDown, placeholder: placeholder, disabled: disabled, rows: 2, wrap: "soft", "aria-label": "Message input" }), jsxRuntimeExports.jsx("button", { className: `ai-chat-send-button ${canSend ? 'active' : ''}`, onClick: handleSend, disabled: disabled || !canSend, "aria-label": "Send message", children: jsxRuntimeExports.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: [jsxRuntimeExports.jsx("path", { d: "M12 19V5" }), jsxRuntimeExports.jsx("path", { d: "M5 12l7-7 7 7" })] }) })] }), showDataPolicy && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy", children: [jsxRuntimeExports.jsx("span", { children: "AI-generated responses may be inaccurate." }), onDataPolicyClick && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [' ', jsxRuntimeExports.jsx("button", { type: "button", className: "ai-chat-data-policy-link", onClick: onDataPolicyClick, children: "Privacy Notice" })] }))] }))] }));
|
|
44241
|
-
};
|
|
44242
|
-
|
|
44243
|
-
const CloseButton = ({ onClick, className = "", ariaLabel = "Close", }) => {
|
|
44244
|
-
return (jsxRuntimeExports.jsx("button", { type: "button", className: `ai-chat-action-close-btn ${className}`, onClick: onClick, "aria-label": ariaLabel, children: jsxRuntimeExports.jsx("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "2", children: jsxRuntimeExports.jsx("path", { d: "M1 1L13 13M1 13L13 1" }) }) }));
|
|
44291
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-input-container ${separateFromChat ? 'separate' : 'integrated'}`, children: [selectedFiles.length > 0 && (jsxRuntimeExports.jsx("div", { className: "ai-chat-file-list", children: selectedFiles.map((file, index) => (jsxRuntimeExports.jsxs("div", { className: "ai-chat-file-item", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-file-extension", children: getFileExtension(file.name) }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-file-info", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-file-name", children: file.name }), jsxRuntimeExports.jsx("span", { className: "ai-chat-file-size", children: formatFileSize(file.size) })] }), jsxRuntimeExports.jsx("button", { className: "ai-chat-file-remove", onClick: () => handleRemoveFile(index), "aria-label": "Remove file", children: jsxRuntimeExports.jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: jsxRuntimeExports.jsx("path", { d: "M18 6L6 18M6 6l12 12" }) }) })] }, index))) })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-input-wrapper", children: [enableFileUpload && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("input", { ref: fileInputRef, type: "file", onChange: handleFileSelect, style: { display: 'none' }, multiple: true, accept: ALLOWED_EXTENSIONS.join(',') }), jsxRuntimeExports.jsx("button", { className: "ai-chat-file-button", onClick: () => fileInputRef.current?.click(), disabled: disabled, "aria-label": "Attach file", children: jsxRuntimeExports.jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: jsxRuntimeExports.jsx("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" }) }) })] })), jsxRuntimeExports.jsx("textarea", { ref: textareaRef, className: "ai-chat-input", value: value, onChange: (e) => setValue(e.target.value), onKeyDown: handleKeyDown, onFocus: onInputFocus, placeholder: placeholder, disabled: disabled, rows: 2, wrap: "soft", "aria-label": "Message input" }), jsxRuntimeExports.jsx("button", { className: `ai-chat-send-button ${canSend ? 'active' : ''}`, onClick: handleSend, disabled: disabled || !canSend, "aria-label": "Send message", children: jsxRuntimeExports.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: [jsxRuntimeExports.jsx("path", { d: "M12 19V5" }), jsxRuntimeExports.jsx("path", { d: "M5 12l7-7 7 7" })] }) })] }), showDataPolicy && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-data-policy", children: [jsxRuntimeExports.jsx("span", { children: "AI-generated responses may be inaccurate." }), onDataPolicyClick && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [' ', jsxRuntimeExports.jsx("button", { type: "button", className: "ai-chat-data-policy-link", onClick: onDataPolicyClick, children: "Privacy Notice" })] }))] }))] }));
|
|
44245
44292
|
};
|
|
44246
44293
|
|
|
44247
|
-
function
|
|
44248
|
-
const grouped = new Map();
|
|
44249
|
-
for (const slot of slots) {
|
|
44250
|
-
if (!slot || typeof slot !== 'object' || !slot.startTime || typeof slot.startTime !== 'string') {
|
|
44251
|
-
continue;
|
|
44252
|
-
}
|
|
44253
|
-
const date = slot.startTime.slice(0, 10);
|
|
44254
|
-
if (!grouped.has(date)) {
|
|
44255
|
-
grouped.set(date, []);
|
|
44256
|
-
}
|
|
44257
|
-
grouped.get(date).push(slot);
|
|
44258
|
-
}
|
|
44259
|
-
return grouped;
|
|
44260
|
-
}
|
|
44261
|
-
function formatDate$1(dateStr) {
|
|
44262
|
-
try {
|
|
44263
|
-
const date = new Date(dateStr);
|
|
44264
|
-
return new Intl.DateTimeFormat("en-US", {
|
|
44265
|
-
weekday: "short",
|
|
44266
|
-
month: "short",
|
|
44267
|
-
day: "numeric",
|
|
44268
|
-
}).format(date);
|
|
44269
|
-
}
|
|
44270
|
-
catch {
|
|
44271
|
-
return dateStr;
|
|
44272
|
-
}
|
|
44273
|
-
}
|
|
44274
|
-
function CalendarIcon$1() {
|
|
44275
|
-
return (jsxRuntimeExports.jsx("svg", { className: "ai-chat-action-icon", viewBox: "0 0 20 20", fill: "currentColor", children: jsxRuntimeExports.jsx("path", { fillRule: "evenodd", d: "M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z", clipRule: "evenodd" }) }));
|
|
44276
|
-
}
|
|
44277
|
-
function CheckIcon$1() {
|
|
44278
|
-
return (jsxRuntimeExports.jsx("svg", { className: "ai-chat-action-icon-success", viewBox: "0 0 20 20", fill: "currentColor", children: jsxRuntimeExports.jsx("path", { fillRule: "evenodd", d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z", clipRule: "evenodd" }) }));
|
|
44279
|
-
}
|
|
44280
|
-
function ExternalLinkIcon$2() {
|
|
44281
|
-
return (jsxRuntimeExports.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }), jsxRuntimeExports.jsx("polyline", { points: "15 3 21 3 21 9" }), jsxRuntimeExports.jsx("line", { x1: "10", y1: "14", x2: "21", y2: "3" })] }));
|
|
44282
|
-
}
|
|
44283
|
-
function Skeleton$2({ width, height, borderRadius = '4px' }) {
|
|
44284
|
-
return (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-skeleton-item", style: { width, height, borderRadius } }));
|
|
44285
|
-
}
|
|
44286
|
-
function GoogleCalendarCard({ action, onComplete, onDismiss, accentColor, className = '' }) {
|
|
44287
|
-
const state = action.state;
|
|
44288
|
-
const rawSlots = state.availableSlots;
|
|
44289
|
-
const availableSlots = Array.isArray(rawSlots)
|
|
44290
|
-
? rawSlots.filter((slot) => slot !== null &&
|
|
44291
|
-
slot !== undefined &&
|
|
44292
|
-
typeof slot === "object" &&
|
|
44293
|
-
"startTime" in slot &&
|
|
44294
|
-
"endTime" in slot &&
|
|
44295
|
-
typeof slot.startTime === "string" &&
|
|
44296
|
-
typeof slot.endTime === "string")
|
|
44297
|
-
: [];
|
|
44298
|
-
const allowTopic = state.allowTopic !== false;
|
|
44299
|
-
const isBooked = state.status === "booked";
|
|
44300
|
-
const slotsByDate = groupSlotsByDate$1(availableSlots);
|
|
44301
|
-
const dates = Array.from(slotsByDate.keys()).sort();
|
|
44302
|
-
const [selectedDate, setSelectedDate] = reactExports.useState(dates[0] ?? "");
|
|
44303
|
-
const [selectedSlot, setSelectedSlot] = reactExports.useState(null);
|
|
44304
|
-
const [topic, setTopic] = reactExports.useState("");
|
|
44305
|
-
const [error, setError] = reactExports.useState(null);
|
|
44306
|
-
const slotsForSelectedDate = selectedDate ? slotsByDate.get(selectedDate) ?? [] : [];
|
|
44307
|
-
const accentStyle = accentColor ? { '--action-accent': accentColor } : {};
|
|
44308
|
-
const onConfirm = () => {
|
|
44309
|
-
if (!selectedSlot) {
|
|
44310
|
-
setError("Please select a time slot.");
|
|
44311
|
-
return;
|
|
44312
|
-
}
|
|
44313
|
-
if (allowTopic && !topic.trim()) {
|
|
44314
|
-
setError("Please enter a topic for the meeting.");
|
|
44315
|
-
return;
|
|
44316
|
-
}
|
|
44317
|
-
setError(null);
|
|
44318
|
-
onComplete?.(action.toolCallId, {
|
|
44319
|
-
...action.state,
|
|
44320
|
-
selectedSlot: {
|
|
44321
|
-
startTime: selectedSlot.startTime,
|
|
44322
|
-
endTime: selectedSlot.endTime,
|
|
44323
|
-
},
|
|
44324
|
-
topic: allowTopic ? topic.trim() : null,
|
|
44325
|
-
});
|
|
44326
|
-
};
|
|
44327
|
-
const handleDismiss = () => {
|
|
44328
|
-
onDismiss?.(action.toolCallId);
|
|
44329
|
-
};
|
|
44330
|
-
// Booked state
|
|
44331
|
-
if (isBooked) {
|
|
44332
|
-
const bookedSlot = state.selectedSlot;
|
|
44333
|
-
const bookedTopic = state.topic;
|
|
44334
|
-
const eventLink = state.bookedEventLink;
|
|
44335
|
-
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-action-booked ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-action-success-icon-wrapper", children: jsxRuntimeExports.jsx(CheckIcon$1, {}) }), "Appointment Confirmed"] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [bookedTopic && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-detail-box", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-action-label-small", children: "TOPIC" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-action-value-large", children: bookedTopic })] })), bookedSlot && bookedSlot.startTime && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-detail-box", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-action-label-small", children: "TIME" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-action-value-large", children: bookedSlot.displayTime || new Date(bookedSlot.startTime).toLocaleString() })] })), eventLink && (jsxRuntimeExports.jsxs("a", { href: eventLink, target: "_blank", rel: "noopener noreferrer", className: "ai-chat-action-link-button", children: ["View in Google Calendar", jsxRuntimeExports.jsx(ExternalLinkIcon$2, {})] }))] })] }));
|
|
44336
|
-
}
|
|
44337
|
-
// Skeleton loading state - show when waiting for backend after user confirms
|
|
44338
|
-
const isWaitingForBackend = !action.done && state.selectedSlot && !isBooked;
|
|
44339
|
-
if (isWaitingForBackend) {
|
|
44340
|
-
return (jsxRuntimeExports.jsx("div", { className: `ai-chat-action-card ai-chat-action-skeleton ${className}`, style: accentStyle, children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-content", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-header", children: [jsxRuntimeExports.jsx(Skeleton$2, { width: "28px", height: "28px", borderRadius: "50%" }), jsxRuntimeExports.jsx(Skeleton$2, { width: "180px", height: "20px", borderRadius: "4px" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-box", children: [jsxRuntimeExports.jsx(Skeleton$2, { width: "60px", height: "12px", borderRadius: "4px" }), jsxRuntimeExports.jsx(Skeleton$2, { width: "120px", height: "18px", borderRadius: "4px" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-box", children: [jsxRuntimeExports.jsx(Skeleton$2, { width: "50px", height: "12px", borderRadius: "4px" }), jsxRuntimeExports.jsx(Skeleton$2, { width: "200px", height: "18px", borderRadius: "4px" })] }), jsxRuntimeExports.jsx(Skeleton$2, { width: "100%", height: "44px", borderRadius: "999px" })] }) }));
|
|
44341
|
-
}
|
|
44342
|
-
// Booking form
|
|
44343
|
-
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-action-card--closable ai-chat-google-calendar ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx(CalendarIcon$1, {}), "Schedule an Appointment", onDismiss && (jsxRuntimeExports.jsx(CloseButton, { onClick: handleDismiss, ariaLabel: "Cancel appointment booking" }))] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [allowTopic && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntimeExports.jsx("label", { htmlFor: `topic-${action.toolCallId}`, className: "ai-chat-action-label", children: "Meeting Topic" }), jsxRuntimeExports.jsx("input", { id: `topic-${action.toolCallId}`, type: "text", className: "ai-chat-action-input", placeholder: "e.g., Product Demo", value: topic, onChange: (e) => setTopic(e.target.value) })] })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntimeExports.jsx("label", { className: "ai-chat-action-label", children: "Select Date" }), jsxRuntimeExports.jsx("div", { className: "ai-chat-action-date-grid", children: dates.slice(0, 7).map((date) => (jsxRuntimeExports.jsx("button", { type: "button", className: `ai-chat-action-date-btn ${selectedDate === date ? "active" : ""}`, onClick: () => {
|
|
44344
|
-
setSelectedDate(date);
|
|
44345
|
-
setSelectedSlot(null);
|
|
44346
|
-
}, children: formatDate$1(date) }, date))) })] }), selectedDate && slotsForSelectedDate.length > 0 && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntimeExports.jsx("label", { className: "ai-chat-action-label", children: "Select Time" }), jsxRuntimeExports.jsx("div", { className: "ai-chat-action-time-grid", children: slotsForSelectedDate.map((slot) => (jsxRuntimeExports.jsx("button", { type: "button", className: `ai-chat-action-time-btn ${selectedSlot?.startTime === slot.startTime ? "active" : ""}`, onClick: () => setSelectedSlot(slot), children: slot.displayTime || new Date(slot.startTime).toLocaleTimeString([], { hour: "numeric", minute: "2-digit" }) }, slot.startTime))) })] })), error && jsxRuntimeExports.jsx("div", { className: "ai-chat-action-error", children: error }), jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button", type: "button", onClick: onConfirm, disabled: !selectedSlot, children: "Confirm Appointment" }), availableSlots.length === 0 && (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-hint", children: "No available time slots found." }))] })] }));
|
|
44347
|
-
}
|
|
44348
|
-
|
|
44349
|
-
function groupSlotsByDate(slots) {
|
|
44350
|
-
const grouped = new Map();
|
|
44351
|
-
for (const slot of slots) {
|
|
44352
|
-
if (!slot || typeof slot !== 'object' || !slot.startTime || typeof slot.startTime !== 'string') {
|
|
44353
|
-
continue;
|
|
44354
|
-
}
|
|
44355
|
-
const date = slot.startTime.slice(0, 10);
|
|
44356
|
-
if (!grouped.has(date)) {
|
|
44357
|
-
grouped.set(date, []);
|
|
44358
|
-
}
|
|
44359
|
-
grouped.get(date).push(slot);
|
|
44360
|
-
}
|
|
44361
|
-
return grouped;
|
|
44362
|
-
}
|
|
44363
|
-
function formatDate(dateStr) {
|
|
44364
|
-
try {
|
|
44365
|
-
const date = new Date(dateStr);
|
|
44366
|
-
return new Intl.DateTimeFormat("en-US", {
|
|
44367
|
-
weekday: "short",
|
|
44368
|
-
month: "short",
|
|
44369
|
-
day: "numeric",
|
|
44370
|
-
}).format(date);
|
|
44371
|
-
}
|
|
44372
|
-
catch {
|
|
44373
|
-
return dateStr;
|
|
44374
|
-
}
|
|
44375
|
-
}
|
|
44376
|
-
function CalendarIcon() {
|
|
44377
|
-
return (jsxRuntimeExports.jsx("svg", { className: "ai-chat-action-icon", viewBox: "0 0 20 20", fill: "currentColor", children: jsxRuntimeExports.jsx("path", { fillRule: "evenodd", d: "M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z", clipRule: "evenodd" }) }));
|
|
44378
|
-
}
|
|
44379
|
-
function MailIcon() {
|
|
44380
|
-
return (jsxRuntimeExports.jsxs("svg", { className: "ai-chat-action-icon", viewBox: "0 0 20 20", fill: "currentColor", children: [jsxRuntimeExports.jsx("path", { d: "M2.003 5.884L10 9.882l7.997-3.998A2 2 0 0016 4H4a2 2 0 00-1.997 1.884z" }), jsxRuntimeExports.jsx("path", { d: "M18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z" })] }));
|
|
44381
|
-
}
|
|
44382
|
-
function CheckIcon() {
|
|
44383
|
-
return (jsxRuntimeExports.jsx("svg", { className: "ai-chat-action-icon-success", viewBox: "0 0 20 20", fill: "currentColor", children: jsxRuntimeExports.jsx("path", { fillRule: "evenodd", d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z", clipRule: "evenodd" }) }));
|
|
44384
|
-
}
|
|
44385
|
-
function ErrorIcon() {
|
|
44386
|
-
return (jsxRuntimeExports.jsx("svg", { className: "ai-chat-action-icon-error", viewBox: "0 0 20 20", fill: "currentColor", children: jsxRuntimeExports.jsx("path", { fillRule: "evenodd", d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z", clipRule: "evenodd" }) }));
|
|
44387
|
-
}
|
|
44388
|
-
function ExternalLinkIcon$1() {
|
|
44389
|
-
return (jsxRuntimeExports.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }), jsxRuntimeExports.jsx("polyline", { points: "15 3 21 3 21 9" }), jsxRuntimeExports.jsx("line", { x1: "10", y1: "14", x2: "21", y2: "3" })] }));
|
|
44390
|
-
}
|
|
44391
|
-
function Skeleton$1({ width, height, borderRadius = '4px' }) {
|
|
44392
|
-
return (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-skeleton-item", style: { width, height, borderRadius } }));
|
|
44393
|
-
}
|
|
44394
|
-
function PinInputGroup$1({ values, onChange, disabled }) {
|
|
44395
|
-
const inputRefs = reactExports.useRef([]);
|
|
44396
|
-
const handleChange = (index, value) => {
|
|
44397
|
-
// Only allow digits
|
|
44398
|
-
const digit = value.replace(/[^0-9]/g, '');
|
|
44399
|
-
const newValues = [...values];
|
|
44400
|
-
newValues[index] = digit.slice(-1);
|
|
44401
|
-
onChange(newValues);
|
|
44402
|
-
// Auto-focus next input
|
|
44403
|
-
if (digit && index < 5) {
|
|
44404
|
-
inputRefs.current[index + 1]?.focus();
|
|
44405
|
-
}
|
|
44406
|
-
};
|
|
44407
|
-
const handleKeyDown = (index, e) => {
|
|
44408
|
-
if (e.key === 'Backspace' && !values[index] && index > 0) {
|
|
44409
|
-
inputRefs.current[index - 1]?.focus();
|
|
44410
|
-
}
|
|
44411
|
-
};
|
|
44412
|
-
const handlePaste = (e) => {
|
|
44413
|
-
e.preventDefault();
|
|
44414
|
-
const pastedData = e.clipboardData.getData('text').replace(/[^0-9]/g, '').slice(0, 6);
|
|
44415
|
-
const newValues = pastedData.split('').concat(Array(6 - pastedData.length).fill(''));
|
|
44416
|
-
onChange(newValues);
|
|
44417
|
-
// Focus the next empty input or the last one
|
|
44418
|
-
const nextIndex = Math.min(pastedData.length, 5);
|
|
44419
|
-
inputRefs.current[nextIndex]?.focus();
|
|
44420
|
-
};
|
|
44421
|
-
return (jsxRuntimeExports.jsx("div", { className: "ai-chat-pin-input-group", children: values.map((value, index) => (jsxRuntimeExports.jsx("input", { ref: (el) => {
|
|
44422
|
-
inputRefs.current[index] = el;
|
|
44423
|
-
}, type: "text", inputMode: "numeric", maxLength: 1, className: "ai-chat-pin-input", value: value, onChange: (e) => handleChange(index, e.target.value), onKeyDown: (e) => handleKeyDown(index, e), onPaste: handlePaste, disabled: disabled, autoFocus: index === 0 }, index))) }));
|
|
44424
|
-
}
|
|
44425
|
-
function MicrosoftCalendarCard({ action, onComplete, onDismiss, accentColor, className = '' }) {
|
|
44426
|
-
const state = action.state;
|
|
44427
|
-
const phase = state.phase || "awaiting_email";
|
|
44428
|
-
const allowTopic = state.allowTopic !== false;
|
|
44429
|
-
const accentStyle = accentColor ? { '--action-accent': accentColor } : {};
|
|
44430
|
-
const handleDismiss = () => {
|
|
44431
|
-
onDismiss?.(action.toolCallId);
|
|
44432
|
-
};
|
|
44433
|
-
const showCloseButton = Boolean(onDismiss);
|
|
44434
|
-
// Debug: Log state changes
|
|
44435
|
-
const prevStateRef = reactExports.useRef(null);
|
|
44436
|
-
reactExports.useEffect(() => {
|
|
44437
|
-
if (JSON.stringify(prevStateRef.current) !== JSON.stringify(state)) {
|
|
44438
|
-
console.log('[MicrosoftCalendarCard] State updated:', {
|
|
44439
|
-
phase: state.phase,
|
|
44440
|
-
hasError: !!state.errorMessage,
|
|
44441
|
-
error: state.errorMessage,
|
|
44442
|
-
slotsCount: state.availableSlots?.length || 0
|
|
44443
|
-
});
|
|
44444
|
-
prevStateRef.current = state;
|
|
44445
|
-
}
|
|
44446
|
-
}, [state]);
|
|
44447
|
-
// Email phase state
|
|
44448
|
-
const [email, setEmail] = reactExports.useState("");
|
|
44449
|
-
const [emailError, setEmailError] = reactExports.useState(null);
|
|
44450
|
-
// OTP phase state
|
|
44451
|
-
const [otpValues, setOtpValues] = reactExports.useState(Array(6).fill(''));
|
|
44452
|
-
const [otpError, setOtpError] = reactExports.useState(null);
|
|
44453
|
-
// Loading states
|
|
44454
|
-
const [isSubmitting, setIsSubmitting] = reactExports.useState(false);
|
|
44455
|
-
// Reset loading state when phase changes (backend has responded)
|
|
44456
|
-
// Use useEffect for reliable re-rendering
|
|
44457
|
-
reactExports.useEffect(() => {
|
|
44458
|
-
console.log('[MicrosoftCalendarCard] Phase changed to:', phase);
|
|
44459
|
-
setIsSubmitting(false);
|
|
44460
|
-
// Clear errors when transitioning to new phase
|
|
44461
|
-
if (phase === "awaiting_email") {
|
|
44462
|
-
setEmailError(null);
|
|
44463
|
-
setOtpError(null);
|
|
44464
|
-
setSelectionError(null);
|
|
44465
|
-
}
|
|
44466
|
-
else if (phase === "awaiting_otp") {
|
|
44467
|
-
setOtpError(state.errorMessage || null);
|
|
44468
|
-
setEmailError(null);
|
|
44469
|
-
setSelectionError(null);
|
|
44470
|
-
// Clear OTP input for fresh attempt
|
|
44471
|
-
setOtpValues(Array(6).fill(''));
|
|
44472
|
-
}
|
|
44473
|
-
else if (phase === "awaiting_options") {
|
|
44474
|
-
setEmailError(null);
|
|
44475
|
-
setOtpError(null);
|
|
44476
|
-
setSelectionError(null);
|
|
44477
|
-
}
|
|
44478
|
-
else if (phase === "awaiting_booking") {
|
|
44479
|
-
setSelectionError(state.errorMessage || null);
|
|
44480
|
-
setEmailError(null);
|
|
44481
|
-
setOtpError(null);
|
|
44482
|
-
}
|
|
44483
|
-
else if (phase === "booked" || phase === "cancelled" || phase === "error") {
|
|
44484
|
-
setEmailError(null);
|
|
44485
|
-
setOtpError(null);
|
|
44486
|
-
setSelectionError(null);
|
|
44487
|
-
setSelectedId(null); // Reset selection
|
|
44488
|
-
}
|
|
44489
|
-
}, [phase, state.errorMessage]);
|
|
44490
|
-
// Selection phase state
|
|
44491
|
-
const rawSlots = state.availableSlots;
|
|
44492
|
-
const availableSlots = Array.isArray(rawSlots)
|
|
44493
|
-
? rawSlots.filter((slot) => slot !== null &&
|
|
44494
|
-
slot !== undefined &&
|
|
44495
|
-
typeof slot === "object" &&
|
|
44496
|
-
"startTime" in slot &&
|
|
44497
|
-
"endTime" in slot &&
|
|
44498
|
-
typeof slot.startTime === "string" &&
|
|
44499
|
-
typeof slot.endTime === "string")
|
|
44500
|
-
: [];
|
|
44501
|
-
const slotsByDate = groupSlotsByDate(availableSlots);
|
|
44502
|
-
const dates = Array.from(slotsByDate.keys()).sort();
|
|
44503
|
-
const [selectedDate, setSelectedDate] = reactExports.useState(dates[0] ?? "");
|
|
44504
|
-
const [selectedSlot, setSelectedSlot] = reactExports.useState(null);
|
|
44505
|
-
const [topic, setTopic] = reactExports.useState("");
|
|
44506
|
-
const [selectionError, setSelectionError] = reactExports.useState(null);
|
|
44507
|
-
// Cancellation phase state
|
|
44508
|
-
const [selectedId, setSelectedId] = reactExports.useState(null);
|
|
44509
|
-
const slotsForSelectedDate = selectedDate ? slotsByDate.get(selectedDate) ?? [] : [];
|
|
44510
|
-
// Phase 1: Email Input
|
|
44511
|
-
const handleEmailSubmit = () => {
|
|
44512
|
-
const trimmedEmail = email.trim();
|
|
44513
|
-
if (!trimmedEmail) {
|
|
44514
|
-
setEmailError("Please enter your email address");
|
|
44515
|
-
return;
|
|
44516
|
-
}
|
|
44517
|
-
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(trimmedEmail)) {
|
|
44518
|
-
setEmailError("Please enter a valid email address");
|
|
44519
|
-
return;
|
|
44520
|
-
}
|
|
44521
|
-
setEmailError(null);
|
|
44522
|
-
setIsSubmitting(true);
|
|
44523
|
-
console.log('[MicrosoftCalendarCard] Submitting email:', trimmedEmail);
|
|
44524
|
-
setTimeout(() => {
|
|
44525
|
-
onComplete?.(action.toolCallId, {
|
|
44526
|
-
...action.state,
|
|
44527
|
-
email: trimmedEmail,
|
|
44528
|
-
});
|
|
44529
|
-
}, 50);
|
|
44530
|
-
};
|
|
44531
|
-
// Phase 2: OTP Verification
|
|
44532
|
-
const handleOtpSubmit = () => {
|
|
44533
|
-
const otpCode = otpValues.join('');
|
|
44534
|
-
if (otpCode.length !== 6) {
|
|
44535
|
-
setOtpError("Please enter the 6-digit code");
|
|
44536
|
-
return;
|
|
44537
|
-
}
|
|
44538
|
-
setOtpError(null);
|
|
44539
|
-
setIsSubmitting(true);
|
|
44540
|
-
console.log('[MicrosoftCalendarCard] Submitting OTP code');
|
|
44541
|
-
setTimeout(() => {
|
|
44542
|
-
onComplete?.(action.toolCallId, {
|
|
44543
|
-
...action.state,
|
|
44544
|
-
otpCode,
|
|
44545
|
-
});
|
|
44546
|
-
}, 50);
|
|
44547
|
-
};
|
|
44548
|
-
// Phase 3: Appointment Selection
|
|
44549
|
-
const handleAppointmentConfirm = () => {
|
|
44550
|
-
if (!selectedSlot) {
|
|
44551
|
-
setSelectionError("Please select a time slot");
|
|
44552
|
-
return;
|
|
44553
|
-
}
|
|
44554
|
-
if (allowTopic && !topic.trim()) {
|
|
44555
|
-
setSelectionError("Please enter a meeting topic");
|
|
44556
|
-
return;
|
|
44557
|
-
}
|
|
44558
|
-
setSelectionError(null);
|
|
44559
|
-
setIsSubmitting(true);
|
|
44560
|
-
console.log('[MicrosoftCalendarCard] Confirming appointment:', {
|
|
44561
|
-
slot: selectedSlot,
|
|
44562
|
-
topic: topic.trim()
|
|
44563
|
-
});
|
|
44564
|
-
setTimeout(() => {
|
|
44565
|
-
onComplete?.(action.toolCallId, {
|
|
44566
|
-
...action.state,
|
|
44567
|
-
selectedSlot: {
|
|
44568
|
-
startTime: selectedSlot.startTime,
|
|
44569
|
-
endTime: selectedSlot.endTime,
|
|
44570
|
-
},
|
|
44571
|
-
topic: allowTopic ? topic.trim() : null,
|
|
44572
|
-
});
|
|
44573
|
-
}, 50);
|
|
44574
|
-
};
|
|
44575
|
-
// Handle "Use different email" button
|
|
44576
|
-
const handleUseDifferentEmail = () => {
|
|
44577
|
-
setEmail("");
|
|
44578
|
-
setEmailError(null);
|
|
44579
|
-
setOtpValues(Array(6).fill(''));
|
|
44580
|
-
setOtpError(null);
|
|
44581
|
-
onComplete?.(action.toolCallId, {
|
|
44582
|
-
phase: "awaiting_email",
|
|
44583
|
-
email: null,
|
|
44584
|
-
otpVerified: false,
|
|
44585
|
-
otpAttempts: 0,
|
|
44586
|
-
availableSlots: [],
|
|
44587
|
-
selectedSlot: null,
|
|
44588
|
-
topic: null,
|
|
44589
|
-
bookedEventId: null,
|
|
44590
|
-
bookedEventLink: null,
|
|
44591
|
-
allowTopic,
|
|
44592
|
-
errorMessage: null,
|
|
44593
|
-
});
|
|
44594
|
-
};
|
|
44595
|
-
// Phase 5: Booked Confirmation
|
|
44596
|
-
if (phase === "booked") {
|
|
44597
|
-
const bookedSlot = state.selectedSlot;
|
|
44598
|
-
const bookedTopic = state.topic;
|
|
44599
|
-
const eventLink = state.bookedEventLink;
|
|
44600
|
-
const bookedEmail = state.email;
|
|
44601
|
-
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-action-booked ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-action-success-icon-wrapper", children: jsxRuntimeExports.jsx(CheckIcon, {}) }), "Appointment Confirmed"] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [bookedTopic && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-detail-box", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-action-label-small", children: "TOPIC" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-action-value-large", children: bookedTopic })] })), bookedSlot && bookedSlot.startTime && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-detail-box", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-action-label-small", children: "TIME" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-action-value-large", children: bookedSlot.displayTime || new Date(bookedSlot.startTime).toLocaleString() })] })), bookedEmail && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-hint", children: ["A calendar invitation has been sent to ", bookedEmail] })), eventLink && (jsxRuntimeExports.jsxs("a", { href: eventLink, target: "_blank", rel: "noopener noreferrer", className: "ai-chat-action-link-button", children: ["View in Outlook Calendar", jsxRuntimeExports.jsx(ExternalLinkIcon$1, {})] }))] })] }));
|
|
44602
|
-
}
|
|
44603
|
-
// Phase 6: Cancelled Confirmation
|
|
44604
|
-
if (phase === "cancelled") {
|
|
44605
|
-
const cancelledSubject = state.cancelledEventSubject;
|
|
44606
|
-
const userEmail = state.email;
|
|
44607
|
-
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-action-booked ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-action-success-icon-wrapper", children: jsxRuntimeExports.jsx(CheckIcon, {}) }), "Appointment Cancelled"] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [cancelledSubject && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-detail-box", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-action-label-small", children: "CANCELLED" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-action-value-large", children: cancelledSubject })] })), userEmail && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-hint", children: ["A cancellation notice has been sent to ", userEmail] }))] })] }));
|
|
44608
|
-
}
|
|
44609
|
-
// Error State
|
|
44610
|
-
if (phase === "error") {
|
|
44611
|
-
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-action-error ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx(ErrorIcon, {}), "Error"] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-action-error-message", children: state.errorMessage || "An error occurred. Please try again." }), jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button-secondary", type: "button", onClick: () => {
|
|
44612
|
-
setEmail("");
|
|
44613
|
-
setEmailError(null);
|
|
44614
|
-
setOtpValues(Array(6).fill(''));
|
|
44615
|
-
setOtpError(null);
|
|
44616
|
-
onComplete?.(action.toolCallId, {
|
|
44617
|
-
phase: "awaiting_email",
|
|
44618
|
-
email: null,
|
|
44619
|
-
otpVerified: false,
|
|
44620
|
-
otpAttempts: 0,
|
|
44621
|
-
availableSlots: [],
|
|
44622
|
-
selectedSlot: null,
|
|
44623
|
-
topic: null,
|
|
44624
|
-
bookedEventId: null,
|
|
44625
|
-
bookedEventLink: null,
|
|
44626
|
-
allowTopic,
|
|
44627
|
-
errorMessage: null,
|
|
44628
|
-
});
|
|
44629
|
-
}, children: "Start Over" })] })] }));
|
|
44630
|
-
}
|
|
44631
|
-
// Loading State
|
|
44632
|
-
if (isSubmitting) {
|
|
44633
|
-
return (jsxRuntimeExports.jsx("div", { className: `ai-chat-action-card ai-chat-action-skeleton ${className}`, style: accentStyle, children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-content", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-header", children: [jsxRuntimeExports.jsx(Skeleton$1, { width: "28px", height: "28px", borderRadius: "50%" }), jsxRuntimeExports.jsx(Skeleton$1, { width: "180px", height: "20px", borderRadius: "4px" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-box", children: [jsxRuntimeExports.jsx(Skeleton$1, { width: "60px", height: "12px", borderRadius: "4px" }), jsxRuntimeExports.jsx(Skeleton$1, { width: "120px", height: "18px", borderRadius: "4px" })] }), jsxRuntimeExports.jsx(Skeleton$1, { width: "100%", height: "44px", borderRadius: "999px" })] }) }));
|
|
44634
|
-
}
|
|
44635
|
-
// Phase 1: Email Input
|
|
44636
|
-
if (phase === "awaiting_email") {
|
|
44637
|
-
const displayError = state.errorMessage || emailError;
|
|
44638
|
-
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-action-card--closable ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx(CalendarIcon, {}), "Schedule an Appointment", showCloseButton && (jsxRuntimeExports.jsx(CloseButton, { onClick: handleDismiss, ariaLabel: "Cancel appointment booking" }))] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-action-hint", children: "We'll send a verification code to your email" }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntimeExports.jsx("label", { htmlFor: `email-${action.toolCallId}`, className: "ai-chat-action-label", children: "Email Address" }), jsxRuntimeExports.jsx("input", { id: `email-${action.toolCallId}`, type: "email", className: "ai-chat-action-input", placeholder: "your@email.com", value: email, onChange: (e) => {
|
|
44639
|
-
setEmail(e.target.value);
|
|
44640
|
-
setEmailError(null);
|
|
44641
|
-
}, onKeyPress: (e) => {
|
|
44642
|
-
if (e.key === 'Enter') {
|
|
44643
|
-
handleEmailSubmit();
|
|
44644
|
-
}
|
|
44645
|
-
}, autoFocus: true })] }), displayError && (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-error", children: displayError })), jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button", type: "button", onClick: handleEmailSubmit, children: "Continue" })] })] }));
|
|
44646
|
-
}
|
|
44647
|
-
// Phase 2: OTP Input
|
|
44648
|
-
if (phase === "awaiting_otp") {
|
|
44649
|
-
const displayError = state.errorMessage || otpError;
|
|
44650
|
-
const userEmail = state.email;
|
|
44651
|
-
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-action-card--closable ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx(MailIcon, {}), "Verify Your Email", showCloseButton && (jsxRuntimeExports.jsx(CloseButton, { onClick: handleDismiss, ariaLabel: "Cancel appointment booking" }))] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-hint", children: ["We sent a 6-digit code to ", jsxRuntimeExports.jsx("strong", { children: userEmail })] }), jsxRuntimeExports.jsx(PinInputGroup$1, { values: otpValues, onChange: (newValues) => {
|
|
44652
|
-
setOtpValues(newValues);
|
|
44653
|
-
setOtpError(null);
|
|
44654
|
-
// Auto-submit when all 6 digits are entered
|
|
44655
|
-
if (newValues.every(v => v.length === 1)) {
|
|
44656
|
-
console.log('[MicrosoftCalendarCard] Auto-submitting OTP (all 6 digits entered)');
|
|
44657
|
-
setIsSubmitting(true);
|
|
44658
|
-
const code = newValues.join('');
|
|
44659
|
-
setTimeout(() => {
|
|
44660
|
-
onComplete?.(action.toolCallId, {
|
|
44661
|
-
...action.state,
|
|
44662
|
-
otpCode: code,
|
|
44663
|
-
});
|
|
44664
|
-
}, 100);
|
|
44665
|
-
}
|
|
44666
|
-
}, disabled: isSubmitting }), displayError && (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-error", children: displayError })), jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button", type: "button", onClick: handleOtpSubmit, disabled: otpValues.join('').length !== 6, children: "Verify Code" }), jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button-secondary", type: "button", onClick: handleUseDifferentEmail, children: "Use different email" })] })] }));
|
|
44667
|
-
}
|
|
44668
|
-
// Phase 3: Options Menu (with inline cancel buttons and confirmation)
|
|
44669
|
-
if (phase === "awaiting_options") {
|
|
44670
|
-
const userAppointments = state.userAppointments || [];
|
|
44671
|
-
const maxAppointments = state.maxAppointmentsPerUser || 3;
|
|
44672
|
-
const appointmentCount = userAppointments.length;
|
|
44673
|
-
const canBook = appointmentCount < maxAppointments;
|
|
44674
|
-
const hasAppointments = appointmentCount > 0;
|
|
44675
|
-
const displayError = state.errorMessage || selectionError;
|
|
44676
|
-
// If confirming cancellation, show confirmation dialog
|
|
44677
|
-
if (selectedId) {
|
|
44678
|
-
const appointmentToCancel = userAppointments.find(appt => appt.id === selectedId);
|
|
44679
|
-
if (!appointmentToCancel) {
|
|
44680
|
-
setSelectedId(null); // Reset if appointment not found
|
|
44681
|
-
}
|
|
44682
|
-
else {
|
|
44683
|
-
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-action-card--closable ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx(CalendarIcon, {}), "Confirm Cancellation", showCloseButton && (jsxRuntimeExports.jsx(CloseButton, { onClick: handleDismiss, ariaLabel: "Cancel appointment booking" }))] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-action-hint", children: "Are you sure you want to cancel this appointment?" }), jsxRuntimeExports.jsx("div", { className: "ai-chat-action-appointment-item", style: { marginBottom: '16px' }, children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-appointment-info", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-action-appointment-subject", children: appointmentToCancel.subject }), jsxRuntimeExports.jsx("div", { className: "ai-chat-action-appointment-time", children: appointmentToCancel.displayTime })] }) }), displayError && (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-error", children: displayError })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-button-group", children: [jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button", type: "button", onClick: () => {
|
|
44684
|
-
setIsSubmitting(true);
|
|
44685
|
-
onComplete?.(action.toolCallId, {
|
|
44686
|
-
...action.state,
|
|
44687
|
-
selectedOption: "cancel",
|
|
44688
|
-
selectedAppointmentId: selectedId,
|
|
44689
|
-
});
|
|
44690
|
-
}, disabled: isSubmitting, children: isSubmitting ? 'Cancelling...' : 'Confirm Cancellation' }), jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button-secondary", type: "button", onClick: () => {
|
|
44691
|
-
setSelectedId(null);
|
|
44692
|
-
setSelectionError(null);
|
|
44693
|
-
}, disabled: isSubmitting, children: "Go Back" })] })] })] }));
|
|
44694
|
-
}
|
|
44695
|
-
}
|
|
44696
|
-
// Normal view with inline cancel buttons
|
|
44697
|
-
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-action-card--closable ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx(CalendarIcon, {}), "Manage Your Appointments", showCloseButton && (jsxRuntimeExports.jsx(CloseButton, { onClick: handleDismiss, ariaLabel: "Cancel appointment booking" }))] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-hint", children: ["You have ", appointmentCount, " active appointment", appointmentCount !== 1 ? 's' : '', canBook && ` (${maxAppointments - appointmentCount} slot${maxAppointments - appointmentCount !== 1 ? 's' : ''} remaining)`] }), hasAppointments && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-appointment-list", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-action-label", children: "Your Upcoming Appointments" }), userAppointments.map((appt) => (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-appointment-item", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-appointment-info", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-action-appointment-subject", children: appt.subject }), jsxRuntimeExports.jsx("div", { className: "ai-chat-action-appointment-time", children: appt.displayTime })] }), jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button-secondary", type: "button", onClick: () => {
|
|
44698
|
-
setSelectedId(appt.id);
|
|
44699
|
-
setSelectionError(null);
|
|
44700
|
-
}, children: "Cancel" })] }, appt.id)))] })), displayError && (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-error", children: displayError })), canBook && (jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button", type: "button", onClick: () => {
|
|
44701
|
-
setIsSubmitting(true);
|
|
44702
|
-
onComplete?.(action.toolCallId, {
|
|
44703
|
-
...action.state,
|
|
44704
|
-
selectedOption: "book",
|
|
44705
|
-
});
|
|
44706
|
-
}, disabled: isSubmitting, children: isSubmitting ? 'Loading...' : 'Book New Appointment' })), !canBook && !hasAppointments && (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-hint", children: "No appointments found." }))] })] }));
|
|
44707
|
-
}
|
|
44708
|
-
// Phase 4: Appointment Selection (Booking)
|
|
44709
|
-
if (phase === "awaiting_booking") {
|
|
44710
|
-
const displayError = state.errorMessage || selectionError;
|
|
44711
|
-
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-action-card--closable ${className}`, style: accentStyle, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-header", children: [jsxRuntimeExports.jsx(CalendarIcon, {}), "Select Appointment Time", showCloseButton && (jsxRuntimeExports.jsx(CloseButton, { onClick: handleDismiss, ariaLabel: "Cancel appointment booking" }))] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-body", children: [allowTopic && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntimeExports.jsx("label", { htmlFor: `topic-${action.toolCallId}`, className: "ai-chat-action-label", children: "Meeting Topic" }), jsxRuntimeExports.jsx("input", { id: `topic-${action.toolCallId}`, type: "text", className: "ai-chat-action-input", placeholder: "e.g., Product Demo", value: topic, onChange: (e) => setTopic(e.target.value) })] })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntimeExports.jsx("label", { className: "ai-chat-action-label", children: "Select Date" }), jsxRuntimeExports.jsx("div", { className: "ai-chat-action-date-grid", children: dates.slice(0, 7).map((date) => (jsxRuntimeExports.jsx("button", { type: "button", className: `ai-chat-action-date-btn ${selectedDate === date ? "active" : ""}`, onClick: () => {
|
|
44712
|
-
setSelectedDate(date);
|
|
44713
|
-
setSelectedSlot(null);
|
|
44714
|
-
}, children: formatDate(date) }, date))) })] }), selectedDate && slotsForSelectedDate.length > 0 && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-field", children: [jsxRuntimeExports.jsx("label", { className: "ai-chat-action-label", children: "Select Time" }), jsxRuntimeExports.jsx("div", { className: "ai-chat-action-time-grid", children: slotsForSelectedDate.map((slot) => (jsxRuntimeExports.jsx("button", { type: "button", className: `ai-chat-action-time-btn ${selectedSlot?.startTime === slot.startTime ? "active" : ""}`, onClick: () => setSelectedSlot(slot), children: slot.displayTime || new Date(slot.startTime).toLocaleTimeString([], { hour: "numeric", minute: "2-digit" }) }, slot.startTime))) })] })), displayError && (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-error", children: displayError })), jsxRuntimeExports.jsx("button", { className: "ai-chat-action-button", type: "button", onClick: handleAppointmentConfirm, disabled: !selectedSlot, children: "Confirm Appointment" }), availableSlots.length === 0 && (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-hint", children: "No available time slots found." }))] })] }));
|
|
44715
|
-
}
|
|
44716
|
-
// Fallback
|
|
44717
|
-
return null;
|
|
44718
|
-
}
|
|
44719
|
-
|
|
44720
|
-
function truncate(text, maxLength) {
|
|
44294
|
+
function truncate$1(text, maxLength) {
|
|
44721
44295
|
if (text.length <= maxLength)
|
|
44722
44296
|
return text;
|
|
44723
44297
|
return text.slice(0, maxLength).trim() + '...';
|
|
44724
44298
|
}
|
|
44725
|
-
function ExternalLinkIcon() {
|
|
44299
|
+
function ExternalLinkIcon$2() {
|
|
44726
44300
|
return (jsxRuntimeExports.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }), jsxRuntimeExports.jsx("polyline", { points: "15 3 21 3 21 9" }), jsxRuntimeExports.jsx("line", { x1: "10", y1: "14", x2: "21", y2: "3" })] }));
|
|
44727
44301
|
}
|
|
44728
44302
|
function SingleLinkPreview({ link, onLinkClick, accentColor }) {
|
|
@@ -44741,10 +44315,10 @@
|
|
|
44741
44315
|
e.currentTarget.parentElement.style.display = 'none';
|
|
44742
44316
|
} }) })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-link-preview__content", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-link-preview__site", children: [link.favicon && (jsxRuntimeExports.jsx("img", { src: link.favicon, alt: "", className: "ai-chat-link-preview__favicon", onError: (e) => {
|
|
44743
44317
|
e.currentTarget.style.display = 'none';
|
|
44744
|
-
} })), jsxRuntimeExports.jsx("span", { className: "ai-chat-link-preview__domain", children: link.siteName || domain })] }), jsxRuntimeExports.jsx("h4", { className: "ai-chat-link-preview__title", children: link.title }), link.description && (jsxRuntimeExports.jsx("p", { className: "ai-chat-link-preview__description", children: truncate(link.description, 120) }))] }), jsxRuntimeExports.jsx("div", { className: "ai-chat-link-preview__arrow", children: jsxRuntimeExports.jsx(ExternalLinkIcon, {}) })] }));
|
|
44318
|
+
} })), jsxRuntimeExports.jsx("span", { className: "ai-chat-link-preview__domain", children: link.siteName || domain })] }), jsxRuntimeExports.jsx("h4", { className: "ai-chat-link-preview__title", children: link.title }), link.description && (jsxRuntimeExports.jsx("p", { className: "ai-chat-link-preview__description", children: truncate$1(link.description, 120) }))] }), jsxRuntimeExports.jsx("div", { className: "ai-chat-link-preview__arrow", children: jsxRuntimeExports.jsx(ExternalLinkIcon$2, {}) })] }));
|
|
44745
44319
|
}
|
|
44746
44320
|
function LinkPreviewCard({ action, onComplete, accentColor }) {
|
|
44747
|
-
const rawState = action.
|
|
44321
|
+
const rawState = action.input;
|
|
44748
44322
|
const hasCompletedRef = reactExports.useRef(false);
|
|
44749
44323
|
// Provide safe defaults if state is missing
|
|
44750
44324
|
const state = {
|
|
@@ -44774,11 +44348,12 @@
|
|
|
44774
44348
|
if (state.links.length === 0) {
|
|
44775
44349
|
return null;
|
|
44776
44350
|
}
|
|
44777
|
-
|
|
44778
|
-
|
|
44779
|
-
|
|
44780
|
-
|
|
44781
|
-
|
|
44351
|
+
const gridClass = state.links.length === 1
|
|
44352
|
+
? 'ai-chat-link-preview-grid ai-chat-link-preview-grid--single'
|
|
44353
|
+
: state.links.length === 2
|
|
44354
|
+
? 'ai-chat-link-preview-grid ai-chat-link-preview-grid--double'
|
|
44355
|
+
: 'ai-chat-link-preview-grid ai-chat-link-preview-grid--triple';
|
|
44356
|
+
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-link-preview-container", children: [state.context && (jsxRuntimeExports.jsx("p", { className: "ai-chat-link-preview__context", style: { marginBottom: '8px', fontSize: '0.9em', color: 'var(--ai-chat-fg-muted)' }, children: state.context })), jsxRuntimeExports.jsx("div", { className: gridClass, children: state.links.map((link, index) => (jsxRuntimeExports.jsx(SingleLinkPreview, { link: link, onLinkClick: () => handleLinkClick(link.url), accentColor: accentColor }, index))) })] }));
|
|
44782
44357
|
}
|
|
44783
44358
|
|
|
44784
44359
|
function PlayIcon() {
|
|
@@ -44799,7 +44374,7 @@
|
|
|
44799
44374
|
}
|
|
44800
44375
|
}
|
|
44801
44376
|
function VideoPlayerCard({ action, onComplete, accentColor }) {
|
|
44802
|
-
const rawState = action.
|
|
44377
|
+
const rawState = action.input;
|
|
44803
44378
|
const hasCompletedRef = reactExports.useRef(false);
|
|
44804
44379
|
const [isPlaying, setIsPlaying] = reactExports.useState(false);
|
|
44805
44380
|
// Provide safe defaults if state is missing
|
|
@@ -44910,7 +44485,7 @@
|
|
|
44910
44485
|
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-action-card ai-chat-location-card ${compact ? 'ai-chat-location-card--compact' : ''}`, style: style, children: [showMap && settings.showMap !== false && (jsxRuntimeExports.jsx("div", { className: "ai-chat-location-card__map", style: { height: effectiveMapHeight }, children: jsxRuntimeExports.jsx("iframe", { src: getMapEmbedUrl(), allowFullScreen: true, loading: "lazy", referrerPolicy: "no-referrer-when-downgrade", title: `Map of ${location.name}` }) })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-location-card__content", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-location-card__header", children: [jsxRuntimeExports.jsx("h4", { className: "ai-chat-location-card__name", children: location.name }), location.type && (jsxRuntimeExports.jsx("span", { className: "ai-chat-location-card__type", children: location.type })), openStatus !== null && (jsxRuntimeExports.jsx("span", { className: `ai-chat-location-card__status ai-chat-location-card__status--${openStatus ? 'open' : 'closed'}`, children: openStatus ? 'Open' : 'Closed' }))] }), jsxRuntimeExports.jsxs("p", { className: "ai-chat-location-card__address", children: [jsxRuntimeExports.jsx(MapPinIcon, {}), location.address] }), location.description && (jsxRuntimeExports.jsx("p", { className: "ai-chat-location-card__description", children: location.description })), settings.showHours !== false && location.hours && location.hours.length > 0 && (jsxRuntimeExports.jsx(HoursDisplay, { hours: location.hours, compact: compact })), settings.showPhone !== false && location.phone && (jsxRuntimeExports.jsxs("button", { type: "button", className: "ai-chat-location-card__phone", onClick: handleCall, children: [jsxRuntimeExports.jsx(PhoneIcon, {}), location.phone] })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-location-card__actions", children: [settings.showDirectionsButton !== false && (jsxRuntimeExports.jsxs("button", { type: "button", className: "ai-chat-location-card__button", style: accentColor ? { backgroundColor: accentColor } : undefined, onClick: onDirections, children: [jsxRuntimeExports.jsx(NavigationIcon, {}), compact ? 'Directions' : 'Get Directions'] })), !compact && location.website && (jsxRuntimeExports.jsxs("a", { href: location.website, target: "_blank", rel: "noopener noreferrer", className: "ai-chat-location-card__link", children: [jsxRuntimeExports.jsx(GlobeIcon, {}), "Website"] }))] })] })] }));
|
|
44911
44486
|
}
|
|
44912
44487
|
function LocationCard({ action, onComplete, accentColor, maxColumns = 3 }) {
|
|
44913
|
-
const rawState = action.
|
|
44488
|
+
const rawState = action.input;
|
|
44914
44489
|
const hasCompletedRef = reactExports.useRef(false);
|
|
44915
44490
|
const state = {
|
|
44916
44491
|
locations: rawState?.locations || [],
|
|
@@ -44992,7 +44567,7 @@
|
|
|
44992
44567
|
})()] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-contact-card__info", children: [jsxRuntimeExports.jsx("h4", { className: "ai-chat-contact-card__name", children: contact.name }), settings.showRole !== false && contact.role && (jsxRuntimeExports.jsx("p", { className: "ai-chat-contact-card__role", children: contact.role })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-contact-card__details", children: [settings.showEmail !== false && contact.email && (jsxRuntimeExports.jsx("a", { href: `mailto:${contact.email}`, className: "ai-chat-contact-card__detail", onClick: onEmail, children: contact.email })), settings.showPhone !== false && contact.phone && (jsxRuntimeExports.jsx("a", { href: `tel:${contact.phone}`, className: "ai-chat-contact-card__detail", onClick: onPhone, children: contact.phone }))] }), settings.showResponsibilities !== false && contact.responsibilities && contact.responsibilities.length > 0 && !compact && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-contact-card__responsibilities", children: [contact.responsibilities.slice(0, 3).map((resp, idx) => (jsxRuntimeExports.jsx("span", { className: "ai-chat-contact-card__responsibility-tag", children: resp }, idx))), contact.responsibilities.length > 3 && (jsxRuntimeExports.jsxs("span", { className: "ai-chat-contact-card__responsibility-more", children: ["+", contact.responsibilities.length - 3, " more"] }))] }))] })] }));
|
|
44993
44568
|
}
|
|
44994
44569
|
function ContactCard({ action, onComplete, accentColor, maxColumns = 3 }) {
|
|
44995
|
-
const rawState = action.
|
|
44570
|
+
const rawState = action.input;
|
|
44996
44571
|
const hasCompletedRef = reactExports.useRef(false);
|
|
44997
44572
|
const state = {
|
|
44998
44573
|
contacts: rawState?.contacts || [],
|
|
@@ -45027,11 +44602,37 @@
|
|
|
45027
44602
|
}, children: contacts.map((contact) => (jsxRuntimeExports.jsx(ContactItem, { contact: contact, settings: settings, accentColor: accentColor, onEmail: handleContact, onPhone: handleContact, compact: true, layout: settings.layout || 'vertical' }, contact.id))) })] }));
|
|
45028
44603
|
}
|
|
45029
44604
|
|
|
44605
|
+
const CloseButton = ({ onClick, className = "", ariaLabel = "Close", }) => {
|
|
44606
|
+
return (jsxRuntimeExports.jsx("button", { type: "button", className: `ai-chat-action-close-btn ${className}`, onClick: onClick, "aria-label": ariaLabel, children: jsxRuntimeExports.jsx("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "2", children: jsxRuntimeExports.jsx("path", { d: "M1 1L13 13M1 13L13 1" }) }) }));
|
|
44607
|
+
};
|
|
44608
|
+
|
|
44609
|
+
function FormIcon(props) {
|
|
44610
|
+
return (jsxRuntimeExports.jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", ...props, children: [jsxRuntimeExports.jsx("path", { d: "M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z" }), jsxRuntimeExports.jsx("polyline", { points: "14,2 14,8 20,8" }), jsxRuntimeExports.jsx("line", { x1: "16", y1: "13", x2: "8", y2: "13" }), jsxRuntimeExports.jsx("line", { x1: "16", y1: "17", x2: "8", y2: "17" }), jsxRuntimeExports.jsx("line", { x1: "10", y1: "9", x2: "8", y2: "9" })] }));
|
|
44611
|
+
}
|
|
44612
|
+
function CheckIcon(props) {
|
|
44613
|
+
return (jsxRuntimeExports.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", ...props, children: jsxRuntimeExports.jsx("polyline", { points: "20,6 9,17 4,12" }) }));
|
|
44614
|
+
}
|
|
44615
|
+
function WarningIcon(props) {
|
|
44616
|
+
return (jsxRuntimeExports.jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", ...props, children: [jsxRuntimeExports.jsx("path", { d: "M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" }), jsxRuntimeExports.jsx("line", { x1: "12", y1: "9", x2: "12", y2: "13" }), jsxRuntimeExports.jsx("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })] }));
|
|
44617
|
+
}
|
|
44618
|
+
function SkipIcon(props) {
|
|
44619
|
+
return (jsxRuntimeExports.jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", ...props, children: [jsxRuntimeExports.jsx("polygon", { points: "5,4 15,12 5,20 5,4" }), jsxRuntimeExports.jsx("line", { x1: "19", y1: "5", x2: "19", y2: "19" })] }));
|
|
44620
|
+
}
|
|
44621
|
+
function BackArrowIcon(props) {
|
|
44622
|
+
return (jsxRuntimeExports.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", ...props, children: jsxRuntimeExports.jsx("polyline", { points: "15,18 9,12 15,6" }) }));
|
|
44623
|
+
}
|
|
44624
|
+
|
|
45030
44625
|
function FormCard({ action, onComplete, onDismiss, accentColor }) {
|
|
45031
|
-
const state = action.
|
|
44626
|
+
const state = action.input;
|
|
45032
44627
|
const [currentStep, setCurrentStep] = reactExports.useState(0);
|
|
45033
44628
|
const [answers, setAnswers] = reactExports.useState({});
|
|
45034
44629
|
const [isSubmitting, setIsSubmitting] = reactExports.useState(false);
|
|
44630
|
+
const [localStatus, setLocalStatus] = reactExports.useState(null);
|
|
44631
|
+
// If action is already done, show simple completion indicator
|
|
44632
|
+
// The agent's response will convey what happened
|
|
44633
|
+
if (action.done) {
|
|
44634
|
+
return (jsxRuntimeExports.jsx("div", { className: "ai-chat-form-card ai-chat-form-card--completed", children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__icon", children: jsxRuntimeExports.jsx(CheckIcon, {}) }), jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__title", children: "Form completed" })] }) }));
|
|
44635
|
+
}
|
|
45035
44636
|
const questions = state.questions || [];
|
|
45036
44637
|
const currentQuestion = questions[currentStep];
|
|
45037
44638
|
const totalQuestions = questions.length;
|
|
@@ -45052,6 +44653,7 @@
|
|
|
45052
44653
|
if (!onComplete)
|
|
45053
44654
|
return;
|
|
45054
44655
|
setIsSubmitting(true);
|
|
44656
|
+
setLocalStatus('submitted');
|
|
45055
44657
|
const formattedAnswers = Object.entries(answers).map(([questionId, value]) => ({
|
|
45056
44658
|
questionId,
|
|
45057
44659
|
value,
|
|
@@ -45065,6 +44667,7 @@
|
|
|
45065
44667
|
const handleSkip = () => {
|
|
45066
44668
|
if (!onComplete || !state.settings.allowSkip)
|
|
45067
44669
|
return;
|
|
44670
|
+
setLocalStatus('skipped');
|
|
45068
44671
|
onComplete(action.toolCallId, {
|
|
45069
44672
|
...state,
|
|
45070
44673
|
status: 'skipped',
|
|
@@ -45095,24 +44698,26 @@
|
|
|
45095
44698
|
const handleDismiss = () => {
|
|
45096
44699
|
onDismiss?.(action.toolCallId);
|
|
45097
44700
|
};
|
|
44701
|
+
// Use local status if available (for immediate UI feedback), otherwise use state.status
|
|
44702
|
+
const effectiveStatus = localStatus || state.status;
|
|
45098
44703
|
// Error state
|
|
45099
|
-
if (
|
|
45100
|
-
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card ai-chat-form-card--error", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__icon", children:
|
|
44704
|
+
if (effectiveStatus === 'error') {
|
|
44705
|
+
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card ai-chat-form-card--error", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__icon", children: jsxRuntimeExports.jsx(WarningIcon, {}) }), jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__title", children: "Form Error" })] }), jsxRuntimeExports.jsx("p", { className: "ai-chat-form-card__error", children: state.error || 'Could not load form' })] }));
|
|
45101
44706
|
}
|
|
45102
44707
|
// Submitted state
|
|
45103
|
-
if (
|
|
45104
|
-
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card ai-chat-form-card--submitted", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__icon", children:
|
|
44708
|
+
if (effectiveStatus === 'submitted') {
|
|
44709
|
+
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card ai-chat-form-card--submitted", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__icon", children: jsxRuntimeExports.jsx(CheckIcon, {}) }), jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__title", children: state.title })] }), jsxRuntimeExports.jsx("p", { className: "ai-chat-form-card__success", children: state.settings.successMessage || 'Thank you for your response!' })] }));
|
|
45105
44710
|
}
|
|
45106
44711
|
// Skipped state
|
|
45107
|
-
if (
|
|
45108
|
-
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card ai-chat-form-card--skipped", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__icon", children:
|
|
44712
|
+
if (effectiveStatus === 'skipped') {
|
|
44713
|
+
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card ai-chat-form-card--skipped", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__icon", children: jsxRuntimeExports.jsx(SkipIcon, {}) }), jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__title", children: state.title })] }), jsxRuntimeExports.jsx("p", { className: "ai-chat-form-card__skipped-text", children: "Form skipped" })] }));
|
|
45109
44714
|
}
|
|
45110
44715
|
// No questions
|
|
45111
44716
|
if (totalQuestions === 0) {
|
|
45112
|
-
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card ai-chat-form-card--empty", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__icon", children:
|
|
44717
|
+
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card ai-chat-form-card--empty", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__icon", children: jsxRuntimeExports.jsx(FormIcon, {}) }), jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__title", children: state.title })] }), jsxRuntimeExports.jsx("p", { className: "ai-chat-form-card__empty-text", children: "This form has no questions." })] }));
|
|
45113
44718
|
}
|
|
45114
|
-
const showCloseButton =
|
|
45115
|
-
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-form-card${showCloseButton ? " ai-chat-form-card--closable" : ""}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__icon", children:
|
|
44719
|
+
const showCloseButton = effectiveStatus === "displaying" && !action.done && Boolean(onDismiss);
|
|
44720
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-form-card${showCloseButton ? " ai-chat-form-card--closable" : ""}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__icon", children: jsxRuntimeExports.jsx(FormIcon, {}) }), jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__title", children: state.title }), showCloseButton && (jsxRuntimeExports.jsx(CloseButton, { onClick: handleDismiss, ariaLabel: "Close form" }))] }), state.description && (jsxRuntimeExports.jsx("p", { className: "ai-chat-form-card__description", children: state.description })), state.context && (jsxRuntimeExports.jsx("p", { className: "ai-chat-form-card__context", children: state.context })), state.settings.showProgress && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__progress", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-form-card__progress-bar", style: {
|
|
45116
44721
|
width: `${((currentStep + 1) / totalQuestions) * 100}%`,
|
|
45117
44722
|
backgroundColor: accentColor || 'var(--ai-chat-accent-color, #3b82f6)',
|
|
45118
44723
|
} }), jsxRuntimeExports.jsxs("span", { className: "ai-chat-form-card__progress-text", children: [currentStep + 1, " of ", totalQuestions] })] })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__question", children: [jsxRuntimeExports.jsxs("p", { className: "ai-chat-form-card__question-text", children: [currentQuestion.text, currentQuestion.required && jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__required", children: "*" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-form-card__answer", children: [currentQuestion.type === 'text' && (jsxRuntimeExports.jsx("textarea", { className: "ai-chat-form-card__textarea", placeholder: currentQuestion.placeholder || 'Type your answer...', value: answers[currentQuestion.id] || '', onChange: (e) => handleAnswerChange(currentQuestion.id, e.target.value), rows: 3 })), currentQuestion.type === 'single_choice' && currentQuestion.options && (jsxRuntimeExports.jsx("div", { className: "ai-chat-form-card__options", children: currentQuestion.options.map((option) => (jsxRuntimeExports.jsxs("label", { className: "ai-chat-form-card__option", children: [jsxRuntimeExports.jsx("input", { type: "radio", name: currentQuestion.id, value: option.value, checked: answers[currentQuestion.id] === option.value, onChange: () => handleAnswerChange(currentQuestion.id, option.value) }), jsxRuntimeExports.jsx("span", { className: "ai-chat-form-card__option-text", children: option.text })] }, option.id))) })), currentQuestion.type === 'multiple_choice' && currentQuestion.options && (jsxRuntimeExports.jsx("div", { className: "ai-chat-form-card__options", children: currentQuestion.options.map((option) => {
|
|
@@ -45138,9 +44743,37 @@
|
|
|
45138
44743
|
}, children: isSubmitting ? 'Submitting...' : (state.settings.submitButtonText || 'Submit') }))] })] }));
|
|
45139
44744
|
}
|
|
45140
44745
|
|
|
44746
|
+
function EmailPhase({ accentColor, onDismiss, showCloseButton, onSubmit, isLoading, error, }) {
|
|
44747
|
+
const [emailInput, setEmailInput] = reactExports.useState('');
|
|
44748
|
+
const [localError, setLocalError] = reactExports.useState(null);
|
|
44749
|
+
const handleSubmit = () => {
|
|
44750
|
+
const trimmedEmail = emailInput.trim();
|
|
44751
|
+
if (!trimmedEmail) {
|
|
44752
|
+
setLocalError('Please enter your email address');
|
|
44753
|
+
return;
|
|
44754
|
+
}
|
|
44755
|
+
if (!trimmedEmail.includes('@')) {
|
|
44756
|
+
setLocalError('Please enter a valid email address');
|
|
44757
|
+
return;
|
|
44758
|
+
}
|
|
44759
|
+
setLocalError(null);
|
|
44760
|
+
onSubmit(trimmedEmail);
|
|
44761
|
+
};
|
|
44762
|
+
const displayError = localError || error;
|
|
44763
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-booking-card${showCloseButton ? ' ai-chat-booking-card--closable' : ''}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Enter Your Email" }), showCloseButton && onDismiss && jsxRuntimeExports.jsx(CloseButton, { onClick: onDismiss, ariaLabel: "Cancel booking" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__description", children: "Please enter your email address to start the booking process." }), displayError && (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__error", children: displayError })), jsxRuntimeExports.jsx("input", { type: "email", className: "ai-chat-booking-card__input", placeholder: "your@email.com", value: emailInput, onChange: (e) => {
|
|
44764
|
+
setEmailInput(e.target.value);
|
|
44765
|
+
setLocalError(null);
|
|
44766
|
+
}, onKeyDown: (e) => {
|
|
44767
|
+
if (e.key === 'Enter' && !isLoading) {
|
|
44768
|
+
handleSubmit();
|
|
44769
|
+
}
|
|
44770
|
+
}, disabled: isLoading }), jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__btn ai-chat-booking-card__btn--primary", onClick: handleSubmit, disabled: !emailInput.trim() || isLoading, children: isLoading ? 'Sending...' : 'Continue' })] })] }));
|
|
44771
|
+
}
|
|
44772
|
+
|
|
45141
44773
|
function Skeleton({ width, height, borderRadius = '4px' }) {
|
|
45142
44774
|
return (jsxRuntimeExports.jsx("div", { className: "ai-chat-action-skeleton-item", style: { width, height, borderRadius } }));
|
|
45143
44775
|
}
|
|
44776
|
+
|
|
45144
44777
|
function PinInputGroup({ values, onChange, disabled }) {
|
|
45145
44778
|
const inputRefs = reactExports.useRef([]);
|
|
45146
44779
|
const handleChange = (index, value) => {
|
|
@@ -45172,299 +44805,853 @@
|
|
|
45172
44805
|
inputRefs.current[index] = el;
|
|
45173
44806
|
}, type: "text", inputMode: "numeric", maxLength: 1, className: "ai-chat-pin-input", value: value, onChange: (e) => handleChange(index, e.target.value), onKeyDown: (e) => handleKeyDown(index, e), onPaste: handlePaste, disabled: disabled, autoFocus: index === 0 }, index))) }));
|
|
45174
44807
|
}
|
|
45175
|
-
|
|
45176
|
-
|
|
45177
|
-
const [emailInput, setEmailInput] = reactExports.useState('');
|
|
44808
|
+
|
|
44809
|
+
function OtpPhase({ accentColor, onDismiss, showCloseButton, email, onSubmit, onResend, isLoading, error, }) {
|
|
45178
44810
|
const [otpValues, setOtpValues] = reactExports.useState(Array(6).fill(''));
|
|
45179
|
-
const [
|
|
45180
|
-
const [
|
|
45181
|
-
const
|
|
45182
|
-
|
|
45183
|
-
|
|
45184
|
-
|
|
45185
|
-
if (!onComplete)
|
|
44811
|
+
const [localError, setLocalError] = reactExports.useState(null);
|
|
44812
|
+
const [isResending, setIsResending] = reactExports.useState(false);
|
|
44813
|
+
const handleSubmit = () => {
|
|
44814
|
+
const code = otpValues.join('');
|
|
44815
|
+
if (code.length !== 6) {
|
|
44816
|
+
setLocalError('Please enter the 6-digit code');
|
|
45186
44817
|
return;
|
|
45187
|
-
setIsSubmitting(true);
|
|
45188
|
-
setTimeout(() => {
|
|
45189
|
-
onComplete(action.toolCallId, { ...state, ...newState, errorMessage: null });
|
|
45190
|
-
}, delay);
|
|
45191
|
-
};
|
|
45192
|
-
reactExports.useEffect(() => {
|
|
45193
|
-
setIsSubmitting(false);
|
|
45194
|
-
if (phase === 'awaiting_email') {
|
|
45195
|
-
setEmailError(null);
|
|
45196
|
-
setOtpError(null);
|
|
45197
|
-
}
|
|
45198
|
-
else if (phase === 'awaiting_otp') {
|
|
45199
|
-
setOtpError(state.errorMessage || null);
|
|
45200
|
-
setEmailError(null);
|
|
45201
|
-
setOtpValues(Array(6).fill(''));
|
|
45202
|
-
if (state.email) {
|
|
45203
|
-
setEmailInput(state.email);
|
|
45204
|
-
}
|
|
45205
44818
|
}
|
|
45206
|
-
|
|
45207
|
-
|
|
45208
|
-
|
|
44819
|
+
setLocalError(null);
|
|
44820
|
+
onSubmit(code);
|
|
44821
|
+
};
|
|
44822
|
+
const handleResend = async () => {
|
|
44823
|
+
setIsResending(true);
|
|
44824
|
+
setLocalError(null);
|
|
44825
|
+
try {
|
|
44826
|
+
await onResend();
|
|
45209
44827
|
}
|
|
45210
|
-
|
|
45211
|
-
|
|
45212
|
-
const renderSkeleton = () => (jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card", children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-content", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-header", children: [jsxRuntimeExports.jsx(Skeleton, { width: "28px", height: "28px", borderRadius: "50%" }), jsxRuntimeExports.jsx(Skeleton, { width: "180px", height: "20px", borderRadius: "4px" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-box", children: [jsxRuntimeExports.jsx(Skeleton, { width: "60px", height: "12px", borderRadius: "4px" }), jsxRuntimeExports.jsx(Skeleton, { width: "120px", height: "18px", borderRadius: "4px" })] }), jsxRuntimeExports.jsx(Skeleton, { width: "100%", height: "44px", borderRadius: "999px" })] }) }));
|
|
45213
|
-
const handleEmailSubmit = () => {
|
|
45214
|
-
const trimmedEmail = emailInput.trim();
|
|
45215
|
-
if (!trimmedEmail) {
|
|
45216
|
-
setEmailError('Please enter your email address');
|
|
45217
|
-
return;
|
|
44828
|
+
finally {
|
|
44829
|
+
setIsResending(false);
|
|
45218
44830
|
}
|
|
45219
|
-
setEmailError(null);
|
|
45220
|
-
setEmailInput(trimmedEmail);
|
|
45221
|
-
handleSubmit({ email: trimmedEmail });
|
|
45222
44831
|
};
|
|
45223
|
-
const
|
|
45224
|
-
|
|
45225
|
-
|
|
45226
|
-
|
|
44832
|
+
const displayError = localError || error;
|
|
44833
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-booking-card${showCloseButton ? ' ai-chat-booking-card--closable' : ''}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Verify Your Email" }), showCloseButton && onDismiss && jsxRuntimeExports.jsx(CloseButton, { onClick: onDismiss, ariaLabel: "Cancel booking" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [jsxRuntimeExports.jsxs("p", { className: "ai-chat-booking-card__description", children: ["Enter the verification code sent to ", jsxRuntimeExports.jsx("strong", { children: email })] }), jsxRuntimeExports.jsx(PinInputGroup, { values: otpValues, onChange: (newValues) => {
|
|
44834
|
+
setOtpValues(newValues);
|
|
44835
|
+
setLocalError(null);
|
|
44836
|
+
// Auto-submit when all 6 digits are entered
|
|
44837
|
+
if (newValues.every((value) => value.length === 1) && !isLoading) {
|
|
44838
|
+
onSubmit(newValues.join(''));
|
|
44839
|
+
}
|
|
44840
|
+
}, disabled: isLoading }), displayError && (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__error", children: displayError })), jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__btn ai-chat-booking-card__btn--primary", onClick: handleSubmit, disabled: otpValues.join('').length !== 6 || isLoading, children: isLoading ? 'Verifying...' : 'Verify' }), jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__btn ai-chat-booking-card__btn--secondary", onClick: handleResend, disabled: isLoading || isResending, children: isResending ? 'Sending...' : 'Resend Code' })] })] }));
|
|
44841
|
+
}
|
|
44842
|
+
|
|
44843
|
+
function ContactSelectionPhase({ accentColor, onDismiss, showCloseButton, contacts, onSelect, }) {
|
|
44844
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-booking-card${showCloseButton ? ' ai-chat-booking-card--closable' : ''}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Select Contact" }), showCloseButton && onDismiss && jsxRuntimeExports.jsx(CloseButton, { onClick: onDismiss, ariaLabel: "Cancel booking" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__description", children: "Choose who you would like to book an appointment with:" }), jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__list", children: contacts.map((contact) => (jsxRuntimeExports.jsxs("button", { className: "ai-chat-booking-card__list-item", onClick: () => onSelect(contact.id), children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__list-item-content", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__list-item-name", children: contact.name }), contact.role && (jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__list-item-role", children: contact.role }))] }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__list-item-arrow", "aria-hidden": "true" })] }, contact.id))) })] })] }));
|
|
44845
|
+
}
|
|
44846
|
+
|
|
44847
|
+
// Calendar icon SVG
|
|
44848
|
+
const CalendarIcon = () => (jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2", ry: "2" }), jsxRuntimeExports.jsx("line", { x1: "16", y1: "2", x2: "16", y2: "6" }), jsxRuntimeExports.jsx("line", { x1: "8", y1: "2", x2: "8", y2: "6" }), jsxRuntimeExports.jsx("line", { x1: "3", y1: "10", x2: "21", y2: "10" })] }));
|
|
44849
|
+
// List icon SVG
|
|
44850
|
+
const ListIcon = () => (jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("line", { x1: "8", y1: "6", x2: "21", y2: "6" }), jsxRuntimeExports.jsx("line", { x1: "8", y1: "12", x2: "21", y2: "12" }), jsxRuntimeExports.jsx("line", { x1: "8", y1: "18", x2: "21", y2: "18" }), jsxRuntimeExports.jsx("line", { x1: "3", y1: "6", x2: "3.01", y2: "6" }), jsxRuntimeExports.jsx("line", { x1: "3", y1: "12", x2: "3.01", y2: "12" }), jsxRuntimeExports.jsx("line", { x1: "3", y1: "18", x2: "3.01", y2: "18" })] }));
|
|
44851
|
+
function OptionsPhase({ onDismiss, showCloseButton, appointments, maxAppointments, onBookNew, onViewAppointments, isCancelling, }) {
|
|
44852
|
+
const activeAppointments = appointments.filter(a => a.status !== 'cancelled' && a.status !== 'declined');
|
|
44853
|
+
const canBookNew = activeAppointments.length < maxAppointments;
|
|
44854
|
+
const hasAppointments = appointments.length > 0;
|
|
44855
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-booking-card${showCloseButton ? ' ai-chat-booking-card--closable' : ''}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Booking Options" }), showCloseButton && onDismiss && jsxRuntimeExports.jsx(CloseButton, { onClick: onDismiss, ariaLabel: "Cancel booking" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [!canBookNew && (jsxRuntimeExports.jsxs("p", { className: "ai-chat-booking-card__warning", children: ["You have reached the maximum number of appointments (", maxAppointments, "). Please cancel an existing appointment to book a new one."] })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__options", children: [jsxRuntimeExports.jsxs("button", { className: "ai-chat-booking-card__option-btn", onClick: onBookNew, disabled: !canBookNew || isCancelling, children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__option-icon", children: jsxRuntimeExports.jsx(CalendarIcon, {}) }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__option-text", children: "Book New Appointment" })] }), hasAppointments && (jsxRuntimeExports.jsxs("button", { className: "ai-chat-booking-card__option-btn", onClick: onViewAppointments, disabled: isCancelling, children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__option-icon", children: jsxRuntimeExports.jsx(ListIcon, {}) }), jsxRuntimeExports.jsxs("span", { className: "ai-chat-booking-card__option-text", children: ["View My Appointments (", activeAppointments.length, ")"] })] }))] })] })] }));
|
|
44856
|
+
}
|
|
44857
|
+
|
|
44858
|
+
function ViewAppointmentsPhase({ accentColor, onDismiss, showCloseButton, appointments, onBack, onCancelAppointment, isCancelling, }) {
|
|
44859
|
+
const [cancellingId, setCancellingId] = reactExports.useState(null);
|
|
44860
|
+
const handleCancel = async (appointmentId) => {
|
|
44861
|
+
setCancellingId(appointmentId);
|
|
44862
|
+
await onCancelAppointment(appointmentId);
|
|
44863
|
+
setCancellingId(null);
|
|
44864
|
+
};
|
|
44865
|
+
const activeAppointments = appointments.filter(a => a.status !== 'cancelled');
|
|
44866
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-booking-card${showCloseButton ? ' ai-chat-booking-card--closable' : ''}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__back-btn", onClick: onBack, children: "Back" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "My Appointments" }), showCloseButton && onDismiss && jsxRuntimeExports.jsx(CloseButton, { onClick: onDismiss, ariaLabel: "Cancel booking" })] }), jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__content", children: activeAppointments.length === 0 ? (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__empty", children: "No appointments found." })) : (jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__appointments", children: activeAppointments.map((apt) => (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__appointment", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__appointment-info", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__appointment-subject", children: apt.subject }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__appointment-contact", children: apt.contactName }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__appointment-time", children: apt.displayTime }), jsxRuntimeExports.jsx("span", { className: `ai-chat-booking-card__appointment-status ai-chat-booking-card__appointment-status--${apt.status}`, children: apt.status === 'pending' ? 'Pending Approval' : apt.status })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__appointment-actions", children: [apt.teamsLink && (jsxRuntimeExports.jsx("a", { href: apt.teamsLink, target: "_blank", rel: "noopener noreferrer", className: "ai-chat-booking-card__appointment-link", children: "Join Meeting" })), apt.googleMeetLink && (jsxRuntimeExports.jsx("a", { href: apt.googleMeetLink, target: "_blank", rel: "noopener noreferrer", className: "ai-chat-booking-card__appointment-link", children: "Join Meeting" })), jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__appointment-cancel", onClick: () => handleCancel(apt.id), disabled: isCancelling || cancellingId === apt.id, children: cancellingId === apt.id ? 'Cancelling...' : 'Cancel' })] })] }, apt.id))) })) })] }));
|
|
44867
|
+
}
|
|
44868
|
+
|
|
44869
|
+
function SlotSelectionPhase({ onDismiss, showCloseButton, slots, contactName, onSelect, onBack, isLoading, error, }) {
|
|
44870
|
+
// Group slots by date
|
|
44871
|
+
const slotsByDate = reactExports.useMemo(() => {
|
|
44872
|
+
const grouped = {};
|
|
44873
|
+
for (const slot of slots) {
|
|
44874
|
+
const date = slot.displayDate;
|
|
44875
|
+
if (!grouped[date]) {
|
|
44876
|
+
grouped[date] = [];
|
|
44877
|
+
}
|
|
44878
|
+
grouped[date].push(slot);
|
|
44879
|
+
}
|
|
44880
|
+
return grouped;
|
|
44881
|
+
}, [slots]);
|
|
44882
|
+
const dates = Object.keys(slotsByDate);
|
|
44883
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-booking-card${showCloseButton ? ' ai-chat-booking-card--closable' : ''}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__back-btn", onClick: onBack, children: "Back" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Select Time Slot" }), showCloseButton && onDismiss && jsxRuntimeExports.jsx(CloseButton, { onClick: onDismiss, ariaLabel: "Cancel booking" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [contactName && (jsxRuntimeExports.jsxs("p", { className: "ai-chat-booking-card__description", children: ["Available times for ", jsxRuntimeExports.jsx("strong", { children: contactName }), ":"] })), error && (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__error", children: error })), slots.length === 0 ? (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__empty", children: "No available time slots found. Please try again later." })) : (jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__slots-container", children: dates.map((date) => (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__date-group", children: [jsxRuntimeExports.jsx("h4", { className: "ai-chat-booking-card__date-header", children: date }), jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__slots", children: slotsByDate[date].map((slot) => (jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__slot", onClick: () => onSelect({ startTime: slot.startTime, endTime: slot.endTime }), disabled: isLoading, children: slot.displayTime }, `${slot.startTime}-${slot.endTime}`))) })] }, date))) }))] })] }));
|
|
44884
|
+
}
|
|
44885
|
+
|
|
44886
|
+
function ConfirmationPhase({ onDismiss, showCloseButton, contactName, slotDisplay, subjectMode, predefinedSubjects, onConfirm, onBack, isLoading, error, }) {
|
|
44887
|
+
const [subject, setSubject] = reactExports.useState('');
|
|
44888
|
+
const [selectedPredefined, setSelectedPredefined] = reactExports.useState('');
|
|
44889
|
+
const [localError, setLocalError] = reactExports.useState(null);
|
|
44890
|
+
const handleConfirm = () => {
|
|
44891
|
+
const finalSubject = subjectMode === 'predefined' ? selectedPredefined : subject.trim();
|
|
44892
|
+
if (!finalSubject) {
|
|
44893
|
+
setLocalError('Please enter a subject for your appointment');
|
|
45227
44894
|
return;
|
|
45228
44895
|
}
|
|
45229
|
-
|
|
45230
|
-
|
|
45231
|
-
handleSubmit({ otpCode: code, email: resolvedEmail });
|
|
44896
|
+
setLocalError(null);
|
|
44897
|
+
onConfirm(finalSubject);
|
|
45232
44898
|
};
|
|
45233
|
-
|
|
45234
|
-
|
|
45235
|
-
|
|
45236
|
-
|
|
45237
|
-
|
|
45238
|
-
|
|
45239
|
-
|
|
45240
|
-
|
|
45241
|
-
|
|
45242
|
-
|
|
45243
|
-
|
|
45244
|
-
|
|
45245
|
-
|
|
45246
|
-
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card ai-chat-booking-card--error", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__icon", children: "\u26A0\uFE0F" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Booking Error" })] }), state.errorMessage && (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__error", children: state.errorMessage }))] }));
|
|
45247
|
-
}
|
|
45248
|
-
if (isSubmitting || isWaitingForBackend) {
|
|
45249
|
-
return renderSkeleton();
|
|
45250
|
-
}
|
|
45251
|
-
// ========================================
|
|
45252
|
-
// Phase: Email Collection
|
|
45253
|
-
// ========================================
|
|
45254
|
-
if (phase === 'awaiting_email') {
|
|
45255
|
-
const displayError = emailError || state.errorMessage;
|
|
45256
|
-
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__icon", children: "\uD83D\uDCE7" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Enter Your Email" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__description", children: "Please enter your email address to start the booking process." }), displayError && (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__error", children: displayError })), jsxRuntimeExports.jsx("input", { type: "email", className: "ai-chat-booking-card__input", placeholder: "your@email.com", value: emailInput, onChange: (e) => {
|
|
45257
|
-
setEmailInput(e.target.value);
|
|
45258
|
-
setEmailError(null);
|
|
45259
|
-
}, onKeyDown: (e) => {
|
|
45260
|
-
if (e.key === 'Enter') {
|
|
45261
|
-
handleEmailSubmit();
|
|
45262
|
-
}
|
|
45263
|
-
} }), jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__btn ai-chat-booking-card__btn--primary", onClick: handleEmailSubmit, disabled: !emailInput.trim(), style: {
|
|
45264
|
-
backgroundColor: accentColor || undefined,
|
|
45265
|
-
borderColor: accentColor || undefined,
|
|
45266
|
-
}, children: "Continue" })] })] }));
|
|
45267
|
-
}
|
|
45268
|
-
// ========================================
|
|
45269
|
-
// Phase: OTP Verification
|
|
45270
|
-
// ========================================
|
|
45271
|
-
if (phase === 'awaiting_otp') {
|
|
45272
|
-
const displayError = otpError || state.errorMessage;
|
|
45273
|
-
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__icon", children: "\uD83D\uDD10" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Verify Your Email" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [jsxRuntimeExports.jsxs("p", { className: "ai-chat-booking-card__description", children: ["Enter the verification code sent to ", jsxRuntimeExports.jsx("strong", { children: state.email })] }), jsxRuntimeExports.jsx(PinInputGroup, { values: otpValues, onChange: (newValues) => {
|
|
45274
|
-
setOtpValues(newValues);
|
|
45275
|
-
setOtpError(null);
|
|
45276
|
-
if (newValues.every((value) => value.length === 1) && !isSubmitting) {
|
|
45277
|
-
const resolvedEmail = state.email || emailInput.trim() || null;
|
|
45278
|
-
handleSubmit({ otpCode: newValues.join(''), email: resolvedEmail }, 100);
|
|
45279
|
-
}
|
|
45280
|
-
}, disabled: isSubmitting }), displayError && (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__error", children: displayError })), jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__btn ai-chat-booking-card__btn--primary", onClick: handleOtpSubmit, disabled: otpValues.join('').length !== 6, style: {
|
|
45281
|
-
backgroundColor: accentColor || undefined,
|
|
45282
|
-
borderColor: accentColor || undefined,
|
|
45283
|
-
}, children: "Verify" })] })] }));
|
|
45284
|
-
}
|
|
45285
|
-
// ========================================
|
|
45286
|
-
// Phase: Contact Selection
|
|
45287
|
-
// ========================================
|
|
45288
|
-
if (phase === 'awaiting_contact_selection') {
|
|
45289
|
-
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__icon", children: "\uD83D\uDC65" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Select a Contact" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [state.errorMessage && (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__error", children: state.errorMessage })), state.bookableContacts.length === 0 ? (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__empty", children: "No contacts available for booking." })) : (jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__grid", children: state.bookableContacts.map((contact) => (jsxRuntimeExports.jsxs("button", { className: `ai-chat-booking-card__contact ${state.selectedContactId === contact.id ? 'ai-chat-booking-card__contact--selected' : ''}`, onClick: () => handleSubmit({ selectedContactId: contact.id }), style: {
|
|
45290
|
-
borderColor: state.selectedContactId === contact.id
|
|
45291
|
-
? accentColor || undefined
|
|
45292
|
-
: undefined,
|
|
45293
|
-
backgroundColor: state.selectedContactId === contact.id
|
|
45294
|
-
? `${accentColor || '#3b82f6'}15`
|
|
45295
|
-
: undefined,
|
|
45296
|
-
}, children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__contact-name", children: contact.name }), contact.role && (jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__contact-role", children: contact.role }))] }, contact.id))) }))] })] }));
|
|
45297
|
-
}
|
|
45298
|
-
// ========================================
|
|
45299
|
-
// Phase: Options Selection
|
|
45300
|
-
// ========================================
|
|
45301
|
-
if (phase === 'awaiting_options') {
|
|
45302
|
-
const selectedContact = state.bookableContacts.find((c) => c.id === state.selectedContactId);
|
|
45303
|
-
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__icon", children: "\uD83D\uDCC5" }), jsxRuntimeExports.jsxs("span", { className: "ai-chat-booking-card__title", children: ["Book with ", selectedContact?.name] })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [state.errorMessage && (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__error", children: state.errorMessage })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__options", children: [jsxRuntimeExports.jsxs("button", { className: "ai-chat-booking-card__option-btn", onClick: () => handleSubmit({ selectedOption: 'book_new' }), children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__option-icon", children: "\u2795" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__option-text", children: "Book New Appointment" })] }), state.userAppointments.length > 0 && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsxs("button", { className: "ai-chat-booking-card__option-btn", onClick: () => handleSubmit({ selectedOption: 'view_existing' }), children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__option-icon", children: "\uD83D\uDCCB" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__option-text", children: "View Appointments" })] }), jsxRuntimeExports.jsxs("button", { className: "ai-chat-booking-card__option-btn", onClick: () => handleSubmit({ selectedOption: 'cancel_existing' }), children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__option-icon", children: "\u2715" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__option-text", children: "Cancel Appointment" })] })] }))] })] })] }));
|
|
45304
|
-
}
|
|
45305
|
-
// ========================================
|
|
45306
|
-
// Phase: View Existing Appointments
|
|
45307
|
-
// ========================================
|
|
45308
|
-
if (state.phase === 'awaiting_options' && state.selectedOption === 'view_existing') {
|
|
45309
|
-
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__icon", children: "\uD83D\uDCCB" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Your Appointments" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [state.userAppointments.length === 0 ? (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__empty", children: "You have no appointments yet." })) : (jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__appointments", children: state.userAppointments.map((apt) => (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__appointment", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__appointment-header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__appointment-subject", children: apt.subject }), jsxRuntimeExports.jsx("span", { className: `ai-chat-booking-card__appointment-status ai-chat-booking-card__appointment-status--${apt.status}`, children: apt.status })] }), jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__appointment-time", children: apt.displayTime }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__appointment-contact", children: ["with ", apt.contactName] }), apt.teamsLink && (jsxRuntimeExports.jsx("a", { href: apt.teamsLink, target: "_blank", rel: "noopener noreferrer", className: "ai-chat-booking-card__link", style: { color: accentColor }, children: "Join Teams Meeting \u2192" }))] }, apt.id))) })), jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__btn ai-chat-booking-card__btn--secondary", onClick: () => handleSubmit({ selectedOption: undefined }), children: "Back" })] })] }));
|
|
45310
|
-
}
|
|
45311
|
-
// ========================================
|
|
45312
|
-
// Phase: Cancel Appointment
|
|
45313
|
-
// ========================================
|
|
45314
|
-
if (state.phase === 'awaiting_options' && state.selectedOption === 'cancel_existing') {
|
|
45315
|
-
const activeAppointments = state.userAppointments.filter((a) => a.status !== 'cancelled' && a.status !== 'declined');
|
|
45316
|
-
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__icon", children: "\u2715" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Cancel Appointment" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [state.errorMessage && (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__error", children: state.errorMessage })), activeAppointments.length === 0 ? (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__empty", children: "No active appointments to cancel." }), jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__btn ai-chat-booking-card__btn--secondary", onClick: () => handleSubmit({ selectedOption: undefined }), children: "Back" })] })) : (jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__appointments", children: activeAppointments.map((apt) => (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__appointment", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__appointment-header", children: jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__appointment-subject", children: apt.subject }) }), jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__appointment-time", children: apt.displayTime }), jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__btn ai-chat-booking-card__btn--danger", onClick: () => handleSubmit({ selectedAppointmentId: apt.id, confirmCancel: true }), children: "Cancel This Appointment" })] }, apt.id))) }))] })] }));
|
|
45317
|
-
}
|
|
45318
|
-
// ========================================
|
|
45319
|
-
// Phase: Slot Selection
|
|
45320
|
-
// ========================================
|
|
45321
|
-
if (phase === 'awaiting_slot_selection') {
|
|
45322
|
-
const groupedSlots = state.availableSlots.reduce((acc, slot) => {
|
|
45323
|
-
if (!acc[slot.displayDate]) {
|
|
45324
|
-
acc[slot.displayDate] = [];
|
|
45325
|
-
}
|
|
45326
|
-
acc[slot.displayDate].push(slot);
|
|
45327
|
-
return acc;
|
|
45328
|
-
}, {});
|
|
45329
|
-
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__icon", children: "\uD83D\uDD50" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Select a Time Slot" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [jsxRuntimeExports.jsxs("p", { className: "ai-chat-booking-card__description", children: ["Available times in ", state.timeZone] }), state.errorMessage && (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__error", children: state.errorMessage })), Object.entries(groupedSlots).map(([date, slots]) => (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__date-group", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__date-header", children: date }), jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__slots", children: slots.map((slot, idx) => {
|
|
45330
|
-
const isSelected = state.selectedSlot?.startTime === slot.startTime &&
|
|
45331
|
-
state.selectedSlot?.endTime === slot.endTime;
|
|
45332
|
-
return (jsxRuntimeExports.jsx("button", { className: `ai-chat-booking-card__slot ${isSelected ? 'ai-chat-booking-card__slot--selected' : ''}`, onClick: () => handleSubmit({
|
|
45333
|
-
selectedSlot: { startTime: slot.startTime, endTime: slot.endTime },
|
|
45334
|
-
}), style: {
|
|
45335
|
-
borderColor: isSelected ? accentColor || undefined : undefined,
|
|
45336
|
-
backgroundColor: isSelected ? `${accentColor || '#3b82f6'}15` : undefined,
|
|
45337
|
-
}, children: slot.displayTime }, `${slot.startTime}-${idx}`));
|
|
45338
|
-
}) })] }, date))), state.availableSlots.length === 0 && (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__empty", children: "No available time slots." }))] })] }));
|
|
45339
|
-
}
|
|
45340
|
-
// ========================================
|
|
45341
|
-
// Phase: Confirmation
|
|
45342
|
-
// ========================================
|
|
45343
|
-
if (phase === 'awaiting_confirmation') {
|
|
45344
|
-
const selectedContact = state.bookableContacts.find((c) => c.id === state.selectedContactId);
|
|
45345
|
-
const selectedSlot = state.availableSlots.find((s) => s.startTime === state.selectedSlot?.startTime && s.endTime === state.selectedSlot?.endTime);
|
|
45346
|
-
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__icon", children: "\u2713" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Confirm Booking" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [state.errorMessage && (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__error", children: state.errorMessage })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__summary", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__summary-row", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-label", children: "Contact:" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-value", children: selectedContact?.name })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__summary-row", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-label", children: "Date:" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-value", children: selectedSlot?.displayDate })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__summary-row", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-label", children: "Time:" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-value", children: selectedSlot?.displayTime })] })] }), state.allowCustomSubject && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("label", { className: "ai-chat-booking-card__label", children: "Subject (optional):" }), jsxRuntimeExports.jsx("input", { type: "text", className: "ai-chat-booking-card__input", placeholder: "Meeting subject", value: subjectInput, onChange: (e) => setSubjectInput(e.target.value) })] })), jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__btn ai-chat-booking-card__btn--primary", onClick: () => handleSubmit({
|
|
45347
|
-
subject: state.allowCustomSubject ? subjectInput || undefined : undefined,
|
|
45348
|
-
confirmed: true,
|
|
45349
|
-
}), style: {
|
|
45350
|
-
backgroundColor: accentColor || undefined,
|
|
45351
|
-
borderColor: accentColor || undefined,
|
|
45352
|
-
}, children: "Confirm Booking" })] })] }));
|
|
45353
|
-
}
|
|
45354
|
-
// Fallback for unknown states
|
|
45355
|
-
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__icon", children: "\uD83D\uDCC5" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Booking" })] }), jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__content", children: jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__description", children: "Loading booking options..." }) })] }));
|
|
44899
|
+
const displayError = localError || error;
|
|
44900
|
+
const isValid = subjectMode === 'predefined' ? !!selectedPredefined : !!subject.trim();
|
|
44901
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-booking-card${showCloseButton ? ' ai-chat-booking-card--closable' : ''}`, children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__back-btn", onClick: onBack, "aria-label": "Go back", children: jsxRuntimeExports.jsx(BackArrowIcon, {}) }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Confirm Booking" }), showCloseButton && onDismiss && jsxRuntimeExports.jsx(CloseButton, { onClick: onDismiss, ariaLabel: "Cancel booking" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__summary", children: [contactName && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__summary-row", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-label", children: "With:" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-value", children: contactName })] })), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__summary-row", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-label", children: "When:" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-value", children: slotDisplay })] })] }), displayError && (jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__error", children: displayError })), subjectMode === 'predefined' ? (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__field", children: [jsxRuntimeExports.jsx("label", { className: "ai-chat-booking-card__label", children: "Select a topic:" }), jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__subject-options", children: predefinedSubjects.map((subj) => (jsxRuntimeExports.jsx("button", { className: `ai-chat-booking-card__subject-option ${selectedPredefined === subj ? 'ai-chat-booking-card__subject-option--selected' : ''}`, onClick: () => {
|
|
44902
|
+
setSelectedPredefined(subj);
|
|
44903
|
+
setLocalError(null);
|
|
44904
|
+
}, disabled: isLoading, children: subj }, subj))) })] })) : (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__field", children: [jsxRuntimeExports.jsx("label", { className: "ai-chat-booking-card__label", children: "What would you like to discuss?" }), jsxRuntimeExports.jsx("input", { type: "text", className: "ai-chat-booking-card__input", placeholder: "Enter appointment subject...", value: subject, onChange: (e) => {
|
|
44905
|
+
setSubject(e.target.value);
|
|
44906
|
+
setLocalError(null);
|
|
44907
|
+
}, onKeyDown: (e) => {
|
|
44908
|
+
if (e.key === 'Enter' && isValid && !isLoading) {
|
|
44909
|
+
handleConfirm();
|
|
44910
|
+
}
|
|
44911
|
+
}, disabled: isLoading })] })), jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__btn ai-chat-booking-card__btn--primary", onClick: handleConfirm, disabled: !isValid || isLoading, children: isLoading ? 'Booking...' : 'Confirm Booking' })] })] }));
|
|
45356
44912
|
}
|
|
45357
44913
|
|
|
45358
|
-
|
|
45359
|
-
|
|
45360
|
-
|
|
45361
|
-
|
|
45362
|
-
|
|
45363
|
-
|
|
44914
|
+
function BookedPhase({ subject, contactName, meetingLink, meetingProvider, }) {
|
|
44915
|
+
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card ai-chat-booking-card--success", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__header", children: jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Appointment Booked" }) }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__success-icon", "aria-hidden": "true" }), jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__success-message", children: "Your appointment has been successfully scheduled." }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__summary", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__summary-row", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-label", children: "Subject:" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-value", children: subject })] }), contactName && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__summary-row", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-label", children: "With:" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-value", children: contactName })] }))] }), meetingLink && (jsxRuntimeExports.jsx("a", { href: meetingLink, target: "_blank", rel: "noopener noreferrer", className: "ai-chat-booking-card__btn ai-chat-booking-card__btn--primary", style: {
|
|
44916
|
+
textDecoration: 'none',
|
|
44917
|
+
display: 'inline-block',
|
|
44918
|
+
textAlign: 'center',
|
|
44919
|
+
}, children: meetingProvider === 'google' ? 'Join Google Meet' : 'Join Teams Meeting' }))] })] }));
|
|
45364
44920
|
}
|
|
45365
|
-
|
|
45366
|
-
|
|
44921
|
+
|
|
44922
|
+
function PendingApprovalPhase({ subject, contactName }) {
|
|
44923
|
+
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card ai-chat-booking-card--pending", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__status-icon ai-chat-booking-card__status-icon--pending" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Awaiting Approval" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__pending-text", children: "Your appointment request has been sent and is awaiting approval." }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__summary", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__summary-row", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-label", children: "Subject:" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-value", children: subject })] }), contactName && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__summary-row", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-label", children: "With:" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__summary-value", children: contactName })] }))] })] })] }));
|
|
45367
44924
|
}
|
|
45368
|
-
|
|
45369
|
-
|
|
45370
|
-
|
|
45371
|
-
|
|
44925
|
+
|
|
44926
|
+
/**
|
|
44927
|
+
* Cancelled Phase Component (terminal state)
|
|
44928
|
+
*/
|
|
44929
|
+
function CancelledPhase() {
|
|
44930
|
+
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card ai-chat-booking-card--cancelled", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__status-icon ai-chat-booking-card__status-icon--cancelled" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Appointment Cancelled" })] }), jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card__content", children: jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__description", children: "This appointment has been cancelled." }) })] }));
|
|
45372
44931
|
}
|
|
45373
|
-
|
|
45374
|
-
|
|
45375
|
-
|
|
45376
|
-
pendingResolvers.delete(toolCallId);
|
|
45377
|
-
resolver(state);
|
|
45378
|
-
return;
|
|
45379
|
-
}
|
|
45380
|
-
const resumeCallback = resumeCallbacks.get(toolCallId);
|
|
45381
|
-
if (resumeCallback) {
|
|
45382
|
-
resumeCallback(state).catch((error) => {
|
|
45383
|
-
console.error("[Action] Failed to resume action:", error);
|
|
45384
|
-
});
|
|
45385
|
-
}
|
|
44932
|
+
|
|
44933
|
+
function ErrorPhase({ error, onRetry }) {
|
|
44934
|
+
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card ai-chat-booking-card--error", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__header", children: [jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__status-icon ai-chat-booking-card__status-icon--error" }), jsxRuntimeExports.jsx("span", { className: "ai-chat-booking-card__title", children: "Booking Error" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__content", children: [jsxRuntimeExports.jsx("p", { className: "ai-chat-booking-card__error", children: error }), onRetry && (jsxRuntimeExports.jsx("button", { className: "ai-chat-booking-card__btn ai-chat-booking-card__btn--secondary", onClick: onRetry, children: "Try Again" }))] })] }));
|
|
45386
44935
|
}
|
|
45387
|
-
|
|
45388
|
-
|
|
44936
|
+
|
|
44937
|
+
function CompletedPhase() {
|
|
44938
|
+
return (jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card ai-chat-booking-card--completed", children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-booking-card__completed-indicator", children: [jsxRuntimeExports.jsx(CheckIcon, {}), jsxRuntimeExports.jsx("span", { children: "Booking action completed" })] }) }));
|
|
45389
44939
|
}
|
|
45390
|
-
|
|
45391
|
-
|
|
44940
|
+
|
|
44941
|
+
function LoadingPhase() {
|
|
44942
|
+
return (jsxRuntimeExports.jsx("div", { className: "ai-chat-booking-card", children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-content", children: [jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-header", children: [jsxRuntimeExports.jsx(Skeleton, { width: "28px", height: "28px", borderRadius: "50%" }), jsxRuntimeExports.jsx(Skeleton, { width: "180px", height: "20px", borderRadius: "4px" })] }), jsxRuntimeExports.jsxs("div", { className: "ai-chat-action-skeleton-box", children: [jsxRuntimeExports.jsx(Skeleton, { width: "60px", height: "12px", borderRadius: "4px" }), jsxRuntimeExports.jsx(Skeleton, { width: "120px", height: "18px", borderRadius: "4px" })] }), jsxRuntimeExports.jsx(Skeleton, { width: "100%", height: "44px", borderRadius: "999px" })] }) }));
|
|
45392
44943
|
}
|
|
45393
44944
|
|
|
45394
|
-
|
|
45395
|
-
|
|
45396
|
-
|
|
44945
|
+
/**
|
|
44946
|
+
* Core action lifecycle handlers for booking flow
|
|
44947
|
+
*/
|
|
44948
|
+
function useBookingAction({ onComplete, onDismiss, toolCallId, }) {
|
|
44949
|
+
const handleDismiss = reactExports.useCallback(() => {
|
|
44950
|
+
onDismiss?.(toolCallId);
|
|
44951
|
+
}, [onDismiss, toolCallId]);
|
|
44952
|
+
const finishAction = reactExports.useCallback((body) => {
|
|
44953
|
+
if (!onComplete)
|
|
44954
|
+
return;
|
|
44955
|
+
onComplete(toolCallId, body);
|
|
44956
|
+
}, [onComplete, toolCallId]);
|
|
44957
|
+
return {
|
|
44958
|
+
handleDismiss,
|
|
44959
|
+
finishAction,
|
|
45397
44960
|
};
|
|
45398
44961
|
}
|
|
45399
44962
|
|
|
45400
44963
|
/**
|
|
45401
|
-
*
|
|
45402
|
-
* Called by initializeActionHandlers to prevent tree-shaking.
|
|
44964
|
+
* Helper functions for accessing booking data
|
|
45403
44965
|
*/
|
|
45404
|
-
function
|
|
45405
|
-
|
|
45406
|
-
|
|
45407
|
-
|
|
45408
|
-
|
|
45409
|
-
|
|
45410
|
-
|
|
45411
|
-
|
|
45412
|
-
|
|
45413
|
-
|
|
45414
|
-
|
|
45415
|
-
|
|
45416
|
-
|
|
45417
|
-
|
|
45418
|
-
|
|
44966
|
+
function useBookingHelpers({ contacts, slots, bookingMode, }) {
|
|
44967
|
+
const getContactName = reactExports.useCallback((contactId) => {
|
|
44968
|
+
if (!contactId)
|
|
44969
|
+
return bookingMode === 'general' ? 'Shared Calendar' : null;
|
|
44970
|
+
const contact = contacts.find(c => c.id === contactId);
|
|
44971
|
+
return contact?.name || null;
|
|
44972
|
+
}, [contacts, bookingMode]);
|
|
44973
|
+
const getSlotDisplay = reactExports.useCallback((slot) => {
|
|
44974
|
+
if (!slot)
|
|
44975
|
+
return '';
|
|
44976
|
+
const slotData = slots.find(s => s.startTime === slot.startTime && s.endTime === slot.endTime);
|
|
44977
|
+
return slotData ? `${slotData.displayDate} ${slotData.displayTime}` : '';
|
|
44978
|
+
}, [slots]);
|
|
44979
|
+
return {
|
|
44980
|
+
getContactName,
|
|
44981
|
+
getSlotDisplay,
|
|
44982
|
+
};
|
|
44983
|
+
}
|
|
44984
|
+
|
|
44985
|
+
/**
|
|
44986
|
+
* OTP-related operations for email verification
|
|
44987
|
+
*/
|
|
44988
|
+
function useBookingOtp({ onCallEndpoint, state, setState, config, }) {
|
|
44989
|
+
const handleSendOtp = reactExports.useCallback(async (email) => {
|
|
44990
|
+
if (!onCallEndpoint) {
|
|
44991
|
+
setState(prev => ({ ...prev, error: 'Endpoint not available' }));
|
|
44992
|
+
return;
|
|
44993
|
+
}
|
|
44994
|
+
setState(prev => ({ ...prev, isLoading: true, error: null, email }));
|
|
44995
|
+
try {
|
|
44996
|
+
await onCallEndpoint('send-otp', { email });
|
|
44997
|
+
setState(prev => ({ ...prev, isLoading: false, step: 'otp' }));
|
|
44998
|
+
}
|
|
44999
|
+
catch (err) {
|
|
45000
|
+
const message = err instanceof Error ? err.message : 'Failed to send verification code';
|
|
45001
|
+
setState(prev => ({ ...prev, isLoading: false, error: message }));
|
|
45002
|
+
}
|
|
45003
|
+
}, [onCallEndpoint, setState]);
|
|
45004
|
+
const handleVerifyOtp = reactExports.useCallback(async (code) => {
|
|
45005
|
+
if (!onCallEndpoint) {
|
|
45006
|
+
setState(prev => ({ ...prev, error: 'Endpoint not available' }));
|
|
45007
|
+
return;
|
|
45008
|
+
}
|
|
45009
|
+
setState(prev => ({ ...prev, isLoading: true, error: null }));
|
|
45010
|
+
try {
|
|
45011
|
+
const result = await onCallEndpoint('verify-otp', {
|
|
45012
|
+
email: state.email,
|
|
45013
|
+
code,
|
|
45014
|
+
bookingMode: config.bookingMode,
|
|
45015
|
+
timeZone: config.timeZone,
|
|
45016
|
+
});
|
|
45017
|
+
const nextStep = config.bookingMode === 'general'
|
|
45018
|
+
? 'options'
|
|
45019
|
+
: result.contacts.length === 1
|
|
45020
|
+
? 'options'
|
|
45021
|
+
: 'contact_selection';
|
|
45022
|
+
setState(prev => ({
|
|
45023
|
+
...prev,
|
|
45024
|
+
isLoading: false,
|
|
45025
|
+
token: result.token,
|
|
45026
|
+
contacts: result.contacts,
|
|
45027
|
+
appointments: result.appointments,
|
|
45028
|
+
selectedContactId: result.contacts.length === 1 ? result.contacts[0].id : null,
|
|
45029
|
+
step: nextStep,
|
|
45030
|
+
}));
|
|
45031
|
+
}
|
|
45032
|
+
catch (err) {
|
|
45033
|
+
const message = err instanceof Error ? err.message : 'Invalid verification code';
|
|
45034
|
+
setState(prev => ({ ...prev, isLoading: false, error: message }));
|
|
45035
|
+
}
|
|
45036
|
+
}, [onCallEndpoint, state.email, config.bookingMode, config.timeZone, setState]);
|
|
45037
|
+
const handleResendOtp = reactExports.useCallback(async () => {
|
|
45038
|
+
await handleSendOtp(state.email);
|
|
45039
|
+
}, [handleSendOtp, state.email]);
|
|
45040
|
+
return {
|
|
45041
|
+
handleSendOtp,
|
|
45042
|
+
handleVerifyOtp,
|
|
45043
|
+
handleResendOtp,
|
|
45044
|
+
};
|
|
45045
|
+
}
|
|
45046
|
+
|
|
45047
|
+
/**
|
|
45048
|
+
* Navigation and flow control handlers for booking steps
|
|
45049
|
+
*/
|
|
45050
|
+
function useBookingNavigation({ onCallEndpoint, state, setState, config, }) {
|
|
45051
|
+
const handleSelectContact = reactExports.useCallback((contactId) => {
|
|
45052
|
+
setState(prev => ({
|
|
45053
|
+
...prev,
|
|
45054
|
+
selectedContactId: contactId,
|
|
45055
|
+
step: 'options',
|
|
45056
|
+
}));
|
|
45057
|
+
}, [setState]);
|
|
45058
|
+
const handleBookNew = reactExports.useCallback(async () => {
|
|
45059
|
+
if (!onCallEndpoint || !state.token) {
|
|
45060
|
+
setState(prev => ({ ...prev, error: 'Not authenticated' }));
|
|
45061
|
+
return;
|
|
45062
|
+
}
|
|
45063
|
+
setState(prev => ({ ...prev, isLoading: true, error: null }));
|
|
45064
|
+
try {
|
|
45065
|
+
const result = await onCallEndpoint('get-slots', {
|
|
45066
|
+
contactId: state.selectedContactId,
|
|
45067
|
+
daysAhead: config.daysAhead,
|
|
45068
|
+
timeZone: config.timeZone,
|
|
45069
|
+
}, { token: state.token });
|
|
45070
|
+
setState(prev => ({
|
|
45071
|
+
...prev,
|
|
45072
|
+
isLoading: false,
|
|
45073
|
+
slots: result.slots,
|
|
45074
|
+
step: 'slot_selection',
|
|
45075
|
+
}));
|
|
45076
|
+
}
|
|
45077
|
+
catch (err) {
|
|
45078
|
+
const message = err instanceof Error ? err.message : 'Failed to load available slots';
|
|
45079
|
+
setState(prev => ({ ...prev, isLoading: false, error: message }));
|
|
45080
|
+
}
|
|
45081
|
+
}, [onCallEndpoint, state.token, state.selectedContactId, config.daysAhead, config.timeZone, setState]);
|
|
45082
|
+
const handleViewAppointments = reactExports.useCallback(() => {
|
|
45083
|
+
setState(prev => ({ ...prev, step: 'view_appointments' }));
|
|
45084
|
+
}, [setState]);
|
|
45085
|
+
const handleBackToOptions = reactExports.useCallback(() => {
|
|
45086
|
+
setState(prev => ({ ...prev, step: 'options', error: null }));
|
|
45087
|
+
}, [setState]);
|
|
45088
|
+
const handleSelectSlot = reactExports.useCallback((slot) => {
|
|
45089
|
+
setState(prev => ({
|
|
45090
|
+
...prev,
|
|
45091
|
+
selectedSlot: slot,
|
|
45092
|
+
step: 'confirmation',
|
|
45093
|
+
}));
|
|
45094
|
+
}, [setState]);
|
|
45095
|
+
const handleBackToSlots = reactExports.useCallback(() => {
|
|
45096
|
+
setState(prev => ({ ...prev, step: 'slot_selection', error: null }));
|
|
45097
|
+
}, [setState]);
|
|
45098
|
+
return {
|
|
45099
|
+
handleSelectContact,
|
|
45100
|
+
handleBookNew,
|
|
45101
|
+
handleViewAppointments,
|
|
45102
|
+
handleBackToOptions,
|
|
45103
|
+
handleSelectSlot,
|
|
45104
|
+
handleBackToSlots,
|
|
45105
|
+
};
|
|
45106
|
+
}
|
|
45107
|
+
|
|
45108
|
+
/**
|
|
45109
|
+
* Core booking operations (confirm and cancel)
|
|
45110
|
+
*/
|
|
45111
|
+
function useBookingOperations({ onCallEndpoint, state, setState, config, getContactName, finishAction, }) {
|
|
45112
|
+
const [isCancelling, setIsCancelling] = reactExports.useState(false);
|
|
45113
|
+
const handleConfirmBooking = reactExports.useCallback(async (subject) => {
|
|
45114
|
+
if (!onCallEndpoint || !state.token || !state.selectedSlot) {
|
|
45115
|
+
setState(prev => ({ ...prev, error: 'Missing required data' }));
|
|
45116
|
+
return;
|
|
45117
|
+
}
|
|
45118
|
+
setState(prev => ({ ...prev, isLoading: true, error: null, subject }));
|
|
45119
|
+
try {
|
|
45120
|
+
const result = await onCallEndpoint('book', {
|
|
45121
|
+
contactId: state.selectedContactId,
|
|
45122
|
+
slot: state.selectedSlot,
|
|
45123
|
+
subject,
|
|
45124
|
+
timeZone: config.timeZone,
|
|
45125
|
+
}, { token: state.token });
|
|
45126
|
+
const contactName = getContactName(state.selectedContactId);
|
|
45127
|
+
if (result.status === 'pending_approval') {
|
|
45128
|
+
setState(prev => ({
|
|
45129
|
+
...prev,
|
|
45130
|
+
isLoading: false,
|
|
45131
|
+
step: 'pending_approval',
|
|
45132
|
+
}));
|
|
45133
|
+
// Finish with pending status
|
|
45134
|
+
finishAction({
|
|
45135
|
+
status: 'pending_approval',
|
|
45136
|
+
subject,
|
|
45137
|
+
contactName,
|
|
45138
|
+
message: `Appointment request "${subject}" submitted and awaiting approval.`,
|
|
45139
|
+
});
|
|
45419
45140
|
}
|
|
45420
|
-
|
|
45421
|
-
|
|
45422
|
-
|
|
45423
|
-
|
|
45424
|
-
|
|
45425
|
-
|
|
45426
|
-
|
|
45427
|
-
|
|
45428
|
-
|
|
45141
|
+
else {
|
|
45142
|
+
setState(prev => ({
|
|
45143
|
+
...prev,
|
|
45144
|
+
isLoading: false,
|
|
45145
|
+
bookedMeetingLink: result.meetingLink || null,
|
|
45146
|
+
bookedMeetingProvider: result.meetingProvider || null,
|
|
45147
|
+
step: 'booked',
|
|
45148
|
+
}));
|
|
45149
|
+
// Finish with booked status
|
|
45150
|
+
finishAction({
|
|
45151
|
+
status: 'booked',
|
|
45152
|
+
subject,
|
|
45153
|
+
contactName,
|
|
45154
|
+
meetingLink: result.meetingLink,
|
|
45155
|
+
message: `Successfully booked appointment "${subject}"${contactName ? ` with ${contactName}` : ''}.`,
|
|
45156
|
+
});
|
|
45157
|
+
}
|
|
45158
|
+
}
|
|
45159
|
+
catch (err) {
|
|
45160
|
+
const message = err instanceof Error ? err.message : 'Failed to book appointment';
|
|
45161
|
+
setState(prev => ({ ...prev, isLoading: false, error: message }));
|
|
45162
|
+
}
|
|
45163
|
+
}, [onCallEndpoint, state.token, state.selectedSlot, state.selectedContactId, config.timeZone, getContactName, finishAction, setState]);
|
|
45164
|
+
const handleCancelAppointment = reactExports.useCallback(async (appointmentId) => {
|
|
45165
|
+
if (!onCallEndpoint || !state.token) {
|
|
45166
|
+
setState(prev => ({ ...prev, error: 'Not authenticated' }));
|
|
45167
|
+
return;
|
|
45168
|
+
}
|
|
45169
|
+
setIsCancelling(true);
|
|
45170
|
+
try {
|
|
45171
|
+
await onCallEndpoint('cancel', { appointmentId }, { token: state.token });
|
|
45172
|
+
// Update local appointments list
|
|
45173
|
+
setState(prev => ({
|
|
45174
|
+
...prev,
|
|
45175
|
+
appointments: prev.appointments.map(apt => apt.id === appointmentId ? { ...apt, status: 'cancelled' } : apt),
|
|
45176
|
+
}));
|
|
45177
|
+
}
|
|
45178
|
+
catch (err) {
|
|
45179
|
+
const message = err instanceof Error ? err.message : 'Failed to cancel appointment';
|
|
45180
|
+
setState(prev => ({ ...prev, error: message }));
|
|
45181
|
+
}
|
|
45182
|
+
finally {
|
|
45183
|
+
setIsCancelling(false);
|
|
45184
|
+
}
|
|
45185
|
+
}, [onCallEndpoint, state.token, setState]);
|
|
45186
|
+
return {
|
|
45187
|
+
handleConfirmBooking,
|
|
45188
|
+
handleCancelAppointment,
|
|
45189
|
+
isCancelling,
|
|
45429
45190
|
};
|
|
45430
45191
|
}
|
|
45431
45192
|
|
|
45432
|
-
|
|
45433
|
-
|
|
45434
|
-
|
|
45193
|
+
// Default config values
|
|
45194
|
+
const DEFAULT_CONFIG = {
|
|
45195
|
+
bookingMode: 'per-contact',
|
|
45196
|
+
timeZone: 'UTC',
|
|
45197
|
+
maxAppointmentsPerUser: 3,
|
|
45198
|
+
daysAhead: 14,
|
|
45199
|
+
subjectMode: 'user_defined',
|
|
45200
|
+
predefinedSubjects: [],
|
|
45201
|
+
};
|
|
45202
|
+
// Initial UI state
|
|
45203
|
+
const createInitialState = () => ({
|
|
45204
|
+
step: 'email',
|
|
45205
|
+
email: '',
|
|
45206
|
+
selectedContactId: null,
|
|
45207
|
+
selectedSlot: null,
|
|
45208
|
+
subject: '',
|
|
45209
|
+
token: null,
|
|
45210
|
+
contacts: [],
|
|
45211
|
+
appointments: [],
|
|
45212
|
+
slots: [],
|
|
45213
|
+
bookedMeetingLink: null,
|
|
45214
|
+
bookedMeetingProvider: null,
|
|
45215
|
+
isLoading: false,
|
|
45216
|
+
error: null,
|
|
45217
|
+
});
|
|
45218
|
+
function BookContactAppointmentCard({ action, onComplete, onDismiss, onCallEndpoint, accentColor, }) {
|
|
45219
|
+
// Parse config from input (from getInitialClientState)
|
|
45220
|
+
const initialState = action.input;
|
|
45221
|
+
const config = {
|
|
45222
|
+
bookingMode: initialState.bookingMode || DEFAULT_CONFIG.bookingMode,
|
|
45223
|
+
timeZone: initialState.timeZone || DEFAULT_CONFIG.timeZone,
|
|
45224
|
+
maxAppointmentsPerUser: initialState.maxAppointmentsPerUser || DEFAULT_CONFIG.maxAppointmentsPerUser,
|
|
45225
|
+
daysAhead: initialState.daysAhead || DEFAULT_CONFIG.daysAhead,
|
|
45226
|
+
subjectMode: initialState.subjectMode || DEFAULT_CONFIG.subjectMode,
|
|
45227
|
+
predefinedSubjects: initialState.predefinedSubjects || DEFAULT_CONFIG.predefinedSubjects,
|
|
45228
|
+
};
|
|
45229
|
+
// Local UI state
|
|
45230
|
+
const [state, setState] = reactExports.useState(createInitialState);
|
|
45231
|
+
// Check if action is already done (from server state)
|
|
45232
|
+
const isDone = action.done;
|
|
45233
|
+
// Determine if dismiss should be available
|
|
45234
|
+
const isInteractiveStep = ['email', 'otp', 'contact_selection', 'options', 'view_appointments', 'slot_selection', 'confirmation'].includes(state.step);
|
|
45235
|
+
const showCloseButton = !isDone && isInteractiveStep && Boolean(onDismiss);
|
|
45236
|
+
// =========================================================================
|
|
45237
|
+
// Custom Hooks
|
|
45238
|
+
// =========================================================================
|
|
45239
|
+
// Core action lifecycle
|
|
45240
|
+
const { handleDismiss, finishAction } = useBookingAction({
|
|
45241
|
+
onComplete,
|
|
45242
|
+
onDismiss,
|
|
45243
|
+
toolCallId: action.toolCallId,
|
|
45244
|
+
});
|
|
45245
|
+
// Helper functions
|
|
45246
|
+
const { getContactName, getSlotDisplay } = useBookingHelpers({
|
|
45247
|
+
contacts: state.contacts,
|
|
45248
|
+
slots: state.slots,
|
|
45249
|
+
bookingMode: config.bookingMode,
|
|
45250
|
+
});
|
|
45251
|
+
// OTP operations
|
|
45252
|
+
const { handleSendOtp, handleVerifyOtp, handleResendOtp, } = useBookingOtp({
|
|
45253
|
+
onCallEndpoint,
|
|
45254
|
+
state: { email: state.email },
|
|
45255
|
+
setState,
|
|
45256
|
+
config: {
|
|
45257
|
+
bookingMode: config.bookingMode,
|
|
45258
|
+
timeZone: config.timeZone,
|
|
45259
|
+
},
|
|
45260
|
+
});
|
|
45261
|
+
// Navigation handlers
|
|
45262
|
+
const { handleSelectContact, handleBookNew, handleViewAppointments, handleBackToOptions, handleSelectSlot, handleBackToSlots, } = useBookingNavigation({
|
|
45263
|
+
onCallEndpoint,
|
|
45264
|
+
state,
|
|
45265
|
+
setState,
|
|
45266
|
+
config: {
|
|
45267
|
+
daysAhead: config.daysAhead,
|
|
45268
|
+
timeZone: config.timeZone,
|
|
45269
|
+
},
|
|
45270
|
+
});
|
|
45271
|
+
// Booking operations
|
|
45272
|
+
const { handleConfirmBooking, handleCancelAppointment, isCancelling, } = useBookingOperations({
|
|
45273
|
+
onCallEndpoint,
|
|
45274
|
+
state,
|
|
45275
|
+
setState,
|
|
45276
|
+
config: {
|
|
45277
|
+
timeZone: config.timeZone,
|
|
45278
|
+
},
|
|
45279
|
+
getContactName,
|
|
45280
|
+
finishAction,
|
|
45281
|
+
});
|
|
45282
|
+
// =========================================================================
|
|
45283
|
+
// Render
|
|
45284
|
+
// =========================================================================
|
|
45285
|
+
// If action is already done, show a simple completion indicator
|
|
45286
|
+
// The agent's response will convey what happened - no need to reconstruct terminal state
|
|
45287
|
+
if (isDone) {
|
|
45288
|
+
return jsxRuntimeExports.jsx(CompletedPhase, {});
|
|
45289
|
+
}
|
|
45290
|
+
// Show loading when making API calls
|
|
45291
|
+
if (state.isLoading) {
|
|
45292
|
+
return jsxRuntimeExports.jsx(LoadingPhase, {});
|
|
45293
|
+
}
|
|
45294
|
+
// Render based on current step
|
|
45295
|
+
switch (state.step) {
|
|
45296
|
+
case 'email':
|
|
45297
|
+
return (jsxRuntimeExports.jsx(EmailPhase, { accentColor: accentColor, onDismiss: handleDismiss, showCloseButton: showCloseButton, onSubmit: handleSendOtp, isLoading: state.isLoading, error: state.error }));
|
|
45298
|
+
case 'otp':
|
|
45299
|
+
return (jsxRuntimeExports.jsx(OtpPhase, { accentColor: accentColor, onDismiss: handleDismiss, showCloseButton: showCloseButton, email: state.email, onSubmit: handleVerifyOtp, onResend: handleResendOtp, isLoading: state.isLoading, error: state.error }));
|
|
45300
|
+
case 'contact_selection':
|
|
45301
|
+
return (jsxRuntimeExports.jsx(ContactSelectionPhase, { accentColor: accentColor, onDismiss: handleDismiss, showCloseButton: showCloseButton, contacts: state.contacts, onSelect: handleSelectContact }));
|
|
45302
|
+
case 'options':
|
|
45303
|
+
return (jsxRuntimeExports.jsx(OptionsPhase, { accentColor: accentColor, onDismiss: handleDismiss, showCloseButton: showCloseButton, appointments: state.appointments.filter(a => a.status !== 'cancelled'), maxAppointments: config.maxAppointmentsPerUser, onBookNew: handleBookNew, onViewAppointments: handleViewAppointments, onCancelAppointment: handleCancelAppointment, isCancelling: isCancelling }));
|
|
45304
|
+
case 'view_appointments':
|
|
45305
|
+
return (jsxRuntimeExports.jsx(ViewAppointmentsPhase, { accentColor: accentColor, onDismiss: handleDismiss, showCloseButton: showCloseButton, appointments: state.appointments, onBack: handleBackToOptions, onCancelAppointment: handleCancelAppointment, isCancelling: isCancelling }));
|
|
45306
|
+
case 'slot_selection':
|
|
45307
|
+
return (jsxRuntimeExports.jsx(SlotSelectionPhase, { accentColor: accentColor, onDismiss: handleDismiss, showCloseButton: showCloseButton, slots: state.slots, contactName: getContactName(state.selectedContactId), onSelect: handleSelectSlot, onBack: handleBackToOptions, isLoading: state.isLoading, error: state.error }));
|
|
45308
|
+
case 'confirmation':
|
|
45309
|
+
return (jsxRuntimeExports.jsx(ConfirmationPhase, { accentColor: accentColor, onDismiss: handleDismiss, showCloseButton: showCloseButton, contactName: getContactName(state.selectedContactId), slot: state.selectedSlot, slotDisplay: getSlotDisplay(state.selectedSlot), subjectMode: config.subjectMode, predefinedSubjects: config.predefinedSubjects, onConfirm: handleConfirmBooking, onBack: handleBackToSlots, isLoading: state.isLoading, error: state.error }));
|
|
45310
|
+
case 'booked':
|
|
45311
|
+
return (jsxRuntimeExports.jsx(BookedPhase, { subject: state.subject, contactName: getContactName(state.selectedContactId), meetingLink: state.bookedMeetingLink, meetingProvider: state.bookedMeetingProvider }));
|
|
45312
|
+
case 'pending_approval':
|
|
45313
|
+
return (jsxRuntimeExports.jsx(PendingApprovalPhase, { subject: state.subject, contactName: getContactName(state.selectedContactId) }));
|
|
45314
|
+
case 'cancelled':
|
|
45315
|
+
return jsxRuntimeExports.jsx(CancelledPhase, {});
|
|
45316
|
+
case 'error':
|
|
45317
|
+
return jsxRuntimeExports.jsx(ErrorPhase, { error: state.error || 'An error occurred' });
|
|
45318
|
+
default:
|
|
45319
|
+
return jsxRuntimeExports.jsx(ErrorPhase, { error: "Unknown state" });
|
|
45320
|
+
}
|
|
45321
|
+
}
|
|
45322
|
+
|
|
45323
|
+
function ExternalLinkIcon$1() {
|
|
45324
|
+
return (jsxRuntimeExports.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }), jsxRuntimeExports.jsx("polyline", { points: "15 3 21 3 21 9" }), jsxRuntimeExports.jsx("line", { x1: "10", y1: "14", x2: "21", y2: "3" })] }));
|
|
45325
|
+
}
|
|
45326
|
+
function ImageCard({ item, accentColor, showOverlay = true, onClick, onLinkClick }) {
|
|
45327
|
+
const [imageError, setImageError] = reactExports.useState(false);
|
|
45328
|
+
const style = accentColor ? { '--action-accent': accentColor } : undefined;
|
|
45329
|
+
const hasMetadata = item.title || item.description || item.link;
|
|
45330
|
+
const handleLinkClick = (e) => {
|
|
45331
|
+
e.stopPropagation();
|
|
45332
|
+
if (item.link) {
|
|
45333
|
+
onLinkClick?.(item.link);
|
|
45334
|
+
window.open(item.link, '_blank', 'noopener,noreferrer');
|
|
45335
|
+
}
|
|
45336
|
+
};
|
|
45337
|
+
const handleImageClick = () => {
|
|
45338
|
+
if (onClick) {
|
|
45339
|
+
onClick();
|
|
45340
|
+
}
|
|
45435
45341
|
};
|
|
45342
|
+
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-image-card", style: style, onClick: handleImageClick, children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-image-card__media", children: !imageError ? (jsxRuntimeExports.jsx("img", { src: item.url, alt: item.alt || item.title || 'Image', className: "ai-chat-image-card__image", onError: () => setImageError(true) })) : (jsxRuntimeExports.jsx("div", { className: "ai-chat-image-card__image-error", children: jsxRuntimeExports.jsx("span", { children: "Failed to load image" }) })) }), hasMetadata && showOverlay && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-image-card__content", children: [item.title && (jsxRuntimeExports.jsx("h4", { className: "ai-chat-image-card__title", children: item.title })), item.description && (jsxRuntimeExports.jsx("p", { className: "ai-chat-image-card__description", children: item.description })), item.link && (jsxRuntimeExports.jsxs("button", { className: "ai-chat-image-card__link-btn", onClick: handleLinkClick, children: [item.linkText || 'View More', jsxRuntimeExports.jsx(ExternalLinkIcon$1, {})] }))] }))] }));
|
|
45343
|
+
}
|
|
45344
|
+
|
|
45345
|
+
function ImageGallery({ items, columns = 2, accentColor }) {
|
|
45346
|
+
const [imageErrors, setImageErrors] = reactExports.useState(new Set());
|
|
45347
|
+
const imageItems = items;
|
|
45348
|
+
if (imageItems.length === 0)
|
|
45349
|
+
return null;
|
|
45350
|
+
// Determine if first item should span full width (for odd counts > 1)
|
|
45351
|
+
const itemCount = imageItems.length;
|
|
45352
|
+
const isOddCount = itemCount > 1 && itemCount % 2 === 1;
|
|
45353
|
+
const style = {
|
|
45354
|
+
...(accentColor ? { '--action-accent': accentColor } : {}),
|
|
45355
|
+
'--gallery-item-count': itemCount,
|
|
45356
|
+
};
|
|
45357
|
+
const handleImageError = (index) => {
|
|
45358
|
+
setImageErrors(prev => new Set(prev).add(index));
|
|
45359
|
+
};
|
|
45360
|
+
return (jsxRuntimeExports.jsx("div", { className: "ai-chat-image-gallery", style: style, "data-item-count": itemCount, children: jsxRuntimeExports.jsx("div", { className: `ai-chat-image-gallery__grid ${isOddCount ? 'odd-count' : ''}`, "data-count": itemCount, children: imageItems.map((item, index) => (jsxRuntimeExports.jsx("div", { className: `ai-chat-image-gallery__item ${isOddCount && index === 0 ? 'span-full' : ''}`, children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-image-gallery__item-media", children: [!imageErrors.has(index) ? (jsxRuntimeExports.jsx("img", { src: item.url, alt: item.alt || item.title || `Image ${index + 1}`, onError: () => handleImageError(index) })) : (jsxRuntimeExports.jsx("div", { className: "ai-chat-image-gallery__error", children: jsxRuntimeExports.jsx("span", { children: "Failed to load" }) })), item.title && (jsxRuntimeExports.jsx("div", { className: "ai-chat-image-gallery__item-overlay", children: jsxRuntimeExports.jsx("span", { className: "ai-chat-image-gallery__item-title", children: item.title }) }))] }) }, index))) }) }));
|
|
45361
|
+
}
|
|
45362
|
+
|
|
45363
|
+
function ExternalLinkIcon() {
|
|
45364
|
+
return (jsxRuntimeExports.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }), jsxRuntimeExports.jsx("polyline", { points: "15 3 21 3 21 9" }), jsxRuntimeExports.jsx("line", { x1: "10", y1: "14", x2: "21", y2: "3" })] }));
|
|
45365
|
+
}
|
|
45366
|
+
function truncate(text, maxLength) {
|
|
45367
|
+
if (text.length <= maxLength)
|
|
45368
|
+
return text;
|
|
45369
|
+
return text.slice(0, maxLength).trim() + '...';
|
|
45370
|
+
}
|
|
45371
|
+
function ProjectCard({ item, accentColor, onLinkClick, variant }) {
|
|
45372
|
+
const [imageError, setImageError] = reactExports.useState(false);
|
|
45373
|
+
const style = accentColor ? { '--action-accent': accentColor } : undefined;
|
|
45374
|
+
const imageUrl = item.url;
|
|
45375
|
+
// Determine variant based on content if not specified
|
|
45376
|
+
const hasTextContent = item.title || item.description;
|
|
45377
|
+
const effectiveVariant = variant || (hasTextContent ? 'full' : 'image-only');
|
|
45378
|
+
const handleCardClick = () => {
|
|
45379
|
+
if (item.link) {
|
|
45380
|
+
onLinkClick?.(item.link);
|
|
45381
|
+
window.open(item.link, '_blank', 'noopener,noreferrer');
|
|
45382
|
+
}
|
|
45383
|
+
};
|
|
45384
|
+
// Image-only variant - just the image with optional hover effect
|
|
45385
|
+
if (effectiveVariant === 'image-only') {
|
|
45386
|
+
return (jsxRuntimeExports.jsx("div", { className: `ai-chat-project-card ai-chat-project-card--image-only ${item.link ? 'clickable' : ''}`, style: style, onClick: item.link ? handleCardClick : undefined, role: item.link ? 'link' : undefined, tabIndex: item.link ? 0 : undefined, onKeyDown: (e) => e.key === 'Enter' && item.link && handleCardClick(), children: jsxRuntimeExports.jsx("div", { className: "ai-chat-project-card__media", children: imageUrl && !imageError ? (jsxRuntimeExports.jsx("img", { src: imageUrl, alt: item.alt || 'Image', onError: () => setImageError(true) })) : (jsxRuntimeExports.jsx("div", { className: "ai-chat-project-card__placeholder", children: imageError ? 'Failed to load' : 'No image' })) }) }));
|
|
45387
|
+
}
|
|
45388
|
+
// Overlay variant - title overlaid on image
|
|
45389
|
+
if (effectiveVariant === 'overlay') {
|
|
45390
|
+
return (jsxRuntimeExports.jsx("div", { className: `ai-chat-project-card ai-chat-project-card--overlay ${item.link ? 'clickable' : ''}`, style: style, onClick: item.link ? handleCardClick : undefined, role: item.link ? 'link' : undefined, tabIndex: item.link ? 0 : undefined, onKeyDown: (e) => e.key === 'Enter' && item.link && handleCardClick(), children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-project-card__media", children: [imageUrl && !imageError ? (jsxRuntimeExports.jsx("img", { src: imageUrl, alt: item.alt || item.title || 'Image', onError: () => setImageError(true) })) : (jsxRuntimeExports.jsx("div", { className: "ai-chat-project-card__placeholder", children: imageError ? 'Failed to load' : 'No image' })), item.title && (jsxRuntimeExports.jsx("div", { className: "ai-chat-project-card__overlay", children: jsxRuntimeExports.jsx("h4", { className: "ai-chat-project-card__overlay-title", children: truncate(item.title, 50) }) }))] }) }));
|
|
45391
|
+
}
|
|
45392
|
+
// Full variant - image with separate content section below
|
|
45393
|
+
return (jsxRuntimeExports.jsxs("div", { className: `ai-chat-project-card ai-chat-project-card--full ${item.link ? 'clickable' : ''}`, style: style, onClick: item.link ? handleCardClick : undefined, role: item.link ? 'link' : undefined, tabIndex: item.link ? 0 : undefined, onKeyDown: (e) => e.key === 'Enter' && item.link && handleCardClick(), children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-project-card__media", children: imageUrl && !imageError ? (jsxRuntimeExports.jsx("img", { src: imageUrl, alt: item.alt || item.title || 'Project image', onError: () => setImageError(true) })) : (jsxRuntimeExports.jsx("div", { className: "ai-chat-project-card__placeholder", children: imageError ? 'Failed to load' : 'No image' })) }), hasTextContent && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-project-card__content", children: [item.title && (jsxRuntimeExports.jsx("h4", { className: "ai-chat-project-card__title", children: truncate(item.title, 60) })), item.description && (jsxRuntimeExports.jsx("p", { className: "ai-chat-project-card__description", children: truncate(item.description, 120) })), item.link && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-project-card__link", children: [jsxRuntimeExports.jsx("span", { children: item.linkText || 'View' }), jsxRuntimeExports.jsx(ExternalLinkIcon, {})] }))] }))] }));
|
|
45436
45394
|
}
|
|
45437
45395
|
|
|
45438
45396
|
/**
|
|
45439
|
-
*
|
|
45440
|
-
*
|
|
45397
|
+
* URL validation utilities for images, cards, and links
|
|
45398
|
+
* Prevents 404 errors by validating URLs before display
|
|
45441
45399
|
*/
|
|
45442
|
-
|
|
45443
|
-
|
|
45444
|
-
|
|
45445
|
-
|
|
45446
|
-
|
|
45447
|
-
|
|
45448
|
-
|
|
45449
|
-
|
|
45450
|
-
|
|
45451
|
-
|
|
45400
|
+
/**
|
|
45401
|
+
* Validate a single URL by attempting to load it
|
|
45402
|
+
*/
|
|
45403
|
+
/**
|
|
45404
|
+
* Validate an image URL by attempting to load it as an Image
|
|
45405
|
+
*/
|
|
45406
|
+
async function validateImageUrl(url, timeout = 5000) {
|
|
45407
|
+
if (!url || typeof url !== 'string') {
|
|
45408
|
+
return { isValid: false, error: 'Invalid URL format' };
|
|
45409
|
+
}
|
|
45410
|
+
try {
|
|
45411
|
+
new URL(url);
|
|
45412
|
+
}
|
|
45413
|
+
catch (e) {
|
|
45414
|
+
return { isValid: false, error: 'Invalid URL structure' };
|
|
45415
|
+
}
|
|
45416
|
+
return new Promise((resolve) => {
|
|
45417
|
+
const img = new Image();
|
|
45418
|
+
const timeoutId = setTimeout(() => {
|
|
45419
|
+
img.src = '';
|
|
45420
|
+
resolve({ isValid: false, error: 'Image load timeout' });
|
|
45421
|
+
}, timeout);
|
|
45422
|
+
img.onload = () => {
|
|
45423
|
+
clearTimeout(timeoutId);
|
|
45424
|
+
resolve({ isValid: true });
|
|
45452
45425
|
};
|
|
45453
|
-
|
|
45454
|
-
|
|
45455
|
-
|
|
45456
|
-
|
|
45426
|
+
img.onerror = () => {
|
|
45427
|
+
clearTimeout(timeoutId);
|
|
45428
|
+
resolve({ isValid: false, error: 'Failed to load image' });
|
|
45429
|
+
};
|
|
45430
|
+
img.src = url;
|
|
45431
|
+
});
|
|
45432
|
+
}
|
|
45433
|
+
/**
|
|
45434
|
+
* Validate multiple image URLs concurrently
|
|
45435
|
+
*/
|
|
45436
|
+
async function validateImageUrls(urls, timeout = 5000, maxConcurrent = 10) {
|
|
45437
|
+
const results = new Map();
|
|
45438
|
+
// Process in batches to limit concurrent requests
|
|
45439
|
+
for (let i = 0; i < urls.length; i += maxConcurrent) {
|
|
45440
|
+
const batch = urls.slice(i, i + maxConcurrent);
|
|
45441
|
+
const batchResults = await Promise.all(batch.map(async (url) => {
|
|
45442
|
+
const result = await validateImageUrl(url, timeout);
|
|
45443
|
+
return { url, result };
|
|
45444
|
+
}));
|
|
45445
|
+
batchResults.forEach(({ url, result }) => {
|
|
45446
|
+
results.set(url, result);
|
|
45447
|
+
});
|
|
45448
|
+
}
|
|
45449
|
+
return results;
|
|
45450
|
+
}
|
|
45451
|
+
/**
|
|
45452
|
+
* Validate image items and separate valid from invalid
|
|
45453
|
+
*/
|
|
45454
|
+
async function validateImageItems(items, timeout = 5000) {
|
|
45455
|
+
const urls = items.map(item => item.url).filter(Boolean);
|
|
45456
|
+
if (urls.length === 0) {
|
|
45457
|
+
return { validItems: [], invalidItems: items };
|
|
45458
|
+
}
|
|
45459
|
+
const validationResults = await validateImageUrls(urls, timeout);
|
|
45460
|
+
const validItems = [];
|
|
45461
|
+
const invalidItems = [];
|
|
45462
|
+
items.forEach(item => {
|
|
45463
|
+
if (!item.url) {
|
|
45464
|
+
invalidItems.push({
|
|
45465
|
+
...item,
|
|
45466
|
+
isValid: false,
|
|
45467
|
+
validationError: 'Missing URL',
|
|
45468
|
+
});
|
|
45469
|
+
return;
|
|
45470
|
+
}
|
|
45471
|
+
const result = validationResults.get(item.url);
|
|
45472
|
+
if (result?.isValid) {
|
|
45473
|
+
validItems.push({
|
|
45474
|
+
...item,
|
|
45475
|
+
isValid: true,
|
|
45476
|
+
});
|
|
45477
|
+
}
|
|
45478
|
+
else {
|
|
45479
|
+
invalidItems.push({
|
|
45480
|
+
...item,
|
|
45481
|
+
isValid: false,
|
|
45482
|
+
validationError: result?.error || 'Unknown error',
|
|
45483
|
+
});
|
|
45484
|
+
}
|
|
45485
|
+
});
|
|
45486
|
+
return { validItems, invalidItems };
|
|
45487
|
+
}
|
|
45488
|
+
/**
|
|
45489
|
+
* Preload and validate images before rendering
|
|
45490
|
+
* Returns items with validation status
|
|
45491
|
+
*/
|
|
45492
|
+
async function preloadAndValidateImages(items, timeout = 5000) {
|
|
45493
|
+
const { validItems, invalidItems } = await validateImageItems(items, timeout);
|
|
45494
|
+
if (invalidItems.length > 0) {
|
|
45495
|
+
console.warn('[URLValidator] Invalid image URLs detected:', invalidItems.map(i => ({
|
|
45496
|
+
url: i.url,
|
|
45497
|
+
error: i.validationError,
|
|
45498
|
+
})));
|
|
45499
|
+
}
|
|
45500
|
+
return [...validItems, ...invalidItems];
|
|
45501
|
+
}
|
|
45502
|
+
|
|
45503
|
+
function determineLayout(items, requestedLayout) {
|
|
45504
|
+
// Single item always uses single layout
|
|
45505
|
+
if (items.length === 1) {
|
|
45506
|
+
return 'single';
|
|
45507
|
+
}
|
|
45508
|
+
// For multiple items, use gallery (which now supports overlay titles)
|
|
45509
|
+
// Cards and gallery are now visually the same - 2-column grid with overlay titles
|
|
45510
|
+
return 'gallery';
|
|
45511
|
+
}
|
|
45512
|
+
function determineColumns(itemCount, maxColumns = 2) {
|
|
45513
|
+
if (itemCount === 1)
|
|
45514
|
+
return 1;
|
|
45515
|
+
return Math.min(2, maxColumns);
|
|
45516
|
+
}
|
|
45517
|
+
function StructuredImageDisplay({ action, onComplete, accentColor, maxColumns = 3 }) {
|
|
45518
|
+
const rawState = action.input;
|
|
45519
|
+
const hasCompletedRef = reactExports.useRef(false);
|
|
45520
|
+
const [validatedItems, setValidatedItems] = reactExports.useState([]);
|
|
45521
|
+
const [isValidating, setIsValidating] = reactExports.useState(true);
|
|
45522
|
+
const [validationErrors, setValidationErrors] = reactExports.useState([]);
|
|
45523
|
+
// Provide safe defaults if state is missing
|
|
45524
|
+
const state = {
|
|
45525
|
+
items: rawState?.items || [],
|
|
45526
|
+
layout: rawState?.layout || 'single',
|
|
45527
|
+
context: rawState?.context,
|
|
45528
|
+
columns: rawState?.columns,
|
|
45529
|
+
status: rawState?.status || 'displaying',
|
|
45530
|
+
error: rawState?.error,
|
|
45531
|
+
};
|
|
45532
|
+
const isError = state.status === 'error';
|
|
45533
|
+
// Validate URLs before displaying
|
|
45534
|
+
reactExports.useEffect(() => {
|
|
45535
|
+
if (state.items.length === 0) {
|
|
45536
|
+
setIsValidating(false);
|
|
45537
|
+
return;
|
|
45538
|
+
}
|
|
45539
|
+
let isMounted = true;
|
|
45540
|
+
const validateItems = async () => {
|
|
45541
|
+
try {
|
|
45542
|
+
const validated = await preloadAndValidateImages(state.items, 3000);
|
|
45543
|
+
if (!isMounted)
|
|
45544
|
+
return;
|
|
45545
|
+
const valid = validated.filter(item => item.isValid !== false);
|
|
45546
|
+
const invalid = validated.filter(item => item.isValid === false);
|
|
45547
|
+
setValidatedItems(valid);
|
|
45548
|
+
if (invalid.length > 0) {
|
|
45549
|
+
const errors = invalid.map(item => `${item.url}: ${item.validationError || 'Failed to load'}`);
|
|
45550
|
+
setValidationErrors(errors);
|
|
45551
|
+
console.warn('[StructuredImageDisplay] Filtered invalid URLs:', errors);
|
|
45552
|
+
}
|
|
45457
45553
|
}
|
|
45458
|
-
|
|
45459
|
-
|
|
45460
|
-
|
|
45461
|
-
|
|
45462
|
-
|
|
45463
|
-
|
|
45464
|
-
|
|
45465
|
-
|
|
45466
|
-
|
|
45554
|
+
catch (error) {
|
|
45555
|
+
console.error('[StructuredImageDisplay] Validation error:', error);
|
|
45556
|
+
// Fallback to unvalidated items on error
|
|
45557
|
+
if (isMounted) {
|
|
45558
|
+
setValidatedItems(state.items);
|
|
45559
|
+
}
|
|
45560
|
+
}
|
|
45561
|
+
finally {
|
|
45562
|
+
if (isMounted) {
|
|
45563
|
+
setIsValidating(false);
|
|
45564
|
+
}
|
|
45565
|
+
}
|
|
45566
|
+
};
|
|
45567
|
+
validateItems();
|
|
45568
|
+
return () => {
|
|
45569
|
+
isMounted = false;
|
|
45570
|
+
};
|
|
45571
|
+
}, [state.items]);
|
|
45572
|
+
// Auto-complete on mount so AI can continue generating text response
|
|
45573
|
+
reactExports.useEffect(() => {
|
|
45574
|
+
if (!action.done && !hasCompletedRef.current && onComplete && state.items.length > 0) {
|
|
45575
|
+
hasCompletedRef.current = true;
|
|
45576
|
+
onComplete(action.toolCallId, { ...state, status: 'displaying' });
|
|
45577
|
+
}
|
|
45578
|
+
}, [action.done, action.toolCallId, onComplete, state]);
|
|
45579
|
+
const handleInteraction = () => {
|
|
45580
|
+
onComplete?.(action.toolCallId, { ...state, status: 'interacted' });
|
|
45581
|
+
};
|
|
45582
|
+
const handleLinkClick = (url) => {
|
|
45583
|
+
handleInteraction();
|
|
45584
|
+
};
|
|
45585
|
+
const style = accentColor ? { '--action-accent': accentColor } : undefined;
|
|
45586
|
+
// Error state
|
|
45587
|
+
if (isError) {
|
|
45588
|
+
return (jsxRuntimeExports.jsx("div", { className: "ai-chat-structured-image ai-chat-structured-image--error", style: style, children: jsxRuntimeExports.jsx("div", { className: "ai-chat-structured-image__error", children: state.error || 'Failed to load media' }) }));
|
|
45589
|
+
}
|
|
45590
|
+
// Loading state
|
|
45591
|
+
if (isValidating) {
|
|
45592
|
+
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-structured-image", style: style, children: [state.context && (jsxRuntimeExports.jsx("p", { className: "ai-chat-structured-image__context", children: state.context })), jsxRuntimeExports.jsx("div", { className: "ai-chat-structured-image__loading", children: "Validating images..." })] }));
|
|
45593
|
+
}
|
|
45594
|
+
// No valid items after validation
|
|
45595
|
+
if (validatedItems.length === 0) {
|
|
45596
|
+
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-structured-image", style: style, children: [state.context && (jsxRuntimeExports.jsx("p", { className: "ai-chat-structured-image__context", children: state.context })), validationErrors.length > 0 && (jsxRuntimeExports.jsx("div", { className: "ai-chat-structured-image__error", children: "All images failed to load. Please check the URLs." }))] }));
|
|
45597
|
+
}
|
|
45598
|
+
const layout = determineLayout(validatedItems, state.layout);
|
|
45599
|
+
const columns = state.columns || determineColumns(validatedItems.length, maxColumns);
|
|
45600
|
+
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-structured-image", style: style, children: [state.context && (jsxRuntimeExports.jsx("p", { className: "ai-chat-structured-image__context", children: state.context })), validationErrors.length > 0 && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-structured-image__warning", children: [validationErrors.length, " image(s) could not be loaded and were filtered."] })), layout === 'single' && validatedItems[0] && (jsxRuntimeExports.jsx(ImageCard, { item: validatedItems[0], accentColor: accentColor, onLinkClick: handleLinkClick })), layout === 'gallery' && (jsxRuntimeExports.jsx(ImageGallery, { items: validatedItems, columns: columns, accentColor: accentColor, maxColumns: maxColumns })), layout === 'cards' && (jsxRuntimeExports.jsx("div", { className: "ai-chat-structured-image__cards", style: { '--card-columns': validatedItems.length === 1 ? 1 : 2 }, children: validatedItems.map((item, index) => (jsxRuntimeExports.jsx(ProjectCard, { item: item, accentColor: accentColor, onLinkClick: handleLinkClick, variant: "overlay" }, index))) })), layout === 'carousel' && (jsxRuntimeExports.jsx(ImageCarousel, { items: validatedItems, accentColor: accentColor, onLinkClick: handleLinkClick }))] }));
|
|
45601
|
+
}
|
|
45602
|
+
function ChevronLeftIcon() {
|
|
45603
|
+
return (jsxRuntimeExports.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("polyline", { points: "15 18 9 12 15 6" }) }));
|
|
45604
|
+
}
|
|
45605
|
+
function ChevronRightIcon() {
|
|
45606
|
+
return (jsxRuntimeExports.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("polyline", { points: "9 18 15 12 9 6" }) }));
|
|
45607
|
+
}
|
|
45608
|
+
function ImageCarousel({ items, accentColor, onLinkClick }) {
|
|
45609
|
+
const [currentIndex, setCurrentIndex] = React.useState(0);
|
|
45610
|
+
const containerRef = reactExports.useRef(null);
|
|
45611
|
+
const goToPrevious = () => {
|
|
45612
|
+
setCurrentIndex(prev => prev === 0 ? items.length - 1 : prev - 1);
|
|
45467
45613
|
};
|
|
45614
|
+
const goToNext = () => {
|
|
45615
|
+
setCurrentIndex(prev => prev === items.length - 1 ? 0 : prev + 1);
|
|
45616
|
+
};
|
|
45617
|
+
const style = accentColor ? { '--action-accent': accentColor } : undefined;
|
|
45618
|
+
return (jsxRuntimeExports.jsxs("div", { className: "ai-chat-image-carousel", style: style, ref: containerRef, children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-image-carousel__track", style: { transform: `translateX(-${currentIndex * 100}%)` }, children: items.map((item, index) => (jsxRuntimeExports.jsx("div", { className: "ai-chat-image-carousel__slide", children: jsxRuntimeExports.jsx(ProjectCard, { item: item, accentColor: accentColor, onLinkClick: onLinkClick }) }, index))) }), items.length > 1 && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("button", { className: "ai-chat-image-carousel__nav prev", onClick: goToPrevious, "aria-label": "Previous", children: jsxRuntimeExports.jsx(ChevronLeftIcon, {}) }), jsxRuntimeExports.jsx("button", { className: "ai-chat-image-carousel__nav next", onClick: goToNext, "aria-label": "Next", children: jsxRuntimeExports.jsx(ChevronRightIcon, {}) }), jsxRuntimeExports.jsx("div", { className: "ai-chat-image-carousel__dots", children: items.map((_, index) => (jsxRuntimeExports.jsx("button", { className: `ai-chat-image-carousel__dot ${index === currentIndex ? 'active' : ''}`, onClick: () => setCurrentIndex(index), "aria-label": `Go to slide ${index + 1}` }, index))) })] }))] }));
|
|
45619
|
+
}
|
|
45620
|
+
|
|
45621
|
+
const pendingResolvers = new Map();
|
|
45622
|
+
const resumeCallbacks = new Map();
|
|
45623
|
+
const frontendActionHandlers = {};
|
|
45624
|
+
const actionRenderers = {};
|
|
45625
|
+
function getFrontendActionHandler(implementation) {
|
|
45626
|
+
return frontendActionHandlers[implementation];
|
|
45627
|
+
}
|
|
45628
|
+
function getActionRenderer(implementation) {
|
|
45629
|
+
return actionRenderers[implementation];
|
|
45630
|
+
}
|
|
45631
|
+
function waitForActionState(toolCallId) {
|
|
45632
|
+
return new Promise((resolve) => {
|
|
45633
|
+
pendingResolvers.set(toolCallId, resolve);
|
|
45634
|
+
});
|
|
45635
|
+
}
|
|
45636
|
+
function resolveActionState(toolCallId, state) {
|
|
45637
|
+
const resolver = pendingResolvers.get(toolCallId);
|
|
45638
|
+
if (resolver) {
|
|
45639
|
+
pendingResolvers.delete(toolCallId);
|
|
45640
|
+
resolver(state);
|
|
45641
|
+
return;
|
|
45642
|
+
}
|
|
45643
|
+
const resumeCallback = resumeCallbacks.get(toolCallId);
|
|
45644
|
+
if (resumeCallback) {
|
|
45645
|
+
resumeCallback(state).catch((error) => {
|
|
45646
|
+
console.error("[Action] Failed to resume action:", error);
|
|
45647
|
+
});
|
|
45648
|
+
}
|
|
45649
|
+
}
|
|
45650
|
+
function registerActionResumeCallback(toolCallId, callback) {
|
|
45651
|
+
resumeCallbacks.set(toolCallId, callback);
|
|
45652
|
+
}
|
|
45653
|
+
function unregisterActionResumeCallback(toolCallId) {
|
|
45654
|
+
resumeCallbacks.delete(toolCallId);
|
|
45468
45655
|
}
|
|
45469
45656
|
|
|
45470
45657
|
/**
|
|
@@ -45472,9 +45659,15 @@
|
|
|
45472
45659
|
* Called by initializeActionHandlers to prevent tree-shaking.
|
|
45473
45660
|
*/
|
|
45474
45661
|
function registerLinkPreviewAction() {
|
|
45475
|
-
// Handler - auto-completes immediately
|
|
45662
|
+
// Handler - auto-completes immediately, returns body for agent
|
|
45476
45663
|
frontendActionHandlers["link-preview"] = async (_input, state, _context) => {
|
|
45477
|
-
|
|
45664
|
+
const links = state?.links || [];
|
|
45665
|
+
// Return body directly - sent to backend via continueAgentAction
|
|
45666
|
+
return {
|
|
45667
|
+
status: "displayed",
|
|
45668
|
+
linkCount: links.length,
|
|
45669
|
+
message: `Displayed ${links.length} link preview${links.length > 1 ? 's' : ''}.`,
|
|
45670
|
+
};
|
|
45478
45671
|
};
|
|
45479
45672
|
// Renderer - displays the link preview card
|
|
45480
45673
|
actionRenderers["link-preview"] = (message, accentColor) => {
|
|
@@ -45484,16 +45677,15 @@
|
|
|
45484
45677
|
const handleComplete = (toolCallId, newState) => {
|
|
45485
45678
|
resolveActionState(toolCallId, newState);
|
|
45486
45679
|
};
|
|
45487
|
-
// Check if action
|
|
45488
|
-
const
|
|
45489
|
-
const status =
|
|
45490
|
-
const isDone = action.done || status === "displaying" || status === "clicked";
|
|
45680
|
+
// Check if action input indicates it's already complete (displaying or clicked)
|
|
45681
|
+
const input = action.input;
|
|
45682
|
+
const status = input?.status;
|
|
45683
|
+
const isDone = action.done || status === "displaying" || status === "displayed" || status === "clicked";
|
|
45491
45684
|
return (jsxRuntimeExports.jsx(LinkPreviewCard, { action: {
|
|
45492
45685
|
implementation: action.implementation,
|
|
45493
45686
|
toolCallId: action.toolCallId,
|
|
45494
45687
|
actionId: action.actionId,
|
|
45495
45688
|
input: action.input,
|
|
45496
|
-
state: action.state,
|
|
45497
45689
|
done: isDone,
|
|
45498
45690
|
}, onComplete: handleComplete, accentColor: accentColor }));
|
|
45499
45691
|
};
|
|
@@ -45504,9 +45696,15 @@
|
|
|
45504
45696
|
* Called by initializeActionHandlers to prevent tree-shaking.
|
|
45505
45697
|
*/
|
|
45506
45698
|
function registerVideoPlayerAction() {
|
|
45507
|
-
// Handler - auto-completes immediately
|
|
45699
|
+
// Handler - auto-completes immediately, returns body for agent
|
|
45508
45700
|
frontendActionHandlers["video-player"] = async (_input, state, _context) => {
|
|
45509
|
-
|
|
45701
|
+
const videos = state?.videos || [];
|
|
45702
|
+
// Return body directly - sent to backend via continueAgentAction
|
|
45703
|
+
return {
|
|
45704
|
+
status: "displayed",
|
|
45705
|
+
videoCount: videos.length,
|
|
45706
|
+
message: `Displayed ${videos.length} video${videos.length !== 1 ? 's' : ''}.`,
|
|
45707
|
+
};
|
|
45510
45708
|
};
|
|
45511
45709
|
// Renderer - displays the embedded video player card
|
|
45512
45710
|
actionRenderers["video-player"] = (message, accentColor) => {
|
|
@@ -45516,16 +45714,15 @@
|
|
|
45516
45714
|
const handleComplete = (toolCallId, newState) => {
|
|
45517
45715
|
resolveActionState(toolCallId, newState);
|
|
45518
45716
|
};
|
|
45519
|
-
// Check if action
|
|
45520
|
-
const
|
|
45521
|
-
const status =
|
|
45522
|
-
const isDone = action.done || status === "displaying" || status === "played";
|
|
45717
|
+
// Check if action input indicates it's already complete (displaying or played)
|
|
45718
|
+
const input = action.input;
|
|
45719
|
+
const status = input?.status;
|
|
45720
|
+
const isDone = action.done || status === "displaying" || status === "displayed" || status === "played";
|
|
45523
45721
|
return (jsxRuntimeExports.jsx(VideoPlayerCard, { action: {
|
|
45524
45722
|
implementation: action.implementation,
|
|
45525
45723
|
toolCallId: action.toolCallId,
|
|
45526
45724
|
actionId: action.actionId,
|
|
45527
45725
|
input: action.input,
|
|
45528
|
-
state: action.state,
|
|
45529
45726
|
done: isDone,
|
|
45530
45727
|
}, onComplete: handleComplete, accentColor: accentColor }));
|
|
45531
45728
|
};
|
|
@@ -45536,9 +45733,15 @@
|
|
|
45536
45733
|
* Called by initializeActionHandlers to prevent tree-shaking.
|
|
45537
45734
|
*/
|
|
45538
45735
|
function registerLocationCardAction() {
|
|
45539
|
-
// Handler - auto-completes immediately
|
|
45736
|
+
// Handler - auto-completes immediately, returns body for agent
|
|
45540
45737
|
frontendActionHandlers["location-card"] = async (_input, state, _context) => {
|
|
45541
|
-
|
|
45738
|
+
const locations = state?.locations || [];
|
|
45739
|
+
// Return body directly - sent to backend via continueAgentAction
|
|
45740
|
+
return {
|
|
45741
|
+
status: "displayed",
|
|
45742
|
+
locationCount: locations.length,
|
|
45743
|
+
message: `Displayed ${locations.length} location${locations.length !== 1 ? 's' : ''}.`,
|
|
45744
|
+
};
|
|
45542
45745
|
};
|
|
45543
45746
|
// Renderer - displays the location card
|
|
45544
45747
|
actionRenderers["location-card"] = (message, accentColor, variant) => {
|
|
@@ -45548,25 +45751,30 @@
|
|
|
45548
45751
|
const handleComplete = (toolCallId, newState) => {
|
|
45549
45752
|
resolveActionState(toolCallId, newState);
|
|
45550
45753
|
};
|
|
45551
|
-
// Check if action
|
|
45552
|
-
const
|
|
45553
|
-
const status =
|
|
45554
|
-
const isDone = action.done || status === "displaying" || status === "directions_opened";
|
|
45754
|
+
// Check if action input indicates it's already complete
|
|
45755
|
+
const input = action.input;
|
|
45756
|
+
const status = input?.status;
|
|
45757
|
+
const isDone = action.done || status === "displaying" || status === "displayed" || status === "directions_opened";
|
|
45555
45758
|
return (jsxRuntimeExports.jsx(LocationCard, { action: {
|
|
45556
45759
|
implementation: action.implementation,
|
|
45557
45760
|
toolCallId: action.toolCallId,
|
|
45558
45761
|
actionId: action.actionId,
|
|
45559
45762
|
input: action.input,
|
|
45560
|
-
state: action.state,
|
|
45561
45763
|
done: isDone,
|
|
45562
45764
|
}, onComplete: handleComplete, accentColor: accentColor, maxColumns: variant === 'fullpage' ? 3 : 1 }));
|
|
45563
45765
|
};
|
|
45564
45766
|
}
|
|
45565
45767
|
|
|
45566
45768
|
function registerContactCardAction() {
|
|
45567
|
-
// Handler - auto-completes immediately
|
|
45769
|
+
// Handler - auto-completes immediately, returns body for agent
|
|
45568
45770
|
frontendActionHandlers['contact-card'] = async (_input, state, _context) => {
|
|
45569
|
-
|
|
45771
|
+
const contacts = state?.contacts || [];
|
|
45772
|
+
// Return body directly - sent to backend via continueAgentAction
|
|
45773
|
+
return {
|
|
45774
|
+
status: 'displayed',
|
|
45775
|
+
contactCount: contacts.length,
|
|
45776
|
+
message: `Displayed ${contacts.length} contact${contacts.length !== 1 ? 's' : ''}.`,
|
|
45777
|
+
};
|
|
45570
45778
|
};
|
|
45571
45779
|
// Renderer - displays the contact card
|
|
45572
45780
|
actionRenderers['contact-card'] = (message, accentColor, variant) => {
|
|
@@ -45576,16 +45784,15 @@
|
|
|
45576
45784
|
const handleComplete = (toolCallId, newState) => {
|
|
45577
45785
|
resolveActionState(toolCallId, newState);
|
|
45578
45786
|
};
|
|
45579
|
-
// Check if action
|
|
45580
|
-
const
|
|
45581
|
-
const status =
|
|
45582
|
-
const isDone = action.done || status === 'displaying' || status === 'contacted';
|
|
45787
|
+
// Check if action input indicates it's already complete
|
|
45788
|
+
const input = action.input;
|
|
45789
|
+
const status = input?.status;
|
|
45790
|
+
const isDone = action.done || status === 'displaying' || status === 'displayed' || status === 'contacted';
|
|
45583
45791
|
return (jsxRuntimeExports.jsx(ContactCard, { action: {
|
|
45584
45792
|
implementation: action.implementation,
|
|
45585
45793
|
toolCallId: action.toolCallId,
|
|
45586
45794
|
actionId: action.actionId,
|
|
45587
45795
|
input: action.input,
|
|
45588
|
-
state: action.state,
|
|
45589
45796
|
done: isDone,
|
|
45590
45797
|
}, onComplete: handleComplete, accentColor: accentColor, maxColumns: variant === 'fullpage' ? 3 : 1 }));
|
|
45591
45798
|
};
|
|
@@ -45605,16 +45812,15 @@
|
|
|
45605
45812
|
const handleComplete = (toolCallId, newState) => {
|
|
45606
45813
|
resolveActionState(toolCallId, newState);
|
|
45607
45814
|
};
|
|
45608
|
-
// Check if action
|
|
45609
|
-
const
|
|
45610
|
-
const status =
|
|
45815
|
+
// Check if action input indicates it's already complete
|
|
45816
|
+
const input = action.input;
|
|
45817
|
+
const status = input?.status;
|
|
45611
45818
|
const isDone = action.done || status === 'displaying' || status === 'contacted';
|
|
45612
45819
|
return (jsxRuntimeExports.jsx(ContactCard, { action: {
|
|
45613
45820
|
implementation: action.implementation,
|
|
45614
45821
|
toolCallId: action.toolCallId,
|
|
45615
45822
|
actionId: action.actionId,
|
|
45616
45823
|
input: action.input,
|
|
45617
|
-
state: action.state,
|
|
45618
45824
|
done: isDone,
|
|
45619
45825
|
}, onComplete: handleComplete, accentColor: accentColor, maxColumns: variant === 'fullpage' ? 3 : 1 }));
|
|
45620
45826
|
};
|
|
@@ -45626,7 +45832,9 @@
|
|
|
45626
45832
|
return waitForActionState(context.toolCallId);
|
|
45627
45833
|
};
|
|
45628
45834
|
// Renderer - displays the form card
|
|
45629
|
-
|
|
45835
|
+
// Rendering is based only on action.input and action.done
|
|
45836
|
+
// When done=true, FormCard shows a simple completion indicator
|
|
45837
|
+
actionRenderers['display-form'] = (message, accentColor, _variant, onActionDismiss) => {
|
|
45630
45838
|
const action = message.action;
|
|
45631
45839
|
if (!action)
|
|
45632
45840
|
return null;
|
|
@@ -45634,22 +45842,14 @@
|
|
|
45634
45842
|
resolveActionState(toolCallId, newState);
|
|
45635
45843
|
};
|
|
45636
45844
|
const handleDismiss = onActionDismiss
|
|
45637
|
-
? (toolCallId) =>
|
|
45638
|
-
resolveActionState(toolCallId, { __dismissed: true });
|
|
45639
|
-
onActionDismiss(toolCallId);
|
|
45640
|
-
}
|
|
45845
|
+
? (toolCallId) => onActionDismiss(toolCallId)
|
|
45641
45846
|
: undefined;
|
|
45642
|
-
// Check if action state indicates it's already complete
|
|
45643
|
-
const state = action.state;
|
|
45644
|
-
const status = state?.status;
|
|
45645
|
-
const isDone = action.done || status === 'completed' || status === 'submitted';
|
|
45646
45847
|
return (jsxRuntimeExports.jsx(FormCard, { action: {
|
|
45647
45848
|
implementation: action.implementation,
|
|
45648
45849
|
toolCallId: action.toolCallId,
|
|
45649
45850
|
actionId: action.actionId,
|
|
45650
45851
|
input: action.input,
|
|
45651
|
-
|
|
45652
|
-
done: isDone,
|
|
45852
|
+
done: action.done ?? false,
|
|
45653
45853
|
}, onComplete: handleComplete, onDismiss: handleDismiss, accentColor: accentColor }));
|
|
45654
45854
|
};
|
|
45655
45855
|
}
|
|
@@ -45672,21 +45872,64 @@
|
|
|
45672
45872
|
// Register the handler
|
|
45673
45873
|
registerBookContactAppointmentHandler();
|
|
45674
45874
|
// Register the renderer
|
|
45675
|
-
actionRenderers['book-contact-appointment'] = (message, accentColor) => {
|
|
45875
|
+
actionRenderers['book-contact-appointment'] = (message, accentColor, _variant, _onActionDismiss, onCallEndpoint) => {
|
|
45676
45876
|
const action = message.action;
|
|
45677
45877
|
if (!action)
|
|
45678
45878
|
return null;
|
|
45679
45879
|
const handleComplete = (toolCallId, newState) => {
|
|
45680
45880
|
resolveActionState(toolCallId, newState);
|
|
45681
45881
|
};
|
|
45882
|
+
// Create action-specific endpoint callback
|
|
45883
|
+
// Include toolCallId for done flag enforcement (server rejects calls for completed actions)
|
|
45884
|
+
const handleCallEndpoint = onCallEndpoint
|
|
45885
|
+
? async (endpoint, input, options) => {
|
|
45886
|
+
return onCallEndpoint(action.actionId, endpoint, input, { ...options, toolCallId: action.toolCallId });
|
|
45887
|
+
}
|
|
45888
|
+
: undefined;
|
|
45889
|
+
// Create dismiss handler
|
|
45890
|
+
const handleDismiss = _onActionDismiss
|
|
45891
|
+
? (toolCallId) => _onActionDismiss(toolCallId)
|
|
45892
|
+
: undefined;
|
|
45682
45893
|
return (jsxRuntimeExports.jsx(BookContactAppointmentCard, { action: {
|
|
45683
45894
|
implementation: action.implementation,
|
|
45684
45895
|
toolCallId: action.toolCallId,
|
|
45685
45896
|
actionId: action.actionId,
|
|
45686
45897
|
input: action.input,
|
|
45687
|
-
state: action.state,
|
|
45688
45898
|
done: action.done ?? false,
|
|
45689
|
-
}, onComplete: handleComplete, accentColor: accentColor }));
|
|
45899
|
+
}, onComplete: handleComplete, onDismiss: handleDismiss, onCallEndpoint: handleCallEndpoint, accentColor: accentColor }));
|
|
45900
|
+
};
|
|
45901
|
+
}
|
|
45902
|
+
|
|
45903
|
+
function registerStructuredImageAction() {
|
|
45904
|
+
// Handler - auto-completes immediately, returns body for agent
|
|
45905
|
+
frontendActionHandlers['structured-image'] = async (_input, state, _context) => {
|
|
45906
|
+
const images = state?.images || [];
|
|
45907
|
+
// Return body directly - sent to backend via continueAgentAction
|
|
45908
|
+
return {
|
|
45909
|
+
status: 'displayed',
|
|
45910
|
+
imageCount: images.length,
|
|
45911
|
+
message: `Displayed ${images.length} image${images.length !== 1 ? 's' : ''}.`,
|
|
45912
|
+
};
|
|
45913
|
+
};
|
|
45914
|
+
// Renderer - displays the image content
|
|
45915
|
+
actionRenderers['structured-image'] = (message, accentColor, variant, onActionDismiss) => {
|
|
45916
|
+
const action = message.action;
|
|
45917
|
+
if (!action)
|
|
45918
|
+
return null;
|
|
45919
|
+
const handleComplete = (toolCallId, newState) => {
|
|
45920
|
+
resolveActionState(toolCallId, newState);
|
|
45921
|
+
};
|
|
45922
|
+
// Check if action input indicates it's already complete
|
|
45923
|
+
const input = action.input;
|
|
45924
|
+
const status = input?.status;
|
|
45925
|
+
const isDone = action.done || status === 'displaying' || status === 'displayed' || status === 'interacted';
|
|
45926
|
+
return (jsxRuntimeExports.jsx(StructuredImageDisplay, { action: {
|
|
45927
|
+
implementation: action.implementation,
|
|
45928
|
+
toolCallId: action.toolCallId,
|
|
45929
|
+
actionId: action.actionId,
|
|
45930
|
+
input: action.input,
|
|
45931
|
+
done: isDone,
|
|
45932
|
+
}, onComplete: handleComplete, onDismiss: onActionDismiss ? () => onActionDismiss(action.toolCallId) : undefined, accentColor: accentColor, maxColumns: variant === 'fullpage' ? 3 : 2 }));
|
|
45690
45933
|
};
|
|
45691
45934
|
}
|
|
45692
45935
|
|
|
@@ -45702,8 +45945,6 @@
|
|
|
45702
45945
|
return;
|
|
45703
45946
|
initialized = true;
|
|
45704
45947
|
// Explicitly call each registration function to prevent tree-shaking
|
|
45705
|
-
registerGoogleCalendarAction();
|
|
45706
|
-
registerMicrosoftCalendarAction();
|
|
45707
45948
|
registerLinkPreviewAction();
|
|
45708
45949
|
registerVideoPlayerAction();
|
|
45709
45950
|
registerLocationCardAction();
|
|
@@ -45711,6 +45952,7 @@
|
|
|
45711
45952
|
registerContactCardAction();
|
|
45712
45953
|
registerDisplayFormAction();
|
|
45713
45954
|
registerBookContactAppointmentAction();
|
|
45955
|
+
registerStructuredImageAction();
|
|
45714
45956
|
}
|
|
45715
45957
|
|
|
45716
45958
|
/**
|
|
@@ -45973,9 +46215,49 @@
|
|
|
45973
46215
|
};
|
|
45974
46216
|
});
|
|
45975
46217
|
}
|
|
46218
|
+
/**
|
|
46219
|
+
* Clean up messages that were interrupted during streaming.
|
|
46220
|
+
* - Marks streaming messages as complete
|
|
46221
|
+
* - Removes empty assistant messages
|
|
46222
|
+
* - Marks incomplete tool calls as done
|
|
46223
|
+
*/
|
|
46224
|
+
function cleanupInterruptedMessages(messages) {
|
|
46225
|
+
return messages
|
|
46226
|
+
.map((msg) => {
|
|
46227
|
+
// Mark streaming messages as complete
|
|
46228
|
+
if (msg.isStreaming) {
|
|
46229
|
+
msg = { ...msg, isStreaming: false };
|
|
46230
|
+
}
|
|
46231
|
+
// Mark incomplete tool calls as done (they were interrupted)
|
|
46232
|
+
if (msg.message.role === 'tool' && msg.action && !msg.action.done) {
|
|
46233
|
+
msg = {
|
|
46234
|
+
...msg,
|
|
46235
|
+
action: {
|
|
46236
|
+
...msg.action,
|
|
46237
|
+
done: true,
|
|
46238
|
+
// Mark as interrupted so UI can show appropriate state
|
|
46239
|
+
input: {
|
|
46240
|
+
...msg.action.input,
|
|
46241
|
+
_interrupted: true,
|
|
46242
|
+
},
|
|
46243
|
+
},
|
|
46244
|
+
};
|
|
46245
|
+
}
|
|
46246
|
+
return msg;
|
|
46247
|
+
})
|
|
46248
|
+
// Remove empty assistant messages (streaming was interrupted before content)
|
|
46249
|
+
.filter((msg) => {
|
|
46250
|
+
if (msg.message.role === 'assistant') {
|
|
46251
|
+
const content = msg.message.content;
|
|
46252
|
+
return content && typeof content === 'string' && content.trim().length > 0;
|
|
46253
|
+
}
|
|
46254
|
+
return true;
|
|
46255
|
+
});
|
|
46256
|
+
}
|
|
45976
46257
|
function hydrateMessages(messages) {
|
|
45977
46258
|
const visibleMessages = messages.filter((message) => !message.action?.hidden);
|
|
45978
|
-
|
|
46259
|
+
const cleanedMessages = cleanupInterruptedMessages(visibleMessages);
|
|
46260
|
+
return hydrateToolNames(cleanedMessages);
|
|
45979
46261
|
}
|
|
45980
46262
|
|
|
45981
46263
|
function deriveErrorInfo(error) {
|
|
@@ -46045,6 +46327,75 @@
|
|
|
46045
46327
|
return { message: 'Something went wrong. Please try again.' };
|
|
46046
46328
|
}
|
|
46047
46329
|
|
|
46330
|
+
/**
|
|
46331
|
+
* Stream Buffer
|
|
46332
|
+
* Smooths out streaming text rendering by buffering words and draining them
|
|
46333
|
+
* with requestAnimationFrame for a fluid typing effect.
|
|
46334
|
+
*/
|
|
46335
|
+
function createStreamBuffer() {
|
|
46336
|
+
return {
|
|
46337
|
+
pendingWords: [],
|
|
46338
|
+
displayedContent: '',
|
|
46339
|
+
streamEnded: false,
|
|
46340
|
+
rafHandle: null,
|
|
46341
|
+
};
|
|
46342
|
+
}
|
|
46343
|
+
function appendToBuffer(buffer, content) {
|
|
46344
|
+
// Split by whitespace while preserving the whitespace characters
|
|
46345
|
+
const words = content.split(/(\s+)/);
|
|
46346
|
+
buffer.pendingWords.push(...words.filter(w => w.length > 0));
|
|
46347
|
+
}
|
|
46348
|
+
function startBufferDrain(buffer, onContentUpdate) {
|
|
46349
|
+
if (buffer.rafHandle !== null) {
|
|
46350
|
+
return; // Already draining
|
|
46351
|
+
}
|
|
46352
|
+
const drainLoop = () => {
|
|
46353
|
+
if (buffer.pendingWords.length === 0) {
|
|
46354
|
+
if (buffer.streamEnded) {
|
|
46355
|
+
buffer.rafHandle = null;
|
|
46356
|
+
return;
|
|
46357
|
+
}
|
|
46358
|
+
// No words to render, wait for more
|
|
46359
|
+
buffer.rafHandle = requestAnimationFrame(drainLoop);
|
|
46360
|
+
return;
|
|
46361
|
+
}
|
|
46362
|
+
// Adaptive: render more words if buffer is filling up
|
|
46363
|
+
const wordsToRender = buffer.pendingWords.length > 20 ? 3 : 1;
|
|
46364
|
+
const chunk = buffer.pendingWords.splice(0, wordsToRender).join('');
|
|
46365
|
+
buffer.displayedContent += chunk;
|
|
46366
|
+
onContentUpdate(buffer.displayedContent);
|
|
46367
|
+
buffer.rafHandle = requestAnimationFrame(drainLoop);
|
|
46368
|
+
};
|
|
46369
|
+
buffer.rafHandle = requestAnimationFrame(drainLoop);
|
|
46370
|
+
}
|
|
46371
|
+
function flushBuffer(buffer) {
|
|
46372
|
+
buffer.streamEnded = true;
|
|
46373
|
+
if (buffer.rafHandle !== null) {
|
|
46374
|
+
cancelAnimationFrame(buffer.rafHandle);
|
|
46375
|
+
buffer.rafHandle = null;
|
|
46376
|
+
}
|
|
46377
|
+
const remaining = buffer.pendingWords.join('');
|
|
46378
|
+
buffer.displayedContent += remaining;
|
|
46379
|
+
buffer.pendingWords = [];
|
|
46380
|
+
return buffer.displayedContent;
|
|
46381
|
+
}
|
|
46382
|
+
function cancelBuffer(buffer) {
|
|
46383
|
+
if (buffer.rafHandle !== null) {
|
|
46384
|
+
cancelAnimationFrame(buffer.rafHandle);
|
|
46385
|
+
buffer.rafHandle = null;
|
|
46386
|
+
}
|
|
46387
|
+
buffer.streamEnded = true;
|
|
46388
|
+
}
|
|
46389
|
+
function resetBuffer(buffer) {
|
|
46390
|
+
if (buffer.rafHandle !== null) {
|
|
46391
|
+
cancelAnimationFrame(buffer.rafHandle);
|
|
46392
|
+
buffer.rafHandle = null;
|
|
46393
|
+
}
|
|
46394
|
+
buffer.pendingWords = [];
|
|
46395
|
+
buffer.displayedContent = '';
|
|
46396
|
+
buffer.streamEnded = false;
|
|
46397
|
+
}
|
|
46398
|
+
|
|
46048
46399
|
function createStreamState() {
|
|
46049
46400
|
return {
|
|
46050
46401
|
currentContent: "",
|
|
@@ -46054,6 +46405,7 @@
|
|
|
46054
46405
|
sources: [],
|
|
46055
46406
|
toolCallToActionId: {},
|
|
46056
46407
|
requestId: generateMessageId(),
|
|
46408
|
+
buffer: createStreamBuffer(),
|
|
46057
46409
|
};
|
|
46058
46410
|
}
|
|
46059
46411
|
function upsertMessage(setState, message, isTyping) {
|
|
@@ -46116,6 +46468,8 @@
|
|
|
46116
46468
|
},
|
|
46117
46469
|
isStreaming: false,
|
|
46118
46470
|
toolExecuting: existingName,
|
|
46471
|
+
// Mark action as done when tool message is finalized
|
|
46472
|
+
action: entry.action ? { ...entry.action, done: true } : undefined,
|
|
46119
46473
|
};
|
|
46120
46474
|
});
|
|
46121
46475
|
return { ...prev, messages, isTyping: false, isLoading: false };
|
|
@@ -46124,26 +46478,34 @@
|
|
|
46124
46478
|
}
|
|
46125
46479
|
|
|
46126
46480
|
function handleContentEvent(event, streamState, onMessageUpdate, setState) {
|
|
46481
|
+
// Track full content for finalization
|
|
46127
46482
|
streamState.currentContent += event.content;
|
|
46128
|
-
|
|
46129
|
-
|
|
46130
|
-
|
|
46131
|
-
|
|
46132
|
-
|
|
46133
|
-
|
|
46134
|
-
|
|
46135
|
-
|
|
46136
|
-
|
|
46137
|
-
|
|
46138
|
-
|
|
46139
|
-
|
|
46140
|
-
|
|
46483
|
+
// Add to buffer for smooth rendering
|
|
46484
|
+
appendToBuffer(streamState.buffer, event.content);
|
|
46485
|
+
// Start drain loop if not already running
|
|
46486
|
+
startBufferDrain(streamState.buffer, (displayedContent) => {
|
|
46487
|
+
const assistantMessage = {
|
|
46488
|
+
id: streamState.currentMessageId,
|
|
46489
|
+
message: { role: "assistant", content: displayedContent },
|
|
46490
|
+
timestamp: new Date().toISOString(),
|
|
46491
|
+
sources: streamState.sources,
|
|
46492
|
+
isStreaming: true,
|
|
46493
|
+
};
|
|
46494
|
+
streamState.newMessageIds.add(assistantMessage.id);
|
|
46495
|
+
onMessageUpdate(assistantMessage);
|
|
46496
|
+
const hasContent = displayedContent.trim().length > 0;
|
|
46497
|
+
const isToolExecuting = streamState.activeToolCallCount > 0;
|
|
46498
|
+
const isTyping = (!hasContent && assistantMessage.isStreaming) || isToolExecuting;
|
|
46499
|
+
upsertMessage(setState, assistantMessage, isTyping);
|
|
46500
|
+
});
|
|
46141
46501
|
}
|
|
46142
46502
|
function handleToolStartEvent(event, streamState, onMessageUpdate, setState) {
|
|
46143
|
-
|
|
46503
|
+
// Flush buffer before tool starts
|
|
46504
|
+
const flushedContent = flushBuffer(streamState.buffer);
|
|
46505
|
+
if (flushedContent.trim()) {
|
|
46144
46506
|
const finalAssistant = {
|
|
46145
46507
|
id: streamState.currentMessageId,
|
|
46146
|
-
message: { role: "assistant", content:
|
|
46508
|
+
message: { role: "assistant", content: flushedContent },
|
|
46147
46509
|
timestamp: new Date().toISOString(),
|
|
46148
46510
|
sources: streamState.sources,
|
|
46149
46511
|
isStreaming: false,
|
|
@@ -46154,6 +46516,8 @@
|
|
|
46154
46516
|
streamState.currentContent = "";
|
|
46155
46517
|
streamState.currentMessageId = generateMessageId();
|
|
46156
46518
|
}
|
|
46519
|
+
// Reset buffer for post-tool content
|
|
46520
|
+
resetBuffer(streamState.buffer);
|
|
46157
46521
|
const toolMessageId = event.tool_call_id;
|
|
46158
46522
|
streamState.activeToolCallCount += 1;
|
|
46159
46523
|
streamState.newMessageIds.add(toolMessageId);
|
|
@@ -46171,44 +46535,22 @@
|
|
|
46171
46535
|
streamState.activeToolCallCount = Math.max(0, streamState.activeToolCallCount - 1);
|
|
46172
46536
|
setState(prev => {
|
|
46173
46537
|
const messages = prev.messages.map((msg) => {
|
|
46174
|
-
|
|
46175
|
-
if (!matchesToolCall) {
|
|
46538
|
+
if (msg.message.role !== "tool" || msg.message.tool_call_id !== event.tool_call_id) {
|
|
46176
46539
|
return msg;
|
|
46177
46540
|
}
|
|
46178
|
-
const
|
|
46179
|
-
|
|
46180
|
-
|
|
46181
|
-
|
|
46182
|
-
|
|
46183
|
-
|
|
46184
|
-
|
|
46185
|
-
actionId: event.action_id,
|
|
46186
|
-
input: (event.input || {}),
|
|
46187
|
-
state: (event.state || {}),
|
|
46188
|
-
done: event.done,
|
|
46189
|
-
};
|
|
46190
|
-
}
|
|
46191
|
-
else if (action) {
|
|
46192
|
-
action = {
|
|
46193
|
-
...action,
|
|
46194
|
-
input: event.input ? event.input : action.input,
|
|
46195
|
-
state: event.state ? event.state : action.state,
|
|
46196
|
-
done: event.done,
|
|
46197
|
-
};
|
|
46198
|
-
}
|
|
46199
|
-
const updatedMsg = {
|
|
46541
|
+
const toolName = msg.message.name || event.tool_name;
|
|
46542
|
+
// For actions: just mark as done, preserve existing input (display data is immutable)
|
|
46543
|
+
// For non-action tools: update normally
|
|
46544
|
+
const action = msg.action
|
|
46545
|
+
? { ...msg.action, done: event.done }
|
|
46546
|
+
: undefined;
|
|
46547
|
+
return {
|
|
46200
46548
|
...msg,
|
|
46201
|
-
message: {
|
|
46202
|
-
role: "tool",
|
|
46203
|
-
content: event.state ? JSON.stringify(event.state) : (typeof msg.message.content === "string" ? msg.message.content : ""),
|
|
46204
|
-
tool_call_id: event.tool_call_id,
|
|
46205
|
-
name: existingName,
|
|
46206
|
-
},
|
|
46549
|
+
message: { ...msg.message, name: toolName },
|
|
46207
46550
|
isStreaming: false,
|
|
46208
|
-
toolExecuting:
|
|
46551
|
+
toolExecuting: toolName,
|
|
46209
46552
|
action,
|
|
46210
46553
|
};
|
|
46211
|
-
return updatedMsg;
|
|
46212
46554
|
});
|
|
46213
46555
|
return { ...prev, messages, isTyping: true, isLoading: false };
|
|
46214
46556
|
});
|
|
@@ -46241,11 +46583,6 @@
|
|
|
46241
46583
|
return { ...prev, messages, isTyping: true, isLoading: false };
|
|
46242
46584
|
});
|
|
46243
46585
|
}
|
|
46244
|
-
function handleDoneEvent(event, streamState, _onMessageUpdate, setState) {
|
|
46245
|
-
streamState.sources = event.sources;
|
|
46246
|
-
streamState.toolCallToActionId = event.tool_call_to_action_id;
|
|
46247
|
-
finalizeStreamMessages(setState, streamState.newMessageIds, event.sources, event.tool_call_to_action_id, event.suggestions);
|
|
46248
|
-
}
|
|
46249
46586
|
function handleHaltEvent(event, _streamState, onMessageUpdate, setState) {
|
|
46250
46587
|
const toolNames = event.tool_calls.map(call => call.name).join(", ");
|
|
46251
46588
|
const notice = toolNames
|
|
@@ -46260,7 +46597,8 @@
|
|
|
46260
46597
|
};
|
|
46261
46598
|
onMessageUpdate(haltMessage);
|
|
46262
46599
|
upsertMessage(setState, haltMessage, false);
|
|
46263
|
-
|
|
46600
|
+
// Stop loading/typing state when halted
|
|
46601
|
+
setState(prev => ({ ...prev, isLoading: false, isTyping: false, error: "Awaiting external tool handling." }));
|
|
46264
46602
|
}
|
|
46265
46603
|
function handleErrorEvent(_event, _streamState, onMessageUpdate, setState) {
|
|
46266
46604
|
const errorMessage = {
|
|
@@ -46272,6 +46610,8 @@
|
|
|
46272
46610
|
};
|
|
46273
46611
|
onMessageUpdate(errorMessage);
|
|
46274
46612
|
upsertMessage(setState, errorMessage, false);
|
|
46613
|
+
// Stop loading/typing state on error
|
|
46614
|
+
setState(prev => ({ ...prev, isLoading: false, isTyping: false }));
|
|
46275
46615
|
}
|
|
46276
46616
|
const eventHandlers = {
|
|
46277
46617
|
content: handleContentEvent,
|
|
@@ -46299,10 +46639,37 @@
|
|
|
46299
46639
|
console.warn('[Chat] Unknown event type:', event.type);
|
|
46300
46640
|
}
|
|
46301
46641
|
}
|
|
46302
|
-
|
|
46303
|
-
|
|
46304
|
-
|
|
46642
|
+
function handleDoneEvent(event, streamState, onMessageUpdate, setState) {
|
|
46643
|
+
// Flush any remaining buffered content
|
|
46644
|
+
const flushedContent = flushBuffer(streamState.buffer);
|
|
46645
|
+
// Update the final message with complete content if there was content
|
|
46646
|
+
if (flushedContent.trim()) {
|
|
46647
|
+
const finalMessage = {
|
|
46648
|
+
id: streamState.currentMessageId,
|
|
46649
|
+
message: { role: "assistant", content: flushedContent },
|
|
46650
|
+
timestamp: new Date().toISOString(),
|
|
46651
|
+
sources: event.sources,
|
|
46652
|
+
isStreaming: false,
|
|
46653
|
+
};
|
|
46654
|
+
streamState.newMessageIds.add(finalMessage.id);
|
|
46655
|
+
onMessageUpdate(finalMessage);
|
|
46656
|
+
upsertMessage(setState, finalMessage, false);
|
|
46657
|
+
}
|
|
46658
|
+
streamState.sources = event.sources;
|
|
46659
|
+
streamState.toolCallToActionId = event.tool_call_to_action_id;
|
|
46660
|
+
finalizeStreamMessages(setState, streamState.newMessageIds, event.sources, event.tool_call_to_action_id, event.suggestions);
|
|
46305
46661
|
}
|
|
46662
|
+
|
|
46663
|
+
/**
|
|
46664
|
+
* Handle the action loop for halting actions.
|
|
46665
|
+
*
|
|
46666
|
+
* Flow:
|
|
46667
|
+
* 1. Display the action in UI
|
|
46668
|
+
* 2. Call the frontend handler (which waits for user interaction or returns immediately for display actions)
|
|
46669
|
+
* 3. Handler returns body when complete
|
|
46670
|
+
* 4. Send body to backend via continueAgentAction
|
|
46671
|
+
* 5. Process any subsequent events (may include new action_request for chained actions)
|
|
46672
|
+
*/
|
|
46306
46673
|
async function handleActionLoop(client, initialEvent, streamState, onMessageUpdate, setState, widgetId, conversationId, getMessages) {
|
|
46307
46674
|
let pendingEvent = initialEvent;
|
|
46308
46675
|
while (pendingEvent) {
|
|
@@ -46328,7 +46695,6 @@
|
|
|
46328
46695
|
toolCallId: pendingEvent.tool_call_id,
|
|
46329
46696
|
actionId: pendingEvent.action_id,
|
|
46330
46697
|
input: pendingEvent.input,
|
|
46331
|
-
state: pendingEvent.state,
|
|
46332
46698
|
done: pendingEvent.done ?? false,
|
|
46333
46699
|
},
|
|
46334
46700
|
};
|
|
@@ -46353,9 +46719,13 @@
|
|
|
46353
46719
|
upsertMessage(setState, errorMessage, false);
|
|
46354
46720
|
return;
|
|
46355
46721
|
}
|
|
46356
|
-
|
|
46722
|
+
// Handler returns body when complete (for display actions this is immediate,
|
|
46723
|
+
// for interactive actions this waits for user completion)
|
|
46724
|
+
// Note: For halting actions, input contains the transformed data from getInitialClientState
|
|
46725
|
+
let body;
|
|
46357
46726
|
try {
|
|
46358
|
-
|
|
46727
|
+
body = await handler(pendingEvent.input, pendingEvent.input, // Input now contains the display data for halting actions
|
|
46728
|
+
{
|
|
46359
46729
|
widgetId,
|
|
46360
46730
|
conversationId,
|
|
46361
46731
|
toolCallId: pendingEvent.tool_call_id,
|
|
@@ -46377,25 +46747,16 @@
|
|
|
46377
46747
|
return;
|
|
46378
46748
|
}
|
|
46379
46749
|
pendingEvent = null;
|
|
46380
|
-
|
|
46381
|
-
|
|
46382
|
-
const updatedToolMessage = {
|
|
46383
|
-
...toolMessage,
|
|
46384
|
-
action: toolMessage.action ? { ...toolMessage.action, state: nextState } : toolMessage.action,
|
|
46385
|
-
};
|
|
46386
|
-
upsertMessage(setState, updatedToolMessage, true);
|
|
46387
|
-
}
|
|
46388
|
-
if (dismissed) {
|
|
46389
|
-
return;
|
|
46390
|
-
}
|
|
46750
|
+
// Send body to backend and continue agent
|
|
46751
|
+
// No need to update message - input is immutable and already contains display data
|
|
46391
46752
|
let streamEnded = false;
|
|
46392
|
-
for await (const event of client.
|
|
46753
|
+
for await (const event of client.continueAgentAction(conversationId, resumeToolCallId, body)) {
|
|
46393
46754
|
if (event.type === "action_request") {
|
|
46755
|
+
// Chained action - continue the loop
|
|
46394
46756
|
pendingEvent = event;
|
|
46395
46757
|
break;
|
|
46396
46758
|
}
|
|
46397
46759
|
if (event.type === "done") {
|
|
46398
|
-
// Finalize tool message and stream messages
|
|
46399
46760
|
finalizeToolMessage(streamState, setState, resumeToolCallId, toolName);
|
|
46400
46761
|
streamState.sources = event.sources;
|
|
46401
46762
|
streamState.toolCallToActionId = event.tool_call_to_action_id;
|
|
@@ -46425,61 +46786,118 @@
|
|
|
46425
46786
|
}
|
|
46426
46787
|
}
|
|
46427
46788
|
}
|
|
46428
|
-
|
|
46789
|
+
/**
|
|
46790
|
+
* Setup resume callbacks for incomplete actions after page reload.
|
|
46791
|
+
*
|
|
46792
|
+
* When a page reloads with an incomplete action, this sets up callbacks
|
|
46793
|
+
* so when the user completes the action, we can continue the agent flow.
|
|
46794
|
+
*/
|
|
46795
|
+
function setupActionResumeCallbacks(messages, client, conversationId, widgetId, setState, onMessageUpdate, createStreamState, registerCallback) {
|
|
46429
46796
|
// Find all incomplete actions and register resume callbacks
|
|
46430
46797
|
for (const message of messages) {
|
|
46431
46798
|
if (message.action && !message.action.done && !message.action.hidden) {
|
|
46432
|
-
const
|
|
46433
|
-
const
|
|
46434
|
-
registerCallback(
|
|
46435
|
-
// When user
|
|
46799
|
+
const initialToolCallId = message.action.toolCallId;
|
|
46800
|
+
const initialToolName = message.message.name || message.toolExecuting || "tool";
|
|
46801
|
+
registerCallback(initialToolCallId, async (body) => {
|
|
46802
|
+
// When user completes the action after reload, continue the stream
|
|
46436
46803
|
try {
|
|
46437
|
-
// Update the action message with the new state and check completion
|
|
46438
|
-
if (isDismissedState(newState)) {
|
|
46439
|
-
setState(prev => ({ ...prev, isTyping: false }));
|
|
46440
|
-
return;
|
|
46441
|
-
}
|
|
46442
46804
|
setState(prev => ({
|
|
46443
46805
|
...prev,
|
|
46444
|
-
messages: prev.messages.map(m => {
|
|
46445
|
-
if (m.action?.toolCallId !== toolCallId) {
|
|
46446
|
-
return m;
|
|
46447
|
-
}
|
|
46448
|
-
if (!m.action) {
|
|
46449
|
-
return m;
|
|
46450
|
-
}
|
|
46451
|
-
return { ...m, action: { ...m.action, state: newState } };
|
|
46452
|
-
}),
|
|
46453
46806
|
isTyping: true,
|
|
46454
46807
|
}));
|
|
46455
46808
|
const streamState = createStreamState();
|
|
46456
|
-
|
|
46457
|
-
|
|
46458
|
-
|
|
46459
|
-
|
|
46460
|
-
|
|
46461
|
-
|
|
46462
|
-
|
|
46463
|
-
|
|
46809
|
+
let currentToolCallId = initialToolCallId;
|
|
46810
|
+
let currentToolName = initialToolName;
|
|
46811
|
+
let currentBody = body;
|
|
46812
|
+
// Loop to handle chained action_requests
|
|
46813
|
+
while (true) {
|
|
46814
|
+
let nextActionRequest = null;
|
|
46815
|
+
// Continue the agent with the body
|
|
46816
|
+
for await (const event of client.continueAgentAction(conversationId, currentToolCallId, currentBody)) {
|
|
46817
|
+
if (event.type === "action_request") {
|
|
46818
|
+
// Chained action - need to handle the new action request
|
|
46819
|
+
nextActionRequest = event;
|
|
46820
|
+
break;
|
|
46821
|
+
}
|
|
46822
|
+
if (event.type === "done") {
|
|
46823
|
+
finalizeToolMessage(streamState, setState, currentToolCallId, currentToolName);
|
|
46824
|
+
streamState.sources = event.sources;
|
|
46825
|
+
streamState.toolCallToActionId = event.tool_call_to_action_id;
|
|
46826
|
+
finalizeStreamMessages(setState, streamState.newMessageIds, event.sources, event.tool_call_to_action_id, event.suggestions);
|
|
46827
|
+
setState(prev => ({ ...prev, isTyping: false }));
|
|
46828
|
+
return;
|
|
46829
|
+
}
|
|
46830
|
+
if (event.type === "error") {
|
|
46831
|
+
const errorMessage = {
|
|
46832
|
+
id: generateMessageId(),
|
|
46833
|
+
message: {
|
|
46834
|
+
role: "assistant",
|
|
46835
|
+
content: "Sorry, an error occurred. Please try again later.",
|
|
46836
|
+
},
|
|
46837
|
+
timestamp: new Date().toISOString(),
|
|
46838
|
+
sources: [],
|
|
46839
|
+
isError: true,
|
|
46840
|
+
};
|
|
46841
|
+
upsertMessage(setState, errorMessage, false);
|
|
46842
|
+
setState(prev => ({ ...prev, isTyping: false }));
|
|
46843
|
+
return;
|
|
46844
|
+
}
|
|
46845
|
+
handleStreamEvent(event, streamState, onMessageUpdate, setState);
|
|
46846
|
+
}
|
|
46847
|
+
// If no action_request, stream ended normally
|
|
46848
|
+
if (!nextActionRequest) {
|
|
46849
|
+
setState(prev => ({ ...prev, isTyping: false }));
|
|
46850
|
+
return;
|
|
46851
|
+
}
|
|
46852
|
+
// Update UI with new action for the chained action
|
|
46853
|
+
const toolMessage = {
|
|
46854
|
+
id: nextActionRequest.tool_call_id,
|
|
46855
|
+
sources: [],
|
|
46856
|
+
message: {
|
|
46857
|
+
role: "tool",
|
|
46858
|
+
content: "",
|
|
46859
|
+
tool_call_id: nextActionRequest.tool_call_id,
|
|
46860
|
+
name: currentToolName,
|
|
46861
|
+
},
|
|
46862
|
+
timestamp: new Date().toISOString(),
|
|
46863
|
+
isStreaming: true,
|
|
46864
|
+
toolExecuting: currentToolName,
|
|
46865
|
+
action: {
|
|
46866
|
+
implementation: nextActionRequest.implementation,
|
|
46867
|
+
toolCallId: nextActionRequest.tool_call_id,
|
|
46868
|
+
actionId: nextActionRequest.action_id,
|
|
46869
|
+
input: nextActionRequest.input,
|
|
46870
|
+
done: nextActionRequest.done ?? false,
|
|
46871
|
+
},
|
|
46872
|
+
};
|
|
46873
|
+
upsertMessage(setState, toolMessage, true);
|
|
46874
|
+
// Wait for user to complete the chained action
|
|
46875
|
+
const handler = getFrontendActionHandler(nextActionRequest.implementation);
|
|
46876
|
+
if (!handler) {
|
|
46877
|
+
console.error("[Action Resume] No handler for implementation:", nextActionRequest.implementation);
|
|
46878
|
+
setState(prev => ({ ...prev, isTyping: false }));
|
|
46879
|
+
return;
|
|
46880
|
+
}
|
|
46881
|
+
let handlerResult;
|
|
46882
|
+
try {
|
|
46883
|
+
handlerResult = await handler(nextActionRequest.input, nextActionRequest.input, // Input contains display data for halting actions
|
|
46884
|
+
{
|
|
46885
|
+
widgetId,
|
|
46886
|
+
conversationId,
|
|
46887
|
+
toolCallId: nextActionRequest.tool_call_id,
|
|
46888
|
+
actionId: nextActionRequest.action_id,
|
|
46889
|
+
implementation: nextActionRequest.implementation,
|
|
46890
|
+
});
|
|
46464
46891
|
}
|
|
46465
|
-
|
|
46466
|
-
|
|
46467
|
-
id: generateMessageId(),
|
|
46468
|
-
message: {
|
|
46469
|
-
role: "assistant",
|
|
46470
|
-
content: "Sorry, an error occurred. Please try again later.",
|
|
46471
|
-
},
|
|
46472
|
-
timestamp: new Date().toISOString(),
|
|
46473
|
-
sources: [],
|
|
46474
|
-
isError: true,
|
|
46475
|
-
};
|
|
46476
|
-
upsertMessage(setState, errorMessage, false);
|
|
46892
|
+
catch (handlerError) {
|
|
46893
|
+
console.error("[Action Resume] Handler failed:", handlerError);
|
|
46477
46894
|
setState(prev => ({ ...prev, isTyping: false }));
|
|
46478
46895
|
return;
|
|
46479
46896
|
}
|
|
46480
|
-
|
|
46897
|
+
// Continue loop with new body
|
|
46898
|
+
currentToolCallId = nextActionRequest.tool_call_id;
|
|
46899
|
+
currentBody = handlerResult;
|
|
46481
46900
|
}
|
|
46482
|
-
setState(prev => ({ ...prev, isTyping: false }));
|
|
46483
46901
|
}
|
|
46484
46902
|
catch (error) {
|
|
46485
46903
|
console.error("[Action Resume] Failed to continue stream:", error);
|
|
@@ -46558,7 +46976,7 @@
|
|
|
46558
46976
|
}));
|
|
46559
46977
|
// Setup resume callbacks for incomplete actions
|
|
46560
46978
|
if (conversationId) {
|
|
46561
|
-
setupActionResumeCallbacks(hydratedMessages, apiClient.current, conversationId, setState, onMessage ?? (() => { }), createStreamState, registerActionResumeCallback);
|
|
46979
|
+
setupActionResumeCallbacks(hydratedMessages, apiClient.current, conversationId, widgetId, setState, onMessage ?? (() => { }), createStreamState, registerActionResumeCallback);
|
|
46562
46980
|
}
|
|
46563
46981
|
}
|
|
46564
46982
|
catch (error) {
|
|
@@ -46592,6 +47010,21 @@
|
|
|
46592
47010
|
saveConversation(widgetId, state.conversationId, state.messages);
|
|
46593
47011
|
}
|
|
46594
47012
|
}, [widgetId, state.messages, state.conversationId, state.config?.settings.persistConversation]);
|
|
47013
|
+
// Save conversation on page unload to preserve streaming state
|
|
47014
|
+
reactExports.useEffect(() => {
|
|
47015
|
+
const persistConversation = state.config?.settings.persistConversation ?? true;
|
|
47016
|
+
if (!persistConversation || !isStorageAvailable())
|
|
47017
|
+
return;
|
|
47018
|
+
const handleBeforeUnload = () => {
|
|
47019
|
+
const currentState = stateRef.current;
|
|
47020
|
+
if (currentState.messages.length > 0 && currentState.conversationId) {
|
|
47021
|
+
// Force save current state before page closes
|
|
47022
|
+
saveConversation(widgetId, currentState.conversationId, currentState.messages);
|
|
47023
|
+
}
|
|
47024
|
+
};
|
|
47025
|
+
window.addEventListener('beforeunload', handleBeforeUnload);
|
|
47026
|
+
return () => window.removeEventListener('beforeunload', handleBeforeUnload);
|
|
47027
|
+
}, [widgetId, state.config?.settings.persistConversation]);
|
|
46595
47028
|
const sendMessage = reactExports.useCallback(async (content, files) => {
|
|
46596
47029
|
const trimmedContent = content.trim();
|
|
46597
47030
|
const hasFiles = !!files && files.length > 0;
|
|
@@ -46675,12 +47108,14 @@
|
|
|
46675
47108
|
stateRef.current.conversationId !== streamConversationId ||
|
|
46676
47109
|
currentRequestIdRef.current !== streamRequestId) {
|
|
46677
47110
|
console.log('[Widget] Stream aborted, conversation changed, or superseded by new request');
|
|
47111
|
+
cancelBuffer(streamState.buffer);
|
|
46678
47112
|
break;
|
|
46679
47113
|
}
|
|
46680
47114
|
if (event.type === "action_request") {
|
|
46681
47115
|
if (currentAbortController?.signal.aborted ||
|
|
46682
47116
|
stateRef.current.conversationId !== streamConversationId ||
|
|
46683
47117
|
currentRequestIdRef.current !== streamRequestId) {
|
|
47118
|
+
cancelBuffer(streamState.buffer);
|
|
46684
47119
|
break;
|
|
46685
47120
|
}
|
|
46686
47121
|
await handleActionLoop(apiClient.current, event, streamState, (message) => {
|
|
@@ -46706,26 +47141,8 @@
|
|
|
46706
47141
|
if (lastStreamedMessage) {
|
|
46707
47142
|
onMessage?.(lastStreamedMessage);
|
|
46708
47143
|
}
|
|
46709
|
-
|
|
46710
|
-
|
|
46711
|
-
if (enableFollowUps) {
|
|
46712
|
-
apiClient.current.generateFollowUps(stateRef.current.messages, actionIds)
|
|
46713
|
-
.then(suggestions => {
|
|
46714
|
-
if (suggestions.length > 0) {
|
|
46715
|
-
setState(prev => {
|
|
46716
|
-
const messages = [...prev.messages];
|
|
46717
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
46718
|
-
if (messages[i].message.role === 'assistant' && !messages[i].isError) {
|
|
46719
|
-
messages[i] = { ...messages[i], suggestions };
|
|
46720
|
-
break;
|
|
46721
|
-
}
|
|
46722
|
-
}
|
|
46723
|
-
return { ...prev, messages };
|
|
46724
|
-
});
|
|
46725
|
-
}
|
|
46726
|
-
})
|
|
46727
|
-
.catch(err => console.warn('[Widget] Follow-up generation failed:', err));
|
|
46728
|
-
}
|
|
47144
|
+
// Follow-up suggestions are now generated server-side in parallel and included in the done event
|
|
47145
|
+
// They are automatically attached to the last assistant message by finalizeStreamMessages()
|
|
46729
47146
|
}
|
|
46730
47147
|
catch (error) {
|
|
46731
47148
|
console.error("[Widget] sendMessage error:", error);
|
|
@@ -46882,7 +47299,7 @@
|
|
|
46882
47299
|
messages: hydratedMessages,
|
|
46883
47300
|
isLoading: false,
|
|
46884
47301
|
}));
|
|
46885
|
-
setupActionResumeCallbacks(hydratedMessages, apiClient.current, conversation.id, setState, onMessage ?? (() => { }), createStreamState, registerActionResumeCallback);
|
|
47302
|
+
setupActionResumeCallbacks(hydratedMessages, apiClient.current, conversation.id, widgetId, setState, onMessage ?? (() => { }), createStreamState, registerActionResumeCallback);
|
|
46886
47303
|
if (persistConversation && isStorageAvailable()) {
|
|
46887
47304
|
saveConversation(widgetId, conversation.id, hydratedMessages);
|
|
46888
47305
|
}
|
|
@@ -46969,6 +47386,16 @@
|
|
|
46969
47386
|
return null;
|
|
46970
47387
|
}
|
|
46971
47388
|
}, [widgetId, state.config?.settings.persistConversation]);
|
|
47389
|
+
// Call an action endpoint directly (frontend-owned flow)
|
|
47390
|
+
// Auto-injects conversationId and toolCallId for done flag enforcement
|
|
47391
|
+
const callActionEndpoint = reactExports.useCallback(async (actionId, endpoint, input, options) => {
|
|
47392
|
+
const enrichedInput = {
|
|
47393
|
+
...input,
|
|
47394
|
+
conversationId: state.conversationId,
|
|
47395
|
+
toolCallId: options?.toolCallId,
|
|
47396
|
+
};
|
|
47397
|
+
return apiClient.current.callActionEndpoint(actionId, endpoint, enrichedInput, options?.token);
|
|
47398
|
+
}, [state.conversationId]);
|
|
46972
47399
|
return {
|
|
46973
47400
|
messages: state.messages,
|
|
46974
47401
|
isLoading: state.isLoading,
|
|
@@ -46986,6 +47413,7 @@
|
|
|
46986
47413
|
startNewConversation,
|
|
46987
47414
|
deleteConversation: deleteConversation$1,
|
|
46988
47415
|
createDemoConversation,
|
|
47416
|
+
callActionEndpoint,
|
|
46989
47417
|
};
|
|
46990
47418
|
}
|
|
46991
47419
|
|
|
@@ -47001,17 +47429,19 @@
|
|
|
47001
47429
|
const TrashIcon = () => (jsxRuntimeExports.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M3 6h18" }), jsxRuntimeExports.jsx("path", { d: "M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" }), jsxRuntimeExports.jsx("path", { d: "M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" })] }));
|
|
47002
47430
|
const CloseIcon = () => (jsxRuntimeExports.jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), jsxRuntimeExports.jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }));
|
|
47003
47431
|
const BackIcon = () => (jsxRuntimeExports.jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M19 12H5" }), jsxRuntimeExports.jsx("path", { d: "M12 19l-7-7 7-7" })] }));
|
|
47004
|
-
const ChatWindow = ({ messages, isLoading, isTyping, config, onSendMessage, onClose: _onClose, onFeedback, onActionClick, onActionDismiss,
|
|
47432
|
+
const ChatWindow = ({ messages, isLoading, isTyping, config, onSendMessage, onClose: _onClose, onFeedback, onActionClick, onActionDismiss, onCallEndpoint,
|
|
47005
47433
|
// Chat history props (only active when persistConversation is true)
|
|
47006
47434
|
conversations = [], onLoadConversations, onSwitchConversation, onStartNewConversation, onDeleteConversation, currentConversationId,
|
|
47007
47435
|
// Override props for live preview
|
|
47008
|
-
headerTitleOverride, welcomeTitleOverride, welcomeMessageOverride, placeholderOverride, suggestedQuestionsOverride,
|
|
47436
|
+
sizeOverride, headerTitleOverride, welcomeTitleOverride, welcomeMessageOverride, placeholderOverride, suggestedQuestionsOverride,
|
|
47437
|
+
// Demo mode
|
|
47438
|
+
onInputFocus, }) => {
|
|
47009
47439
|
const appearance = config?.appearance;
|
|
47010
47440
|
const settings = config?.settings;
|
|
47011
47441
|
// Check if chat history should be shown (requires both persistConversation AND showChatHistory)
|
|
47012
47442
|
const canShowHistory = (settings?.persistConversation ?? true) && (settings?.showChatHistory ?? true);
|
|
47013
47443
|
// Apply overrides for live preview (overrides take priority over saved config)
|
|
47014
|
-
const size = appearance?.size
|
|
47444
|
+
const size = sizeOverride ?? appearance?.size ?? 'medium';
|
|
47015
47445
|
const headerTitle = headerTitleOverride ?? appearance?.headerTitle ?? 'AI Assistant';
|
|
47016
47446
|
const welcomeTitle = welcomeTitleOverride ?? appearance?.welcomeTitle ?? '';
|
|
47017
47447
|
const welcomeMessage = welcomeMessageOverride ?? appearance?.welcomeMessage ?? '';
|
|
@@ -47088,7 +47518,7 @@
|
|
|
47088
47518
|
jsxRuntimeExports.jsxs("div", { className: "ai-chat-history-panel", children: [conversations.length === 0 ? (jsxRuntimeExports.jsx("div", { className: "ai-chat-history-empty", children: "No previous conversations" })) : (jsxRuntimeExports.jsx("div", { className: `ai-chat-history-list ${isHistoryExiting ? 'exiting' : ''}`, children: conversations.map((conv) => (jsxRuntimeExports.jsx("div", { className: `ai-chat-history-item ${conv.id === currentConversationId ? 'active' : ''}`, onClick: () => handleSelectConversation(conv.id), children: jsxRuntimeExports.jsxs("div", { className: "ai-chat-history-item-content", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-history-item-preview", children: conv.preview }), onDeleteConversation && (jsxRuntimeExports.jsx("button", { className: "ai-chat-history-item-delete", onClick: (e) => {
|
|
47089
47519
|
e.stopPropagation();
|
|
47090
47520
|
onDeleteConversation(conv.id);
|
|
47091
|
-
}, "aria-label": "Delete conversation", children: jsxRuntimeExports.jsx(TrashIcon, {}) }))] }) }, conv.id))) })), jsxRuntimeExports.jsx(MessageInput, { onSend: (text) => handleSendFromOverview(text), placeholder: inputPlaceholder, disabled: isLoading, enableFileUpload: settings?.enableFileUpload, showDataPolicy: settings?.showDataPolicy ?? true, onDataPolicyClick: handleDataPolicyClick })] })) : (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [maxMessages && userMessageCount >= maxMessages - 2 && !isLimitReached && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-warning", role: "alert", children: [maxMessages - userMessageCount, " message", maxMessages - userMessageCount !== 1 ? 's' : '', " remaining"] })), isLimitReached && (jsxRuntimeExports.jsx("div", { className: "ai-chat-error", role: "alert", children: "Message limit reached. Please start a new conversation." })), (() => {
|
|
47521
|
+
}, "aria-label": "Delete conversation", children: jsxRuntimeExports.jsx(TrashIcon, {}) }))] }) }, conv.id))) })), jsxRuntimeExports.jsx(MessageInput, { onSend: (text) => handleSendFromOverview(text), placeholder: inputPlaceholder, disabled: isLoading, enableFileUpload: settings?.enableFileUpload, showDataPolicy: settings?.showDataPolicy ?? true, onDataPolicyClick: handleDataPolicyClick, onInputFocus: onInputFocus })] })) : (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [maxMessages && userMessageCount >= maxMessages - 2 && !isLimitReached && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-warning", role: "alert", children: [maxMessages - userMessageCount, " message", maxMessages - userMessageCount !== 1 ? 's' : '', " remaining"] })), isLimitReached && (jsxRuntimeExports.jsx("div", { className: "ai-chat-error", role: "alert", children: "Message limit reached. Please start a new conversation." })), (() => {
|
|
47092
47522
|
console.log('[DEBUG ChatWindow] Rendering MessageList with', messages.length, 'messages');
|
|
47093
47523
|
messages.forEach((m, i) => {
|
|
47094
47524
|
console.log(`[DEBUG ChatWindow] msg ${i}:`, { role: m.message.role, hasAction: !!m.action, impl: m.action?.implementation });
|
|
@@ -47098,7 +47528,15 @@
|
|
|
47098
47528
|
console.log('[DEBUG ChatWindow] Testing renderer for query-contact-directory:', !!getActionRenderer('query-contact-directory'));
|
|
47099
47529
|
}
|
|
47100
47530
|
return null;
|
|
47101
|
-
})(), jsxRuntimeExports.jsx(MessageList, { messages: messages, isTyping: isTyping, showTypingIndicator: settings?.showTypingIndicator, showTimestamps: settings?.showTimestamps, showToolCalls: settings?.showToolCalls, enableFeedback: settings?.enableFeedback, welcomeTitle: welcomeTitle || 'Welcome Message', welcomeMessage: welcomeMessage, suggestedQuestions: suggestedQuestionsOverride ?? settings?.suggestedQuestions, accentColor: appearance?.primaryColor, onSuggestedQuestionClick: handleQuestionClick, onActionClick: onActionClick, onActionDismiss: onActionDismiss, onFeedback: onFeedback, onScrollStateChange: handleScrollStateChange, getActionRenderer: getActionRenderer }), settings?.showDataPolicy && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-page-disclaimer", children: [jsxRuntimeExports.jsx("span", { children: "AI-generated responses may be inaccurate." }), jsxRuntimeExports.jsx("button", { type: "button", className: "ai-chat-page-disclaimer-link", onClick: handleDataPolicyClick, children: "Privacy Notice" })] })), jsxRuntimeExports.jsx(ScrollButton, { onClick: () => scrollToBottom?.(), visible: showScrollButton }), jsxRuntimeExports.jsx(MessageInput, { onSend: onSendMessage, placeholder: isLimitReached ? 'Message limit reached' : (isTyping ? 'Waiting for response...' : inputPlaceholder), disabled: isLoading || isTyping || isLimitReached, enableFileUpload: settings?.enableFileUpload, showDataPolicy: settings?.showDataPolicy ?? true, onDataPolicyClick: handleDataPolicyClick })] }))] }));
|
|
47531
|
+
})(), jsxRuntimeExports.jsx(MessageList, { messages: messages, isTyping: isTyping, showTypingIndicator: settings?.showTypingIndicator, showTimestamps: settings?.showTimestamps, showToolCalls: settings?.showToolCalls, enableFeedback: settings?.enableFeedback, welcomeTitle: welcomeTitle || 'Welcome Message', welcomeMessage: welcomeMessage, suggestedQuestions: suggestedQuestionsOverride ?? settings?.suggestedQuestions, accentColor: appearance?.primaryColor, onSuggestedQuestionClick: handleQuestionClick, onActionClick: onActionClick, onActionDismiss: onActionDismiss, onFeedback: onFeedback, onScrollStateChange: handleScrollStateChange, getActionRenderer: getActionRenderer, onCallEndpoint: onCallEndpoint }), settings?.showDataPolicy && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-page-disclaimer", children: [jsxRuntimeExports.jsx("span", { children: "AI-generated responses may be inaccurate." }), jsxRuntimeExports.jsx("button", { type: "button", className: "ai-chat-page-disclaimer-link", onClick: handleDataPolicyClick, children: "Privacy Notice" })] })), jsxRuntimeExports.jsx(ScrollButton, { onClick: () => scrollToBottom?.(), visible: showScrollButton }), jsxRuntimeExports.jsx(MessageInput, { onSend: onSendMessage, placeholder: isLimitReached ? 'Message limit reached' : (isTyping ? 'Waiting for response...' : inputPlaceholder), disabled: isLoading || isTyping || isLimitReached, enableFileUpload: settings?.enableFileUpload, showDataPolicy: settings?.showDataPolicy ?? true, onDataPolicyClick: handleDataPolicyClick, onInputFocus: onInputFocus })] }))] }));
|
|
47532
|
+
};
|
|
47533
|
+
|
|
47534
|
+
const MessageCircleIcon = () => (jsxRuntimeExports.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("path", { d: "M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" }) }));
|
|
47535
|
+
const ChevronDownIcon = () => (jsxRuntimeExports.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("polyline", { points: "6 9 12 15 18 9" }) }));
|
|
47536
|
+
// Icon components mapping for dynamic lookup
|
|
47537
|
+
const iconComponents = {
|
|
47538
|
+
FiMessageCircle: MessageCircleIcon,
|
|
47539
|
+
FiChevronDown: ChevronDownIcon,
|
|
47102
47540
|
};
|
|
47103
47541
|
|
|
47104
47542
|
/**
|
|
@@ -47396,108 +47834,60 @@
|
|
|
47396
47834
|
return styles;
|
|
47397
47835
|
}
|
|
47398
47836
|
|
|
47399
|
-
|
|
47400
|
-
|
|
47401
|
-
|
|
47402
|
-
|
|
47403
|
-
|
|
47404
|
-
|
|
47405
|
-
|
|
47406
|
-
* Uses multiple sampling points for accuracy
|
|
47407
|
-
*/
|
|
47408
|
-
function sampleBackgroundColor(element) {
|
|
47409
|
-
const rect = element.getBoundingClientRect();
|
|
47410
|
-
const centerX = rect.left + rect.width / 2;
|
|
47411
|
-
const centerY = rect.top + rect.height / 2;
|
|
47412
|
-
// Try to get the element behind our widget
|
|
47413
|
-
// Temporarily hide the element to sample what's behind
|
|
47414
|
-
const originalVisibility = element.style.visibility;
|
|
47415
|
-
element.style.visibility = 'hidden';
|
|
47416
|
-
// Sample the center point
|
|
47417
|
-
const elementBehind = document.elementFromPoint(centerX, centerY);
|
|
47418
|
-
// Restore visibility
|
|
47419
|
-
element.style.visibility = originalVisibility;
|
|
47420
|
-
if (!elementBehind) {
|
|
47421
|
-
return '#ffffff'; // Default to white
|
|
47422
|
-
}
|
|
47423
|
-
// Get computed background color
|
|
47424
|
-
const computedStyle = window.getComputedStyle(elementBehind);
|
|
47425
|
-
let bgColor = computedStyle.backgroundColor;
|
|
47426
|
-
// If transparent, walk up the DOM tree
|
|
47427
|
-
if (bgColor === 'rgba(0, 0, 0, 0)' || bgColor === 'transparent') {
|
|
47428
|
-
let parent = elementBehind.parentElement;
|
|
47429
|
-
while (parent) {
|
|
47430
|
-
const parentStyle = window.getComputedStyle(parent);
|
|
47431
|
-
bgColor = parentStyle.backgroundColor;
|
|
47432
|
-
if (bgColor !== 'rgba(0, 0, 0, 0)' && bgColor !== 'transparent') {
|
|
47433
|
-
break;
|
|
47434
|
-
}
|
|
47435
|
-
parent = parent.parentElement;
|
|
47436
|
-
}
|
|
47437
|
-
}
|
|
47438
|
-
// If still transparent, check body/html
|
|
47439
|
-
if (bgColor === 'rgba(0, 0, 0, 0)' || bgColor === 'transparent') {
|
|
47440
|
-
const bodyStyle = window.getComputedStyle(document.body);
|
|
47441
|
-
bgColor = bodyStyle.backgroundColor;
|
|
47442
|
-
if (bgColor === 'rgba(0, 0, 0, 0)' || bgColor === 'transparent') {
|
|
47443
|
-
return '#ffffff'; // Default to white
|
|
47837
|
+
function useWidgetAppearance({ containerRef, config, theme, primaryColor, position, size, headerTitle, welcomeTitle, welcomeMessage, placeholder, welcomeBubbleText, triggerType, triggerText, customStyles, zIndex, previewMode: _previewMode, }) {
|
|
47838
|
+
// Use theme prop directly - no dynamic detection
|
|
47839
|
+
const effectiveTheme = theme ?? "light";
|
|
47840
|
+
// Set data attribute for CSS styling
|
|
47841
|
+
reactExports.useEffect(() => {
|
|
47842
|
+
if (containerRef.current) {
|
|
47843
|
+
containerRef.current.setAttribute('data-theme', effectiveTheme);
|
|
47444
47844
|
}
|
|
47445
|
-
}
|
|
47446
|
-
|
|
47447
|
-
|
|
47448
|
-
|
|
47449
|
-
|
|
47450
|
-
|
|
47451
|
-
|
|
47452
|
-
|
|
47453
|
-
const
|
|
47454
|
-
|
|
47455
|
-
|
|
47456
|
-
const
|
|
47457
|
-
const
|
|
47458
|
-
|
|
47459
|
-
|
|
47460
|
-
|
|
47461
|
-
|
|
47462
|
-
|
|
47463
|
-
|
|
47464
|
-
|
|
47465
|
-
|
|
47466
|
-
|
|
47467
|
-
|
|
47468
|
-
const
|
|
47469
|
-
return
|
|
47470
|
-
|
|
47471
|
-
|
|
47472
|
-
|
|
47473
|
-
|
|
47474
|
-
|
|
47475
|
-
|
|
47476
|
-
|
|
47845
|
+
}, [effectiveTheme, containerRef]);
|
|
47846
|
+
const appearanceConfig = config?.appearance;
|
|
47847
|
+
const effectivePosition = position || appearanceConfig?.position || "bottom-right";
|
|
47848
|
+
const accentColor = primaryColor !== undefined ? primaryColor : appearanceConfig?.primaryColor ?? "";
|
|
47849
|
+
const effectiveSize = size || appearanceConfig?.size || "small";
|
|
47850
|
+
const effectiveHeaderTitle = headerTitle ?? appearanceConfig?.headerTitle ?? "";
|
|
47851
|
+
const effectiveWelcomeTitle = welcomeTitle ?? appearanceConfig?.welcomeTitle ?? "";
|
|
47852
|
+
const effectiveWelcomeMessage = welcomeMessage ?? appearanceConfig?.welcomeMessage ?? "";
|
|
47853
|
+
const effectivePlaceholder = placeholder ?? appearanceConfig?.placeholder ?? "";
|
|
47854
|
+
const effectiveWelcomeBubbleText = welcomeBubbleText ?? appearanceConfig?.welcomeBubbleText ?? "";
|
|
47855
|
+
const effectiveTriggerType = triggerType ?? appearanceConfig?.triggerType ?? "button";
|
|
47856
|
+
const effectiveTriggerText = triggerText ?? appearanceConfig?.triggerText ?? "Chat";
|
|
47857
|
+
const simpleAppearance = {
|
|
47858
|
+
accentColor};
|
|
47859
|
+
const generatedStyles = generateThemeStyles(simpleAppearance, effectiveTheme);
|
|
47860
|
+
const legacyStyles = appearanceConfig ? applyAppearanceStyles(appearanceConfig) : {};
|
|
47861
|
+
const mergedStyles = {
|
|
47862
|
+
...legacyStyles,
|
|
47863
|
+
...generatedStyles,
|
|
47864
|
+
...customStyles,
|
|
47865
|
+
...(zIndex !== undefined ? { "--widget-z-index": String(zIndex) } : {}),
|
|
47866
|
+
};
|
|
47867
|
+
// Compute icon contrast color for inline button styling (prevents FOUC)
|
|
47868
|
+
const iconContrastColor = accentColor ? getContrastText(accentColor) : undefined;
|
|
47869
|
+
return {
|
|
47870
|
+
effectiveTheme,
|
|
47871
|
+
effectivePosition,
|
|
47872
|
+
accentColor,
|
|
47873
|
+
iconContrastColor,
|
|
47874
|
+
effectiveSize,
|
|
47875
|
+
effectiveHeaderTitle,
|
|
47876
|
+
effectiveWelcomeTitle,
|
|
47877
|
+
effectiveWelcomeMessage,
|
|
47878
|
+
effectivePlaceholder,
|
|
47879
|
+
effectiveWelcomeBubbleText,
|
|
47880
|
+
effectiveTriggerType,
|
|
47881
|
+
effectiveTriggerText,
|
|
47882
|
+
mergedStyles,
|
|
47883
|
+
};
|
|
47477
47884
|
}
|
|
47478
|
-
|
|
47479
|
-
|
|
47480
|
-
|
|
47481
|
-
|
|
47482
|
-
|
|
47483
|
-
|
|
47484
|
-
const theme = detectTheme(element);
|
|
47485
|
-
if (theme !== lastTheme) {
|
|
47486
|
-
lastTheme = theme;
|
|
47487
|
-
callback(theme);
|
|
47488
|
-
}
|
|
47489
|
-
});
|
|
47490
|
-
// Observe body for class/style changes (common for theme switching)
|
|
47491
|
-
observer.observe(document.body, {
|
|
47492
|
-
attributes: true,
|
|
47493
|
-
attributeFilter: ['class', 'style', 'data-theme', 'data-bs-theme'],
|
|
47494
|
-
});
|
|
47495
|
-
// Also observe html element
|
|
47496
|
-
observer.observe(document.documentElement, {
|
|
47497
|
-
attributes: true,
|
|
47498
|
-
attributeFilter: ['class', 'style', 'data-theme', 'data-bs-theme'],
|
|
47499
|
-
});
|
|
47500
|
-
return observer;
|
|
47885
|
+
|
|
47886
|
+
function WidgetTriggers({ triggerType, isOpen, onToggle, triggerText, placeholder, IconComponent, showWelcomeBubble, welcomeBubbleText, previewMode, onDismissBubble, isInputBarCollapsed, setIsInputBarCollapsed, inputBarValue, setInputBarValue, onSubmitInputBar, accentColor, iconColor, }) {
|
|
47887
|
+
// Inline button styles to prevent flash of unstyled content (FOUC)
|
|
47888
|
+
// Applied directly to button elements, bypassing CSS variable cascade timing
|
|
47889
|
+
const buttonStyle = accentColor ? { background: accentColor, color: iconColor } : undefined;
|
|
47890
|
+
return (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [triggerType === "button" && !isOpen && welcomeBubbleText && (previewMode || showWelcomeBubble) && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-welcome-bubble", onClick: onToggle, children: [jsxRuntimeExports.jsx("span", { children: welcomeBubbleText }), jsxRuntimeExports.jsx("button", { className: "ai-chat-welcome-bubble-close", onClick: onDismissBubble, "aria-label": "Dismiss", children: jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), jsxRuntimeExports.jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }) }), jsxRuntimeExports.jsx("div", { className: "ai-chat-welcome-bubble-arrow" })] })), triggerType === "button" && (jsxRuntimeExports.jsx("button", { className: `ai-chat-button ${isOpen ? "is-open" : ""}`, onClick: onToggle, "aria-label": isOpen ? "Minimize chat" : "Open chat", style: buttonStyle, children: jsxRuntimeExports.jsx("div", { className: "ai-chat-button-svg", children: jsxRuntimeExports.jsx(IconComponent, {}) }) })), triggerType === "pill-text" && (jsxRuntimeExports.jsxs("button", { className: `ai-chat-trigger-pill ${isOpen ? "is-open" : ""}`, onClick: onToggle, "aria-label": isOpen ? "Close chat" : "Open chat", style: isOpen ? buttonStyle : undefined, children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-trigger-pill-icon", children: jsxRuntimeExports.jsx(IconComponent, {}) }), !isOpen && jsxRuntimeExports.jsx("span", { children: triggerText })] })), triggerType === "input-bar" && !isOpen && (jsxRuntimeExports.jsx("div", { className: "ai-chat-trigger-input-container", children: isInputBarCollapsed ? (jsxRuntimeExports.jsxs("div", { className: "ai-chat-trigger-input-row", children: [jsxRuntimeExports.jsx("button", { type: "button", className: "ai-chat-trigger-collapse-toggle", onClick: () => setIsInputBarCollapsed(false), "aria-label": "Expand input bar", children: jsxRuntimeExports.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("polyline", { points: "15 18 9 12 15 6" }) }) }), jsxRuntimeExports.jsx("button", { type: "button", className: "ai-chat-button", onClick: onToggle, "aria-label": "Open chat", style: buttonStyle, children: jsxRuntimeExports.jsx("div", { className: "ai-chat-button-svg", children: jsxRuntimeExports.jsx(IconComponent, {}) }) })] })) : (jsxRuntimeExports.jsxs("div", { className: "ai-chat-trigger-input-row", children: [jsxRuntimeExports.jsx("button", { type: "button", className: "ai-chat-trigger-collapse-toggle", onClick: () => setIsInputBarCollapsed(true), "aria-label": "Collapse input bar", children: jsxRuntimeExports.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("polyline", { points: "9 18 15 12 9 6" }) }) }), jsxRuntimeExports.jsxs("form", { className: "ai-chat-trigger-input-wrapper", onSubmit: onSubmitInputBar, children: [jsxRuntimeExports.jsx("input", { type: "text", className: "ai-chat-trigger-input", placeholder: placeholder || "Ask me anything...", value: inputBarValue, onChange: (event) => setInputBarValue(event.target.value), "aria-label": "Chat input" }), jsxRuntimeExports.jsx("button", { type: "submit", className: "ai-chat-trigger-input-btn", disabled: !inputBarValue.trim(), "aria-label": "Send message", style: buttonStyle, children: jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("line", { x1: "12", y1: "19", x2: "12", y2: "5" }), jsxRuntimeExports.jsx("polyline", { points: "5 12 12 5 19 12" })] }) })] }), jsxRuntimeExports.jsx("button", { type: "button", className: "ai-chat-trigger-input-expand", onClick: onToggle, "aria-label": "Open chat", children: jsxRuntimeExports.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("polyline", { points: "18 15 12 9 6 15" }) }) })] })) }))] }));
|
|
47501
47891
|
}
|
|
47502
47892
|
|
|
47503
47893
|
function styleInject(css, ref) {
|
|
@@ -47527,34 +47917,19 @@
|
|
|
47527
47917
|
}
|
|
47528
47918
|
}
|
|
47529
47919
|
|
|
47530
|
-
var css_248z$1 = ".ai-chat-message{animation:ai-chat-message-appear .2s var(--chat-ease-bounce);max-width:85%}.ai-chat-message-content{border-radius:var(--chat-radius-bubble,14px);font-size:var(--chat-text-md,15px);line-height:var(--chat-line-relaxed,1.6);padding:var(--chat-space-sm,8px) var(--chat-space-md,16px)}.ai-chat-message.user .ai-chat-message-content{background:var(--chat-user-bg,#f4f3f0);border-bottom-right-radius:var(--chat-radius-sm,4px);color:var(--chat-user-text,#000)}.ai-chat-message.assistant .ai-chat-message-content{background:var(--chat-assistant-bg,transparent);color:var(--chat-assistant-text,#000)}.ai-chat-message-timestamp{color:var(--chat-text-muted,#71717a);font-size:var(--chat-text-xs,12px);margin-top:var(--chat-space-xs,4px);padding:0 var(--chat-space-xs,4px)}.ai-chat-message.streaming .ai-chat-message-content:after{animation:ai-chat-cursor-blink .8s infinite;content:\"▋\";margin-left:2px;opacity:.7}@keyframes ai-chat-message-appear{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}@keyframes ai-chat-cursor-blink{0%,50%{opacity:1}51%,to{opacity:0}}.ai-chat-message.fullpage .ai-chat-message-content{font-size:var(--chat-text-lg,18px);padding:var(--chat-space-md,16px) var(--chat-space-lg,24px)}.ai-chat-typing{gap:var(--chat-space-xs,4px);padding:var(--chat-space-sm,8px) var(--chat-space-md,16px)}.ai-chat-typing-dot{background:var(--chat-text-muted,#71717a)}.ai-chat-tool-row{padding:0 16px}.ai-chat-tool-gear{color:var(--text-primary,#3e3e3e)}.ai-chat-tool-badge{border-radius:8px}.ai-chat-tool-badge.loading{background:#e5e7eb;border:1px solid #d1d5db;color:#1f2937}.ai-chat-tool-badge.error{background:rgba(239,68,68,.1);color:#ef4444}.ai-chat-tool-check{color:#22c55e;flex-shrink:0}.ai-chat-tool-error{color:#ef4444;flex-shrink:0}.ai-chat-tool-badge .tool-name{max-width:150px;overflow:hidden;text-overflow:ellipsis}.ai-chat-widget.dark .ai-chat-tool-gear,.ai-chat-widget[data-theme=dark] .ai-chat-tool-gear,.dark .ai-chat-tool-gear,[data-theme=dark] .ai-chat-tool-gear{color:#fff}.ai-chat-widget.dark .ai-chat-tool-badge,.ai-chat-widget[data-theme=dark] .ai-chat-tool-badge,.dark .ai-chat-tool-badge,[data-theme=dark] .ai-chat-tool-badge{background:hsla(0,0%,100%,.12);border:1px solid hsla(0,0%,100%,.2);color:hsla(0,0%,100%,.9)}.ai-chat-widget.dark .ai-chat-tool-badge.error,.ai-chat-widget[data-theme=dark] .ai-chat-tool-badge.error,.dark .ai-chat-tool-badge.error,[data-theme=dark] .ai-chat-tool-badge.error{background:rgba(239,68,68,.2);color:#f87171}.chakra-ui-dark .ai-chat-tool-gear,html.dark .ai-chat-tool-gear{color:#fff}.chakra-ui-dark .ai-chat-tool-badge,html.dark .ai-chat-tool-badge{background:hsla(0,0%,100%,.12);border:1px solid hsla(0,0%,100%,.2);color:hsla(0,0%,100%,.9)}.chakra-ui-dark .ai-chat-tool-badge.error,html.dark .ai-chat-tool-badge.error{background:rgba(239,68,68,.2);color:#f87171}.ai-chat-pin-input-group{align-items:center;display:flex;flex-wrap:nowrap;gap:8px;justify-content:center;margin:4px 0 8px}.ai-chat-pin-input{align-items:center;appearance:none;background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);box-sizing:border-box;color:var(--text-primary,#3e3e3e);display:inline-flex;flex:0 0 42px;font-family:inherit;font-size:18px;font-weight:600;height:46px;justify-content:center;line-height:1;max-width:42px;min-width:42px;outline:none;padding:0;text-align:center;transition:border-color .2s ease,box-shadow .2s ease;width:42px}.ai-chat-pin-input:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.1)}.ai-chat-pin-input:disabled{cursor:not-allowed;opacity:.6}.ai-chat-widget.dark .ai-chat-pin-input,.chakra-ui-dark .ai-chat-pin-input,.dark .ai-chat-pin-input,[data-theme=dark] .ai-chat-pin-input{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-pin-input:focus,.chakra-ui-dark .ai-chat-pin-input:focus,.dark .ai-chat-pin-input:focus,[data-theme=dark] .ai-chat-pin-input:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.2)}.ai-chat-action-button-secondary{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:9999px;color:var(--text-secondary,#6b7280);cursor:pointer;font-size:var(--text-sm,13px);font-weight:var(--font-weight-medium,500);padding:10px 16px;transition:all .2s ease;width:100%}.ai-chat-action-button-secondary:hover:not(:disabled){background:rgba(59,130,246,.05);border-color:var(--action-accent,var(--primary-color,#3b82f6));color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-action-button-secondary:disabled{cursor:not-allowed;opacity:.5}.ai-chat-widget.dark .ai-chat-action-button-secondary,.chakra-ui-dark .ai-chat-action-button-secondary,.dark .ai-chat-action-button-secondary,[data-theme=dark] .ai-chat-action-button-secondary{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#e5e7eb}.ai-chat-widget.dark .ai-chat-action-button-secondary:hover:not(:disabled),.chakra-ui-dark .ai-chat-action-button-secondary:hover:not(:disabled),.dark .ai-chat-action-button-secondary:hover:not(:disabled),[data-theme=dark] .ai-chat-action-button-secondary:hover:not(:disabled){background:rgba(59,130,246,.2);border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-action-appointment-list,.ai-chat-action-button-group{display:flex;flex-direction:column;gap:8px}.ai-chat-action-appointment-item{align-items:center;background:var(--bg-primary,#fff);border:1px solid var(--border-subtle,rgba(0,0,0,.08));border-radius:var(--radius-md,8px);display:flex;gap:12px;justify-content:space-between;padding:10px 12px}.ai-chat-widget.dark .ai-chat-action-appointment-item,.chakra-ui-dark .ai-chat-action-appointment-item,.dark .ai-chat-action-appointment-item,[data-theme=dark] .ai-chat-action-appointment-item{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.08)}.ai-chat-action-appointment-info{display:flex;flex-direction:column;gap:2px;min-width:0}.ai-chat-action-appointment-subject{color:var(--text-primary,#3e3e3e);font-size:14px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-widget.dark .ai-chat-action-appointment-subject,.chakra-ui-dark .ai-chat-action-appointment-subject,.dark .ai-chat-action-appointment-subject,[data-theme=dark] .ai-chat-action-appointment-subject{color:#fff}.ai-chat-action-appointment-time{color:var(--text-muted,#71717a);font-size:12px}.ai-chat-action-appointment-item .ai-chat-action-button-secondary{font-size:12px;padding:6px 12px;width:auto}.ai-chat-action-error-message{background:rgba(239,68,68,.1);border-radius:var(--radius-md,8px);color:#dc2626;font-size:var(--text-sm,13px);padding:12px}.ai-chat-widget.dark .ai-chat-action-error-message,.chakra-ui-dark .ai-chat-action-error-message,.dark .ai-chat-action-error-message,[data-theme=dark] .ai-chat-action-error-message{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-widget,.chat-ui{--radius-sm:4px;--radius-md:8px;--radius-lg:12px;--radius-xl:16px;--radius-2xl:18px;--radius-pill:9999px;--radius-window-top:22px;--radius-window-bottom:44px;--radius-window-gutter:16px;--radius-chat-bubble:14px;--radius-preset-badge:13px;--radius-history-item:14px;--radius-action-badge:8px;--radius-input:62px;--space-xs:4px;--space-sm:8px;--space-md:16px;--space-lg:24px;--space-xl:32px;--text-xs:12px;--text-sm:14px;--text-md:15px;--text-lg:18px;--text-xl:22px;--text-2xl:28px;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--line-height-tight:1.3;--line-height-normal:1.4;--line-height-relaxed:1.6;--bg-primary:#fff;--bg-secondary:#f4f4f4;--bg-tertiary:#e5e7eb;--bg-hover:#e5e7eb;--text-primary:#3e3e3e;--text-secondary:#000;--text-muted:#71717a;--text-placeholder:#a1a1aa;--border-default:#d3d3d3;--border-subtle:#e5e7eb;--border-muted:#f4f4f5;--user-bg:#f4f3f0;--user-text:#000;--user-bg-hover:#e8e7e4;--agent-bg:transparent;--agent-text:#000;--input-bg:#f4f4f4;--input-border:#d3d3d3;--input-text:#000;--btn-primary-bg:#151515;--btn-primary-text:#f4f4f4;--btn-secondary-bg:transparent;--btn-secondary-text:#71717a;--spring-bounce:cubic-bezier(0.34,1.56,0.64,1);--spring-smooth:cubic-bezier(0.4,0,0.2,1);--spring-snappy:cubic-bezier(0.2,0,0,1);--duration-fast:0.15s;--duration-normal:0.25s;--duration-slow:0.35s;--shadow-sm:0 1px 2px rgba(0,0,0,.05);--shadow-md:0 2px 8px rgba(0,0,0,.1);--shadow-lg:0 4px 16px rgba(0,0,0,.12);--shadow-window:0px 0px 15px 9px rgba(0,0,0,.1);--shadow-button:0px 0px 15px 9px rgba(0,0,0,.03)}.ai-chat-widget.dark,.chat-ui.dark{--bg-primary:#282625;--bg-secondary:#4a4846;--bg-tertiary:#484848;--bg-hover:#484848;--text-primary:#fff;--text-secondary:#fff;--text-muted:#a1a1aa;--text-placeholder:#71717a;--border-default:#5d5b5b;--border-subtle:#5d5b5b;--border-muted:#5d5b5b;--user-bg:#484848;--user-text:#fff;--user-bg-hover:#5a5a5a;--agent-bg:transparent;--agent-text:#fff;--input-bg:#4a4846;--input-border:#5d5b5b;--input-text:#fff;--btn-primary-bg:#fff;--btn-primary-text:#312f2d;--btn-secondary-bg:transparent;--btn-secondary-text:#a1a1aa;--shadow-window:0px 0px 15px 9px rgba(0,0,0,.2);--shadow-button:0px 0px 15px 9px rgba(0,0,0,.03);--shadow-input:0px 0px 10px rgba(0,0,0,.15)}.ai-chat-widget,.chat-ui{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}.ai-chat-widget-container{font-size:var(--text-sm);line-height:1.5;position:fixed;z-index:var(--widget-z-index,2147483647)}.ai-chat-widget-container.bottom-right{bottom:20px;right:20px}.ai-chat-widget-container.bottom-left{bottom:20px;left:20px}.ai-chat-widget-container.top-right{right:20px;top:20px}.ai-chat-widget-container.top-left{left:20px;top:20px}.ai-chat-widget-container.container-mode{position:absolute}@keyframes ai-chat-window-open{0%{opacity:0;transform:scale(.9) translateY(20px)}to{opacity:1;transform:scale(1) translateY(0)}}@keyframes ai-chat-window-close{0%{opacity:1;transform:scale(1) translateY(0)}to{opacity:0;transform:scale(.9) translateY(20px)}}@keyframes ai-chat-message-slide-in{0%{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}@keyframes ai-chat-welcome-fade-in{0%{opacity:0;transform:translateY(16px)}to{opacity:1;transform:translateY(0)}}@keyframes ai-chat-typing-pulse{0%,60%,to{opacity:.4;transform:translateY(0) scale(1)}30%{opacity:1;transform:translateY(-4px) scale(1.1)}}@keyframes ai-chat-gear-spin{to{transform:rotate(1turn)}}@keyframes ai-chat-tool-active{0%,to{background:var(--bg-secondary);opacity:1}50%{background:var(--bg-tertiary);opacity:1}}@keyframes ai-chat-feedback-morph{0%{opacity:.5;transform:scale(.8)}to{opacity:1;transform:scale(1)}}@keyframes ai-chat-checkmark-pop{0%{opacity:0;transform:scale(0) rotate(-45deg)}50%{transform:scale(1.3) rotate(0deg)}to{opacity:1;transform:scale(1) rotate(0deg)}}@keyframes ai-chat-history-exit{to{opacity:0;transform:translateY(-18px)}}@keyframes ai-chat-tool-gradient{0%{background-position:200% 0}to{background-position:-200% 0}}.ai-chat-window{animation:ai-chat-window-open var(--duration-slow,.35s) var(--spring-bounce);background:var(--bg-primary,#fff);border:1px solid var(--border-default,#d3d3d3);border-radius:var(--radius-window-top,22px) var(--radius-window-top,22px) var(--radius-window-bottom,44px) var(--radius-window-bottom,44px);box-shadow:var(--shadow-window,0 0 15px 5px rgba(0,0,0,.08));display:flex;flex-direction:column;overflow:hidden;position:absolute;transform-origin:bottom right;z-index:2}.ai-chat-widget.dark .ai-chat-window{background:var(--bg-primary,#282625);border-color:var(--border-default,#5d5b5b);border-width:.7px}.ai-chat-window.closing{animation:ai-chat-window-close var(--duration-normal) var(--spring-smooth) forwards}.ai-chat-window.size-small{height:500px;width:380px}.ai-chat-window.size-medium,.ai-chat-window.size-small{max-height:calc(100vh - 100px);max-width:calc(100vw - 40px)}.ai-chat-window.size-medium{height:600px;width:420px}.ai-chat-window.size-large{height:700px;max-height:calc(100vh - 100px);max-width:calc(100vw - 40px);width:480px}.ai-chat-widget-container.bottom-right .ai-chat-window{bottom:calc(var(--button-size, 56px) + 8px);right:0}.ai-chat-widget-container.bottom-left .ai-chat-window{bottom:calc(var(--button-size, 56px) + 8px);left:0}.ai-chat-widget-container.top-right .ai-chat-window{right:0;top:calc(var(--button-size, 56px) + 8px)}.ai-chat-widget-container.top-left .ai-chat-window{left:0;top:calc(var(--button-size, 56px) + 8px)}.ai-chat-header{align-items:center;background:var(--bg-primary,#fff);border-bottom:1px solid var(--border-default,#d3d3d3);border-radius:var(--radius-window-top,22px) var(--radius-window-top,22px) 0 0;display:flex;justify-content:space-between;padding:12px var(--space-md,16px);position:relative;z-index:10}.ai-chat-widget.dark .ai-chat-header{background:var(--bg-primary,#282625);border-bottom-color:var(--border-default,#5d5b5b);border-bottom-width:.7px}.ai-chat-header.is-history{padding-left:var(--space-md)}.ai-chat-header.is-history .ai-chat-title{flex:1;min-width:0;overflow:hidden;padding-right:var(--space-lg);text-overflow:ellipsis;white-space:nowrap}.ai-chat-header-content{align-items:center;display:flex;flex:1;gap:var(--space-lg)}.ai-chat-header-actions{align-items:center;display:flex;gap:var(--space-sm)}.ai-chat-logo{border-radius:10px;height:36px;object-fit:cover;width:36px}.ai-chat-title{color:var(--text-primary,#3e3e3e);font-size:var(--text-xl,22px);font-weight:var(--font-weight-bold,700);letter-spacing:-.02em}.ai-chat-widget.dark .ai-chat-title{color:var(--text-primary,#fff)}.ai-chat-close-button,.ai-chat-header-button{align-items:center;background:transparent;border:none;border-radius:var(--radius-md);color:var(--text-muted);cursor:pointer;display:flex;height:32px;justify-content:center;padding:0;transition:color var(--duration-fast) ease;width:32px}.ai-chat-close-button:hover,.ai-chat-header-button:hover{color:var(--text-primary)}.ai-chat-close-button:active,.ai-chat-header-button:active{transform:scale(.95)}.ai-chat-close-button svg,.ai-chat-header-button svg{height:22px;width:22px}.ai-chat-button{align-items:center;background:var(--button-color,var(--btn-primary-bg));border:1px solid var(--border-default,#d3d3d3);border-radius:50%;box-shadow:var(--shadow-button,0 0 15px 9px rgba(0,0,0,.03));color:var(--button-icon-color,var(--btn-primary-text));cursor:pointer;display:flex;height:var(--button-size,56px);justify-content:center;overflow:hidden;position:relative;transition:transform var(--duration-fast) ease;width:var(--button-size,56px);z-index:1}.ai-chat-button:hover{transform:scale(1.05)}.ai-chat-button:active{transform:scale(.98)}.ai-chat-button-svg{height:50%;min-height:24px;min-width:24px;transition:transform var(--duration-fast) ease;width:50%}.ai-chat-button.is-open .ai-chat-button-svg{transform:rotate(0deg)}.ai-chat-button-icon{font-size:1.5em;line-height:1}.ai-chat-welcome-bubble{animation:ai-chat-bubble-fade-in .3s ease-out;background:var(--button-color,var(--btn-primary-bg,#07f));border:none;border-radius:16px;box-shadow:none;box-sizing:border-box;color:var(--button-icon-color,var(--btn-primary-text,#fff));cursor:pointer;font-size:13px;font-weight:500;line-height:1.5;max-width:min(420px,90vw);padding:12px 32px 12px 16px;position:absolute;text-align:left;white-space:normal;width:auto;z-index:0}.ai-chat-welcome-bubble-close{align-items:center;background:transparent;border:none;border-radius:50%;color:inherit;cursor:pointer;display:flex;height:20px;justify-content:center;opacity:.8;padding:0;position:absolute;right:8px;top:8px;transition:opacity .15s ease,background .15s ease;width:20px}.ai-chat-welcome-bubble-close:hover{background:hsla(0,0%,100%,.2);opacity:1}.ai-chat-welcome-bubble-close svg{height:12px;width:12px}.ai-chat-welcome-bubble-arrow{border-bottom:8px solid transparent;border-top:8px solid transparent;height:0;position:absolute;width:0}.ai-chat-widget-container.bottom-right .ai-chat-welcome-bubble{bottom:50%;right:calc(100% + 12px);text-align:left;transform:translateY(50%)}.ai-chat-widget-container.bottom-left .ai-chat-welcome-bubble{bottom:50%;left:calc(100% + 12px);text-align:left;transform:translateY(50%)}.ai-chat-widget-container.top-right .ai-chat-welcome-bubble{right:calc(100% + 12px);text-align:left;top:50%;transform:translateY(-50%)}.ai-chat-widget-container.top-left .ai-chat-welcome-bubble{left:calc(100% + 12px);text-align:left;top:50%;transform:translateY(-50%)}.ai-chat-widget-container.bottom-right .ai-chat-welcome-bubble-arrow{border-left:8px solid var(--button-color,var(--btn-primary-bg,#07f));right:-8px;top:50%;transform:translateY(-50%)}.ai-chat-widget-container.bottom-left .ai-chat-welcome-bubble-arrow{border-right:8px solid var(--button-color,var(--btn-primary-bg,#07f));left:-8px;top:50%;transform:translateY(-50%)}.ai-chat-widget-container.top-right .ai-chat-welcome-bubble-arrow{border-left:8px solid var(--button-color,var(--btn-primary-bg,#07f));right:-8px;top:50%;transform:translateY(-50%)}.ai-chat-widget-container.top-left .ai-chat-welcome-bubble-arrow{border-right:8px solid var(--button-color,var(--btn-primary-bg,#07f));left:-8px;top:50%;transform:translateY(-50%)}.ai-chat-welcome-bubble:hover{filter:brightness(1.1)}.ai-chat-widget-container.bottom-right .ai-chat-welcome-bubble{animation-name:ai-chat-bubble-fade-in-bottom-right}@keyframes ai-chat-bubble-fade-in-bottom-right{0%{opacity:0;transform:translateY(50%) translateX(8px)}to{opacity:1;transform:translateY(50%) translateX(0)}}.ai-chat-widget-container.bottom-left .ai-chat-welcome-bubble{animation-name:ai-chat-bubble-fade-in-bottom-left}@keyframes ai-chat-bubble-fade-in-bottom-left{0%{opacity:0;transform:translateY(50%) translateX(-8px)}to{opacity:1;transform:translateY(50%) translateX(0)}}.ai-chat-widget-container.top-right .ai-chat-welcome-bubble{animation-name:ai-chat-bubble-fade-in-top-right}@keyframes ai-chat-bubble-fade-in-top-right{0%{opacity:0;transform:translateY(-50%) translateX(8px)}to{opacity:1;transform:translateY(-50%) translateX(0)}}.ai-chat-widget-container.top-left .ai-chat-welcome-bubble{animation-name:ai-chat-bubble-fade-in-top-left}@keyframes ai-chat-bubble-fade-in-top-left{0%{opacity:0;transform:translateY(-50%) translateX(-8px)}to{opacity:1;transform:translateY(-50%) translateX(0)}}.ai-chat-trigger-pill{align-items:center;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);background:hsla(0,0%,100%,.08);border:1px solid hsla(0,0%,100%,.15);border-radius:9999px;color:var(--text-primary,#fff);cursor:pointer;display:flex;font-size:13px;font-weight:500;gap:8px;height:40px;justify-content:center;padding:0 20px;position:relative;transition:all .3s ease;white-space:nowrap;z-index:1}.ai-chat-trigger-pill.is-open{background:var(--button-color,var(--btn-primary-bg));border-color:var(--border-default,#d3d3d3);box-shadow:var(--shadow-button,0 0 15px 9px rgba(0,0,0,.03));height:56px;padding:0;width:56px}.ai-chat-trigger-pill.is-open .ai-chat-trigger-pill-icon{height:24px;width:24px}.ai-chat-trigger-pill:hover:not(.is-open){background:hsla(0,0%,100%,.12);border-color:hsla(0,0%,100%,.25)}.ai-chat-trigger-pill.is-open:hover{transform:scale(1.05)}.ai-chat-trigger-pill:active{transform:scale(.98)}.ai-chat-trigger-pill-icon{flex-shrink:0;height:16px;transition:all .3s ease;width:16px}.ai-chat-widget.light .ai-chat-trigger-pill{background:rgba(0,0,0,.04);border-color:rgba(0,0,0,.12);color:var(--text-primary,#1a1a1a)}.ai-chat-widget.light .ai-chat-trigger-pill:hover:not(.is-open){background:rgba(0,0,0,.08);border-color:rgba(0,0,0,.2)}.ai-chat-trigger-input-container{align-items:flex-end;display:flex;flex-direction:column;gap:8px}.ai-chat-widget-container.bottom-left .ai-chat-trigger-input-container,.ai-chat-widget-container.top-left .ai-chat-trigger-input-container{align-items:flex-start}.ai-chat-trigger-input-expand{align-items:center;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);background:hsla(0,0%,100%,.1);border:1px solid hsla(0,0%,100%,.15);border-radius:50%;color:hsla(0,0%,100%,.7);cursor:pointer;display:flex;height:32px;justify-content:center;padding:0;transition:all .2s ease;width:32px}.ai-chat-trigger-input-expand:hover{background:hsla(0,0%,100%,.15);color:hsla(0,0%,100%,.9);transform:translateY(-2px)}.ai-chat-trigger-input-expand:active{transform:translateY(0)}.ai-chat-trigger-input-expand svg{height:16px;width:16px}.ai-chat-widget.light .ai-chat-trigger-input-expand{background:rgba(0,0,0,.05);border:1px solid rgba(0,0,0,.1);color:rgba(0,0,0,.5)}.ai-chat-widget.light .ai-chat-trigger-input-expand:hover{background:rgba(0,0,0,.1);color:rgba(0,0,0,.7)}.ai-chat-trigger-input-wrapper{max-width:calc(100vw - 40px);position:relative;z-index:1}.ai-chat-widget-container.trigger-input-bar .ai-chat-trigger-input-wrapper{width:348px}.ai-chat-widget-container.trigger-input-bar.size-medium .ai-chat-trigger-input-wrapper{width:388px}.ai-chat-widget-container.trigger-input-bar.size-large .ai-chat-trigger-input-wrapper{width:448px}.ai-chat-trigger-input{backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);background:hsla(0,0%,100%,.08);border:1px solid hsla(0,0%,100%,.12);border-radius:var(--radius-input,62px);box-shadow:0 4px 24px rgba(0,0,0,.15);box-sizing:border-box;color:var(--input-text,#fff);font-size:var(--text-md,15px);height:52px;outline:none;padding:6px 52px 6px 16px;transition:all .2s ease;width:100%}.ai-chat-trigger-input::placeholder{color:var(--text-placeholder,hsla(0,0%,100%,.5))}.ai-chat-trigger-input:focus{background:hsla(0,0%,100%,.12);border-color:hsla(0,0%,100%,.25)}.ai-chat-trigger-input-btn{align-items:center;background:var(--primary-color,var(--button-color,#07f));border:none;border-radius:50%;box-shadow:0 2px 8px rgba(0,119,255,.3);color:#fff;cursor:pointer;display:flex;height:40px;justify-content:center;position:absolute;right:6px;top:50%;transform:translateY(-50%);transition:all .2s ease;width:40px}.ai-chat-trigger-input-btn:hover:not(:disabled){box-shadow:0 4px 12px rgba(0,119,255,.4);transform:translateY(-50%) scale(1.05)}.ai-chat-trigger-input-btn:active:not(:disabled){transform:translateY(-50%) scale(.95)}.ai-chat-trigger-input-btn:disabled{box-shadow:none;cursor:not-allowed;opacity:.4}.ai-chat-trigger-input-btn svg{height:18px;width:18px}.ai-chat-widget.light .ai-chat-trigger-input{backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);background:hsla(0,0%,100%,.7);border:1px solid rgba(0,0,0,.1);box-shadow:0 4px 24px rgba(0,0,0,.08);color:var(--input-text,#1a1a1a)}.ai-chat-widget.light .ai-chat-trigger-input::placeholder{color:var(--text-placeholder,rgba(0,0,0,.4))}.ai-chat-widget.light .ai-chat-trigger-input:focus{background:hsla(0,0%,100%,.85);border-color:rgba(0,0,0,.2)}.ai-chat-widget.light .ai-chat-trigger-input-btn{background:var(--primary-color,var(--button-color,#07f));box-shadow:0 2px 8px rgba(0,119,255,.25);color:#fff}.ai-chat-widget.light .ai-chat-trigger-input-btn:hover:not(:disabled){box-shadow:0 4px 12px rgba(0,119,255,.35)}.ai-chat-widget-container.trigger-input-bar{align-items:flex-end;display:flex;flex-direction:column;gap:12px}.ai-chat-widget-container.trigger-input-bar.bottom-left,.ai-chat-widget-container.trigger-input-bar.top-left{align-items:flex-start}.ai-chat-widget-container.trigger-input-bar .ai-chat-window{bottom:auto;left:auto;order:-1;position:relative;right:auto;top:auto;width:100%}.ai-chat-widget-container.trigger-input-bar .ai-chat-window.size-small{max-width:calc(100vw - 40px);width:380px}.ai-chat-widget-container.trigger-input-bar .ai-chat-window.size-medium{max-width:calc(100vw - 40px);width:420px}.ai-chat-widget-container.trigger-input-bar .ai-chat-window.size-large{max-width:calc(100vw - 40px);width:480px}.ai-chat-widget-container.trigger-input-bar .ai-chat-button,.ai-chat-widget-container.trigger-pill-text .ai-chat-button{display:none}.ai-chat-widget-container.trigger-pill-text.is-open{gap:8px}.ai-chat-input-container{background:var(--bg-primary,#fff);bottom:0;left:0;padding:8px 0 16px;position:absolute;right:0;z-index:10}.ai-chat-widget.dark .ai-chat-input-container{background:var(--bg-primary,#282625)}.ai-chat-input-container.separate{padding:0 var(--radius-window-gutter,16px) var(--radius-window-gutter,16px)}.ai-chat-input-wrapper{align-items:flex-end;background:var(--input-bg,#f4f4f4);border:1px solid var(--input-border,#d3d3d3);border-radius:var(--radius-input,62px);box-sizing:border-box;display:flex;gap:0;height:52px;overflow:hidden;padding:6px 6px 6px 16px;position:relative;transition:all var(--duration-fast,.15s) ease;z-index:5}.ai-chat-input-wrapper.multiline{border-radius:14px!important;min-height:64px;padding:10px 10px 10px 14px}.ai-chat-widget.dark .ai-chat-input-wrapper{background:var(--input-bg,#4a4846);border-color:var(--input-border,#5d5b5b);border-width:.7px;box-shadow:var(--shadow-input,0 0 10px rgba(0,0,0,.15))}.ai-chat-input-wrapper:focus-within{border-color:var(--text-muted,#a1a1aa)}.ai-chat-input{word-wrap:break-word!important;background:transparent!important;border:none!important;border-radius:0!important;box-shadow:none!important;box-sizing:border-box!important;color:var(--input-text,#000)!important;flex:1!important;font-family:inherit!important;font-size:var(--text-md,15px)!important;height:40px!important;line-height:20px!important;margin:0!important;max-height:40px!important;min-height:40px!important;min-width:0!important;outline:none!important;overflow-wrap:anywhere!important;overflow-x:hidden!important;overflow-y:auto!important;padding:10px var(--space-sm,8px)!important;resize:none!important;white-space:pre-wrap!important;width:0!important;word-break:break-word!important}.ai-chat-widget.dark .ai-chat-input{color:var(--input-text,#fff)}.ai-chat-input::placeholder{color:var(--text-placeholder,#a1a1aa)}.ai-chat-widget.dark .ai-chat-input::placeholder{color:var(--text-placeholder,#52525b)}.ai-chat-file-button{align-items:center;align-self:center;background:transparent;border:none;color:var(--text-placeholder);cursor:pointer;display:flex;flex-shrink:0;height:28px;justify-content:center;padding:0;transition:color var(--duration-fast) ease;width:28px}.ai-chat-file-button:hover{color:var(--text-secondary)}.ai-chat-file-button:disabled{cursor:not-allowed;opacity:.5}.ai-chat-send-button{align-items:center;align-self:center;background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#151515))));border:none;border-radius:50%;color:var(--button-icon-color,var(--btn-primary-text,#f4f4f4));cursor:pointer;display:flex;flex-shrink:0;height:40px;justify-content:center;min-height:40px;min-width:40px;padding:0;transition:all var(--duration-fast,.15s) ease;width:40px}.ai-chat-widget.dark .ai-chat-send-button{background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#fff))));color:var(--button-icon-color,var(--btn-primary-text,#312f2d))}.ai-chat-send-button.active{background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#151515))));color:var(--button-icon-color,var(--btn-primary-text,#f4f4f4))}.ai-chat-widget.dark .ai-chat-send-button.active{background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#fff))));color:var(--button-icon-color,var(--btn-primary-text,#312f2d))}.ai-chat-send-button:hover:not(:disabled){opacity:.8}.ai-chat-send-button:active:not(:disabled){transform:scale(.95)}.ai-chat-send-button:disabled{cursor:not-allowed;opacity:.3}.ai-chat-file-list{display:flex;flex-wrap:wrap;gap:var(--space-sm);padding:var(--space-sm) var(--space-sm)}.ai-chat-file-item{align-items:center;background:rgba(0,0,0,.05);border-radius:6px;display:flex;font-size:var(--text-xs);gap:var(--space-sm);padding:6px 10px}.ai-chat-file-extension{background:var(--btn-primary-bg);border-radius:3px;color:var(--btn-primary-text);display:inline-block;font-size:10px;font-weight:var(--font-weight-semibold);min-width:40px;padding:2px 6px;text-align:center;text-transform:uppercase}.ai-chat-file-info{display:flex;flex:1;flex-direction:column;gap:2px;min-width:0}.ai-chat-file-name{font-weight:var(--font-weight-medium);max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-file-size{color:var(--text-muted);font-size:10px;opacity:.7}.ai-chat-file-remove{align-items:center;background:none;border:none;color:inherit;cursor:pointer;display:flex;justify-content:center;opacity:.5;padding:var(--space-xs);transition:opacity var(--duration-fast) ease}.ai-chat-file-remove:hover{opacity:1}.ai-chat-data-policy{bottom:2px;color:var(--text-muted,#71717a);font-size:9px;left:0;line-height:1.4;opacity:.5;pointer-events:auto;position:absolute;right:0;text-align:center}.ai-chat-widget.dark .ai-chat-data-policy{color:var(--text-muted,#a1a1aa)}.ai-chat-data-policy-link{background:none;border:none;color:var(--text-muted,#71717a);cursor:pointer;font-family:inherit;font-size:inherit;margin:0;padding:0;text-decoration:underline;text-underline-offset:2px;transition:color .15s ease}.ai-chat-data-policy-link:hover{color:var(--text-secondary,#52525b)}.ai-chat-widget.dark .ai-chat-data-policy-link{color:var(--text-muted,#a1a1aa)}.ai-chat-widget.dark .ai-chat-data-policy-link:hover{color:var(--text-secondary,#d4d4d8)}.ai-chat-page-disclaimer{align-items:center;color:var(--text-muted,#71717a);display:flex;font-size:10px;gap:4px;justify-content:center;line-height:1.4;opacity:.7;padding:8px 16px;text-align:center}.ai-chat-widget.dark .ai-chat-page-disclaimer{color:var(--text-muted,#a1a1aa)}.ai-chat-page-disclaimer-link{background:none;border:none;color:var(--text-muted,#71717a);cursor:pointer;font-family:inherit;font-size:inherit;margin:0;padding:0;text-decoration:underline;text-underline-offset:2px;transition:color .15s ease}.ai-chat-page-disclaimer-link:hover{color:var(--text-secondary,#52525b)}.ai-chat-widget.dark .ai-chat-page-disclaimer-link{color:var(--text-muted,#a1a1aa)}.ai-chat-widget.dark .ai-chat-page-disclaimer-link:hover{color:var(--text-secondary,#d4d4d8)}.ai-chat-messages{-webkit-overflow-scrolling:touch;-ms-overflow-style:none;align-items:stretch;background:var(--bg-primary,#fff);display:flex;flex:1;flex-direction:column;gap:var(--space-md,16px);justify-content:flex-start;overflow-x:hidden;overflow-y:auto;padding:0 var(--space-md,16px) 100px;position:relative;scroll-behavior:smooth;scrollbar-width:none}.ai-chat-widget.dark .ai-chat-messages{background:var(--bg-primary,#18181b)}.ai-chat-messages::-webkit-scrollbar{display:none}.ai-chat-message{animation:ai-chat-message-slide-in .2s var(--spring-bounce);display:flex;flex-direction:column;max-width:90%}.ai-chat-message.user{align-items:flex-end;align-self:flex-end}.ai-chat-message.assistant{align-items:flex-start;align-self:flex-start;max-width:100%;width:100%}.ai-chat-message.tool{align-self:stretch;max-width:none;padding:0}.ai-chat-message-content{word-wrap:break-word;border-radius:18px;font-size:var(--text-md,15px);line-height:var(--line-height-relaxed,1.6);overflow-wrap:break-word;padding:8px 14px}.ai-chat-message.user .ai-chat-message-content{background:var(--user-bg,#f4f3f0);border-radius:18px;color:var(--user-text,#000)}.ai-chat-widget.dark .ai-chat-message.user .ai-chat-message-content{background:var(--user-bg,#484848);color:var(--user-text,#fff)}.ai-chat-message.assistant .ai-chat-message-content{background:var(--agent-bg,transparent);box-sizing:border-box;color:var(--agent-text,#000);padding:0;width:100%}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content{color:var(--agent-text,#fff)}.ai-chat-message-timestamp{color:var(--text-muted,#71717a);font-size:var(--text-xs,12px);margin-top:var(--space-xs,4px);padding:0 var(--space-xs,4px)}.ai-chat-welcome{animation:ai-chat-welcome-fade-in .3s var(--spring-smooth);display:flex;flex-direction:column;gap:var(--space-md,16px);padding:var(--space-lg,24px) 0}.ai-chat-welcome-title{color:var(--text-primary,#3e3e3e);font-size:var(--text-2xl,28px);font-weight:var(--font-weight-bold,700);line-height:var(--line-height-tight,1.3)}.ai-chat-widget.dark .ai-chat-welcome-title{color:var(--text-primary,#fff)}.ai-chat-welcome-text{color:var(--text-secondary,#000);font-size:var(--text-md,15px);line-height:var(--line-height-relaxed,1.6);max-width:100%}.ai-chat-widget.dark .ai-chat-welcome-text{color:var(--text-secondary,#fff)}.ai-chat-typing{align-items:center;display:flex;gap:var(--space-xs,4px);padding:var(--space-sm,8px) var(--space-md,16px)}.ai-chat-typing-dot{animation:ai-chat-typing-bounce 1.4s ease-in-out infinite both;background:var(--text-muted,#71717a);border-radius:50%;height:8px;width:8px}.ai-chat-typing-dot:first-child{animation-delay:-.32s}.ai-chat-typing-dot:nth-child(2){animation-delay:-.16s}.ai-chat-typing-dot:nth-child(3){animation-delay:0s}@keyframes ai-chat-typing-bounce{0%,80%,to{opacity:.4;transform:scale(.6)}40%{opacity:1;transform:scale(1)}}.ai-chat-scroll-button{align-items:center;background:var(--bg-secondary,#f4f4f5);border:1px solid var(--border-subtle,rgba(0,0,0,.1));border-radius:50%;bottom:80px;box-shadow:0 2px 8px rgba(0,0,0,.1);color:var(--text-secondary,#71717a);cursor:pointer;display:flex;height:36px;justify-content:center;left:50%;opacity:0;pointer-events:none;position:absolute;transform:translateX(-50%);transition:background .15s ease,box-shadow .15s ease,opacity .15s ease,visibility .15s ease;visibility:hidden;width:36px;z-index:15}.ai-chat-scroll-button.visible{opacity:1;pointer-events:auto;visibility:visible}.ai-chat-scroll-button:hover{background:var(--bg-tertiary,#e4e4e7);box-shadow:0 4px 12px rgba(0,0,0,.15)}.ai-chat-scroll-button:active{background:var(--bg-tertiary,#d4d4d8)}.ai-chat-widget.dark .ai-chat-scroll-button{background:var(--bg-secondary,#3f3f46);border-color:var(--border-subtle,hsla(0,0%,100%,.1));box-shadow:0 2px 8px rgba(0,0,0,.3);color:var(--text-secondary,#a1a1aa)}.ai-chat-widget.dark .ai-chat-scroll-button:hover{background:var(--bg-tertiary,#52525b);box-shadow:0 4px 12px rgba(0,0,0,.4)}.ai-chat-error{background:var(--bg-secondary);border-radius:var(--radius-chat-bubble);color:var(--text-primary);font-size:var(--text-md);margin:0 auto;padding:10px var(--space-md)}.ai-chat-message.assistant .ai-chat-message-content p{margin:0 0 var(--space-sm) 0}.ai-chat-message.assistant .ai-chat-message-content p:last-child{margin-bottom:0}.ai-chat-message.assistant .ai-chat-message-content h1{font-size:1.5em}.ai-chat-message.assistant .ai-chat-message-content h1,.ai-chat-message.assistant .ai-chat-message-content h2{color:var(--text-primary,#3e3e3e);font-weight:var(--font-weight-bold,700);line-height:var(--line-height-tight,1.3);margin:var(--space-md,16px) 0 var(--space-sm,8px) 0}.ai-chat-message.assistant .ai-chat-message-content h2{font-size:1.3em}.ai-chat-message.assistant .ai-chat-message-content h3{color:var(--text-primary,#3e3e3e);font-size:1.15em;font-weight:var(--font-weight-semibold,600);line-height:var(--line-height-tight,1.3);margin:var(--space-sm,8px) 0 var(--space-xs,4px) 0}.ai-chat-message.assistant .ai-chat-message-content h4,.ai-chat-message.assistant .ai-chat-message-content h5,.ai-chat-message.assistant .ai-chat-message-content h6{color:var(--text-primary,#3e3e3e);font-size:1em;font-weight:var(--font-weight-semibold,600);line-height:var(--line-height-tight,1.3);margin:var(--space-sm,8px) 0 var(--space-xs,4px) 0}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content h1,.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content h2,.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content h3,.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content h4,.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content h5,.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content h6{color:var(--text-primary,#fff)}.ai-chat-message.assistant .ai-chat-message-content>h1:first-child,.ai-chat-message.assistant .ai-chat-message-content>h2:first-child,.ai-chat-message.assistant .ai-chat-message-content>h3:first-child,.ai-chat-message.assistant .ai-chat-message-content>h4:first-child,.ai-chat-message.assistant .ai-chat-message-content>h5:first-child,.ai-chat-message.assistant .ai-chat-message-content>h6:first-child{margin-top:0}.ai-chat-message.assistant .ai-chat-message-content ul{list-style-type:disc;margin:var(--space-sm,8px) 0;padding-left:var(--space-lg,24px)}.ai-chat-message.assistant .ai-chat-message-content ul ul{list-style-type:circle;margin:var(--space-xs,4px) 0}.ai-chat-message.assistant .ai-chat-message-content ul ul ul{list-style-type:square}.ai-chat-message.assistant .ai-chat-message-content ol{list-style-type:decimal;margin:var(--space-sm,8px) 0;padding-left:var(--space-lg,24px)}.ai-chat-message.assistant .ai-chat-message-content ol ol{list-style-type:lower-alpha;margin:var(--space-xs,4px) 0}.ai-chat-message.assistant .ai-chat-message-content ol ol ol{list-style-type:lower-roman}.ai-chat-message.assistant .ai-chat-message-content li{margin-bottom:var(--space-xs,4px);padding-left:var(--space-xs,4px)}.ai-chat-message.assistant .ai-chat-message-content li:last-child{margin-bottom:0}.ai-chat-message.assistant .ai-chat-message-content li>ol,.ai-chat-message.assistant .ai-chat-message-content li>ul{margin-top:var(--space-xs,4px)}.ai-chat-message.assistant .ai-chat-message-content code{background:rgba(0,0,0,.05);border-radius:var(--radius-sm);font-family:SF Mono,Monaco,Cascadia Code,monospace;font-size:.9em;padding:2px 6px}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content code{background:hsla(0,0%,100%,.1)}.ai-chat-message.assistant .ai-chat-message-content pre{background:rgba(0,0,0,.05);border-radius:var(--radius-md);margin:var(--space-sm) 0;overflow-x:auto;padding:var(--space-sm)}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content pre{background:hsla(0,0%,100%,.05)}.ai-chat-message.assistant .ai-chat-message-content pre code{background:transparent;padding:0}.ai-chat-message.assistant .ai-chat-message-content a{color:var(--btn-primary-bg);text-decoration:underline}.ai-chat-message.assistant .ai-chat-message-content strong{font-weight:var(--font-weight-semibold)}.ai-chat-message.assistant .ai-chat-message-content blockquote{border-left:3px solid var(--border-default);color:var(--text-muted);margin:var(--space-sm) 0;padding-left:var(--space-md)}.ai-chat-message.assistant .ai-chat-message-content hr{border:none;border-top:1px solid var(--border-subtle,rgba(0,0,0,.1));margin:var(--space-lg,24px) 0}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content hr{border-top-color:var(--border-subtle,hsla(0,0%,100%,.1))}.ai-chat-message.assistant .ai-chat-message-content .table-wrapper{border:1px solid var(--border-subtle,rgba(0,0,0,.1));border-radius:var(--radius-md,8px);box-sizing:border-box;display:block;margin:var(--space-sm) var(--space-sm);max-width:100%;overflow:hidden;width:auto}.ai-chat-message.assistant .ai-chat-message-content .table-scroll{max-width:100%;overflow-x:auto;overflow-y:hidden;width:100%}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content .table-wrapper{border-color:var(--border-subtle,hsla(0,0%,100%,.1))}.ai-chat-message.assistant .ai-chat-message-content table{border-collapse:collapse;font-size:var(--text-sm);min-width:100%;width:max-content}.ai-chat-message.assistant .ai-chat-message-content td,.ai-chat-message.assistant .ai-chat-message-content th{border-bottom:1px solid var(--border-subtle,rgba(0,0,0,.1));border-right:1px solid var(--border-subtle,rgba(0,0,0,.1));padding:var(--space-sm);text-align:left}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content td,.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content th{border-color:var(--border-subtle,hsla(0,0%,100%,.1))}.ai-chat-message.assistant .ai-chat-message-content td:last-child,.ai-chat-message.assistant .ai-chat-message-content th:last-child{border-right:none}.ai-chat-message.assistant .ai-chat-message-content tr:last-child td{border-bottom:none}.ai-chat-message.assistant .ai-chat-message-content th{background:rgba(0,0,0,.03);font-weight:var(--font-weight-semibold);white-space:nowrap}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content th{background:hsla(0,0%,100%,.05)}.ai-chat-message.assistant .ai-chat-message-content tbody tr:nth-child(2n){background:rgba(0,0,0,.02)}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content tbody tr:nth-child(2n){background:hsla(0,0%,100%,.03)}.ai-chat-suggested-questions{align-self:flex-end;margin:0;padding:16px 0 0;width:100%}.ai-chat-suggested-questions-list{align-items:center;display:flex;flex-wrap:wrap;gap:6px;justify-content:flex-end}.ai-chat-suggested-question{align-items:center;background:transparent;border:1px solid var(--border-default,#d4d4d8);border-radius:var(--radius-preset-badge,18px);color:var(--text-primary,#18181b);cursor:pointer;display:inline-flex;font-size:14px;font-weight:400;gap:6px;justify-content:center;line-height:1.3;max-width:100%;overflow:hidden;padding:8px 14px;text-overflow:ellipsis;transition:background .15s ease,border-color .15s ease,transform .1s ease;white-space:nowrap}.ai-chat-widget.dark .ai-chat-suggested-question{background:transparent;border-color:var(--border-subtle,#52525b);color:var(--text-primary,#fafafa)}.ai-chat-suggested-question-text{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-suggested-question:hover{background:var(--bg-hover,#f4f4f5);border-color:var(--border-default,#d4d4d8)}.ai-chat-widget.dark .ai-chat-suggested-question:hover{background:var(--bg-hover,#3f3f46);border-color:var(--border-subtle,#52525b)}.ai-chat-suggested-question:active{transform:scale(.98)}.ai-chat-suggested-question.action-type{border:none}.ai-chat-suggested-question.action-type,.ai-chat-widget.dark .ai-chat-suggested-question.action-type{background:var(--primary-color,var(--button-color,#ef4444));color:var(--button-icon-color,#fff)}.ai-chat-suggested-question.action-type:hover{background:var(--primary-color,var(--button-color,#ef4444));opacity:.9}.ai-chat-suggested-question-icon{align-items:center;display:flex;flex-shrink:0;justify-content:center}.ai-chat-suggested-question:not(.action-type) .ai-chat-suggested-question-icon{display:none}.ai-chat-follow-up-suggestions{box-sizing:border-box;margin:0;padding:8px 16px 0;width:100%}.ai-chat-follow-up-list{align-items:flex-end;display:flex;flex-direction:column;gap:6px}.ai-chat-follow-up-item{align-items:center;border:none;border-radius:var(--radius-preset-badge,18px);cursor:pointer;display:inline-flex;font-size:14px;font-weight:400;gap:6px;justify-content:center;line-height:1.3;max-width:100%;overflow:hidden;padding:8px 14px;text-overflow:ellipsis;transition:opacity .15s ease,transform .1s ease;white-space:nowrap}.ai-chat-follow-up-item,.ai-chat-widget.dark .ai-chat-follow-up-item{background:var(--primary-color,var(--button-color,#07f));color:var(--button-icon-color,#fff)}.ai-chat-follow-up-item:hover{opacity:.9}.ai-chat-follow-up-item:active{transform:scale(.98)}.ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-default,#d4d4d8);color:var(--text-primary,#18181b)}.ai-chat-widget.dark .ai-chat-follow-up-item.question-type,.dark .ai-chat-follow-up-item.question-type,[data-color-mode=dark] .ai-chat-follow-up-item.question-type,[data-theme=dark] .ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-subtle,#52525b);color:var(--text-primary,#fafafa)}@media (prefers-color-scheme:dark){.ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-subtle,#52525b);color:var(--text-primary,#fafafa)}}.ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#f4f4f5);opacity:1}.ai-chat-widget.dark .ai-chat-follow-up-item.question-type:hover,.dark .ai-chat-follow-up-item.question-type:hover,[data-color-mode=dark] .ai-chat-follow-up-item.question-type:hover,[data-theme=dark] .ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#3f3f46);opacity:1}@media (prefers-color-scheme:dark){.ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#3f3f46);opacity:1}}.ai-chat-follow-up-item.action-type{background:var(--primary-color,var(--button-color,#07f));border:none;color:var(--button-icon-color,#fff)}.ai-chat-follow-up-icon{align-items:center;display:flex;flex-shrink:0;justify-content:center}.ai-chat-follow-up-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-feedback-buttons{align-items:center;display:flex;gap:var(--space-xs)}.ai-chat-feedback{align-items:center;display:inline-flex;gap:0;height:20px}.ai-chat-feedback-button{align-items:center;background:transparent!important;border:none;border-radius:var(--radius-sm);color:var(--text-placeholder);cursor:pointer;display:flex;font-size:var(--text-sm);height:20px;justify-content:center;padding:var(--space-xs);transition:all var(--duration-fast) var(--spring-bounce)}.ai-chat-feedback-button:hover:not(:disabled){background:none!important;color:var(--text-secondary)}.ai-chat-feedback-button:active:not(:disabled){transform:scale(.9)}.ai-chat-feedback-button:disabled{cursor:not-allowed;opacity:.4}.ai-chat-feedback-button.active{background:none!important;color:var(--text-primary)}.ai-chat-feedback.submitted{align-items:center;animation:ai-chat-feedback-morph .3s var(--spring-bounce);gap:var(--space-xs)}.ai-chat-feedback-message{align-items:center;display:flex;gap:4px;margin-left:var(--space-xxs)}.ai-chat-feedback-checkmark{animation:ai-chat-checkmark-pop .3s var(--spring-bounce);color:#10b981;font-size:var(--text-md);font-weight:700}.ai-chat-feedback-text{color:#10b981;font-size:var(--text-xs);font-weight:var(--font-weight-medium)}.ai-chat-history-panel{background:var(--bg-primary,#fff);display:flex;flex:1;flex-direction:column;overflow:hidden}.ai-chat-widget.dark .ai-chat-history-panel{background:var(--bg-primary,#18181b)}.ai-chat-history-empty,.ai-chat-history-loading{align-items:center;color:var(--text-muted);display:flex;flex:1;font-size:var(--text-sm);justify-content:center;padding:var(--space-lg);text-align:center}.ai-chat-history-list{-ms-overflow-style:none;display:flex;flex:1;flex-direction:column;gap:var(--space-sm);overflow-y:auto;padding:var(--space-xs) var(--space-md) 120px;scrollbar-width:none}.ai-chat-history-list::-webkit-scrollbar{display:none}.ai-chat-history-list.exiting{animation:ai-chat-history-exit .22s var(--spring-smooth) forwards}.ai-chat-history-item{align-items:center;background:var(--user-bg,#f4f4f5);border-radius:var(--radius-history-item,15px);display:flex;flex:0 0 auto;flex-direction:row;height:var(--history-item-height,36px);margin:0;overflow:hidden;transition:background var(--duration-fast,.15s) ease;width:100%}.ai-chat-history-item-content{align-items:center;background:transparent;border:none;cursor:pointer;display:flex;flex:1;flex-direction:row;height:100%;min-width:0;padding:0 var(--space-xs,4px) 0 var(--space-md,16px);text-align:left}.ai-chat-widget.dark .ai-chat-history-item{background:var(--user-bg,#27272a)}.ai-chat-history-item:hover{background:var(--user-bg-hover,#e5e7eb)}.ai-chat-widget.dark .ai-chat-history-item:hover{background:var(--user-bg-hover,#3f3f46)}.ai-chat-history-item.active{background:var(--user-bg-hover,#e5e7eb)}.ai-chat-widget.dark .ai-chat-history-item.active{background:var(--user-bg-hover,#3f3f46)}.ai-chat-history-item-preview{color:var(--text-primary,#18181b);flex:1;font-size:var(--text-sm,14px);font-weight:var(--font-weight-medium,500);line-height:var(--line-height-normal,1.4);margin-bottom:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-widget.dark .ai-chat-history-item-preview{color:var(--text-primary,#fafafa)}.ai-chat-history-item.active .ai-chat-history-item-preview{font-weight:var(--font-weight-medium)}.ai-chat-history-item-meta{display:none}.ai-chat-history-item-delete{align-items:center;background:transparent;border:none;border-radius:var(--radius-sm,6px);color:var(--text-muted,#71717a);cursor:pointer;display:flex;flex-shrink:0;height:24px;justify-content:center;margin-left:auto;margin-right:var(--space-xs,4px);opacity:0;transition:opacity var(--duration-fast,.15s) ease,background var(--duration-fast,.15s) ease,color var(--duration-fast,.15s) ease;width:24px}.ai-chat-history-item-delete svg{height:14px;width:14px}.ai-chat-history-item:hover .ai-chat-history-item-delete{opacity:1}.ai-chat-history-item-delete:hover{background:rgba(239,68,68,.1);color:#ef4444}.ai-chat-widget.dark .ai-chat-history-item-delete:hover{background:rgba(239,68,68,.2);color:#f87171}.ai-chat-tool-row{align-items:center;display:flex;gap:10px;margin:2px 0;padding:0}.ai-chat-tool-gear{color:#1f2937;flex-shrink:0;height:20px;width:20px}.ai-chat-tool-gear.spinning{animation:ai-chat-gear-spin 1.5s linear infinite}.ai-chat-tool-badges{align-items:center;display:flex;flex-wrap:wrap;gap:8px}.ai-chat-tool-badge{align-items:center;background:#e5e7eb;border:1px solid #d1d5db;border-radius:var(--radius-action-badge,8px);color:#1f2937;display:inline-flex;font-size:12px;font-weight:500;gap:4px;line-height:1.2;padding:5px 12px;transition:all .2s ease;white-space:nowrap}.ai-chat-tool-badge.loading{animation:ai-chat-tool-gradient 2s linear infinite;background:linear-gradient(90deg,var(--tool-loading-bg-1,#e0e0e0) 0,var(--tool-loading-bg-2,#f0f0f0) 25%,var(--tool-loading-bg-3,#fff) 50%,var(--tool-loading-bg-2,#f0f0f0) 75%,var(--tool-loading-bg-1,#e0e0e0) 100%);background-size:200% 100%;color:var(--tool-loading-text,#1a1a1a);position:relative}.ai-chat-widget:not(.dark) .ai-chat-tool-badge.loading{--tool-loading-bg-1:#2a2a2a;--tool-loading-bg-2:#3a3a3a;--tool-loading-bg-3:#4a4a4a;--tool-loading-text:#fff}.ai-chat-tool-badge.completed{background:#e5e7eb;border:1px solid #d1d5db;color:#1f2937}.ai-chat-widget.dark .ai-chat-tool-badge,.ai-chat-widget[data-theme=dark] .ai-chat-tool-badge,.chakra-ui-dark .ai-chat-tool-badge,.dark .ai-chat-tool-badge,[data-theme=dark] .ai-chat-tool-badge,html.dark .ai-chat-tool-badge{background:hsla(0,0%,100%,.12);border:1px solid hsla(0,0%,100%,.2);color:hsla(0,0%,100%,.9)}.ai-chat-widget.dark .ai-chat-tool-gear,.ai-chat-widget[data-theme=dark] .ai-chat-tool-gear,.chakra-ui-dark .ai-chat-tool-gear,.dark .ai-chat-tool-gear,[data-theme=dark] .ai-chat-tool-gear,html.dark .ai-chat-tool-gear{color:#fff}.ai-chat-tool-badge.error{background:var(--tool-error-bg,rgba(239,68,68,.15));color:var(--tool-error-text,#ef4444)}.ai-chat-tool-badge .ai-chat-tool-check{color:#fff;flex-shrink:0}.ai-chat-tool-badge .ai-chat-tool-error{color:#ef4444;flex-shrink:0}.tool-name{font-weight:500;line-height:1.2;white-space:nowrap}.ai-chat-tool-action{box-sizing:border-box;padding:0;width:100%}@keyframes ai-chat-skeleton-pulse{0%,to{opacity:.4}50%{opacity:.7}}.ai-chat-action-skeleton-item{animation:ai-chat-skeleton-pulse 1.5s ease-in-out infinite;background:var(--bg-secondary,#e5e7eb)}.ai-chat-widget.dark .ai-chat-action-skeleton-item,.chakra-ui-dark .ai-chat-action-skeleton-item,.dark .ai-chat-action-skeleton-item,[data-theme=dark] .ai-chat-action-skeleton-item{background:hsla(0,0%,100%,.1)}.ai-chat-action-skeleton-content{display:flex;flex-direction:column;gap:16px}.ai-chat-action-skeleton-header{align-items:center;display:flex;gap:10px}.ai-chat-action-skeleton-box{background:rgba(0,0,0,.08);border-radius:10px;display:flex;flex-direction:column;gap:8px;padding:14px}.ai-chat-widget.dark .ai-chat-action-skeleton-box,.chakra-ui-dark .ai-chat-action-skeleton-box,.dark .ai-chat-action-skeleton-box,[data-theme=dark] .ai-chat-action-skeleton-box{background:rgba(0,0,0,.25)}.ai-chat-action-card{--action-accent:var(--primary-color,#3b82f6);background:var(--bg-secondary,#f9fafb);border:1px solid var(--border-subtle,rgba(0,0,0,.06));border-radius:12px;box-sizing:border-box;margin-top:4px;padding:16px;transition:all .2s ease;width:100%}.ai-chat-widget.dark .ai-chat-action-card,.chakra-ui-dark .ai-chat-action-card,.dark .ai-chat-action-card,[data-theme=dark] .ai-chat-action-card{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1)}.ai-chat-action-booked{background:var(--bg-secondary,#f9fafb);border:1px solid var(--border-subtle,rgba(0,0,0,.06))}.ai-chat-widget.dark .ai-chat-action-booked,.chakra-ui-dark .ai-chat-action-booked,.dark .ai-chat-action-booked,[data-theme=dark] .ai-chat-action-booked{background:var(--bg-secondary,#3a3a3a)}.ai-chat-action-header{align-items:center;color:var(--text-primary,#3e3e3e);display:flex;font-size:var(--text-md,15px);font-weight:var(--font-weight-semibold,600);gap:var(--space-sm,8px);margin-bottom:var(--space-md,16px)}.ai-chat-widget.dark .ai-chat-action-header,.chakra-ui-dark .ai-chat-action-header,.dark .ai-chat-action-header,[data-theme=dark] .ai-chat-action-header{color:var(--text-primary,#fff)}.ai-chat-action-icon{color:var(--action-accent,var(--primary-color,#3b82f6));flex-shrink:0;height:20px;width:20px}.ai-chat-action-success-icon-wrapper{align-items:center;background:var(--action-accent,var(--primary-color,#22c55e));border-radius:50%;color:#fff;display:flex;flex-shrink:0;height:24px;justify-content:center;width:24px}.ai-chat-action-icon-success{color:currentColor;height:14px;width:14px}.ai-chat-action-detail-box{background:var(--bg-primary,#fff);border:1px solid var(--border-subtle,rgba(0,0,0,.08));border-radius:var(--radius-md,8px);display:flex;flex-direction:column;gap:4px;padding:12px 16px}.ai-chat-widget.dark .ai-chat-action-detail-box,.chakra-ui-dark .ai-chat-action-detail-box,.dark .ai-chat-action-detail-box,[data-theme=dark] .ai-chat-action-detail-box{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.05)}.ai-chat-action-label-small{color:var(--text-muted,#71717a);font-size:11px;font-weight:600;letter-spacing:.5px;text-transform:uppercase}.ai-chat-action-value-large{color:var(--text-primary,#3e3e3e);font-size:15px;font-weight:500}.ai-chat-widget.dark .ai-chat-action-value-large,.chakra-ui-dark .ai-chat-action-value-large,.dark .ai-chat-action-value-large,[data-theme=dark] .ai-chat-action-value-large{color:#fff}.ai-chat-action-body{display:flex;flex-direction:column;gap:var(--space-md,16px)}.ai-chat-action-close-btn{align-items:center;background:transparent;border:none;border-radius:6px;color:var(--ai-chat-fg-muted,#6b7280);cursor:pointer;display:flex;height:28px;justify-content:center;padding:0;position:absolute;right:12px;top:12px;transition:all .15s ease;width:28px;z-index:10}.ai-chat-action-close-btn:hover{background:var(--ai-chat-bg-muted,#f3f4f6);color:var(--ai-chat-fg,#1f2937)}.ai-chat-action-close-btn:active{transform:scale(.95)}.ai-chat-action-close-btn:focus-visible{outline:2px solid var(--ai-chat-accent,#2563eb);outline-offset:2px}.ai-chat-action-card--closable,.ai-chat-form-card--closable{position:relative}.ai-chat-action-card--closable .ai-chat-action-header,.ai-chat-form-card--closable .ai-chat-form-card__header{padding-right:40px}.ai-chat-widget.dark .ai-chat-action-close-btn:hover,.chakra-ui-dark .ai-chat-action-close-btn:hover,.dark .ai-chat-action-close-btn:hover,[data-theme=dark] .ai-chat-action-close-btn:hover{background:hsla(0,0%,100%,.1);color:var(--ai-chat-fg,#f3f4f6)}.ai-chat-action-field{display:flex;flex-direction:column;gap:var(--space-xs,6px)}.ai-chat-action-label{color:var(--text-secondary,#6b7280);font-size:var(--text-sm,13px);font-weight:var(--font-weight-medium,500)}.ai-chat-widget.dark .ai-chat-action-label,.chakra-ui-dark .ai-chat-action-label,.dark .ai-chat-action-label,[data-theme=dark] .ai-chat-action-label{color:var(--text-secondary,#a1a1aa)}.ai-chat-action-input{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);color:var(--text-primary,#3e3e3e);font-size:var(--text-sm,13px);outline:none;padding:10px 12px;transition:border-color .2s ease,box-shadow .2s ease}.ai-chat-action-input:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.1)}.ai-chat-action-input::placeholder{color:var(--text-muted,#9ca3af)}.ai-chat-widget.dark .ai-chat-action-input,.chakra-ui-dark .ai-chat-action-input,.dark .ai-chat-action-input,[data-theme=dark] .ai-chat-action-input{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-action-input:focus,.chakra-ui-dark .ai-chat-action-input:focus,.dark .ai-chat-action-input:focus,[data-theme=dark] .ai-chat-action-input:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.2)}.ai-chat-action-button{background:var(--action-accent,var(--primary-color,#3b82f6));border:none;border-radius:9999px;color:#fff;cursor:pointer;font-size:var(--text-sm,13px);font-weight:var(--font-weight-semibold,600);padding:12px 16px;transition:all .2s ease;width:100%}.ai-chat-action-button:hover:not(:disabled){opacity:.9;transform:translateY(-1px)}.ai-chat-action-button:disabled{cursor:not-allowed;opacity:.5}.ai-chat-action-link-button{align-items:center;background:var(--action-accent,var(--primary-color,#3b82f6));border:none;border-radius:9999px;box-sizing:border-box;color:#fff;display:flex;font-size:14px;font-weight:600;gap:6px;justify-content:center;margin-top:8px;padding:12px;text-decoration:none;transition:all .2s ease;width:100%}.ai-chat-action-link-button:hover{opacity:.9;transform:translateY(-1px)}.ai-chat-action-error{background:rgba(239,68,68,.1);border-radius:var(--radius-md,8px);color:#dc2626;font-size:var(--text-sm,13px);padding:10px 12px}.ai-chat-widget.dark .ai-chat-action-error,.chakra-ui-dark .ai-chat-action-error,.dark .ai-chat-action-error,[data-theme=dark] .ai-chat-action-error{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-action-hint{color:var(--text-muted,#9ca3af);font-size:var(--text-sm,13px);padding:var(--space-sm,8px);text-align:center}.ai-chat-action-date-grid{display:grid;gap:var(--space-xs,6px);grid-template-columns:repeat(auto-fill,minmax(90px,1fr))}.ai-chat-action-date-btn{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);color:var(--text-primary,#3e3e3e);cursor:pointer;font-size:var(--text-xs,12px);font-weight:var(--font-weight-medium,500);padding:8px 10px;text-align:center;transition:all .15s ease}.ai-chat-action-date-btn:hover{background:rgba(59,130,246,.05);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-action-date-btn.active{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-widget.dark .ai-chat-action-date-btn,.chakra-ui-dark .ai-chat-action-date-btn,.dark .ai-chat-action-date-btn,[data-theme=dark] .ai-chat-action-date-btn{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-action-date-btn:hover,.chakra-ui-dark .ai-chat-action-date-btn:hover,.dark .ai-chat-action-date-btn:hover,[data-theme=dark] .ai-chat-action-date-btn:hover{background:rgba(59,130,246,.15);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-action-date-btn.active,.chakra-ui-dark .ai-chat-action-date-btn.active,.dark .ai-chat-action-date-btn.active,[data-theme=dark] .ai-chat-action-date-btn.active{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-action-time-grid{display:grid;gap:var(--space-xs,6px);grid-template-columns:repeat(auto-fill,minmax(100px,1fr))}.ai-chat-action-time-btn{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);color:var(--text-primary,#3e3e3e);cursor:pointer;font-size:var(--text-xs,12px);font-weight:var(--font-weight-medium,500);padding:8px 10px;text-align:center;transition:all .15s ease}.ai-chat-action-time-btn:hover{background:rgba(59,130,246,.05);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-action-time-btn.active{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-widget.dark .ai-chat-action-time-btn,.chakra-ui-dark .ai-chat-action-time-btn,.dark .ai-chat-action-time-btn,[data-theme=dark] .ai-chat-action-time-btn{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-action-time-btn:hover,.chakra-ui-dark .ai-chat-action-time-btn:hover,.dark .ai-chat-action-time-btn:hover,[data-theme=dark] .ai-chat-action-time-btn:hover{background:rgba(59,130,246,.15);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-action-time-btn.active,.chakra-ui-dark .ai-chat-action-time-btn.active,.dark .ai-chat-action-time-btn.active,[data-theme=dark] .ai-chat-action-time-btn.active{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-link-preview{--action-accent:var(--primary-color,#3b82f6);background:var(--bg-secondary,#f4f4f4);border:1px solid var(--border-subtle,rgba(0,0,0,.08));border-radius:var(--radius-lg,12px);cursor:pointer;display:flex;flex-direction:column;margin-top:4px;overflow:hidden;padding:0!important;position:relative;transition:border-color .2s,box-shadow .2s,transform .2s}.ai-chat-link-preview:hover{border-color:var(--action-accent);box-shadow:0 2px 8px rgba(0,0,0,.1);transform:translateY(-1px)}.ai-chat-link-preview:focus{border-color:var(--action-accent);box-shadow:0 0 0 2px rgba(59,130,246,.2);outline:none}.ai-chat-widget.dark .ai-chat-link-preview,.chakra-ui-dark .ai-chat-link-preview,.dark .ai-chat-link-preview,[data-theme=dark] .ai-chat-link-preview{background:var(--bg-secondary,#3a3a3a);border-color:hsla(0,0%,100%,.08)}.ai-chat-widget.dark .ai-chat-link-preview:hover,.chakra-ui-dark .ai-chat-link-preview:hover,.dark .ai-chat-link-preview:hover,[data-theme=dark] .ai-chat-link-preview:hover{border-color:var(--action-accent);box-shadow:0 2px 12px rgba(0,0,0,.3)}.ai-chat-link-preview__image{aspect-ratio:1.91/1;background:var(--bg-muted,#e5e7eb);overflow:hidden;width:100%}.ai-chat-widget.dark .ai-chat-link-preview__image,.chakra-ui-dark .ai-chat-link-preview__image,.dark .ai-chat-link-preview__image,[data-theme=dark] .ai-chat-link-preview__image{background:hsla(0,0%,100%,.05)}.ai-chat-link-preview__image img{height:100%;object-fit:cover;width:100%}.ai-chat-link-preview__content{flex:1;padding:8px 10px}.ai-chat-link-preview__site{align-items:center;display:flex;gap:6px;margin-bottom:6px}.ai-chat-link-preview__favicon{border-radius:2px;flex-shrink:0;height:16px;width:16px}.ai-chat-link-preview__domain{color:var(--text-muted,#71717a);font-size:12px;letter-spacing:.5px;overflow:hidden;text-overflow:ellipsis;text-transform:uppercase;white-space:nowrap}.ai-chat-link-preview__title{-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;color:var(--text-primary,#3e3e3e);display:-webkit-box;font-size:15px;font-weight:600;line-height:1.3;margin:0 0 4px;overflow:hidden}.ai-chat-widget.dark .ai-chat-link-preview__title,.chakra-ui-dark .ai-chat-link-preview__title,.dark .ai-chat-link-preview__title,[data-theme=dark] .ai-chat-link-preview__title{color:#fff}.ai-chat-link-preview__description{-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;color:var(--text-muted,#71717a);display:-webkit-box;font-size:13px;line-height:1.4;margin:0;overflow:hidden}.ai-chat-link-preview__context{border-top:1px solid var(--border-subtle,rgba(0,0,0,.08));color:var(--text-muted,#71717a);font-size:12px;font-style:italic;margin:8px 0 0;padding-top:8px}.ai-chat-widget.dark .ai-chat-link-preview__context,.chakra-ui-dark .ai-chat-link-preview__context,.dark .ai-chat-link-preview__context,[data-theme=dark] .ai-chat-link-preview__context{border-color:hsla(0,0%,100%,.08)}.ai-chat-link-preview__arrow{align-items:center;background:var(--bg-primary,#fff);border-radius:50%;box-shadow:0 1px 3px rgba(0,0,0,.1);color:var(--text-muted,#71717a);display:flex;height:28px;justify-content:center;opacity:0;position:absolute;right:12px;top:12px;transition:opacity .2s,background .2s;width:28px}.ai-chat-link-preview:hover .ai-chat-link-preview__arrow{opacity:1}.ai-chat-widget.dark .ai-chat-link-preview__arrow,.chakra-ui-dark .ai-chat-link-preview__arrow,.dark .ai-chat-link-preview__arrow,[data-theme=dark] .ai-chat-link-preview__arrow{background:hsla(0,0%,100%,.1);color:#fff}.ai-chat-link-preview--error{border-color:rgba(239,68,68,.3)}.ai-chat-link-preview--error:hover{border-color:rgba(239,68,68,.5)}.ai-chat-link-preview__error-text{color:#dc2626;font-size:12px;margin:4px 0 0}.ai-chat-widget.dark .ai-chat-link-preview__error-text,.chakra-ui-dark .ai-chat-link-preview__error-text,.dark .ai-chat-link-preview__error-text,[data-theme=dark] .ai-chat-link-preview__error-text{color:#fca5a5}.ai-chat-video-player{--action-accent:var(--primary-color,#3b82f6);background:var(--bg-secondary,#f4f4f4);border-radius:var(--radius-lg,12px);display:flex;flex-direction:column;gap:0;margin-top:4px;overflow:hidden;padding:0!important}.ai-chat-widget.dark .ai-chat-video-player,.chakra-ui-dark .ai-chat-video-player,.dark .ai-chat-video-player,[data-theme=dark] .ai-chat-video-player{background:var(--bg-secondary,#3a3a3a)}.ai-chat-video-player__header{align-items:center;color:var(--action-accent,var(--primary-color,#3b82f6));display:flex;gap:8px}.ai-chat-video-player__title{color:var(--text-primary,#3e3e3e);font-size:14px;font-weight:600}.ai-chat-widget.dark .ai-chat-video-player__title,.chakra-ui-dark .ai-chat-video-player__title,.dark .ai-chat-video-player__title,[data-theme=dark] .ai-chat-video-player__title{color:#fff}.ai-chat-video-player__container{aspect-ratio:16/9;background:#000;border-radius:8px;overflow:hidden;position:relative;width:100%}.ai-chat-video-player__thumbnail{cursor:pointer;height:100%;position:relative;width:100%}.ai-chat-video-player__thumbnail img{height:100%;object-fit:cover;width:100%}.ai-chat-video-player__placeholder{align-items:center;background:linear-gradient(135deg,#1a1a2e,#16213e);cursor:pointer;display:flex;flex-direction:column;gap:8px;height:100%;justify-content:center;position:relative;width:100%}.ai-chat-video-player__click-text{color:hsla(0,0%,100%,.7);font-size:13px}.ai-chat-video-player__play-btn{align-items:center;background:rgba(0,0,0,.7);border:none;border-radius:50%;color:#fff;cursor:pointer;display:flex;height:64px;justify-content:center;left:50%;position:absolute;top:50%;transform:translate(-50%,-50%);transition:background .2s,transform .2s;width:64px}.ai-chat-video-player__placeholder .ai-chat-video-player__play-btn{left:auto;position:relative;top:auto;transform:none}.ai-chat-video-player__play-btn:hover{background:rgba(0,0,0,.9);transform:translate(-50%,-50%) scale(1.05)}.ai-chat-video-player__placeholder .ai-chat-video-player__play-btn:hover{transform:scale(1.05)}.ai-chat-video-player__provider-badge{background:rgba(0,0,0,.8);border-radius:4px;bottom:8px;color:#fff;font-size:11px;font-weight:600;letter-spacing:.5px;padding:4px 8px;position:absolute;right:8px;text-transform:uppercase}.ai-chat-video-player__iframe,.ai-chat-video-player__video{border:none;height:100%;left:0;position:absolute;top:0;width:100%}.ai-chat-video-player__error{align-items:center;background:rgba(239,68,68,.1);color:#dc2626;display:flex;font-size:13px;height:100%;justify-content:center;padding:16px;text-align:center;width:100%}.ai-chat-widget.dark .ai-chat-video-player__error,.chakra-ui-dark .ai-chat-video-player__error,.dark .ai-chat-video-player__error,[data-theme=dark] .ai-chat-video-player__error{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-video-player__context{color:var(--text-muted,#71717a);font-size:12px;font-style:italic;margin-top:4px;padding:8px 12px 12px}.ai-chat-location-card{background:var(--bg-secondary,#fff);border:1px solid var(--border-subtle,rgba(0,0,0,.08));border-radius:12px;overflow:hidden;padding:0}.ai-chat-widget.dark .ai-chat-location-card,.chakra-ui-dark .ai-chat-location-card,.dark .ai-chat-location-card,[data-theme=dark] .ai-chat-location-card{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1)}.ai-chat-location-card--compact{border-radius:10px}.ai-chat-location-card--error{color:var(--text-muted,#71717a);padding:16px;text-align:center}.ai-chat-location-card__map{background:var(--bg-muted,#f4f4f5);position:relative;width:100%}.ai-chat-widget.dark .ai-chat-location-card__map,.chakra-ui-dark .ai-chat-location-card__map,.dark .ai-chat-location-card__map,[data-theme=dark] .ai-chat-location-card__map{background:rgba(0,0,0,.2)}.ai-chat-location-card__map iframe{border:none;display:block;height:100%;width:100%}.ai-chat-location-card__content{padding:12px}.ai-chat-location-card--compact .ai-chat-location-card__content{padding:10px}.ai-chat-location-card__header{align-items:center;display:flex;flex-wrap:wrap;gap:8px;margin-bottom:8px}.ai-chat-location-card__name{color:var(--text-primary,#18181b);flex:1;font-size:16px;font-weight:600;margin:0;min-width:0}.ai-chat-widget.dark .ai-chat-location-card__name,.chakra-ui-dark .ai-chat-location-card__name,.dark .ai-chat-location-card__name,[data-theme=dark] .ai-chat-location-card__name{color:#fff}.ai-chat-location-card--compact .ai-chat-location-card__name{font-size:14px}.ai-chat-location-card__type{background:var(--bg-muted,#f4f4f5);border-radius:10px;color:var(--text-muted,#71717a);font-size:11px;font-weight:500;letter-spacing:.5px;padding:2px 8px;text-transform:uppercase}.ai-chat-widget.dark .ai-chat-location-card__type,.chakra-ui-dark .ai-chat-location-card__type,.dark .ai-chat-location-card__type,[data-theme=dark] .ai-chat-location-card__type{background:hsla(0,0%,100%,.1);color:hsla(0,0%,100%,.7)}.ai-chat-location-card__status{border-radius:12px;font-size:12px;font-weight:500;padding:2px 8px}.ai-chat-location-card__status--open{background:#dcfce7;color:#16a34a}.ai-chat-location-card__status--closed{background:#fef2f2;color:#dc2626}.ai-chat-widget.dark .ai-chat-location-card__status--open,.chakra-ui-dark .ai-chat-location-card__status--open,.dark .ai-chat-location-card__status--open,[data-theme=dark] .ai-chat-location-card__status--open{background:rgba(34,197,94,.2);color:#4ade80}.ai-chat-widget.dark .ai-chat-location-card__status--closed,.chakra-ui-dark .ai-chat-location-card__status--closed,.dark .ai-chat-location-card__status--closed,[data-theme=dark] .ai-chat-location-card__status--closed{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-location-card__address{align-items:flex-start;color:var(--text-muted,#71717a);display:flex;font-size:13px;gap:6px;line-height:1.4;margin:0 0 8px}.ai-chat-location-card__address svg{flex-shrink:0;margin-top:2px}.ai-chat-location-card__description{color:var(--text-muted,#71717a);font-size:13px;line-height:1.4;margin:0 0 8px}.ai-chat-location-card__hours{align-items:flex-start;color:var(--text-muted,#71717a);display:flex;font-size:13px;gap:6px;margin-bottom:8px}.ai-chat-location-card__hours svg{flex-shrink:0;margin-top:2px}.ai-chat-location-card__hours-list{flex:1}.ai-chat-location-card__hours-toggle{align-items:center;background:none;border:none;color:inherit;cursor:pointer;display:flex;font:inherit;gap:4px;padding:0}.ai-chat-location-card__hours-toggle:hover{text-decoration:underline}.ai-chat-location-card__hours-full{list-style:none;margin:8px 0 0;padding:0}.ai-chat-location-card__hours-full li{display:flex;font-size:12px;justify-content:space-between;padding:4px 0}.ai-chat-location-card__hours-today{color:var(--text-primary,#18181b);font-weight:600}.ai-chat-widget.dark .ai-chat-location-card__hours-today,.chakra-ui-dark .ai-chat-location-card__hours-today,.dark .ai-chat-location-card__hours-today,[data-theme=dark] .ai-chat-location-card__hours-today{color:#fff}.ai-chat-location-card__phone{align-items:center;background:none;border:none;color:var(--action-accent,#3b82f6);cursor:pointer;display:flex;font-size:13px;gap:6px;margin-bottom:12px;padding:0}.ai-chat-location-card__phone:hover{text-decoration:underline}.ai-chat-location-card__actions{display:flex;gap:8px;justify-content:flex-start;width:100%}.ai-chat-location-card__button{align-items:center;background:var(--action-accent,#3b82f6);border:none;border-radius:20px;color:#fff;cursor:pointer;display:flex;flex:1;font-size:13px;font-weight:500;gap:6px;justify-content:center;padding:10px 16px;transition:opacity .2s}.ai-chat-location-card__button:hover{opacity:.9}.ai-chat-location-card--compact .ai-chat-location-card__button{font-size:12px;padding:8px 12px}.ai-chat-location-card__link{align-items:center;background:var(--bg-secondary,#fff);border:1px solid var(--border-subtle,rgba(0,0,0,.08));border-radius:20px;color:var(--text-primary,#18181b);display:flex;font-size:13px;gap:6px;padding:10px 16px;text-decoration:none;transition:border-color .2s}.ai-chat-widget.dark .ai-chat-location-card__link,.chakra-ui-dark .ai-chat-location-card__link,.dark .ai-chat-location-card__link,[data-theme=dark] .ai-chat-location-card__link{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-location-card__link:hover{border-color:var(--action-accent,#3b82f6)}.ai-chat-location-card-list{display:flex;flex-direction:column;gap:8px}.ai-chat-location-card-list__header{align-items:center;color:var(--text-muted,#71717a);display:flex;font-size:13px;font-weight:500;gap:6px;margin-bottom:4px;padding:0 4px}.ai-chat-location-card-list__stack{display:grid;gap:12px;grid-template-columns:1fr}.ai-chat-location-card-list__stack--cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.ai-chat-location-card-list__stack--cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}@media (max-width:1000px){.ai-chat-location-card-list__stack--cols-3{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (max-width:640px){.ai-chat-location-card-list__stack--cols-2,.ai-chat-location-card-list__stack--cols-3{grid-template-columns:1fr}}.ai-chat-location-card-list__grid{display:grid;gap:8px;grid-template-columns:repeat(2,1fr)}@media (max-width:400px){.ai-chat-location-card-list__grid{grid-template-columns:1fr}}.ai-chat-location-card-list__carousel{-webkit-overflow-scrolling:touch;-ms-overflow-style:none;display:flex;gap:8px;overflow-x:auto;padding-bottom:4px;scroll-snap-type:x mandatory;scrollbar-width:none}.ai-chat-location-card-list__carousel::-webkit-scrollbar{display:none}.ai-chat-location-card-list__carousel>.ai-chat-location-card{flex:0 0 280px;scroll-snap-align:start}.ai-chat-contact-card{background:#fff;border:1px solid rgba(0,0,0,.08);border-radius:16px;overflow:hidden;padding:0;position:relative}.ai-chat-widget.dark .ai-chat-contact-card,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card,.chakra-ui-dark .ai-chat-contact-card,.dark .ai-chat-contact-card,[data-theme=dark] .ai-chat-contact-card,html.dark .ai-chat-contact-card{background:#4a4a4a;border-color:hsla(0,0%,100%,.08)}.ai-chat-contact-card-list{gap:12px;width:100%}.ai-chat-contact-card--compact{border-radius:12px}.ai-chat-contact-card--empty{align-items:center;background:var(--bg-secondary,#f4f4f5);display:flex;flex-direction:column;gap:8px;justify-content:center;padding:24px 16px;text-align:center}.ai-chat-widget.dark .ai-chat-contact-card--empty,.chakra-ui-dark .ai-chat-contact-card--empty,.dark .ai-chat-contact-card--empty,[data-theme=dark] .ai-chat-contact-card--empty{background:#3a3a3a}.ai-chat-contact-card__empty-icon{color:var(--text-muted,#71717a);opacity:.6}.ai-chat-contact-card__empty-text{color:var(--text-muted,#71717a);font-size:14px;margin:0}.ai-chat-contact-card--vertical{display:flex;flex-direction:column}.ai-chat-contact-card--vertical .ai-chat-contact-card__image-section{aspect-ratio:3/2;overflow:hidden;width:100%}.ai-chat-contact-card--vertical .ai-chat-contact-card__image{height:100%;object-fit:cover;width:100%}.ai-chat-contact-card--vertical .ai-chat-contact-card__image-placeholder{align-items:center;background:linear-gradient(135deg,#5a5a5a,#3a3a3a);color:hsla(0,0%,100%,.5);display:flex;height:100%;justify-content:center;width:100%}.ai-chat-contact-card--vertical .ai-chat-contact-card__image-placeholder svg{height:48px;width:48px}.ai-chat-contact-card--vertical .ai-chat-contact-card__info{padding:16px;text-align:center}.ai-chat-contact-card--horizontal{display:flex;flex-direction:row}.ai-chat-contact-card--horizontal .ai-chat-contact-card__image-section{height:160px;min-width:140px;overflow:hidden;width:140px}.ai-chat-contact-card--horizontal.ai-chat-contact-card--compact .ai-chat-contact-card__image-section{height:120px;min-width:100px;width:100px}.ai-chat-contact-card--horizontal .ai-chat-contact-card__image{height:100%;object-fit:cover;width:100%}.ai-chat-contact-card--horizontal .ai-chat-contact-card__image-placeholder{align-items:center;background:linear-gradient(135deg,#5a5a5a,#3a3a3a);color:hsla(0,0%,100%,.5);display:flex;height:100%;justify-content:center;width:100%}.ai-chat-contact-card--horizontal .ai-chat-contact-card__image-placeholder svg{height:36px;width:36px}.ai-chat-contact-card--horizontal .ai-chat-contact-card__info{display:flex;flex:1;flex-direction:column;justify-content:center;padding:16px}.ai-chat-contact-card__name{color:var(--action-accent,#ef4444);font-size:18px;font-weight:600;line-height:1.3;margin:0}.ai-chat-contact-card--compact .ai-chat-contact-card__name{font-size:15px}.ai-chat-contact-card__role{color:rgba(0,0,0,.7);font-size:14px;font-weight:400;margin:2px 0 0}.ai-chat-widget.dark .ai-chat-contact-card__role,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card__role,.chakra-ui-dark .ai-chat-contact-card__role,.dark .ai-chat-contact-card__role,[data-theme=dark] .ai-chat-contact-card__role,html.dark .ai-chat-contact-card__role{color:hsla(0,0%,100%,.9)}.ai-chat-contact-card--compact .ai-chat-contact-card__role{font-size:13px}.ai-chat-contact-card__details{display:flex;flex-direction:column;gap:2px;margin-top:12px}.ai-chat-contact-card__detail{color:rgba(0,0,0,.6);display:block;font-size:14px;line-height:1.5;margin:0;text-decoration:none}.ai-chat-contact-card__detail:hover{color:#000;text-decoration:underline}.ai-chat-widget.dark .ai-chat-contact-card__detail,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card__detail,.chakra-ui-dark .ai-chat-contact-card__detail,.dark .ai-chat-contact-card__detail,[data-theme=dark] .ai-chat-contact-card__detail,html.dark .ai-chat-contact-card__detail{color:hsla(0,0%,100%,.7)}.ai-chat-widget.dark .ai-chat-contact-card__detail:hover,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card__detail:hover,.chakra-ui-dark .ai-chat-contact-card__detail:hover,.dark .ai-chat-contact-card__detail:hover,[data-theme=dark] .ai-chat-contact-card__detail:hover,html.dark .ai-chat-contact-card__detail:hover{color:#fff}.ai-chat-contact-card--compact .ai-chat-contact-card__detail{font-size:13px}.ai-chat-contact-card__responsibilities{display:flex;flex-wrap:wrap;gap:4px;margin-top:8px}.ai-chat-contact-card__responsibility-tag{background:rgba(0,0,0,.08);border-radius:10px;color:rgba(0,0,0,.8);font-size:11px;font-weight:500;padding:3px 10px}.ai-chat-widget.dark .ai-chat-contact-card__responsibility-tag,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card__responsibility-tag,.chakra-ui-dark .ai-chat-contact-card__responsibility-tag,.dark .ai-chat-contact-card__responsibility-tag,[data-theme=dark] .ai-chat-contact-card__responsibility-tag,html.dark .ai-chat-contact-card__responsibility-tag{background:hsla(0,0%,100%,.15);color:hsla(0,0%,100%,.9)}.ai-chat-contact-card__responsibility-more{color:rgba(0,0,0,.5);font-size:11px;padding:3px 4px}.ai-chat-widget.dark .ai-chat-contact-card__responsibility-more,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card__responsibility-more,.chakra-ui-dark .ai-chat-contact-card__responsibility-more,.dark .ai-chat-contact-card__responsibility-more,[data-theme=dark] .ai-chat-contact-card__responsibility-more,html.dark .ai-chat-contact-card__responsibility-more{color:hsla(0,0%,100%,.5)}.ai-chat-contact-card__actions{display:flex;gap:8px;padding:0 12px 12px}.ai-chat-contact-card--compact .ai-chat-contact-card__actions{gap:6px;padding:0 10px 10px}.ai-chat-contact-card__button{align-items:center;border:none;border-radius:9999px;cursor:pointer;display:flex;font-size:14px;font-weight:600;gap:8px;justify-content:center;padding:12px 20px;transition:all .15s ease;white-space:nowrap}.ai-chat-contact-card--compact .ai-chat-contact-card__button{font-size:13px;padding:10px 16px}.ai-chat-contact-card__button:hover{box-shadow:0 4px 12px rgba(0,0,0,.15);transform:translateY(-1px)}.ai-chat-contact-card__button:active{transform:translateY(0)}.ai-chat-contact-card__button--primary{background:var(--action-accent,#3b82f6);color:#fff;flex:1}.ai-chat-contact-card__button--primary:hover{background:color-mix(in srgb,var(--action-accent,#3b82f6) 90%,#000)}.ai-chat-contact-card__button--secondary{background:var(--bg-muted,#f4f4f5);border:1px solid var(--border-subtle,rgba(0,0,0,.08));color:var(--text-primary,#18181b);flex:1}.ai-chat-contact-card__button--secondary:hover{background:var(--bg-hover,#e4e4e7)}.ai-chat-widget.dark .ai-chat-contact-card__button--secondary,.chakra-ui-dark .ai-chat-contact-card__button--secondary,.dark .ai-chat-contact-card__button--secondary,[data-theme=dark] .ai-chat-contact-card__button--secondary{background:hsla(0,0%,100%,.1);border-color:hsla(0,0%,100%,.15);color:#fff}.ai-chat-widget.dark .ai-chat-contact-card__button--secondary:hover,.chakra-ui-dark .ai-chat-contact-card__button--secondary:hover,.dark .ai-chat-contact-card__button--secondary:hover,[data-theme=dark] .ai-chat-contact-card__button--secondary:hover{background:hsla(0,0%,100%,.15)}.ai-chat-contact-card-list{display:flex;flex-direction:column;gap:8px}.ai-chat-contact-card-list__header{align-items:center;color:var(--text-muted,#71717a);display:flex;font-size:13px;font-weight:500;gap:6px;margin-bottom:2px;margin-top:8px;padding:0 4px}.ai-chat-contact-card-list__stack{display:grid;gap:12px;grid-template-columns:repeat(3,minmax(0,1fr))}@media (max-width:900px){.ai-chat-contact-card-list__stack{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (max-width:600px){.ai-chat-contact-card-list__stack{grid-template-columns:1fr}}.ai-chat-contact-card-list__stack--widget{grid-template-columns:1fr}@container (min-width: 380px){.ai-chat-contact-card-list__stack--widget{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (max-width:520px){.ai-chat-contact-card-list__stack{grid-template-columns:1fr!important}.ai-chat-contact-card--horizontal{flex-direction:column}.ai-chat-contact-card--horizontal .ai-chat-contact-card__image-section{aspect-ratio:3/2;height:auto;min-width:100%;width:100%}}.ai-chat-contact-card__initials{align-items:center;display:flex;font-size:48px;font-weight:600;height:100%;justify-content:center;letter-spacing:.05em;text-transform:uppercase;width:100%}.ai-chat-contact-card--compact .ai-chat-contact-card__initials{font-size:32px}.ai-chat-contact-card--horizontal .ai-chat-contact-card__initials{font-size:28px}.ai-chat-contact-card--horizontal.ai-chat-contact-card--compact .ai-chat-contact-card__initials{font-size:22px}.ai-chat-form-card{--action-accent:var(--primary-color,#3b82f6);background:var(--bg-secondary,#f9fafb);border:1px solid var(--border-subtle,rgba(0,0,0,.06));border-radius:12px;box-sizing:border-box;margin:6px 0;overflow:hidden;padding:16px;width:100%}.ai-chat-widget.dark .ai-chat-form-card,.chakra-ui-dark .ai-chat-form-card,.dark .ai-chat-form-card,[data-theme=dark] .ai-chat-form-card{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1)}.ai-chat-form-card--empty,.ai-chat-form-card--error,.ai-chat-form-card--skipped,.ai-chat-form-card--submitted{padding:12px 16px}.ai-chat-form-card__header{align-items:center;display:flex;gap:8px;margin-bottom:12px}.ai-chat-form-card__icon{font-size:18px}.ai-chat-form-card__title{color:var(--text-primary,#3e3e3e);font-size:15px;font-weight:600}.ai-chat-widget.dark .ai-chat-form-card__title,.chakra-ui-dark .ai-chat-form-card__title,.dark .ai-chat-form-card__title,[data-theme=dark] .ai-chat-form-card__title{color:#fff}.ai-chat-form-card__description{color:var(--text-muted,#71717a);font-size:13px;line-height:1.4;margin:0 0 12px}.ai-chat-form-card__context{color:var(--text-muted,#71717a);font-size:12px;font-style:italic;margin:0 0 12px}.ai-chat-form-card__error{color:#dc2626;font-size:13px;margin:0}.ai-chat-widget.dark .ai-chat-form-card__error,.chakra-ui-dark .ai-chat-form-card__error,.dark .ai-chat-form-card__error,[data-theme=dark] .ai-chat-form-card__error{color:#fca5a5}.ai-chat-form-card__success{color:#16a34a;font-size:13px;margin:0}.ai-chat-widget.dark .ai-chat-form-card__success,.chakra-ui-dark .ai-chat-form-card__success,.dark .ai-chat-form-card__success,[data-theme=dark] .ai-chat-form-card__success{color:#4ade80}.ai-chat-form-card__empty-text,.ai-chat-form-card__skipped-text{color:var(--text-muted,#71717a);font-size:13px;margin:0}.ai-chat-form-card__progress{align-items:center;display:flex;gap:12px;margin-bottom:16px}.ai-chat-form-card__progress-bar{background:var(--action-accent,var(--primary-color,#3b82f6));border-radius:2px;flex:1;height:4px;transition:width .3s ease}.ai-chat-form-card__progress-text{color:var(--text-muted,#71717a);font-size:12px;white-space:nowrap}.ai-chat-form-card__question{margin-bottom:16px}.ai-chat-form-card__question-text{color:var(--text-primary,#3e3e3e);font-size:14px;font-weight:500;line-height:1.4;margin:0 0 12px}.ai-chat-widget.dark .ai-chat-form-card__question-text,.chakra-ui-dark .ai-chat-form-card__question-text,.dark .ai-chat-form-card__question-text,[data-theme=dark] .ai-chat-form-card__question-text{color:#fff}.ai-chat-form-card__required{color:#dc2626;margin-left:2px}.ai-chat-form-card__answer{margin-top:8px}.ai-chat-form-card__textarea{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);box-sizing:border-box;color:var(--text-primary,#3e3e3e);font-family:inherit;font-size:14px;min-height:80px;outline:none;padding:10px 12px;resize:vertical;transition:border-color .2s ease,box-shadow .2s ease;width:100%}.ai-chat-form-card__textarea:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.1)}.ai-chat-form-card__textarea::placeholder{color:var(--text-muted,#9ca3af)}.ai-chat-widget.dark .ai-chat-form-card__textarea,.chakra-ui-dark .ai-chat-form-card__textarea,.dark .ai-chat-form-card__textarea,[data-theme=dark] .ai-chat-form-card__textarea{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-form-card__textarea:focus,.chakra-ui-dark .ai-chat-form-card__textarea:focus,.dark .ai-chat-form-card__textarea:focus,[data-theme=dark] .ai-chat-form-card__textarea:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.2)}.ai-chat-form-card__options{display:flex;flex-direction:column;gap:8px}.ai-chat-form-card__option{align-items:center;background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);cursor:pointer;display:flex;gap:10px;padding:10px 12px;transition:border-color .15s,background .15s}.ai-chat-form-card__option:hover{background:rgba(59,130,246,.05);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-form-card__option,.chakra-ui-dark .ai-chat-form-card__option,.dark .ai-chat-form-card__option,[data-theme=dark] .ai-chat-form-card__option{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1)}.ai-chat-widget.dark .ai-chat-form-card__option:hover,.chakra-ui-dark .ai-chat-form-card__option:hover,.dark .ai-chat-form-card__option:hover,[data-theme=dark] .ai-chat-form-card__option:hover{background:rgba(59,130,246,.15);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-form-card__option input{accent-color:var(--action-accent,var(--primary-color,#3b82f6));margin:0}.ai-chat-form-card__option-text{color:var(--text-primary,#3e3e3e);font-size:14px}.ai-chat-widget.dark .ai-chat-form-card__option-text,.chakra-ui-dark .ai-chat-form-card__option-text,.dark .ai-chat-form-card__option-text,[data-theme=dark] .ai-chat-form-card__option-text{color:#fff}.ai-chat-form-card__rating{display:flex;flex-wrap:wrap;gap:8px}.ai-chat-form-card__rating-btn{align-items:center;background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);color:var(--text-primary,#3e3e3e);cursor:pointer;display:flex;font-size:14px;font-weight:500;height:40px;justify-content:center;transition:all .15s ease;width:40px}.ai-chat-form-card__rating-btn--selected,.ai-chat-form-card__rating-btn:hover{border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-form-card__rating-btn--selected{background:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-widget.dark .ai-chat-form-card__rating-btn,.chakra-ui-dark .ai-chat-form-card__rating-btn,.dark .ai-chat-form-card__rating-btn,[data-theme=dark] .ai-chat-form-card__rating-btn{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-form-card__rating-btn:hover,.chakra-ui-dark .ai-chat-form-card__rating-btn:hover,.dark .ai-chat-form-card__rating-btn:hover,[data-theme=dark] .ai-chat-form-card__rating-btn:hover{border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-form-card__rating-btn--selected,.chakra-ui-dark .ai-chat-form-card__rating-btn--selected,.dark .ai-chat-form-card__rating-btn--selected,[data-theme=dark] .ai-chat-form-card__rating-btn--selected{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-form-card__actions{align-items:center;border-top:1px solid var(--border-subtle,rgba(0,0,0,.08));display:flex;gap:8px;margin-top:16px;padding-top:16px}.ai-chat-widget.dark .ai-chat-form-card__actions,.chakra-ui-dark .ai-chat-form-card__actions,.dark .ai-chat-form-card__actions,[data-theme=dark] .ai-chat-form-card__actions{border-color:hsla(0,0%,100%,.08)}.ai-chat-form-card__actions-spacer{flex:1}.ai-chat-form-card__btn{border:none;border-radius:9999px;cursor:pointer;font-family:inherit;font-size:13px;font-weight:500;padding:8px 16px;transition:all .2s ease}.ai-chat-form-card__btn:disabled{cursor:not-allowed;opacity:.5}.ai-chat-form-card__btn--primary{background:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-form-card__btn--primary:hover:not(:disabled){opacity:.9;transform:translateY(-1px)}.ai-chat-form-card__btn--secondary{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);color:var(--text-primary,#3e3e3e)}.ai-chat-form-card__btn--secondary:hover:not(:disabled){border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-form-card__btn--secondary,.chakra-ui-dark .ai-chat-form-card__btn--secondary,.dark .ai-chat-form-card__btn--secondary,[data-theme=dark] .ai-chat-form-card__btn--secondary{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-form-card__btn--ghost{background:transparent;color:var(--text-muted,#71717a)}.ai-chat-form-card__btn--ghost:hover:not(:disabled){background:rgba(0,0,0,.05);color:var(--text-primary,#3e3e3e)}.ai-chat-widget.dark .ai-chat-form-card__btn--ghost:hover:not(:disabled),.chakra-ui-dark .ai-chat-form-card__btn--ghost:hover:not(:disabled),.dark .ai-chat-form-card__btn--ghost:hover:not(:disabled),[data-theme=dark] .ai-chat-form-card__btn--ghost:hover:not(:disabled){background:hsla(0,0%,100%,.05);color:#fff}.ai-chat-booking-card{--action-accent:var(--primary-color,#3b82f6);background:var(--bg-secondary,#f9fafb);border:1px solid var(--border-subtle,rgba(0,0,0,.06));border-radius:12px;box-sizing:border-box;margin:6px 0;padding:16px;width:100%}.ai-chat-widget.dark .ai-chat-booking-card,.chakra-ui-dark .ai-chat-booking-card,.dark .ai-chat-booking-card,[data-theme=dark] .ai-chat-booking-card{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1)}.ai-chat-booking-card__header{align-items:center;display:flex;gap:8px;margin-bottom:12px}.ai-chat-booking-card__icon{flex-shrink:0;font-size:18px}.ai-chat-booking-card__title{color:var(--text-primary,#3e3e3e);font-size:15px;font-weight:600}.ai-chat-widget.dark .ai-chat-booking-card__title,.chakra-ui-dark .ai-chat-booking-card__title,.dark .ai-chat-booking-card__title,[data-theme=dark] .ai-chat-booking-card__title{color:#fff}.ai-chat-booking-card__content{display:flex;flex-direction:column;gap:12px}.ai-chat-booking-card__description{color:var(--text-muted,#71717a);font-size:13px;line-height:1.4;margin:0}.ai-chat-booking-card__empty{color:var(--text-muted,#71717a);font-size:13px;padding:16px;text-align:center}.ai-chat-booking-card__input{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:8px;box-sizing:border-box;color:var(--text-primary,#3e3e3e);font-family:inherit;font-size:14px;outline:none;padding:10px 12px;transition:border-color .2s ease,box-shadow .2s ease;width:100%}.ai-chat-booking-card__input:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.1)}.ai-chat-booking-card__input::placeholder{color:var(--text-muted,#9ca3af)}.ai-chat-widget.dark .ai-chat-booking-card__input,.chakra-ui-dark .ai-chat-booking-card__input,.dark .ai-chat-booking-card__input,[data-theme=dark] .ai-chat-booking-card__input{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-booking-card__input:focus,.chakra-ui-dark .ai-chat-booking-card__input:focus,.dark .ai-chat-booking-card__input:focus,[data-theme=dark] .ai-chat-booking-card__input:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.2)}.ai-chat-booking-card__label{color:var(--text-secondary,#6b7280);display:block;font-size:13px;font-weight:500;margin-bottom:4px}.ai-chat-widget.dark .ai-chat-booking-card__label,.chakra-ui-dark .ai-chat-booking-card__label,.dark .ai-chat-booking-card__label,[data-theme=dark] .ai-chat-booking-card__label{color:var(--text-secondary,#a1a1aa)}.ai-chat-booking-card__btn{border:none;border-radius:9999px;box-sizing:border-box;cursor:pointer;font-family:inherit;font-size:13px;font-weight:500;padding:10px 16px;transition:all .2s ease;width:100%}.ai-chat-booking-card__btn:disabled{cursor:not-allowed;opacity:.5}.ai-chat-booking-card__btn--primary{background:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-booking-card__btn--primary:hover:not(:disabled){opacity:.9;transform:translateY(-1px)}.ai-chat-booking-card__btn--secondary{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);color:var(--text-primary,#3e3e3e)}.ai-chat-booking-card__btn--secondary:hover:not(:disabled){border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-booking-card__btn--secondary,.chakra-ui-dark .ai-chat-booking-card__btn--secondary,.dark .ai-chat-booking-card__btn--secondary,[data-theme=dark] .ai-chat-booking-card__btn--secondary{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-booking-card__btn--danger{background:rgba(220,38,38,.1);border:1px solid rgba(220,38,38,.2);color:#dc2626}.ai-chat-booking-card__btn--danger:hover:not(:disabled){background:rgba(220,38,38,.15)}.ai-chat-widget.dark .ai-chat-booking-card__btn--danger,.chakra-ui-dark .ai-chat-booking-card__btn--danger,.dark .ai-chat-booking-card__btn--danger,[data-theme=dark] .ai-chat-booking-card__btn--danger{background:rgba(239,68,68,.2);border-color:rgba(239,68,68,.3);color:#fca5a5}.ai-chat-booking-card__grid{display:grid;gap:10px;grid-template-columns:repeat(auto-fill,minmax(200px,1fr))}.ai-chat-booking-card__contact{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:8px;cursor:pointer;display:flex;flex-direction:column;font-family:inherit;padding:12px;text-align:left;transition:all .2s ease}.ai-chat-booking-card__contact:hover{background:rgba(59,130,246,.05);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-booking-card__contact--selected{border-width:2px}.ai-chat-widget.dark .ai-chat-booking-card__contact,.chakra-ui-dark .ai-chat-booking-card__contact,.dark .ai-chat-booking-card__contact,[data-theme=dark] .ai-chat-booking-card__contact{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1)}.ai-chat-widget.dark .ai-chat-booking-card__contact--selected,.chakra-ui-dark .ai-chat-booking-card__contact--selected,.dark .ai-chat-booking-card__contact--selected,[data-theme=dark] .ai-chat-booking-card__contact--selected{background:rgba(59,130,246,.15)}.ai-chat-booking-card__contact-name{color:var(--text-primary,#3e3e3e);font-size:14px;font-weight:500}.ai-chat-widget.dark .ai-chat-booking-card__contact-name,.chakra-ui-dark .ai-chat-booking-card__contact-name,.dark .ai-chat-booking-card__contact-name,[data-theme=dark] .ai-chat-booking-card__contact-name{color:#fff}.ai-chat-booking-card__contact-role{color:var(--text-muted,#71717a);font-size:12px;margin-top:2px}.ai-chat-booking-card__options{display:flex;flex-direction:column;gap:8px}.ai-chat-booking-card__option-btn{align-items:center;background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:8px;box-sizing:border-box;cursor:pointer;display:flex;font-family:inherit;gap:12px;padding:12px;text-align:left;transition:all .2s ease;width:100%}.ai-chat-booking-card__option-btn:hover{background:rgba(59,130,246,.05);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-booking-card__option-btn,.chakra-ui-dark .ai-chat-booking-card__option-btn,.dark .ai-chat-booking-card__option-btn,[data-theme=dark] .ai-chat-booking-card__option-btn{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1)}.ai-chat-booking-card__option-icon{flex-shrink:0;font-size:18px}.ai-chat-booking-card__option-text{color:var(--text-primary,#3e3e3e);font-size:14px;font-weight:500}.ai-chat-widget.dark .ai-chat-booking-card__option-text,.chakra-ui-dark .ai-chat-booking-card__option-text,.dark .ai-chat-booking-card__option-text,[data-theme=dark] .ai-chat-booking-card__option-text{color:#fff}.ai-chat-booking-card__date-group{margin-bottom:12px}.ai-chat-booking-card__date-header{color:var(--text-muted,#71717a);font-size:12px;font-weight:600;letter-spacing:.5px;margin-bottom:8px;text-transform:uppercase}.ai-chat-booking-card__slots{display:grid;gap:8px;grid-template-columns:repeat(auto-fill,minmax(120px,1fr))}.ai-chat-booking-card__slot{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:8px;color:var(--text-primary,#3e3e3e);cursor:pointer;font-family:inherit;font-size:13px;font-weight:500;padding:10px 12px;transition:all .2s ease}.ai-chat-booking-card__slot:hover{background:rgba(59,130,246,.05);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-booking-card__slot--selected{border-width:2px}.ai-chat-widget.dark .ai-chat-booking-card__slot,.chakra-ui-dark .ai-chat-booking-card__slot,.dark .ai-chat-booking-card__slot,[data-theme=dark] .ai-chat-booking-card__slot{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-booking-card__slot--selected,.chakra-ui-dark .ai-chat-booking-card__slot--selected,.dark .ai-chat-booking-card__slot--selected,[data-theme=dark] .ai-chat-booking-card__slot--selected{background:rgba(59,130,246,.15)}.ai-chat-booking-card__appointments{display:flex;flex-direction:column;gap:10px}.ai-chat-booking-card__appointment{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:8px;padding:12px}.ai-chat-widget.dark .ai-chat-booking-card__appointment,.chakra-ui-dark .ai-chat-booking-card__appointment,.dark .ai-chat-booking-card__appointment,[data-theme=dark] .ai-chat-booking-card__appointment{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1)}.ai-chat-booking-card__appointment-header{align-items:center;display:flex;gap:8px;justify-content:space-between;margin-bottom:6px}.ai-chat-booking-card__appointment-subject{color:var(--text-primary,#3e3e3e);font-size:14px;font-weight:500}.ai-chat-widget.dark .ai-chat-booking-card__appointment-subject,.chakra-ui-dark .ai-chat-booking-card__appointment-subject,.dark .ai-chat-booking-card__appointment-subject,[data-theme=dark] .ai-chat-booking-card__appointment-subject{color:#fff}.ai-chat-booking-card__appointment-status{border-radius:4px;font-size:11px;font-weight:600;padding:2px 6px;text-transform:uppercase}.ai-chat-booking-card__appointment-status--confirmed,.ai-chat-booking-card__appointment-status--pending{background:rgba(34,197,94,.1);color:#16a34a}.ai-chat-widget.dark .ai-chat-booking-card__appointment-status--confirmed,.ai-chat-widget.dark .ai-chat-booking-card__appointment-status--pending,.chakra-ui-dark .ai-chat-booking-card__appointment-status--confirmed,.chakra-ui-dark .ai-chat-booking-card__appointment-status--pending,.dark .ai-chat-booking-card__appointment-status--confirmed,.dark .ai-chat-booking-card__appointment-status--pending,[data-theme=dark] .ai-chat-booking-card__appointment-status--confirmed,[data-theme=dark] .ai-chat-booking-card__appointment-status--pending{background:rgba(34,197,94,.2);color:#4ade80}.ai-chat-booking-card__appointment-status--cancelled{background:hsla(220,9%,46%,.1);color:#6b7280}.ai-chat-booking-card__appointment-time{color:var(--text-secondary,#6b7280);font-size:13px;margin-bottom:4px}.ai-chat-widget.dark .ai-chat-booking-card__appointment-time,.chakra-ui-dark .ai-chat-booking-card__appointment-time,.dark .ai-chat-booking-card__appointment-time,[data-theme=dark] .ai-chat-booking-card__appointment-time{color:var(--text-secondary,#a1a1aa)}.ai-chat-booking-card__appointment-contact{color:var(--text-muted,#71717a);font-size:12px}.ai-chat-booking-card__summary{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:8px;margin-bottom:12px;padding:12px}.ai-chat-widget.dark .ai-chat-booking-card__summary,.chakra-ui-dark .ai-chat-booking-card__summary,.dark .ai-chat-booking-card__summary,[data-theme=dark] .ai-chat-booking-card__summary{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1)}.ai-chat-booking-card__summary-row{align-items:center;display:flex;justify-content:space-between;padding:6px 0}.ai-chat-booking-card__summary-row:not(:last-child){border-bottom:1px solid var(--border-subtle,rgba(0,0,0,.06))}.ai-chat-widget.dark .ai-chat-booking-card__summary-row:not(:last-child),.chakra-ui-dark .ai-chat-booking-card__summary-row:not(:last-child),.dark .ai-chat-booking-card__summary-row:not(:last-child),[data-theme=dark] .ai-chat-booking-card__summary-row:not(:last-child){border-bottom-color:hsla(0,0%,100%,.08)}.ai-chat-booking-card__summary-label{color:var(--text-muted,#71717a);font-size:12px;font-weight:600;letter-spacing:.5px;text-transform:uppercase}.ai-chat-booking-card__summary-value{color:var(--text-primary,#3e3e3e);font-size:14px;font-weight:500;text-align:right}.ai-chat-widget.dark .ai-chat-booking-card__summary-value,.chakra-ui-dark .ai-chat-booking-card__summary-value,.dark .ai-chat-booking-card__summary-value,[data-theme=dark] .ai-chat-booking-card__summary-value{color:#fff}.ai-chat-booking-card__link{display:inline-block;font-size:13px;font-weight:500;margin-top:8px;text-decoration:none;transition:opacity .2s ease}.ai-chat-booking-card__link:hover{opacity:.8;text-decoration:underline}.ai-chat-booking-card--success{background:rgba(34,197,94,.05);border-color:rgba(34,197,94,.2)}.ai-chat-widget.dark .ai-chat-booking-card--success,.chakra-ui-dark .ai-chat-booking-card--success,.dark .ai-chat-booking-card--success,[data-theme=dark] .ai-chat-booking-card--success{background:rgba(34,197,94,.1);border-color:rgba(34,197,94,.3)}.ai-chat-booking-card--pending{background:rgba(234,179,8,.05);border-color:rgba(234,179,8,.2)}.ai-chat-widget.dark .ai-chat-booking-card--pending,.chakra-ui-dark .ai-chat-booking-card--pending,.dark .ai-chat-booking-card--pending,[data-theme=dark] .ai-chat-booking-card--pending{background:rgba(234,179,8,.1);border-color:rgba(234,179,8,.3)}.ai-chat-booking-card--cancelled{background:hsla(220,9%,46%,.05);border-color:hsla(220,9%,46%,.2)}.ai-chat-widget.dark .ai-chat-booking-card--cancelled,.chakra-ui-dark .ai-chat-booking-card--cancelled,.dark .ai-chat-booking-card--cancelled,[data-theme=dark] .ai-chat-booking-card--cancelled{background:hsla(220,9%,46%,.1);border-color:hsla(220,9%,46%,.3)}.ai-chat-booking-card--error{background:rgba(239,68,68,.05);border-color:rgba(239,68,68,.2)}.ai-chat-widget.dark .ai-chat-booking-card--error,.chakra-ui-dark .ai-chat-booking-card--error,.dark .ai-chat-booking-card--error,[data-theme=dark] .ai-chat-booking-card--error{background:rgba(239,68,68,.1);border-color:rgba(239,68,68,.3)}.ai-chat-booking-card__pending-text,.ai-chat-booking-card__success-text{color:var(--text-secondary,#6b7280);font-size:13px;margin:0}.ai-chat-widget.dark .ai-chat-booking-card__pending-text,.ai-chat-widget.dark .ai-chat-booking-card__success-text,.chakra-ui-dark .ai-chat-booking-card__pending-text,.chakra-ui-dark .ai-chat-booking-card__success-text,.dark .ai-chat-booking-card__pending-text,.dark .ai-chat-booking-card__success-text,[data-theme=dark] .ai-chat-booking-card__pending-text,[data-theme=dark] .ai-chat-booking-card__success-text{color:var(--text-secondary,#a1a1aa)}.ai-chat-booking-card__error{color:#dc2626;font-size:13px;margin:0}.ai-chat-widget.dark .ai-chat-booking-card__error,.chakra-ui-dark .ai-chat-booking-card__error,.dark .ai-chat-booking-card__error,[data-theme=dark] .ai-chat-booking-card__error{color:#fca5a5}.chat-fullpage{--fp-max-width:800px;--fp-padding-x:16px;--fp-padding-top-mobile:64px;--fp-padding-top-desktop:16px;--fp-padding-bottom:200px;--fp-input-bottom:0}.chat-fullpage .ai-chat-messages{background:transparent;height:100%;margin:0 auto;max-width:var(--fp-max-width);padding:var(--fp-padding-top-desktop) var(--fp-padding-x) var(--fp-padding-bottom)}@media (max-width:768px){.chat-fullpage .ai-chat-messages{padding-top:var(--fp-padding-top-mobile)}}.chat-fullpage .ai-chat-message{animation:none}.chat-fullpage .ai-chat-message.user{max-width:85%}.chat-fullpage .ai-chat-message.user .ai-chat-message-content{background:var(--bg-muted,#f4f4f5);border-radius:24px;color:#000;padding:8px 16px}.chat-fullpage.dark .ai-chat-message.user .ai-chat-message-content{background:var(--bg-muted,#27272a);color:#fff}.chat-fullpage .ai-chat-message.assistant{width:100%}.chat-fullpage .ai-chat-message.assistant .ai-chat-message-content{color:#000;padding:8px 16px}.chat-fullpage.dark .ai-chat-message.assistant .ai-chat-message-content{color:#fff}.chat-fullpage .ai-chat-message.tool{margin:0;padding:0;width:100%}.chat-fullpage .ai-chat-welcome{align-items:center;display:flex;flex-direction:column;gap:24px;justify-content:center;min-height:60vh;padding:24px;text-align:center}.chat-fullpage .ai-chat-welcome-title{font-size:32px;font-weight:600}.chat-fullpage .ai-chat-welcome-text{color:var(--text-muted,#71717a);font-size:18px;max-width:400px}.chat-fullpage .ai-chat-input-container{background:transparent;bottom:0;left:0;padding:16px 16px calc(16px + env(safe-area-inset-bottom));position:fixed;right:0;z-index:20}.chat-fullpage .ai-chat-input-container:after{background:var(--bg-primary,#fff);bottom:0;content:\"\";height:calc(40% + 16px);left:0;pointer-events:none;position:absolute;right:0;z-index:-1}.chat-fullpage.dark .ai-chat-input-container:after{background:var(--bg-primary,#18181b)}@media (min-width:769px){.chat-fullpage .ai-chat-input-container{background:transparent;bottom:var(--fp-input-bottom);left:50%;max-width:var(--fp-max-width);padding:0;position:absolute;right:auto;transform:translateX(-50%);width:100%}}.chat-fullpage .ai-chat-input-wrapper{background:var(--bg-muted,#f4f4f5);border:1px solid var(--border-muted,#e4e4e7);border-radius:24px;box-shadow:0 1px 8px rgba(0,0,0,.06);margin:0 auto;max-width:var(--fp-max-width)}.chat-fullpage.dark .ai-chat-input-wrapper{background:var(--bg-muted,#27272a);border-color:var(--border-muted,#3f3f46);box-shadow:0 1px 12px rgba(0,0,0,.25)}.chat-fullpage .ai-chat-scroll-button{bottom:100px}@media (min-width:769px){.chat-fullpage .ai-chat-scroll-button{bottom:90px}}.chat-fullpage .ai-chat-suggested-questions{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;max-width:600px}.chat-fullpage .ai-chat-suggested-question{border-radius:9999px;font-size:14px;padding:8px 16px}.chat-fullpage .ai-chat-follow-up-suggestions{margin-top:12px}.chat-fullpage .ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-default,#d4d4d8);color:#000}.chat-fullpage .ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#f4f4f5)}.chat-fullpage.dark .ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-subtle,#52525b);color:#fff}.chat-fullpage.dark .ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#3f3f46)}.chat-fullpage .ai-chat-typing{padding:8px 16px}@media (max-width:480px){body.ai-chat-widget-open{height:100%!important;overflow:hidden!important;position:fixed!important;touch-action:none!important;width:100%!important}.ai-chat-widget-container.is-open{height:100vh!important;height:100dvh!important;width:100vw!important;z-index:var(--widget-z-index,2147483647)!important}.ai-chat-widget-container.is-open,.ai-chat-widget-container.is-open .ai-chat-window{bottom:0!important;left:0!important;position:fixed!important;right:0!important;top:0!important}.ai-chat-widget-container.is-open .ai-chat-window{animation:none!important;border:none!important;border-radius:0!important;box-shadow:none!important;height:100%!important;max-height:100%!important;max-width:100%!important;outline:none!important;transform:none!important;width:100%!important}.ai-chat-widget-container.is-open .ai-chat-button{display:none!important;pointer-events:none!important;visibility:hidden!important}.ai-chat-widget-container.is-open .ai-chat-header{border-radius:0!important;flex-shrink:0;padding-left:max(16px,env(safe-area-inset-left));padding-right:max(16px,env(safe-area-inset-right));padding-top:max(12px,env(safe-area-inset-top));position:relative;z-index:100}.ai-chat-widget-container.is-open .ai-chat-messages{-webkit-overflow-scrolling:touch;flex:1;overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain;padding-bottom:120px;padding-left:max(16px,env(safe-area-inset-left));padding-right:max(16px,env(safe-area-inset-right));touch-action:pan-y}.ai-chat-widget-container.is-open .ai-chat-input-container{background:var(--bg-primary,#fff);bottom:0!important;left:0!important;padding:8px max(12px,env(safe-area-inset-right)) max(16px,calc(env(safe-area-inset-bottom) + 8px)) max(12px,env(safe-area-inset-left));position:fixed!important;right:0!important;z-index:100}.ai-chat-widget.dark .ai-chat-widget-container.is-open .ai-chat-input-container{background:var(--bg-primary,#282625)}.ai-chat-widget-container.is-open .ai-chat-input-container:after{display:none}.ai-chat-widget-container.is-open .ai-chat-input-wrapper{margin:0;max-width:100%}.ai-chat-widget-container.is-open .ai-chat-scroll-button{bottom:calc(80px + env(safe-area-inset-bottom))}.ai-chat-widget-container.is-open .ai-chat-welcome{padding:16px 0}.ai-chat-widget-container.is-open .ai-chat-welcome-title{font-size:24px}.ai-chat-widget-container.is-open .ai-chat-suggested-questions{align-items:stretch;flex-direction:column}.ai-chat-widget-container.is-open .ai-chat-suggested-question{text-align:center;width:100%}}@media (min-width:481px) and (max-width:768px){.ai-chat-widget-container.is-open .ai-chat-window{border-radius:22px 22px 44px 44px;max-height:calc(100vh - 100px);max-width:calc(100vw - 32px)}}";
|
|
47920
|
+
var css_248z$1 = ".ai-chat-message{animation:ai-chat-message-appear .2s var(--chat-ease-bounce);max-width:85%}.ai-chat-message-content{border-radius:var(--chat-radius-bubble,14px);font-size:var(--chat-text-md,15px);line-height:var(--chat-line-relaxed,1.6);padding:var(--chat-space-sm,8px) var(--chat-space-md,16px)}.ai-chat-message.user .ai-chat-message-content{background:var(--chat-user-bg,#f4f3f0);border-bottom-right-radius:var(--chat-radius-sm,4px);color:var(--chat-user-text,#000)}.ai-chat-message.assistant .ai-chat-message-content{background:var(--chat-assistant-bg,transparent);color:var(--chat-assistant-text,#000)}.ai-chat-message-timestamp{color:var(--chat-text-muted,#71717a);font-size:var(--chat-text-xs,12px);margin-top:var(--chat-space-xs,4px);padding:0 var(--chat-space-xs,4px)}@keyframes ai-chat-message-appear{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.ai-chat-message.fullpage .ai-chat-message-content{font-size:var(--chat-text-lg,18px);padding:var(--chat-space-md,16px) var(--chat-space-lg,24px)}.ai-chat-typing{gap:var(--chat-space-xs,4px);padding:var(--chat-space-sm,8px) var(--chat-space-md,16px)}.ai-chat-typing-dot{background:var(--chat-text-muted,#71717a)}.ai-chat-tool-row{padding:0 16px}.ai-chat-tool-gear{color:var(--text-primary,#3e3e3e)}.ai-chat-tool-badge{border-radius:8px}.ai-chat-tool-badge.loading{background:#e5e7eb;border:1px solid #d1d5db;color:#1f2937}.ai-chat-tool-badge.error{background:rgba(239,68,68,.1);color:#ef4444}.ai-chat-tool-check{color:#22c55e;flex-shrink:0}.ai-chat-tool-error{color:#ef4444;flex-shrink:0}.ai-chat-tool-badge .tool-name{max-width:150px;overflow:hidden;text-overflow:ellipsis}.ai-chat-widget.dark .ai-chat-tool-gear,.ai-chat-widget[data-theme=dark] .ai-chat-tool-gear,.dark .ai-chat-tool-gear,[data-theme=dark] .ai-chat-tool-gear{color:#fff}.ai-chat-widget.dark .ai-chat-tool-badge,.ai-chat-widget[data-theme=dark] .ai-chat-tool-badge,.dark .ai-chat-tool-badge,[data-theme=dark] .ai-chat-tool-badge{background:hsla(0,0%,100%,.12);border:1px solid hsla(0,0%,100%,.2);color:hsla(0,0%,100%,.9)}.ai-chat-widget.dark .ai-chat-tool-badge.error,.ai-chat-widget[data-theme=dark] .ai-chat-tool-badge.error,.dark .ai-chat-tool-badge.error,[data-theme=dark] .ai-chat-tool-badge.error{background:rgba(239,68,68,.2);color:#f87171}.chakra-ui-dark .ai-chat-tool-gear,html.dark .ai-chat-tool-gear{color:#fff}.chakra-ui-dark .ai-chat-tool-badge,html.dark .ai-chat-tool-badge{background:hsla(0,0%,100%,.12);border:1px solid hsla(0,0%,100%,.2);color:hsla(0,0%,100%,.9)}.chakra-ui-dark .ai-chat-tool-badge.error,html.dark .ai-chat-tool-badge.error{background:rgba(239,68,68,.2);color:#f87171}.ai-chat-widget,.chat-ui{--radius-sm:4px;--radius-md:8px;--radius-lg:12px;--radius-xl:16px;--radius-2xl:18px;--radius-pill:9999px;--radius-window-top:22px;--radius-window-bottom:44px;--radius-window-gutter:16px;--radius-chat-bubble:14px;--radius-preset-badge:13px;--radius-history-item:14px;--radius-action-badge:8px;--radius-input:62px;--space-xs:4px;--space-sm:8px;--space-md:16px;--space-lg:24px;--space-xl:32px;--text-xs:12px;--text-sm:14px;--text-md:15px;--text-lg:18px;--text-xl:22px;--text-2xl:28px;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--line-height-tight:1.3;--line-height-normal:1.4;--line-height-relaxed:1.6;--breakpoint-mobile:480px;--breakpoint-tablet:768px;--breakpoint-desktop:769px;--bg-primary:#fff;--bg-secondary:#f4f4f4;--bg-tertiary:#e5e7eb;--bg-hover:#e5e7eb;--text-primary:#3e3e3e;--text-secondary:#000;--text-muted:#71717a;--text-placeholder:#a1a1aa;--border-default:#d3d3d3;--border-subtle:#e5e7eb;--border-muted:#f4f4f5;--user-bg:#f4f3f0;--user-text:#000;--user-bg-hover:#e8e7e4;--agent-bg:transparent;--agent-text:#000;--input-bg:#f4f4f4;--input-border:#d3d3d3;--input-text:#000;--btn-primary-bg:#151515;--btn-primary-text:#f4f4f4;--btn-secondary-bg:transparent;--btn-secondary-text:#71717a;--spring-bounce:cubic-bezier(0.34,1.56,0.64,1);--spring-smooth:cubic-bezier(0.4,0,0.2,1);--spring-snappy:cubic-bezier(0.2,0,0,1);--duration-fast:0.15s;--duration-normal:0.25s;--duration-slow:0.35s;--shadow-sm:0 1px 2px rgba(0,0,0,.05);--shadow-md:0 2px 8px rgba(0,0,0,.1);--shadow-lg:0 4px 16px rgba(0,0,0,.12);--shadow-window:0px 0px 15px 9px rgba(0,0,0,.1);--shadow-button:0px 0px 15px 9px rgba(0,0,0,.03)}.ai-chat-widget.dark,.chat-ui.dark{--bg-primary:#282625;--bg-secondary:#4a4846;--bg-tertiary:#484848;--bg-hover:#484848;--text-primary:#fff;--text-secondary:#fff;--text-muted:#a1a1aa;--text-placeholder:#71717a;--border-default:#5d5b5b;--border-subtle:#5d5b5b;--border-muted:#5d5b5b;--user-bg:#484848;--user-text:#fff;--user-bg-hover:#5a5a5a;--agent-bg:transparent;--agent-text:#fff;--input-bg:#4a4846;--input-border:#5d5b5b;--input-text:#fff;--btn-primary-bg:#fff;--btn-primary-text:#312f2d;--btn-secondary-bg:transparent;--btn-secondary-text:#a1a1aa;--shadow-window:0px 0px 15px 9px rgba(0,0,0,.2);--shadow-button:0px 0px 15px 9px rgba(0,0,0,.03);--shadow-input:0px 0px 10px rgba(0,0,0,.15)}.ai-chat-widget,.chat-ui{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}.ai-chat-widget-container{font-size:var(--text-sm);line-height:1.5;position:fixed;z-index:var(--widget-z-index,2147483647)!important}.ai-chat-widget-container.bottom-right{bottom:20px;right:20px}.ai-chat-widget-container.bottom-left{bottom:20px;left:20px}.ai-chat-widget-container.top-right{right:20px;top:20px}.ai-chat-widget-container.top-left{left:20px;top:20px}.ai-chat-widget-container.container-mode{height:100%;inset:0;pointer-events:none;position:absolute;width:100%}.ai-chat-widget-container.container-mode .ai-chat-button,.ai-chat-widget-container.container-mode .ai-chat-trigger-button,.ai-chat-widget-container.container-mode .ai-chat-trigger-input-container,.ai-chat-widget-container.container-mode .ai-chat-window{pointer-events:auto}.ai-chat-widget-container.container-mode:not(.trigger-input-bar) .ai-chat-button{position:absolute}.ai-chat-widget-container.container-mode:not(.trigger-input-bar).bottom-right .ai-chat-button{bottom:20px;left:auto;right:20px;top:auto}.ai-chat-widget-container.container-mode:not(.trigger-input-bar).bottom-left .ai-chat-button{bottom:20px;left:20px;right:auto;top:auto}.ai-chat-widget-container.container-mode:not(.trigger-input-bar).top-right .ai-chat-button{bottom:auto;left:auto;right:20px;top:20px}.ai-chat-widget-container.container-mode:not(.trigger-input-bar).top-left .ai-chat-button{bottom:auto;left:20px;right:auto;top:20px}@keyframes ai-chat-window-open{0%{opacity:0;transform:scale(.9) translateY(20px)}to{opacity:1;transform:scale(1) translateY(0)}}@keyframes ai-chat-window-close{0%{opacity:1;transform:scale(1) translateY(0)}to{opacity:0;transform:scale(.9) translateY(20px)}}@keyframes ai-chat-message-slide-in{0%{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}@keyframes ai-chat-user-message-sent{0%{opacity:0;transform:translateX(20px) scale(.95)}60%{opacity:1;transform:translateX(-4px) scale(1.02)}to{opacity:1;transform:translateX(0) scale(1)}}@keyframes ai-chat-welcome-fade-in{0%{opacity:0;transform:translateY(16px)}to{opacity:1;transform:translateY(0)}}@keyframes ai-chat-typing-pulse{0%,60%,to{opacity:.4;transform:translateY(0) scale(1)}30%{opacity:1;transform:translateY(-4px) scale(1.1)}}@keyframes ai-chat-gear-spin{to{transform:rotate(1turn)}}@keyframes ai-chat-tool-active{0%,to{background:var(--bg-secondary);opacity:1}50%{background:var(--bg-tertiary);opacity:1}}@keyframes ai-chat-feedback-morph{0%{opacity:.5;transform:scale(.8)}to{opacity:1;transform:scale(1)}}@keyframes ai-chat-checkmark-pop{0%{opacity:0;transform:scale(0) rotate(-45deg)}50%{transform:scale(1.3) rotate(0deg)}to{opacity:1;transform:scale(1) rotate(0deg)}}@keyframes ai-chat-history-exit{to{opacity:0;transform:translateY(-18px)}}@keyframes ai-chat-tool-gradient{0%{background-position:200% 0}to{background-position:-200% 0}}.ai-chat-window{-webkit-font-smoothing:subpixel-antialiased;-moz-osx-font-smoothing:auto;animation:ai-chat-window-open var(--duration-slow,.35s) var(--spring-bounce);-webkit-backface-visibility:hidden;backface-visibility:hidden;background:var(--bg-primary,#fff);border:1px solid var(--border-default,#d3d3d3);border-radius:var(--radius-window-top,22px) var(--radius-window-top,22px) var(--radius-window-bottom,44px) var(--radius-window-bottom,44px);box-shadow:var(--shadow-window,0 0 15px 5px rgba(0,0,0,.08));display:flex;flex-direction:column;overflow:hidden;position:absolute;-webkit-transform:translateZ(0);transform:translateZ(0);transform-origin:bottom right;will-change:transform,opacity;z-index:2147483647!important}.ai-chat-widget.dark .ai-chat-window{background:var(--bg-primary,#282625);border-color:var(--border-default,#5d5b5b);border-width:.7px}.ai-chat-window.closing{animation:ai-chat-window-close var(--duration-normal) var(--spring-smooth) forwards}.ai-chat-window.size-small{height:500px;max-height:calc(100vh - 100px);max-width:calc(100vw - 40px);min-width:320px;width:380px}.ai-chat-window.size-medium{height:calc(100vh - 140px);max-height:680px;max-width:calc(100vw - 40px);min-width:380px;width:440px}.ai-chat-window.size-large{height:calc(100vh - 48px);max-height:calc(100vh - 48px);max-width:560px;min-width:440px;width:33vw}.ai-chat-widget-container.bottom-right .ai-chat-window{bottom:calc(var(--button-size, 56px) + 8px);right:0}.ai-chat-widget-container.bottom-left .ai-chat-window{bottom:calc(var(--button-size, 56px) + 8px);left:0}.ai-chat-widget-container.top-right .ai-chat-window{right:0;top:calc(var(--button-size, 56px) + 8px)}.ai-chat-widget-container.top-left .ai-chat-window{left:0;top:calc(var(--button-size, 56px) + 8px)}.ai-chat-widget-container.trigger-button.size-large.bottom-left .ai-chat-window,.ai-chat-widget-container.trigger-button.size-large.bottom-right .ai-chat-window{bottom:0}.ai-chat-widget-container.trigger-button.size-large.top-left .ai-chat-window,.ai-chat-widget-container.trigger-button.size-large.top-right .ai-chat-window{top:0}.ai-chat-widget-container.trigger-pill-text.size-large.bottom-left .ai-chat-window,.ai-chat-widget-container.trigger-pill-text.size-large.bottom-right .ai-chat-window{bottom:72px;height:calc(100vh - 120px);max-height:calc(100vh - 120px)}.ai-chat-widget-container.trigger-pill-text.size-large.top-left .ai-chat-window,.ai-chat-widget-container.trigger-pill-text.size-large.top-right .ai-chat-window{height:calc(100vh - 120px);max-height:calc(100vh - 120px);top:72px}.ai-chat-widget-container.trigger-input-bar.size-large.bottom-left .ai-chat-window,.ai-chat-widget-container.trigger-input-bar.size-large.bottom-right .ai-chat-window{bottom:72px;height:calc(100vh - 120px);max-height:calc(100vh - 120px)}.ai-chat-widget-container.trigger-input-bar.size-large.top-left .ai-chat-window,.ai-chat-widget-container.trigger-input-bar.size-large.top-right .ai-chat-window{height:calc(100vh - 120px);max-height:calc(100vh - 120px);top:72px}.ai-chat-widget-container.container-mode.bottom-right .ai-chat-window{bottom:20px;left:auto;right:20px;top:auto}.ai-chat-widget-container.container-mode.bottom-left .ai-chat-window{bottom:20px;left:20px;right:auto;top:auto}.ai-chat-widget-container.container-mode.top-right .ai-chat-window{bottom:auto;left:auto;right:20px;top:20px}.ai-chat-widget-container.container-mode.top-left .ai-chat-window{bottom:auto;left:20px;right:auto;top:20px}.ai-chat-widget-container.container-mode.size-small .ai-chat-window{height:min(500px,50%);max-height:calc(100% - 100px);max-width:calc(100% - 40px);min-height:300px;min-width:280px;width:min(380px,calc(100% - 40px))}.ai-chat-widget-container.container-mode.size-medium .ai-chat-window{height:min(680px,70%);max-height:calc(100% - 80px);max-width:calc(100% - 40px);min-height:400px;min-width:320px;width:min(440px,calc(100% - 40px))}.ai-chat-widget-container.container-mode.size-large .ai-chat-window{height:90%;max-height:calc(100% - 60px);max-width:calc(100% - 40px);min-height:500px;min-width:380px;width:min(560px,calc(100% - 40px))}.ai-chat-widget-container.trigger-button.container-mode.bottom-left .ai-chat-window,.ai-chat-widget-container.trigger-button.container-mode.bottom-right .ai-chat-window{bottom:88px}.ai-chat-widget-container.trigger-pill-text.container-mode.bottom-left .ai-chat-window,.ai-chat-widget-container.trigger-pill-text.container-mode.bottom-right .ai-chat-window{bottom:80px}.ai-chat-widget-container.trigger-button.container-mode.size-medium .ai-chat-window,.ai-chat-widget-container.trigger-button.container-mode.size-small .ai-chat-window,.ai-chat-widget-container.trigger-pill-text.container-mode.size-medium .ai-chat-window,.ai-chat-widget-container.trigger-pill-text.container-mode.size-small .ai-chat-window{max-height:calc(100% - 108px)}.ai-chat-widget-container.trigger-button.container-mode.size-large .ai-chat-window,.ai-chat-widget-container.trigger-pill-text.container-mode.size-large .ai-chat-window{height:calc(100% - 108px);max-height:calc(100% - 108px)}.ai-chat-widget-container.trigger-button.container-mode.top-left .ai-chat-window,.ai-chat-widget-container.trigger-button.container-mode.top-right .ai-chat-window{bottom:auto;top:88px}.ai-chat-widget-container.trigger-pill-text.container-mode.top-left .ai-chat-window,.ai-chat-widget-container.trigger-pill-text.container-mode.top-right .ai-chat-window{bottom:auto;top:80px}.ai-chat-widget-container.container-mode.mobile-mode.is-open{margin:0!important;padding:0!important}.ai-chat-widget-container.container-mode.mobile-mode.is-open,.ai-chat-widget-container.container-mode.mobile-mode.is-open .ai-chat-window{bottom:0!important;height:100%!important;left:0!important;position:absolute!important;right:0!important;top:0!important;width:100%!important}.ai-chat-widget-container.container-mode.mobile-mode.is-open .ai-chat-window{animation:none!important;border:none!important;border-radius:0!important;box-shadow:none!important;max-height:100%!important;max-width:100%!important;min-height:100%!important;min-width:100%!important}.ai-chat-widget-container.container-mode.mobile-mode.is-open .ai-chat-button,.ai-chat-widget-container.container-mode.mobile-mode.is-open .ai-chat-trigger-input-container,.ai-chat-widget-container.container-mode.mobile-mode.is-open .ai-chat-trigger-pill{display:none!important}.ai-chat-header{align-items:center;background:var(--bg-primary,#fff);border-bottom:1px solid var(--border-default,#d3d3d3);border-radius:var(--radius-window-top,22px) var(--radius-window-top,22px) 0 0;display:flex;justify-content:space-between;padding:12px var(--space-md,16px);position:relative;z-index:10}.ai-chat-widget.dark .ai-chat-header{background:var(--bg-primary,#282625);border-bottom-color:var(--border-default,#5d5b5b);border-bottom-width:.7px}.ai-chat-header.is-history{padding-left:var(--space-md)}.ai-chat-header.is-history .ai-chat-title{flex:1;min-width:0;overflow:hidden;padding-right:var(--space-lg);text-overflow:ellipsis;white-space:nowrap}.ai-chat-header-content{align-items:center;display:flex;flex:1;gap:var(--space-lg)}.ai-chat-header-actions{align-items:center;display:flex;gap:var(--space-sm)}.ai-chat-logo{border-radius:10px;height:36px;object-fit:cover;width:36px}.ai-chat-title{color:var(--text-primary,#3e3e3e);font-size:var(--text-xl,22px);font-weight:var(--font-weight-bold,700);letter-spacing:-.02em}.ai-chat-widget.dark .ai-chat-title{color:var(--text-primary,#fff)}.ai-chat-close-button,.ai-chat-header-button{align-items:center;background:transparent;border:none;border-radius:var(--radius-md);color:var(--text-muted);cursor:pointer;display:flex;height:32px;justify-content:center;padding:0;transition:color var(--duration-fast) ease;width:32px}.ai-chat-close-button:hover,.ai-chat-header-button:hover{color:var(--text-primary)}.ai-chat-close-button:active,.ai-chat-header-button:active{transform:scale(.95)}.ai-chat-close-button svg,.ai-chat-header-button svg{height:22px;width:22px}.ai-chat-button{-webkit-font-smoothing:subpixel-antialiased;-moz-osx-font-smoothing:auto;align-items:center;-webkit-backface-visibility:hidden;backface-visibility:hidden;background:var(--button-color,var(--btn-primary-bg));border:1px solid var(--border-default,#d3d3d3);border-radius:50%;box-shadow:var(--shadow-button,0 0 15px 9px rgba(0,0,0,.03));color:var(--button-icon-color,var(--btn-primary-text));cursor:pointer;display:flex;height:var(--button-size,56px);justify-content:center;overflow:hidden;position:relative;-webkit-transform:translateZ(0);transform:translateZ(0);transition:transform var(--duration-fast) ease;width:var(--button-size,56px);will-change:transform;z-index:2147483647!important}.ai-chat-button:hover{transform:scale(1.05)}.ai-chat-button:active{transform:scale(.98)}.ai-chat-button-svg{height:50%;min-height:24px;min-width:24px;transition:transform var(--duration-fast) ease;width:50%}.ai-chat-button.is-open .ai-chat-button-svg{transform:rotate(0deg)}.ai-chat-button-icon{font-size:1.5em;line-height:1}.ai-chat-welcome-bubble{animation:ai-chat-bubble-fade-in .3s ease-out;background:var(--button-color,var(--btn-primary-bg,#07f));border:none;border-radius:16px;box-shadow:none;box-sizing:border-box;color:var(--button-icon-color,var(--btn-primary-text,#fff));cursor:pointer;font-size:13px;font-weight:500;line-height:1.5;max-width:min(420px,90vw);padding:12px 32px 12px 16px;position:absolute;text-align:left;white-space:normal;width:auto;z-index:2147483647!important}.ai-chat-welcome-bubble-close{align-items:center;background:transparent;border:none;border-radius:50%;color:inherit;cursor:pointer;display:flex;height:20px;justify-content:center;opacity:.8;padding:0;position:absolute;right:8px;top:8px;transition:opacity .15s ease,background .15s ease;width:20px}.ai-chat-welcome-bubble-close:hover{background:hsla(0,0%,100%,.2);opacity:1}.ai-chat-welcome-bubble-close svg{height:12px;width:12px}.ai-chat-welcome-bubble-arrow{border-bottom:8px solid transparent;border-top:8px solid transparent;height:0;position:absolute;width:0}.ai-chat-widget-container.bottom-right .ai-chat-welcome-bubble{bottom:50%;right:calc(100% + 12px);text-align:left;transform:translateY(50%)}.ai-chat-widget-container.bottom-left .ai-chat-welcome-bubble{bottom:50%;left:calc(100% + 12px);text-align:left;transform:translateY(50%)}.ai-chat-widget-container.top-right .ai-chat-welcome-bubble{right:calc(100% + 12px);text-align:left;top:50%;transform:translateY(-50%)}.ai-chat-widget-container.top-left .ai-chat-welcome-bubble{left:calc(100% + 12px);text-align:left;top:50%;transform:translateY(-50%)}.ai-chat-widget-container.bottom-right .ai-chat-welcome-bubble-arrow{border-left:8px solid var(--button-color,var(--btn-primary-bg,#07f));right:-8px;top:50%;transform:translateY(-50%)}.ai-chat-widget-container.bottom-left .ai-chat-welcome-bubble-arrow{border-right:8px solid var(--button-color,var(--btn-primary-bg,#07f));left:-8px;top:50%;transform:translateY(-50%)}.ai-chat-widget-container.top-right .ai-chat-welcome-bubble-arrow{border-left:8px solid var(--button-color,var(--btn-primary-bg,#07f));right:-8px;top:50%;transform:translateY(-50%)}.ai-chat-widget-container.top-left .ai-chat-welcome-bubble-arrow{border-right:8px solid var(--button-color,var(--btn-primary-bg,#07f));left:-8px;top:50%;transform:translateY(-50%)}.ai-chat-welcome-bubble:hover{filter:brightness(1.1)}.ai-chat-widget-container.bottom-right .ai-chat-welcome-bubble{animation-name:ai-chat-bubble-fade-in-bottom-right}@keyframes ai-chat-bubble-fade-in-bottom-right{0%{opacity:0;transform:translateY(50%) translateX(8px)}to{opacity:1;transform:translateY(50%) translateX(0)}}.ai-chat-widget-container.bottom-left .ai-chat-welcome-bubble{animation-name:ai-chat-bubble-fade-in-bottom-left}@keyframes ai-chat-bubble-fade-in-bottom-left{0%{opacity:0;transform:translateY(50%) translateX(-8px)}to{opacity:1;transform:translateY(50%) translateX(0)}}.ai-chat-widget-container.top-right .ai-chat-welcome-bubble{animation-name:ai-chat-bubble-fade-in-top-right}@keyframes ai-chat-bubble-fade-in-top-right{0%{opacity:0;transform:translateY(-50%) translateX(8px)}to{opacity:1;transform:translateY(-50%) translateX(0)}}.ai-chat-widget-container.top-left .ai-chat-welcome-bubble{animation-name:ai-chat-bubble-fade-in-top-left}@keyframes ai-chat-bubble-fade-in-top-left{0%{opacity:0;transform:translateY(-50%) translateX(-8px)}to{opacity:1;transform:translateY(-50%) translateX(0)}}.ai-chat-trigger-pill{-webkit-font-smoothing:subpixel-antialiased;-moz-osx-font-smoothing:auto;align-items:center;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);-webkit-backface-visibility:hidden;backface-visibility:hidden;background:var(--trigger-bg,rgba(0,0,0,.04));border:1px solid var(--trigger-border,rgba(0,0,0,.12));border-radius:9999px;box-shadow:0 4px 16px rgba(0,0,0,.12);color:var(--trigger-text,#1a1a1a);cursor:pointer;display:flex;font-size:14px;font-weight:500;gap:10px;height:48px;justify-content:center;padding:0 24px;position:relative;-webkit-transform:translateZ(0);transform:translateZ(0);transition:all .3s ease,color .4s ease,background .4s ease,border-color .4s ease;white-space:nowrap;will-change:transform;z-index:2147483647!important}.ai-chat-trigger-pill.is-open{background:var(--button-color,var(--btn-primary-bg));border-color:var(--border-default,#d3d3d3);box-shadow:var(--shadow-button,0 0 15px 9px rgba(0,0,0,.03));color:var(--button-icon-color,var(--btn-primary-text));height:56px;padding:0;width:56px}.ai-chat-trigger-pill.is-open .ai-chat-trigger-pill-icon{height:24px;width:24px}.ai-chat-trigger-pill:hover:not(.is-open){background:var(--trigger-bg-hover,rgba(0,0,0,.08));border-color:var(--trigger-border-hover,rgba(0,0,0,.2))}.ai-chat-trigger-pill.is-open:hover{transform:scale(1.05)}.ai-chat-trigger-pill:active{transform:scale(.98)}.ai-chat-trigger-pill-icon{flex-shrink:0;height:20px;transition:all .3s ease;width:20px}.ai-chat-widget-container.trigger-pill-text.container-mode .ai-chat-trigger-pill{position:absolute}.ai-chat-widget-container.trigger-pill-text.container-mode.bottom-right .ai-chat-trigger-pill{bottom:20px;left:auto;right:20px;top:auto}.ai-chat-widget-container.trigger-pill-text.container-mode.bottom-left .ai-chat-trigger-pill{bottom:20px;left:20px;right:auto;top:auto}.ai-chat-widget-container.trigger-pill-text.container-mode.top-right .ai-chat-trigger-pill{bottom:auto;left:auto;right:20px;top:20px}.ai-chat-widget-container.trigger-pill-text.container-mode.top-left .ai-chat-trigger-pill{bottom:auto;left:20px;right:auto;top:20px}.ai-chat-widget-container.trigger-pill-text.container-mode .ai-chat-trigger-pill{pointer-events:auto}.ai-chat-trigger-input-container{align-items:flex-end;display:flex;flex-direction:column;gap:8px;z-index:2147483647!important}.ai-chat-widget-container.bottom-left .ai-chat-trigger-input-container,.ai-chat-widget-container.top-left .ai-chat-trigger-input-container{align-items:flex-start}.ai-chat-trigger-input-row{align-items:center;display:flex;gap:8px;transition:gap .4s cubic-bezier(.4,0,.2,1),width .4s cubic-bezier(.4,0,.2,1)}.ai-chat-widget-container.trigger-input-bar.is-collapsed .ai-chat-trigger-input-row{gap:4px}.ai-chat-trigger-input-expand{-webkit-font-smoothing:subpixel-antialiased;-moz-osx-font-smoothing:auto;align-items:center;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);-webkit-backface-visibility:hidden;backface-visibility:hidden;background:var(--trigger-bg,rgba(0,0,0,.04));border:1px solid var(--trigger-border,rgba(0,0,0,.12));border-radius:50%;box-shadow:0 2px 12px rgba(0,0,0,.12);color:var(--trigger-text-muted,rgba(0,0,0,.5));cursor:pointer;display:flex;flex-shrink:0;height:48px;justify-content:center;padding:0;-webkit-transform:translateZ(0);transform:translateZ(0);transition:all .2s ease,color .4s ease,background .4s ease,border-color .4s ease;width:48px;will-change:transform}.ai-chat-trigger-input-expand:hover{background:var(--trigger-bg-hover,rgba(0,0,0,.08));color:var(--trigger-text,#1a1a1a);transform:translateY(-2px)}.ai-chat-trigger-input-expand:active{transform:translateY(0)}.ai-chat-trigger-input-expand svg{stroke-width:2.5;height:20px;width:20px}.ai-chat-trigger-input-wrapper{flex:1;min-width:120px;position:relative;transform-origin:right center;transition:flex .4s cubic-bezier(.4,0,.2,1),width .4s cubic-bezier(.4,0,.2,1),opacity .3s cubic-bezier(.4,0,.2,1),transform .4s cubic-bezier(.4,0,.2,1);z-index:1}.ai-chat-widget-container.bottom-left .ai-chat-trigger-input-wrapper,.ai-chat-widget-container.top-left .ai-chat-trigger-input-wrapper{transform-origin:left center}.ai-chat-trigger-input{-webkit-font-smoothing:subpixel-antialiased;-moz-osx-font-smoothing:auto;backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);-webkit-backface-visibility:hidden;backface-visibility:hidden;background:var(--trigger-bg,rgba(0,0,0,.04));border:1px solid var(--trigger-border,rgba(0,0,0,.12));border-radius:var(--radius-input,62px);box-shadow:0 4px 24px rgba(0,0,0,.15);box-sizing:border-box;color:var(--trigger-text,#1a1a1a);font-size:var(--text-md,15px);height:48px;outline:none;padding:6px 52px 6px 16px;-webkit-transform:translateZ(0);transform:translateZ(0);transition:all .2s ease,color .4s ease,background .4s ease,border-color .4s ease;width:100%}.ai-chat-trigger-input::placeholder{color:var(--trigger-text-muted,rgba(0,0,0,.5))}.ai-chat-trigger-input:focus{background:var(--trigger-bg-hover,rgba(0,0,0,.08));border-color:var(--trigger-border-hover,rgba(0,0,0,.2))}.ai-chat-trigger-input-btn{-webkit-font-smoothing:subpixel-antialiased;-moz-osx-font-smoothing:auto;align-items:center;-webkit-backface-visibility:hidden;backface-visibility:hidden;background:var(--primary-color,var(--button-color,#07f));border:none;border-radius:50%;box-shadow:0 2px 8px rgba(0,119,255,.3);color:var(--send-button-icon-color,var(--button-icon-color,#fff));cursor:pointer;display:flex;height:38px;justify-content:center;position:absolute;right:4px;top:50%;transform:translateY(-50%);transition:all .2s ease;width:38px;will-change:transform}.ai-chat-trigger-input-btn:hover:not(:disabled){box-shadow:0 4px 12px rgba(0,119,255,.4);transform:translateY(-50%) scale(1.05)}.ai-chat-trigger-input-btn:active:not(:disabled){transform:translateY(-50%) scale(.95)}.ai-chat-trigger-input-btn:disabled{box-shadow:none;cursor:not-allowed;opacity:.4}.ai-chat-trigger-input-btn svg{height:18px;width:18px}.ai-chat-widget-container.trigger-input-bar .ai-chat-trigger-input-row{width:min(380px,calc(100vw - 40px))}.ai-chat-widget-container.trigger-input-bar.size-medium .ai-chat-trigger-input-row{width:min(440px,calc(100vw - 40px))}.ai-chat-widget-container.trigger-input-bar.size-large .ai-chat-trigger-input-row{width:min(560px,calc(100vw - 40px))}.ai-chat-widget-container.trigger-input-bar .ai-chat-trigger-input-wrapper{flex:1;min-width:160px}.ai-chat-widget-container.trigger-input-bar.container-mode .ai-chat-trigger-input-container{position:absolute;width:min(380px,calc(100% - 40px))}.ai-chat-widget-container.trigger-input-bar.container-mode.size-small .ai-chat-trigger-input-container{width:min(380px,calc(100% - 40px))}.ai-chat-widget-container.trigger-input-bar.container-mode.size-medium .ai-chat-trigger-input-container{width:min(440px,calc(100% - 40px))}.ai-chat-widget-container.trigger-input-bar.container-mode.size-large .ai-chat-trigger-input-container{width:min(560px,calc(100% - 40px))}.ai-chat-widget-container.trigger-input-bar.container-mode.bottom-right .ai-chat-trigger-input-container{bottom:20px;left:auto;right:20px;top:auto}.ai-chat-widget-container.trigger-input-bar.container-mode.bottom-left .ai-chat-trigger-input-container{bottom:20px;left:20px;right:auto;top:auto}.ai-chat-widget-container.trigger-input-bar.container-mode.top-right .ai-chat-trigger-input-container{bottom:auto;left:auto;right:20px;top:20px}.ai-chat-widget-container.trigger-input-bar.container-mode.top-left .ai-chat-trigger-input-container{bottom:auto;left:20px;right:auto;top:20px}.ai-chat-widget-container.trigger-input-bar.container-mode .ai-chat-trigger-input-row{width:100%}.ai-chat-widget-container.trigger-input-bar.container-mode .ai-chat-trigger-input-wrapper{flex:1;min-width:120px}.ai-chat-widget-container.trigger-input-bar.is-collapsed .ai-chat-trigger-input-wrapper{opacity:0;overflow:hidden;pointer-events:none;transform:scaleX(0);width:0}.ai-chat-widget-container.trigger-input-bar{align-items:flex-end;display:flex;flex-direction:column;gap:12px}.ai-chat-widget-container.trigger-input-bar.bottom-left,.ai-chat-widget-container.trigger-input-bar.top-left{align-items:flex-start}.ai-chat-widget-container.trigger-input-bar .ai-chat-window{bottom:auto;left:auto;order:-1;position:relative;right:auto;top:auto}.ai-chat-widget-container.trigger-input-bar .ai-chat-window.size-small{max-width:calc(100vw - 40px);min-width:320px;width:380px}.ai-chat-widget-container.trigger-input-bar .ai-chat-window.size-medium{max-width:calc(100vw - 40px);min-width:380px;width:440px}.ai-chat-widget-container.trigger-input-bar .ai-chat-window.size-large{max-width:calc(100vw - 40px);min-width:440px;width:560px}.ai-chat-widget-container.trigger-input-bar.container-mode .ai-chat-window{max-width:calc(100% - 40px);position:absolute}.ai-chat-widget-container.trigger-input-bar.container-mode.bottom-right .ai-chat-window{bottom:20px;left:auto;right:20px;top:auto}.ai-chat-widget-container.trigger-input-bar.container-mode.bottom-left .ai-chat-window{bottom:20px;left:20px;right:auto;top:auto}.ai-chat-widget-container.trigger-input-bar.container-mode.top-right .ai-chat-window{bottom:auto;left:auto;right:20px;top:20px}.ai-chat-widget-container.trigger-input-bar.container-mode.top-left .ai-chat-window{bottom:auto;left:20px;right:auto;top:20px}.ai-chat-widget-container.trigger-input-bar.container-mode.size-small .ai-chat-window{max-width:calc(100% - 40px);width:380px}.ai-chat-widget-container.trigger-input-bar.container-mode.size-medium .ai-chat-window{max-width:calc(100% - 40px);width:440px}.ai-chat-widget-container.trigger-input-bar.container-mode.size-large .ai-chat-window{max-width:calc(100% - 40px);width:560px}.ai-chat-widget-container.trigger-input-bar.mobile-mode .ai-chat-trigger-input-container{width:calc(100% - 40px)}.ai-chat-widget-container.trigger-input-bar.mobile-mode .ai-chat-trigger-input-row{width:100%}.ai-chat-widget-container.trigger-input-bar.mobile-mode .ai-chat-trigger-input-wrapper{flex:1;min-width:120px}.ai-chat-widget-container.trigger-input-bar.mobile-mode.is-collapsed .ai-chat-trigger-input-container{width:auto}.ai-chat-widget-container.trigger-input-bar.mobile-mode.is-collapsed .ai-chat-trigger-input-row{gap:8px;justify-content:flex-end}.ai-chat-trigger-collapse-toggle{align-items:center;background:transparent;border:none;border-radius:50%;color:var(--trigger-text-muted,rgba(0,0,0,.5));cursor:pointer;display:flex;flex-shrink:0;height:24px;justify-content:center;margin-right:-4px;order:-1;padding:0;transition:all .2s ease;width:24px}.ai-chat-trigger-collapse-toggle:hover{color:var(--trigger-text,#1a1a1a)}.ai-chat-trigger-collapse-toggle svg{stroke-width:2.5;height:20px;transition:transform .4s cubic-bezier(.4,0,.2,1);width:20px}.ai-chat-widget-container.trigger-input-bar.bottom-left .ai-chat-trigger-collapse-toggle svg,.ai-chat-widget-container.trigger-input-bar.top-left .ai-chat-trigger-collapse-toggle svg{transform:rotate(180deg)}.ai-chat-trigger-input-expand{margin-left:-4px;order:1;transition:transform .2s ease,opacity .3s ease}.ai-chat-widget-container.container-mode .ai-chat-trigger-input-expand{margin-left:0}.ai-chat-trigger-input-expand svg{transition:transform .4s cubic-bezier(.4,0,.2,1)}.ai-chat-widget-container.trigger-input-bar .ai-chat-trigger-input-expand svg{transform:rotate(0deg)}.ai-chat-widget-container.bottom-left .ai-chat-trigger-collapse-toggle,.ai-chat-widget-container.top-left .ai-chat-trigger-collapse-toggle{margin-left:-4px;margin-right:0;order:1}.ai-chat-widget-container.bottom-left .ai-chat-trigger-input-expand,.ai-chat-widget-container.top-left .ai-chat-trigger-input-expand{margin-left:0;margin-right:-4px;order:-1}.ai-chat-widget-container.trigger-input-bar .ai-chat-trigger-input-row .ai-chat-button{order:1}.ai-chat-widget-container.trigger-input-bar.bottom-left .ai-chat-trigger-input-row .ai-chat-button,.ai-chat-widget-container.trigger-input-bar.top-left .ai-chat-trigger-input-row .ai-chat-button{order:-1}.ai-chat-widget-container.trigger-input-bar.is-collapsed.bottom-right .ai-chat-button,.ai-chat-widget-container.trigger-input-bar.is-collapsed.top-right .ai-chat-button{margin-right:16px}.ai-chat-widget-container.trigger-input-bar.is-collapsed.bottom-left .ai-chat-button,.ai-chat-widget-container.trigger-input-bar.is-collapsed.top-left .ai-chat-button{margin-left:16px}.ai-chat-widget-container.trigger-input-bar.is-collapsed .ai-chat-trigger-input-row{flex-direction:row;justify-content:flex-end}.ai-chat-widget-container.trigger-input-bar.is-collapsed.bottom-left .ai-chat-trigger-input-row,.ai-chat-widget-container.trigger-input-bar.is-collapsed.top-left .ai-chat-trigger-input-row{justify-content:flex-start}.ai-chat-widget-container.trigger-input-bar .ai-chat-button{display:flex;opacity:1;transform:scale(1);transition:transform .4s cubic-bezier(.4,0,.2,1),opacity .3s cubic-bezier(.4,0,.2,1),width .4s cubic-bezier(.4,0,.2,1),height .4s cubic-bezier(.4,0,.2,1)}.ai-chat-widget-container.trigger-input-bar:not(.is-collapsed) .ai-chat-button{border:none;height:0;margin:0;min-width:0;opacity:0;overflow:hidden;padding:0;pointer-events:none;transform:scale(0);width:0}.ai-chat-widget-container.trigger-pill-text .ai-chat-button{display:none}.ai-chat-widget-container.trigger-pill-text.is-open{gap:8px}.ai-chat-widget.light .ai-chat-trigger-pill:not(.is-open){backdrop-filter:none;-webkit-backdrop-filter:none;background:#fff;border:1px solid rgba(0,0,0,.15);box-shadow:0 2px 8px rgba(0,0,0,.08);color:#18181b}.ai-chat-widget.light .ai-chat-trigger-pill:not(.is-open):hover{background:#fafafa;border-color:rgba(0,0,0,.2)}.ai-chat-widget.light .ai-chat-trigger-input-expand{backdrop-filter:none;-webkit-backdrop-filter:none;background:#fff;border:1px solid rgba(0,0,0,.15);box-shadow:0 2px 8px rgba(0,0,0,.08);color:#52525b}.ai-chat-widget.light .ai-chat-trigger-input-expand:hover{background:#fafafa;color:#18181b}.ai-chat-widget.light .ai-chat-trigger-input{backdrop-filter:none;-webkit-backdrop-filter:none;background:#fff;border:1px solid rgba(0,0,0,.15);box-shadow:0 2px 8px rgba(0,0,0,.08);color:#18181b}.ai-chat-widget.light .ai-chat-trigger-input::placeholder{color:#71717a}.ai-chat-widget.light .ai-chat-trigger-input:focus{background:#fff;border-color:rgba(0,0,0,.25)}.ai-chat-widget.light .ai-chat-trigger-collapse-toggle{color:#71717a}.ai-chat-widget.light .ai-chat-trigger-collapse-toggle:hover{color:#18181b}.ai-chat-widget.dark .ai-chat-trigger-pill:not(.is-open){backdrop-filter:none;-webkit-backdrop-filter:none;background:#27272a;border:1px solid hsla(0,0%,100%,.15);box-shadow:0 2px 8px rgba(0,0,0,.3);color:#fafafa}.ai-chat-widget.dark .ai-chat-trigger-pill:not(.is-open):hover{background:#3f3f46;border-color:hsla(0,0%,100%,.25)}.ai-chat-widget.dark .ai-chat-trigger-input-expand{backdrop-filter:none;-webkit-backdrop-filter:none;background:#27272a;border:1px solid hsla(0,0%,100%,.15);box-shadow:0 2px 8px rgba(0,0,0,.3);color:#a1a1aa}.ai-chat-widget.dark .ai-chat-trigger-input-expand:hover{background:#3f3f46;color:#fafafa}.ai-chat-widget.dark .ai-chat-trigger-input{backdrop-filter:none;-webkit-backdrop-filter:none;background:#27272a;border:1px solid hsla(0,0%,100%,.15);box-shadow:0 2px 8px rgba(0,0,0,.3);color:#fafafa}.ai-chat-widget.dark .ai-chat-trigger-input::placeholder{color:#71717a}.ai-chat-widget.dark .ai-chat-trigger-input:focus{background:#27272a;border-color:hsla(0,0%,100%,.25)}.ai-chat-widget.dark .ai-chat-trigger-collapse-toggle{color:#71717a}.ai-chat-widget.dark .ai-chat-trigger-collapse-toggle:hover{color:#fafafa}.ai-chat-input-container{background:var(--bg-primary,#fff);bottom:0;left:0;padding:8px 0 16px;position:absolute;right:0;z-index:10}.ai-chat-widget.dark .ai-chat-input-container{background:var(--bg-primary,#282625)}.ai-chat-input-container.separate{padding:0 var(--radius-window-gutter,16px) var(--radius-window-gutter,16px)}.ai-chat-input-wrapper{-webkit-font-smoothing:subpixel-antialiased;-moz-osx-font-smoothing:auto;align-items:flex-end;-webkit-backface-visibility:hidden;backface-visibility:hidden;background:var(--input-bg,#f4f4f4);border:1px solid var(--input-border,#d3d3d3);border-radius:var(--radius-input,62px);box-sizing:border-box;display:flex;gap:0;height:52px;overflow:hidden;padding:6px 6px 6px 16px;position:relative;-webkit-transform:translateZ(0);transform:translateZ(0);transition:all var(--duration-fast,.15s) ease;will-change:transform;z-index:5}.ai-chat-input-wrapper.multiline{border-radius:14px!important;min-height:64px;padding:10px 10px 10px 14px}.ai-chat-widget.dark .ai-chat-input-wrapper{background:var(--input-bg,#4a4846);border-color:var(--input-border,#5d5b5b);border-width:.7px;box-shadow:var(--shadow-input,0 0 10px rgba(0,0,0,.15))}.ai-chat-input-wrapper:focus-within{border-color:var(--text-muted,#a1a1aa)}.ai-chat-input{word-wrap:break-word!important;background:transparent!important;border:none!important;border-radius:0!important;box-shadow:none!important;box-sizing:border-box!important;color:var(--input-text,#000)!important;flex:1!important;font-family:inherit!important;font-size:16px!important;height:40px!important;line-height:20px!important;margin:0!important;max-height:40px!important;min-height:40px!important;min-width:0!important;outline:none!important;overflow-wrap:anywhere!important;overflow-x:hidden!important;overflow-y:auto!important;padding:10px var(--space-sm,8px)!important;resize:none!important;white-space:pre-wrap!important;width:0!important;word-break:break-word!important}.ai-chat-widget.dark .ai-chat-input{color:var(--input-text,#fff)}.ai-chat-input::placeholder{color:var(--text-placeholder,#a1a1aa)}.ai-chat-widget.dark .ai-chat-input::placeholder{color:var(--text-placeholder,#52525b)}.ai-chat-file-button{align-items:center;align-self:center;background:transparent;border:none;color:var(--text-placeholder);cursor:pointer;display:flex;flex-shrink:0;height:28px;justify-content:center;padding:0;transition:color var(--duration-fast) ease;width:28px}.ai-chat-file-button:hover{color:var(--text-secondary)}.ai-chat-file-button:disabled{cursor:not-allowed;opacity:.5}.ai-chat-send-button{-webkit-font-smoothing:subpixel-antialiased;-moz-osx-font-smoothing:auto;align-items:center;align-self:center;-webkit-backface-visibility:hidden;backface-visibility:hidden;background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#151515))));border:none;border-radius:50%;color:var(--send-button-icon-color,var(--button-icon-color,var(--btn-primary-text,#f4f4f4)));cursor:pointer;display:flex;flex-shrink:0;height:40px;justify-content:center;min-height:40px;min-width:40px;padding:0;-webkit-transform:translateZ(0);transform:translateZ(0);transition:all var(--duration-fast,.15s) ease;width:40px;will-change:transform,opacity}.ai-chat-widget.dark .ai-chat-send-button{background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#fff))));color:var(--send-button-icon-color,var(--button-icon-color,var(--btn-primary-text,#312f2d)))}.ai-chat-send-button.active{background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#151515))));color:var(--send-button-icon-color,var(--button-icon-color,var(--btn-primary-text,#f4f4f4)))}.ai-chat-widget.dark .ai-chat-send-button.active{background:var(--send-button-background,var(--primary-color,var(--button-color,var(--btn-primary-bg,#fff))));color:var(--send-button-icon-color,var(--button-icon-color,var(--btn-primary-text,#312f2d)))}.ai-chat-send-button:hover:not(:disabled){opacity:.8}.ai-chat-send-button:active:not(:disabled){transform:scale(.95)}.ai-chat-send-button:disabled{cursor:not-allowed;opacity:.3}.ai-chat-file-list{display:flex;flex-wrap:wrap;gap:var(--space-sm);padding:var(--space-sm) var(--space-sm)}.ai-chat-file-item{align-items:center;background:rgba(0,0,0,.05);border-radius:6px;display:flex;font-size:var(--text-xs);gap:var(--space-sm);padding:6px 10px}.ai-chat-file-extension{background:var(--btn-primary-bg);border-radius:3px;color:var(--btn-primary-text);display:inline-block;font-size:10px;font-weight:var(--font-weight-semibold);min-width:40px;padding:2px 6px;text-align:center;text-transform:uppercase}.ai-chat-file-info{display:flex;flex:1;flex-direction:column;gap:2px;min-width:0}.ai-chat-file-name{font-weight:var(--font-weight-medium);max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-file-size{color:var(--text-muted);font-size:10px;opacity:.7}.ai-chat-file-remove{align-items:center;background:none;border:none;color:inherit;cursor:pointer;display:flex;justify-content:center;opacity:.5;padding:var(--space-xs);transition:opacity var(--duration-fast) ease}.ai-chat-file-remove:hover{opacity:1}.ai-chat-data-policy{bottom:2px;color:var(--text-muted,#71717a);font-size:9px;left:0;line-height:1.4;opacity:.5;pointer-events:auto;position:absolute;right:0;text-align:center}.ai-chat-widget.dark .ai-chat-data-policy{color:var(--text-muted,#a1a1aa)}.ai-chat-data-policy-link{background:none;border:none;color:var(--text-muted,#71717a);cursor:pointer;font-family:inherit;font-size:inherit;margin:0;padding:0;text-decoration:underline;text-underline-offset:2px;transition:color .15s ease}.ai-chat-data-policy-link:hover{color:var(--text-secondary,#52525b)}.ai-chat-widget.dark .ai-chat-data-policy-link{color:var(--text-muted,#a1a1aa)}.ai-chat-widget.dark .ai-chat-data-policy-link:hover{color:var(--text-secondary,#d4d4d8)}.ai-chat-page-disclaimer{align-items:center;color:var(--text-muted,#71717a);display:flex;font-size:10px;gap:4px;justify-content:center;line-height:1.4;opacity:.7;padding:8px 16px;text-align:center}.ai-chat-widget.dark .ai-chat-page-disclaimer{color:var(--text-muted,#a1a1aa)}.ai-chat-page-disclaimer-link{background:none;border:none;color:var(--text-muted,#71717a);cursor:pointer;font-family:inherit;font-size:inherit;margin:0;padding:0;text-decoration:underline;text-underline-offset:2px;transition:color .15s ease}.ai-chat-page-disclaimer-link:hover{color:var(--text-secondary,#52525b)}.ai-chat-widget.dark .ai-chat-page-disclaimer-link{color:var(--text-muted,#a1a1aa)}.ai-chat-widget.dark .ai-chat-page-disclaimer-link:hover{color:var(--text-secondary,#d4d4d8)}.ai-chat-messages{-webkit-overflow-scrolling:touch;-ms-overflow-style:none;align-items:stretch;background:var(--bg-primary,#fff);display:flex;flex:1;flex-direction:column;gap:var(--space-md,16px);justify-content:flex-start;min-height:0;overflow-x:hidden;overflow-y:auto;padding:0 var(--space-md,16px) 100px;position:relative;scroll-behavior:smooth;scrollbar-width:none}.ai-chat-widget.dark .ai-chat-messages{background:var(--bg-primary,#18181b)}.ai-chat-messages::-webkit-scrollbar{display:none}.ai-chat-message{animation:ai-chat-message-slide-in .2s var(--spring-bounce);display:flex;flex-direction:column;max-width:90%}.ai-chat-message.user{align-items:flex-end;align-self:flex-end;animation:ai-chat-user-message-sent .35s var(--spring-bounce)}.ai-chat-message.assistant{align-items:flex-start;align-self:flex-start;max-width:100%;width:100%}.ai-chat-message.tool{align-self:stretch;max-width:none;padding:0}.ai-chat-message-content{word-wrap:break-word;border-radius:18px;font-size:var(--text-md,15px);line-height:var(--line-height-relaxed,1.6);max-width:100%;overflow-wrap:break-word;padding:8px 14px;word-break:break-word}.ai-chat-message.user .ai-chat-message-content{background:var(--user-bg,#f4f3f0);border-radius:18px;color:var(--user-text,#000)}.ai-chat-widget.dark .ai-chat-message.user .ai-chat-message-content{background:var(--user-bg,#484848);color:var(--user-text,#fff)}.ai-chat-message.assistant .ai-chat-message-content{background:var(--agent-bg,transparent);box-sizing:border-box;color:var(--agent-text,#000);padding:0;width:100%}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content{color:var(--agent-text,#fff)}.ai-chat-message-meta{align-items:center;display:flex;gap:var(--space-sm,8px);margin-top:var(--space-xs,4px);padding:0 var(--space-xs,4px)}.ai-chat-message.user .ai-chat-message-meta{justify-content:flex-end}.ai-chat-message.assistant .ai-chat-message-meta{justify-content:flex-start}.ai-chat-message-timestamp{color:var(--text-muted,#71717a);font-size:var(--text-xs,12px)}.ai-chat-welcome{animation:ai-chat-welcome-fade-in .3s var(--spring-smooth);display:flex;flex-direction:column;gap:var(--space-md,16px);padding:var(--space-lg,24px) 0}.ai-chat-welcome-title{color:var(--text-primary,#3e3e3e);font-size:var(--text-2xl,28px);font-weight:var(--font-weight-bold,700);line-height:var(--line-height-tight,1.3)}.ai-chat-widget.dark .ai-chat-welcome-title{color:var(--text-primary,#fff)}.ai-chat-welcome-text{color:var(--text-secondary,#000);font-size:var(--text-md,15px);line-height:var(--line-height-relaxed,1.6);max-width:100%}.ai-chat-widget.dark .ai-chat-welcome-text{color:var(--text-secondary,#fff)}.ai-chat-typing{align-items:center;display:flex;gap:var(--space-xs,4px);padding:var(--space-sm,8px) var(--space-md,16px)}.ai-chat-typing-dot{animation:ai-chat-typing-bounce 1.4s ease-in-out infinite both;background:var(--text-muted,#71717a);border-radius:50%;height:8px;width:8px}.ai-chat-typing-dot:first-child{animation-delay:-.32s}.ai-chat-typing-dot:nth-child(2){animation-delay:-.16s}.ai-chat-typing-dot:nth-child(3){animation-delay:0s}@keyframes ai-chat-typing-bounce{0%,80%,to{opacity:.4;transform:scale(.6)}40%{opacity:1;transform:scale(1)}}.ai-chat-scroll-button{align-items:center;background:var(--bg-secondary,#f4f4f5);border:1px solid var(--border-subtle,rgba(0,0,0,.1));border-radius:50%;bottom:80px;box-shadow:0 2px 8px rgba(0,0,0,.1);color:var(--text-secondary,#71717a);cursor:pointer;display:flex;height:36px;justify-content:center;left:50%;opacity:0;pointer-events:none;position:absolute;transform:translateX(-50%);transition:background .15s ease,box-shadow .15s ease,opacity .15s ease,visibility .15s ease;visibility:hidden;width:36px;z-index:15}.ai-chat-scroll-button.visible{opacity:1;pointer-events:auto;visibility:visible}.ai-chat-scroll-button:hover{background:var(--bg-tertiary,#e4e4e7);box-shadow:0 4px 12px rgba(0,0,0,.15)}.ai-chat-scroll-button:active{background:var(--bg-tertiary,#d4d4d8)}.ai-chat-widget.dark .ai-chat-scroll-button{background:var(--bg-secondary,#3f3f46);border-color:var(--border-subtle,hsla(0,0%,100%,.1));box-shadow:0 2px 8px rgba(0,0,0,.3);color:var(--text-secondary,#a1a1aa)}.ai-chat-widget.dark .ai-chat-scroll-button:hover{background:var(--bg-tertiary,#52525b);box-shadow:0 4px 12px rgba(0,0,0,.4)}.ai-chat-error{background:var(--bg-secondary);border-radius:var(--radius-chat-bubble);color:var(--text-primary);font-size:var(--text-md);margin:0 auto;padding:10px var(--space-md)}.ai-chat-message.assistant .ai-chat-message-content p{margin:0 0 var(--space-sm) 0}.ai-chat-message.assistant .ai-chat-message-content p:last-child{margin-bottom:0}.ai-chat-message.assistant .ai-chat-message-content h1{font-size:1.5em}.ai-chat-message.assistant .ai-chat-message-content h1,.ai-chat-message.assistant .ai-chat-message-content h2{color:var(--text-primary,#3e3e3e);font-weight:var(--font-weight-bold,700);line-height:var(--line-height-tight,1.3);margin:var(--space-md,16px) 0 var(--space-sm,8px) 0}.ai-chat-message.assistant .ai-chat-message-content h2{font-size:1.3em}.ai-chat-message.assistant .ai-chat-message-content h3{color:var(--text-primary,#3e3e3e);font-size:1.15em;font-weight:var(--font-weight-semibold,600);line-height:var(--line-height-tight,1.3);margin:var(--space-sm,8px) 0 var(--space-xs,4px) 0}.ai-chat-message.assistant .ai-chat-message-content h4,.ai-chat-message.assistant .ai-chat-message-content h5,.ai-chat-message.assistant .ai-chat-message-content h6{color:var(--text-primary,#3e3e3e);font-size:1em;font-weight:var(--font-weight-semibold,600);line-height:var(--line-height-tight,1.3);margin:var(--space-sm,8px) 0 var(--space-xs,4px) 0}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content h1,.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content h2,.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content h3,.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content h4,.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content h5,.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content h6{color:var(--text-primary,#fff)}.ai-chat-message.assistant .ai-chat-message-content>h1:first-child,.ai-chat-message.assistant .ai-chat-message-content>h2:first-child,.ai-chat-message.assistant .ai-chat-message-content>h3:first-child,.ai-chat-message.assistant .ai-chat-message-content>h4:first-child,.ai-chat-message.assistant .ai-chat-message-content>h5:first-child,.ai-chat-message.assistant .ai-chat-message-content>h6:first-child{margin-top:0}.ai-chat-message.assistant .ai-chat-message-content ul{list-style-type:disc;margin:var(--space-sm,8px) 0;padding-left:var(--space-lg,24px)}.ai-chat-message.assistant .ai-chat-message-content ul ul{list-style-type:circle;margin:var(--space-xs,4px) 0}.ai-chat-message.assistant .ai-chat-message-content ul ul ul{list-style-type:square}.ai-chat-message.assistant .ai-chat-message-content ol{list-style-type:decimal;margin:var(--space-sm,8px) 0;padding-left:var(--space-lg,24px)}.ai-chat-message.assistant .ai-chat-message-content ol ol{list-style-type:lower-alpha;margin:var(--space-xs,4px) 0}.ai-chat-message.assistant .ai-chat-message-content ol ol ol{list-style-type:lower-roman}.ai-chat-message.assistant .ai-chat-message-content li{margin-bottom:var(--space-xs,4px);padding-left:var(--space-xs,4px)}.ai-chat-message.assistant .ai-chat-message-content li:last-child{margin-bottom:0}.ai-chat-message.assistant .ai-chat-message-content li>ol,.ai-chat-message.assistant .ai-chat-message-content li>ul{margin-top:var(--space-xs,4px)}.ai-chat-message.assistant .ai-chat-message-content code{background:rgba(0,0,0,.05);border-radius:var(--radius-sm);font-family:SF Mono,Monaco,Cascadia Code,monospace;font-size:.9em;padding:2px 6px}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content code{background:hsla(0,0%,100%,.1)}.ai-chat-message.assistant .ai-chat-message-content pre{background:rgba(0,0,0,.05);border-radius:var(--radius-md);margin:var(--space-sm) 0;overflow-x:auto;padding:var(--space-sm)}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content pre{background:hsla(0,0%,100%,.05)}.ai-chat-message.assistant .ai-chat-message-content pre code{background:transparent;padding:0}.ai-chat-message.assistant .ai-chat-message-content a{color:var(--btn-primary-bg);text-decoration:underline}.ai-chat-message.assistant .ai-chat-message-content strong{font-weight:var(--font-weight-semibold)}.ai-chat-message.assistant .ai-chat-message-content blockquote{border-left:3px solid var(--border-default);color:var(--text-muted);margin:var(--space-sm) 0;padding-left:var(--space-md)}.ai-chat-message.assistant .ai-chat-message-content hr{border:none;border-top:1px solid var(--border-subtle,rgba(0,0,0,.1));margin:var(--space-lg,24px) 0}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content hr{border-top-color:var(--border-subtle,hsla(0,0%,100%,.1))}.ai-chat-message.assistant .ai-chat-message-content .table-wrapper{border:1px solid var(--border-subtle,rgba(0,0,0,.1));border-radius:var(--radius-md,8px);box-sizing:border-box;display:block;margin:var(--space-sm) var(--space-sm);max-width:100%;overflow:hidden;width:auto}.ai-chat-message.assistant .ai-chat-message-content .table-scroll{max-width:100%;overflow-x:auto;overflow-y:hidden;width:100%}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content .table-wrapper{border-color:var(--border-subtle,hsla(0,0%,100%,.1))}.ai-chat-message.assistant .ai-chat-message-content table{border-collapse:collapse;font-size:var(--text-sm);min-width:100%;width:max-content}.ai-chat-message.assistant .ai-chat-message-content td,.ai-chat-message.assistant .ai-chat-message-content th{border-bottom:1px solid var(--border-subtle,rgba(0,0,0,.1));border-right:1px solid var(--border-subtle,rgba(0,0,0,.1));padding:var(--space-sm);text-align:left}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content td,.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content th{border-color:var(--border-subtle,hsla(0,0%,100%,.1))}.ai-chat-message.assistant .ai-chat-message-content td:last-child,.ai-chat-message.assistant .ai-chat-message-content th:last-child{border-right:none}.ai-chat-message.assistant .ai-chat-message-content tr:last-child td{border-bottom:none}.ai-chat-message.assistant .ai-chat-message-content th{background:rgba(0,0,0,.03);font-weight:var(--font-weight-semibold);white-space:nowrap}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content th{background:hsla(0,0%,100%,.05)}.ai-chat-message.assistant .ai-chat-message-content tbody tr:nth-child(2n){background:rgba(0,0,0,.02)}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content tbody tr:nth-child(2n){background:hsla(0,0%,100%,.03)}.ai-chat-message.assistant.streaming .ai-chat-message-content>ol:last-child>li:last-child,.ai-chat-message.assistant.streaming .ai-chat-message-content>p:last-child,.ai-chat-message.assistant.streaming .ai-chat-message-content>ul:last-child>li:last-child{animation:ai-chat-text-fade-in .3s ease-out}@keyframes ai-chat-text-fade-in{0%{opacity:0}to{opacity:1}}.ai-chat-suggested-questions{align-self:flex-end;margin:0;padding:16px 0 0;width:100%}.ai-chat-suggested-questions-list{align-items:center;display:flex;flex-wrap:wrap;gap:6px;justify-content:flex-end}.ai-chat-suggested-question{align-items:center;background:transparent;border:1px solid var(--border-default,#d4d4d8);border-radius:var(--radius-preset-badge,18px);color:var(--text-primary,#18181b);cursor:pointer;display:inline-flex;font-size:14px;font-weight:400;gap:6px;justify-content:center;line-height:1.3;max-width:100%;overflow:hidden;padding:8px 14px;text-overflow:ellipsis;transition:background .15s ease,border-color .15s ease,transform .1s ease;white-space:nowrap}.ai-chat-widget.dark .ai-chat-suggested-question{background:transparent;border-color:var(--border-subtle,#52525b);color:var(--text-primary,#fafafa)}.ai-chat-suggested-question-text{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-suggested-question:hover{background:var(--bg-hover,#f4f4f5);border-color:var(--border-default,#d4d4d8)}.ai-chat-widget.dark .ai-chat-suggested-question:hover{background:var(--bg-hover,#3f3f46);border-color:var(--border-subtle,#52525b)}.ai-chat-suggested-question:active{transform:scale(.98)}.ai-chat-suggested-question.action-type{border:none}.ai-chat-suggested-question.action-type,.ai-chat-widget.dark .ai-chat-suggested-question.action-type{background:var(--primary-color,var(--button-color,#ef4444));color:var(--button-icon-color,#fff)}.ai-chat-suggested-question.action-type:hover{background:var(--primary-color,var(--button-color,#ef4444));opacity:.9}.ai-chat-suggested-question-icon{align-items:center;display:flex;flex-shrink:0;justify-content:center}.ai-chat-suggested-question:not(.action-type) .ai-chat-suggested-question-icon{display:none}.ai-chat-widget-container.container-mode.trigger-input-bar .ai-chat-suggested-questions{box-sizing:border-box;margin:0;padding:16px 0 0;width:100%}.ai-chat-widget-container.container-mode.trigger-input-bar .ai-chat-suggested-questions-list{box-sizing:border-box;display:flex;flex-wrap:wrap;gap:6px}.ai-chat-widget-container.container-mode.trigger-input-bar.bottom-right .ai-chat-suggested-questions-list,.ai-chat-widget-container.container-mode.trigger-input-bar.top-right .ai-chat-suggested-questions-list{justify-content:flex-end;margin-left:auto;margin-right:0;padding-right:0}.ai-chat-widget-container.container-mode.trigger-input-bar.bottom-left .ai-chat-suggested-questions-list,.ai-chat-widget-container.container-mode.trigger-input-bar.top-left .ai-chat-suggested-questions-list{justify-content:flex-start;margin-left:0;margin-right:auto;padding-left:0}.ai-chat-widget-container.container-mode.trigger-input-bar.size-small .ai-chat-suggested-questions-list{max-width:calc(100% - 132px);width:348px}.ai-chat-widget-container.container-mode.trigger-input-bar.size-medium .ai-chat-suggested-questions-list{max-width:calc(100% - 132px);width:408px}.ai-chat-widget-container.container-mode.trigger-input-bar.size-large .ai-chat-suggested-questions-list{max-width:calc(100% - 132px);width:528px}.ai-chat-follow-up-suggestions{box-sizing:border-box;margin:0;padding:8px 16px 0;width:100%}.ai-chat-follow-up-list{align-items:flex-end;display:flex;flex-direction:column;gap:6px}.ai-chat-follow-up-item{align-items:center;animation:followUpFadeIn .25s ease-out forwards;background:var(--primary-color,var(--button-color,#07f));border:none;border-radius:var(--radius-preset-badge,18px);color:var(--button-icon-color,#fff);cursor:pointer;display:inline-flex;font-size:14px;font-weight:400;gap:6px;justify-content:center;line-height:1.3;max-width:100%;overflow:hidden;padding:8px 14px;text-overflow:ellipsis;white-space:nowrap}@keyframes followUpFadeIn{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.ai-chat-widget.dark .ai-chat-follow-up-item{background:var(--primary-color,var(--button-color,#07f));color:var(--button-icon-color,#fff)}.ai-chat-follow-up-item:hover{opacity:.9}.ai-chat-follow-up-item:active{transform:scale(.98)}.ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-default,#d4d4d8);color:var(--text-primary,#18181b)}.ai-chat-widget.dark .ai-chat-follow-up-item.question-type,.dark .ai-chat-follow-up-item.question-type,[data-color-mode=dark] .ai-chat-follow-up-item.question-type,[data-theme=dark] .ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-subtle,#52525b);color:var(--text-primary,#fafafa)}@media (prefers-color-scheme:dark){.ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-subtle,#52525b);color:var(--text-primary,#fafafa)}}.ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#f4f4f5);opacity:1}.ai-chat-widget.dark .ai-chat-follow-up-item.question-type:hover,.dark .ai-chat-follow-up-item.question-type:hover,[data-color-mode=dark] .ai-chat-follow-up-item.question-type:hover,[data-theme=dark] .ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#3f3f46);opacity:1}@media (prefers-color-scheme:dark){.ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#3f3f46);opacity:1}}.ai-chat-follow-up-item.action-type{background:var(--primary-color,var(--button-color,#07f));border:none;color:var(--button-icon-color,#fff)}.ai-chat-follow-up-icon{align-items:center;display:flex;flex-shrink:0;justify-content:center}.ai-chat-follow-up-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-feedback-buttons{align-items:center;display:flex;gap:var(--space-xs)}.ai-chat-feedback{align-items:center;display:inline-flex;gap:0;height:20px}.ai-chat-feedback-button{align-items:center;background:transparent!important;border:none;border-radius:var(--radius-sm);color:var(--text-placeholder);cursor:pointer;display:flex;font-size:var(--text-sm);height:20px;justify-content:center;padding:var(--space-xs);transition:all var(--duration-fast) var(--spring-bounce)}.ai-chat-feedback-button:hover:not(:disabled){background:none!important;color:var(--text-secondary)}.ai-chat-feedback-button:active:not(:disabled){transform:scale(.9)}.ai-chat-feedback-button:disabled{cursor:not-allowed;opacity:.4}.ai-chat-feedback-button.active{background:none!important;color:var(--text-primary)}.ai-chat-feedback.submitted{align-items:center;animation:ai-chat-feedback-morph .3s var(--spring-bounce);gap:var(--space-xs)}.ai-chat-feedback-message{align-items:center;display:flex;gap:4px;margin-left:var(--space-xxs)}.ai-chat-feedback-checkmark{animation:ai-chat-checkmark-pop .3s var(--spring-bounce);color:#10b981;font-size:var(--text-md);font-weight:700}.ai-chat-feedback-text{color:#10b981;font-size:var(--text-xs);font-weight:var(--font-weight-medium)}.ai-chat-history-panel{background:var(--bg-primary,#fff);display:flex;flex:1;flex-direction:column;overflow:hidden}.ai-chat-widget.dark .ai-chat-history-panel{background:var(--bg-primary,#18181b)}.ai-chat-history-empty,.ai-chat-history-loading{align-items:center;color:var(--text-muted);display:flex;flex:1;font-size:var(--text-sm);justify-content:center;padding:var(--space-lg);text-align:center}.ai-chat-history-list{-ms-overflow-style:none;display:flex;flex:1;flex-direction:column;gap:var(--space-sm);overflow-y:auto;padding:var(--space-xs) var(--space-md) 120px;scrollbar-width:none}.ai-chat-history-list::-webkit-scrollbar{display:none}.ai-chat-history-list.exiting{animation:ai-chat-history-exit .22s var(--spring-smooth) forwards}.ai-chat-history-item{align-items:center;background:var(--user-bg,#f4f4f5);border-radius:var(--radius-history-item,15px);display:flex;flex:0 0 auto;flex-direction:row;height:var(--history-item-height,36px);margin:0;overflow:hidden;transition:background var(--duration-fast,.15s) ease;width:100%}.ai-chat-history-item-content{align-items:center;background:transparent;border:none;cursor:pointer;display:flex;flex:1;flex-direction:row;height:100%;min-width:0;padding:0 var(--space-xs,4px) 0 var(--space-md,16px);text-align:left}.ai-chat-widget.dark .ai-chat-history-item{background:var(--user-bg,#27272a)}.ai-chat-history-item:hover{background:var(--user-bg-hover,#e5e7eb)}.ai-chat-widget.dark .ai-chat-history-item:hover{background:var(--user-bg-hover,#3f3f46)}.ai-chat-history-item.active{background:var(--user-bg-hover,#e5e7eb)}.ai-chat-widget.dark .ai-chat-history-item.active{background:var(--user-bg-hover,#3f3f46)}.ai-chat-history-item-preview{color:var(--text-primary,#18181b);flex:1;font-size:var(--text-sm,14px);font-weight:var(--font-weight-medium,500);line-height:var(--line-height-normal,1.4);margin-bottom:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-widget.dark .ai-chat-history-item-preview{color:var(--text-primary,#fafafa)}.ai-chat-history-item.active .ai-chat-history-item-preview{font-weight:var(--font-weight-medium)}.ai-chat-history-item-meta{display:none}.ai-chat-history-item-delete{align-items:center;background:transparent;border:none;border-radius:var(--radius-sm,6px);color:var(--text-muted,#71717a);cursor:pointer;display:flex;flex-shrink:0;height:24px;justify-content:center;margin-left:auto;margin-right:var(--space-xs,4px);opacity:0;transition:opacity var(--duration-fast,.15s) ease,background var(--duration-fast,.15s) ease,color var(--duration-fast,.15s) ease;width:24px}.ai-chat-history-item-delete svg{height:14px;width:14px}.ai-chat-history-item:hover .ai-chat-history-item-delete{opacity:1}.ai-chat-history-item-delete:hover{background:rgba(239,68,68,.1);color:#ef4444}.ai-chat-widget.dark .ai-chat-history-item-delete:hover{background:rgba(239,68,68,.2);color:#f87171}.ai-chat-tool-row{align-items:center;display:flex;gap:10px;margin:2px 0;padding:0}.ai-chat-tool-gear{color:#1f2937;flex-shrink:0;height:20px;width:20px}.ai-chat-tool-gear.spinning{animation:ai-chat-gear-spin 1.5s linear infinite}.ai-chat-tool-badges{align-items:center;display:flex;flex-wrap:wrap;gap:8px}.ai-chat-tool-badge{align-items:center;background:#e5e7eb;border:1px solid #d1d5db;border-radius:var(--radius-action-badge,8px);color:#1f2937;display:inline-flex;font-size:12px;font-weight:500;gap:4px;line-height:1.2;padding:5px 12px;transition:all .2s ease;white-space:nowrap}.ai-chat-tool-badge.loading{animation:ai-chat-tool-gradient 2s linear infinite;background:linear-gradient(90deg,var(--tool-loading-bg-1,#e0e0e0) 0,var(--tool-loading-bg-2,#f0f0f0) 25%,var(--tool-loading-bg-3,#fff) 50%,var(--tool-loading-bg-2,#f0f0f0) 75%,var(--tool-loading-bg-1,#e0e0e0) 100%);background-size:200% 100%;color:var(--tool-loading-text,#1a1a1a);position:relative}.ai-chat-widget:not(.dark) .ai-chat-tool-badge.loading{--tool-loading-bg-1:#2a2a2a;--tool-loading-bg-2:#3a3a3a;--tool-loading-bg-3:#4a4a4a;--tool-loading-text:#fff}.ai-chat-tool-badge.completed{background:#e5e7eb;border:1px solid #d1d5db;color:#1f2937}.ai-chat-widget.dark .ai-chat-tool-badge,.ai-chat-widget[data-theme=dark] .ai-chat-tool-badge,.chakra-ui-dark .ai-chat-tool-badge,.dark .ai-chat-tool-badge,[data-theme=dark] .ai-chat-tool-badge,html.dark .ai-chat-tool-badge{background:hsla(0,0%,100%,.12);border:1px solid hsla(0,0%,100%,.2);color:hsla(0,0%,100%,.9)}.ai-chat-widget.dark .ai-chat-tool-gear,.ai-chat-widget[data-theme=dark] .ai-chat-tool-gear,.chakra-ui-dark .ai-chat-tool-gear,.dark .ai-chat-tool-gear,[data-theme=dark] .ai-chat-tool-gear,html.dark .ai-chat-tool-gear{color:#fff}.ai-chat-tool-badge.error{background:var(--tool-error-bg,rgba(239,68,68,.15));color:var(--tool-error-text,#ef4444)}.ai-chat-tool-badge .ai-chat-tool-check{color:#fff;flex-shrink:0}.ai-chat-tool-badge .ai-chat-tool-error{color:#ef4444;flex-shrink:0}.tool-name{font-weight:500;line-height:1.2;white-space:nowrap}.ai-chat-tool-action{box-sizing:border-box;padding:0;width:100%}@keyframes ai-chat-skeleton-pulse{0%,to{opacity:.4}50%{opacity:.7}}.ai-chat-action-skeleton-item{animation:ai-chat-skeleton-pulse 1.5s ease-in-out infinite;background:var(--bg-secondary,#e5e7eb)}.ai-chat-widget.dark .ai-chat-action-skeleton-item,.chakra-ui-dark .ai-chat-action-skeleton-item,.dark .ai-chat-action-skeleton-item,[data-theme=dark] .ai-chat-action-skeleton-item{background:hsla(0,0%,100%,.1)}.ai-chat-action-skeleton-content{display:flex;flex-direction:column;gap:16px}.ai-chat-action-skeleton-header{align-items:center;display:flex;gap:10px}.ai-chat-action-skeleton-box{background:rgba(0,0,0,.08);border-radius:10px;display:flex;flex-direction:column;gap:8px;padding:14px}.ai-chat-widget.dark .ai-chat-action-skeleton-box,.chakra-ui-dark .ai-chat-action-skeleton-box,.dark .ai-chat-action-skeleton-box,[data-theme=dark] .ai-chat-action-skeleton-box{background:rgba(0,0,0,.25)}.ai-chat-action-card{--action-accent:var(--primary-color,#3b82f6);background:var(--bg-secondary,#f9fafb);border:1px solid var(--border-subtle,rgba(0,0,0,.06));border-radius:12px;box-sizing:border-box;margin-top:4px;padding:16px;transition:all .2s ease;width:100%}.ai-chat-widget.dark .ai-chat-action-card,.chakra-ui-dark .ai-chat-action-card,.dark .ai-chat-action-card,[data-theme=dark] .ai-chat-action-card{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1)}.ai-chat-action-booked{background:var(--bg-secondary,#f9fafb);border:1px solid var(--border-subtle,rgba(0,0,0,.06))}.ai-chat-widget.dark .ai-chat-action-booked,.chakra-ui-dark .ai-chat-action-booked,.dark .ai-chat-action-booked,[data-theme=dark] .ai-chat-action-booked{background:var(--bg-secondary,#3a3a3a)}.ai-chat-action-header{align-items:center;color:var(--text-primary,#3e3e3e);display:flex;font-size:var(--text-md,15px);font-weight:var(--font-weight-semibold,600);gap:var(--space-sm,8px);margin-bottom:var(--space-md,16px)}.ai-chat-widget.dark .ai-chat-action-header,.chakra-ui-dark .ai-chat-action-header,.dark .ai-chat-action-header,[data-theme=dark] .ai-chat-action-header{color:var(--text-primary,#fff)}.ai-chat-action-icon{color:var(--action-accent,var(--primary-color,#3b82f6));flex-shrink:0;height:20px;width:20px}.ai-chat-action-success-icon-wrapper{align-items:center;background:var(--action-accent,var(--primary-color,#22c55e));border-radius:50%;color:#fff;display:flex;flex-shrink:0;height:24px;justify-content:center;width:24px}.ai-chat-action-icon-success{color:currentColor;height:14px;width:14px}.ai-chat-action-detail-box{background:var(--bg-primary,#fff);border:1px solid var(--border-subtle,rgba(0,0,0,.08));border-radius:var(--radius-md,8px);display:flex;flex-direction:column;gap:4px;padding:12px 16px}.ai-chat-widget.dark .ai-chat-action-detail-box,.chakra-ui-dark .ai-chat-action-detail-box,.dark .ai-chat-action-detail-box,[data-theme=dark] .ai-chat-action-detail-box{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.05)}.ai-chat-action-label-small{color:var(--text-muted,#71717a);font-size:11px;font-weight:600;letter-spacing:.5px;text-transform:uppercase}.ai-chat-action-value-large{color:var(--text-primary,#3e3e3e);font-size:15px;font-weight:500}.ai-chat-widget.dark .ai-chat-action-value-large,.chakra-ui-dark .ai-chat-action-value-large,.dark .ai-chat-action-value-large,[data-theme=dark] .ai-chat-action-value-large{color:#fff}.ai-chat-action-body{display:flex;flex-direction:column;gap:var(--space-md,16px)}.ai-chat-action-close-btn{align-items:center;background:transparent;border:none;border-radius:6px;color:var(--ai-chat-fg-muted,#6b7280);cursor:pointer;display:flex;height:28px;justify-content:center;padding:0;position:absolute;right:12px;top:12px;transition:all .15s ease;width:28px;z-index:10}.ai-chat-action-close-btn:hover{background:var(--ai-chat-bg-muted,#f3f4f6);color:var(--ai-chat-fg,#1f2937)}.ai-chat-action-close-btn:active{transform:scale(.95)}.ai-chat-action-close-btn:focus-visible{outline:2px solid var(--ai-chat-accent,#2563eb);outline-offset:2px}.ai-chat-action-card--closable,.ai-chat-form-card--closable{position:relative}.ai-chat-action-card--closable .ai-chat-action-header,.ai-chat-form-card--closable .ai-chat-form-card__header{padding-right:40px}.ai-chat-widget.dark .ai-chat-action-close-btn:hover,.chakra-ui-dark .ai-chat-action-close-btn:hover,.dark .ai-chat-action-close-btn:hover,[data-theme=dark] .ai-chat-action-close-btn:hover{background:hsla(0,0%,100%,.1);color:var(--ai-chat-fg,#f3f4f6)}.ai-chat-action-field{display:flex;flex-direction:column;gap:var(--space-xs,6px)}.ai-chat-action-label{color:var(--text-secondary,#6b7280);font-size:var(--text-sm,13px);font-weight:var(--font-weight-medium,500)}.ai-chat-widget.dark .ai-chat-action-label,.chakra-ui-dark .ai-chat-action-label,.dark .ai-chat-action-label,[data-theme=dark] .ai-chat-action-label{color:var(--text-secondary,#a1a1aa)}.ai-chat-action-input{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);color:var(--text-primary,#3e3e3e);font-size:var(--text-sm,13px);outline:none;padding:10px 12px;transition:border-color .2s ease,box-shadow .2s ease}.ai-chat-action-input:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.1)}.ai-chat-action-input::placeholder{color:var(--text-muted,#9ca3af)}.ai-chat-widget.dark .ai-chat-action-input,.chakra-ui-dark .ai-chat-action-input,.dark .ai-chat-action-input,[data-theme=dark] .ai-chat-action-input{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-action-input:focus,.chakra-ui-dark .ai-chat-action-input:focus,.dark .ai-chat-action-input:focus,[data-theme=dark] .ai-chat-action-input:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.2)}.ai-chat-action-button{background:var(--action-accent,var(--primary-color,#3b82f6));border:none;border-radius:9999px;color:#fff;cursor:pointer;font-size:var(--text-sm,13px);font-weight:var(--font-weight-semibold,600);padding:12px 16px;transition:all .2s ease;width:100%}.ai-chat-action-button:hover:not(:disabled){opacity:.9;transform:translateY(-1px)}.ai-chat-action-button:disabled{cursor:not-allowed;opacity:.5}.ai-chat-action-link-button{align-items:center;background:var(--action-accent,var(--primary-color,#3b82f6));border:none;border-radius:9999px;box-sizing:border-box;color:#fff;display:flex;font-size:14px;font-weight:600;gap:6px;justify-content:center;margin-top:8px;padding:12px;text-decoration:none;transition:all .2s ease;width:100%}.ai-chat-action-link-button:hover{opacity:.9;transform:translateY(-1px)}.ai-chat-action-error{background:rgba(239,68,68,.1);border-radius:var(--radius-md,8px);color:#dc2626;font-size:var(--text-sm,13px);padding:10px 12px}.ai-chat-widget.dark .ai-chat-action-error,.chakra-ui-dark .ai-chat-action-error,.dark .ai-chat-action-error,[data-theme=dark] .ai-chat-action-error{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-action-hint{color:var(--text-muted,#9ca3af);font-size:var(--text-sm,13px);padding:var(--space-sm,8px);text-align:center}@media (max-width:480px){.ai-chat-action-card{padding:12px}.ai-chat-action-header{font-size:var(--text-sm,14px);margin-bottom:var(--space-sm,12px)}.ai-chat-action-button{font-size:13px;padding:10px 14px}.ai-chat-action-link-button{font-size:13px;padding:10px}}.ai-chat-link-preview{--action-accent:var(--primary-color,#3b82f6);background:var(--bg-secondary,#f4f4f4);border:1px solid var(--border-subtle,rgba(0,0,0,.08));border-radius:var(--radius-lg,12px);cursor:pointer;display:flex;flex-direction:column;margin-top:4px;overflow:hidden;padding:0!important;position:relative;transition:border-color .2s,box-shadow .2s,transform .2s}.ai-chat-link-preview:hover{border-color:var(--action-accent);box-shadow:0 2px 8px rgba(0,0,0,.1);transform:translateY(-1px)}.ai-chat-link-preview:focus{border-color:var(--action-accent);box-shadow:0 0 0 2px rgba(59,130,246,.2);outline:none}.ai-chat-widget.dark .ai-chat-link-preview,.chakra-ui-dark .ai-chat-link-preview,.dark .ai-chat-link-preview,[data-theme=dark] .ai-chat-link-preview{background:var(--bg-secondary,#3a3a3a);border-color:hsla(0,0%,100%,.08)}.ai-chat-widget.dark .ai-chat-link-preview:hover,.chakra-ui-dark .ai-chat-link-preview:hover,.dark .ai-chat-link-preview:hover,[data-theme=dark] .ai-chat-link-preview:hover{border-color:var(--action-accent);box-shadow:0 2px 12px rgba(0,0,0,.3)}.ai-chat-link-preview__image{aspect-ratio:1.91/1;background:var(--bg-muted,#e5e7eb);overflow:hidden;width:100%}.ai-chat-widget.dark .ai-chat-link-preview__image,.chakra-ui-dark .ai-chat-link-preview__image,.dark .ai-chat-link-preview__image,[data-theme=dark] .ai-chat-link-preview__image{background:hsla(0,0%,100%,.05)}.ai-chat-link-preview__image img{height:100%;object-fit:cover;width:100%}.ai-chat-link-preview__content{flex:1;padding:8px 10px}.ai-chat-link-preview__site{align-items:center;display:flex;gap:6px;margin-bottom:6px}.ai-chat-link-preview__favicon{border-radius:2px;flex-shrink:0;height:16px;width:16px}.ai-chat-link-preview__domain{color:var(--text-muted,#71717a);font-size:12px;letter-spacing:.5px;overflow:hidden;text-overflow:ellipsis;text-transform:uppercase;white-space:nowrap}.ai-chat-link-preview__title{-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;color:var(--text-primary,#3e3e3e);display:-webkit-box;font-size:15px;font-weight:600;line-height:1.3;margin:0 0 4px;overflow:hidden}.ai-chat-widget.dark .ai-chat-link-preview__title,.chakra-ui-dark .ai-chat-link-preview__title,.dark .ai-chat-link-preview__title,[data-theme=dark] .ai-chat-link-preview__title{color:#fff}.ai-chat-link-preview__description{-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;color:var(--text-muted,#71717a);display:-webkit-box;font-size:13px;line-height:1.4;margin:0;overflow:hidden}.ai-chat-link-preview__context{border-top:1px solid var(--border-subtle,rgba(0,0,0,.08));color:var(--text-muted,#71717a);font-size:12px;font-style:italic;margin:8px 0 0;padding-top:8px}.ai-chat-widget.dark .ai-chat-link-preview__context,.chakra-ui-dark .ai-chat-link-preview__context,.dark .ai-chat-link-preview__context,[data-theme=dark] .ai-chat-link-preview__context{border-color:hsla(0,0%,100%,.08)}.ai-chat-link-preview__arrow{align-items:center;background:var(--bg-primary,#fff);border-radius:50%;box-shadow:0 1px 3px rgba(0,0,0,.1);color:var(--text-muted,#71717a);display:flex;height:28px;justify-content:center;opacity:0;position:absolute;right:12px;top:12px;transition:opacity .2s,background .2s;width:28px}.ai-chat-link-preview:hover .ai-chat-link-preview__arrow{opacity:1}.ai-chat-widget.dark .ai-chat-link-preview__arrow,.chakra-ui-dark .ai-chat-link-preview__arrow,.dark .ai-chat-link-preview__arrow,[data-theme=dark] .ai-chat-link-preview__arrow{background:hsla(0,0%,100%,.1);color:#fff}.ai-chat-link-preview--error{border-color:rgba(239,68,68,.3)}.ai-chat-link-preview--error:hover{border-color:rgba(239,68,68,.5)}.ai-chat-link-preview__error-text{color:#dc2626;font-size:12px;margin:4px 0 0}.ai-chat-widget.dark .ai-chat-link-preview__error-text,.chakra-ui-dark .ai-chat-link-preview__error-text,.dark .ai-chat-link-preview__error-text,[data-theme=dark] .ai-chat-link-preview__error-text{color:#fca5a5}.ai-chat-link-preview-grid{display:grid;gap:12px}.ai-chat-link-preview-grid--single{grid-template-columns:1fr}.ai-chat-link-preview-grid--double{grid-template-columns:repeat(2,1fr)}.ai-chat-link-preview-grid--triple{grid-template-columns:repeat(3,1fr)}@media (max-width:768px){.ai-chat-link-preview-grid--triple{grid-template-columns:repeat(2,1fr)}}@media (max-width:480px){.ai-chat-link-preview-grid--double,.ai-chat-link-preview-grid--triple{grid-template-columns:1fr}}.ai-chat-video-player{--action-accent:var(--primary-color,#3b82f6);background:var(--bg-secondary,#f4f4f4);border-radius:var(--radius-lg,12px);display:flex;flex-direction:column;gap:0;margin-top:4px;overflow:hidden;padding:0!important}.ai-chat-widget.dark .ai-chat-video-player,.chakra-ui-dark .ai-chat-video-player,.dark .ai-chat-video-player,[data-theme=dark] .ai-chat-video-player{background:var(--bg-secondary,#3a3a3a)}.ai-chat-video-player__header{align-items:center;color:var(--action-accent,var(--primary-color,#3b82f6));display:flex;gap:8px}.ai-chat-video-player__title{color:var(--text-primary,#3e3e3e);font-size:14px;font-weight:600}.ai-chat-widget.dark .ai-chat-video-player__title,.chakra-ui-dark .ai-chat-video-player__title,.dark .ai-chat-video-player__title,[data-theme=dark] .ai-chat-video-player__title{color:#fff}.ai-chat-video-player__container{aspect-ratio:16/9;background:#000;border-radius:8px;overflow:hidden;position:relative;width:100%}.ai-chat-video-player__thumbnail{cursor:pointer;height:100%;position:relative;width:100%}.ai-chat-video-player__thumbnail img{height:100%;object-fit:cover;width:100%}.ai-chat-video-player__placeholder{align-items:center;background:linear-gradient(135deg,#1a1a2e,#16213e);cursor:pointer;display:flex;flex-direction:column;gap:8px;height:100%;justify-content:center;position:relative;width:100%}.ai-chat-video-player__click-text{color:hsla(0,0%,100%,.7);font-size:13px}.ai-chat-video-player__play-btn{align-items:center;background:rgba(0,0,0,.7);border:none;border-radius:50%;color:#fff;cursor:pointer;display:flex;height:64px;justify-content:center;left:50%;position:absolute;top:50%;transform:translate(-50%,-50%);transition:background .2s,transform .2s;width:64px}.ai-chat-video-player__placeholder .ai-chat-video-player__play-btn{left:auto;position:relative;top:auto;transform:none}.ai-chat-video-player__play-btn:hover{background:rgba(0,0,0,.9);transform:translate(-50%,-50%) scale(1.05)}.ai-chat-video-player__placeholder .ai-chat-video-player__play-btn:hover{transform:scale(1.05)}.ai-chat-video-player__provider-badge{background:rgba(0,0,0,.8);border-radius:4px;bottom:8px;color:#fff;font-size:11px;font-weight:600;letter-spacing:.5px;padding:4px 8px;position:absolute;right:8px;text-transform:uppercase}.ai-chat-video-player__iframe,.ai-chat-video-player__video{border:none;height:100%;left:0;position:absolute;top:0;width:100%}.ai-chat-video-player__error{align-items:center;background:rgba(239,68,68,.1);color:#dc2626;display:flex;font-size:13px;height:100%;justify-content:center;padding:16px;text-align:center;width:100%}.ai-chat-widget.dark .ai-chat-video-player__error,.chakra-ui-dark .ai-chat-video-player__error,.dark .ai-chat-video-player__error,[data-theme=dark] .ai-chat-video-player__error{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-video-player__context{color:var(--text-muted,#71717a);font-size:12px;font-style:italic;margin-top:4px;padding:8px 12px 12px}@media (max-width:480px){.ai-chat-video-player__play-btn{height:56px;width:56px}.ai-chat-video-player__provider-badge{font-size:10px;padding:3px 6px}}.ai-chat-location-card{background:var(--bg-secondary,#fff);border:1px solid var(--border-subtle,rgba(0,0,0,.08));border-radius:12px;overflow:hidden;padding:0}.ai-chat-widget.dark .ai-chat-location-card,.chakra-ui-dark .ai-chat-location-card,.dark .ai-chat-location-card,[data-theme=dark] .ai-chat-location-card{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1)}.ai-chat-location-card--compact{border-radius:10px}.ai-chat-location-card--error{color:var(--text-muted,#71717a);padding:16px;text-align:center}.ai-chat-location-card__map{background:var(--bg-muted,#f4f4f5);position:relative;width:100%}.ai-chat-widget.dark .ai-chat-location-card__map,.chakra-ui-dark .ai-chat-location-card__map,.dark .ai-chat-location-card__map,[data-theme=dark] .ai-chat-location-card__map{background:rgba(0,0,0,.2)}.ai-chat-location-card__map iframe{border:none;display:block;height:100%;width:100%}.ai-chat-location-card__content{padding:12px}.ai-chat-location-card--compact .ai-chat-location-card__content{padding:10px}.ai-chat-location-card__header{align-items:center;display:flex;flex-wrap:wrap;gap:8px;margin-bottom:8px}.ai-chat-location-card__name{color:var(--text-primary,#18181b);flex:1;font-size:16px;font-weight:600;margin:0;min-width:0}.ai-chat-widget.dark .ai-chat-location-card__name,.chakra-ui-dark .ai-chat-location-card__name,.dark .ai-chat-location-card__name,[data-theme=dark] .ai-chat-location-card__name{color:#fff}.ai-chat-location-card--compact .ai-chat-location-card__name{font-size:14px}.ai-chat-location-card__type{background:var(--bg-muted,#f4f4f5);border-radius:10px;color:var(--text-muted,#71717a);font-size:11px;font-weight:500;letter-spacing:.5px;padding:2px 8px;text-transform:uppercase}.ai-chat-widget.dark .ai-chat-location-card__type,.chakra-ui-dark .ai-chat-location-card__type,.dark .ai-chat-location-card__type,[data-theme=dark] .ai-chat-location-card__type{background:hsla(0,0%,100%,.1);color:hsla(0,0%,100%,.7)}.ai-chat-location-card__status{border-radius:12px;font-size:12px;font-weight:500;padding:2px 8px}.ai-chat-location-card__status--open{background:#dcfce7;color:#16a34a}.ai-chat-location-card__status--closed{background:#fef2f2;color:#dc2626}.ai-chat-widget.dark .ai-chat-location-card__status--open,.chakra-ui-dark .ai-chat-location-card__status--open,.dark .ai-chat-location-card__status--open,[data-theme=dark] .ai-chat-location-card__status--open{background:rgba(34,197,94,.2);color:#4ade80}.ai-chat-widget.dark .ai-chat-location-card__status--closed,.chakra-ui-dark .ai-chat-location-card__status--closed,.dark .ai-chat-location-card__status--closed,[data-theme=dark] .ai-chat-location-card__status--closed{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-location-card__address{align-items:flex-start;color:var(--text-muted,#71717a);display:flex;font-size:13px;gap:6px;line-height:1.4;margin:0 0 8px}.ai-chat-location-card__address svg{flex-shrink:0;margin-top:2px}.ai-chat-location-card__description{color:var(--text-muted,#71717a);font-size:13px;line-height:1.4;margin:0 0 8px}.ai-chat-location-card__hours{align-items:flex-start;color:var(--text-muted,#71717a);display:flex;font-size:13px;gap:6px;margin-bottom:8px}.ai-chat-location-card__hours svg{flex-shrink:0;margin-top:2px}.ai-chat-location-card__hours-list{flex:1}.ai-chat-location-card__hours-toggle{align-items:center;background:none;border:none;color:inherit;cursor:pointer;display:flex;font:inherit;gap:4px;padding:0}.ai-chat-location-card__hours-toggle:hover{text-decoration:underline}.ai-chat-location-card__hours-full{list-style:none;margin:8px 0 0;padding:0}.ai-chat-location-card__hours-full li{display:flex;font-size:12px;justify-content:space-between;padding:4px 0}.ai-chat-location-card__hours-today{color:var(--text-primary,#18181b);font-weight:600}.ai-chat-widget.dark .ai-chat-location-card__hours-today,.chakra-ui-dark .ai-chat-location-card__hours-today,.dark .ai-chat-location-card__hours-today,[data-theme=dark] .ai-chat-location-card__hours-today{color:#fff}.ai-chat-location-card__phone{align-items:center;background:none;border:none;color:var(--action-accent,#3b82f6);cursor:pointer;display:flex;font-size:13px;gap:6px;margin-bottom:12px;padding:0}.ai-chat-location-card__phone:hover{text-decoration:underline}.ai-chat-location-card__actions{display:flex;flex-wrap:wrap;gap:8px;justify-content:flex-start;width:100%}@media (max-width:380px){.ai-chat-location-card__actions{flex-direction:column}.ai-chat-location-card__button,.ai-chat-location-card__link{flex:none;justify-content:center;width:100%}}.ai-chat-location-card__button{align-items:center;background:var(--action-accent,#3b82f6);border:none;border-radius:20px;color:#fff;cursor:pointer;display:flex;flex:1;font-size:13px;font-weight:500;gap:6px;justify-content:center;padding:10px 16px;transition:opacity .2s}.ai-chat-location-card__button:hover{opacity:.9}.ai-chat-location-card--compact .ai-chat-location-card__button{font-size:12px;padding:8px 12px}.ai-chat-location-card__link{align-items:center;background:var(--bg-secondary,#fff);border:1px solid var(--border-subtle,rgba(0,0,0,.08));border-radius:20px;color:var(--text-primary,#18181b);display:flex;font-size:13px;gap:6px;padding:10px 16px;text-decoration:none;transition:border-color .2s}.ai-chat-widget.dark .ai-chat-location-card__link,.chakra-ui-dark .ai-chat-location-card__link,.dark .ai-chat-location-card__link,[data-theme=dark] .ai-chat-location-card__link{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-location-card__link:hover{border-color:var(--action-accent,#3b82f6)}.ai-chat-location-card-list{display:flex;flex-direction:column;gap:8px}.ai-chat-location-card-list__header{align-items:center;color:var(--text-muted,#71717a);display:flex;font-size:13px;font-weight:500;gap:6px;margin-bottom:4px;padding:0 4px}.ai-chat-location-card-list__stack{display:grid;gap:12px;grid-template-columns:1fr}.ai-chat-location-card-list__stack--cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.ai-chat-location-card-list__stack--cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}@media (max-width:1000px){.ai-chat-location-card-list__stack--cols-3{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (max-width:640px){.ai-chat-location-card-list__stack--cols-2,.ai-chat-location-card-list__stack--cols-3{grid-template-columns:1fr}}.ai-chat-location-card-list__grid{display:grid;gap:8px;grid-template-columns:repeat(2,1fr)}@media (max-width:400px){.ai-chat-location-card-list__grid{grid-template-columns:1fr}}.ai-chat-location-card-list__carousel{-webkit-overflow-scrolling:touch;-ms-overflow-style:none;display:flex;gap:8px;overflow-x:auto;padding-bottom:4px;scroll-snap-type:x mandatory;scrollbar-width:none}.ai-chat-location-card-list__carousel::-webkit-scrollbar{display:none}.ai-chat-location-card-list__carousel>.ai-chat-location-card{flex:0 0 280px;scroll-snap-align:start}@media (max-width:480px){.ai-chat-location-card__content{padding:10px}.ai-chat-location-card__name{font-size:14px}.ai-chat-location-card__address,.ai-chat-location-card__description,.ai-chat-location-card__hours{font-size:12px}.ai-chat-location-card__button,.ai-chat-location-card__link{font-size:12px;padding:8px 12px}.ai-chat-location-card-list__carousel>.ai-chat-location-card{flex:0 0 240px}}.ai-chat-contact-card{background:#fff;border:1px solid rgba(0,0,0,.08);border-radius:16px;overflow:hidden;padding:0;position:relative}.ai-chat-widget.dark .ai-chat-contact-card,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card,.chakra-ui-dark .ai-chat-contact-card,.dark .ai-chat-contact-card,[data-theme=dark] .ai-chat-contact-card,html.dark .ai-chat-contact-card{background:#4a4a4a;border-color:hsla(0,0%,100%,.08)}.ai-chat-contact-card-list{gap:12px;width:100%}.ai-chat-contact-card--compact{border-radius:12px}.ai-chat-contact-card--empty{align-items:center;background:var(--bg-secondary,#f4f4f5);display:flex;flex-direction:column;gap:8px;justify-content:center;padding:24px 16px;text-align:center}.ai-chat-widget.dark .ai-chat-contact-card--empty,.chakra-ui-dark .ai-chat-contact-card--empty,.dark .ai-chat-contact-card--empty,[data-theme=dark] .ai-chat-contact-card--empty{background:#3a3a3a}.ai-chat-contact-card__empty-icon{color:var(--text-muted,#71717a);opacity:.6}.ai-chat-contact-card__empty-text{color:var(--text-muted,#71717a);font-size:14px;margin:0}.ai-chat-contact-card--vertical{display:flex;flex-direction:column}.ai-chat-contact-card--vertical .ai-chat-contact-card__image-section{aspect-ratio:3/2;overflow:hidden;width:100%}.ai-chat-contact-card--vertical .ai-chat-contact-card__image{height:100%;object-fit:cover;width:100%}.ai-chat-contact-card--vertical .ai-chat-contact-card__image-placeholder{align-items:center;background:linear-gradient(135deg,#5a5a5a,#3a3a3a);color:hsla(0,0%,100%,.5);display:flex;height:100%;justify-content:center;width:100%}.ai-chat-contact-card--vertical .ai-chat-contact-card__image-placeholder svg{height:48px;width:48px}.ai-chat-contact-card--vertical .ai-chat-contact-card__info{padding:16px;text-align:center}.ai-chat-contact-card--horizontal{display:flex;flex-direction:row}.ai-chat-contact-card--horizontal .ai-chat-contact-card__image-section{height:160px;min-width:140px;overflow:hidden;width:140px}.ai-chat-contact-card--horizontal.ai-chat-contact-card--compact .ai-chat-contact-card__image-section{height:120px;min-width:100px;width:100px}.ai-chat-contact-card--horizontal .ai-chat-contact-card__image{height:100%;object-fit:cover;width:100%}.ai-chat-contact-card--horizontal .ai-chat-contact-card__image-placeholder{align-items:center;background:linear-gradient(135deg,#5a5a5a,#3a3a3a);color:hsla(0,0%,100%,.5);display:flex;height:100%;justify-content:center;width:100%}.ai-chat-contact-card--horizontal .ai-chat-contact-card__image-placeholder svg{height:36px;width:36px}.ai-chat-contact-card--horizontal .ai-chat-contact-card__info{display:flex;flex:1;flex-direction:column;justify-content:center;padding:16px}.ai-chat-contact-card__name{color:var(--action-accent,#ef4444);font-size:18px;font-weight:600;line-height:1.3;margin:0}.ai-chat-contact-card--compact .ai-chat-contact-card__name{font-size:15px}.ai-chat-contact-card__role{color:rgba(0,0,0,.7);font-size:14px;font-weight:400;margin:2px 0 0}.ai-chat-widget.dark .ai-chat-contact-card__role,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card__role,.chakra-ui-dark .ai-chat-contact-card__role,.dark .ai-chat-contact-card__role,[data-theme=dark] .ai-chat-contact-card__role,html.dark .ai-chat-contact-card__role{color:hsla(0,0%,100%,.9)}.ai-chat-contact-card--compact .ai-chat-contact-card__role{font-size:13px}.ai-chat-contact-card__details{display:flex;flex-direction:column;gap:2px;margin-top:12px}.ai-chat-contact-card__detail{color:rgba(0,0,0,.6);display:block;font-size:14px;line-height:1.5;margin:0;text-decoration:none}.ai-chat-contact-card__detail:hover{color:#000;text-decoration:underline}.ai-chat-widget.dark .ai-chat-contact-card__detail,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card__detail,.chakra-ui-dark .ai-chat-contact-card__detail,.dark .ai-chat-contact-card__detail,[data-theme=dark] .ai-chat-contact-card__detail,html.dark .ai-chat-contact-card__detail{color:hsla(0,0%,100%,.7)}.ai-chat-widget.dark .ai-chat-contact-card__detail:hover,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card__detail:hover,.chakra-ui-dark .ai-chat-contact-card__detail:hover,.dark .ai-chat-contact-card__detail:hover,[data-theme=dark] .ai-chat-contact-card__detail:hover,html.dark .ai-chat-contact-card__detail:hover{color:#fff}.ai-chat-contact-card--compact .ai-chat-contact-card__detail{font-size:13px}.ai-chat-contact-card__responsibilities{display:flex;flex-wrap:wrap;gap:4px;margin-top:8px}.ai-chat-contact-card__responsibility-tag{background:rgba(0,0,0,.08);border-radius:10px;color:rgba(0,0,0,.8);font-size:11px;font-weight:500;padding:3px 10px}.ai-chat-widget.dark .ai-chat-contact-card__responsibility-tag,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card__responsibility-tag,.chakra-ui-dark .ai-chat-contact-card__responsibility-tag,.dark .ai-chat-contact-card__responsibility-tag,[data-theme=dark] .ai-chat-contact-card__responsibility-tag,html.dark .ai-chat-contact-card__responsibility-tag{background:hsla(0,0%,100%,.15);color:hsla(0,0%,100%,.9)}.ai-chat-contact-card__responsibility-more{color:rgba(0,0,0,.5);font-size:11px;padding:3px 4px}.ai-chat-widget.dark .ai-chat-contact-card__responsibility-more,.ai-chat-widget[data-theme=dark] .ai-chat-contact-card__responsibility-more,.chakra-ui-dark .ai-chat-contact-card__responsibility-more,.dark .ai-chat-contact-card__responsibility-more,[data-theme=dark] .ai-chat-contact-card__responsibility-more,html.dark .ai-chat-contact-card__responsibility-more{color:hsla(0,0%,100%,.5)}.ai-chat-contact-card__actions{display:flex;flex-wrap:wrap;gap:8px;padding:0 12px 12px}@media (max-width:380px){.ai-chat-contact-card__actions{flex-direction:column}.ai-chat-contact-card__button{flex:none;width:100%}}.ai-chat-contact-card--compact .ai-chat-contact-card__actions{gap:6px;padding:0 10px 10px}.ai-chat-contact-card__button{align-items:center;border:none;border-radius:9999px;cursor:pointer;display:flex;font-size:14px;font-weight:600;gap:8px;justify-content:center;padding:12px 20px;transition:all .15s ease;white-space:nowrap}.ai-chat-contact-card--compact .ai-chat-contact-card__button{font-size:13px;padding:10px 16px}.ai-chat-contact-card__button:hover{box-shadow:0 4px 12px rgba(0,0,0,.15);transform:translateY(-1px)}.ai-chat-contact-card__button:active{transform:translateY(0)}.ai-chat-contact-card__button--primary{background:var(--action-accent,#3b82f6);color:#fff;flex:1}.ai-chat-contact-card__button--primary:hover{background:color-mix(in srgb,var(--action-accent,#3b82f6) 90%,#000)}.ai-chat-contact-card__button--secondary{background:var(--bg-muted,#f4f4f5);border:1px solid var(--border-subtle,rgba(0,0,0,.08));color:var(--text-primary,#18181b);flex:1}.ai-chat-contact-card__button--secondary:hover{background:var(--bg-hover,#e4e4e7)}.ai-chat-widget.dark .ai-chat-contact-card__button--secondary,.chakra-ui-dark .ai-chat-contact-card__button--secondary,.dark .ai-chat-contact-card__button--secondary,[data-theme=dark] .ai-chat-contact-card__button--secondary{background:hsla(0,0%,100%,.1);border-color:hsla(0,0%,100%,.15);color:#fff}.ai-chat-widget.dark .ai-chat-contact-card__button--secondary:hover,.chakra-ui-dark .ai-chat-contact-card__button--secondary:hover,.dark .ai-chat-contact-card__button--secondary:hover,[data-theme=dark] .ai-chat-contact-card__button--secondary:hover{background:hsla(0,0%,100%,.15)}.ai-chat-contact-card-list{display:flex;flex-direction:column;gap:8px}.ai-chat-contact-card-list__header{align-items:center;color:var(--text-muted,#71717a);display:flex;font-size:13px;font-weight:500;gap:6px;margin-bottom:2px;margin-top:8px;padding:0 4px}.ai-chat-contact-card-list__stack{display:grid;gap:12px;grid-template-columns:repeat(3,minmax(0,1fr))}@media (max-width:900px){.ai-chat-contact-card-list__stack{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (max-width:600px){.ai-chat-contact-card-list__stack{grid-template-columns:1fr}}.ai-chat-contact-card-list__stack--widget{grid-template-columns:1fr}@container (min-width: 380px){.ai-chat-contact-card-list__stack--widget{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (max-width:520px){.ai-chat-contact-card-list__stack{grid-template-columns:1fr!important}.ai-chat-contact-card--horizontal{flex-direction:column}.ai-chat-contact-card--horizontal .ai-chat-contact-card__image-section{aspect-ratio:3/2;height:auto;min-width:100%;width:100%}}.ai-chat-contact-card__initials{align-items:center;display:flex;font-size:48px;font-weight:600;height:100%;justify-content:center;letter-spacing:.05em;text-transform:uppercase;width:100%}.ai-chat-contact-card--compact .ai-chat-contact-card__initials{font-size:32px}.ai-chat-contact-card--horizontal .ai-chat-contact-card__initials{font-size:28px}.ai-chat-contact-card--horizontal.ai-chat-contact-card--compact .ai-chat-contact-card__initials{font-size:22px}@media (max-width:480px){.ai-chat-contact-card__name{font-size:16px}.ai-chat-contact-card__detail,.ai-chat-contact-card__role{font-size:13px}.ai-chat-contact-card__button{font-size:13px;padding:10px 16px}.ai-chat-contact-card--horizontal .ai-chat-contact-card__info,.ai-chat-contact-card--vertical .ai-chat-contact-card__info{padding:12px}}.ai-chat-form-card{--action-accent:var(--primary-color,#3b82f6);background:var(--bg-secondary,#f9fafb);border:1px solid var(--border-subtle,rgba(0,0,0,.06));border-radius:12px;box-sizing:border-box;margin:6px 0;overflow:hidden;padding:16px;width:100%}.ai-chat-widget.dark .ai-chat-form-card,.chakra-ui-dark .ai-chat-form-card,.dark .ai-chat-form-card,[data-theme=dark] .ai-chat-form-card{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1)}.ai-chat-form-card--completed,.ai-chat-form-card--empty,.ai-chat-form-card--error,.ai-chat-form-card--skipped,.ai-chat-form-card--submitted{padding:12px 16px}.ai-chat-form-card--completed .ai-chat-form-card__header{margin-bottom:0}.ai-chat-form-card--completed .ai-chat-form-card__icon svg{color:#10b981}.ai-chat-form-card__header{align-items:center;display:flex;gap:8px;margin-bottom:12px}.ai-chat-form-card__icon{align-items:center;display:inline-flex;justify-content:center}.ai-chat-form-card__icon svg{color:var(--text-primary,#3e3e3e);height:18px;width:18px}.ai-chat-widget.dark .ai-chat-form-card__icon svg,.chakra-ui-dark .ai-chat-form-card__icon svg,.dark .ai-chat-form-card__icon svg,[data-theme=dark] .ai-chat-form-card__icon svg{color:#fff}.ai-chat-form-card__title{color:var(--text-primary,#3e3e3e);font-size:15px;font-weight:600}.ai-chat-widget.dark .ai-chat-form-card__title,.chakra-ui-dark .ai-chat-form-card__title,.dark .ai-chat-form-card__title,[data-theme=dark] .ai-chat-form-card__title{color:#fff}.ai-chat-form-card__description{color:var(--text-muted,#71717a);font-size:13px;line-height:1.4;margin:0 0 12px}.ai-chat-form-card__context{color:var(--text-muted,#71717a);font-size:12px;font-style:italic;margin:0 0 12px}.ai-chat-form-card--error .ai-chat-form-card__icon svg{color:#dc2626}.ai-chat-form-card--submitted .ai-chat-form-card__icon svg{color:#16a34a}.ai-chat-widget.dark .ai-chat-form-card--error .ai-chat-form-card__icon svg,.chakra-ui-dark .ai-chat-form-card--error .ai-chat-form-card__icon svg,.dark .ai-chat-form-card--error .ai-chat-form-card__icon svg,[data-theme=dark] .ai-chat-form-card--error .ai-chat-form-card__icon svg{color:#fca5a5}.ai-chat-widget.dark .ai-chat-form-card--submitted .ai-chat-form-card__icon svg,.chakra-ui-dark .ai-chat-form-card--submitted .ai-chat-form-card__icon svg,.dark .ai-chat-form-card--submitted .ai-chat-form-card__icon svg,[data-theme=dark] .ai-chat-form-card--submitted .ai-chat-form-card__icon svg{color:#4ade80}.ai-chat-form-card__error{color:#dc2626;font-size:13px;margin:0}.ai-chat-widget.dark .ai-chat-form-card__error,.chakra-ui-dark .ai-chat-form-card__error,.dark .ai-chat-form-card__error,[data-theme=dark] .ai-chat-form-card__error{color:#fca5a5}.ai-chat-form-card__success{color:#16a34a;font-size:13px;margin:0}.ai-chat-widget.dark .ai-chat-form-card__success,.chakra-ui-dark .ai-chat-form-card__success,.dark .ai-chat-form-card__success,[data-theme=dark] .ai-chat-form-card__success{color:#4ade80}.ai-chat-form-card__empty-text,.ai-chat-form-card__skipped-text{color:var(--text-muted,#71717a);font-size:13px;margin:0}.ai-chat-form-card__progress{align-items:center;display:flex;gap:12px;margin-bottom:16px}.ai-chat-form-card__progress-bar{background:var(--action-accent,var(--primary-color,#3b82f6));border-radius:2px;flex:1;height:4px;transition:width .3s ease}.ai-chat-form-card__progress-text{color:var(--text-muted,#71717a);font-size:12px;white-space:nowrap}.ai-chat-form-card__question{margin-bottom:16px}.ai-chat-form-card__question-text{color:var(--text-primary,#3e3e3e);font-size:14px;font-weight:500;line-height:1.4;margin:0 0 12px}.ai-chat-widget.dark .ai-chat-form-card__question-text,.chakra-ui-dark .ai-chat-form-card__question-text,.dark .ai-chat-form-card__question-text,[data-theme=dark] .ai-chat-form-card__question-text{color:#fff}.ai-chat-form-card__required{color:#dc2626;margin-left:2px}.ai-chat-form-card__answer{margin-top:8px}.ai-chat-form-card__textarea{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);box-sizing:border-box;color:var(--text-primary,#3e3e3e);font-family:inherit;font-size:14px;min-height:80px;outline:none;padding:10px 12px;resize:vertical;transition:border-color .2s ease,box-shadow .2s ease;width:100%}.ai-chat-form-card__textarea:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.1)}.ai-chat-form-card__textarea::placeholder{color:var(--text-muted,#9ca3af)}.ai-chat-widget.dark .ai-chat-form-card__textarea,.chakra-ui-dark .ai-chat-form-card__textarea,.dark .ai-chat-form-card__textarea,[data-theme=dark] .ai-chat-form-card__textarea{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-form-card__textarea:focus,.chakra-ui-dark .ai-chat-form-card__textarea:focus,.dark .ai-chat-form-card__textarea:focus,[data-theme=dark] .ai-chat-form-card__textarea:focus{border-color:var(--action-accent,var(--primary-color,#3b82f6));box-shadow:0 0 0 3px rgba(59,130,246,.2)}.ai-chat-form-card__options{display:flex;flex-direction:column;gap:8px}.ai-chat-form-card__option{align-items:center;background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);cursor:pointer;display:flex;gap:10px;padding:10px 12px;transition:border-color .15s,background .15s}.ai-chat-form-card__option:hover{background:rgba(59,130,246,.05);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-form-card__option,.chakra-ui-dark .ai-chat-form-card__option,.dark .ai-chat-form-card__option,[data-theme=dark] .ai-chat-form-card__option{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1)}.ai-chat-widget.dark .ai-chat-form-card__option:hover,.chakra-ui-dark .ai-chat-form-card__option:hover,.dark .ai-chat-form-card__option:hover,[data-theme=dark] .ai-chat-form-card__option:hover{background:rgba(59,130,246,.15);border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-form-card__option input{accent-color:var(--action-accent,var(--primary-color,#3b82f6));margin:0}.ai-chat-form-card__option-text{color:var(--text-primary,#3e3e3e);font-size:14px}.ai-chat-widget.dark .ai-chat-form-card__option-text,.chakra-ui-dark .ai-chat-form-card__option-text,.dark .ai-chat-form-card__option-text,[data-theme=dark] .ai-chat-form-card__option-text{color:#fff}.ai-chat-form-card__rating{display:flex;flex-wrap:wrap;gap:8px;justify-content:flex-start}@media (max-width:380px){.ai-chat-form-card__rating{gap:6px}.ai-chat-form-card__rating-btn{font-size:13px;height:36px;width:36px}}.ai-chat-form-card__rating-btn{align-items:center;background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);border-radius:var(--radius-md,8px);color:var(--text-primary,#3e3e3e);cursor:pointer;display:flex;font-size:14px;font-weight:500;height:40px;justify-content:center;transition:all .15s ease;width:40px}.ai-chat-form-card__rating-btn--selected,.ai-chat-form-card__rating-btn:hover{border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-form-card__rating-btn--selected{background:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-widget.dark .ai-chat-form-card__rating-btn,.chakra-ui-dark .ai-chat-form-card__rating-btn,.dark .ai-chat-form-card__rating-btn,[data-theme=dark] .ai-chat-form-card__rating-btn{background:rgba(0,0,0,.2);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-form-card__rating-btn:hover,.chakra-ui-dark .ai-chat-form-card__rating-btn:hover,.dark .ai-chat-form-card__rating-btn:hover,[data-theme=dark] .ai-chat-form-card__rating-btn:hover{border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-form-card__rating-btn--selected,.chakra-ui-dark .ai-chat-form-card__rating-btn--selected,.dark .ai-chat-form-card__rating-btn--selected,[data-theme=dark] .ai-chat-form-card__rating-btn--selected{background:var(--action-accent,var(--primary-color,#3b82f6));border-color:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-form-card__actions{align-items:center;border-top:1px solid var(--border-subtle,rgba(0,0,0,.08));display:flex;flex-wrap:wrap;gap:8px;margin-top:16px;padding-top:16px}@media (max-width:380px){.ai-chat-form-card__actions{align-items:stretch;flex-direction:column}.ai-chat-form-card__actions-spacer{display:none}.ai-chat-form-card__btn{width:100%}}.ai-chat-widget.dark .ai-chat-form-card__actions,.chakra-ui-dark .ai-chat-form-card__actions,.dark .ai-chat-form-card__actions,[data-theme=dark] .ai-chat-form-card__actions{border-color:hsla(0,0%,100%,.08)}.ai-chat-form-card__actions-spacer{flex:1}.ai-chat-form-card__btn{border:none;border-radius:9999px;cursor:pointer;font-family:inherit;font-size:13px;font-weight:500;padding:8px 16px;transition:all .2s ease}.ai-chat-form-card__btn:disabled{cursor:not-allowed;opacity:.5}.ai-chat-form-card__btn--primary{background:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-form-card__btn--primary:hover:not(:disabled){opacity:.9;transform:translateY(-1px)}.ai-chat-form-card__btn--secondary{background:var(--bg-primary,#fff);border:1px solid var(--border-default,#e5e7eb);color:var(--text-primary,#3e3e3e)}.ai-chat-form-card__btn--secondary:hover:not(:disabled){border-color:var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-widget.dark .ai-chat-form-card__btn--secondary,.chakra-ui-dark .ai-chat-form-card__btn--secondary,.dark .ai-chat-form-card__btn--secondary,[data-theme=dark] .ai-chat-form-card__btn--secondary{background:hsla(0,0%,100%,.05);border-color:hsla(0,0%,100%,.1);color:#fff}.ai-chat-form-card__btn--ghost{background:transparent;color:var(--text-muted,#71717a)}.ai-chat-form-card__btn--ghost:hover:not(:disabled){background:rgba(0,0,0,.05);color:var(--text-primary,#3e3e3e)}.ai-chat-widget.dark .ai-chat-form-card__btn--ghost:hover:not(:disabled),.chakra-ui-dark .ai-chat-form-card__btn--ghost:hover:not(:disabled),.dark .ai-chat-form-card__btn--ghost:hover:not(:disabled),[data-theme=dark] .ai-chat-form-card__btn--ghost:hover:not(:disabled){background:hsla(0,0%,100%,.05);color:#fff}@media (max-width:480px){.ai-chat-form-card{padding:12px}.ai-chat-form-card__title{font-size:14px}.ai-chat-form-card__context,.ai-chat-form-card__description{font-size:12px}.ai-chat-form-card__question-text{font-size:13px}.ai-chat-form-card__textarea{font-size:13px;min-height:70px}.ai-chat-form-card__option{padding:8px 10px}.ai-chat-form-card__option-text{font-size:13px}}.ai-chat-booking-card{--action-accent:var(--primary-color,#3b82f6);background:var(--bg-secondary,#f5f5f5);border-radius:12px;box-sizing:border-box;margin:6px 0;padding:16px;width:100%}.ai-chat-widget.dark .ai-chat-booking-card,.chakra-ui-dark .ai-chat-booking-card,.dark .ai-chat-booking-card,[data-theme=dark] .ai-chat-booking-card{background:hsla(0,0%,100%,.06)}.ai-chat-booking-card__header{align-items:center;display:flex;gap:8px;margin-bottom:12px}.ai-chat-booking-card__back-btn{align-items:center;background:rgba(0,0,0,.05);border:none;border-radius:6px;color:var(--text-secondary,#6b7280);cursor:pointer;display:flex;font-family:inherit;font-size:13px;font-weight:500;justify-content:center;padding:6px;transition:background .15s ease,color .15s ease}.ai-chat-booking-card__back-btn svg{height:16px;width:16px}.ai-chat-booking-card__back-btn:hover{background:rgba(0,0,0,.1);color:var(--text-primary,#3e3e3e)}.ai-chat-widget.dark .ai-chat-booking-card__back-btn,.chakra-ui-dark .ai-chat-booking-card__back-btn,.dark .ai-chat-booking-card__back-btn,[data-theme=dark] .ai-chat-booking-card__back-btn{background:hsla(0,0%,100%,.08);color:var(--text-secondary,#a1a1aa)}.ai-chat-widget.dark .ai-chat-booking-card__back-btn:hover,.chakra-ui-dark .ai-chat-booking-card__back-btn:hover,.dark .ai-chat-booking-card__back-btn:hover,[data-theme=dark] .ai-chat-booking-card__back-btn:hover{background:hsla(0,0%,100%,.15);color:#fff}.ai-chat-booking-card__title{color:var(--text-primary,#3e3e3e);font-size:15px;font-weight:600}.ai-chat-widget.dark .ai-chat-booking-card__title,.chakra-ui-dark .ai-chat-booking-card__title,.dark .ai-chat-booking-card__title,[data-theme=dark] .ai-chat-booking-card__title{color:#fff}.ai-chat-booking-card__status-icon{align-items:center;border-radius:50%;display:flex;flex-shrink:0;height:20px;justify-content:center;position:relative;width:20px}.ai-chat-booking-card__status-icon--pending{background:#6b7280}.ai-chat-booking-card__status-icon--pending:before{background:#fff;border-radius:1px;content:\"\";height:6px;position:absolute;top:5px;width:2px}.ai-chat-booking-card__status-icon--pending:after{background:#fff;border-radius:1px;content:\"\";height:2px;left:9px;position:absolute;top:9px;width:4px}.ai-chat-booking-card__status-icon--cancelled{background:#6b7280}.ai-chat-booking-card__status-icon--cancelled:after,.ai-chat-booking-card__status-icon--cancelled:before{background:#fff;border-radius:1px;content:\"\";height:2px;position:absolute;width:10px}.ai-chat-booking-card__status-icon--cancelled:before{transform:rotate(45deg)}.ai-chat-booking-card__status-icon--cancelled:after{transform:rotate(-45deg)}.ai-chat-booking-card__status-icon--error{background:#6b7280}.ai-chat-booking-card__status-icon--error:after{color:#fff;content:\"!\";font-size:12px;font-weight:700}.ai-chat-booking-card__content{display:flex;flex-direction:column;gap:12px}.ai-chat-booking-card__description{color:var(--text-muted,#71717a);font-size:13px;line-height:1.4;margin:0}.ai-chat-booking-card__empty{color:var(--text-muted,#71717a);font-size:13px;padding:16px;text-align:center}.ai-chat-booking-card__warning{background:rgba(0,0,0,.04);border-radius:8px;color:var(--text-secondary,#6b7280);font-size:13px;margin:0;padding:10px 12px}.ai-chat-widget.dark .ai-chat-booking-card__warning,.chakra-ui-dark .ai-chat-booking-card__warning,.dark .ai-chat-booking-card__warning,[data-theme=dark] .ai-chat-booking-card__warning{background:hsla(0,0%,100%,.06);color:var(--text-secondary,#a1a1aa)}.ai-chat-booking-card__input{background:rgba(0,0,0,.05);border:none;border-radius:8px;box-sizing:border-box;color:var(--text-primary,#3e3e3e);font-family:inherit;font-size:14px;outline:none;padding:10px 12px;transition:background .15s ease,box-shadow .15s ease;width:100%}.ai-chat-booking-card__input:focus{background:rgba(0,0,0,.08);box-shadow:0 0 0 2px var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-booking-card__input::placeholder{color:var(--text-muted,#9ca3af)}.ai-chat-widget.dark .ai-chat-booking-card__input,.chakra-ui-dark .ai-chat-booking-card__input,.dark .ai-chat-booking-card__input,[data-theme=dark] .ai-chat-booking-card__input{background:hsla(0,0%,100%,.08);color:#fff}.ai-chat-widget.dark .ai-chat-booking-card__input:focus,.chakra-ui-dark .ai-chat-booking-card__input:focus,.dark .ai-chat-booking-card__input:focus,[data-theme=dark] .ai-chat-booking-card__input:focus{background:hsla(0,0%,100%,.12)}.ai-chat-booking-card__field{display:flex;flex-direction:column;gap:8px}.ai-chat-booking-card__label{color:var(--text-secondary,#6b7280);display:block;font-size:13px;font-weight:500;margin-bottom:4px}.ai-chat-widget.dark .ai-chat-booking-card__label,.chakra-ui-dark .ai-chat-booking-card__label,.dark .ai-chat-booking-card__label,[data-theme=dark] .ai-chat-booking-card__label{color:var(--text-secondary,#a1a1aa)}.ai-chat-booking-card__btn{border:none;border-radius:9999px;box-sizing:border-box;cursor:pointer;font-family:inherit;font-size:13px;font-weight:500;padding:10px 16px;transition:all .15s ease;width:100%}.ai-chat-booking-card__btn:disabled{cursor:not-allowed;opacity:.5}.ai-chat-booking-card__btn--primary{background:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-booking-card__btn--primary:hover:not(:disabled){filter:brightness(1.1);transform:translateY(-1px)}.ai-chat-booking-card__btn--secondary{background:rgba(0,0,0,.06);color:var(--text-primary,#3e3e3e)}.ai-chat-booking-card__btn--secondary:hover:not(:disabled){background:rgba(0,0,0,.1)}.ai-chat-widget.dark .ai-chat-booking-card__btn--secondary,.chakra-ui-dark .ai-chat-booking-card__btn--secondary,.dark .ai-chat-booking-card__btn--secondary,[data-theme=dark] .ai-chat-booking-card__btn--secondary{background:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-booking-card__btn--secondary:hover:not(:disabled),.chakra-ui-dark .ai-chat-booking-card__btn--secondary:hover:not(:disabled),.dark .ai-chat-booking-card__btn--secondary:hover:not(:disabled),[data-theme=dark] .ai-chat-booking-card__btn--secondary:hover:not(:disabled){background:hsla(0,0%,100%,.15)}.ai-chat-booking-card__btn--danger{background:rgba(220,38,38,.1);color:#dc2626}.ai-chat-booking-card__btn--danger:hover:not(:disabled){background:rgba(220,38,38,.18)}.ai-chat-widget.dark .ai-chat-booking-card__btn--danger,.chakra-ui-dark .ai-chat-booking-card__btn--danger,.dark .ai-chat-booking-card__btn--danger,[data-theme=dark] .ai-chat-booking-card__btn--danger{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-booking-card__btn--inline{font-size:12px;margin-top:8px;padding:6px 12px;width:auto}.ai-chat-booking-card__options{display:flex;flex-direction:column;gap:8px}.ai-chat-booking-card__option-btn{align-items:center;background:rgba(0,0,0,.04);border:none;border-radius:10px;box-sizing:border-box;cursor:pointer;display:flex;font-family:inherit;gap:12px;padding:14px 16px;text-align:left;transition:background .15s ease;width:100%}.ai-chat-booking-card__option-btn:hover:not(:disabled){background:rgba(0,0,0,.08)}.ai-chat-booking-card__option-btn:disabled{cursor:not-allowed;opacity:.5}.ai-chat-widget.dark .ai-chat-booking-card__option-btn,.chakra-ui-dark .ai-chat-booking-card__option-btn,.dark .ai-chat-booking-card__option-btn,[data-theme=dark] .ai-chat-booking-card__option-btn{background:hsla(0,0%,100%,.06)}.ai-chat-widget.dark .ai-chat-booking-card__option-btn:hover:not(:disabled),.chakra-ui-dark .ai-chat-booking-card__option-btn:hover:not(:disabled),.dark .ai-chat-booking-card__option-btn:hover:not(:disabled),[data-theme=dark] .ai-chat-booking-card__option-btn:hover:not(:disabled){background:hsla(0,0%,100%,.1)}.ai-chat-booking-card__option-icon{align-items:center;background:var(--action-accent,var(--primary-color,#3b82f6));border-radius:8px;color:#fff;display:flex;flex-shrink:0;height:32px;justify-content:center;width:32px}.ai-chat-booking-card__option-icon svg{height:16px;width:16px}.ai-chat-booking-card__option-text{color:var(--text-primary,#3e3e3e);font-size:14px;font-weight:500}.ai-chat-widget.dark .ai-chat-booking-card__option-text,.chakra-ui-dark .ai-chat-booking-card__option-text,.dark .ai-chat-booking-card__option-text,[data-theme=dark] .ai-chat-booking-card__option-text{color:#fff}.ai-chat-booking-card__list{display:flex;flex-direction:column;gap:6px}.ai-chat-booking-card__list-item{align-items:center;background:rgba(0,0,0,.04);border:none;border-radius:10px;box-sizing:border-box;cursor:pointer;display:flex;font-family:inherit;justify-content:space-between;padding:12px 14px;text-align:left;transition:background .15s ease;width:100%}.ai-chat-booking-card__list-item:hover{background:rgba(0,0,0,.08)}.ai-chat-widget.dark .ai-chat-booking-card__list-item,.chakra-ui-dark .ai-chat-booking-card__list-item,.dark .ai-chat-booking-card__list-item,[data-theme=dark] .ai-chat-booking-card__list-item{background:hsla(0,0%,100%,.06)}.ai-chat-widget.dark .ai-chat-booking-card__list-item:hover,.chakra-ui-dark .ai-chat-booking-card__list-item:hover,.dark .ai-chat-booking-card__list-item:hover,[data-theme=dark] .ai-chat-booking-card__list-item:hover{background:hsla(0,0%,100%,.1)}.ai-chat-booking-card__list-item-content{display:flex;flex-direction:column;gap:2px}.ai-chat-booking-card__list-item-name{color:var(--text-primary,#3e3e3e);font-size:14px;font-weight:500}.ai-chat-widget.dark .ai-chat-booking-card__list-item-name,.chakra-ui-dark .ai-chat-booking-card__list-item-name,.dark .ai-chat-booking-card__list-item-name,[data-theme=dark] .ai-chat-booking-card__list-item-name{color:#fff}.ai-chat-booking-card__list-item-role{color:var(--text-muted,#71717a);font-size:12px}.ai-chat-booking-card__list-item-arrow{flex-shrink:0;height:16px;position:relative;width:16px}.ai-chat-booking-card__list-item-arrow:before{border-width:medium;border-bottom:2px solid var(--text-muted,#9ca3af);border-left:0 solid var(--text-muted,#9ca3af);border-right:2px solid var(--text-muted,#9ca3af);border-top:0 solid var(--text-muted,#9ca3af);content:\"\";height:6px;left:50%;position:absolute;top:50%;transform:translate(-70%,-50%) rotate(-45deg);width:6px}.ai-chat-booking-card__slots-container{display:flex;flex-direction:column;gap:12px;max-height:280px;overflow-y:auto}.ai-chat-booking-card__date-group{display:flex;flex-direction:column;gap:8px}.ai-chat-booking-card__date-header{color:var(--text-muted,#71717a);font-size:12px;font-weight:600;letter-spacing:.5px;margin:0;padding-left:2px;text-transform:uppercase}.ai-chat-booking-card__slots{display:flex;flex-wrap:wrap;gap:6px}.ai-chat-booking-card__slot{background:rgba(0,0,0,.05);border:none;border-radius:20px;color:var(--text-primary,#3e3e3e);cursor:pointer;flex:0 0 auto;font-family:inherit;font-size:13px;font-weight:500;padding:8px 14px;transition:background .15s ease,transform .1s ease;white-space:nowrap}.ai-chat-booking-card__slot:hover:not(:disabled){background:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-booking-card__slot:active:not(:disabled){transform:scale(.97)}.ai-chat-booking-card__slot:disabled{cursor:not-allowed;opacity:.5}.ai-chat-widget.dark .ai-chat-booking-card__slot,.chakra-ui-dark .ai-chat-booking-card__slot,.dark .ai-chat-booking-card__slot,[data-theme=dark] .ai-chat-booking-card__slot{background:hsla(0,0%,100%,.1);color:#fff}.ai-chat-widget.dark .ai-chat-booking-card__slot:hover:not(:disabled),.chakra-ui-dark .ai-chat-booking-card__slot:hover:not(:disabled),.dark .ai-chat-booking-card__slot:hover:not(:disabled),[data-theme=dark] .ai-chat-booking-card__slot:hover:not(:disabled){background:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-booking-card__subject-options{display:flex;flex-direction:column;gap:6px}.ai-chat-booking-card__subject-option{background:rgba(0,0,0,.04);border:none;border-radius:10px;color:var(--text-primary,#3e3e3e);cursor:pointer;font-family:inherit;font-size:14px;font-weight:500;padding:12px 14px;text-align:left;transition:background .15s ease,filter .15s ease}.ai-chat-booking-card__subject-option:hover:not(.ai-chat-booking-card__subject-option--selected){background:rgba(0,0,0,.08)}.ai-chat-booking-card__subject-option--selected,.ai-chat-booking-card__subject-option--selected:hover{background:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-booking-card__subject-option--selected:hover{filter:brightness(1.1)}.ai-chat-widget.dark .ai-chat-booking-card__subject-option,.chakra-ui-dark .ai-chat-booking-card__subject-option,.dark .ai-chat-booking-card__subject-option,[data-theme=dark] .ai-chat-booking-card__subject-option{background:hsla(0,0%,100%,.06);color:#fff}.ai-chat-widget.dark .ai-chat-booking-card__subject-option:hover:not(.ai-chat-booking-card__subject-option--selected),.chakra-ui-dark .ai-chat-booking-card__subject-option:hover:not(.ai-chat-booking-card__subject-option--selected),.dark .ai-chat-booking-card__subject-option:hover:not(.ai-chat-booking-card__subject-option--selected),[data-theme=dark] .ai-chat-booking-card__subject-option:hover:not(.ai-chat-booking-card__subject-option--selected){background:hsla(0,0%,100%,.1)}.ai-chat-widget.dark .ai-chat-booking-card__subject-option--selected,.ai-chat-widget.dark .ai-chat-booking-card__subject-option--selected:hover,.chakra-ui-dark .ai-chat-booking-card__subject-option--selected,.chakra-ui-dark .ai-chat-booking-card__subject-option--selected:hover,.dark .ai-chat-booking-card__subject-option--selected,.dark .ai-chat-booking-card__subject-option--selected:hover,[data-theme=dark] .ai-chat-booking-card__subject-option--selected,[data-theme=dark] .ai-chat-booking-card__subject-option--selected:hover{background:var(--action-accent,var(--primary-color,#3b82f6));color:#fff}.ai-chat-booking-card__appointments{display:flex;flex-direction:column;gap:8px}.ai-chat-booking-card__appointment{background:rgba(0,0,0,.04);border-radius:10px;padding:12px 14px}.ai-chat-widget.dark .ai-chat-booking-card__appointment,.chakra-ui-dark .ai-chat-booking-card__appointment,.dark .ai-chat-booking-card__appointment,[data-theme=dark] .ai-chat-booking-card__appointment{background:hsla(0,0%,100%,.06)}.ai-chat-booking-card__appointment-header{align-items:center;display:flex;gap:8px;justify-content:space-between;margin-bottom:6px}.ai-chat-booking-card__appointment-subject{color:var(--text-primary,#3e3e3e);font-size:14px;font-weight:500}.ai-chat-widget.dark .ai-chat-booking-card__appointment-subject,.chakra-ui-dark .ai-chat-booking-card__appointment-subject,.dark .ai-chat-booking-card__appointment-subject,[data-theme=dark] .ai-chat-booking-card__appointment-subject{color:#fff}.ai-chat-booking-card__appointment-status{border-radius:10px;font-size:11px;font-weight:600;padding:3px 8px;text-transform:uppercase}.ai-chat-booking-card__appointment-status--confirmed{background:rgba(59,130,246,.15);color:#3b82f6}.ai-chat-booking-card__appointment-status--pending{background:hsla(220,9%,46%,.15);color:#6b7280}.ai-chat-widget.dark .ai-chat-booking-card__appointment-status--confirmed,.chakra-ui-dark .ai-chat-booking-card__appointment-status--confirmed,.dark .ai-chat-booking-card__appointment-status--confirmed,[data-theme=dark] .ai-chat-booking-card__appointment-status--confirmed{background:rgba(59,130,246,.25);color:#60a5fa}.ai-chat-widget.dark .ai-chat-booking-card__appointment-status--pending,.chakra-ui-dark .ai-chat-booking-card__appointment-status--pending,.dark .ai-chat-booking-card__appointment-status--pending,[data-theme=dark] .ai-chat-booking-card__appointment-status--pending{background:hsla(220,9%,46%,.25);color:#9ca3af}.ai-chat-booking-card__appointment-status--cancelled{background:hsla(220,9%,46%,.15);color:#6b7280}.ai-chat-booking-card__appointment-time{color:var(--text-secondary,#6b7280);font-size:13px;margin-bottom:4px}.ai-chat-widget.dark .ai-chat-booking-card__appointment-time,.chakra-ui-dark .ai-chat-booking-card__appointment-time,.dark .ai-chat-booking-card__appointment-time,[data-theme=dark] .ai-chat-booking-card__appointment-time{color:var(--text-secondary,#a1a1aa)}.ai-chat-booking-card__appointment-contact{color:var(--text-muted,#71717a);font-size:12px}.ai-chat-booking-card__appointment-info{display:flex;flex-direction:column;gap:4px;margin-bottom:10px}.ai-chat-booking-card__appointment-actions{display:flex;flex-wrap:wrap;gap:8px}@media (max-width:380px){.ai-chat-booking-card__appointment-actions{flex-direction:column}.ai-chat-booking-card__appointment-cancel,.ai-chat-booking-card__appointment-link{justify-content:center;text-align:center;width:100%}}.ai-chat-booking-card__appointment-link{background:var(--action-accent,var(--primary-color,#3b82f6));border-radius:6px;color:#fff;display:inline-block;font-size:12px;font-weight:500;padding:6px 12px;text-decoration:none;transition:filter .15s ease}.ai-chat-booking-card__appointment-link:hover{filter:brightness(1.1);text-decoration:none}.ai-chat-booking-card__appointment-cancel{background:rgba(220,38,38,.1);border:none;border-radius:6px;color:#dc2626;cursor:pointer;font-family:inherit;font-size:12px;font-weight:500;padding:6px 12px;transition:background .15s ease}.ai-chat-booking-card__appointment-cancel:hover:not(:disabled){background:rgba(220,38,38,.18)}.ai-chat-booking-card__appointment-cancel:disabled{cursor:not-allowed;opacity:.5}.ai-chat-widget.dark .ai-chat-booking-card__appointment-cancel,.chakra-ui-dark .ai-chat-booking-card__appointment-cancel,.dark .ai-chat-booking-card__appointment-cancel,[data-theme=dark] .ai-chat-booking-card__appointment-cancel{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-booking-card__summary{background:rgba(0,0,0,.04);border-radius:10px;padding:12px 14px}.ai-chat-widget.dark .ai-chat-booking-card__summary,.chakra-ui-dark .ai-chat-booking-card__summary,.dark .ai-chat-booking-card__summary,[data-theme=dark] .ai-chat-booking-card__summary{background:hsla(0,0%,100%,.06)}.ai-chat-booking-card__summary-row{align-items:center;display:flex;gap:8px;justify-content:space-between;padding:6px 0}@media (max-width:380px){.ai-chat-booking-card__summary-row{align-items:flex-start;flex-direction:column;gap:2px}.ai-chat-booking-card__summary-value{text-align:left}}.ai-chat-booking-card__summary-row:not(:last-child){border-bottom:1px solid rgba(0,0,0,.06)}.ai-chat-widget.dark .ai-chat-booking-card__summary-row:not(:last-child),.chakra-ui-dark .ai-chat-booking-card__summary-row:not(:last-child),.dark .ai-chat-booking-card__summary-row:not(:last-child),[data-theme=dark] .ai-chat-booking-card__summary-row:not(:last-child){border-bottom-color:hsla(0,0%,100%,.08)}.ai-chat-booking-card__summary-label{color:var(--text-muted,#71717a);font-size:12px;font-weight:600;letter-spacing:.5px;text-transform:uppercase}.ai-chat-booking-card__summary-value{color:var(--text-primary,#3e3e3e);font-size:14px;font-weight:500;text-align:right}.ai-chat-widget.dark .ai-chat-booking-card__summary-value,.chakra-ui-dark .ai-chat-booking-card__summary-value,.dark .ai-chat-booking-card__summary-value,[data-theme=dark] .ai-chat-booking-card__summary-value{color:#fff}.ai-chat-booking-card__success-icon{align-items:center;background:var(--action-accent,var(--primary-color,#3b82f6));border-radius:50%;display:flex;height:40px;justify-content:center;margin:0 auto 12px;position:relative;width:40px}.ai-chat-booking-card__success-icon:after{border:solid #fff;border-width:0 3px 3px 0;content:\"\";height:16px;margin-bottom:4px;transform:rotate(45deg);width:10px}.ai-chat-booking-card__success-message{color:var(--text-secondary,#6b7280);font-size:14px;margin:0 0 12px;text-align:center}.ai-chat-widget.dark .ai-chat-booking-card__success-message,.chakra-ui-dark .ai-chat-booking-card__success-message,.dark .ai-chat-booking-card__success-message,[data-theme=dark] .ai-chat-booking-card__success-message{color:var(--text-secondary,#a1a1aa)}.ai-chat-booking-card__link{display:inline-block;font-size:13px;font-weight:500;margin-top:8px;text-decoration:none;transition:opacity .15s ease}.ai-chat-booking-card__link:hover{opacity:.8;text-decoration:underline}.ai-chat-booking-card--success{background:rgba(59,130,246,.08)}.ai-chat-widget.dark .ai-chat-booking-card--success,.chakra-ui-dark .ai-chat-booking-card--success,.dark .ai-chat-booking-card--success,[data-theme=dark] .ai-chat-booking-card--success{background:rgba(59,130,246,.12)}.ai-chat-booking-card--pending{background:hsla(220,9%,46%,.08)}.ai-chat-widget.dark .ai-chat-booking-card--pending,.chakra-ui-dark .ai-chat-booking-card--pending,.dark .ai-chat-booking-card--pending,[data-theme=dark] .ai-chat-booking-card--pending{background:hsla(220,9%,46%,.12)}.ai-chat-booking-card--cancelled{background:hsla(220,9%,46%,.08)}.ai-chat-widget.dark .ai-chat-booking-card--cancelled,.chakra-ui-dark .ai-chat-booking-card--cancelled,.dark .ai-chat-booking-card--cancelled,[data-theme=dark] .ai-chat-booking-card--cancelled{background:hsla(220,9%,46%,.12)}.ai-chat-booking-card--error{background:hsla(220,9%,46%,.08)}.ai-chat-widget.dark .ai-chat-booking-card--error,.chakra-ui-dark .ai-chat-booking-card--error,.dark .ai-chat-booking-card--error,[data-theme=dark] .ai-chat-booking-card--error{background:hsla(220,9%,46%,.12)}.ai-chat-booking-card__pending-text,.ai-chat-booking-card__success-text{color:var(--text-secondary,#6b7280);font-size:13px;margin:0}.ai-chat-widget.dark .ai-chat-booking-card__pending-text,.ai-chat-widget.dark .ai-chat-booking-card__success-text,.chakra-ui-dark .ai-chat-booking-card__pending-text,.chakra-ui-dark .ai-chat-booking-card__success-text,.dark .ai-chat-booking-card__pending-text,.dark .ai-chat-booking-card__success-text,[data-theme=dark] .ai-chat-booking-card__pending-text,[data-theme=dark] .ai-chat-booking-card__success-text{color:var(--text-secondary,#a1a1aa)}.ai-chat-booking-card__error{background:rgba(220,38,38,.08);border-radius:8px;color:#dc2626;font-size:13px;margin:0;padding:10px 12px}.ai-chat-widget.dark .ai-chat-booking-card__error,.chakra-ui-dark .ai-chat-booking-card__error,.dark .ai-chat-booking-card__error,[data-theme=dark] .ai-chat-booking-card__error{background:rgba(239,68,68,.15);color:#fca5a5}.ai-chat-booking-card--closable{position:relative}.ai-chat-booking-card--closable .ai-chat-booking-card__header{padding-right:40px}.ai-chat-pin-input-group{display:flex;flex-wrap:wrap;gap:8px;justify-content:center}@media (max-width:320px){.ai-chat-pin-input-group{gap:6px}}.ai-chat-pin-input{background:rgba(0,0,0,.05);border:none;border-radius:8px;box-sizing:border-box;color:var(--text-primary,#3e3e3e);font-family:inherit;font-size:20px;font-weight:600;height:48px;outline:none;padding:0;text-align:center;transition:background .15s ease,box-shadow .15s ease;width:42px}@media (max-width:320px){.ai-chat-pin-input{font-size:18px;height:42px;width:36px}}.ai-chat-pin-input:focus{background:rgba(0,0,0,.08);box-shadow:0 0 0 2px var(--action-accent,var(--primary-color,#3b82f6))}.ai-chat-pin-input::placeholder{color:var(--text-muted,#9ca3af)}.ai-chat-pin-input:disabled{cursor:not-allowed;opacity:.5}.ai-chat-widget.dark .ai-chat-pin-input,.chakra-ui-dark .ai-chat-pin-input,.dark .ai-chat-pin-input,[data-theme=dark] .ai-chat-pin-input{background:hsla(0,0%,100%,.08);color:#fff}.ai-chat-widget.dark .ai-chat-pin-input:focus,.chakra-ui-dark .ai-chat-pin-input:focus,.dark .ai-chat-pin-input:focus,[data-theme=dark] .ai-chat-pin-input:focus{background:hsla(0,0%,100%,.12)}@media (max-width:480px){.ai-chat-booking-card{padding:12px}.ai-chat-booking-card__title{font-size:14px}.ai-chat-booking-card__option-btn{padding:12px 14px}.ai-chat-booking-card__option-icon{height:28px;width:28px}.ai-chat-booking-card__option-icon svg{height:14px;width:14px}.ai-chat-booking-card__option-text{font-size:13px}.ai-chat-booking-card__slots-container{max-height:240px}.ai-chat-booking-card__slot{font-size:12px;padding:6px 12px}}.ai-chat-structured-image{--action-accent:var(--primary-color,#3b82f6);display:flex;flex-direction:column;gap:8px;width:100%}.ai-chat-structured-image__context{color:var(--text-primary,#3e3e3e);font-size:13px;line-height:1.4;margin:0 0 4px}.ai-chat-widget.dark .ai-chat-structured-image__context,.chakra-ui-dark .ai-chat-structured-image__context,.dark .ai-chat-structured-image__context,[data-theme=dark] .ai-chat-structured-image__context{color:var(--text-primary,#fff)}.ai-chat-structured-image__error{background:rgba(239,68,68,.1);border-radius:var(--radius-md,8px);color:#dc2626;font-size:13px;padding:12px 16px;text-align:center}.ai-chat-widget.dark .ai-chat-structured-image__error,.chakra-ui-dark .ai-chat-structured-image__error,.dark .ai-chat-structured-image__error,[data-theme=dark] .ai-chat-structured-image__error{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-structured-image__cards{display:grid;gap:8px;grid-template-columns:repeat(2,1fr)}.ai-chat-structured-image__cards:has(.ai-chat-project-card:only-child){grid-template-columns:1fr}@supports not selector(:has(*)){.ai-chat-structured-image__cards{grid-template-columns:repeat(var(--card-columns,2),1fr)}}@media (max-width:480px){.ai-chat-structured-image__cards{grid-template-columns:1fr}}.ai-chat-media-display{--action-accent:var(--primary-color,#3b82f6);display:flex;flex-direction:column;gap:8px;margin-top:4px;padding:0!important}.ai-chat-media-display__context{color:var(--text-muted,#71717a);font-size:13px;margin:0 0 4px;padding:0 4px}.ai-chat-media-display__error{background:rgba(239,68,68,.1);border-radius:var(--radius-lg,12px);color:#dc2626;font-size:13px;padding:16px;text-align:center}.ai-chat-widget.dark .ai-chat-media-display__error,.chakra-ui-dark .ai-chat-media-display__error,.dark .ai-chat-media-display__error,[data-theme=dark] .ai-chat-media-display__error{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-media-display__cards{display:grid;gap:12px;grid-template-columns:repeat(var(--card-columns,1),1fr)}.ai-chat-image-card{--action-accent:var(--primary-color,#3b82f6);background:transparent;display:flex;flex-direction:column}.ai-chat-image-card,.ai-chat-image-card__media{border-radius:var(--radius-lg,12px);overflow:hidden}.ai-chat-image-card__media{position:relative;width:100%}.ai-chat-image-card__image{border-radius:var(--radius-lg,12px);display:block;height:auto;max-height:300px;object-fit:cover;width:100%}.ai-chat-image-card__image-error{align-items:center;background:var(--bg-muted,#e5e7eb);border-radius:var(--radius-lg,12px);color:var(--text-muted,#71717a);display:flex;font-size:13px;height:150px;justify-content:center;width:100%}.ai-chat-image-card__content{padding:10px 0 0}.ai-chat-image-card__title{color:var(--text-primary,#1a1a1a);font-size:14px;font-weight:600;line-height:1.3;margin:0 0 4px}.ai-chat-widget.dark .ai-chat-image-card__title,.dark .ai-chat-image-card__title,[data-theme=dark] .ai-chat-image-card__title{color:#fff}.ai-chat-image-card__description{color:var(--text-muted,#6b7280);font-size:13px;line-height:1.4;margin:0 0 8px}.ai-chat-image-card__link-btn{align-items:center;background:transparent;border:none;color:var(--action-accent);cursor:pointer;display:inline-flex;font-size:13px;font-weight:500;gap:4px;padding:0;transition:opacity .2s}.ai-chat-image-card__link-btn:hover{opacity:.8}.ai-chat-media-card{--action-accent:var(--primary-color,#3b82f6);background:var(--bg-secondary,#f4f4f4);border:1px solid var(--border-subtle,rgba(0,0,0,.08));border-radius:var(--radius-lg,12px);display:flex;flex-direction:column;overflow:hidden}.ai-chat-widget.dark .ai-chat-media-card,.chakra-ui-dark .ai-chat-media-card,.dark .ai-chat-media-card,[data-theme=dark] .ai-chat-media-card{background:var(--bg-secondary,#3a3a3a);border-color:hsla(0,0%,100%,.08)}.ai-chat-media-card__media{background:#000;position:relative;width:100%}.ai-chat-media-card__media.video{aspect-ratio:16/9}.ai-chat-media-card__media.image{aspect-ratio:auto;max-height:400px}.ai-chat-media-card__image{display:block;height:100%;object-fit:cover;width:100%}.ai-chat-media-card__image-error{align-items:center;background:var(--bg-muted,#e5e7eb);color:var(--text-muted,#71717a);display:flex;font-size:13px;height:200px;justify-content:center;width:100%}.ai-chat-media-card__video-placeholder{cursor:pointer;height:100%;position:relative;width:100%}.ai-chat-media-card__video-placeholder img{height:100%;object-fit:cover;width:100%}.ai-chat-media-card__video-bg{background:linear-gradient(135deg,#1a1a2e,#16213e);height:100%;width:100%}.ai-chat-media-card__play-btn{align-items:center;background:rgba(0,0,0,.7);border:none;border-radius:50%;color:#fff;cursor:pointer;display:flex;height:56px;justify-content:center;left:50%;position:absolute;top:50%;transform:translate(-50%,-50%);transition:background .2s,transform .2s;width:56px}.ai-chat-media-card__play-btn:hover{background:rgba(0,0,0,.9);transform:translate(-50%,-50%) scale(1.05)}.ai-chat-media-card__provider-badge{background:rgba(0,0,0,.8);border-radius:4px;bottom:8px;color:#fff;font-size:11px;font-weight:600;letter-spacing:.5px;padding:4px 8px;position:absolute;right:8px;text-transform:uppercase}.ai-chat-media-card__iframe,.ai-chat-media-card__video{border:none;height:100%;left:0;position:absolute;top:0;width:100%}.ai-chat-media-card__content{padding:12px}.ai-chat-media-card__title{color:var(--text-primary,#3e3e3e);font-size:15px;font-weight:600;line-height:1.3;margin:0 0 4px}.ai-chat-widget.dark .ai-chat-media-card__title,.chakra-ui-dark .ai-chat-media-card__title,.dark .ai-chat-media-card__title,[data-theme=dark] .ai-chat-media-card__title{color:#fff}.ai-chat-media-card__description{color:var(--text-muted,#71717a);font-size:13px;line-height:1.4;margin:0 0 8px}.ai-chat-media-card__link-btn{align-items:center;background:var(--action-accent);border:none;border-radius:6px;color:#fff;cursor:pointer;display:inline-flex;font-size:13px;font-weight:500;gap:6px;padding:6px 12px;transition:opacity .2s}.ai-chat-media-card__link-btn:hover{opacity:.9}.ai-chat-image-gallery{--action-accent:var(--primary-color,#3b82f6)}.ai-chat-image-gallery__grid{display:grid;gap:8px;grid-template-columns:repeat(2,1fr)}@media (max-width:480px){.ai-chat-image-gallery__grid{grid-template-columns:1fr}.ai-chat-image-gallery__grid .ai-chat-image-gallery__item:first-child{grid-column:span 1}}.ai-chat-image-gallery__grid:has(.ai-chat-image-gallery__item:only-child){grid-template-columns:1fr}.ai-chat-image-gallery__grid:has(.ai-chat-image-gallery__item:nth-child(3):last-child) .ai-chat-image-gallery__item:first-child{grid-column:span 2}.ai-chat-image-gallery__grid:has(.ai-chat-image-gallery__item:nth-child(5):last-child) .ai-chat-image-gallery__item:first-child{grid-column:span 2}.ai-chat-image-gallery__grid:has(.ai-chat-image-gallery__item:nth-child(7):last-child) .ai-chat-image-gallery__item:first-child{grid-column:span 2}.ai-chat-image-gallery__item.span-full{grid-column:span 2}.ai-chat-image-gallery[data-item-count=\"1\"] .ai-chat-image-gallery__grid{grid-template-columns:1fr}.ai-chat-image-gallery__item{position:relative}.ai-chat-image-gallery__item-media{aspect-ratio:4/3;background:var(--bg-muted,#e5e7eb);border-radius:var(--radius-lg,12px);overflow:hidden;position:relative}.ai-chat-image-gallery__item-media img{height:100%;object-fit:cover;width:100%}.ai-chat-image-gallery__item-overlay{background:linear-gradient(0deg,rgba(0,0,0,.85) 0,rgba(0,0,0,.4) 60%,transparent);border-radius:0 0 var(--radius-lg,12px) var(--radius-lg,12px);bottom:0;left:0;padding:24px 12px 10px;position:absolute;right:0}.ai-chat-image-gallery__item-title{-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;color:#fff;display:-webkit-box;font-size:12px;font-weight:600;line-height:1.3;margin:0;overflow:hidden;text-shadow:0 1px 3px rgba(0,0,0,.5)}.ai-chat-image-gallery__error{align-items:center;color:var(--text-muted,#71717a);display:flex;font-size:12px;height:100%;justify-content:center;width:100%}.ai-chat-media-gallery{--action-accent:var(--primary-color,#3b82f6)}.ai-chat-media-gallery__grid{display:grid;gap:8px;grid-template-columns:repeat(2,1fr)}.ai-chat-image-gallery__lightbox,.ai-chat-media-gallery__lightbox{align-items:center;background:rgba(0,0,0,.95);bottom:0;display:flex;justify-content:center;left:0;padding:40px;position:fixed;right:0;top:0;z-index:10000}.ai-chat-image-gallery__lightbox-close,.ai-chat-media-gallery__lightbox-close{align-items:center;background:hsla(0,0%,100%,.1);border:none;border-radius:50%;color:#fff;cursor:pointer;display:flex;height:40px;justify-content:center;position:absolute;right:16px;top:16px;transition:background .2s;width:40px}.ai-chat-image-gallery__lightbox-close:hover,.ai-chat-media-gallery__lightbox-close:hover{background:hsla(0,0%,100%,.2)}.ai-chat-image-gallery__lightbox-nav,.ai-chat-media-gallery__lightbox-nav{align-items:center;background:hsla(0,0%,100%,.1);border:none;border-radius:50%;color:#fff;cursor:pointer;display:flex;height:48px;justify-content:center;position:absolute;top:50%;transform:translateY(-50%);transition:background .2s;width:48px}.ai-chat-image-gallery__lightbox-nav:hover,.ai-chat-media-gallery__lightbox-nav:hover{background:hsla(0,0%,100%,.2)}.ai-chat-image-gallery__lightbox-nav.prev,.ai-chat-media-gallery__lightbox-nav.prev{left:16px}.ai-chat-image-gallery__lightbox-nav.next,.ai-chat-media-gallery__lightbox-nav.next{right:16px}.ai-chat-image-gallery__lightbox-content,.ai-chat-media-gallery__lightbox-content{align-items:center;display:flex;flex-direction:column;max-height:80vh;max-width:90vw}.ai-chat-image-gallery__lightbox-content img,.ai-chat-media-gallery__lightbox-content img{border-radius:4px;max-height:70vh;max-width:100%;object-fit:contain}.ai-chat-image-gallery__lightbox-caption,.ai-chat-media-gallery__lightbox-caption{color:#fff;margin-top:16px;text-align:center}.ai-chat-image-gallery__lightbox-caption h4,.ai-chat-media-gallery__lightbox-caption h4{font-size:16px;font-weight:600;margin:0 0 4px}.ai-chat-image-gallery__lightbox-caption p,.ai-chat-media-gallery__lightbox-caption p{color:hsla(0,0%,100%,.7);font-size:14px;margin:0}.ai-chat-image-gallery__lightbox-counter,.ai-chat-media-gallery__lightbox-counter{background:rgba(0,0,0,.6);border-radius:20px;bottom:16px;color:#fff;font-size:13px;left:50%;padding:6px 12px;position:absolute;transform:translateX(-50%)}.ai-chat-project-card{--action-accent:var(--primary-color,#3b82f6);background:var(--bg-secondary,#f4f4f4);border:1px solid var(--border-subtle,rgba(0,0,0,.08));border-radius:var(--radius-lg,12px);display:flex;flex-direction:column;overflow:hidden;transition:border-color .2s,box-shadow .2s,transform .2s}.ai-chat-project-card.clickable{cursor:pointer}.ai-chat-project-card.clickable:hover{border-color:var(--action-accent);box-shadow:0 4px 12px rgba(0,0,0,.1);transform:translateY(-2px)}.ai-chat-widget.dark .ai-chat-project-card,.chakra-ui-dark .ai-chat-project-card,.dark .ai-chat-project-card,[data-theme=dark] .ai-chat-project-card{background:var(--bg-secondary,#2a2a2a);border-color:hsla(0,0%,100%,.1)}.ai-chat-widget.dark .ai-chat-project-card.clickable:hover,.chakra-ui-dark .ai-chat-project-card.clickable:hover,.dark .ai-chat-project-card.clickable:hover,[data-theme=dark] .ai-chat-project-card.clickable:hover{border-color:var(--action-accent);box-shadow:0 4px 16px rgba(0,0,0,.3)}.ai-chat-project-card--image-only{background:transparent;border:none}.ai-chat-project-card--image-only .ai-chat-project-card__media{aspect-ratio:16/9;border-radius:var(--radius-lg,12px)}.ai-chat-project-card--image-only.clickable:hover{border:none;box-shadow:0 4px 16px rgba(0,0,0,.2)}.ai-chat-project-card--overlay{background:transparent;border:none;border-radius:var(--radius-lg,12px);overflow:hidden}.ai-chat-project-card--overlay .ai-chat-project-card__media{aspect-ratio:4/3;border-radius:var(--radius-lg,12px)}.ai-chat-project-card__overlay{background:linear-gradient(0deg,rgba(0,0,0,.85) 0,rgba(0,0,0,.5) 50%,transparent);border-radius:0 0 var(--radius-lg,12px) var(--radius-lg,12px);bottom:0;left:0;padding:10px 12px;position:absolute;right:0}.ai-chat-project-card__overlay-title{-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;color:#fff;display:-webkit-box;font-size:12px;font-weight:600;line-height:1.3;margin:0;overflow:hidden;text-shadow:0 1px 3px rgba(0,0,0,.5)}.ai-chat-project-card--full .ai-chat-project-card__media{aspect-ratio:16/10;border-bottom:1px solid var(--border-subtle,rgba(0,0,0,.06))}.ai-chat-widget.dark .ai-chat-project-card--full .ai-chat-project-card__media,.chakra-ui-dark .ai-chat-project-card--full .ai-chat-project-card__media,.dark .ai-chat-project-card--full .ai-chat-project-card__media,[data-theme=dark] .ai-chat-project-card--full .ai-chat-project-card__media{border-bottom-color:hsla(0,0%,100%,.08)}.ai-chat-project-card__media{aspect-ratio:16/10;background:var(--bg-muted,#e5e7eb);overflow:hidden;position:relative;width:100%}.ai-chat-widget.dark .ai-chat-project-card__media,.chakra-ui-dark .ai-chat-project-card__media,.dark .ai-chat-project-card__media,[data-theme=dark] .ai-chat-project-card__media{background:hsla(0,0%,100%,.05)}.ai-chat-project-card__media img{height:100%;object-fit:cover;transition:transform .3s ease;width:100%}.ai-chat-project-card.clickable:hover .ai-chat-project-card__media img{transform:scale(1.03)}.ai-chat-project-card__iframe,.ai-chat-project-card__video{border:none;height:100%;left:0;position:absolute;top:0;width:100%}.ai-chat-project-card__placeholder{align-items:center;color:var(--text-muted,#71717a);display:flex;font-size:13px;height:100%;justify-content:center;width:100%}.ai-chat-project-card__play-btn{align-items:center;background:rgba(0,0,0,.7);border:none;border-radius:50%;color:#fff;cursor:pointer;display:flex;height:48px;justify-content:center;left:50%;position:absolute;top:50%;transform:translate(-50%,-50%);transition:background .2s,transform .2s;width:48px}.ai-chat-project-card__play-btn:hover{background:rgba(0,0,0,.9);transform:translate(-50%,-50%) scale(1.1)}.ai-chat-project-card__content{background:var(--bg-secondary,#f4f4f4);padding:12px 14px 14px}.ai-chat-widget.dark .ai-chat-project-card__content,.chakra-ui-dark .ai-chat-project-card__content,.dark .ai-chat-project-card__content,[data-theme=dark] .ai-chat-project-card__content{background:var(--bg-secondary,#2a2a2a)}.ai-chat-project-card__title{color:var(--text-primary,#1a1a1a);font-size:14px;font-weight:600;line-height:1.35;margin:0 0 6px}.ai-chat-widget.dark .ai-chat-project-card__title,.chakra-ui-dark .ai-chat-project-card__title,.dark .ai-chat-project-card__title,[data-theme=dark] .ai-chat-project-card__title{color:#fff}.ai-chat-project-card__description{-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;color:var(--text-muted,#6b7280);display:-webkit-box;font-size:13px;line-height:1.45;margin:0 0 10px;overflow:hidden}.ai-chat-project-card__link{align-items:center;color:var(--action-accent);display:inline-flex;font-size:13px;font-weight:500;gap:4px;transition:opacity .2s}.ai-chat-project-card__link:hover{opacity:.8}.ai-chat-media-carousel{--action-accent:var(--primary-color,#3b82f6);border-radius:var(--radius-lg,12px);overflow:hidden;position:relative}.ai-chat-media-carousel__track{display:flex;transition:transform .3s ease-out}.ai-chat-media-carousel__slide{flex:0 0 100%;min-width:0}.ai-chat-media-carousel__slide .ai-chat-project-card{border-radius:var(--radius-md,8px);margin:0 4px}.ai-chat-media-carousel__nav{align-items:center;background:hsla(0,0%,100%,.9);border:none;border-radius:50%;box-shadow:0 2px 8px rgba(0,0,0,.15);color:#333;cursor:pointer;display:flex;height:32px;justify-content:center;position:absolute;top:50%;transform:translateY(-50%);transition:background .2s;width:32px;z-index:2}.ai-chat-media-carousel__nav:hover{background:#fff}.ai-chat-media-carousel__nav.prev{left:8px}.ai-chat-media-carousel__nav.next{right:8px}.ai-chat-widget.dark .ai-chat-media-carousel__nav,.chakra-ui-dark .ai-chat-media-carousel__nav,.dark .ai-chat-media-carousel__nav,[data-theme=dark] .ai-chat-media-carousel__nav{background:rgba(0,0,0,.7);color:#fff}.ai-chat-widget.dark .ai-chat-media-carousel__nav:hover,.chakra-ui-dark .ai-chat-media-carousel__nav:hover,.dark .ai-chat-media-carousel__nav:hover,[data-theme=dark] .ai-chat-media-carousel__nav:hover{background:rgba(0,0,0,.9)}.ai-chat-media-carousel__dots{display:flex;gap:6px;justify-content:center;padding:12px 0 4px}.ai-chat-media-carousel__dot{background:var(--border-subtle,rgba(0,0,0,.2));border:none;border-radius:50%;cursor:pointer;height:8px;padding:0;transition:background .2s,transform .2s;width:8px}.ai-chat-media-carousel__dot:hover{transform:scale(1.2)}.ai-chat-media-carousel__dot.active{background:var(--action-accent)}.ai-chat-widget.dark .ai-chat-media-carousel__dot,.chakra-ui-dark .ai-chat-media-carousel__dot,.dark .ai-chat-media-carousel__dot,[data-theme=dark] .ai-chat-media-carousel__dot{background:hsla(0,0%,100%,.3)}.ai-chat-widget.dark .ai-chat-media-carousel__dot.active,.chakra-ui-dark .ai-chat-media-carousel__dot.active,.dark .ai-chat-media-carousel__dot.active,[data-theme=dark] .ai-chat-media-carousel__dot.active{background:var(--action-accent)}@media (max-width:480px){.ai-chat-media-carousel__nav{height:28px;width:28px}.ai-chat-media-carousel__nav.prev{left:4px}.ai-chat-media-carousel__nav.next{right:4px}.ai-chat-image-gallery__lightbox-nav,.ai-chat-media-gallery__lightbox-nav{height:40px;width:40px}.ai-chat-image-gallery__lightbox,.ai-chat-media-gallery__lightbox{padding:16px}.ai-chat-project-card__content{padding:10px 12px 12px}.ai-chat-project-card__title{font-size:13px}.ai-chat-project-card__description{font-size:12px}}.chat-fullpage{--fp-max-width:800px;--fp-padding-x:16px;--fp-padding-top-mobile:64px;--fp-padding-top-desktop:24px;--fp-padding-bottom:200px;--fp-input-bottom:0}.chat-fullpage .ai-chat-messages{background:transparent;flex:1 1 auto;height:auto;justify-content:flex-start;margin:0 auto;max-height:none;max-width:var(--fp-max-width);min-height:0!important;overflow-x:hidden!important;overflow-y:scroll!important;padding:var(--fp-padding-top-desktop) var(--fp-padding-x) var(--fp-padding-bottom);position:relative}@media (max-width:767px){.chat-fullpage .ai-chat-messages{padding-top:var(--fp-padding-top-mobile)!important}}@media (max-width:480px){.chat-fullpage .ai-chat-messages{padding-top:calc(var(--fp-padding-top-mobile) + env(safe-area-inset-top, 0px))}}.chat-fullpage .ai-chat-messages>.ai-chat-message:first-child,.chat-fullpage .ai-chat-messages>.ai-chat-welcome:first-child{margin-top:0}.chat-fullpage .ai-chat-message{animation:none}.chat-fullpage .ai-chat-message.user{max-width:85%}.chat-fullpage .ai-chat-message.user .ai-chat-message-content{background:var(--bg-muted,#f4f4f5);border-radius:24px;color:#000;padding:8px 16px}.chat-fullpage.dark .ai-chat-message.user .ai-chat-message-content{background:var(--bg-muted,#27272a);color:#fff}.chat-fullpage .ai-chat-message.assistant{width:100%}.chat-fullpage .ai-chat-message.assistant .ai-chat-message-content{color:#000;padding:8px 16px}.chat-fullpage.dark .ai-chat-message.assistant .ai-chat-message-content{color:#fff}.chat-fullpage .ai-chat-message.tool{margin:0;padding:0;width:100%}.chat-fullpage .ai-chat-welcome{align-items:center;display:flex;flex-direction:column;gap:24px;justify-content:center;min-height:60vh;padding:24px;text-align:center}.chat-fullpage .ai-chat-welcome-title{font-size:32px;font-weight:600}.chat-fullpage .ai-chat-welcome-text{color:var(--text-muted,#71717a);font-size:18px;max-width:400px}.chat-fullpage .ai-chat-input-container{background:transparent;bottom:0;left:0;padding:16px 16px calc(16px + env(safe-area-inset-bottom));position:fixed;right:0;z-index:20}.chat-fullpage .ai-chat-input-container:after{background:var(--bg-primary,#fff);bottom:0;content:\"\";height:calc(40% + 16px);left:0;pointer-events:none;position:absolute;right:0;z-index:-1}.chat-fullpage.dark .ai-chat-input-container:after{background:var(--bg-primary,#18181b)}@media (min-width:769px){.chat-fullpage .ai-chat-input-container{background:transparent;bottom:var(--fp-input-bottom);left:50%;max-width:var(--fp-max-width);padding:12px 0 0;position:absolute;right:auto;transform:translateX(-50%);width:100%}}.chat-fullpage .ai-chat-input-wrapper{background:var(--bg-muted,#f4f4f5);border:1px solid var(--border-muted,#e4e4e7);border-radius:24px;box-shadow:0 1px 8px rgba(0,0,0,.06);margin:0 auto;max-width:var(--fp-max-width)}.chat-fullpage.dark .ai-chat-input-wrapper{background:var(--bg-muted,#27272a);border-color:var(--border-muted,#3f3f46);box-shadow:0 1px 12px rgba(0,0,0,.25)}.chat-fullpage .ai-chat-scroll-button{bottom:100px}@media (min-width:769px){.chat-fullpage .ai-chat-scroll-button{bottom:110px}}.chat-fullpage .ai-chat-suggested-questions{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;max-width:600px}.chat-fullpage .ai-chat-suggested-question{border-radius:9999px;font-size:14px;padding:8px 16px}.chat-fullpage .ai-chat-follow-up-suggestions{margin-top:12px}.chat-fullpage .ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-default,#d4d4d8);color:#000}.chat-fullpage .ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#f4f4f5)}.chat-fullpage.dark .ai-chat-follow-up-item.question-type{background:transparent;border:1px solid var(--border-subtle,#52525b);color:#fff}.chat-fullpage.dark .ai-chat-follow-up-item.question-type:hover{background:var(--bg-hover,#3f3f46)}.chat-fullpage .ai-chat-typing{padding:8px 16px}.chat-fullpage .ai-chat-message-meta{align-items:center;display:flex;gap:8px;margin-top:4px;padding:0 16px}.chat-fullpage .ai-chat-message-timestamp{color:var(--text-muted,#71717a);font-size:12px}.chat-fullpage .ai-chat-feedback{display:inline-flex}.chat-fullpage .ai-chat-feedback-button{display:flex}@media (max-width:480px){body.ai-chat-widget-open{height:100%!important;overflow:hidden!important;position:fixed!important;touch-action:none!important;width:100%!important}.ai-chat-widget-container:not(.is-open).bottom-right .ai-chat-button{bottom:12px!important;right:12px!important}.ai-chat-widget-container:not(.is-open).bottom-left .ai-chat-button{bottom:12px!important;left:12px!important}.ai-chat-widget-container:not(.is-open).top-right .ai-chat-button{right:12px!important;top:12px!important}.ai-chat-widget-container:not(.is-open).top-left .ai-chat-button{left:12px!important;top:12px!important}.ai-chat-widget-container.trigger-pill-text.container-mode:not(.is-open).bottom-right .ai-chat-trigger-pill{bottom:12px!important;right:12px!important}.ai-chat-widget-container.trigger-pill-text.container-mode:not(.is-open).bottom-left .ai-chat-trigger-pill{bottom:12px!important;left:12px!important}.ai-chat-widget-container.trigger-pill-text.container-mode:not(.is-open).top-right .ai-chat-trigger-pill{right:12px!important;top:12px!important}.ai-chat-widget-container.trigger-pill-text.container-mode:not(.is-open).top-left .ai-chat-trigger-pill{left:12px!important;top:12px!important}.ai-chat-widget-container.trigger-input-bar.container-mode:not(.is-open) .ai-chat-trigger-input-container{bottom:12px!important;left:12px!important;right:12px!important;width:calc(100% - 24px)!important}.ai-chat-widget-container.trigger-input-bar:not(.is-open) .ai-chat-trigger-input-wrapper{max-width:100%!important;width:100%!important}.ai-chat-widget-container.trigger-input-bar:not(.is-open) .ai-chat-trigger-input-row{display:flex;gap:8px;max-width:calc(100vw - 24px)!important;width:calc(100vw - 24px)!important}.ai-chat-widget-container.trigger-input-bar.is-collapsed:not(.is-open) .ai-chat-trigger-input-container{bottom:12px!important;right:12px!important;width:auto!important}.ai-chat-widget-container.trigger-input-bar.is-collapsed:not(.is-open) .ai-chat-button{margin-left:0!important;margin-right:0!important}.ai-chat-widget-container.is-open{height:100vh!important;height:100dvh!important;width:100vw!important;z-index:var(--widget-z-index,2147483647)!important}.ai-chat-widget-container.is-open,.ai-chat-widget-container.is-open .ai-chat-window{bottom:0!important;left:0!important;position:fixed!important;right:0!important;top:0!important}.ai-chat-widget-container.is-open .ai-chat-window{animation:none!important;border:none!important;border-radius:0!important;box-shadow:none!important;height:100%!important;max-height:100%!important;max-width:100%!important;outline:none!important;transform:none!important;width:100%!important}.ai-chat-widget-container.is-open .ai-chat-button{display:none!important;pointer-events:none!important;visibility:hidden!important}.ai-chat-widget-container.is-open .ai-chat-header{border-radius:0!important;flex-shrink:0;padding-left:max(16px,env(safe-area-inset-left));padding-right:max(16px,env(safe-area-inset-right));padding-top:max(12px,env(safe-area-inset-top));position:relative;z-index:100}.ai-chat-widget-container.is-open .ai-chat-messages{-webkit-overflow-scrolling:touch;flex:1;overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain;padding-bottom:120px;padding-left:max(16px,env(safe-area-inset-left));padding-right:max(16px,env(safe-area-inset-right));touch-action:pan-y}.ai-chat-widget-container.is-open .ai-chat-input-container{background:var(--bg-primary,#fff);bottom:0!important;left:0!important;padding:8px max(12px,env(safe-area-inset-right)) max(16px,calc(env(safe-area-inset-bottom) + 8px)) max(12px,env(safe-area-inset-left));position:fixed!important;right:0!important;z-index:100}.ai-chat-widget.dark .ai-chat-widget-container.is-open .ai-chat-input-container{background:var(--bg-primary,#282625)}.ai-chat-widget-container.is-open .ai-chat-input-container:after{display:none}.ai-chat-widget-container.is-open .ai-chat-input-wrapper{margin:0;max-width:100%}.ai-chat-widget-container.is-open .ai-chat-scroll-button{bottom:calc(80px + env(safe-area-inset-bottom))}.ai-chat-widget-container.is-open .ai-chat-welcome{padding:16px 0}.ai-chat-widget-container.is-open .ai-chat-welcome-title{font-size:24px}.ai-chat-widget-container.is-open .ai-chat-suggested-questions{align-items:stretch;flex-direction:column}.ai-chat-widget-container.is-open .ai-chat-suggested-question{text-align:center;width:100%}.ai-chat-widget-container.is-open .ai-chat-message-meta{align-items:center;display:flex;gap:8px;margin-top:4px}.ai-chat-widget-container.is-open .ai-chat-message-timestamp{font-size:11px}.ai-chat-widget-container.is-open .ai-chat-feedback{display:inline-flex}.ai-chat-widget-container.is-open .ai-chat-feedback-button{display:flex;padding:4px}.ai-chat-widget-container.is-open .ai-chat-input{font-size:16px!important}}@media (min-width:481px) and (max-width:768px){.ai-chat-widget-container.is-open .ai-chat-window{border-radius:22px 22px 44px 44px;max-height:calc(100vh - 100px);max-width:calc(100vw - 32px)}}.ai-chat-widget-container.desktop-mode.container-mode.is-open{height:100%!important;inset:0!important;position:absolute!important;width:100%!important}.ai-chat-widget-container.desktop-mode.container-mode.is-open .ai-chat-window{border:1px solid var(--border-color,rgba(0,0,0,.08))!important;border-radius:var(--radius-window-top,22px) var(--radius-window-top,22px) var(--radius-window-bottom,44px) var(--radius-window-bottom,44px)!important;box-shadow:var(--window-shadow,0 20px 60px -10px rgba(0,0,0,.25))!important;position:absolute!important}.ai-chat-widget-container.desktop-mode.container-mode.size-small.is-open .ai-chat-window{height:min(500px,calc(100% - 120px))!important;max-height:500px!important;max-width:380px!important;min-height:300px!important;min-width:280px!important;width:min(380px,calc(100% - 40px))!important}.ai-chat-widget-container.desktop-mode.container-mode.size-medium.is-open .ai-chat-window{height:min(65%,calc(100% - 120px))!important;max-height:680px!important;max-width:440px!important;min-height:400px!important;min-width:320px!important;width:min(440px,calc(100% - 40px))!important}.ai-chat-widget-container.desktop-mode.container-mode.size-large.is-open .ai-chat-window{height:calc(100% - 100px)!important;max-height:calc(100% - 100px)!important;max-width:560px!important;min-height:500px!important;min-width:380px!important;width:min(560px,calc(100% - 40px))!important}.ai-chat-widget-container.desktop-mode.container-mode.is-open.bottom-right .ai-chat-window{bottom:88px!important;left:auto!important;right:20px!important;top:auto!important}.ai-chat-widget-container.desktop-mode.container-mode.is-open.bottom-left .ai-chat-window{bottom:88px!important;left:20px!important;right:auto!important;top:auto!important}.ai-chat-widget-container.desktop-mode.container-mode.is-open.top-right .ai-chat-window{bottom:auto!important;left:auto!important;right:20px!important;top:88px!important}.ai-chat-widget-container.desktop-mode.container-mode.is-open.top-left .ai-chat-window{bottom:auto!important;left:20px!important;right:auto!important;top:88px!important}.ai-chat-widget-container.desktop-mode.is-open .ai-chat-button{display:flex!important;opacity:1!important;pointer-events:auto!important;visibility:visible!important}.ai-chat-widget-container.desktop-mode.container-mode:not(.trigger-input-bar).bottom-right .ai-chat-button{bottom:20px!important;left:auto!important;right:20px!important;top:auto!important}.ai-chat-widget-container.desktop-mode.container-mode:not(.trigger-input-bar).bottom-left .ai-chat-button{bottom:20px!important;left:20px!important;right:auto!important;top:auto!important}.ai-chat-widget-container.desktop-mode.container-mode:not(.trigger-input-bar).top-right .ai-chat-button{bottom:auto!important;left:auto!important;right:20px!important;top:20px!important}.ai-chat-widget-container.desktop-mode.container-mode:not(.trigger-input-bar).top-left .ai-chat-button{bottom:auto!important;left:20px!important;right:auto!important;top:20px!important}.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.bottom-right .ai-chat-trigger-input-container{bottom:20px!important;left:auto!important;right:20px!important;top:auto!important}.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.bottom-left .ai-chat-trigger-input-container{bottom:20px!important;left:20px!important;right:auto!important;top:auto!important}.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.top-right .ai-chat-trigger-input-container{bottom:auto!important;left:auto!important;right:20px!important;top:20px!important}.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.top-left .ai-chat-trigger-input-container{bottom:auto!important;left:20px!important;right:auto!important;top:20px!important}.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.size-small .ai-chat-trigger-input-container{width:min(380px,calc(100% - 40px))!important}.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.size-medium .ai-chat-trigger-input-container{width:min(440px,calc(100% - 40px))!important}.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.size-large .ai-chat-trigger-input-container{width:min(560px,calc(100% - 40px))!important}.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.is-open.bottom-left .ai-chat-window,.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.is-open.bottom-right .ai-chat-window{bottom:20px!important}.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.is-open.top-left .ai-chat-window,.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.is-open.top-right .ai-chat-window{top:20px!important}.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.is-open.bottom-right .ai-chat-window,.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.is-open.top-right .ai-chat-window{left:auto!important;right:20px!important}.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.is-open.bottom-left .ai-chat-window,.ai-chat-widget-container.desktop-mode.container-mode.trigger-input-bar.is-open.top-left .ai-chat-window{left:20px!important;right:auto!important}";
|
|
47531
47921
|
styleInject(css_248z$1);
|
|
47532
47922
|
|
|
47533
|
-
var css_248z = ".ai-chat-data-policy-view{display:flex;flex:1;flex-direction:column;min-height:0;overflow:hidden}.ai-chat-data-policy-content{-webkit-overflow-scrolling:touch;flex:1;overflow-y:auto;padding:20px 16px 40px}.ai-chat-data-policy-intro{margin-bottom:24px}.ai-chat-data-policy-intro p{color:var(--text-primary,#18181b);font-size:13px;line-height:1.6;margin:0;text-align:left}.ai-chat-widget.dark .ai-chat-data-policy-intro p{color:var(--text-primary,#fafafa)}.ai-chat-data-policy-intro strong{color:var(--text-primary,#18181b)}.ai-chat-widget.dark .ai-chat-data-policy-intro strong{color:var(--text-primary,#fafafa)}.ai-chat-data-policy-section{margin-bottom:20px}.ai-chat-data-policy-section h3{color:var(--text-primary,#18181b);font-size:14px;font-weight:600;margin:0 0 12px}.ai-chat-widget.dark .ai-chat-data-policy-section h3{color:var(--text-primary,#fafafa)}.ai-chat-data-policy-section p{color:var(--text-secondary,#52525b);font-size:12px;line-height:1.6;margin:0 0 12px;text-align:justify;text-justify:inter-word}.ai-chat-widget.dark .ai-chat-data-policy-section p{color:var(--text-secondary,#a1a1aa)}.ai-chat-data-policy-section p strong{color:var(--text-primary,#18181b)}.ai-chat-widget.dark .ai-chat-data-policy-section p strong{color:var(--text-primary,#fafafa)}.ai-chat-data-policy-section p:last-child{margin-bottom:0}";
|
|
47923
|
+
var css_248z = ".ai-chat-data-policy-view{display:flex;flex:1;flex-direction:column;min-height:0;overflow:hidden}.ai-chat-data-policy-content{-webkit-overflow-scrolling:touch;flex:1;overflow-y:auto;padding:20px 16px 40px}.ai-chat-data-policy-intro{margin-bottom:24px}.ai-chat-data-policy-intro p{color:var(--text-primary,#18181b);font-size:13px;line-height:1.6;margin:0;text-align:left}.ai-chat-widget.dark .ai-chat-data-policy-intro p{color:var(--text-primary,#fafafa)}.ai-chat-data-policy-intro strong{color:var(--text-primary,#18181b)}.ai-chat-widget.dark .ai-chat-data-policy-intro strong{color:var(--text-primary,#fafafa)}.ai-chat-data-policy-section{margin-bottom:20px}.ai-chat-data-policy-section h3{color:var(--text-primary,#18181b);font-size:14px;font-weight:600;margin:0 0 12px}.ai-chat-widget.dark .ai-chat-data-policy-section h3{color:var(--text-primary,#fafafa)}.ai-chat-data-policy-section p{color:var(--text-secondary,#52525b);font-size:12px;line-height:1.6;margin:0 0 12px;text-align:justify;text-justify:inter-word}.ai-chat-widget.dark .ai-chat-data-policy-section p{color:var(--text-secondary,#a1a1aa)}.ai-chat-data-policy-section p strong{color:var(--text-primary,#18181b)}.ai-chat-widget.dark .ai-chat-data-policy-section p strong{color:var(--text-primary,#fafafa)}.ai-chat-data-policy-section p:last-child{margin-bottom:0}.ai-chat-widget-embedded .ai-chat-data-policy-view{-webkit-overflow-scrolling:touch;overflow-y:auto}.ai-chat-widget-embedded .ai-chat-data-policy-content{margin:0 auto;max-width:640px;overflow-y:visible;padding:32px 24px 60px}.ai-chat-widget-embedded .ai-chat-data-policy-intro p{font-size:14px;line-height:1.7}.ai-chat-widget-embedded .ai-chat-data-policy-section h3{font-size:15px;margin-bottom:14px}.ai-chat-widget-embedded .ai-chat-data-policy-section p{font-size:13px;line-height:1.7}.ai-chat-widget-embedded.dark .ai-chat-data-policy-intro p,.ai-chat-widget-embedded.dark .ai-chat-data-policy-intro strong,.ai-chat-widget-embedded.dark .ai-chat-data-policy-section h3{color:var(--text-primary,#fafafa)}.ai-chat-widget-embedded.dark .ai-chat-data-policy-section p{color:var(--text-secondary,#a1a1aa)}.ai-chat-widget-embedded.dark .ai-chat-data-policy-section p strong{color:var(--text-primary,#fafafa)}";
|
|
47534
47924
|
styleInject(css_248z);
|
|
47535
47925
|
|
|
47536
|
-
|
|
47537
|
-
const iconComponents = {
|
|
47538
|
-
FiMessageCircle: () => (jsxRuntimeExports.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("path", { d: "M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" }) })),
|
|
47539
|
-
FiChevronDown: () => (jsxRuntimeExports.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("polyline", { points: "6 9 12 15 18 9" }) })),
|
|
47540
|
-
};
|
|
47541
|
-
const ChatWidget = ({ widgetId, apiUrl = window.location.origin, previewMode = false, previewConfig, demoMode = false, demoInput, demoOutput, onDemoComplete, position = 'bottom-right', primaryColor, size, headerTitle, welcomeTitle, welcomeMessage, placeholder, welcomeBubbleText, triggerType, triggerText, theme, suggestedQuestions, customStyles, currentRoute, defaultOpen = false, zIndex, containerMode = false, onOpen, onClose, onMessage, onError, mode = 'bubble', }) => {
|
|
47926
|
+
const ChatWidget = ({ widgetId, apiUrl = window.location.origin, previewMode = false, previewConfig, position = 'bottom-right', primaryColor, size, headerTitle, welcomeTitle, welcomeMessage, placeholder, welcomeBubbleText, triggerType, triggerText, theme, suggestedQuestions, customStyles, currentRoute, defaultOpen = false, zIndex, containerMode = false, mobileMode = false, desktopMode = false, onOpen, onClose, onMessage, onError, mode = 'bubble', }) => {
|
|
47542
47927
|
const [isOpen, setIsOpen] = reactExports.useState(defaultOpen);
|
|
47543
47928
|
const [inputBarValue, setInputBarValue] = reactExports.useState('');
|
|
47544
|
-
const [autoDetectedTheme, setAutoDetectedTheme] = reactExports.useState('light');
|
|
47545
47929
|
const [showWelcomeBubble, setShowWelcomeBubble] = reactExports.useState(false);
|
|
47930
|
+
const [isInputBarCollapsed, setIsInputBarCollapsed] = reactExports.useState(false);
|
|
47546
47931
|
const widgetRef = reactExports.useRef(null);
|
|
47547
47932
|
const containerRef = reactExports.useRef(null);
|
|
47548
|
-
// Demo mode state - track whether demo has been activated and completed
|
|
47549
|
-
const [demoMessages, setDemoMessages] = reactExports.useState([]);
|
|
47550
|
-
const [isDemoComplete, setIsDemoComplete] = reactExports.useState(false);
|
|
47551
|
-
const [isDemoTyping, setIsDemoTyping] = reactExports.useState(false);
|
|
47552
|
-
const [demoInputBarText, setDemoInputBarText] = reactExports.useState(''); // For animating text in input bar
|
|
47553
|
-
const [isDemoAnimatingInput, setIsDemoAnimatingInput] = reactExports.useState(false); // True while typing into input bar
|
|
47554
|
-
const [isDemoActive, setIsDemoActive] = reactExports.useState(false); // True when demo animation is running
|
|
47555
|
-
const demoStartedRef = reactExports.useRef(false);
|
|
47556
|
-
// Track if user has sent a real message (transitions from demo to real chat)
|
|
47557
|
-
const [userSentRealMessage, setUserSentRealMessage] = reactExports.useState(false);
|
|
47558
47933
|
// Determine mode
|
|
47559
47934
|
const isEmbedded = mode === 'embedded';
|
|
47560
47935
|
// Default config for preview mode
|
|
@@ -47600,24 +47975,22 @@
|
|
|
47600
47975
|
...previewConfig?.behavior,
|
|
47601
47976
|
},
|
|
47602
47977
|
};
|
|
47603
|
-
// Always call useChat hook (React rules), but skip initialization in preview mode
|
|
47604
|
-
|
|
47605
|
-
// Note: We still pass the real widgetId so createDemoConversation works correctly
|
|
47606
|
-
const shouldSkipInit = previewMode || (demoMode && !userSentRealMessage);
|
|
47978
|
+
// Always call useChat hook (React rules), but skip initialization in preview mode
|
|
47979
|
+
const shouldSkipInit = previewMode;
|
|
47607
47980
|
const chatHook = useChat({
|
|
47608
47981
|
widgetId: previewMode ? '__preview__' : (widgetId || '__preview__'),
|
|
47609
47982
|
apiUrl,
|
|
47610
47983
|
currentRoute,
|
|
47611
47984
|
onMessage: shouldSkipInit ? undefined : onMessage,
|
|
47612
47985
|
onError: shouldSkipInit ? undefined : onError,
|
|
47613
|
-
skipInitialization: shouldSkipInit,
|
|
47986
|
+
skipInitialization: shouldSkipInit,
|
|
47614
47987
|
});
|
|
47615
47988
|
// Extract values from hook or use preview defaults
|
|
47616
|
-
const
|
|
47617
|
-
const
|
|
47618
|
-
const
|
|
47989
|
+
const messages = previewMode ? [] : chatHook.messages;
|
|
47990
|
+
const isLoading = previewMode ? false : chatHook.isLoading;
|
|
47991
|
+
const isTyping = previewMode ? false : chatHook.isTyping;
|
|
47619
47992
|
const config = previewMode ? mergedPreviewConfig : chatHook.config;
|
|
47620
|
-
const
|
|
47993
|
+
const sendMessage = previewMode ? (() => Promise.resolve()) : chatHook.sendMessage;
|
|
47621
47994
|
const submitFeedback = previewMode ? (() => Promise.resolve()) : chatHook.submitFeedback;
|
|
47622
47995
|
const dismissAction = previewMode ? (() => Promise.resolve()) : chatHook.dismissAction;
|
|
47623
47996
|
const conversations = previewMode ? [] : chatHook.conversations;
|
|
@@ -47625,54 +47998,26 @@
|
|
|
47625
47998
|
const switchConversation = previewMode ? (() => Promise.resolve()) : chatHook.switchConversation;
|
|
47626
47999
|
const startNewConversation = previewMode ? (() => { }) : chatHook.startNewConversation;
|
|
47627
48000
|
const deleteConversation = previewMode ? (() => { }) : chatHook.deleteConversation;
|
|
47628
|
-
const createDemoConversation = previewMode ? (() => Promise.resolve(null)) : chatHook.createDemoConversation;
|
|
47629
48001
|
const conversationId = previewMode ? '' : chatHook.conversationId;
|
|
47630
|
-
|
|
47631
|
-
|
|
47632
|
-
|
|
47633
|
-
|
|
47634
|
-
|
|
47635
|
-
|
|
47636
|
-
|
|
47637
|
-
|
|
47638
|
-
|
|
47639
|
-
|
|
47640
|
-
|
|
47641
|
-
|
|
47642
|
-
|
|
47643
|
-
|
|
47644
|
-
|
|
47645
|
-
|
|
47646
|
-
|
|
47647
|
-
|
|
47648
|
-
|
|
47649
|
-
return hookSendMessage(content);
|
|
47650
|
-
}, [demoMode, isDemoActive, isDemoComplete, userSentRealMessage, hookSendMessage]);
|
|
47651
|
-
// Auto-detect theme from background
|
|
47652
|
-
reactExports.useEffect(() => {
|
|
47653
|
-
if (!containerRef.current)
|
|
47654
|
-
return;
|
|
47655
|
-
// Initial detection
|
|
47656
|
-
const detected = detectTheme(containerRef.current);
|
|
47657
|
-
setAutoDetectedTheme(detected);
|
|
47658
|
-
// Watch for theme changes on the page
|
|
47659
|
-
const observer = createThemeObserver(containerRef.current, (newTheme) => {
|
|
47660
|
-
setAutoDetectedTheme(newTheme);
|
|
47661
|
-
});
|
|
47662
|
-
// Also listen for system preference changes
|
|
47663
|
-
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
|
47664
|
-
const handleMediaChange = () => {
|
|
47665
|
-
if (containerRef.current) {
|
|
47666
|
-
const detected = detectTheme(containerRef.current);
|
|
47667
|
-
setAutoDetectedTheme(detected);
|
|
47668
|
-
}
|
|
47669
|
-
};
|
|
47670
|
-
mediaQuery.addEventListener('change', handleMediaChange);
|
|
47671
|
-
return () => {
|
|
47672
|
-
observer.disconnect();
|
|
47673
|
-
mediaQuery.removeEventListener('change', handleMediaChange);
|
|
47674
|
-
};
|
|
47675
|
-
}, [config]);
|
|
48002
|
+
const callActionEndpoint = previewMode ? (async () => { throw new Error('Not available in preview mode'); }) : chatHook.callActionEndpoint;
|
|
48003
|
+
const { effectiveTheme, effectivePosition, accentColor, iconContrastColor, effectiveSize, effectiveHeaderTitle, effectiveWelcomeTitle, effectiveWelcomeMessage, effectivePlaceholder, effectiveWelcomeBubbleText, effectiveTriggerType, effectiveTriggerText, mergedStyles, } = useWidgetAppearance({
|
|
48004
|
+
containerRef,
|
|
48005
|
+
config,
|
|
48006
|
+
theme,
|
|
48007
|
+
primaryColor,
|
|
48008
|
+
position,
|
|
48009
|
+
size,
|
|
48010
|
+
headerTitle,
|
|
48011
|
+
welcomeTitle,
|
|
48012
|
+
welcomeMessage,
|
|
48013
|
+
placeholder,
|
|
48014
|
+
welcomeBubbleText,
|
|
48015
|
+
triggerType,
|
|
48016
|
+
triggerText,
|
|
48017
|
+
customStyles,
|
|
48018
|
+
zIndex,
|
|
48019
|
+
previewMode,
|
|
48020
|
+
});
|
|
47676
48021
|
// Check if device is mobile
|
|
47677
48022
|
const isMobile = typeof window !== 'undefined' && window.innerWidth <= 480;
|
|
47678
48023
|
// Handle auto-open (only for bubble mode, disabled on mobile)
|
|
@@ -47680,9 +48025,6 @@
|
|
|
47680
48025
|
// Never auto-open on mobile devices
|
|
47681
48026
|
if (isMobile)
|
|
47682
48027
|
return undefined;
|
|
47683
|
-
// Don't auto-open if demo mode is active - let demo animation control opening
|
|
47684
|
-
if (demoMode && !isDemoComplete)
|
|
47685
|
-
return undefined;
|
|
47686
48028
|
if (!isEmbedded && config?.settings.autoOpen) {
|
|
47687
48029
|
const delay = config.settings.autoOpenDelay || 0;
|
|
47688
48030
|
const timer = setTimeout(() => {
|
|
@@ -47692,7 +48034,7 @@
|
|
|
47692
48034
|
return () => clearTimeout(timer);
|
|
47693
48035
|
}
|
|
47694
48036
|
return undefined;
|
|
47695
|
-
}, [config, onOpen, isEmbedded, isMobile
|
|
48037
|
+
}, [config, onOpen, isEmbedded, isMobile]);
|
|
47696
48038
|
// Handle close on Escape key (only for bubble mode)
|
|
47697
48039
|
reactExports.useEffect(() => {
|
|
47698
48040
|
if (!isOpen || isEmbedded)
|
|
@@ -47769,172 +48111,12 @@
|
|
|
47769
48111
|
setShowWelcomeBubble(true);
|
|
47770
48112
|
}
|
|
47771
48113
|
}, [widgetId, welcomeBubbleText, config, isOpen, isEmbedded, previewMode]);
|
|
47772
|
-
|
|
47773
|
-
|
|
47774
|
-
|
|
47775
|
-
|
|
47776
|
-
|
|
47777
|
-
|
|
47778
|
-
const effectiveTriggerTypeForDemo = triggerType ?? config?.appearance?.triggerType ?? 'button';
|
|
47779
|
-
const isInputBarTrigger = effectiveTriggerTypeForDemo === 'input-bar';
|
|
47780
|
-
// Debug logging
|
|
47781
|
-
console.log('[Widget] Demo effect check:', {
|
|
47782
|
-
demoMode,
|
|
47783
|
-
isDemoComplete,
|
|
47784
|
-
demoStartedRef: demoStartedRef.current,
|
|
47785
|
-
hasDemoInput: !!demoInput,
|
|
47786
|
-
hasDemoOutput: !!demoOutput,
|
|
47787
|
-
triggerType: effectiveTriggerTypeForDemo,
|
|
47788
|
-
isInputBar: isInputBarTrigger,
|
|
47789
|
-
isOpen,
|
|
47790
|
-
});
|
|
47791
|
-
// Start demo when demoMode is enabled and we have input/output
|
|
47792
|
-
const shouldStartDemo = demoMode && !isDemoComplete && !demoStartedRef.current && demoInput && demoOutput;
|
|
47793
|
-
if (!shouldStartDemo) {
|
|
47794
|
-
console.log('[Widget] Demo not starting:', { shouldStartDemo, reason: !demoMode ? 'demoMode false' : !demoInput ? 'no demoInput' : !demoOutput ? 'no demoOutput' : isDemoComplete ? 'already complete' : demoStartedRef.current ? 'already started' : 'unknown' });
|
|
47795
|
-
return;
|
|
47796
|
-
}
|
|
47797
|
-
// Wait for config to load before starting demo (unless triggerType prop is explicitly provided)
|
|
47798
|
-
// This prevents the demo from starting with wrong trigger type
|
|
47799
|
-
if (!triggerType && !config) {
|
|
47800
|
-
console.log('[Widget] Demo waiting for config or triggerType prop');
|
|
47801
|
-
return;
|
|
47802
|
-
}
|
|
47803
|
-
// For input-bar: start immediately (widget closed, type into bar)
|
|
47804
|
-
// For others: wait until widget is open
|
|
47805
|
-
if (!isInputBarTrigger && !isOpen) {
|
|
47806
|
-
console.log('[Widget] Demo waiting for widget to open (non-input-bar trigger)');
|
|
47807
|
-
return;
|
|
47808
|
-
}
|
|
47809
|
-
console.log('[Widget] Starting demo animation...', {
|
|
47810
|
-
triggerType: effectiveTriggerTypeForDemo,
|
|
47811
|
-
isInputBar: isInputBarTrigger,
|
|
47812
|
-
demoInput,
|
|
47813
|
-
demoOutput: demoOutput?.substring(0, 50) + '...',
|
|
47814
|
-
});
|
|
47815
|
-
demoStartedRef.current = true;
|
|
47816
|
-
setIsDemoActive(true);
|
|
47817
|
-
// Use stable IDs to prevent React from remounting components
|
|
47818
|
-
const userMessageId = 'demo-user-message';
|
|
47819
|
-
const assistantMessageId = 'demo-assistant-message';
|
|
47820
|
-
// Helper to create a message with stable ID
|
|
47821
|
-
const createMessage = (id, role, content, isStreaming = false) => ({
|
|
47822
|
-
id,
|
|
47823
|
-
message: { role, content },
|
|
47824
|
-
timestamp: new Date().toISOString(),
|
|
47825
|
-
sources: [],
|
|
47826
|
-
isStreaming,
|
|
47827
|
-
});
|
|
47828
|
-
// Animation sequence - runs to completion even if widget is closed
|
|
47829
|
-
// This ensures conversation is always created and saved consistently
|
|
47830
|
-
const runDemoAnimation = async () => {
|
|
47831
|
-
// STEP 1: Create conversation IMMEDIATELY at the start
|
|
47832
|
-
// This ensures we have a conversation ID before any animation
|
|
47833
|
-
console.log('[Widget] Creating demo conversation at start...');
|
|
47834
|
-
let conversationId = null;
|
|
47835
|
-
try {
|
|
47836
|
-
conversationId = await createDemoConversation(demoInput, demoOutput);
|
|
47837
|
-
if (conversationId) {
|
|
47838
|
-
console.log('[Widget] Demo conversation created:', conversationId);
|
|
47839
|
-
}
|
|
47840
|
-
}
|
|
47841
|
-
catch (err) {
|
|
47842
|
-
console.warn('[Widget] Failed to create demo conversation:', err);
|
|
47843
|
-
}
|
|
47844
|
-
// STEP 2: For input-bar trigger, animate typing into input bar first
|
|
47845
|
-
if (isInputBarTrigger && !isOpen) {
|
|
47846
|
-
setIsDemoAnimatingInput(true);
|
|
47847
|
-
// Wait before starting to type - ensure input bar is fully visible
|
|
47848
|
-
await new Promise(resolve => setTimeout(resolve, 1500));
|
|
47849
|
-
// Type into input bar character by character
|
|
47850
|
-
const inputChars = demoInput.split('');
|
|
47851
|
-
for (let i = 0; i < inputChars.length; i++) {
|
|
47852
|
-
setDemoInputBarText(demoInput.slice(0, i + 1));
|
|
47853
|
-
// Slower typing speed for better visibility
|
|
47854
|
-
const delay = inputChars[i] === ' ' ? 100 : 60 + Math.random() * 40;
|
|
47855
|
-
await new Promise(resolve => setTimeout(resolve, delay));
|
|
47856
|
-
}
|
|
47857
|
-
// Longer pause after typing so user can read the question
|
|
47858
|
-
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
47859
|
-
setIsDemoAnimatingInput(false);
|
|
47860
|
-
setDemoInputBarText('');
|
|
47861
|
-
setIsOpen(true);
|
|
47862
|
-
onOpen?.();
|
|
47863
|
-
// Let widget open animation complete
|
|
47864
|
-
await new Promise(resolve => setTimeout(resolve, 500));
|
|
47865
|
-
}
|
|
47866
|
-
else {
|
|
47867
|
-
// For non-input-bar triggers, just wait for widget to settle
|
|
47868
|
-
await new Promise(resolve => setTimeout(resolve, 800));
|
|
47869
|
-
}
|
|
47870
|
-
// STEP 3: Add user message
|
|
47871
|
-
setDemoMessages([createMessage(userMessageId, 'user', demoInput)]);
|
|
47872
|
-
// Show typing indicator after a pause
|
|
47873
|
-
await new Promise(resolve => setTimeout(resolve, 500));
|
|
47874
|
-
setIsDemoTyping(true);
|
|
47875
|
-
// "Thinking" pause
|
|
47876
|
-
await new Promise(resolve => setTimeout(resolve, 1200));
|
|
47877
|
-
setIsDemoTyping(false);
|
|
47878
|
-
// STEP 4: Stream the response character by character
|
|
47879
|
-
const chars = demoOutput.split('');
|
|
47880
|
-
let currentText = '';
|
|
47881
|
-
// Initial message with empty content
|
|
47882
|
-
setDemoMessages([
|
|
47883
|
-
createMessage(userMessageId, 'user', demoInput),
|
|
47884
|
-
createMessage(assistantMessageId, 'assistant', '', true),
|
|
47885
|
-
]);
|
|
47886
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
47887
|
-
// Stream characters - continues even if widget is closed
|
|
47888
|
-
for (let i = 0; i < chars.length; i++) {
|
|
47889
|
-
currentText += chars[i];
|
|
47890
|
-
setDemoMessages([
|
|
47891
|
-
createMessage(userMessageId, 'user', demoInput),
|
|
47892
|
-
createMessage(assistantMessageId, 'assistant', currentText, i < chars.length - 1),
|
|
47893
|
-
]);
|
|
47894
|
-
const delay = chars[i] === ' ' ? 12 : 20;
|
|
47895
|
-
await new Promise(resolve => setTimeout(resolve, delay));
|
|
47896
|
-
}
|
|
47897
|
-
// STEP 5: Mark demo complete
|
|
47898
|
-
await new Promise(resolve => setTimeout(resolve, 500));
|
|
47899
|
-
setIsDemoComplete(true);
|
|
47900
|
-
setIsDemoActive(false);
|
|
47901
|
-
console.log('[Widget] Demo animation complete');
|
|
47902
|
-
onDemoComplete?.();
|
|
47903
|
-
};
|
|
47904
|
-
runDemoAnimation();
|
|
47905
|
-
}, [demoMode, isOpen, isDemoComplete, demoInput, demoOutput, onDemoComplete, triggerType, config?.appearance?.triggerType, onOpen, createDemoConversation]);
|
|
47906
|
-
// Determine theme - use prop override if provided, otherwise auto-detect
|
|
47907
|
-
const appearanceConfig = config?.appearance;
|
|
47908
|
-
const effectiveTheme = theme ?? autoDetectedTheme;
|
|
47909
|
-
// Determine position (prop override takes priority for live preview)
|
|
47910
|
-
const effectivePosition = position || config?.appearance.position || 'bottom-right';
|
|
47911
|
-
// Get accent color from prop or config (empty string means no accent color / vanilla mode)
|
|
47912
|
-
const accentColor = primaryColor ?? appearanceConfig?.primaryColor ?? '';
|
|
47913
|
-
// Apply prop overrides for live preview (props take priority over config)
|
|
47914
|
-
const effectiveSize = size || appearanceConfig?.size || 'small';
|
|
47915
|
-
const effectiveHeaderTitle = headerTitle ?? appearanceConfig?.headerTitle ?? '';
|
|
47916
|
-
const effectiveWelcomeTitle = welcomeTitle ?? appearanceConfig?.welcomeTitle ?? '';
|
|
47917
|
-
const effectiveWelcomeMessage = welcomeMessage ?? appearanceConfig?.welcomeMessage ?? '';
|
|
47918
|
-
const effectivePlaceholder = placeholder ?? appearanceConfig?.placeholder ?? '';
|
|
47919
|
-
const effectiveWelcomeBubbleText = welcomeBubbleText ?? appearanceConfig?.welcomeBubbleText ?? '';
|
|
47920
|
-
const effectiveTriggerType = triggerType ?? appearanceConfig?.triggerType ?? 'button';
|
|
47921
|
-
const effectiveTriggerText = triggerText ?? appearanceConfig?.triggerText ?? 'Chat';
|
|
47922
|
-
// Generate styles using simplified theme system
|
|
47923
|
-
const simpleAppearance = {
|
|
47924
|
-
accentColor};
|
|
47925
|
-
// Generate theme styles from accent color
|
|
47926
|
-
const generatedStyles = generateThemeStyles(simpleAppearance, effectiveTheme);
|
|
47927
|
-
// Also apply legacy styles for backward compatibility
|
|
47928
|
-
const legacyStyles = appearanceConfig
|
|
47929
|
-
? applyAppearanceStyles(appearanceConfig)
|
|
47930
|
-
: {};
|
|
47931
|
-
// Merge styles (generated takes priority for new simplified system, then custom overrides)
|
|
47932
|
-
const mergedStyles = {
|
|
47933
|
-
...legacyStyles,
|
|
47934
|
-
...generatedStyles,
|
|
47935
|
-
...customStyles,
|
|
47936
|
-
...(zIndex !== undefined ? { '--widget-z-index': String(zIndex) } : {}),
|
|
47937
|
-
};
|
|
48114
|
+
const handleStartNewConversation = reactExports.useCallback(() => {
|
|
48115
|
+
startNewConversation();
|
|
48116
|
+
}, [startNewConversation]);
|
|
48117
|
+
const handleSendMessage = reactExports.useCallback((content) => {
|
|
48118
|
+
sendMessage(content);
|
|
48119
|
+
}, [sendMessage]);
|
|
47938
48120
|
// Dismiss bubble and store based on frequency setting
|
|
47939
48121
|
const dismissBubble = () => {
|
|
47940
48122
|
setShowWelcomeBubble(false);
|
|
@@ -47970,9 +48152,6 @@
|
|
|
47970
48152
|
onOpen?.();
|
|
47971
48153
|
}
|
|
47972
48154
|
else {
|
|
47973
|
-
// Demo animation continues in background when widget is closed
|
|
47974
|
-
// The conversation was already created at the start, so closing is safe
|
|
47975
|
-
// When user reopens, they'll see the current state of the demo animation
|
|
47976
48155
|
onClose?.();
|
|
47977
48156
|
}
|
|
47978
48157
|
};
|
|
@@ -48009,10 +48188,13 @@
|
|
|
48009
48188
|
sendMessage(actionInstruction);
|
|
48010
48189
|
};
|
|
48011
48190
|
// Don't render until config is loaded to avoid flash of unstyled content
|
|
48012
|
-
//
|
|
48013
|
-
//
|
|
48191
|
+
// Exceptions that allow immediate rendering:
|
|
48192
|
+
// 1. triggerType prop provided - user wants specific trigger shown immediately
|
|
48193
|
+
// 2. primaryColor prop provided - we have initial styling, no flash will occur
|
|
48194
|
+
// This improves perceived loading speed - users see the correctly styled trigger while config loads
|
|
48014
48195
|
// In preview mode, config is always available
|
|
48015
|
-
const
|
|
48196
|
+
const hasInitialStyling = !!primaryColor;
|
|
48197
|
+
const canRenderWithoutConfig = !!triggerType || hasInitialStyling;
|
|
48016
48198
|
if (!config && !previewMode && !canRenderWithoutConfig) {
|
|
48017
48199
|
return null;
|
|
48018
48200
|
}
|
|
@@ -48020,21 +48202,21 @@
|
|
|
48020
48202
|
const IconComponent = isOpen ? iconComponents.FiChevronDown : iconComponents.FiMessageCircle;
|
|
48021
48203
|
// Embedded mode renders directly without wrapper positioning
|
|
48022
48204
|
if (isEmbedded) {
|
|
48023
|
-
return (jsxRuntimeExports.jsx("div", { ref: containerRef, className: `ai-chat-widget ai-chat-widget-embedded ${effectiveTheme}`, style: { ...mergedStyles, width: '100%', height: '100%' }, children: jsxRuntimeExports.jsx(ChatWindow, { messages: messages, isLoading: isLoading, isTyping: isTyping, config: config, onSendMessage:
|
|
48205
|
+
return (jsxRuntimeExports.jsx("div", { ref: containerRef, className: `ai-chat-widget ai-chat-widget-embedded ${effectiveTheme}`, style: { ...mergedStyles, width: '100%', height: '100%' }, children: jsxRuntimeExports.jsx(ChatWindow, { messages: messages, isLoading: isLoading, isTyping: isTyping, config: config, onSendMessage: handleSendMessage, onClose: () => { }, onFeedback: handleFeedback, onActionClick: handleActionClick, onActionDismiss: dismissAction, onCallEndpoint: callActionEndpoint, conversations: conversations, onLoadConversations: loadConversations, onSwitchConversation: switchConversation, onStartNewConversation: handleStartNewConversation, onDeleteConversation: deleteConversation, currentConversationId: conversationId, sizeOverride: effectiveSize, headerTitleOverride: effectiveHeaderTitle, welcomeTitleOverride: effectiveWelcomeTitle, welcomeMessageOverride: effectiveWelcomeMessage, placeholderOverride: effectivePlaceholder, suggestedQuestionsOverride: suggestedQuestions }) }));
|
|
48024
48206
|
}
|
|
48025
48207
|
// Determine trigger class for container
|
|
48026
48208
|
const triggerClass = effectiveTriggerType === 'pill-text'
|
|
48027
48209
|
? 'trigger-pill-text'
|
|
48028
48210
|
: effectiveTriggerType === 'input-bar'
|
|
48029
48211
|
? 'trigger-input-bar'
|
|
48030
|
-
: '';
|
|
48212
|
+
: 'trigger-button';
|
|
48031
48213
|
// Size class for CSS targeting (used by input-bar trigger for width matching)
|
|
48032
48214
|
const sizeClass = `size-${effectiveSize}`;
|
|
48033
|
-
|
|
48215
|
+
// Collapsed class for input bar
|
|
48216
|
+
const collapsedClass = isInputBarCollapsed ? 'is-collapsed' : '';
|
|
48217
|
+
return (jsxRuntimeExports.jsx("div", { ref: containerRef, className: `ai-chat-widget ${effectiveTheme}`, style: mergedStyles, children: jsxRuntimeExports.jsxs("div", { ref: widgetRef, className: `ai-chat-widget-container ${effectivePosition} ${isOpen ? 'is-open' : ''} ${containerMode ? 'container-mode' : ''} ${mobileMode ? 'mobile-mode' : ''} ${desktopMode ? 'desktop-mode' : ''} ${triggerClass} ${sizeClass} ${collapsedClass}`, children: [isOpen && (jsxRuntimeExports.jsx(ChatWindow, { messages: messages, isLoading: isLoading, isTyping: isTyping, config: config, onSendMessage: handleSendMessage, onClose: handleToggle, onFeedback: handleFeedback, onActionClick: handleActionClick, onActionDismiss: dismissAction, onCallEndpoint: callActionEndpoint,
|
|
48034
48218
|
// Chat history props (only active when persistConversation is true)
|
|
48035
|
-
conversations: conversations, onLoadConversations: loadConversations, onSwitchConversation: switchConversation, onStartNewConversation:
|
|
48036
|
-
// Override props for live preview
|
|
48037
|
-
headerTitleOverride: effectiveHeaderTitle, welcomeTitleOverride: effectiveWelcomeTitle, welcomeMessageOverride: effectiveWelcomeMessage, placeholderOverride: effectivePlaceholder, suggestedQuestionsOverride: suggestedQuestions })), effectiveTriggerType === 'button' && !isOpen && effectiveWelcomeBubbleText && (previewMode || showWelcomeBubble) && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-welcome-bubble", onClick: handleToggle, children: [jsxRuntimeExports.jsx("span", { children: effectiveWelcomeBubbleText }), jsxRuntimeExports.jsx("button", { className: "ai-chat-welcome-bubble-close", onClick: handleDismissBubble, "aria-label": "Dismiss", children: jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), jsxRuntimeExports.jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }) }), jsxRuntimeExports.jsx("div", { className: "ai-chat-welcome-bubble-arrow" })] })), effectiveTriggerType === 'button' && (jsxRuntimeExports.jsx("button", { className: `ai-chat-button ${isOpen ? 'is-open' : ''}`, onClick: handleToggle, "aria-label": isOpen ? "Minimize chat" : "Open chat", children: jsxRuntimeExports.jsx("div", { className: "ai-chat-button-svg", children: jsxRuntimeExports.jsx(IconComponent, {}) }) })), effectiveTriggerType === 'pill-text' && (jsxRuntimeExports.jsxs("button", { className: `ai-chat-trigger-pill ${isOpen ? 'is-open' : ''}`, onClick: handleToggle, "aria-label": isOpen ? "Close chat" : "Open chat", children: [jsxRuntimeExports.jsx("div", { className: "ai-chat-trigger-pill-icon", children: jsxRuntimeExports.jsx(IconComponent, {}) }), !isOpen && jsxRuntimeExports.jsx("span", { children: effectiveTriggerText })] })), effectiveTriggerType === 'input-bar' && !isOpen && (jsxRuntimeExports.jsxs("div", { className: "ai-chat-trigger-input-container", children: [jsxRuntimeExports.jsx("button", { type: "button", className: "ai-chat-trigger-input-expand", onClick: handleToggle, "aria-label": "Open chat", children: jsxRuntimeExports.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("polyline", { points: "18 15 12 9 6 15" }) }) }), jsxRuntimeExports.jsxs("form", { className: "ai-chat-trigger-input-wrapper", onSubmit: handleInputBarSubmit, children: [jsxRuntimeExports.jsx("input", { type: "text", className: "ai-chat-trigger-input", placeholder: effectivePlaceholder || "Ask me anything...", value: isDemoAnimatingInput ? demoInputBarText : inputBarValue, onChange: (e) => !isDemoAnimatingInput && setInputBarValue(e.target.value), readOnly: isDemoAnimatingInput, "aria-label": "Chat input" }), jsxRuntimeExports.jsx("button", { type: "submit", className: "ai-chat-trigger-input-btn", disabled: isDemoAnimatingInput ? !demoInputBarText.trim() : !inputBarValue.trim(), "aria-label": "Send message", children: jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("line", { x1: "22", y1: "2", x2: "11", y2: "13" }), jsxRuntimeExports.jsx("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })] }) })] })] }))] }) }));
|
|
48219
|
+
conversations: conversations, onLoadConversations: loadConversations, onSwitchConversation: switchConversation, onStartNewConversation: handleStartNewConversation, onDeleteConversation: deleteConversation, currentConversationId: conversationId, sizeOverride: effectiveSize, headerTitleOverride: effectiveHeaderTitle, welcomeTitleOverride: effectiveWelcomeTitle, welcomeMessageOverride: effectiveWelcomeMessage, placeholderOverride: effectivePlaceholder, suggestedQuestionsOverride: suggestedQuestions })), jsxRuntimeExports.jsx(WidgetTriggers, { triggerType: effectiveTriggerType, isOpen: isOpen, onToggle: handleToggle, triggerText: effectiveTriggerText, placeholder: effectivePlaceholder, IconComponent: IconComponent, showWelcomeBubble: showWelcomeBubble, welcomeBubbleText: effectiveWelcomeBubbleText, previewMode: previewMode, onDismissBubble: handleDismissBubble, isInputBarCollapsed: isInputBarCollapsed, setIsInputBarCollapsed: setIsInputBarCollapsed, inputBarValue: inputBarValue, setInputBarValue: setInputBarValue, onSubmitInputBar: handleInputBarSubmit, accentColor: accentColor, iconColor: iconContrastColor })] }) }));
|
|
48038
48220
|
};
|
|
48039
48221
|
|
|
48040
48222
|
/**
|