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