@chatwidgetai/chat-widget 0.1.1 → 0.1.3

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
@@ -67,6 +67,19 @@ async function buildApiError(response, defaultMessage) {
67
67
  class WidgetApiClient {
68
68
  constructor(config) {
69
69
  this.config = config;
70
+ this.detectedTimeZone = WidgetApiClient.detectTimeZone();
71
+ }
72
+ static detectTimeZone() {
73
+ try {
74
+ const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
75
+ return tz && tz.trim().length > 0 ? tz : "UTC";
76
+ }
77
+ catch {
78
+ return "UTC";
79
+ }
80
+ }
81
+ getTimeZone() {
82
+ return this.detectedTimeZone;
70
83
  }
71
84
  /**
72
85
  * Get widget configuration
@@ -87,7 +100,15 @@ class WidgetApiClient {
87
100
  }
88
101
  async getOrCreateConversation(conversationId) {
89
102
  const baseUrl = `${this.config.apiUrl}/api/widget/${this.config.widgetId}/conversation`;
90
- const query = conversationId ? `?conversationId=${encodeURIComponent(conversationId)}` : '';
103
+ const params = new URLSearchParams();
104
+ if (conversationId) {
105
+ params.set('conversationId', conversationId);
106
+ }
107
+ const timeZone = this.getTimeZone();
108
+ if (timeZone) {
109
+ params.set('timeZone', timeZone);
110
+ }
111
+ const query = params.toString() ? `?${params.toString()}` : '';
91
112
  const response = await fetch(`${baseUrl}${query}`, {
92
113
  method: 'GET',
93
114
  headers: {
@@ -134,6 +155,7 @@ class WidgetApiClient {
134
155
  conversationId: conversationId,
135
156
  message,
136
157
  fileIds,
158
+ timeZone: this.getTimeZone(),
137
159
  }),
138
160
  });
139
161
  if (!response.ok) {
@@ -156,6 +178,7 @@ class WidgetApiClient {
156
178
  conversationId: conversationId,
157
179
  message,
158
180
  fileIds,
181
+ timeZone: this.getTimeZone(),
159
182
  }),
160
183
  });
161
184
  if (!response.ok) {
@@ -232,11 +255,6 @@ class WidgetApiClient {
232
255
  /**
233
256
  * Generate a unique session ID
234
257
  */
235
- function generateSessionId() {
236
- const timestamp = Date.now().toString(36);
237
- const randomStr = Math.random().toString(36).substring(2, 15);
238
- return `session_${timestamp}_${randomStr}`;
239
- }
240
258
  /**
241
259
  * Generate a unique message ID
242
260
  */
@@ -291,6 +309,18 @@ function loadConversation(widgetId) {
291
309
  return null;
292
310
  }
293
311
  }
312
+ /**
313
+ * Clear conversation from localStorage
314
+ */
315
+ function clearConversation(widgetId) {
316
+ try {
317
+ const key = getStorageKey(widgetId);
318
+ localStorage.removeItem(key);
319
+ }
320
+ catch (error) {
321
+ console.error('Failed to clear conversation:', error);
322
+ }
323
+ }
294
324
  /**
295
325
  * Check if localStorage is available
296
326
  */
@@ -383,29 +413,53 @@ function useChat(options) {
383
413
  config: null,
384
414
  });
385
415
  const apiClient = useRef(new WidgetApiClient({ widgetId, apiKey, apiUrl }));
