ttp-agent-sdk 2.34.0 → 2.34.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-widget.dev.js +653 -175
- package/dist/agent-widget.dev.js.map +1 -1
- package/dist/agent-widget.esm.js +1 -1
- package/dist/agent-widget.esm.js.map +1 -1
- package/dist/agent-widget.js +1 -1
- package/dist/agent-widget.js.map +1 -1
- package/dist/demos/widget-customization.html +1464 -198
- package/dist/examples/widget-customization.html +1464 -198
- package/examples/widget-customization.html +1464 -198
- package/package.json +1 -1
package/dist/agent-widget.dev.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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$
|
|
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$
|
|
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
|
-
//
|
|
12876
|
-
//
|
|
12877
|
-
|
|
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
|
-
|
|
12952
|
-
|
|
12953
|
-
|
|
12954
|
-
|
|
12955
|
-
|
|
12956
|
-
|
|
12957
|
-
|
|
12958
|
-
|
|
12959
|
-
|
|
12960
|
-
|
|
12961
|
-
|
|
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$
|
|
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
|
-
|
|
12996
|
-
|
|
12997
|
-
|
|
12998
|
-
|
|
12999
|
-
|
|
13000
|
-
|
|
13001
|
-
|
|
13002
|
-
|
|
13003
|
-
|
|
13004
|
-
|
|
13005
|
-
|
|
13006
|
-
|
|
13007
|
-
|
|
13008
|
-
|
|
13009
|
-
|
|
13010
|
-
|
|
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:
|
|
13013
|
-
|
|
13014
|
-
|
|
13015
|
-
|
|
13016
|
-
|
|
13017
|
-
|
|
13018
|
-
|
|
13019
|
-
|
|
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
|
-
|
|
13046
|
-
|
|
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
|
-
|
|
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 =
|
|
13311
|
-
var translations =
|
|
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
|
|
13318
|
-
var tooltip = (
|
|
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
|
-
|
|
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
|
-
//
|
|
13417
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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 ((
|
|
13457
|
-
var
|
|
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
|
-
|
|
13639
|
+
_this6.voiceInterface.isShowingDomainError = false;
|
|
13461
13640
|
// Reset the connecting state (this will restore normal UI)
|
|
13462
|
-
if ((
|
|
13463
|
-
|
|
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
|
-
|
|
13645
|
+
_this6.showLanding();
|
|
13467
13646
|
return;
|
|
13468
13647
|
}
|
|
13469
|
-
if ((
|
|
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
|
-
|
|
13650
|
+
_this6.showBackButtonWarning();
|
|
13472
13651
|
} else {
|
|
13473
13652
|
// If not active, just show landing
|
|
13474
|
-
|
|
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
|
|
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 (!
|
|
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
|
-
|
|
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
|
-
|
|
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 ((
|
|
13502
|
-
|
|
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
|
|
13686
|
+
return _this6.startVoiceCall();
|
|
13508
13687
|
case 3:
|
|
13509
|
-
if (!((
|
|
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 = (
|
|
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 = (
|
|
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
|
-
|
|
13720
|
+
_this6.currentView = 'voice';
|
|
13542
13721
|
// Ensure voice interface is visible
|
|
13543
|
-
|
|
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 ((
|
|
13551
|
-
|
|
13729
|
+
if ((_this6$voiceInterface8 = _this6.voiceInterface) !== null && _this6$voiceInterface8 !== void 0 && _this6$voiceInterface8.resetConnectingState) {
|
|
13730
|
+
_this6.voiceInterface.resetConnectingState();
|
|
13552
13731
|
}
|
|
13553
|
-
_widgetMode = ((
|
|
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
|
-
|
|
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 ((
|
|
13570
|
-
|
|
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 ((
|
|
13580
|
-
|
|
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
|
-
|
|
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 = ((
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
13938
|
+
var _this7 = this;
|
|
13760
13939
|
document.addEventListener('keydown', function (e) {
|
|
13761
|
-
if (e.key === 'Escape' &&
|
|
13762
|
-
|
|
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
|
|
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
|
-
//
|
|
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 =
|
|
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$
|
|
14077
|
-
mergedConfig.text.sendButtonHint = _objectSpread(_objectSpread({}, (_this$config$
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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$
|
|
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$
|
|
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
|
-
|
|
17475
|
-
|
|
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 (
|
|
18132
|
-
|
|
18133
|
-
|
|
18134
|
-
|
|
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
|
-
|
|
18139
|
-
|
|
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
|
-
|
|
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
|
/**
|
|
@@ -22624,6 +23044,11 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
22624
23044
|
_this.sentenceTimings = []; // [{startTime, text, displayed}, ...]
|
|
22625
23045
|
_this.isCheckingTranscripts = false;
|
|
22626
23046
|
|
|
23047
|
+
// Flag to prevent queuing new audio after stopImmediate() is called (barge-in protection)
|
|
23048
|
+
// This prevents race conditions where audio chunks arrive after stop but before sources are stopped
|
|
23049
|
+
// Cleared when markNewSentence() is called (signals new audio is starting)
|
|
23050
|
+
_this._isStopped = false;
|
|
23051
|
+
|
|
22627
23052
|
// Codec registry
|
|
22628
23053
|
|
|
22629
23054
|
_this.codecs = {
|
|
@@ -22724,6 +23149,12 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
22724
23149
|
key: "playAudio",
|
|
22725
23150
|
value: function playAudio(binaryData) {
|
|
22726
23151
|
var _this2 = this;
|
|
23152
|
+
// CRITICAL: Ignore audio if playback was stopped (barge-in protection)
|
|
23153
|
+
// This prevents overlapping audio when chunks arrive after stopImmediate() is called
|
|
23154
|
+
if (this._isStopped) {
|
|
23155
|
+
console.log('🛑 AudioPlayer: Ignoring audio chunk - playback was stopped (barge-in)');
|
|
23156
|
+
return;
|
|
23157
|
+
}
|
|
22727
23158
|
try {
|
|
22728
23159
|
var audioBlob = this.createAudioBlob(binaryData);
|
|
22729
23160
|
this.audioQueue.push(audioBlob);
|
|
@@ -22758,6 +23189,13 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
22758
23189
|
return _regenerator().w(function (_context) {
|
|
22759
23190
|
while (1) switch (_context.n) {
|
|
22760
23191
|
case 0:
|
|
23192
|
+
if (!this._isStopped) {
|
|
23193
|
+
_context.n = 1;
|
|
23194
|
+
break;
|
|
23195
|
+
}
|
|
23196
|
+
console.log('🛑 AudioPlayer: Ignoring PCM chunk - playback was stopped (barge-in)');
|
|
23197
|
+
return _context.a(2);
|
|
23198
|
+
case 1:
|
|
22761
23199
|
// Pre-process frame immediately (convert to AudioBuffer)
|
|
22762
23200
|
preparedFrame = this.prepareChunk(pcmData);
|
|
22763
23201
|
if (preparedFrame) {
|
|
@@ -22802,7 +23240,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
22802
23240
|
// Emit error event
|
|
22803
23241
|
this.emit('playbackError', new Error('Failed to prepare PCM chunk for playback'));
|
|
22804
23242
|
}
|
|
22805
|
-
case
|
|
23243
|
+
case 2:
|
|
22806
23244
|
return _context.a(2);
|
|
22807
23245
|
}
|
|
22808
23246
|
}, _callee, this);
|
|
@@ -22923,12 +23361,19 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
22923
23361
|
return _regenerator().w(function (_context3) {
|
|
22924
23362
|
while (1) switch (_context3.p = _context3.n) {
|
|
22925
23363
|
case 0:
|
|
22926
|
-
if (!this.
|
|
23364
|
+
if (!this._isStopped) {
|
|
22927
23365
|
_context3.n = 1;
|
|
22928
23366
|
break;
|
|
22929
23367
|
}
|
|
23368
|
+
console.log('🛑 AudioPlayer: Not scheduling frames - playback was stopped (barge-in)');
|
|
22930
23369
|
return _context3.a(2);
|
|
22931
23370
|
case 1:
|
|
23371
|
+
if (!this.isSchedulingFrames) {
|
|
23372
|
+
_context3.n = 2;
|
|
23373
|
+
break;
|
|
23374
|
+
}
|
|
23375
|
+
return _context3.a(2);
|
|
23376
|
+
case 2:
|
|
22932
23377
|
this.isSchedulingFrames = true;
|
|
22933
23378
|
|
|
22934
23379
|
// Schedule multiple frames ahead to ensure continuous playback
|
|
@@ -22940,7 +23385,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
22940
23385
|
if (targetLookaheadFrames === 0 && queuedFrames > 0) {
|
|
22941
23386
|
targetLookaheadFrames = 1; // At least schedule 1 frame
|
|
22942
23387
|
}
|
|
22943
|
-
_context3.p =
|
|
23388
|
+
_context3.p = 3;
|
|
22944
23389
|
// Initialize audio context if needed
|
|
22945
23390
|
|
|
22946
23391
|
if (!this.audioContext) {
|
|
@@ -22951,9 +23396,9 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
22951
23396
|
// This is critical for mobile devices where AudioContext initialization takes time
|
|
22952
23397
|
// Replaces fixed timeouts with event-driven waiting
|
|
22953
23398
|
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 =
|
|
23399
|
+
_context3.n = 4;
|
|
22955
23400
|
return this.waitForAudioContextReady();
|
|
22956
|
-
case
|
|
23401
|
+
case 4:
|
|
22957
23402
|
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
23403
|
|
|
22959
23404
|
// Schedule frames up to target lookahead (ensures smooth playback)
|
|
@@ -23099,22 +23544,22 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
23099
23544
|
}
|
|
23100
23545
|
}, _loop);
|
|
23101
23546
|
});
|
|
23102
|
-
case
|
|
23547
|
+
case 5:
|
|
23103
23548
|
if (!(this.preparedBuffer.length > 0 && scheduledCount < targetLookaheadFrames)) {
|
|
23104
|
-
_context3.n =
|
|
23549
|
+
_context3.n = 8;
|
|
23105
23550
|
break;
|
|
23106
23551
|
}
|
|
23107
|
-
return _context3.d(_regeneratorValues(_loop()),
|
|
23108
|
-
case
|
|
23552
|
+
return _context3.d(_regeneratorValues(_loop()), 6);
|
|
23553
|
+
case 6:
|
|
23109
23554
|
if (!_context3.v) {
|
|
23110
|
-
_context3.n =
|
|
23555
|
+
_context3.n = 7;
|
|
23111
23556
|
break;
|
|
23112
23557
|
}
|
|
23113
|
-
return _context3.a(3,
|
|
23114
|
-
case 6:
|
|
23115
|
-
_context3.n = 4;
|
|
23116
|
-
break;
|
|
23558
|
+
return _context3.a(3, 8);
|
|
23117
23559
|
case 7:
|
|
23560
|
+
_context3.n = 5;
|
|
23561
|
+
break;
|
|
23562
|
+
case 8:
|
|
23118
23563
|
// All prepared frames scheduled, reset flag
|
|
23119
23564
|
|
|
23120
23565
|
this.isSchedulingFrames = false;
|
|
@@ -23154,18 +23599,18 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
23154
23599
|
}
|
|
23155
23600
|
}, 10); // Check every 10ms for new frames
|
|
23156
23601
|
}
|
|
23157
|
-
_context3.n =
|
|
23602
|
+
_context3.n = 10;
|
|
23158
23603
|
break;
|
|
23159
|
-
case
|
|
23160
|
-
_context3.p =
|
|
23604
|
+
case 9:
|
|
23605
|
+
_context3.p = 9;
|
|
23161
23606
|
_t = _context3.v;
|
|
23162
23607
|
console.error('❌ AudioPlayer v2: Error scheduling frames:', _t);
|
|
23163
23608
|
this.emit('playbackError', _t);
|
|
23164
23609
|
this.isSchedulingFrames = false;
|
|
23165
|
-
case
|
|
23610
|
+
case 10:
|
|
23166
23611
|
return _context3.a(2);
|
|
23167
23612
|
}
|
|
23168
|
-
}, _callee2, this, [[
|
|
23613
|
+
}, _callee2, this, [[3, 9]]);
|
|
23169
23614
|
}));
|
|
23170
23615
|
function schedulePreparedFrames() {
|
|
23171
23616
|
return _schedulePreparedFrames.apply(this, arguments);
|
|
@@ -23186,14 +23631,21 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
23186
23631
|
return _regenerator().w(function (_context4) {
|
|
23187
23632
|
while (1) switch (_context4.p = _context4.n) {
|
|
23188
23633
|
case 0:
|
|
23189
|
-
if (!this.
|
|
23634
|
+
if (!this._isStopped) {
|
|
23190
23635
|
_context4.n = 1;
|
|
23191
23636
|
break;
|
|
23192
23637
|
}
|
|
23638
|
+
console.log('🛑 AudioPlayer: Not processing PCM queue - playback was stopped (barge-in)');
|
|
23193
23639
|
return _context4.a(2);
|
|
23194
23640
|
case 1:
|
|
23641
|
+
if (!this.isProcessingPcmQueue) {
|
|
23642
|
+
_context4.n = 2;
|
|
23643
|
+
break;
|
|
23644
|
+
}
|
|
23645
|
+
return _context4.a(2);
|
|
23646
|
+
case 2:
|
|
23195
23647
|
this.isProcessingPcmQueue = true;
|
|
23196
|
-
_context4.p =
|
|
23648
|
+
_context4.p = 3;
|
|
23197
23649
|
// Initialize audio context if needed
|
|
23198
23650
|
|
|
23199
23651
|
if (!this.audioContext) {
|
|
@@ -23203,20 +23655,20 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
23203
23655
|
// ✅ NEW: Wait for AudioContext to be in 'running' state before proceeding
|
|
23204
23656
|
// This is critical for mobile devices where AudioContext initialization takes time
|
|
23205
23657
|
// Replaces fixed timeouts with event-driven waiting
|
|
23206
|
-
_context4.n =
|
|
23658
|
+
_context4.n = 4;
|
|
23207
23659
|
return this.waitForAudioContextReady();
|
|
23208
|
-
case
|
|
23660
|
+
case 4:
|
|
23209
23661
|
if (!(this.pcmChunkQueue.length > 0)) {
|
|
23210
|
-
_context4.n =
|
|
23662
|
+
_context4.n = 6;
|
|
23211
23663
|
break;
|
|
23212
23664
|
}
|
|
23213
23665
|
pcmData = this.pcmChunkQueue.shift();
|
|
23214
23666
|
if (pcmData) {
|
|
23215
|
-
_context4.n =
|
|
23667
|
+
_context4.n = 5;
|
|
23216
23668
|
break;
|
|
23217
23669
|
}
|
|
23218
|
-
return _context4.a(3,
|
|
23219
|
-
case
|
|
23670
|
+
return _context4.a(3, 4);
|
|
23671
|
+
case 5:
|
|
23220
23672
|
// Ensure even byte count for 16-bit PCM
|
|
23221
23673
|
processedData = pcmData;
|
|
23222
23674
|
if (pcmData.byteLength % 2 !== 0) {
|
|
@@ -23308,25 +23760,25 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
23308
23760
|
this.isPlaying = true;
|
|
23309
23761
|
this.emit('playbackStarted');
|
|
23310
23762
|
}
|
|
23311
|
-
_context4.n =
|
|
23763
|
+
_context4.n = 4;
|
|
23312
23764
|
break;
|
|
23313
|
-
case
|
|
23765
|
+
case 6:
|
|
23314
23766
|
// end while loop
|
|
23315
23767
|
|
|
23316
23768
|
// All chunks scheduled, reset processing flag
|
|
23317
23769
|
this.isProcessingPcmQueue = false;
|
|
23318
|
-
_context4.n =
|
|
23770
|
+
_context4.n = 8;
|
|
23319
23771
|
break;
|
|
23320
|
-
case
|
|
23321
|
-
_context4.p =
|
|
23772
|
+
case 7:
|
|
23773
|
+
_context4.p = 7;
|
|
23322
23774
|
_t2 = _context4.v;
|
|
23323
23775
|
console.error('❌ AudioPlayer v2: Error playing chunk:', _t2);
|
|
23324
23776
|
this.emit('playbackError', _t2);
|
|
23325
23777
|
this.isProcessingPcmQueue = false;
|
|
23326
|
-
case
|
|
23778
|
+
case 8:
|
|
23327
23779
|
return _context4.a(2);
|
|
23328
23780
|
}
|
|
23329
|
-
}, _callee3, this, [[
|
|
23781
|
+
}, _callee3, this, [[3, 7]]);
|
|
23330
23782
|
}));
|
|
23331
23783
|
function processPcmQueue() {
|
|
23332
23784
|
return _processPcmQueue.apply(this, arguments);
|
|
@@ -24036,22 +24488,29 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
24036
24488
|
return _regenerator().w(function (_context6) {
|
|
24037
24489
|
while (1) switch (_context6.p = _context6.n) {
|
|
24038
24490
|
case 0:
|
|
24039
|
-
if (!
|
|
24491
|
+
if (!this._isStopped) {
|
|
24040
24492
|
_context6.n = 1;
|
|
24041
24493
|
break;
|
|
24042
24494
|
}
|
|
24495
|
+
console.log('🛑 AudioPlayer: Not processing queue - playback was stopped (barge-in)');
|
|
24043
24496
|
return _context6.a(2);
|
|
24044
24497
|
case 1:
|
|
24498
|
+
if (!(this.isProcessingQueue || this.audioQueue.length === 0)) {
|
|
24499
|
+
_context6.n = 2;
|
|
24500
|
+
break;
|
|
24501
|
+
}
|
|
24502
|
+
return _context6.a(2);
|
|
24503
|
+
case 2:
|
|
24045
24504
|
this.isProcessingQueue = true;
|
|
24046
24505
|
audioBlob = this.audioQueue.shift();
|
|
24047
24506
|
if (audioBlob) {
|
|
24048
|
-
_context6.n =
|
|
24507
|
+
_context6.n = 3;
|
|
24049
24508
|
break;
|
|
24050
24509
|
}
|
|
24051
24510
|
this.isProcessingQueue = false;
|
|
24052
24511
|
return _context6.a(2);
|
|
24053
|
-
case
|
|
24054
|
-
_context6.p =
|
|
24512
|
+
case 3:
|
|
24513
|
+
_context6.p = 3;
|
|
24055
24514
|
wasFirstPlay = !this.isPlaying && this.currentSource === null; // Initialize audio context if needed
|
|
24056
24515
|
if (!this.audioContext) {
|
|
24057
24516
|
this.initializeAudioContext();
|
|
@@ -24060,17 +24519,17 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
24060
24519
|
// ✅ NEW: Wait for AudioContext to be in 'running' state before proceeding
|
|
24061
24520
|
// This is critical for mobile devices where AudioContext initialization takes time
|
|
24062
24521
|
// Replaces fixed timeouts with event-driven waiting
|
|
24063
|
-
_context6.n =
|
|
24522
|
+
_context6.n = 4;
|
|
24064
24523
|
return this.waitForAudioContextReady();
|
|
24065
|
-
case
|
|
24524
|
+
case 4:
|
|
24066
24525
|
audioContext = this.audioContext; // Decode audio
|
|
24067
|
-
_context6.n =
|
|
24526
|
+
_context6.n = 5;
|
|
24068
24527
|
return audioBlob.arrayBuffer();
|
|
24069
|
-
case
|
|
24528
|
+
case 5:
|
|
24070
24529
|
arrayBuffer = _context6.v;
|
|
24071
|
-
_context6.n =
|
|
24530
|
+
_context6.n = 6;
|
|
24072
24531
|
return audioContext.decodeAudioData(arrayBuffer);
|
|
24073
|
-
case
|
|
24532
|
+
case 6:
|
|
24074
24533
|
audioBuffer = _context6.v;
|
|
24075
24534
|
shouldEmitStart = wasFirstPlay && !this.isPlaying && this.currentSource === null; // Create source
|
|
24076
24535
|
source = audioContext.createBufferSource();
|
|
@@ -24114,10 +24573,10 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
24114
24573
|
// Start playback - AudioContext should now be fully ready
|
|
24115
24574
|
|
|
24116
24575
|
source.start();
|
|
24117
|
-
_context6.n =
|
|
24576
|
+
_context6.n = 8;
|
|
24118
24577
|
break;
|
|
24119
|
-
case
|
|
24120
|
-
_context6.p =
|
|
24578
|
+
case 7:
|
|
24579
|
+
_context6.p = 7;
|
|
24121
24580
|
_t3 = _context6.v;
|
|
24122
24581
|
console.error('❌ AudioPlayer v2: Error processing queue:', _t3);
|
|
24123
24582
|
this.currentSource = null;
|
|
@@ -24135,10 +24594,10 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
24135
24594
|
this.isProcessingQueue = false;
|
|
24136
24595
|
this.emit('playbackStopped');
|
|
24137
24596
|
}
|
|
24138
|
-
case
|
|
24597
|
+
case 8:
|
|
24139
24598
|
return _context6.a(2);
|
|
24140
24599
|
}
|
|
24141
|
-
}, _callee5, this, [[
|
|
24600
|
+
}, _callee5, this, [[3, 7]]);
|
|
24142
24601
|
}));
|
|
24143
24602
|
function processQueue() {
|
|
24144
24603
|
return _processQueue.apply(this, arguments);
|
|
@@ -24236,6 +24695,11 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
24236
24695
|
this.isProcessingPcmQueue = false;
|
|
24237
24696
|
this.isSchedulingFrames = false;
|
|
24238
24697
|
|
|
24698
|
+
// CRITICAL: Set stopped flag to prevent new audio from being queued
|
|
24699
|
+
// This prevents race conditions where audio chunks arrive after stop but before sources are stopped
|
|
24700
|
+
// The flag will be cleared when markNewSentence() is called (signals new audio is starting)
|
|
24701
|
+
this._isStopped = true;
|
|
24702
|
+
|
|
24239
24703
|
// Reset scheduling properties
|
|
24240
24704
|
|
|
24241
24705
|
this.nextStartTime = 0;
|
|
@@ -24259,6 +24723,12 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
24259
24723
|
}, {
|
|
24260
24724
|
key: "markNewSentence",
|
|
24261
24725
|
value: function markNewSentence(text) {
|
|
24726
|
+
// CRITICAL: Clear stopped flag when new audio starts
|
|
24727
|
+
// This allows new audio chunks to be queued after barge-in
|
|
24728
|
+
if (this._isStopped) {
|
|
24729
|
+
console.log('🛑 AudioPlayer: Clearing stopped flag - new audio starting');
|
|
24730
|
+
this._isStopped = false;
|
|
24731
|
+
}
|
|
24262
24732
|
this.pendingSentenceText = text;
|
|
24263
24733
|
console.log("\uD83D\uDCDD AudioPlayer: New sentence marked: \"".concat(text.substring(0, 40), "...\""));
|
|
24264
24734
|
}
|
|
@@ -25578,7 +26048,8 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
25578
26048
|
}, {
|
|
25579
26049
|
key: "handleMessage",
|
|
25580
26050
|
value: function handleMessage(event) {
|
|
25581
|
-
var
|
|
26051
|
+
var _this$audioPlayer$sch,
|
|
26052
|
+
_this7 = this;
|
|
25582
26053
|
// Binary message (audio data)
|
|
25583
26054
|
|
|
25584
26055
|
if (event.data instanceof ArrayBuffer || event.data instanceof Blob) {
|
|
@@ -25657,6 +26128,13 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
25657
26128
|
// Backend sends audio_start with transcript text before audio chunks
|
|
25658
26129
|
// Store the text in AudioPlayer for synced display when audio actually starts playing
|
|
25659
26130
|
console.log('📝 VoiceSDK v2: Received audio_start with text:', message.text);
|
|
26131
|
+
|
|
26132
|
+
// CRITICAL: Stop any currently playing audio when new sentence starts
|
|
26133
|
+
// This prevents overlapping audio from multiple sentences playing simultaneously
|
|
26134
|
+
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)) {
|
|
26135
|
+
console.log('🛑 VoiceSDK v2: Stopping current audio playback - new sentence starting');
|
|
26136
|
+
this.audioPlayer.stopImmediate();
|
|
26137
|
+
}
|
|
25660
26138
|
if (message.text && this.audioPlayer) {
|
|
25661
26139
|
// Use AudioPlayer's transcript sync mechanism
|
|
25662
26140
|
// AudioPlayer will emit transcriptDisplay when audio actually starts playing (synced with audioContext.currentTime)
|