@ihoomanai/chat-widget 3.0.21 → 4.0.0

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/src/widget.ts CHANGED
@@ -17,21 +17,21 @@ import type {
17
17
  WidgetView,
18
18
  } from './types';
19
19
 
20
- const VERSION = '3.0.21';
20
+ const VERSION = '4.0.0';
21
21
  const STORAGE_PREFIX = 'ihooman_chat_';
22
22
  const DEFAULT_SERVER_URL = 'https://api.ihooman.ai';
23
23
 
24
24
  const defaultConfig: Partial<WidgetConfig> = {
25
25
  serverUrl: DEFAULT_SERVER_URL,
26
- theme: 'light',
26
+ theme: 'dark',
27
27
  position: 'bottom-right',
28
- title: 'Chat Support',
29
- subtitle: 'We typically reply within minutes',
30
- welcomeMessage: 'Hi there! 👋 How can we help you today?',
31
- placeholder: 'Type a message...',
32
- primaryColor: '#00aeff',
33
- gradientFrom: '#00aeff',
34
- gradientTo: '#0066ff',
28
+ title: 'AI Assistant',
29
+ subtitle: 'Always here to help',
30
+ welcomeMessage: 'Hello! How can I help you today?',
31
+ placeholder: 'Send a message...',
32
+ primaryColor: '#ededed',
33
+ gradientFrom: '#171717',
34
+ gradientTo: '#171717',
35
35
  showTimestamps: true,
36
36
  showTypingIndicator: true,
37
37
  enableSounds: true,
@@ -39,11 +39,11 @@ const defaultConfig: Partial<WidgetConfig> = {
39
39
  startOpen: false,
40
40
  persistSession: true,
41
41
  zIndex: 9999,
42
- width: 380,
43
- height: 560,
44
- buttonSize: 60,
42
+ width: 400,
43
+ height: 620,
44
+ buttonSize: 52,
45
45
  borderRadius: 16,
46
- fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
46
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, Roboto, sans-serif',
47
47
  avatarUrl: '',
48
48
  poweredBy: true,
49
49
  presetQuestions: [],
@@ -54,22 +54,23 @@ const defaultConfig: Partial<WidgetConfig> = {
54
54
  };
55
55
 
56
56
  const icons = {
57
- chat: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path></svg>`,
58
- close: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>`,
59
- send: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="22" y1="2" x2="11" y2="13"></line><polygon points="22 2 15 22 11 13 2 9 22 2"></polygon></svg>`,
60
- attach: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><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"></path></svg>`,
61
- minimize: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="5" y1="12" x2="19" y2="12"></line></svg>`,
62
- bot: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="11" width="18" height="10" rx="2"></rect><circle cx="12" cy="5" r="2"></circle><path d="M12 7v4"></path></svg>`,
63
- agent: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path><circle cx="12" cy="7" r="4"></circle></svg>`,
64
- ticket: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"></path><polyline points="14 2 14 8 20 8"></polyline></svg>`,
65
- history: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline></svg>`,
66
- plus: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>`,
67
- star: `<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"></path></svg>`,
68
- starEmpty: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"></path></svg>`,
69
- thumbUp: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3"></path></svg>`,
70
- thumbDown: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17"></path></svg>`,
71
- chevronLeft: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15 18 9 12 15 6"></polyline></svg>`,
72
- chevronRight: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="9 18 15 12 9 6"></polyline></svg>`,
57
+ chat: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path></svg>`,
58
+ close: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>`,
59
+ send: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"></path><path d="m12 5 7 7-7 7"></path></svg>`,
60
+ attach: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="m21.44 11.05-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"></path></svg>`,
61
+ minimize: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"></path></svg>`,
62
+ sparkle: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"></path></svg>`,
63
+ bot: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M12 8V4H8"></path><rect width="16" height="12" x="4" y="8" rx="2"></rect><path d="M2 14h2"></path><path d="M20 14h2"></path><path d="M15 13v2"></path><path d="M9 13v2"></path></svg>`,
64
+ agent: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="8" r="5"></circle><path d="M20 21a8 8 0 0 0-16 0"></path></svg>`,
65
+ ticket: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"></path><path d="M14 2v4a2 2 0 0 0 2 2h4"></path><path d="M10 18v-1"></path><path d="M14 18v-1"></path><path d="M10 14v-1"></path><path d="M14 14v-1"></path></svg>`,
66
+ history: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"></path><path d="M3 3v5h5"></path><path d="M12 7v5l4 2"></path></svg>`,
67
+ plus: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"></path><path d="M12 5v14"></path></svg>`,
68
+ star: `<svg viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-width="1"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon></svg>`,
69
+ starEmpty: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon></svg>`,
70
+ thumbUp: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M7 10v12"></path><path d="M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2a3.13 3.13 0 0 1 3 3.88Z"></path></svg>`,
71
+ thumbDown: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M17 14V2"></path><path d="M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22a3.13 3.13 0 0 1-3-3.88Z"></path></svg>`,
72
+ chevronLeft: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="m15 18-6-6 6-6"></path></svg>`,
73
+ chevronRight: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"></path></svg>`,
73
74
  };
74
75
 
75
76
  let config: WidgetConfig = { widgetId: '', ...defaultConfig };
@@ -245,22 +246,34 @@ function matchUrlPattern(pattern: string): boolean {
245
246
  // ============================================================================
246
247
 
247
248
  function generateStyles(): string {
248
- const { primaryColor, gradientFrom, gradientTo, fontFamily, borderRadius, zIndex, width, height, buttonSize } = config;
249
- const isDark = config.theme === 'dark';
250
- const bgColor = isDark ? '#1a1a2e' : '#ffffff';
251
- const textColor = isDark ? '#e4e4e7' : '#1f2937';
252
- const mutedColor = isDark ? '#71717a' : '#6b7280';
253
- const borderColor = isDark ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.08)';
254
- const inputBg = isDark ? '#16162a' : '#f9fafb';
255
- const messageBgUser = `linear-gradient(135deg, ${gradientFrom}, ${gradientTo})`;
256
- const messageBgBot = isDark ? '#252542' : '#f1f5f9';
249
+ const { fontFamily, borderRadius, zIndex, width, height, buttonSize } = config;
250
+ const isDark = config.theme === 'dark' || config.theme === 'auto';
251
+
252
+ // Professional dark/light color tokens Vercel-inspired
253
+ const bgColor = isDark ? '#0a0a0a' : '#ffffff';
254
+ const bgElevated = isDark ? '#141414' : '#fafafa';
255
+ const bgSurface = isDark ? '#1a1a1a' : '#f4f4f5';
256
+ const textColor = isDark ? '#ededed' : '#09090b';
257
+ const textSecondary = isDark ? '#a1a1aa' : '#71717a';
258
+ const mutedColor = isDark ? '#52525b' : '#a1a1aa';
259
+ const borderColor = isDark ? '#27272a' : '#e4e4e7';
260
+ const borderSubtle = isDark ? '#1f1f23' : '#f4f4f5';
261
+ const inputBg = isDark ? '#141414' : '#fafafa';
262
+ const hoverBg = isDark ? '#1c1c1c' : '#f4f4f5';
263
+ const accentColor = isDark ? '#ededed' : '#18181b';
264
+ const accentBg = isDark ? '#ededed' : '#18181b';
265
+ const accentText = isDark ? '#09090b' : '#fafafa';
266
+ const userMsgBg = isDark ? '#27272a' : '#18181b';
267
+ const userMsgText = isDark ? '#ededed' : '#fafafa';
268
+ const botMsgBg = 'transparent';
257
269
  const positionRight = config.position?.includes('right') ?? true;
258
270
  const positionBottom = config.position?.includes('bottom') ?? true;
271
+ const shadowLg = isDark ? '0 24px 48px rgba(0,0,0,0.6), 0 0 0 1px rgba(255,255,255,0.05)' : '0 24px 48px rgba(0,0,0,0.12), 0 0 0 1px rgba(0,0,0,0.05)';
259
272
 
260
273
  return `
261
274
  *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
262
275
  :host { all: initial; }
263
- .ihooman-widget { font-family: ${fontFamily}; font-size: 14px; line-height: 1.5; color: ${textColor}; -webkit-font-smoothing: antialiased; }
276
+ .ihooman-widget { font-family: ${fontFamily}; font-size: 14px; line-height: 1.6; color: ${textColor}; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
264
277
  button {
265
278
  font-family: inherit;
266
279
  font-size: 100%;
@@ -273,144 +286,188 @@ function generateStyles(): string {
273
286
  cursor: pointer;
274
287
  outline: none;
275
288
  }
276
- .ihooman-toggle { position: fixed !important; ${positionRight ? 'right: 20px' : 'left: 20px'}; ${positionBottom ? 'bottom: 20px' : 'top: 20px'}; width: ${buttonSize}px !important; height: ${buttonSize}px !important; border-radius: 50% !important; background: linear-gradient(135deg, ${gradientFrom}, ${gradientTo}) !important; border: none !important; cursor: pointer; z-index: ${zIndex}; display: flex !important; align-items: center; justify-content: center; box-shadow: 0 4px 20px rgba(0, 174, 255, 0.35); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); overflow: hidden; }
277
- .ihooman-toggle:hover { transform: scale(1.08); box-shadow: 0 6px 28px rgba(0, 174, 255, 0.45); }
278
- .ihooman-toggle:active { transform: scale(0.95); }
279
- .ihooman-toggle::before { content: ''; position: absolute; inset: 0; background: linear-gradient(to bottom, rgba(255,255,255,0.2), transparent); border-radius: 50%; }
280
- .ihooman-toggle svg { width: 26px; height: 26px; color: white; transition: transform 0.3s ease, opacity 0.2s ease; position: relative; z-index: 1; }
281
- .ihooman-toggle .chat-icon { display: flex; align-items: center; justify-content: center; transition: transform 0.3s ease, opacity 0.2s ease; }
282
- .ihooman-toggle .close-icon { position: absolute; display: flex; align-items: center; justify-content: center; transform: rotate(-90deg) scale(0); opacity: 0; transition: transform 0.3s ease, opacity 0.2s ease; }
289
+ button:focus-visible { outline: 2px solid ${accentColor}; outline-offset: 2px; }
290
+
291
+ /* ── Toggle Button ── */
292
+ .ihooman-toggle { position: fixed !important; ${positionRight ? 'right: 20px' : 'left: 20px'}; ${positionBottom ? 'bottom: 20px' : 'top: 20px'}; width: ${buttonSize}px !important; height: ${buttonSize}px !important; border-radius: 50% !important; background: ${accentBg} !important; border: 1px solid ${borderColor} !important; cursor: pointer; z-index: ${zIndex}; display: flex !important; align-items: center; justify-content: center; box-shadow: ${shadowLg}; transition: all 0.2s ease-out; overflow: hidden; }
293
+ .ihooman-toggle:hover { transform: scale(1.05); box-shadow: ${shadowLg}; }
294
+ .ihooman-toggle:active { transform: scale(0.96); }
295
+ .ihooman-toggle svg { width: 22px; height: 22px; color: ${accentText}; transition: transform 0.25s ease-out, opacity 0.15s ease; position: relative; z-index: 1; }
296
+ .ihooman-toggle .chat-icon { display: flex; align-items: center; justify-content: center; transition: transform 0.25s ease-out, opacity 0.15s ease; }
297
+ .ihooman-toggle .close-icon { position: absolute; display: flex; align-items: center; justify-content: center; transform: rotate(-90deg) scale(0); opacity: 0; transition: transform 0.25s ease-out, opacity 0.15s ease; }
283
298
  .ihooman-toggle.open .chat-icon { transform: rotate(90deg) scale(0); opacity: 0; }
284
299
  .ihooman-toggle.open .close-icon { transform: rotate(0) scale(1); opacity: 1; }
285
- .ihooman-pulse { position: absolute; inset: 0; border-radius: 50%; background: ${primaryColor}; animation: ihooman-pulse 2s ease-out infinite; }
286
- @keyframes ihooman-pulse { 0% { transform: scale(1); opacity: 0.5; } 100% { transform: scale(1.6); opacity: 0; } }
287
- .ihooman-toggle.open .ihooman-pulse { display: none; }
288
- .ihooman-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 6px; background: #ef4444; color: white; font-size: 11px; font-weight: 600; border-radius: 10px; display: flex; align-items: center; justify-content: center; z-index: 2; }
300
+ .ihooman-pulse { display: none; }
301
+ .ihooman-badge { position: absolute; top: -3px; right: -3px; min-width: 18px; height: 18px; padding: 0 5px; background: #dc2626; color: white; font-size: 10px; font-weight: 600; border-radius: 9px; display: flex; align-items: center; justify-content: center; z-index: 2; border: 2px solid ${bgColor}; }
289
302
  .ihooman-badge:empty { display: none; }
290
- .ihooman-window { position: fixed; ${positionRight ? 'right: 20px' : 'left: 20px'}; ${positionBottom ? 'bottom: 90px' : 'top: 90px'}; width: ${width}px; height: ${height}px; min-height: ${height}px; max-height: ${height}px; z-index: ${(zIndex ?? 9999) - 1}; display: flex; flex-direction: column; opacity: 0; visibility: hidden; transform: translateY(20px) scale(0.95); transition: opacity 0.3s, visibility 0.3s, transform 0.3s; overscroll-behavior: contain; }
303
+
304
+ /* ── Window ── */
305
+ .ihooman-window { position: fixed; ${positionRight ? 'right: 20px' : 'left: 20px'}; ${positionBottom ? 'bottom: 84px' : 'top: 84px'}; width: ${width}px; height: ${height}px; min-height: ${height}px; max-height: ${height}px; z-index: ${(zIndex ?? 9999) - 1}; display: flex; flex-direction: column; opacity: 0; visibility: hidden; transform: translateY(12px) scale(0.97); transition: opacity 0.2s ease-out, visibility 0.2s ease-out, transform 0.2s ease-out; overscroll-behavior: contain; }
291
306
  .ihooman-window.open { opacity: 1; visibility: visible; transform: translateY(0) scale(1); }
292
- .ihooman-container { position: relative; width: 100%; height: 100%; display: flex; flex-direction: column; border-radius: ${borderRadius}px; overflow: hidden; flex-shrink: 0; }
293
- .ihooman-container::before { content: ''; position: absolute; inset: 0; background: ${bgColor}; opacity: 0.97; backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); border-radius: ${borderRadius}px; border: 1px solid ${borderColor}; box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25); }
294
- .ihooman-container > * { position: relative; z-index: 1; }
295
- .ihooman-header { padding: 16px 20px; background: linear-gradient(135deg, ${gradientFrom}, ${gradientTo}); color: white; display: flex; align-items: center; gap: 12px; flex-shrink: 0; }
296
- .ihooman-header-avatar { width: 42px; height: 42px; border-radius: 50%; background: rgba(255,255,255,0.2); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
297
- .ihooman-header-avatar img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; }
298
- .ihooman-header-avatar svg { width: 22px; height: 22px; }
307
+
308
+ /* ── Container ── */
309
+ .ihooman-container { position: relative; width: 100%; height: 100%; display: flex; flex-direction: column; border-radius: ${borderRadius}px; overflow: hidden; flex-shrink: 0; background: ${bgColor}; border: 1px solid ${borderColor}; box-shadow: ${shadowLg}; }
310
+
311
+ /* ── Header ── */
312
+ .ihooman-header { padding: 14px 16px; background: ${bgElevated}; color: ${textColor}; display: flex; align-items: center; gap: 12px; flex-shrink: 0; border-bottom: 1px solid ${borderColor}; }
313
+ .ihooman-header-avatar { width: 36px; height: 36px; border-radius: 10px; background: ${bgSurface}; display: flex; align-items: center; justify-content: center; flex-shrink: 0; border: 1px solid ${borderColor}; }
314
+ .ihooman-header-avatar img { width: 100%; height: 100%; border-radius: 10px; object-fit: cover; }
315
+ .ihooman-header-avatar svg { width: 18px; height: 18px; color: ${textSecondary}; }
299
316
  .ihooman-header-info { flex: 1; min-width: 0; }
300
- .ihooman-header-title { font-size: 16px; font-weight: 600; margin-bottom: 2px; }
301
- .ihooman-header-status { display: flex; align-items: center; gap: 6px; font-size: 12px; opacity: 0.9; }
302
- .ihooman-status-dot { width: 8px; height: 8px; border-radius: 50%; background: #22c55e; }
303
- .ihooman-status-dot.offline { background: #f59e0b; }
304
- .ihooman-header-actions { display: flex; gap: 8px; }
305
- .ihooman-header-btn { width: 28px; height: 28px; border-radius: 6px; background: rgba(255,255,255,0.15); border: none; cursor: pointer; display: flex; align-items: center; justify-content: center; color: white; transition: background 0.2s; }
306
- .ihooman-header-btn:hover { background: rgba(255,255,255,0.25); }
307
- .ihooman-header-btn svg { width: 14px; height: 14px; }
308
- .ihooman-messages { flex: 1; overflow-y: auto; overflow-x: hidden; padding: 16px; display: flex; flex-direction: column; gap: 12px; background: ${bgColor}; overscroll-behavior: contain; min-height: 0; }
309
- .ihooman-messages::-webkit-scrollbar { width: 6px; }
317
+ .ihooman-header-title { font-size: 14px; font-weight: 600; margin-bottom: 1px; letter-spacing: -0.01em; color: ${textColor}; }
318
+ .ihooman-header-status { display: flex; align-items: center; gap: 5px; font-size: 12px; color: ${textSecondary}; }
319
+ .ihooman-status-dot { width: 6px; height: 6px; border-radius: 50%; background: #22c55e; flex-shrink: 0; }
320
+ .ihooman-status-dot.offline { background: #a1a1aa; }
321
+ .ihooman-header-actions { display: flex; gap: 4px; }
322
+ .ihooman-header-btn { width: 30px; height: 30px; border-radius: 8px; background: transparent; border: none; cursor: pointer; display: flex; align-items: center; justify-content: center; color: ${textSecondary}; transition: background 0.15s ease, color 0.15s ease; }
323
+ .ihooman-header-btn:hover { background: ${hoverBg}; color: ${textColor}; }
324
+ .ihooman-header-btn svg { width: 15px; height: 15px; }
325
+
326
+ /* ── Messages ── */
327
+ .ihooman-messages { flex: 1; overflow-y: auto; overflow-x: hidden; padding: 20px 16px; display: flex; flex-direction: column; gap: 6px; background: ${bgColor}; overscroll-behavior: contain; min-height: 0; }
328
+ .ihooman-messages::-webkit-scrollbar { width: 4px; }
310
329
  .ihooman-messages::-webkit-scrollbar-track { background: transparent; }
311
- .ihooman-messages::-webkit-scrollbar-thumb { background: ${borderColor}; border-radius: 3px; }
312
- .ihooman-message { display: flex; flex-direction: column; max-width: 85%; animation: ihooman-fadeIn 0.3s ease; }
313
- @keyframes ihooman-fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
330
+ .ihooman-messages::-webkit-scrollbar-thumb { background: ${isDark ? '#27272a' : '#d4d4d8'}; border-radius: 2px; }
331
+ .ihooman-message { display: flex; flex-direction: column; max-width: 88%; animation: ihooman-fadeIn 0.25s ease-out; }
332
+ @keyframes ihooman-fadeIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }
314
333
  .ihooman-message.user { align-self: flex-end; align-items: flex-end; }
315
- .ihooman-message.bot { align-self: flex-start; align-items: flex-start; }
316
- .ihooman-message-content { padding: 12px 16px; border-radius: 16px; word-wrap: break-word; }
317
- .ihooman-message.user .ihooman-message-content { background: ${messageBgUser}; color: white; border-bottom-right-radius: 4px; }
318
- .ihooman-message.bot .ihooman-message-content { background: ${messageBgBot}; color: ${textColor}; border-bottom-left-radius: 4px; }
319
- .ihooman-message-content code { background: rgba(0,0,0,0.1); padding: 2px 6px; border-radius: 4px; font-family: monospace; font-size: 13px; }
320
- .ihooman-message-time { font-size: 11px; color: ${mutedColor}; margin-top: 4px; padding: 0 4px; }
321
- .ihooman-typing { display: flex; align-items: center; gap: 8px; padding: 12px 16px; background: ${messageBgBot}; border-radius: 16px; border-bottom-left-radius: 4px; max-width: 80px; align-self: flex-start; }
322
- .ihooman-typing-dots { display: flex; gap: 4px; }
323
- .ihooman-typing-dot { width: 8px; height: 8px; background: ${mutedColor}; border-radius: 50%; animation: ihooman-typing 1.4s infinite; }
324
- .ihooman-typing-dot:nth-child(2) { animation-delay: 0.2s; }
325
- .ihooman-typing-dot:nth-child(3) { animation-delay: 0.4s; }
326
- @keyframes ihooman-typing { 0%, 60%, 100% { transform: translateY(0); opacity: 0.4; } 30% { transform: translateY(-4px); opacity: 1; } }
334
+ .ihooman-message.bot { align-self: flex-start; align-items: flex-start; max-width: 100%; }
335
+ .ihooman-message-content { padding: 10px 14px; border-radius: 14px; word-wrap: break-word; overflow-wrap: break-word; font-size: 14px; line-height: 1.6; }
336
+ .ihooman-message.user .ihooman-message-content { background: ${userMsgBg}; color: ${userMsgText}; border-bottom-right-radius: 4px; }
337
+ .ihooman-message.bot .ihooman-message-content { background: ${botMsgBg}; color: ${textColor}; padding: 6px 2px; }
338
+ .ihooman-message-content a { color: ${isDark ? '#60a5fa' : '#2563eb'}; text-decoration: underline; text-underline-offset: 2px; }
339
+ .ihooman-message-content a:hover { opacity: 0.8; }
340
+ .ihooman-message-content code { background: ${isDark ? '#27272a' : '#f4f4f5'}; padding: 2px 6px; border-radius: 4px; font-family: 'SF Mono', 'Fira Code', 'Fira Mono', Menlo, Consolas, monospace; font-size: 12.5px; border: 1px solid ${borderSubtle}; }
341
+ .ihooman-message-content strong { font-weight: 600; }
342
+ .ihooman-message-time { font-size: 11px; color: ${mutedColor}; margin-top: 3px; padding: 0 4px; }
343
+
344
+ /* ── Typing Indicator — Shimmer ── */
345
+ .ihooman-typing { display: flex; align-items: center; gap: 10px; padding: 10px 2px; max-width: 180px; align-self: flex-start; animation: ihooman-fadeIn 0.2s ease-out; }
346
+ .ihooman-typing-shimmer { font-size: 13px; color: ${mutedColor}; background: linear-gradient(90deg, ${mutedColor} 25%, ${textSecondary} 50%, ${mutedColor} 75%); background-size: 200% 100%; -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; animation: ihooman-shimmer 1.5s ease-in-out infinite; }
347
+ @keyframes ihooman-shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
348
+ .ihooman-typing-dots { display: flex; gap: 3px; align-items: center; }
349
+ .ihooman-typing-dot { width: 5px; height: 5px; background: ${mutedColor}; border-radius: 50%; animation: ihooman-typing 1.2s ease-in-out infinite; }
350
+ .ihooman-typing-dot:nth-child(2) { animation-delay: 0.15s; }
351
+ .ihooman-typing-dot:nth-child(3) { animation-delay: 0.3s; }
352
+ @keyframes ihooman-typing { 0%, 60%, 100% { opacity: 0.3; transform: scale(0.8); } 30% { opacity: 1; transform: scale(1); } }
353
+
354
+ /* ── Input Area ── */
327
355
  .ihooman-input-area { padding: 12px 16px; background: ${bgColor}; border-top: 1px solid ${borderColor}; flex-shrink: 0; }
328
- .ihooman-input-wrapper { display: flex; align-items: flex-end; gap: 8px; background: ${inputBg}; border: 1px solid ${borderColor}; border-radius: 12px; padding: 8px 12px; transition: border-color 0.2s, box-shadow 0.2s; }
329
- .ihooman-input-wrapper:focus-within { border-color: ${primaryColor}; box-shadow: 0 0 0 3px rgba(0, 174, 255, 0.1); }
330
- .ihooman-input { flex: 1; border: none; background: transparent; font-family: inherit; font-size: 14px; color: ${textColor}; resize: none; max-height: 100px; outline: none; line-height: 1.4; }
356
+ .ihooman-input-wrapper { display: flex; align-items: flex-end; gap: 8px; background: ${inputBg}; border: 1px solid ${borderColor}; border-radius: 12px; padding: 8px 12px; transition: border-color 0.15s ease, box-shadow 0.15s ease; }
357
+ .ihooman-input-wrapper:focus-within { border-color: ${isDark ? '#3f3f46' : '#a1a1aa'}; }
358
+ .ihooman-input { flex: 1; border: none; background: transparent; font-family: inherit; font-size: 14px; color: ${textColor}; resize: none; max-height: 100px; outline: none; line-height: 1.5; }
331
359
  .ihooman-input::placeholder { color: ${mutedColor}; }
332
- .ihooman-input-btn { width: 32px; height: 32px; border-radius: 8px; border: none; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.2s; background: transparent; color: ${mutedColor}; }
333
- .ihooman-input-btn:hover { background: ${borderColor}; color: ${textColor}; }
334
- .ihooman-input-btn.send { background: linear-gradient(135deg, ${gradientFrom}, ${gradientTo}); color: white; }
335
- .ihooman-input-btn.send:hover { opacity: 0.9; }
336
- .ihooman-input-btn.send:disabled { opacity: 0.5; cursor: not-allowed; }
360
+ .ihooman-input-btn { width: 30px; height: 30px; border-radius: 8px; border: none; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.15s ease; background: transparent; color: ${mutedColor}; flex-shrink: 0; }
361
+ .ihooman-input-btn:hover { color: ${textColor}; background: ${hoverBg}; }
362
+ .ihooman-input-btn.send { background: ${accentBg}; color: ${accentText}; }
363
+ .ihooman-input-btn.send:hover { opacity: 0.85; }
364
+ .ihooman-input-btn.send:disabled { opacity: 0.3; cursor: not-allowed; }
337
365
  .ihooman-input-btn svg { width: 16px; height: 16px; }
338
- .ihooman-input:disabled { opacity: 0.6; cursor: not-allowed; }
339
- .ihooman-input-btn.attach:disabled { opacity: 0.4; cursor: not-allowed; }
366
+ .ihooman-input:disabled { opacity: 0.5; cursor: not-allowed; }
367
+ .ihooman-input-btn.attach:disabled { opacity: 0.3; cursor: not-allowed; }
340
368
  .ihooman-file-input { display: none; }
341
- .ihooman-powered { text-align: center; padding: 8px; font-size: 11px; color: ${mutedColor}; background: ${bgColor}; }
342
- .ihooman-powered a { color: ${primaryColor}; text-decoration: none; }
369
+
370
+ /* ── Powered By ── */
371
+ .ihooman-powered { text-align: center; padding: 8px; font-size: 11px; color: ${mutedColor}; background: ${bgColor}; border-top: 1px solid ${borderSubtle}; }
372
+ .ihooman-powered a { color: ${textSecondary}; text-decoration: none; font-weight: 500; }
373
+ .ihooman-powered a:hover { color: ${textColor}; }
374
+
375
+ /* ── Escalation ── */
343
376
  .ihooman-escalation-actions { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
344
377
  .ihooman-escalation-btn svg { width: 14px; height: 14px; flex-shrink: 0; }
345
- .ihooman-status-bar { padding: 10px 16px; text-align: center; font-size: 13px; display: none; }
378
+
379
+ /* ── Status Bar ── */
380
+ .ihooman-status-bar { padding: 8px 16px; text-align: center; font-size: 12px; display: none; font-weight: 500; }
346
381
  .ihooman-status-bar.show { display: block; }
347
- .ihooman-status-bar.waiting { background: #fef3c7; color: #92400e; }
348
- .ihooman-status-bar.connected { background: #dcfce7; color: #166534; }
382
+ .ihooman-status-bar.waiting { background: ${isDark ? '#1c1917' : '#fef9c3'}; color: ${isDark ? '#fbbf24' : '#92400e'}; border-bottom: 1px solid ${isDark ? '#292524' : '#fef08a'}; }
383
+ .ihooman-status-bar.connected { background: ${isDark ? '#052e16' : '#dcfce7'}; color: ${isDark ? '#4ade80' : '#166534'}; border-bottom: 1px solid ${isDark ? '#14532d' : '#bbf7d0'}; }
384
+
385
+ /* ── Chat View ── */
349
386
  .ihooman-chat-view { display: flex; flex-direction: column; flex: 1; overflow: hidden; min-height: 0; }
350
387
  .ihooman-chat-view.hidden { display: none; }
351
- .ihooman-ticket-view { display: none; flex-direction: column; padding: 20px; gap: 16px; background: ${bgColor}; flex: 1; overflow-y: auto; min-height: 0; }
388
+
389
+ /* ── Ticket View ── */
390
+ .ihooman-ticket-view { display: none; flex-direction: column; padding: 20px; gap: 14px; background: ${bgColor}; flex: 1; overflow-y: auto; min-height: 0; }
352
391
  .ihooman-ticket-view.show { display: flex; }
353
- .ihooman-ticket-title { font-size: 18px; font-weight: 600; color: ${textColor}; margin: 0; }
354
- .ihooman-ticket-subtitle { font-size: 13px; color: ${mutedColor}; margin: 0; }
355
- .ihooman-ticket-input { padding: 12px 14px; border: 1px solid ${borderColor}; border-radius: 10px; font-size: 14px; font-family: inherit; background: ${inputBg}; color: ${textColor}; outline: none; transition: border-color 0.2s; }
356
- .ihooman-ticket-input:focus { border-color: ${primaryColor}; }
392
+ .ihooman-ticket-title { font-size: 16px; font-weight: 600; color: ${textColor}; margin: 0; letter-spacing: -0.01em; }
393
+ .ihooman-ticket-subtitle { font-size: 13px; color: ${textSecondary}; margin: 0; }
394
+ .ihooman-ticket-input { padding: 10px 14px; border: 1px solid ${borderColor}; border-radius: 10px; font-size: 14px; font-family: inherit; background: ${inputBg}; color: ${textColor}; outline: none; transition: border-color 0.15s ease; }
395
+ .ihooman-ticket-input:focus { border-color: ${isDark ? '#3f3f46' : '#a1a1aa'}; }
357
396
  .ihooman-ticket-input::placeholder { color: ${mutedColor}; }
358
397
  .ihooman-ticket-textarea { min-height: 100px; resize: vertical; }
359
- .ihooman-ticket-submit { display: flex; align-items: center; justify-content: center; padding: 12px; background: linear-gradient(135deg, ${gradientFrom}, ${gradientTo}); color: white; border: none; border-radius: 8px; font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.2s; line-height: 1.4; }
360
- .ihooman-ticket-submit:hover { opacity: 0.9; }
361
- .ihooman-ticket-submit:disabled { opacity: 0.5; cursor: not-allowed; }
362
- .ihooman-ticket-back { display: flex; align-items: center; justify-content: center; padding: 10px; background: transparent; color: ${mutedColor}; border: 1px solid ${borderColor}; border-radius: 8px; font-size: 13px; cursor: pointer; transition: all 0.2s; line-height: 1.4; }
363
- .ihooman-ticket-back:hover { background: ${isDark ? 'rgba(255,255,255,0.05)' : 'rgba(0,0,0,0.03)'}; }
398
+ .ihooman-ticket-submit { display: flex; align-items: center; justify-content: center; padding: 10px; background: ${accentBg}; color: ${accentText}; border: none; border-radius: 10px; font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.15s ease; line-height: 1.4; }
399
+ .ihooman-ticket-submit:hover { opacity: 0.85; }
400
+ .ihooman-ticket-submit:disabled { opacity: 0.4; cursor: not-allowed; }
401
+ .ihooman-ticket-back { display: flex; align-items: center; justify-content: center; padding: 10px; background: transparent; color: ${textSecondary}; border: 1px solid ${borderColor}; border-radius: 10px; font-size: 13px; cursor: pointer; transition: all 0.15s ease; line-height: 1.4; }
402
+ .ihooman-ticket-back:hover { background: ${hoverBg}; color: ${textColor}; }
403
+
404
+ /* ── History View ── */
364
405
  .ihooman-history-view { display: none; flex-direction: column; flex: 1; overflow: hidden; background: ${bgColor}; }
365
406
  .ihooman-history-view.show { display: flex; }
366
407
  .ihooman-history-header { padding: 12px 16px; border-bottom: 1px solid ${borderColor}; display: flex; justify-content: space-between; align-items: center; }
367
- .ihooman-history-title { font-size: 14px; font-weight: 600; color: ${textColor}; margin: 0; }
368
- .ihooman-history-new { display: inline-flex; align-items: center; justify-content: center; gap: 4px; background: linear-gradient(135deg, ${gradientFrom}, ${gradientTo}); color: white; border: none; padding: 6px 12px; border-radius: 6px; font-size: 12px; font-weight: 500; cursor: pointer; transition: all 0.2s; line-height: 1.4; }
369
- .ihooman-history-new:hover { opacity: 0.9; }
408
+ .ihooman-history-title { font-size: 13px; font-weight: 600; color: ${textColor}; margin: 0; }
409
+ .ihooman-history-new { display: inline-flex; align-items: center; justify-content: center; gap: 4px; background: ${accentBg}; color: ${accentText}; border: none; padding: 6px 12px; border-radius: 8px; font-size: 12px; font-weight: 500; cursor: pointer; transition: all 0.15s ease; line-height: 1.4; }
410
+ .ihooman-history-new:hover { opacity: 0.85; }
370
411
  .ihooman-history-new svg { width: 12px; height: 12px; flex-shrink: 0; }
371
412
  .ihooman-history-list { flex: 1; overflow-y: auto; padding: 8px; overscroll-behavior: contain; }
372
- .ihooman-history-item { padding: 12px; border: 1px solid ${borderColor}; border-radius: 8px; margin-bottom: 6px; cursor: pointer; transition: all 0.2s; background: ${bgColor}; }
373
- .ihooman-history-item:hover { background: ${isDark ? 'rgba(255,255,255,0.05)' : '#f8fafc'}; }
374
- .ihooman-history-item.active { background: ${isDark ? 'rgba(0, 174, 255, 0.1)' : '#eff6ff'}; border-color: ${primaryColor}; }
413
+ .ihooman-history-item { padding: 12px; border: 1px solid ${borderColor}; border-radius: 10px; margin-bottom: 6px; cursor: pointer; transition: all 0.15s ease; background: ${bgColor}; }
414
+ .ihooman-history-item:hover { background: ${hoverBg}; }
415
+ .ihooman-history-item.active { background: ${hoverBg}; border-color: ${isDark ? '#3f3f46' : '#a1a1aa'}; }
375
416
  .ihooman-history-preview { font-size: 13px; color: ${textColor}; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
376
417
  .ihooman-history-meta { font-size: 11px; color: ${mutedColor}; margin-top: 4px; display: flex; justify-content: space-between; }
377
- .ihooman-history-empty { padding: 40px; text-align: center; color: ${mutedColor}; font-size: 14px; }
378
- .ihooman-preset-questions { padding: 10px 16px; display: flex; flex-wrap: wrap; gap: 6px; background: ${bgColor}; border-top: 1px solid ${borderColor}; }
418
+ .ihooman-history-empty { padding: 40px; text-align: center; color: ${mutedColor}; font-size: 13px; }
419
+
420
+ /* ── Preset Questions ── */
421
+ .ihooman-preset-questions { padding: 10px 16px; display: flex; flex-wrap: wrap; gap: 6px; background: ${bgColor}; border-top: 1px solid ${borderSubtle}; }
379
422
  .ihooman-preset-questions:empty { display: none; }
380
423
  .ihooman-preset-questions.hidden { display: none; }
381
- .ihooman-proactive-toast { position: fixed; ${positionRight ? 'right: 20px' : 'left: 20px'}; ${positionBottom ? 'bottom: 90px' : 'top: 90px'}; max-width: 300px; padding: 16px; background: ${bgColor}; border-radius: 12px; box-shadow: 0 10px 40px rgba(0,0,0,0.15); z-index: ${(zIndex ?? 9999) - 2}; opacity: 0; visibility: hidden; transform: translateY(10px); transition: all 0.3s ease; border: 1px solid ${borderColor}; }
424
+
425
+ /* ── Proactive Toast ── */
426
+ .ihooman-proactive-toast { position: fixed; ${positionRight ? 'right: 20px' : 'left: 20px'}; ${positionBottom ? 'bottom: 84px' : 'top: 84px'}; max-width: 320px; padding: 16px; background: ${bgElevated}; border-radius: 14px; box-shadow: ${shadowLg}; z-index: ${(zIndex ?? 9999) - 2}; opacity: 0; visibility: hidden; transform: translateY(8px); transition: all 0.2s ease-out; border: 1px solid ${borderColor}; }
382
427
  .ihooman-proactive-toast.show { opacity: 1; visibility: visible; transform: translateY(0); }
383
- .ihooman-proactive-toast-content { font-size: 14px; color: ${textColor}; margin-bottom: 12px; }
428
+ .ihooman-proactive-toast-content { font-size: 14px; color: ${textColor}; margin-bottom: 12px; line-height: 1.5; }
384
429
  .ihooman-proactive-toast-actions { display: flex; gap: 8px; }
385
- .ihooman-proactive-toast-btn { display: inline-flex; align-items: center; justify-content: center; padding: 8px 16px; border-radius: 6px; font-size: 13px; font-weight: 500; cursor: pointer; transition: all 0.2s; line-height: 1.4; }
386
- .ihooman-proactive-toast-btn.primary { background: linear-gradient(135deg, ${gradientFrom}, ${gradientTo}); color: white; border: none; }
387
- .ihooman-proactive-toast-btn.primary:hover { opacity: 0.9; }
388
- .ihooman-proactive-toast-btn.secondary { background: transparent; color: ${mutedColor}; border: 1px solid ${borderColor}; }
389
- .ihooman-proactive-toast-btn.secondary:hover { background: ${isDark ? 'rgba(255,255,255,0.05)' : 'rgba(0,0,0,0.03)'}; }
390
- .ihooman-survey-view { display: none; flex-direction: column; padding: 20px; gap: 16px; background: ${bgColor}; flex: 1; align-items: center; justify-content: center; }
430
+ .ihooman-proactive-toast-btn { display: inline-flex; align-items: center; justify-content: center; padding: 8px 16px; border-radius: 8px; font-size: 13px; font-weight: 500; cursor: pointer; transition: all 0.15s ease; line-height: 1.4; }
431
+ .ihooman-proactive-toast-btn.primary { background: ${accentBg}; color: ${accentText}; border: none; }
432
+ .ihooman-proactive-toast-btn.primary:hover { opacity: 0.85; }
433
+ .ihooman-proactive-toast-btn.secondary { background: transparent; color: ${textSecondary}; border: 1px solid ${borderColor}; }
434
+ .ihooman-proactive-toast-btn.secondary:hover { background: ${hoverBg}; }
435
+
436
+ /* ── Survey View ── */
437
+ .ihooman-survey-view { display: none; flex-direction: column; padding: 24px; gap: 16px; background: ${bgColor}; flex: 1; align-items: center; justify-content: center; }
391
438
  .ihooman-survey-view.show { display: flex; }
392
- .ihooman-survey-question { font-size: 16px; font-weight: 600; color: ${textColor}; text-align: center; }
439
+ .ihooman-survey-question { font-size: 16px; font-weight: 600; color: ${textColor}; text-align: center; letter-spacing: -0.01em; }
393
440
  .ihooman-survey-stars { display: flex; gap: 8px; }
394
- .ihooman-survey-star { width: 40px; height: 40px; cursor: pointer; color: ${mutedColor}; transition: all 0.2s; }
441
+ .ihooman-survey-star { width: 36px; height: 36px; cursor: pointer; color: ${mutedColor}; transition: all 0.15s ease; }
395
442
  .ihooman-survey-star:hover, .ihooman-survey-star.active { color: #fbbf24; transform: scale(1.1); }
396
443
  .ihooman-survey-star svg { width: 100%; height: 100%; }
397
- .ihooman-survey-comment { width: 100%; padding: 12px; border: 1px solid ${borderColor}; border-radius: 8px; font-size: 14px; resize: none; min-height: 80px; background: ${inputBg}; color: ${textColor}; }
398
- .ihooman-survey-submit { display: inline-flex; align-items: center; justify-content: center; padding: 10px 20px; background: linear-gradient(135deg, ${gradientFrom}, ${gradientTo}); color: white; border: none; border-radius: 6px; font-size: 13px; font-weight: 500; cursor: pointer; line-height: 1.4; }
399
- .ihooman-survey-submit:hover { opacity: 0.9; }
444
+ .ihooman-survey-comment { width: 100%; padding: 12px; border: 1px solid ${borderColor}; border-radius: 10px; font-size: 14px; font-family: inherit; resize: none; min-height: 80px; background: ${inputBg}; color: ${textColor}; outline: none; }
445
+ .ihooman-survey-comment:focus { border-color: ${isDark ? '#3f3f46' : '#a1a1aa'}; }
446
+ .ihooman-survey-submit { display: inline-flex; align-items: center; justify-content: center; padding: 10px 20px; background: ${accentBg}; color: ${accentText}; border: none; border-radius: 8px; font-size: 13px; font-weight: 500; cursor: pointer; line-height: 1.4; transition: all 0.15s ease; }
447
+ .ihooman-survey-submit:hover { opacity: 0.85; }
400
448
  .ihooman-survey-skip { display: inline-flex; align-items: center; justify-content: center; padding: 8px 16px; background: transparent; color: ${mutedColor}; border: none; font-size: 12px; cursor: pointer; line-height: 1.4; }
401
449
  .ihooman-survey-skip:hover { color: ${textColor}; }
402
- .ihooman-feedback-btns { display: flex; gap: 6px; margin-top: 6px; }
450
+
451
+ /* ── Feedback ── */
452
+ .ihooman-feedback-btns { display: flex; gap: 4px; margin-top: 4px; }
403
453
  .ihooman-feedback-btn svg { width: 12px; height: 12px; }
404
- .ihooman-carousel { display: flex; gap: 12px; overflow-x: auto; padding: 8px 0; scroll-snap-type: x mandatory; }
405
- .ihooman-carousel::-webkit-scrollbar { height: 4px; }
406
- .ihooman-carousel-card { min-width: 200px; max-width: 250px; border: 1px solid ${borderColor}; border-radius: 12px; overflow: hidden; scroll-snap-align: start; background: ${bgColor}; }
454
+
455
+ /* ── Carousel ── */
456
+ .ihooman-carousel { display: flex; gap: 10px; overflow-x: auto; padding: 8px 0; scroll-snap-type: x mandatory; }
457
+ .ihooman-carousel::-webkit-scrollbar { height: 3px; }
458
+ .ihooman-carousel::-webkit-scrollbar-thumb { background: ${isDark ? '#27272a' : '#d4d4d8'}; border-radius: 2px; }
459
+ .ihooman-carousel-card { min-width: 200px; max-width: 250px; border: 1px solid ${borderColor}; border-radius: 12px; overflow: hidden; scroll-snap-align: start; background: ${bgElevated}; }
407
460
  .ihooman-carousel-card img { width: 100%; height: 120px; object-fit: cover; }
408
461
  .ihooman-carousel-card-content { padding: 12px; }
409
- .ihooman-carousel-card-title { font-size: 14px; font-weight: 600; color: ${textColor}; margin-bottom: 4px; }
410
- .ihooman-carousel-card-desc { font-size: 12px; color: ${mutedColor}; margin-bottom: 8px; }
462
+ .ihooman-carousel-card-title { font-size: 13px; font-weight: 600; color: ${textColor}; margin-bottom: 4px; }
463
+ .ihooman-carousel-card-desc { font-size: 12px; color: ${textSecondary}; margin-bottom: 8px; }
411
464
  .ihooman-carousel-card-btns { display: flex; flex-direction: column; gap: 6px; }
465
+
466
+ /* ── Quick Replies ── */
412
467
  .ihooman-quick-replies { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
413
- @media (max-width: 480px) { .ihooman-window { width: calc(100vw - 20px); height: calc(100vh - 100px); min-height: 400px; max-height: calc(100vh - 100px); left: 10px; right: 10px; bottom: 80px; } .ihooman-toggle { ${positionRight ? 'right: 16px' : 'left: 16px'}; bottom: 16px; } .ihooman-proactive-toast { left: 10px; right: 10px; max-width: none; } }
468
+
469
+ /* ── Responsive ── */
470
+ @media (max-width: 480px) { .ihooman-window { width: calc(100vw - 16px); height: calc(100vh - 100px); min-height: 400px; max-height: calc(100vh - 100px); left: 8px; right: 8px; bottom: 80px; } .ihooman-toggle { ${positionRight ? 'right: 16px' : 'left: 16px'}; bottom: 16px; } .ihooman-proactive-toast { left: 8px; right: 8px; max-width: none; } }
414
471
  `;
415
472
  }
416
473
 
@@ -457,9 +514,9 @@ function createWidget(): void {
457
514
  <div class="ihooman-window" role="dialog" aria-label="Chat window">
458
515
  <div class="ihooman-container">
459
516
  <div class="ihooman-header">
460
- <div class="ihooman-header-avatar">${config.avatarUrl ? `<img src="${escapeHtml(config.avatarUrl)}" alt="Support">` : icons.bot}</div>
517
+ <div class="ihooman-header-avatar">${config.avatarUrl ? `<img src="${escapeHtml(config.avatarUrl)}" alt="Assistant">` : icons.sparkle}</div>
461
518
  <div class="ihooman-header-info">
462
- <div class="ihooman-header-title">${escapeHtml(config.title || 'Chat Support')}</div>
519
+ <div class="ihooman-header-title">${escapeHtml(config.title || 'AI Assistant')}</div>
463
520
  <div class="ihooman-header-status"><span class="ihooman-status-dot"></span><span class="ihooman-status-text">Online</span></div>
464
521
  </div>
465
522
  <div class="ihooman-header-actions">
@@ -481,7 +538,7 @@ function createWidget(): void {
481
538
  </div>
482
539
  </div>
483
540
  <div class="ihooman-ticket-view">
484
- <h4 class="ihooman-ticket-title">📝 Submit a Ticket</h4>
541
+ <h4 class="ihooman-ticket-title">Submit a Ticket</h4>
485
542
  <p class="ihooman-ticket-subtitle">We'll get back to you via email</p>
486
543
  <input class="ihooman-ticket-input" id="ihooman-ticket-name" placeholder="Your name" required>
487
544
  <input class="ihooman-ticket-input" id="ihooman-ticket-email" type="email" placeholder="Your email" required>
@@ -990,6 +1047,8 @@ async function handleRequestLiveAgent(): Promise<void> {
990
1047
  function startLiveAgentPolling(): void {
991
1048
  if (liveAgentPollInterval) return;
992
1049
 
1050
+ let agentConnected = false;
1051
+
993
1052
  liveAgentPollInterval = setInterval(async () => {
994
1053
  if (!state.sessionId || !isLiveAgentMode) {
995
1054
  stopLiveAgentPolling();
@@ -1006,6 +1065,12 @@ function startLiveAgentPolling(): void {
1006
1065
  // Check both ticket_status and conversation_status for agent handling
1007
1066
  if (data.ticket_status === 'in_progress' || data.conversation_status === 'active') {
1008
1067
  updateStatusBar('connected', '🟢 Connected to live agent');
1068
+ // Agent is connected — stop polling, WebSocket handles real-time updates.
1069
+ // Status changes (close/resolve) will come through WebSocket messages.
1070
+ if (!agentConnected) {
1071
+ agentConnected = true;
1072
+ stopLiveAgentPolling();
1073
+ }
1009
1074
  } else if (data.ticket_status === 'open') {
1010
1075
  updateStatusBar('waiting', data.position_in_queue > 1
1011
1076
  ? `⏳ Waiting for agent (Position: #${data.position_in_queue})`
@@ -1020,7 +1085,7 @@ function startLiveAgentPolling(): void {
1020
1085
  }
1021
1086
  }
1022
1087
  } catch { /* ignore */ }
1023
- }, 3000);
1088
+ }, 15000);
1024
1089
  }
1025
1090
 
1026
1091
  function stopLiveAgentPolling(): void {
@@ -1126,7 +1191,7 @@ function showTyping(): void {
1126
1191
 
1127
1192
  const typing = document.createElement('div');
1128
1193
  typing.className = 'ihooman-typing';
1129
- typing.innerHTML = `<div class="ihooman-typing-dots"><span class="ihooman-typing-dot"></span><span class="ihooman-typing-dot"></span><span class="ihooman-typing-dot"></span></div>`;
1194
+ typing.innerHTML = `<span class="ihooman-typing-shimmer">Thinking...</span><div class="ihooman-typing-dots"><span class="ihooman-typing-dot"></span><span class="ihooman-typing-dot"></span><span class="ihooman-typing-dot"></span></div>`;
1130
1195
  elements.messages.appendChild(typing);
1131
1196
  elements.messages.scrollTop = elements.messages.scrollHeight;
1132
1197
  }
@@ -1148,7 +1213,7 @@ function disableInput(): void {
1148
1213
  function enableInput(): void {
1149
1214
  if (elements.input) {
1150
1215
  elements.input.disabled = false;
1151
- elements.input.placeholder = config.placeholder || 'Type a message...';
1216
+ elements.input.placeholder = config.placeholder || 'Send a message...';
1152
1217
  }
1153
1218
  if (elements.sendBtn) elements.sendBtn.disabled = !elements.input?.value.trim();
1154
1219
  if (elements.attachBtn) elements.attachBtn.disabled = false;
@@ -1473,7 +1538,7 @@ function connectWebSocket(chatEndpoint?: string): void {
1473
1538
  startHeartbeat();
1474
1539
  };
1475
1540
 
1476
- ws.onclose = (_event) => {
1541
+ ws.onclose = (event) => {
1477
1542
  state.isConnected = false;
1478
1543
  state.connectionStatus = 'disconnected';
1479
1544
  updateStatus(false);
@@ -1485,6 +1550,9 @@ function connectWebSocket(chatEndpoint?: string): void {
1485
1550
  return;
1486
1551
  }
1487
1552
 
1553
+ // Code 4002 means this connection was replaced by a newer one — don't reconnect
1554
+ if (event.code === 4002) return;
1555
+
1488
1556
  if (!state.isOpen) return;
1489
1557
 
1490
1558
  if (reconnectAttempts < maxReconnectAttempts) {
@@ -1868,11 +1936,10 @@ function getFontWeightValue(weight: string): number {
1868
1936
  }
1869
1937
  }
1870
1938
 
1871
- // Default button styles - MUST match client-dashboard/src/components/widget/ButtonStylingEditor.tsx
1872
1939
  const DEFAULT_BUTTON_STYLES = {
1873
1940
  primary: {
1874
- backgroundColor: '#00aeff',
1875
- textColor: '#ffffff',
1941
+ backgroundColor: '#ededed',
1942
+ textColor: '#09090b',
1876
1943
  borderColor: 'transparent',
1877
1944
  borderWidth: 0,
1878
1945
  borderRadius: 8,
@@ -1883,8 +1950,8 @@ const DEFAULT_BUTTON_STYLES = {
1883
1950
  },
1884
1951
  secondary: {
1885
1952
  backgroundColor: 'transparent',
1886
- textColor: '#6b7280',
1887
- borderColor: '#e5e7eb',
1953
+ textColor: '#a1a1aa',
1954
+ borderColor: '#27272a',
1888
1955
  borderWidth: 1,
1889
1956
  borderRadius: 8,
1890
1957
  paddingVertical: 8,
@@ -1893,9 +1960,9 @@ const DEFAULT_BUTTON_STYLES = {
1893
1960
  fontWeight: 'medium',
1894
1961
  },
1895
1962
  presetQuestions: {
1896
- backgroundColor: 'rgba(0, 174, 255, 0.1)',
1897
- textColor: '#00aeff',
1898
- borderColor: 'rgba(0, 174, 255, 0.2)',
1963
+ backgroundColor: 'transparent',
1964
+ textColor: '#a1a1aa',
1965
+ borderColor: '#27272a',
1899
1966
  borderWidth: 1,
1900
1967
  borderRadius: 20,
1901
1968
  paddingVertical: 6,
@@ -1904,9 +1971,9 @@ const DEFAULT_BUTTON_STYLES = {
1904
1971
  fontWeight: 'medium',
1905
1972
  },
1906
1973
  quickReplies: {
1907
- backgroundColor: '#f3f4f6',
1908
- textColor: '#374151',
1909
- borderColor: '#e5e7eb',
1974
+ backgroundColor: '#1a1a1a',
1975
+ textColor: '#a1a1aa',
1976
+ borderColor: '#27272a',
1910
1977
  borderWidth: 1,
1911
1978
  borderRadius: 16,
1912
1979
  paddingVertical: 5,
@@ -1916,8 +1983,8 @@ const DEFAULT_BUTTON_STYLES = {
1916
1983
  },
1917
1984
  feedback: {
1918
1985
  backgroundColor: 'transparent',
1919
- textColor: '#9ca3af',
1920
- borderColor: '#e5e7eb',
1986
+ textColor: '#52525b',
1987
+ borderColor: '#27272a',
1921
1988
  borderWidth: 1,
1922
1989
  borderRadius: 6,
1923
1990
  paddingVertical: 4,
@@ -1926,19 +1993,19 @@ const DEFAULT_BUTTON_STYLES = {
1926
1993
  fontWeight: 'medium',
1927
1994
  },
1928
1995
  headerActions: {
1929
- backgroundColor: 'rgba(255, 255, 255, 0.1)',
1930
- textColor: '#ffffff',
1996
+ backgroundColor: 'transparent',
1997
+ textColor: '#a1a1aa',
1931
1998
  borderColor: 'transparent',
1932
1999
  borderWidth: 0,
1933
- borderRadius: 6,
2000
+ borderRadius: 8,
1934
2001
  paddingVertical: 6,
1935
2002
  paddingHorizontal: 6,
1936
2003
  fontSize: 14,
1937
2004
  fontWeight: 'medium',
1938
2005
  },
1939
2006
  escalation: {
1940
- backgroundColor: '#00aeff',
1941
- textColor: '#ffffff',
2007
+ backgroundColor: '#ededed',
2008
+ textColor: '#09090b',
1942
2009
  borderColor: 'transparent',
1943
2010
  borderWidth: 0,
1944
2011
  borderRadius: 8,
@@ -1948,21 +2015,21 @@ const DEFAULT_BUTTON_STYLES = {
1948
2015
  fontWeight: 'medium',
1949
2016
  },
1950
2017
  cardActions: {
1951
- backgroundColor: '#00aeff',
1952
- textColor: '#ffffff',
2018
+ backgroundColor: '#ededed',
2019
+ textColor: '#09090b',
1953
2020
  borderColor: 'transparent',
1954
2021
  borderWidth: 0,
1955
- borderRadius: 6,
2022
+ borderRadius: 8,
1956
2023
  paddingVertical: 6,
1957
2024
  paddingHorizontal: 12,
1958
2025
  fontSize: 12,
1959
2026
  fontWeight: 'medium',
1960
2027
  },
1961
2028
  toggleButton: {
1962
- backgroundColor: '#00aeff',
1963
- textColor: '#ffffff',
1964
- borderColor: 'transparent',
1965
- borderWidth: 0,
2029
+ backgroundColor: '#ededed',
2030
+ textColor: '#09090b',
2031
+ borderColor: '#27272a',
2032
+ borderWidth: 1,
1966
2033
  borderRadius: 30,
1967
2034
  paddingVertical: 0,
1968
2035
  paddingHorizontal: 0,
@@ -1971,7 +2038,7 @@ const DEFAULT_BUTTON_STYLES = {
1971
2038
  },
1972
2039
  attachButton: {
1973
2040
  backgroundColor: 'transparent',
1974
- textColor: '#6b7280',
2041
+ textColor: '#52525b',
1975
2042
  borderColor: 'transparent',
1976
2043
  borderWidth: 0,
1977
2044
  borderRadius: 8,