@chatwidgetai/chat-widget 0.1.8 → 0.1.9

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/index.esm.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
- import { useState, useRef, useEffect, useCallback, useMemo } from 'react';
2
+ import { useState, useRef, useEffect, useCallback } from 'react';
3
3
 
4
4
  /**
5
5
  * API Client for Widget Communication
@@ -193,6 +193,124 @@ class WidgetApiClient {
193
193
  throw error;
194
194
  }
195
195
  }
196
+ /**
197
+ * Stream chat message responses
198
+ */
199
+ async *sendMessageStream(conversationId, message, fileIds) {
200
+ const response = await fetch(`${this.config.apiUrl}/api/widget/${this.config.widgetId}/chat`, {
201
+ method: 'POST',
202
+ headers: {
203
+ 'Content-Type': 'application/json',
204
+ },
205
+ body: JSON.stringify({
206
+ conversationId: conversationId,
207
+ message,
208
+ fileIds,
209
+ timeZone: this.getTimeZone(),
210
+ }),
211
+ });
212
+ if (!response.ok) {
213
+ throw await buildApiError(response, 'Failed to send message');
214
+ }
215
+ if (!response.body) {
216
+ throw new Error('Response body is null');
217
+ }
218
+ const reader = response.body.getReader();
219
+ const decoder = new TextDecoder();
220
+ let buffer = '';
221
+ try {
222
+ while (true) {
223
+ const { done, value } = await reader.read();
224
+ if (done)
225
+ break;
226
+ buffer += decoder.decode(value, { stream: true });
227
+ const lines = buffer.split('\n');
228
+ buffer = lines.pop() || '';
229
+ for (const line of lines) {
230
+ if (line.startsWith('data: ')) {
231
+ try {
232
+ const data = JSON.parse(line.slice(6));
233
+ // Handle error events
234
+ if (data.type === 'error') {
235
+ throw new Error(data.error || 'Stream error');
236
+ }
237
+ // Yield ConversationMessage objects
238
+ if (data.id) {
239
+ yield data;
240
+ }
241
+ }
242
+ catch (e) {
243
+ console.error('[Widget API Client] Failed to parse SSE data:', line, e);
244
+ throw e;
245
+ }
246
+ }
247
+ }
248
+ }
249
+ }
250
+ finally {
251
+ reader.releaseLock();
252
+ }
253
+ }
254
+ /**
255
+ * Stream agent message responses with tool execution
256
+ * Handles streaming events from backend and yields ConversationMessage updates
257
+ */
258
+ async *sendAgentMessageStream(conversationId, message, fileIds) {
259
+ const response = await fetch(`${this.config.apiUrl}/api/widget/${this.config.widgetId}/agent`, {
260
+ method: 'POST',
261
+ headers: {
262
+ 'Content-Type': 'application/json',
263
+ },
264
+ body: JSON.stringify({
265
+ conversationId: conversationId,
266
+ message,
267
+ fileIds,
268
+ timeZone: this.getTimeZone(),
269
+ }),
270
+ });
271
+ if (!response.ok) {
272
+ throw await buildApiError(response, 'Failed to send agent message');
273
+ }
274
+ if (!response.body) {
275
+ throw new Error('Response body is null');
276
+ }
277
+ const reader = response.body.getReader();
278
+ const decoder = new TextDecoder();
279
+ let buffer = '';
280
+ try {
281
+ while (true) {
282
+ const { done, value } = await reader.read();
283
+ if (done)
284
+ break;
285
+ buffer += decoder.decode(value, { stream: true });
286
+ const lines = buffer.split('\n');
287
+ buffer = lines.pop() || '';
288
+ for (const line of lines) {
289
+ if (line.startsWith('data: ')) {
290
+ try {
291
+ const data = JSON.parse(line.slice(6));
292
+ // Handle error events
293
+ if (data.type === 'error') {
294
+ throw new Error(data.error || 'Stream error');
295
+ }
296
+ // Yield ConversationMessage objects that come from the backend
297
+ // The backend yields full ConversationMessage objects during streaming
298
+ if (data.id) {
299
+ yield data;
300
+ }
301
+ }
302
+ catch (e) {
303
+ console.error('[Widget API Client] Failed to parse SSE data:', line, e);
304
+ throw e;
305
+ }
306
+ }
307
+ }
308
+ }
309
+ }
310
+ finally {
311
+ reader.releaseLock();
312
+ }
313
+ }
196
314
  /**
197
315
  * Submit feedback for a message
198
316
  */
@@ -540,7 +658,7 @@ function useChat(options) {
540
658
  console.log('[useChat] Config fetched successfully:', {
541
659
  hasAppearance: !!config.appearance,
542
660
  });
543
- const persistConversation = config.behavior.persistConversation ?? true;
661
+ const persistConversation = config.settings.persistConversation ?? true;
544
662
  let conversationId = '';
545
663
  let messages = [];
546
664
  if (persistConversation && isStorageAvailable()) {
@@ -588,14 +706,14 @@ function useChat(options) {
588
706
  }, [widgetId, apiUrl, onError]);
589
707
  // Save conversation when messages change
590
708
  useEffect(() => {
591
- const persistConversation = state.config?.behavior.persistConversation ?? true;
709
+ const persistConversation = state.config?.settings.persistConversation ?? true;
592
710
  if (persistConversation &&
593
711
  isStorageAvailable() &&
594
712
  state.messages.length > 0 &&
595
713
  state.conversationId) {
596
714
  saveConversation(widgetId, state.conversationId, state.messages);
597
715
  }
598
- }, [widgetId, state.messages, state.conversationId, state.config?.behavior.persistConversation]);
716
+ }, [widgetId, state.messages, state.conversationId, state.config?.settings.persistConversation]);
599
717
  /**
600
718
  * Send a message
601
719
  */
@@ -617,8 +735,8 @@ function useChat(options) {
617
735
  setState(prev => ({
618
736
  ...prev,
619
737
  messages: [...prev.messages, userMessage],
620
- isLoading: true,
621
- isTyping: true,
738
+ isLoading: false, // Don't show loading, will show typing when stream starts
739
+ isTyping: true, // Show typing indicator immediately
622
740
  error: null,
623
741
  }));
624
742
  onMessage?.(userMessage);
@@ -664,71 +782,56 @@ function useChat(options) {
664
782
  }
665
783
  // Determine if widget has actions (use agent endpoint)
666
784
  const useAgent = state.config?.behavior.agentic || (state.config?.actions && state.config.actions.length > 0);
667
- let response;
668
- if (useAgent) {
669
- // Use agent endpoint - returns ConversationMessage[]
670
- response = await apiClient.current.sendAgentMessage(conversationId, trimmedContent, fileIds);
671
- }
672
- else {
673
- // Use standard chat endpoint
674
- response = await apiClient.current.sendMessage(conversationId, trimmedContent, fileIds);
675
- }
676
- // Both endpoints now return ConversationMessage[] array (FULL conversation)
677
- if (Array.isArray(response)) {
678
- // Response is already ConversationMessage[]
679
- const allMessages = response;
680
- // Find new messages (those not in current state)
681
- const existingIds = new Set(state.messages.map(m => m.id));
682
- const newMessages = allMessages.filter(msg => !existingIds.has(msg.id));
683
- setState(prev => ({
684
- ...prev,
685
- messages: allMessages, // Replace with full conversation
686
- isLoading: false,
687
- isTyping: false,
688
- }));
689
- // Only notify about new messages
690
- newMessages.forEach(msg => onMessage?.(msg));
691
- }
692
- else if (response.type === 'error') {
693
- // Error response from agent
694
- const errorContent = response.message || response.error || 'An error occurred';
695
- const errorMessage = {
696
- id: response.message_id || generateMessageId(),
697
- message: {
698
- type: 'ai',
699
- content: `⚠️ ${errorContent}`,
700
- },
701
- timestamp: response.timestamp || new Date().toISOString(),
702
- sources: [],
703
- };
704
- setState(prev => ({
705
- ...prev,
706
- messages: [...prev.messages, errorMessage],
707
- isLoading: false,
708
- isTyping: false,
709
- error: errorContent,
710
- }));
711
- onMessage?.(errorMessage);
785
+ // Stream the response
786
+ let lastStreamedMessage = null;
787
+ const stream = useAgent
788
+ ? apiClient.current.sendAgentMessageStream(conversationId, trimmedContent, fileIds)
789
+ : apiClient.current.sendMessageStream(conversationId, trimmedContent, fileIds);
790
+ for await (const message of stream) {
791
+ lastStreamedMessage = message;
792
+ // Update state with streamed message
793
+ setState(prev => {
794
+ const existingIndex = prev.messages.findIndex(m => m.id === message.id);
795
+ if (existingIndex >= 0) {
796
+ // Update existing streaming message
797
+ const newMessages = [...prev.messages];
798
+ newMessages[existingIndex] = message;
799
+ // Show typing indicator if:
800
+ // 1. Message is streaming AND has no content (waiting for first token or after tool call)
801
+ // 2. Message is a tool execution (shows loading spinner on the tool)
802
+ const isAIMessage = message.message.type === 'ai';
803
+ const hasContent = isAIMessage && message.message.content.trim().length > 0;
804
+ const isToolExecuting = message.toolExecuting !== undefined;
805
+ return {
806
+ ...prev,
807
+ messages: newMessages,
808
+ isTyping: (message.isStreaming && !hasContent && isAIMessage) || isToolExecuting,
809
+ isLoading: false,
810
+ };
811
+ }
812
+ else {
813
+ // Add new streaming message
814
+ const isAIMessage = message.message.type === 'ai';
815
+ const hasContent = isAIMessage && message.message.content.trim().length > 0;
816
+ const isToolExecuting = message.toolExecuting !== undefined;
817
+ return {
818
+ ...prev,
819
+ messages: [...prev.messages, message],
820
+ isTyping: (message.isStreaming && !hasContent && isAIMessage) || isToolExecuting,
821
+ isLoading: false,
822
+ };
823
+ }
824
+ });
712
825
  }
713
- else {
714
- // Standard message response (type: 'message' or undefined)
715
- const messageContent = response.content || response.message || '';
716
- const assistantMessage = {
717
- id: response.message_id || response.messageId || generateMessageId(),
718
- message: {
719
- type: 'ai',
720
- content: messageContent,
721
- },
722
- timestamp: response.timestamp || new Date().toISOString(),
723
- sources: response.sources || [],
724
- };
725
- setState(prev => ({
726
- ...prev,
727
- messages: [...prev.messages, assistantMessage],
728
- isLoading: false,
729
- isTyping: false,
730
- }));
731
- onMessage?.(assistantMessage);
826
+ // Stream completed - finalize state
827
+ setState(prev => ({
828
+ ...prev,
829
+ isLoading: false,
830
+ isTyping: false,
831
+ }));
832
+ // Notify about final message
833
+ if (lastStreamedMessage) {
834
+ onMessage?.(lastStreamedMessage);
732
835
  }
733
836
  }
734
837
  catch (error) {
@@ -786,11 +889,11 @@ function useChat(options) {
786
889
  conversationId: '',
787
890
  error: null,
788
891
  }));
789
- const persistConversation = state.config?.behavior.persistConversation ?? true;
892
+ const persistConversation = state.config?.settings.persistConversation ?? true;
790
893
  if (persistConversation && isStorageAvailable()) {
791
894
  clearConversation(widgetId);
792
895
  }
793
- }, [widgetId, state.config?.behavior.persistConversation]);
896
+ }, [widgetId, state.config?.settings.persistConversation]);
794
897
  /**
795
898
  * Submit feedback for a message
796
899
  */
@@ -817,7 +920,7 @@ function useChat(options) {
817
920
  * Load conversation history list from localStorage
818
921
  */
819
922
  const loadConversations = useCallback(() => {
820
- const persistConversation = state.config?.behavior.persistConversation ?? true;
923
+ const persistConversation = state.config?.settings.persistConversation ?? true;
821
924
  if (!persistConversation || !isStorageAvailable()) {
822
925
  setConversations([]);
823
926
  return;
@@ -830,12 +933,12 @@ function useChat(options) {
830
933
  messageCount: entry.messageCount,
831
934
  startedAt: entry.lastUpdated,
832
935
  })));
833
- }, [widgetId, state.config?.behavior.persistConversation]);
936
+ }, [widgetId, state.config?.settings.persistConversation]);
834
937
  /**
835
938
  * Switch to a different conversation (from localStorage first, then fetch from server if needed)
836
939
  */
837
940
  const switchConversation = useCallback(async (conversationId) => {
838
- const persistConversation = state.config?.behavior.persistConversation ?? true;
941
+ const persistConversation = state.config?.settings.persistConversation ?? true;
839
942
  // First try to load from localStorage
840
943
  if (persistConversation && isStorageAvailable()) {
841
944
  const stored = loadConversationById(widgetId, conversationId);
@@ -868,7 +971,7 @@ function useChat(options) {
868
971
  const errorInfo = deriveErrorInfo(error);
869
972
  setState(prev => ({ ...prev, isLoading: false, error: errorInfo.message }));
870
973
  }
871
- }, [widgetId, state.config?.behavior.persistConversation]);
974
+ }, [widgetId, state.config?.settings.persistConversation]);
872
975
  /**
873
976
  * Start a new conversation (keeps history)
874
977
  */
@@ -880,11 +983,11 @@ function useChat(options) {
880
983
  error: null,
881
984
  }));
882
985
  // Clear active conversation but keep history
883
- const persistConversation = state.config?.behavior.persistConversation ?? true;
986
+ const persistConversation = state.config?.settings.persistConversation ?? true;
884
987
  if (persistConversation && isStorageAvailable()) {
885
988
  clearConversation(widgetId);
886
989
  }
