ttp-agent-sdk 2.34.0 → 2.34.4

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.
@@ -12543,7 +12543,15 @@ var LandingScreen = /*#__PURE__*/function () {
12543
12543
  key: "generateHTML",
12544
12544
  value: function generateHTML() {
12545
12545
  var landing = this.config.landing || {};
12546
- return "\n <div class=\"landing-screen\" id=\"landingScreen\">\n <!-- Avatar -->\n <div class=\"landing-avatar\">\n <span class=\"landing-avatar-emoji\">".concat(landing.logo || '🤖', "</span>\n </div>\n\n <!-- Title -->\n <h2 class=\"landing-title\">").concat(landing.title || this.t('landingTitle'), "</h2>\n <p class=\"landing-subtitle\">").concat(landing.subtitle || this.t('landingSubtitle') || 'Choose your preferred method', "</p>\n\n <!-- Mode Selection - Side by Side -->\n <div class=\"mode-selection\">\n <!-- Voice Call Option -->\n <button class=\"mode-card\" id=\"mode-card-voice\">\n <div class=\"mode-card-icon\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n <line x1=\"12\" y1=\"19\" x2=\"12\" y2=\"23\"/>\n <line x1=\"8\" y1=\"23\" x2=\"16\" y2=\"23\"/>\n </svg>\n </div>\n <span class=\"mode-card-title\">").concat(landing.voiceCardTitle || this.t('voiceCall'), "</span>\n </button>\n\n <!-- Text Chat Option -->\n <button class=\"mode-card\" id=\"mode-card-text\">\n <div class=\"mode-card-icon\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z\"/>\n </svg>\n </div>\n <span class=\"mode-card-title\">").concat(landing.textCardTitle || this.t('textChat'), "</span>\n </button>\n </div>\n </div>\n ");
12546
+
12547
+ // Determine logo content based on logoType
12548
+ var logoContent = '';
12549
+ if (landing.logoType === 'image' && landing.logoImageUrl) {
12550
+ logoContent = "<img src=\"".concat(landing.logoImageUrl, "\" alt=\"Logo\" style=\"max-width: 44px; max-height: 44px; object-fit: contain; border: none; outline: none;\">");
12551
+ } else {
12552
+ logoContent = "<span class=\"landing-avatar-emoji\">".concat(landing.logoIcon || landing.logo || '🤖', "</span>");
12553
+ }
12554
+ return "\n <div class=\"landing-screen\" id=\"landingScreen\">\n <!-- Avatar -->\n <div class=\"landing-avatar\">\n ".concat(logoContent, "\n </div>\n\n <!-- Title -->\n <h2 class=\"landing-title\">").concat(landing.title || this.t('landingTitle'), "</h2>\n <p class=\"landing-subtitle\">").concat(landing.subtitle || this.t('landingSubtitle') || 'Choose your preferred method', "</p>\n\n <!-- Mode Selection - Side by Side -->\n <div class=\"mode-selection\">\n <!-- Voice Call Option -->\n <button class=\"mode-card\" id=\"mode-card-voice\">\n <div class=\"mode-card-icon\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n <line x1=\"12\" y1=\"19\" x2=\"12\" y2=\"23\"/>\n <line x1=\"8\" y1=\"23\" x2=\"16\" y2=\"23\"/>\n </svg>\n </div>\n <span class=\"mode-card-title\">").concat(landing.voiceCardTitle || this.t('voiceCall'), "</span>\n </button>\n\n <!-- Text Chat Option -->\n <button class=\"mode-card\" id=\"mode-card-text\">\n <div class=\"mode-card-icon\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z\"/>\n </svg>\n </div>\n <span class=\"mode-card-title\">").concat(landing.textCardTitle || this.t('textChat'), "</span>\n </button>\n </div>\n </div>\n ");
12547
12555
  }
12548
12556
 
12549
12557
  /**
@@ -12553,13 +12561,26 @@ var LandingScreen = /*#__PURE__*/function () {
12553
12561
  key: "generateCSS",
12554
12562
  value: function generateCSS() {
12555
12563
  var landing = this.config.landing || {};
12556
- var header = this.config.header || {};
12557
12564
  var anim = this.config.animation || {};
12558
- var headerColor = header.backgroundColor || '#7C3AED';
12559
12565
 
12560
12566
  // Add !important when not using Shadow DOM
12561
12567
  var important = this.config.useShadowDOM === false ? ' !important' : '';
12562
- return "\n /* ===== LANDING SCREEN - New Design ===== */\n .landing-screen { \n display: none".concat(important, "; \n flex: 1; \n padding: 32px 24px; \n background: ").concat(landing.backgroundColor || 'linear-gradient(180deg, #ffffff 0%, rgba(168, 85, 247, 0.03) 100%)', "; \n align-items: center; \n justify-content: flex-start; \n flex-direction: column; \n gap: 0; \n overflow-y: auto; \n min-height: 0;\n text-align: center;\n }\n \n .landing-screen.active { \n display: flex").concat(important, "; \n }\n\n /* Avatar - Richer purple gradient */\n .landing-avatar {\n width: 88px;\n height: 88px;\n border-radius: 22px;\n margin-bottom: 20px;\n background: ").concat(landing.avatarBackground || 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', ";\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: 0 8px 28px rgba(102, 126, 234, 0.35);\n }\n\n .landing-avatar-emoji {\n font-size: 44px;\n line-height: 1;\n }\n\n /* Title & Subtitle */\n .landing-title { \n font-size: 20px; \n color: ").concat(landing.titleColor || '#1e1b4b', "; \n font-weight: 600; \n margin-bottom: 6px; \n text-align: center;\n line-height: 1.3;\n }\n\n .landing-subtitle {\n font-size: 14px;\n color: ").concat(landing.subtitleColor || '#64748b', ";\n margin-bottom: 28px;\n text-align: center;\n }\n\n /* Mode Selection - Side by Side */\n .mode-selection { \n display: flex; \n gap: 12px; \n width: 100%; \n justify-content: center; \n }\n\n .mode-card { \n flex: 1; \n max-width: 160px; \n padding: 20px 16px;\n background: ").concat(landing.modeCardBackgroundColor || '#ffffff', "; \n border: 1px solid ").concat(landing.modeCardBorderColor || 'rgba(0, 0, 0, 0.06)', "; \n border-radius: 18px; \n cursor: pointer; \n display: flex; \n flex-direction: column; \n align-items: center; \n gap: 12px; \n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); \n box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06); \n font-family: inherit;\n }\n\n .mode-card:hover { \n transform: translateY(-4px); \n box-shadow: 0 8px 24px rgba(124, 58, 237, 0.2); \n border-color: rgba(124, 58, 237, 0.3); \n }\n\n .mode-card:active {\n transform: translateY(-2px);\n }\n\n /* Mode Card Icon - Vibrant purple gradient */\n .mode-card-icon { \n width: 56px; \n height: 56px; \n display: flex; \n align-items: center; \n justify-content: center; \n border-radius: 16px; \n background: ").concat(landing.modeCardIconBackgroundColor || 'linear-gradient(135deg, #7c3aed, #a855f7)', "; \n color: #fff; \n box-shadow: 0 4px 14px rgba(124, 58, 237, 0.35);\n }\n\n .mode-card-icon svg {\n width: 26px;\n height: 26px;\n stroke: white;\n fill: none;\n }\n\n .mode-card-title { \n color: ").concat(landing.modeCardTitleColor || '#1e1b4b', "; \n font-weight: 600; \n font-size: 14px;\n text-align: center;\n }\n\n /* Mobile Responsive */\n @media (max-width: 768px) {\n .landing-screen {\n padding: 24px 16px;\n }\n\n .landing-avatar {\n width: 72px;\n height: 72px;\n border-radius: 18px;\n margin-bottom: 16px;\n }\n\n .landing-avatar-emoji {\n font-size: 36px;\n }\n\n .landing-title {\n font-size: 18px;\n }\n\n .landing-subtitle {\n font-size: 13px;\n margin-bottom: 20px;\n }\n\n .mode-selection {\n gap: 10px;\n }\n\n .mode-card {\n padding: 16px 12px;\n max-width: 140px;\n }\n\n .mode-card-icon {\n width: 48px;\n height: 48px;\n border-radius: 14px;\n }\n\n .mode-card-icon svg {\n width: 22px;\n height: 22px;\n }\n\n .mode-card-title {\n font-size: 13px;\n }\n }\n\n @media (max-width: 380px) {\n .mode-selection {\n flex-direction: column;\n align-items: center;\n }\n\n .mode-card {\n max-width: 100%;\n width: 100%;\n flex-direction: row;\n padding: 14px 18px;\n gap: 14px;\n }\n\n .mode-card-icon {\n flex-shrink: 0;\n }\n\n .mode-card-title {\n text-align: left;\n }\n }\n ");
12568
+ return "\n /* ===== LANDING SCREEN - New Design ===== */\n .landing-screen { \n display: none".concat(important, "; \n flex: 1; \n padding: 32px 24px; \n background: ").concat(landing.backgroundColor || 'linear-gradient(180deg, #ffffff 0%, rgba(168, 85, 247, 0.03) 100%)', "; \n align-items: center; \n justify-content: flex-start; \n flex-direction: column; \n gap: 0; \n overflow-y: auto; \n min-height: 0;\n text-align: center;\n }\n \n .landing-screen.active { \n display: flex").concat(important, "; \n }\n\n /* Avatar - Richer purple gradient */\n .landing-avatar {\n width: 88px;\n height: 88px;\n border-radius: 22px;\n margin-bottom: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n ").concat(function () {
12569
+ // Determine background based on logo type and background settings
12570
+ if (landing.logoType === 'image') {
12571
+ // For image logos, use logoBackgroundColor if enabled, otherwise transparent
12572
+ if (landing.logoBackgroundEnabled !== false) {
12573
+ var bgColor = landing.logoBackgroundColor || landing.avatarBackground || 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)';
12574
+ return "background: ".concat(bgColor, "; box-shadow: 0 8px 28px rgba(102, 126, 234, 0.35); border: none;");
12575
+ } else {
12576
+ return "background: transparent; box-shadow: none; border: none; outline: none;";
12577
+ }
12578
+ } else {
12579
+ // For icon logos, use avatarBackground (default behavior)
12580
+ var _bgColor = landing.avatarBackground || 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)';
12581
+ return "background: ".concat(_bgColor, "; box-shadow: 0 8px 28px rgba(102, 126, 234, 0.35); border: none;");
12582
+ }
12583
+ }(), "\n }\n \n .landing-avatar img {\n border: none !important;\n outline: none !important;\n }\n\n .landing-avatar-emoji {\n font-size: 44px;\n line-height: 1;\n }\n\n /* Title & Subtitle */\n .landing-title { \n font-size: 20px; \n color: ").concat(landing.titleColor || '#1e1b4b', "; \n font-weight: 600; \n margin-bottom: 6px; \n text-align: center;\n line-height: 1.3;\n }\n\n .landing-subtitle {\n font-size: 14px;\n color: ").concat(landing.subtitleColor || '#64748b', ";\n margin-bottom: 28px;\n text-align: center;\n }\n\n /* Mode Selection - Side by Side */\n .mode-selection { \n display: flex; \n gap: 12px; \n width: 100%; \n justify-content: center; \n }\n\n .mode-card { \n flex: 1; \n max-width: 160px; \n padding: 20px 16px;\n background: ").concat(landing.modeCardBackgroundColor || '#ffffff', "; \n border: 1px solid ").concat(landing.modeCardBorderColor || 'rgba(0, 0, 0, 0.06)', "; \n border-radius: 18px; \n cursor: pointer; \n display: flex; \n flex-direction: column; \n align-items: center; \n gap: 12px; \n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); \n box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06); \n font-family: inherit;\n }\n\n .mode-card:hover { \n transform: translateY(-4px); \n box-shadow: 0 8px 24px rgba(124, 58, 237, 0.2); \n border-color: rgba(124, 58, 237, 0.3); \n }\n\n .mode-card:active {\n transform: translateY(-2px);\n }\n\n /* Mode Card Icon - Vibrant purple gradient */\n .mode-card-icon { \n width: 56px; \n height: 56px; \n display: flex; \n align-items: center; \n justify-content: center; \n border-radius: 16px; \n background: ").concat(landing.modeCardIconBackgroundColor || 'linear-gradient(135deg, #7c3aed, #a855f7)', "; \n color: #fff; \n box-shadow: 0 4px 14px rgba(124, 58, 237, 0.35);\n }\n\n .mode-card-icon svg {\n width: 26px;\n height: 26px;\n stroke: white;\n fill: none;\n }\n\n .mode-card-title { \n color: ").concat(landing.modeCardTitleColor || '#1e1b4b', "; \n font-weight: 600; \n font-size: 14px;\n text-align: center;\n }\n\n /* Mobile Responsive */\n @media (max-width: 768px) {\n .landing-screen {\n padding: 24px 16px;\n }\n\n .landing-avatar {\n width: 72px;\n height: 72px;\n border-radius: 18px;\n margin-bottom: 16px;\n }\n\n .landing-avatar-emoji {\n font-size: 36px;\n }\n\n .landing-title {\n font-size: 18px;\n }\n\n .landing-subtitle {\n font-size: 13px;\n margin-bottom: 20px;\n }\n\n .mode-selection {\n gap: 10px;\n }\n\n .mode-card {\n padding: 16px 12px;\n max-width: 140px;\n }\n\n .mode-card-icon {\n width: 48px;\n height: 48px;\n border-radius: 14px;\n }\n\n .mode-card-icon svg {\n width: 22px;\n height: 22px;\n }\n\n .mode-card-title {\n font-size: 13px;\n }\n }\n\n @media (max-width: 380px) {\n .mode-selection {\n flex-direction: column;\n align-items: center;\n }\n\n .mode-card {\n max-width: 100%;\n width: 100%;\n flex-direction: row;\n padding: 14px 18px;\n gap: 14px;\n }\n\n .mode-card-icon {\n flex-shrink: 0;\n }\n\n .mode-card-title {\n text-align: left;\n }\n }\n ");
12563
12584
  }
12564
12585
 
12565
12586
  /**
@@ -12651,7 +12672,9 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
12651
12672
 
12652
12673
  var TTPChatWidget = /*#__PURE__*/function () {
12653
12674
  function TTPChatWidget() {
12654
- var _this$config$voice,
12675
+ var _this$config$text,
12676
+ _this$config$text2,
12677
+ _this$config$voice,
12655
12678
  _this$config$voice2,
12656
12679
  _this$config$voice3,
12657
12680
  _this$config$voice4,
@@ -12692,6 +12715,10 @@ var TTPChatWidget = /*#__PURE__*/function () {
12692
12715
  // Initialize interfaces with proper config (after shadow root is created)
12693
12716
  // Voice interface needs voice config merged with main config
12694
12717
  var voiceConfig = _objectSpread(_objectSpread(_objectSpread({}, this.config), this.config.voice), {}, {
12718
+ // Pass through text input placeholder for voice text input
12719
+ inputPlaceholder: ((_this$config$text = this.config.text) === null || _this$config$text === void 0 ? void 0 : _this$config$text.inputPlaceholder) || this.config.inputPlaceholder || 'Type your message...',
12720
+ // Pass through send button color for voice send button
12721
+ sendButtonColor: ((_this$config$text2 = this.config.text) === null || _this$config$text2 === void 0 ? void 0 : _this$config$text2.sendButtonColor) || this.config.sendButtonColor || '#7C3AED',
12695
12722
  language: ((_this$config$voice = this.config.voice) === null || _this$config$voice === void 0 ? void 0 : _this$config$voice.language) || this.config.language || 'en',
12696
12723
  signedUrl: this.config.signedUrl,
12697
12724
  // Pass through signedUrl if provided
@@ -12853,7 +12880,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
12853
12880
  }, {
12854
12881
  key: "mergeWithDefaults",
12855
12882
  value: function mergeWithDefaults(userConfig) {
12856
- var _userConfig$button, _userConfig$button2, _userConfig$header, _userConfig$icon, _userConfig$icon2, _userConfig$icon3, _userConfig$icon4, _userConfig$icon5, _userConfig$icon6, _userConfig$button3, _userConfig$button4, _userConfig$button5, _userConfig$icon7, _userConfig$button6, _userConfig$button7, _userConfig$button8, _userConfig$button9, _userConfig$icon8, _userConfig$panel, _userConfig$panel2, _userConfig$panel3, _userConfig$panel4, _userConfig$panel5, _userConfig$panel6, _userConfig$voice, _userConfig$panel7, _userConfig$voice2, _userConfig$panel8, _userConfig$voice3, _userConfig$panel9, _userConfig$voice4, _userConfig$panel0, _userConfig$voice5, _userConfig$panel1, _userConfig$voice6, _userConfig$panel10, _userConfig$voice7, _userConfig$voice8, _userConfig$voice9, _userConfig$voice0, _userConfig$voice1, _userConfig$voice10, _userConfig$voice11, _userConfig$voice12, _userConfig$voice13, _userConfig$voice14, _userConfig$voice15, _userConfig$voice16, _userConfig$voice17, _userConfig$voice18, _userConfig$voice19, _userConfig$voice20, _userConfig$text, _userConfig$panel11, _userConfig$text2, _userConfig$panel12, _userConfig$text3, _userConfig$panel13, _userConfig$text4, _userConfig$panel14, _userConfig$text5, _userConfig$panel15, _userConfig$text6, _userConfig$panel16, _userConfig$text7, _userConfig$panel17, _userConfig$text8, _userConfig$panel18, _userConfig$text9, _userConfig$panel19, _userConfig$text0, _userConfig$panel20, _userConfig$text1, _userConfig$panel21, _userConfig$text10, _userConfig$panel22, _userConfig$text11, _userConfig$panel23, _userConfig$text12, _userConfig$panel24, _userConfig$text13, _userConfig$panel25, _userConfig$text14, _userConfig$panel26, _userConfig$text15, _userConfig$panel27, _userConfig$text16, _userConfig$panel28, _userConfig$text17, _userConfig$panel29, _userConfig$landing, _userConfig$landing2, _userConfig$landing3, _userConfig$landing4, _userConfig$landing5, _userConfig$landing6, _userConfig$landing7, _userConfig$landing8, _userConfig$landing9, _userConfig$landing0, _userConfig$landing1, _userConfig$landing10, _userConfig$landing11, _userConfig$header2, _userConfig$header3, _userConfig$header4, _userConfig$header5, _userConfig$header6, _userConfig$footer, _userConfig$footer2, _userConfig$footer3, _userConfig$footer4, _userConfig$tooltips, _userConfig$tooltips2, _userConfig$tooltips3, _userConfig$tooltips4, _userConfig$tooltips5, _userConfig$tooltips6, _userConfig$messages, _userConfig$messages2, _userConfig$messages3, _userConfig$messages4, _userConfig$messages5, _userConfig$messages6, _userConfig$messages7, _userConfig$animation, _userConfig$animation2, _userConfig$animation3, _userConfig$animation4, _userConfig$behavior, _userConfig$behavior2, _userConfig$behavior3, _userConfig$behavior4, _userConfig$behavior5, _userConfig$behavior6, _userConfig$behavior7, _userConfig$behavior8, _userConfig$accessibi, _userConfig$accessibi2, _userConfig$accessibi3;
12883
+ var _userConfig$button, _userConfig$button2, _userConfig$icon, _userConfig$icon2, _userConfig$icon3, _userConfig$icon4, _userConfig$icon5, _userConfig$icon6, _userConfig$button3, _userConfig$button4, _userConfig$button5, _userConfig$icon7, _userConfig$button6, _userConfig$button7, _userConfig$button8, _userConfig$button9, _userConfig$icon8, _userConfig$panel, _userConfig$panel2, _userConfig$panel3, _userConfig$panel4, _userConfig$panel5, _userConfig$panel6, _userConfig$voice, _userConfig$panel7, _userConfig$voice2, _userConfig$panel8, _userConfig$voice3, _userConfig$panel9, _userConfig$voice4, _userConfig$panel0, _userConfig$voice5, _userConfig$panel1, _userConfig$voice6, _userConfig$panel10, _userConfig$voice7, _userConfig$voice8, _userConfig$voice9, _userConfig$voice0, _userConfig$voice1, _userConfig$voice10, _userConfig$voice11, _userConfig$voice12, _userConfig$voice13, _userConfig$voice14, _userConfig$voice15, _userConfig$voice16, _userConfig$voice17, _userConfig$voice18, _userConfig$voice19, _userConfig$voice20, _userConfig$voice21, _userConfig$voice22, _userConfig$text, _userConfig$panel11, _userConfig$text2, _userConfig$panel12, _userConfig$text3, _userConfig$panel13, _userConfig$text4, _userConfig$panel14, _userConfig$text5, _userConfig$panel15, _userConfig$text6, _userConfig$panel16, _userConfig$text7, _userConfig$panel17, _userConfig$text8, _userConfig$panel18, _userConfig$text9, _userConfig$panel19, _userConfig$text0, _userConfig$panel20, _userConfig$text1, _userConfig$panel21, _userConfig$text10, _userConfig$panel22, _userConfig$text11, _userConfig$panel23, _userConfig$text12, _userConfig$panel24, _userConfig$text13, _userConfig$panel25, _userConfig$text14, _userConfig$panel26, _userConfig$text15, _userConfig$panel27, _userConfig$text16, _userConfig$panel28, _userConfig$text17, _userConfig$panel29, _userConfig$footer, _userConfig$footer2, _userConfig$footer3, _userConfig$footer4, _userConfig$tooltips, _userConfig$tooltips2, _userConfig$tooltips3, _userConfig$tooltips4, _userConfig$tooltips5, _userConfig$tooltips6, _userConfig$messages, _userConfig$messages2, _userConfig$messages3, _userConfig$messages4, _userConfig$messages5, _userConfig$messages6, _userConfig$messages7, _userConfig$messages8, _userConfig$messages9, _userConfig$messages0, _userConfig$messages1, _userConfig$messages10, _userConfig$messages11, _userConfig$animation, _userConfig$animation2, _userConfig$animation3, _userConfig$animation4, _userConfig$promptAni, _userConfig$promptAni2, _userConfig$promptAni3, _userConfig$promptAni4, _userConfig$promptAni5, _userConfig$promptAni6, _userConfig$promptAni7, _userConfig$promptAni8, _userConfig$promptAni9, _userConfig$promptAni0, _userConfig$behavior, _userConfig$behavior2, _userConfig$behavior3, _userConfig$behavior4, _userConfig$behavior5, _userConfig$behavior6, _userConfig$behavior7, _userConfig$behavior8, _userConfig$accessibi, _userConfig$accessibi2, _userConfig$accessibi3;
12857
12884
  // Handle legacy position string format
12858
12885
  var positionConfig = userConfig.position || 'bottom-right';
12859
12886
  if (typeof positionConfig === 'string') {
@@ -12872,9 +12899,9 @@ var TTPChatWidget = /*#__PURE__*/function () {
12872
12899
  // Handle legacy primaryColor - default to white (for floating button)
12873
12900
  var primaryColor = userConfig.primaryColor || ((_userConfig$button = userConfig.button) === null || _userConfig$button === void 0 ? void 0 : _userConfig$button.primaryColor) || ((_userConfig$button2 = userConfig.button) === null || _userConfig$button2 === void 0 ? void 0 : _userConfig$button2.backgroundColor) || '#FFFFFF';
12874
12901
 
12875
- // Calculate headerColor for use in landing config (needed before landing config is defined)
12876
- // Header should default to purple (#7C3AED), not button color (white)
12877
- var headerColor = ((_userConfig$header = userConfig.header) === null || _userConfig$header === void 0 ? void 0 : _userConfig$header.backgroundColor) || '#7C3AED';
12902
+ // FIX: Don't calculate headerColor here - it causes buttons to inherit header color
12903
+ // Instead, use explicit defaults for landing screen colors that don't depend on header
12904
+
12878
12905
  return _objectSpread({
12879
12906
  // Required (agentId is required, appId is optional)
12880
12907
  agentId: userConfig.agentId,
@@ -12948,19 +12975,21 @@ var TTPChatWidget = /*#__PURE__*/function () {
12948
12975
  avatarActiveBackgroundColor: ((_userConfig$voice8 = userConfig.voice) === null || _userConfig$voice8 === void 0 ? void 0 : _userConfig$voice8.avatarActiveBackgroundColor) || '#667eea',
12949
12976
  statusTitleColor: ((_userConfig$voice9 = userConfig.voice) === null || _userConfig$voice9 === void 0 ? void 0 : _userConfig$voice9.statusTitleColor) || '#1e293b',
12950
12977
  statusSubtitleColor: ((_userConfig$voice0 = userConfig.voice) === null || _userConfig$voice0 === void 0 ? void 0 : _userConfig$voice0.statusSubtitleColor) || '#64748b',
12951
- startCallButtonColor: ((_userConfig$voice1 = userConfig.voice) === null || _userConfig$voice1 === void 0 ? void 0 : _userConfig$voice1.startCallButtonColor) || '#667eea',
12952
- startCallButtonTextColor: ((_userConfig$voice10 = userConfig.voice) === null || _userConfig$voice10 === void 0 ? void 0 : _userConfig$voice10.startCallButtonTextColor) || '#FFFFFF',
12953
- startCallTitle: ((_userConfig$voice11 = userConfig.voice) === null || _userConfig$voice11 === void 0 ? void 0 : _userConfig$voice11.startCallTitle) || null,
12954
- startCallSubtitle: ((_userConfig$voice12 = userConfig.voice) === null || _userConfig$voice12 === void 0 ? void 0 : _userConfig$voice12.startCallSubtitle) || null,
12955
- startCallButtonText: ((_userConfig$voice13 = userConfig.voice) === null || _userConfig$voice13 === void 0 ? void 0 : _userConfig$voice13.startCallButtonText) || null,
12956
- transcriptBackgroundColor: ((_userConfig$voice14 = userConfig.voice) === null || _userConfig$voice14 === void 0 ? void 0 : _userConfig$voice14.transcriptBackgroundColor) || '#FFFFFF',
12957
- transcriptTextColor: ((_userConfig$voice15 = userConfig.voice) === null || _userConfig$voice15 === void 0 ? void 0 : _userConfig$voice15.transcriptTextColor) || '#1e293b',
12958
- transcriptLabelColor: ((_userConfig$voice16 = userConfig.voice) === null || _userConfig$voice16 === void 0 ? void 0 : _userConfig$voice16.transcriptLabelColor) || '#94a3b8',
12959
- controlButtonColor: ((_userConfig$voice17 = userConfig.voice) === null || _userConfig$voice17 === void 0 ? void 0 : _userConfig$voice17.controlButtonColor) || '#FFFFFF',
12960
- controlButtonSecondaryColor: ((_userConfig$voice18 = userConfig.voice) === null || _userConfig$voice18 === void 0 ? void 0 : _userConfig$voice18.controlButtonSecondaryColor) || '#64748b',
12961
- endCallButtonColor: ((_userConfig$voice19 = userConfig.voice) === null || _userConfig$voice19 === void 0 ? void 0 : _userConfig$voice19.endCallButtonColor) || '#ef4444',
12978
+ statusDotColor: ((_userConfig$voice1 = userConfig.voice) === null || _userConfig$voice1 === void 0 ? void 0 : _userConfig$voice1.statusDotColor) || '#10b981',
12979
+ statusText: ((_userConfig$voice10 = userConfig.voice) === null || _userConfig$voice10 === void 0 ? void 0 : _userConfig$voice10.statusText) || null,
12980
+ startCallButtonColor: ((_userConfig$voice11 = userConfig.voice) === null || _userConfig$voice11 === void 0 ? void 0 : _userConfig$voice11.startCallButtonColor) || '#667eea',
12981
+ startCallButtonTextColor: ((_userConfig$voice12 = userConfig.voice) === null || _userConfig$voice12 === void 0 ? void 0 : _userConfig$voice12.startCallButtonTextColor) || '#FFFFFF',
12982
+ startCallTitle: ((_userConfig$voice13 = userConfig.voice) === null || _userConfig$voice13 === void 0 ? void 0 : _userConfig$voice13.startCallTitle) || null,
12983
+ startCallSubtitle: ((_userConfig$voice14 = userConfig.voice) === null || _userConfig$voice14 === void 0 ? void 0 : _userConfig$voice14.startCallSubtitle) || null,
12984
+ startCallButtonText: ((_userConfig$voice15 = userConfig.voice) === null || _userConfig$voice15 === void 0 ? void 0 : _userConfig$voice15.startCallButtonText) || null,
12985
+ transcriptBackgroundColor: ((_userConfig$voice16 = userConfig.voice) === null || _userConfig$voice16 === void 0 ? void 0 : _userConfig$voice16.transcriptBackgroundColor) || '#FFFFFF',
12986
+ transcriptTextColor: ((_userConfig$voice17 = userConfig.voice) === null || _userConfig$voice17 === void 0 ? void 0 : _userConfig$voice17.transcriptTextColor) || '#1e293b',
12987
+ transcriptLabelColor: ((_userConfig$voice18 = userConfig.voice) === null || _userConfig$voice18 === void 0 ? void 0 : _userConfig$voice18.transcriptLabelColor) || '#94a3b8',
12988
+ controlButtonColor: ((_userConfig$voice19 = userConfig.voice) === null || _userConfig$voice19 === void 0 ? void 0 : _userConfig$voice19.controlButtonColor) || '#FFFFFF',
12989
+ controlButtonSecondaryColor: ((_userConfig$voice20 = userConfig.voice) === null || _userConfig$voice20 === void 0 ? void 0 : _userConfig$voice20.controlButtonSecondaryColor) || '#64748b',
12990
+ endCallButtonColor: ((_userConfig$voice21 = userConfig.voice) === null || _userConfig$voice21 === void 0 ? void 0 : _userConfig$voice21.endCallButtonColor) || '#ef4444',
12962
12991
  // Voice language setting
12963
- language: ((_userConfig$voice20 = userConfig.voice) === null || _userConfig$voice20 === void 0 ? void 0 : _userConfig$voice20.language) || userConfig.language || 'en'
12992
+ language: ((_userConfig$voice22 = userConfig.voice) === null || _userConfig$voice22 === void 0 ? void 0 : _userConfig$voice22.language) || userConfig.language || 'en'
12964
12993
  }, userConfig.voice),
12965
12994
  // Text-specific Configuration
12966
12995
  text: _objectSpread({
@@ -12992,31 +13021,73 @@ var TTPChatWidget = /*#__PURE__*/function () {
12992
13021
  inputPadding: ((_userConfig$text17 = userConfig.text) === null || _userConfig$text17 === void 0 ? void 0 : _userConfig$text17.inputPadding) || ((_userConfig$panel29 = userConfig.panel) === null || _userConfig$panel29 === void 0 ? void 0 : _userConfig$panel29.inputPadding) || '6px 14px'
12993
13022
  }, userConfig.text),
12994
13023
  // Landing Screen Configuration (only for unified mode)
12995
- landing: _objectSpread({
12996
- backgroundColor: ((_userConfig$landing = userConfig.landing) === null || _userConfig$landing === void 0 ? void 0 : _userConfig$landing.backgroundColor) || 'linear-gradient(180deg, #f8fafc 0%, #e0e7ff 100%)',
12997
- logo: ((_userConfig$landing2 = userConfig.landing) === null || _userConfig$landing2 === void 0 ? void 0 : _userConfig$landing2.logo) || '🤖',
12998
- title: ((_userConfig$landing3 = userConfig.landing) === null || _userConfig$landing3 === void 0 ? void 0 : _userConfig$landing3.title) || null,
12999
- // null means use default translated text
13000
- titleColor: ((_userConfig$landing4 = userConfig.landing) === null || _userConfig$landing4 === void 0 ? void 0 : _userConfig$landing4.titleColor) || '#1e293b',
13001
- modeCardBackgroundColor: ((_userConfig$landing5 = userConfig.landing) === null || _userConfig$landing5 === void 0 ? void 0 : _userConfig$landing5.modeCardBackgroundColor) || '#FFFFFF',
13002
- modeCardBorderColor: ((_userConfig$landing6 = userConfig.landing) === null || _userConfig$landing6 === void 0 ? void 0 : _userConfig$landing6.modeCardBorderColor) || '#E2E8F0',
13003
- modeCardHoverBorderColor: ((_userConfig$landing7 = userConfig.landing) === null || _userConfig$landing7 === void 0 ? void 0 : _userConfig$landing7.modeCardHoverBorderColor) || headerColor,
13004
- modeCardIconBackgroundColor: ((_userConfig$landing8 = userConfig.landing) === null || _userConfig$landing8 === void 0 ? void 0 : _userConfig$landing8.modeCardIconBackgroundColor) || headerColor,
13005
- modeCardTitleColor: ((_userConfig$landing9 = userConfig.landing) === null || _userConfig$landing9 === void 0 ? void 0 : _userConfig$landing9.modeCardTitleColor) || '#111827',
13006
- voiceCardIcon: ((_userConfig$landing0 = userConfig.landing) === null || _userConfig$landing0 === void 0 ? void 0 : _userConfig$landing0.voiceCardIcon) || '🎤',
13007
- textCardIcon: ((_userConfig$landing1 = userConfig.landing) === null || _userConfig$landing1 === void 0 ? void 0 : _userConfig$landing1.textCardIcon) || '💬',
13008
- voiceCardTitle: ((_userConfig$landing10 = userConfig.landing) === null || _userConfig$landing10 === void 0 ? void 0 : _userConfig$landing10.voiceCardTitle) || null,
13009
- textCardTitle: ((_userConfig$landing11 = userConfig.landing) === null || _userConfig$landing11 === void 0 ? void 0 : _userConfig$landing11.textCardTitle) || null
13010
- }, userConfig.landing),
13024
+ // FIX: Use explicit defaults instead of headerColor to prevent buttons from inheriting header color
13025
+ landing: function () {
13026
+ // Filter out empty strings from userConfig.landing to prevent overriding defaults
13027
+ var cleanLandingConfig = {};
13028
+ if (userConfig.landing) {
13029
+ Object.keys(userConfig.landing).forEach(function (key) {
13030
+ var value = userConfig.landing[key];
13031
+ // Include non-empty values, but also include boolean false values
13032
+ // Skip only: null, undefined, and empty strings
13033
+ if (value !== null && value !== undefined && value !== '') {
13034
+ cleanLandingConfig[key] = value;
13035
+ } else if (value === false) {
13036
+ // Explicitly include false boolean values (e.g., logoBackgroundEnabled: false)
13037
+ cleanLandingConfig[key] = value;
13038
+ }
13039
+ });
13040
+ }
13041
+ return _objectSpread({
13042
+ backgroundColor: cleanLandingConfig.backgroundColor || 'linear-gradient(180deg, #f8fafc 0%, #e0e7ff 100%)',
13043
+ logo: cleanLandingConfig.logo || '🤖',
13044
+ title: cleanLandingConfig.title || null,
13045
+ // null means use default translated text
13046
+ titleColor: cleanLandingConfig.titleColor || '#1e293b',
13047
+ modeCardBackgroundColor: cleanLandingConfig.modeCardBackgroundColor || '#FFFFFF',
13048
+ modeCardBorderColor: cleanLandingConfig.modeCardBorderColor || '#E2E8F0',
13049
+ modeCardHoverBorderColor: cleanLandingConfig.modeCardHoverBorderColor || '#7C3AED',
13050
+ // Fixed: Use explicit default instead of headerColor
13051
+ modeCardIconBackgroundColor: cleanLandingConfig.modeCardIconBackgroundColor || '#7C3AED',
13052
+ // Fixed: Use explicit default instead of headerColor
13053
+ modeCardTitleColor: cleanLandingConfig.modeCardTitleColor || '#111827',
13054
+ voiceCardIcon: cleanLandingConfig.voiceCardIcon || '🎤',
13055
+ textCardIcon: cleanLandingConfig.textCardIcon || '💬',
13056
+ voiceCardTitle: cleanLandingConfig.voiceCardTitle || null,
13057
+ textCardTitle: cleanLandingConfig.textCardTitle || null
13058
+ }, cleanLandingConfig);
13059
+ }(),
13011
13060
  // Header Configuration (top of panel)
13012
- header: _objectSpread({
13013
- title: ((_userConfig$header2 = userConfig.header) === null || _userConfig$header2 === void 0 ? void 0 : _userConfig$header2.title) || 'Chat Assistant',
13014
- showTitle: ((_userConfig$header3 = userConfig.header) === null || _userConfig$header3 === void 0 ? void 0 : _userConfig$header3.showTitle) !== false,
13015
- backgroundColor: ((_userConfig$header4 = userConfig.header) === null || _userConfig$header4 === void 0 ? void 0 : _userConfig$header4.backgroundColor) || '#7C3AED',
13016
- // Default purple (not button backgroundColor which is white)
13017
- textColor: ((_userConfig$header5 = userConfig.header) === null || _userConfig$header5 === void 0 ? void 0 : _userConfig$header5.textColor) || '#FFFFFF',
13018
- showCloseButton: ((_userConfig$header6 = userConfig.header) === null || _userConfig$header6 === void 0 ? void 0 : _userConfig$header6.showCloseButton) !== false
13019
- }, userConfig.header),
13061
+ header: function () {
13062
+ // Filter out empty strings to prevent overriding defaults
13063
+ var cleanHeaderConfig = {};
13064
+ if (userConfig.header) {
13065
+ Object.keys(userConfig.header).forEach(function (key) {
13066
+ var value = userConfig.header[key];
13067
+ // For online indicator properties, allow empty strings (they might be intentionally set)
13068
+ // For other properties, only include non-empty values
13069
+ if (key.startsWith('onlineIndicator')) {
13070
+ if (value !== null && value !== undefined) {
13071
+ cleanHeaderConfig[key] = value;
13072
+ }
13073
+ } else {
13074
+ // Only include non-empty values (skip empty strings, null, undefined)
13075
+ if (value !== null && value !== undefined && value !== '') {
13076
+ cleanHeaderConfig[key] = value;
13077
+ }
13078
+ }
13079
+ });
13080
+ }
13081
+ var finalHeader = _objectSpread({
13082
+ title: cleanHeaderConfig.title || 'Chat Assistant',
13083
+ showTitle: cleanHeaderConfig.showTitle !== false,
13084
+ backgroundColor: cleanHeaderConfig.backgroundColor || '#7C3AED',
13085
+ // Default purple
13086
+ textColor: cleanHeaderConfig.textColor || '#FFFFFF',
13087
+ showCloseButton: cleanHeaderConfig.showCloseButton !== false
13088
+ }, cleanHeaderConfig);
13089
+ return finalHeader;
13090
+ }(),
13020
13091
  // Footer Configuration (TTP Branding - always shown by default)
13021
13092
  footer: _objectSpread({
13022
13093
  show: ((_userConfig$footer = userConfig.footer) === null || _userConfig$footer === void 0 ? void 0 : _userConfig$footer.show) !== false,
@@ -13042,8 +13113,13 @@ var TTPChatWidget = /*#__PURE__*/function () {
13042
13113
  systemBackgroundColor: ((_userConfig$messages3 = userConfig.messages) === null || _userConfig$messages3 === void 0 ? void 0 : _userConfig$messages3.systemBackgroundColor) || '#DCFCE7',
13043
13114
  errorBackgroundColor: ((_userConfig$messages4 = userConfig.messages) === null || _userConfig$messages4 === void 0 ? void 0 : _userConfig$messages4.errorBackgroundColor) || '#FEE2E2',
13044
13115
  textColor: ((_userConfig$messages5 = userConfig.messages) === null || _userConfig$messages5 === void 0 ? void 0 : _userConfig$messages5.textColor) || '#1F2937',
13045
- fontSize: ((_userConfig$messages6 = userConfig.messages) === null || _userConfig$messages6 === void 0 ? void 0 : _userConfig$messages6.fontSize) || '14px',
13046
- borderRadius: ((_userConfig$messages7 = userConfig.messages) === null || _userConfig$messages7 === void 0 ? void 0 : _userConfig$messages7.borderRadius) || 8
13116
+ // Fallback for backward compatibility
13117
+ userTextColor: ((_userConfig$messages6 = userConfig.messages) === null || _userConfig$messages6 === void 0 ? void 0 : _userConfig$messages6.userTextColor) || ((_userConfig$messages7 = userConfig.messages) === null || _userConfig$messages7 === void 0 ? void 0 : _userConfig$messages7.textColor) || '#1F2937',
13118
+ agentTextColor: ((_userConfig$messages8 = userConfig.messages) === null || _userConfig$messages8 === void 0 ? void 0 : _userConfig$messages8.agentTextColor) || ((_userConfig$messages9 = userConfig.messages) === null || _userConfig$messages9 === void 0 ? void 0 : _userConfig$messages9.textColor) || '#1F2937',
13119
+ userAvatarIcon: ((_userConfig$messages0 = userConfig.messages) === null || _userConfig$messages0 === void 0 ? void 0 : _userConfig$messages0.userAvatarIcon) || '👤',
13120
+ agentAvatarIcon: ((_userConfig$messages1 = userConfig.messages) === null || _userConfig$messages1 === void 0 ? void 0 : _userConfig$messages1.agentAvatarIcon) || '🤖',
13121
+ fontSize: ((_userConfig$messages10 = userConfig.messages) === null || _userConfig$messages10 === void 0 ? void 0 : _userConfig$messages10.fontSize) || '14px',
13122
+ borderRadius: ((_userConfig$messages11 = userConfig.messages) === null || _userConfig$messages11 === void 0 ? void 0 : _userConfig$messages11.borderRadius) || 16
13047
13123
  }, userConfig.messages),
13048
13124
  // Animation Configuration
13049
13125
  animation: _objectSpread({
@@ -13052,6 +13128,25 @@ var TTPChatWidget = /*#__PURE__*/function () {
13052
13128
  enableSlide: ((_userConfig$animation3 = userConfig.animation) === null || _userConfig$animation3 === void 0 ? void 0 : _userConfig$animation3.enableSlide) !== false,
13053
13129
  duration: ((_userConfig$animation4 = userConfig.animation) === null || _userConfig$animation4 === void 0 ? void 0 : _userConfig$animation4.duration) || 0.3
13054
13130
  }, userConfig.animation),
13131
+ // Prompt Animation Configuration
13132
+ promptAnimation: _objectSpread({
13133
+ enabled: ((_userConfig$promptAni = userConfig.promptAnimation) === null || _userConfig$promptAni === void 0 ? void 0 : _userConfig$promptAni.enabled) === true,
13134
+ // Default false
13135
+ text: ((_userConfig$promptAni2 = userConfig.promptAnimation) === null || _userConfig$promptAni2 === void 0 ? void 0 : _userConfig$promptAni2.text) || 'Try me!',
13136
+ backgroundColor: ((_userConfig$promptAni3 = userConfig.promptAnimation) === null || _userConfig$promptAni3 === void 0 ? void 0 : _userConfig$promptAni3.backgroundColor) || 'linear-gradient(135deg, #7c3aed, #4f46e5)',
13137
+ textColor: ((_userConfig$promptAni4 = userConfig.promptAnimation) === null || _userConfig$promptAni4 === void 0 ? void 0 : _userConfig$promptAni4.textColor) || '#ffffff',
13138
+ animationType: ((_userConfig$promptAni5 = userConfig.promptAnimation) === null || _userConfig$promptAni5 === void 0 ? void 0 : _userConfig$promptAni5.animationType) || 'bounce',
13139
+ // 'bounce' | 'pulse' | 'float' | 'none'
13140
+ showShimmer: ((_userConfig$promptAni6 = userConfig.promptAnimation) === null || _userConfig$promptAni6 === void 0 ? void 0 : _userConfig$promptAni6.showShimmer) !== false,
13141
+ // Default true
13142
+ showPulseRings: ((_userConfig$promptAni7 = userConfig.promptAnimation) === null || _userConfig$promptAni7 === void 0 ? void 0 : _userConfig$promptAni7.showPulseRings) !== false,
13143
+ // Default true
13144
+ hideAfterClick: ((_userConfig$promptAni8 = userConfig.promptAnimation) === null || _userConfig$promptAni8 === void 0 ? void 0 : _userConfig$promptAni8.hideAfterClick) !== false,
13145
+ // Default true
13146
+ hideAfterSeconds: ((_userConfig$promptAni9 = userConfig.promptAnimation) === null || _userConfig$promptAni9 === void 0 ? void 0 : _userConfig$promptAni9.hideAfterSeconds) !== undefined ? userConfig.promptAnimation.hideAfterSeconds : null,
13147
+ // null = never
13148
+ position: ((_userConfig$promptAni0 = userConfig.promptAnimation) === null || _userConfig$promptAni0 === void 0 ? void 0 : _userConfig$promptAni0.position) || 'top'
13149
+ }, userConfig.promptAnimation),
13055
13150
  // Behavior Configuration
13056
13151
  behavior: _objectSpread({
13057
13152
  autoOpen: ((_userConfig$behavior = userConfig.behavior) === null || _userConfig$behavior === void 0 ? void 0 : _userConfig$behavior.autoOpen) || false,
@@ -13177,6 +13272,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
13177
13272
  }, {
13178
13273
  key: "createWidget",
13179
13274
  value: function createWidget() {
13275
+ var _this4 = this;
13180
13276
  // Ensure container exists
13181
13277
  if (!this.container) {
13182
13278
  if (this.config.useShadowDOM) {
@@ -13216,8 +13312,29 @@ var TTPChatWidget = /*#__PURE__*/function () {
13216
13312
  if (this.config.behavior.startOpen || this.config.behavior.autoOpen) {
13217
13313
  this.isOpen = true;
13218
13314
  panel.classList.add('open');
13315
+ // Hide prompt if widget starts open
13316
+ this.hidePrompt();
13317
+ } else {
13318
+ // Widget starts closed - show prompt
13319
+ this.showPrompt();
13219
13320
  }
13321
+ } else {
13322
+ // Panel not found yet, but widget should start closed - show prompt
13323
+ // Use setTimeout to ensure prompt HTML is generated first
13324
+ setTimeout(function () {
13325
+ _this4.showPrompt();
13326
+ }, 100);
13220
13327
  }
13328
+
13329
+ // Also ensure prompt visibility is correct after a short delay
13330
+ // This handles cases where setupPromptAnimation was called before widget HTML was ready
13331
+ setTimeout(function () {
13332
+ if (!_this4.isOpen) {
13333
+ _this4.showPrompt();
13334
+ } else {
13335
+ _this4.hidePrompt();
13336
+ }
13337
+ }, 200);
13221
13338
  }
13222
13339
 
13223
13340
  /**
@@ -13268,7 +13385,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
13268
13385
  key: "generateWidgetHTML",
13269
13386
  value: function generateWidgetHTML() {
13270
13387
  var _this$config$behavior3,
13271
- _this4 = this;
13388
+ _this5 = this;
13272
13389
  var pos = this.config.position;
13273
13390
  var btn = this.config.button;
13274
13391
  var icon = this.config.icon;
@@ -13307,15 +13424,15 @@ var TTPChatWidget = /*#__PURE__*/function () {
13307
13424
 
13308
13425
  // Helper function to get translated text
13309
13426
  var t = function t(key) {
13310
- var lang = _this4.config.language || 'en';
13311
- var translations = _this4.translations[lang] || _this4.translations.en;
13427
+ var lang = _this5.config.language || 'en';
13428
+ var translations = _this5.translations[lang] || _this5.translations.en;
13312
13429
  return translations[key] || key;
13313
13430
  };
13314
13431
 
13315
13432
  // Helper function to get tooltip text
13316
13433
  var getTooltip = function getTooltip(key) {
13317
- var _this4$config$tooltip;
13318
- var tooltip = (_this4$config$tooltip = _this4.config.tooltips) === null || _this4$config$tooltip === void 0 ? void 0 : _this4$config$tooltip[key];
13434
+ var _this5$config$tooltip;
13435
+ var tooltip = (_this5$config$tooltip = _this5.config.tooltips) === null || _this5$config$tooltip === void 0 ? void 0 : _this5$config$tooltip[key];
13319
13436
  if (tooltip !== null && tooltip !== undefined) return tooltip;
13320
13437
  // Use translations for default tooltips
13321
13438
  var defaults = {
@@ -13331,7 +13448,20 @@ var TTPChatWidget = /*#__PURE__*/function () {
13331
13448
 
13332
13449
  // Only include style tag in Shadow DOM mode (styles injected into head for regular DOM)
13333
13450
  var styleTag = this.config.useShadowDOM ? "\n <style>\n ".concat(this.generateCSS(positionStyles, buttonSize, iconSize), "\n ").concat(this.config.customStyles, "\n </style>\n ") : '';
13334
- return "\n ".concat(styleTag, "\n \n ").concat(this.config.behavior.hidden ? '' : "\n <button id=\"text-chat-button\" \n aria-label=\"".concat(this.config.accessibility.ariaLabel, "\"\n aria-description=\"").concat(this.config.accessibility.ariaDescription, "\">\n ").concat(iconHTML, "\n </button>\n "), "\n \n <div id=\"text-chat-panel\">\n <div class=\"widget-shell\">\n <div class=\"panel-inner widget-container\" style=\"direction: ").concat(this.config.direction, ";\">\n <div class=\"widget-header\" style=\"background: linear-gradient(135deg, #581c87, #7c3aed); color: ").concat(header.textColor, ";\">\n <div>\n ").concat(header.showTitle ? "<div class=\"header-title\">".concat(header.title, "</div>") : '', "\n <div class=\"header-status\">\n <span class=\"status-dot\"></span>\n <span>").concat(t('online'), "</span>\n </div>\n </div>\n \n <div style=\"display: flex; gap: 6px; align-items: center; position: relative; z-index: 1;\">\n <!-- New Chat Button (hide on landing screen, show otherwise) -->\n <button class=\"header-icon new-chat-btn\" id=\"newChatBtn\" title=\"").concat(getTooltip('newChat'), "\" style=\"").concat(showLanding ? 'display: none;' : '', "\">\n <span style=\"font-size: 18px; font-weight: bold;\">+</span>\n </button>\n \n <!-- Back Button (only show in unified mode) -->\n ").concat(widgetMode === 'unified' ? "<button class=\"header-icon back-btn\" id=\"backBtn\" title=\"".concat(getTooltip('back'), "\" style=\"display: none;\">\n <span style=\"font-size: 16px;\">\u2039</span>\n </button>") : '', "\n \n <!-- Close Button -->\n ").concat(header.showCloseButton ? '<button class="header-icon close-btn" id="closeBtn" title="' + getTooltip('close') + '">' + '<span style="font-size: 18px; font-weight: bold;">×</span>' + '</button>' : '', "\n </div>\n </div>\n\n ").concat(showLanding && this.landingScreen ? this.landingScreen.generateHTML() : '', "\n\n ").concat(showVoice ? this.voiceInterface.generateHTML() : '', "\n ").concat(showText ? this.textInterface.generateHTML() : '', "\n ").concat(this.generateFooterHTML(), "\n </div>\n </div>\n </div>\n ");
13451
+
13452
+ // Generate prompt bubble HTML if enabled
13453
+ var promptConfig = this.config.promptAnimation || {};
13454
+ // Default to disabled if not specified (enabled === true means explicitly enabled)
13455
+ var isPromptEnabled = promptConfig.enabled === true;
13456
+ var promptBubbleHTML = isPromptEnabled ? this.generatePromptBubbleHTML(promptConfig, buttonSize) : '';
13457
+ console.log('📝 generateWidgetHTML - promptAnimation:', {
13458
+ hasConfig: !!this.config.promptAnimation,
13459
+ promptConfig: promptConfig,
13460
+ enabled: promptConfig.enabled,
13461
+ isPromptEnabled: isPromptEnabled,
13462
+ willGenerateHTML: !!promptBubbleHTML
13463
+ });
13464
+ return "\n ".concat(styleTag, "\n \n ").concat(this.config.behavior.hidden ? '' : "\n <div id=\"text-chat-button-container\">\n ".concat(promptBubbleHTML, "\n ").concat(isPromptEnabled && promptConfig.showPulseRings !== false ? this.generatePulseRingsHTML(promptConfig) : '', "\n <button id=\"text-chat-button\" \n aria-label=\"").concat(this.config.accessibility.ariaLabel, "\"\n aria-description=\"").concat(this.config.accessibility.ariaDescription, "\">\n ").concat(iconHTML, "\n </button>\n </div>\n "), "\n \n <div id=\"text-chat-panel\">\n <div class=\"widget-shell\">\n <div class=\"panel-inner widget-container\" style=\"direction: ").concat(this.config.direction, ";\">\n <div class=\"widget-header\" style=\"background: ").concat(header.backgroundColor || '#7C3AED', " !important; color: ").concat(header.textColor || '#FFFFFF', " !important;\">\n <div>\n ").concat(header.showTitle ? "<div class=\"header-title\">".concat(header.title, "</div>") : '', "\n <div class=\"header-status\" style=\"color: ").concat(header.onlineIndicatorColor || 'rgba(255,255,255,0.7)', " !important;\">\n <span class=\"status-dot\" style=\"background: ").concat(header.onlineIndicatorDotColor || '#10b981', " !important;\"></span>\n <span>").concat(header.onlineIndicatorText !== undefined && header.onlineIndicatorText !== null ? header.onlineIndicatorText : t('online'), "</span>\n </div>\n </div>\n \n <div style=\"display: flex; gap: 6px; align-items: center; position: relative; z-index: 1;\">\n <!-- New Chat Button (hide on landing screen, show otherwise) -->\n <button class=\"header-icon new-chat-btn\" id=\"newChatBtn\" title=\"").concat(getTooltip('newChat'), "\" style=\"").concat(showLanding ? 'display: none;' : '', "\">\n <span style=\"font-size: 18px; font-weight: bold;\">+</span>\n </button>\n \n <!-- Back Button (only show in unified mode) -->\n ").concat(widgetMode === 'unified' ? "<button class=\"header-icon back-btn\" id=\"backBtn\" title=\"".concat(getTooltip('back'), "\" style=\"display: none;\">\n <span style=\"font-size: 16px;\">\u2039</span>\n </button>") : '', "\n \n <!-- Close Button -->\n ").concat(header.showCloseButton ? '<button class="header-icon close-btn" id="closeBtn" title="' + getTooltip('close') + '">' + '<span style="font-size: 18px; font-weight: bold;">×</span>' + '</button>' : '', "\n </div>\n </div>\n\n ").concat(showLanding && this.landingScreen ? this.landingScreen.generateHTML() : '', "\n\n ").concat(showVoice ? this.voiceInterface.generateHTML() : '', "\n ").concat(showText ? this.textInterface.generateHTML() : '', "\n ").concat(this.generateFooterHTML(), "\n </div>\n </div>\n </div>\n ");
13335
13465
  }
13336
13466
 
13337
13467
  /**
@@ -13393,6 +13523,47 @@ var TTPChatWidget = /*#__PURE__*/function () {
13393
13523
  return "<svg viewBox=\"0 0 24 24\" style=\"width: ".concat(size, "px; height: ").concat(size, "px; fill: white;\">\n <path d=\"M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H6l-2 2V4h16v12z\"/>\n </svg>");
13394
13524
  }
13395
13525
  }
13526
+
13527
+ /**
13528
+ * Generate prompt bubble HTML
13529
+ */
13530
+ }, {
13531
+ key: "generatePromptBubbleHTML",
13532
+ value: function generatePromptBubbleHTML(promptConfig, buttonSize) {
13533
+ // Extract solid color from gradient for arrow (fallback)
13534
+ var arrowColor = '#7c3aed';
13535
+ if (promptConfig.backgroundColor && promptConfig.backgroundColor.includes('gradient')) {
13536
+ // Try to extract first color from gradient
13537
+ var match = promptConfig.backgroundColor.match(/#[0-9a-fA-F]{6}/);
13538
+ if (match) {
13539
+ arrowColor = match[0];
13540
+ }
13541
+ } else {
13542
+ arrowColor = promptConfig.backgroundColor;
13543
+ }
13544
+ var animationClass = promptConfig.animationType === 'none' ? '' : "animation-".concat(promptConfig.animationType);
13545
+ var shimmerHTML = promptConfig.showShimmer ? '<div class="prompt-bubble-shimmer"></div>' : '';
13546
+ return "\n <div class=\"prompt-bubble ".concat(promptConfig.position, " ").concat(animationClass, "\" \n id=\"prompt-bubble\"\n role=\"tooltip\"\n style=\"--prompt-bubble-bg-color: ").concat(arrowColor, ";\">\n <div class=\"prompt-bubble-content\" \n style=\"background: ").concat(promptConfig.backgroundColor, "; color: ").concat(promptConfig.textColor, ";\">\n ").concat(shimmerHTML, "\n <span style=\"position: relative; z-index: 1;\">").concat(promptConfig.text, "</span>\n </div>\n <div class=\"prompt-bubble-arrow\"></div>\n </div>\n ");
13547
+ }
13548
+
13549
+ /**
13550
+ * Generate pulse rings HTML
13551
+ */
13552
+ }, {
13553
+ key: "generatePulseRingsHTML",
13554
+ value: function generatePulseRingsHTML(promptConfig) {
13555
+ // Extract solid color from gradient for rings (fallback)
13556
+ var ringColor = '#7c3aed';
13557
+ if (promptConfig.backgroundColor && promptConfig.backgroundColor.includes('gradient')) {
13558
+ var match = promptConfig.backgroundColor.match(/#[0-9a-fA-F]{6}/);
13559
+ if (match) {
13560
+ ringColor = match[0];
13561
+ }
13562
+ } else {
13563
+ ringColor = promptConfig.backgroundColor;
13564
+ }
13565
+ return "\n <div class=\"prompt-pulse-rings\" id=\"prompt-pulse-rings\">\n <div class=\"prompt-pulse-ring\" style=\"background-color: ".concat(ringColor, "33;\"></div>\n <div class=\"prompt-pulse-ring\" style=\"background-color: ").concat(ringColor, "1a;\"></div>\n </div>\n ");
13566
+ }
13396
13567
  }, {
13397
13568
  key: "generateCSS",
13398
13569
  value: function generateCSS(positionStyles, buttonSize, iconSize) {
@@ -13413,20 +13584,28 @@ var TTPChatWidget = /*#__PURE__*/function () {
13413
13584
  // Add !important to display rules when not using Shadow DOM (to override theme CSS)
13414
13585
  var important = this.config.useShadowDOM === false ? ' !important' : '';
13415
13586
 
13416
- // Color references for clarity (needed for landing screen styles)
13417
- var headerColor = header.backgroundColor;
13418
- return "\n /* MOBILE FIRST - Default styles for all devices */\n #text-chat-widget {\n position: fixed !important;\n z-index: 10000;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n /* Mobile defaults */\n right: 10px;\n bottom: 10px;\n left: auto;\n top: auto;\n }\n \n /* Desktop positioning (only on larger screens) */\n @media (min-width: 769px) {\n #text-chat-widget {\n ".concat(positionStyles, "\n right: ").concat(this.config.position.horizontal === 'right' ? '20px' : 'auto', ";\n left: ").concat(this.config.position.horizontal === 'left' ? '20px' : 'auto', ";\n bottom: ").concat(this.config.position.vertical === 'bottom' ? '20px' : 'auto', ";\n top: ").concat(this.config.position.vertical === 'top' ? '20px' : 'auto', ";\n }\n }\n \n /* Mobile override (force mobile positioning) */\n @media (max-width: 768px) {\n #text-chat-widget {\n right: 10px !important;\n bottom: 10px !important;\n left: auto !important;\n top: auto !important;\n transform: none !important;\n }\n }\n \n @media (max-width: 480px) {\n #text-chat-widget {\n right: 8px !important;\n bottom: 8px !important;\n left: auto !important;\n top: auto !important;\n }\n }\n \n #text-chat-button {\n position: fixed;\n ").concat(this.config.position.vertical === 'bottom' ? "bottom: ".concat(((_this$config$position = this.config.position.offset) === null || _this$config$position === void 0 ? void 0 : _this$config$position.y) || 20, "px;") : "top: ".concat(((_this$config$position2 = this.config.position.offset) === null || _this$config$position2 === void 0 ? void 0 : _this$config$position2.y) || 20, "px;"), "\n ").concat(this.config.position.horizontal === 'right' ? "right: ".concat(((_this$config$position3 = this.config.position.offset) === null || _this$config$position3 === void 0 ? void 0 : _this$config$position3.x) || 20, "px;") : "left: ".concat(((_this$config$position4 = this.config.position.offset) === null || _this$config$position4 === void 0 ? void 0 : _this$config$position4.x) || 20, "px;"), "\n width: ").concat(buttonSize, "px;\n height: ").concat(buttonSize, "px;\n border-radius: ").concat(btn.shape === 'circle' ? '50%' : btn.shape === 'square' ? '0' : '12px', ";\n background: ").concat(btn.backgroundColor || icon.backgroundColor || '#7C3AED', ";\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all ").concat(anim.duration, "s ease;\n box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);\n touch-action: manipulation;\n -webkit-tap-highlight-color: transparent;\n -webkit-touch-callout: none;\n user-select: none;\n min-width: 44px;\n min-height: 44px;\n z-index: 10001;\n }\n \n @media (max-width: 768px) {\n #text-chat-widget {\n right: 10px !important;\n bottom: 10px !important;\n left: auto !important;\n top: auto !important;\n transform: none !important;\n }\n \n #text-chat-button {\n right: 10px !important;\n bottom: 10px !important;\n left: auto !important;\n top: auto !important;\n width: 56px !important;\n height: 56px !important;\n min-width: 56px !important;\n min-height: 56px !important;\n max-width: 56px !important;\n max-height: 56px !important;\n }\n \n #text-chat-panel {\n position: fixed !important;\n left: 10px !important;\n right: 10px !important;\n bottom: 92px !important; /* 56px button + 20px gap + 16px footer */\n top: 60px !important; /* Add top spacing */\n width: auto !important;\n max-width: none !important;\n height: auto !important; /* Change from max-height to auto */\n max-height: none !important; /* Remove max-height */\n transform: none !important;\n margin: 0 !important;\n }\n \n #text-chat-panel .widget-header {\n padding: 10px 14px;\n min-height: 56px;\n }\n \n #text-chat-panel .header-title {\n font-size: 15px;\n }\n \n #text-chat-panel .header-icon {\n width: 40px;\n height: 40px;\n min-width: 40px;\n min-height: 40px;\n }\n \n #text-chat-input {\n font-size: 16px !important; /* Prevents iOS zoom on focus */\n padding: 12px 16px !important;\n min-height: 48px !important;\n }\n \n #text-chat-send {\n min-width: 48px !important;\n min-height: 48px !important;\n width: 48px !important;\n height: 48px !important;\n }\n \n .landing-screen {\n padding: 16px;\n }\n \n .landing-logo {\n font-size: 40px;\n }\n \n .landing-title {\n font-size: 18px;\n margin-bottom: 16px;\n }\n \n .mode-selection {\n flex-direction: column;\n gap: 12px;\n align-items: center;\n }\n \n .mode-card {\n max-width: 100%;\n width: 100%;\n padding: 16px;\n }\n \n .mode-card-icon {\n width: 50px;\n height: 50px;\n font-size: 28px;\n }\n \n .mode-card-title {\n font-size: 14px;\n }\n }\n \n @media (max-width: 480px) {\n #text-chat-widget {\n right: 8px !important;\n bottom: 8px !important;\n left: auto !important;\n top: auto !important;\n }\n \n #text-chat-button {\n right: 8px !important;\n bottom: 8px !important;\n left: auto !important;\n top: auto !important;\n width: 54px !important;\n height: 54px !important;\n min-width: 54px !important;\n min-height: 54px !important;\n }\n \n #text-chat-panel {\n left: 8px !important;\n right: 8px !important;\n bottom: 86px !important; /* 54px button + 20px gap + 12px footer */\n top: 50px !important; /* Add top spacing for very small screens */\n height: auto !important;\n max-height: none !important;\n }\n \n #text-chat-panel .widget-header {\n padding: 8px 12px;\n min-height: 52px;\n }\n \n #text-chat-panel .header-title {\n font-size: 14px;\n }\n \n .landing-logo {\n font-size: 36px;\n }\n \n .landing-title {\n font-size: 16px;\n }\n }\n \n ").concat(anim.enableHover ? "\n #text-chat-button:hover {\n ".concat(btn.hoverColor ? "background: ".concat(btn.hoverColor, ";") : '', "\n transform: scale(1.05);\n box-shadow: 0 8px 20px rgba(102, 126, 234, 0.5);\n }\n ") : '', "\n \n #text-chat-panel {\n display: none").concat(important, ";\n position: fixed;\n bottom: calc(").concat(buttonSize, "px + 20px + 20px); /* Button + gap + reduced footer offset */\n ").concat(this.config.position.horizontal === 'right' ? 'right: 20px;' : 'left: 20px;', "\n width: ").concat(panel.width, "px;\n max-width: calc(100vw - 40px);\n height: ").concat(panel.height, "px;\n max-height: calc(100vh - ").concat(buttonSize, "px - 40px - 20px); /* Account for footer height */\n background: transparent;\n border-radius: ").concat(panel.borderRadius, "px;\n border: none;\n flex-direction: column;\n overflow: hidden;\n ").concat(panel.backdropFilter ? "backdrop-filter: ".concat(panel.backdropFilter, ";") : '', "\n ").concat(anim.enableSlide ? "transition: all ".concat(anim.duration, "s ease;") : '', "\n box-sizing: border-box;\n }\n \n #text-chat-panel.open {\n display: flex").concat(important, ";\n ").concat(anim.enableSlide ? 'transform: translateY(0); opacity: 1;' : '', "\n }\n\n /* Shell for gradient border/background */\n .widget-shell { width: 100%; height: 100%; padding: 0; border-radius: ").concat(panel.borderRadius, "px; background: transparent; box-shadow: 0 20px 60px rgba(0,0,0,0.15); overflow: hidden; display: flex; flex-direction: column; box-sizing: border-box; }\n .panel-inner { width: 100%; height: 100%; background: #ffffff; border-radius: ").concat(panel.borderRadius, "px; border: ").concat(panel.border, "; overflow: hidden; display:flex; flex-direction: column; padding: 0; box-sizing: border-box; max-width: 100%; }\n\n /* New structure styles matching provided design */\n #text-chat-panel .widget-container {\n width: 100%; height: 100%; background: #FFFFFF; overflow: visible; display: flex; flex-direction: column; border-radius: ").concat(panel.borderRadius, "px;\n container-type: size;\n }\n \n /* Ensure content areas can scroll when height is constrained */\n #text-chat-panel .widget-container > .landing-screen,\n #text-chat-panel .widget-container > .voice-interface,\n #text-chat-panel .widget-container > .text-interface {\n flex: 1;\n overflow-y: auto;\n overflow-x: visible; /* Change from hidden to visible */\n }\n \n /* Header should not scroll */\n #text-chat-panel .widget-header {\n padding: 14px 16px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n border-top-left-radius: ").concat(panel.borderRadius, "px;\n border-top-right-radius: ").concat(panel.borderRadius, "px;\n flex-shrink: 0;\n box-sizing: border-box;\n position: relative;\n overflow: hidden;\n }\n \n #text-chat-panel .widget-header::before {\n content: '';\n position: absolute;\n top: -50%;\n right: -20%;\n width: 180px;\n height: 180px;\n background: radial-gradient(circle, rgba(255,255,255,0.08) 0%, transparent 70%);\n pointer-events: none;\n }\n \n #text-chat-panel .widget-header > div:first-child {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 4px;\n position: relative;\n z-index: 1;\n }\n \n #text-chat-panel .header-title { font-size: 15px; font-weight: 600; margin: 0; }\n #text-chat-panel .header-status { display: flex; align-items: center; gap: 5px; font-size: 12px; color: rgba(255,255,255,0.7); margin: 0; }\n #text-chat-panel .status-dot { width: 6px; height: 6px; background: #10b981; border-radius: 50%; animation: pulse 2s ease-in-out infinite; }\n @keyframes pulse { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.15); opacity: 0.8; } }\n /* Header icon buttons */\n .header-icon {\n background: rgba(255, 255, 255, 0.1);\n border: none;\n color: white;\n width: 34px;\n height: 34px;\n min-width: 34px;\n min-height: 34px;\n border-radius: 10px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.2s;\n flex-shrink: 0;\n font-size: 16px;\n padding: 0;\n box-sizing: border-box;\n position: relative;\n z-index: 1;\n }\n \n .header-icon:hover {\n background: rgba(255, 255, 255, 0.2);\n }\n \n .header-icon svg {\n pointer-events: none;\n stroke: white;\n fill: none;\n }\n \n .back-btn.visible {\n display: flex !important;\n }\n\n ").concat(showLanding && this.landingScreen ? this.landingScreen.generateCSS() : '', "\n\n ").concat(showVoice ? this.voiceInterface.generateCSS() : '', "\n ").concat(showText ? this.textInterface.generateCSS() : '', "\n \n /* Footer Branding */\n .widget-footer {\n box-sizing: border-box;\n }\n \n .footer-brand-link {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n }\n \n .footer-brand-link:hover {\n opacity: 0.9;\n }\n \n @media (max-width: 768px) {\n .widget-footer {\n height: 32px;\n }\n .widget-footer span {\n font-size: 10px;\n }\n .widget-footer span:last-child {\n font-size: 8px;\n }\n }\n \n #text-chat-send-hint {\n text-align: center;\n line-height: 1.4;\n }\n \n .agent-thinking {\n font-style: italic;\n color: #6B7280;\n }\n ");
13587
+ // Note: Removed headerColor variable - landing screen colors now use explicit defaults
13588
+ // to prevent buttons from inheriting header backgroundColor
13589
+
13590
+ return "\n /* MOBILE FIRST - Default styles for all devices */\n #text-chat-widget {\n position: fixed !important;\n z-index: 10000;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n /* Mobile defaults */\n right: 10px;\n bottom: 10px;\n left: auto;\n top: auto;\n }\n \n /* Desktop positioning (only on larger screens) */\n @media (min-width: 769px) {\n #text-chat-widget {\n ".concat(positionStyles, "\n right: ").concat(this.config.position.horizontal === 'right' ? '20px' : 'auto', ";\n left: ").concat(this.config.position.horizontal === 'left' ? '20px' : 'auto', ";\n bottom: ").concat(this.config.position.vertical === 'bottom' ? '20px' : 'auto', ";\n top: ").concat(this.config.position.vertical === 'top' ? '20px' : 'auto', ";\n }\n }\n \n /* Mobile override (force mobile positioning) */\n @media (max-width: 768px) {\n #text-chat-widget {\n right: 10px !important;\n bottom: 10px !important;\n left: auto !important;\n top: auto !important;\n transform: none !important;\n }\n }\n \n @media (max-width: 480px) {\n #text-chat-widget {\n right: 8px !important;\n bottom: 8px !important;\n left: auto !important;\n top: auto !important;\n }\n }\n \n #text-chat-button {\n position: relative;\n width: ").concat(buttonSize, "px;\n height: ").concat(buttonSize, "px;\n margin: 0;\n flex-shrink: 0;\n border-radius: ").concat(btn.shape === 'circle' ? '50%' : btn.shape === 'square' ? '0' : '12px', ";\n background: ").concat(btn.backgroundColor || icon.backgroundColor || '#7C3AED', ";\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all ").concat(anim.duration, "s ease;\n box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);\n touch-action: manipulation;\n -webkit-tap-highlight-color: transparent;\n -webkit-touch-callout: none;\n user-select: none;\n min-width: 44px;\n min-height: 44px;\n z-index: 1;\n }\n \n @media (max-width: 768px) {\n #text-chat-widget {\n right: 10px !important;\n bottom: 10px !important;\n left: auto !important;\n top: auto !important;\n transform: none !important;\n }\n \n #text-chat-button-container {\n width: 56px !important;\n height: 56px !important;\n }\n \n #text-chat-button {\n width: 56px !important;\n height: 56px !important;\n min-width: 56px !important;\n min-height: 56px !important;\n max-width: 56px !important;\n max-height: 56px !important;\n }\n \n #text-chat-panel {\n position: fixed !important;\n left: 10px !important;\n right: 10px !important;\n bottom: 92px !important; /* 56px button + 20px gap + 16px footer */\n top: 60px !important; /* Add top spacing */\n width: auto !important;\n max-width: none !important;\n height: auto !important; /* Change from max-height to auto */\n max-height: none !important; /* Remove max-height */\n transform: none !important;\n margin: 0 !important;\n }\n \n #text-chat-panel .widget-header {\n padding: 10px 14px;\n min-height: 56px;\n }\n \n #text-chat-panel .header-title {\n font-size: 15px;\n }\n \n #text-chat-panel .header-icon {\n width: 40px;\n height: 40px;\n min-width: 40px;\n min-height: 40px;\n }\n \n #text-chat-input {\n font-size: 16px !important; /* Prevents iOS zoom on focus */\n padding: 12px 16px !important;\n min-height: 48px !important;\n }\n \n #text-chat-send {\n min-width: 48px !important;\n min-height: 48px !important;\n width: 48px !important;\n height: 48px !important;\n }\n \n .landing-screen {\n padding: 16px;\n }\n \n .landing-logo {\n font-size: 40px;\n }\n \n .landing-title {\n font-size: 18px;\n margin-bottom: 16px;\n }\n \n .mode-selection {\n flex-direction: column;\n gap: 12px;\n align-items: center;\n }\n \n .mode-card {\n max-width: 100%;\n width: 100%;\n padding: 16px;\n }\n \n .mode-card-icon {\n width: 50px;\n height: 50px;\n font-size: 28px;\n }\n \n .mode-card-title {\n font-size: 14px;\n }\n }\n \n @media (max-width: 480px) {\n #text-chat-widget {\n right: 8px !important;\n bottom: 8px !important;\n left: auto !important;\n top: auto !important;\n }\n \n #text-chat-button-container {\n width: 54px !important;\n height: 54px !important;\n }\n \n #text-chat-button {\n width: 54px !important;\n height: 54px !important;\n min-width: 54px !important;\n min-height: 54px !important;\n }\n \n #text-chat-panel {\n left: 8px !important;\n right: 8px !important;\n bottom: 86px !important; /* 54px button + 20px gap + 12px footer */\n top: 50px !important; /* Add top spacing for very small screens */\n height: auto !important;\n max-height: none !important;\n }\n \n #text-chat-panel .widget-header {\n padding: 8px 12px;\n min-height: 52px;\n }\n \n #text-chat-panel .header-title {\n font-size: 14px;\n }\n \n .landing-logo {\n font-size: 36px;\n }\n \n .landing-title {\n font-size: 16px;\n }\n }\n \n ").concat(anim.enableHover ? "\n #text-chat-button:hover {\n ".concat(btn.hoverColor ? "background: ".concat(btn.hoverColor, ";") : '', "\n transform: scale(1.05);\n box-shadow: 0 8px 20px rgba(102, 126, 234, 0.5);\n }\n ") : '', "\n \n /* Prompt Animation Keyframes */\n @keyframes widget-shimmer {\n 0% { transform: translateX(-100%); }\n 100% { transform: translateX(200%); }\n }\n \n @keyframes widget-ripple {\n 0% { transform: scale(1); opacity: 0.6; }\n 100% { transform: scale(2.5); opacity: 0; }\n }\n \n @keyframes widget-float {\n 0%, 100% { transform: translateX(-50%) translateY(0); }\n 50% { transform: translateX(-50%) translateY(-8px); }\n }\n \n @keyframes widget-bounce {\n 0%, 100% { transform: translateX(-50%) translateY(0); }\n 50% { transform: translateX(-50%) translateY(-10px); }\n }\n \n @keyframes widget-pulse-ring {\n 0% { transform: scale(1); opacity: 0.4; }\n 100% { transform: scale(1.8); opacity: 0; }\n }\n \n /* Prompt Bubble Container */\n #text-chat-button-container {\n position: fixed;\n ").concat(this.config.position.vertical === 'bottom' ? "bottom: ".concat(((_this$config$position = this.config.position.offset) === null || _this$config$position === void 0 ? void 0 : _this$config$position.y) || 20, "px;") : "top: ".concat(((_this$config$position2 = this.config.position.offset) === null || _this$config$position2 === void 0 ? void 0 : _this$config$position2.y) || 20, "px;"), "\n ").concat(this.config.position.horizontal === 'right' ? "right: ".concat(((_this$config$position3 = this.config.position.offset) === null || _this$config$position3 === void 0 ? void 0 : _this$config$position3.x) || 20, "px;") : "left: ".concat(((_this$config$position4 = this.config.position.offset) === null || _this$config$position4 === void 0 ? void 0 : _this$config$position4.x) || 20, "px;"), "\n width: ").concat(buttonSize, "px;\n height: ").concat(buttonSize, "px;\n z-index: 10001;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n \n @media (max-width: 768px) {\n #text-chat-button-container {\n right: 10px !important;\n bottom: 10px !important;\n left: auto !important;\n top: auto !important;\n }\n }\n \n @media (max-width: 480px) {\n #text-chat-button-container {\n right: 8px !important;\n bottom: 8px !important;\n left: auto !important;\n top: auto !important;\n }\n }\n \n /* Prompt Bubble Styles */\n .prompt-bubble {\n position: absolute;\n z-index: 10002;\n pointer-events: none;\n white-space: nowrap;\n }\n \n .prompt-bubble.top {\n bottom: calc(100% + 18px);\n left: 50%;\n transform: translateX(-50%);\n }\n \n .prompt-bubble.left {\n right: calc(100% + 12px);\n top: 50%;\n transform: translateY(-50%);\n }\n \n .prompt-bubble.right {\n left: calc(100% + 12px);\n top: 50%;\n transform: translateY(-50%);\n }\n \n /* Ensure animations preserve horizontal centering for top position */\n .prompt-bubble.top.animation-bounce {\n animation: widget-bounce 1s ease-in-out infinite;\n transform: translateX(-50%); /* Keep centering */\n }\n \n .prompt-bubble.top.animation-float {\n animation: widget-float 2s ease-in-out infinite;\n transform: translateX(-50%); /* Keep centering */\n }\n \n .prompt-bubble.top.animation-pulse {\n animation: pulse 2s ease-in-out infinite;\n transform: translateX(-50%); /* Keep centering */\n }\n \n .prompt-bubble-content {\n position: relative;\n padding: 8px 16px;\n border-radius: 20px;\n font-weight: 500;\n font-size: 14px;\n box-shadow: 0 4px 15px rgba(124, 58, 237, 0.3);\n overflow: hidden;\n }\n \n .prompt-bubble-shimmer {\n position: absolute;\n inset: 0;\n background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.25), transparent);\n animation: widget-shimmer 2s infinite;\n }\n \n .prompt-bubble.animation-bounce {\n animation: widget-bounce 1s ease-in-out infinite;\n }\n \n .prompt-bubble.animation-pulse {\n animation: pulse 2s ease-in-out infinite;\n }\n \n .prompt-bubble.animation-float {\n animation: widget-float 2s ease-in-out infinite;\n }\n \n /* Ensure top-positioned bubbles maintain horizontal centering during animations */\n .prompt-bubble.top.animation-bounce,\n .prompt-bubble.top.animation-float,\n .prompt-bubble.top.animation-pulse {\n /* Animation keyframes already include translateX(-50%) for centering */\n }\n \n /* Prompt Bubble Arrow */\n .prompt-bubble-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border: 8px solid transparent;\n }\n \n .prompt-bubble.top .prompt-bubble-arrow {\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n border-top-color: var(--prompt-bubble-bg-color, #7c3aed);\n border-bottom: none;\n margin-left: 0;\n }\n \n .prompt-bubble.left .prompt-bubble-arrow {\n left: 100%;\n top: 50%;\n transform: translateY(-50%);\n border-left-color: var(--prompt-bubble-bg-color, #7c3aed);\n border-right: none;\n }\n \n .prompt-bubble.right .prompt-bubble-arrow {\n right: 100%;\n top: 50%;\n transform: translateY(-50%);\n border-right-color: var(--prompt-bubble-bg-color, #7c3aed);\n border-left: none;\n }\n \n /* Pulse Rings */\n .prompt-pulse-rings {\n position: absolute;\n inset: 0;\n border-radius: 50%;\n pointer-events: none;\n }\n \n .prompt-pulse-ring {\n position: absolute;\n inset: 0;\n border-radius: 50%;\n animation: widget-pulse-ring 2s ease-out infinite;\n }\n \n .prompt-pulse-ring:nth-child(2) {\n animation-delay: 0.5s;\n }\n \n /* Mobile adjustments for prompt bubble */\n @media (max-width: 768px) {\n .prompt-bubble-content {\n font-size: 12px;\n padding: 6px 12px;\n }\n \n .prompt-bubble.top {\n bottom: calc(100% + 14px);\n }\n \n .prompt-bubble.left,\n .prompt-bubble.right {\n display: none; /* Hide side prompts on mobile */\n }\n }\n \n #text-chat-panel {\n display: none").concat(important, ";\n position: fixed;\n bottom: calc(").concat(buttonSize, "px + 20px + 20px); /* Button + gap + reduced footer offset */\n ").concat(this.config.position.horizontal === 'right' ? 'right: 20px;' : 'left: 20px;', "\n width: ").concat(panel.width, "px;\n max-width: calc(100vw - 40px);\n height: ").concat(panel.height, "px;\n max-height: calc(100vh - ").concat(buttonSize, "px - 40px - 20px); /* Account for footer height */\n background: transparent;\n border-radius: ").concat(panel.borderRadius, "px;\n border: none;\n flex-direction: column;\n overflow: hidden;\n ").concat(panel.backdropFilter ? "backdrop-filter: ".concat(panel.backdropFilter, ";") : '', "\n ").concat(anim.enableSlide ? "transition: all ".concat(anim.duration, "s ease;") : '', "\n box-sizing: border-box;\n }\n \n #text-chat-panel.open {\n display: flex").concat(important, ";\n ").concat(anim.enableSlide ? 'transform: translateY(0); opacity: 1;' : '', "\n }\n\n /* Shell for gradient border/background */\n .widget-shell { width: 100%; height: 100%; padding: 0; border-radius: ").concat(panel.borderRadius, "px; background: transparent; box-shadow: 0 20px 60px rgba(0,0,0,0.15); overflow: hidden; display: flex; flex-direction: column; box-sizing: border-box; }\n .panel-inner { width: 100%; height: 100%; background: #ffffff; border-radius: ").concat(panel.borderRadius, "px; border: ").concat(panel.border, "; overflow: hidden; display:flex; flex-direction: column; padding: 0; box-sizing: border-box; max-width: 100%; }\n\n /* New structure styles matching provided design */\n #text-chat-panel .widget-container {\n width: 100%; height: 100%; background: #FFFFFF; overflow: visible; display: flex; flex-direction: column; border-radius: ").concat(panel.borderRadius, "px;\n container-type: size;\n }\n \n /* Ensure content areas can scroll when height is constrained */\n #text-chat-panel .widget-container > .landing-screen,\n #text-chat-panel .widget-container > .voice-interface,\n #text-chat-panel .widget-container > .text-interface {\n flex: 1;\n overflow-y: auto;\n overflow-x: visible; /* Change from hidden to visible */\n }\n \n /* Header should not scroll */\n #text-chat-panel .widget-header {\n padding: 14px 16px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n border-top-left-radius: ").concat(panel.borderRadius, "px;\n border-top-right-radius: ").concat(panel.borderRadius, "px;\n flex-shrink: 0;\n box-sizing: border-box;\n position: relative;\n overflow: hidden;\n background: ").concat(header.backgroundColor || '#7C3AED').concat(important, ";\n color: ").concat(header.textColor || '#FFFFFF').concat(important, ";\n }\n \n #text-chat-panel .widget-header::before {\n content: '';\n position: absolute;\n top: -50%;\n right: -20%;\n width: 180px;\n height: 180px;\n background: radial-gradient(circle, rgba(255,255,255,0.08) 0%, transparent 70%);\n pointer-events: none;\n }\n \n #text-chat-panel .widget-header > div:first-child {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 4px;\n position: relative;\n z-index: 1;\n }\n \n #text-chat-panel .header-title { font-size: 15px; font-weight: 600; margin: 0; }\n #text-chat-panel .header-status { display: flex; align-items: center; gap: 5px; font-size: 12px; margin: 0; }\n #text-chat-panel .status-dot { width: 6px; height: 6px; border-radius: 50%; animation: pulse 2s ease-in-out infinite; }\n /* Online indicator customization - inline styles take precedence */\n @keyframes pulse { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.15); opacity: 0.8; } }\n /* Header icon buttons */\n .header-icon {\n background: rgba(255, 255, 255, 0.1);\n border: none;\n color: white;\n width: 34px;\n height: 34px;\n min-width: 34px;\n min-height: 34px;\n border-radius: 10px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.2s;\n flex-shrink: 0;\n font-size: 16px;\n padding: 0;\n box-sizing: border-box;\n position: relative;\n z-index: 1;\n }\n \n .header-icon:hover {\n background: rgba(255, 255, 255, 0.2);\n }\n \n .header-icon svg {\n pointer-events: none;\n stroke: white;\n fill: none;\n }\n \n .back-btn.visible {\n display: flex !important;\n }\n\n ").concat(showLanding && this.landingScreen ? this.landingScreen.generateCSS() : '', "\n\n ").concat(showVoice ? this.voiceInterface.generateCSS() : '', "\n ").concat(showText ? this.textInterface.generateCSS() : '', "\n \n /* Footer Branding */\n .widget-footer {\n box-sizing: border-box;\n }\n \n .footer-brand-link {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n }\n \n .footer-brand-link:hover {\n opacity: 0.9;\n }\n \n @media (max-width: 768px) {\n .widget-footer {\n height: 32px;\n }\n .widget-footer span {\n font-size: 10px;\n }\n .widget-footer span:last-child {\n font-size: 8px;\n }\n }\n \n #text-chat-send-hint {\n text-align: center;\n line-height: 1.4;\n }\n \n .agent-thinking {\n font-style: italic;\n color: #6B7280;\n }\n ");
13419
13591
  }
13420
13592
  }, {
13421
13593
  key: "setupWidgetEvents",
13422
13594
  value: function setupWidgetEvents() {
13423
- var _this5 = this,
13595
+ var _this6 = this,
13424
13596
  _this$config$behavior5;
13425
13597
  if (!this.shadowRoot) return;
13598
+
13599
+ // Setup prompt animation visibility and interactions
13600
+ this.setupPromptAnimation();
13426
13601
  var openBtn = this.shadowRoot.getElementById('text-chat-button');
13427
13602
  if (openBtn) {
13428
13603
  openBtn.onclick = function () {
13429
- return _this5.togglePanel();
13604
+ // Hide prompt after click if configured
13605
+ if (_this6.config.promptAnimation.hideAfterClick) {
13606
+ _this6.hidePrompt();
13607
+ }
13608
+ _this6.togglePanel();
13430
13609
  };
13431
13610
  }
13432
13611
  var closeBtn = this.shadowRoot.getElementById('closeBtn');
@@ -13434,7 +13613,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
13434
13613
  closeBtn.onclick = function () {
13435
13614
  // Just close the widget panel - call continues in background
13436
13615
  // User can reopen widget to continue the call
13437
- _this5._doTogglePanel();
13616
+ _this6._doTogglePanel();
13438
13617
  };
13439
13618
  }
13440
13619
 
@@ -13451,27 +13630,27 @@ var TTPChatWidget = /*#__PURE__*/function () {
13451
13630
  // Setup back button handler
13452
13631
  if (backBtn) {
13453
13632
  backBtn.onclick = function () {
13454
- var _this5$voiceInterface, _this5$voiceInterface3;
13633
+ var _this6$voiceInterface, _this6$voiceInterface3;
13455
13634
  // Check if we're showing a domain error - if so, clear it and go back to landing
13456
- if ((_this5$voiceInterface = _this5.voiceInterface) !== null && _this5$voiceInterface !== void 0 && _this5$voiceInterface.isShowingDomainError) {
13457
- var _this5$voiceInterface2;
13635
+ if ((_this6$voiceInterface = _this6.voiceInterface) !== null && _this6$voiceInterface !== void 0 && _this6$voiceInterface.isShowingDomainError) {
13636
+ var _this6$voiceInterface2;
13458
13637
  console.log('🔙 Back button clicked - clearing domain error and returning to landing');
13459
13638
  // Clear the domain error flag
13460
- _this5.voiceInterface.isShowingDomainError = false;
13639
+ _this6.voiceInterface.isShowingDomainError = false;
13461
13640
  // Reset the connecting state (this will restore normal UI)
13462
- if ((_this5$voiceInterface2 = _this5.voiceInterface) !== null && _this5$voiceInterface2 !== void 0 && _this5$voiceInterface2.resetConnectingState) {
13463
- _this5.voiceInterface.resetConnectingState();
13641
+ if ((_this6$voiceInterface2 = _this6.voiceInterface) !== null && _this6$voiceInterface2 !== void 0 && _this6$voiceInterface2.resetConnectingState) {
13642
+ _this6.voiceInterface.resetConnectingState();
13464
13643
  }
13465
13644
  // Now show landing (will work since error flag is cleared)
13466
- _this5.showLanding();
13645
+ _this6.showLanding();
13467
13646
  return;
13468
13647
  }
13469
- if ((_this5$voiceInterface3 = _this5.voiceInterface) !== null && _this5$voiceInterface3 !== void 0 && _this5$voiceInterface3.isActive) {
13648
+ if ((_this6$voiceInterface3 = _this6.voiceInterface) !== null && _this6$voiceInterface3 !== void 0 && _this6$voiceInterface3.isActive) {
13470
13649
  // If call is active, show message inside widget instead of modal
13471
- _this5.showBackButtonWarning();
13650
+ _this6.showBackButtonWarning();
13472
13651
  } else {
13473
13652
  // If not active, just show landing
13474
- _this5.showLanding();
13653
+ _this6.showLanding();
13475
13654
  }
13476
13655
  };
13477
13656
  }
@@ -13479,34 +13658,34 @@ var TTPChatWidget = /*#__PURE__*/function () {
13479
13658
  this.landingScreen.setupEventHandlers({
13480
13659
  onSelectVoice: function () {
13481
13660
  var _onSelectVoice = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
13482
- var _this5$voiceInterface4, _this5$voiceInterface5, _this5$voiceInterface6, _this5$voiceInterface8, _this5$config$behavio, idleState, isDomainError, statusTitle, _this5$voiceInterface7, titleText, domainErrorTitle, _widgetMode, _this5$voiceInterface0, _this5$config$behavio2, _this5$voiceInterface9, _widgetMode2, _t;
13661
+ var _this6$voiceInterface4, _this6$voiceInterface5, _this6$voiceInterface6, _this6$voiceInterface8, _this6$config$behavio, idleState, isDomainError, statusTitle, _this6$voiceInterface7, titleText, domainErrorTitle, _widgetMode, _this6$voiceInterface0, _this6$config$behavio2, _this6$voiceInterface9, _widgetMode2, _t;
13483
13662
  return _regenerator().w(function (_context) {
13484
13663
  while (1) switch (_context.p = _context.n) {
13485
13664
  case 0:
13486
- if (!_this5.isStartingCall) {
13665
+ if (!_this6.isStartingCall) {
13487
13666
  _context.n = 1;
13488
13667
  break;
13489
13668
  }
13490
13669
  console.log('⚠️ Call already starting, ignoring duplicate click');
13491
13670
  return _context.a(2);
13492
13671
  case 1:
13493
- _this5.isStartingCall = true;
13672
+ _this6.isStartingCall = true;
13494
13673
  _context.p = 2;
13495
13674
  // Show voice interface first (needed for UI state)
13496
13675
  // Note: If showVoice() throws, finally block will still reset flag
13497
- _this5.showVoice();
13676
+ _this6.showVoice();
13498
13677
 
13499
13678
  // Show connecting/loading state immediately
13500
13679
  // This provides feedback during WebSocket connection and SDK initialization
13501
- if ((_this5$voiceInterface4 = _this5.voiceInterface) !== null && _this5$voiceInterface4 !== void 0 && _this5$voiceInterface4.showConnectingState) {
13502
- _this5.voiceInterface.showConnectingState();
13680
+ if ((_this6$voiceInterface4 = _this6.voiceInterface) !== null && _this6$voiceInterface4 !== void 0 && _this6$voiceInterface4.showConnectingState) {
13681
+ _this6.voiceInterface.showConnectingState();
13503
13682
  }
13504
13683
 
13505
13684
  // Start the call
13506
13685
  _context.n = 3;
13507
- return _this5.startVoiceCall();
13686
+ return _this6.startVoiceCall();
13508
13687
  case 3:
13509
- if (!((_this5$voiceInterface5 = _this5.voiceInterface) !== null && _this5$voiceInterface5 !== void 0 && _this5$voiceInterface5.isActive)) {
13688
+ if (!((_this6$voiceInterface5 = _this6.voiceInterface) !== null && _this6$voiceInterface5 !== void 0 && _this6$voiceInterface5.isActive)) {
13510
13689
  _context.n = 4;
13511
13690
  break;
13512
13691
  }
@@ -13519,13 +13698,13 @@ var TTPChatWidget = /*#__PURE__*/function () {
13519
13698
 
13520
13699
  // CRITICAL: Check if we're showing a domain error - if so, stay on voice interface
13521
13700
  // We check by looking at the status title text content
13522
- idleState = (_this5$voiceInterface6 = _this5.voiceInterface) === null || _this5$voiceInterface6 === void 0 || (_this5$voiceInterface6 = _this5$voiceInterface6.shadowRoot) === null || _this5$voiceInterface6 === void 0 ? void 0 : _this5$voiceInterface6.getElementById('voiceIdleState');
13701
+ idleState = (_this6$voiceInterface6 = _this6.voiceInterface) === null || _this6$voiceInterface6 === void 0 || (_this6$voiceInterface6 = _this6$voiceInterface6.shadowRoot) === null || _this6$voiceInterface6 === void 0 ? void 0 : _this6$voiceInterface6.getElementById('voiceIdleState');
13523
13702
  isDomainError = false;
13524
13703
  if (idleState && idleState.style.display !== 'none') {
13525
13704
  statusTitle = idleState.querySelector('.voice-status-title');
13526
13705
  if (statusTitle) {
13527
13706
  titleText = statusTitle.textContent.trim();
13528
- domainErrorTitle = (_this5$voiceInterface7 = _this5.voiceInterface) === null || _this5$voiceInterface7 === void 0 ? void 0 : _this5$voiceInterface7.t('domainNotValidated');
13707
+ domainErrorTitle = (_this6$voiceInterface7 = _this6.voiceInterface) === null || _this6$voiceInterface7 === void 0 ? void 0 : _this6$voiceInterface7.t('domainNotValidated');
13529
13708
  console.log('🔍 Checking for domain error - titleText:', titleText, 'domainErrorTitle:', domainErrorTitle);
13530
13709
  if (titleText === domainErrorTitle || titleText.includes('Domain not') || titleText.includes('not whitelisted')) {
13531
13710
  isDomainError = true;
@@ -13538,21 +13717,21 @@ var TTPChatWidget = /*#__PURE__*/function () {
13538
13717
  break;
13539
13718
  }
13540
13719
  // Set currentView to voice so we don't return to landing
13541
- _this5.currentView = 'voice';
13720
+ _this6.currentView = 'voice';
13542
13721
  // Ensure voice interface is visible
13543
- _this5.showVoice();
13722
+ _this6.showVoice();
13544
13723
  // Don't reset connecting state or return to landing - stay on voice interface showing error
13545
13724
  console.log('✅ Staying on voice interface with domain error displayed');
13546
13725
  return _context.a(2);
13547
13726
  case 5:
13548
13727
  // Not a domain error - reset connecting state and return to landing
13549
13728
  console.log('⚠️ Not a domain error - returning to landing screen');
13550
- if ((_this5$voiceInterface8 = _this5.voiceInterface) !== null && _this5$voiceInterface8 !== void 0 && _this5$voiceInterface8.resetConnectingState) {
13551
- _this5.voiceInterface.resetConnectingState();
13729
+ if ((_this6$voiceInterface8 = _this6.voiceInterface) !== null && _this6$voiceInterface8 !== void 0 && _this6$voiceInterface8.resetConnectingState) {
13730
+ _this6.voiceInterface.resetConnectingState();
13552
13731
  }
13553
- _widgetMode = ((_this5$config$behavio = _this5.config.behavior) === null || _this5$config$behavio === void 0 ? void 0 : _this5$config$behavio.mode) || 'unified';
13732
+ _widgetMode = ((_this6$config$behavio = _this6.config.behavior) === null || _this6$config$behavio === void 0 ? void 0 : _this6$config$behavio.mode) || 'unified';
13554
13733
  if (_widgetMode === 'unified') {
13555
- _this5.showLanding();
13734
+ _this6.showLanding();
13556
13735
  }
13557
13736
  case 6:
13558
13737
  _context.n = 9;
@@ -13566,8 +13745,8 @@ var TTPChatWidget = /*#__PURE__*/function () {
13566
13745
  }
13567
13746
  // Server rejection is expected - the error handler will show domain error message
13568
13747
  // Reset connecting state but don't log as error
13569
- if ((_this5$voiceInterface9 = _this5.voiceInterface) !== null && _this5$voiceInterface9 !== void 0 && _this5$voiceInterface9.resetConnectingState) {
13570
- _this5.voiceInterface.resetConnectingState();
13748
+ if ((_this6$voiceInterface9 = _this6.voiceInterface) !== null && _this6$voiceInterface9 !== void 0 && _this6$voiceInterface9.resetConnectingState) {
13749
+ _this6.voiceInterface.resetConnectingState();
13571
13750
  }
13572
13751
  // Don't show toast for server rejection - domain error handler will show message
13573
13752
  return _context.a(2);
@@ -13576,24 +13755,24 @@ var TTPChatWidget = /*#__PURE__*/function () {
13576
13755
  console.error('❌ Failed to start voice call:', _t);
13577
13756
 
13578
13757
  // Reset connecting state on error
13579
- if ((_this5$voiceInterface0 = _this5.voiceInterface) !== null && _this5$voiceInterface0 !== void 0 && _this5$voiceInterface0.resetConnectingState) {
13580
- _this5.voiceInterface.resetConnectingState();
13758
+ if ((_this6$voiceInterface0 = _this6.voiceInterface) !== null && _this6$voiceInterface0 !== void 0 && _this6$voiceInterface0.resetConnectingState) {
13759
+ _this6.voiceInterface.resetConnectingState();
13581
13760
  }
13582
13761
 
13583
13762
  // Show user-friendly error message (unless it's a user cancellation)
13584
13763
  if (_t.message !== 'Call cancelled by user') {
13585
- _this5.showErrorToast(_t.message || 'Failed to start voice call. Please try again.', 'error');
13764
+ _this6.showErrorToast(_t.message || 'Failed to start voice call. Please try again.', 'error');
13586
13765
  }
13587
13766
 
13588
13767
  // Return to landing screen on error
13589
- _widgetMode2 = ((_this5$config$behavio2 = _this5.config.behavior) === null || _this5$config$behavio2 === void 0 ? void 0 : _this5$config$behavio2.mode) || 'unified';
13768
+ _widgetMode2 = ((_this6$config$behavio2 = _this6.config.behavior) === null || _this6$config$behavio2 === void 0 ? void 0 : _this6$config$behavio2.mode) || 'unified';
13590
13769
  if (_widgetMode2 === 'unified') {
13591
- _this5.showLanding();
13770
+ _this6.showLanding();
13592
13771
  }
13593
13772
  case 9:
13594
13773
  _context.p = 9;
13595
13774
  // ✅ Always reset flag, even if showVoice() or startVoiceCall() throws
13596
- _this5.isStartingCall = false;
13775
+ _this6.isStartingCall = false;
13597
13776
  return _context.f(9);
13598
13777
  case 10:
13599
13778
  return _context.a(2);
@@ -13606,7 +13785,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
13606
13785
  return onSelectVoice;
13607
13786
  }(),
13608
13787
  onSelectText: function onSelectText() {
13609
- return _this5.showText();
13788
+ return _this6.showText();
13610
13789
  }
13611
13790
  });
13612
13791
 
@@ -13662,7 +13841,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
13662
13841
  var newChatBtn = this.shadowRoot.getElementById('newChatBtn');
13663
13842
  if (newChatBtn) {
13664
13843
  newChatBtn.onclick = function () {
13665
- return _this5.textInterface.startNewChat();
13844
+ return _this6.textInterface.startNewChat();
13666
13845
  };
13667
13846
  // Hide new chat button on landing screen initially
13668
13847
  if (showLanding) {
@@ -13756,13 +13935,199 @@ var TTPChatWidget = /*#__PURE__*/function () {
13756
13935
  }, {
13757
13936
  key: "setupKeyboardNavigation",
13758
13937
  value: function setupKeyboardNavigation() {
13759
- var _this6 = this;
13938
+ var _this7 = this;
13760
13939
  document.addEventListener('keydown', function (e) {
13761
- if (e.key === 'Escape' && _this6.isOpen) {
13762
- _this6.togglePanel();
13940
+ if (e.key === 'Escape' && _this7.isOpen) {
13941
+ _this7.togglePanel();
13763
13942
  }
13764
13943
  });
13765
13944
  }
13945
+
13946
+ /**
13947
+ * Setup prompt animation visibility and auto-hide timer
13948
+ */
13949
+ }, {
13950
+ key: "setupPromptAnimation",
13951
+ value: function setupPromptAnimation() {
13952
+ var _this8 = this;
13953
+ if (!this.shadowRoot) return;
13954
+ var promptConfig = this.config.promptAnimation || {};
13955
+ // Default to disabled if not specified (enabled === true means explicitly enabled)
13956
+ var isPromptEnabled = promptConfig.enabled === true;
13957
+ console.log('🎨 setupPromptAnimation called:', {
13958
+ hasPromptConfig: !!this.config.promptAnimation,
13959
+ promptConfig: promptConfig,
13960
+ enabled: promptConfig.enabled,
13961
+ isPromptEnabled: isPromptEnabled,
13962
+ isOpen: this.isOpen
13963
+ });
13964
+ if (!isPromptEnabled) {
13965
+ // Hide prompt if disabled
13966
+ console.log('❌ Prompt disabled, hiding');
13967
+ this.hidePrompt();
13968
+ return;
13969
+ }
13970
+
13971
+ // Show or hide prompt based on widget state
13972
+ // If widget is closed, show the prompt; if open, hide it
13973
+ if (this.isOpen) {
13974
+ this.hidePrompt();
13975
+ } else {
13976
+ this.showPrompt();
13977
+ }
13978
+
13979
+ // Auto-hide after configured seconds (only if widget is closed)
13980
+ if (!this.isOpen && promptConfig.hideAfterSeconds !== null && promptConfig.hideAfterSeconds > 0) {
13981
+ this.promptAutoHideTimer = setTimeout(function () {
13982
+ _this8.hidePrompt();
13983
+ }, promptConfig.hideAfterSeconds * 1000);
13984
+ }
13985
+
13986
+ // Hide pulse rings when voice call starts (listen to voice interface events)
13987
+ if (this.voiceInterface && this.voiceInterface.sdk) {
13988
+ // Store original onConversationStart if it exists
13989
+ var originalOnConversationStart = this.config.onConversationStart;
13990
+
13991
+ // Wrap the callback to also hide pulse rings
13992
+ this.config.onConversationStart = function () {
13993
+ // Hide pulse rings when call starts
13994
+ var pulseRings = _this8.shadowRoot.getElementById('prompt-pulse-rings');
13995
+ if (pulseRings) pulseRings.style.display = 'none';
13996
+
13997
+ // Call original callback if it exists
13998
+ if (originalOnConversationStart) {
13999
+ originalOnConversationStart.apply(void 0, arguments);
14000
+ }
14001
+ };
14002
+
14003
+ // Also listen to recordingStarted event from SDK if available
14004
+ if (this.voiceInterface.sdk.voiceSDK) {
14005
+ this.voiceInterface.sdk.voiceSDK.on('recordingStarted', function () {
14006
+ var pulseRings = _this8.shadowRoot.getElementById('prompt-pulse-rings');
14007
+ if (pulseRings) pulseRings.style.display = 'none';
14008
+ });
14009
+ }
14010
+ }
14011
+ }
14012
+
14013
+ /**
14014
+ * Hide the prompt bubble and pulse rings
14015
+ */
14016
+ }, {
14017
+ key: "hidePrompt",
14018
+ value: function hidePrompt() {
14019
+ if (!this.shadowRoot) return;
14020
+
14021
+ // Clear auto-hide timer if it exists
14022
+ if (this.promptAutoHideTimer) {
14023
+ clearTimeout(this.promptAutoHideTimer);
14024
+ this.promptAutoHideTimer = null;
14025
+ }
14026
+
14027
+ // Hide prompt bubble (check both shadow root and document for compatibility)
14028
+ var promptBubble = this.shadowRoot.getElementById('prompt-bubble');
14029
+ if (!promptBubble && this.shadowRoot !== document) {
14030
+ promptBubble = document.getElementById('prompt-bubble');
14031
+ }
14032
+ if (promptBubble) {
14033
+ promptBubble.style.display = 'none';
14034
+ promptBubble.style.visibility = 'hidden';
14035
+ }
14036
+
14037
+ // Hide pulse rings (check both shadow root and document for compatibility)
14038
+ var pulseRings = this.shadowRoot.getElementById('prompt-pulse-rings');
14039
+ if (!pulseRings && this.shadowRoot !== document) {
14040
+ pulseRings = document.getElementById('prompt-pulse-rings');
14041
+ }
14042
+ if (pulseRings) {
14043
+ pulseRings.style.display = 'none';
14044
+ pulseRings.style.visibility = 'hidden';
14045
+ }
14046
+ }
14047
+
14048
+ /**
14049
+ * Show the prompt bubble and pulse rings (when widget is closed)
14050
+ */
14051
+ }, {
14052
+ key: "showPrompt",
14053
+ value: function showPrompt() {
14054
+ var _this9 = this;
14055
+ if (!this.shadowRoot) return;
14056
+ var promptConfig = this.config.promptAnimation || {};
14057
+ // Default to enabled if not specified
14058
+ var isPromptEnabled = promptConfig.enabled !== false;
14059
+ console.log('👁️ showPrompt called:', {
14060
+ hasPromptConfig: !!this.config.promptAnimation,
14061
+ promptConfig: promptConfig,
14062
+ enabled: promptConfig.enabled,
14063
+ isPromptEnabled: isPromptEnabled,
14064
+ shadowRoot: !!this.shadowRoot
14065
+ });
14066
+ if (!isPromptEnabled) {
14067
+ console.log('❌ Prompt not enabled, skipping show');
14068
+ return; // Don't show if disabled
14069
+ }
14070
+
14071
+ // Function to actually show the elements
14072
+ var doShow = function doShow() {
14073
+ // Show prompt bubble (check both shadow root and document for compatibility)
14074
+ var promptBubble = _this9.shadowRoot.getElementById('prompt-bubble');
14075
+ if (!promptBubble && _this9.shadowRoot !== document) {
14076
+ promptBubble = document.getElementById('prompt-bubble');
14077
+ }
14078
+ if (promptBubble) {
14079
+ promptBubble.style.display = 'block';
14080
+ promptBubble.style.visibility = 'visible';
14081
+ promptBubble.style.opacity = '1';
14082
+ console.log('✅ Prompt bubble shown:', promptBubble);
14083
+ } else {
14084
+ console.warn('⚠️ Prompt bubble not found in shadowRoot or document');
14085
+ }
14086
+
14087
+ // Show pulse rings if enabled
14088
+ if (promptConfig.showPulseRings !== false) {
14089
+ var _pulseRings = _this9.shadowRoot.getElementById('prompt-pulse-rings');
14090
+ if (!_pulseRings && _this9.shadowRoot !== document) {
14091
+ _pulseRings = document.getElementById('prompt-pulse-rings');
14092
+ }
14093
+ if (_pulseRings) {
14094
+ _pulseRings.style.display = 'block';
14095
+ _pulseRings.style.visibility = 'visible';
14096
+ _pulseRings.style.opacity = '1';
14097
+ }
14098
+ }
14099
+ };
14100
+
14101
+ // Try to show immediately
14102
+ doShow();
14103
+
14104
+ // If elements don't exist yet, retry after delays (for widget initialization)
14105
+ var promptBubble = this.shadowRoot.getElementById('prompt-bubble');
14106
+ var pulseRings = promptConfig.showPulseRings !== false ? this.shadowRoot.getElementById('prompt-pulse-rings') : null;
14107
+ if (!promptBubble || promptConfig.showPulseRings !== false && !pulseRings) {
14108
+ // Retry after short delay
14109
+ setTimeout(function () {
14110
+ doShow();
14111
+ }, 100);
14112
+
14113
+ // Retry after longer delay if still not found
14114
+ setTimeout(function () {
14115
+ doShow();
14116
+ }, 500);
14117
+ }
14118
+
14119
+ // Restart auto-hide timer if configured
14120
+ if (promptConfig.hideAfterSeconds !== null && promptConfig.hideAfterSeconds > 0) {
14121
+ // Clear any existing timer
14122
+ if (this.promptAutoHideTimer) {
14123
+ clearTimeout(this.promptAutoHideTimer);
14124
+ }
14125
+ // Start new timer
14126
+ this.promptAutoHideTimer = setTimeout(function () {
14127
+ _this9.hidePrompt();
14128
+ }, promptConfig.hideAfterSeconds * 1000);
14129
+ }
14130
+ }
13766
14131
  }, {
13767
14132
  key: "togglePanel",
13768
14133
  value: function togglePanel() {
@@ -13775,7 +14140,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
13775
14140
  }, {
13776
14141
  key: "_doTogglePanel",
13777
14142
  value: function _doTogglePanel() {
13778
- var _this7 = this;
14143
+ var _this0 = this;
13779
14144
  if (!this.shadowRoot) return;
13780
14145
  this.isOpen = !this.isOpen;
13781
14146
  var panel = this.shadowRoot.getElementById('text-chat-panel');
@@ -13783,12 +14148,32 @@ var TTPChatWidget = /*#__PURE__*/function () {
13783
14148
  panel.classList.toggle('open');
13784
14149
  }
13785
14150
 
13786
- // Focus input when opening
14151
+ // Hide/show prompt animation based on panel state
13787
14152
  if (this.isOpen) {
14153
+ // Panel is opening - hide prompt
14154
+ this.hidePrompt();
13788
14155
  setTimeout(function () {
13789
- var input = _this7.shadowRoot.getElementById('messageInput');
14156
+ var input = _this0.shadowRoot.getElementById('messageInput');
13790
14157
  if (input) input.focus();
13791
14158
  }, 100);
14159
+ } else {
14160
+ // Panel is closing - show prompt (if enabled)
14161
+ // Call showPrompt immediately, then also retry after a delay to ensure it's visible
14162
+ this.showPrompt();
14163
+ setTimeout(function () {
14164
+ var _this0$config$promptA;
14165
+ // Double-check and ensure prompt is visible
14166
+ var promptBubble = _this0.shadowRoot.getElementById('prompt-bubble');
14167
+ if (promptBubble && promptBubble.style.display === 'none') {
14168
+ promptBubble.style.display = 'block';
14169
+ }
14170
+ var pulseRings = _this0.shadowRoot.getElementById('prompt-pulse-rings');
14171
+ if (pulseRings && ((_this0$config$promptA = _this0.config.promptAnimation) === null || _this0$config$promptA === void 0 ? void 0 : _this0$config$promptA.showPulseRings) !== false) {
14172
+ if (pulseRings.style.display === 'none') {
14173
+ pulseRings.style.display = 'block';
14174
+ }
14175
+ }
14176
+ }, 100);
13792
14177
  }
13793
14178
 
13794
14179
  // Auto-connect if enabled
@@ -14073,8 +14458,8 @@ var TTPChatWidget = /*#__PURE__*/function () {
14073
14458
  mergedConfig.text = _objectSpread(_objectSpread({}, this.config.text), newConfig.text);
14074
14459
  // Deep merge sendButtonHint if it exists
14075
14460
  if (newConfig.text.sendButtonHint) {
14076
- var _this$config$text;
14077
- mergedConfig.text.sendButtonHint = _objectSpread(_objectSpread({}, (_this$config$text = this.config.text) === null || _this$config$text === void 0 ? void 0 : _this$config$text.sendButtonHint), newConfig.text.sendButtonHint);
14461
+ var _this$config$text3;
14462
+ mergedConfig.text.sendButtonHint = _objectSpread(_objectSpread({}, (_this$config$text3 = this.config.text) === null || _this$config$text3 === void 0 ? void 0 : _this$config$text3.sendButtonHint), newConfig.text.sendButtonHint);
14078
14463
  }
14079
14464
  }
14080
14465
 
@@ -14300,6 +14685,12 @@ var TTPChatWidget = /*#__PURE__*/function () {
14300
14685
  }, {
14301
14686
  key: "destroy",
14302
14687
  value: function destroy() {
14688
+ // Clear prompt animation timer if it exists
14689
+ if (this.promptAutoHideTimer) {
14690
+ clearTimeout(this.promptAutoHideTimer);
14691
+ this.promptAutoHideTimer = null;
14692
+ }
14693
+
14303
14694
  // Remove shadow host if it exists
14304
14695
  var host = document.getElementById('ttp-widget-shadow-host');
14305
14696
  if (host) {
@@ -14541,12 +14932,12 @@ var TTPChatWidget = /*#__PURE__*/function () {
14541
14932
  key: "_flushPendingClientTools",
14542
14933
  value: function _flushPendingClientTools() {
14543
14934
  var _this$voiceInterface1,
14544
- _this8 = this;
14935
+ _this1 = this;
14545
14936
  if (this._pendingClientTools && (_this$voiceInterface1 = this.voiceInterface) !== null && _this$voiceInterface1 !== void 0 && _this$voiceInterface1.sdk) {
14546
14937
  this._pendingClientTools.forEach(function (_ref2) {
14547
14938
  var name = _ref2.name,
14548
14939
  handler = _ref2.handler;
14549
- _this8.voiceInterface.sdk.registerToolHandler(name, handler);
14940
+ _this1.voiceInterface.sdk.registerToolHandler(name, handler);
14550
14941
  });
14551
14942
  this._pendingClientTools = null;
14552
14943
  console.log('TTPChatWidget: Flushed pending client tools');
@@ -14703,7 +15094,7 @@ var TextInterface = /*#__PURE__*/function () {
14703
15094
 
14704
15095
  // Add !important to display rules when not using Shadow DOM (to override theme CSS)
14705
15096
  var important = this.config.useShadowDOM === false ? ' !important' : '';
14706
- return "\n /* Messages container using new classes */\n #messagesContainer { \n flex: 1; \n overflow-y: auto; \n overflow-x: hidden; \n padding: 20px; \n background: #f8fafc; \n display: flex; \n flex-direction: column; \n gap: 16px; \n min-height: 0; \n }\n .empty-state { \n flex: 1; \n display: flex; \n flex-direction: column; \n align-items: center; \n justify-content: center; \n gap: 12px; \n color: #64748b; \n text-align: center; \n padding: 20px; \n }\n .empty-state-icon { font-size: 48px; opacity: 0.3; }\n .empty-state-title { font-size: 20px; font-weight: 700; color: #334155; }\n .empty-state-text { font-size: 13px; max-width: 280px; }\n\n .text-interface { \n display: none".concat(important, "; \n flex: 1; \n flex-direction: column; \n min-height: 0; \n overflow: hidden; \n }\n .text-interface.active { display: flex").concat(important, "; }\n \n .message { \n display: flex; \n gap: 8px; \n padding: 4px 0; \n max-width: 100%; \n align-items: center; \n }\n .message.edge-left { flex-direction: row; }\n .message.edge-right { flex-direction: row-reverse; }\n .message-bubble { \n padding: 12px; \n border-radius: ").concat(messages.borderRadius, "px; \n max-width: 80%; \n font-size: ").concat(messages.fontSize, "; \n color: ").concat(messages.textColor, "; \n word-wrap: break-word; \n text-align: ").concat(this.config.direction === 'rtl' ? 'right' : 'left', "; \n direction: ").concat(this.config.direction || 'ltr', ";\n }\n .message.user { \n background: ").concat(messages.userBackgroundColor, "; \n align-self: ").concat(this.config.direction === 'rtl' ? 'flex-start' : 'flex-end', "; \n }\n .message.agent { \n background: ").concat(messages.agentBackgroundColor, "; \n align-self: ").concat(this.config.direction === 'rtl' ? 'flex-end' : 'flex-start', "; \n }\n .message .message-bubble { \n text-align: ").concat(this.config.direction === 'rtl' ? 'right' : 'left', " !important; \n }\n ").concat(this.config.direction === 'rtl' ? "\n .message-bubble {\n text-align: right !important;\n }\n " : '', "\n .message-avatar { \n width: 20px; \n height: 20px; \n display: flex; \n align-items: center; \n justify-content: center; \n flex-shrink: 0; \n color: inherit; \n font-size: 18px; \n line-height: 1; \n background: transparent; \n border: none; \n }\n .message-avatar.user { background: transparent; }\n .message-avatar.agent { background: transparent; }\n \n .message.system {\n background: ").concat(messages.systemBackgroundColor, ";\n align-self: flex-start;\n }\n .message.error {\n background: ").concat(messages.errorBackgroundColor, ";\n align-self: flex-start;\n }\n \n .input-container {\n display: flex;\n gap: 8px;\n padding: 12px 16px;\n background: #FFFFFF;\n border-top: 1px solid #E5E7EB;\n align-items: center;\n flex-shrink: 0;\n flex-direction: ").concat(this.config.direction === 'rtl' ? 'row-reverse' : 'row', ";\n }\n \n .input-wrapper {\n position: relative;\n display: flex;\n align-items: center;\n }\n \n .message-input {\n width: 100%;\n min-height: 32px;\n max-height: 120px;\n padding: ").concat(inputPadding, ";\n border: 1px solid ").concat(inputBorderColor, ";\n border-radius: ").concat(inputBorderRadius, "px;\n font-size: ").concat(inputFontSize, ";\n font-family: inherit;\n line-height: 1.3;\n resize: none;\n overflow-y: auto;\n background: ").concat(inputBackgroundColor, ";\n color: ").concat(inputTextColor, ";\n vertical-align: top;\n margin: 0;\n display: block;\n white-space: pre-wrap;\n word-wrap: break-word;\n text-align: ").concat(this.config.direction === 'rtl' ? 'right' : 'left', ";\n direction: ").concat(this.config.direction || 'ltr', ";\n -webkit-appearance: none;\n appearance: none;\n box-sizing: border-box;\n }\n \n .message-input:focus {\n outline: none;\n border-color: ").concat(inputFocusColor, ";\n background: ").concat(inputBackgroundColor === '#FFFFFF' ? '#FFFFFF' : inputBackgroundColor, ";\n box-shadow: 0 0 0 3px ").concat(inputFocusColor, "33;\n }\n \n .message-input::placeholder {\n color: #9CA3AF;\n text-align: ").concat(this.config.direction === 'rtl' ? 'right' : 'left', ";\n }\n \n .send-button {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n border: none;\n background: ").concat(sendButtonColor, ";\n color: ").concat(sendButtonTextColor, ";\n font-size: ").concat(this.config.sendButtonFontSize || ((_this$config$panel15 = this.config.panel) === null || _this$config$panel15 === void 0 ? void 0 : _this$config$panel15.sendButtonFontSize) || '18px', ";\n font-weight: ").concat(this.config.sendButtonFontWeight || ((_this$config$panel16 = this.config.panel) === null || _this$config$panel16 === void 0 ? void 0 : _this$config$panel16.sendButtonFontWeight) || '500', ";\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: all 0.2s ease;\n box-shadow: 0 4px 12px rgba(124, 60, 237, 0.3);\n }\n \n .send-button:hover:not(:disabled) {\n background: ").concat(sendButtonHoverColor, ";\n transform: scale(1.05);\n box-shadow: 0 6px 16px rgba(124, 60, 237, 0.4);\n }\n \n .send-button-hint {\n width: 100%;\n text-align: center;\n margin-top: 4px;\n }\n \n .send-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n \n .typing-indicator {\n display: inline-flex;\n gap: 4px;\n align-items: center;\n }\n \n .typing-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: #64748b;\n animation: typingDot 1.4s ease-in-out infinite;\n }\n \n .typing-dot:nth-child(2) { animation-delay: 0.2s; }\n .typing-dot:nth-child(3) { animation-delay: 0.4s; }\n \n @keyframes typingDot {\n 0%, 60%, 100% { transform: translateY(0); opacity: 0.7; }\n 30% { transform: translateY(-8px); opacity: 1; }\n }\n \n .error-message {\n padding: 12px;\n background: ").concat(messages.errorBackgroundColor, ";\n border-radius: ").concat(messages.borderRadius, "px;\n color: #991B1B;\n font-size: ").concat(messages.fontSize, ";\n margin: 8px 0;\n }\n \n @media (max-width: 768px) {\n #messagesContainer {\n padding: 12px;\n gap: 12px;\n }\n \n .message-bubble {\n max-width: 85%;\n font-size: 14px;\n padding: 10px;\n }\n \n .text-input-container {\n padding: 10px;\n gap: 8px;\n }\n \n #text-chat-input {\n font-size: 16px !important; /* Prevents iOS zoom on focus */\n padding: 10px 14px;\n min-height: 44px;\n }\n \n #text-chat-send {\n min-width: 56px;\n min-height: 44px;\n width: 56px;\n height: 44px;\n }\n \n .empty-state-icon {\n font-size: 40px;\n }\n \n .empty-state-title {\n font-size: 18px;\n }\n \n .empty-state-text {\n font-size: 12px;\n }\n }\n \n @media (max-width: 480px) {\n #messagesContainer {\n padding: 10px;\n gap: 10px;\n }\n \n .message-bubble {\n max-width: 90%;\n font-size: 13px;\n padding: 8px;\n }\n \n .text-input-container {\n padding: 8px;\n }\n \n #text-chat-input {\n font-size: 16px !important;\n padding: 8px 12px;\n }\n }\n ");
15097
+ return "\n /* Messages container using new classes */\n #messagesContainer { \n flex: 1; \n overflow-y: auto; \n overflow-x: hidden; \n padding: 20px; \n background: #f8fafc; \n display: flex; \n flex-direction: column; \n gap: 16px; \n min-height: 0; \n }\n .empty-state { \n flex: 1; \n display: flex; \n flex-direction: column; \n align-items: center; \n justify-content: center; \n gap: 12px; \n color: #64748b; \n text-align: center; \n padding: 20px; \n }\n .empty-state-icon { font-size: 48px; opacity: 0.3; }\n .empty-state-title { font-size: 20px; font-weight: 700; color: #334155; }\n .empty-state-text { font-size: 13px; max-width: 280px; }\n\n .text-interface { \n display: none".concat(important, "; \n flex: 1; \n flex-direction: column; \n min-height: 0; \n overflow: hidden; \n }\n .text-interface.active { display: flex").concat(important, "; }\n \n .message { \n display: flex; \n gap: 8px; \n padding: 4px 0; \n max-width: 100%; \n align-items: center; \n }\n .message.edge-left { flex-direction: row; }\n .message.edge-right { flex-direction: row-reverse; }\n .message-bubble { \n padding: 12px; \n border-radius: ").concat(messages.borderRadius, "px").concat(important, "; \n max-width: 80%; \n font-size: ").concat(messages.fontSize, "; \n word-wrap: break-word; \n text-align: ").concat(this.config.direction === 'rtl' ? 'right' : 'left', "; \n direction: ").concat(this.config.direction || 'ltr', ";\n }\n .message.user .message-bubble { \n background: ").concat(messages.userBackgroundColor).concat(important, "; \n color: ").concat(messages.userTextColor || messages.textColor).concat(important, "; \n }\n .message.agent .message-bubble { \n background: ").concat(messages.agentBackgroundColor).concat(important, "; \n color: ").concat(messages.agentTextColor || messages.textColor).concat(important, "; \n }\n .message.user { \n align-self: ").concat(this.config.direction === 'rtl' ? 'flex-start' : 'flex-end', "; \n }\n .message.agent { \n align-self: ").concat(this.config.direction === 'rtl' ? 'flex-end' : 'flex-start', "; \n }\n .message .message-bubble { \n text-align: ").concat(this.config.direction === 'rtl' ? 'right' : 'left', " !important; \n }\n ").concat(this.config.direction === 'rtl' ? "\n .message-bubble {\n text-align: right !important;\n }\n " : '', "\n .message-avatar { \n width: 20px; \n height: 20px; \n display: flex; \n align-items: center; \n justify-content: center; \n flex-shrink: 0; \n color: inherit; \n font-size: 18px; \n line-height: 1; \n background: transparent; \n border: none; \n }\n .message-avatar.user { background: transparent; }\n .message-avatar.agent { background: transparent; }\n \n .message.system {\n background: ").concat(messages.systemBackgroundColor, ";\n align-self: flex-start;\n }\n .message.error {\n background: ").concat(messages.errorBackgroundColor, ";\n align-self: flex-start;\n }\n \n .input-container {\n display: flex;\n gap: 8px;\n padding: 12px 16px;\n background: #FFFFFF;\n border-top: 1px solid #E5E7EB;\n align-items: center;\n flex-shrink: 0;\n flex-direction: ").concat(this.config.direction === 'rtl' ? 'row-reverse' : 'row', ";\n }\n \n .input-wrapper {\n position: relative;\n display: flex;\n align-items: center;\n }\n \n .message-input {\n width: 100%;\n min-height: 32px;\n max-height: 120px;\n padding: ").concat(inputPadding, ";\n border: 1px solid ").concat(inputBorderColor, ";\n border-radius: ").concat(inputBorderRadius, "px;\n font-size: ").concat(inputFontSize, ";\n font-family: inherit;\n line-height: 1.3;\n resize: none;\n overflow-y: auto;\n background: ").concat(inputBackgroundColor, ";\n color: ").concat(inputTextColor, ";\n vertical-align: top;\n margin: 0;\n display: block;\n white-space: pre-wrap;\n word-wrap: break-word;\n text-align: ").concat(this.config.direction === 'rtl' ? 'right' : 'left', ";\n direction: ").concat(this.config.direction || 'ltr', ";\n -webkit-appearance: none;\n appearance: none;\n box-sizing: border-box;\n }\n \n .message-input:focus {\n outline: none;\n border-color: ").concat(inputFocusColor, ";\n background: ").concat(inputBackgroundColor === '#FFFFFF' ? '#FFFFFF' : inputBackgroundColor, ";\n box-shadow: 0 0 0 3px ").concat(inputFocusColor, "33;\n }\n \n .message-input::placeholder {\n color: #9CA3AF;\n text-align: ").concat(this.config.direction === 'rtl' ? 'right' : 'left', ";\n }\n \n .send-button {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n border: none;\n background: ").concat(sendButtonColor, ";\n color: ").concat(sendButtonTextColor, ";\n font-size: ").concat(this.config.sendButtonFontSize || ((_this$config$panel15 = this.config.panel) === null || _this$config$panel15 === void 0 ? void 0 : _this$config$panel15.sendButtonFontSize) || '18px', ";\n font-weight: ").concat(this.config.sendButtonFontWeight || ((_this$config$panel16 = this.config.panel) === null || _this$config$panel16 === void 0 ? void 0 : _this$config$panel16.sendButtonFontWeight) || '500', ";\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: all 0.2s ease;\n box-shadow: 0 4px 12px rgba(124, 60, 237, 0.3);\n }\n \n .send-button:hover:not(:disabled) {\n background: ").concat(sendButtonHoverColor, ";\n transform: scale(1.05);\n box-shadow: 0 6px 16px rgba(124, 60, 237, 0.4);\n }\n \n .send-button-hint {\n width: 100%;\n text-align: center;\n margin-top: 4px;\n }\n \n .send-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n \n .typing-indicator {\n display: inline-flex;\n gap: 4px;\n align-items: center;\n }\n \n .typing-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: #64748b;\n animation: typingDot 1.4s ease-in-out infinite;\n }\n \n .typing-dot:nth-child(2) { animation-delay: 0.2s; }\n .typing-dot:nth-child(3) { animation-delay: 0.4s; }\n \n @keyframes typingDot {\n 0%, 60%, 100% { transform: translateY(0); opacity: 0.7; }\n 30% { transform: translateY(-8px); opacity: 1; }\n }\n \n .error-message {\n padding: 12px;\n background: ").concat(messages.errorBackgroundColor, ";\n border-radius: ").concat(messages.borderRadius, "px;\n color: #991B1B;\n font-size: ").concat(messages.fontSize, ";\n margin: 8px 0;\n }\n \n @media (max-width: 768px) {\n #messagesContainer {\n padding: 12px;\n gap: 12px;\n }\n \n .message-bubble {\n max-width: 85%;\n font-size: 14px;\n padding: 10px;\n }\n \n .text-input-container {\n padding: 10px;\n gap: 8px;\n }\n \n #text-chat-input {\n font-size: 16px !important; /* Prevents iOS zoom on focus */\n padding: 10px 14px;\n min-height: 44px;\n }\n \n #text-chat-send {\n min-width: 56px;\n min-height: 44px;\n width: 56px;\n height: 44px;\n }\n \n .empty-state-icon {\n font-size: 40px;\n }\n \n .empty-state-title {\n font-size: 18px;\n }\n \n .empty-state-text {\n font-size: 12px;\n }\n }\n \n @media (max-width: 480px) {\n #messagesContainer {\n padding: 10px;\n gap: 10px;\n }\n \n .message-bubble {\n max-width: 90%;\n font-size: 13px;\n padding: 8px;\n }\n \n .text-input-container {\n padding: 8px;\n }\n \n #text-chat-input {\n font-size: 16px !important;\n padding: 8px 12px;\n }\n }\n ");
14707
15098
  }
14708
15099
 
14709
15100
  /**
@@ -14938,6 +15329,7 @@ var TextInterface = /*#__PURE__*/function () {
14938
15329
  }, {
14939
15330
  key: "addMessage",
14940
15331
  value: function addMessage(type, text) {
15332
+ var _this$config$messages, _this$config$messages2;
14941
15333
  var messages = this.shadowRoot.getElementById('messagesContainer');
14942
15334
  if (!messages) return;
14943
15335
 
@@ -14951,7 +15343,8 @@ var TextInterface = /*#__PURE__*/function () {
14951
15343
  message.className = "message ".concat(type, " ").concat(edgeClass);
14952
15344
  var avatar = document.createElement('div');
14953
15345
  avatar.className = "message-avatar ".concat(type);
14954
- avatar.textContent = type === 'user' ? '👤' : '🤖';
15346
+ var avatarIcon = type === 'user' ? ((_this$config$messages = this.config.messages) === null || _this$config$messages === void 0 ? void 0 : _this$config$messages.userAvatarIcon) || '👤' : ((_this$config$messages2 = this.config.messages) === null || _this$config$messages2 === void 0 ? void 0 : _this$config$messages2.agentAvatarIcon) || '🤖';
15347
+ avatar.textContent = avatarIcon;
14955
15348
  var bubble = document.createElement('div');
14956
15349
  bubble.className = 'message-bubble';
14957
15350
  bubble.textContent = text;
@@ -14969,6 +15362,7 @@ var TextInterface = /*#__PURE__*/function () {
14969
15362
  }, {
14970
15363
  key: "beginStreaming",
14971
15364
  value: function beginStreaming() {
15365
+ var _this$config$messages3;
14972
15366
  var messages = this.shadowRoot.getElementById('messagesContainer');
14973
15367
  if (!messages) return;
14974
15368
 
@@ -14980,7 +15374,7 @@ var TextInterface = /*#__PURE__*/function () {
14980
15374
  el.id = 'agent-streaming';
14981
15375
  var avatar = document.createElement('div');
14982
15376
  avatar.className = 'message-avatar agent';
14983
- avatar.textContent = '🤖';
15377
+ avatar.textContent = ((_this$config$messages3 = this.config.messages) === null || _this$config$messages3 === void 0 ? void 0 : _this$config$messages3.agentAvatarIcon) || '🤖';
14984
15378
  var bubble = document.createElement('div');
14985
15379
  bubble.className = 'message-bubble';
14986
15380
  // show typing dots until first chunk
@@ -15051,11 +15445,11 @@ var TextInterface = /*#__PURE__*/function () {
15051
15445
  // Check if this is a domain validation error
15052
15446
  var isDomainError = error && (error.message === 'DOMAIN_NOT_WHITELISTED' || typeof error === 'string' && error.includes('DOMAIN_NOT_WHITELISTED') || error.message && error.message.includes('Domain not whitelisted') || typeof error === 'string' && error.includes('Domain not whitelisted'));
15053
15447
  if (isDomainError) {
15054
- var _this$config$messages;
15448
+ var _this$config$messages4;
15055
15449
  // Show domain error with title and message
15056
15450
  var errorContainer = document.createElement('div');
15057
15451
  errorContainer.className = 'error-message';
15058
- errorContainer.style.cssText = 'padding: 16px; margin: 12px; border-radius: 8px; background: ' + (((_this$config$messages = this.config.messages) === null || _this$config$messages === void 0 ? void 0 : _this$config$messages.errorBackgroundColor) || '#FEE2E2') + ';';
15452
+ errorContainer.style.cssText = 'padding: 16px; margin: 12px; border-radius: 8px; background: ' + (((_this$config$messages4 = this.config.messages) === null || _this$config$messages4 === void 0 ? void 0 : _this$config$messages4.errorBackgroundColor) || '#FEE2E2') + ';';
15059
15453
  var title = document.createElement('div');
15060
15454
  title.style.cssText = 'font-weight: 600; font-size: 16px; margin-bottom: 8px; color: #991B1B;';
15061
15455
  title.textContent = this.t('domainNotValidated');
@@ -17471,8 +17865,16 @@ var Desktop = /*#__PURE__*/function () {
17471
17865
  // Update both old and new status text elements
17472
17866
  var statusText = this.shadowRoot.getElementById('compactStatusText') || this.shadowRoot.getElementById('desktopStatusText');
17473
17867
  if (!statusText) return;
17474
- var isListening = this.voiceInterface.isActive && !this.voiceInterface.isMicMuted;
17475
- var statusMessage = isListening ? this.t('listening') : this.t('connected');
17868
+
17869
+ // Use custom statusText from config if provided, otherwise use translations
17870
+ var customStatusText = this.config.statusText;
17871
+ var statusMessage;
17872
+ if (customStatusText) {
17873
+ statusMessage = customStatusText;
17874
+ } else {
17875
+ var isListening = this.voiceInterface.isActive && !this.voiceInterface.isMicMuted;
17876
+ statusMessage = isListening ? this.t('listening') : this.t('connected');
17877
+ }
17476
17878
  statusText.textContent = statusMessage;
17477
17879
 
17478
17880
  // Also update the old one if it exists
@@ -18126,17 +18528,27 @@ var Mobile = /*#__PURE__*/function () {
18126
18528
  var headerStatusText = document.getElementById('mobileHeaderStatusText');
18127
18529
  var statusDot = document.getElementById('mobileStatusDot');
18128
18530
  if (!statusText && !headerStatusText) return;
18531
+
18532
+ // Use custom statusText from config if provided, otherwise use translations
18533
+ var customStatusText = this.config.statusText;
18129
18534
  var displayText = '';
18130
18535
  var dotColor = '#6b7280';
18131
- if (status === 'listening' || status === 'recording') {
18132
- displayText = this.t('listening') || 'Listening...';
18133
- dotColor = '#22c55e';
18134
- } else if (status === 'speaking') {
18135
- displayText = this.t('speaking') || 'Speaking...';
18136
- dotColor = '#a855f7';
18536
+ if (customStatusText) {
18537
+ // Use custom status text for all states
18538
+ displayText = customStatusText;
18539
+ dotColor = this.config.statusDotColor || '#10b981';
18137
18540
  } else {
18138
- displayText = this.t('paused') || 'Paused';
18139
- dotColor = '#facc15';
18541
+ // Use dynamic status based on state
18542
+ if (status === 'listening' || status === 'recording') {
18543
+ displayText = this.t('listening') || 'Listening...';
18544
+ dotColor = '#22c55e';
18545
+ } else if (status === 'speaking') {
18546
+ displayText = this.t('speaking') || 'Speaking...';
18547
+ dotColor = '#a855f7';
18548
+ } else {
18549
+ displayText = this.t('paused') || 'Paused';
18550
+ dotColor = '#facc15';
18551
+ }
18140
18552
  }
18141
18553
  if (statusText) statusText.textContent = displayText;
18142
18554
  if (headerStatusText) headerStatusText.textContent = displayText;
@@ -18266,22 +18678,30 @@ var Styles = /*#__PURE__*/function () {
18266
18678
  return _createClass(Styles, [{
18267
18679
  key: "generateCSS",
18268
18680
  value: function generateCSS() {
18681
+ var _this$config$text;
18269
18682
  var avatarBg = this.config.avatarBackgroundColor || '#667eea';
18270
18683
  var avatarActiveBg = this.config.avatarActiveBackgroundColor || this.config.avatarBackgroundColor || '#667eea';
18271
18684
  var statusTitleColor = this.config.statusTitleColor || '#1e293b';
18272
18685
  var statusSubtitleColor = this.config.statusSubtitleColor || '#64748b';
18686
+ var statusDotColor = this.config.statusDotColor || '#10b981';
18687
+ var statusText = this.config.statusText || null; // Custom status text (null = use translations)
18273
18688
  var startCallBtnColor = this.config.startCallButtonColor || '#667eea';
18274
18689
  var startCallBtnTextColor = this.config.startCallButtonTextColor || '#FFFFFF';
18275
18690
  var transcriptBg = this.config.transcriptBackgroundColor || '#FFFFFF';
18276
18691
  var transcriptTextColor = this.config.transcriptTextColor || '#1e293b';
18277
18692
  var transcriptLabelColor = this.config.transcriptLabelColor || '#94a3b8';
18278
18693
  var controlBtnColor = this.config.controlButtonColor || '#FFFFFF';
18694
+ var liveTranscriptTextColor = this.config.liveTranscriptTextColor || this.config.transcriptTextColor || '#64748b';
18695
+ var liveTranscriptFontSize = this.config.liveTranscriptFontSize || '14px';
18279
18696
  var controlBtnSecondaryColor = this.config.controlButtonSecondaryColor || '#64748b';
18697
+ var liveIndicatorDotColor = this.config.liveIndicatorDotColor || '#10b981';
18698
+ var liveIndicatorTextColor = this.config.liveIndicatorTextColor || '#10b981';
18699
+ var micButtonColor = this.config.micButtonColor || controlBtnColor;
18700
+ var speakerButtonColor = this.config.speakerButtonColor || controlBtnColor;
18280
18701
  var endCallBtnColor = this.config.endCallButtonColor || '#ef4444';
18281
-
18282
- // Add !important to display rules when not using Shadow DOM (to override theme CSS)
18283
- var important = this.config.useShadowDOM === false ? ' !important' : '';
18284
- return "\n /* Voice Interface Styles - Ultra-compact for Wix iframes */\n .voice-interface { \n display: none".concat(important, "; \n flex: 1; \n flex-direction: column;\n align-items: stretch; \n justify-content: flex-start; \n padding: 0; \n background: linear-gradient(180deg, #f8fafc 0%, #e0e7ff 100%);\n overflow: hidden;\n min-height: 0;\n height: 100%;\n width: 100%;\n box-sizing: border-box;\n }\n .voice-interface.active { display: flex").concat(important, "; }\n \n /* Voice States - Better scaling gaps */\n #voiceIdleState {\n display: flex;\n flex-direction: column;\n align-items: center;\n width: 100%;\n height: 100%;\n min-height: 0;\n justify-content: center;\n overflow: hidden;\n flex: 1;\n box-sizing: border-box;\n gap: clamp(6px, 1.5vh, 12px);\n }\n \n #voiceActiveState {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n width: 100%;\n height: 100%;\n min-height: 0;\n justify-content: flex-start;\n overflow: hidden;\n flex: 1;\n box-sizing: border-box;\n gap: 0;\n padding: 0;\n }\n \n #voiceActiveState[style*=\"display: none\"] {\n display: none !important;\n }\n \n /* Voice Avatar - Scales better from small to large */\n .voice-avatar,\n .voice-avatar-active {\n width: clamp(80px, 18vh, 160px);\n height: clamp(80px, 18vh, 160px);\n aspect-ratio: 1;\n border-radius: 50%;\n background: linear-gradient(135deg, ").concat(avatarBg, " 0%, ").concat(avatarActiveBg, " 100%);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: clamp(40px, 9vh, 80px);\n margin: 0;\n box-shadow: 0 8px 30px rgba(102, 126, 234, 0.3);\n transition: all 0.3s ease;\n flex-shrink: 0;\n position: relative;\n }\n \n .voice-avatar-active {\n animation: avatarPulse 2s ease-in-out infinite;\n }\n \n @keyframes avatarPulse {\n 0%, 100% { \n transform: scale(1);\n }\n 50% { \n transform: scale(1.05);\n }\n }\n \n .voice-avatar-active.speaking {\n animation: avatarSpeak 0.5s ease-in-out infinite;\n }\n \n @keyframes avatarSpeak {\n 0%, 100% { transform: scale(1); }\n 50% { transform: scale(1.08); }\n }\n \n /* Voice Rings Animation */\n .voice-rings {\n position: absolute;\n width: 100%;\n height: 100%;\n border-radius: 50%;\n }\n \n .voice-ring {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n border: 2px solid rgba(102, 126, 234, 0.3);\n border-radius: 50%;\n opacity: 0;\n animation: ringExpand 2s ease-out infinite;\n }\n \n .voice-ring:nth-child(2) { animation-delay: 0.5s; }\n .voice-ring:nth-child(3) { animation-delay: 1s; }\n \n @keyframes ringExpand {\n 0% {\n width: 100%;\n height: 100%;\n opacity: 0.6;\n }\n 100% {\n width: 160%;\n height: 160%;\n opacity: 0;\n }\n }\n \n /* Voice Status - Scales with container */\n .voice-status {\n text-align: center;\n margin: 0;\n flex-shrink: 0;\n min-height: 0;\n }\n \n .voice-status-title {\n font-size: clamp(12px, 3vh, 20px);\n font-weight: 600;\n color: ").concat(statusTitleColor, ";\n margin-bottom: clamp(2px, 0.5vh, 4px);\n line-height: 1.2;\n }\n \n .voice-status-subtitle {\n font-size: clamp(10px, 2vh, 14px);\n color: ").concat(statusSubtitleColor, ";\n line-height: 1.2;\n }\n \n /* Start Call Button - Scales with container */\n .start-call-btn {\n margin: 0;\n width: min(280px, 70vw)").concat(important, ";\n height: clamp(48px, 8vh, 64px)").concat(important, ";\n border-radius: clamp(24px, 4vh, 32px)").concat(important, ";\n border: none").concat(important, ";\n background: ").concat(startCallBtnColor).concat(important, ";\n color: ").concat(startCallBtnTextColor).concat(important, ";\n font-size: clamp(14px, 2.5vh, 18px)").concat(important, ";\n font-weight: 600").concat(important, ";\n cursor: pointer").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n gap: clamp(8px, 1.5vh, 12px);\n box-shadow: 0 12px 30px rgba(102, 126, 234, 0.4);\n transition: all 0.3s ease;\n flex-shrink: 0;\n }\n \n .start-call-btn svg {\n display: block").concat(important, ";\n visibility: visible").concat(important, ";\n opacity: 1").concat(important, ";\n width: auto").concat(important, ";\n height: auto").concat(important, ";\n }\n \n .start-call-btn svg {\n width: clamp(22px, 4vh, 32px);\n height: clamp(22px, 4vh, 32px);\n }\n \n .start-call-btn:hover {\n transform: translateY(-2px);\n box-shadow: 0 12px 28px rgba(102, 126, 234, 0.5);\n }\n \n .start-call-btn:active {\n transform: translateY(-1px);\n }\n .start-call-btn:disabled {\n cursor: not-allowed").concat(important, ";\n opacity: 0.6").concat(important, ";\n }\n \n /* Connecting Spinner */\n .connecting-spinner {\n display: inline-block;\n width: 16px;\n height: 16px;\n border: 2px solid rgba(255, 255, 255, 0.3);\n border-top-color: ").concat(startCallBtnTextColor, ";\n border-radius: 50%;\n animation: spin 1s linear infinite;\n margin-right: 8px;\n vertical-align: middle;\n }\n \n @keyframes spin {\n to { transform: rotate(360deg); }\n }\n\n \n /* Voice Transcript - Scales with container */\n .voice-transcript {\n background: ").concat(transcriptBg, ";\n padding: clamp(6px, 1.5vh, 12px);\n border-radius: 10px;\n width: min(360px, calc(100% - 40px));\n margin: 0;\n min-height: clamp(80px, 15vh, 120px);\n max-height: clamp(100px, 18vh, 140px);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\n flex-shrink: 1;\n overflow-y: auto;\n overflow-x: hidden;\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n }\n \n .transcript-label {\n font-size: clamp(8px, 1.4vh, 11px);\n color: ").concat(transcriptLabelColor, ";\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n margin-bottom: clamp(3px, 0.6vh, 6px);\n flex-shrink: 0;\n word-wrap: break-word;\n }\n \n .transcript-text {\n font-size: clamp(11px, 2vh, 15px);\n color: ").concat(transcriptTextColor, ";\n line-height: 1.4;\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n word-wrap: break-word;\n overflow-wrap: break-word;\n }\n \n .transcript-text.empty {\n color: #cbd5e1;\n font-style: italic;\n }\n \n /* Voice Text Input Area - Type while on voice call */\n .voice-text-input-area {\n width: 100%;\n padding: 14px 16px;\n margin: 0;\n flex-shrink: 0;\n background: #ffffff;\n border-top: 1px solid rgba(0, 0, 0, 0.06);\n box-sizing: border-box;\n }\n \n .voice-input-wrapper {\n display: flex;\n align-items: center;\n gap: 10px;\n background: #f1f5f9;\n border-radius: 12px;\n padding: 4px 4px 4px 14px;\n border: 1px solid transparent;\n transition: all 0.2s ease;\n }\n \n .voice-input-wrapper:focus-within {\n background: #fff;\n border-color: #a855f7;\n box-shadow: 0 0 0 3px rgba(168, 85, 247, 0.1);\n }\n \n .voice-text-input {\n flex: 1;\n border: none;\n outline: none;\n font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, sans-serif;\n font-size: 14px;\n color: #1e1b4b;\n background: transparent;\n padding: 10px 0;\n }\n \n .voice-text-input::placeholder {\n color: #94a3b8;\n }\n \n .voice-send-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 38px;\n height: 38px;\n border-radius: 10px;\n border: none;\n background: linear-gradient(135deg, #7c3aed, #a855f7);\n color: #fff;\n cursor: pointer;\n transition: transform 0.2s ease;\n flex-shrink: 0;\n }\n \n .voice-send-btn:hover:not(:disabled) {\n transform: scale(1.05);\n }\n \n .voice-send-btn:active:not(:disabled) {\n transform: scale(0.95);\n }\n \n .voice-send-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n transform: none;\n }\n \n .voice-send-btn svg {\n width: 16px;\n height: 16px;\n }\n \n .voice-input-hint {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 5px;\n margin-top: 10px;\n font-size: 11px;\n color: #64748b;\n transition: color 0.2s ease;\n }\n \n .voice-input-hint svg {\n width: 12px;\n height: 12px;\n color: #10b981;\n }\n \n /* Text input status states */\n .voice-input-hint--sending {\n color: #666;\n }\n \n .voice-input-hint--success {\n color: #28a745;\n }\n \n .voice-input-hint--queued {\n color: #ffc107;\n }\n \n .voice-input-hint--error {\n color: #dc3545;\n }\n \n /* Disabled input styling */\n .voice-text-input:disabled,\n #mobileTextInput:disabled {\n background-color: #f5f5f5;\n cursor: not-allowed;\n }\n \n .voice-send-btn:disabled,\n #mobileSendBtn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n \n /* Voice Controls - Scales with container */\n .voice-controls {\n display: flex;\n gap: clamp(8px, 1.8vh, 14px);\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n margin: 0;\n padding-top: 0;\n }\n \n .voice-control-btn {\n width: clamp(48px, 9vh, 72px)").concat(important, ";\n height: clamp(48px, 9vh, 72px)").concat(important, ";\n min-width: clamp(48px, 9vh, 72px)").concat(important, ";\n min-height: clamp(48px, 9vh, 72px)").concat(important, ";\n max-width: clamp(48px, 9vh, 72px)").concat(important, ";\n max-height: clamp(48px, 9vh, 72px)").concat(important, ";\n aspect-ratio: 1").concat(important, ";\n border-radius: 50%").concat(important, ";\n border: none").concat(important, ";\n cursor: pointer").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n transition: all 0.2s;\n position: relative").concat(important, ";\n flex-shrink: 0;\n overflow: hidden").concat(important, ";\n padding: 0").concat(important, ";\n margin: 0").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n \n .voice-control-btn svg {\n width: 48%").concat(important, ";\n height: 48%").concat(important, ";\n min-width: 48%").concat(important, ";\n min-height: 48%").concat(important, ";\n max-width: 48%").concat(important, ";\n max-height: 48%").concat(important, ";\n display: block").concat(important, ";\n visibility: visible").concat(important, ";\n opacity: 1").concat(important, ";\n margin: 0").concat(important, ";\n padding: 0").concat(important, ";\n position: relative").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n \n .voice-control-btn.primary {\n width: clamp(54px, 10vh, 80px)").concat(important, ";\n height: clamp(54px, 10vh, 80px)").concat(important, ";\n min-width: clamp(54px, 10vh, 80px)").concat(important, ";\n min-height: clamp(54px, 10vh, 80px)").concat(important, ";\n max-width: clamp(54px, 10vh, 80px)").concat(important, ";\n max-height: clamp(54px, 10vh, 80px)").concat(important, ";\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%)").concat(important, ";\n color: white").concat(important, ";\n box-shadow: 0 6px 18px rgba(102, 126, 234, 0.4);\n }\n \n .voice-control-btn.primary:hover {\n transform: scale(1.05);\n }\n \n .voice-control-btn.primary.active {\n background: white").concat(important, ";\n animation: recordingPulse 1.5s ease-in-out infinite;\n }\n \n .voice-control-btn.primary.active svg {\n fill: ").concat(endCallBtnColor).concat(important, ";\n }\n \n /* More specific selectors for WordPress compatibility */\n #endCallBtn.voice-control-btn.primary.active,\n #muteBtn.voice-control-btn.secondary,\n #speakerBtn.voice-control-btn.secondary {\n border-radius: 50% !important;\n width: clamp(48px, 9vh, 72px) !important;\n height: clamp(48px, 9vh, 72px) !important;\n min-width: clamp(48px, 9vh, 72px) !important;\n min-height: clamp(48px, 9vh, 72px) !important;\n max-width: clamp(48px, 9vh, 72px) !important;\n max-height: clamp(48px, 9vh, 72px) !important;\n aspect-ratio: 1 !important;\n overflow: hidden !important;\n }\n \n #endCallBtn.voice-control-btn.primary.active {\n width: clamp(54px, 10vh, 80px) !important;\n height: clamp(54px, 10vh, 80px) !important;\n min-width: clamp(54px, 10vh, 80px) !important;\n min-height: clamp(54px, 10vh, 80px) !important;\n max-width: clamp(54px, 10vh, 80px) !important;\n max-height: clamp(54px, 10vh, 80px) !important;\n }\n \n #endCallBtn.voice-control-btn.primary.active svg,\n #muteBtn.voice-control-btn.secondary svg,\n #speakerBtn.voice-control-btn.secondary svg {\n display: block !important;\n visibility: visible !important;\n opacity: 1 !important;\n width: 48% !important;\n height: 48% !important;\n margin: 0 !important;\n padding: 0 !important;\n position: relative !important;\n }\n \n @keyframes recordingPulse {\n 0%, 100% { \n box-shadow: 0 6px 16px rgba(239, 68, 68, 0.4);\n }\n 50% { \n box-shadow: 0 6px 24px rgba(239, 68, 68, 0.7);\n }\n }\n \n .voice-control-btn.secondary {\n background: ").concat(controlBtnColor).concat(important, ";\n color: ").concat(controlBtnSecondaryColor).concat(important, ";\n box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);\n width: clamp(48px, 9vh, 72px)").concat(important, ";\n height: clamp(48px, 9vh, 72px)").concat(important, ";\n min-width: clamp(48px, 9vh, 72px)").concat(important, ";\n min-height: clamp(48px, 9vh, 72px)").concat(important, ";\n max-width: clamp(48px, 9vh, 72px)").concat(important, ";\n max-height: clamp(48px, 9vh, 72px)").concat(important, ";\n }\n \n .voice-control-btn.secondary:hover {\n background: #f8fafc").concat(important, ";\n transform: scale(1.05);\n }\n \n .voice-control-btn.secondary.muted {\n background: #f3f4f6").concat(important, ";\n }\n \n .voice-control-btn.secondary.muted .mute-icon {\n stroke: #9ca3af !important;\n }\n \n .voice-control-btn.secondary svg {\n width: 48%").concat(important, ";\n height: 48%").concat(important, ";\n display: block").concat(important, ";\n visibility: visible").concat(important, ";\n opacity: 1").concat(important, ";\n margin: 0").concat(important, ";\n padding: 0").concat(important, ";\n position: relative").concat(important, ";\n }\n \n .voice-timer {\n position: absolute;\n bottom: clamp(-18px, -3vh, -24px);\n font-size: clamp(9px, 1.6vh, 12px);\n color: #64748b;\n font-weight: 500;\n white-space: nowrap;\n }\n \n /* ===== DESKTOP VOICE SECTION - New Design ===== */\n .desktop-voice-section {\n padding: 16px 20px;\n background: linear-gradient(180deg, #ffffff 0%, rgba(168, 85, 247, 0.04) 100%);\n width: 100%;\n flex-shrink: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n box-sizing: border-box;\n text-align: center;\n }\n \n /* Ensure all children are centered */\n .desktop-voice-section > * {\n margin-left: auto;\n margin-right: auto;\n }\n \n .desktop-timer {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n padding: 5px 10px;\n background: rgba(0, 0, 0, 0.05);\n border-radius: 20px;\n font-family: 'JetBrains Mono', 'Courier New', monospace;\n font-size: 11px;\n color: #64748b;\n margin: 0 auto;\n }\n \n .desktop-timer .timer-dot {\n width: 5px;\n height: 5px;\n background: #ef4444;\n border-radius: 50%;\n animation: timerPulse 1s ease-in-out infinite;\n }\n \n @keyframes timerPulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.4; }\n }\n \n .desktop-avatar-container {\n margin-bottom: 12px;\n }\n \n .desktop-avatar-large {\n width: 80px !important;\n height: 80px !important;\n border-radius: 20px !important;\n margin: 0 auto 12px !important;\n box-shadow: 0 8px 24px rgba(168, 85, 247, 0.35) !important;\n background: linear-gradient(135deg, ").concat(avatarBg, " 0%, ").concat(avatarActiveBg, " 100%) !important;\n }\n \n .desktop-waveform {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n height: 36px;\n width: 100%;\n }\n \n .desktop-waveform-bar {\n width: 4px;\n background: rgba(255, 255, 255, 0.9);\n border-radius: 2px;\n animation: waveformAnimation 0.8s ease-in-out infinite;\n }\n \n .desktop-waveform-bar[data-index=\"0\"] { height: 14px; animation-delay: 0s; }\n .desktop-waveform-bar[data-index=\"1\"] { height: 26px; animation-delay: 0.1s; }\n .desktop-waveform-bar[data-index=\"2\"] { height: 36px; animation-delay: 0.2s; }\n .desktop-waveform-bar[data-index=\"3\"] { height: 22px; animation-delay: 0.3s; }\n .desktop-waveform-bar[data-index=\"4\"] { height: 16px; animation-delay: 0.4s; }\n \n @keyframes waveformAnimation {\n 0%, 100% { transform: scaleY(0.5); }\n 50% { transform: scaleY(1); }\n }\n \n .desktop-waveform.paused .desktop-waveform-bar {\n animation-play-state: paused;\n }\n\n /* New main waveform (used in updated template) */\n .desktop-main-waveform {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 3px;\n height: 48px;\n width: 100%;\n max-width: 200px;\n margin: 0 auto;\n padding: 0 20px;\n }\n\n .desktop-main-waveform .waveform-bar {\n width: 3px;\n background: #a855f7;\n border-radius: 2px;\n height: 8px;\n animation: waveformAnimation 0.8s ease-in-out infinite;\n }\n\n .desktop-main-waveform .waveform-bar:nth-child(1) { height: 12px; animation-delay: 0s; }\n .desktop-main-waveform .waveform-bar:nth-child(2) { height: 20px; animation-delay: 0.05s; }\n .desktop-main-waveform .waveform-bar:nth-child(3) { height: 28px; animation-delay: 0.1s; }\n .desktop-main-waveform .waveform-bar:nth-child(4) { height: 36px; animation-delay: 0.15s; }\n .desktop-main-waveform .waveform-bar:nth-child(5) { height: 44px; animation-delay: 0.2s; }\n .desktop-main-waveform .waveform-bar:nth-child(6) { height: 50px; animation-delay: 0.25s; }\n .desktop-main-waveform .waveform-bar:nth-child(7) { height: 54px; animation-delay: 0.3s; }\n .desktop-main-waveform .waveform-bar:nth-child(8) { height: 56px; animation-delay: 0.35s; }\n .desktop-main-waveform .waveform-bar:nth-child(9) { height: 54px; animation-delay: 0.4s; }\n .desktop-main-waveform .waveform-bar:nth-child(10) { height: 50px; animation-delay: 0.45s; }\n .desktop-main-waveform .waveform-bar:nth-child(11) { height: 44px; animation-delay: 0.5s; }\n .desktop-main-waveform .waveform-bar:nth-child(12) { height: 36px; animation-delay: 0.55s; }\n .desktop-main-waveform .waveform-bar:nth-child(13) { height: 28px; animation-delay: 0.6s; }\n .desktop-main-waveform .waveform-bar:nth-child(14) { height: 20px; animation-delay: 0.65s; }\n .desktop-main-waveform .waveform-bar:nth-child(15) { height: 12px; animation-delay: 0.7s; }\n\n .desktop-status {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 5px;\n font-size: 12px;\n color: #10b981;\n font-weight: 500;\n width: 100%;\n text-align: center;\n margin: 0 auto;\n }\n \n .desktop-status .status-dot {\n width: 5px;\n height: 5px;\n background: #10b981;\n border-radius: 50%;\n animation: statusPulse 1.5s ease-in-out infinite;\n }\n \n @keyframes statusPulse {\n 0%, 100% { transform: scale(1); opacity: 1; }\n 50% { transform: scale(1.15); opacity: 0.8; }\n }\n \n .desktop-live-waveform {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 3px;\n height: 48px;\n margin-bottom: 20px;\n }\n \n .desktop-live-bar {\n width: 3px;\n background: linear-gradient(180deg, ").concat(avatarBg, ", ").concat(avatarActiveBg, ");\n border-radius: 2px;\n transition: height 0.1s ease;\n height: 8px;\n }\n \n .desktop-controls {\n display: flex;\n gap: 8px;\n align-items: center;\n justify-content: center;\n width: 100%;\n margin: 0 auto;\n }\n \n .desktop-control-btn {\n width: 46px;\n height: 46px;\n border-radius: 50%;\n border: none;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n }\n \n .desktop-control-btn svg {\n width: 20px;\n height: 20px;\n }\n \n .desktop-mic-icon,\n .desktop-speaker-icon {\n width: 20px !important;\n height: 20px !important;\n display: block;\n flex-shrink: 0;\n }\n \n .desktop-control-btn.secondary.muted .desktop-mic-icon,\n .desktop-control-btn.secondary.muted .desktop-speaker-icon {\n width: 20px !important;\n height: 20px !important;\n }\n \n \n .desktop-control-btn.secondary:hover {\n background: rgba(0, 0, 0, 0.1);\n color: #1e293b;\n transform: scale(1.05);\n }\n .desktop-control-btn.secondary.muted {\n background: #f3f4f6;\n color: #9ca3af;\n }\n \n .desktop-control-btn.secondary.muted .desktop-mic-icon,\n .desktop-control-btn.secondary.muted .desktop-speaker-icon {\n stroke: #9ca3af;\n }\n \n .desktop-control-btn.secondary {\n position: relative;\n }\n .desktop-mic-off-icon,\n .desktop-speaker-off-icon {\n position: absolute;\n top: 50%;\n left: 50%;\n width: 46px;\n height: 46px;\n transform: translate(-50%, -50%);\n z-index: 10;\n }\n .desktop-control-btn.danger {\n width: 50px;\n height: 50px;\n background: linear-gradient(135deg, #ef4444, #dc2626);\n color: #ffffff;\n box-shadow: 0 4px 14px rgba(239, 68, 68, 0.4);\n overflow: visible;\n }\n \n .desktop-control-btn.danger svg {\n width: 20px;\n height: 20px;\n overflow: visible;\n }\n \n .desktop-control-btn.danger:hover {\n transform: scale(1.06);\n box-shadow: 0 6px 20px rgba(239, 68, 68, 0.5);\n }\n \n .desktop-control-btn.danger:hover {\n transform: scale(1.06);\n box-shadow: 0 6px 20px rgba(239, 68, 68, 0.5);\n }\n \n \n /* ===== COMPACT VOICE SECTION (Single-row layout) ===== */\n .compact-voice-section {\n padding: 10px 14px;\n background: linear-gradient(180deg, #ffffff, rgba(168, 85, 247, 0.04));\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n border-bottom: 1px solid rgba(0, 0, 0, 0.06);\n min-height: 62px;\n flex-shrink: 0;\n }\n \n .compact-left {\n display: flex;\n align-items: center;\n gap: 10px;\n }\n \n .compact-avatar {\n width: 42px;\n height: 42px;\n min-width: 42px;\n min-height: 42px;\n border-radius: 12px;\n background: transparent;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n overflow: visible;\n position: relative;\n }\n \n /* Waveform container in compact avatar - ensure it's visible */\n .compact-avatar .desktop-main-waveform {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 2px;\n height: 100%;\n width: 100%;\n padding: 4px;\n transform: scale(0.75);\n transform-origin: center;\n }\n \n /* Ensure waveform bars are visible and animated in compact mode */\n .compact-avatar .desktop-main-waveform .waveform-bar {\n width: 2px;\n min-width: 2px;\n background: #a855f7;\n border-radius: 1px;\n flex-shrink: 0;\n animation: waveformAnimation 0.8s ease-in-out infinite;\n }\n \n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(1) { height: 6px; animation-delay: 0s; }\n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(2) { height: 10px; animation-delay: 0.05s; }\n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(3) { height: 14px; animation-delay: 0.1s; }\n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(4) { height: 18px; animation-delay: 0.15s; }\n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(5) { height: 22px; animation-delay: 0.2s; }\n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(6) { height: 26px; animation-delay: 0.25s; }\n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(7) { height: 28px; animation-delay: 0.3s; }\n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(8) { height: 30px; animation-delay: 0.35s; }\n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(9) { height: 28px; animation-delay: 0.4s; }\n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(10) { height: 26px; animation-delay: 0.45s; }\n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(11) { height: 22px; animation-delay: 0.5s; }\n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(12) { height: 18px; animation-delay: 0.55s; }\n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(13) { height: 14px; animation-delay: 0.6s; }\n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(14) { height: 10px; animation-delay: 0.65s; }\n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(15) { height: 6px; animation-delay: 0.7s; }\n\n }\n \n .compact-info {\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n \n .compact-timer {\n display: flex;\n align-items: center;\n gap: 5px;\n font-family: 'JetBrains Mono', 'Courier New', monospace;\n font-size: 13px;\n font-weight: 600;\n color: #1e1b4b;\n }\n \n .compact-timer .timer-dot {\n width: 6px;\n height: 6px;\n background: #ef4444;\n border-radius: 50%;\n animation: timerPulse 1s ease-in-out infinite;\n }\n \n .compact-status {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n color: #10b981;\n }\n \n .compact-status .status-dot {\n width: 5px;\n height: 5px;\n background: #10b981;\n border-radius: 50%;\n animation: statusPulse 1.5s ease-in-out infinite;\n }\n \n @keyframes statusPulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.7; transform: scale(1.1); }\n }\n \n .compact-controls {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n \n .compact-control-btn {\n width: 36px;\n height: 36px;\n min-width: 36px;\n min-height: 36px;\n border-radius: 50%;\n border: none;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.2s ease;\n padding: 0;\n position: relative;\n }\n \n .compact-control-btn svg {\n width: 16px;\n height: 16px;\n }\n \n .compact-control-btn.secondary {\n background: #f1f5f9;\n color: #64748b;\n }\n \n .compact-control-btn.secondary:hover {\n background: #e2e8f0;\n color: #475569;\n }\n \n .compact-control-btn.secondary.muted {\n background: rgba(239, 68, 68, 0.1);\n color: #ef4444;\n }\n \n \n .compact-control-btn.secondary.muted .desktop-mic-icon,\n .compact-control-btn.secondary.muted .desktop-speaker-icon {\n stroke: #ef4444;\n }\n \n .compact-control-btn.secondary.muted .desktop-mic-off-icon,\n .compact-control-btn.secondary.muted .desktop-speaker-off-icon {\n width: 46px;\n height: 46px;\n }\n\n .compact-control-btn.danger {\n width: 40px;\n height: 40px;\n min-width: 40px;\n min-height: 40px;\n background: linear-gradient(135deg, #ef4444, #dc2626);\n color: white;\n box-shadow: 0 3px 10px rgba(239, 68, 68, 0.35);\n }\n \n .compact-control-btn.danger:hover {\n transform: scale(1.05);\n box-shadow: 0 4px 14px rgba(239, 68, 68, 0.45);\n }\n \n .compact-control-btn.danger svg {\n width: 18px;\n height: 18px;\n overflow: visible;\n }\n \n/* ===== CONVERSATION PANEL ===== */\n .desktop-conversation-panel {\n border-top: 1px solid rgba(0, 0, 0, 0.06);\n width: 100%;\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: hidden;\n flex: 1;\n }\n \n .conversation-header {\n padding: 10px 16px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n background: #fafafa;\n cursor: pointer;\n flex-shrink: 0;\n border-bottom: 1px solid rgba(0, 0, 0, 0.04);\n transition: background 0.2s ease;\n }\n \n .conversation-header:hover {\n background: #f5f5f5;\n }\n \n .conversation-label {\n font-size: 11px;\n font-weight: 600;\n color: #64748b;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n }\n \n .conversation-toggle {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n color: #94a3b8;\n font-weight: 500;\n }\n \n .conversation-toggle svg {\n transition: transform 0.2s ease;\n }\n \n .conversation-header.expanded .conversation-toggle svg {\n transform: rotate(180deg);\n }\n \n /* ===== COLLAPSED: Live Transcript Only (2 lines) ===== */\n .live-transcript-collapsed {\n padding: 12px 16px;\n background: #fafafa;\n display: flex;\n flex-direction: column;\n gap: 6px;\n flex-shrink: 0;\n min-height: 50px;\n }\n \n .live-indicator {\n display: flex;\n align-items: center;\n gap: 5px;\n font-size: 9px;\n font-weight: 700;\n color: #10b981;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n }\n \n .live-indicator .live-dot {\n width: 5px;\n height: 5px;\n background: #10b981;\n border-radius: 50%;\n animation: statusPulse 1.5s ease-in-out infinite;\n }\n \n .live-text-collapsed {\n font-size: 13px;\n color: #1e1b4b;\n line-height: 1.5;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n \n .live-text-collapsed.muted {\n color: #94a3b8;\n font-style: italic;\n }\n \n .typing-cursor {\n display: inline-block;\n width: 2px;\n height: 14px;\n background: #a855f7;\n margin-left: 2px;\n animation: blink 1s step-end infinite;\n vertical-align: middle;\n }\n \n @keyframes blink {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0; }\n }\n \n /* ===== EXPANDED: Full Conversation History ===== */\n .conversation-history {\n flex: 1;\n flex-direction: column;\n gap: 10px;\n overflow-y: auto;\n padding: 14px 16px;\n min-height: 0;\n }\n .conversation-history.visible {\n display: flex;\n }\n\n .conversation-messages {\n display: flex;\n flex-direction: column;\n gap: 10px;\n }\n\n /* Message Rows */\n .message-row {\n display: flex;\n gap: 8px;\n animation: msgIn 0.25s ease;\n }\n \n @keyframes msgIn {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n }\n @keyframes slideIn {\n from { opacity: 0; transform: translateY(-10px); }\n to { opacity: 1; transform: translateY(0); }\n }\n \n @keyframes slideOut {\n from { opacity: 1; transform: translateY(0); }\n to { opacity: 0; transform: translateY(-10px); }\n }\n \n .message-row.user {\n flex-direction: row-reverse;\n }\n \n .message-avatar {\n width: 28px;\n height: 28px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n }\n\n .message-avatar.assistant {\n background: linear-gradient(135deg, #c084fc, #a855f7);\n }\n\n .message-avatar.assistant .orb {\n width: 12px;\n height: 12px;\n background: rgba(255, 255, 255, 0.9);\n border-radius: 50%;\n }\n\n .message-avatar.user {\n background: linear-gradient(135deg, #64748b, #475569);\n color: #fff;\n font-size: 11px;\n font-weight: 600;\n }\n\n .message-bubble {\n max-width: 80%;\n padding: 9px 13px;\n border-radius: 12px;\n font-size: 13px;\n line-height: 1.5;\n }\n \n .message-row.assistant .message-bubble {\n background: #fff;\n color: #1e1b4b;\n border: 1px solid rgba(0, 0, 0, 0.06);\n border-bottom-left-radius: 4px;\n }\n \n .message-row.user .message-bubble {\n background: linear-gradient(135deg, #7c3aed 0%, #a855f7 100%);\n color: #fff;\n border-bottom-right-radius: 4px;\n }\n \n /* Live message at bottom of history */\n .live-message-row {\n display: flex;\n gap: 8px;\n padding-top: 8px;\n border-top: 1px dashed rgba(0, 0, 0, 0.08);\n margin-top: auto;\n }\n \n .live-message-row .message-bubble {\n background: #fff;\n border: 1px solid rgba(16, 185, 129, 0.3);\n color: #1e1b4b;\n position: relative;\n border-radius: 14px;\n border-bottom-left-radius: 4px;\n }\n \n .live-message-row .live-badge {\n position: absolute;\n top: -8px;\n left: 10px;\n background: #10b981;\n color: #fff;\n font-size: 8px;\n font-weight: 700;\n padding: 2px 6px;\n border-radius: 4px;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n }\n \n /* Hide/show based on expanded state */\n .desktop-conversation-panel.collapsed .conversation-history {\n display: none;\n }\n \n .desktop-conversation-panel.collapsed .live-transcript-collapsed {\n display: flex;\n }\n \n .desktop-conversation-panel.expanded .conversation-history {\n display: flex;\n max-height: 400px;\n }\n \n .desktop-conversation-panel.expanded .live-transcript-collapsed {\n display: none;\n }\n \n /* ===== DARK MODE SUPPORT ===== */\n @media (prefers-color-scheme: dark) {\n .desktop-voice-section {\n background: linear-gradient(180deg, #1e1e2e 0%, rgba(168, 85, 247, 0.08) 100%);\n }\n\n .desktop-timer {\n color: #94a3b8;\n }\n\n .desktop-status {\n color: #34d399;\n }\n\n .desktop-status .status-dot {\n \n .desktop-control-btn.secondary.muted {\n background: rgba(255, 255, 255, 0.1);\n color: #9ca3af;\n \n .compact-voice-section {\n background: linear-gradient(180deg, #1e1e2e 0%, rgba(168, 85, 247, 0.08) 100%);\n border-bottom: 1px solid rgba(255, 255, 255, 0.08);\n }\n \n .compact-timer {\n color: #e2e8f0;\n }\n \n .compact-status {\n color: #34d399;\n }\n \n .compact-status .status-dot {\n background: #34d399;\n }\n \n .compact-control-btn.secondary {\n background: rgba(255, 255, 255, 0.08);\n color: #94a3b8;\n }\n \n .compact-control-btn.secondary:hover {\n background: rgba(255, 255, 255, 0.15);\n color: #e2e8f0;\n }\n \n .compact-control-btn.secondary.muted {\n background: rgba(239, 68, 68, 0.2);\n color: #f87171;\n }\n\n }\n \n .desktop-control-btn.secondary.muted svg {\n \n .desktop-control-btn.secondary {\n position: relative;\n }\n \n .desktop-mic-off-icon,\n .desktop-speaker-off-icon {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 20px;\n height: 20px;\n }\n \n .desktop-control-btn.secondary.muted {\n background: #f3f4f6;\n color: #9ca3af;\n }\n \n .desktop-control-btn.secondary.muted svg {\n \n .desktop-control-btn.secondary {\n position: relative;\n }\n \n .desktop-mic-off-icon,\n .desktop-speaker-off-icon {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 20px;\n height: 20px;\n }\n stroke: #9ca3af;\n }\n stroke: #9ca3af;\n }\n background: #34d399;\n }\n\n .desktop-control-btn.secondary {\n background: rgba(255, 255, 255, 0.08);\n color: #94a3b8;\n }\n\n .desktop-control-btn.secondary:hover {\n background: rgba(255, 255, 255, 0.15);\n color: #e2e8f0;\n }\n\n .desktop-conversation-panel {\n border-top: 1px solid rgba(255, 255, 255, 0.08);\n }\n\n .conversation-header {\n background: #1a1a2e;\n }\n\n .conversation-header:hover {\n background: #252540;\n }\n\n .conversation-label {\n color: #94a3b8;\n }\n\n .conversation-toggle {\n color: #64748b;\n }\n\n .live-transcript-preview {\n background: #1a1a2e;\n border-top: 1px solid rgba(255, 255, 255, 0.08);\n }\n\n .live-indicator {\n color: #34d399;\n }\n\n .live-indicator .live-dot {\n background: #34d399;\n }\n\n .live-text {\n color: #e2e8f0;\n }\n\n .live-text.muted {\n color: #64748b;\n }\n\n .conversation-history {\n background: #1a1a2e;\n }\n\n .conversation-msg.assistant .conversation-msg-bubble {\n background: #252540;\n color: #e2e8f0;\n border: 1px solid rgba(255, 255, 255, 0.08);\n }\n\n .voice-text-input-area {\n background: #1a1a2e;\n }\n\n .voice-text-input {\n background: #252540 !important;\n color: #e2e8f0 !important;\n border-color: rgba(255, 255, 255, 0.1) !important;\n }\n\n .voice-text-input::placeholder {\n color: #64748b !important;\n }\n\n .voice-text-input:focus {\n border-color: ").concat(avatarBg, " !important;\n box-shadow: 0 0 0 3px rgba(168, 85, 247, 0.2) !important;\n }\n\n .voice-input-hint {\n color: #64748b !important;\n }\n\n .voice-send-btn {\n background: linear-gradient(135deg, ").concat(avatarBg, ", ").concat(avatarActiveBg, ") !important;\n }\n\n .voice-send-btn:disabled {\n background: #374151 !important;\n color: #4b5563 !important;\n }\n }\n\n /* Mobile optimization */\n @media (max-width: 768px) {\n .voice-interface {\n padding: 6px 10px;\n }\n }\n \n @media (max-width: 480px) {\n .voice-interface {\n padding: 5px 8px;\n }\n }\n \n /* Mobile Voice Call UI - Shared styles (also used in generateMobileCSS) */\n ").concat(this._getSharedMobileCSS(important), "\n ");
18702
+ var voiceSendButtonColor = this.config.sendButtonColor || ((_this$config$text = this.config.text) === null || _this$config$text === void 0 ? void 0 : _this$config$text.sendButtonColor) || this.config.voiceSendButtonColor || '#7C3AED';
18703
+ var important = ' !important';
18704
+ return "\n /* Voice Interface Styles - Ultra-compact for Wix iframes */\n .voice-interface { \n display: none".concat(important, "; \n flex: 1; \n flex-direction: column;\n align-items: stretch; \n justify-content: flex-start; \n padding: 0; \n background: linear-gradient(180deg, #f8fafc 0%, #e0e7ff 100%);\n overflow: hidden;\n min-height: 0;\n height: 100%;\n width: 100%;\n box-sizing: border-box;\n }\n .voice-interface.active { display: flex").concat(important, "; }\n \n /* Voice States - Better scaling gaps */\n #voiceIdleState {\n display: flex;\n flex-direction: column;\n align-items: center;\n width: 100%;\n height: 100%;\n min-height: 0;\n justify-content: center;\n overflow: hidden;\n flex: 1;\n box-sizing: border-box;\n gap: clamp(6px, 1.5vh, 12px);\n }\n \n #voiceActiveState {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n width: 100%;\n height: 100%;\n min-height: 0;\n justify-content: flex-start;\n overflow: hidden;\n flex: 1;\n box-sizing: border-box;\n gap: 0;\n padding: 0;\n }\n \n #voiceActiveState[style*=\"display: none\"] {\n display: none !important;\n }\n \n /* Voice Avatar - Scales better from small to large */\n .voice-avatar,\n .voice-avatar-active {\n width: clamp(80px, 18vh, 160px);\n height: clamp(80px, 18vh, 160px);\n aspect-ratio: 1;\n border-radius: 50%;\n background: linear-gradient(135deg, ").concat(avatarBg, " 0%, ").concat(avatarActiveBg, " 100%);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: clamp(40px, 9vh, 80px);\n margin: 0;\n box-shadow: 0 8px 30px rgba(102, 126, 234, 0.3);\n transition: all 0.3s ease;\n flex-shrink: 0;\n position: relative;\n }\n \n .voice-avatar-active {\n animation: avatarPulse 2s ease-in-out infinite;\n }\n \n @keyframes avatarPulse {\n 0%, 100% { \n transform: scale(1);\n }\n 50% { \n transform: scale(1.05);\n }\n }\n \n .voice-avatar-active.speaking {\n animation: avatarSpeak 0.5s ease-in-out infinite;\n }\n \n @keyframes avatarSpeak {\n 0%, 100% { transform: scale(1); }\n 50% { transform: scale(1.08); }\n }\n \n /* Voice Rings Animation */\n .voice-rings {\n position: absolute;\n width: 100%;\n height: 100%;\n border-radius: 50%;\n }\n \n .voice-ring {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n border: 2px solid rgba(102, 126, 234, 0.3);\n border-radius: 50%;\n opacity: 0;\n animation: ringExpand 2s ease-out infinite;\n }\n \n .voice-ring:nth-child(2) { animation-delay: 0.5s; }\n .voice-ring:nth-child(3) { animation-delay: 1s; }\n \n @keyframes ringExpand {\n 0% {\n width: 100%;\n height: 100%;\n opacity: 0.6;\n }\n 100% {\n width: 160%;\n height: 160%;\n opacity: 0;\n }\n }\n \n /* Voice Status - Scales with container */\n .voice-status {\n text-align: center;\n margin: 0;\n flex-shrink: 0;\n min-height: 0;\n }\n \n .voice-status-title {\n font-size: clamp(12px, 3vh, 20px);\n font-weight: 600;\n color: ").concat(statusTitleColor, ";\n margin-bottom: clamp(2px, 0.5vh, 4px);\n line-height: 1.2;\n }\n \n .voice-status-subtitle {\n font-size: clamp(10px, 2vh, 14px);\n color: ").concat(statusSubtitleColor, ";\n line-height: 1.2;\n }\n \n /* Start Call Button - Scales with container */\n .start-call-btn {\n margin: 0;\n width: min(280px, 70vw)").concat(important, ";\n height: clamp(48px, 8vh, 64px)").concat(important, ";\n border-radius: clamp(24px, 4vh, 32px)").concat(important, ";\n border: none").concat(important, ";\n background: ").concat(startCallBtnColor).concat(important, ";\n color: ").concat(startCallBtnTextColor).concat(important, ";\n font-size: clamp(14px, 2.5vh, 18px)").concat(important, ";\n font-weight: 600").concat(important, ";\n cursor: pointer").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n gap: clamp(8px, 1.5vh, 12px);\n box-shadow: 0 12px 30px rgba(102, 126, 234, 0.4);\n transition: all 0.3s ease;\n flex-shrink: 0;\n }\n \n .start-call-btn svg {\n display: block").concat(important, ";\n visibility: visible").concat(important, ";\n opacity: 1").concat(important, ";\n width: auto").concat(important, ";\n height: auto").concat(important, ";\n }\n \n .start-call-btn svg {\n width: clamp(22px, 4vh, 32px);\n height: clamp(22px, 4vh, 32px);\n }\n \n .start-call-btn:hover {\n transform: translateY(-2px);\n box-shadow: 0 12px 28px rgba(102, 126, 234, 0.5);\n }\n \n .start-call-btn:active {\n transform: translateY(-1px);\n }\n .start-call-btn:disabled {\n cursor: not-allowed").concat(important, ";\n opacity: 0.6").concat(important, ";\n }\n \n /* Connecting Spinner */\n .connecting-spinner {\n display: inline-block;\n width: 16px;\n height: 16px;\n border: 2px solid rgba(255, 255, 255, 0.3);\n border-top-color: ").concat(startCallBtnTextColor, ";\n border-radius: 50%;\n animation: spin 1s linear infinite;\n margin-right: 8px;\n vertical-align: middle;\n }\n \n @keyframes spin {\n to { transform: rotate(360deg); }\n }\n\n \n /* Voice Transcript - Scales with container */\n .voice-transcript {\n background: ").concat(transcriptBg, ";\n padding: clamp(6px, 1.5vh, 12px);\n border-radius: 10px;\n width: min(360px, calc(100% - 40px));\n margin: 0;\n min-height: clamp(80px, 15vh, 120px);\n max-height: clamp(100px, 18vh, 140px);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\n flex-shrink: 1;\n overflow-y: auto;\n overflow-x: hidden;\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n }\n \n .transcript-label {\n font-size: clamp(8px, 1.4vh, 11px);\n color: ").concat(transcriptLabelColor, ";\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n margin-bottom: clamp(3px, 0.6vh, 6px);\n flex-shrink: 0;\n word-wrap: break-word;\n }\n \n .transcript-text {\n font-size: clamp(11px, 2vh, 15px);\n color: ").concat(transcriptTextColor, ";\n line-height: 1.4;\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n word-wrap: break-word;\n overflow-wrap: break-word;\n }\n \n .transcript-text.empty {\n color: #cbd5e1;\n font-style: italic;\n }\n \n /* Voice Text Input Area - Type while on voice call */\n .voice-text-input-area {\n width: 100%;\n padding: 14px 16px;\n margin: 0;\n flex-shrink: 0;\n background: #ffffff;\n border-top: 1px solid rgba(0, 0, 0, 0.06);\n box-sizing: border-box;\n }\n \n .voice-input-wrapper {\n display: flex;\n align-items: center;\n gap: 10px;\n background: #f1f5f9;\n border-radius: 12px;\n padding: 4px 4px 4px 14px;\n border: 1px solid transparent;\n transition: all 0.2s ease;\n }\n \n .voice-input-wrapper:focus-within {\n background: #fff;\n border-color: #a855f7;\n box-shadow: 0 0 0 3px rgba(168, 85, 247, 0.1);\n }\n \n .voice-text-input {\n flex: 1;\n border: none;\n outline: none;\n font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, sans-serif;\n font-size: 14px;\n color: ").concat(liveTranscriptTextColor).concat(important, ";\n background: transparent;\n padding: 10px 0;\n }\n \n .voice-text-input::placeholder {\n color: #94a3b8;\n }\n \n .voice-send-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 38px;\n height: 38px;\n border-radius: 10px;\n border: none;\n background: ").concat(voiceSendButtonColor).concat(important, ";\n color: #fff;\n cursor: pointer;\n transition: transform 0.2s ease;\n flex-shrink: 0;\n }\n \n .voice-send-btn:hover:not(:disabled) {\n transform: scale(1.05);\n }\n \n .voice-send-btn:active:not(:disabled) {\n transform: scale(0.95);\n }\n \n .voice-send-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n transform: none;\n }\n \n .voice-send-btn svg {\n width: 16px;\n height: 16px;\n }\n \n .voice-input-hint {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 5px;\n margin-top: 10px;\n font-size: 11px;\n color: #64748b;\n transition: color 0.2s ease;\n }\n \n .voice-input-hint svg {\n width: 12px;\n height: 12px;\n color: #10b981;\n }\n \n /* Text input status states */\n .voice-input-hint--sending {\n color: #666;\n }\n \n .voice-input-hint--success {\n color: #28a745;\n }\n \n .voice-input-hint--queued {\n color: #ffc107;\n }\n \n .voice-input-hint--error {\n color: #dc3545;\n }\n \n /* Disabled input styling */\n .voice-text-input:disabled,\n #mobileTextInput:disabled {\n background-color: #f5f5f5;\n cursor: not-allowed;\n }\n \n .voice-send-btn:disabled,\n #mobileSendBtn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n \n /* Voice Controls - Scales with container */\n .voice-controls {\n display: flex;\n gap: clamp(8px, 1.8vh, 14px);\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n margin: 0;\n padding-top: 0;\n }\n \n .voice-control-btn {\n width: clamp(48px, 9vh, 72px)").concat(important, ";\n height: clamp(48px, 9vh, 72px)").concat(important, ";\n min-width: clamp(48px, 9vh, 72px)").concat(important, ";\n min-height: clamp(48px, 9vh, 72px)").concat(important, ";\n max-width: clamp(48px, 9vh, 72px)").concat(important, ";\n max-height: clamp(48px, 9vh, 72px)").concat(important, ";\n aspect-ratio: 1").concat(important, ";\n border-radius: 50%").concat(important, ";\n border: none").concat(important, ";\n cursor: pointer").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n transition: all 0.2s;\n position: relative").concat(important, ";\n flex-shrink: 0;\n overflow: hidden").concat(important, ";\n padding: 0").concat(important, ";\n margin: 0").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n \n .voice-control-btn svg {\n width: 48%").concat(important, ";\n height: 48%").concat(important, ";\n min-width: 48%").concat(important, ";\n min-height: 48%").concat(important, ";\n max-width: 48%").concat(important, ";\n max-height: 48%").concat(important, ";\n display: block").concat(important, ";\n visibility: visible").concat(important, ";\n opacity: 1").concat(important, ";\n margin: 0").concat(important, ";\n padding: 0").concat(important, ";\n position: relative").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n \n .voice-control-btn.primary {\n width: clamp(54px, 10vh, 80px)").concat(important, ";\n height: clamp(54px, 10vh, 80px)").concat(important, ";\n min-width: clamp(54px, 10vh, 80px)").concat(important, ";\n min-height: clamp(54px, 10vh, 80px)").concat(important, ";\n max-width: clamp(54px, 10vh, 80px)").concat(important, ";\n max-height: clamp(54px, 10vh, 80px)").concat(important, ";\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%)").concat(important, ";\n color: white").concat(important, ";\n box-shadow: 0 6px 18px rgba(102, 126, 234, 0.4);\n }\n \n .voice-control-btn.primary:hover {\n transform: scale(1.05);\n }\n \n .voice-control-btn.primary.active {\n background: ").concat(endCallBtnColor).concat(important, ";\n animation: recordingPulse 1.5s ease-in-out infinite;\n }\n .voice-control-btn.primary.active svg {\n fill: white").concat(important, ";\n }\n \n /* More specific selectors for WordPress compatibility */\n #endCallBtn.voice-control-btn.primary.active,\n #muteBtn.voice-control-btn.secondary,\n #speakerBtn.voice-control-btn.secondary {\n border-radius: 50% !important;\n width: clamp(48px, 9vh, 72px) !important;\n height: clamp(48px, 9vh, 72px) !important;\n min-width: clamp(48px, 9vh, 72px) !important;\n min-height: clamp(48px, 9vh, 72px) !important;\n max-width: clamp(48px, 9vh, 72px) !important;\n max-height: clamp(48px, 9vh, 72px) !important;\n aspect-ratio: 1 !important;\n overflow: hidden !important;\n }\n \n #endCallBtn.voice-control-btn.primary.active {\n width: clamp(54px, 10vh, 80px) !important;\n height: clamp(54px, 10vh, 80px) !important;\n min-width: clamp(54px, 10vh, 80px) !important;\n min-height: clamp(54px, 10vh, 80px) !important;\n max-width: clamp(54px, 10vh, 80px) !important;\n max-height: clamp(54px, 10vh, 80px) !important;\n }\n \n \n /* Microphone button specific background color */\n #muteBtn.voice-control-btn.secondary {\n background: ").concat(micButtonColor).concat(important, ";\n }\n \n /* Speaker button specific background color */\n #speakerBtn.voice-control-btn.secondary {\n background: ").concat(speakerButtonColor).concat(important, ";\n }\n \n #endCallBtn.voice-control-btn.primary.active svg,\n #muteBtn.voice-control-btn.secondary svg,\n #speakerBtn.voice-control-btn.secondary svg {\n display: block !important;\n visibility: visible !important;\n opacity: 1 !important;\n width: 48% !important;\n height: 48% !important;\n margin: 0 !important;\n padding: 0 !important;\n position: relative !important;\n }\n \n @keyframes recordingPulse {\n 0%, 100% { \n box-shadow: 0 6px 16px rgba(239, 68, 68, 0.4);\n }\n 50% { \n box-shadow: 0 6px 24px rgba(239, 68, 68, 0.7);\n }\n }\n \n .voice-control-btn.secondary {\n background: ").concat(controlBtnColor).concat(important, ";\n color: ").concat(controlBtnSecondaryColor).concat(important, ";\n box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);\n width: clamp(48px, 9vh, 72px)").concat(important, ";\n height: clamp(48px, 9vh, 72px)").concat(important, ";\n min-width: clamp(48px, 9vh, 72px)").concat(important, ";\n min-height: clamp(48px, 9vh, 72px)").concat(important, ";\n max-width: clamp(48px, 9vh, 72px)").concat(important, ";\n max-height: clamp(48px, 9vh, 72px)").concat(important, ";\n }\n \n .voice-control-btn.secondary:hover {\n background: #f8fafc").concat(important, ";\n transform: scale(1.05);\n }\n \n .voice-control-btn.secondary.muted {\n background: #f3f4f6").concat(important, ";\n }\n \n .voice-control-btn.secondary.muted .mute-icon {\n stroke: #9ca3af !important;\n }\n \n .voice-control-btn.secondary svg {\n width: 48%").concat(important, ";\n height: 48%").concat(important, ";\n display: block").concat(important, ";\n visibility: visible").concat(important, ";\n opacity: 1").concat(important, ";\n margin: 0").concat(important, ";\n padding: 0").concat(important, ";\n position: relative").concat(important, ";\n }\n \n .voice-timer {\n position: absolute;\n bottom: clamp(-18px, -3vh, -24px);\n font-size: clamp(9px, 1.6vh, 12px);\n color: #64748b;\n font-weight: 500;\n white-space: nowrap;\n }\n \n /* ===== DESKTOP VOICE SECTION - New Design ===== */\n .desktop-voice-section {\n padding: 16px 20px;\n background: linear-gradient(180deg, #ffffff 0%, rgba(168, 85, 247, 0.04) 100%);\n width: 100%;\n flex-shrink: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n box-sizing: border-box;\n text-align: center;\n }\n \n /* Ensure all children are centered */\n .desktop-voice-section > * {\n margin-left: auto;\n margin-right: auto;\n }\n \n .desktop-timer {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n padding: 5px 10px;\n background: rgba(0, 0, 0, 0.05);\n border-radius: 20px;\n font-family: 'JetBrains Mono', 'Courier New', monospace;\n font-size: 11px;\n color: #64748b;\n margin: 0 auto;\n }\n \n .desktop-timer .timer-dot {\n width: 5px;\n height: 5px;\n background: #ef4444;\n border-radius: 50%;\n animation: timerPulse 1s ease-in-out infinite;\n }\n \n @keyframes timerPulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.4; }\n }\n \n .desktop-avatar-container {\n margin-bottom: 12px;\n }\n \n .desktop-avatar-large {\n width: 80px !important;\n height: 80px !important;\n border-radius: 20px !important;\n margin: 0 auto 12px !important;\n box-shadow: 0 8px 24px rgba(168, 85, 247, 0.35) !important;\n background: linear-gradient(135deg, ").concat(avatarBg, " 0%, ").concat(avatarActiveBg, " 100%) !important;\n }\n \n .desktop-waveform {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n height: 36px;\n width: 100%;\n }\n \n .desktop-waveform-bar {\n width: 4px;\n background: rgba(255, 255, 255, 0.9);\n border-radius: 2px;\n animation: waveformAnimation 0.8s ease-in-out infinite;\n }\n \n .desktop-waveform-bar[data-index=\"0\"] { height: 14px; animation-delay: 0s; }\n .desktop-waveform-bar[data-index=\"1\"] { height: 26px; animation-delay: 0.1s; }\n .desktop-waveform-bar[data-index=\"2\"] { height: 36px; animation-delay: 0.2s; }\n .desktop-waveform-bar[data-index=\"3\"] { height: 22px; animation-delay: 0.3s; }\n .desktop-waveform-bar[data-index=\"4\"] { height: 16px; animation-delay: 0.4s; }\n \n @keyframes waveformAnimation {\n 0%, 100% { transform: scaleY(0.5); }\n 50% { transform: scaleY(1); }\n }\n \n .desktop-waveform.paused .desktop-waveform-bar {\n animation-play-state: paused;\n }\n\n /* New main waveform (used in updated template) */\n .desktop-main-waveform {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 3px;\n height: 48px;\n width: 100%;\n max-width: 200px;\n margin: 0 auto;\n padding: 0 20px;\n }\n\n .desktop-main-waveform .waveform-bar {\n width: 3px;\n background: #a855f7;\n border-radius: 2px;\n height: 8px;\n animation: waveformAnimation 0.8s ease-in-out infinite;\n }\n\n .desktop-main-waveform .waveform-bar:nth-child(1) { height: 12px; animation-delay: 0s; }\n .desktop-main-waveform .waveform-bar:nth-child(2) { height: 20px; animation-delay: 0.05s; }\n .desktop-main-waveform .waveform-bar:nth-child(3) { height: 28px; animation-delay: 0.1s; }\n .desktop-main-waveform .waveform-bar:nth-child(4) { height: 36px; animation-delay: 0.15s; }\n .desktop-main-waveform .waveform-bar:nth-child(5) { height: 44px; animation-delay: 0.2s; }\n .desktop-main-waveform .waveform-bar:nth-child(6) { height: 50px; animation-delay: 0.25s; }\n .desktop-main-waveform .waveform-bar:nth-child(7) { height: 54px; animation-delay: 0.3s; }\n .desktop-main-waveform .waveform-bar:nth-child(8) { height: 56px; animation-delay: 0.35s; }\n .desktop-main-waveform .waveform-bar:nth-child(9) { height: 54px; animation-delay: 0.4s; }\n .desktop-main-waveform .waveform-bar:nth-child(10) { height: 50px; animation-delay: 0.45s; }\n .desktop-main-waveform .waveform-bar:nth-child(11) { height: 44px; animation-delay: 0.5s; }\n .desktop-main-waveform .waveform-bar:nth-child(12) { height: 36px; animation-delay: 0.55s; }\n .desktop-main-waveform .waveform-bar:nth-child(13) { height: 28px; animation-delay: 0.6s; }\n .desktop-main-waveform .waveform-bar:nth-child(14) { height: 20px; animation-delay: 0.65s; }\n .desktop-main-waveform .waveform-bar:nth-child(15) { height: 12px; animation-delay: 0.7s; }\n\n .desktop-status {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 5px;\n font-size: 12px;\n color: ").concat(statusTitleColor, ";\n font-weight: 500;\n width: 100%;\n text-align: center;\n margin: 0 auto;\n }\n \n .desktop-status .status-dot {\n width: 5px;\n height: 5px;\n background: ").concat(statusDotColor, ";\n border-radius: 50%;\n animation: statusPulse 1.5s ease-in-out infinite;\n }\n \n @keyframes statusPulse {\n 0%, 100% { transform: scale(1); opacity: 1; }\n 50% { transform: scale(1.15); opacity: 0.8; }\n }\n \n .desktop-live-waveform {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 3px;\n height: 48px;\n margin-bottom: 20px;\n }\n \n .desktop-live-bar {\n width: 3px;\n background: linear-gradient(180deg, ").concat(avatarBg, ", ").concat(avatarActiveBg, ");\n border-radius: 2px;\n transition: height 0.1s ease;\n height: 8px;\n }\n \n .desktop-controls {\n display: flex;\n gap: 8px;\n align-items: center;\n justify-content: center;\n width: 100%;\n margin: 0 auto;\n }\n \n .desktop-control-btn {\n width: 46px;\n height: 46px;\n border-radius: 50%;\n border: none;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n }\n \n .desktop-control-btn svg {\n width: 20px;\n height: 20px;\n }\n \n .desktop-mic-icon,\n .desktop-speaker-icon {\n width: 20px !important;\n height: 20px !important;\n display: block;\n flex-shrink: 0;\n }\n \n .desktop-control-btn.secondary.muted .desktop-mic-icon,\n .desktop-control-btn.secondary.muted .desktop-speaker-icon {\n width: 20px !important;\n height: 20px !important;\n }\n \n \n .desktop-control-btn.secondary:hover {\n background: rgba(0, 0, 0, 0.1);\n color: #1e293b;\n transform: scale(1.05);\n }\n .desktop-control-btn.secondary.muted {\n background: #f3f4f6;\n color: #9ca3af;\n }\n \n .desktop-control-btn.secondary.muted .desktop-mic-icon,\n .desktop-control-btn.secondary.muted .desktop-speaker-icon {\n stroke: #9ca3af;\n }\n \n .desktop-control-btn.secondary {\n position: relative;\n }\n \n \n /* Desktop microphone button background color */\n #desktopMuteBtn.desktop-control-btn.secondary,\n #desktopMuteBtnCompact.compact-control-btn.secondary {\n background: ").concat(micButtonColor).concat(important, ";\n }\n \n /* Desktop speaker button background color */\n #desktopSpeakerBtn.desktop-control-btn.secondary,\n #desktopSpeakerBtnCompact.compact-control-btn.secondary {\n background: ").concat(speakerButtonColor).concat(important, ";\n }\n .desktop-mic-off-icon,\n .desktop-speaker-off-icon {\n position: absolute;\n top: 50%;\n left: 50%;\n width: 46px;\n height: 46px;\n transform: translate(-50%, -50%);\n z-index: 10;\n }\n .desktop-control-btn.danger {\n width: 50px;\n height: 50px;\n background: ").concat(endCallBtnColor).concat(important, ";\n color: #ffffff;\n box-shadow: 0 4px 14px rgba(239, 68, 68, 0.4);\n overflow: visible;\n }\n \n .desktop-control-btn.danger svg {\n width: 20px;\n height: 20px;\n overflow: visible;\n }\n \n .desktop-control-btn.danger:hover {\n transform: scale(1.06);\n box-shadow: 0 6px 20px rgba(239, 68, 68, 0.5);\n }\n \n .desktop-control-btn.danger:hover {\n transform: scale(1.06);\n box-shadow: 0 6px 20px rgba(239, 68, 68, 0.5);\n }\n \n \n /* ===== COMPACT VOICE SECTION (Single-row layout) ===== */\n .compact-voice-section {\n padding: 10px 14px;\n background: linear-gradient(180deg, #ffffff, rgba(168, 85, 247, 0.04));\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n border-bottom: 1px solid rgba(0, 0, 0, 0.06);\n min-height: 62px;\n flex-shrink: 0;\n }\n \n .compact-left {\n display: flex;\n align-items: center;\n gap: 10px;\n }\n \n .compact-avatar {\n width: 42px;\n height: 42px;\n min-width: 42px;\n min-height: 42px;\n border-radius: 12px;\n background: transparent;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n overflow: visible;\n position: relative;\n }\n \n /* Waveform container in compact avatar - ensure it's visible */\n .compact-avatar .desktop-main-waveform {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 2px;\n height: 100%;\n width: 100%;\n padding: 4px;\n transform: scale(0.75);\n transform-origin: center;\n }\n \n /* Ensure waveform bars are visible and animated in compact mode */\n .compact-avatar .desktop-main-waveform .waveform-bar {\n width: 2px;\n min-width: 2px;\n background: #a855f7;\n border-radius: 1px;\n flex-shrink: 0;\n animation: waveformAnimation 0.8s ease-in-out infinite;\n }\n \n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(1) { height: 6px; animation-delay: 0s; }\n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(2) { height: 10px; animation-delay: 0.05s; }\n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(3) { height: 14px; animation-delay: 0.1s; }\n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(4) { height: 18px; animation-delay: 0.15s; }\n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(5) { height: 22px; animation-delay: 0.2s; }\n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(6) { height: 26px; animation-delay: 0.25s; }\n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(7) { height: 28px; animation-delay: 0.3s; }\n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(8) { height: 30px; animation-delay: 0.35s; }\n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(9) { height: 28px; animation-delay: 0.4s; }\n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(10) { height: 26px; animation-delay: 0.45s; }\n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(11) { height: 22px; animation-delay: 0.5s; }\n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(12) { height: 18px; animation-delay: 0.55s; }\n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(13) { height: 14px; animation-delay: 0.6s; }\n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(14) { height: 10px; animation-delay: 0.65s; }\n .compact-avatar .desktop-main-waveform .waveform-bar:nth-child(15) { height: 6px; animation-delay: 0.7s; }\n\n }\n \n .compact-info {\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n \n .compact-timer {\n display: flex;\n align-items: center;\n gap: 5px;\n font-family: 'JetBrains Mono', 'Courier New', monospace;\n font-size: 13px;\n font-weight: 600;\n color: ").concat(liveTranscriptTextColor).concat(important, ";\n }\n \n .compact-timer .timer-dot {\n width: 6px;\n height: 6px;\n background: #ef4444;\n border-radius: 50%;\n animation: timerPulse 1s ease-in-out infinite;\n }\n \n .compact-status {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n color: ").concat(statusTitleColor, ";\n }\n \n .compact-status .status-dot {\n width: 5px;\n height: 5px;\n background: ").concat(statusDotColor, ";\n border-radius: 50%;\n animation: statusPulse 1.5s ease-in-out infinite;\n }\n \n @keyframes statusPulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.7; transform: scale(1.1); }\n }\n \n .compact-controls {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n \n .compact-control-btn {\n width: 36px;\n height: 36px;\n min-width: 36px;\n min-height: 36px;\n border-radius: 50%;\n border: none;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.2s ease;\n padding: 0;\n position: relative;\n }\n \n .compact-control-btn svg {\n width: 16px;\n height: 16px;\n }\n \n .compact-control-btn.secondary {\n background: #f1f5f9;\n color: #64748b;\n }\n \n \n /* Compact speaker button background color */\n #desktopSpeakerBtnCompact.compact-control-btn.secondary {\n background: ").concat(speakerButtonColor).concat(important, ";\n }\n /* Compact microphone button background color */\n #desktopMuteBtnCompact.compact-control-btn.secondary {\n background: ").concat(micButtonColor).concat(important, ";\n }\n \n .compact-control-btn.secondary:hover {\n background: #e2e8f0;\n color: #475569;\n }\n \n .compact-control-btn.secondary.muted {\n background: rgba(239, 68, 68, 0.1);\n color: #ef4444;\n }\n \n \n .compact-control-btn.secondary.muted .desktop-mic-icon,\n .compact-control-btn.secondary.muted .desktop-speaker-icon {\n stroke: #ef4444;\n }\n \n .compact-control-btn.secondary.muted .desktop-mic-off-icon,\n .compact-control-btn.secondary.muted .desktop-speaker-off-icon {\n width: 46px;\n height: 46px;\n }\n\n .compact-control-btn.danger {\n width: 40px;\n height: 40px;\n min-width: 40px;\n min-height: 40px;\n background: ").concat(endCallBtnColor).concat(important, ";\n color: white;\n box-shadow: 0 3px 10px rgba(239, 68, 68, 0.35);\n }\n \n .compact-control-btn.danger:hover {\n transform: scale(1.05);\n box-shadow: 0 4px 14px rgba(239, 68, 68, 0.45);\n }\n \n .compact-control-btn.danger svg {\n width: 18px;\n height: 18px;\n overflow: visible;\n }\n \n/* ===== CONVERSATION PANEL ===== */\n .desktop-conversation-panel {\n border-top: 1px solid rgba(0, 0, 0, 0.06);\n width: 100%;\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: hidden;\n flex: 1;\n }\n \n .conversation-header {\n padding: 10px 16px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n background: #fafafa;\n cursor: pointer;\n flex-shrink: 0;\n border-bottom: 1px solid rgba(0, 0, 0, 0.04);\n transition: background 0.2s ease;\n }\n \n .conversation-header:hover {\n background: #f5f5f5;\n }\n \n .conversation-label {\n font-size: 11px;\n font-weight: 600;\n color: #64748b;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n }\n \n .conversation-toggle {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n color: #94a3b8;\n font-weight: 500;\n }\n \n .conversation-toggle svg {\n transition: transform 0.2s ease;\n }\n \n .conversation-header.expanded .conversation-toggle svg {\n transform: rotate(180deg);\n }\n \n /* ===== COLLAPSED: Live Transcript Only (2 lines) ===== */\n .live-transcript-collapsed {\n padding: 12px 16px;\n background: #fafafa;\n display: flex;\n flex-direction: column;\n gap: 6px;\n flex-shrink: 0;\n min-height: 50px;\n }\n \n .live-indicator {\n display: flex;\n align-items: center;\n gap: 5px;\n font-size: 9px;\n font-weight: 700;\n color: ").concat(liveIndicatorTextColor).concat(important, ";\n text-transform: uppercase;\n letter-spacing: 0.08em;\n }\n \n .live-indicator .live-dot {\n height: 5px;\n width: 5px;\n background: ").concat(liveIndicatorDotColor).concat(important, ";\n border-radius: 50%;\n animation: statusPulse 1.5s ease-in-out infinite;\n }\n \n .live-text-collapsed {\n font-size: ").concat(liveTranscriptFontSize).concat(important, ";\n color: ").concat(liveTranscriptTextColor).concat(important, ";\n line-height: 1.5;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n \n .live-text-collapsed.muted {\n color: #94a3b8;\n font-style: italic;\n }\n \n .typing-cursor {\n display: inline-block;\n width: 2px;\n height: 14px;\n background: #a855f7;\n margin-left: 2px;\n animation: blink 1s step-end infinite;\n vertical-align: middle;\n }\n \n @keyframes blink {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0; }\n }\n \n /* ===== EXPANDED: Full Conversation History ===== */\n .conversation-history {\n flex: 1;\n flex-direction: column;\n gap: 10px;\n overflow-y: auto;\n padding: 14px 16px;\n min-height: 0;\n }\n .conversation-history.visible {\n display: flex;\n }\n\n .conversation-messages {\n display: flex;\n flex-direction: column;\n gap: 10px;\n }\n\n /* Message Rows */\n .message-row {\n display: flex;\n gap: 8px;\n animation: msgIn 0.25s ease;\n }\n \n @keyframes msgIn {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n }\n @keyframes slideIn {\n from { opacity: 0; transform: translateY(-10px); }\n to { opacity: 1; transform: translateY(0); }\n }\n \n @keyframes slideOut {\n from { opacity: 1; transform: translateY(0); }\n to { opacity: 0; transform: translateY(-10px); }\n }\n \n .message-row.user {\n flex-direction: row-reverse;\n }\n \n .message-avatar {\n width: 28px;\n height: 28px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n }\n\n .message-avatar.assistant {\n background: linear-gradient(135deg, #c084fc, #a855f7);\n }\n\n .message-avatar.assistant .orb {\n width: 12px;\n height: 12px;\n background: rgba(255, 255, 255, 0.9);\n border-radius: 50%;\n }\n\n .message-avatar.user {\n background: linear-gradient(135deg, #64748b, #475569);\n color: #fff;\n font-size: 11px;\n font-weight: 600;\n }\n\n .message-bubble {\n max-width: 80%;\n padding: 9px 13px;\n border-radius: 12px;\n font-size: 13px;\n line-height: 1.5;\n }\n \n .message-row.assistant .message-bubble {\n background: #fff;\n color: ").concat(liveTranscriptTextColor).concat(important, ";\n border: 1px solid rgba(0, 0, 0, 0.06);\n border-bottom-left-radius: 4px;\n }\n \n .message-row.user .message-bubble {\n background: linear-gradient(135deg, #7c3aed 0%, #a855f7 100%);\n color: #fff;\n border-bottom-right-radius: 4px;\n }\n \n /* Live message at bottom of history */\n .live-message-row {\n display: flex;\n gap: 8px;\n padding-top: 8px;\n border-top: 1px dashed rgba(0, 0, 0, 0.08);\n margin-top: auto;\n }\n \n .live-message-row .message-bubble {\n background: #fff;\n border: 1px solid rgba(16, 185, 129, 0.3);\n color: ").concat(liveTranscriptTextColor).concat(important, ";\n position: relative;\n border-radius: 14px;\n border-bottom-left-radius: 4px;\n }\n \n .live-message-row .live-badge {\n position: absolute;\n top: -8px;\n left: 10px;\n background: #10b981;\n color: #fff;\n font-size: 8px;\n font-weight: 700;\n padding: 2px 6px;\n border-radius: 4px;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n }\n \n /* Hide/show based on expanded state */\n .desktop-conversation-panel.collapsed .conversation-history {\n display: none;\n }\n \n .desktop-conversation-panel.collapsed .live-transcript-collapsed {\n display: flex;\n }\n \n .desktop-conversation-panel.expanded .conversation-history {\n display: flex;\n max-height: 400px;\n }\n \n .desktop-conversation-panel.expanded .live-transcript-collapsed {\n display: none;\n }\n \n /* ===== DARK MODE SUPPORT ===== */\n @media (prefers-color-scheme: dark) {\n .desktop-voice-section {\n background: linear-gradient(180deg, #1e1e2e 0%, rgba(168, 85, 247, 0.08) 100%);\n }\n\n .desktop-timer {\n color: #94a3b8;\n }\n\n .desktop-status {\n color: #34d399;\n }\n\n .desktop-status .status-dot {\n \n .desktop-control-btn.secondary.muted {\n background: rgba(255, 255, 255, 0.1);\n color: #9ca3af;\n \n .compact-voice-section {\n background: linear-gradient(180deg, #1e1e2e 0%, rgba(168, 85, 247, 0.08) 100%);\n border-bottom: 1px solid rgba(255, 255, 255, 0.08);\n }\n \n .compact-timer {\n color: #e2e8f0;\n }\n \n .compact-status {\n color: #34d399;\n }\n \n .compact-status .status-dot {\n background: #34d399;\n }\n \n .compact-control-btn.secondary {\n background: rgba(255, 255, 255, 0.08);\n color: #94a3b8;\n }\n \n .compact-control-btn.secondary:hover {\n background: rgba(255, 255, 255, 0.15);\n color: #e2e8f0;\n }\n \n .compact-control-btn.secondary.muted {\n background: rgba(239, 68, 68, 0.2);\n color: #f87171;\n }\n\n }\n \n .desktop-control-btn.secondary.muted svg {\n \n .desktop-control-btn.secondary {\n position: relative;\n }\n \n /* Desktop microphone button background color */\n #desktopMuteBtn.desktop-control-btn.secondary,\n #desktopMuteBtnCompact.compact-control-btn.secondary {\n background: ").concat(micButtonColor).concat(important, ";\n }\n \n .desktop-mic-off-icon,\n .desktop-speaker-off-icon {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 20px;\n height: 20px;\n }\n \n .desktop-control-btn.secondary.muted {\n background: #f3f4f6;\n color: #9ca3af;\n }\n \n .desktop-control-btn.secondary.muted svg {\n \n .desktop-control-btn.secondary {\n position: relative;\n }\n \n /* Desktop microphone button background color */\n #desktopMuteBtn.desktop-control-btn.secondary,\n #desktopMuteBtnCompact.compact-control-btn.secondary {\n background: ").concat(micButtonColor).concat(important, ";\n }\n \n .desktop-mic-off-icon,\n .desktop-speaker-off-icon {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 20px;\n height: 20px;\n }\n stroke: #9ca3af;\n }\n stroke: #9ca3af;\n }\n background: #34d399;\n }\n\n .desktop-control-btn.secondary {\n background: rgba(255, 255, 255, 0.08);\n color: #94a3b8;\n }\n\n .desktop-control-btn.secondary:hover {\n background: rgba(255, 255, 255, 0.15);\n color: #e2e8f0;\n }\n\n .desktop-conversation-panel {\n border-top: 1px solid rgba(255, 255, 255, 0.08);\n }\n\n .conversation-header {\n background: #1a1a2e;\n }\n\n .conversation-header:hover {\n background: #252540;\n }\n\n .conversation-label {\n color: #94a3b8;\n }\n\n .conversation-toggle {\n color: #64748b;\n }\n\n .live-transcript-preview {\n background: #1a1a2e;\n }\n .live-indicator {\n color: ").concat(liveIndicatorTextColor).concat(important, ";\n }\n .live-indicator .live-dot {\n background: ").concat(liveIndicatorDotColor).concat(important, ";\n }\n\n .live-text {\n color: #e2e8f0;\n }\n\n .live-text.muted {\n color: #64748b;\n }\n\n .conversation-history {\n background: #1a1a2e;\n }\n\n .conversation-msg.assistant .conversation-msg-bubble {\n background: #252540;\n color: #e2e8f0;\n border: 1px solid rgba(255, 255, 255, 0.08);\n }\n\n .voice-text-input-area {\n background: #1a1a2e;\n }\n\n .voice-text-input {\n background: #252540 !important;\n color: #e2e8f0 !important;\n border-color: rgba(255, 255, 255, 0.1) !important;\n }\n\n .voice-text-input::placeholder {\n color: #64748b !important;\n }\n\n .voice-text-input:focus {\n border-color: ").concat(avatarBg, " !important;\n box-shadow: 0 0 0 3px rgba(168, 85, 247, 0.2) !important;\n }\n\n .voice-input-hint {\n color: #64748b !important;\n }\n\n .voice-send-btn {\n background: ").concat(voiceSendButtonColor, " !important;\n }\n\n .voice-send-btn:disabled {\n background: #374151 !important;\n color: #4b5563 !important;\n }\n }\n\n /* Mobile optimization */\n @media (max-width: 768px) {\n .voice-interface {\n padding: 6px 10px;\n }\n }\n \n @media (max-width: 480px) {\n .voice-interface {\n padding: 5px 8px;\n }\n }\n \n /* Mobile Voice Call UI - Shared styles (also used in generateMobileCSS) */\n ").concat(this._getSharedMobileCSS(important), "\n ");
18285
18705
  }
18286
18706
 
18287
18707
  /**
@@ -18291,7 +18711,7 @@ var Styles = /*#__PURE__*/function () {
18291
18711
  }, {
18292
18712
  key: "_getSharedMobileCSS",
18293
18713
  value: function _getSharedMobileCSS(important) {
18294
- return "\n .mobile-duration-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background-color: #ef4444;\n animation: mobilePulse 1.5s ease-in-out infinite;\n }\n\n @keyframes mobilePulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.5; transform: scale(0.95); }\n }\n\n .mobile-voice-bar {\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding: 14px;\n background: linear-gradient(135deg, #7c3aed 0%, #a855f7 50%, #c084fc 100%);\n border-radius: 24px 24px 0 0;\n box-shadow: 0 -8px 32px rgba(124, 58, 237, 0.5), 0 -2px 8px rgba(0,0,0,0.3), inset 0 1px 0 rgba(255,255,255,0.2);\n width: 100%;\n max-width: 100%;\n pointer-events: auto;\n }\n\n .mobile-top-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n position: relative;\n }\n\n .mobile-status-indicator {\n display: flex;\n align-items: center;\n gap: 5px;\n min-width: 85px;\n }\n\n .mobile-status-dot {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background-color: #22c55e;\n box-shadow: 0 0 8px #22c55e;\n transition: all 0.3s ease;\n }\n\n .mobile-status-text {\n font-size: 11px;\n font-weight: 700;\n color: rgba(255,255,255,0.95);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n }\n\n .mobile-waveform-center {\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 3px;\n height: 24px;\n }\n\n .mobile-waveform-bar {\n width: 4px;\n height: 4px;\n background-color: #fff;\n border-radius: 2px;\n transition: height 0.15s ease;\n box-shadow: 0 0 8px rgba(255,255,255,0.5);\n }\n\n .mobile-controls {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .mobile-control-btn {\n display: flex".concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n width: 32px").concat(important, ";\n height: 32px").concat(important, ";\n min-width: 32px").concat(important, ";\n min-height: 32px").concat(important, ";\n max-width: 32px").concat(important, ";\n max-height: 32px").concat(important, ";\n border-radius: 50%").concat(important, ";\n border: none").concat(important, ";\n cursor: pointer").concat(important, ";\n transition: all 0.2s ease;\n background-color: rgba(255,255,255,0.15)").concat(important, ";\n position: relative").concat(important, ";\n overflow: hidden").concat(important, ";\n padding: 0").concat(important, ";\n margin: 0").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n\n .mobile-control-btn:hover {\n background-color: rgba(255,255,255,0.25)").concat(important, ";\n }\n\n .mobile-control-btn.muted {\n background-color: rgba(239, 68, 68, 0.3)").concat(important, ";\n }\n\n .mobile-control-btn svg {\n position: absolute").concat(important, ";\n top: 50%").concat(important, ";\n left: 50%").concat(important, ";\n transform: translate(-50%, -50%)").concat(important, ";\n display: block").concat(important, ";\n visibility: visible").concat(important, ";\n opacity: 1").concat(important, ";\n width: 15px").concat(important, ";\n height: 15px").concat(important, ";\n margin: 0").concat(important, ";\n padding: 0").concat(important, ";\n }\n\n .mobile-mic-off-icon,\n .mobile-speaker-off-icon {\n display: none !important;\n }\n\n .mobile-control-btn.muted .mobile-mic-icon,\n .mobile-control-btn.muted .mobile-speaker-icon {\n display: none !important;\n }\n\n .mobile-control-btn.muted .mobile-mic-off-icon,\n .mobile-control-btn.muted .mobile-speaker-off-icon {\n display: block !important;\n }\n\n .mobile-end-call-btn {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n width: 36px").concat(important, ";\n height: 36px").concat(important, ";\n min-width: 36px").concat(important, ";\n min-height: 36px").concat(important, ";\n max-width: 36px").concat(important, ";\n max-height: 36px").concat(important, ";\n border-radius: 50%").concat(important, ";\n border: none").concat(important, ";\n cursor: pointer").concat(important, ";\n background-color: #ef4444").concat(important, ";\n box-shadow: 0 4px 14px rgba(239, 68, 68, 0.5);\n transition: all 0.2s ease;\n overflow: hidden").concat(important, ";\n padding: 0").concat(important, ";\n margin: 0").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n\n .mobile-end-call-btn svg {\n display: block").concat(important, ";\n visibility: visible").concat(important, ";\n opacity: 1").concat(important, ";\n width: 15px").concat(important, ";\n height: 15px").concat(important, ";\n margin: 0").concat(important, ";\n padding: 0").concat(important, ";\n position: relative").concat(important, ";\n }\n\n /* ID-specific selectors for WordPress compatibility */\n #mobileMuteBtn.mobile-control-btn,\n #mobileSpeakerBtn.mobile-control-btn,\n #mobileEndCallBtn.mobile-end-call-btn {\n border-radius: 50% !important;\n overflow: hidden !important;\n }\n\n #mobileMuteBtn.mobile-control-btn,\n #mobileSpeakerBtn.mobile-control-btn {\n width: 32px !important;\n height: 32px !important;\n min-width: 32px !important;\n min-height: 32px !important;\n max-width: 32px !important;\n max-height: 32px !important;\n }\n\n #mobileEndCallBtn.mobile-end-call-btn {\n width: 36px !important;\n height: 36px !important;\n min-width: 36px !important;\n min-height: 36px !important;\n max-width: 36px !important;\n max-height: 36px !important;\n }\n\n #mobileMuteBtn.mobile-control-btn svg,\n #mobileSpeakerBtn.mobile-control-btn svg,\n #mobileEndCallBtn.mobile-end-call-btn svg {\n display: block !important;\n visibility: visible !important;\n opacity: 1 !important;\n width: 15px !important;\n height: 15px !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n .mobile-end-call-btn:hover {\n transform: scale(1.05);\n }\n\n .mobile-transcript-row {\n width: 100%;\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 10px 12px;\n background: rgba(255,255,255,0.18);\n border-radius: 14px;\n border: none;\n cursor: pointer;\n text-align: left;\n backdrop-filter: blur(4px);\n transition: background 0.2s ease;\n }\n\n .mobile-transcript-row:hover {\n background: rgba(255,255,255,0.25);\n }\n\n .mobile-transcript-text {\n margin: 0;\n font-size: 13px;\n color: #fff;\n line-height: 1.4;\n font-weight: 500;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n\n .mobile-transcript-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n\n .mobile-expand-hint {\n font-size: 10px;\n color: rgba(255,255,255,0.6);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n font-weight: 600;\n }\n\n .mobile-transcript-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(0,0,0,0.6);\n display: flex;\n align-items: flex-end;\n padding: 12px;\n z-index: 100000;\n pointer-events: auto;\n }\n\n .mobile-expanded-transcript {\n width: 100%;\n max-height: 75%;\n background: #fff;\n border-radius: 24px 24px 16px 16px;\n overflow: hidden;\n box-shadow: 0 -8px 40px rgba(0,0,0,0.3);\n display: flex;\n flex-direction: column;\n }\n\n .mobile-transcript-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 14px 16px;\n background: linear-gradient(135deg, #7c3aed 0%, #a855f7 100%);\n flex-shrink: 0;\n }\n\n .mobile-header-left {\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n\n .mobile-header-status {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .mobile-header-status-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background-color: #22c55e;\n box-shadow: 0 0 6px #22c55e;\n }\n\n .mobile-header-status-text {\n font-size: 10px;\n font-weight: 700;\n color: rgba(255,255,255,0.9);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n .mobile-header-duration {\n font-size: 10px;\n font-weight: 600;\n color: rgba(255,255,255,0.7);\n margin-left: 8px;\n }\n\n .mobile-transcript-label {\n font-size: 11px;\n font-weight: 800;\n color: rgba(255,255,255,0.7);\n letter-spacing: 1px;\n }\n\n .mobile-close-transcript-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border-radius: 50%;\n border: none;\n background: rgba(255,255,255,0.2);\n color: #fff;\n cursor: pointer;\n }\n\n .mobile-close-transcript-btn:hover {\n background: rgba(255,255,255,0.3);\n }\n\n .mobile-messages-container {\n flex: 1;\n padding: 16px;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n\n .mobile-message-bubble {\n max-width: 85%;\n padding: 12px 16px;\n border-radius: 18px;\n font-size: 14px;\n line-height: 1.5;\n word-wrap: break-word;\n }\n\n .mobile-message-bubble.assistant {\n align-self: flex-start;\n background-color: #f3f4f6;\n color: #374151;\n border-bottom-left-radius: 4px;\n }\n\n .mobile-message-bubble.user {\n align-self: flex-end;\n background: linear-gradient(135deg, #7c3aed 0%, #a855f7 100%);\n color: #fff;\n border-bottom-right-radius: 4px;\n }\n\n .mobile-input-area {\n padding: 12px 16px 16px;\n border-top: 1px solid #e5e7eb;\n background: #f9fafb;\n flex-shrink: 0;\n }\n\n .mobile-input-wrapper {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 4px 4px 16px;\n background: #fff;\n border-radius: 24px;\n border: 2px solid #e5e7eb;\n }\n\n .mobile-text-input {\n flex: 1;\n border: none;\n outline: none;\n font-size: 14px;\n color: #374151;\n background: transparent;\n padding: 10px 0;\n }\n\n .mobile-text-input::placeholder {\n color: #9ca3af;\n }\n\n .mobile-send-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n border-radius: 50%;\n border: none;\n background: linear-gradient(135deg, #7c3aed 0%, #a855f7 100%);\n color: #fff;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .mobile-send-btn:hover:not(:disabled) {\n transform: scale(1.05);\n }\n\n .mobile-send-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .mobile-input-hint {\n margin: 8px 0 0;\n font-size: 11px;\n color: #9ca3af;\n text-align: center;\n transition: color 0.2s ease;\n }\n\n /* Mobile text input status states */\n .mobile-input-hint--sending {\n color: #666;\n }\n\n .mobile-input-hint--success {\n color: #28a745;\n }\n\n .mobile-input-hint--queued {\n color: #ffc107;\n }\n\n .mobile-input-hint--error {\n color: #dc3545;\n }\n\n /* Disabled mobile input styling */\n #mobileTextInput:disabled {\n background-color: #f5f5f5;\n cursor: not-allowed;\n }\n\n #mobileSendBtn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n ");
18714
+ return "\n .mobile-duration-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background-color: #ef4444;\n animation: mobilePulse 1.5s ease-in-out infinite;\n }\n\n @keyframes mobilePulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.5; transform: scale(0.95); }\n }\n\n .mobile-voice-bar {\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding: 14px;\n background: linear-gradient(135deg, #7c3aed 0%, #a855f7 50%, #c084fc 100%);\n border-radius: 24px 24px 0 0;\n box-shadow: 0 -8px 32px rgba(124, 58, 237, 0.5), 0 -2px 8px rgba(0,0,0,0.3), inset 0 1px 0 rgba(255,255,255,0.2);\n width: 100%;\n max-width: 100%;\n pointer-events: auto;\n }\n\n .mobile-top-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n position: relative;\n }\n\n .mobile-status-indicator {\n display: flex;\n align-items: center;\n gap: 5px;\n min-width: 85px;\n }\n\n .mobile-status-dot {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background-color: #22c55e;\n box-shadow: 0 0 8px #22c55e;\n transition: all 0.3s ease;\n }\n\n .mobile-status-text {\n font-size: 11px;\n font-weight: 700;\n color: rgba(255,255,255,0.95);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n }\n\n .mobile-waveform-center {\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 3px;\n height: 24px;\n }\n\n .mobile-waveform-bar {\n width: 4px;\n height: 4px;\n background-color: #fff;\n border-radius: 2px;\n transition: height 0.15s ease;\n box-shadow: 0 0 8px rgba(255,255,255,0.5);\n }\n\n .mobile-controls {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .mobile-control-btn {\n display: flex".concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n width: 32px").concat(important, ";\n height: 32px").concat(important, ";\n min-width: 32px").concat(important, ";\n min-height: 32px").concat(important, ";\n max-width: 32px").concat(important, ";\n max-height: 32px").concat(important, ";\n border-radius: 50%").concat(important, ";\n border: none").concat(important, ";\n cursor: pointer").concat(important, ";\n transition: all 0.2s ease;\n background-color: rgba(255,255,255,0.15)").concat(important, ";\n position: relative").concat(important, ";\n overflow: hidden").concat(important, ";\n padding: 0").concat(important, ";\n margin: 0").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n\n .mobile-control-btn:hover {\n background-color: rgba(255,255,255,0.25)").concat(important, ";\n }\n\n .mobile-control-btn.muted {\n background-color: rgba(239, 68, 68, 0.3)").concat(important, ";\n }\n\n .mobile-control-btn svg {\n position: absolute").concat(important, ";\n top: 50%").concat(important, ";\n left: 50%").concat(important, ";\n transform: translate(-50%, -50%)").concat(important, ";\n display: block").concat(important, ";\n visibility: visible").concat(important, ";\n opacity: 1").concat(important, ";\n width: 15px").concat(important, ";\n height: 15px").concat(important, ";\n margin: 0").concat(important, ";\n padding: 0").concat(important, ";\n }\n\n .mobile-mic-off-icon,\n .mobile-speaker-off-icon {\n display: none !important;\n }\n\n .mobile-control-btn.muted .mobile-mic-icon,\n .mobile-control-btn.muted .mobile-speaker-icon {\n display: none !important;\n }\n\n .mobile-control-btn.muted .mobile-mic-off-icon,\n .mobile-control-btn.muted .mobile-speaker-off-icon {\n display: block !important;\n }\n\n .mobile-end-call-btn {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n width: 36px").concat(important, ";\n height: 36px").concat(important, ";\n min-width: 36px").concat(important, ";\n min-height: 36px").concat(important, ";\n max-width: 36px").concat(important, ";\n max-height: 36px").concat(important, ";\n border-radius: 50%").concat(important, ";\n border: none").concat(important, ";\n cursor: pointer").concat(important, ";\n background-color: #ef4444").concat(important, ";\n box-shadow: 0 4px 14px rgba(239, 68, 68, 0.5);\n transition: all 0.2s ease;\n overflow: hidden").concat(important, ";\n padding: 0").concat(important, ";\n margin: 0").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n\n .mobile-end-call-btn svg {\n display: block").concat(important, ";\n visibility: visible").concat(important, ";\n opacity: 1").concat(important, ";\n width: 15px").concat(important, ";\n height: 15px").concat(important, ";\n margin: 0").concat(important, ";\n padding: 0").concat(important, ";\n position: relative").concat(important, ";\n }\n\n /* ID-specific selectors for WordPress compatibility */\n #mobileMuteBtn.mobile-control-btn,\n #mobileSpeakerBtn.mobile-control-btn,\n #mobileEndCallBtn.mobile-end-call-btn {\n border-radius: 50% !important;\n overflow: hidden !important;\n }\n \n /* Mobile microphone button background color */\n #mobileMuteBtn.mobile-control-btn {\n background: ").concat(this.config.micButtonColor || this.config.controlButtonColor || '#FFFFFF').concat(important, ";\n }\n\n #mobileMuteBtn.mobile-control-btn,\n #mobileSpeakerBtn.mobile-control-btn {\n width: 32px !important;\n height: 32px !important;\n min-width: 32px !important;\n min-height: 32px !important;\n max-width: 32px !important;\n max-height: 32px !important;\n }\n\n #mobileEndCallBtn.mobile-end-call-btn {\n width: 36px !important;\n height: 36px !important;\n min-width: 36px !important;\n min-height: 36px !important;\n max-width: 36px !important;\n max-height: 36px !important;\n }\n\n #mobileMuteBtn.mobile-control-btn svg,\n #mobileSpeakerBtn.mobile-control-btn svg,\n #mobileEndCallBtn.mobile-end-call-btn svg {\n display: block !important;\n visibility: visible !important;\n opacity: 1 !important;\n width: 15px !important;\n height: 15px !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n .mobile-end-call-btn:hover {\n transform: scale(1.05);\n }\n\n .mobile-transcript-row {\n width: 100%;\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 10px 12px;\n background: rgba(255,255,255,0.18);\n border-radius: 14px;\n border: none;\n cursor: pointer;\n text-align: left;\n backdrop-filter: blur(4px);\n transition: background 0.2s ease;\n }\n\n .mobile-transcript-row:hover {\n background: rgba(255,255,255,0.25);\n }\n\n .mobile-transcript-text {\n margin: 0;\n font-size: 13px;\n color: #fff;\n line-height: 1.4;\n font-weight: 500;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n\n .mobile-transcript-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n\n .mobile-expand-hint {\n font-size: 10px;\n color: rgba(255,255,255,0.6);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n font-weight: 600;\n }\n\n .mobile-transcript-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(0,0,0,0.6);\n display: flex;\n align-items: flex-end;\n padding: 12px;\n z-index: 100000;\n pointer-events: auto;\n }\n\n .mobile-expanded-transcript {\n width: 100%;\n max-height: 75%;\n background: #fff;\n border-radius: 24px 24px 16px 16px;\n overflow: hidden;\n box-shadow: 0 -8px 40px rgba(0,0,0,0.3);\n display: flex;\n flex-direction: column;\n }\n\n .mobile-transcript-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 14px 16px;\n background: linear-gradient(135deg, #7c3aed 0%, #a855f7 100%);\n flex-shrink: 0;\n }\n\n .mobile-header-left {\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n\n .mobile-header-status {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .mobile-header-status-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background-color: #22c55e;\n box-shadow: 0 0 6px #22c55e;\n }\n\n .mobile-header-status-text {\n font-size: 10px;\n font-weight: 700;\n color: rgba(255,255,255,0.9);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n .mobile-header-duration {\n font-size: 10px;\n font-weight: 600;\n color: rgba(255,255,255,0.7);\n margin-left: 8px;\n }\n\n .mobile-transcript-label {\n font-size: 11px;\n font-weight: 800;\n color: rgba(255,255,255,0.7);\n letter-spacing: 1px;\n }\n\n .mobile-close-transcript-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border-radius: 50%;\n border: none;\n background: rgba(255,255,255,0.2);\n color: #fff;\n cursor: pointer;\n }\n\n .mobile-close-transcript-btn:hover {\n background: rgba(255,255,255,0.3);\n }\n\n .mobile-messages-container {\n flex: 1;\n padding: 16px;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n\n .mobile-message-bubble {\n max-width: 85%;\n padding: 12px 16px;\n border-radius: 18px;\n font-size: 14px;\n line-height: 1.5;\n word-wrap: break-word;\n }\n\n .mobile-message-bubble.assistant {\n align-self: flex-start;\n background-color: #f3f4f6;\n color: #374151;\n border-bottom-left-radius: 4px;\n }\n\n .mobile-message-bubble.user {\n align-self: flex-end;\n background: linear-gradient(135deg, #7c3aed 0%, #a855f7 100%);\n color: #fff;\n border-bottom-right-radius: 4px;\n }\n\n .mobile-input-area {\n padding: 12px 16px 16px;\n border-top: 1px solid #e5e7eb;\n background: #f9fafb;\n flex-shrink: 0;\n }\n\n .mobile-input-wrapper {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 4px 4px 16px;\n background: #fff;\n border-radius: 24px;\n border: 2px solid #e5e7eb;\n }\n\n .mobile-text-input {\n flex: 1;\n border: none;\n outline: none;\n font-size: 14px;\n color: #374151;\n background: transparent;\n padding: 10px 0;\n }\n\n .mobile-text-input::placeholder {\n color: #9ca3af;\n }\n\n .mobile-send-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n border-radius: 50%;\n border: none;\n background: linear-gradient(135deg, #7c3aed 0%, #a855f7 100%);\n color: #fff;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .mobile-send-btn:hover:not(:disabled) {\n transform: scale(1.05);\n }\n\n .mobile-send-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .mobile-input-hint {\n margin: 8px 0 0;\n font-size: 11px;\n color: #9ca3af;\n text-align: center;\n transition: color 0.2s ease;\n }\n\n /* Mobile text input status states */\n .mobile-input-hint--sending {\n color: #666;\n }\n\n .mobile-input-hint--success {\n color: #28a745;\n }\n\n .mobile-input-hint--queued {\n color: #ffc107;\n }\n\n .mobile-input-hint--error {\n color: #dc3545;\n }\n\n /* Disabled mobile input styling */\n #mobileTextInput:disabled {\n background-color: #f5f5f5;\n cursor: not-allowed;\n }\n\n #mobileSendBtn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n ");
18295
18715
  }
18296
18716
 
18297
18717
  /**
@@ -22611,9 +23031,18 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
22611
23031
 
22612
23032
  // Queue for prepared AudioBuffers (ready to schedule)
22613
23033
  _this.preparedBuffer = [];
23034
+
23035
+ // Maximum buffer sizes to prevent unbounded memory growth
23036
+ // If backend sends sentences faster than playback, oldest frames are dropped
23037
+ _this.MAX_PREPARED_BUFFER_SIZE = 200; // Max prepared frames (~10-12 seconds at 600ms per frame)
23038
+ _this.MAX_PCM_CHUNK_QUEUE_SIZE = 50; // Max raw PCM chunks
23039
+
22614
23040
  _this.isProcessingPcmQueue = false;
22615
23041
  _this.isSchedulingFrames = false;
22616
23042
 
23043
+ // Timeout to detect empty sentences (audio_start but no chunks)
23044
+ _this._emptySentenceTimeout = null;
23045
+
22617
23046
  // Minimal scheduling delay to avoid scheduling audio in the past
22618
23047
  // REMOVED: Lookahead buffering was causing quality degradation due to browser resampling/timing issues
22619
23048
  // Now we only schedule with minimal delay (20ms) just enough to avoid gaps
@@ -22624,6 +23053,15 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
22624
23053
  _this.sentenceTimings = []; // [{startTime, text, displayed}, ...]
22625
23054
  _this.isCheckingTranscripts = false;
22626
23055
 
23056
+ // Flag to prevent queuing new audio after stopImmediate() is called (barge-in protection)
23057
+ // This prevents race conditions where audio chunks arrive after stop but before sources are stopped
23058
+ // Cleared when markNewSentence() is called (signals new audio is starting)
23059
+ _this._isStopped = false;
23060
+
23061
+ // Track current sentence ID to reject chunks from previous sentences
23062
+ // Incremented each time markNewSentence() is called
23063
+ _this._currentSentenceId = 0;
23064
+
22627
23065
  // Codec registry
22628
23066
 
22629
23067
  _this.codecs = {
@@ -22724,6 +23162,12 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
22724
23162
  key: "playAudio",
22725
23163
  value: function playAudio(binaryData) {
22726
23164
  var _this2 = this;
23165
+ // CRITICAL: Ignore audio if playback was stopped (barge-in protection)
23166
+ // This prevents overlapping audio when chunks arrive after stopImmediate() is called
23167
+ if (this._isStopped) {
23168
+ console.log('🛑 AudioPlayer: Ignoring audio chunk - playback was stopped (barge-in)');
23169
+ return;
23170
+ }
22727
23171
  try {
22728
23172
  var audioBlob = this.createAudioBlob(binaryData);
22729
23173
  this.audioQueue.push(audioBlob);
@@ -22754,13 +23198,34 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
22754
23198
  value: (function () {
22755
23199
  var _playChunk = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(pcmData) {
22756
23200
  var _this3 = this;
22757
- var preparedFrame, _this$audioContext;
23201
+ var preparedFrame, dropped, _this$audioContext;
22758
23202
  return _regenerator().w(function (_context) {
22759
23203
  while (1) switch (_context.n) {
22760
23204
  case 0:
23205
+ if (!this._isStopped) {
23206
+ _context.n = 1;
23207
+ break;
23208
+ }
23209
+ console.log('🛑 AudioPlayer: Ignoring PCM chunk - playback was stopped (barge-in)');
23210
+ return _context.a(2);
23211
+ case 1:
22761
23212
  // Pre-process frame immediately (convert to AudioBuffer)
22762
23213
  preparedFrame = this.prepareChunk(pcmData);
22763
23214
  if (preparedFrame) {
23215
+ // CRITICAL: Clear empty sentence timeout since chunks are arriving
23216
+ // This resets the timer for the current sentence
23217
+ if (this._emptySentenceTimeout) {
23218
+ clearTimeout(this._emptySentenceTimeout);
23219
+ this._emptySentenceTimeout = null;
23220
+ }
23221
+
23222
+ // CRITICAL: Prevent unbounded buffer growth
23223
+ // If backend sends sentences faster than playback, drop oldest frames
23224
+ if (this.preparedBuffer.length >= this.MAX_PREPARED_BUFFER_SIZE) {
23225
+ dropped = this.preparedBuffer.shift(); // Drop oldest frame
23226
+ console.warn("\u26A0\uFE0F AudioPlayer: preparedBuffer at max size (".concat(this.MAX_PREPARED_BUFFER_SIZE, "), dropped oldest frame"));
23227
+ }
23228
+
22764
23229
  // Add prepared frame to buffer
22765
23230
  this.preparedBuffer.push(preparedFrame);
22766
23231
 
@@ -22768,7 +23233,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
22768
23233
 
22769
23234
  // Use requestAnimationFrame to avoid blocking, but ensure scheduling happens
22770
23235
 
22771
- if (!this.isSchedulingFrames) {
23236
+ if (!this.isSchedulingFrames && !this._isStopped) {
22772
23237
  // Schedule immediately if not already scheduling
22773
23238
 
22774
23239
  this.schedulePreparedFrames();
@@ -22780,7 +23245,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
22780
23245
  // Use a short timeout to ensure we check again after current scheduling completes
22781
23246
 
22782
23247
  setTimeout(function () {
22783
- if (_this3.preparedBuffer.length > 0 && !_this3.isSchedulingFrames) {
23248
+ if (_this3.preparedBuffer.length > 0 && !_this3.isSchedulingFrames && !_this3._isStopped) {
22784
23249
  _this3.schedulePreparedFrames();
22785
23250
  }
22786
23251
  }, 5); // Very short delay to check after current scheduling completes
@@ -22802,7 +23267,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
22802
23267
  // Emit error event
22803
23268
  this.emit('playbackError', new Error('Failed to prepare PCM chunk for playback'));
22804
23269
  }
22805
- case 1:
23270
+ case 2:
22806
23271
  return _context.a(2);
22807
23272
  }
22808
23273
  }, _callee, this);
@@ -22919,16 +23384,23 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
22919
23384
  value: (function () {
22920
23385
  var _schedulePreparedFrames = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
22921
23386
  var _this4 = this;
22922
- var queuedFrames, targetLookaheadFrames, _this$audioContext2, _this$audioContext3, _this$audioContext4, _this$audioContext5, scheduledCount, _loop, _t;
23387
+ var queuedFrames, targetLookaheadFrames, _this$audioContext2, _this$audioContext3, _this$audioContext4, _this$audioContext5, scheduledCount, _loop, _ret, _t;
22923
23388
  return _regenerator().w(function (_context3) {
22924
23389
  while (1) switch (_context3.p = _context3.n) {
22925
23390
  case 0:
22926
- if (!this.isSchedulingFrames) {
23391
+ if (!this._isStopped) {
22927
23392
  _context3.n = 1;
22928
23393
  break;
22929
23394
  }
23395
+ console.log('🛑 AudioPlayer: Not scheduling frames - playback was stopped (barge-in)');
22930
23396
  return _context3.a(2);
22931
23397
  case 1:
23398
+ if (!this.isSchedulingFrames) {
23399
+ _context3.n = 2;
23400
+ break;
23401
+ }
23402
+ return _context3.a(2);
23403
+ case 2:
22932
23404
  this.isSchedulingFrames = true;
22933
23405
 
22934
23406
  // Schedule multiple frames ahead to ensure continuous playback
@@ -22940,7 +23412,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
22940
23412
  if (targetLookaheadFrames === 0 && queuedFrames > 0) {
22941
23413
  targetLookaheadFrames = 1; // At least schedule 1 frame
22942
23414
  }
22943
- _context3.p = 2;
23415
+ _context3.p = 3;
22944
23416
  // Initialize audio context if needed
22945
23417
 
22946
23418
  if (!this.audioContext) {
@@ -22951,9 +23423,9 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
22951
23423
  // This is critical for mobile devices where AudioContext initialization takes time
22952
23424
  // Replaces fixed timeouts with event-driven waiting
22953
23425
  console.log('🔍 [scheduleWAV] BEFORE waitForAudioContextReady - state:', (_this$audioContext2 = this.audioContext) === null || _this$audioContext2 === void 0 ? void 0 : _this$audioContext2.state, 'currentTime:', (_this$audioContext3 = this.audioContext) === null || _this$audioContext3 === void 0 ? void 0 : _this$audioContext3.currentTime);
22954
- _context3.n = 3;
23426
+ _context3.n = 4;
22955
23427
  return this.waitForAudioContextReady();
22956
- case 3:
23428
+ case 4:
22957
23429
  console.log('🔍 [scheduleWAV] AFTER waitForAudioContextReady - state:', (_this$audioContext4 = this.audioContext) === null || _this$audioContext4 === void 0 ? void 0 : _this$audioContext4.state, 'currentTime:', (_this$audioContext5 = this.audioContext) === null || _this$audioContext5 === void 0 ? void 0 : _this$audioContext5.currentTime);
22958
23430
 
22959
23431
  // Schedule frames up to target lookahead (ensures smooth playback)
@@ -22964,14 +23436,21 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
22964
23436
  return _regenerator().w(function (_context2) {
22965
23437
  while (1) switch (_context2.n) {
22966
23438
  case 0:
23439
+ if (!_this4._isStopped) {
23440
+ _context2.n = 1;
23441
+ break;
23442
+ }
23443
+ console.log('🛑 AudioPlayer: Stopping frame scheduling - playback was stopped');
23444
+ return _context2.a(2, 0);
23445
+ case 1:
22967
23446
  // Get next prepared frame
22968
23447
  preparedFrame = _this4.preparedBuffer.shift();
22969
23448
  if (preparedFrame) {
22970
- _context2.n = 1;
23449
+ _context2.n = 2;
22971
23450
  break;
22972
23451
  }
22973
- return _context2.a(2, 1);
22974
- case 1:
23452
+ return _context2.a(2, 0);
23453
+ case 2:
22975
23454
  // Create source and schedule playback
22976
23455
  source = _this4.audioContext.createBufferSource();
22977
23456
  source.buffer = preparedFrame.buffer;
@@ -23048,29 +23527,46 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
23048
23527
  // Track when this buffer finishes (for cleanup only)
23049
23528
 
23050
23529
  source.onended = function () {
23051
- // Remove from tracked sources
23530
+ // CRITICAL: Check if playback was stopped before processing cleanup
23531
+ // This prevents race conditions where onended fires after stopImmediate() was called
23532
+ if (_this4._isStopped) {
23533
+ // Playback was stopped, ignore this callback
23534
+ return;
23535
+ }
23052
23536
 
23537
+ // CRITICAL: Only process if source is still in scheduledSources set
23538
+ // This prevents race conditions where stopImmediate() cleared the set but callback fires later
23539
+ if (!_this4.scheduledSources.has(source)) {
23540
+ // Source was already removed (probably by stopImmediate), ignore this callback
23541
+ return;
23542
+ }
23543
+
23544
+ // Remove from tracked sources
23053
23545
  _this4.scheduledSources.delete(source);
23054
- _this4.scheduledBuffers--;
23546
+
23547
+ // Only decrement if we're still playing and buffer count is positive
23548
+ if (!_this4._isStopped && _this4.scheduledBuffers > 0) {
23549
+ _this4.scheduledBuffers--;
23550
+ }
23055
23551
 
23056
23552
  // If no more scheduled buffers and no prepared frames, playback is complete
23057
23553
 
23058
- if (_this4.scheduledBuffers === 0 && _this4.preparedBuffer.length === 0 && _this4.pcmChunkQueue.length === 0) {
23554
+ if (_this4.scheduledBuffers === 0 && _this4.preparedBuffer.length === 0 && _this4.pcmChunkQueue.length === 0 && !_this4._isStopped) {
23059
23555
  _this4.isPlaying = false;
23060
23556
  _this4.isSchedulingFrames = false;
23061
23557
  console.log('🛑 AudioPlayer: Emitting playbackStopped event (all buffers finished)');
23062
23558
  _this4.emit('playbackStopped');
23063
- } else if (_this4.preparedBuffer.length > 0) {
23559
+ } else if (_this4.preparedBuffer.length > 0 && !_this4._isStopped) {
23064
23560
  // More frames available, schedule them immediately
23065
23561
 
23066
23562
  // Use setTimeout to avoid blocking, but schedule quickly
23067
23563
 
23068
23564
  setTimeout(function () {
23069
- if (_this4.preparedBuffer.length > 0 && !_this4.isSchedulingFrames) {
23565
+ if (_this4.preparedBuffer.length > 0 && !_this4.isSchedulingFrames && !_this4._isStopped) {
23070
23566
  _this4.schedulePreparedFrames();
23071
23567
  }
23072
23568
  }, 0);
23073
- } else if (_this4.scheduledBuffers > 0) {
23569
+ } else if (_this4.scheduledBuffers > 0 && !_this4._isStopped) {
23074
23570
  // No more prepared frames but still have scheduled buffers playing
23075
23571
 
23076
23572
  // Set up a check to schedule new frames when they arrive
@@ -23078,9 +23574,13 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
23078
23574
  // Keep checking periodically until we have no more scheduled buffers
23079
23575
 
23080
23576
  var _checkForMoreFrames = function checkForMoreFrames() {
23577
+ // CRITICAL: Check if stopped before scheduling
23578
+ if (_this4._isStopped) {
23579
+ return;
23580
+ }
23081
23581
  if (_this4.preparedBuffer.length > 0 && !_this4.isSchedulingFrames && _this4.scheduledBuffers > 0) {
23082
23582
  _this4.schedulePreparedFrames();
23083
- } else if (_this4.scheduledBuffers > 0) {
23583
+ } else if (_this4.scheduledBuffers > 0 && !_this4._isStopped) {
23084
23584
  // Keep checking - frames might arrive soon
23085
23585
 
23086
23586
  setTimeout(_checkForMoreFrames, 10);
@@ -23094,27 +23594,28 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
23094
23594
  console.log('🎵 AudioPlayer: Emitting playbackStarted event');
23095
23595
  _this4.emit('playbackStarted');
23096
23596
  }
23097
- case 2:
23597
+ case 3:
23098
23598
  return _context2.a(2);
23099
23599
  }
23100
23600
  }, _loop);
23101
23601
  });
23102
- case 4:
23602
+ case 5:
23103
23603
  if (!(this.preparedBuffer.length > 0 && scheduledCount < targetLookaheadFrames)) {
23104
- _context3.n = 7;
23604
+ _context3.n = 8;
23105
23605
  break;
23106
23606
  }
23107
- return _context3.d(_regeneratorValues(_loop()), 5);
23108
- case 5:
23109
- if (!_context3.v) {
23110
- _context3.n = 6;
23607
+ return _context3.d(_regeneratorValues(_loop()), 6);
23608
+ case 6:
23609
+ _ret = _context3.v;
23610
+ if (!(_ret === 0)) {
23611
+ _context3.n = 7;
23111
23612
  break;
23112
23613
  }
23113
- return _context3.a(3, 7);
23114
- case 6:
23115
- _context3.n = 4;
23116
- break;
23614
+ return _context3.a(3, 8);
23117
23615
  case 7:
23616
+ _context3.n = 5;
23617
+ break;
23618
+ case 8:
23118
23619
  // All prepared frames scheduled, reset flag
23119
23620
 
23120
23621
  this.isSchedulingFrames = false;
@@ -23123,11 +23624,11 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
23123
23624
 
23124
23625
  // Use requestAnimationFrame for smooth scheduling without blocking
23125
23626
 
23126
- if (this.preparedBuffer.length > 0) {
23627
+ if (this.preparedBuffer.length > 0 && !this._isStopped) {
23127
23628
  // More frames arrived, schedule them immediately
23128
23629
 
23129
23630
  requestAnimationFrame(function () {
23130
- if (_this4.preparedBuffer.length > 0 && !_this4.isSchedulingFrames) {
23631
+ if (_this4.preparedBuffer.length > 0 && !_this4.isSchedulingFrames && !_this4._isStopped) {
23131
23632
  _this4.schedulePreparedFrames();
23132
23633
  }
23133
23634
  });
@@ -23135,37 +23636,37 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
23135
23636
 
23136
23637
  // Always set up a periodic check if we have scheduled buffers playing
23137
23638
  // This ensures continuous playback even if frames arrive slowly
23138
- if (this.scheduledBuffers > 0) {
23639
+ if (this.scheduledBuffers > 0 && !this._isStopped) {
23139
23640
  // Set up a periodic check to schedule new frames as they arrive
23140
23641
  // Use a shorter interval to catch new frames quickly
23141
23642
  setTimeout(function () {
23142
- if (_this4.preparedBuffer.length > 0 && !_this4.isSchedulingFrames && _this4.scheduledBuffers > 0) {
23643
+ if (_this4.preparedBuffer.length > 0 && !_this4.isSchedulingFrames && _this4.scheduledBuffers > 0 && !_this4._isStopped) {
23143
23644
  _this4.schedulePreparedFrames();
23144
- } else if (_this4.scheduledBuffers > 0) {
23645
+ } else if (_this4.scheduledBuffers > 0 && !_this4._isStopped) {
23145
23646
  // Keep checking even if no frames yet - they might arrive soon
23146
23647
 
23147
23648
  // Recursively check until we have no more scheduled buffers
23148
23649
 
23149
23650
  setTimeout(function () {
23150
- if (_this4.preparedBuffer.length > 0 && !_this4.isSchedulingFrames && _this4.scheduledBuffers > 0) {
23651
+ if (_this4.preparedBuffer.length > 0 && !_this4.isSchedulingFrames && _this4.scheduledBuffers > 0 && !_this4._isStopped) {
23151
23652
  _this4.schedulePreparedFrames();
23152
23653
  }
23153
23654
  }, 10);
23154
23655
  }
23155
23656
  }, 10); // Check every 10ms for new frames
23156
23657
  }
23157
- _context3.n = 9;
23658
+ _context3.n = 10;
23158
23659
  break;
23159
- case 8:
23160
- _context3.p = 8;
23660
+ case 9:
23661
+ _context3.p = 9;
23161
23662
  _t = _context3.v;
23162
23663
  console.error('❌ AudioPlayer v2: Error scheduling frames:', _t);
23163
23664
  this.emit('playbackError', _t);
23164
23665
  this.isSchedulingFrames = false;
23165
- case 9:
23666
+ case 10:
23166
23667
  return _context3.a(2);
23167
23668
  }
23168
- }, _callee2, this, [[2, 8]]);
23669
+ }, _callee2, this, [[3, 9]]);
23169
23670
  }));
23170
23671
  function schedulePreparedFrames() {
23171
23672
  return _schedulePreparedFrames.apply(this, arguments);
@@ -23186,14 +23687,21 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
23186
23687
  return _regenerator().w(function (_context4) {
23187
23688
  while (1) switch (_context4.p = _context4.n) {
23188
23689
  case 0:
23189
- if (!this.isProcessingPcmQueue) {
23690
+ if (!this._isStopped) {
23190
23691
  _context4.n = 1;
23191
23692
  break;
23192
23693
  }
23694
+ console.log('🛑 AudioPlayer: Not processing PCM queue - playback was stopped (barge-in)');
23193
23695
  return _context4.a(2);
23194
23696
  case 1:
23697
+ if (!this.isProcessingPcmQueue) {
23698
+ _context4.n = 2;
23699
+ break;
23700
+ }
23701
+ return _context4.a(2);
23702
+ case 2:
23195
23703
  this.isProcessingPcmQueue = true;
23196
- _context4.p = 2;
23704
+ _context4.p = 3;
23197
23705
  // Initialize audio context if needed
23198
23706
 
23199
23707
  if (!this.audioContext) {
@@ -23203,20 +23711,27 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
23203
23711
  // ✅ NEW: Wait for AudioContext to be in 'running' state before proceeding
23204
23712
  // This is critical for mobile devices where AudioContext initialization takes time
23205
23713
  // Replaces fixed timeouts with event-driven waiting
23206
- _context4.n = 3;
23714
+ _context4.n = 4;
23207
23715
  return this.waitForAudioContextReady();
23208
- case 3:
23716
+ case 4:
23209
23717
  if (!(this.pcmChunkQueue.length > 0)) {
23718
+ _context4.n = 7;
23719
+ break;
23720
+ }
23721
+ if (!this._isStopped) {
23210
23722
  _context4.n = 5;
23211
23723
  break;
23212
23724
  }
23725
+ console.log('🛑 AudioPlayer: Stopping PCM queue processing - playback was stopped');
23726
+ return _context4.a(3, 7);
23727
+ case 5:
23213
23728
  pcmData = this.pcmChunkQueue.shift();
23214
23729
  if (pcmData) {
23215
- _context4.n = 4;
23730
+ _context4.n = 6;
23216
23731
  break;
23217
23732
  }
23218
- return _context4.a(3, 3);
23219
- case 4:
23733
+ return _context4.a(3, 4);
23734
+ case 6:
23220
23735
  // Ensure even byte count for 16-bit PCM
23221
23736
  processedData = pcmData;
23222
23737
  if (pcmData.byteLength % 2 !== 0) {
@@ -23308,25 +23823,25 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
23308
23823
  this.isPlaying = true;
23309
23824
  this.emit('playbackStarted');
23310
23825
  }
23311
- _context4.n = 3;
23826
+ _context4.n = 4;
23312
23827
  break;
23313
- case 5:
23828
+ case 7:
23314
23829
  // end while loop
23315
23830
 
23316
23831
  // All chunks scheduled, reset processing flag
23317
23832
  this.isProcessingPcmQueue = false;
23318
- _context4.n = 7;
23833
+ _context4.n = 9;
23319
23834
  break;
23320
- case 6:
23321
- _context4.p = 6;
23835
+ case 8:
23836
+ _context4.p = 8;
23322
23837
  _t2 = _context4.v;
23323
23838
  console.error('❌ AudioPlayer v2: Error playing chunk:', _t2);
23324
23839
  this.emit('playbackError', _t2);
23325
23840
  this.isProcessingPcmQueue = false;
23326
- case 7:
23841
+ case 9:
23327
23842
  return _context4.a(2);
23328
23843
  }
23329
- }, _callee3, this, [[2, 6]]);
23844
+ }, _callee3, this, [[3, 8]]);
23330
23845
  }));
23331
23846
  function processPcmQueue() {
23332
23847
  return _processPcmQueue.apply(this, arguments);
@@ -24036,22 +24551,29 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
24036
24551
  return _regenerator().w(function (_context6) {
24037
24552
  while (1) switch (_context6.p = _context6.n) {
24038
24553
  case 0:
24039
- if (!(this.isProcessingQueue || this.audioQueue.length === 0)) {
24554
+ if (!this._isStopped) {
24040
24555
  _context6.n = 1;
24041
24556
  break;
24042
24557
  }
24558
+ console.log('🛑 AudioPlayer: Not processing queue - playback was stopped (barge-in)');
24043
24559
  return _context6.a(2);
24044
24560
  case 1:
24561
+ if (!(this.isProcessingQueue || this.audioQueue.length === 0)) {
24562
+ _context6.n = 2;
24563
+ break;
24564
+ }
24565
+ return _context6.a(2);
24566
+ case 2:
24045
24567
  this.isProcessingQueue = true;
24046
24568
  audioBlob = this.audioQueue.shift();
24047
24569
  if (audioBlob) {
24048
- _context6.n = 2;
24570
+ _context6.n = 3;
24049
24571
  break;
24050
24572
  }
24051
24573
  this.isProcessingQueue = false;
24052
24574
  return _context6.a(2);
24053
- case 2:
24054
- _context6.p = 2;
24575
+ case 3:
24576
+ _context6.p = 3;
24055
24577
  wasFirstPlay = !this.isPlaying && this.currentSource === null; // Initialize audio context if needed
24056
24578
  if (!this.audioContext) {
24057
24579
  this.initializeAudioContext();
@@ -24060,17 +24582,17 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
24060
24582
  // ✅ NEW: Wait for AudioContext to be in 'running' state before proceeding
24061
24583
  // This is critical for mobile devices where AudioContext initialization takes time
24062
24584
  // Replaces fixed timeouts with event-driven waiting
24063
- _context6.n = 3;
24585
+ _context6.n = 4;
24064
24586
  return this.waitForAudioContextReady();
24065
- case 3:
24587
+ case 4:
24066
24588
  audioContext = this.audioContext; // Decode audio
24067
- _context6.n = 4;
24589
+ _context6.n = 5;
24068
24590
  return audioBlob.arrayBuffer();
24069
- case 4:
24591
+ case 5:
24070
24592
  arrayBuffer = _context6.v;
24071
- _context6.n = 5;
24593
+ _context6.n = 6;
24072
24594
  return audioContext.decodeAudioData(arrayBuffer);
24073
- case 5:
24595
+ case 6:
24074
24596
  audioBuffer = _context6.v;
24075
24597
  shouldEmitStart = wasFirstPlay && !this.isPlaying && this.currentSource === null; // Create source
24076
24598
  source = audioContext.createBufferSource();
@@ -24114,10 +24636,10 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
24114
24636
  // Start playback - AudioContext should now be fully ready
24115
24637
 
24116
24638
  source.start();
24117
- _context6.n = 7;
24639
+ _context6.n = 8;
24118
24640
  break;
24119
- case 6:
24120
- _context6.p = 6;
24641
+ case 7:
24642
+ _context6.p = 7;
24121
24643
  _t3 = _context6.v;
24122
24644
  console.error('❌ AudioPlayer v2: Error processing queue:', _t3);
24123
24645
  this.currentSource = null;
@@ -24135,10 +24657,10 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
24135
24657
  this.isProcessingQueue = false;
24136
24658
  this.emit('playbackStopped');
24137
24659
  }
24138
- case 7:
24660
+ case 8:
24139
24661
  return _context6.a(2);
24140
24662
  }
24141
- }, _callee5, this, [[2, 6]]);
24663
+ }, _callee5, this, [[3, 7]]);
24142
24664
  }));
24143
24665
  function processQueue() {
24144
24666
  return _processQueue.apply(this, arguments);
@@ -24179,6 +24701,15 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
24179
24701
  console.log(' scheduledSources.size:', this.scheduledSources.size);
24180
24702
  console.log(' scheduledBuffers:', this.scheduledBuffers);
24181
24703
 
24704
+ // CRITICAL: Set stopped flag FIRST to prevent new audio from being queued/scheduled
24705
+ // This prevents race conditions where audio chunks arrive after stop but before sources are stopped
24706
+ // The flag will be cleared when markNewSentence() is called (signals new audio is starting)
24707
+ this._isStopped = true;
24708
+
24709
+ // CRITICAL: Stop scheduling immediately to prevent frames from being scheduled
24710
+ // This ensures schedulePreparedFrames() loop will exit on next _isStopped check
24711
+ this.isSchedulingFrames = false;
24712
+
24182
24713
  // Stop current source (legacy queue-based system)
24183
24714
 
24184
24715
  if (this.currentSource) {
@@ -24200,27 +24731,31 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
24200
24731
  if (this.scheduledSources.size > 0) {
24201
24732
  console.log(" Stopping ".concat(this.scheduledSources.size, " scheduled sources..."));
24202
24733
  var stoppedCount = 0;
24203
- var _iterator = _createForOfIteratorHelper(this.scheduledSources),
24204
- _step;
24205
- try {
24206
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
24207
- var source = _step.value;
24208
- try {
24209
- source.stop();
24210
- stoppedCount++;
24211
- } catch (e) {
24212
- // Ignore if already stopped or not started yet
24213
24734
 
24214
- console.log(' Source already stopped or not started:', e.message);
24215
- }
24735
+ // Store sources to stop and count before clearing the set
24736
+ var sourcesToStop = Array.from(this.scheduledSources);
24737
+ var sourcesCount = sourcesToStop.length;
24738
+
24739
+ // Clear the set BEFORE stopping sources to prevent onended callbacks from modifying it
24740
+ // This ensures onended callbacks will see empty set and return early
24741
+ this.scheduledSources.clear();
24742
+
24743
+ // CRITICAL: Reset scheduledBuffers to 0 BEFORE stopping sources
24744
+ // This prevents onended callbacks from decrementing it below 0
24745
+ // Any onended callbacks that fire will see scheduledSources is empty and return early
24746
+ this.scheduledBuffers = 0;
24747
+ for (var _i = 0, _sourcesToStop = sourcesToStop; _i < _sourcesToStop.length; _i++) {
24748
+ var source = _sourcesToStop[_i];
24749
+ try {
24750
+ source.stop();
24751
+ stoppedCount++;
24752
+ } catch (e) {
24753
+ // Ignore if already stopped or not started yet
24754
+
24755
+ console.log(' Source already stopped or not started:', e.message);
24216
24756
  }
24217
- } catch (err) {
24218
- _iterator.e(err);
24219
- } finally {
24220
- _iterator.f();
24221
24757
  }
24222
- console.log(" Stopped ".concat(stoppedCount, " sources"));
24223
- this.scheduledSources.clear();
24758
+ console.log(" Stopped ".concat(stoppedCount, " sources (cleared ").concat(sourcesCount, " from scheduledSources)"));
24224
24759
  }
24225
24760
 
24226
24761
  // Clear state
@@ -24236,10 +24771,15 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
24236
24771
  this.isProcessingPcmQueue = false;
24237
24772
  this.isSchedulingFrames = false;
24238
24773
 
24239
- // Reset scheduling properties
24774
+ // Clear empty sentence timeout (barge-in means sentence was interrupted, not empty)
24775
+ if (this._emptySentenceTimeout) {
24776
+ clearTimeout(this._emptySentenceTimeout);
24777
+ this._emptySentenceTimeout = null;
24778
+ }
24240
24779
 
24780
+ // Reset scheduling properties
24781
+ // Note: scheduledBuffers was already reset to 0 above when clearing scheduledSources
24241
24782
  this.nextStartTime = 0;
24242
- this.scheduledBuffers = 0;
24243
24783
 
24244
24784
  // Clear transcript state
24245
24785
  this.clearTranscriptState();
@@ -24259,8 +24799,77 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
24259
24799
  }, {
24260
24800
  key: "markNewSentence",
24261
24801
  value: function markNewSentence(text) {
24802
+ var _this9 = this;
24803
+ var wasStopped = this._isStopped;
24804
+ var isCurrentlyPlaying = this.isPlaying || this.scheduledSources.size > 0;
24805
+
24806
+ // CRITICAL: Clear stopped flag when new audio starts (after barge-in)
24807
+ // This allows new audio chunks to be queued after barge-in
24808
+ if (this._isStopped) {
24809
+ console.log('🛑 AudioPlayer: Clearing stopped flag - new audio starting after barge-in');
24810
+ this._isStopped = false;
24811
+
24812
+ // CRITICAL: Reset scheduling state when starting a new sentence after a stop
24813
+ // This ensures the new sentence starts immediately without delay
24814
+ // Reset nextStartTime so first chunk schedules immediately (not in the past)
24815
+ this.nextStartTime = 0;
24816
+
24817
+ // CRITICAL: Reset scheduledBuffers to 0, but ensure it's not negative
24818
+ // This accounts for any onended callbacks that might fire from stopped sources
24819
+ // If scheduledBuffers is negative, it means onended callbacks fired after stopImmediate()
24820
+ // In that case, we should reset to 0 to start fresh
24821
+ if (this.scheduledBuffers < 0) {
24822
+ console.log("\uD83D\uDD04 AudioPlayer: scheduledBuffers was negative (".concat(this.scheduledBuffers, "), resetting to 0"));
24823
+ }
24824
+ this.scheduledBuffers = 0;
24825
+
24826
+ // CRITICAL: ALWAYS clear preparedBuffer after barge-in - any remaining chunks are from previous sentence
24827
+ // This prevents old audio from playing when new sentence starts after interruption
24828
+ if (this.preparedBuffer.length > 0) {
24829
+ console.log("\uD83D\uDD04 AudioPlayer: Clearing ".concat(this.preparedBuffer.length, " prepared frames from previous sentence (after barge-in)"));
24830
+ }
24831
+ this.preparedBuffer = [];
24832
+
24833
+ // CRITICAL: Also clear pcmChunkQueue to prevent raw chunks from previous sentence being processed
24834
+ if (this.pcmChunkQueue.length > 0) {
24835
+ console.log("\uD83D\uDD04 AudioPlayer: Clearing ".concat(this.pcmChunkQueue.length, " raw PCM chunks from previous sentence (after barge-in)"));
24836
+ }
24837
+ this.pcmChunkQueue = [];
24838
+ this.isProcessingPcmQueue = false;
24839
+ console.log('🔄 AudioPlayer: Reset scheduling state for new sentence (after barge-in)');
24840
+ } else if (isCurrentlyPlaying) {
24841
+ // New sentence received while audio is currently playing (no barge-in)
24842
+ // Don't clear buffers or reset state - let current sentence finish, then new one will play
24843
+ console.log("\uD83D\uDCDD AudioPlayer: New sentence queued while audio playing - will start after current sentence finishes");
24844
+ }
24845
+
24846
+ // Always update pending sentence text (for transcript display)
24262
24847
  this.pendingSentenceText = text;
24263
- console.log("\uD83D\uDCDD AudioPlayer: New sentence marked: \"".concat(text.substring(0, 40), "...\""));
24848
+ console.log("\uD83D\uDCDD AudioPlayer: New sentence marked: \"".concat(text.substring(0, 40), "...\" (wasStopped: ").concat(wasStopped, ", isPlaying: ").concat(isCurrentlyPlaying, ")"));
24849
+
24850
+ // CRITICAL: Set timeout to detect empty sentences (audio_start but no chunks)
24851
+ // This prevents queue blocking if backend sends audio_start but no audio chunks follow
24852
+ if (this._emptySentenceTimeout) {
24853
+ clearTimeout(this._emptySentenceTimeout);
24854
+ }
24855
+ var sentenceText = text; // Capture for timeout callback
24856
+ this._emptySentenceTimeout = setTimeout(function () {
24857
+ // Check if this sentence still has no chunks after timeout
24858
+ if (_this9.pendingSentenceText === sentenceText && _this9.scheduledBuffers === 0 && _this9.preparedBuffer.length === 0 && _this9.pcmChunkQueue.length === 0 && !_this9._isStopped) {
24859
+ console.warn("\u26A0\uFE0F AudioPlayer: Empty sentence detected after 5s timeout - no chunks received for: \"".concat(sentenceText.substring(0, 40), "...\""));
24860
+ // Clear pending sentence to unblock next sentence
24861
+ if (_this9.pendingSentenceText === sentenceText) {
24862
+ _this9.pendingSentenceText = null;
24863
+ }
24864
+ // Emit playbackStopped to allow next sentence to start
24865
+ // Only if we're not currently playing (to avoid interrupting real playback)
24866
+ if (!_this9.isPlaying && _this9.scheduledSources.size === 0) {
24867
+ console.log('🛑 AudioPlayer: Emitting playbackStopped for empty sentence timeout');
24868
+ _this9.emit('playbackStopped');
24869
+ }
24870
+ }
24871
+ _this9._emptySentenceTimeout = null;
24872
+ }, 5000); // 5 second timeout - adjust based on expected chunk arrival rate
24264
24873
  }
24265
24874
 
24266
24875
  /**
@@ -24269,35 +24878,35 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
24269
24878
  }, {
24270
24879
  key: "startTranscriptChecker",
24271
24880
  value: function startTranscriptChecker() {
24272
- var _this9 = this;
24881
+ var _this0 = this;
24273
24882
  if (this.isCheckingTranscripts) return;
24274
24883
  this.isCheckingTranscripts = true;
24275
24884
  console.log('📝 AudioPlayer: Transcript checker started');
24276
24885
  var _checkLoop = function checkLoop() {
24277
- if (!_this9.isCheckingTranscripts || !_this9.audioContext) return;
24278
- var currentTime = _this9.audioContext.currentTime;
24279
- var _iterator2 = _createForOfIteratorHelper(_this9.sentenceTimings),
24280
- _step2;
24886
+ if (!_this0.isCheckingTranscripts || !_this0.audioContext) return;
24887
+ var currentTime = _this0.audioContext.currentTime;
24888
+ var _iterator = _createForOfIteratorHelper(_this0.sentenceTimings),
24889
+ _step;
24281
24890
  try {
24282
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
24283
- var timing = _step2.value;
24891
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
24892
+ var timing = _step.value;
24284
24893
  if (!timing.displayed && currentTime >= timing.startTime) {
24285
24894
  timing.displayed = true;
24286
24895
  console.log("\uD83D\uDCDD AudioPlayer: Display transcript at ".concat(currentTime.toFixed(3), "s: \"").concat(timing.text.substring(0, 40), "...\""));
24287
- _this9.emit('transcriptDisplay', {
24896
+ _this0.emit('transcriptDisplay', {
24288
24897
  text: timing.text
24289
24898
  });
24290
24899
  }
24291
24900
  }
24292
24901
  } catch (err) {
24293
- _iterator2.e(err);
24902
+ _iterator.e(err);
24294
24903
  } finally {
24295
- _iterator2.f();
24904
+ _iterator.f();
24296
24905
  }
24297
- if (_this9.isPlaying || _this9.scheduledBuffers > 0) {
24906
+ if (_this0.isPlaying || _this0.scheduledBuffers > 0) {
24298
24907
  requestAnimationFrame(_checkLoop);
24299
24908
  } else {
24300
- _this9.isCheckingTranscripts = false;
24909
+ _this0.isCheckingTranscripts = false;
24301
24910
  console.log('📝 AudioPlayer: Transcript checker stopped');
24302
24911
  }
24303
24912
  };
@@ -25578,7 +26187,8 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
25578
26187
  }, {
25579
26188
  key: "handleMessage",
25580
26189
  value: function handleMessage(event) {
25581
- var _this7 = this;
26190
+ var _this$audioPlayer$sch,
26191
+ _this7 = this;
25582
26192
  // Binary message (audio data)
25583
26193
 
25584
26194
  if (event.data instanceof ArrayBuffer || event.data instanceof Blob) {
@@ -25657,9 +26267,17 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
25657
26267
  // Backend sends audio_start with transcript text before audio chunks
25658
26268
  // Store the text in AudioPlayer for synced display when audio actually starts playing
25659
26269
  console.log('📝 VoiceSDK v2: Received audio_start with text:', message.text);
26270
+
26271
+ // NOTE: We do NOT stop current audio here - that only happens on user barge-in (stop_playing)
26272
+ // If audio is already playing, the new sentence will queue and wait for current one to finish
26273
+ // This allows sentences to play sequentially without interruption
26274
+ if (this.audioPlayer && (this.audioPlayer.isPlaying || ((_this$audioPlayer$sch = this.audioPlayer.scheduledSources) === null || _this$audioPlayer$sch === void 0 ? void 0 : _this$audioPlayer$sch.size) > 0)) {
26275
+ console.log('📝 VoiceSDK v2: New sentence received while audio playing - will queue and wait for current sentence to finish');
26276
+ }
25660
26277
  if (message.text && this.audioPlayer) {
25661
26278
  // Use AudioPlayer's transcript sync mechanism
25662
26279
  // AudioPlayer will emit transcriptDisplay when audio actually starts playing (synced with audioContext.currentTime)
26280
+ // If audio is currently playing, markNewSentence will queue this sentence
25663
26281
  this.audioPlayer.markNewSentence(message.text);
25664
26282
  }
25665
26283
  // Also emit as message for other listeners