386
- // Load configuration and conversation on mount
416
+ // Load configuration on mount and hydrate with existing conversation if available
387
417
  useEffect(() => {
418
+ let isMounted = true;
419
+ console.log('[useChat] Effect running, mounting component');
388
420
  const initialize = async () => {
389
421
  try {
390
- // Load config
422
+ console.log('[useChat] Fetching config...');
391
423
  const config = await apiClient.current.getConfig();
392
- // Get or create conversation
424
+ console.log('[useChat] Config fetched successfully:', {
425
+ hasAppearance: !!config.appearance,
426
+ hasLightMode: !!config.appearance?.lightMode,
427
+ hasDarkMode: !!config.appearance?.darkMode,
428
+ });
393
429
  const persistConversation = config.behavior.persistConversation ?? true;
394
- let conversationId;
430
+ let conversationId = '';
431
+ let messages = [];
395
432
  if (persistConversation && isStorageAvailable()) {
396
433
  const stored = loadConversation(widgetId);
397
- conversationId = stored?.conversationId || stored?.sessionId; // Support old sessionId for backwards compatibility
434
+ const storedId = stored?.conversationId || stored?.sessionId;
435
+ if (storedId) {
436
+ try {
437
+ const conversation = await apiClient.current.getOrCreateConversation(storedId);
438
+ conversationId = conversation.id;
439
+ messages = conversation.messages;
440
+ }
441
+ catch (conversationError) {
442
+ console.warn('Failed to load existing conversation:', conversationError);
443
+ }
444
+ }
398
445
  }
399
- // Get conversation from backend
400
- const conversation = await apiClient.current.getOrCreateConversation(conversationId);
446
+ if (!isMounted) {
447
+ console.log('[useChat] Component unmounted, skipping state update');
448
+ return;
449
+ }
450
+ console.log('[useChat] Setting config in state');
401
451
  setState(prev => ({
402
452
  ...prev,
403
453
  config,
404
- conversationId: conversation.id,
405
- messages: conversation.messages,
454
+ conversationId,
455
+ messages,
406
456
  }));
407
457
  }
408
458
  catch (error) {
459
+ console.error('[useChat] Error fetching config:', error);
460
+ if (!isMounted) {
461
+ return;
462
+ }
409
463
  const errorInfo = deriveErrorInfo(error);
410
464
  const err = error instanceof Error ? error : new Error(errorInfo.message);
411
465
  setState(prev => ({ ...prev, error: errorInfo.message }));
@@ -413,11 +467,18 @@ function useChat(options) {
413
467
  }
414
468
  };
415
469
  initialize();
470
+ return () => {
471
+ console.log('[useChat] Effect cleanup, unmounting component');
472
+ isMounted = false;
473
+ };
416
474
  }, [widgetId, apiKey, apiUrl, onError]);
417
475
  // Save conversation when messages change
418
476
  useEffect(() => {
419
477
  const persistConversation = state.config?.behavior.persistConversation ?? true;
420
- if (persistConversation && isStorageAvailable() && state.messages.length > 0) {
478
+ if (persistConversation &&
479
+ isStorageAvailable() &&
480
+ state.messages.length > 0 &&
481
+ state.conversationId) {
421
482
  saveConversation(widgetId, state.conversationId, state.messages);
422
483
  }
423
484
  }, [widgetId, state.messages, state.conversationId, state.config?.behavior.persistConversation]);
@@ -425,13 +486,15 @@ function useChat(options) {
425
486
  * Send a message
426
487
  */
427
488
  const sendMessage = useCallback(async (content, files) => {
428
- if (!content.trim() && (!files || files.length === 0))
489
+ const trimmedContent = content.trim();
490
+ const hasFiles = !!files && files.length > 0;
491
+ if (!trimmedContent && !hasFiles)
429
492
  return;
430
493
  const userMessage = {
431
494
  id: generateMessageId(),
432
495
  message: {
433
496
  type: 'human',
434
- content: content.trim(),
497
+ content: trimmedContent,
435
498
  },
436
499
  timestamp: new Date().toISOString(),
437
500
  sources: [],
@@ -446,13 +509,37 @@ function useChat(options) {
446
509
  }));
447
510
  onMessage?.(userMessage);
448
511
  try {
512
+ let conversationId = state.conversationId;
513
+ if (!conversationId) {
514
+ const conversation = await apiClient.current.getOrCreateConversation();
515
+ conversationId = conversation.id;
516
+ setState(prev => {
517
+ const serverMessages = conversation.messages ?? [];
518
+ if (serverMessages.length === 0) {
519
+ return {
520
+ ...prev,
521
+ conversationId,
522
+ };
523
+ }
524
+ const serverIds = new Set(serverMessages.map(msg => msg.id));
525
+ const mergedMessages = [
526
+ ...serverMessages,
527
+ ...prev.messages.filter(msg => !serverIds.has(msg.id)),
528
+ ];
529
+ return {
530
+ ...prev,
531
+ conversationId,
532
+ messages: mergedMessages,
533
+ };
534
+ });
535
+ }
449
536
  // Upload files if provided
450
537
  let fileIds;
451
538
  if (files && files.length > 0) {
452
539
  fileIds = [];
453
540
  for (const file of files) {
454
541
  try {
455
- const uploadedFile = await apiClient.current.uploadFile(state.conversationId, file);
542
+ const uploadedFile = await apiClient.current.uploadFile(conversationId, file);
456
543
  fileIds.push(uploadedFile.id);
457
544
  }
458
545
  catch (uploadError) {
@@ -466,11 +553,11 @@ function useChat(options) {
466
553
  let response;
467
554
  if (useAgent) {
468
555
  // Use agent endpoint - returns ConversationMessage[]
469
- response = await apiClient.current.sendAgentMessage(state.conversationId, content.trim(), fileIds);
556
+ response = await apiClient.current.sendAgentMessage(conversationId, trimmedContent, fileIds);
470
557
  }
471
558
  else {
472
559
  // Use standard chat endpoint
473
- response = await apiClient.current.sendMessage(state.conversationId, content.trim(), fileIds);
560
+ response = await apiClient.current.sendMessage(conversationId, trimmedContent, fileIds);
474
561
  }
475
562
  // Both endpoints now return ConversationMessage[] array (FULL conversation)
476
563
  if (Array.isArray(response)) {
@@ -582,12 +669,12 @@ function useChat(options) {
582
669
  setState(prev => ({
583
670
  ...prev,
584
671
  messages: [],
585
- conversationId: generateSessionId(),
672
+ conversationId: '',
586
673
  error: null,
587
674
  }));
588
675
  const persistConversation = state.config?.behavior.persistConversation ?? true;
589
676
  if (persistConversation && isStorageAvailable()) {
590
- saveConversation(widgetId, generateSessionId(), []);
677
+ clearConversation(widgetId);
591
678
  }
592
679
  }, [widgetId, state.config?.behavior.persistConversation]);
593
680
  /**
@@ -21355,7 +21442,7 @@ const TypingIndicator = () => {
21355
21442
  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" })] }) }));
21356
21443
  };
21357
21444
 
21358
- const MessageList = ({ messages, isTyping = false, showTypingIndicator = true, showTimestamps = true, enableFeedback = true, showSources = true, sourceDisplayMode = 'with-score', welcomeMessage, onFeedback, }) => {
21445
+ const MessageList = ({ messages, isTyping = false, showTypingIndicator = true, showTimestamps = true, enableFeedback = true, showSources = true, sourceDisplayMode = 'with-score', welcomeTitle, welcomeMessage, onFeedback, }) => {
21359
21446
  const messagesEndRef = useRef(null);
21360
21447
  // Auto-scroll to bottom when new messages arrive
21361
21448
  useEffect(() => {
@@ -21375,7 +21462,7 @@ const MessageList = ({ messages, isTyping = false, showTypingIndicator = true, s
21375
21462
  }
21376
21463
  return map;
21377
21464
  }, [messages]);
21378
- return (jsxs("div", { className: "ai-chat-messages", role: "log", "aria-live": "polite", "aria-atomic": "false", children: [messages.length === 0 && welcomeMessage && (jsxs("div", { className: "ai-chat-welcome", children: [jsx("div", { className: "ai-chat-welcome-title", children: "Welcome!" }), 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 })] }));
21465
+ 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 })] }));
21379
21466
  };
21380
21467
 
21381
21468
  // Allowed file types
@@ -21401,7 +21488,7 @@ const formatFileSize = (bytes) => {
21401
21488
  return (bytes / 1024).toFixed(1) + ' KB';
21402
21489
  return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
21403
21490
  };
21404
- const MessageInput = ({ onSend, placeholder = 'Type your message...', disabled = false, enableFileUpload = false, }) => {
21491
+ const MessageInput = ({ onSend, placeholder = 'Type your message...', disabled = false, enableFileUpload = false, separateFromChat = true, }) => {
21405
21492
  const [value, setValue] = useState('');
21406
21493
  const [selectedFiles, setSelectedFiles] = useState([]);
21407
21494
  const textareaRef = useRef(null);
@@ -21459,7 +21546,8 @@ const MessageInput = ({ onSend, placeholder = 'Type your message...', disabled =
21459
21546
  textareaRef.current.style.height = `${textareaRef.current.scrollHeight}px`;
21460
21547
  }
21461
21548
  };
21462
- return (jsxs("div", { className: "ai-chat-input-container", children: [selectedFiles.length > 0 && (jsx("div", { className: "ai-chat-file-list", children: selectedFiles.map((file, index) => {
21549
+ console.log('[MessageInput] separateFromChat:', separateFromChat, 'class:', separateFromChat ? 'separate' : 'integrated');
21550
+ 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) => {
21463
21551
  const ext = getFileExtension(file.name);
21464
21552
  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: "\u00D7" })] }, index));
21465
21553
  }) })), 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: "20", height: "20", 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", onClick: handleSend, disabled: disabled || (!value.trim() && selectedFiles.length === 0), "aria-label": "Send message", children: jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsx("line", { x1: "22", y1: "2", x2: "11", y2: "13" }), jsx("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })] }) })] })] }));
@@ -21478,9 +21566,23 @@ const SuggestedQuestions = ({ questions, onQuestionClick, }) => {
21478
21566
  };
21479
21567
 
21480
21568
  const ChatWindow = ({ messages, isLoading, isTyping, error, config, onSendMessage, onClose, onFeedback, }) => {
21569
+ console.log('[ChatWindow] Rendering ChatWindow component');
21481
21570
  const appearance = config?.appearance;
21482
21571
  const behavior = config?.behavior;
21483
21572
  const size = appearance?.size || 'medium';
21573
+ console.log('[ChatWindow] Size:', size, 'Appearance:', !!appearance);
21574
+ // Determine current theme config
21575
+ const themePreference = appearance?.theme ?? 'light';
21576
+ const canUseDarkMode = appearance?.darkModeEnabled !== false;
21577
+ const prefersDark = typeof window !== 'undefined' && window.matchMedia('(prefers-color-scheme: dark)').matches;
21578
+ const isDarkMode = themePreference === 'auto'
21579
+ ? (canUseDarkMode && prefersDark)
21580
+ : themePreference === 'dark' && canUseDarkMode;
21581
+ const themeConfig = (isDarkMode ? appearance?.darkMode : appearance?.lightMode) ?? (appearance?.lightMode || appearance?.darkMode);
21582
+ const headerTitle = themeConfig?.header?.title ?? appearance?.header?.title ?? appearance?.companyName ?? 'AI Assistant';
21583
+ const welcomeTitle = themeConfig?.chat?.welcomeTitle ?? 'Welcome!';
21584
+ const welcomeMessage = themeConfig?.chat?.welcomeMessage ?? appearance?.welcomeMessage ?? '👋 Hi there! How can I assist you today?';
21585
+ const inputPlaceholder = themeConfig?.footer?.inputPlaceholder ?? appearance?.placeholder ?? 'Ask me anything...';
21484
21586
  // Track if suggested questions should be shown
21485
21587
  const [showSuggestedQuestions, setShowSuggestedQuestions] = useState(true);
21486
21588
  // Hide suggested questions after first user message
@@ -21499,9 +21601,240 @@ const ChatWindow = ({ messages, isLoading, isTyping, error, config, onSendMessag
21499
21601
  setShowSuggestedQuestions(false);
21500
21602
  onSendMessage(question);
21501
21603
  };
21502
- return (jsxs("div", { className: `ai-chat-window size-${size}`, role: "dialog", "aria-label": "Chat window", children: [jsxs("div", { className: "ai-chat-header", 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: appearance?.companyName || 'AI Assistant' })] }), jsx("button", { className: "ai-chat-close-button", onClick: onClose, "aria-label": "Close chat", children: jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }) })] }), 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 in this session"] })), isLimitReached && (jsxs("div", { className: "ai-chat-error", role: "alert", children: ["Message limit reached (", maxMessages, " messages per session). 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: appearance?.welcomeMessage, onFeedback: onFeedback }), showSuggestedQuestions && behavior?.suggestedQuestions && behavior.suggestedQuestions.length > 0 && (jsx(SuggestedQuestions, { questions: behavior.suggestedQuestions, onQuestionClick: handleQuestionClick })), jsx(MessageInput, { onSend: onSendMessage, placeholder: isLimitReached ? 'Message limit reached' : appearance?.placeholder, disabled: isLoading || isLimitReached, enableFileUpload: behavior?.enableFileUpload })] }));
21604
+ return (jsxs("div", { className: `ai-chat-window size-${size}`, role: "dialog", "aria-label": "Chat window", children: [jsxs("div", { className: "ai-chat-header", 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 })] }), jsx("button", { className: "ai-chat-close-button", onClick: onClose, "aria-label": "Close chat", children: jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }) })] }), 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 in this session"] })), isLimitReached && (jsxs("div", { className: "ai-chat-error", role: "alert", children: ["Message limit reached (", maxMessages, " messages per session). 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, welcomeTitle: welcomeTitle, welcomeMessage: welcomeMessage, onFeedback: onFeedback }), showSuggestedQuestions && 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, separateFromChat: themeConfig?.footer?.separateFromChat })] }));
21503
21605
  };
21504
21606
 
21607
+ /**
21608
+ * Convert shadow size to CSS box-shadow value
21609
+ */
21610
+ function getShadowValue(size) {
21611
+ const shadows = {
21612
+ 'none': 'none',
21613
+ 'sm': '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
21614
+ 'md': '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
21615
+ 'lg': '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
21616
+ 'xl': '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
21617
+ '2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.25)',
21618
+ };
21619
+ return shadows[size] || shadows.none;
21620
+ }
21621
+ /**
21622
+ * Apply appearance configuration as CSS custom properties
21623
+ * This allows the widget to be fully customizable via the appearance config
21624
+ *
21625
+ * @param appearance - Widget appearance configuration
21626
+ * @param theme - Current theme ('light' or 'dark')
21627
+ */
21628
+ function applyAppearanceStyles(appearance, theme = 'light') {
21629
+ const styles = {};
21630
+ // Global font family
21631
+ if (appearance.fontFamily) {
21632
+ styles.fontFamily = appearance.fontFamily;
21633
+ }
21634
+ // Select the correct theme configuration
21635
+ const themeConfig = theme === 'dark' ? appearance.darkMode : appearance.lightMode;
21636
+ // If theme config exists and has required properties, use it
21637
+ if (themeConfig && themeConfig.button) {
21638
+ // ========================================================================
21639
+ // BUTTON APPEARANCE
21640
+ // ========================================================================
21641
+ const btn = themeConfig.button;
21642
+ if (btn.color)
21643
+ styles['--button-color'] = btn.color;
21644
+ if (btn.opacity !== undefined)
21645
+ styles['--button-opacity'] = btn.opacity.toString();
21646
+ if (btn.size)
21647
+ styles['--button-size'] = `${btn.size}px`;
21648
+ if (btn.borderRadius !== undefined)
21649
+ styles['--button-border-radius'] = `${btn.borderRadius}px`;
21650
+ if (btn.borderWidth !== undefined)
21651
+ styles['--button-border-width'] = `${btn.borderWidth}px`;
21652
+ if (btn.borderColor)
21653
+ styles['--button-border-color'] = btn.borderColor;
21654
+ if (btn.borderOpacity !== undefined)
21655
+ styles['--button-border-opacity'] = btn.borderOpacity.toString();
21656
+ if (btn.backdropBlur !== undefined)
21657
+ styles['--button-backdrop-blur'] = `${btn.backdropBlur}px`;
21658
+ if (btn.shadow)
21659
+ styles['--button-shadow'] = getShadowValue(btn.shadow);
21660
+ // ========================================================================
21661
+ // CARD/WINDOW APPEARANCE
21662
+ // ========================================================================
21663
+ const card = themeConfig.card;
21664
+ if (card.backgroundColor)
21665
+ styles['--card-background'] = card.backgroundColor;
21666
+ if (card.opacity !== undefined)
21667
+ styles['--card-opacity'] = card.opacity.toString();
21668
+ if (card.borderRadius !== undefined)
21669
+ styles['--card-border-radius'] = `${card.borderRadius}px`;
21670
+ if (card.borderWidth !== undefined)
21671
+ styles['--card-border-width'] = `${card.borderWidth}px`;
21672
+ if (card.borderColor) {
21673
+ styles['--card-border-color'] = card.borderColor;
21674
+ // Create rgba border color with opacity for box-shadow
21675
+ if (card.borderOpacity !== undefined) {
21676
+ const opacity = card.borderOpacity;
21677
+ // Convert hex to rgba
21678
+ const hex = card.borderColor.replace('#', '');
21679
+ const r = parseInt(hex.substring(0, 2), 16);
21680
+ const g = parseInt(hex.substring(2, 4), 16);
21681
+ const b = parseInt(hex.substring(4, 6), 16);
21682
+ styles['--card-border-color-rgba'] = `rgba(${r}, ${g}, ${b}, ${opacity})`;
21683
+ }
21684
+ }
21685
+ if (card.borderOpacity !== undefined)
21686
+ styles['--card-border-opacity'] = card.borderOpacity.toString();
21687
+ if (card.backdropBlur !== undefined)
21688
+ styles['--card-backdrop-blur'] = `${card.backdropBlur}px`;
21689
+ if (card.shadow)
21690
+ styles['--card-shadow'] = getShadowValue(card.shadow);
21691
+ // ========================================================================
21692
+ // HEADER APPEARANCE
21693
+ // ========================================================================
21694
+ const header = themeConfig.header;
21695
+ if (header.backgroundColor)
21696
+ styles['--header-background'] = header.backgroundColor;
21697
+ if (header.opacity !== undefined)
21698
+ styles['--header-opacity'] = header.opacity.toString();
21699
+ if (header.textColor)
21700
+ styles['--header-text-color'] = header.textColor;
21701
+ if (header.borderBottomWidth !== undefined)
21702
+ styles['--header-border-bottom-width'] = `${header.borderBottomWidth}px`;
21703
+ if (header.borderBottomColor)
21704
+ styles['--header-border-bottom-color'] = header.borderBottomColor;
21705
+ if (header.borderBottomOpacity !== undefined)
21706
+ styles['--header-border-bottom-opacity'] = header.borderBottomOpacity.toString();
21707
+ // ========================================================================
21708
+ // CHAT APPEARANCE
21709
+ // ========================================================================
21710
+ const chat = themeConfig.chat;
21711
+ if (chat.backgroundColor)
21712
+ styles['--chat-background'] = chat.backgroundColor;
21713
+ if (chat.opacity !== undefined)
21714
+ styles['--chat-opacity'] = chat.opacity.toString();
21715
+ // Welcome message
21716
+ if (chat.welcomeColor)
21717
+ styles['--welcome-color'] = chat.welcomeColor;
21718
+ // Message bubbles
21719
+ if (chat.enableBubbles) {
21720
+ if (chat.bubbleUserColor)
21721
+ styles['--bubble-user-color'] = chat.bubbleUserColor;
21722
+ if (chat.bubbleUserOpacity !== undefined)
21723
+ styles['--bubble-user-opacity'] = chat.bubbleUserOpacity.toString();
21724
+ if (chat.bubbleAssistantColor)
21725
+ styles['--bubble-assistant-color'] = chat.bubbleAssistantColor;
21726
+ if (chat.bubbleAssistantOpacity !== undefined)
21727
+ styles['--bubble-assistant-opacity'] = chat.bubbleAssistantOpacity.toString();
21728
+ if (chat.bubbleBorderWidth !== undefined)
21729
+ styles['--bubble-border-width'] = `${chat.bubbleBorderWidth}px`;
21730
+ if (chat.bubbleBorderColor)
21731
+ styles['--bubble-border-color'] = chat.bubbleBorderColor;
21732
+ if (chat.bubbleBorderOpacity !== undefined)
21733
+ styles['--bubble-border-opacity'] = chat.bubbleBorderOpacity.toString();
21734
+ }
21735
+ else {
21736
+ // Plain text mode
21737
+ if (chat.textColor)
21738
+ styles['--message-text-color'] = chat.textColor;
21739
+ }
21740
+ // ========================================================================
21741
+ // FOOTER APPEARANCE
21742
+ // ========================================================================
21743
+ const footer = themeConfig.footer;
21744
+ // Only if separate from chat
21745
+ if (footer.separateFromChat) {
21746
+ if (footer.backgroundColor)
21747
+ styles['--footer-background'] = footer.backgroundColor;
21748
+ if (footer.opacity !== undefined)
21749
+ styles['--footer-opacity'] = footer.opacity.toString();
21750
+ if (footer.borderTopWidth !== undefined)
21751
+ styles['--footer-border-top-width'] = `${footer.borderTopWidth}px`;
21752
+ if (footer.borderTopColor)
21753
+ styles['--footer-border-top-color'] = footer.borderTopColor;
21754
+ if (footer.borderTopOpacity !== undefined)
21755
+ styles['--footer-border-top-opacity'] = footer.borderTopOpacity.toString();
21756
+ }
21757
+ // Backdrop blur (only when floating)
21758
+ if (!footer.separateFromChat && footer.backdropBlur !== undefined) {
21759
+ styles['--footer-backdrop-blur'] = `${footer.backdropBlur}px`;
21760
+ }
21761
+ // Input field
21762
+ if (footer.inputBackgroundColor)
21763
+ styles['--input-background'] = footer.inputBackgroundColor;
21764
+ if (footer.inputBackgroundOpacity !== undefined)
21765
+ styles['--input-background-opacity'] = footer.inputBackgroundOpacity.toString();
21766
+ if (footer.inputBorderRadius !== undefined)
21767
+ styles['--input-border-radius'] = `${footer.inputBorderRadius}px`;
21768
+ if (footer.inputBorderWidth !== undefined)
21769
+ styles['--input-border-width'] = `${footer.inputBorderWidth}px`;
21770
+ if (footer.inputBorderColor)
21771
+ styles['--input-border-color'] = footer.inputBorderColor;
21772
+ if (footer.inputBorderOpacity !== undefined)
21773
+ styles['--input-border-opacity'] = footer.inputBorderOpacity.toString();
21774
+ if (footer.inputShadow)
21775
+ styles['--input-shadow'] = getShadowValue(footer.inputShadow);
21776
+ // Send button
21777
+ if (footer.buttonBackgroundColor)
21778
+ styles['--send-button-background'] = footer.buttonBackgroundColor;
21779
+ if (footer.buttonOpacity !== undefined)
21780
+ styles['--send-button-opacity'] = footer.buttonOpacity.toString();
21781
+ if (footer.buttonBorderRadius !== undefined)
21782
+ styles['--send-button-border-radius'] = `${footer.buttonBorderRadius}px`;
21783
+ if (footer.buttonBorderWidth !== undefined)
21784
+ styles['--send-button-border-width'] = `${footer.buttonBorderWidth}px`;
21785
+ if (footer.buttonBorderColor)
21786
+ styles['--send-button-border-color'] = footer.buttonBorderColor;
21787
+ if (footer.buttonBorderOpacity !== undefined)
21788
+ styles['--send-button-border-opacity'] = footer.buttonBorderOpacity.toString();
21789
+ // ========================================================================
21790
+ // HOVER STATES
21791
+ // ========================================================================
21792
+ const hover = themeConfig.hover;
21793
+ if (hover.buttonScale !== undefined)
21794
+ styles['--hover-button-scale'] = hover.buttonScale.toString();
21795
+ if (hover.buttonOpacity !== undefined)
21796
+ styles['--hover-button-opacity'] = hover.buttonOpacity.toString();
21797
+ if (hover.inputBorderColor)
21798
+ styles['--hover-input-border-color'] = hover.inputBorderColor;
21799
+ if (hover.sendButtonOpacity !== undefined)
21800
+ styles['--hover-send-button-opacity'] = hover.sendButtonOpacity.toString();
21801
+ if (hover.closeButtonOpacity !== undefined)
21802
+ styles['--hover-close-button-opacity'] = hover.closeButtonOpacity.toString();
21803
+ // ========================================================================
21804
+ // ACTIVE STATES
21805
+ // ========================================================================
21806
+ const active = themeConfig.active;
21807
+ if (active.inputBorderColor)
21808
+ styles['--active-input-border-color'] = active.inputBorderColor;
21809
+ if (active.inputShadow)
21810
+ styles['--active-input-shadow'] = active.inputShadow;
21811
+ }
21812
+ else {
21813
+ // Fallback to legacy fields if no theme config
21814
+ if (appearance.primaryColor)
21815
+ styles['--primary-color'] = appearance.primaryColor;
21816
+ if (appearance.borderRadius !== undefined)
21817
+ styles['--border-radius'] = `${appearance.borderRadius}px`;
21818
+ // Legacy button
21819
+ if (appearance.button) {
21820
+ const btn = appearance.button;
21821
+ if (btn.color)
21822
+ styles['--button-color'] = btn.color;
21823
+ if (btn.size)
21824
+ styles['--button-size'] = `${btn.size}px`;
21825
+ if (btn.borderRadius !== undefined)
21826
+ styles['--button-border-radius'] = `${btn.borderRadius}px`;
21827
+ if (btn.borderWidth !== undefined)
21828
+ styles['--button-border-width'] = `${btn.borderWidth}px`;
21829
+ if (btn.borderColor)
21830
+ styles['--button-border-color'] = btn.borderColor;
21831
+ if (btn.opacity !== undefined)
21832
+ styles['--button-opacity'] = btn.opacity.toString();
21833
+ }
21834
+ }
21835
+ return styles;
21836
+ }
21837
+
21505
21838
  function styleInject(css, ref) {
21506
21839
  if ( ref === void 0 ) ref = {};
21507
21840
  var insertAt = ref.insertAt;
@@ -21529,11 +21862,12 @@ function styleInject(css, ref) {
21529
21862
  }
21530
21863
  }
21531
21864
 
21532
- var css_248z = ".ai-chat-widget{--primary-color:#7c3aed;--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:#1f2937;--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);-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:#1f2937;--text-color:#f9fafb;--border-color:#374151;--assistant-message-bg:#374151;--assistant-message-text:#f9fafb;--input-bg:#374151;--input-border:#4b5563}.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;background-color:var(--primary-color);border:none;border-radius:50%;box-shadow:var(--shadow-lg);color:#fff;cursor:pointer;display:flex;font-size:24px;height:60px;justify-content:center;transition:transform .2s,box-shadow .2s;width:60px}.ai-chat-button:hover{box-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 10px 10px -5px rgba(0,0,0,.04);transform:scale(1.05)}.ai-chat-button:active{transform:scale(.95)}.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{background-color:var(--background-color);border-radius:12px;box-shadow:var(--shadow-lg);display:flex;flex-direction:column;overflow:hidden;transition:opacity .2s,transform .2s}.ai-chat-window.size-small{height:400px;width:300px}.ai-chat-window.size-medium{height:600px;width:400px}.ai-chat-window.size-large{height:700px;width:500px}.ai-chat-header{align-items:center;background-color:var(--primary-color);color:#fff;display:flex;justify-content:space-between;padding:16px}.ai-chat-header-content{align-items:center;display:flex;flex:1;gap:12px}.ai-chat-logo{border-radius:50%;height:32px;object-fit:cover;width:32px}.ai-chat-title{font-size:16px;font-weight:600}.ai-chat-close-button{align-items:center;background:none;border:none;border-radius:4px;color:#fff;cursor:pointer;display:flex;justify-content:center;padding:4px;transition:background-color .2s}.ai-chat-close-button:hover{background-color:hsla(0,0%,100%,.1)}.ai-chat-messages{background-color:var(--background-color);display:flex;flex:1;flex-direction:column;gap:12px;overflow-y:auto;padding:16px}.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{animation:slideIn .2s ease-out;display:flex;flex-direction:column;gap:4px}@keyframes slideIn{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.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-radius:12px;line-height:1.5;max-width:80%;padding:10px 14px}.ai-chat-message.user .ai-chat-message-content{background-color:var(--user-message-bg);border-bottom-right-radius:4px;color:var(--user-message-text)}.ai-chat-message.assistant .ai-chat-message-content{background-color:var(--assistant-message-bg);border-bottom-left-radius:4px;color:var(--assistant-message-text)}.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{background:linear-gradient(135deg,#ecfdf5,#d1fae5);border:1px solid #a7f3d0;border-radius:9999px;box-shadow:0 1px 2px rgba(0,0,0,.04),0 1px 8px rgba(16,185,129,.08);color:#065f46;gap:10px;padding:6px 12px}.ai-chat-tool-message,.tool-finished{align-items:center;display:inline-flex}.tool-finished{background:rgba(16,185,129,.12);border-radius:50%;color:#059669;height:22px;justify-content:center;position:relative;width:22px}.tool-finished .tool-icon{font-size:14px}.tool-finished .tool-check{align-items:center;background:#10b981;border-radius:50%;bottom:-3px;box-shadow:0 1px 2px rgba(0,0,0,.12);color:#fff;display:inline-flex;font-size:10px;height:14px;justify-content:center;position:absolute;right:-3px;width:14px}.tool-name{font-size:12px;font-weight:600}.ai-chat-message-timestamp{color:#9ca3af;font-size:11px;padding:0 4px}.ai-chat-welcome{color:var(--text-color);padding:32px 16px;text-align:center}.ai-chat-welcome-title{font-size:18px;font-weight:600;margin-bottom:8px}.ai-chat-welcome-text{color:#6b7280;font-size:14px}.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-input-container{background-color:var(--background-color);border-top:1px solid var(--border-color);padding:16px}.ai-chat-input-wrapper{align-items:flex-end;display:flex;gap:8px}.ai-chat-input{background-color:var(--input-bg);border:1px solid var(--input-border);border-radius:8px;color:var(--text-color);flex:1;font-family:inherit;font-size:14px;max-height:120px;min-height:40px;outline:none;padding:10px 12px;resize:none;transition:border-color .2s}.ai-chat-input:focus{border-color:var(--primary-color)}.ai-chat-input::placeholder{color:#9ca3af}.ai-chat-send-button{align-items:center;background-color:var(--primary-color);border:none;border-radius:8px;color:#fff;cursor:pointer;display:flex;font-weight:500;height:40px;justify-content:center;min-width:40px;padding:10px 16px;transition:opacity .2s,transform .1s}.ai-chat-send-button:hover:not(:disabled){opacity:.9}.ai-chat-send-button:active:not(:disabled){transform:scale(.95)}.ai-chat-send-button:disabled{cursor:not-allowed;opacity:.5}.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{background:none;border:none;cursor:pointer;font-size:18px;line-height:1;opacity:.6;padding:0 4px;transition:opacity .2s}.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-feedback{align-items:center;display:flex;gap:8px;margin-top:8px;min-height:32px}.ai-chat-feedback-button{align-items:center;background:none;border:none;border-radius:6px;cursor:pointer;display:flex;font-size:16px;gap:4px;overflow:hidden;padding:6px 10px;position:relative;transition:all .2s ease}.ai-chat-feedback-button:hover:not(:disabled){background-color:rgba(0,0,0,.05);transform:scale(1.2)}.ai-chat-feedback-button:active:not(:disabled){transform:scale(.95)}.ai-chat-feedback-button:disabled{cursor:not-allowed;opacity:.5}.ai-chat-feedback-button.active{background-color:rgba(124,58,237,.1)}.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:#fee2e2;border-left:4px solid #dc2626;border-radius:8px;color:#991b1b;display:flex;font-size:14px;font-weight:500;gap:8px;line-height:1.5;margin:8px 16px;padding:12px 16px}.ai-chat-error:before{content:\"⚠️\";flex-shrink:0;font-size:16px}.ai-chat-warning{background-color:#fef3c7;border-radius:8px;color:#92400e;font-size:13px;margin:8px 16px;padding:12px}.ai-chat-suggested-questions{margin-bottom:8px;padding:12px 16px}.ai-chat-suggested-questions-label{color:#6b7280;font-size:12px;font-weight:500;margin-bottom:8px}.ai-chat-suggested-questions-list{display:flex;flex-direction:column;gap:8px}.ai-chat-suggested-question{align-items:center;background-color:#f9fafb;border:1px solid #e5e7eb;border-radius:8px;color:#374151;cursor:pointer;display:flex;font-size:14px;gap:8px;padding:10px 12px;text-align:left;transition:all .2s ease;width:100%}.ai-chat-suggested-question:hover{background-color:#f3f4f6;border-color:var(--ai-chat-primary-color,#6366f1);box-shadow:0 2px 4px rgba(0,0,0,.05);transform:translateY(-1px)}.ai-chat-suggested-question:active{transform:translateY(0)}.ai-chat-suggested-question-icon{flex-shrink:0;font-size:16px}.ai-chat-suggested-question-text{flex:1;line-height:1.4}@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,#667eea,#764ba2);border-radius:12px;box-shadow:0 4px 12px rgba(102,126,234,.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:#667eea}.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(102,126,234,.3);border-radius:50%;border-top-color:#667eea;display:inline-block;height:14px;width:14px}@keyframes ai-chat-spin{to{transform:rotate(1turn)}}";
21865
+ var css_248z = ".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{box-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 10px 10px -5px rgba(0,0,0,.04);opacity:var(--hover-button-opacity);transform:scale(var(--hover-button-scale))}.ai-chat-button:active{transform:scale(.95)}.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:0;right:0}.ai-chat-widget-container.bottom-left .ai-chat-window{bottom:0;left:0}.ai-chat-widget-container.top-right .ai-chat-window{right:0;top:0}.ai-chat-widget-container.top-left .ai-chat-window{left:0;top:0}.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-header{align-items:center;border-bottom:var(--header-border-bottom-width) solid var(--header-border-bottom-color);box-shadow:0 2px 8px rgba(0,0,0,.1);color:var(--header-text-color);display:flex;justify-content:space-between;padding:20px;position:relative}.ai-chat-header:before{backdrop-filter:blur(var(--header-backdrop-blur));-webkit-backdrop-filter:blur(var(--header-backdrop-blur));background-color:var(--header-background);content:\"\";inset:0;opacity:var(--header-opacity);pointer-events:none;position:absolute;z-index:0}.ai-chat-header>*{position:relative;z-index:1}.ai-chat-header-content{align-items:center;display:flex;flex:1;gap:12px}.ai-chat-logo{border-radius:50%;height:32px;object-fit:cover;width:32px}.ai-chat-title{color:var(--header-text-color);font-size:var(--header-font-size);font-weight:600;letter-spacing:-.01em}.ai-chat-close-button{align-items:center;background:none;border:none;border-radius:8px;color:var(--header-text-color);cursor:pointer;display:flex;justify-content:center;opacity:.9;padding:8px;transition:all .2s ease}.ai-chat-close-button:hover{background-color:hsla(0,0%,100%,.15);opacity:var(--hover-close-button-opacity);transform:scale(1.05)}.ai-chat-messages{background-color:var(--chat-background);display:flex;flex:1;flex-direction:column;gap:16px;overflow-x:hidden;overflow-y:auto;padding:20px;position:relative}.ai-chat-window:has(.ai-chat-input-container.integrated) .ai-chat-messages{padding-bottom:100px}.ai-chat-messages:before{backdrop-filter:blur(var(--chat-backdrop-blur));-webkit-backdrop-filter:blur(var(--chat-backdrop-blur));background-color:var(--chat-background);bottom:0;content:\"\";left:0;opacity:var(--chat-opacity);pointer-events:none;position:absolute;right:0;top:0;z-index:0}.ai-chat-messages>*{position:relative;z-index:1}.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{animation:slideIn .2s ease-out;display:flex;flex-direction:column;gap:4px}@keyframes slideIn{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.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);border-bottom-left-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.05);color:var(--assistant-message-text)}.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{background:linear-gradient(135deg,#ecfdf5,#d1fae5);border:1px solid #a7f3d0;border-radius:9999px;box-shadow:0 1px 2px rgba(0,0,0,.04),0 1px 8px rgba(16,185,129,.08);color:#065f46;gap:10px;padding:6px 12px}.ai-chat-tool-message,.tool-finished{align-items:center;display:inline-flex}.tool-finished{background:rgba(16,185,129,.12);border-radius:50%;color:#059669;height:22px;justify-content:center;position:relative;width:22px}.tool-finished .tool-icon{font-size:14px}.tool-finished .tool-check{align-items:center;background:#10b981;border-radius:50%;bottom:-3px;box-shadow:0 1px 2px rgba(0,0,0,.12);color:#fff;display:inline-flex;font-size:10px;height:14px;justify-content:center;position:absolute;right:-3px;width:14px}.tool-name{font-size:12px;font-weight:600}.ai-chat-message-timestamp{color:rgba(0,0,0,.6);filter:invert(1) grayscale(1) contrast(1.2);font-size:11px;mix-blend-mode:difference;padding:0 4px}.ai-chat-welcome{color:var(--welcome-color);opacity:var(--welcome-opacity);padding:48px 24px;text-align:center}.ai-chat-welcome-title{color:var(--welcome-color);font-size:calc(var(--welcome-font-size)*1.5);font-weight:700;letter-spacing:-.02em;margin-bottom:12px}.ai-chat-welcome-text{color:var(--welcome-color);font-size:var(--welcome-font-size);line-height:1.6}.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-input-container{padding:20px;position:relative}.ai-chat-input-container.separate{border-top:var(--footer-border-top-width) solid var(--footer-border-top-color)}.ai-chat-input-container.integrated{bottom:0;left:0;padding-bottom:calc(20px + var(--card-border-width));position:absolute;right:0;z-index:10}.ai-chat-input-container.separate:before{backdrop-filter:blur(var(--footer-backdrop-blur));-webkit-backdrop-filter:blur(var(--footer-backdrop-blur));background-color:var(--footer-background);content:\"\";inset:0;opacity:var(--footer-opacity);pointer-events:none;position:absolute;z-index:0}.ai-chat-input-container>*{position:relative;z-index:1}.ai-chat-input-wrapper{align-items:center;background-color:var(--input-background);border:var(--input-border-width) solid var(--input-border-color);border-radius:var(--input-border-radius);display:flex;gap:0;opacity:var(--input-opacity);padding:6px 6px 6px 16px;transition:all .2s ease}.ai-chat-input-wrapper:hover{border-color:var(--hover-input-border-color)}.ai-chat-input-wrapper:focus-within{border-color:var(--active-input-border-color);box-shadow:var(--active-input-shadow)}.ai-chat-input{background-color:transparent;border:none;border-radius:0;color:var(--text-color);flex:1;font-family:inherit;font-size:15px;max-height:120px;min-height:40px;outline:none;padding:10px 0;resize:none}.ai-chat-input::placeholder{color:#9ca3af}.ai-chat-send-button{align-items:center;background-color:var(--send-button-background);border:var(--send-button-border-width) solid var(--send-button-border-color);border-radius:var(--send-button-border-radius);color:#fff;cursor:pointer;display:flex;flex-shrink:0;font-weight:500;height:40px;justify-content:center;min-width:40px;opacity:var(--send-button-opacity);padding:0;transition:all .2s ease;width:40px}.ai-chat-send-button:hover:not(:disabled){opacity:var(--hover-send-button-opacity);transform:scale(1.05)}.ai-chat-send-button:active:not(:disabled){transform:scale(.98)}.ai-chat-send-button:disabled{cursor:not-allowed;opacity:.5}.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{background:none;border:none;cursor:pointer;font-size:18px;line-height:1;opacity:.6;padding:0 4px;transition:opacity .2s}.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-feedback{align-items:center;display:flex;gap:8px;margin-top:8px;min-height:32px}.ai-chat-feedback-button{align-items:center;background:none;border:none;border-radius:6px;cursor:pointer;display:flex;filter:drop-shadow(0 1px 2px rgba(0,0,0,.3));font-size:16px;gap:4px;overflow:hidden;padding:6px 10px;position:relative;transition:all .2s ease}.ai-chat-feedback-button:hover:not(:disabled){background-color:rgba(0,0,0,.05);transform:scale(1.2)}.ai-chat-feedback-button:active:not(:disabled){transform:scale(.95)}.ai-chat-feedback-button:disabled{cursor:not-allowed;opacity:.5}.ai-chat-feedback-button.active{background-color:rgba(0,119,255,.1)}.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:#fee2e2;border-left:4px solid #dc2626;border-radius:8px;color:#991b1b;display:flex;font-size:14px;font-weight:500;gap:8px;line-height:1.5;margin:8px 16px;padding:12px 16px}.ai-chat-error:before{content:\"⚠️\";flex-shrink:0;font-size:16px}.ai-chat-warning{background-color:#fef3c7;border-radius:8px;color:#92400e;font-size:13px;margin:8px 16px;padding:12px}.ai-chat-suggested-questions{margin-bottom:8px;padding:12px 16px}.ai-chat-suggested-questions-label{color:#6b7280;font-size:12px;font-weight:500;margin-bottom:8px}.ai-chat-suggested-questions-list{display:flex;flex-direction:column;gap:8px}.ai-chat-suggested-question{align-items:center;background-color:#f9fafb;border:1px solid #e5e7eb;border-radius:8px;color:#374151;cursor:pointer;display:flex;font-size:14px;gap:8px;padding:10px 12px;text-align:left;transition:all .2s ease;width:100%}.ai-chat-suggested-question:hover{background-color:#f3f4f6;border-color:var(--ai-chat-primary-color,#6366f1);box-shadow:0 2px 4px rgba(0,0,0,.05);transform:translateY(-1px)}.ai-chat-suggested-question:active{transform:translateY(0)}.ai-chat-suggested-question-icon{flex-shrink:0;font-size:16px}.ai-chat-suggested-question-text{flex:1;line-height:1.4}@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)}}";
21533
21866
  styleInject(css_248z);
21534
21867
 
21535
21868
  const ChatWidget = ({ widgetId, apiKey, apiUrl = window.location.origin, position = 'bottom-right', theme: themeOverride, primaryColor, onOpen, onClose, onMessage, onError, }) => {
21536
21869
  const [isOpen, setIsOpen] = useState(false);
21870
+ const widgetRef = useRef(null);
21537
21871
  const { messages, isLoading, isTyping, error, config, sendMessage, submitFeedback, } = useChat({
21538
21872
  widgetId,
21539
21873
  apiKey,
@@ -21541,6 +21875,21 @@ const ChatWidget = ({ widgetId, apiKey, apiUrl = window.location.origin, positio
21541
21875
  onMessage,
21542
21876
  onError,
21543
21877
  });
21878
+ // Debug logging
21879
+ useEffect(() => {
21880
+ console.log('[ChatWidget] Config loaded:', config ? 'YES' : 'NO');
21881
+ if (config) {
21882
+ console.log('[ChatWidget] Config details:', {
21883
+ theme: config.appearance?.theme,
21884
+ darkModeEnabled: config.appearance?.darkModeEnabled,
21885
+ hasLightMode: !!config.appearance?.lightMode,
21886
+ hasDarkMode: !!config.appearance?.darkMode,
21887
+ });
21888
+ }
21889
+ }, [config]);
21890
+ useEffect(() => {
21891
+ console.log('[ChatWidget] isOpen changed:', isOpen);
21892
+ }, [isOpen]);
21544
21893
  // Handle auto-open
21545
21894
  useEffect(() => {
21546
21895
  if (config?.behavior.autoOpen) {
@@ -21553,26 +21902,84 @@ const ChatWidget = ({ widgetId, apiKey, apiUrl = window.location.origin, positio
21553
21902
  }
21554
21903
  return undefined;
21555
21904
  }, [config, onOpen]);
21905
+ // Handle close on outside click
21906
+ useEffect(() => {
21907
+ if (!isOpen || !config?.appearance.closeOnOutsideClick)
21908
+ return;
21909
+ const handleClickOutside = (event) => {
21910
+ if (widgetRef.current && !widgetRef.current.contains(event.target)) {
21911
+ console.log('[ChatWidget] Closing due to outside click');
21912
+ setIsOpen(false);
21913
+ onClose?.();
21914
+ }
21915
+ };
21916
+ // Add slight delay to avoid immediate close on open
21917
+ const timer = setTimeout(() => {
21918
+ document.addEventListener('mousedown', handleClickOutside);
21919
+ }, 100);
21920
+ return () => {
21921
+ clearTimeout(timer);
21922
+ document.removeEventListener('mousedown', handleClickOutside);
21923
+ };
21924
+ }, [isOpen, config, onClose]);
21925
+ // Handle close on Escape key
21926
+ useEffect(() => {
21927
+ if (!isOpen || !config?.appearance.closeOnEscape)
21928
+ return;
21929
+ const handleEscapeKey = (event) => {
21930
+ if (event.key === 'Escape') {
21931
+ setIsOpen(false);
21932
+ onClose?.();
21933
+ }
21934
+ };
21935
+ document.addEventListener('keydown', handleEscapeKey);
21936
+ return () => document.removeEventListener('keydown', handleEscapeKey);
21937
+ }, [isOpen, config, onClose]);
21556
21938
  // Determine theme
21557
- const theme = themeOverride || config?.appearance.theme || 'light';
21558
- const effectiveTheme = theme === 'auto'
21559
- ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')
21560
- : theme;
21939
+ const appearanceConfig = config?.appearance;
21940
+ const themeSetting = themeOverride || appearanceConfig?.theme || 'light';
21941
+ const canUseDarkMode = appearanceConfig?.darkModeEnabled !== false;
21942
+ // Only check system preference if dark mode is enabled
21943
+ const systemPrefersDark = canUseDarkMode && typeof window !== "undefined"
21944
+ ? window.matchMedia('(prefers-color-scheme: dark)').matches
21945
+ : false;
21946
+ const effectiveTheme = !canUseDarkMode
21947
+ ? 'light' // Force light mode if dark mode is disabled
21948
+ : themeSetting === 'auto'
21949
+ ? (systemPrefersDark ? 'dark' : 'light')
21950
+ : themeSetting === 'dark'
21951
+ ? 'dark'
21952
+ : 'light';
21561
21953
  // Determine position (config takes priority over prop)
21562
21954
  const effectivePosition = config?.appearance.position || position;
21563
- // Apply custom styles
21564
- const customStyles = {};
21565
- if (primaryColor || config?.appearance.primaryColor) {
21566
- customStyles['--primary-color'] = primaryColor || config?.appearance.primaryColor || '';
21567
- }
21568
- if (config?.appearance.fontFamily) {
21569
- customStyles.fontFamily = config.appearance.fontFamily;
21570
- }
21571
- if (config?.appearance.borderRadius !== undefined) {
21572
- customStyles['--border-radius'] = `${config.appearance.borderRadius}px`;
21573
- }
21955
+ // Apply custom styles from appearance configuration
21956
+ // Use the correct theme configuration (lightMode or darkMode)
21957
+ const customStyles = appearanceConfig
21958
+ ? applyAppearanceStyles(appearanceConfig, effectiveTheme)
21959
+ : {};
21960
+ // Override with prop values if provided
21961
+ if (primaryColor) {
21962
+ customStyles['--primary-color'] = primaryColor;
21963
+ }
21964
+ // Debug logging for theme and styles
21965
+ useEffect(() => {
21966
+ console.log('[ChatWidget] Theme info:', {
21967
+ effectiveTheme,
21968
+ canUseDarkMode,
21969
+ themeSetting,
21970
+ systemPrefersDark,
21971
+ hasCustomStyles: Object.keys(customStyles).length > 0,
21972
+ buttonColor: customStyles['--button-color'],
21973
+ buttonSize: customStyles['--button-size'],
21974
+ cardBackground: customStyles['--card-background'],
21975
+ cardOpacity: customStyles['--card-opacity'],
21976
+ cardBorderRadius: customStyles['--card-border-radius'],
21977
+ });
21978
+ console.log('[ChatWidget] All CSS variables:', customStyles);
21979
+ }, [effectiveTheme, customStyles]);
21574
21980
  const handleToggle = () => {
21575
21981
  const newState = !isOpen;
21982
+ console.log('[ChatWidget] handleToggle called, setting isOpen to:', newState);
21576
21983
  setIsOpen(newState);
21577
21984
  if (newState) {
21578
21985
  onOpen?.();
@@ -21584,10 +21991,13 @@ const ChatWidget = ({ widgetId, apiKey, apiUrl = window.location.origin, positio
21584
21991
  const handleFeedback = async (messageId, feedback) => {
21585
21992
  await submitFeedback(messageId, feedback);
21586
21993
  };
21587
- return (jsx("div", { className: `ai-chat-widget ${effectiveTheme}`, style: customStyles, children: jsx("div", { 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 })) : (jsx("button", { className: "ai-chat-button", onClick: handleToggle, "aria-label": "Open chat", style: {
21588
- width: config?.appearance.buttonSize || 60,
21589
- height: config?.appearance.buttonSize || 60,
21590
- }, children: config?.appearance.buttonIcon ? (jsx("span", { className: "ai-chat-button-icon", children: config.appearance.buttonIcon })) : (jsx("svg", { className: "ai-chat-button-svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsx("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) })) })) }) }));
21994
+ // Don't render until config is loaded to avoid flash of unstyled content
21995
+ if (!config) {
21996
+ console.log('[ChatWidget] Not rendering - config not loaded yet');
21997
+ return null;
21998
+ }
21999
+ console.log('[ChatWidget] Rendering widget', { isOpen, hasConfig: !!config });
22000
+ return (jsx("div", { 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 })), !isOpen && (jsx("button", { className: "ai-chat-button", onClick: handleToggle, "aria-label": "Open chat", children: config?.appearance.buttonIcon ? (jsx("span", { className: "ai-chat-button-icon", children: config.appearance.buttonIcon })) : (jsx("svg", { className: "ai-chat-button-svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsx("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) })) }))] }) }));
21591
22001
  };
21592
22002
 
21593
22003
  export { ApiError, ChatWidget, useChat };