887
- }, [widgetId, state.config?.behavior.persistConversation]);
990
+ }, [widgetId, state.config?.settings.persistConversation]);
888
991
  return {
889
992
  messages: state.messages,
890
993
  isLoading: state.isLoading,
@@ -21592,7 +21695,7 @@ const Sources = ({ sources, displayMode = 'with-score' }) => {
21592
21695
  return (jsxs("div", { className: "ai-chat-sources", children: [jsxs("button", { className: "ai-chat-sources-toggle", onClick: () => setIsExpanded(!isExpanded), "aria-expanded": isExpanded, children: [jsx("span", { className: "ai-chat-sources-icon", children: isExpanded ? '▼' : '▶' }), jsxs("span", { className: "ai-chat-sources-title", children: [sources.length, " source", sources.length > 1 ? 's' : ''] })] }), isExpanded && displayMode !== 'minimal' && (jsx("div", { className: "ai-chat-sources-list", children: sources.map((source, index) => (jsxs("div", { className: "ai-chat-source-item", children: [jsxs("div", { className: "ai-chat-source-number", children: [index + 1, "."] }), jsxs("div", { className: "ai-chat-source-details", children: [displayMode === 'with-score' && source.score && (jsxs("div", { className: "ai-chat-source-score", children: ["Score: ", (source.score * 100).toFixed(0), "%"] })), (displayMode === 'with-content' || displayMode === 'full') && source.doc.pageContent && (jsxs("div", { className: "ai-chat-source-content", children: [source.doc.pageContent.substring(0, 100), source.doc.pageContent.length > 100 ? '...' : ''] })), displayMode === 'full' && (jsxs(Fragment, { children: [source.score && (jsxs("div", { className: "ai-chat-source-score", children: ["Score: ", (source.score * 100).toFixed(0), "%"] })), source.doc.metadata && Object.keys(source.doc.metadata).length > 0 && (jsx("div", { className: "ai-chat-source-metadata", children: Object.entries(source.doc.metadata).map(([key, value]) => (jsxs("span", { className: "ai-chat-source-meta-item", children: [key, ": ", String(value)] }, key))) }))] }))] })] }, `${source.kbId}-${source.doc.id}-${index}`))) }))] }));
21593
21696
  };
21594
21697
 
21595
- const Message = ({ message, showTimestamp = true, enableFeedback = true, showSources = true, sourceDisplayMode = 'with-score', onFeedback, toolCallNameById, }) => {
21698
+ const Message = ({ message, showTimestamp = true, enableFeedback = true, showSources = true, sourceDisplayMode = 'with-score', onFeedback, }) => {
21596
21699
  const formatTime = (timestamp) => {
21597
21700
  const date = typeof timestamp === 'string' ? new Date(timestamp) : timestamp;
21598
21701
  return date.toLocaleTimeString('en-US', {
@@ -21601,72 +21704,84 @@ const Message = ({ message, showTimestamp = true, enableFeedback = true, showSou
21601
21704
  hour12: true,
21602
21705
  });
21603
21706
  };
21604
- // Map message type to CSS class
21605
- const messageClass = message.message.type === 'human' ? 'user' :
21606
- message.message.type === 'ai' ? 'assistant' :
21607
- message.message.type === 'system' ? 'system' : 'tool';
21608
- const isAssistant = message.message.type === 'ai';
21609
- const isSystem = message.message.type === 'system';
21610
- const isTool = message.message.type === 'tool';
21611
- const isHuman = message.message.type === 'human';
21612
- const userMessage = isHuman ? message.message.content.split('--- File Content ---')[0] : '';
21613
- const aiContent = isAssistant ? (message.message.content || '') : '';
21614
- const aiHasContent = isAssistant ? aiContent.trim().length > 0 : false;
21615
- const renderAssistant = () => {
21616
- // Only render assistant bubble if there's textual content
21617
- return jsx(Markdown, { children: aiContent });
21618
- };
21619
21707
  const formatToolName = (name) => {
21620
- // Remove common prefixes like "action_" or "tool_"
21621
- let formatted = name.replace(/^(action_|tool_)/, '');
21622
- // Convert snake_case to Title Case
21623
- formatted = formatted
21708
+ return name
21709
+ .replace(/^(action_|tool_)/, '')
21624
21710
  .split('_')
21625
21711
  .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
21626
21712
  .join(' ');
21627
- return formatted;
21628
- };
21629
- const renderTool = () => {
21630
- const tool = message.message;
21631
- const rawToolName = (toolCallNameById && toolCallNameById[tool.tool_call_id]) || 'Tool';
21632
- const displayName = formatToolName(rawToolName);
21633
- return (jsxs("div", { className: "ai-chat-tool-message", title: rawToolName, children: [jsx("span", { className: "tool-finished", children: jsx("span", { className: "tool-check", children: "\u2713" }) }), jsx("span", { className: "tool-name", children: displayName })] }));
21634
21713
  };
21635
- // If assistant message has no content (e.g., only started a tool), render nothing at all
21636
- if (isAssistant && !aiHasContent) {
21637
- return null;
21714
+ const SpinnerIcon = () => (jsx("svg", { className: "ai-chat-tool-spinner", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsx("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }) }));
21715
+ const CheckIcon = () => (jsx("svg", { className: "ai-chat-tool-check", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsx("polyline", { points: "20 6 9 17 4 12" }) }));
21716
+ const ErrorIcon = () => (jsx("svg", { className: "ai-chat-tool-error", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsx("path", { d: "M18 6L6 18M6 6l12 12" }) }));
21717
+ const msgType = message.message.type;
21718
+ const isError = message.isError || false;
21719
+ const isTool = msgType === 'tool';
21720
+ const isAssistant = msgType === 'ai';
21721
+ const isSystem = msgType === 'system';
21722
+ const isHuman = msgType === 'human';
21723
+ // Tool message rendering - show as a minimal pill
21724
+ if (isTool) {
21725
+ // Get tool name from toolExecuting (during execution) or message.name (persisted)
21726
+ const toolName = message.toolExecuting || message.message.name || 'Tool';
21727
+ const hasError = isError;
21728
+ return (jsx("div", { className: "ai-chat-message tool", children: jsxs("div", { className: `ai-chat-tool-message ${hasError ? 'error' : ''}`, title: toolName, children: [message.isStreaming ? (jsx(SpinnerIcon, {})) : hasError ? (jsx(ErrorIcon, {})) : (jsx(CheckIcon, {})), jsx("span", { className: "tool-name", children: formatToolName(toolName) })] }) }));
21729
+ }
21730
+ // AI message rendering
21731
+ if (isAssistant) {
21732
+ const aiContent = message.message.content || '';
21733
+ const hasContent = aiContent.trim().length > 0;
21734
+ if (!hasContent)
21735
+ return null;
21736
+ return (jsxs("div", { className: `ai-chat-message assistant ${isError ? 'error' : ''}`, children: [jsxs("div", { className: "ai-chat-message-content", children: [isError && (jsxs("div", { className: "ai-chat-error-indicator", children: [jsx("span", { className: "error-icon", children: "\u26A0\uFE0F" }), jsx("span", { className: "error-text", children: "Error" })] })), jsx(Markdown, { children: aiContent })] }), showTimestamp && (jsxs("div", { className: "ai-chat-message-meta", children: [jsx("span", { className: "ai-chat-message-timestamp", children: formatTime(message.timestamp) }), enableFeedback && onFeedback && (jsx(FeedbackButtons, { messageId: message.id, currentFeedback: message.feedback, onFeedback: onFeedback }))] })), showSources && message.sources?.length > 0 && (jsx(Sources, { sources: message.sources, displayMode: sourceDisplayMode }))] }));
21737
+ }
21738
+ // System message rendering
21739
+ if (isSystem) {
21740
+ return (jsxs("div", { className: "ai-chat-message system", children: [jsx("div", { className: "ai-chat-message-content", children: jsxs("div", { className: "ai-chat-system-message", children: [jsx("span", { className: "system-icon", children: "\u2139\uFE0F" }), message.message.content] }) }), showTimestamp && (jsx("div", { className: "ai-chat-message-meta", children: jsx("span", { className: "ai-chat-message-timestamp", children: formatTime(message.timestamp) }) }))] }));
21638
21741
  }
21639
- const showTimestampForThis = showTimestamp && !isTool && !(isAssistant && !aiHasContent);
21640
- return (jsxs("div", { className: `ai-chat-message ${messageClass}`, children: [isTool ? (
21641
- // Render tool call completion as a standalone, non-bubble event
21642
- renderTool()) : (jsx("div", { className: "ai-chat-message-content", children: isAssistant ? (renderAssistant()) : isSystem ? (jsxs("div", { className: "ai-chat-system-message", children: [jsx("span", { className: "system-icon", children: "\u2139\uFE0F" }), message.message.content] })) : (userMessage) })), showTimestampForThis && (jsxs("div", { className: "ai-chat-message-meta", children: [jsx("span", { className: "ai-chat-message-timestamp", children: formatTime(message.timestamp) }), isAssistant && aiHasContent && enableFeedback && onFeedback && (jsx(FeedbackButtons, { messageId: message.id, currentFeedback: message.feedback, onFeedback: onFeedback }))] })), isAssistant && aiHasContent && showSources && message.sources && message.sources.length > 0 && (jsx(Sources, { sources: message.sources, displayMode: sourceDisplayMode }))] }));
21742
+ // Human message rendering
21743
+ if (isHuman) {
21744
+ const userContent = message.message.content.split('--- File Content ---')[0];
21745
+ return (jsxs("div", { className: "ai-chat-message user", children: [jsx("div", { className: "ai-chat-message-content", children: userContent }), showTimestamp && (jsx("div", { className: "ai-chat-message-meta", children: jsx("span", { className: "ai-chat-message-timestamp", children: formatTime(message.timestamp) }) }))] }));
21746
+ }
21747
+ return null;
21643
21748
  };
21644
21749
 
21645
21750
  const TypingIndicator = () => {
21646
21751
  return (jsx("div", { className: "ai-chat-message assistant", children: jsxs("div", { className: "ai-chat-typing", children: [jsx("span", { className: "ai-chat-typing-dot" }), jsx("span", { className: "ai-chat-typing-dot" }), jsx("span", { className: "ai-chat-typing-dot" })] }) }));
21647
21752
  };
21648
21753
 
21649
- const MessageList = ({ messages, isTyping = false, showTypingIndicator = true, showTimestamps = true, enableFeedback = true, showSources = true, sourceDisplayMode = 'with-score', welcomeTitle, welcomeMessage, onFeedback, }) => {
21754
+ const SuggestedQuestions = ({ questions, onQuestionClick, }) => {
21755
+ if (!questions || questions.length === 0) {
21756
+ return null;
21757
+ }
21758
+ // Filter out empty questions
21759
+ const validQuestions = questions.filter(q => q && q.trim());
21760
+ if (validQuestions.length === 0) {
21761
+ return null;
21762
+ }
21763
+ return (jsx("div", { className: "ai-chat-suggested-questions", children: jsx("div", { className: "ai-chat-suggested-questions-list", children: validQuestions.slice(0, 5).map((question, index) => (jsx("button", { className: "ai-chat-suggested-question", onClick: () => onQuestionClick(question), type: "button", children: jsx("span", { className: "ai-chat-suggested-question-text", children: question }) }, index))) }) }));
21764
+ };
21765
+
21766
+ const MessageList = ({ messages, isTyping = false, showTypingIndicator = true, showTimestamps = true, enableFeedback = true, showSources = true, sourceDisplayMode = 'with-score', welcomeTitle, welcomeMessage, suggestedQuestions, onSuggestedQuestionClick, onFeedback, }) => {
21767
+ const containerRef = useRef(null);
21650
21768
  const messagesEndRef = useRef(null);
21651
- // Auto-scroll to bottom when new messages arrive
21769
+ // Auto-scroll to bottom only on initial mount/load
21652
21770
  useEffect(() => {
21653
- messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
21654
- }, [messages, isTyping]);
21655
- // Build a map from tool_call_id -> tool name from AI messages
21656
- const toolCallNameById = useMemo(() => {
21657
- const map = {};
21658
- for (const m of messages) {
21659
- if (m.message.type === 'ai' && Array.isArray(m.message.tool_calls)) {
21660
- for (const tc of m.message.tool_calls) {
21661
- if (tc?.id && tc?.name) {
21662
- map[tc.id] = tc.name;
21663
- }
21664
- }
21665
- }
21771
+ const container = containerRef.current;
21772
+ if (!container)
21773
+ return;
21774
+ // Only scroll if content actually overflows AND the user is near the bottom.
21775
+ // This prevents the "first message" case from being pushed to the very bottom
21776
+ // (which looks like a huge empty gap above the first user message).
21777
+ const overflow = container.scrollHeight - container.clientHeight;
21778
+ const isOverflowing = overflow > 20;
21779
+ const nearBottom = container.scrollTop + container.clientHeight >= container.scrollHeight - 80;
21780
+ if (isOverflowing && nearBottom) {
21781
+ messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
21666
21782
  }
21667
- return map;
21668
- }, [messages]);
21669
- return (jsxs("div", { className: "ai-chat-messages", role: "log", "aria-live": "polite", "aria-atomic": "false", children: [messages.length === 0 && (welcomeTitle || welcomeMessage) && (jsxs("div", { className: "ai-chat-welcome", children: [welcomeTitle && (jsx("div", { className: "ai-chat-welcome-title", children: welcomeTitle })), welcomeMessage && (jsx("div", { className: "ai-chat-welcome-text", children: welcomeMessage }))] })), messages.map((message) => (jsx(Message, { message: message, showTimestamp: showTimestamps, enableFeedback: enableFeedback, showSources: showSources, sourceDisplayMode: sourceDisplayMode, toolCallNameById: toolCallNameById, onFeedback: onFeedback }, message.id))), isTyping && showTypingIndicator && jsx(TypingIndicator, {}), jsx("div", { ref: messagesEndRef })] }));
21783
+ }, [messages, isTyping]);
21784
+ return (jsxs("div", { ref: containerRef, className: "ai-chat-messages", role: "log", "aria-live": "polite", "aria-atomic": "false", children: [(welcomeTitle || welcomeMessage) && (jsxs("div", { className: "ai-chat-welcome", children: [welcomeTitle && (jsx("div", { className: "ai-chat-welcome-title", children: welcomeTitle })), welcomeMessage && (jsx("div", { className: "ai-chat-welcome-text", children: welcomeMessage })), messages.length === 0 && onSuggestedQuestionClick && suggestedQuestions && suggestedQuestions.length > 0 && (jsx(SuggestedQuestions, { questions: suggestedQuestions, onQuestionClick: onSuggestedQuestionClick }))] })), messages.map((message) => (jsx(Message, { message: message, showTimestamp: showTimestamps, enableFeedback: enableFeedback, showSources: showSources, sourceDisplayMode: sourceDisplayMode, onFeedback: onFeedback }, message.id))), isTyping && showTypingIndicator && jsx(TypingIndicator, {}), jsx("div", { ref: messagesEndRef })] }));
21670
21785
  };
21671
21786
 
21672
21787
  // Allowed file types
@@ -21754,49 +21869,38 @@ const MessageInput = ({ onSend, placeholder = 'Type your message...', disabled =
21754
21869
  return (jsxs("div", { className: `ai-chat-input-container ${separateFromChat ? 'separate' : 'integrated'}`, children: [selectedFiles.length > 0 && (jsx("div", { className: "ai-chat-file-list", children: selectedFiles.map((file, index) => {
21755
21870
  const ext = getFileExtension(file.name);
21756
21871
  return (jsxs("div", { className: "ai-chat-file-item", children: [jsx("span", { className: "ai-chat-file-extension", children: ext }), jsxs("div", { className: "ai-chat-file-info", children: [jsx("span", { className: "ai-chat-file-name", children: file.name }), jsx("span", { className: "ai-chat-file-size", children: formatFileSize(file.size) })] }), jsx("button", { className: "ai-chat-file-remove", onClick: () => handleRemoveFile(index), "aria-label": "Remove file", children: jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsx("path", { d: "M18 6L6 18M6 6l12 12" }) }) })] }, index));
21757
- }) })), jsxs("div", { className: "ai-chat-input-wrapper", children: [enableFileUpload && (jsxs(Fragment, { children: [jsx("input", { ref: fileInputRef, type: "file", onChange: handleFileSelect, style: { display: 'none' }, multiple: true, accept: ALLOWED_EXTENSIONS.join(','), "aria-label": "File input" }), jsx("button", { className: "ai-chat-file-button", onClick: () => fileInputRef.current?.click(), disabled: disabled, "aria-label": "Attach file", children: jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: 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" }) }) })] })), jsx("textarea", { ref: textareaRef, className: "ai-chat-input", value: value, onChange: handleChange, onKeyDown: handleKeyDown, placeholder: placeholder, disabled: disabled, rows: 1, "aria-label": "Message input" }), jsx("button", { className: `ai-chat-send-button ${canSend ? 'active' : ''}`, onClick: handleSend, disabled: disabled || !canSend, "aria-label": "Send message", children: jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [jsx("path", { d: "M22 2L11 13" }), jsx("path", { d: "M22 2L15 22L11 13L2 9L22 2Z" })] }) })] })] }));
21758
- };
21759
-
21760
- const ArrowIcon = () => (jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsx("path", { d: "M5 12h14M12 5l7 7-7 7" }) }));
21761
- const SuggestedQuestions = ({ questions, onQuestionClick, }) => {
21762
- if (!questions || questions.length === 0) {
21763
- return null;
21764
- }
21765
- // Filter out empty questions
21766
- const validQuestions = questions.filter(q => q && q.trim());
21767
- if (validQuestions.length === 0) {
21768
- return null;
21769
- }
21770
- return (jsx("div", { className: "ai-chat-suggested-questions", children: jsx("div", { className: "ai-chat-suggested-questions-list", children: validQuestions.slice(0, 3).map((question, index) => (jsxs("button", { className: "ai-chat-suggested-question", onClick: () => onQuestionClick(question), type: "button", children: [jsx("span", { className: "ai-chat-suggested-question-text", children: question }), jsx("span", { className: "ai-chat-suggested-question-icon", children: jsx(ArrowIcon, {}) })] }, index))) }) }));
21872
+ }) })), jsxs("div", { className: "ai-chat-input-wrapper", children: [enableFileUpload && (jsxs(Fragment, { children: [jsx("input", { ref: fileInputRef, type: "file", onChange: handleFileSelect, style: { display: 'none' }, multiple: true, accept: ALLOWED_EXTENSIONS.join(','), "aria-label": "File input" }), jsx("button", { className: "ai-chat-file-button", onClick: () => fileInputRef.current?.click(), disabled: disabled, "aria-label": "Attach file", children: jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: 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" }) }) })] })), jsx("textarea", { ref: textareaRef, className: "ai-chat-input", value: value, onChange: handleChange, onKeyDown: handleKeyDown, placeholder: placeholder, disabled: disabled, rows: 1, "aria-label": "Message input" }), jsx("button", { className: `ai-chat-send-button ${canSend ? 'active' : ''}`, onClick: handleSend, disabled: disabled || !canSend, "aria-label": "Send message", children: jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [jsx("path", { d: "M12 19V5" }), jsx("path", { d: "M5 12l7-7 7 7" })] }) })] })] }));
21771
21873
  };
21772
21874
 
21773
- const MinimizeIcon = () => (jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsx("path", { d: "M5 12h14" }) }));
21774
- const HistoryIcon = () => (jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsx("circle", { cx: "12", cy: "12", r: "10" }), jsx("polyline", { points: "12 6 12 12 16 14" })] }));
21775
- const NewChatIcon = () => (jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsx("path", { d: "M12 5v14M5 12h14" }) }));
21776
- const BackIcon = () => (jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsx("path", { d: "M19 12H5M12 19l-7-7 7-7" }) }));
21777
- const ChatWindow = ({ messages, isLoading, isTyping, error, config, onSendMessage, onClose, onFeedback,
21875
+ const MenuIcon = () => (jsxs("svg", { width: "26", height: "26", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [jsx("path", { d: "M4 10h16" }), jsx("path", { d: "M10 14h10" })] }));
21876
+ const PlusIcon = () => (jsxs("svg", { width: "26", height: "26", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [jsx("path", { d: "M12 5v14" }), jsx("path", { d: "M5 12h14" })] }));
21877
+ const ChatWindow = ({ messages, isLoading, isTyping, error, config, onSendMessage, onClose: _onClose, onFeedback,
21778
21878
  // Chat history props (only active when persistConversation is true)
21779
- conversations = [], onLoadConversations, onSwitchConversation, onStartNewConversation, currentConversationId, }) => {
21879
+ conversations = [], onLoadConversations, onSwitchConversation, onStartNewConversation, currentConversationId,
21880
+ // Override props for live preview
21881
+ headerTitleOverride, welcomeTitleOverride, welcomeMessageOverride, placeholderOverride, suggestedQuestionsOverride, }) => {
21780
21882
  console.log('[ChatWindow] Rendering ChatWindow component');
21781
21883
  const appearance = config?.appearance;
21782
- const behavior = config?.behavior;
21783
- // Use simplified appearance fields
21884
+ const settings = config?.settings;
21885
+ // Check if chat history should be shown (requires both persistConversation AND showChatHistory)
21886
+ const canShowHistory = (settings?.persistConversation ?? true) && (settings?.showChatHistory ?? true);
21887
+ // Apply overrides for live preview (overrides take priority over saved config)
21784
21888
  const size = appearance?.size || 'medium';
21785
- const headerTitle = appearance?.headerTitle || 'AI Assistant';
21786
- const welcomeMessage = appearance?.welcomeMessage || '👋 Hi there! How can I assist you today?';
21787
- const inputPlaceholder = appearance?.placeholder || 'Ask me anything...';
21889
+ const headerTitle = headerTitleOverride ?? appearance?.headerTitle ?? 'AI Assistant';
21890
+ const welcomeTitle = welcomeTitleOverride ?? appearance?.welcomeTitle ?? '';
21891
+ const welcomeMessage = welcomeMessageOverride ?? appearance?.welcomeMessage ?? '';
21892
+ const inputPlaceholder = placeholderOverride ?? appearance?.placeholder ?? 'Ask me anything...';
21788
21893
  console.log('[ChatWindow] Appearance values:', {
21789
21894
  size,
21790
21895
  headerTitle,
21896
+ welcomeTitle,
21791
21897
  welcomeMessage,
21792
21898
  inputPlaceholder,
21793
21899
  });
21794
- // Track if suggested questions should be shown
21795
- const [showSuggestedQuestions, setShowSuggestedQuestions] = useState(true);
21796
21900
  // Track if history panel is open
21797
21901
  const [showHistory, setShowHistory] = useState(false);
21798
- // Check if chat history feature is enabled (only when persistConversation is true)
21799
- const isHistoryEnabled = behavior?.persistConversation !== false && !!onLoadConversations;
21902
+ // History exit animation when starting a new chat from overview
21903
+ const [isHistoryExiting, setIsHistoryExiting] = useState(false);
21800
21904
  // Load conversations when history panel opens
21801
21905
  const handleOpenHistory = () => {
21802
21906
  setShowHistory(true);
@@ -21811,30 +21915,37 @@ conversations = [], onLoadConversations, onSwitchConversation, onStartNewConvers
21811
21915
  setShowHistory(false);
21812
21916
  }
21813
21917
  };
21814
- // Handle new conversation
21815
21918
  const handleNewConversation = () => {
21816
- if (onStartNewConversation) {
21817
- onStartNewConversation();
21919
+ if (!onStartNewConversation)
21920
+ return;
21921
+ onStartNewConversation();
21922
+ setShowHistory(false);
21923
+ };
21924
+ const handleSendFromOverview = (content) => {
21925
+ const trimmed = content.trim();
21926
+ if (!trimmed)
21927
+ return;
21928
+ if (!onStartNewConversation) {
21929
+ // Fallback: just go back to chat and send
21818
21930
  setShowHistory(false);
21931
+ onSendMessage(trimmed);
21932
+ return;
21819
21933
  }
21934
+ setIsHistoryExiting(true);
21935
+ window.setTimeout(() => {
21936
+ onStartNewConversation();
21937
+ setShowHistory(false);
21938
+ setIsHistoryExiting(false);
21939
+ onSendMessage(trimmed);
21940
+ }, 240);
21820
21941
  };
21821
- // Hide suggested questions after first user message
21822
- useEffect(() => {
21823
- const userMessages = messages.filter(m => m.message.type === 'human');
21824
- if (userMessages.length > 0) {
21825
- setShowSuggestedQuestions(false);
21826
- }
21827
- }, [messages]);
21828
21942
  // Check if message limit is reached
21829
- const maxMessages = behavior?.maxMessagesPerSession;
21943
+ const maxMessages = settings?.maxMessagesPerSession;
21830
21944
  const userMessageCount = messages.filter(m => m.message.type === 'human').length;
21831
21945
  const isLimitReached = maxMessages ? userMessageCount >= maxMessages : false;
21832
- // Handle suggested question click
21833
21946
  const handleQuestionClick = (question) => {
21834
- setShowSuggestedQuestions(false);
21835
21947
  onSendMessage(question);
21836
21948
  };
21837
- const hasMessages = messages.length > 0;
21838
21949
  // Format date for conversation list
21839
21950
  const formatDate = (dateString) => {
21840
21951
  const date = new Date(dateString);
@@ -21849,7 +21960,7 @@ conversations = [], onLoadConversations, onSwitchConversation, onStartNewConvers
21849
21960
  return `${diffDays} days ago`;
21850
21961
  return date.toLocaleDateString();
21851
21962
  };
21852
- return (jsxs("div", { className: `ai-chat-window size-${size}`, role: "dialog", "aria-label": "Chat window", children: [jsx("div", { className: "ai-chat-header", children: showHistory ? (jsxs(Fragment, { children: [jsx("button", { className: "ai-chat-header-button", onClick: () => setShowHistory(false), "aria-label": "Back to chat", children: jsx(BackIcon, {}) }), jsx("div", { className: "ai-chat-title", children: "Chat History" }), jsx("button", { className: "ai-chat-header-button", onClick: handleNewConversation, "aria-label": "New conversation", children: jsx(NewChatIcon, {}) })] })) : (jsxs(Fragment, { children: [jsxs("div", { className: "ai-chat-header-content", children: [appearance?.logo && (jsx("img", { src: appearance.logo, alt: "Logo", className: "ai-chat-logo" })), jsx("div", { className: "ai-chat-title", children: headerTitle })] }), jsxs("div", { className: "ai-chat-header-actions", children: [isHistoryEnabled && (jsx("button", { className: "ai-chat-header-button", onClick: handleOpenHistory, "aria-label": "Chat history", children: jsx(HistoryIcon, {}) })), jsx("button", { className: "ai-chat-close-button", onClick: onClose, "aria-label": "Minimize chat", children: jsx(MinimizeIcon, {}) })] })] })) }), showHistory ? (jsx("div", { className: "ai-chat-history-panel", children: conversations.length === 0 ? (jsx("div", { className: "ai-chat-history-empty", children: "No previous conversations" })) : (jsx("div", { className: "ai-chat-history-list", children: conversations.map((conv) => (jsxs("button", { className: `ai-chat-history-item ${conv.id === currentConversationId ? 'active' : ''}`, onClick: () => handleSelectConversation(conv.id), children: [jsx("div", { className: "ai-chat-history-item-preview", children: conv.preview }), jsxs("div", { className: "ai-chat-history-item-meta", children: [jsx("span", { children: formatDate(conv.lastMessageAt) }), jsxs("span", { children: [conv.messageCount, " messages"] })] })] }, conv.id))) })) })) : (jsxs(Fragment, { children: [error && (jsx("div", { className: "ai-chat-error", role: "alert", children: error })), maxMessages && userMessageCount >= maxMessages - 2 && !isLimitReached && (jsxs("div", { className: "ai-chat-warning", role: "alert", children: [maxMessages - userMessageCount, " message", maxMessages - userMessageCount !== 1 ? 's' : '', " remaining"] })), isLimitReached && (jsx("div", { className: "ai-chat-error", role: "alert", children: "Message limit reached. Please start a new conversation." })), jsx(MessageList, { messages: messages, isTyping: isTyping, showTypingIndicator: behavior?.showTypingIndicator, showTimestamps: behavior?.showTimestamps, enableFeedback: behavior?.enableFeedback, showSources: behavior?.showSources, sourceDisplayMode: behavior?.sourceDisplayMode, welcomeMessage: welcomeMessage, onFeedback: onFeedback }), showSuggestedQuestions && !hasMessages && behavior?.suggestedQuestions && behavior.suggestedQuestions.length > 0 && (jsx(SuggestedQuestions, { questions: behavior.suggestedQuestions, onQuestionClick: handleQuestionClick })), jsx(MessageInput, { onSend: onSendMessage, placeholder: isLimitReached ? 'Message limit reached' : inputPlaceholder, disabled: isLoading || isLimitReached, enableFileUpload: behavior?.enableFileUpload })] }))] }));
21963
+ return (jsxs("div", { className: `ai-chat-window size-${size}`, role: "dialog", "aria-label": "Chat window", children: [jsx("div", { className: `ai-chat-header ${showHistory ? 'is-history' : ''}`, children: showHistory ? (jsxs(Fragment, { children: [jsx("div", { className: "ai-chat-title", children: headerTitle }), jsx("button", { className: "ai-chat-header-button", onClick: handleNewConversation, "aria-label": "New chat", children: jsx(PlusIcon, {}) })] })) : (jsxs(Fragment, { children: [jsxs("div", { className: "ai-chat-header-content", children: [appearance?.logo && (jsx("img", { src: appearance.logo, alt: "Logo", className: "ai-chat-logo" })), jsx("div", { className: "ai-chat-title", children: headerTitle })] }), canShowHistory && (jsx("div", { className: "ai-chat-header-actions", children: jsx("button", { className: "ai-chat-close-button", onClick: handleOpenHistory, "aria-label": "Chat overview", children: jsx(MenuIcon, {}) }) }))] })) }), showHistory ? (jsxs("div", { className: "ai-chat-history-panel", children: [conversations.length === 0 ? (jsx("div", { className: "ai-chat-history-empty", children: "No previous conversations" })) : (jsx("div", { className: `ai-chat-history-list ${isHistoryExiting ? 'exiting' : ''}`, children: conversations.map((conv) => (jsxs("button", { className: `ai-chat-history-item ${conv.id === currentConversationId ? 'active' : ''}`, onClick: () => handleSelectConversation(conv.id), children: [jsx("div", { className: "ai-chat-history-item-preview", children: conv.preview }), jsxs("div", { className: "ai-chat-history-item-meta", children: [jsx("span", { children: formatDate(conv.lastMessageAt) }), jsxs("span", { children: [conv.messageCount, " messages"] })] })] }, conv.id))) })), jsx(MessageInput, { onSend: (text) => handleSendFromOverview(text), placeholder: inputPlaceholder, disabled: isLoading, enableFileUpload: settings?.enableFileUpload })] })) : (jsxs(Fragment, { children: [error && (jsx("div", { className: "ai-chat-error", role: "alert", children: error })), maxMessages && userMessageCount >= maxMessages - 2 && !isLimitReached && (jsxs("div", { className: "ai-chat-warning", role: "alert", children: [maxMessages - userMessageCount, " message", maxMessages - userMessageCount !== 1 ? 's' : '', " remaining"] })), isLimitReached && (jsx("div", { className: "ai-chat-error", role: "alert", children: "Message limit reached. Please start a new conversation." })), jsx(MessageList, { messages: messages, isTyping: isTyping, showTypingIndicator: settings?.showTypingIndicator, showTimestamps: settings?.showTimestamps, enableFeedback: settings?.enableFeedback, showSources: settings?.showSources, sourceDisplayMode: settings?.sourceDisplayMode, welcomeTitle: welcomeTitle || 'Welcome Message', welcomeMessage: welcomeMessage, suggestedQuestions: suggestedQuestionsOverride ?? settings?.suggestedQuestions, onSuggestedQuestionClick: handleQuestionClick, onFeedback: onFeedback }), jsx(MessageInput, { onSend: onSendMessage, placeholder: isLimitReached ? 'Message limit reached' : inputPlaceholder, disabled: isLoading || isLimitReached, enableFileUpload: settings?.enableFileUpload })] }))] }));
21853
21964
  };
21854
21965
 
21855
21966
  /**
@@ -22032,22 +22143,18 @@ function generateDarkPalette(accentColor) {
22032
22143
  * Generate all CSS custom properties for the widget
22033
22144
  */
22034
22145
  function generateThemeStyles(appearance, theme) {
22035
- const palette = theme === 'dark'
22036
- ? generateDarkPalette(appearance.accentColor)
22037
- : generateLightPalette(appearance.accentColor);
22146
+ const hasAccentColor = appearance.accentColor && appearance.accentColor.trim() !== '';
22038
22147
  // Liquid glass design - frosted glass with transparency
22039
22148
  const isLight = theme === 'light';
22040
- return {
22149
+ // Base styles that don't depend on accent color
22150
+ const styles = {
22041
22151
  // ========================================================================
22042
- // BUTTON (FAB) - Liquid Glass Style
22152
+ // BUTTON (FAB) - Base styles
22043
22153
  // ========================================================================
22044
- '--button-color': palette.accent,
22045
22154
  '--button-opacity': '1',
22046
22155
  '--button-size': '56px',
22047
- '--button-icon-color': palette.userBubbleText,
22048
22156
  '--button-border-radius': '50%',
22049
22157
  '--button-border-width': '0px',
22050
- '--button-border-color': palette.accent,
22051
22158
  '--button-border-opacity': '1',
22052
22159
  '--button-backdrop-blur': '20px',
22053
22160
  '--button-shadow': `0 4px 24px rgba(0, 0, 0, 0.15), 0 2px 8px rgba(0, 0, 0, 0.1)`,
@@ -22070,7 +22177,6 @@ function generateThemeStyles(appearance, theme) {
22070
22177
  // ========================================================================
22071
22178
  '--header-background': 'transparent',
22072
22179
  '--header-opacity': '1',
22073
- '--header-text-color': palette.accent,
22074
22180
  '--header-border-bottom-width': '0px',
22075
22181
  '--header-border-bottom-color': 'transparent',
22076
22182
  '--header-border-bottom-opacity': '0',
@@ -22080,17 +22186,13 @@ function generateThemeStyles(appearance, theme) {
22080
22186
  // ========================================================================
22081
22187
  '--chat-background': 'transparent',
22082
22188
  '--chat-opacity': '1',
22083
- '--welcome-color': palette.text,
22084
- '--message-text-color': palette.text,
22085
22189
  // ========================================================================
22086
22190
  // MESSAGE BUBBLES - Glass style
22087
22191
  // ========================================================================
22088
- '--bubble-user-color': palette.userBubble,
22089
22192
  '--bubble-user-opacity': '1',
22090
- '--user-message-text': palette.userBubbleText,
22091
22193
  '--bubble-assistant-color': isLight ? 'rgba(255, 255, 255, 0.8)' : 'rgba(255, 255, 255, 0.1)',
22092
22194
  '--bubble-assistant-opacity': '1',
22093
- '--assistant-message-text': isLight ? palette.text : '#f0f0f0',
22195
+ '--assistant-message-text': isLight ? '#000000' : '#f0f0f0',
22094
22196
  '--bubble-border-radius': '20px',
22095
22197
  '--bubble-border-width': isLight ? '1px' : '1px',
22096
22198
  '--bubble-border-color': isLight ? 'rgba(0, 0, 0, 0.05)' : 'rgba(255, 255, 255, 0.08)',
@@ -22112,38 +22214,48 @@ function generateThemeStyles(appearance, theme) {
22112
22214
  '--input-border-color': isLight ? 'rgba(0, 0, 0, 0.08)' : 'rgba(255, 255, 255, 0.1)',
22113
22215
  '--input-border-opacity': '1',
22114
22216
  '--input-shadow': `inset 0 1px 3px rgba(0, 0, 0, 0.04), 0 2px 8px rgba(0, 0, 0, 0.04)`,
22115
- '--send-button-background': palette.accent,
22116
22217
  '--send-button-opacity': '1',
22117
22218
  '--send-button-border-radius': '50%',
22118
22219
  '--send-button-border-width': '0px',
22119
- '--send-button-border-color': palette.accent,
22120
22220
  '--send-button-border-opacity': '1',
22121
22221
  // ========================================================================
22122
22222
  // HOVER STATES
22123
22223
  // ========================================================================
22124
22224
  '--hover-button-scale': '1.08',
22125
22225
  '--hover-button-opacity': '1',
22126
- '--hover-input-border-color': palette.accent,
22127
22226
  '--hover-send-button-opacity': '1',
22128
22227
  '--hover-close-button-opacity': '1',
22129
22228
  // ========================================================================
22130
- // ACTIVE STATES
22131
- // ========================================================================
22132
- '--active-input-border-color': palette.accent,
22133
- '--active-input-shadow': `0 0 0 4px ${withAlpha(palette.accent, 0.15)}`,
22134
- // ========================================================================
22135
- // GENERAL
22136
- // ========================================================================
22137
- '--primary-color': palette.accent,
22138
- '--background-color': palette.background,
22139
- '--text-color': palette.text,
22140
- '--border-color': palette.border,
22141
- // ========================================================================
22142
22229
  // GLASS EFFECTS
22143
22230
  // ========================================================================
22144
22231
  '--glass-blur': '20px',
22145
22232
  '--glass-saturation': '180%',
22146
22233
  };
22234
+ // Only add accent-color-based styles if an accent color is provided
22235
+ if (hasAccentColor) {
22236
+ const palette = theme === 'dark'
22237
+ ? generateDarkPalette(appearance.accentColor)
22238
+ : generateLightPalette(appearance.accentColor);
22239
+ // Add accent color styles
22240
+ styles['--button-color'] = palette.accent;
22241
+ styles['--button-icon-color'] = palette.userBubbleText;
22242
+ styles['--button-border-color'] = palette.accent;
22243
+ styles['--header-text-color'] = palette.accent;
22244
+ styles['--welcome-color'] = palette.text;
22245
+ styles['--message-text-color'] = palette.text;
22246
+ styles['--bubble-user-color'] = palette.userBubble;
22247
+ styles['--user-message-text'] = palette.userBubbleText;
22248
+ styles['--send-button-background'] = palette.accent;
22249
+ styles['--send-button-border-color'] = palette.accent;
22250
+ styles['--hover-input-border-color'] = palette.accent;
22251
+ styles['--active-input-border-color'] = palette.accent;
22252
+ styles['--active-input-shadow'] = `0 0 0 4px ${withAlpha(palette.accent, 0.15)}`;
22253
+ styles['--primary-color'] = palette.accent;
22254
+ styles['--background-color'] = palette.background;
22255
+ styles['--text-color'] = palette.text;
22256
+ styles['--border-color'] = palette.border;
22257
+ }
22258
+ return styles;
22147
22259
  }
22148
22260
 
22149
22261
  /**
@@ -22254,7 +22366,7 @@ function styleInject(css, ref) {
22254
22366
  if ( ref === void 0 ) ref = {};
22255
22367
  var insertAt = ref.insertAt;
22256
22368
 
22257
- if (!css || typeof document === 'undefined') { return; }
22369
+ if (typeof document === 'undefined') { return; }
22258
22370
 
22259
22371
  var head = document.head || document.getElementsByTagName('head')[0];
22260
22372
  var style = document.createElement('style');
@@ -22277,10 +22389,7 @@ function styleInject(css, ref) {
22277
22389
  }
22278
22390
  }
22279
22391
 
22280
- var css_248z$1 = ".ai-chat-widget{--primary-color:#07f;--background-color:#fff;--text-color:#1f2937;--border-color:#e5e7eb;--user-message-bg:var(--primary-color);--user-message-text:#fff;--assistant-message-bg:#f3f4f6;--assistant-message-text:#374151;--input-bg:#fff;--input-border:#d1d5db;--shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06);--shadow-lg:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -2px rgba(0,0,0,.05);--button-color:#07f;--button-size:56px;--button-border-radius:28px;--button-border-width:0px;--button-border-color:#07f;--button-opacity:1;--button-backdrop-blur:0px;--button-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -2px rgba(0,0,0,.05);--card-background:#fff;--card-border-radius:16px;--card-border-width:0px;--card-border-color:#e5e7eb;--card-opacity:1;--card-backdrop-blur:0px;--card-shadow:0 25px 50px -12px rgba(0,0,0,.25);--header-background:#07f;--header-text-color:#fff;--header-font-size:18px;--header-border-bottom-width:0px;--header-border-bottom-color:#e5e7eb;--header-opacity:1;--header-backdrop-blur:0px;--chat-background:#fff;--chat-opacity:1;--chat-backdrop-blur:0px;--welcome-font-size:16px;--welcome-color:#1f2937;--welcome-opacity:1;--bubble-user-color:#07f;--bubble-assistant-color:#f3f4f6;--bubble-border-radius:16px;--bubble-border-width:0px;--bubble-border-color:#e5e7eb;--bubble-opacity:1;--typing-animation-color:#f3f4f6;--typing-animation-opacity:1;--typing-animation-border-width:0px;--typing-animation-border-color:#e5e7eb;--typing-animation-border-radius:16px;--footer-background:#fff;--footer-border-top-width:1px;--footer-border-top-color:#e5e7eb;--footer-opacity:1;--footer-backdrop-blur:0px;--input-background:#fff;--input-border-radius:24px;--input-border-width:1.5px;--input-border-color:#d1d5db;--input-opacity:1;--input-shadow:0 1px 2px 0 rgba(0,0,0,.05);--send-button-background:#07f;--send-button-border-radius:20px;--send-button-border-width:0px;--send-button-border-color:#07f;--send-button-opacity:1;--hover-button-scale:1.05;--hover-button-opacity:0.9;--hover-input-border-color:#9ca3af;--hover-send-button-opacity:0.85;--hover-close-button-opacity:1;--active-input-border-color:#07f;--active-input-shadow:0 0 0 3px rgba(0,119,255,.1);-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.dark{--background-color:#001d3d;--text-color:#f9fafb;--border-color:#374151;--assistant-message-bg:#036;--assistant-message-text:#e5e7eb;--input-bg:#002855;--input-border:#374151}.ai-chat-widget.dark .ai-chat-message.system .ai-chat-message-content{background-color:#78350f;color:#fef3c7}.ai-chat-widget.dark .ai-chat-message.tool .ai-chat-message-content{background-color:#1e3a8a;color:#dbeafe}.ai-chat-widget-container{font-size:14px;line-height:1.5;position:fixed;z-index:9999}.ai-chat-widget-container.bottom-right{bottom:20px;right:20px}.ai-chat-widget-container.bottom-left{bottom:20px;left:20px}.ai-chat-widget-container.top-right{right:20px;top:20px}.ai-chat-widget-container.top-left{left:20px;top:20px}.ai-chat-button{align-items:center;backdrop-filter:blur(var(--button-backdrop-blur));-webkit-backdrop-filter:blur(var(--button-backdrop-blur));background-color:var(--button-color);border:var(--button-border-width) solid var(--button-border-color);border-radius:var(--button-border-radius);box-shadow:var(--button-shadow);color:#fff;cursor:pointer;display:flex;height:var(--button-size);justify-content:center;opacity:var(--button-opacity);transition:all .3s cubic-bezier(.4,0,.2,1);width:var(--button-size)}.ai-chat-button:hover{opacity:.9}.ai-chat-button:active{opacity:.8}.ai-chat-button-svg{height:50%;min-height:24px;min-width:24px;width:50%}.ai-chat-button-icon{font-size:1.5em;line-height:1}.ai-chat-window{border-radius:var(--card-border-radius);box-shadow:0 0 0 var(--card-border-width) var(--card-border-color-rgba,var(--card-border-color)),var(--card-shadow);display:flex;flex-direction:column;overflow:hidden;position:absolute}.ai-chat-window>*{position:relative;z-index:1}.ai-chat-window:before{backdrop-filter:blur(var(--card-backdrop-blur));-webkit-backdrop-filter:blur(var(--card-backdrop-blur));background-color:var(--card-background);border-radius:var(--card-border-radius);content:\"\";inset:0;opacity:var(--card-opacity);pointer-events:none;position:absolute;z-index:0}.ai-chat-widget-container.bottom-right .ai-chat-window{bottom:calc(var(--button-size, 60px) + 16px);right:0}.ai-chat-widget-container.bottom-left .ai-chat-window{bottom:calc(var(--button-size, 60px) + 16px);left:0}.ai-chat-widget-container.top-right .ai-chat-window{right:0;top:calc(var(--button-size, 60px) + 16px)}.ai-chat-widget-container.top-left .ai-chat-window{left:0;top:calc(var(--button-size, 60px) + 16px)}.ai-chat-button{z-index:1}.ai-chat-window{z-index:2}.ai-chat-window.size-small{height:500px;width:380px}.ai-chat-window.size-medium{height:650px;width:440px}.ai-chat-window.size-large{height:750px;width:520px}.ai-chat-logo{border-radius:50%;height:32px;object-fit:cover;width:32px}.ai-chat-messages::-webkit-scrollbar{width:6px}.ai-chat-messages::-webkit-scrollbar-track{background:transparent}.ai-chat-messages::-webkit-scrollbar-thumb{background:var(--border-color);border-radius:3px}.ai-chat-messages::-webkit-scrollbar-thumb:hover{background:var(--input-border)}.ai-chat-message{display:flex;flex-direction:column;gap:4px}.ai-chat-message.user{align-items:flex-end}.ai-chat-message.assistant{align-items:flex-start}.ai-chat-message.system{align-items:center}.ai-chat-message.tool{align-items:flex-start}.ai-chat-message-content{word-wrap:break-word;border:var(--bubble-border-width) solid var(--bubble-border-color);border-radius:var(--bubble-border-radius);font-size:15px;line-height:1.6;max-width:80%;opacity:var(--bubble-opacity);padding:12px 16px}.ai-chat-message.user .ai-chat-message-content{background-color:var(--bubble-user-color);border-bottom-right-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.1);color:var(--user-message-text)}.ai-chat-message.assistant .ai-chat-message-content{background-color:var(--bubble-assistant-color,#f3f4f6);border:1px solid var(--bubble-border-color,rgba(0,0,0,.08));border-radius:var(--bubble-border-radius,16px);border-bottom-left-radius:4px;box-shadow:none;color:var(--assistant-message-text);max-width:85%;padding:12px 16px}.ai-chat-message.assistant .ai-chat-message-content p{margin:0 0 12px}.ai-chat-message.assistant .ai-chat-message-content p:last-child{margin-bottom:0}.ai-chat-message.assistant .ai-chat-message-content ol,.ai-chat-message.assistant .ai-chat-message-content ul{margin:8px 0 12px;padding-left:24px}.ai-chat-message.assistant .ai-chat-message-content li{line-height:1.5;margin:6px 0}.ai-chat-message.assistant .ai-chat-message-content li::marker{color:var(--primary-color,#07f)}.ai-chat-message.assistant .ai-chat-message-content ol li::marker{font-weight:600}.ai-chat-message.assistant .ai-chat-message-content strong{font-weight:600}.ai-chat-message.assistant .ai-chat-message-content em{font-style:italic}.ai-chat-message.assistant .ai-chat-message-content code{background-color:rgba(0,0,0,.06);border-radius:4px;font-family:SF Mono,Consolas,Monaco,monospace;font-size:.9em;padding:2px 6px}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content code{background-color:hsla(0,0%,100%,.1)}.ai-chat-message.assistant .ai-chat-message-content pre{background-color:rgba(0,0,0,.06);border-radius:8px;margin:8px 0 12px;overflow-x:auto;padding:12px}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content pre{background-color:hsla(0,0%,100%,.08)}.ai-chat-message.assistant .ai-chat-message-content pre code{background-color:transparent;border-radius:0;padding:0}.ai-chat-message.assistant .ai-chat-message-content blockquote{border-left:3px solid var(--primary-color,#07f);color:var(--text-muted,#6b7280);margin:8px 0 12px;padding:4px 0 4px 12px}.ai-chat-message.assistant .ai-chat-message-content a{color:var(--primary-color,#07f);text-decoration:underline}.ai-chat-message.assistant .ai-chat-message-content a:hover{opacity:.8}.ai-chat-message.assistant .ai-chat-message-content h1,.ai-chat-message.assistant .ai-chat-message-content h2,.ai-chat-message.assistant .ai-chat-message-content h3,.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{font-weight:600;line-height:1.3;margin:16px 0 8px}.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{margin-top:0}.ai-chat-message.assistant .ai-chat-message-content hr{border:none;border-top:1px solid var(--border-color,#e5e7eb);margin:12px 0}.ai-chat-message.system .ai-chat-message-content{background-color:#fef3c7;border-radius:8px;color:#92400e;font-size:12px;font-style:italic;max-width:90%;text-align:center}.ai-chat-message.tool .ai-chat-message-content{background-color:#dbeafe;border-bottom-left-radius:4px;color:#1e40af;font-family:Courier New,monospace;font-size:13px}.ai-chat-tool-indicators{display:flex;gap:6px;margin-top:6px}.tool-indicator{align-items:center;background:#dbeafe;border-radius:50%;color:#1e40af;display:inline-flex;height:18px;justify-content:center;overflow:hidden;position:relative;width:18px}.tool-indicator .icon{font-size:12px;line-height:1;z-index:1}.tool-indicator.started:after{animation:ai-spin 1s linear infinite;border:2px solid rgba(30,64,175,.25);border-radius:50%;border-top-color:#1e40af;content:\"\";inset:0;position:absolute}@keyframes ai-spin{to{transform:rotate(1turn)}}.ai-chat-tool-message{align-items:center;background:rgba(16,185,129,.1);border:1px solid rgba(16,185,129,.2);border-radius:20px;color:#059669;display:inline-flex;gap:8px;padding:8px 14px}.ai-chat-widget.dark .ai-chat-tool-message{background:rgba(16,185,129,.15);border-color:rgba(16,185,129,.25);color:#34d399}.tool-finished{align-items:center;display:inline-flex;font-size:14px;justify-content:center}.tool-finished .tool-icon{display:none}.tool-finished .tool-check{font-size:14px;font-weight:700}.tool-name{font-size:13px;font-weight:500}.ai-chat-message-timestamp{color:rgba(0,0,0,.6);filter:invert(1) grayscale(1) contrast(1.2);mix-blend-mode:difference;padding:0 4px}.ai-chat-welcome{align-items:center;color:var(--welcome-color);display:flex;flex-direction:column;justify-content:center;min-height:200px;opacity:var(--welcome-opacity);padding:60px 32px 40px;text-align:center}.ai-chat-welcome-title{color:var(--primary-color);font-size:28px;font-weight:700;letter-spacing:-.03em;margin-bottom:12px}.ai-chat-welcome-text{color:var(--assistant-message-text);font-size:16px;line-height:1.6;max-width:280px;opacity:.7}.ai-chat-typing{align-items:center;background-color:var(--assistant-message-bg);border-radius:12px;border-bottom-left-radius:4px;display:flex;gap:4px;max-width:80px;padding:10px 14px}.ai-chat-typing-dot{animation:typingBounce 1.4s infinite;background-color:#9ca3af;border-radius:50%;height:8px;width:8px}.ai-chat-typing-dot:nth-child(2){animation-delay:.2s}.ai-chat-typing-dot:nth-child(3){animation-delay:.4s}@keyframes typingBounce{0%,60%,to{transform:translateY(0)}30%{transform:translateY(-8px)}}.ai-chat-file-button{align-items:center;background:none;border:none;border-radius:6px;color:var(--text-color);cursor:pointer;display:flex;justify-content:center;padding:8px;transition:background-color .2s}.ai-chat-file-button:hover:not(:disabled){background-color:rgba(0,0,0,.05)}.ai-chat-file-button:disabled{cursor:not-allowed;opacity:.5}.ai-chat-file-list{display:flex;flex-wrap:wrap;gap:8px;padding:8px 12px}.ai-chat-file-item{align-items:center;background-color:rgba(0,0,0,.05);border-radius:6px;display:flex;font-size:12px;gap:8px;padding:6px 10px}.ai-chat-file-extension{background-color:var(--primary-color);border-radius:3px;color:#fff;display:inline-block;font-size:10px;font-weight:600;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:500;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:4px;transition:opacity .15s ease}.ai-chat-file-remove:hover{opacity:1}.ai-chat-message-attachments{display:flex;flex-wrap:wrap;gap:6px;margin-top:6px}.ai-chat-message-attachment{align-items:center;background-color:rgba(0,0,0,.08);border-radius:4px;display:inline-flex;font-size:11px;gap:4px;padding:3px 8px}.ai-chat-attachment-icon{font-size:12px}.ai-chat-attachment-ext{background-color:var(--primary-color);border-radius:2px;color:#fff;display:inline-block;font-size:9px;font-weight:600;padding:1px 4px;text-transform:uppercase}.ai-chat-attachment-name{max-width:120px;opacity:.8;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-sources{background-color:rgba(0,0,0,.02);border-radius:6px;font-size:12px;margin-top:8px;overflow:hidden}.ai-chat-sources-toggle{align-items:center;background:none;border:none;cursor:pointer;display:flex;gap:6px;padding:8px 10px;text-align:left;transition:background-color .2s;width:100%}.ai-chat-sources-toggle:hover{background-color:rgba(0,0,0,.03)}.ai-chat-sources-icon{color:var(--text-muted);font-size:10px;transition:transform .2s}.ai-chat-sources-title{color:var(--text-color);flex:1;font-size:11px;font-weight:600;letter-spacing:.5px;text-transform:uppercase}.ai-chat-source-item{border-top:1px solid rgba(0,0,0,.05);color:#6b7280;display:flex;gap:8px;padding:8px 10px}.ai-chat-source-item:last-child{border-bottom:none}.ai-chat-source-number{color:var(--primary-color);flex-shrink:0;font-weight:600}.ai-chat-source-details{display:flex;flex:1;flex-direction:column;gap:4px}.ai-chat-source-score{color:#9ca3af;font-size:11px}.ai-chat-source-content{color:#6b7280;font-size:11px;font-style:italic;line-height:1.4}.ai-chat-source-metadata{display:flex;flex-wrap:wrap;gap:6px;margin-top:2px}.ai-chat-source-meta-item{background-color:rgba(0,0,0,.05);border-radius:3px;color:#6b7280;font-size:10px;padding:2px 6px}.ai-chat-message-meta{align-items:center;display:inline-flex;gap:6px;height:20px}.ai-chat-message-timestamp{color:#71717a;font-size:11px;line-height:1}.ai-chat-feedback{gap:0}.ai-chat-feedback,.ai-chat-feedback-button{align-items:center;display:inline-flex;height:20px}.ai-chat-feedback-button{background:none!important;border:none;border-radius:0;color:#71717a;cursor:pointer;justify-content:center;padding:0 4px;transition:color .15s ease}.ai-chat-feedback-button:hover:not(:disabled){background:none!important;color:#52525b}.ai-chat-feedback-button:active:not(:disabled){opacity:.7}.ai-chat-feedback-button:disabled{cursor:not-allowed;opacity:.4}.ai-chat-feedback-button.active{background:none!important;color:var(--primary-color,#07f)}.ai-chat-feedback-submitted{align-items:center;animation:feedbackMorph .3s cubic-bezier(.34,1.56,.64,1);display:flex;gap:6px}.ai-chat-feedback-checkmark{animation:checkmarkPop .3s cubic-bezier(.34,1.56,.64,1);color:#10b981;font-size:16px;font-weight:700}.ai-chat-feedback-text{animation:textSlideIn .3s ease;color:#10b981;font-size:13px;font-weight:500}@keyframes feedbackMorph{0%{opacity:.5;transform:scale(.8)}to{opacity:1;transform:scale(1)}}@keyframes checkmarkPop{0%{opacity:0;transform:scale(0) rotate(-45deg)}50%{transform:scale(1.3) rotate(0deg)}to{opacity:1;transform:scale(1) rotate(0deg)}}@keyframes textSlideIn{0%{opacity:0;transform:translateX(-10px)}to{opacity:1;transform:translateX(0)}}.ai-chat-error{align-items:flex-start;background-color:rgba(239,68,68,.1);border:1px solid rgba(239,68,68,.2);border-radius:12px;color:#ef4444;display:flex;font-size:14px;font-weight:500;gap:10px;line-height:1.5;margin:8px 16px;padding:12px 16px}.ai-chat-widget.dark .ai-chat-error{background-color:rgba(239,68,68,.15);border-color:rgba(239,68,68,.25);color:#fca5a5}.ai-chat-error:before{align-items:center;background:rgba(239,68,68,.2);border-radius:50%;content:\"⚠\";display:flex;flex-shrink:0;font-size:14px;font-weight:700;height:20px;justify-content:center;width:20px}.ai-chat-widget.dark .ai-chat-error:before{background:rgba(239,68,68,.25)}.ai-chat-warning{background-color:rgba(245,158,11,.1);border:1px solid rgba(245,158,11,.2);border-radius:12px;color:#d97706;font-size:13px;margin:8px 16px;padding:12px 16px}.ai-chat-widget.dark .ai-chat-warning{background-color:rgba(245,158,11,.15);border-color:rgba(245,158,11,.25);color:#fbbf24}.ai-chat-suggested-questions{bottom:80px;left:0;padding:0 20px 16px;position:absolute;right:0;z-index:5}.ai-chat-suggested-questions-list{display:flex;flex-direction:column;gap:8px}.ai-chat-suggested-question{align-items:center;background:#fff;border:1px solid rgba(0,0,0,.08);border-radius:14px;box-shadow:0 1px 3px rgba(0,0,0,.04);color:#374151;cursor:pointer;display:flex;font-size:14px;font-weight:500;gap:12px;justify-content:space-between;padding:14px 16px;text-align:left;transition:all .15s ease;width:100%}.ai-chat-suggested-question:hover{background:#f9fafb;border-color:rgba(0,0,0,.12);box-shadow:0 2px 8px rgba(0,0,0,.06)}.ai-chat-suggested-question:active{transform:scale(.98)}.ai-chat-suggested-question-text{flex:1;line-height:1.4}.ai-chat-suggested-question-icon{color:var(--primary-color,#07f);flex-shrink:0;opacity:.7;transition:transform .15s ease,opacity .15s ease}.ai-chat-suggested-question:hover .ai-chat-suggested-question-icon{opacity:1;transform:translateX(3px)}@media (max-width:480px){.ai-chat-window{border-radius:0!important;bottom:0!important;height:100%!important;left:0!important;position:fixed!important;right:0!important;top:0!important;width:100%!important}.ai-chat-widget-container{bottom:20px!important;right:20px!important}.ai-chat-suggested-question{font-size:13px;padding:9px 10px}}.ai-chat-action-approval{background:linear-gradient(135deg,#07f,#001d3d);border-radius:16px;box-shadow:0 4px 12px rgba(0,119,255,.3);color:#fff;margin:16px;padding:16px}.ai-chat-action-approval-content{align-items:flex-start;display:flex;gap:12px;margin-bottom:16px}.ai-chat-action-approval-icon{align-items:center;background:hsla(0,0%,100%,.2);border-radius:8px;display:flex;flex-shrink:0;height:40px;justify-content:center;width:40px}.ai-chat-action-approval-text{flex:1}.ai-chat-action-approval-title{font-size:15px;font-weight:600;margin-bottom:4px}.ai-chat-action-approval-description{font-size:13px;line-height:1.4;opacity:.95}.ai-chat-action-approval-buttons{display:flex;gap:8px;justify-content:flex-end}.ai-chat-action-button{align-items:center;border:none;border-radius:8px;cursor:pointer;display:flex;font-family:inherit;font-size:14px;font-weight:500;gap:6px;padding:8px 16px;transition:all .2s ease}.ai-chat-action-button:disabled{cursor:not-allowed;opacity:.6}.ai-chat-action-button-reject{background:hsla(0,0%,100%,.2);color:#fff}.ai-chat-action-button-reject:hover:not(:disabled){background:hsla(0,0%,100%,.3)}.ai-chat-action-button-approve{background:#fff;color:#07f}.ai-chat-action-button-approve:hover:not(:disabled){background:#f0f0f0;box-shadow:0 2px 8px rgba(0,0,0,.15);transform:translateY(-1px)}.ai-chat-action-spinner{animation:ai-chat-spin .6s linear infinite;border:2px solid rgba(0,119,255,.3);border-radius:50%;border-top-color:#07f;display:inline-block;height:14px;width:14px}@keyframes ai-chat-spin{to{transform:rotate(1turn)}}.ai-chat-header-actions{align-items:center;display:flex;gap:4px}.ai-chat-header-button{align-items:center;background:transparent;border:none;border-radius:8px;color:var(--header-text-color,#fff);cursor:pointer;display:flex;height:32px;justify-content:center;opacity:.8;transition:background-color .15s ease;width:32px}.ai-chat-header-button:hover{background:hsla(0,0%,100%,.15);opacity:1}.ai-chat-header-button svg{height:18px;width:18px}.ai-chat-history-panel{background:var(--chat-background,#fff);display:flex;flex:1;flex-direction:column;overflow:hidden}.ai-chat-history-empty,.ai-chat-history-loading{align-items:center;color:var(--text-color,#6b7280);display:flex;flex:1;font-size:14px;justify-content:center;padding:24px;text-align:center}.ai-chat-history-list{flex:1;overflow-y:auto;padding:8px}.ai-chat-history-item{align-items:stretch;background:transparent;border:none;border-bottom:1px solid var(--border-color,rgba(0,0,0,.06));border-radius:0;cursor:pointer;display:flex;flex-direction:column;padding:12px 16px;text-align:left;transition:background-color .12s ease;width:100%}.ai-chat-history-item:last-child{border-bottom:none}.ai-chat-history-item:hover{background:rgba(0,0,0,.03)}.ai-chat-widget.dark .ai-chat-history-item:hover{background:hsla(0,0%,100%,.05)}.ai-chat-history-item.active{background:rgba(0,0,0,.05)}.ai-chat-widget.dark .ai-chat-history-item.active{background:hsla(0,0%,100%,.08)}.ai-chat-history-item.active .ai-chat-history-item-meta{opacity:.8}.ai-chat-history-item-preview{color:var(--text-color,#1f2937);font-size:14px;font-weight:400;line-height:1.4;margin-bottom:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-history-item.active .ai-chat-history-item-preview{font-weight:500}.ai-chat-history-item-meta{color:var(--text-color,#9ca3af);display:flex;font-size:11px;gap:8px;opacity:.8}.ai-chat-history-list::-webkit-scrollbar{width:6px}.ai-chat-history-list::-webkit-scrollbar-track{background:transparent}.ai-chat-history-list::-webkit-scrollbar-thumb{background:var(--border-color,#e5e7eb);border-radius:3px}.ai-chat-history-list::-webkit-scrollbar-thumb:hover{background:var(--input-border,#d1d5db)}";
22281
- styleInject(css_248z$1);
22282
-
22283
- var css_248z = ".ai-chat-widget{--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.2s;--duration-normal:0.35s;--duration-slow:0.5s}.ai-chat-button{align-items:center;background:var(--button-color,var(--primary-color,#07f));border:none;border-radius:50%;box-shadow:0 2px 8px rgba(0,0,0,.15);cursor:pointer;display:flex;height:48px;justify-content:center;overflow:hidden;position:relative;transition:opacity .15s ease;width:48px}.ai-chat-button:hover{opacity:.9}.ai-chat-button:active{opacity:.8}.ai-chat-button-svg{height:20px;transition:transform .15s ease;width:20px}.ai-chat-button.is-open .ai-chat-button-svg{transform:rotate(0deg)}.ai-chat-window{animation:windowOpen var(--duration-slow) var(--spring-bounce);background:#fff;border:1px solid #e5e7eb;border-radius:16px;box-shadow:0 4px 24px rgba(0,0,0,.12),0 1px 3px rgba(0,0,0,.08);display:flex;flex-direction:column;overflow:hidden;position:absolute;transform-origin:bottom right}.ai-chat-widget.dark .ai-chat-window{background:#18181b;border-color:#27272a}@keyframes windowOpen{0%{opacity:0;transform:scale(.9) translateY(20px)}to{opacity:1;transform:scale(1) translateY(0)}}.ai-chat-window.closing{animation:windowClose var(--duration-normal) var(--spring-smooth) forwards}@keyframes windowClose{0%{opacity:1;transform:scale(1) translateY(0)}to{opacity:0;transform:scale(.9) translateY(20px)}}.ai-chat-header{align-items:center;background:#fff;border-bottom:1px solid #e5e7eb;display:flex;justify-content:space-between;padding:16px 20px;position:relative;z-index:10}.ai-chat-widget.dark .ai-chat-header{background:#18181b;border-bottom-color:#27272a}.ai-chat-header-content{align-items:center;display:flex;flex:1;gap:12px}.ai-chat-logo{border-radius:10px;height:36px;object-fit:cover;width:36px}.ai-chat-title{color:#18181b;font-size:15px;font-weight:600;letter-spacing:-.01em}.ai-chat-widget.dark .ai-chat-title{color:#fafafa}.ai-chat-close-button{align-items:center;background:transparent;border:none;border-radius:8px;color:#a1a1aa;cursor:pointer;display:flex;height:32px;justify-content:center;padding:0;transition:all .15s ease;width:32px}.ai-chat-widget.dark .ai-chat-close-button{color:#71717a}.ai-chat-close-button:hover{background:#f4f4f5;color:#52525b}.ai-chat-widget.dark .ai-chat-close-button:hover{background:#27272a;color:#a1a1aa}.ai-chat-close-button:active{transform:scale(.95)}.ai-chat-messages{-webkit-overflow-scrolling:touch;background:#f4f4f5;display:flex;flex:1;flex-direction:column;gap:12px;overflow-x:hidden;overflow-y:auto;padding:16px 16px 90px;position:relative;scroll-behavior:smooth}.ai-chat-widget.dark .ai-chat-messages{background:#18181b}.ai-chat-messages::-webkit-scrollbar{width:4px}.ai-chat-messages::-webkit-scrollbar-track{background:transparent}.ai-chat-messages::-webkit-scrollbar-thumb{background:rgba(0,0,0,.15);border-radius:4px}.ai-chat-messages::-webkit-scrollbar-thumb:hover{background:rgba(0,0,0,.25)}.ai-chat-message{animation:messageSlideIn var(--duration-normal) var(--spring-bounce);display:flex;flex-direction:column;gap:6px}@keyframes messageSlideIn{0%{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}.ai-chat-message-content{word-wrap:break-word;border-radius:12px;font-size:14px;line-height:1.5;max-width:85%;padding:8px 14px}.ai-chat-message.user .ai-chat-message-content{background:var(--bubble-user-color,var(--primary-color,#07f));border-bottom-right-radius:4px;color:#fff;margin-left:auto}.ai-chat-message.assistant .ai-chat-message-content{background:#fff;border:1px solid #e5e7eb;border-bottom-left-radius:4px;color:#374151}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content{background:#18181b;border-color:#27272a;color:#e4e4e7}.ai-chat-typing{align-items:center;animation:messageSlideIn var(--duration-normal) var(--spring-bounce);background:#fff;border:1px solid #e5e7eb;border-radius:12px;border-bottom-left-radius:4px;display:flex;gap:4px;max-width:64px;padding:12px 16px}.ai-chat-widget.dark .ai-chat-typing{background:#18181b;border-color:#27272a}.ai-chat-typing-dot{animation:typingPulse 1.4s ease-in-out infinite;background:linear-gradient(135deg,var(--primary-color) 0,color-mix(in srgb,var(--primary-color) 70%,#000) 100%);border-radius:50%;height:8px;width:8px}.ai-chat-typing-dot:nth-child(2){animation-delay:.15s}.ai-chat-typing-dot:nth-child(3){animation-delay:.3s}@keyframes typingPulse{0%,60%,to{opacity:.4;transform:translateY(0) scale(1)}30%{opacity:1;transform:translateY(-6px) scale(1.1)}}.ai-chat-input-container{background:transparent;bottom:0;left:0;padding:0 16px 16px;position:absolute;right:0;z-index:10}.ai-chat-input-container:before{background:linear-gradient(0deg,#f4f4f5 80%,transparent);bottom:0;content:\"\";height:48px;left:0;pointer-events:none;position:absolute;right:0;z-index:-1}.ai-chat-widget.dark .ai-chat-input-container:before{background:linear-gradient(0deg,#18181b 80%,transparent)}.ai-chat-input-wrapper{align-items:center;background:#f4f4f5;border:1px solid #e5e7eb;border-radius:9999px;display:flex;gap:0;padding:4px 4px 4px 16px;position:relative;transition:all .15s ease;z-index:5}.ai-chat-widget.dark .ai-chat-input-wrapper{background:#27272a;border-color:#3f3f46}.ai-chat-input-wrapper:focus-within{border-color:var(--primary-color);box-shadow:0 0 0 2px rgba(var(--primary-color-rgb,0,119,255),.15)}.ai-chat-input{background:transparent;border:none;color:var(--text-color);flex:1;font-family:inherit;font-size:14px;line-height:1.4;max-height:100px;min-height:20px;outline:none;padding:8px 0;resize:none}.ai-chat-input::placeholder{color:rgba(0,0,0,.35)}.ai-chat-widget.dark .ai-chat-input::placeholder{color:hsla(0,0%,100%,.35)}.ai-chat-send-button{align-items:center;background:transparent;border:none;border-radius:8px;color:#a1a1aa;cursor:pointer;display:flex;flex-shrink:0;height:36px;justify-content:center;padding:0;transition:all .15s ease;width:36px}.ai-chat-widget.dark .ai-chat-send-button{color:#71717a}.ai-chat-send-button.active{background:var(--primary-color,#07f);color:#fff}.ai-chat-send-button.active:hover:not(:disabled){opacity:.9}.ai-chat-send-button:active:not(:disabled){transform:scale(.95)}.ai-chat-send-button:disabled{cursor:not-allowed;opacity:.4}.ai-chat-tool-message{align-items:center;animation:toolPulse 2s ease-in-out infinite;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);background:linear-gradient(135deg,rgba(16,185,129,.15),rgba(16,185,129,.08));border:1px solid rgba(16,185,129,.2);border-radius:16px;display:inline-flex;gap:10px;padding:10px 16px}@keyframes toolPulse{0%,to{box-shadow:0 0 0 0 rgba(16,185,129,.2)}50%{box-shadow:0 0 0 8px rgba(16,185,129,0)}}.tool-finished{align-items:center;animation:toolComplete .5s var(--spring-bounce);background:linear-gradient(135deg,#10b981,#059669);border-radius:50%;color:#fff;display:inline-flex;height:28px;justify-content:center;position:relative;width:28px}@keyframes toolComplete{0%{transform:scale(0) rotate(-180deg)}to{transform:scale(1) rotate(0deg)}}.tool-indicator{align-items:center;background:linear-gradient(135deg,rgba(59,130,246,.2),rgba(59,130,246,.1));border-radius:50%;color:#3b82f6;display:inline-flex;height:24px;justify-content:center;position:relative;width:24px}.tool-indicator.started:after{animation:toolSpin .8s linear infinite;border:2px solid transparent;border-radius:50%;border-top-color:#3b82f6;content:\"\";inset:-2px;position:absolute}@keyframes toolSpin{to{transform:rotate(1turn)}}.ai-chat-welcome{align-items:center;animation:welcomeFadeIn var(--duration-slow) var(--spring-smooth);display:flex;flex-direction:column;justify-content:center;min-height:200px;padding:60px 32px 40px;text-align:center}@keyframes welcomeFadeIn{0%{opacity:0;transform:translateY(16px)}to{opacity:1;transform:translateY(0)}}.ai-chat-welcome-title{color:var(--primary-color);font-size:28px;font-weight:700;letter-spacing:-.03em;margin-bottom:12px}.ai-chat-welcome-text{color:var(--text-color);font-size:16px;line-height:1.6;max-width:280px;opacity:.6}.ai-chat-suggested-questions{bottom:76px;left:0;padding:0 16px 12px;position:absolute;right:0;z-index:5}.ai-chat-suggested-questions-list{display:flex;flex-direction:column;gap:6px}.ai-chat-suggested-question{align-items:center;background:#fff;border:1px solid #e5e7eb;border-radius:10px;color:#374151;cursor:pointer;display:flex;font-size:13px;font-weight:500;gap:10px;justify-content:space-between;padding:10px 14px;text-align:left;transition:all .15s ease;width:100%}.ai-chat-widget.dark .ai-chat-suggested-question{background:#18181b;border-color:#27272a;color:#e4e4e7}.ai-chat-suggested-question:hover{background:#f4f4f5;border-color:#d4d4d8}.ai-chat-widget.dark .ai-chat-suggested-question:hover{background:#27272a;border-color:#3f3f46}.ai-chat-suggested-question:active{transform:scale(.98)}.ai-chat-suggested-question-text{flex:1;line-height:1.4}.ai-chat-suggested-question-icon{color:var(--primary-color,#07f);flex-shrink:0;opacity:.7;transition:transform .15s ease,opacity .15s ease}.ai-chat-suggested-question:hover .ai-chat-suggested-question-icon{opacity:1;transform:translateX(3px)}.ai-chat-feedback-button{align-items:center;background:rgba(0,0,0,.04);border:none;border-radius:8px;cursor:pointer;display:flex;font-size:16px;gap:4px;padding:6px 10px;transition:all var(--duration-fast) var(--spring-bounce)}.ai-chat-feedback-button:hover:not(:disabled){background:rgba(0,0,0,.08);transform:scale(1.15)}.ai-chat-feedback-button:active:not(:disabled){transform:scale(.9)}.ai-chat-feedback-button.active{background:rgba(var(--primary-color-rgb,0,119,255),.15)}@media (max-width:480px){.ai-chat-window{animation:mobileSlideUp var(--duration-normal) var(--spring-smooth);border-radius:0!important;bottom:0!important;height:100%!important;left:0!important;position:fixed!important;right:0!important;top:0!important;width:100%!important}@keyframes mobileSlideUp{0%{transform:translateY(100%)}to{transform:translateY(0)}}.ai-chat-header{padding-top:max(16px,env(safe-area-inset-top))}.ai-chat-input-container{padding-bottom:max(20px,env(safe-area-inset-bottom))}}";
22392
+ var css_248z = ".ai-chat-widget{--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:14px;--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{--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{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}.ai-chat-widget-container{font-size:var(--text-sm);line-height:1.5;position:fixed;z-index:9999}.ai-chat-widget-container.bottom-right{bottom:20px;right:20px}.ai-chat-widget-container.bottom-left{bottom:20px;left:20px}.ai-chat-widget-container.top-right{right:20px;top:20px}.ai-chat-widget-container.top-left{left:20px;top:20px}@keyframes windowOpen{0%{opacity:0;transform:scale(.9) translateY(20px)}to{opacity:1;transform:scale(1) translateY(0)}}@keyframes windowClose{0%{opacity:1;transform:scale(1) translateY(0)}to{opacity:0;transform:scale(.9) translateY(20px)}}@keyframes messageSlideIn{0%{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}@keyframes welcomeFadeIn{0%{opacity:0;transform:translateY(16px)}to{opacity:1;transform:translateY(0)}}@keyframes typingPulse{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 feedbackMorph{0%{opacity:.5;transform:scale(.8)}to{opacity:1;transform:scale(1)}}@keyframes checkmarkPop{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)}}@media (max-width:480px){.ai-chat-window{animation:mobileSlideUp var(--duration-normal) var(--spring-smooth);border-radius:0!important;bottom:0!important;height:100%!important;left:0!important;position:fixed!important;right:0!important;top:0!important;width:100%!important}@keyframes mobileSlideUp{0%{transform:translateY(100%)}to{transform:translateY(0)}}.ai-chat-header{padding-top:max(16px,env(safe-area-inset-top))}.ai-chat-input-container{padding-bottom:max(20px,env(safe-area-inset-bottom))}}.ai-chat-button{align-items:center;background:var(--button-color,var(--btn-primary-bg));border:1px solid var(--button-border-color,var(--button-color,var(--btn-primary-bg)));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:filter var(--duration-fast) ease,transform var(--duration-fast) ease;width:var(--button-size,56px);z-index:1}.ai-chat-button:hover{transform:scale(1.02)}.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-window{animation:windowOpen var(--duration-slow,.35s) var(--spring-bounce,cubic-bezier(.34,1.56,.64,1));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:windowClose var(--duration-normal) var(--spring-smooth) forwards}.ai-chat-window.size-small{height:580px;width:380px}.ai-chat-window.size-medium{height:720px;width:440px}.ai-chat-window.size-large{height:820px;width:520px}.ai-chat-widget-container.bottom-right .ai-chat-window{bottom:calc(var(--button-size, 56px) + 8px);right:0}.ai-chat-widget-container.bottom-left .ai-chat-window{bottom:calc(var(--button-size, 56px) + 8px);left:0}.ai-chat-widget-container.top-right .ai-chat-window{right:0;top:calc(var(--button-size, 56px) + 8px)}.ai-chat-widget-container.top-left .ai-chat-window{left:0;top:calc(var(--button-size, 56px) + 8px)}.ai-chat-header{align-items:center;background:var(--bg-primary,#fff);border-bottom:1px solid var(--border-default,#d3d3d3);border-radius:var(--radius-window-top,22px) var(--radius-window-top,22px) 0 0;display:flex;justify-content:space-between;padding:18px var(--space-md,16px);position:relative;z-index:10}.ai-chat-widget.dark .ai-chat-header{background:var(--bg-primary,#282625);border-bottom-color:var(--border-default,#5d5b5b);border-bottom-width:.7px}.ai-chat-header.is-history{padding-left:var(--space-md)}.ai-chat-header.is-history .ai-chat-title{flex:1;min-width:0;overflow:hidden;padding-right:var(--space-lg);text-overflow:ellipsis;white-space:nowrap}.ai-chat-header-content{align-items:center;display:flex;flex:1;gap:var(--space-lg)}.ai-chat-header-actions{align-items:center;display:flex;gap:var(--space-sm)}.ai-chat-logo{border-radius:10px;height:36px;object-fit:cover;width:36px}.ai-chat-title{color:var(--text-primary,#3e3e3e);font-size:var(--text-xl,22px);font-weight:var(--font-weight-bold,700);letter-spacing:-.02em}.ai-chat-widget.dark .ai-chat-title{color:var(--text-primary,#fff)}.ai-chat-close-button{align-items:center;background:transparent;border:none;border-radius:var(--radius-md);color:var(--text-primary);cursor:pointer;display:flex;height:32px;justify-content:center;padding:0;transition:color var(--duration-fast) ease;width:32px}.ai-chat-close-button:hover{color:var(--text-muted)}.ai-chat-close-button:active{transform:scale(.95)}.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:all var(--duration-fast) ease;width:32px}.ai-chat-header-button:hover{background:var(--bg-secondary);color:var(--text-secondary)}.ai-chat-header-button svg{height:18px;width:18px}.ai-chat-messages{-webkit-overflow-scrolling:touch;-ms-overflow-style:none;align-items:stretch;background:var(--bg-primary,#fff);display:flex;flex:1;flex-direction:column;gap:var(--space-md,16px);justify-content:flex-start;overflow-x:hidden;overflow-y:auto;padding:var(--space-lg,24px) var(--space-md,16px) 100px;position:relative;scroll-behavior:smooth;scrollbar-width:none}.ai-chat-widget.dark .ai-chat-messages{background:var(--bg-primary,#18181b)}.ai-chat-messages::-webkit-scrollbar{display:none}.ai-chat-message{animation:messageSlideIn var(--duration-normal) var(--spring-bounce);display:flex;flex-direction:column;gap:6px}.ai-chat-message-content{word-wrap:break-word;font-size:var(--text-md);line-height:var(--line-height-relaxed);max-width:85%}.ai-chat-message.user{align-items:flex-end}.ai-chat-message.user .ai-chat-message-content{background:var(--user-bg,#f4f3f0);border:none;border-radius:var(--radius-chat-bubble,15px);box-shadow:none;color:var(--user-text,#000);padding:var(--space-sm,8px) var(--space-md,16px)}.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.user .ai-chat-message-meta{justify-content:flex-end;padding-right:var(--space-xs)}.ai-chat-message.assistant{align-items:flex-start}.ai-chat-message.assistant .ai-chat-message-content{background:var(--agent-bg,transparent);border:none;color:var(--agent-text,#18181b);padding:0}.ai-chat-widget.dark .ai-chat-message.assistant .ai-chat-message-content{color:var(--agent-text,#fafafa)}.ai-chat-message.system{align-items:center}.ai-chat-message.system .ai-chat-message-content{background:hsla(48,96%,89%,.8);border-radius:var(--radius-md);color:#92400e;font-size:var(--text-xs);font-style:italic;max-width:90%;padding:var(--space-sm) var(--space-md);text-align:center}.ai-chat-widget.dark .ai-chat-message.system .ai-chat-message-content{background:rgba(120,53,15,.5);color:#fef3c7}.ai-chat-message.tool{align-items:flex-start}.ai-chat-message.tool .ai-chat-message-content{background:rgba(219,234,254,.8);border-radius:var(--radius-chat-bubble);border-bottom-left-radius:var(--radius-xs);color:#1e40af;font-family:Courier New,monospace;font-size:var(--text-sm);padding:var(--space-sm) var(--space-md)}.ai-chat-widget.dark .ai-chat-message.tool .ai-chat-message-content{background:rgba(30,58,138,.5);color:#dbeafe}.ai-chat-message-meta{align-items:center;color:var(--text-muted);display:flex;font-size:var(--text-xs);gap:var(--space-sm);padding-left:var(--space-xs)}.ai-chat-message-timestamp{font-size:var(--text-xs);line-height:1}.ai-chat-typing{align-items:center;animation:messageSlideIn var(--duration-normal) var(--spring-bounce);background:transparent;display:flex;gap:5px;padding:0}.ai-chat-typing-dot{animation:typingPulse 1.4s ease-in-out infinite;background:var(--text-muted);border-radius:50%;height:6px;width:6px}.ai-chat-typing-dot:nth-child(2){animation-delay:.15s}.ai-chat-typing-dot:nth-child(3){animation-delay:.3s}.ai-chat-welcome{align-items:stretch;animation:welcomeFadeIn var(--duration-slow) var(--spring-smooth);display:flex;flex-direction:column;justify-content:flex-start;padding:0;text-align:left}.ai-chat-welcome-text,.ai-chat-welcome-title{align-self:flex-start}.ai-chat-welcome-title{color:var(--text-primary);font-size:var(--text-2xl);font-weight:var(--font-weight-semibold);letter-spacing:-.02em;margin-bottom:var(--space-md)}.ai-chat-welcome-text{color:var(--text-secondary);font-size:var(--text-md);line-height:var(--line-height-relaxed);max-width:100%}.ai-chat-error{align-items:flex-start;align-self:center;background:var(--bg-secondary);border:none;border-radius:var(--radius-chat-bubble);color:var(--text-primary);display:flex;font-size:var(--text-md);font-weight:var(--font-weight-normal);gap:10px;line-height:1.5;margin:0 auto;max-width:90%;padding:10px var(--space-md)}.ai-chat-error:before{align-items:center;background:rgba(239,68,68,.15);border-radius:50%;color:#ef4444;content:\"⚠\";display:flex;flex-shrink:0;font-size:var(--text-xs);font-weight:700;height:18px;justify-content:center;margin-top:2px;width:18px}.ai-chat-widget.dark .ai-chat-error:before{background:rgba(239,68,68,.2);color:#fca5a5}.ai-chat-message.assistant .ai-chat-message-content p{margin:0 0 12px}.ai-chat-message.assistant .ai-chat-message-content p:last-child{margin-bottom:0}.ai-chat-message.assistant .ai-chat-message-content ol,.ai-chat-message.assistant .ai-chat-message-content ul{margin:8px 0 12px;padding-left:24px}.ai-chat-message.assistant .ai-chat-message-content li{line-height:1.5;margin:6px 0}.ai-chat-message.assistant .ai-chat-message-content strong{font-weight:var(--font-weight-semibold)}.ai-chat-message.assistant .ai-chat-message-content em{font-style:italic}.ai-chat-message.assistant .ai-chat-message-content code{background:rgba(0,0,0,.06);border-radius:var(--radius-sm);font-family:SF Mono,Consolas,Monaco,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,.06);border-radius:var(--radius-md);margin:8px 0 12px;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%,.08)}.ai-chat-message.assistant .ai-chat-message-content pre code{background:transparent;border-radius:0;padding:0}.ai-chat-message.assistant .ai-chat-message-content blockquote{border-left:3px solid var(--btn-primary-bg);color:var(--text-muted);margin:8px 0 12px;padding:4px 0 4px 12px}.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 a:hover{opacity:.8}.ai-chat-message.assistant .ai-chat-message-content h1,.ai-chat-message.assistant .ai-chat-message-content h2,.ai-chat-message.assistant .ai-chat-message-content h3,.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{font-weight:var(--font-weight-semibold);line-height:var(--line-height-tight);margin:16px 0 8px}.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{margin-top:0}.ai-chat-message.assistant .ai-chat-message-content hr{border:none;border-top:1px solid var(--border-subtle);margin:12px 0}.ai-chat-input-container{background:linear-gradient(to bottom,transparent 0,var(--bg-primary,#fff) 50%,var(--bg-primary,#fff) 100%);bottom:0;left:0;padding-top:30px;position:absolute;right:0;z-index:10}.ai-chat-widget.dark .ai-chat-input-container{background:linear-gradient(to bottom,transparent 0,var(--bg-primary,#282625) 50%,var(--bg-primary,#282625) 100%)}.ai-chat-input-container.separate{padding:0 var(--radius-window-gutter,16px) var(--radius-window-gutter,16px);padding-top:30px}.ai-chat-input-wrapper{align-items:center;background:var(--input-bg,#f4f4f4);border:1px solid var(--input-border,#d3d3d3);border-radius:var(--radius-input,62px);display:flex;gap:0;height:52px;padding:6px 6px 6px 12px;position:relative;transition:all var(--duration-fast,.15s) ease;z-index:5}.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{background:transparent;border:none;color:var(--input-text,#000);flex:1;font-family:inherit;font-size:var(--text-md,15px);height:20px;line-height:var(--line-height-normal,1.4);max-height:20px;min-height:20px;outline:none;overflow:hidden;padding:0 var(--space-sm,8px);resize:none}.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;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;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;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-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{background:var(--primary-color,var(--button-color,var(--user-bg,#f4f3f0)));border:none;border-radius:var(--radius-preset-badge,13px);color:var(--button-icon-color,var(--user-text,#000));cursor:pointer;font-size:14px;font-weight:400;line-height:1.3;padding:8px 14px;transition:background .15s ease,opacity .15s ease;white-space:nowrap}.ai-chat-widget.dark .ai-chat-suggested-question{background:var(--primary-color,var(--button-color,var(--user-bg,#484848)));color:var(--button-icon-color,var(--user-text,#fff))}.ai-chat-suggested-question-text{white-space:nowrap}.ai-chat-suggested-question:hover{filter:brightness(.9)}.ai-chat-widget.dark .ai-chat-suggested-question:hover{filter:brightness(1.15)}.ai-chat-suggested-question:active{transform:scale(.98)}.ai-chat-suggested-question-icon{display:none}.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:feedbackMorph .3s var(--spring-bounce);display:flex;gap:6px}.ai-chat-feedback-checkmark{animation:checkmarkPop .3s var(--spring-bounce);color:#10b981;font-size:var(--text-md);font-weight:700}.ai-chat-feedback-text{color:#10b981;font-size:var(--text-sm);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-md) 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:stretch;background:var(--user-bg,#f4f4f5);border:none;border-radius:var(--radius-history-item,15px);cursor:pointer;display:flex;flex-direction:column;margin:0;padding:var(--space-sm,8px) var(--space-md,16px);text-align:left;transition:background var(--duration-fast,.15s) ease;width:100%}.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);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-tool-row{align-items:center;display:flex;gap:10px;margin:var(--space-sm) 0 6px}.ai-chat-tool-gear{align-items:center;color:var(--text-primary);display:inline-flex;height:26px;justify-content:center;width:26px}.ai-chat-tool-gear.spinning{animation:ai-chat-gear-spin .9s linear infinite}.ai-chat-tool-pills{display:flex;flex-wrap:wrap;gap:var(--space-sm)}.ai-chat-tool-pill{align-items:center;border-radius:var(--radius-pill);color:var(--button-icon-color,var(--btn-primary-text,var(--text-primary)));display:inline-flex;font-size:var(--text-sm);font-weight:var(--font-weight-medium);justify-content:center;line-height:1;padding:var(--space-sm) 14px}.ai-chat-tool-pill,.ai-chat-tool-pill.active{background:var(--primary-color,var(--button-color,var(--btn-primary-bg,var(--bg-secondary))))}.ai-chat-tool-pill.active{animation:ai-chat-tool-active 1.1s ease-in-out infinite;overflow:hidden;position:relative}.ai-chat-tool-pill.done{background:var(--primary-color,var(--button-color,var(--btn-primary-bg)));color:var(--button-icon-color,var(--btn-primary-text))}.ai-chat-tool-indicators{display:flex;gap:6px;margin-top:6px}.tool-indicator{align-items:center;background:linear-gradient(135deg,rgba(59,130,246,.2),rgba(59,130,246,.1));border-radius:50%;color:#3b82f6;display:inline-flex;height:24px;justify-content:center;position:relative;width:24px}.tool-indicator .icon{font-size:var(--text-xs);line-height:1;z-index:1}.tool-indicator.started:after{animation:ai-chat-gear-spin .8s linear infinite;border:2px solid transparent;border-radius:50%;border-top-color:#3b82f6;content:\"\";inset:-2px;position:absolute}.ai-chat-tool-message{align-items:center;background:hsla(0,0%,50%,.1);border:none;border-radius:var(--radius-pill);color:hsla(0,0%,50%,.8);display:inline-flex;font-size:12px;gap:5px;padding:4px 10px}.ai-chat-tool-message .ai-chat-tool-spinner{animation:ai-chat-tool-spin 1s linear infinite;flex-shrink:0;opacity:.6}.ai-chat-tool-message .ai-chat-tool-check{flex-shrink:0;opacity:.7}.ai-chat-tool-message .ai-chat-tool-error{color:#ef4444;flex-shrink:0;opacity:.7}.ai-chat-tool-message.error{background:rgba(239,68,68,.1);color:rgba(239,68,68,.9)}.tool-name{font-size:12px;font-weight:var(--font-weight-regular);line-height:1.2;white-space:nowrap}@keyframes ai-chat-tool-spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@keyframes ai-chat-tool-check-appear{0%{opacity:0;transform:scale(.5)}to{opacity:.7;transform:scale(1)}}.ai-chat-sources{background:rgba(0,0,0,.02);border-radius:6px;font-size:var(--text-xs);margin-top:var(--space-sm);overflow:hidden}.ai-chat-sources-toggle{align-items:center;background:none;border:none;cursor:pointer;display:flex;gap:6px;padding:var(--space-sm) 10px;text-align:left;transition:background var(--duration-fast) ease;width:100%}.ai-chat-sources-toggle:hover{background:rgba(0,0,0,.03)}.ai-chat-sources-icon{color:var(--text-muted);font-size:10px;transition:transform var(--duration-fast) ease}.ai-chat-sources-title{color:var(--text-primary);flex:1;font-size:11px;font-weight:var(--font-weight-semibold);letter-spacing:.5px;text-transform:uppercase}.ai-chat-source-item{border-top:1px solid rgba(0,0,0,.05);color:var(--text-muted);display:flex;gap:var(--space-sm);padding:var(--space-sm) 10px}.ai-chat-source-item:last-child{border-bottom:none}.ai-chat-source-number{color:var(--btn-primary-bg);flex-shrink:0;font-weight:var(--font-weight-semibold)}.ai-chat-source-details{display:flex;flex:1;flex-direction:column;gap:var(--space-xs)}.ai-chat-source-score{color:var(--text-placeholder);font-size:11px}.ai-chat-source-content{color:var(--text-muted);font-size:11px;font-style:italic;line-height:var(--line-height-normal)}.ai-chat-source-metadata{display:flex;flex-wrap:wrap;gap:6px;margin-top:2px}.ai-chat-source-meta-item{background:rgba(0,0,0,.05);border-radius:3px;color:var(--text-muted);font-size:10px;padding:2px 6px}";
22284
22393
  styleInject(css_248z);
22285
22394
 
22286
22395
  // Icon components mapping
@@ -22288,19 +22397,76 @@ const iconComponents = {
22288
22397
  FiMessageCircle: () => (jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: 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" }) })),
22289
22398
  FiChevronDown: () => (jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsx("polyline", { points: "6 9 12 15 18 9" }) })),
22290
22399
  };
22291
- const ChatWidget = ({ widgetId, apiUrl = window.location.origin, position = 'bottom-right', primaryColor, onOpen, onClose, onMessage, onError, }) => {
22400
+ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, previewMode = false, previewConfig, position = 'bottom-right', primaryColor, size, headerTitle, welcomeTitle, welcomeMessage, placeholder, theme, suggestedQuestions, customStyles, onOpen, onClose, onMessage, onError, }) => {
22292
22401
  const [isOpen, setIsOpen] = useState(false);
22293
22402
  const [autoDetectedTheme, setAutoDetectedTheme] = useState('light');
22294
22403
  const widgetRef = useRef(null);
22295
22404
  const containerRef = useRef(null);
22296
- const { messages, isLoading, isTyping, error, config, sendMessage, submitFeedback,
22297
- // Chat history (only active when persistConversation is true)
22298
- conversations, loadConversations, switchConversation, startNewConversation, conversationId, } = useChat({
22299
- widgetId,
22405
+ // Default config for preview mode
22406
+ const defaultPreviewConfig = {
22407
+ appearance: {
22408
+ primaryColor: primaryColor || '#0077FF',
22409
+ position: position || 'bottom-right',
22410
+ size: size || 'small',
22411
+ headerTitle: headerTitle || 'AI Assistant',
22412
+ welcomeTitle: welcomeTitle || 'Welcome!',
22413
+ welcomeMessage: welcomeMessage || 'Hi there! How can I help you today?',
22414
+ placeholder: placeholder || 'Ask me anything...',
22415
+ },
22416
+ settings: {
22417
+ autoOpen: false,
22418
+ persistConversation: true,
22419
+ showChatHistory: true,
22420
+ showTimestamps: true,
22421
+ showTypingIndicator: true,
22422
+ enableFileUpload: false,
22423
+ enableFeedback: true,
22424
+ showSources: false,
22425
+ sourceDisplayMode: 'none',
22426
+ },
22427
+ behavior: {
22428
+ agentic: false,
22429
+ },
22430
+ knowledgeBases: [],
22431
+ };
22432
+ // Merge preview config with defaults
22433
+ const mergedPreviewConfig = {
22434
+ ...defaultPreviewConfig,
22435
+ ...previewConfig,
22436
+ appearance: {
22437
+ ...defaultPreviewConfig.appearance,
22438
+ ...previewConfig?.appearance,
22439
+ },
22440
+ settings: {
22441
+ ...defaultPreviewConfig.settings,
22442
+ ...previewConfig?.settings,
22443
+ },
22444
+ behavior: {
22445
+ ...defaultPreviewConfig.behavior,
22446
+ ...previewConfig?.behavior,
22447
+ },
22448
+ };
22449
+ // Always call useChat hook (React rules), but use a dummy widgetId in preview mode
22450
+ // The hook will fail to load config, but we don't use its results in preview mode anyway
22451
+ const chatHook = useChat({
22452
+ widgetId: previewMode ? '__preview__' : (widgetId || '__preview__'),
22300
22453
  apiUrl,
22301
- onMessage,
22302
- onError,
22454
+ onMessage: previewMode ? undefined : onMessage,
22455
+ onError: previewMode ? undefined : onError,
22303
22456
  });
22457
+ // Extract values from hook or use preview defaults
22458
+ const messages = previewMode ? [] : chatHook.messages;
22459
+ const isLoading = previewMode ? false : chatHook.isLoading;
22460
+ const isTyping = previewMode ? false : chatHook.isTyping;
22461
+ const error = previewMode ? null : chatHook.error;
22462
+ const config = previewMode ? mergedPreviewConfig : chatHook.config;
22463
+ const sendMessage = previewMode ? (() => Promise.resolve()) : chatHook.sendMessage;
22464
+ const submitFeedback = previewMode ? (() => Promise.resolve()) : chatHook.submitFeedback;
22465
+ const conversations = previewMode ? [] : chatHook.conversations;
22466
+ const loadConversations = previewMode ? (() => { }) : chatHook.loadConversations;
22467
+ const switchConversation = previewMode ? (() => Promise.resolve()) : chatHook.switchConversation;
22468
+ const startNewConversation = previewMode ? (() => { }) : chatHook.startNewConversation;
22469
+ const conversationId = previewMode ? '' : chatHook.conversationId;
22304
22470
  // Auto-detect theme from background
22305
22471
  useEffect(() => {
22306
22472
  if (!containerRef.current)
@@ -22338,8 +22504,8 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, position = 'bot
22338
22504
  }, [config, autoDetectedTheme]);
22339
22505
  // Handle auto-open
22340
22506
  useEffect(() => {
22341
- if (config?.behavior.autoOpen) {
22342
- const delay = config.behavior.autoOpenDelay || 0;
22507
+ if (config?.settings.autoOpen) {
22508
+ const delay = config.settings.autoOpenDelay || 0;
22343
22509
  const timer = setTimeout(() => {
22344
22510
  setIsOpen(true);
22345
22511
  onOpen?.();
@@ -22361,31 +22527,33 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, position = 'bot
22361
22527
  document.addEventListener('keydown', handleEscapeKey);
22362
22528
  return () => document.removeEventListener('keydown', handleEscapeKey);
22363
22529
  }, [isOpen, onClose]);
22364
- // Determine theme - always auto-detect from background
22530
+ // Determine theme - use prop override if provided, otherwise auto-detect
22365
22531
  const appearanceConfig = config?.appearance;
22366
- const effectiveTheme = autoDetectedTheme;
22367
- // Determine position (config takes priority over prop)
22368
- const effectivePosition = config?.appearance.position || position;
22369
- // Get accent color from config or prop
22370
- const accentColor = primaryColor || appearanceConfig?.primaryColor || '#0077FF';
22532
+ const effectiveTheme = theme ?? autoDetectedTheme;
22533
+ // Determine position (prop override takes priority for live preview)
22534
+ const effectivePosition = position || config?.appearance.position || 'bottom-right';
22535
+ // Get accent color from prop or config (empty string means no accent color / vanilla mode)
22536
+ const accentColor = primaryColor ?? appearanceConfig?.primaryColor ?? '';
22537
+ // Apply prop overrides for live preview (props take priority over config)
22538
+ size || appearanceConfig?.size || 'small';
22539
+ const effectiveHeaderTitle = headerTitle ?? appearanceConfig?.headerTitle ?? '';
22540
+ const effectiveWelcomeTitle = welcomeTitle ?? appearanceConfig?.welcomeTitle ?? '';
22541
+ const effectiveWelcomeMessage = welcomeMessage ?? appearanceConfig?.welcomeMessage ?? '';
22542
+ const effectivePlaceholder = placeholder ?? appearanceConfig?.placeholder ?? '';
22371
22543
  // Generate styles using simplified theme system
22372
22544
  const simpleAppearance = {
22373
- accentColor,
22374
- size: appearanceConfig?.size || 'small',
22375
- welcomeMessage: appearanceConfig?.welcomeMessage || '',
22376
- placeholder: appearanceConfig?.placeholder || '',
22377
- headerTitle: appearanceConfig?.headerTitle || '',
22378
- };
22545
+ accentColor};
22379
22546
  // Generate theme styles from accent color
22380
22547
  const generatedStyles = generateThemeStyles(simpleAppearance, effectiveTheme);
22381
22548
  // Also apply legacy styles for backward compatibility
22382
22549
  const legacyStyles = appearanceConfig
22383
22550
  ? applyAppearanceStyles(appearanceConfig)
22384
22551
  : {};
22385
- // Merge styles (generated takes priority for new simplified system)
22386
- const customStyles = {
22552
+ // Merge styles (generated takes priority for new simplified system, then custom overrides)
22553
+ const mergedStyles = {
22387
22554
  ...legacyStyles,
22388
22555
  ...generatedStyles,
22556
+ ...customStyles,
22389
22557
  };
22390
22558
  // Debug logging for theme and styles
22391
22559
  useEffect(() => {
@@ -22410,16 +22578,19 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, position = 'bot
22410
22578
  await submitFeedback(messageId, feedback);
22411
22579
  };
22412
22580
  // Don't render until config is loaded to avoid flash of unstyled content
22413
- if (!config) {
22581
+ // In preview mode, config is always available
22582
+ if (!config && !previewMode) {
22414
22583
  console.log('[ChatWidget] Not rendering - config not loaded yet');
22415
22584
  return null;
22416
22585
  }
22417
22586
  console.log('[ChatWidget] Rendering widget', { isOpen, hasConfig: !!config });
22418
22587
  // Get button icon based on state
22419
22588
  const IconComponent = isOpen ? iconComponents.FiChevronDown : iconComponents.FiMessageCircle;
22420
- return (jsx("div", { ref: containerRef, className: `ai-chat-widget ${effectiveTheme}`, style: customStyles, children: jsxs("div", { ref: widgetRef, className: `ai-chat-widget-container ${effectivePosition}`, children: [isOpen && (jsx(ChatWindow, { messages: messages, isLoading: isLoading, isTyping: isTyping, error: error, config: config, onSendMessage: sendMessage, onClose: handleToggle, onFeedback: handleFeedback,
22589
+ return (jsx("div", { ref: containerRef, className: `ai-chat-widget ${effectiveTheme}`, style: mergedStyles, children: jsxs("div", { ref: widgetRef, className: `ai-chat-widget-container ${effectivePosition}`, children: [isOpen && (jsx(ChatWindow, { messages: messages, isLoading: isLoading, isTyping: isTyping, error: error, config: config, onSendMessage: sendMessage, onClose: handleToggle, onFeedback: handleFeedback,
22421
22590
  // Chat history props (only active when persistConversation is true)
22422
- conversations: conversations, onLoadConversations: loadConversations, onSwitchConversation: switchConversation, onStartNewConversation: startNewConversation, currentConversationId: conversationId })), jsx("button", { className: `ai-chat-button ${isOpen ? 'is-open' : ''}`, onClick: handleToggle, "aria-label": isOpen ? "Minimize chat" : "Open chat", children: jsx("div", { className: "ai-chat-button-svg", children: jsx(IconComponent, {}) }) })] }) }));
22591
+ conversations: conversations, onLoadConversations: loadConversations, onSwitchConversation: switchConversation, onStartNewConversation: startNewConversation, currentConversationId: conversationId,
22592
+ // Override props for live preview
22593
+ headerTitleOverride: effectiveHeaderTitle, welcomeTitleOverride: effectiveWelcomeTitle, welcomeMessageOverride: effectiveWelcomeMessage, placeholderOverride: effectivePlaceholder, suggestedQuestionsOverride: suggestedQuestions })), jsx("button", { className: `ai-chat-button ${isOpen ? 'is-open' : ''}`, onClick: handleToggle, "aria-label": isOpen ? "Minimize chat" : "Open chat", children: jsx("div", { className: "ai-chat-button-svg", children: jsx(IconComponent, {}) }) })] }) }));
22423
22594
  };
22424
22595
 
22425
22596
  export { ApiError, ChatWidget, useChat };