ttp-agent-sdk 2.40.0 → 2.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9707,6 +9707,30 @@ function buildAudioConstraints(sampleRate) {
9707
9707
  }
9708
9708
  return _objectSpread(_objectSpread({}, base), userOverrides);
9709
9709
  }
9710
+
9711
+ /**
9712
+ * Linear PCM16 resample (main thread). Safari/iOS often runs AudioContext at 44.1/48 kHz
9713
+ * while the voice server expects hello_ack inputSampleRate (e.g. 16 kHz).
9714
+ */
9715
+ function resamplePCM16Linear(input, fromRate, toRate) {
9716
+ if (!input || input.length === 0 || fromRate === toRate) {
9717
+ return input;
9718
+ }
9719
+ var ratio = fromRate / toRate;
9720
+ var outLength = Math.max(1, Math.floor(input.length / ratio));
9721
+ var output = new Int16Array(outLength);
9722
+ for (var i = 0; i < outLength; i++) {
9723
+ var srcPos = i * ratio;
9724
+ var i0 = Math.floor(srcPos);
9725
+ var i1 = Math.min(i0 + 1, input.length - 1);
9726
+ var frac = srcPos - i0;
9727
+ var s0 = input[i0];
9728
+ var s1 = input[i1];
9729
+ var s = s0 + (s1 - s0) * frac;
9730
+ output[i] = Math.max(-32768, Math.min(32767, Math.round(s)));
9731
+ }
9732
+ return output;
9733
+ }
9710
9734
  var _sharedRecorderContext = null;
9711
9735
  var _sharedRecorderSampleRate = null;
9712
9736
  var _sharedRecorderWorkletLoaded = false;
@@ -9719,6 +9743,7 @@ var AudioRecorder = /*#__PURE__*/function (_EventEmitter) {
9719
9743
  _this.config = config;
9720
9744
  _this.audioContext = null;
9721
9745
  _this.audioWorkletNode = null;
9746
+ _this._recorderSinkGain = null;
9722
9747
  _this.mediaStream = null;
9723
9748
  _this.isRecording = false;
9724
9749
  _this._starting = false;
@@ -9923,6 +9948,8 @@ var AudioRecorder = /*#__PURE__*/function (_EventEmitter) {
9923
9948
  _isConnected2,
9924
9949
  _error2,
9925
9950
  source,
9951
+ negotiatedRate,
9952
+ contextRate,
9926
9953
  userMessage,
9927
9954
  _permissionState,
9928
9955
  enhancedError,
@@ -10129,16 +10156,34 @@ var AudioRecorder = /*#__PURE__*/function (_EventEmitter) {
10129
10156
  source = this.audioContext.createMediaStreamSource(this.mediaStream);
10130
10157
  source.connect(this.audioWorkletNode);
10131
10158
 
10159
+ // WebKit/iOS: a graph that dead-ends at an AudioWorkletNode may not be pulled; force a
10160
+ // silent sink so the worklet process() runs reliably (no audible output).
10161
+ this._recorderSinkGain = this.audioContext.createGain();
10162
+ this._recorderSinkGain.gain.value = 0;
10163
+ this.audioWorkletNode.connect(this._recorderSinkGain);
10164
+ this._recorderSinkGain.connect(this.audioContext.destination);
10165
+
10132
10166
  // Store source reference so we can disconnect it when stopping
10133
10167
  this.mediaStreamSource = source;
10168
+ negotiatedRate = this.config.sampleRate || 16000;
10169
+ contextRate = this.audioContext.sampleRate;
10170
+ if (Math.abs(contextRate - negotiatedRate) > 1) {
10171
+ console.log("\u2139\uFE0F AudioRecorder: Context sample rate ".concat(contextRate, "Hz \u2260 negotiated uplink ").concat(negotiatedRate, "Hz \u2014 resampling in main thread"));
10172
+ }
10134
10173
 
10135
10174
  // Handle messages from AudioWorklet
10136
10175
  this.audioWorkletNode.port.onmessage = function (event) {
10137
- var _event$data = event.data,
10138
- type = _event$data.type,
10139
- data = _event$data.data;
10176
+ var payload = event.data;
10177
+ var type = payload.type,
10178
+ data = payload.data;
10140
10179
  if (type === 'pcm_audio_data') {
10141
- _this2.emit('audioData', data);
10180
+ var chunkRate = payload.sampleRate || contextRate;
10181
+ var targetRate = _this2.config.sampleRate || 16000;
10182
+ if (chunkRate && targetRate && Math.abs(chunkRate - targetRate) > 1) {
10183
+ _this2.emit('audioData', resamplePCM16Linear(data, chunkRate, targetRate));
10184
+ } else {
10185
+ _this2.emit('audioData', data);
10186
+ }
10142
10187
  }
10143
10188
  };
10144
10189
 
@@ -10285,6 +10330,15 @@ var AudioRecorder = /*#__PURE__*/function (_EventEmitter) {
10285
10330
  console.log('⚠️ AudioRecorder: AudioWorkletNode already disconnected');
10286
10331
  }
10287
10332
  case 4:
10333
+ if (this._recorderSinkGain) {
10334
+ try {
10335
+ this._recorderSinkGain.disconnect();
10336
+ } catch (e) {
10337
+ /* ignore */
10338
+ }
10339
+ this._recorderSinkGain = null;
10340
+ }
10341
+
10288
10342
  // Stop media stream tracks (this stops microphone access)
10289
10343
  if (this.mediaStream) {
10290
10344
  console.log('🛑 AudioRecorder: Stopping media stream tracks...');
@@ -10432,6 +10486,78 @@ var AudioRecorder = /*#__PURE__*/function (_EventEmitter) {
10432
10486
  _sharedRecorderWorkletLoaded = false;
10433
10487
  _sharedRecorderWorkletPath = null;
10434
10488
  }
10489
+
10490
+ /**
10491
+ * Create or resume the shared recorder AudioContext during the user-gesture window (e.g. right
10492
+ * after getUserMedia on mobile). Reduces iOS failures when recording starts only after a long
10493
+ * async WebSocket / hello_ack wait.
10494
+ */
10495
+ }, {
10496
+ key: "primeSharedContext",
10497
+ value: (function () {
10498
+ var _primeSharedContext = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee7() {
10499
+ var sampleRateHint,
10500
+ rate,
10501
+ ctx,
10502
+ _args7 = arguments,
10503
+ _t7;
10504
+ return _regenerator().w(function (_context7) {
10505
+ while (1) switch (_context7.p = _context7.n) {
10506
+ case 0:
10507
+ sampleRateHint = _args7.length > 0 && _args7[0] !== undefined ? _args7[0] : 16000;
10508
+ if (!(typeof window === 'undefined')) {
10509
+ _context7.n = 1;
10510
+ break;
10511
+ }
10512
+ return _context7.a(2);
10513
+ case 1:
10514
+ rate = sampleRateHint || 16000;
10515
+ _context7.p = 2;
10516
+ if (!(_sharedRecorderContext && _sharedRecorderContext.state !== 'closed')) {
10517
+ _context7.n = 4;
10518
+ break;
10519
+ }
10520
+ if (!(_sharedRecorderContext.state === 'suspended')) {
10521
+ _context7.n = 3;
10522
+ break;
10523
+ }
10524
+ _context7.n = 3;
10525
+ return _sharedRecorderContext.resume();
10526
+ case 3:
10527
+ console.log('♻️ AudioRecorder.primeSharedContext: reused context', _sharedRecorderContext.sampleRate, 'Hz');
10528
+ return _context7.a(2);
10529
+ case 4:
10530
+ ctx = new (window.AudioContext || window.webkitAudioContext)({
10531
+ sampleRate: rate
10532
+ });
10533
+ _sharedRecorderContext = ctx;
10534
+ _sharedRecorderSampleRate = rate;
10535
+ _sharedRecorderWorkletLoaded = false;
10536
+ _sharedRecorderWorkletPath = null;
10537
+ if (!(ctx.state === 'suspended')) {
10538
+ _context7.n = 5;
10539
+ break;
10540
+ }
10541
+ _context7.n = 5;
10542
+ return ctx.resume();
10543
+ case 5:
10544
+ console.log('🎵 AudioRecorder.primeSharedContext: primed requested', rate, 'Hz, actual', ctx.sampleRate, 'Hz');
10545
+ _context7.n = 7;
10546
+ break;
10547
+ case 6:
10548
+ _context7.p = 6;
10549
+ _t7 = _context7.v;
10550
+ console.warn('⚠️ AudioRecorder.primeSharedContext failed (non-fatal):', _t7);
10551
+ case 7:
10552
+ return _context7.a(2);
10553
+ }
10554
+ }, _callee7, null, [[2, 6]]);
10555
+ }));
10556
+ function primeSharedContext() {
10557
+ return _primeSharedContext.apply(this, arguments);
10558
+ }
10559
+ return primeSharedContext;
10560
+ }())
10435
10561
  }]);
10436
10562
  }(_EventEmitter_js__WEBPACK_IMPORTED_MODULE_0__["default"]);
10437
10563
 
@@ -15645,8 +15771,22 @@ var FLAVORS = {
15645
15771
  restaurants: _restaurants_js__WEBPACK_IMPORTED_MODULE_2__.createRestaurantsFlavor,
15646
15772
  tours: _tours_js__WEBPACK_IMPORTED_MODULE_3__.createToursFlavor
15647
15773
  };
15774
+
15775
+ /** Common client typos / aliases → canonical keys in FLAVORS */
15776
+ var FLAVOR_ALIASES = {
15777
+ resturants: 'restaurants'
15778
+ };
15779
+
15780
+ /**
15781
+ * Resolve a widget flavor name to a registered factory.
15782
+ * Accepts case-insensitive keys and known aliases (e.g. resturants → restaurants).
15783
+ */
15648
15784
  function loadFlavor(name) {
15649
- return FLAVORS[name] || null;
15785
+ if (name == null || typeof name !== 'string') {
15786
+ return null;
15787
+ }
15788
+ var key = FLAVOR_ALIASES[name.trim().toLowerCase()] || name.trim().toLowerCase();
15789
+ return FLAVORS[key] || null;
15650
15790
  }
15651
15791
 
15652
15792
  /***/ }),
@@ -17324,8 +17464,8 @@ __webpack_require__.r(__webpack_exports__);
17324
17464
 
17325
17465
 
17326
17466
  // Version - injected at build time from package.json via webpack DefinePlugin
17327
- var VERSION = "2.40.0";
17328
- var BUILD_TIME = "2026-03-25T07:23:14.569Z";
17467
+ var VERSION = "2.43.0";
17468
+ var BUILD_TIME = "2026-03-26T01:57:03.238Z";
17329
17469
  console.log("%c TTP Agent SDK v".concat(VERSION, " (").concat(BUILD_TIME, ") "), 'background: #4f46e5; color: white; font-size: 12px; font-weight: bold; padding: 2px 6px; border-radius: 4px;');
17330
17470
 
17331
17471
  // Named exports
@@ -18376,7 +18516,8 @@ __webpack_require__.r(__webpack_exports__);
18376
18516
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
18377
18517
  /* harmony export */ showBlockedModal: () => (/* binding */ showBlockedModal),
18378
18518
  /* harmony export */ showNoMicrophoneModal: () => (/* binding */ showNoMicrophoneModal),
18379
- /* harmony export */ showPrePromptModal: () => (/* binding */ showPrePromptModal)
18519
+ /* harmony export */ showPrePromptModal: () => (/* binding */ showPrePromptModal),
18520
+ /* harmony export */ showServerDisclaimerModal: () => (/* binding */ showServerDisclaimerModal)
18380
18521
  /* harmony export */ });
18381
18522
  /* harmony import */ var _MicPermissionUtils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./MicPermissionUtils.js */ "./src/shared/MicPermissionUtils.js");
18382
18523
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
@@ -18538,6 +18679,7 @@ var MicPermissionModal = /*#__PURE__*/function () {
18538
18679
  value: function createOverlay() {
18539
18680
  var overlay = document.createElement('div');
18540
18681
  overlay.className = 'mic-permission-overlay';
18682
+ overlay.setAttribute('dir', 'ltr');
18541
18683
  overlay.style.cssText = "\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.6);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 100001;\n padding: 20px;\n animation: mic-fadeIn 0.2s ease-out;\n ";
18542
18684
 
18543
18685
  // Add fade-in animation if not already added
@@ -18558,7 +18700,7 @@ var MicPermissionModal = /*#__PURE__*/function () {
18558
18700
  }
18559
18701
  var style = document.createElement('style');
18560
18702
  style.id = 'mic-permission-styles';
18561
- style.textContent = "\n @keyframes mic-fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n \n @keyframes mic-slideUp {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n \n @keyframes mic-bounce {\n 0%, 100% { transform: translateY(0); }\n 50% { transform: translateY(-5px); }\n }\n \n .mic-permission-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.6);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 100001;\n padding: 20px;\n animation: mic-fadeIn 0.2s ease-out;\n }\n \n .mic-permission-modal {\n background: #ffffff;\n border-radius: 16px;\n box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);\n max-width: 480px;\n width: 100%;\n padding: 32px;\n position: relative;\n animation: mic-slideUp 0.3s ease-out;\n max-height: 90vh;\n overflow-y: auto;\n }\n \n .mic-permission-modal__close {\n position: absolute;\n top: 16px;\n right: 16px;\n background: none;\n border: none;\n font-size: 20px;\n cursor: pointer;\n color: #6b7280;\n width: 32px;\n height: 32px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.2s;\n }\n \n .mic-permission-modal__close:hover {\n background: #e5e7eb;\n }\n \n .mic-permission-modal__icon {\n font-size: 48px;\n text-align: center;\n margin-bottom: 16px;\n }\n \n .mic-permission-modal__title {\n font-size: 24px;\n font-weight: 700;\n color: #111827;\n margin: 0 0 12px;\n line-height: 1.3;\n text-align: center;\n }\n \n .mic-permission-modal__description {\n color: #6b7280;\n font-size: 16px;\n line-height: 1.6;\n margin: 0 0 20px;\n text-align: center;\n }\n \n .mic-permission-modal__highlight {\n display: flex;\n align-items: center;\n gap: 12px;\n background: linear-gradient(135deg, #dbeafe, #ede9fe);\n padding: 16px 20px;\n border-radius: 8px;\n margin-bottom: 20px;\n border: 1px solid #bfdbfe;\n }\n \n .mic-permission-modal__highlight-icon {\n font-size: 24px;\n animation: mic-bounce 1s infinite;\n }\n \n .mic-permission-modal__status {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n background: #fef2f2;\n color: #ef4444;\n padding: 12px 16px;\n border-radius: 8px;\n margin-bottom: 20px;\n font-weight: 500;\n }\n \n .mic-permission-modal__note {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n background: #fffbeb;\n color: #92400e;\n padding: 12px 16px;\n border-radius: 8px;\n margin-bottom: 20px;\n font-size: 14px;\n line-height: 1.5;\n border: 1px solid #fde68a;\n }\n \n .mic-permission-modal__steps {\n margin-bottom: 20px;\n }\n \n .mic-permission-modal__steps h3 {\n font-size: 14px;\n font-weight: 600;\n color: #6b7280;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin: 0 0 12px;\n }\n \n .mic-permission-modal__steps ol {\n margin: 0;\n padding-left: 24px;\n counter-reset: step-counter;\n list-style: none;\n }\n \n .mic-permission-modal__steps li {\n position: relative;\n padding: 12px 0 12px 16px;\n border-left: 2px solid #e5e7eb;\n color: #111827;\n font-size: 15px;\n line-height: 1.5;\n counter-increment: step-counter;\n }\n \n .mic-permission-modal__steps li::before {\n content: counter(step-counter);\n position: absolute;\n left: -14px;\n top: 10px;\n width: 24px;\n height: 24px;\n background: #4f46e5;\n color: white;\n border-radius: 50%;\n font-size: 12px;\n font-weight: 600;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n \n .mic-permission-modal__steps li:last-child {\n border-left-color: transparent;\n }\n \n .mic-permission-modal__actions {\n display: flex;\n flex-direction: column;\n gap: 10px;\n margin-top: 24px;\n }\n \n .mic-permission-modal__btn {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 14px 24px;\n border-radius: 8px;\n font-size: 16px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s;\n border: none;\n width: 100%;\n }\n \n .mic-permission-modal__btn--primary {\n background: #4f46e5;\n color: white;\n }\n \n .mic-permission-modal__btn--primary:hover {\n background: #4338ca;\n transform: translateY(-1px);\n }\n \n .mic-permission-modal__btn--secondary {\n background: #e5e7eb;\n color: #111827;\n }\n \n .mic-permission-modal__btn--secondary:hover {\n background: #d1d5db;\n }\n \n .mic-permission-modal__footer {\n text-align: center;\n font-size: 13px;\n color: #6b7280;\n margin-top: 20px;\n margin-bottom: 0;\n }\n \n .mic-permission-modal__visual-guide {\n width: 100%;\n max-width: 380px;\n height: auto;\n margin: 20px auto;\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n display: block;\n }\n \n .mic-permission-modal__visual-guide-container {\n text-align: center;\n margin: 20px 0;\n }\n \n @media (max-width: 480px) {\n .mic-permission-modal {\n padding: 24px 20px;\n margin: 10px;\n max-height: 85vh;\n }\n \n .mic-permission-modal__title {\n font-size: 20px;\n }\n \n .mic-permission-modal__icon {\n font-size: 40px;\n }\n \n .mic-permission-modal__visual-guide {\n max-width: 100%;\n }\n }\n \n /* Mobile pre-prompt: compact, action-first layout - buttons always visible above safe area */\n .mic-permission-modal--mobile {\n max-height: none;\n padding: 20px 20px 24px;\n padding-bottom: max(24px, env(safe-area-inset-bottom, 24px));\n margin: 12px;\n align-self: flex-end;\n }\n \n .mic-permission-modal--mobile .mic-permission-modal__icon {\n font-size: 36px;\n margin-bottom: 12px;\n }\n \n .mic-permission-modal--mobile .mic-permission-modal__title {\n font-size: 18px;\n margin-bottom: 8px;\n }\n \n .mic-permission-modal--mobile .mic-permission-modal__description {\n font-size: 14px;\n margin-bottom: 12px;\n line-height: 1.5;\n }\n \n .mic-permission-modal--mobile .mic-permission-modal__highlight {\n padding: 12px 16px;\n margin-bottom: 12px;\n font-size: 14px;\n }\n \n .mic-permission-modal--mobile .mic-permission-modal__note {\n padding: 10px 14px;\n margin-bottom: 16px;\n font-size: 13px;\n }\n \n .mic-permission-modal--mobile .mic-permission-modal__actions {\n margin-top: 16px;\n gap: 10px;\n }\n \n .mic-permission-modal--mobile .mic-permission-modal__btn {\n padding: 16px 24px;\n font-size: 16px;\n min-height: 48px;\n }\n ";
18703
+ style.textContent = "\n @keyframes mic-fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n \n @keyframes mic-slideUp {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n \n @keyframes mic-bounce {\n 0%, 100% { transform: translateY(0); }\n 50% { transform: translateY(-5px); }\n }\n \n /* direction ltr: host page may be RTL (e.g. Hebrew); keep overlay + modal English copy readable */\n .mic-permission-overlay {\n position: fixed;\n inset: 0;\n direction: ltr;\n background: rgba(0, 0, 0, 0.6);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 100001;\n padding: 20px;\n animation: mic-fadeIn 0.2s ease-out;\n }\n \n .mic-permission-modal {\n direction: ltr;\n unicode-bidi: isolate;\n background: #ffffff;\n border-radius: 16px;\n box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);\n max-width: 480px;\n width: 100%;\n padding: 32px;\n position: relative;\n animation: mic-slideUp 0.3s ease-out;\n max-height: 90vh;\n overflow-y: auto;\n }\n \n .mic-permission-modal__close {\n position: absolute;\n top: 16px;\n right: 16px;\n background: none;\n border: none;\n font-size: 20px;\n cursor: pointer;\n color: #6b7280;\n width: 32px;\n height: 32px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.2s;\n }\n \n .mic-permission-modal__close:hover {\n background: #e5e7eb;\n }\n \n .mic-permission-modal__icon {\n font-size: 48px;\n text-align: center;\n margin-bottom: 16px;\n }\n \n .mic-permission-modal__title {\n font-size: 24px;\n font-weight: 700;\n color: #111827;\n margin: 0 0 12px;\n line-height: 1.3;\n text-align: center;\n }\n \n .mic-permission-modal__description {\n color: #6b7280;\n font-size: 16px;\n line-height: 1.6;\n margin: 0 0 20px;\n text-align: center;\n }\n \n .mic-permission-modal__highlight {\n display: flex;\n align-items: center;\n gap: 12px;\n background: linear-gradient(135deg, #dbeafe, #ede9fe);\n padding: 16px 20px;\n border-radius: 8px;\n margin-bottom: 20px;\n border: 1px solid #bfdbfe;\n }\n \n .mic-permission-modal__highlight-icon {\n font-size: 24px;\n animation: mic-bounce 1s infinite;\n }\n \n .mic-permission-modal__status {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n background: #fef2f2;\n color: #ef4444;\n padding: 12px 16px;\n border-radius: 8px;\n margin-bottom: 20px;\n font-weight: 500;\n }\n \n .mic-permission-modal__note {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n background: #fffbeb;\n color: #92400e;\n padding: 12px 16px;\n border-radius: 8px;\n margin-bottom: 20px;\n font-size: 14px;\n line-height: 1.5;\n border: 1px solid #fde68a;\n }\n \n .mic-permission-modal__steps {\n margin-bottom: 20px;\n }\n \n .mic-permission-modal__steps h3 {\n font-size: 14px;\n font-weight: 600;\n color: #6b7280;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin: 0 0 12px;\n }\n \n .mic-permission-modal__steps ol {\n margin: 0;\n padding-left: 24px;\n counter-reset: step-counter;\n list-style: none;\n }\n \n .mic-permission-modal__steps li {\n position: relative;\n padding: 12px 0 12px 16px;\n border-left: 2px solid #e5e7eb;\n color: #111827;\n font-size: 15px;\n line-height: 1.5;\n counter-increment: step-counter;\n }\n \n .mic-permission-modal__steps li::before {\n content: counter(step-counter);\n position: absolute;\n left: -14px;\n top: 10px;\n width: 24px;\n height: 24px;\n background: #4f46e5;\n color: white;\n border-radius: 50%;\n font-size: 12px;\n font-weight: 600;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n \n .mic-permission-modal__steps li:last-child {\n border-left-color: transparent;\n }\n \n .mic-permission-modal__actions {\n display: flex;\n flex-direction: column;\n gap: 10px;\n margin-top: 24px;\n }\n \n .mic-permission-modal__btn {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 14px 24px;\n border-radius: 8px;\n font-size: 16px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s;\n border: none;\n width: 100%;\n }\n \n .mic-permission-modal__btn--primary {\n background: #4f46e5;\n color: white;\n }\n \n .mic-permission-modal__btn--primary:hover {\n background: #4338ca;\n transform: translateY(-1px);\n }\n \n .mic-permission-modal__btn--secondary {\n background: #e5e7eb;\n color: #111827;\n }\n \n .mic-permission-modal__btn--secondary:hover {\n background: #d1d5db;\n }\n \n .mic-permission-modal__footer {\n text-align: center;\n font-size: 13px;\n color: #6b7280;\n margin-top: 20px;\n margin-bottom: 0;\n }\n \n .mic-permission-modal__visual-guide {\n width: 100%;\n max-width: 380px;\n height: auto;\n margin: 20px auto;\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n display: block;\n }\n \n .mic-permission-modal__visual-guide-container {\n text-align: center;\n margin: 20px 0;\n }\n \n @media (max-width: 480px) {\n .mic-permission-modal {\n padding: 24px 20px;\n margin: 10px;\n max-height: 85vh;\n }\n \n .mic-permission-modal__title {\n font-size: 20px;\n }\n \n .mic-permission-modal__icon {\n font-size: 40px;\n }\n \n .mic-permission-modal__visual-guide {\n max-width: 100%;\n }\n }\n \n /* Mobile pre-prompt: compact, action-first layout - buttons always visible above safe area */\n .mic-permission-modal--mobile {\n max-height: none;\n padding: 20px 20px 24px;\n padding-bottom: max(24px, env(safe-area-inset-bottom, 24px));\n margin: 12px;\n align-self: flex-end;\n }\n \n .mic-permission-modal--mobile .mic-permission-modal__icon {\n font-size: 36px;\n margin-bottom: 12px;\n }\n \n .mic-permission-modal--mobile .mic-permission-modal__title {\n font-size: 18px;\n margin-bottom: 8px;\n }\n \n .mic-permission-modal--mobile .mic-permission-modal__description {\n font-size: 14px;\n margin-bottom: 12px;\n line-height: 1.5;\n }\n \n .mic-permission-modal--mobile .mic-permission-modal__highlight {\n padding: 12px 16px;\n margin-bottom: 12px;\n font-size: 14px;\n }\n \n .mic-permission-modal--mobile .mic-permission-modal__note {\n padding: 10px 14px;\n margin-bottom: 16px;\n font-size: 13px;\n }\n \n .mic-permission-modal--mobile .mic-permission-modal__actions {\n margin-top: 16px;\n gap: 10px;\n }\n \n .mic-permission-modal--mobile .mic-permission-modal__btn {\n padding: 16px 24px;\n font-size: 16px;\n min-height: 48px;\n }\n ";
18562
18704
  document.head.appendChild(style);
18563
18705
  }
18564
18706
 
@@ -18914,6 +19056,52 @@ function showNoMicrophoneModal(onClose) {
18914
19056
  return modal;
18915
19057
  }
18916
19058
 
19059
+ /**
19060
+ * Server-driven disclaimer (legal copy from backend hello_ack). Plain text only.
19061
+ */
19062
+ function showServerDisclaimerModal(_ref) {
19063
+ var texts = _ref.texts,
19064
+ onAccept = _ref.onAccept,
19065
+ onCancel = _ref.onCancel;
19066
+ var modal = new MicPermissionModal();
19067
+ var overlay = modal.createOverlay();
19068
+ overlay.style.background = 'rgba(0, 0, 0, 0.5)';
19069
+ overlay.style.backdropFilter = 'blur(2px)';
19070
+ var isMobile = isMobileDevice();
19071
+ var modalDiv = document.createElement('div');
19072
+ modalDiv.className = 'mic-permission-modal' + (isMobile ? ' mic-permission-modal--mobile' : '');
19073
+ var lines = (texts || []).map(function (t) {
19074
+ return String(t).trim();
19075
+ }).filter(Boolean);
19076
+ var body = lines.length ? lines.join('\n\n') : 'Please confirm to continue.';
19077
+ var safe = body.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
19078
+ modalDiv.innerHTML = "\n <h2 class=\"mic-permission-modal__title\">Notice</h2>\n <div class=\"mic-permission-modal__description\" style=\"white-space:pre-wrap;max-height:50vh;overflow:auto;text-align:left;font-size:15px;line-height:1.5;\">".concat(safe, "</div>\n <div class=\"mic-permission-modal__actions\">\n <button type=\"button\" class=\"mic-permission-modal__btn mic-permission-modal__btn--primary\" data-action=\"accept\">Accept</button>\n <button type=\"button\" class=\"mic-permission-modal__btn mic-permission-modal__btn--secondary\" data-action=\"cancel\">Decline</button>\n </div>\n ");
19079
+ if (isMobile) {
19080
+ overlay.style.alignItems = 'flex-end';
19081
+ overlay.style.paddingBottom = 'max(20px, env(safe-area-inset-bottom, 20px))';
19082
+ overlay.style.paddingTop = '20px';
19083
+ }
19084
+ overlay.appendChild(modalDiv);
19085
+ modal.overlay = overlay;
19086
+ modal.modal = modalDiv;
19087
+ modalDiv.querySelector('[data-action="accept"]').addEventListener('click', function () {
19088
+ modal.close();
19089
+ onAccept();
19090
+ });
19091
+ modalDiv.querySelector('[data-action="cancel"]').addEventListener('click', function () {
19092
+ modal.close();
19093
+ onCancel();
19094
+ });
19095
+ overlay.addEventListener('click', function (e) {
19096
+ if (e.target === overlay) {
19097
+ modal.close();
19098
+ onCancel();
19099
+ }
19100
+ });
19101
+ modal.show();
19102
+ return modal;
19103
+ }
19104
+
18917
19105
  /***/ }),
18918
19106
 
18919
19107
  /***/ "./src/shared/MicPermissionUtils.js":
@@ -18928,7 +19116,8 @@ __webpack_require__.r(__webpack_exports__);
18928
19116
  /* harmony export */ checkPermissionState: () => (/* binding */ checkPermissionState),
18929
19117
  /* harmony export */ getDeviceInfo: () => (/* binding */ getDeviceInfo),
18930
19118
  /* harmony export */ getPermissionInstructions: () => (/* binding */ getPermissionInstructions),
18931
- /* harmony export */ openSettings: () => (/* binding */ openSettings)
19119
+ /* harmony export */ openSettings: () => (/* binding */ openSettings),
19120
+ /* harmony export */ shouldUseMobileVoiceCallUI: () => (/* binding */ shouldUseMobileVoiceCallUI)
18932
19121
  /* harmony export */ });
18933
19122
  function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i.return) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
18934
19123
  function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
@@ -18996,6 +19185,28 @@ function getDeviceInfo() {
18996
19185
  };
18997
19186
  }
18998
19187
 
19188
+ /**
19189
+ * Use the compact mobile voice-call UI (minimized bar + transcript overlay).
19190
+ * Native iOS/Android always use it. Other cases: viewport ≤768px and touch/coarse pointer
19191
+ * (in-app browsers, Instagram/Facebook WebViews with desktop UA, etc.).
19192
+ */
19193
+ function shouldUseMobileVoiceCallUI() {
19194
+ var _getDeviceInfo = getDeviceInfo(),
19195
+ isIOS = _getDeviceInfo.isIOS,
19196
+ isAndroid = _getDeviceInfo.isAndroid;
19197
+ if (isIOS || isAndroid) return true;
19198
+ if (typeof window === 'undefined') return false;
19199
+ if (window.innerWidth > 768) return false;
19200
+ var touchCapable = navigator.maxTouchPoints > 0;
19201
+ var coarsePointer = false;
19202
+ try {
19203
+ coarsePointer = window.matchMedia('(pointer: coarse)').matches;
19204
+ } catch (_) {
19205
+ /* matchMedia unsupported */
19206
+ }
19207
+ return touchCapable || coarsePointer;
19208
+ }
19209
+
18999
19210
  /**
19000
19211
  * Check microphone permission state using Permissions API
19001
19212
  * Returns 'granted', 'denied', 'prompt', or 'unknown'
@@ -23541,6 +23752,9 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
23541
23752
  * - 'dataInjected' - Data injection successfully acknowledged by server
23542
23753
  *
23543
23754
  * - 'dataInjectionError' - Data injection failed (validation, timeout, or server error)
23755
+ *
23756
+ * - 'disclaimersRequired' - Server requires disclaimer acknowledgement (payload: texts, disclaimersHash, ...)
23757
+ * - 'disclaimerRejected' - Server closed or rejected disclaimer ({ code, message })
23544
23758
 
23545
23759
  */
23546
23760
  var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
@@ -23609,6 +23823,18 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
23609
23823
  _this.hasEverConnected = false; // Track if we've successfully connected at least once
23610
23824
 
23611
23825
  _this.helloAckReceived = false;
23826
+
23827
+ /** When true, server hello_ack requires disclaimer_ack before STT/greeting; block recording until cleared */
23828
+ _this.disclaimersPending = false;
23829
+
23830
+ /** Server copy hash (SHA-256) echoed in disclaimer_ack */
23831
+ _this.disclaimersHash = null;
23832
+
23833
+ /** Last server disclaimer payload (for UI) */
23834
+ _this.lastDisclaimerPayload = null;
23835
+
23836
+ /** Set when hangup() runs with an open socket — skip resume-key clear in destroy() */
23837
+ _this._gracefulHangupInitiated = false;
23612
23838
  _this.isRecording = false;
23613
23839
  _this.isPlaying = false;
23614
23840
  _this.isDestroyed = false;
@@ -24379,6 +24605,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
24379
24605
  console.log('🔌 VoiceSDK v2: WebSocket closed:', event.code, event.reason);
24380
24606
  _this6.isConnected = false;
24381
24607
  _this6.helloAckReceived = false;
24608
+ _this6.disclaimersPending = false;
24382
24609
 
24383
24610
  // Stop recording if active
24384
24611
 
@@ -24566,7 +24793,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
24566
24793
 
24567
24794
  // Include SDK build time for debugging
24568
24795
  if (true) {
24569
- helloMessage.lastBuildTime = "2026-03-25T07:23:14.569Z";
24796
+ helloMessage.lastBuildTime = "2026-03-26T01:57:03.238Z";
24570
24797
  }
24571
24798
 
24572
24799
  // TEMPORARILY DISABLED: Always attach page context - backend decides what to use
@@ -24698,6 +24925,19 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
24698
24925
  this.emit('message', message);
24699
24926
  break;
24700
24927
  case 'error':
24928
+ if (message.code && String(message.code).startsWith('DISCLAIMER_')) {
24929
+ if (message.code === 'DISCLAIMER_PENDING') {
24930
+ var err = new Error(message.message || 'Disclaimer acknowledgement required first');
24931
+ err.code = 'DISCLAIMER_PENDING';
24932
+ this.emit('error', err);
24933
+ } else {
24934
+ this.disclaimersPending = false;
24935
+ this.emit('disclaimerRejected', {
24936
+ code: message.code,
24937
+ message: message.message || ''
24938
+ });
24939
+ }
24940
+ }
24701
24941
  this.emit('message', message);
24702
24942
  break;
24703
24943
  case 'barge_in':
@@ -24832,10 +25072,11 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
24832
25072
  console.warn('⚠️ [VISUAL ASSISTANT] Screenshot error:', message.error);
24833
25073
  }
24834
25074
  break;
25075
+ case 'show_items':
24835
25076
  case 'show_products':
24836
25077
  case 'cart_updated':
24837
25078
  case 'add_to_store_cart':
24838
- // E-commerce messages - emit for TTPEcommerceWidget to handle
25079
+ // Flavor / commerce messages (show_items = menu, rooms, tours, etc.)
24839
25080
  this.emit('message', message);
24840
25081
  break;
24841
25082
  default:
@@ -25073,6 +25314,10 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
25073
25314
  this.emit('inputFormatNegotiated', message.inputAudioFormat);
25074
25315
  }
25075
25316
 
25317
+ // Server-driven disclaimer gate (voice): when true, client must send disclaimer_ack before using the session.
25318
+ this.disclaimersPending = message.disclaimersRequired === true;
25319
+ this.disclaimersHash = this.disclaimersPending ? message.disclaimersHash || null : null;
25320
+
25076
25321
  // IMPORTANT: Set this AFTER input format negotiation above.
25077
25322
  // VoiceInterface waits for this flag before starting recording,
25078
25323
  // so config.sampleRate must be finalized first.
@@ -25170,6 +25415,47 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
25170
25415
  this.audioPlayer.setOutputFormat(defaultFormat);
25171
25416
  this.formatConverter = null; // No conversion needed when using defaults
25172
25417
  }
25418
+ if (this.disclaimersPending) {
25419
+ var payload = {
25420
+ texts: Array.isArray(message.disclaimerTexts) ? message.disclaimerTexts : [],
25421
+ disclaimersHash: this.disclaimersHash,
25422
+ disclaimersVersion: message.disclaimersVersion,
25423
+ disclaimerTimeoutMs: message.disclaimerTimeoutMs,
25424
+ conversationId: this.conversationId
25425
+ };
25426
+ this.lastDisclaimerPayload = payload;
25427
+ this.emit('disclaimersRequired', payload);
25428
+ } else {
25429
+ this.lastDisclaimerPayload = null;
25430
+ }
25431
+ }
25432
+
25433
+ /**
25434
+ * Acknowledge server disclaimer gate (voice protocol).
25435
+ * @param {boolean} accepted
25436
+ */
25437
+ }, {
25438
+ key: "sendDisclaimerAck",
25439
+ value: function sendDisclaimerAck(accepted) {
25440
+ if (!this.isConnected || !this.websocket || this.websocket.readyState !== WebSocket.OPEN) {
25441
+ console.warn('VoiceSDK v2: Cannot send disclaimer_ack — socket not open');
25442
+ return;
25443
+ }
25444
+ var payload = {
25445
+ t: 'disclaimer_ack',
25446
+ accepted: !!accepted,
25447
+ disclaimersHash: this.disclaimersHash || '',
25448
+ conversationId: this.conversationId || undefined
25449
+ };
25450
+ try {
25451
+ this.websocket.send(JSON.stringify(payload));
25452
+ console.log('📤 VoiceSDK v2: disclaimer_ack sent', {
25453
+ accepted: payload.accepted
25454
+ });
25455
+ this.disclaimersPending = false;
25456
+ } catch (e) {
25457
+ console.error('VoiceSDK v2: disclaimer_ack send failed', e);
25458
+ }
25173
25459
  }
25174
25460
 
25175
25461
  /**
@@ -25649,6 +25935,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
25649
25935
  return;
25650
25936
  }
25651
25937
  console.log('📞 VoiceSDK v2: Hanging up call...');
25938
+ this._gracefulHangupInitiated = true;
25652
25939
 
25653
25940
  // Clear stored conversationId on graceful hangup
25654
25941
  // This prevents attempting resume after intentional end
@@ -25702,6 +25989,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
25702
25989
  var existingMediaStream,
25703
25990
  error,
25704
25991
  _error4,
25992
+ _error5,
25705
25993
  permissionError,
25706
25994
  _args6 = arguments,
25707
25995
  _t4,
@@ -25726,40 +26014,49 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
25726
26014
  console.warn('VoiceSDK v2: Already recording');
25727
26015
  return _context6.a(2, true);
25728
26016
  case 2:
26017
+ if (!this.disclaimersPending) {
26018
+ _context6.n = 3;
26019
+ break;
26020
+ }
26021
+ _error4 = new Error('Server disclaimers must be accepted before recording. Call sendDisclaimerAck(true) first.');
26022
+ _error4.code = 'DISCLAIMER_PENDING';
26023
+ this.emit('error', _error4);
26024
+ throw _error4;
26025
+ case 3:
25729
26026
  console.log('🎤 VoiceSDK v2: Starting recording...');
25730
- _context6.p = 3;
26027
+ _context6.p = 4;
25731
26028
  // CRITICAL for mobile browsers: Request microphone permission FIRST
25732
26029
  // iOS: Pass existingMediaStream to avoid second getUserMedia (can fail on iOS)
25733
26030
  console.log('🎤 VoiceSDK v2: Requesting microphone permission (mobile-friendly)...');
25734
- _context6.n = 4;
26031
+ _context6.n = 5;
25735
26032
  return this.audioRecorder.start(existingMediaStream ? {
25736
26033
  existingMediaStream: existingMediaStream
25737
26034
  } : {});
25738
- case 4:
26035
+ case 5:
25739
26036
  if (!(!this.isConnected || !this.websocket || this.websocket.readyState !== WebSocket.OPEN)) {
25740
- _context6.n = 9;
26037
+ _context6.n = 10;
25741
26038
  break;
25742
26039
  }
25743
- _context6.p = 5;
25744
- _context6.n = 6;
26040
+ _context6.p = 6;
26041
+ _context6.n = 7;
25745
26042
  return this.audioRecorder.stop();
25746
- case 6:
25747
- _context6.n = 8;
25748
- break;
25749
26043
  case 7:
25750
- _context6.p = 7;
25751
- _t4 = _context6.v;
26044
+ _context6.n = 9;
26045
+ break;
25752
26046
  case 8:
25753
- _error4 = new Error('Connection lost - server may have rejected the call');
25754
- _error4.name = 'ServerRejected';
25755
- _error4.isServerRejection = true;
26047
+ _context6.p = 8;
26048
+ _t4 = _context6.v;
26049
+ case 9:
26050
+ _error5 = new Error('Connection lost - server may have rejected the call');
26051
+ _error5.name = 'ServerRejected';
26052
+ _error5.isServerRejection = true;
25756
26053
  // Don't emit error event - this is expected when server rejects
25757
26054
  // The error handler in VoiceInterface will handle it appropriately
25758
- throw _error4;
25759
- case 9:
25760
- _context6.n = 10;
25761
- return this.audioPlayer.resumeAudioContext();
26055
+ throw _error5;
25762
26056
  case 10:
26057
+ _context6.n = 11;
26058
+ return this.audioPlayer.resumeAudioContext();
26059
+ case 11:
25763
26060
  // After permission is granted, send start_continuous_mode message to server
25764
26061
  this.sendMessage({
25765
26062
  t: 'start_continuous_mode',
@@ -25769,29 +26066,29 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
25769
26066
  // Request screen wake lock to keep screen on during voice call (mobile)
25770
26067
  this._requestWakeLock();
25771
26068
  return _context6.a(2, true);
25772
- case 11:
25773
- _context6.p = 11;
26069
+ case 12:
26070
+ _context6.p = 12;
25774
26071
  _t5 = _context6.v;
25775
26072
  if (!(this.audioRecorder && this.audioRecorder.isRecording)) {
25776
- _context6.n = 15;
26073
+ _context6.n = 16;
25777
26074
  break;
25778
26075
  }
25779
- _context6.p = 12;
25780
- _context6.n = 13;
26076
+ _context6.p = 13;
26077
+ _context6.n = 14;
25781
26078
  return this.audioRecorder.stop();
25782
- case 13:
25783
- _context6.n = 15;
25784
- break;
25785
26079
  case 14:
25786
- _context6.p = 14;
25787
- _t6 = _context6.v;
26080
+ _context6.n = 16;
26081
+ break;
25788
26082
  case 15:
26083
+ _context6.p = 15;
26084
+ _t6 = _context6.v;
26085
+ case 16:
25789
26086
  if (!(_t5.isServerRejection || _t5.name === 'ServerRejected')) {
25790
- _context6.n = 16;
26087
+ _context6.n = 17;
25791
26088
  break;
25792
26089
  }
25793
26090
  return _context6.a(2, false);
25794
- case 16:
26091
+ case 17:
25795
26092
  // Log and emit other errors (permission denied, etc.)
25796
26093
  console.error('❌ VoiceSDK v2: Failed to start recording:', _t5);
25797
26094
 
@@ -25806,7 +26103,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
25806
26103
  }
25807
26104
  return _context6.a(2, false);
25808
26105
  }
25809
- }, _callee6, this, [[12, 14], [5, 7], [3, 11]]);
26106
+ }, _callee6, this, [[13, 15], [6, 8], [4, 12]]);
25810
26107
  }));
25811
26108
  function startRecording() {
25812
26109
  return _startRecording.apply(this, arguments);
@@ -26198,6 +26495,14 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
26198
26495
  }
26199
26496
  this.isConnected = false;
26200
26497
 
26498
+ // hello_ack calls storeConversationId(), which refreshes RESUME_TTL_MS. If connect
26499
+ // then aborts (mic denied, disconnect, etc.) without hangup(), sessionStorage still
26500
+ // looks like a fresh in-call navigation and the widget auto-resumes on refresh.
26501
+ // Graceful hangup() clears storage and sets _gracefulHangupInitiated — do not wipe here.
26502
+ if (this.helloAckReceived && !this._gracefulHangupInitiated) {
26503
+ this.clearStoredConversationId();
26504
+ }
26505
+
26201
26506
  // Reject all pending data injections on destroy
26202
26507
  if (this.pendingInjections.size > 0) {
26203
26508
  console.warn("VoiceSDK v2: Rejecting ".concat(this.pendingInjections.size, " pending data injections due to destroy"));
@@ -27824,6 +28129,7 @@ var AgentSDK = /*#__PURE__*/function () {
27824
28129
  case 'error':
27825
28130
  this.onError(new Error(message.message || message.error || 'Unknown error'));
27826
28131
  break;
28132
+ case 'show_items':
27827
28133
  case 'show_products':
27828
28134
  case 'cart_updated':
27829
28135
  case 'add_to_store_cart':
@@ -28574,190 +28880,99 @@ var ItemCard = /*#__PURE__*/function () {
28574
28880
 
28575
28881
  /***/ }),
28576
28882
 
28577
- /***/ "./src/widget/LandingScreen.js":
28883
+ /***/ "./src/widget/TTPChatWidget.js":
28578
28884
  /*!*************************************!*\
28579
- !*** ./src/widget/LandingScreen.js ***!
28885
+ !*** ./src/widget/TTPChatWidget.js ***!
28580
28886
  \*************************************/
28581
28887
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
28582
28888
 
28583
28889
  "use strict";
28584
28890
  __webpack_require__.r(__webpack_exports__);
28585
28891
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
28586
- /* harmony export */ LandingScreen: () => (/* binding */ LandingScreen)
28892
+ /* harmony export */ TTPChatWidget: () => (/* binding */ TTPChatWidget)
28587
28893
  /* harmony export */ });
28588
- function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
28894
+ /* harmony import */ var _core_TextChatSDK_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../core/TextChatSDK.js */ "./src/core/TextChatSDK.js");
28895
+ /* harmony import */ var _VoiceInterface_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./VoiceInterface.js */ "./src/widget/VoiceInterface.js");
28896
+ /* harmony import */ var _TextInterface_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./TextInterface.js */ "./src/widget/TextInterface.js");
28897
+ /* harmony import */ var _widget_translations_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./widget-translations.js */ "./src/widget/widget-translations.js");
28898
+ /* harmony import */ var _flavors_index_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../flavors/index.js */ "./src/flavors/index.js");
28899
+ var _excluded = ["agentName"];
28900
+ function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
28901
+ function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
28902
+ function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i.return) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
28903
+ function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
28904
+ function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
28905
+ function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
28906
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
28907
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
28908
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
28589
28909
  function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
28590
28910
  function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
28591
28911
  function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
28592
28912
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
28593
28913
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
28914
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
28594
28915
  /**
28595
- * LandingScreen - Mode selection screen for unified widget mode
28596
- *
28597
- * Required from parent (widget):
28598
- * - config: { landing, header, language, ... }
28599
- * - translations: object
28600
- * - shadowRoot: ShadowRoot | Document
28916
+ * TTPChatWidget - Pre-built UI widget for text chat using TextChatSDK
28917
+ * Similar to AgentWidget but designed for text-based chat
28601
28918
  */
28602
28919
 
28603
- var LandingScreen = /*#__PURE__*/function () {
28604
- function LandingScreen(config) {
28605
- _classCallCheck(this, LandingScreen);
28606
- this.config = config;
28607
- this.translations = config.translations || {};
28608
- this.shadowRoot = config.shadowRoot;
28609
- }
28610
-
28611
- /**
28612
- * Helper to get translated text
28613
- */
28614
- return _createClass(LandingScreen, [{
28615
- key: "t",
28616
- value: function t(key) {
28617
- var lang = this.config.language || 'en';
28618
- var translations = this.translations[lang] || this.translations.en || {};
28619
- return translations[key] || key;
28620
- }
28621
28920
 
28622
- /**
28623
- * Generate HTML for landing screen
28624
- */
28625
- }, {
28626
- key: "generateHTML",
28627
- value: function generateHTML() {
28628
- var landing = this.config.landing || {};
28629
28921
 
28630
- // Determine logo content based on logoType
28631
- var logoContent = '';
28632
- if (landing.logoType === 'image' && landing.logoImageUrl) {
28633
- logoContent = "<img src=\"".concat(landing.logoImageUrl, "\" alt=\"Logo\" style=\"max-width: 44px; max-height: 44px; object-fit: contain; border: none; outline: none;\">");
28634
- } else {
28635
- logoContent = "<span class=\"landing-avatar-emoji\">".concat(landing.logoIcon || landing.logo || '🤖', "</span>");
28636
- }
28637
- 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 ");
28638
- }
28639
28922
 
28640
- /**
28641
- * Generate CSS for landing screen
28642
- */
28643
- }, {
28644
- key: "generateCSS",
28645
- value: function generateCSS() {
28646
- var landing = this.config.landing || {};
28647
- var anim = this.config.animation || {};
28648
28923
 
28649
- // Add !important when not using Shadow DOM
28650
- var important = this.config.useShadowDOM === false ? ' !important' : '';
28651
- return "\n /* ===== LANDING SCREEN - New Design ===== */\n .landing-screen { \n display: none".concat(important, "; \n flex: 1").concat(important, "; \n padding: 32px 24px").concat(important, "; \n background: ").concat(landing.backgroundColor || 'linear-gradient(180deg, #ffffff 0%, rgba(168, 85, 247, 0.03) 100%)', "; \n align-items: center").concat(important, "; \n justify-content: flex-start").concat(important, "; \n flex-direction: column").concat(important, "; \n gap: 0").concat(important, "; \n overflow-y: auto").concat(important, "; \n min-height: 0").concat(important, ";\n text-align: center").concat(important, ";\n }\n \n .landing-screen.active { \n display: flex").concat(important, "; \n }\n\n /* Avatar - Richer purple gradient */\n .landing-avatar {\n width: 88px").concat(important, ";\n height: 88px").concat(important, ";\n border-radius: 22px").concat(important, ";\n margin-bottom: 20px").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n ").concat(function () {
28652
- // Determine background based on logo type and background settings
28653
- if (landing.logoType === 'image') {
28654
- // For image logos, use logoBackgroundColor if enabled, otherwise transparent
28655
- if (landing.logoBackgroundEnabled !== false) {
28656
- var bgColor = landing.logoBackgroundColor || landing.avatarBackground || 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)';
28657
- return "background: ".concat(bgColor, "; box-shadow: 0 8px 28px rgba(102, 126, 234, 0.35); border: none;");
28658
- } else {
28659
- return "background: transparent; box-shadow: none; border: none; outline: none;";
28660
- }
28661
- } else {
28662
- // For icon logos, use avatarBackground (default behavior)
28663
- var _bgColor = landing.avatarBackground || 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)';
28664
- return "background: ".concat(_bgColor, "; box-shadow: 0 8px 28px rgba(102, 126, 234, 0.35); border: none;");
28665
- }
28666
- }(), "\n }\n \n .landing-avatar img {\n border: none !important;\n outline: none !important;\n }\n\n .landing-avatar-emoji {\n font-size: 44px").concat(important, ";\n line-height: 1").concat(important, ";\n }\n\n /* Title & Subtitle */\n .landing-title { \n font-size: 20px").concat(important, "; \n color: ").concat(landing.titleColor || '#1e1b4b', "; \n font-weight: 600").concat(important, "; \n margin-bottom: 6px").concat(important, "; \n text-align: center").concat(important, ";\n line-height: 1.3").concat(important, ";\n }\n\n .landing-subtitle {\n font-size: 14px").concat(important, ";\n color: ").concat(landing.subtitleColor || '#64748b', ";\n margin-bottom: 28px").concat(important, ";\n text-align: center").concat(important, ";\n }\n\n /* Mode Selection - Side by Side */\n .mode-selection { \n display: flex").concat(important, "; \n gap: 12px").concat(important, "; \n width: 100%").concat(important, "; \n justify-content: center").concat(important, "; \n }\n\n .mode-card { \n flex: 1").concat(important, "; \n max-width: 160px").concat(important, "; \n padding: 20px 16px").concat(important, ";\n background: ").concat(landing.modeCardBackgroundColor || '#ffffff', "; \n border: 1px solid ").concat(landing.modeCardBorderColor || 'rgba(0, 0, 0, 0.06)', "; \n border-radius: 18px").concat(important, "; \n cursor: pointer").concat(important, "; \n display: flex").concat(important, "; \n flex-direction: column").concat(important, "; \n align-items: center").concat(important, "; \n gap: 12px").concat(important, "; \n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1)").concat(important, "; \n box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06)").concat(important, "; \n font-family: inherit").concat(important, ";\n }\n\n .mode-card:hover { \n transform: translateY(-4px)").concat(important, "; \n box-shadow: 0 8px 24px rgba(124, 58, 237, 0.2)").concat(important, "; \n border-color: rgba(124, 58, 237, 0.3)").concat(important, "; \n }\n\n .mode-card:active {\n transform: translateY(-2px)").concat(important, ";\n }\n\n /* Mode Card Icon - Vibrant purple gradient */\n .mode-card-icon { \n width: 56px").concat(important, "; \n height: 56px").concat(important, "; \n display: flex").concat(important, "; \n align-items: center").concat(important, "; \n justify-content: center").concat(important, "; \n border-radius: 16px").concat(important, "; \n background: ").concat(landing.modeCardIconBackgroundColor || 'linear-gradient(135deg, #7c3aed, #a855f7)', "; \n color: #fff").concat(important, "; \n box-shadow: 0 4px 14px rgba(124, 58, 237, 0.35)").concat(important, ";\n }\n\n .mode-card-icon svg {\n width: 26px").concat(important, ";\n height: 26px").concat(important, ";\n stroke: white").concat(important, ";\n fill: none").concat(important, ";\n }\n\n .mode-card-title { \n color: ").concat(landing.modeCardTitleColor || '#1e1b4b', "; \n font-weight: 600").concat(important, "; \n font-size: 14px").concat(important, ";\n text-align: center").concat(important, ";\n }\n\n /* Mobile Responsive */\n @media (max-width: 768px) {\n .landing-screen {\n padding: 24px 16px").concat(important, ";\n }\n\n .landing-avatar {\n width: 72px").concat(important, ";\n height: 72px").concat(important, ";\n border-radius: 18px").concat(important, ";\n margin-bottom: 16px").concat(important, ";\n }\n\n .landing-avatar-emoji {\n font-size: 36px").concat(important, ";\n }\n\n .landing-title {\n font-size: 18px").concat(important, ";\n }\n\n .landing-subtitle {\n font-size: 13px").concat(important, ";\n margin-bottom: 20px").concat(important, ";\n }\n\n .mode-selection {\n gap: 10px").concat(important, ";\n }\n\n .mode-card {\n padding: 16px 12px").concat(important, ";\n max-width: 140px").concat(important, ";\n }\n\n .mode-card-icon {\n width: 48px").concat(important, ";\n height: 48px").concat(important, ";\n border-radius: 14px").concat(important, ";\n }\n\n .mode-card-icon svg {\n width: 22px").concat(important, ";\n height: 22px").concat(important, ";\n }\n\n .mode-card-title {\n font-size: 13px").concat(important, ";\n }\n }\n\n @media (max-width: 380px) {\n .mode-selection {\n flex-direction: column").concat(important, ";\n align-items: center").concat(important, ";\n }\n\n .mode-card {\n max-width: 100%").concat(important, ";\n width: 100%").concat(important, ";\n flex-direction: row").concat(important, ";\n padding: 14px 18px").concat(important, ";\n gap: 14px").concat(important, ";\n }\n\n .mode-card-icon {\n flex-shrink: 0").concat(important, ";\n }\n\n .mode-card-title {\n text-align: left").concat(important, ";\n }\n }\n ");
28667
- }
28668
28924
 
28669
- /**
28670
- * Show the landing screen
28671
- */
28672
- }, {
28673
- key: "show",
28674
- value: function show() {
28675
- var _this$shadowRoot;
28676
- var landing = (_this$shadowRoot = this.shadowRoot) === null || _this$shadowRoot === void 0 ? void 0 : _this$shadowRoot.getElementById('landingScreen');
28677
- if (landing) {
28678
- landing.classList.add('active');
28679
- }
28680
- }
28925
+ function isNonEmptyConfigString(v) {
28926
+ return v != null && String(v).trim() !== '';
28927
+ }
28681
28928
 
28682
- /**
28683
- * Hide the landing screen
28684
- */
28685
- }, {
28686
- key: "hide",
28687
- value: function hide() {
28688
- var _this$shadowRoot2;
28689
- var landing = (_this$shadowRoot2 = this.shadowRoot) === null || _this$shadowRoot2 === void 0 ? void 0 : _this$shadowRoot2.getElementById('landingScreen');
28690
- if (landing) {
28691
- landing.classList.remove('active');
28692
- }
28693
- }
28929
+ /** True when the integrator set voice start-call colors (not relying on SDK defaults). */
28930
+ function isVoiceStartCallAppearanceCustomized(rawConfig) {
28931
+ var v = rawConfig === null || rawConfig === void 0 ? void 0 : rawConfig.voice;
28932
+ if (!v || _typeof(v) !== 'object') return false;
28933
+ var set = function set(k) {
28934
+ return Object.prototype.hasOwnProperty.call(v, k) && isNonEmptyConfigString(v[k]);
28935
+ };
28936
+ return set('primaryBtnGradient1') || set('primaryBtnGradient2') || set('startCallButtonColor');
28937
+ }
28938
+ function computeIsLightPanel(panelBg) {
28939
+ if (!panelBg || panelBg.charAt(0) !== '#') return false;
28940
+ var r = parseInt(panelBg.substr(1, 2), 16);
28941
+ var g = parseInt(panelBg.substr(3, 2), 16);
28942
+ var b = parseInt(panelBg.substr(5, 2), 16);
28943
+ return (r * 299 + g * 587 + b * 114) / 1000 > 160;
28944
+ }
28694
28945
 
28695
- /**
28696
- * Setup event handlers (called by parent widget)
28697
- */
28698
- }, {
28699
- key: "setupEventHandlers",
28700
- value: function setupEventHandlers() {
28701
- var _this$shadowRoot3, _this$shadowRoot4;
28702
- var callbacks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
28703
- var voiceCard = (_this$shadowRoot3 = this.shadowRoot) === null || _this$shadowRoot3 === void 0 ? void 0 : _this$shadowRoot3.getElementById('mode-card-voice');
28704
- var textCard = (_this$shadowRoot4 = this.shadowRoot) === null || _this$shadowRoot4 === void 0 ? void 0 : _this$shadowRoot4.getElementById('mode-card-text');
28705
- if (voiceCard && callbacks.onSelectVoice) {
28706
- voiceCard.onclick = callbacks.onSelectVoice;
28707
- }
28708
- if (textCard && callbacks.onSelectText) {
28709
- textCard.onclick = callbacks.onSelectText;
28710
- }
28711
- }
28712
- }]);
28713
- }();
28714
-
28715
- /***/ }),
28716
-
28717
- /***/ "./src/widget/TTPChatWidget.js":
28718
- /*!*************************************!*\
28719
- !*** ./src/widget/TTPChatWidget.js ***!
28720
- \*************************************/
28721
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
28722
-
28723
- "use strict";
28724
- __webpack_require__.r(__webpack_exports__);
28725
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
28726
- /* harmony export */ TTPChatWidget: () => (/* binding */ TTPChatWidget)
28727
- /* harmony export */ });
28728
- /* harmony import */ var _core_TextChatSDK_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../core/TextChatSDK.js */ "./src/core/TextChatSDK.js");
28729
- /* harmony import */ var _VoiceInterface_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./VoiceInterface.js */ "./src/widget/VoiceInterface.js");
28730
- /* harmony import */ var _TextInterface_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./TextInterface.js */ "./src/widget/TextInterface.js");
28731
- /* harmony import */ var _LandingScreen_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./LandingScreen.js */ "./src/widget/LandingScreen.js");
28732
- /* harmony import */ var _widget_translations_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./widget-translations.js */ "./src/widget/widget-translations.js");
28733
- /* harmony import */ var _flavors_index_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../flavors/index.js */ "./src/flavors/index.js");
28734
- function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i.return) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
28735
- function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
28736
- function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
28737
- function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
28738
- function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
28739
- function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
28740
- function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
28741
- function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
28742
- function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
28743
- function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
28744
- function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
28745
- function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
28746
- function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
28747
28946
  /**
28748
- * TTPChatWidget - Pre-built UI widget for text chat using TextChatSDK
28749
- * Similar to AgentWidget but designed for text-based chat
28947
+ * Solid CSS color for "TalkToPC" footer link: brand purple by default; matches start-call accent when customized.
28750
28948
  */
28751
-
28752
-
28753
-
28754
-
28755
-
28756
-
28757
-
28949
+ function talkToPcLinkColorForPanel(isLightPanel, mergedVoice, rawConfig, voiceUiEnabled) {
28950
+ var startAccentDark = mergedVoice.primaryBtnGradient1 || mergedVoice.primaryBtnGradient2 || mergedVoice.startCallButtonColor || '#6d56f5';
28951
+ var defaultDark = startAccentDark;
28952
+ var defaultLight = '#7C3AED';
28953
+ var defaults = isLightPanel ? defaultLight : defaultDark;
28954
+ if (!voiceUiEnabled || !isVoiceStartCallAppearanceCustomized(rawConfig)) return defaults;
28955
+ var raw = mergedVoice.primaryBtnGradient1 || mergedVoice.primaryBtnGradient2 || mergedVoice.startCallButtonColor;
28956
+ if (!isNonEmptyConfigString(raw)) return defaults;
28957
+ var t = String(raw).trim();
28958
+ if (t.startsWith('#')) {
28959
+ if (t.length === 4) {
28960
+ var r = t[1];
28961
+ var g = t[2];
28962
+ var b = t[3];
28963
+ return "#".concat(r).concat(r).concat(g).concat(g).concat(b).concat(b);
28964
+ }
28965
+ if (t.length === 7) return t;
28966
+ }
28967
+ var m = t.match(/#[0-9a-fA-F]{6}/i);
28968
+ if (m) return m[0];
28969
+ return defaults;
28970
+ }
28758
28971
  var TTPChatWidget = /*#__PURE__*/function () {
28759
28972
  function TTPChatWidget() {
28760
- var _this$config$text,
28973
+ var _this$config$behavior,
28974
+ _this$config$panel,
28975
+ _this$config$text,
28761
28976
  _this$config$text2,
28762
28977
  _this$config$voice,
28763
28978
  _this$config$voice2,
@@ -28765,8 +28980,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
28765
28980
  _this$config$voice4,
28766
28981
  _this$config$voice5,
28767
28982
  _this$config$voice6,
28768
- _this = this,
28769
- _this$config$behavior2;
28983
+ _this = this;
28770
28984
  var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
28771
28985
  _classCallCheck(this, TTPChatWidget);
28772
28986
  this._rawConfig = config;
@@ -28782,9 +28996,9 @@ var TTPChatWidget = /*#__PURE__*/function () {
28782
28996
  this.sdk = new _core_TextChatSDK_js__WEBPACK_IMPORTED_MODULE_0__["default"](this.config);
28783
28997
  this.isOpen = false;
28784
28998
  this.isActive = false;
28785
- this.translations = _widget_translations_js__WEBPACK_IMPORTED_MODULE_4__["default"];
28999
+ this.translations = _widget_translations_js__WEBPACK_IMPORTED_MODULE_3__["default"];
28786
29000
  // Track current view state in unified mode to prevent resetting when widget is recreated
28787
- this.currentView = 'landing'; // 'landing', 'text', or 'voice'
29001
+ this.currentView = 'voice'; // 'text' or 'voice' (unified home is always voice hero)
28788
29002
  // Race condition prevention: prevent multiple rapid clicks on Voice Call button
28789
29003
  this.isStartingCall = false;
28790
29004
  // Shadow DOM root for CSS isolation
@@ -28807,7 +29021,13 @@ var TTPChatWidget = /*#__PURE__*/function () {
28807
29021
 
28808
29022
  // Initialize interfaces with proper config (after shadow root is created)
28809
29023
  // Voice interface needs voice config merged with main config
29024
+ var widgetModeForVoice = ((_this$config$behavior = this.config.behavior) === null || _this$config$behavior === void 0 ? void 0 : _this$config$behavior.mode) || 'unified';
29025
+ var showVoiceUi = widgetModeForVoice === 'unified' || widgetModeForVoice === 'voice-only';
29026
+ var panelBgForBrand = ((_this$config$panel = this.config.panel) === null || _this$config$panel === void 0 ? void 0 : _this$config$panel.backgroundColor) || '#16161e';
29027
+ var talkToPcLink = talkToPcLinkColorForPanel(computeIsLightPanel(panelBgForBrand), this.config.voice, this._rawConfig, showVoiceUi);
28810
29028
  var voiceConfig = _objectSpread(_objectSpread(_objectSpread({}, this.config), this.config.voice), {}, {
29029
+ agentName: this.config.agentName,
29030
+ _talkToPcLinkColor: talkToPcLink,
28811
29031
  // Pass through text input placeholder for voice text input
28812
29032
  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...',
28813
29033
  // Pass through send button color for voice send button
@@ -28835,15 +29055,15 @@ var TTPChatWidget = /*#__PURE__*/function () {
28835
29055
  onAudioStoppedPlaying: this.config.onAudioStoppedPlaying,
28836
29056
  onSubtitleDisplay: this.config.onSubtitleDisplay,
28837
29057
  onVoiceCallButtonClick: this.config.onVoiceCallButtonClick,
28838
- // Callback when call ends - show landing screen (only in unified mode)
28839
- // BUT: Don't return to landing if we're showing a domain error
29058
+ // Callback when call ends return to unified home (voice hero), not legacy mode picker
29059
+ // BUT: Don't switch views if we're showing a domain error
28840
29060
  onCallEnd: function onCallEnd() {
28841
- var _this$config$behavior;
29061
+ var _this$config$behavior2;
28842
29062
  if (_this._isDomainErrorVisible()) {
28843
- console.log('🚫 Domain error is displayed - NOT returning to landing screen from onCallEnd');
29063
+ console.log('🚫 Domain error is displayed - NOT returning to home from onCallEnd');
28844
29064
  return;
28845
29065
  }
28846
- var widgetMode = ((_this$config$behavior = _this.config.behavior) === null || _this$config$behavior === void 0 ? void 0 : _this$config$behavior.mode) || 'unified';
29066
+ var widgetMode = ((_this$config$behavior2 = _this.config.behavior) === null || _this$config$behavior2 === void 0 ? void 0 : _this$config$behavior2.mode) || 'unified';
28847
29067
  if (widgetMode === 'unified') {
28848
29068
  if (window.innerWidth <= 768) {
28849
29069
  var _this$shadowRoot, _this$shadowRoot2;
@@ -28863,7 +29083,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
28863
29083
  onShowVoice: function onShowVoice() {
28864
29084
  _this.showVoice();
28865
29085
  },
28866
- // Callback to show landing page (used by domain error back button)
29086
+ // Callback to show unified home (voice hero; used by domain error back button)
28867
29087
  onShowLanding: function onShowLanding() {
28868
29088
  _this.showLanding();
28869
29089
  },
@@ -28883,18 +29103,6 @@ var TTPChatWidget = /*#__PURE__*/function () {
28883
29103
  });
28884
29104
  this.textInterface = new _TextInterface_js__WEBPACK_IMPORTED_MODULE_2__.TextInterface(textConfig, this.sdk);
28885
29105
 
28886
- // Landing screen (only for unified mode)
28887
- var widgetMode = ((_this$config$behavior2 = this.config.behavior) === null || _this$config$behavior2 === void 0 ? void 0 : _this$config$behavior2.mode) || 'unified';
28888
- if (widgetMode === 'unified') {
28889
- var landingConfig = _objectSpread(_objectSpread({}, this.config), {}, {
28890
- translations: this.translations,
28891
- shadowRoot: this.shadowRoot
28892
- });
28893
- this.landingScreen = new _LandingScreen_js__WEBPACK_IMPORTED_MODULE_3__.LandingScreen(landingConfig);
28894
- } else {
28895
- this.landingScreen = null;
28896
- }
28897
-
28898
29106
  // Now create widget HTML and populate shadow root
28899
29107
  this.createWidget();
28900
29108
  this.setupEventHandlers();
@@ -28998,7 +29206,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
28998
29206
  value: function _initFlavor(flavorName) {
28999
29207
  var _this$_flavorObj,
29000
29208
  _this3 = this;
29001
- var factory = (0,_flavors_index_js__WEBPACK_IMPORTED_MODULE_5__.loadFlavor)(flavorName);
29209
+ var factory = (0,_flavors_index_js__WEBPACK_IMPORTED_MODULE_4__.loadFlavor)(flavorName);
29002
29210
  if (!factory) {
29003
29211
  console.error("[TTPChatWidget] Unknown flavor: \"".concat(flavorName, "\". Available flavors: ecommerce. Widget will run in vanilla mode."));
29004
29212
  return;
@@ -29064,6 +29272,17 @@ var TTPChatWidget = /*#__PURE__*/function () {
29064
29272
  }
29065
29273
  }
29066
29274
 
29275
+ /**
29276
+ * Resolved direction for widget chrome (shadow host, launcher). After mergeWithDefaults,
29277
+ * config.direction is always 'ltr' or 'rtl'.
29278
+ */
29279
+ }, {
29280
+ key: "getEffectiveTextDirection",
29281
+ value: function getEffectiveTextDirection() {
29282
+ var _this$config;
29283
+ return ((_this$config = this.config) === null || _this$config === void 0 ? void 0 : _this$config.direction) === 'rtl' ? 'rtl' : 'ltr';
29284
+ }
29285
+
29067
29286
  /**
29068
29287
  * Open the widget
29069
29288
  */
@@ -29086,7 +29305,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
29086
29305
  }, {
29087
29306
  key: "mergeWithDefaults",
29088
29307
  value: function mergeWithDefaults(userConfig) {
29089
- 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;
29308
+ var _userConfig$button, _userConfig$button2, _userConfig$icon, _userConfig$icon2, _userConfig$icon3, _userConfig$icon4, _userConfig$icon5, _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$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;
29090
29309
  // Handle legacy position string format
29091
29310
  var positionConfig = userConfig.position || 'bottom-right';
29092
29311
  if (typeof positionConfig === 'string') {
@@ -29130,7 +29349,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
29130
29349
  }
29131
29350
  });
29132
29351
  }
29133
- return _objectSpread({
29352
+ return _objectSpread(_objectSpread({
29134
29353
  // Required (agentId is required, appId is optional)
29135
29354
  agentId: userConfig.agentId,
29136
29355
  appId: userConfig.appId,
@@ -29138,22 +29357,35 @@ var TTPChatWidget = /*#__PURE__*/function () {
29138
29357
  // signedUrl accepted as backward-compat alias
29139
29358
  agentSettingsOverride: userConfig.agentSettingsOverride,
29140
29359
  demo: userConfig.demo !== false,
29141
- direction: userConfig.direction || 'ltr',
29142
- // Optional - text direction: 'ltr' or 'rtl'
29143
- language: userConfig.language || 'en',
29144
- // Optional - language for voice (defaults to 'en')
29145
-
29360
+ direction: function () {
29361
+ if (userConfig.direction === 'rtl' || userConfig.direction === 'ltr') {
29362
+ return userConfig.direction;
29363
+ }
29364
+ var langBase = String(userConfig.language || 'en').toLowerCase().split(/[-_]/)[0];
29365
+ if (langBase === 'he' || langBase === 'ar') return 'rtl';
29366
+ return 'ltr';
29367
+ }(),
29368
+ language: userConfig.language || 'en'
29369
+ }, isNonEmptyConfigString(userConfig.agentName) ? {
29370
+ agentName: String(userConfig.agentName).trim()
29371
+ } : {}), {}, {
29146
29372
  // Icon/Image Configuration
29147
- icon: _objectSpread({
29373
+ icon: _objectSpread(_objectSpread({
29148
29374
  type: ((_userConfig$icon = userConfig.icon) === null || _userConfig$icon === void 0 ? void 0 : _userConfig$icon.type) || 'custom',
29149
29375
  // 'microphone', 'custom', 'emoji', 'text'
29150
- customImage: ((_userConfig$icon2 = userConfig.icon) === null || _userConfig$icon2 === void 0 ? void 0 : _userConfig$icon2.customImage) || 'https://talktopc.com/logo192.png',
29151
- emoji: ((_userConfig$icon3 = userConfig.icon) === null || _userConfig$icon3 === void 0 ? void 0 : _userConfig$icon3.emoji) || '🎤',
29152
- text: ((_userConfig$icon4 = userConfig.icon) === null || _userConfig$icon4 === void 0 ? void 0 : _userConfig$icon4.text) || 'AI',
29153
- size: ((_userConfig$icon5 = userConfig.icon) === null || _userConfig$icon5 === void 0 ? void 0 : _userConfig$icon5.size) || 'medium',
29376
+ emoji: ((_userConfig$icon2 = userConfig.icon) === null || _userConfig$icon2 === void 0 ? void 0 : _userConfig$icon2.emoji) || '🎤',
29377
+ text: ((_userConfig$icon3 = userConfig.icon) === null || _userConfig$icon3 === void 0 ? void 0 : _userConfig$icon3.text) || 'AI',
29378
+ size: ((_userConfig$icon4 = userConfig.icon) === null || _userConfig$icon4 === void 0 ? void 0 : _userConfig$icon4.size) || 'medium',
29154
29379
  // 'small', 'medium', 'large', 'xl'
29155
- backgroundColor: ((_userConfig$icon6 = userConfig.icon) === null || _userConfig$icon6 === void 0 ? void 0 : _userConfig$icon6.backgroundColor) || '#FFFFFF'
29156
- }, userConfig.icon),
29380
+ backgroundColor: ((_userConfig$icon5 = userConfig.icon) === null || _userConfig$icon5 === void 0 ? void 0 : _userConfig$icon5.backgroundColor) || '#FFFFFF'
29381
+ }, userConfig.icon), {}, {
29382
+ /* After spread: empty / omitted URL → null so desktop pill uses waveform like mobile FAB */
29383
+ customImage: function (_userConfig$icon6) {
29384
+ var v = (_userConfig$icon6 = userConfig.icon) === null || _userConfig$icon6 === void 0 ? void 0 : _userConfig$icon6.customImage;
29385
+ if (v == null || String(v).trim() === '') return null;
29386
+ return String(v).trim();
29387
+ }()
29388
+ }),
29157
29389
  // Positioning Configuration (supports both object and legacy string)
29158
29390
  position: _objectSpread({
29159
29391
  vertical: positionConfig.vertical || 'bottom',
@@ -29185,38 +29417,46 @@ var TTPChatWidget = /*#__PURE__*/function () {
29185
29417
  backdropFilter: ((_userConfig$panel5 = userConfig.panel) === null || _userConfig$panel5 === void 0 ? void 0 : _userConfig$panel5.backdropFilter) || null,
29186
29418
  border: ((_userConfig$panel6 = userConfig.panel) === null || _userConfig$panel6 === void 0 ? void 0 : _userConfig$panel6.border) || '1px solid #E5E7EB'
29187
29419
  }, userConfig.panel),
29188
- // Voice-specific Configuration
29189
- voice: _objectSpread({
29190
- // Voice button colors (inside panel)
29191
- micButtonColor: ((_userConfig$voice = userConfig.voice) === null || _userConfig$voice === void 0 ? void 0 : _userConfig$voice.micButtonColor) || ((_userConfig$panel7 = userConfig.panel) === null || _userConfig$panel7 === void 0 ? void 0 : _userConfig$panel7.micButtonColor) || primaryColor,
29192
- micButtonActiveColor: ((_userConfig$voice2 = userConfig.voice) === null || _userConfig$voice2 === void 0 ? void 0 : _userConfig$voice2.micButtonActiveColor) || ((_userConfig$panel8 = userConfig.panel) === null || _userConfig$panel8 === void 0 ? void 0 : _userConfig$panel8.micButtonActiveColor) || '#EF4444',
29193
- // Voice button hint text (below button)
29194
- micButtonHint: _objectSpread(_objectSpread({
29195
- text: ((_userConfig$voice3 = userConfig.voice) === null || _userConfig$voice3 === void 0 || (_userConfig$voice3 = _userConfig$voice3.micButtonHint) === null || _userConfig$voice3 === void 0 ? void 0 : _userConfig$voice3.text) || ((_userConfig$panel9 = userConfig.panel) === null || _userConfig$panel9 === void 0 || (_userConfig$panel9 = _userConfig$panel9.micButtonHint) === null || _userConfig$panel9 === void 0 ? void 0 : _userConfig$panel9.text) || 'Click the button to start voice conversation',
29196
- color: ((_userConfig$voice4 = userConfig.voice) === null || _userConfig$voice4 === void 0 || (_userConfig$voice4 = _userConfig$voice4.micButtonHint) === null || _userConfig$voice4 === void 0 ? void 0 : _userConfig$voice4.color) || ((_userConfig$panel0 = userConfig.panel) === null || _userConfig$panel0 === void 0 || (_userConfig$panel0 = _userConfig$panel0.micButtonHint) === null || _userConfig$panel0 === void 0 ? void 0 : _userConfig$panel0.color) || '#6B7280',
29197
- fontSize: ((_userConfig$voice5 = userConfig.voice) === null || _userConfig$voice5 === void 0 || (_userConfig$voice5 = _userConfig$voice5.micButtonHint) === null || _userConfig$voice5 === void 0 ? void 0 : _userConfig$voice5.fontSize) || ((_userConfig$panel1 = userConfig.panel) === null || _userConfig$panel1 === void 0 || (_userConfig$panel1 = _userConfig$panel1.micButtonHint) === null || _userConfig$panel1 === void 0 ? void 0 : _userConfig$panel1.fontSize) || '12px'
29198
- }, (_userConfig$voice6 = userConfig.voice) === null || _userConfig$voice6 === void 0 ? void 0 : _userConfig$voice6.micButtonHint), (_userConfig$panel10 = userConfig.panel) === null || _userConfig$panel10 === void 0 ? void 0 : _userConfig$panel10.micButtonHint),
29199
- // Voice interface colors
29200
- avatarBackgroundColor: ((_userConfig$voice7 = userConfig.voice) === null || _userConfig$voice7 === void 0 ? void 0 : _userConfig$voice7.avatarBackgroundColor) || '#667eea',
29201
- avatarActiveBackgroundColor: ((_userConfig$voice8 = userConfig.voice) === null || _userConfig$voice8 === void 0 ? void 0 : _userConfig$voice8.avatarActiveBackgroundColor) || '#667eea',
29202
- statusTitleColor: ((_userConfig$voice9 = userConfig.voice) === null || _userConfig$voice9 === void 0 ? void 0 : _userConfig$voice9.statusTitleColor) || '#1e293b',
29203
- statusSubtitleColor: ((_userConfig$voice0 = userConfig.voice) === null || _userConfig$voice0 === void 0 ? void 0 : _userConfig$voice0.statusSubtitleColor) || '#64748b',
29204
- statusDotColor: ((_userConfig$voice1 = userConfig.voice) === null || _userConfig$voice1 === void 0 ? void 0 : _userConfig$voice1.statusDotColor) || '#10b981',
29205
- statusText: ((_userConfig$voice10 = userConfig.voice) === null || _userConfig$voice10 === void 0 ? void 0 : _userConfig$voice10.statusText) || null,
29206
- startCallButtonColor: ((_userConfig$voice11 = userConfig.voice) === null || _userConfig$voice11 === void 0 ? void 0 : _userConfig$voice11.startCallButtonColor) || '#667eea',
29207
- startCallButtonTextColor: ((_userConfig$voice12 = userConfig.voice) === null || _userConfig$voice12 === void 0 ? void 0 : _userConfig$voice12.startCallButtonTextColor) || '#FFFFFF',
29208
- startCallTitle: ((_userConfig$voice13 = userConfig.voice) === null || _userConfig$voice13 === void 0 ? void 0 : _userConfig$voice13.startCallTitle) || null,
29209
- startCallSubtitle: ((_userConfig$voice14 = userConfig.voice) === null || _userConfig$voice14 === void 0 ? void 0 : _userConfig$voice14.startCallSubtitle) || null,
29210
- startCallButtonText: ((_userConfig$voice15 = userConfig.voice) === null || _userConfig$voice15 === void 0 ? void 0 : _userConfig$voice15.startCallButtonText) || null,
29211
- transcriptBackgroundColor: ((_userConfig$voice16 = userConfig.voice) === null || _userConfig$voice16 === void 0 ? void 0 : _userConfig$voice16.transcriptBackgroundColor) || '#FFFFFF',
29212
- transcriptTextColor: ((_userConfig$voice17 = userConfig.voice) === null || _userConfig$voice17 === void 0 ? void 0 : _userConfig$voice17.transcriptTextColor) || '#1e293b',
29213
- transcriptLabelColor: ((_userConfig$voice18 = userConfig.voice) === null || _userConfig$voice18 === void 0 ? void 0 : _userConfig$voice18.transcriptLabelColor) || '#94a3b8',
29214
- controlButtonColor: ((_userConfig$voice19 = userConfig.voice) === null || _userConfig$voice19 === void 0 ? void 0 : _userConfig$voice19.controlButtonColor) || '#FFFFFF',
29215
- controlButtonSecondaryColor: ((_userConfig$voice20 = userConfig.voice) === null || _userConfig$voice20 === void 0 ? void 0 : _userConfig$voice20.controlButtonSecondaryColor) || '#64748b',
29216
- endCallButtonColor: ((_userConfig$voice21 = userConfig.voice) === null || _userConfig$voice21 === void 0 ? void 0 : _userConfig$voice21.endCallButtonColor) || '#ef4444',
29217
- // Voice language setting
29218
- language: ((_userConfig$voice22 = userConfig.voice) === null || _userConfig$voice22 === void 0 ? void 0 : _userConfig$voice22.language) || userConfig.language || 'en'
29219
- }, userConfig.voice),
29420
+ // Voice-specific Configuration (`voice.agentName` is ignored — use root `agentName`)
29421
+ voice: function (_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$voice$use, _userConfig$voice19, _userConfig$voice20, _userConfig$voice21, _userConfig$voice22, _userConfig$voice23, _userConfig$voice24) {
29422
+ var voiceOut = _objectSpread(_objectSpread({
29423
+ // Voice button colors (inside panel)
29424
+ micButtonColor: ((_userConfig$voice = userConfig.voice) === null || _userConfig$voice === void 0 ? void 0 : _userConfig$voice.micButtonColor) || ((_userConfig$panel7 = userConfig.panel) === null || _userConfig$panel7 === void 0 ? void 0 : _userConfig$panel7.micButtonColor) || primaryColor,
29425
+ micButtonActiveColor: ((_userConfig$voice2 = userConfig.voice) === null || _userConfig$voice2 === void 0 ? void 0 : _userConfig$voice2.micButtonActiveColor) || ((_userConfig$panel8 = userConfig.panel) === null || _userConfig$panel8 === void 0 ? void 0 : _userConfig$panel8.micButtonActiveColor) || '#EF4444',
29426
+ // Voice button hint text (below button)
29427
+ micButtonHint: _objectSpread(_objectSpread({
29428
+ text: ((_userConfig$voice3 = userConfig.voice) === null || _userConfig$voice3 === void 0 || (_userConfig$voice3 = _userConfig$voice3.micButtonHint) === null || _userConfig$voice3 === void 0 ? void 0 : _userConfig$voice3.text) || ((_userConfig$panel9 = userConfig.panel) === null || _userConfig$panel9 === void 0 || (_userConfig$panel9 = _userConfig$panel9.micButtonHint) === null || _userConfig$panel9 === void 0 ? void 0 : _userConfig$panel9.text) || 'Click the button to start voice conversation',
29429
+ color: ((_userConfig$voice4 = userConfig.voice) === null || _userConfig$voice4 === void 0 || (_userConfig$voice4 = _userConfig$voice4.micButtonHint) === null || _userConfig$voice4 === void 0 ? void 0 : _userConfig$voice4.color) || ((_userConfig$panel0 = userConfig.panel) === null || _userConfig$panel0 === void 0 || (_userConfig$panel0 = _userConfig$panel0.micButtonHint) === null || _userConfig$panel0 === void 0 ? void 0 : _userConfig$panel0.color) || '#6B7280',
29430
+ fontSize: ((_userConfig$voice5 = userConfig.voice) === null || _userConfig$voice5 === void 0 || (_userConfig$voice5 = _userConfig$voice5.micButtonHint) === null || _userConfig$voice5 === void 0 ? void 0 : _userConfig$voice5.fontSize) || ((_userConfig$panel1 = userConfig.panel) === null || _userConfig$panel1 === void 0 || (_userConfig$panel1 = _userConfig$panel1.micButtonHint) === null || _userConfig$panel1 === void 0 ? void 0 : _userConfig$panel1.fontSize) || '12px'
29431
+ }, (_userConfig$voice6 = userConfig.voice) === null || _userConfig$voice6 === void 0 ? void 0 : _userConfig$voice6.micButtonHint), (_userConfig$panel10 = userConfig.panel) === null || _userConfig$panel10 === void 0 ? void 0 : _userConfig$panel10.micButtonHint),
29432
+ // Voice interface colors
29433
+ avatarBackgroundColor: ((_userConfig$voice7 = userConfig.voice) === null || _userConfig$voice7 === void 0 ? void 0 : _userConfig$voice7.avatarBackgroundColor) || '#667eea',
29434
+ avatarActiveBackgroundColor: ((_userConfig$voice8 = userConfig.voice) === null || _userConfig$voice8 === void 0 ? void 0 : _userConfig$voice8.avatarActiveBackgroundColor) || '#667eea',
29435
+ statusTitleColor: ((_userConfig$voice9 = userConfig.voice) === null || _userConfig$voice9 === void 0 ? void 0 : _userConfig$voice9.statusTitleColor) || '#1e293b',
29436
+ statusSubtitleColor: ((_userConfig$voice0 = userConfig.voice) === null || _userConfig$voice0 === void 0 ? void 0 : _userConfig$voice0.statusSubtitleColor) || '#64748b',
29437
+ statusDotColor: ((_userConfig$voice1 = userConfig.voice) === null || _userConfig$voice1 === void 0 ? void 0 : _userConfig$voice1.statusDotColor) || '#10b981',
29438
+ statusText: ((_userConfig$voice10 = userConfig.voice) === null || _userConfig$voice10 === void 0 ? void 0 : _userConfig$voice10.statusText) || null,
29439
+ startCallButtonColor: ((_userConfig$voice11 = userConfig.voice) === null || _userConfig$voice11 === void 0 ? void 0 : _userConfig$voice11.startCallButtonColor) || '#667eea',
29440
+ startCallButtonTextColor: ((_userConfig$voice12 = userConfig.voice) === null || _userConfig$voice12 === void 0 ? void 0 : _userConfig$voice12.startCallButtonTextColor) || '#FFFFFF',
29441
+ startCallTitle: ((_userConfig$voice13 = userConfig.voice) === null || _userConfig$voice13 === void 0 ? void 0 : _userConfig$voice13.startCallTitle) || null,
29442
+ startCallSubtitle: ((_userConfig$voice14 = userConfig.voice) === null || _userConfig$voice14 === void 0 ? void 0 : _userConfig$voice14.startCallSubtitle) || null,
29443
+ startCallButtonText: ((_userConfig$voice15 = userConfig.voice) === null || _userConfig$voice15 === void 0 ? void 0 : _userConfig$voice15.startCallButtonText) || null,
29444
+ transcriptBackgroundColor: ((_userConfig$voice16 = userConfig.voice) === null || _userConfig$voice16 === void 0 ? void 0 : _userConfig$voice16.transcriptBackgroundColor) || '#FFFFFF',
29445
+ transcriptTextColor: ((_userConfig$voice17 = userConfig.voice) === null || _userConfig$voice17 === void 0 ? void 0 : _userConfig$voice17.transcriptTextColor) || '#1e293b',
29446
+ transcriptLabelColor: ((_userConfig$voice18 = userConfig.voice) === null || _userConfig$voice18 === void 0 ? void 0 : _userConfig$voice18.transcriptLabelColor) || '#94a3b8',
29447
+ // Live user STT line prefix (e.g. "You: "). null = use translation userTranscriptPrefix; '' = no prefix
29448
+ userTranscriptPrefix: (_userConfig$voice$use = (_userConfig$voice19 = userConfig.voice) === null || _userConfig$voice19 === void 0 ? void 0 : _userConfig$voice19.userTranscriptPrefix) !== null && _userConfig$voice$use !== void 0 ? _userConfig$voice$use : null,
29449
+ controlButtonColor: ((_userConfig$voice20 = userConfig.voice) === null || _userConfig$voice20 === void 0 ? void 0 : _userConfig$voice20.controlButtonColor) || '#FFFFFF',
29450
+ controlButtonSecondaryColor: ((_userConfig$voice21 = userConfig.voice) === null || _userConfig$voice21 === void 0 ? void 0 : _userConfig$voice21.controlButtonSecondaryColor) || '#64748b',
29451
+ endCallButtonColor: ((_userConfig$voice22 = userConfig.voice) === null || _userConfig$voice22 === void 0 ? void 0 : _userConfig$voice22.endCallButtonColor) || '#ef4444',
29452
+ // Voice language setting
29453
+ language: ((_userConfig$voice23 = userConfig.voice) === null || _userConfig$voice23 === void 0 ? void 0 : _userConfig$voice23.language) || userConfig.language || 'en'
29454
+ }, userConfig.voice), isNonEmptyConfigString(userConfig.headerAvatarImageUrl) && !isNonEmptyConfigString((_userConfig$voice24 = userConfig.voice) === null || _userConfig$voice24 === void 0 ? void 0 : _userConfig$voice24.headerAvatarImageUrl) ? {
29455
+ headerAvatarImageUrl: String(userConfig.headerAvatarImageUrl).trim()
29456
+ } : {});
29457
+ delete voiceOut.agentName;
29458
+ return voiceOut;
29459
+ }(),
29220
29460
  // Text-specific Configuration
29221
29461
  text: _objectSpread({
29222
29462
  // Send button colors (inside panel)
@@ -29314,8 +29554,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
29314
29554
  backgroundColor: cleanHeaderConfig.backgroundColor || '#7C3AED',
29315
29555
  // Default purple
29316
29556
  textColor: cleanHeaderConfig.textColor || '#FFFFFF',
29317
- showCloseButton: cleanHeaderConfig.showCloseButton !== false,
29318
- mobileLabel: cleanHeaderConfig.mobileLabel || 'Chat'
29557
+ showCloseButton: cleanHeaderConfig.showCloseButton !== false
29319
29558
  }, cleanHeaderConfig);
29320
29559
  return finalHeader;
29321
29560
  }(),
@@ -29386,9 +29625,8 @@ var TTPChatWidget = /*#__PURE__*/function () {
29386
29625
  autoConnect: ((_userConfig$behavior4 = userConfig.behavior) === null || _userConfig$behavior4 === void 0 ? void 0 : _userConfig$behavior4.autoConnect) || false,
29387
29626
  showWelcomeMessage: ((_userConfig$behavior5 = userConfig.behavior) === null || _userConfig$behavior5 === void 0 ? void 0 : _userConfig$behavior5.showWelcomeMessage) !== false,
29388
29627
  welcomeMessage: ((_userConfig$behavior6 = userConfig.behavior) === null || _userConfig$behavior6 === void 0 ? void 0 : _userConfig$behavior6.welcomeMessage) || 'Hello! How can I help you today?',
29389
- // Voice selection landing (enabled by default)
29390
29628
  enableVoiceMode: ((_userConfig$behavior7 = userConfig.behavior) === null || _userConfig$behavior7 === void 0 ? void 0 : _userConfig$behavior7.enableVoiceMode) !== undefined ? userConfig.behavior.enableVoiceMode : true,
29391
- // Widget mode: 'unified' (both voice and text with landing screen), 'voice-only' (only voice), 'text-only' (only text)
29629
+ // Widget mode: 'unified' (voice hero + text chat in panel; mobile pre-chat overlay), 'voice-only', 'text-only'
29392
29630
  mode: ((_userConfig$behavior8 = userConfig.behavior) === null || _userConfig$behavior8 === void 0 ? void 0 : _userConfig$behavior8.mode) || 'unified'
29393
29631
  }, userConfig.behavior),
29394
29632
  // Accessibility Configuration
@@ -29470,6 +29708,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
29470
29708
  // The actual button and panel have pointer-events: auto to receive clicks
29471
29709
  // Using width/height 100% ensures fixed-position children have proper containing block
29472
29710
  host.style.cssText = 'position: fixed; z-index: 10000; pointer-events: none; top: 0; left: 0; width: 100%; height: 100%; overflow: visible;';
29711
+ host.setAttribute('dir', this.getEffectiveTextDirection());
29473
29712
 
29474
29713
  // Attach shadow DOM
29475
29714
  this.shadowRoot = host.attachShadow({
@@ -29498,6 +29737,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
29498
29737
  // Container covers viewport but is click-through (pointer-events: none)
29499
29738
  // The actual button and panel have pointer-events: auto to receive clicks
29500
29739
  container.style.cssText = 'position: fixed; z-index: 10000; pointer-events: none; top: 0; left: 0; width: 100%; height: 100%; overflow: visible;';
29740
+ container.setAttribute('dir', this.getEffectiveTextDirection());
29501
29741
 
29502
29742
  // Append container to body
29503
29743
  document.body.appendChild(container);
@@ -29529,7 +29769,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
29529
29769
  resetCSS = "\n :host {\n all: initial".concat(important, ";\n display: block").concat(important, ";\n pointer-events: none").concat(important, ";\n }\n img {\n max-width: none !important;\n }\n #text-chat-button img {\n width: 22px !important;\n height: 22px !important;\n }\n #text-chat-button {\n pointer-events: auto").concat(important, ";\n }\n #text-chat-panel {\n pointer-events: auto").concat(important, ";\n }\n .ttp-mobile-fab {\n pointer-events: auto").concat(important, ";\n }\n #ttpMobileLanding {\n pointer-events: auto").concat(important, ";\n }\n ");
29530
29770
  } else {
29531
29771
  // Regular DOM mode - targeted reset without breaking widget styles
29532
- resetCSS = "\n /* Reset only problematic inherited styles, not all styles */\n #text-chat-button,\n #text-chat-panel,\n #text-chat-panel * {\n box-sizing: border-box".concat(important, ";\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif").concat(important, ";\n }\n \n /* Theme often sets img { max-width: 100% } which squashes widget art.\n Do NOT set width/height: auto on all #text-chat-panel img \u2014 that uses\n !important and overrides ecommerce card images (.ttp-product-image img\n needs width/height 100% + object-fit), which shows as empty/blank tiles. */\n #text-chat-panel img {\n max-width: none").concat(important, ";\n }\n \n #text-chat-button img {\n max-width: none").concat(important, ";\n width: 22px !important;\n height: 22px !important;\n }\n \n /* Ensure button and panel can receive clicks */\n #text-chat-button,\n #text-chat-panel,\n .ttp-mobile-fab,\n #ttpMobileLanding {\n pointer-events: auto").concat(important, ";\n }\n \n /* Reset any inherited text styles that might break layout */\n #text-chat-panel {\n text-align: left").concat(important, ";\n line-height: normal").concat(important, ";\n letter-spacing: normal").concat(important, ";\n word-spacing: normal").concat(important, ";\n text-transform: none").concat(important, ";\n text-indent: 0").concat(important, ";\n text-shadow: none").concat(important, ";\n white-space: normal").concat(important, ";\n }\n \n /* Flex layout for shell only \u2014 do NOT force display on .landing-screen /\n .voice-interface / .text-interface: #text-chat-panel + class beats\n component rules and keeps all three visible (breaks Shopify / useShadowDOM: false). */\n #text-chat-panel .widget-shell,\n #text-chat-panel .panel-inner,\n #text-chat-panel .widget-container,\n #text-chat-panel .widget-header,\n #text-chat-panel .mode-selection {\n display: flex").concat(important, ";\n }\n \n #text-chat-panel .widget-shell,\n #text-chat-panel .panel-inner,\n #text-chat-panel .widget-container {\n flex-direction: column").concat(important, ";\n }\n \n #text-chat-panel .mode-selection {\n flex-direction: row").concat(important, ";\n }\n \n /* Ensure proper stacking */\n #text-chat-button {\n z-index: 10001 !important;\n }\n \n #text-chat-panel {\n z-index: 10000 !important;\n }\n ");
29772
+ resetCSS = "\n /* Reset only problematic inherited styles, not all styles */\n #text-chat-button,\n #text-chat-panel,\n #text-chat-panel * {\n box-sizing: border-box".concat(important, ";\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif").concat(important, ";\n }\n \n /* Theme often sets img { max-width: 100% } which squashes widget art.\n Do NOT set width/height: auto on all #text-chat-panel img \u2014 that uses\n !important and overrides ecommerce card images (.ttp-product-image img\n needs width/height 100% + object-fit), which shows as empty/blank tiles. */\n #text-chat-panel img {\n max-width: none").concat(important, ";\n }\n \n #text-chat-button img {\n max-width: none").concat(important, ";\n width: 22px !important;\n height: 22px !important;\n }\n \n /* Ensure button and panel can receive clicks */\n #text-chat-button,\n #text-chat-panel,\n .ttp-mobile-fab,\n #ttpMobileLanding {\n pointer-events: auto").concat(important, ";\n }\n \n /* Reset any inherited text styles that might break layout */\n #text-chat-panel {\n text-align: left").concat(important, ";\n line-height: normal").concat(important, ";\n letter-spacing: normal").concat(important, ";\n word-spacing: normal").concat(important, ";\n text-transform: none").concat(important, ";\n text-indent: 0").concat(important, ";\n text-shadow: none").concat(important, ";\n white-space: normal").concat(important, ";\n }\n \n /* Flex layout for shell only \u2014 do NOT force display on .voice-interface /\n .text-interface: #text-chat-panel + class beats component rules and keeps\n both visible (breaks Shopify / useShadowDOM: false). */\n #text-chat-panel .widget-shell,\n #text-chat-panel .panel-inner,\n #text-chat-panel .widget-container,\n #text-chat-panel .widget-header {\n display: flex").concat(important, ";\n }\n \n #text-chat-panel .widget-shell,\n #text-chat-panel .panel-inner,\n #text-chat-panel .widget-container {\n flex-direction: column").concat(important, ";\n }\n \n /* Ensure proper stacking */\n #text-chat-button {\n z-index: 10001 !important;\n }\n \n #text-chat-panel {\n z-index: 10000 !important;\n }\n ");
29533
29773
  }
29534
29774
  var widgetHTML = this.generateWidgetHTML();
29535
29775
  if (this.config.useShadowDOM) {
@@ -29543,12 +29783,12 @@ var TTPChatWidget = /*#__PURE__*/function () {
29543
29783
  }
29544
29784
  this.setupWidgetEvents();
29545
29785
 
29546
- // On desktop, default to voice view (skip landing screen)
29547
- if (window.innerWidth > 768 && this.currentView === 'landing') {
29786
+ // On desktop, ensure voice hero is shown for unified/voice-only (in-panel mode picker removed)
29787
+ if (window.innerWidth > 768) {
29548
29788
  var _this$config$behavior3;
29549
29789
  var widgetMode = ((_this$config$behavior3 = this.config.behavior) === null || _this$config$behavior3 === void 0 ? void 0 : _this$config$behavior3.mode) || 'unified';
29550
- var showVoice = widgetMode === 'unified' || widgetMode === 'voice-only';
29551
- if (showVoice) {
29790
+ var preferVoice = widgetMode === 'unified' || widgetMode === 'voice-only';
29791
+ if (preferVoice && this.currentView !== 'text') {
29552
29792
  this.showVoice();
29553
29793
  }
29554
29794
  }
@@ -29644,8 +29884,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
29644
29884
  key: "generateWidgetHTML",
29645
29885
  value: function generateWidgetHTML() {
29646
29886
  var _this$config$behavior4,
29647
- _this6 = this,
29648
- _this$config$icon2;
29887
+ _this6 = this;
29649
29888
  var pos = this.config.position;
29650
29889
  var btn = this.config.button;
29651
29890
  var icon = this.config.icon;
@@ -29673,11 +29912,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
29673
29912
 
29674
29913
  // Generate position styles
29675
29914
  var positionStyles = this.generatePositionStyles();
29676
-
29677
- // Generate icon HTML
29678
- var iconHTML = this.generateIconHTML(iconSize);
29679
29915
  var widgetMode = ((_this$config$behavior4 = this.config.behavior) === null || _this$config$behavior4 === void 0 ? void 0 : _this$config$behavior4.mode) || 'unified';
29680
- var showLanding = widgetMode === 'unified';
29681
29916
  var showVoice = widgetMode === 'unified' || widgetMode === 'voice-only';
29682
29917
  var showText = widgetMode === 'unified' || widgetMode === 'text-only';
29683
29918
  var voiceEnabled = showVoice;
@@ -29721,7 +29956,15 @@ var TTPChatWidget = /*#__PURE__*/function () {
29721
29956
  isPromptEnabled: isPromptEnabled,
29722
29957
  willGenerateHTML: !!promptBubbleHTML
29723
29958
  });
29724
- 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 <!-- Desktop pill launcher (hidden on mobile) -->\n <button type=\"button\" id=\"text-chat-button\" aria-label=\"Open chat with ").concat(header.title || 'Assistant', "\">\n <div class=\"ttp-pill-icon\">\n <img class=\"ttp-launcher-logo\" src=\"").concat(((_this$config$icon2 = this.config.icon) === null || _this$config$icon2 === void 0 ? void 0 : _this$config$icon2.customImage) || 'https://talktopc.com/logo192.png', "\" alt=\"\" />\n </div>\n <div class=\"ttp-pill-text\">\n <span class=\"ttp-pill-title\">").concat(header.title || 'Assistant', "</span>\n <span class=\"ttp-pill-status\">\n <span class=\"ttp-launcher-dot\"></span>\n ").concat(header.onlineIndicatorText !== undefined && header.onlineIndicatorText !== null ? header.onlineIndicatorText : t('online'), "\n </span>\n </div>\n </button>\n <!-- Mobile FAB (hidden on desktop) -->\n <button class=\"ttp-mobile-fab\" aria-label=\"").concat(this.config.accessibility.ariaLabel, "\">\n <div class=\"ttp-mobile-fab__icon-wrap\">\n <div class=\"ttp-mobile-fab__waveform\">\n <span class=\"bar\"></span><span class=\"bar\"></span><span class=\"bar\"></span><span class=\"bar\"></span><span class=\"bar\"></span>\n </div>\n </div>\n <div class=\"ttp-mobile-fab__label-wrap\">\n <span class=\"ttp-mobile-fab__label\">").concat(header.mobileLabel || 'Chat', "</span>\n <span class=\"ttp-mobile-fab__status\">\n <span class=\"ttp-mobile-fab__dot\"></span>\n ").concat(header.onlineIndicatorText !== undefined && header.onlineIndicatorText !== null ? header.onlineIndicatorText : t('online'), "\n </span>\n </div>\n </button>\n </div>\n "), "\n\n ").concat(this.config.behavior.hidden ? '' : "\n <div id=\"ttpMobileLanding\" class=\"ttp-mobile-landing\">\n <div class=\"ttp-mobile-landing__header\">\n <div class=\"ttp-mobile-landing__avatar\">\n <div class=\"ttp-mobile-landing__waveform\">\n <span class=\"bar\"></span><span class=\"bar\"></span><span class=\"bar\"></span><span class=\"bar\"></span><span class=\"bar\"></span>\n </div>\n </div>\n <div class=\"ttp-mobile-landing__info\">\n <div class=\"ttp-mobile-landing__name\">".concat(header.title || 'Chat Assistant', "</div>\n <div class=\"ttp-mobile-landing__status\">\n <span class=\"ttp-mobile-landing__dot\"></span>\n ").concat(this.config.landing.statusText || t('online') + ' • ' + (this.config.landing.subtitle || 'Ready to help'), "\n </div>\n </div>\n <button class=\"ttp-mobile-landing__close\" aria-label=\"Close\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\n </svg>\n </button>\n </div>\n <div class=\"ttp-mobile-landing__error\" id=\"ttpMobileLandingError\" style=\"display:none;\">\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"/><line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"/>\n </svg>\n <span class=\"ttp-mobile-landing__error-text\"></span>\n </div>\n <div class=\"ttp-mobile-landing__actions\">\n ").concat(showVoice ? "\n <button class=\"ttp-mobile-landing__btn ttp-mobile-landing__btn--call\" id=\"ttpMobileCallBtn\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.127.96.361 1.903.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0 1 22 16.92z\"/>\n </svg>\n ".concat(this.config.landing.callButtonText || this.config.landing.voiceCardTitle || t('voiceCall'), "\n </button>\n ") : '', "\n ").concat(showText ? "\n <button class=\"ttp-mobile-landing__btn ttp-mobile-landing__btn--text\" id=\"ttpMobileChatBtn\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"/>\n </svg>\n ".concat(this.config.landing.chatButtonText || this.config.landing.textCardTitle || t('textChat'), "\n </button>\n ") : '', "\n </div>\n ").concat(this.config.footer.show !== false ? "\n <div class=\"ttp-mobile-landing__footer\">\n <div class=\"ttp-mobile-landing__powered\">\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" width=\"10\" height=\"10\">\n <polygon points=\"13 2 3 14 12 14 11 22 21 10 12 10 13 2\"/>\n </svg>\n Powered by <a href=\"https://talktopc.com\" target=\"_blank\" rel=\"noopener\">TalkToPC</a>\n </div>\n </div>\n " : '', "\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\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 ");
29959
+ var pillTitle = header.pillTitle != null && String(header.pillTitle).trim() !== '' ? String(header.pillTitle).trim() : header.title || 'Assistant';
29960
+ /* Mobile FAB: optional header.mobileLabel; otherwise same main line as desktop pill (pillTitle). Not header.mobileLabel default 'Chat' — that hid pillTitle. */
29961
+ var mobileFabLabel = header.mobileLabel != null && String(header.mobileLabel).trim() !== '' ? String(header.mobileLabel).trim() : pillTitle;
29962
+ var mobileLandingHeroName = this.config.agentName != null && String(this.config.agentName).trim() !== '' ? String(this.config.agentName).trim() : header.title || 'Chat Assistant';
29963
+ var pillCustomImage = icon.customImage != null && String(icon.customImage).trim() !== '' ? String(icon.customImage).trim() : null;
29964
+ var pillWaveformBars = '<span class="bar"></span><span class="bar"></span><span class="bar"></span><span class="bar"></span><span class="bar"></span>';
29965
+ var pillIconInner = pillCustomImage ? "<img class=\"ttp-launcher-logo\" src=\"".concat(pillCustomImage, "\" alt=\"\" />") : "<div class=\"ttp-pill-waveform\" aria-hidden=\"true\">".concat(pillWaveformBars, "</div>");
29966
+ var pillIconWrapClass = pillCustomImage ? 'ttp-pill-icon' : 'ttp-pill-icon ttp-pill-icon--wave';
29967
+ 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 <!-- Desktop pill launcher (hidden on mobile) -->\n <button type=\"button\" id=\"text-chat-button\" aria-label=\"Open chat with ").concat(pillTitle, "\">\n <div class=\"").concat(pillIconWrapClass, "\">\n ").concat(pillIconInner, "\n </div>\n <div class=\"ttp-pill-text\">\n <span class=\"ttp-pill-title\">").concat(pillTitle, "</span>\n <span class=\"ttp-pill-status\">\n <span class=\"ttp-launcher-dot\"></span>\n ").concat(header.onlineIndicatorText !== undefined && header.onlineIndicatorText !== null ? header.onlineIndicatorText : t('online'), "\n </span>\n </div>\n </button>\n <!-- Mobile FAB (hidden on desktop) -->\n <button class=\"ttp-mobile-fab\" aria-label=\"").concat(this.config.accessibility.ariaLabel, "\">\n <div class=\"ttp-mobile-fab__icon-wrap\">\n <div class=\"ttp-mobile-fab__waveform\">\n <span class=\"bar\"></span><span class=\"bar\"></span><span class=\"bar\"></span><span class=\"bar\"></span><span class=\"bar\"></span>\n </div>\n </div>\n <div class=\"ttp-mobile-fab__label-wrap\">\n <span class=\"ttp-mobile-fab__label\">").concat(mobileFabLabel, "</span>\n <span class=\"ttp-mobile-fab__status\">\n <span class=\"ttp-mobile-fab__dot\"></span>\n ").concat(header.onlineIndicatorText !== undefined && header.onlineIndicatorText !== null ? header.onlineIndicatorText : t('online'), "\n </span>\n </div>\n </button>\n </div>\n "), "\n\n ").concat(this.config.behavior.hidden ? '' : "\n <div id=\"ttpMobileLanding\" class=\"ttp-mobile-landing\">\n <div class=\"ttp-mobile-landing__header\">\n <div class=\"ttp-mobile-landing__avatar\">\n <div class=\"ttp-mobile-landing__waveform\">\n <span class=\"bar\"></span><span class=\"bar\"></span><span class=\"bar\"></span><span class=\"bar\"></span><span class=\"bar\"></span>\n </div>\n </div>\n <div class=\"ttp-mobile-landing__info\">\n <div class=\"ttp-mobile-landing__name\">".concat(mobileLandingHeroName, "</div>\n <div class=\"ttp-mobile-landing__status\">\n <span class=\"ttp-mobile-landing__dot\"></span>\n ").concat(this.config.landing.statusText || t('online') + ' • ' + (this.config.landing.subtitle || 'Ready to help'), "\n </div>\n </div>\n <button class=\"ttp-mobile-landing__close\" aria-label=\"Close\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\n </svg>\n </button>\n </div>\n <div class=\"ttp-mobile-landing__error\" id=\"ttpMobileLandingError\" style=\"display:none;\">\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"/><line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"/>\n </svg>\n <span class=\"ttp-mobile-landing__error-text\"></span>\n </div>\n <div class=\"ttp-mobile-landing__actions\">\n ").concat(showVoice ? "\n <button class=\"ttp-mobile-landing__btn ttp-mobile-landing__btn--call\" id=\"ttpMobileCallBtn\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.127.96.361 1.903.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0 1 22 16.92z\"/>\n </svg>\n ".concat(this.config.landing.callButtonText || this.config.landing.voiceCardTitle || t('voiceCall'), "\n </button>\n ") : '', "\n ").concat(showText ? "\n <button class=\"ttp-mobile-landing__btn ttp-mobile-landing__btn--text\" id=\"ttpMobileChatBtn\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"/>\n </svg>\n ".concat(this.config.landing.chatButtonText || this.config.landing.textCardTitle || t('textChat'), "\n </button>\n ") : '', "\n </div>\n ").concat(this.config.footer.show !== false ? "\n <div class=\"ttp-mobile-landing__footer\">\n <div class=\"ttp-mobile-landing__powered\">\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" width=\"10\" height=\"10\">\n <polygon points=\"13 2 3 14 12 14 11 22 21 10 12 10 13 2\"/>\n </svg>\n Powered by <a href=\"https://talktopc.com\" target=\"_blank\" rel=\"noopener\">TalkToPC</a>\n </div>\n </div>\n " : '', "\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\n ").concat(showVoice ? this.voiceInterface.generateHTML() : '', "\n ").concat(showText ? this.textInterface.generateHTML() : '', "\n ").concat(this.generateFooterHTML(), "\n </div>\n </div>\n </div>\n ");
29725
29968
  }
29726
29969
 
29727
29970
  /**
@@ -29771,7 +30014,10 @@ var TTPChatWidget = /*#__PURE__*/function () {
29771
30014
  var icon = this.config.icon;
29772
30015
  switch (icon.type) {
29773
30016
  case 'custom':
29774
- return "<img src=\"".concat(icon.customImage, "\" alt=\"Chat Assistant\" style=\"width: ").concat(size, "px; height: ").concat(size, "px; object-fit: contain;\" />");
30017
+ if (icon.customImage != null && String(icon.customImage).trim() !== '') {
30018
+ return "<img src=\"".concat(icon.customImage, "\" alt=\"Chat Assistant\" style=\"width: ").concat(size, "px; height: ").concat(size, "px; object-fit: contain;\" />");
30019
+ }
30020
+ return "<div class=\"ttp-pill-waveform\" aria-hidden=\"true\"><span class=\"bar\"></span><span class=\"bar\"></span><span class=\"bar\"></span><span class=\"bar\"></span><span class=\"bar\"></span></div>";
29775
30021
  case 'emoji':
29776
30022
  return "<span style=\"font-size: ".concat(size, "px; line-height: 1;\">").concat(icon.emoji, "</span>");
29777
30023
  case 'text':
@@ -29837,7 +30083,6 @@ var TTPChatWidget = /*#__PURE__*/function () {
29837
30083
 
29838
30084
  // Determine which interfaces to show
29839
30085
  var widgetMode = ((_this$config$behavior5 = this.config.behavior) === null || _this$config$behavior5 === void 0 ? void 0 : _this$config$behavior5.mode) || 'unified';
29840
- var showLanding = widgetMode === 'unified';
29841
30086
  var showVoice = widgetMode === 'unified' || widgetMode === 'voice-only';
29842
30087
  var showText = widgetMode === 'unified' || widgetMode === 'text-only';
29843
30088
 
@@ -29852,20 +30097,18 @@ var TTPChatWidget = /*#__PURE__*/function () {
29852
30097
 
29853
30098
  // Detect light vs dark panel background for adaptive footer
29854
30099
  var panelBg = panel.backgroundColor || '#16161e';
29855
- var isLightPanel = function () {
29856
- if (!panelBg || panelBg.charAt(0) !== '#') return false;
29857
- var r = parseInt(panelBg.substr(1, 2), 16);
29858
- var g = parseInt(panelBg.substr(3, 2), 16);
29859
- var b = parseInt(panelBg.substr(5, 2), 16);
29860
- return (r * 299 + g * 587 + b * 114) / 1000 > 160;
29861
- }();
30100
+ var isLightPanel = computeIsLightPanel(panelBg);
29862
30101
  var footerTextColor = isLightPanel ? 'rgba(0,0,0,0.4)' : 'rgba(255,255,255,0.35)';
29863
- var footerLinkColor = isLightPanel ? voice.primaryBtnGradient1 || '#7C3AED' : '#a78bfa';
30102
+ var footerLinkColor = talkToPcLinkColorForPanel(isLightPanel, voice, this._rawConfig, showVoice);
29864
30103
  var footerBorderColor = isLightPanel ? 'rgba(0,0,0,0.08)' : 'rgba(255,255,255,0.06)';
29865
30104
  var idleHeroGrad1 = voice.heroGradient1 || '#2a2550';
29866
30105
  var idleHeroGrad2 = voice.heroGradient2 || '#1a1a2e';
30106
+ var callSurfaceGradient = "linear-gradient(160deg, ".concat(idleHeroGrad1, " 0%, ").concat(idleHeroGrad2, " 100%)");
30107
+ /** In-call panel/footer: same gradient as idle so active call matches landing (hero1 → hero2) */
30108
+ var callActivePanelBg = callSurfaceGradient;
29867
30109
  var voiceIdleVisibleSelector = '#voiceInterface.active #voiceIdleState:not([style*="display: none"]):not([style*="display:none"])';
29868
- return "\n /* Inline style display overrides - ensures JS show/hide works with !important CSS */\n #text-chat-panel [style*=\"display: none\"],\n #text-chat-panel [style*=\"display:none\"],\n #text-chat-button-container [style*=\"display: none\"],\n #text-chat-button-container [style*=\"display:none\"],\n #ttpMobileLanding[style*=\"display: none\"],\n #ttpMobileLanding[style*=\"display:none\"] {\n display: none !important;\n }\n #text-chat-panel [style*=\"display: flex\"],\n #text-chat-panel [style*=\"display:flex\"],\n #text-chat-button-container [style*=\"display: flex\"],\n #text-chat-button-container [style*=\"display:flex\"] {\n display: flex !important;\n }\n #text-chat-panel [style*=\"display: block\"],\n #text-chat-panel [style*=\"display:block\"] {\n display: block !important;\n }\n\n /* MOBILE FIRST - Default styles for all devices */\n #text-chat-widget {\n position: fixed !important;\n z-index: 10000".concat(important, ";\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif").concat(important, ";\n /* Mobile defaults */\n right: 10px").concat(important, ";\n bottom: 10px").concat(important, ";\n left: auto").concat(important, ";\n top: auto").concat(important, ";\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').concat(important, ";\n left: ").concat(this.config.position.horizontal === 'left' ? '20px' : 'auto').concat(important, ";\n bottom: ").concat(this.config.position.vertical === 'bottom' ? '20px' : 'auto').concat(important, ";\n top: ").concat(this.config.position.vertical === 'top' ? '20px' : 'auto').concat(important, ";\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 /* \u2500\u2500 Desktop Pill Launcher \u2500\u2500 */\n #text-chat-button {\n position: relative").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 10px").concat(important, ";\n padding: 7px 16px 7px 7px").concat(important, ";\n z-index: 1").concat(important, ";\n background: ").concat(pillGradient, ";\n border: 1px solid rgba(139,92,246,0.15)").concat(important, ";\n border-radius: 999px").concat(important, ";\n box-shadow: 0 8px 32px rgba(0,0,0,0.25), 0 2px 8px rgba(0,0,0,0.15)").concat(important, ";\n cursor: pointer").concat(important, ";\n transition: box-shadow 0.25s, transform 0.2s, padding 0.3s, gap 0.3s").concat(important, ";\n font-family: inherit").concat(important, ";\n color: ").concat(pillTextColor, ";\n overflow: hidden").concat(important, ";\n }\n #text-chat-button:hover {\n transform: translateY(-1px)").concat(important, ";\n box-shadow: 0 10px 40px rgba(0,0,0,0.35), 0 4px 12px rgba(0,0,0,0.2)").concat(important, ";\n }\n #text-chat-button.open {\n gap: 0px").concat(important, ";\n padding: 7px").concat(important, ";\n }\n\n .ttp-pill-icon {\n width: 36px").concat(important, "; height: 36px").concat(important, "; border-radius: 50%").concat(important, ";\n background: #ffffff").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n .ttp-launcher-logo {\n width: 22px").concat(important, "; height: 22px").concat(important, "; border-radius: 50%").concat(important, ";\n object-fit: cover").concat(important, ";\n }\n\n .ttp-pill-text {\n display: flex").concat(important, "; flex-direction: column").concat(important, "; gap: 1px").concat(important, ";\n max-width: 120px").concat(important, ";\n opacity: 1").concat(important, ";\n overflow: hidden").concat(important, ";\n white-space: nowrap").concat(important, ";\n transition: max-width 0.3s, opacity 0.2s").concat(important, ";\n }\n #text-chat-button.open .ttp-pill-text {\n max-width: 0").concat(important, ";\n opacity: 0").concat(important, ";\n }\n .ttp-pill-title {\n font-size: 13px").concat(important, "; font-weight: 600").concat(important, "; color: ").concat(pillTextColor, ";\n line-height: 1.2").concat(important, ";\n }\n .ttp-pill-status {\n display: flex").concat(important, "; align-items: center").concat(important, "; gap: 5px").concat(important, ";\n font-size: 11px").concat(important, "; color: ").concat(pillTextColor, "8c;\n line-height: 1.2").concat(important, ";\n }\n\n /* Online dot (inside pill status) */\n .ttp-launcher-dot {\n width: 7px").concat(important, "; height: 7px").concat(important, "; border-radius: 50%").concat(important, ";\n background: ").concat(pillDotColor, ";\n flex-shrink: 0").concat(important, ";\n animation: ttp-dot-pulse 2s ease-in-out infinite").concat(important, ";\n }\n @keyframes ttp-dot-pulse { 0%,100%{opacity:1} 50%{opacity:.4} }\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: auto !important;\n height: auto !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").concat(important, ";\n min-height: 56px").concat(important, ";\n }\n \n #text-chat-panel .header-title {\n font-size: 15px").concat(important, ";\n }\n \n #text-chat-panel .header-icon {\n width: 40px").concat(important, ";\n height: 40px").concat(important, ";\n min-width: 40px").concat(important, ";\n min-height: 40px").concat(important, ";\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").concat(important, ";\n }\n \n .landing-logo {\n font-size: 40px").concat(important, ";\n }\n \n .landing-title {\n font-size: 18px").concat(important, ";\n margin-bottom: 16px").concat(important, ";\n }\n \n .mode-selection {\n flex-direction: column").concat(important, ";\n gap: 12px").concat(important, ";\n align-items: center").concat(important, ";\n }\n \n .mode-card {\n max-width: 100%").concat(important, ";\n width: 100%").concat(important, ";\n padding: 16px").concat(important, ";\n }\n \n .mode-card-icon {\n width: 50px").concat(important, ";\n height: 50px").concat(important, ";\n font-size: 28px").concat(important, ";\n }\n \n .mode-card-title {\n font-size: 14px").concat(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 #text-chat-button-container {\n width: auto !important;\n height: auto !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").concat(important, ";\n min-height: 52px").concat(important, ";\n }\n \n #text-chat-panel .header-title {\n font-size: 14px").concat(important, ";\n }\n \n .landing-logo {\n font-size: 36px").concat(important, ";\n }\n \n .landing-title {\n font-size: 16px").concat(important, ";\n }\n }\n \n ").concat(anim.enableHover ? "\n #text-chat-button:hover {\n transform: translateY(-1px);\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").concat(important, ";\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: auto").concat(important, ";\n height: auto").concat(important, ";\n z-index: 10001").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\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").concat(important, ";\n z-index: 10002").concat(important, ";\n pointer-events: none").concat(important, ";\n white-space: nowrap").concat(important, ";\n }\n \n .prompt-bubble.top {\n bottom: calc(100% + 18px)").concat(important, ";\n left: 50%").concat(important, ";\n transform: translateX(-50%)").concat(important, ";\n }\n \n .prompt-bubble.left {\n right: calc(100% + 12px)").concat(important, ";\n top: 50%").concat(important, ";\n transform: translateY(-50%)").concat(important, ";\n }\n \n .prompt-bubble.right {\n left: calc(100% + 12px)").concat(important, ";\n top: 50%").concat(important, ";\n transform: translateY(-50%)").concat(important, ";\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").concat(important, ";\n transform: translateX(-50%)").concat(important, "; /* Keep centering */\n }\n \n .prompt-bubble.top.animation-float {\n animation: widget-float 2s ease-in-out infinite").concat(important, ";\n transform: translateX(-50%)").concat(important, "; /* Keep centering */\n }\n \n .prompt-bubble.top.animation-pulse {\n animation: pulse 2s ease-in-out infinite").concat(important, ";\n transform: translateX(-50%)").concat(important, "; /* Keep centering */\n }\n \n .prompt-bubble-content {\n position: relative").concat(important, ";\n padding: 8px 16px").concat(important, ";\n border-radius: 20px").concat(important, ";\n font-weight: 500").concat(important, ";\n font-size: 14px").concat(important, ";\n box-shadow: 0 4px 15px rgba(124, 58, 237, 0.3)").concat(important, ";\n overflow: hidden").concat(important, ";\n }\n \n .prompt-bubble-shimmer {\n position: absolute").concat(important, ";\n inset: 0").concat(important, ";\n background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.25), transparent)").concat(important, ";\n animation: widget-shimmer 2s infinite").concat(important, ";\n }\n \n .prompt-bubble.animation-bounce {\n animation: widget-bounce 1s ease-in-out infinite").concat(important, ";\n }\n \n .prompt-bubble.animation-pulse {\n animation: pulse 2s ease-in-out infinite").concat(important, ";\n }\n \n .prompt-bubble.animation-float {\n animation: widget-float 2s ease-in-out infinite").concat(important, ";\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").concat(important, ";\n width: 0").concat(important, ";\n height: 0").concat(important, ";\n border: 8px solid transparent").concat(important, ";\n }\n \n .prompt-bubble.top .prompt-bubble-arrow {\n top: 100%").concat(important, ";\n left: 50%").concat(important, ";\n transform: translateX(-50%)").concat(important, ";\n border-top-color: var(--prompt-bubble-bg-color, #7c3aed)").concat(important, ";\n border-bottom: none").concat(important, ";\n margin-left: 0").concat(important, ";\n }\n \n .prompt-bubble.left .prompt-bubble-arrow {\n left: 100%").concat(important, ";\n top: 50%").concat(important, ";\n transform: translateY(-50%)").concat(important, ";\n border-left-color: var(--prompt-bubble-bg-color, #7c3aed)").concat(important, ";\n border-right: none").concat(important, ";\n }\n \n .prompt-bubble.right .prompt-bubble-arrow {\n right: 100%").concat(important, ";\n top: 50%").concat(important, ";\n transform: translateY(-50%)").concat(important, ";\n border-right-color: var(--prompt-bubble-bg-color, #7c3aed)").concat(important, ";\n border-left: none").concat(important, ";\n }\n \n /* Pulse Rings */\n .prompt-pulse-rings {\n position: absolute").concat(important, ";\n inset: 0").concat(important, ";\n border-radius: 50%").concat(important, ";\n pointer-events: none").concat(important, ";\n }\n \n .prompt-pulse-ring {\n position: absolute").concat(important, ";\n inset: 0").concat(important, ";\n border-radius: 50%").concat(important, ";\n animation: widget-pulse-ring 2s ease-out infinite").concat(important, ";\n }\n \n .prompt-pulse-ring:nth-child(2) {\n animation-delay: 0.5s").concat(important, ";\n }\n \n /* Mobile adjustments for prompt bubble */\n @media (max-width: 768px) {\n .prompt-bubble-content {\n font-size: 12px").concat(important, ";\n padding: 6px 12px").concat(important, ";\n }\n \n .prompt-bubble.top {\n bottom: calc(100% + 14px)").concat(important, ";\n }\n \n .prompt-bubble.left,\n .prompt-bubble.right {\n display: none").concat(important, "; /* Hide side prompts on mobile */\n }\n }\n \n #text-chat-panel {\n display: none").concat(important, ";\n position: fixed").concat(important, ";\n bottom: calc(54px + 24px)").concat(important, "; /* launcher pill + gap */\n ").concat(this.config.position.horizontal === 'right' ? 'right: 20px;' : 'left: 20px;', "\n width: 340px").concat(important, ";\n max-width: calc(100vw - 40px)").concat(important, ";\n height: auto").concat(important, ";\n max-height: calc(100vh - 100px)").concat(important, ";\n background: ").concat(panelBg, ";\n border-radius: 20px").concat(important, ";\n border: ").concat(panel.border || '1px solid rgba(255,255,255,0.08)', ";\n flex-direction: column").concat(important, ";\n overflow: hidden").concat(important, ";\n box-shadow: 0 24px 60px rgba(0,0,0,0.6)").concat(important, ";\n transform-origin: bottom right").concat(important, ";\n opacity: 0").concat(important, ";\n pointer-events: none").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n \n #text-chat-panel.open {\n display: flex").concat(important, ";\n opacity: 1").concat(important, ";\n pointer-events: auto").concat(important, ";\n }\n\n /* Shell for panel inner */\n .widget-shell { width: 100%").concat(important, "; padding: 0").concat(important, "; border-radius: 20px").concat(important, "; background: transparent").concat(important, "; overflow: hidden").concat(important, "; display: flex").concat(important, "; flex-direction: column").concat(important, "; box-sizing: border-box").concat(important, "; flex: 1").concat(important, "; min-height: 0").concat(important, "; }\n .panel-inner { width: 100%").concat(important, "; background: ").concat(panelBg, "; border-radius: 20px").concat(important, "; border: none").concat(important, "; overflow: hidden").concat(important, "; display:flex").concat(important, "; flex-direction: column").concat(important, "; padding: 0").concat(important, "; box-sizing: border-box").concat(important, "; max-width: 100%").concat(important, "; flex: 1").concat(important, "; min-height: 0").concat(important, "; }\n\n #text-chat-panel .widget-container {\n width: 100%").concat(important, "; background: ").concat(panelBg, "; overflow: visible").concat(important, "; display: flex").concat(important, "; flex-direction: column").concat(important, "; border-radius: 20px").concat(important, "; flex: 1").concat(important, "; min-height: 0").concat(important, ";\n }\n\n /* Voice idle: one gradient for voice UI + footer (Powered by), not a flat strip under buttons */\n #text-chat-panel.open:has(").concat(voiceIdleVisibleSelector, ") {\n background: linear-gradient(160deg, ").concat(idleHeroGrad1, " 0%, ").concat(idleHeroGrad2, " 100%)").concat(important, ";\n }\n #text-chat-panel .widget-container:has(").concat(voiceIdleVisibleSelector, ") {\n background: linear-gradient(160deg, ").concat(idleHeroGrad1, " 0%, ").concat(idleHeroGrad2, " 100%)").concat(important, ";\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").concat(important, ";\n overflow-y: auto").concat(important, ";\n overflow-x: visible").concat(important, "; /* Change from hidden to visible */\n }\n \n /* Header is removed in new design - hero serves as header */\n #text-chat-panel .widget-header { display: none").concat(important, "; }\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 .ttp-footer {\n padding: 6px 18px 10px").concat(important, ";\n border-top: 1px solid ").concat(footerBorderColor, ";\n display: flex").concat(important, ";\n justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n box-sizing: border-box").concat(important, ";\n background: transparent").concat(important, ";\n }\n .ttp-footer span { font-size: 10px").concat(important, "; color: ").concat(footerTextColor, "; }\n .ttp-footer a { color: ").concat(footerLinkColor, "; text-decoration: none").concat(important, "; font-weight: 600").concat(important, "; }\n .ttp-footer a:hover { opacity: 0.85").concat(important, "; }\n .ttp-footer a b { font-weight: 700").concat(important, "; }\n \n #text-chat-send-hint {\n text-align: center").concat(important, ";\n line-height: 1.4").concat(important, ";\n }\n \n .agent-thinking {\n font-style: italic").concat(important, ";\n color: #6B7280").concat(important, ";\n }\n\n /* ========================================\n MOBILE PILL BUTTON & LANDING OVERLAY\n Hidden on desktop, shown on mobile only\n ======================================== */\n .ttp-mobile-fab {\n display: none").concat(important, ";\n }\n\n .ttp-mobile-landing {\n display: none").concat(important, ";\n }\n\n @keyframes ttpWaveAnimation {\n 0%, 100% { transform: scaleY(0.4); }\n 50% { transform: scaleY(1); }\n }\n\n @keyframes ttpPulseAnimation {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n\n @media (max-width: 768px) {\n /* Hide desktop pill button on mobile */\n #text-chat-button {\n display: none !important;\n }\n\n /* Re-flow the container for pill shape */\n #text-chat-button-container {\n width: auto !important;\n height: auto !important;\n min-width: 0 !important;\n min-height: 0 !important;\n max-width: none !important;\n max-height: none !important;\n }\n\n /* Show mobile pill button */\n .ttp-mobile-fab {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 10px").concat(important, ";\n padding: 10px 16px 10px 12px").concat(important, ";\n background: ").concat(pillGradient, ";\n border: none").concat(important, ";\n border-radius: 24px").concat(important, ";\n cursor: pointer").concat(important, ";\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3)").concat(important, ";\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1)").concat(important, ";\n z-index: 1").concat(important, ";\n font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, sans-serif").concat(important, ";\n touch-action: manipulation").concat(important, ";\n -webkit-tap-highlight-color: transparent").concat(important, ";\n }\n\n .ttp-mobile-fab:hover {\n transform: translateY(-3px)").concat(important, ";\n box-shadow: 0 12px 32px rgba(0, 0, 0, 0.4)").concat(important, ";\n }\n\n .ttp-mobile-fab__icon-wrap {\n width: 36px").concat(important, ";\n height: 36px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background: rgba(255, 255, 255, 0.15)").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n\n .ttp-mobile-fab__waveform {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 2px").concat(important, ";\n height: 16px").concat(important, ";\n }\n\n .ttp-mobile-fab__waveform .bar {\n width: 2px").concat(important, ";\n background: #fff").concat(important, ";\n border-radius: 1px").concat(important, ";\n animation: ttpWaveAnimation 0.8s ease-in-out infinite").concat(important, ";\n }\n\n .ttp-mobile-fab__waveform .bar:nth-child(1) { height: 5px").concat(important, "; animation-delay: 0s").concat(important, "; }\n .ttp-mobile-fab__waveform .bar:nth-child(2) { height: 10px").concat(important, "; animation-delay: 0.1s").concat(important, "; }\n .ttp-mobile-fab__waveform .bar:nth-child(3) { height: 16px").concat(important, "; animation-delay: 0.2s").concat(important, "; }\n .ttp-mobile-fab__waveform .bar:nth-child(4) { height: 8px").concat(important, "; animation-delay: 0.3s").concat(important, "; }\n .ttp-mobile-fab__waveform .bar:nth-child(5) { height: 12px").concat(important, "; animation-delay: 0.4s").concat(important, "; }\n\n .ttp-mobile-fab__label-wrap {\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n align-items: flex-start").concat(important, ";\n gap: 1px").concat(important, ";\n }\n\n .ttp-mobile-fab__label {\n color: ").concat(pillTextColor, ";\n font-size: 14px").concat(important, ";\n font-weight: 600").concat(important, ";\n line-height: 1.2").concat(important, ";\n }\n\n .ttp-mobile-fab__status {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 4px").concat(important, ";\n font-size: 11px").concat(important, ";\n color: ").concat(pillTextColor, "b3;\n line-height: 1.2").concat(important, ";\n }\n\n .ttp-mobile-fab__dot {\n width: 6px").concat(important, ";\n height: 6px").concat(important, ";\n background: ").concat(pillDotColor, ";\n border-radius: 50%").concat(important, ";\n box-shadow: 0 0 6px ").concat(pillDotColor, "99;\n }\n\n /* ---- Mobile Landing Overlay ---- */\n .ttp-mobile-landing.active {\n display: block").concat(important, ";\n position: fixed").concat(important, ";\n bottom: 16px").concat(important, ";\n left: 12px").concat(important, ";\n right: 12px").concat(important, ";\n background: ").concat(pillGradient, ";\n border-radius: 20px").concat(important, ";\n overflow: hidden").concat(important, ";\n box-shadow:\n 0 10px 40px rgba(0, 0, 0, 0.3),\n 0 0 0 1px rgba(255, 255, 255, 0.1) inset").concat(important, ";\n z-index: 10002").concat(important, ";\n font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, sans-serif").concat(important, ";\n }\n\n .ttp-mobile-landing::before {\n content: ''").concat(important, ";\n position: absolute").concat(important, ";\n top: 0").concat(important, ";\n left: 0").concat(important, ";\n right: 0").concat(important, ";\n height: 1px").concat(important, ";\n background: linear-gradient(90deg,\n transparent 0%,\n rgba(255, 255, 255, 0.3) 50%,\n transparent 100%);\n }\n\n .ttp-mobile-landing__header {\n padding: 14px 16px").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 12px").concat(important, ";\n }\n\n .ttp-mobile-landing__avatar {\n width: 44px").concat(important, ";\n height: 44px").concat(important, ";\n border-radius: 12px").concat(important, ";\n background: rgba(255, 255, 255, 0.15)").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n\n .ttp-mobile-landing__waveform {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 3px").concat(important, ";\n height: 20px").concat(important, ";\n }\n\n .ttp-mobile-landing__waveform .bar {\n width: 3px").concat(important, ";\n background: rgba(255, 255, 255, 0.9)").concat(important, ";\n border-radius: 2px").concat(important, ";\n animation: ttpWaveAnimation 0.8s ease-in-out infinite").concat(important, ";\n }\n\n .ttp-mobile-landing__waveform .bar:nth-child(1) { height: 6px").concat(important, "; animation-delay: 0s").concat(important, "; }\n .ttp-mobile-landing__waveform .bar:nth-child(2) { height: 12px").concat(important, "; animation-delay: 0.1s").concat(important, "; }\n .ttp-mobile-landing__waveform .bar:nth-child(3) { height: 20px").concat(important, "; animation-delay: 0.2s").concat(important, "; }\n .ttp-mobile-landing__waveform .bar:nth-child(4) { height: 10px").concat(important, "; animation-delay: 0.3s").concat(important, "; }\n .ttp-mobile-landing__waveform .bar:nth-child(5) { height: 16px").concat(important, "; animation-delay: 0.4s").concat(important, "; }\n\n .ttp-mobile-landing__info {\n flex: 1").concat(important, ";\n min-width: 0").concat(important, ";\n }\n\n .ttp-mobile-landing__name {\n color: #fff").concat(important, ";\n font-size: 15px").concat(important, ";\n font-weight: 600").concat(important, ";\n margin-bottom: 2px").concat(important, ";\n }\n\n .ttp-mobile-landing__status {\n color: rgba(255, 255, 255, 0.7)").concat(important, ";\n font-size: 12px").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 5px").concat(important, ";\n }\n\n .ttp-mobile-landing__dot {\n width: 6px").concat(important, ";\n height: 6px").concat(important, ";\n background: ").concat(header.onlineIndicatorDotColor || '#10b981', ";\n border-radius: 50%").concat(important, ";\n animation: ttpPulseAnimation 2s ease-in-out infinite").concat(important, ";\n }\n\n .ttp-mobile-landing__close {\n width: 32px").concat(important, ";\n height: 32px").concat(important, ";\n border-radius: 10px").concat(important, ";\n background: rgba(255, 255, 255, 0.1)").concat(important, ";\n border: none").concat(important, ";\n color: rgba(255, 255, 255, 0.7)").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n cursor: pointer").concat(important, ";\n transition: all 0.2s").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n\n .ttp-mobile-landing__close:hover {\n background: rgba(255, 255, 255, 0.2)").concat(important, ";\n color: #fff").concat(important, ";\n }\n\n .ttp-mobile-landing__error {\n margin: 0 14px 10px").concat(important, ";\n padding: 10px 12px").concat(important, ";\n background: #fef2f2").concat(important, ";\n border: 1px solid #fecaca").concat(important, ";\n border-radius: 10px").concat(important, ";\n display: flex").concat(important, ";\n align-items: flex-start").concat(important, ";\n gap: 8px").concat(important, ";\n color: #b91c1c").concat(important, ";\n font-size: 13px").concat(important, ";\n line-height: 1.4").concat(important, ";\n }\n .ttp-mobile-landing__error svg {\n flex-shrink: 0").concat(important, ";\n margin-top: 1px").concat(important, ";\n stroke: #dc2626").concat(important, ";\n }\n\n .ttp-mobile-landing__actions {\n padding: 0 14px 14px").concat(important, ";\n display: flex").concat(important, ";\n gap: 10px").concat(important, ";\n }\n\n .ttp-mobile-landing__btn {\n flex: 1").concat(important, ";\n padding: 14px").concat(important, ";\n border-radius: 12px").concat(important, ";\n border: none").concat(important, ";\n cursor: pointer").concat(important, ";\n font-family: inherit").concat(important, ";\n font-size: 14px").concat(important, ";\n font-weight: 600").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n gap: 10px").concat(important, ";\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1)").concat(important, ";\n touch-action: manipulation").concat(important, ";\n -webkit-tap-highlight-color: transparent").concat(important, ";\n }\n\n .ttp-mobile-landing__btn svg {\n width: 20px").concat(important, ";\n height: 20px").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n\n .ttp-mobile-landing__btn--call {\n background: #fff").concat(important, ";\n color: ").concat(header.backgroundColor || '#7C3AED', ";\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15)").concat(important, ";\n }\n\n .ttp-mobile-landing__btn--call:hover {\n transform: translateY(-2px)").concat(important, ";\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2)").concat(important, ";\n }\n\n .ttp-mobile-landing__btn--text {\n background: rgba(255, 255, 255, 0.15)").concat(important, ";\n color: #fff").concat(important, ";\n border: 1px solid rgba(255, 255, 255, 0.1)").concat(important, ";\n }\n\n .ttp-mobile-landing__btn--text:hover {\n background: rgba(255, 255, 255, 0.2)").concat(important, ";\n border-color: rgba(255, 255, 255, 0.2)").concat(important, ";\n }\n\n .ttp-mobile-landing__footer {\n padding: 10px 16px").concat(important, ";\n display: flex").concat(important, ";\n justify-content: center").concat(important, ";\n border-top: 1px solid rgba(255, 255, 255, 0.08)").concat(important, ";\n }\n\n .ttp-mobile-landing__powered {\n color: rgba(255, 255, 255, 0.4)").concat(important, ";\n font-size: 11px").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 4px").concat(important, ";\n }\n\n .ttp-mobile-landing__powered svg {\n width: 10px").concat(important, ";\n height: 10px").concat(important, ";\n color: #f59e0b").concat(important, ";\n }\n\n .ttp-mobile-landing__powered a {\n color: rgba(255, 255, 255, 0.6)").concat(important, ";\n text-decoration: none").concat(important, ";\n }\n\n .ttp-mobile-landing__powered a:hover {\n color: #fff").concat(important, ";\n }\n }\n ");
30110
+ var voiceActiveVisibleSelector = '#voiceInterface.active #voiceActiveState:not([style*="display: none"]):not([style*="display:none"])';
30111
+ return "\n /* Inline style display overrides - ensures JS show/hide works with !important CSS */\n #text-chat-panel [style*=\"display: none\"],\n #text-chat-panel [style*=\"display:none\"],\n #text-chat-button-container [style*=\"display: none\"],\n #text-chat-button-container [style*=\"display:none\"],\n #ttpMobileLanding[style*=\"display: none\"],\n #ttpMobileLanding[style*=\"display:none\"] {\n display: none !important;\n }\n #text-chat-panel [style*=\"display: flex\"],\n #text-chat-panel [style*=\"display:flex\"],\n #text-chat-button-container [style*=\"display: flex\"],\n #text-chat-button-container [style*=\"display:flex\"] {\n display: flex !important;\n }\n #text-chat-panel [style*=\"display: block\"],\n #text-chat-panel [style*=\"display:block\"] {\n display: block !important;\n }\n\n /* MOBILE FIRST - Default styles for all devices */\n #text-chat-widget {\n position: fixed !important;\n z-index: 10000".concat(important, ";\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif").concat(important, ";\n /* Mobile defaults */\n right: 10px").concat(important, ";\n bottom: 10px").concat(important, ";\n left: auto").concat(important, ";\n top: auto").concat(important, ";\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').concat(important, ";\n left: ").concat(this.config.position.horizontal === 'left' ? '20px' : 'auto').concat(important, ";\n bottom: ").concat(this.config.position.vertical === 'bottom' ? '20px' : 'auto').concat(important, ";\n top: ").concat(this.config.position.vertical === 'top' ? '20px' : 'auto').concat(important, ";\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 /* \u2500\u2500 Desktop Pill Launcher \u2500\u2500 */\n #text-chat-button {\n position: relative").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 8px").concat(important, ";\n padding-block: 10px").concat(important, ";\n padding-inline-start: 6px").concat(important, ";\n padding-inline-end: 12px").concat(important, ";\n z-index: 1").concat(important, ";\n background: ").concat(pillGradient, ";\n border: 1px solid rgba(139,92,246,0.15)").concat(important, ";\n border-radius: 999px").concat(important, ";\n box-shadow: 0 8px 32px rgba(0,0,0,0.25), 0 2px 8px rgba(0,0,0,0.15)").concat(important, ";\n cursor: pointer").concat(important, ";\n transition: box-shadow 0.25s, transform 0.2s, padding 0.3s, gap 0.3s").concat(important, ";\n font-family: inherit").concat(important, ";\n color: ").concat(pillTextColor, ";\n overflow: hidden").concat(important, ";\n box-sizing: border-box").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n #text-chat-button:hover {\n transform: translateY(-1px)").concat(important, ";\n box-shadow: 0 10px 40px rgba(0,0,0,0.35), 0 4px 12px rgba(0,0,0,0.2)").concat(important, ";\n }\n #text-chat-button.open {\n gap: 0px").concat(important, ";\n padding: 9px").concat(important, ";\n width: auto").concat(important, ";\n min-width: 0").concat(important, ";\n max-width: none").concat(important, ";\n }\n\n @media (min-width: 769px) {\n #text-chat-button {\n width: 158px").concat(important, ";\n min-width: 158px").concat(important, ";\n max-width: 158px").concat(important, ";\n }\n }\n\n .ttp-pill-icon {\n width: 36px").concat(important, "; height: 36px").concat(important, "; border-radius: 50%").concat(important, ";\n background: #ffffff").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n .ttp-launcher-logo {\n width: 22px").concat(important, "; height: 22px").concat(important, "; border-radius: 50%").concat(important, ";\n object-fit: cover").concat(important, ";\n }\n\n /* Default pill launcher: same animated waveform as mobile FAB / landing */\n .ttp-pill-icon--wave {\n background: rgba(255, 255, 255, 0.15)").concat(important, ";\n }\n .ttp-pill-waveform {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 2px").concat(important, ";\n height: 16px").concat(important, ";\n }\n .ttp-pill-waveform .bar {\n width: 2px").concat(important, ";\n background: #fff").concat(important, ";\n border-radius: 1px").concat(important, ";\n animation: ttpWaveAnimation 0.8s ease-in-out infinite").concat(important, ";\n }\n .ttp-pill-waveform .bar:nth-child(1) { height: 5px").concat(important, "; animation-delay: 0s").concat(important, "; }\n .ttp-pill-waveform .bar:nth-child(2) { height: 10px").concat(important, "; animation-delay: 0.1s").concat(important, "; }\n .ttp-pill-waveform .bar:nth-child(3) { height: 16px").concat(important, "; animation-delay: 0.2s").concat(important, "; }\n .ttp-pill-waveform .bar:nth-child(4) { height: 8px").concat(important, "; animation-delay: 0.3s").concat(important, "; }\n .ttp-pill-waveform .bar:nth-child(5) { height: 12px").concat(important, "; animation-delay: 0.4s").concat(important, "; }\n\n .ttp-pill-text {\n display: flex").concat(important, "; flex-direction: column").concat(important, "; gap: 2px").concat(important, ";\n max-width: 82px").concat(important, ";\n opacity: 1").concat(important, ";\n overflow: hidden").concat(important, ";\n white-space: nowrap").concat(important, ";\n transition: max-width 0.3s, opacity 0.2s").concat(important, ";\n }\n #text-chat-button.open .ttp-pill-text {\n max-width: 0").concat(important, ";\n opacity: 0").concat(important, ";\n }\n .ttp-pill-title {\n font-size: 13px").concat(important, "; font-weight: 600").concat(important, "; color: ").concat(pillTextColor, ";\n line-height: 1.25").concat(important, ";\n overflow: hidden").concat(important, ";\n text-overflow: ellipsis").concat(important, ";\n }\n .ttp-pill-status {\n display: flex").concat(important, "; align-items: center").concat(important, "; gap: 4px").concat(important, ";\n font-size: 11px").concat(important, "; color: ").concat(pillTextColor, "8c;\n line-height: 1.25").concat(important, ";\n }\n\n /* Online dot (inside pill status) */\n .ttp-launcher-dot {\n width: 7px").concat(important, "; height: 7px").concat(important, "; border-radius: 50%").concat(important, ";\n background: ").concat(pillDotColor, ";\n flex-shrink: 0").concat(important, ";\n animation: ttp-dot-pulse 2s ease-in-out infinite").concat(important, ";\n }\n @keyframes ttp-dot-pulse { 0%,100%{opacity:1} 50%{opacity:.4} }\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: auto !important;\n height: auto !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").concat(important, ";\n min-height: 56px").concat(important, ";\n }\n \n #text-chat-panel .header-title {\n font-size: 15px").concat(important, ";\n }\n \n #text-chat-panel .header-icon {\n width: 40px").concat(important, ";\n height: 40px").concat(important, ";\n min-width: 40px").concat(important, ";\n min-height: 40px").concat(important, ";\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 }\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: auto !important;\n height: auto !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").concat(important, ";\n min-height: 52px").concat(important, ";\n }\n \n #text-chat-panel .header-title {\n font-size: 14px").concat(important, ";\n }\n \n }\n \n ").concat(anim.enableHover ? "\n #text-chat-button:hover {\n transform: translateY(-1px);\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").concat(important, ";\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: auto").concat(important, ";\n height: auto").concat(important, ";\n z-index: 10001").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\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").concat(important, ";\n z-index: 10002").concat(important, ";\n pointer-events: none").concat(important, ";\n white-space: nowrap").concat(important, ";\n }\n \n .prompt-bubble.top {\n bottom: calc(100% + 18px)").concat(important, ";\n left: 50%").concat(important, ";\n transform: translateX(-50%)").concat(important, ";\n }\n \n .prompt-bubble.left {\n right: calc(100% + 12px)").concat(important, ";\n top: 50%").concat(important, ";\n transform: translateY(-50%)").concat(important, ";\n }\n \n .prompt-bubble.right {\n left: calc(100% + 12px)").concat(important, ";\n top: 50%").concat(important, ";\n transform: translateY(-50%)").concat(important, ";\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").concat(important, ";\n transform: translateX(-50%)").concat(important, "; /* Keep centering */\n }\n \n .prompt-bubble.top.animation-float {\n animation: widget-float 2s ease-in-out infinite").concat(important, ";\n transform: translateX(-50%)").concat(important, "; /* Keep centering */\n }\n \n .prompt-bubble.top.animation-pulse {\n animation: pulse 2s ease-in-out infinite").concat(important, ";\n transform: translateX(-50%)").concat(important, "; /* Keep centering */\n }\n \n .prompt-bubble-content {\n position: relative").concat(important, ";\n padding: 8px 16px").concat(important, ";\n border-radius: 20px").concat(important, ";\n font-weight: 500").concat(important, ";\n font-size: 14px").concat(important, ";\n box-shadow: 0 4px 15px rgba(124, 58, 237, 0.3)").concat(important, ";\n overflow: hidden").concat(important, ";\n }\n \n .prompt-bubble-shimmer {\n position: absolute").concat(important, ";\n inset: 0").concat(important, ";\n background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.25), transparent)").concat(important, ";\n animation: widget-shimmer 2s infinite").concat(important, ";\n }\n \n .prompt-bubble.animation-bounce {\n animation: widget-bounce 1s ease-in-out infinite").concat(important, ";\n }\n \n .prompt-bubble.animation-pulse {\n animation: pulse 2s ease-in-out infinite").concat(important, ";\n }\n \n .prompt-bubble.animation-float {\n animation: widget-float 2s ease-in-out infinite").concat(important, ";\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").concat(important, ";\n width: 0").concat(important, ";\n height: 0").concat(important, ";\n border: 8px solid transparent").concat(important, ";\n }\n \n .prompt-bubble.top .prompt-bubble-arrow {\n top: 100%").concat(important, ";\n left: 50%").concat(important, ";\n transform: translateX(-50%)").concat(important, ";\n border-top-color: var(--prompt-bubble-bg-color, #7c3aed)").concat(important, ";\n border-bottom: none").concat(important, ";\n margin-left: 0").concat(important, ";\n }\n \n .prompt-bubble.left .prompt-bubble-arrow {\n left: 100%").concat(important, ";\n top: 50%").concat(important, ";\n transform: translateY(-50%)").concat(important, ";\n border-left-color: var(--prompt-bubble-bg-color, #7c3aed)").concat(important, ";\n border-right: none").concat(important, ";\n }\n \n .prompt-bubble.right .prompt-bubble-arrow {\n right: 100%").concat(important, ";\n top: 50%").concat(important, ";\n transform: translateY(-50%)").concat(important, ";\n border-right-color: var(--prompt-bubble-bg-color, #7c3aed)").concat(important, ";\n border-left: none").concat(important, ";\n }\n \n /* Pulse Rings */\n .prompt-pulse-rings {\n position: absolute").concat(important, ";\n inset: 0").concat(important, ";\n border-radius: 50%").concat(important, ";\n pointer-events: none").concat(important, ";\n }\n \n .prompt-pulse-ring {\n position: absolute").concat(important, ";\n inset: 0").concat(important, ";\n border-radius: 50%").concat(important, ";\n animation: widget-pulse-ring 2s ease-out infinite").concat(important, ";\n }\n \n .prompt-pulse-ring:nth-child(2) {\n animation-delay: 0.5s").concat(important, ";\n }\n \n /* Mobile adjustments for prompt bubble */\n @media (max-width: 768px) {\n .prompt-bubble-content {\n font-size: 12px").concat(important, ";\n padding: 6px 12px").concat(important, ";\n }\n \n .prompt-bubble.top {\n bottom: calc(100% + 14px)").concat(important, ";\n }\n \n .prompt-bubble.left,\n .prompt-bubble.right {\n display: none").concat(important, "; /* Hide side prompts on mobile */\n }\n }\n \n #text-chat-panel {\n display: none").concat(important, ";\n position: fixed").concat(important, ";\n bottom: calc(54px + 24px)").concat(important, "; /* launcher pill + gap */\n ").concat(this.config.position.horizontal === 'right' ? 'right: 20px;' : 'left: 20px;', "\n width: 340px").concat(important, ";\n max-width: calc(100vw - 40px)").concat(important, ";\n height: auto").concat(important, ";\n max-height: calc(100vh - 100px)").concat(important, ";\n background: ").concat(panelBg, ";\n border-radius: 20px").concat(important, ";\n border: ").concat(panel.border || '1px solid rgba(255,255,255,0.08)', ";\n flex-direction: column").concat(important, ";\n overflow: hidden").concat(important, ";\n box-shadow: 0 24px 60px rgba(0,0,0,0.6)").concat(important, ";\n transform-origin: bottom right").concat(important, ";\n opacity: 0").concat(important, ";\n pointer-events: none").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n \n #text-chat-panel.open {\n display: flex").concat(important, ";\n opacity: 1").concat(important, ";\n pointer-events: auto").concat(important, ";\n }\n\n /* Shell for panel inner */\n .widget-shell { width: 100%").concat(important, "; padding: 0").concat(important, "; border-radius: 20px").concat(important, "; background: transparent").concat(important, "; overflow: hidden").concat(important, "; display: flex").concat(important, "; flex-direction: column").concat(important, "; box-sizing: border-box").concat(important, "; flex: 1").concat(important, "; min-height: 0").concat(important, "; }\n .panel-inner { width: 100%").concat(important, "; background: ").concat(panelBg, "; border-radius: 20px").concat(important, "; border: none").concat(important, "; overflow: hidden").concat(important, "; display:flex").concat(important, "; flex-direction: column").concat(important, "; padding: 0").concat(important, "; box-sizing: border-box").concat(important, "; max-width: 100%").concat(important, "; flex: 1").concat(important, "; min-height: 0").concat(important, "; }\n\n #text-chat-panel .widget-container {\n width: 100%").concat(important, "; background: ").concat(panelBg, "; overflow: visible").concat(important, "; display: flex").concat(important, "; flex-direction: column").concat(important, "; border-radius: 20px").concat(important, "; flex: 1").concat(important, "; min-height: 0").concat(important, ";\n }\n\n /* Voice idle: one gradient for voice UI + footer (Powered by), not a flat strip under buttons */\n #text-chat-panel.open:has(").concat(voiceIdleVisibleSelector, ") {\n background: linear-gradient(160deg, ").concat(idleHeroGrad1, " 0%, ").concat(idleHeroGrad2, " 100%)").concat(important, ";\n }\n #text-chat-panel .widget-container:has(").concat(voiceIdleVisibleSelector, ") {\n background: linear-gradient(160deg, ").concat(idleHeroGrad1, " 0%, ").concat(idleHeroGrad2, " 100%)").concat(important, ";\n }\n\n /* Voice active call: same hero gradient as idle + mobile minimized bar */\n #text-chat-panel.open:has(").concat(voiceActiveVisibleSelector, ") {\n background: ").concat(callActivePanelBg).concat(important, ";\n }\n #text-chat-panel .widget-container:has(").concat(voiceActiveVisibleSelector, ") {\n background: ").concat(callActivePanelBg).concat(important, ";\n }\n #text-chat-panel.open:has(").concat(voiceActiveVisibleSelector, ") .widget-shell {\n background: ").concat(callActivePanelBg).concat(important, ";\n }\n #text-chat-panel.open:has(").concat(voiceActiveVisibleSelector, ") .panel-inner {\n background: ").concat(callActivePanelBg).concat(important, ";\n }\n #text-chat-panel.open:has(").concat(voiceActiveVisibleSelector, ") .ttp-footer {\n background: ").concat(callActivePanelBg).concat(important, ";\n }\n \n /* Ensure content areas can scroll when height is constrained */\n #text-chat-panel .widget-container > .voice-interface,\n #text-chat-panel .widget-container > .text-interface {\n flex: 1").concat(important, ";\n overflow-y: auto").concat(important, ";\n overflow-x: visible").concat(important, "; /* Change from hidden to visible */\n }\n \n /* Header is removed in new design - hero serves as header */\n #text-chat-panel .widget-header { display: none").concat(important, "; }\n\n ").concat(showVoice ? this.voiceInterface.generateCSS() : '', "\n ").concat(showText ? this.textInterface.generateCSS() : '', "\n \n /* Footer Branding */\n .ttp-footer {\n padding: 6px 18px 10px").concat(important, ";\n border-top: 1px solid ").concat(footerBorderColor, ";\n display: flex").concat(important, ";\n justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n box-sizing: border-box").concat(important, ";\n background: transparent").concat(important, ";\n }\n .ttp-footer span { font-size: 10px").concat(important, "; color: ").concat(footerTextColor, "; }\n .ttp-footer a { color: ").concat(footerLinkColor, "; text-decoration: none").concat(important, "; font-weight: 600").concat(important, "; }\n .ttp-footer a:hover { opacity: 0.85").concat(important, "; }\n .ttp-footer a b { font-weight: 700").concat(important, "; }\n \n #text-chat-send-hint {\n text-align: center").concat(important, ";\n line-height: 1.4").concat(important, ";\n }\n \n .agent-thinking {\n font-style: italic").concat(important, ";\n color: #6B7280").concat(important, ";\n }\n\n /* ========================================\n MOBILE PILL BUTTON & LANDING OVERLAY\n Hidden on desktop, shown on mobile only\n ======================================== */\n .ttp-mobile-fab {\n display: none").concat(important, ";\n }\n\n .ttp-mobile-landing {\n display: none").concat(important, ";\n }\n\n @keyframes ttpWaveAnimation {\n 0%, 100% { transform: scaleY(0.4); }\n 50% { transform: scaleY(1); }\n }\n\n @keyframes ttpPulseAnimation {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n\n @media (max-width: 768px) {\n /* Hide desktop pill button on mobile */\n #text-chat-button {\n display: none !important;\n }\n\n /* Re-flow the container for pill shape */\n #text-chat-button-container {\n width: auto !important;\n height: auto !important;\n min-width: 0 !important;\n min-height: 0 !important;\n max-width: none !important;\n max-height: none !important;\n }\n\n /* Show mobile pill button */\n .ttp-mobile-fab {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 10px").concat(important, ";\n padding: 10px 16px 10px 12px").concat(important, ";\n background: ").concat(pillGradient, ";\n border: none").concat(important, ";\n border-radius: 24px").concat(important, ";\n cursor: pointer").concat(important, ";\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3)").concat(important, ";\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1)").concat(important, ";\n z-index: 1").concat(important, ";\n font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, sans-serif").concat(important, ";\n touch-action: manipulation").concat(important, ";\n -webkit-tap-highlight-color: transparent").concat(important, ";\n }\n\n .ttp-mobile-fab:hover {\n transform: translateY(-3px)").concat(important, ";\n box-shadow: 0 12px 32px rgba(0, 0, 0, 0.4)").concat(important, ";\n }\n\n .ttp-mobile-fab__icon-wrap {\n width: 36px").concat(important, ";\n height: 36px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background: rgba(255, 255, 255, 0.15)").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n\n .ttp-mobile-fab__waveform {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 2px").concat(important, ";\n height: 16px").concat(important, ";\n }\n\n .ttp-mobile-fab__waveform .bar {\n width: 2px").concat(important, ";\n background: #fff").concat(important, ";\n border-radius: 1px").concat(important, ";\n animation: ttpWaveAnimation 0.8s ease-in-out infinite").concat(important, ";\n }\n\n .ttp-mobile-fab__waveform .bar:nth-child(1) { height: 5px").concat(important, "; animation-delay: 0s").concat(important, "; }\n .ttp-mobile-fab__waveform .bar:nth-child(2) { height: 10px").concat(important, "; animation-delay: 0.1s").concat(important, "; }\n .ttp-mobile-fab__waveform .bar:nth-child(3) { height: 16px").concat(important, "; animation-delay: 0.2s").concat(important, "; }\n .ttp-mobile-fab__waveform .bar:nth-child(4) { height: 8px").concat(important, "; animation-delay: 0.3s").concat(important, "; }\n .ttp-mobile-fab__waveform .bar:nth-child(5) { height: 12px").concat(important, "; animation-delay: 0.4s").concat(important, "; }\n\n .ttp-mobile-fab__label-wrap {\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n align-items: flex-start").concat(important, ";\n gap: 1px").concat(important, ";\n }\n\n .ttp-mobile-fab__label {\n color: ").concat(pillTextColor, ";\n font-size: 14px").concat(important, ";\n font-weight: 600").concat(important, ";\n line-height: 1.2").concat(important, ";\n }\n\n .ttp-mobile-fab__status {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 4px").concat(important, ";\n font-size: 11px").concat(important, ";\n color: ").concat(pillTextColor, "b3;\n line-height: 1.2").concat(important, ";\n }\n\n .ttp-mobile-fab__dot {\n width: 6px").concat(important, ";\n height: 6px").concat(important, ";\n background: ").concat(pillDotColor, ";\n border-radius: 50%").concat(important, ";\n box-shadow: 0 0 6px ").concat(pillDotColor, "99;\n }\n\n /* ---- Mobile Landing Overlay ---- */\n .ttp-mobile-landing.active {\n display: block").concat(important, ";\n position: fixed").concat(important, ";\n bottom: 16px").concat(important, ";\n left: 12px").concat(important, ";\n right: 12px").concat(important, ";\n background: ").concat(pillGradient, ";\n border-radius: 20px").concat(important, ";\n overflow: hidden").concat(important, ";\n box-shadow:\n 0 10px 40px rgba(0, 0, 0, 0.3),\n 0 0 0 1px rgba(255, 255, 255, 0.1) inset").concat(important, ";\n z-index: 10002").concat(important, ";\n font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, sans-serif").concat(important, ";\n }\n\n .ttp-mobile-landing::before {\n content: ''").concat(important, ";\n position: absolute").concat(important, ";\n top: 0").concat(important, ";\n left: 0").concat(important, ";\n right: 0").concat(important, ";\n height: 1px").concat(important, ";\n background: linear-gradient(90deg,\n transparent 0%,\n rgba(255, 255, 255, 0.3) 50%,\n transparent 100%);\n }\n\n .ttp-mobile-landing__header {\n padding: 14px 16px").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 12px").concat(important, ";\n }\n\n .ttp-mobile-landing__avatar {\n width: 44px").concat(important, ";\n height: 44px").concat(important, ";\n border-radius: 12px").concat(important, ";\n background: rgba(255, 255, 255, 0.15)").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n\n .ttp-mobile-landing__waveform {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 3px").concat(important, ";\n height: 20px").concat(important, ";\n }\n\n .ttp-mobile-landing__waveform .bar {\n width: 3px").concat(important, ";\n background: rgba(255, 255, 255, 0.9)").concat(important, ";\n border-radius: 2px").concat(important, ";\n animation: ttpWaveAnimation 0.8s ease-in-out infinite").concat(important, ";\n }\n\n .ttp-mobile-landing__waveform .bar:nth-child(1) { height: 6px").concat(important, "; animation-delay: 0s").concat(important, "; }\n .ttp-mobile-landing__waveform .bar:nth-child(2) { height: 12px").concat(important, "; animation-delay: 0.1s").concat(important, "; }\n .ttp-mobile-landing__waveform .bar:nth-child(3) { height: 20px").concat(important, "; animation-delay: 0.2s").concat(important, "; }\n .ttp-mobile-landing__waveform .bar:nth-child(4) { height: 10px").concat(important, "; animation-delay: 0.3s").concat(important, "; }\n .ttp-mobile-landing__waveform .bar:nth-child(5) { height: 16px").concat(important, "; animation-delay: 0.4s").concat(important, "; }\n\n .ttp-mobile-landing__info {\n flex: 1").concat(important, ";\n min-width: 0").concat(important, ";\n }\n\n .ttp-mobile-landing__name {\n color: #fff").concat(important, ";\n font-size: 15px").concat(important, ";\n font-weight: 600").concat(important, ";\n margin-bottom: 2px").concat(important, ";\n }\n\n .ttp-mobile-landing__status {\n color: rgba(255, 255, 255, 0.7)").concat(important, ";\n font-size: 12px").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 5px").concat(important, ";\n }\n\n .ttp-mobile-landing__dot {\n width: 6px").concat(important, ";\n height: 6px").concat(important, ";\n background: ").concat(header.onlineIndicatorDotColor || '#10b981', ";\n border-radius: 50%").concat(important, ";\n animation: ttpPulseAnimation 2s ease-in-out infinite").concat(important, ";\n }\n\n .ttp-mobile-landing__close {\n width: 32px").concat(important, ";\n height: 32px").concat(important, ";\n border-radius: 10px").concat(important, ";\n background: rgba(255, 255, 255, 0.1)").concat(important, ";\n border: none").concat(important, ";\n color: rgba(255, 255, 255, 0.7)").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n cursor: pointer").concat(important, ";\n transition: all 0.2s").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n\n .ttp-mobile-landing__close:hover {\n background: rgba(255, 255, 255, 0.2)").concat(important, ";\n color: #fff").concat(important, ";\n }\n\n .ttp-mobile-landing__error {\n margin: 0 14px 10px").concat(important, ";\n padding: 10px 12px").concat(important, ";\n background: #fef2f2").concat(important, ";\n border: 1px solid #fecaca").concat(important, ";\n border-radius: 10px").concat(important, ";\n display: flex").concat(important, ";\n align-items: flex-start").concat(important, ";\n gap: 8px").concat(important, ";\n color: #b91c1c").concat(important, ";\n font-size: 13px").concat(important, ";\n line-height: 1.4").concat(important, ";\n }\n .ttp-mobile-landing__error svg {\n flex-shrink: 0").concat(important, ";\n margin-top: 1px").concat(important, ";\n stroke: #dc2626").concat(important, ";\n }\n\n .ttp-mobile-landing__actions {\n padding: 0 14px 14px").concat(important, ";\n display: flex").concat(important, ";\n gap: 10px").concat(important, ";\n }\n\n .ttp-mobile-landing__btn {\n flex: 1").concat(important, ";\n padding: 14px").concat(important, ";\n border-radius: 12px").concat(important, ";\n border: none").concat(important, ";\n cursor: pointer").concat(important, ";\n font-family: inherit").concat(important, ";\n font-size: 14px").concat(important, ";\n font-weight: 600").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n gap: 10px").concat(important, ";\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1)").concat(important, ";\n touch-action: manipulation").concat(important, ";\n -webkit-tap-highlight-color: transparent").concat(important, ";\n }\n\n .ttp-mobile-landing__btn svg {\n width: 20px").concat(important, ";\n height: 20px").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n\n .ttp-mobile-landing__btn--call {\n background: #fff").concat(important, ";\n color: ").concat(header.backgroundColor || '#7C3AED', ";\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15)").concat(important, ";\n }\n\n .ttp-mobile-landing__btn--call:hover {\n transform: translateY(-2px)").concat(important, ";\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2)").concat(important, ";\n }\n\n .ttp-mobile-landing__btn--text {\n background: rgba(255, 255, 255, 0.15)").concat(important, ";\n color: #fff").concat(important, ";\n border: 1px solid rgba(255, 255, 255, 0.1)").concat(important, ";\n }\n\n .ttp-mobile-landing__btn--text:hover {\n background: rgba(255, 255, 255, 0.2)").concat(important, ";\n border-color: rgba(255, 255, 255, 0.2)").concat(important, ";\n }\n\n .ttp-mobile-landing__footer {\n padding: 10px 16px").concat(important, ";\n display: flex").concat(important, ";\n justify-content: center").concat(important, ";\n border-top: 1px solid rgba(255, 255, 255, 0.08)").concat(important, ";\n }\n\n .ttp-mobile-landing__powered {\n color: rgba(255, 255, 255, 0.4)").concat(important, ";\n font-size: 11px").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 4px").concat(important, ";\n }\n\n .ttp-mobile-landing__powered svg {\n width: 10px").concat(important, ";\n height: 10px").concat(important, ";\n color: #f59e0b").concat(important, ";\n }\n\n .ttp-mobile-landing__powered a {\n color: ").concat(footerLinkColor).concat(important, ";\n text-decoration: none").concat(important, ";\n }\n\n .ttp-mobile-landing__powered a:hover {\n opacity: 0.88").concat(important, ";\n }\n }\n ");
29869
30112
  }
29870
30113
  }, {
29871
30114
  key: "setupWidgetEvents",
@@ -29916,6 +30159,16 @@ var TTPChatWidget = /*#__PURE__*/function () {
29916
30159
  return _this7.showText();
29917
30160
  };
29918
30161
  }
30162
+ var textUnifiedBackBtn = this.shadowRoot.getElementById('textUnifiedBackBtn');
30163
+ if (textUnifiedBackBtn) {
30164
+ textUnifiedBackBtn.onclick = function () {
30165
+ var _this7$config$behavio;
30166
+ var widgetMode = ((_this7$config$behavio = _this7.config.behavior) === null || _this7$config$behavio === void 0 ? void 0 : _this7$config$behavio.mode) || 'unified';
30167
+ if (widgetMode !== 'unified') return;
30168
+ _this7.showLanding();
30169
+ _this7._openMobileCallTextLanding();
30170
+ };
30171
+ }
29919
30172
 
29920
30173
  // Build wave bars inside the orb (desktop active call)
29921
30174
  var waveQueryRoot = this.config.useShadowDOM ? this.shadowRoot : document.getElementById('ttp-widget-container');
@@ -29932,280 +30185,67 @@ var TTPChatWidget = /*#__PURE__*/function () {
29932
30185
 
29933
30186
  // Voice selection events (based on widget mode)
29934
30187
  var widgetMode = ((_this$config$behavior6 = this.config.behavior) === null || _this$config$behavior6 === void 0 ? void 0 : _this$config$behavior6.mode) || 'unified';
29935
- var showLanding = widgetMode === 'unified';
30188
+ var isUnified = widgetMode === 'unified';
29936
30189
  var showVoice = widgetMode === 'unified' || widgetMode === 'voice-only';
29937
30190
  var showText = widgetMode === 'unified' || widgetMode === 'text-only';
29938
30191
  var backBtn = this.shadowRoot.getElementById('backBtn');
29939
- var landing = this.shadowRoot.getElementById('landingScreen');
29940
30192
  var textInterface = this.shadowRoot.getElementById('textInterface');
29941
30193
  var voiceInterface = this.shadowRoot.getElementById('voiceInterface');
30194
+ var newChatBtn = this.shadowRoot.getElementById('newChatBtn');
29942
30195
 
29943
30196
  // Setup back button handler
29944
30197
  if (backBtn) {
29945
30198
  backBtn.onclick = function () {
29946
30199
  var _this7$voiceInterface, _this7$voiceInterface3;
29947
- // Check if we're showing a domain error - if so, clear it and go back to landing
30200
+ // Check if we're showing a domain error clear it and return to voice hero
29948
30201
  if ((_this7$voiceInterface = _this7.voiceInterface) !== null && _this7$voiceInterface !== void 0 && _this7$voiceInterface.isShowingDomainError) {
29949
30202
  var _this7$voiceInterface2;
29950
- console.log('🔙 Back button clicked - clearing domain error and returning to landing');
30203
+ console.log('🔙 Back button clicked - clearing domain error and returning to voice hero');
29951
30204
  // Clear the domain error flag
29952
30205
  _this7.voiceInterface.isShowingDomainError = false;
29953
30206
  // Reset the connecting state (this will restore normal UI)
29954
30207
  if ((_this7$voiceInterface2 = _this7.voiceInterface) !== null && _this7$voiceInterface2 !== void 0 && _this7$voiceInterface2.resetConnectingState) {
29955
30208
  _this7.voiceInterface.resetConnectingState();
29956
30209
  }
29957
- // Now show landing (will work since error flag is cleared)
29958
30210
  _this7.showLanding();
30211
+ _this7._openMobileCallTextLanding();
29959
30212
  return;
29960
30213
  }
29961
30214
  if ((_this7$voiceInterface3 = _this7.voiceInterface) !== null && _this7$voiceInterface3 !== void 0 && _this7$voiceInterface3.isActive) {
29962
30215
  // If call is active, show message inside widget instead of modal
29963
30216
  _this7.showBackButtonWarning();
29964
30217
  } else if (window.innerWidth <= 768) {
29965
- // On mobile, close panel and return to FAB
29966
- var panel = _this7.shadowRoot.getElementById('text-chat-panel');
29967
- if (panel) {
29968
- panel.classList.remove('open');
29969
- _this7.isOpen = false;
29970
- }
29971
- var fab = _this7.shadowRoot.querySelector('.ttp-mobile-fab');
29972
- if (fab) fab.style.display = '';
29973
30218
  _this7.showLanding();
30219
+ _this7._openMobileCallTextLanding();
29974
30220
  } else {
29975
- // Desktop: show landing inside panel
30221
+ // Desktop: return to voice hero (unified home)
29976
30222
  _this7.showLanding();
29977
30223
  }
29978
30224
  };
29979
30225
  }
29980
- if (showLanding && this.landingScreen) {
29981
- this.landingScreen.setupEventHandlers({
29982
- onSelectVoice: function () {
29983
- var _onSelectVoice = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
29984
- var _this7$voiceInterface4, _this7$voiceInterface0, _this7$shadowRoot, _this7$voiceInterface5, _this7$shadowRoot2, _this7$shadowRoot3, _this7$voiceInterface6, panel, idleState, floatingButton, mobileFab, _this7$voiceInterface7, _this7$voiceInterface8, _this7$voiceInterface9, _this7$voiceInterface1, _this7$config$behavio, _widgetMode, _this7$voiceInterface11, _this7$voiceInterface12, _this7$config$behavio2, _this7$voiceInterface10, _this7$voiceInterface13, _this7$shadowRoot4, _this7$shadowRoot5, existingBar, _floatingButton, _mobileFab, _widgetMode2, _t;
29985
- return _regenerator().w(function (_context2) {
29986
- while (1) switch (_context2.p = _context2.n) {
29987
- case 0:
29988
- if (!_this7.isStartingCall) {
29989
- _context2.n = 1;
29990
- break;
29991
- }
29992
- console.log('⚠️ Call already starting, ignoring duplicate click');
29993
- return _context2.a(2);
29994
- case 1:
29995
- // Call the callback if provided
29996
- if (typeof _this7.config.onVoiceCallButtonClick === 'function') {
29997
- try {
29998
- _this7.config.onVoiceCallButtonClick({
29999
- timestamp: Date.now(),
30000
- widgetState: 'start'
30001
- });
30002
- } catch (error) {
30003
- console.error('Error in onVoiceCallButtonClick callback:', error);
30004
- }
30005
- }
30006
- _this7.isStartingCall = true;
30007
- _context2.p = 2;
30008
- // Show voice interface first (needed for UI state)
30009
- // Note: If showVoice() throws, finally block will still reset flag
30010
- _this7.showVoice();
30011
-
30012
- // CRITICAL: On mobile, hide widget panel IMMEDIATELY to prevent showing old UI
30013
- // The idle state with "Connecting..." should never be visible on mobile
30014
- if (!((_this7$voiceInterface4 = _this7.voiceInterface) !== null && _this7$voiceInterface4 !== void 0 && _this7$voiceInterface4.isMobile)) {
30015
- _context2.n = 4;
30016
- break;
30017
- }
30018
- // Hide widget panel immediately before showing any connecting state
30019
- panel = ((_this7$shadowRoot = _this7.shadowRoot) === null || _this7$shadowRoot === void 0 ? void 0 : _this7$shadowRoot.getElementById('text-chat-panel')) || document.getElementById('text-chat-panel');
30020
- if (panel) {
30021
- panel.classList.remove('open');
30022
- panel.style.display = 'none';
30023
- }
30024
- // Hide idle state to prevent it from showing
30025
- idleState = (_this7$voiceInterface5 = _this7.voiceInterface) === null || _this7$voiceInterface5 === void 0 || (_this7$voiceInterface5 = _this7$voiceInterface5.shadowRoot) === null || _this7$voiceInterface5 === void 0 ? void 0 : _this7$voiceInterface5.getElementById('voiceIdleState');
30026
- if (idleState) {
30027
- idleState.style.display = 'none';
30028
- }
30029
- // Hide floating button immediately so minimized bar is visible
30030
- floatingButton = ((_this7$shadowRoot2 = _this7.shadowRoot) === null || _this7$shadowRoot2 === void 0 ? void 0 : _this7$shadowRoot2.getElementById('text-chat-button')) || document.getElementById('text-chat-button');
30031
- if (floatingButton) {
30032
- floatingButton.style.display = 'none';
30033
- }
30034
- mobileFab = (_this7$shadowRoot3 = _this7.shadowRoot) === null || _this7$shadowRoot3 === void 0 ? void 0 : _this7$shadowRoot3.querySelector('.ttp-mobile-fab');
30035
- if (mobileFab) {
30036
- mobileFab.style.display = 'none';
30037
- }
30038
- // Create minimized bar with connecting state
30039
- if (!((_this7$voiceInterface6 = _this7.voiceInterface) !== null && _this7$voiceInterface6 !== void 0 && _this7$voiceInterface6.createMobileMinimizedBar)) {
30040
- _context2.n = 3;
30041
- break;
30042
- }
30043
- _this7.voiceInterface.createMobileMinimizedBar();
30044
- // Show connecting status in minimized bar
30045
- _this7.voiceInterface.updateMobileStatus('connecting');
30046
- // Start timer and waveform immediately - timer runs inside mobile bar (owns its DOM)
30047
- (_this7$voiceInterface7 = (_this7$voiceInterface8 = _this7.voiceInterface).startWaveformAnimation) === null || _this7$voiceInterface7 === void 0 || _this7$voiceInterface7.call(_this7$voiceInterface8);
30048
- // Ensure UI is painted before starting heavy operations
30049
- _context2.n = 3;
30050
- return new Promise(function (resolve) {
30051
- return requestAnimationFrame(function () {
30052
- return requestAnimationFrame(resolve);
30053
- });
30054
- });
30055
- case 3:
30056
- _context2.n = 5;
30057
- break;
30058
- case 4:
30059
- // Desktop: Show connecting/loading state in idle state
30060
- // This provides feedback during WebSocket connection and SDK initialization
30061
- if ((_this7$voiceInterface9 = _this7.voiceInterface) !== null && _this7$voiceInterface9 !== void 0 && _this7$voiceInterface9.showConnectingState) {
30062
- _this7.voiceInterface.showConnectingState();
30063
- }
30064
- case 5:
30065
- _context2.n = 6;
30066
- return _this7.startVoiceCall();
30067
- case 6:
30068
- if (!((_this7$voiceInterface0 = _this7.voiceInterface) !== null && _this7$voiceInterface0 !== void 0 && _this7$voiceInterface0.isActive)) {
30069
- _context2.n = 7;
30070
- break;
30071
- }
30072
- console.log('✅ Voice call started successfully');
30073
- _context2.n = 9;
30074
- break;
30075
- case 7:
30076
- // This shouldn't happen if startVoiceCall() throws properly, but just in case
30077
- console.warn('⚠️ startVoiceCall() returned but call is not active');
30078
-
30079
- // CRITICAL: Check if we're showing a domain error - if so, stay on voice interface
30080
- if (!_this7._isDomainErrorVisible()) {
30081
- _context2.n = 8;
30082
- break;
30083
- }
30084
- // Set currentView to voice so we don't return to landing
30085
- _this7.currentView = 'voice';
30086
- // Ensure voice interface is visible
30087
- _this7.showVoice();
30088
- // Don't reset connecting state or return to landing - stay on voice interface showing error
30089
- console.log('✅ Staying on voice interface with domain error displayed');
30090
- return _context2.a(2);
30091
- case 8:
30092
- // Not a domain error - reset connecting state and return to landing
30093
- console.log('⚠️ Not a domain error - returning to landing screen');
30094
- if ((_this7$voiceInterface1 = _this7.voiceInterface) !== null && _this7$voiceInterface1 !== void 0 && _this7$voiceInterface1.resetConnectingState) {
30095
- _this7.voiceInterface.resetConnectingState();
30096
- }
30097
- _widgetMode = ((_this7$config$behavio = _this7.config.behavior) === null || _this7$config$behavio === void 0 ? void 0 : _this7$config$behavio.mode) || 'unified';
30098
- if (_widgetMode === 'unified') {
30099
- _this7.showLanding();
30100
- }
30101
- case 9:
30102
- _context2.n = 12;
30103
- break;
30104
- case 10:
30105
- _context2.p = 10;
30106
- _t = _context2.v;
30107
- if (!(_t.isServerRejection || _t.name === 'ServerRejected')) {
30108
- _context2.n = 11;
30109
- break;
30110
- }
30111
- // Server rejection is expected - the error handler will show domain error message
30112
- // Reset connecting state but don't log as error
30113
- if ((_this7$voiceInterface10 = _this7.voiceInterface) !== null && _this7$voiceInterface10 !== void 0 && _this7$voiceInterface10.resetConnectingState) {
30114
- _this7.voiceInterface.resetConnectingState();
30115
- }
30116
- // Don't show toast for server rejection - domain error handler will show message
30117
- return _context2.a(2);
30118
- case 11:
30119
- // Log other errors (permission denied, etc.)
30120
- console.error('❌ Failed to start voice call:', _t);
30121
-
30122
- // Reset connecting state on error
30123
- if ((_this7$voiceInterface11 = _this7.voiceInterface) !== null && _this7$voiceInterface11 !== void 0 && _this7$voiceInterface11.resetConnectingState) {
30124
- _this7.voiceInterface.resetConnectingState();
30125
- }
30126
-
30127
- // Clean up mobile bar if it was created early
30128
- if ((_this7$voiceInterface12 = _this7.voiceInterface) !== null && _this7$voiceInterface12 !== void 0 && _this7$voiceInterface12.isMobile) {
30129
- existingBar = document.getElementById('mobile-voice-call-bar-container');
30130
- if (existingBar && (_this7$voiceInterface13 = _this7.voiceInterface) !== null && _this7$voiceInterface13 !== void 0 && _this7$voiceInterface13.removeMobileMinimizedBar) {
30131
- _this7.voiceInterface.removeMobileMinimizedBar();
30132
- }
30133
- // Restore floating button if it was hidden
30134
- _floatingButton = ((_this7$shadowRoot4 = _this7.shadowRoot) === null || _this7$shadowRoot4 === void 0 ? void 0 : _this7$shadowRoot4.getElementById('text-chat-button')) || document.getElementById('text-chat-button');
30135
- if (_floatingButton) {
30136
- _floatingButton.style.display = '';
30137
- }
30138
- _mobileFab = (_this7$shadowRoot5 = _this7.shadowRoot) === null || _this7$shadowRoot5 === void 0 ? void 0 : _this7$shadowRoot5.querySelector('.ttp-mobile-fab');
30139
- if (_mobileFab) {
30140
- _mobileFab.style.display = '';
30141
- }
30142
- }
30143
-
30144
- // Show user-friendly error message (unless it's a user cancellation)
30145
- if (_t.message !== 'Call cancelled by user') {
30146
- _this7.showErrorToast(_t.message || 'Failed to start voice call. Please try again.', 'error');
30147
- }
30148
-
30149
- // Return to landing screen on error
30150
- _widgetMode2 = ((_this7$config$behavio2 = _this7.config.behavior) === null || _this7$config$behavio2 === void 0 ? void 0 : _this7$config$behavio2.mode) || 'unified';
30151
- if (_widgetMode2 === 'unified') {
30152
- _this7.showLanding();
30153
- }
30154
- case 12:
30155
- _context2.p = 12;
30156
- // ✅ Always reset flag, even if showVoice() or startVoiceCall() throws
30157
- _this7.isStartingCall = false;
30158
- return _context2.f(12);
30159
- case 13:
30160
- return _context2.a(2);
30161
- }
30162
- }, _callee2, null, [[2, 10, 12, 13]]);
30163
- }));
30164
- function onSelectVoice() {
30165
- return _onSelectVoice.apply(this, arguments);
30166
- }
30167
- return onSelectVoice;
30168
- }(),
30169
- onSelectText: function onSelectText() {
30170
- return _this7.showText();
30171
- }
30172
- });
30173
-
30174
- // Restore previous view state if user had selected an interface, otherwise show landing
30226
+ if (isUnified) {
30175
30227
  if (this.currentView === 'text') {
30176
- // User was on text interface, restore it
30177
- if (landing) landing.classList.remove('active');
30178
30228
  if (textInterface) textInterface.classList.add('active');
30179
30229
  if (voiceInterface) voiceInterface.classList.remove('active');
30180
- if (backBtn && widgetMode === 'unified') backBtn.classList.add('visible');
30230
+ if (backBtn) backBtn.classList.add('visible');
30181
30231
  if (newChatBtn) newChatBtn.style.display = '';
30182
- } else if (this.currentView === 'voice') {
30183
- // User was on voice interface, restore it
30184
- if (landing) landing.classList.remove('active');
30232
+ } else {
30233
+ // Text-only path is text branch; everything else is unified home (voice hero)
30234
+ this.currentView = 'voice';
30185
30235
  if (textInterface) textInterface.classList.remove('active');
30186
30236
  if (voiceInterface) voiceInterface.classList.add('active');
30187
- if (backBtn && widgetMode === 'unified') backBtn.classList.add('visible');
30237
+ if (backBtn) backBtn.classList.remove('visible');
30188
30238
  if (newChatBtn) newChatBtn.style.display = 'none';
30189
- } else {
30190
- // Initial state or landing: show landing screen
30191
- this.currentView = 'landing';
30192
- if (landing) landing.classList.add('active');
30193
- if (textInterface) textInterface.classList.remove('active');
30194
- if (voiceInterface) voiceInterface.classList.remove('active');
30195
- // Hide back button on landing screen (only exists in unified mode)
30196
- if (backBtn && widgetMode === 'unified') backBtn.classList.remove('visible');
30197
30239
  }
30198
30240
  } else if (widgetMode === 'voice-only') {
30199
30241
  // Voice-only mode: show voice interface directly
30200
30242
  if (voiceInterface) voiceInterface.classList.add('active');
30201
30243
  if (textInterface) textInterface.classList.remove('active');
30202
- if (landing) landing.classList.remove('active');
30203
30244
  // Back button doesn't exist in voice-only mode (only in unified)
30204
30245
  } else if (widgetMode === 'text-only') {
30205
30246
  // Text-only mode: show text interface directly
30206
30247
  if (textInterface) textInterface.classList.add('active');
30207
30248
  if (voiceInterface) voiceInterface.classList.remove('active');
30208
- if (landing) landing.classList.remove('active');
30209
30249
  // Back button doesn't exist in text-only mode (only in unified)
30210
30250
  }
30211
30251
 
@@ -30220,13 +30260,12 @@ var TTPChatWidget = /*#__PURE__*/function () {
30220
30260
  }
30221
30261
 
30222
30262
  // Setup header button handlers
30223
- var newChatBtn = this.shadowRoot.getElementById('newChatBtn');
30224
30263
  if (newChatBtn) {
30225
30264
  newChatBtn.onclick = function () {
30226
30265
  return _this7.textInterface.startNewChat();
30227
30266
  };
30228
- // Hide new chat button on landing screen initially
30229
- if (showLanding) {
30267
+ // Hide new chat on unified home (voice hero) initially
30268
+ if (isUnified && this.currentView !== 'text') {
30230
30269
  newChatBtn.style.display = 'none';
30231
30270
  }
30232
30271
  }
@@ -30244,28 +30283,25 @@ var TTPChatWidget = /*#__PURE__*/function () {
30244
30283
  value: function startNewChat() {
30245
30284
  this.textInterface.startNewChat();
30246
30285
  }
30286
+
30287
+ /**
30288
+ * Unified-mode "home": voice idle hero. Name kept for VoiceInterface callbacks.
30289
+ * Legacy two-card in-panel mode picker has been removed.
30290
+ */
30247
30291
  }, {
30248
30292
  key: "showLanding",
30249
30293
  value: function showLanding() {
30250
30294
  if (!this.shadowRoot) return;
30251
-
30252
- // On desktop, skip landing — show voice idle state as default entry
30253
- if (window.innerWidth > 768) {
30254
- this.showVoice();
30255
- return;
30256
- }
30257
30295
  if (this._isDomainErrorVisible()) return;
30258
30296
  var widgetMode = this.config.behavior.mode || 'unified';
30259
30297
  if (widgetMode !== 'unified') return;
30260
- this.currentView = 'landing';
30261
- var landing = this.shadowRoot.getElementById('landingScreen');
30262
30298
  var textInterface = this.shadowRoot.getElementById('textInterface');
30263
30299
  var voiceInterface = this.shadowRoot.getElementById('voiceInterface');
30264
30300
  var backBtn = this.shadowRoot.getElementById('backBtn');
30265
30301
  var newChatBtn = this.shadowRoot.getElementById('newChatBtn');
30266
- if (landing) landing.classList.add('active');
30302
+ this.currentView = 'voice';
30267
30303
  if (textInterface) textInterface.classList.remove('active');
30268
- if (voiceInterface) voiceInterface.classList.remove('active');
30304
+ if (voiceInterface) voiceInterface.classList.add('active');
30269
30305
  if (backBtn) backBtn.classList.remove('visible');
30270
30306
  if (newChatBtn) newChatBtn.style.display = 'none';
30271
30307
  }
@@ -30274,11 +30310,9 @@ var TTPChatWidget = /*#__PURE__*/function () {
30274
30310
  value: function showText() {
30275
30311
  if (!this.shadowRoot) return;
30276
30312
  this.currentView = 'text'; // Track state
30277
- var landing = this.shadowRoot.getElementById('landingScreen');
30278
30313
  var voiceInterface = this.shadowRoot.getElementById('voiceInterface');
30279
30314
  var backBtn = this.shadowRoot.getElementById('backBtn');
30280
30315
  var newChatBtn = this.shadowRoot.getElementById('newChatBtn');
30281
- if (landing) landing.classList.remove('active');
30282
30316
  if (voiceInterface) voiceInterface.classList.remove('active');
30283
30317
  this.textInterface.show();
30284
30318
  // Show back button when not on landing (only in unified mode)
@@ -30300,45 +30334,73 @@ var TTPChatWidget = /*#__PURE__*/function () {
30300
30334
  value: function showVoice() {
30301
30335
  if (!this.shadowRoot) return;
30302
30336
  this.currentView = 'voice'; // Track state
30303
- var landing = this.shadowRoot.getElementById('landingScreen');
30304
30337
  var textInterface = this.shadowRoot.getElementById('textInterface');
30305
30338
  var voiceInterface = this.shadowRoot.getElementById('voiceInterface');
30306
30339
  var backBtn = this.shadowRoot.getElementById('backBtn');
30307
30340
  var newChatBtn = this.shadowRoot.getElementById('newChatBtn');
30308
- if (landing) landing.classList.remove('active');
30309
30341
  if (textInterface) textInterface.classList.remove('active');
30310
30342
  if (voiceInterface) voiceInterface.classList.add('active');
30311
- // Show back button when not on landing (only in unified mode)
30343
+ // Voice hero is unified home no header back (text chat uses its own back bar)
30312
30344
  var widgetMode = this.config.behavior.mode || 'unified';
30313
- if (backBtn && widgetMode === 'unified') backBtn.classList.add('visible');
30345
+ if (backBtn && widgetMode === 'unified') backBtn.classList.remove('visible');
30314
30346
  // Hide new chat button on voice interface (not applicable)
30315
30347
  if (newChatBtn) newChatBtn.style.display = 'none';
30316
30348
  }
30349
+
30350
+ /**
30351
+ * Mobile (≤768px): close chat panel and show Call vs Chat overlay (#ttpMobileLanding).
30352
+ * Hides FAB while landing is open. No-op on desktop or if mobile chrome is missing.
30353
+ */
30317
30354
  }, {
30318
- key: "setupMobileWidgetEvents",
30319
- value: function setupMobileWidgetEvents() {
30355
+ key: "_openMobileCallTextLanding",
30356
+ value: function _openMobileCallTextLanding() {
30320
30357
  var _this8 = this;
30321
- if (!this.shadowRoot) return;
30358
+ if (!this.shadowRoot || window.innerWidth > 768) return;
30322
30359
  var mobileFab = this.shadowRoot.querySelector('.ttp-mobile-fab');
30323
30360
  var mobileLanding = this.shadowRoot.getElementById('ttpMobileLanding');
30324
30361
  if (!mobileFab || !mobileLanding) return;
30325
- var closeMobileLanding = function closeMobileLanding() {
30326
- mobileLanding.classList.remove('active');
30327
- mobileFab.style.display = '';
30328
- _this8.isMobileLandingOpen = false;
30329
- };
30330
- var openMobileLanding = function openMobileLanding() {
30362
+
30363
+ // Defer showing landing until after the current pointer/click event finishes.
30364
+ // Otherwise document's "outside click" listener runs in the same bubble as e.g. the text
30365
+ // "Back" button: composedPath includes the panel but not #ttpMobileLanding, so it treated
30366
+ // the click as "outside" and closed the landing immediately (user only saw the FAB again).
30367
+ var open = function open() {
30368
+ if (!_this8.shadowRoot || window.innerWidth > 768) return;
30369
+ var panel = _this8.shadowRoot.getElementById('text-chat-panel');
30370
+ if (panel) {
30371
+ panel.classList.remove('open');
30372
+ _this8.isOpen = false;
30373
+ }
30331
30374
  if (_this8.config.promptAnimation.hideAfterClick) {
30332
30375
  _this8.hidePrompt();
30333
30376
  }
30334
- // Clear any previous error banner
30335
30377
  var errorBanner = _this8.shadowRoot.getElementById('ttpMobileLandingError');
30336
30378
  if (errorBanner) errorBanner.style.display = 'none';
30337
- mobileFab.style.display = 'none';
30338
- mobileLanding.classList.add('active');
30379
+ var fab = _this8.shadowRoot.querySelector('.ttp-mobile-fab');
30380
+ var landing = _this8.shadowRoot.getElementById('ttpMobileLanding');
30381
+ if (!fab || !landing) return;
30382
+ fab.style.display = 'none';
30383
+ landing.classList.add('active');
30339
30384
  _this8.isMobileLandingOpen = true;
30340
30385
  };
30341
- mobileFab.onclick = openMobileLanding;
30386
+ queueMicrotask(open);
30387
+ }
30388
+ }, {
30389
+ key: "setupMobileWidgetEvents",
30390
+ value: function setupMobileWidgetEvents() {
30391
+ var _this9 = this;
30392
+ if (!this.shadowRoot) return;
30393
+ var mobileFab = this.shadowRoot.querySelector('.ttp-mobile-fab');
30394
+ var mobileLanding = this.shadowRoot.getElementById('ttpMobileLanding');
30395
+ if (!mobileFab || !mobileLanding) return;
30396
+ var closeMobileLanding = function closeMobileLanding() {
30397
+ mobileLanding.classList.remove('active');
30398
+ mobileFab.style.display = '';
30399
+ _this9.isMobileLandingOpen = false;
30400
+ };
30401
+ mobileFab.onclick = function () {
30402
+ return _this9._openMobileCallTextLanding();
30403
+ };
30342
30404
  var mobileClose = mobileLanding.querySelector('.ttp-mobile-landing__close');
30343
30405
  if (mobileClose) {
30344
30406
  mobileClose.onclick = closeMobileLanding;
@@ -30347,31 +30409,39 @@ var TTPChatWidget = /*#__PURE__*/function () {
30347
30409
  if (mobileCallBtn) {
30348
30410
  mobileCallBtn.onclick = function () {
30349
30411
  closeMobileLanding();
30350
- var desktopVoiceCard = _this8.shadowRoot.getElementById('mode-card-voice');
30351
- if (desktopVoiceCard) {
30352
- desktopVoiceCard.click();
30353
- } else {
30354
- _this8.showVoice();
30412
+ var panel = _this9.shadowRoot.getElementById('text-chat-panel');
30413
+ if (panel) {
30414
+ panel.classList.add('open');
30415
+ _this9.isOpen = true;
30355
30416
  }
30417
+ mobileFab.style.display = 'none';
30418
+ _this9.showVoice();
30419
+ // Landing already chose "Voice call" — start the call (mic permission / pre-prompt) instead of
30420
+ // leaving users on a second "Start Call" tap that feels broken.
30421
+ queueMicrotask(function () {
30422
+ _this9.startVoiceCall().catch(function (err) {
30423
+ console.error('[TTPChatWidget] Mobile landing voice start failed:', err);
30424
+ });
30425
+ });
30356
30426
  };
30357
30427
  }
30358
30428
  var mobileChatBtn = this.shadowRoot.getElementById('ttpMobileChatBtn');
30359
30429
  if (mobileChatBtn) {
30360
30430
  mobileChatBtn.onclick = function () {
30361
30431
  closeMobileLanding();
30362
- var panel = _this8.shadowRoot.getElementById('text-chat-panel');
30432
+ var panel = _this9.shadowRoot.getElementById('text-chat-panel');
30363
30433
  if (panel) {
30364
30434
  panel.classList.add('open');
30365
- _this8.isOpen = true;
30435
+ _this9.isOpen = true;
30366
30436
  }
30367
30437
  mobileFab.style.display = 'none';
30368
- _this8.showText();
30438
+ _this9.showText();
30369
30439
  };
30370
30440
  }
30371
30441
 
30372
30442
  // Close mobile landing on outside click
30373
30443
  document.addEventListener('click', function (e) {
30374
- if (!_this8.isMobileLandingOpen) return;
30444
+ if (!_this9.isMobileLandingOpen) return;
30375
30445
  var path = e.composedPath();
30376
30446
  if (!path.includes(mobileLanding) && !path.includes(mobileFab)) {
30377
30447
  closeMobileLanding();
@@ -30380,7 +30450,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
30380
30450
 
30381
30451
  // Close mobile landing on Escape
30382
30452
  document.addEventListener('keydown', function (e) {
30383
- if (e.key === 'Escape' && _this8.isMobileLandingOpen) {
30453
+ if (e.key === 'Escape' && _this9.isMobileLandingOpen) {
30384
30454
  closeMobileLanding();
30385
30455
  }
30386
30456
  });
@@ -30388,10 +30458,10 @@ var TTPChatWidget = /*#__PURE__*/function () {
30388
30458
  }, {
30389
30459
  key: "setupKeyboardNavigation",
30390
30460
  value: function setupKeyboardNavigation() {
30391
- var _this9 = this;
30461
+ var _this0 = this;
30392
30462
  document.addEventListener('keydown', function (e) {
30393
- if (e.key === 'Escape' && _this9.isOpen) {
30394
- _this9.togglePanel();
30463
+ if (e.key === 'Escape' && _this0.isOpen) {
30464
+ _this0.togglePanel();
30395
30465
  }
30396
30466
  });
30397
30467
  }
@@ -30402,7 +30472,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
30402
30472
  }, {
30403
30473
  key: "setupPromptAnimation",
30404
30474
  value: function setupPromptAnimation() {
30405
- var _this0 = this;
30475
+ var _this1 = this;
30406
30476
  if (!this.shadowRoot) return;
30407
30477
  var promptConfig = this.config.promptAnimation || {};
30408
30478
  // Default to disabled if not specified (enabled === true means explicitly enabled)
@@ -30432,7 +30502,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
30432
30502
  // Auto-hide after configured seconds (only if widget is closed)
30433
30503
  if (!this.isOpen && promptConfig.hideAfterSeconds !== null && promptConfig.hideAfterSeconds > 0) {
30434
30504
  this.promptAutoHideTimer = setTimeout(function () {
30435
- _this0.hidePrompt();
30505
+ _this1.hidePrompt();
30436
30506
  }, promptConfig.hideAfterSeconds * 1000);
30437
30507
  }
30438
30508
 
@@ -30444,7 +30514,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
30444
30514
  // Wrap the callback to also hide pulse rings
30445
30515
  this.config.onConversationStart = function () {
30446
30516
  // Hide pulse rings when call starts
30447
- var pulseRings = _this0.shadowRoot.getElementById('prompt-pulse-rings');
30517
+ var pulseRings = _this1.shadowRoot.getElementById('prompt-pulse-rings');
30448
30518
  if (pulseRings) pulseRings.style.display = 'none';
30449
30519
 
30450
30520
  // Call original callback if it exists
@@ -30456,7 +30526,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
30456
30526
  // Also listen to recordingStarted event from SDK if available
30457
30527
  if (this.voiceInterface.sdk.voiceSDK) {
30458
30528
  this.voiceInterface.sdk.voiceSDK.on('recordingStarted', function () {
30459
- var pulseRings = _this0.shadowRoot.getElementById('prompt-pulse-rings');
30529
+ var pulseRings = _this1.shadowRoot.getElementById('prompt-pulse-rings');
30460
30530
  if (pulseRings) pulseRings.style.display = 'none';
30461
30531
  });
30462
30532
  }
@@ -30504,7 +30574,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
30504
30574
  }, {
30505
30575
  key: "showPrompt",
30506
30576
  value: function showPrompt() {
30507
- var _this1 = this;
30577
+ var _this10 = this;
30508
30578
  if (!this.shadowRoot) return;
30509
30579
  var promptConfig = this.config.promptAnimation || {};
30510
30580
  // Default to enabled if not specified
@@ -30524,8 +30594,8 @@ var TTPChatWidget = /*#__PURE__*/function () {
30524
30594
  // Function to actually show the elements
30525
30595
  var doShow = function doShow() {
30526
30596
  // Show prompt bubble (check both shadow root and document for compatibility)
30527
- var promptBubble = _this1.shadowRoot.getElementById('prompt-bubble');
30528
- if (!promptBubble && _this1.shadowRoot !== document) {
30597
+ var promptBubble = _this10.shadowRoot.getElementById('prompt-bubble');
30598
+ if (!promptBubble && _this10.shadowRoot !== document) {
30529
30599
  promptBubble = document.getElementById('prompt-bubble');
30530
30600
  }
30531
30601
  if (promptBubble) {
@@ -30539,8 +30609,8 @@ var TTPChatWidget = /*#__PURE__*/function () {
30539
30609
 
30540
30610
  // Show pulse rings if enabled
30541
30611
  if (promptConfig.showPulseRings !== false) {
30542
- var _pulseRings = _this1.shadowRoot.getElementById('prompt-pulse-rings');
30543
- if (!_pulseRings && _this1.shadowRoot !== document) {
30612
+ var _pulseRings = _this10.shadowRoot.getElementById('prompt-pulse-rings');
30613
+ if (!_pulseRings && _this10.shadowRoot !== document) {
30544
30614
  _pulseRings = document.getElementById('prompt-pulse-rings');
30545
30615
  }
30546
30616
  if (_pulseRings) {
@@ -30577,7 +30647,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
30577
30647
  }
30578
30648
  // Start new timer
30579
30649
  this.promptAutoHideTimer = setTimeout(function () {
30580
- _this1.hidePrompt();
30650
+ _this10.hidePrompt();
30581
30651
  }, promptConfig.hideAfterSeconds * 1000);
30582
30652
  }
30583
30653
  }
@@ -30593,7 +30663,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
30593
30663
  }, {
30594
30664
  key: "_doTogglePanel",
30595
30665
  value: function _doTogglePanel() {
30596
- var _this10 = this;
30666
+ var _this11 = this;
30597
30667
  if (!this.shadowRoot) return;
30598
30668
  this.isOpen = !this.isOpen;
30599
30669
  var panel = this.shadowRoot.getElementById('text-chat-panel');
@@ -30612,7 +30682,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
30612
30682
  // Panel is opening - hide prompt
30613
30683
  this.hidePrompt();
30614
30684
  setTimeout(function () {
30615
- var input = _this10.shadowRoot.getElementById('messageInput');
30685
+ var input = _this11.shadowRoot.getElementById('messageInput');
30616
30686
  if (input) input.focus();
30617
30687
  }, 100);
30618
30688
  } else {
@@ -30624,13 +30694,13 @@ var TTPChatWidget = /*#__PURE__*/function () {
30624
30694
  // Panel is closing - show prompt (if enabled)
30625
30695
  this.showPrompt();
30626
30696
  setTimeout(function () {
30627
- var _this10$config$prompt;
30628
- var promptBubble = _this10.shadowRoot.getElementById('prompt-bubble');
30697
+ var _this11$config$prompt;
30698
+ var promptBubble = _this11.shadowRoot.getElementById('prompt-bubble');
30629
30699
  if (promptBubble && promptBubble.style.display === 'none') {
30630
30700
  promptBubble.style.display = 'block';
30631
30701
  }
30632
- var pulseRings = _this10.shadowRoot.getElementById('prompt-pulse-rings');
30633
- if (pulseRings && ((_this10$config$prompt = _this10.config.promptAnimation) === null || _this10$config$prompt === void 0 ? void 0 : _this10$config$prompt.showPulseRings) !== false) {
30702
+ var pulseRings = _this11.shadowRoot.getElementById('prompt-pulse-rings');
30703
+ if (pulseRings && ((_this11$config$prompt = _this11.config.promptAnimation) === null || _this11$config$prompt === void 0 ? void 0 : _this11$config$prompt.showPulseRings) !== false) {
30634
30704
  if (pulseRings.style.display === 'none') {
30635
30705
  pulseRings.style.display = 'block';
30636
30706
  }
@@ -30774,17 +30844,17 @@ var TTPChatWidget = /*#__PURE__*/function () {
30774
30844
  }, {
30775
30845
  key: "startChat",
30776
30846
  value: function () {
30777
- var _startChat = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3() {
30778
- return _regenerator().w(function (_context3) {
30779
- while (1) switch (_context3.n) {
30847
+ var _startChat = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
30848
+ return _regenerator().w(function (_context2) {
30849
+ while (1) switch (_context2.n) {
30780
30850
  case 0:
30781
30851
  // No-op with single-shot design; connection happens per message
30782
30852
  this.isActive = true;
30783
30853
  this.textInterface.setActive(true);
30784
30854
  case 1:
30785
- return _context3.a(2);
30855
+ return _context2.a(2);
30786
30856
  }
30787
- }, _callee3, this);
30857
+ }, _callee2, this);
30788
30858
  }));
30789
30859
  function startChat() {
30790
30860
  return _startChat.apply(this, arguments);
@@ -30794,16 +30864,16 @@ var TTPChatWidget = /*#__PURE__*/function () {
30794
30864
  }, {
30795
30865
  key: "sendMessage",
30796
30866
  value: function () {
30797
- var _sendMessage = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4() {
30798
- return _regenerator().w(function (_context4) {
30799
- while (1) switch (_context4.n) {
30867
+ var _sendMessage = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3() {
30868
+ return _regenerator().w(function (_context3) {
30869
+ while (1) switch (_context3.n) {
30800
30870
  case 0:
30801
- _context4.n = 1;
30871
+ _context3.n = 1;
30802
30872
  return this.textInterface.sendMessage();
30803
30873
  case 1:
30804
- return _context4.a(2);
30874
+ return _context3.a(2);
30805
30875
  }
30806
- }, _callee4, this);
30876
+ }, _callee3, this);
30807
30877
  }));
30808
30878
  function sendMessage() {
30809
30879
  return _sendMessage.apply(this, arguments);
@@ -30899,7 +30969,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
30899
30969
  }, {
30900
30970
  key: "updateConfig",
30901
30971
  value: function updateConfig(newConfig) {
30902
- var _this$config, _this$config2, _this$config$voice8, _this$config$voice9, _this$config$voice0, _this$config$voice1, _this$config$voice10, _this$config$behavior7;
30972
+ var _this$config2, _this$config3, _this$config$voice8, _this$config$voice9, _this$config$voice0, _this$config$voice1, _this$config$voice10;
30903
30973
  // Deep merge nested objects
30904
30974
  var mergedConfig = _objectSpread({}, this.config);
30905
30975
 
@@ -30908,14 +30978,18 @@ var TTPChatWidget = /*#__PURE__*/function () {
30908
30978
  mergedConfig.panel = _objectSpread(_objectSpread({}, this.config.panel), newConfig.panel);
30909
30979
  }
30910
30980
 
30911
- // Deep merge voice config if it exists
30981
+ // Deep merge voice config if it exists (root `agentName` only — ignore `voice.agentName`)
30912
30982
  if (newConfig.voice) {
30913
- mergedConfig.voice = _objectSpread(_objectSpread({}, this.config.voice), newConfig.voice);
30983
+ var _newConfig$voice = newConfig.voice,
30984
+ _ignoredVoiceAgentName = _newConfig$voice.agentName,
30985
+ voicePatch = _objectWithoutProperties(_newConfig$voice, _excluded);
30986
+ mergedConfig.voice = _objectSpread(_objectSpread({}, this.config.voice), voicePatch);
30914
30987
  // Deep merge micButtonHint if it exists
30915
30988
  if (newConfig.voice.micButtonHint) {
30916
30989
  var _this$config$voice7;
30917
30990
  mergedConfig.voice.micButtonHint = _objectSpread(_objectSpread({}, (_this$config$voice7 = this.config.voice) === null || _this$config$voice7 === void 0 ? void 0 : _this$config$voice7.micButtonHint), newConfig.voice.micButtonHint);
30918
30991
  }
30992
+ delete mergedConfig.voice.agentName;
30919
30993
  }
30920
30994
 
30921
30995
  // Deep merge text config if it exists
@@ -30935,8 +31009,8 @@ var TTPChatWidget = /*#__PURE__*/function () {
30935
31009
 
30936
31010
  // Update direction if language changed to RTL language
30937
31011
  if (newConfig.language !== undefined) {
30938
- var rtlLanguages = ['he', 'ar'];
30939
- if (rtlLanguages.includes(newConfig.language)) {
31012
+ var langBase = String(newConfig.language).toLowerCase().split(/[-_]/)[0];
31013
+ if (langBase === 'he' || langBase === 'ar') {
30940
31014
  mergedConfig.direction = 'rtl';
30941
31015
  } else if (newConfig.direction === undefined) {
30942
31016
  mergedConfig.direction = 'ltr';
@@ -31013,9 +31087,9 @@ var TTPChatWidget = /*#__PURE__*/function () {
31013
31087
  });
31014
31088
 
31015
31089
  // Store current language before merge to detect changes
31016
- var oldLanguage = ((_this$config = this.config) === null || _this$config === void 0 ? void 0 : _this$config.language) || 'en';
31090
+ var oldLanguage = ((_this$config2 = this.config) === null || _this$config2 === void 0 ? void 0 : _this$config2.language) || 'en';
31017
31091
  // Store current useShadowDOM setting
31018
- var oldUseShadowDOM = ((_this$config2 = this.config) === null || _this$config2 === void 0 ? void 0 : _this$config2.useShadowDOM) !== false;
31092
+ var oldUseShadowDOM = ((_this$config3 = this.config) === null || _this$config3 === void 0 ? void 0 : _this$config3.useShadowDOM) !== false;
31019
31093
  this.config = this.mergeWithDefaults(mergedConfig);
31020
31094
 
31021
31095
  // Check if useShadowDOM changed - if so, need to recreate container
@@ -31094,6 +31168,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
31094
31168
  // Ensure language is correctly passed - use the merged config value
31095
31169
  var currentLanguage = this.config.language || 'en';
31096
31170
  var voiceConfig = _objectSpread(_objectSpread(_objectSpread({}, this.config), this.config.voice), {}, {
31171
+ agentName: this.config.agentName,
31097
31172
  language: currentLanguage,
31098
31173
  // Use the current language from merged config
31099
31174
  translations: this.translations,
@@ -31126,18 +31201,6 @@ var TTPChatWidget = /*#__PURE__*/function () {
31126
31201
  });
31127
31202
  this.textInterface = new _TextInterface_js__WEBPACK_IMPORTED_MODULE_2__.TextInterface(textConfig, this.sdk);
31128
31203
 
31129
- // Recreate landing screen if in unified mode
31130
- var widgetMode = ((_this$config$behavior7 = this.config.behavior) === null || _this$config$behavior7 === void 0 ? void 0 : _this$config$behavior7.mode) || 'unified';
31131
- if (widgetMode === 'unified') {
31132
- var landingConfig = _objectSpread(_objectSpread({}, this.config), {}, {
31133
- translations: this.translations,
31134
- shadowRoot: this.shadowRoot
31135
- });
31136
- this.landingScreen = new _LandingScreen_js__WEBPACK_IMPORTED_MODULE_3__.LandingScreen(landingConfig);
31137
- } else {
31138
- this.landingScreen = null;
31139
- }
31140
-
31141
31204
  // Recreate widget with new config (after interfaces are created)
31142
31205
  this.createWidget();
31143
31206
 
@@ -31188,19 +31251,19 @@ var TTPChatWidget = /*#__PURE__*/function () {
31188
31251
  }, {
31189
31252
  key: "startVoiceCall",
31190
31253
  value: function () {
31191
- var _startVoiceCall = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5() {
31192
- return _regenerator().w(function (_context5) {
31193
- while (1) switch (_context5.n) {
31254
+ var _startVoiceCall = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4() {
31255
+ return _regenerator().w(function (_context4) {
31256
+ while (1) switch (_context4.n) {
31194
31257
  case 0:
31195
- _context5.n = 1;
31258
+ _context4.n = 1;
31196
31259
  return this.voiceInterface.startVoiceCall();
31197
31260
  case 1:
31198
31261
  // Flush pending tools after SDK connects
31199
31262
  this._flushPendingClientTools();
31200
31263
  case 2:
31201
- return _context5.a(2);
31264
+ return _context4.a(2);
31202
31265
  }
31203
- }, _callee5, this);
31266
+ }, _callee4, this);
31204
31267
  }));
31205
31268
  function startVoiceCall() {
31206
31269
  return _startVoiceCall.apply(this, arguments);
@@ -31253,26 +31316,26 @@ var TTPChatWidget = /*#__PURE__*/function () {
31253
31316
  }, {
31254
31317
  key: "injectData",
31255
31318
  value: (function () {
31256
- var _injectData = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6(data) {
31319
+ var _injectData = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5(data) {
31257
31320
  var _this$voiceInterface5;
31258
31321
  var options,
31259
31322
  voiceSDK,
31260
31323
  ack,
31261
- _args6 = arguments,
31262
- _t2;
31263
- return _regenerator().w(function (_context6) {
31264
- while (1) switch (_context6.p = _context6.n) {
31324
+ _args5 = arguments,
31325
+ _t;
31326
+ return _regenerator().w(function (_context5) {
31327
+ while (1) switch (_context5.p = _context5.n) {
31265
31328
  case 0:
31266
- options = _args6.length > 1 && _args6[1] !== undefined ? _args6[1] : {};
31329
+ options = _args5.length > 1 && _args5[1] !== undefined ? _args5[1] : {};
31267
31330
  if (!(!data || !data.trim())) {
31268
- _context6.n = 1;
31331
+ _context5.n = 1;
31269
31332
  break;
31270
31333
  }
31271
31334
  console.warn('TTPChatWidget: Cannot inject empty data');
31272
31335
  throw new Error('Cannot inject empty data');
31273
31336
  case 1:
31274
31337
  if (!(!this.voiceInterface || !this.voiceInterface.isActive)) {
31275
- _context6.n = 2;
31338
+ _context5.n = 2;
31276
31339
  break;
31277
31340
  }
31278
31341
  console.warn('TTPChatWidget: Cannot inject data - voice call is not active');
@@ -31281,28 +31344,28 @@ var TTPChatWidget = /*#__PURE__*/function () {
31281
31344
  // Check if SDK is available
31282
31345
  voiceSDK = (_this$voiceInterface5 = this.voiceInterface) === null || _this$voiceInterface5 === void 0 ? void 0 : _this$voiceInterface5.getVoiceSDK();
31283
31346
  if (voiceSDK) {
31284
- _context6.n = 3;
31347
+ _context5.n = 3;
31285
31348
  break;
31286
31349
  }
31287
31350
  console.warn('TTPChatWidget: VoiceSDK not available');
31288
31351
  throw new Error('VoiceSDK not available');
31289
31352
  case 3:
31290
- _context6.p = 3;
31291
- _context6.n = 4;
31353
+ _context5.p = 3;
31354
+ _context5.n = 4;
31292
31355
  return voiceSDK.injectData(data, _objectSpread(_objectSpread({}, options), {}, {
31293
31356
  source: options.source || 'widget_programmatic'
31294
31357
  }));
31295
31358
  case 4:
31296
- ack = _context6.v;
31297
- return _context6.a(2, ack);
31359
+ ack = _context5.v;
31360
+ return _context5.a(2, ack);
31298
31361
  case 5:
31299
- _context6.p = 5;
31300
- _t2 = _context6.v;
31301
- throw _t2;
31362
+ _context5.p = 5;
31363
+ _t = _context5.v;
31364
+ throw _t;
31302
31365
  case 6:
31303
- return _context6.a(2);
31366
+ return _context5.a(2);
31304
31367
  }
31305
- }, _callee6, this, [[3, 5]]);
31368
+ }, _callee5, this, [[3, 5]]);
31306
31369
  }));
31307
31370
  function injectData(_x) {
31308
31371
  return _injectData.apply(this, arguments);
@@ -31401,12 +31464,12 @@ var TTPChatWidget = /*#__PURE__*/function () {
31401
31464
  key: "_flushPendingClientTools",
31402
31465
  value: function _flushPendingClientTools() {
31403
31466
  var _this$voiceInterface0,
31404
- _this11 = this;
31467
+ _this12 = this;
31405
31468
  if (this._pendingClientTools && (_this$voiceInterface0 = this.voiceInterface) !== null && _this$voiceInterface0 !== void 0 && _this$voiceInterface0.sdk) {
31406
31469
  this._pendingClientTools.forEach(function (_ref3) {
31407
31470
  var name = _ref3.name,
31408
31471
  handler = _ref3.handler;
31409
- _this11.voiceInterface.sdk.registerToolHandler(name, handler);
31472
+ _this12.voiceInterface.sdk.registerToolHandler(name, handler);
31410
31473
  });
31411
31474
  this._pendingClientTools = null;
31412
31475
  console.log('TTPChatWidget: Flushed pending client tools');
@@ -31531,10 +31594,13 @@ var TextInterface = /*#__PURE__*/function () {
31531
31594
  }, {
31532
31595
  key: "generateHTML",
31533
31596
  value: function generateHTML() {
31534
- var _this$config$panel, _this$config$sendButt, _this$config$panel2, _this$config$sendButt2, _this$config$panel3, _this$config$sendButt3, _this$config$panel4, _this$config$sendButt4, _this$config$panel5;
31597
+ var _this$config$panel, _this$config$behavior, _this$config$sendButt, _this$config$panel2, _this$config$sendButt2, _this$config$panel3, _this$config$sendButt3, _this$config$panel4, _this$config$sendButt4, _this$config$panel5;
31535
31598
  // Use text config, fallback to panel config, then translation, then default
31536
31599
  var inputPlaceholder = this.config.inputPlaceholder || ((_this$config$panel = this.config.panel) === null || _this$config$panel === void 0 ? void 0 : _this$config$panel.inputPlaceholder) || this.t('typeMessage') || 'Type your message...';
31537
- return "<div class=\"text-interface\" id=\"textInterface\">\n <div class=\"messages-container\" id=\"messagesContainer\">\n <div class=\"empty-state\">\n <div class=\"empty-state-icon\">\uD83D\uDCAC</div>\n <div class=\"empty-state-title\">".concat(this.t('hello'), "</div>\n <div class=\"empty-state-text\">").concat(this.t('sendMessage'), "</div>\n </div>\n </div>\n <div class=\"input-container\">\n <div class=\"input-wrapper\" style=\"flex:1;\">\n <textarea class=\"message-input\" id=\"messageInput\" placeholder=\"").concat(inputPlaceholder, "\" rows=\"1\" dir=\"").concat(this.config.direction || 'ltr', "\"></textarea>\n </div>\n <button class=\"send-button\" id=\"sendButton\" aria-label=\"").concat(this.t('sendMessageAria'), "\">").concat(this.config.sendButtonText || '➤', "</button>\n ").concat((_this$config$sendButt = this.config.sendButtonHint) !== null && _this$config$sendButt !== void 0 && _this$config$sendButt.text || (_this$config$panel2 = this.config.panel) !== null && _this$config$panel2 !== void 0 && (_this$config$panel2 = _this$config$panel2.sendButtonHint) !== null && _this$config$panel2 !== void 0 && _this$config$panel2.text ? "\n <div class=\"send-button-hint\" style=\"color: ".concat(((_this$config$sendButt2 = this.config.sendButtonHint) === null || _this$config$sendButt2 === void 0 ? void 0 : _this$config$sendButt2.color) || ((_this$config$panel3 = this.config.panel) === null || _this$config$panel3 === void 0 || (_this$config$panel3 = _this$config$panel3.sendButtonHint) === null || _this$config$panel3 === void 0 ? void 0 : _this$config$panel3.color) || '#6B7280', "; font-size: ").concat(((_this$config$sendButt3 = this.config.sendButtonHint) === null || _this$config$sendButt3 === void 0 ? void 0 : _this$config$sendButt3.fontSize) || ((_this$config$panel4 = this.config.panel) === null || _this$config$panel4 === void 0 || (_this$config$panel4 = _this$config$panel4.sendButtonHint) === null || _this$config$panel4 === void 0 ? void 0 : _this$config$panel4.fontSize) || '12px', "; text-align: center; margin-top: 4px;\">\n ").concat(((_this$config$sendButt4 = this.config.sendButtonHint) === null || _this$config$sendButt4 === void 0 ? void 0 : _this$config$sendButt4.text) || ((_this$config$panel5 = this.config.panel) === null || _this$config$panel5 === void 0 || (_this$config$panel5 = _this$config$panel5.sendButtonHint) === null || _this$config$panel5 === void 0 ? void 0 : _this$config$panel5.text), "\n </div>\n ") : '', "\n </div>\n </div>");
31600
+ var unifiedMode = ((_this$config$behavior = this.config.behavior) === null || _this$config$behavior === void 0 ? void 0 : _this$config$behavior.mode) === 'unified';
31601
+ var backArrow = this.config.direction === 'rtl' ? '→' : '←';
31602
+ var backBar = unifiedMode ? "\n <div class=\"text-interface-top-bar\">\n <button type=\"button\" class=\"text-interface-back-btn\" id=\"textUnifiedBackBtn\" aria-label=\"".concat(this.t('back'), "\">\n <span class=\"text-interface-back-icon\" aria-hidden=\"true\">").concat(backArrow, "</span>\n <span class=\"text-interface-back-label\">").concat(this.t('back'), "</span>\n </button>\n </div>") : '';
31603
+ return "<div class=\"text-interface\" id=\"textInterface\">\n ".concat(backBar, "\n <div class=\"messages-container\" id=\"messagesContainer\">\n <div class=\"empty-state\">\n <div class=\"empty-state-icon\">\uD83D\uDCAC</div>\n <div class=\"empty-state-title\">").concat(this.t('hello'), "</div>\n <div class=\"empty-state-text\">").concat(this.t('sendMessage'), "</div>\n </div>\n </div>\n <div class=\"input-container\">\n <div class=\"input-wrapper\" style=\"flex:1;\">\n <textarea class=\"message-input\" id=\"messageInput\" placeholder=\"").concat(inputPlaceholder, "\" rows=\"1\" dir=\"").concat(this.config.direction || 'ltr', "\"></textarea>\n </div>\n <button class=\"send-button\" id=\"sendButton\" aria-label=\"").concat(this.t('sendMessageAria'), "\">").concat(this.config.sendButtonText || '➤', "</button>\n ").concat((_this$config$sendButt = this.config.sendButtonHint) !== null && _this$config$sendButt !== void 0 && _this$config$sendButt.text || (_this$config$panel2 = this.config.panel) !== null && _this$config$panel2 !== void 0 && (_this$config$panel2 = _this$config$panel2.sendButtonHint) !== null && _this$config$panel2 !== void 0 && _this$config$panel2.text ? "\n <div class=\"send-button-hint\" style=\"color: ".concat(((_this$config$sendButt2 = this.config.sendButtonHint) === null || _this$config$sendButt2 === void 0 ? void 0 : _this$config$sendButt2.color) || ((_this$config$panel3 = this.config.panel) === null || _this$config$panel3 === void 0 || (_this$config$panel3 = _this$config$panel3.sendButtonHint) === null || _this$config$panel3 === void 0 ? void 0 : _this$config$panel3.color) || '#6B7280', "; font-size: ").concat(((_this$config$sendButt3 = this.config.sendButtonHint) === null || _this$config$sendButt3 === void 0 ? void 0 : _this$config$sendButt3.fontSize) || ((_this$config$panel4 = this.config.panel) === null || _this$config$panel4 === void 0 || (_this$config$panel4 = _this$config$panel4.sendButtonHint) === null || _this$config$panel4 === void 0 ? void 0 : _this$config$panel4.fontSize) || '12px', "; text-align: center; margin-top: 4px;\">\n ").concat(((_this$config$sendButt4 = this.config.sendButtonHint) === null || _this$config$sendButt4 === void 0 ? void 0 : _this$config$sendButt4.text) || ((_this$config$panel5 = this.config.panel) === null || _this$config$panel5 === void 0 || (_this$config$panel5 = _this$config$panel5.sendButtonHint) === null || _this$config$panel5 === void 0 ? void 0 : _this$config$panel5.text), "\n </div>\n ") : '', "\n </div>\n </div>");
31538
31604
  }
31539
31605
 
31540
31606
  /**
@@ -31563,7 +31629,7 @@ var TextInterface = /*#__PURE__*/function () {
31563
31629
 
31564
31630
  // Add !important to display rules when not using Shadow DOM (to override theme CSS)
31565
31631
  var important = this.config.useShadowDOM === false ? ' !important' : '';
31566
- return "\n /* Messages container using new classes */\n #messagesContainer { \n flex: 1".concat(important, "; \n overflow-y: auto").concat(important, "; \n overflow-x: hidden").concat(important, "; \n padding: 20px").concat(important, "; \n background: #f8fafc").concat(important, "; \n display: flex").concat(important, "; \n flex-direction: column").concat(important, "; \n gap: 16px").concat(important, "; \n min-height: 0").concat(important, "; \n }\n .empty-state { \n flex: 1").concat(important, "; \n display: flex").concat(important, "; \n flex-direction: column").concat(important, "; \n align-items: center").concat(important, "; \n justify-content: center").concat(important, "; \n gap: 12px").concat(important, "; \n color: #64748b").concat(important, "; \n text-align: center").concat(important, "; \n padding: 20px").concat(important, "; \n }\n .empty-state-icon { font-size: 48px").concat(important, "; opacity: 0.3").concat(important, "; }\n .empty-state-title { font-size: 20px").concat(important, "; font-weight: 700").concat(important, "; color: #334155").concat(important, "; }\n .empty-state-text { font-size: 13px").concat(important, "; max-width: 280px").concat(important, "; }\n\n .text-interface { \n display: none").concat(important, "; \n flex: 1").concat(important, "; \n flex-direction: column").concat(important, "; \n min-height: 0").concat(important, "; \n overflow: hidden").concat(important, "; \n }\n .text-interface.active { display: flex").concat(important, "; }\n \n .message { \n display: flex").concat(important, "; \n gap: 8px").concat(important, "; \n padding: 4px 0").concat(important, "; \n max-width: 100%").concat(important, "; \n align-items: center").concat(important, "; \n }\n .message.edge-left { flex-direction: row").concat(important, "; }\n .message.edge-right { flex-direction: row-reverse").concat(important, "; }\n .message-bubble { \n padding: 12px").concat(important, "; \n border-radius: ").concat(messages.borderRadius, "px").concat(important, "; \n max-width: 80%").concat(important, "; \n font-size: ").concat(messages.fontSize, "; \n word-wrap: break-word").concat(important, "; \n text-align: ").concat(this.config.direction === 'rtl' ? 'right' : 'left').concat(important, "; \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').concat(important, "; \n }\n .message.agent { \n align-self: ").concat(this.config.direction === 'rtl' ? 'flex-end' : 'flex-start').concat(important, "; \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").concat(important, "; \n height: 20px").concat(important, "; \n display: flex").concat(important, "; \n align-items: center").concat(important, "; \n justify-content: center").concat(important, "; \n flex-shrink: 0").concat(important, "; \n color: inherit").concat(important, "; \n font-size: 18px").concat(important, "; \n line-height: 1").concat(important, "; \n background: transparent").concat(important, "; \n border: none").concat(important, "; \n }\n .message-avatar.user { background: transparent").concat(important, "; }\n .message-avatar.agent { background: transparent").concat(important, "; }\n \n .message.system {\n background: ").concat(messages.systemBackgroundColor, ";\n align-self: flex-start").concat(important, ";\n }\n .message.error {\n background: ").concat(messages.errorBackgroundColor, ";\n align-self: flex-start").concat(important, ";\n }\n \n .input-container {\n display: flex").concat(important, ";\n gap: 8px").concat(important, ";\n padding: 12px 16px").concat(important, ";\n background: #FFFFFF").concat(important, ";\n border-top: 1px solid #E5E7EB").concat(important, ";\n align-items: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n flex-direction: ").concat(this.config.direction === 'rtl' ? 'row-reverse' : 'row').concat(important, ";\n }\n \n .input-wrapper {\n position: relative").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n }\n \n .message-input {\n width: 100%").concat(important, ";\n min-height: 32px").concat(important, ";\n max-height: 120px").concat(important, ";\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").concat(important, ";\n line-height: 1.3").concat(important, ";\n resize: none").concat(important, ";\n overflow-y: auto").concat(important, ";\n background: ").concat(inputBackgroundColor, ";\n color: ").concat(inputTextColor, ";\n vertical-align: top").concat(important, ";\n margin: 0").concat(important, ";\n display: block").concat(important, ";\n white-space: pre-wrap").concat(important, ";\n word-wrap: break-word").concat(important, ";\n text-align: ").concat(this.config.direction === 'rtl' ? 'right' : 'left').concat(important, ";\n direction: ").concat(this.config.direction || 'ltr', ";\n -webkit-appearance: none").concat(important, ";\n appearance: none").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n \n .message-input:focus {\n outline: none").concat(important, ";\n border-color: ").concat(inputFocusColor, ";\n background: ").concat(inputBackgroundColor === '#FFFFFF' ? '#FFFFFF' : inputBackgroundColor).concat(important, ";\n box-shadow: 0 0 0 3px ").concat(inputFocusColor, "33;\n }\n \n .message-input::placeholder {\n color: #9CA3AF").concat(important, ";\n text-align: ").concat(this.config.direction === 'rtl' ? 'right' : 'left').concat(important, ";\n }\n \n .send-button {\n width: 40px").concat(important, ";\n height: 40px").concat(important, ";\n border-radius: 50%").concat(important, ";\n border: none").concat(important, ";\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").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n transition: all 0.2s ease").concat(important, ";\n box-shadow: 0 4px 12px rgba(124, 60, 237, 0.3)").concat(important, ";\n }\n \n .send-button:hover:not(:disabled) {\n background: ").concat(sendButtonHoverColor, ";\n transform: scale(1.05)").concat(important, ";\n box-shadow: 0 6px 16px rgba(124, 60, 237, 0.4)").concat(important, ";\n }\n \n .send-button-hint {\n width: 100%").concat(important, ";\n text-align: center").concat(important, ";\n margin-top: 4px").concat(important, ";\n }\n \n .send-button:disabled {\n opacity: 0.5").concat(important, ";\n cursor: not-allowed").concat(important, ";\n }\n \n .typing-indicator {\n display: inline-flex").concat(important, ";\n gap: 4px").concat(important, ";\n align-items: center").concat(important, ";\n }\n \n .typing-dot {\n width: 6px").concat(important, ";\n height: 6px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background: #64748b").concat(important, ";\n animation: typingDot 1.4s ease-in-out infinite").concat(important, ";\n }\n \n .typing-dot:nth-child(2) { animation-delay: 0.2s").concat(important, "; }\n .typing-dot:nth-child(3) { animation-delay: 0.4s").concat(important, "; }\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").concat(important, ";\n background: ").concat(messages.errorBackgroundColor, ";\n border-radius: ").concat(messages.borderRadius, "px;\n color: #991B1B").concat(important, ";\n font-size: ").concat(messages.fontSize, ";\n margin: 8px 0").concat(important, ";\n }\n \n @media (max-width: 768px) {\n #messagesContainer {\n padding: 12px").concat(important, ";\n gap: 12px").concat(important, ";\n }\n \n .message-bubble {\n max-width: 85%").concat(important, ";\n font-size: 14px").concat(important, ";\n padding: 10px").concat(important, ";\n }\n \n .text-input-container {\n padding: 10px").concat(important, ";\n gap: 8px").concat(important, ";\n }\n \n #text-chat-input {\n font-size: 16px !important; /* Prevents iOS zoom on focus */\n padding: 10px 14px").concat(important, ";\n min-height: 44px").concat(important, ";\n }\n \n #text-chat-send {\n min-width: 56px").concat(important, ";\n min-height: 44px").concat(important, ";\n width: 56px").concat(important, ";\n height: 44px").concat(important, ";\n }\n \n .empty-state-icon {\n font-size: 40px").concat(important, ";\n }\n \n .empty-state-title {\n font-size: 18px").concat(important, ";\n }\n \n .empty-state-text {\n font-size: 12px").concat(important, ";\n }\n }\n \n @media (max-width: 480px) {\n #messagesContainer {\n padding: 10px").concat(important, ";\n gap: 10px").concat(important, ";\n }\n \n .message-bubble {\n max-width: 90%").concat(important, ";\n font-size: 13px").concat(important, ";\n padding: 8px").concat(important, ";\n }\n \n .text-input-container {\n padding: 8px").concat(important, ";\n }\n \n #text-chat-input {\n font-size: 16px !important;\n padding: 8px 12px").concat(important, ";\n }\n }\n ");
31632
+ return "\n .text-interface-top-bar {\n flex-shrink: 0".concat(important, ";\n padding: 10px 12px 8px").concat(important, ";\n border-bottom: 1px solid #E5E7EB").concat(important, ";\n background: #FFFFFF").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n }\n .text-interface-back-btn {\n display: inline-flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 6px").concat(important, ";\n padding: 6px 10px").concat(important, ";\n margin: 0").concat(important, ";\n border: none").concat(important, ";\n border-radius: 8px").concat(important, ";\n background: transparent").concat(important, ";\n color: #475569").concat(important, ";\n font-size: 14px").concat(important, ";\n font-weight: 600").concat(important, ";\n cursor: pointer").concat(important, ";\n font-family: inherit").concat(important, ";\n }\n .text-interface-back-btn:hover {\n background: #f1f5f9").concat(important, ";\n color: #334155").concat(important, ";\n }\n .text-interface-back-icon {\n font-size: 16px").concat(important, ";\n line-height: 1").concat(important, ";\n }\n .text-interface-back-label {\n line-height: 1.2").concat(important, ";\n }\n /* Messages container using new classes */\n #messagesContainer { \n flex: 1").concat(important, "; \n overflow-y: auto").concat(important, "; \n overflow-x: hidden").concat(important, "; \n padding: 20px").concat(important, "; \n background: #f8fafc").concat(important, "; \n display: flex").concat(important, "; \n flex-direction: column").concat(important, "; \n gap: 16px").concat(important, "; \n min-height: 0").concat(important, "; \n }\n .empty-state { \n flex: 1").concat(important, "; \n display: flex").concat(important, "; \n flex-direction: column").concat(important, "; \n align-items: center").concat(important, "; \n justify-content: center").concat(important, "; \n gap: 12px").concat(important, "; \n color: #64748b").concat(important, "; \n text-align: center").concat(important, "; \n padding: 20px").concat(important, "; \n }\n .empty-state-icon { font-size: 48px").concat(important, "; opacity: 0.3").concat(important, "; }\n .empty-state-title { font-size: 20px").concat(important, "; font-weight: 700").concat(important, "; color: #334155").concat(important, "; }\n .empty-state-text { font-size: 13px").concat(important, "; max-width: 280px").concat(important, "; }\n\n .text-interface { \n display: none").concat(important, "; \n flex: 1").concat(important, "; \n flex-direction: column").concat(important, "; \n min-height: 0").concat(important, "; \n overflow: hidden").concat(important, "; \n }\n .text-interface.active { display: flex").concat(important, "; }\n \n .message { \n display: flex").concat(important, "; \n gap: 8px").concat(important, "; \n padding: 4px 0").concat(important, "; \n max-width: 100%").concat(important, "; \n align-items: center").concat(important, "; \n }\n .message.edge-left { flex-direction: row").concat(important, "; }\n .message.edge-right { flex-direction: row-reverse").concat(important, "; }\n .message-bubble { \n padding: 12px").concat(important, "; \n border-radius: ").concat(messages.borderRadius, "px").concat(important, "; \n max-width: 80%").concat(important, "; \n font-size: ").concat(messages.fontSize, "; \n word-wrap: break-word").concat(important, "; \n text-align: ").concat(this.config.direction === 'rtl' ? 'right' : 'left').concat(important, "; \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').concat(important, "; \n }\n .message.agent { \n align-self: ").concat(this.config.direction === 'rtl' ? 'flex-end' : 'flex-start').concat(important, "; \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").concat(important, "; \n height: 20px").concat(important, "; \n display: flex").concat(important, "; \n align-items: center").concat(important, "; \n justify-content: center").concat(important, "; \n flex-shrink: 0").concat(important, "; \n color: inherit").concat(important, "; \n font-size: 18px").concat(important, "; \n line-height: 1").concat(important, "; \n background: transparent").concat(important, "; \n border: none").concat(important, "; \n }\n .message-avatar.user { background: transparent").concat(important, "; }\n .message-avatar.agent { background: transparent").concat(important, "; }\n \n .message.system {\n background: ").concat(messages.systemBackgroundColor, ";\n align-self: flex-start").concat(important, ";\n }\n .message.error {\n background: ").concat(messages.errorBackgroundColor, ";\n align-self: flex-start").concat(important, ";\n }\n \n .input-container {\n display: flex").concat(important, ";\n gap: 8px").concat(important, ";\n padding: 12px 16px").concat(important, ";\n background: #FFFFFF").concat(important, ";\n border-top: 1px solid #E5E7EB").concat(important, ";\n align-items: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n flex-direction: ").concat(this.config.direction === 'rtl' ? 'row-reverse' : 'row').concat(important, ";\n }\n \n .input-wrapper {\n position: relative").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n }\n \n .message-input {\n width: 100%").concat(important, ";\n min-height: 32px").concat(important, ";\n max-height: 120px").concat(important, ";\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").concat(important, ";\n line-height: 1.3").concat(important, ";\n resize: none").concat(important, ";\n overflow-y: auto").concat(important, ";\n background: ").concat(inputBackgroundColor, ";\n color: ").concat(inputTextColor, ";\n vertical-align: top").concat(important, ";\n margin: 0").concat(important, ";\n display: block").concat(important, ";\n white-space: pre-wrap").concat(important, ";\n word-wrap: break-word").concat(important, ";\n text-align: ").concat(this.config.direction === 'rtl' ? 'right' : 'left').concat(important, ";\n direction: ").concat(this.config.direction || 'ltr', ";\n -webkit-appearance: none").concat(important, ";\n appearance: none").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n \n .message-input:focus {\n outline: none").concat(important, ";\n border-color: ").concat(inputFocusColor, ";\n background: ").concat(inputBackgroundColor === '#FFFFFF' ? '#FFFFFF' : inputBackgroundColor).concat(important, ";\n box-shadow: 0 0 0 3px ").concat(inputFocusColor, "33;\n }\n \n .message-input::placeholder {\n color: #9CA3AF").concat(important, ";\n text-align: ").concat(this.config.direction === 'rtl' ? 'right' : 'left').concat(important, ";\n }\n \n .send-button {\n width: 40px").concat(important, ";\n height: 40px").concat(important, ";\n border-radius: 50%").concat(important, ";\n border: none").concat(important, ";\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").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n transition: all 0.2s ease").concat(important, ";\n box-shadow: 0 4px 12px rgba(124, 60, 237, 0.3)").concat(important, ";\n }\n \n .send-button:hover:not(:disabled) {\n background: ").concat(sendButtonHoverColor, ";\n transform: scale(1.05)").concat(important, ";\n box-shadow: 0 6px 16px rgba(124, 60, 237, 0.4)").concat(important, ";\n }\n \n .send-button-hint {\n width: 100%").concat(important, ";\n text-align: center").concat(important, ";\n margin-top: 4px").concat(important, ";\n }\n \n .send-button:disabled {\n opacity: 0.5").concat(important, ";\n cursor: not-allowed").concat(important, ";\n }\n \n .typing-indicator {\n display: inline-flex").concat(important, ";\n gap: 4px").concat(important, ";\n align-items: center").concat(important, ";\n }\n \n .typing-dot {\n width: 6px").concat(important, ";\n height: 6px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background: #64748b").concat(important, ";\n animation: typingDot 1.4s ease-in-out infinite").concat(important, ";\n }\n \n .typing-dot:nth-child(2) { animation-delay: 0.2s").concat(important, "; }\n .typing-dot:nth-child(3) { animation-delay: 0.4s").concat(important, "; }\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").concat(important, ";\n background: ").concat(messages.errorBackgroundColor, ";\n border-radius: ").concat(messages.borderRadius, "px;\n color: #991B1B").concat(important, ";\n font-size: ").concat(messages.fontSize, ";\n margin: 8px 0").concat(important, ";\n }\n \n @media (max-width: 768px) {\n #messagesContainer {\n padding: 12px").concat(important, ";\n gap: 12px").concat(important, ";\n }\n \n .message-bubble {\n max-width: 85%").concat(important, ";\n font-size: 14px").concat(important, ";\n padding: 10px").concat(important, ";\n }\n \n .text-input-container {\n padding: 10px").concat(important, ";\n gap: 8px").concat(important, ";\n }\n \n #text-chat-input {\n font-size: 16px !important; /* Prevents iOS zoom on focus */\n padding: 10px 14px").concat(important, ";\n min-height: 44px").concat(important, ";\n }\n \n #text-chat-send {\n min-width: 56px").concat(important, ";\n min-height: 44px").concat(important, ";\n width: 56px").concat(important, ";\n height: 44px").concat(important, ";\n }\n \n .empty-state-icon {\n font-size: 40px").concat(important, ";\n }\n \n .empty-state-title {\n font-size: 18px").concat(important, ";\n }\n \n .empty-state-text {\n font-size: 12px").concat(important, ";\n }\n }\n \n @media (max-width: 480px) {\n #messagesContainer {\n padding: 10px").concat(important, ";\n gap: 10px").concat(important, ";\n }\n \n .message-bubble {\n max-width: 90%").concat(important, ";\n font-size: 13px").concat(important, ";\n padding: 8px").concat(important, ";\n }\n \n .text-input-container {\n padding: 8px").concat(important, ";\n }\n \n #text-chat-input {\n font-size: 16px !important;\n padding: 8px 12px").concat(important, ";\n }\n }\n ");
31567
31633
  }
31568
31634
 
31569
31635
  /**
@@ -31964,16 +32030,17 @@ __webpack_require__.r(__webpack_exports__);
31964
32030
  /* harmony export */ VoiceInterface: () => (/* binding */ VoiceInterface)
31965
32031
  /* harmony export */ });
31966
32032
  /* harmony import */ var _index_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../index.js */ "./src/index.js");
31967
- /* harmony import */ var _shared_MicPermissionUtils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../shared/MicPermissionUtils.js */ "./src/shared/MicPermissionUtils.js");
31968
- /* harmony import */ var _shared_applyDelay_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../shared/applyDelay.js */ "./src/shared/applyDelay.js");
31969
- /* harmony import */ var _shared_MicPermissionModals_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../shared/MicPermissionModals.js */ "./src/shared/MicPermissionModals.js");
31970
- /* harmony import */ var _voice_templates_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./voice/templates.js */ "./src/widget/voice/templates.js");
31971
- /* harmony import */ var _voice_styles_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./voice/styles.js */ "./src/widget/voice/styles.js");
31972
- /* harmony import */ var _voice_transcript_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./voice/transcript.js */ "./src/widget/voice/transcript.js");
31973
- /* harmony import */ var _voice_textHandlers_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./voice/textHandlers.js */ "./src/widget/voice/textHandlers.js");
31974
- /* harmony import */ var _voice_handlers_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./voice/handlers.js */ "./src/widget/voice/handlers.js");
31975
- /* harmony import */ var _voice_desktop_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./voice/desktop.js */ "./src/widget/voice/desktop.js");
31976
- /* harmony import */ var _voice_mobile_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./voice/mobile.js */ "./src/widget/voice/mobile.js");
32033
+ /* harmony import */ var _core_AudioRecorder_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../core/AudioRecorder.js */ "./src/core/AudioRecorder.js");
32034
+ /* harmony import */ var _shared_MicPermissionUtils_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../shared/MicPermissionUtils.js */ "./src/shared/MicPermissionUtils.js");
32035
+ /* harmony import */ var _shared_applyDelay_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../shared/applyDelay.js */ "./src/shared/applyDelay.js");
32036
+ /* harmony import */ var _shared_MicPermissionModals_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../shared/MicPermissionModals.js */ "./src/shared/MicPermissionModals.js");
32037
+ /* harmony import */ var _voice_templates_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./voice/templates.js */ "./src/widget/voice/templates.js");
32038
+ /* harmony import */ var _voice_styles_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./voice/styles.js */ "./src/widget/voice/styles.js");
32039
+ /* harmony import */ var _voice_transcript_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./voice/transcript.js */ "./src/widget/voice/transcript.js");
32040
+ /* harmony import */ var _voice_textHandlers_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./voice/textHandlers.js */ "./src/widget/voice/textHandlers.js");
32041
+ /* harmony import */ var _voice_handlers_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./voice/handlers.js */ "./src/widget/voice/handlers.js");
32042
+ /* harmony import */ var _voice_desktop_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./voice/desktop.js */ "./src/widget/voice/desktop.js");
32043
+ /* harmony import */ var _voice_mobile_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./voice/mobile.js */ "./src/widget/voice/mobile.js");
31977
32044
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
31978
32045
  function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i.return) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
31979
32046
  function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
@@ -32001,9 +32068,10 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
32001
32068
 
32002
32069
 
32003
32070
 
32071
+
32004
32072
  var VoiceInterface = /*#__PURE__*/function () {
32005
32073
  function VoiceInterface(config) {
32006
- var _config$agentSettings;
32074
+ var _this$config$behavior, _config$agentSettings;
32007
32075
  _classCallCheck(this, VoiceInterface);
32008
32076
  this.config = config;
32009
32077
  this.audioStream = null;
@@ -32016,9 +32084,10 @@ var VoiceInterface = /*#__PURE__*/function () {
32016
32084
  this.shadowRoot = config.shadowRoot || document;
32017
32085
  // Text SDK reference for sending text messages during voice calls
32018
32086
  this.textSDK = config.textSDK || null;
32019
- // Mobile detection
32020
- this.deviceInfo = (0,_shared_MicPermissionUtils_js__WEBPACK_IMPORTED_MODULE_1__.getDeviceInfo)();
32021
- this.isMobile = this.deviceInfo.isMobile;
32087
+ // Mobile voice UI: native iOS/Android, or narrow + touch (WebViews with desktop UA)
32088
+ this.deviceInfo = (0,_shared_MicPermissionUtils_js__WEBPACK_IMPORTED_MODULE_2__.getDeviceInfo)();
32089
+ var explicitMobileVoice = this.config.mobileVoiceUI !== undefined ? this.config.mobileVoiceUI : (_this$config$behavior = this.config.behavior) === null || _this$config$behavior === void 0 ? void 0 : _this$config$behavior.mobileVoiceUI;
32090
+ this.isMobile = explicitMobileVoice === true ? true : explicitMobileVoice === false ? false : (0,_shared_MicPermissionUtils_js__WEBPACK_IMPORTED_MODULE_2__.shouldUseMobileVoiceCallUI)();
32022
32091
  // Conversation messages for mobile UI (owned by mobile module, initialized there)
32023
32092
  // Desktop conversation state
32024
32093
  this.conversationExpanded = false;
@@ -32057,13 +32126,13 @@ var VoiceInterface = /*#__PURE__*/function () {
32057
32126
  });
32058
32127
 
32059
32128
  // Initialize modules with context (delegation pattern)
32060
- this.templates = new _voice_templates_js__WEBPACK_IMPORTED_MODULE_4__.Templates(this);
32061
- this.styles = new _voice_styles_js__WEBPACK_IMPORTED_MODULE_5__.Styles(this);
32062
- this.transcript = new _voice_transcript_js__WEBPACK_IMPORTED_MODULE_6__.Transcript(this);
32063
- this.textHandlers = new _voice_textHandlers_js__WEBPACK_IMPORTED_MODULE_7__.TextHandlers(this);
32064
- this.handlers = new _voice_handlers_js__WEBPACK_IMPORTED_MODULE_8__.Handlers(this);
32065
- this.desktop = new _voice_desktop_js__WEBPACK_IMPORTED_MODULE_9__.Desktop(this);
32066
- this.mobile = new _voice_mobile_js__WEBPACK_IMPORTED_MODULE_10__.Mobile(this);
32129
+ this.templates = new _voice_templates_js__WEBPACK_IMPORTED_MODULE_5__.Templates(this);
32130
+ this.styles = new _voice_styles_js__WEBPACK_IMPORTED_MODULE_6__.Styles(this);
32131
+ this.transcript = new _voice_transcript_js__WEBPACK_IMPORTED_MODULE_7__.Transcript(this);
32132
+ this.textHandlers = new _voice_textHandlers_js__WEBPACK_IMPORTED_MODULE_8__.TextHandlers(this);
32133
+ this.handlers = new _voice_handlers_js__WEBPACK_IMPORTED_MODULE_9__.Handlers(this);
32134
+ this.desktop = new _voice_desktop_js__WEBPACK_IMPORTED_MODULE_10__.Desktop(this);
32135
+ this.mobile = new _voice_mobile_js__WEBPACK_IMPORTED_MODULE_11__.Mobile(this);
32067
32136
 
32068
32137
  // Setup SDK event handlers
32069
32138
  this.setupSDKEventHandlers();
@@ -32140,27 +32209,8 @@ var VoiceInterface = /*#__PURE__*/function () {
32140
32209
  }
32141
32210
  _this._pendingUserTranscriptFrame = requestAnimationFrame(function () {
32142
32211
  _this._pendingUserTranscriptFrame = null;
32143
- var mobileBar = document.getElementById('mobile-voice-call-bar-container');
32144
- if (mobileBar) {
32145
- var mobileTranscriptText = mobileBar.querySelector('#mobileTranscriptText');
32146
- if (mobileTranscriptText) {
32147
- mobileTranscriptText.textContent = 'You: ' + text;
32148
- mobileTranscriptText.style.color = '#fde68a';
32149
- }
32150
- } else {
32151
- var liveTextCollapsed = _this.shadowRoot.getElementById('liveTextCollapsed');
32152
- if (liveTextCollapsed) {
32153
- liveTextCollapsed.textContent = '';
32154
- liveTextCollapsed.classList.remove('muted');
32155
- liveTextCollapsed.style.color = '#e8e4f0';
32156
- var label = document.createElement('span');
32157
- label.style.fontWeight = '600';
32158
- label.style.color = '#c4b5fd';
32159
- label.textContent = 'You: ';
32160
- liveTextCollapsed.appendChild(label);
32161
- liveTextCollapsed.appendChild(document.createTextNode(text));
32162
- }
32163
- }
32212
+ var userPrefix = _this.getUserTranscriptPrefix();
32213
+ _this._renderUserLiveTranscriptSnippet(userPrefix, text);
32164
32214
  });
32165
32215
 
32166
32216
  // History update is synchronous (small, only on final)
@@ -32378,6 +32428,64 @@ var VoiceInterface = /*#__PURE__*/function () {
32378
32428
  // Fall back to translation system
32379
32429
  return this.t(translationKey);
32380
32430
  }
32431
+
32432
+ /** Prefix before interim/final user speech in the live transcript strip (not history bubbles). */
32433
+ }, {
32434
+ key: "getUserTranscriptPrefix",
32435
+ value: function getUserTranscriptPrefix() {
32436
+ return this.getText('userTranscriptPrefix', 'userTranscriptPrefix');
32437
+ }
32438
+
32439
+ /**
32440
+ * Live user STT line: correct RTL/LTR order, visible gap after "אתה:", and sensible ? placement (utterance in dir=auto).
32441
+ */
32442
+ }, {
32443
+ key: "_renderUserLiveTranscriptSnippet",
32444
+ value: function _renderUserLiveTranscriptSnippet(userPrefix, text) {
32445
+ var isRtl = this.config.direction === 'rtl';
32446
+ var raw = userPrefix !== undefined && userPrefix !== null ? String(userPrefix) : '';
32447
+ var trimmedPrefix = raw.replace(/\s+$/, '');
32448
+ var sepChar = isRtl ? "\xA0" : ' ';
32449
+ var mobileBar = document.getElementById('mobile-voice-call-bar-container');
32450
+ if (mobileBar) {
32451
+ var el = mobileBar.querySelector('#mobileTranscriptText');
32452
+ if (!el) return;
32453
+ el.textContent = '';
32454
+ el.setAttribute('dir', isRtl ? 'rtl' : 'ltr');
32455
+ if (trimmedPrefix) {
32456
+ var prefixSpan = document.createElement('span');
32457
+ prefixSpan.style.fontWeight = '600';
32458
+ prefixSpan.style.color = '#c4b5fd';
32459
+ prefixSpan.textContent = trimmedPrefix;
32460
+ el.appendChild(prefixSpan);
32461
+ el.appendChild(document.createTextNode(sepChar));
32462
+ }
32463
+ var utter = document.createElement('span');
32464
+ utter.setAttribute('dir', 'auto');
32465
+ utter.textContent = text;
32466
+ el.appendChild(utter);
32467
+ el.style.color = '#fde68a';
32468
+ return;
32469
+ }
32470
+ var liveTextCollapsed = this.shadowRoot.getElementById('liveTextCollapsed');
32471
+ if (!liveTextCollapsed) return;
32472
+ liveTextCollapsed.textContent = '';
32473
+ liveTextCollapsed.classList.remove('muted');
32474
+ liveTextCollapsed.style.color = '#e8e4f0';
32475
+ liveTextCollapsed.setAttribute('dir', isRtl ? 'rtl' : 'ltr');
32476
+ if (trimmedPrefix) {
32477
+ var _prefixSpan = document.createElement('span');
32478
+ _prefixSpan.className = 'name ttp-user-live-prefix';
32479
+ _prefixSpan.textContent = trimmedPrefix;
32480
+ liveTextCollapsed.appendChild(_prefixSpan);
32481
+ liveTextCollapsed.appendChild(document.createTextNode(sepChar));
32482
+ }
32483
+ var utterance = document.createElement('span');
32484
+ utterance.className = 'ttp-user-live-utterance';
32485
+ utterance.setAttribute('dir', 'auto');
32486
+ utterance.textContent = text;
32487
+ liveTextCollapsed.appendChild(utterance);
32488
+ }
32381
32489
  }, {
32382
32490
  key: "getTooltip",
32383
32491
  value: function getTooltip(key) {
@@ -32585,7 +32693,7 @@ var VoiceInterface = /*#__PURE__*/function () {
32585
32693
  value: (function () {
32586
32694
  var _startVoiceCall = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4() {
32587
32695
  var _this2 = this;
32588
- var permissionState, deviceInfo, idleState, activeState;
32696
+ var permissionState, deviceInfo, idleState, activeState, mobilePanelPrePrompt, mobilePanelWasOpen;
32589
32697
  return _regenerator().w(function (_context4) {
32590
32698
  while (1) switch (_context4.n) {
32591
32699
  case 0:
@@ -32600,7 +32708,7 @@ var VoiceInterface = /*#__PURE__*/function () {
32600
32708
 
32601
32709
  // Check permission state first
32602
32710
  _context4.n = 2;
32603
- return (0,_shared_MicPermissionUtils_js__WEBPACK_IMPORTED_MODULE_1__.checkPermissionState)();
32711
+ return (0,_shared_MicPermissionUtils_js__WEBPACK_IMPORTED_MODULE_2__.checkPermissionState)();
32604
32712
  case 2:
32605
32713
  permissionState = _context4.v;
32606
32714
  console.log("\uD83D\uDCCB Current permission state: ".concat(permissionState));
@@ -32613,8 +32721,8 @@ var VoiceInterface = /*#__PURE__*/function () {
32613
32721
  console.log('🚫 Permission is denied, showing blocked modal...');
32614
32722
  // Reset connecting state since we're not proceeding
32615
32723
  this.resetConnectingState();
32616
- deviceInfo = (0,_shared_MicPermissionUtils_js__WEBPACK_IMPORTED_MODULE_1__.getDeviceInfo)();
32617
- (0,_shared_MicPermissionModals_js__WEBPACK_IMPORTED_MODULE_3__.showBlockedModal)(function () {
32724
+ deviceInfo = (0,_shared_MicPermissionUtils_js__WEBPACK_IMPORTED_MODULE_2__.getDeviceInfo)();
32725
+ (0,_shared_MicPermissionModals_js__WEBPACK_IMPORTED_MODULE_4__.showBlockedModal)(function () {
32618
32726
  // Modal closed - user can try again
32619
32727
  console.log('Blocked modal closed');
32620
32728
  }, function () {
@@ -32629,14 +32737,28 @@ var VoiceInterface = /*#__PURE__*/function () {
32629
32737
  break;
32630
32738
  }
32631
32739
  console.log('📋 Permission is in prompt state, showing pre-prompt modal with call view...');
32632
-
32633
- // Switch UI to active call view so it's visible behind the modal
32634
32740
  idleState = this.shadowRoot.getElementById('voiceIdleState');
32635
- activeState = this.shadowRoot.getElementById('voiceActiveState');
32636
- if (idleState) idleState.style.display = 'none';
32637
- if (activeState) activeState.style.display = 'flex';
32741
+ activeState = this.shadowRoot.getElementById('voiceActiveState'); // Desktop: show in-panel active call behind the semi-transparent overlay.
32742
+ // Mobile: do NOT show #voiceActiveState — it is only a non-fixed placeholder; flex layout
32743
+ // pins the fake bar to the top of the panel. Real chrome is body-fixed in proceedWithVoiceCall().
32744
+ mobilePanelPrePrompt = null;
32745
+ mobilePanelWasOpen = false;
32746
+ if (this.isMobile) {
32747
+ if (idleState) idleState.style.display = 'none';
32748
+ if (activeState) activeState.style.display = 'none';
32749
+ // Empty open panel reads as a dark "shadow" behind the sheet — hide it until cancel or call end
32750
+ mobilePanelPrePrompt = this.shadowRoot.getElementById('text-chat-panel') || document.getElementById('text-chat-panel');
32751
+ if (mobilePanelPrePrompt) {
32752
+ mobilePanelWasOpen = mobilePanelPrePrompt.classList.contains('open');
32753
+ mobilePanelPrePrompt.classList.remove('open');
32754
+ mobilePanelPrePrompt.style.display = 'none';
32755
+ }
32756
+ } else {
32757
+ if (idleState) idleState.style.display = 'none';
32758
+ if (activeState) activeState.style.display = 'flex';
32759
+ }
32638
32760
  return _context4.a(2, new Promise(function (resolve, reject) {
32639
- (0,_shared_MicPermissionModals_js__WEBPACK_IMPORTED_MODULE_3__.showPrePromptModal)(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3() {
32761
+ (0,_shared_MicPermissionModals_js__WEBPACK_IMPORTED_MODULE_4__.showPrePromptModal)(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3() {
32640
32762
  var _t;
32641
32763
  return _regenerator().w(function (_context3) {
32642
32764
  while (1) switch (_context3.p = _context3.n) {
@@ -32662,6 +32784,10 @@ var VoiceInterface = /*#__PURE__*/function () {
32662
32784
  // Revert UI back to idle state
32663
32785
  if (idleState) idleState.style.display = 'flex';
32664
32786
  if (activeState) activeState.style.display = 'none';
32787
+ if (_this2.isMobile && mobilePanelPrePrompt) {
32788
+ mobilePanelPrePrompt.style.display = '';
32789
+ if (mobilePanelWasOpen) mobilePanelPrePrompt.classList.add('open');
32790
+ }
32665
32791
  _this2.resetConnectingState();
32666
32792
  reject(new Error('Call cancelled by user'));
32667
32793
  });
@@ -32682,17 +32808,52 @@ var VoiceInterface = /*#__PURE__*/function () {
32682
32808
  /**
32683
32809
  * Proceed with voice call after permission check/pre-prompt
32684
32810
  */
32811
+ /**
32812
+ * Show server-driven disclaimer and send disclaimer_ack (voice protocol).
32813
+ */
32685
32814
  )
32686
32815
  }, {
32687
- key: "proceedWithVoiceCall",
32816
+ key: "resolveServerDisclaimer",
32688
32817
  value: (function () {
32689
- var _proceedWithVoiceCall = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5() {
32690
- var _this3 = this;
32691
- var isResumeCall, panel, header, toggleText, originalSection, compactSection, idleState, _panel, fallbackPanel, preliminaryInputStream, floatingButton, fallbackButton, mobileFabGrant, existingBar, _floatingButton, _fallbackButton, mobileFabDeny, _idleState, _panel2, _fallbackPanel, deviceInfo, _idleState2, activeState, voiceInterface, _this$config$connecti, delayConfig, connected, serverRejected, originalOnError, originalOnDisconnected, attempts, streamToUse, _this$sdk$voiceSDK, error, _existingBar, _existingBar2, _idleState3, _panel3, _fallbackPanel2, _floatingButton2, _fallbackButton2, updateTimer, _streamToUse, _existingBar3, _existingBar4, _idleState4, _panel4, _fallbackPanel3, _floatingButton3, _fallbackButton3, _updateTimer, _deviceInfo, _t2, _t3, _t4, _t5, _t6, _t7;
32818
+ var _resolveServerDisclaimer = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5(voiceSDK) {
32819
+ var _payload$texts;
32820
+ var payload, texts;
32692
32821
  return _regenerator().w(function (_context5) {
32693
- while (1) switch (_context5.p = _context5.n) {
32822
+ while (1) switch (_context5.n) {
32694
32823
  case 0:
32695
- _context5.p = 0;
32824
+ payload = voiceSDK.lastDisclaimerPayload;
32825
+ texts = payload !== null && payload !== void 0 && (_payload$texts = payload.texts) !== null && _payload$texts !== void 0 && _payload$texts.length ? payload.texts : ['Please confirm to continue.'];
32826
+ return _context5.a(2, new Promise(function (resolve, reject) {
32827
+ (0,_shared_MicPermissionModals_js__WEBPACK_IMPORTED_MODULE_4__.showServerDisclaimerModal)({
32828
+ texts: texts,
32829
+ onAccept: function onAccept() {
32830
+ voiceSDK.sendDisclaimerAck(true);
32831
+ resolve();
32832
+ },
32833
+ onCancel: function onCancel() {
32834
+ voiceSDK.sendDisclaimerAck(false);
32835
+ reject(new Error('DISCLAIMER_DECLINED'));
32836
+ }
32837
+ });
32838
+ }));
32839
+ }
32840
+ }, _callee5);
32841
+ }));
32842
+ function resolveServerDisclaimer(_x3) {
32843
+ return _resolveServerDisclaimer.apply(this, arguments);
32844
+ }
32845
+ return resolveServerDisclaimer;
32846
+ }())
32847
+ }, {
32848
+ key: "proceedWithVoiceCall",
32849
+ value: function () {
32850
+ var _proceedWithVoiceCall = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6() {
32851
+ var _this3 = this;
32852
+ var isResumeCall, panel, header, toggleText, originalSection, compactSection, idleState, _panel, fallbackPanel, preliminaryInputStream, _this$config$inputFor, primeSr, floatingButton, fallbackButton, mobileFabGrant, existingBar, _floatingButton, _fallbackButton, mobileFabDeny, _idleState, _panel2, _fallbackPanel, deviceInfo, _idleState2, activeState, voiceInterface, _this$config$connecti, delayConfig, connected, serverRejected, originalOnError, originalOnDisconnected, attempts, serverDisclaimerHandled, vs, streamToUse, _this$sdk$voiceSDK, error, _existingBar, _existingBar2, _idleState3, _panel3, _fallbackPanel2, _floatingButton2, _fallbackButton2, updateTimer, _streamToUse, _existingBar3, _existingBar4, _idleState4, _panel4, _fallbackPanel3, _floatingButton3, _fallbackButton3, _updateTimer, _deviceInfo, _t2, _t3, _t4, _t5, _t6, _t7, _t8;
32853
+ return _regenerator().w(function (_context6) {
32854
+ while (1) switch (_context6.p = _context6.n) {
32855
+ case 0:
32856
+ _context6.p = 0;
32696
32857
  // Clear conversation history for new calls (but preserve it for resume calls)
32697
32858
  isResumeCall = this._resumeInfo !== null && this._resumeInfo !== undefined;
32698
32859
  if (!isResumeCall) {
@@ -32728,7 +32889,7 @@ var VoiceInterface = /*#__PURE__*/function () {
32728
32889
 
32729
32890
  // First, handle UI state changes (but don't create mobile bar yet)
32730
32891
  if (!this.isMobile) {
32731
- _context5.n = 5;
32892
+ _context6.n = 6;
32732
32893
  break;
32733
32894
  }
32734
32895
  // On mobile, hide widget panel immediately (but keep floating button visible)
@@ -32753,22 +32914,30 @@ var VoiceInterface = /*#__PURE__*/function () {
32753
32914
  }
32754
32915
  }
32755
32916
 
32917
+ // Body-fixed bar must exist during the native browser mic prompt — otherwise the screen is blank
32918
+ this.showMobileCallBarAwaitingBrowserMic();
32919
+
32756
32920
  // CRITICAL for mobile: Request permission BEFORE connecting to WebSocket
32757
32921
  // This prevents the agent from starting to speak before permission is granted
32758
32922
  // ELEVENLABS PATTERN: Minimal constraints for first getUserMedia, keep stream alive,
32759
32923
  // pass it to AudioRecorder so we never call getUserMedia twice (iOS fails with 2 streams).
32760
32924
  console.log('📱 Mobile device - requesting mic permission before connecting...');
32761
32925
  preliminaryInputStream = null;
32762
- _context5.p = 1;
32763
- _context5.n = 2;
32926
+ _context6.p = 1;
32927
+ _context6.n = 2;
32764
32928
  return navigator.mediaDevices.getUserMedia({
32765
32929
  audio: true
32766
32930
  });
32767
32931
  case 2:
32768
- preliminaryInputStream = _context5.v;
32932
+ preliminaryInputStream = _context6.v;
32769
32933
  // DO NOT stop the stream here - keep it alive until startListening completes
32770
32934
  this._preliminaryInputStream = preliminaryInputStream;
32771
32935
  console.log('✅ Mobile: Microphone permission granted - keeping stream alive (ElevenLabs pattern)');
32936
+ primeSr = ((_this$config$inputFor = this.config.inputFormat) === null || _this$config$inputFor === void 0 ? void 0 : _this$config$inputFor.sampleRate) || this.config.sampleRate || 16000;
32937
+ _context6.n = 3;
32938
+ return _core_AudioRecorder_js__WEBPACK_IMPORTED_MODULE_1__["default"].primeSharedContext(primeSr);
32939
+ case 3:
32940
+ this.applyMobileBarConnectingCopy();
32772
32941
 
32773
32942
  // NOW hide the floating button too (permission granted)
32774
32943
  floatingButton = this.shadowRoot.getElementById('text-chat-button');
@@ -32784,11 +32953,11 @@ var VoiceInterface = /*#__PURE__*/function () {
32784
32953
  }
32785
32954
  mobileFabGrant = this.shadowRoot.querySelector('.ttp-mobile-fab');
32786
32955
  if (mobileFabGrant) mobileFabGrant.style.display = 'none';
32787
- _context5.n = 4;
32956
+ _context6.n = 5;
32788
32957
  break;
32789
- case 3:
32790
- _context5.p = 3;
32791
- _t2 = _context5.v;
32958
+ case 4:
32959
+ _context6.p = 4;
32960
+ _t2 = _context6.v;
32792
32961
  console.error('❌ Mobile: Permission denied before connecting:', _t2);
32793
32962
  // Permission was denied - reset connecting state and restore UI
32794
32963
  this.resetConnectingState();
@@ -32828,24 +32997,24 @@ var VoiceInterface = /*#__PURE__*/function () {
32828
32997
  }
32829
32998
 
32830
32999
  // Show blocked modal
32831
- deviceInfo = (0,_shared_MicPermissionUtils_js__WEBPACK_IMPORTED_MODULE_1__.getDeviceInfo)();
32832
- (0,_shared_MicPermissionModals_js__WEBPACK_IMPORTED_MODULE_3__.showBlockedModal)(function () {
33000
+ deviceInfo = (0,_shared_MicPermissionUtils_js__WEBPACK_IMPORTED_MODULE_2__.getDeviceInfo)();
33001
+ (0,_shared_MicPermissionModals_js__WEBPACK_IMPORTED_MODULE_4__.showBlockedModal)(function () {
32833
33002
  _this3.resetUIState();
32834
33003
  }, function () {
32835
33004
  window.location.reload();
32836
33005
  });
32837
- return _context5.a(2);
32838
- case 4:
32839
- _context5.n = 6;
32840
- break;
33006
+ return _context6.a(2);
32841
33007
  case 5:
33008
+ _context6.n = 7;
33009
+ break;
33010
+ case 6:
32842
33011
  // Desktop: Reset connecting state, then hide idle state and show active state
32843
33012
  this.resetConnectingState();
32844
33013
  _idleState2 = this.shadowRoot.getElementById('voiceIdleState');
32845
33014
  activeState = this.shadowRoot.getElementById('voiceActiveState');
32846
33015
  if (_idleState2) _idleState2.style.display = 'none';
32847
33016
  if (activeState) activeState.style.display = 'flex';
32848
- case 6:
33017
+ case 7:
32849
33018
  voiceInterface = this.shadowRoot.getElementById('voiceInterface'); // Adjust sizes based on container dimensions
32850
33019
  setTimeout(function () {
32851
33020
  return _this3.adjustSizesForContainer();
@@ -32858,32 +33027,32 @@ var VoiceInterface = /*#__PURE__*/function () {
32858
33027
 
32859
33028
  // Connect using agentId + appId (URL built internally by SDK)
32860
33029
  if (this.config.agentId) {
32861
- _context5.n = 7;
33030
+ _context6.n = 8;
32862
33031
  break;
32863
33032
  }
32864
33033
  throw new Error('agentId is required for voice calls');
32865
- case 7:
33034
+ case 8:
32866
33035
  if (!(this.sdk && this.sdk.isConnected)) {
32867
- _context5.n = 11;
33036
+ _context6.n = 12;
32868
33037
  break;
32869
33038
  }
32870
33039
  console.log('🔄 SDK already connected, disconnecting for clean retry...');
32871
- _context5.p = 8;
33040
+ _context6.p = 9;
32872
33041
  this.sdk.disconnect();
32873
- _context5.n = 9;
33042
+ _context6.n = 10;
32874
33043
  return new Promise(function (resolve) {
32875
33044
  return setTimeout(resolve, 100);
32876
33045
  });
32877
- case 9:
32878
- _context5.n = 11;
32879
- break;
32880
33046
  case 10:
32881
- _context5.p = 10;
32882
- _t3 = _context5.v;
32883
- console.warn('Warning: Error disconnecting existing connection:', _t3);
33047
+ _context6.n = 12;
33048
+ break;
32884
33049
  case 11:
33050
+ _context6.p = 11;
33051
+ _t3 = _context6.v;
33052
+ console.warn('Warning: Error disconnecting existing connection:', _t3);
33053
+ case 12:
32885
33054
  if (!this.isMobile) {
32886
- _context5.n = 12;
33055
+ _context6.n = 13;
32887
33056
  break;
32888
33057
  }
32889
33058
  delayConfig = (_this$config$connecti = this.config.connectionDelay) !== null && _this$config$connecti !== void 0 ? _this$config$connecti : {
@@ -32891,13 +33060,13 @@ var VoiceInterface = /*#__PURE__*/function () {
32891
33060
  android: 3000,
32892
33061
  ios: 0
32893
33062
  };
32894
- _context5.n = 12;
32895
- return (0,_shared_applyDelay_js__WEBPACK_IMPORTED_MODULE_2__.applyDelay)(delayConfig);
32896
- case 12:
32897
- _context5.n = 13;
32898
- return this.sdk.connect();
33063
+ _context6.n = 13;
33064
+ return (0,_shared_applyDelay_js__WEBPACK_IMPORTED_MODULE_3__.applyDelay)(delayConfig);
32899
33065
  case 13:
32900
- connected = _context5.v;
33066
+ _context6.n = 14;
33067
+ return this.sdk.connect();
33068
+ case 14:
33069
+ connected = _context6.v;
32901
33070
  console.log('✅ Connected to WebSocket, connected:', connected);
32902
33071
 
32903
33072
  // Set up text inject ack handler using EventEmitter pattern
@@ -32928,39 +33097,70 @@ var VoiceInterface = /*#__PURE__*/function () {
32928
33097
  // Wait for connection to be fully ready (for hello message exchange)
32929
33098
  // Check both AgentSDK.isConnected and underlying VoiceSDK connection
32930
33099
  attempts = 0;
32931
- case 14:
32932
- if (!(attempts < 50)) {
32933
- _context5.n = 18;
33100
+ serverDisclaimerHandled = false;
33101
+ case 15:
33102
+ if (!(attempts < 150)) {
33103
+ _context6.n = 25;
32934
33104
  break;
32935
33105
  }
32936
33106
  if (!serverRejected) {
32937
- _context5.n = 15;
33107
+ _context6.n = 16;
32938
33108
  break;
32939
33109
  }
32940
33110
  console.log('🚫 Server rejected connection, aborting audio capture');
32941
33111
  throw new Error('DOMAIN_NOT_WHITELISTED');
32942
- case 15:
33112
+ case 16:
32943
33113
  if (!this.sdk.isConnected) {
32944
- _context5.n = 16;
33114
+ _context6.n = 23;
32945
33115
  break;
32946
33116
  }
32947
- if (!(this.sdk.voiceSDK && this.sdk.voiceSDK.isConnected && this.sdk.voiceSDK.helloAckReceived && this.sdk.voiceSDK.websocket && this.sdk.voiceSDK.websocket.readyState === WebSocket.OPEN)) {
32948
- _context5.n = 16;
33117
+ vs = this.sdk.voiceSDK; // Verify WebSocket is open AND hello_ack has been received (input format negotiated)
33118
+ if (!(vs && vs.isConnected && vs.helloAckReceived && vs.websocket && vs.websocket.readyState === WebSocket.OPEN)) {
33119
+ _context6.n = 23;
32949
33120
  break;
32950
33121
  }
32951
- return _context5.a(3, 18);
32952
- case 16:
32953
- _context5.n = 17;
33122
+ if (!(vs.disclaimersPending && !serverDisclaimerHandled)) {
33123
+ _context6.n = 22;
33124
+ break;
33125
+ }
33126
+ serverDisclaimerHandled = true;
33127
+ _context6.p = 17;
33128
+ _context6.n = 18;
33129
+ return this.resolveServerDisclaimer(vs);
33130
+ case 18:
33131
+ _context6.n = 21;
33132
+ break;
33133
+ case 19:
33134
+ _context6.p = 19;
33135
+ _t4 = _context6.v;
33136
+ if (!((_t4 === null || _t4 === void 0 ? void 0 : _t4.message) === 'DISCLAIMER_DECLINED')) {
33137
+ _context6.n = 20;
33138
+ break;
33139
+ }
33140
+ this.resetConnectingState();
33141
+ throw _t4;
33142
+ case 20:
33143
+ throw _t4;
33144
+ case 21:
33145
+ return _context6.a(3, 15);
33146
+ case 22:
33147
+ if (vs.disclaimersPending) {
33148
+ _context6.n = 23;
33149
+ break;
33150
+ }
33151
+ return _context6.a(3, 25);
33152
+ case 23:
33153
+ _context6.n = 24;
32954
33154
  return new Promise(function (resolve) {
32955
33155
  return setTimeout(resolve, 100);
32956
33156
  });
32957
- case 17:
33157
+ case 24:
32958
33158
  attempts++;
32959
- _context5.n = 14;
33159
+ _context6.n = 15;
32960
33160
  break;
32961
- case 18:
33161
+ case 25:
32962
33162
  if (!serverRejected) {
32963
- _context5.n = 19;
33163
+ _context6.n = 26;
32964
33164
  break;
32965
33165
  }
32966
33166
  // Restore original handlers before throwing
@@ -32968,9 +33168,9 @@ var VoiceInterface = /*#__PURE__*/function () {
32968
33168
  this.sdk.onDisconnected = originalOnDisconnected;
32969
33169
  console.log('🚫 Server rejected connection, aborting audio capture');
32970
33170
  throw new Error('DOMAIN_NOT_WHITELISTED');
32971
- case 19:
33171
+ case 26:
32972
33172
  if (!(!this.sdk.isConnected || !this.sdk.voiceSDK || !this.sdk.voiceSDK.isConnected || !this.sdk.voiceSDK.websocket || this.sdk.voiceSDK.websocket.readyState !== WebSocket.OPEN)) {
32973
- _context5.n = 20;
33173
+ _context6.n = 27;
32974
33174
  break;
32975
33175
  }
32976
33176
  // Restore original handlers before throwing
@@ -32978,12 +33178,12 @@ var VoiceInterface = /*#__PURE__*/function () {
32978
33178
  this.sdk.onDisconnected = originalOnDisconnected;
32979
33179
  console.warn('⚠️ Connection lost before starting audio capture');
32980
33180
  throw new Error('Connection lost before starting audio capture');
32981
- case 20:
33181
+ case 27:
32982
33182
  // Restore original handlers (connection is valid, proceed with audio)
32983
33183
  this.sdk.onError = originalOnError;
32984
33184
  this.sdk.onDisconnected = originalOnDisconnected;
32985
33185
  if (!(this.sdk.isConnected && this.sdk.voiceSDK && this.sdk.voiceSDK.websocket && this.sdk.voiceSDK.websocket.readyState === WebSocket.OPEN)) {
32986
- _context5.n = 31;
33186
+ _context6.n = 38;
32987
33187
  break;
32988
33188
  }
32989
33189
  console.log('✅ WebSocket ready, starting listening...');
@@ -32993,35 +33193,35 @@ var VoiceInterface = /*#__PURE__*/function () {
32993
33193
 
32994
33194
  // CRITICAL: startListening() will request microphone permission
32995
33195
  // iOS: Pass preliminary stream to avoid second getUserMedia (single-stream fix)
32996
- _context5.p = 21;
33196
+ _context6.p = 28;
32997
33197
  streamToUse = this._preliminaryInputStream || null;
32998
33198
  if (streamToUse) this._preliminaryInputStream = null; // Transfer ownership to AudioRecorder
32999
- _context5.n = 22;
33199
+ _context6.n = 29;
33000
33200
  return this.sdk.startListening(streamToUse);
33001
- case 22:
33201
+ case 29:
33002
33202
  if (!(!this.sdk.isConnected || !this.sdk.voiceSDK || !this.sdk.voiceSDK.isConnected || !this.sdk.voiceSDK.websocket || this.sdk.voiceSDK.websocket.readyState !== WebSocket.OPEN)) {
33003
- _context5.n = 27;
33203
+ _context6.n = 34;
33004
33204
  break;
33005
33205
  }
33006
33206
  if (!((_this$sdk$voiceSDK = this.sdk.voiceSDK) !== null && _this$sdk$voiceSDK !== void 0 && _this$sdk$voiceSDK.isRecording)) {
33007
- _context5.n = 26;
33207
+ _context6.n = 33;
33008
33208
  break;
33009
33209
  }
33010
- _context5.p = 23;
33011
- _context5.n = 24;
33210
+ _context6.p = 30;
33211
+ _context6.n = 31;
33012
33212
  return this.sdk.voiceSDK.stopRecording();
33013
- case 24:
33014
- _context5.n = 26;
33213
+ case 31:
33214
+ _context6.n = 33;
33015
33215
  break;
33016
- case 25:
33017
- _context5.p = 25;
33018
- _t4 = _context5.v;
33019
- case 26:
33216
+ case 32:
33217
+ _context6.p = 32;
33218
+ _t5 = _context6.v;
33219
+ case 33:
33020
33220
  error = new Error('Connection lost - server may have rejected the call');
33021
33221
  error.name = 'ServerRejected';
33022
33222
  error.isServerRejection = true;
33023
33223
  throw error;
33024
- case 27:
33224
+ case 34:
33025
33225
  console.log('🎤 Started listening - permission granted');
33026
33226
 
33027
33227
  // ElevenLabs pattern: NOW stop preliminary stream - real input is ready
@@ -33061,23 +33261,23 @@ var VoiceInterface = /*#__PURE__*/function () {
33061
33261
  // Start live waveform animation interval (delegated to desktop module)
33062
33262
  this.desktop.startLiveWaveformInterval();
33063
33263
  }
33064
- _context5.n = 30;
33264
+ _context6.n = 37;
33065
33265
  break;
33066
- case 28:
33067
- _context5.p = 28;
33068
- _t5 = _context5.v;
33069
- if (!(_t5.isServerRejection || _t5.name === 'ServerRejected')) {
33070
- _context5.n = 29;
33266
+ case 35:
33267
+ _context6.p = 35;
33268
+ _t6 = _context6.v;
33269
+ if (!(_t6.isServerRejection || _t6.name === 'ServerRejected')) {
33270
+ _context6.n = 36;
33071
33271
  break;
33072
33272
  }
33073
33273
  // Server rejection is expected - handle it silently
33074
33274
  // The error handler will show domain error message
33075
33275
  this.resetConnectingState();
33076
33276
  // Re-throw so outer catch can handle it appropriately
33077
- throw _t5;
33078
- case 29:
33277
+ throw _t6;
33278
+ case 36:
33079
33279
  // Log other errors (permission denied, etc.)
33080
- console.error('❌ Failed to start listening - permission denied or error:', _t5);
33280
+ console.error('❌ Failed to start listening - permission denied or error:', _t6);
33081
33281
  // Permission was denied or error occurred - reset connecting state and restore UI
33082
33282
  this.resetConnectingState();
33083
33283
  if (this.isMobile) {
@@ -33113,8 +33313,8 @@ var VoiceInterface = /*#__PURE__*/function () {
33113
33313
  }
33114
33314
  }
33115
33315
  // Re-throw error so it's handled by outer catch
33116
- throw _t5;
33117
- case 30:
33316
+ throw _t6;
33317
+ case 37:
33118
33318
  // Start timer (desktop only - mobile bar owns its own timer)
33119
33319
  if (!this.isMobile && !this.callStartTime) {
33120
33320
  this.callStartTime = Date.now();
@@ -33132,30 +33332,30 @@ var VoiceInterface = /*#__PURE__*/function () {
33132
33332
  _this3.callTimerInterval = setInterval(updateTimer, 1000);
33133
33333
  }, 100);
33134
33334
  }
33135
- _context5.n = 39;
33335
+ _context6.n = 46;
33136
33336
  break;
33137
- case 31:
33337
+ case 38:
33138
33338
  if (!serverRejected) {
33139
- _context5.n = 32;
33339
+ _context6.n = 39;
33140
33340
  break;
33141
33341
  }
33142
33342
  console.log('🚫 Server rejected connection, aborting audio capture');
33143
33343
  throw new Error('DOMAIN_NOT_WHITELISTED');
33144
- case 32:
33344
+ case 39:
33145
33345
  if (!(!this.sdk.isConnected || !this.sdk.voiceSDK || !this.sdk.voiceSDK.isConnected || !this.sdk.voiceSDK.websocket || this.sdk.voiceSDK.websocket.readyState !== WebSocket.OPEN)) {
33146
- _context5.n = 33;
33346
+ _context6.n = 40;
33147
33347
  break;
33148
33348
  }
33149
33349
  console.warn('⚠️ Connection not valid, aborting audio capture');
33150
33350
  throw new Error('Connection lost before starting audio capture');
33151
- case 33:
33351
+ case 40:
33152
33352
  console.warn('⚠️ Connection not fully ready, but trying to start listening anyway...');
33153
- _context5.p = 34;
33353
+ _context6.p = 41;
33154
33354
  _streamToUse = this._preliminaryInputStream || null;
33155
33355
  if (_streamToUse) this._preliminaryInputStream = null;
33156
- _context5.n = 35;
33356
+ _context6.n = 42;
33157
33357
  return this.sdk.startListening(_streamToUse);
33158
- case 35:
33358
+ case 42:
33159
33359
  console.log('🎤 Started listening - permission granted');
33160
33360
 
33161
33361
  // ElevenLabs pattern: NOW stop preliminary stream - real input is ready
@@ -33195,23 +33395,23 @@ var VoiceInterface = /*#__PURE__*/function () {
33195
33395
  // Start live waveform animation interval (delegated to desktop module)
33196
33396
  this.desktop.startLiveWaveformInterval();
33197
33397
  }
33198
- _context5.n = 38;
33398
+ _context6.n = 45;
33199
33399
  break;
33200
- case 36:
33201
- _context5.p = 36;
33202
- _t6 = _context5.v;
33203
- if (!(_t6.isServerRejection || _t6.name === 'ServerRejected')) {
33204
- _context5.n = 37;
33400
+ case 43:
33401
+ _context6.p = 43;
33402
+ _t7 = _context6.v;
33403
+ if (!(_t7.isServerRejection || _t7.name === 'ServerRejected')) {
33404
+ _context6.n = 44;
33205
33405
  break;
33206
33406
  }
33207
33407
  // Server rejection is expected - handle it silently
33208
33408
  // The error handler will show domain error message
33209
33409
  this.resetConnectingState();
33210
33410
  // Re-throw so outer catch can handle it appropriately
33211
- throw _t6;
33212
- case 37:
33411
+ throw _t7;
33412
+ case 44:
33213
33413
  // Log other errors (permission denied, etc.)
33214
- console.error('❌ Failed to start listening - permission denied or error:', _t6);
33414
+ console.error('❌ Failed to start listening - permission denied or error:', _t7);
33215
33415
  // Permission was denied or error occurred - reset connecting state and restore UI
33216
33416
  this.resetConnectingState();
33217
33417
  if (this.isMobile) {
@@ -33247,8 +33447,8 @@ var VoiceInterface = /*#__PURE__*/function () {
33247
33447
  }
33248
33448
  }
33249
33449
  // Re-throw error so it's handled by outer catch
33250
- throw _t6;
33251
- case 38:
33450
+ throw _t7;
33451
+ case 45:
33252
33452
  // Start timer (desktop only - mobile bar owns its own timer)
33253
33453
  if (!this.isMobile && !this.callStartTime) {
33254
33454
  this.callStartTime = Date.now();
@@ -33266,16 +33466,16 @@ var VoiceInterface = /*#__PURE__*/function () {
33266
33466
  _this3.callTimerInterval = setInterval(_updateTimer, 1000);
33267
33467
  }, 100);
33268
33468
  }
33269
- case 39:
33469
+ case 46:
33270
33470
  console.log('✅ Voice call started successfully');
33271
- _context5.n = 45;
33471
+ _context6.n = 52;
33272
33472
  break;
33273
- case 40:
33274
- _context5.p = 40;
33275
- _t7 = _context5.v;
33473
+ case 47:
33474
+ _context6.p = 47;
33475
+ _t8 = _context6.v;
33276
33476
  // Handle server rejection gracefully (don't log as error)
33277
- if (!(_t7.isServerRejection || _t7.name === 'ServerRejected')) {
33278
- console.error('❌ Error starting voice call:', _t7);
33477
+ if (!(_t8.isServerRejection || _t8.name === 'ServerRejected')) {
33478
+ console.error('❌ Error starting voice call:', _t8);
33279
33479
  }
33280
33480
 
33281
33481
  // ElevenLabs pattern: Stop preliminary stream on any error path
@@ -33305,50 +33505,50 @@ var VoiceInterface = /*#__PURE__*/function () {
33305
33505
  }
33306
33506
 
33307
33507
  // Handle specific error types with appropriate modals
33308
- if (!(_t7.name === 'NotAllowedError' || _t7.name === 'PermissionDeniedError')) {
33309
- _context5.n = 41;
33508
+ if (!(_t8.name === 'NotAllowedError' || _t8.name === 'PermissionDeniedError')) {
33509
+ _context6.n = 48;
33310
33510
  break;
33311
33511
  }
33312
33512
  // Permission denied - show blocked modal
33313
- _deviceInfo = (0,_shared_MicPermissionUtils_js__WEBPACK_IMPORTED_MODULE_1__.getDeviceInfo)();
33314
- (0,_shared_MicPermissionModals_js__WEBPACK_IMPORTED_MODULE_3__.showBlockedModal)(function () {
33513
+ _deviceInfo = (0,_shared_MicPermissionUtils_js__WEBPACK_IMPORTED_MODULE_2__.getDeviceInfo)();
33514
+ (0,_shared_MicPermissionModals_js__WEBPACK_IMPORTED_MODULE_4__.showBlockedModal)(function () {
33315
33515
  // Modal closed
33316
33516
  _this3.resetUIState();
33317
33517
  }, function () {
33318
33518
  // User clicked refresh
33319
33519
  window.location.reload();
33320
33520
  });
33321
- _context5.n = 45;
33521
+ _context6.n = 52;
33322
33522
  break;
33323
- case 41:
33324
- if (!(_t7.name === 'NotFoundError' || _t7.name === 'DevicesNotFoundError')) {
33325
- _context5.n = 42;
33523
+ case 48:
33524
+ if (!(_t8.name === 'NotFoundError' || _t8.name === 'DevicesNotFoundError')) {
33525
+ _context6.n = 49;
33326
33526
  break;
33327
33527
  }
33328
33528
  // No microphone found - show no mic modal
33329
- (0,_shared_MicPermissionModals_js__WEBPACK_IMPORTED_MODULE_3__.showNoMicrophoneModal)(function () {
33529
+ (0,_shared_MicPermissionModals_js__WEBPACK_IMPORTED_MODULE_4__.showNoMicrophoneModal)(function () {
33330
33530
  _this3.resetUIState();
33331
33531
  });
33332
- _context5.n = 45;
33532
+ _context6.n = 52;
33333
33533
  break;
33334
- case 42:
33335
- if (!(_t7 && (_t7.message === 'DOMAIN_NOT_WHITELISTED' || _t7.message && _t7.message.includes('Domain not whitelisted')))) {
33336
- _context5.n = 44;
33534
+ case 49:
33535
+ if (!(_t8 && (_t8.message === 'DOMAIN_NOT_WHITELISTED' || _t8.message && _t8.message.includes('Domain not whitelisted')))) {
33536
+ _context6.n = 51;
33337
33537
  break;
33338
33538
  }
33339
- _context5.n = 43;
33539
+ _context6.n = 50;
33340
33540
  return this.endCallOnServerRejection();
33341
- case 43:
33342
- _context5.n = 45;
33541
+ case 50:
33542
+ _context6.n = 52;
33343
33543
  break;
33344
- case 44:
33544
+ case 51:
33345
33545
  // Other errors - show in transcript
33346
- this.showError(_t7.message || _t7);
33546
+ this.showError(_t8.message || _t8);
33347
33547
  this.resetUIState();
33348
- case 45:
33349
- return _context5.a(2);
33548
+ case 52:
33549
+ return _context6.a(2);
33350
33550
  }
33351
- }, _callee5, this, [[34, 36], [23, 25], [21, 28], [8, 10], [1, 3], [0, 40]]);
33551
+ }, _callee6, this, [[41, 43], [30, 32], [28, 35], [17, 19], [9, 11], [1, 4], [0, 47]]);
33352
33552
  }));
33353
33553
  function proceedWithVoiceCall() {
33354
33554
  return _proceedWithVoiceCall.apply(this, arguments);
@@ -33359,7 +33559,6 @@ var VoiceInterface = /*#__PURE__*/function () {
33359
33559
  * Stop preliminary mic stream (ElevenLabs pattern).
33360
33560
  * Must be called after startListening succeeds, or on any error path.
33361
33561
  */
33362
- )
33363
33562
  }, {
33364
33563
  key: "_stopPreliminaryInputStream",
33365
33564
  value: function _stopPreliminaryInputStream() {
@@ -33414,10 +33613,10 @@ var VoiceInterface = /*#__PURE__*/function () {
33414
33613
  }, {
33415
33614
  key: "endCallOnServerRejection",
33416
33615
  value: (function () {
33417
- var _endCallOnServerRejection = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6() {
33418
- var voiceInterfaceEl, landingScreen, _this$sdk$voiceSDK2, _this$sdk$voiceSDK3, audioRecorder, isRecording, _this$sdk$voiceSDK4, activeState, idleState, panel, fallbackPanel, floatingButton, fallbackButton, mobileFabEnd, errorMsg, _t8, _t9, _t0, _t1, _t10;
33419
- return _regenerator().w(function (_context6) {
33420
- while (1) switch (_context6.p = _context6.n) {
33616
+ var _endCallOnServerRejection = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee7() {
33617
+ var voiceInterfaceEl, landingScreen, _this$sdk$voiceSDK2, _this$sdk$voiceSDK3, audioRecorder, isRecording, _this$sdk$voiceSDK4, activeState, idleState, panel, fallbackPanel, floatingButton, fallbackButton, mobileFabEnd, errorMsg, _t9, _t0, _t1, _t10, _t11;
33618
+ return _regenerator().w(function (_context7) {
33619
+ while (1) switch (_context7.p = _context7.n) {
33421
33620
  case 0:
33422
33621
  console.log('🚫 Server rejected call - ending call and stopping audio capture/VAD...');
33423
33622
  console.log('🚫 Calling endCallOnServerRejection() - will show domain error message');
@@ -33444,94 +33643,94 @@ var VoiceInterface = /*#__PURE__*/function () {
33444
33643
 
33445
33644
  // CRITICAL: Stop audio capture/VAD immediately
33446
33645
  if (!this.sdk) {
33447
- _context6.n = 22;
33646
+ _context7.n = 22;
33448
33647
  break;
33449
33648
  }
33450
- _context6.p = 1;
33649
+ _context7.p = 1;
33451
33650
  // CRITICAL: Stop VAD and audio capture immediately
33452
33651
  // Check if AudioRecorder exists and is recording (even if flags aren't set yet)
33453
33652
  audioRecorder = (_this$sdk$voiceSDK2 = this.sdk.voiceSDK) === null || _this$sdk$voiceSDK2 === void 0 ? void 0 : _this$sdk$voiceSDK2.audioRecorder;
33454
33653
  isRecording = this.sdk.isListening || ((_this$sdk$voiceSDK3 = this.sdk.voiceSDK) === null || _this$sdk$voiceSDK3 === void 0 ? void 0 : _this$sdk$voiceSDK3.isRecording) || audioRecorder && audioRecorder.isRecording || audioRecorder && audioRecorder.audioWorkletNode !== null;
33455
33654
  if (!(isRecording || audioRecorder)) {
33456
- _context6.n = 19;
33655
+ _context7.n = 19;
33457
33656
  break;
33458
33657
  }
33459
33658
  console.log('🛑 Stopping audio capture/VAD...');
33460
33659
 
33461
33660
  // First, send stop message to AudioWorklet to stop VAD processing
33462
33661
  if (!(audioRecorder !== null && audioRecorder !== void 0 && audioRecorder.audioWorkletNode)) {
33463
- _context6.n = 5;
33662
+ _context7.n = 5;
33464
33663
  break;
33465
33664
  }
33466
33665
  console.log('🛑 Sending stop message to AudioWorklet to stop VAD...');
33467
- _context6.p = 2;
33666
+ _context7.p = 2;
33468
33667
  audioRecorder.audioWorkletNode.port.postMessage({
33469
33668
  type: 'stop'
33470
33669
  });
33471
- _context6.n = 3;
33670
+ _context7.n = 3;
33472
33671
  return new Promise(function (resolve) {
33473
33672
  return setTimeout(resolve, 150);
33474
33673
  });
33475
33674
  case 3:
33476
- _context6.n = 5;
33675
+ _context7.n = 5;
33477
33676
  break;
33478
33677
  case 4:
33479
- _context6.p = 4;
33480
- _t8 = _context6.v;
33481
- console.warn('Error sending stop message to AudioWorklet:', _t8);
33678
+ _context7.p = 4;
33679
+ _t9 = _context7.v;
33680
+ console.warn('Error sending stop message to AudioWorklet:', _t9);
33482
33681
  case 5:
33483
33682
  if (!(this.sdk.voiceSDK && typeof this.sdk.voiceSDK.stopRecording === 'function')) {
33484
- _context6.n = 10;
33683
+ _context7.n = 10;
33485
33684
  break;
33486
33685
  }
33487
- _context6.p = 6;
33488
- _context6.n = 7;
33686
+ _context7.p = 6;
33687
+ _context7.n = 7;
33489
33688
  return this.sdk.voiceSDK.stopRecording();
33490
33689
  case 7:
33491
33690
  console.log('✅ stopRecording() completed');
33492
- _context6.n = 9;
33691
+ _context7.n = 9;
33493
33692
  break;
33494
33693
  case 8:
33495
- _context6.p = 8;
33496
- _t9 = _context6.v;
33497
- console.warn('Error calling stopRecording:', _t9);
33694
+ _context7.p = 8;
33695
+ _t0 = _context7.v;
33696
+ console.warn('Error calling stopRecording:', _t0);
33498
33697
  case 9:
33499
- _context6.n = 14;
33698
+ _context7.n = 14;
33500
33699
  break;
33501
33700
  case 10:
33502
33701
  if (!this.sdk.stopListening) {
33503
- _context6.n = 14;
33702
+ _context7.n = 14;
33504
33703
  break;
33505
33704
  }
33506
- _context6.p = 11;
33705
+ _context7.p = 11;
33507
33706
  this.sdk.stopListening();
33508
- _context6.n = 12;
33707
+ _context7.n = 12;
33509
33708
  return new Promise(function (resolve) {
33510
33709
  return setTimeout(resolve, 200);
33511
33710
  });
33512
33711
  case 12:
33513
- _context6.n = 14;
33712
+ _context7.n = 14;
33514
33713
  break;
33515
33714
  case 13:
33516
- _context6.p = 13;
33517
- _t0 = _context6.v;
33518
- console.warn('Error calling stopListening:', _t0);
33715
+ _context7.p = 13;
33716
+ _t1 = _context7.v;
33717
+ console.warn('Error calling stopListening:', _t1);
33519
33718
  case 14:
33520
33719
  if (!(audioRecorder && typeof audioRecorder.stop === 'function')) {
33521
- _context6.n = 18;
33720
+ _context7.n = 18;
33522
33721
  break;
33523
33722
  }
33524
- _context6.p = 15;
33525
- _context6.n = 16;
33723
+ _context7.p = 15;
33724
+ _context7.n = 16;
33526
33725
  return audioRecorder.stop();
33527
33726
  case 16:
33528
33727
  console.log('✅ AudioRecorder.stop() completed');
33529
- _context6.n = 18;
33728
+ _context7.n = 18;
33530
33729
  break;
33531
33730
  case 17:
33532
- _context6.p = 17;
33533
- _t1 = _context6.v;
33534
- console.warn('Error calling AudioRecorder.stop():', _t1);
33731
+ _context7.p = 17;
33732
+ _t10 = _context7.v;
33733
+ console.warn('Error calling AudioRecorder.stop():', _t10);
33535
33734
  case 18:
33536
33735
  console.log('✅ Audio capture/VAD stopped');
33537
33736
  case 19:
@@ -33559,12 +33758,12 @@ var VoiceInterface = /*#__PURE__*/function () {
33559
33758
 
33560
33759
  // Hangup the call
33561
33760
  this.sdk.hangup();
33562
- _context6.n = 21;
33761
+ _context7.n = 21;
33563
33762
  break;
33564
33763
  case 20:
33565
- _context6.p = 20;
33566
- _t10 = _context6.v;
33567
- console.warn('Error stopping listening on server rejection:', _t10);
33764
+ _context7.p = 20;
33765
+ _t11 = _context7.v;
33766
+ console.warn('Error stopping listening on server rejection:', _t11);
33568
33767
  // Force stop media streams even if stopListening fails
33569
33768
  try {
33570
33769
  if ((_this$sdk$voiceSDK4 = this.sdk.voiceSDK) !== null && _this$sdk$voiceSDK4 !== void 0 && (_this$sdk$voiceSDK4 = _this$sdk$voiceSDK4.audioRecorder) !== null && _this$sdk$voiceSDK4 !== void 0 && _this$sdk$voiceSDK4.mediaStream) {
@@ -33666,9 +33865,9 @@ var VoiceInterface = /*#__PURE__*/function () {
33666
33865
  }
33667
33866
  }
33668
33867
  case 23:
33669
- return _context6.a(2);
33868
+ return _context7.a(2);
33670
33869
  }
33671
- }, _callee6, this, [[15, 17], [11, 13], [6, 8], [2, 4], [1, 20]]);
33870
+ }, _callee7, this, [[15, 17], [11, 13], [6, 8], [2, 4], [1, 20]]);
33672
33871
  }));
33673
33872
  function endCallOnServerRejection() {
33674
33873
  return _endCallOnServerRejection.apply(this, arguments);
@@ -34262,6 +34461,45 @@ var VoiceInterface = /*#__PURE__*/function () {
34262
34461
  return this.mobile.createMobileMinimizedBar();
34263
34462
  }
34264
34463
 
34464
+ /**
34465
+ * Mobile: ensure minimized bar exists with copy for the native getUserMedia permission dialog.
34466
+ */
34467
+ }, {
34468
+ key: "showMobileCallBarAwaitingBrowserMic",
34469
+ value: function showMobileCallBarAwaitingBrowserMic() {
34470
+ if (!document.getElementById('mobile-voice-call-bar-container')) {
34471
+ this.createMobileMinimizedBar();
34472
+ }
34473
+ var root = document.getElementById('mobile-voice-call-bar-container');
34474
+ if (!root) return;
34475
+ var line = this.t('awaitingBrowserMic');
34476
+ var detail = this.t('awaitingBrowserMicDetail');
34477
+ var status = root.querySelector('#mobileStatusText');
34478
+ var headerStatus = root.querySelector('#mobileHeaderStatusText');
34479
+ if (status) status.textContent = line;
34480
+ if (headerStatus) headerStatus.textContent = line;
34481
+ var tx = root.querySelector('#mobileTranscriptText');
34482
+ if (tx) tx.textContent = detail;
34483
+ }
34484
+
34485
+ /**
34486
+ * Mobile: after mic permission granted, show standard "connecting" copy until audio starts.
34487
+ */
34488
+ }, {
34489
+ key: "applyMobileBarConnectingCopy",
34490
+ value: function applyMobileBarConnectingCopy() {
34491
+ var root = document.getElementById('mobile-voice-call-bar-container');
34492
+ if (!root) return;
34493
+ var line = this.t('connecting');
34494
+ var detail = this.t('connectingSubtitle');
34495
+ var status = root.querySelector('#mobileStatusText');
34496
+ var headerStatus = root.querySelector('#mobileHeaderStatusText');
34497
+ if (status) status.textContent = line;
34498
+ if (headerStatus) headerStatus.textContent = line;
34499
+ var tx = root.querySelector('#mobileTranscriptText');
34500
+ if (tx) tx.textContent = detail;
34501
+ }
34502
+
34265
34503
  /**
34266
34504
  * Remove mobile minimized bar
34267
34505
  * Delegates to mobile module
@@ -35495,7 +35733,7 @@ var Handlers = /*#__PURE__*/function () {
35495
35733
  };
35496
35734
  };
35497
35735
  var onTouchEnd = function onTouchEnd(e) {
35498
- var _mobileTextInputEl$va;
35736
+ var _overlay$classList, _mobileTextInputEl$va;
35499
35737
  var container = document.getElementById('mobile-voice-call-bar-container');
35500
35738
  if (!container || !touchOrigin || !e.changedTouches.length) {
35501
35739
  touchOrigin = null;
@@ -35516,7 +35754,7 @@ var Handlers = /*#__PURE__*/function () {
35516
35754
  var mobileSendBtnEl = container.querySelector('#mobileSendBtn');
35517
35755
  var mobileTextInputEl = container.querySelector('#mobileTextInput');
35518
35756
  var overlay = container.querySelector('#mobileTranscriptOverlay');
35519
- var isOverlayVisible = overlay && (overlay.style.display === 'flex' || getComputedStyle(overlay).display === 'flex');
35757
+ var isOverlayVisible = !!(overlay !== null && overlay !== void 0 && (_overlay$classList = overlay.classList) !== null && _overlay$classList !== void 0 && _overlay$classList.contains('mobile-transcript-overlay--open'));
35520
35758
  if (hitTest(x, y, endBtn)) {
35521
35759
  e.preventDefault();
35522
35760
  e.stopPropagation();
@@ -35710,20 +35948,23 @@ var Mobile = /*#__PURE__*/function () {
35710
35948
  existingBar.remove();
35711
35949
  }
35712
35950
 
35713
- // Inject mobile CSS into document head if not already injected
35714
- if (!document.getElementById('mobile-voice-call-bar-styles')) {
35715
- var style = document.createElement('style');
35716
- style.id = 'mobile-voice-call-bar-styles';
35717
- style.textContent = this.voiceInterface.styles.generateMobileCSS();
35718
- document.head.appendChild(style);
35951
+ // Inject / refresh mobile CSS in document head (must match current voice config each call)
35952
+ var mobileStyleEl = document.getElementById('mobile-voice-call-bar-styles');
35953
+ if (!mobileStyleEl) {
35954
+ mobileStyleEl = document.createElement('style');
35955
+ mobileStyleEl.id = 'mobile-voice-call-bar-styles';
35956
+ document.head.appendChild(mobileStyleEl);
35719
35957
  }
35958
+ mobileStyleEl.textContent = this.voiceInterface.styles.generateMobileCSS();
35720
35959
 
35721
35960
  // Create container div
35722
35961
  var container = document.createElement('div');
35723
35962
  container.id = 'mobile-voice-call-bar-container';
35963
+ var textDir = this.config.direction === 'rtl' ? 'rtl' : 'ltr';
35964
+ container.setAttribute('dir', textDir);
35724
35965
  container.innerHTML = "\n <!-- Duration Badge (hidden until first audio) -->\n <div class=\"mobile-duration-badge mobile-duration-badge--hidden\" id=\"mobileDurationBadge\">\n <div class=\"mobile-duration-dot\"></div>\n <span id=\"mobileDurationText\">00:00</span>\n </div>\n \n <!-- Main Bar -->\n <div class=\"mobile-voice-bar\">\n <!-- Top Row: Status, Waveform/Spinner, Controls -->\n <div class=\"mobile-top-row\">\n <!-- Status Indicator -->\n <div class=\"mobile-status-indicator\">\n <div class=\"mobile-status-dot\" id=\"mobileStatusDot\"></div>\n <span class=\"mobile-status-text\" id=\"mobileStatusText\">".concat(this.t('listening'), "</span>\n </div>\n \n <!-- Centered: Spinner (loading) or Waveform (after first audio) -->\n <div class=\"mobile-waveform-center\" id=\"mobileWaveform\">\n <div class=\"mobile-waveform-spinner\" id=\"mobileWaveformSpinner\" aria-hidden=\"false\">\n <div class=\"mobile-waveform-spinner-inner\"></div>\n </div>\n <div class=\"mobile-waveform-bars mobile-waveform-bars--hidden\" id=\"mobileWaveformBars\">\n ").concat(Array(8).fill(0).map(function (_, i) {
35725
35966
  return "<div class=\"mobile-waveform-bar\" data-index=\"".concat(i, "\"></div>");
35726
- }).join(''), "\n </div>\n </div>\n \n <!-- Controls -->\n <div class=\"mobile-controls\">\n <button type=\"button\" class=\"mobile-control-btn\" id=\"mobileMuteBtn\" aria-label=\"Mute microphone\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-mic-icon\">\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\"/>\n </svg>\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-mic-off-icon\" style=\"display: none;\">\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\"/>\n <line x1=\"4\" y1=\"4\" x2=\"20\" y2=\"20\" stroke=\"#ef4444\" stroke-width=\"1.5\" opacity=\"0.85\"/>\n </svg>\n </button>\n \n <button type=\"button\" class=\"mobile-control-btn\" id=\"mobileSpeakerBtn\" aria-label=\"Toggle speaker\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-speaker-icon\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\"/>\n </svg>\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-speaker-off-icon\" style=\"display: none;\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\"/>\n <line x1=\"4\" y1=\"4\" x2=\"20\" y2=\"20\" stroke=\"#ef4444\" stroke-width=\"1.5\" opacity=\"0.85\"/>\n </svg>\n </button>\n \n <button type=\"button\" class=\"mobile-end-call-btn\" id=\"mobileEndCallBtn\" aria-label=\"End call\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M10.68 13.31a16 16 0 0 0 3.41 2.6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7 2 2 0 0 1 1.72 2v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.42 19.42 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.63A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91\"/>\n <line x1=\"22\" x2=\"2\" y1=\"2\" y2=\"22\"/>\n </svg>\n </button>\n </div>\n </div>\n \n <!-- Bottom Row: Transcript (expandable) -->\n <button type=\"button\" class=\"mobile-transcript-row\" id=\"mobileTranscriptRow\">\n <p class=\"mobile-transcript-text\" id=\"mobileTranscriptText\">").concat(this.t('transcriptWillAppear'), "</p>\n <div class=\"mobile-transcript-footer\">\n <span class=\"mobile-expand-hint\">tap to expand & type</span>\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"opacity: 0.6;\">\n <path d=\"M7 17L17 7M17 7H7M17 7V17\"/>\n </svg>\n </div>\n </button>\n\n <!-- Fly-to-cart target: always visible for animation (positioned where cart icon appears) -->\n <div id=\"ttpFlyToCartTarget\" class=\"ttp-fly-target\" aria-hidden=\"true\"></div>\n\n <!-- Cart Row - shown when items are in cart -->\n <div class=\"mobile-cart-row\" id=\"mobileCartRow\" style=\"display: none;\">\n <div class=\"mobile-cart-row__content\">\n <span class=\"mobile-cart-row__icon\" data-ttp-fly-target>\uD83D\uDED2</span>\n <span class=\"mobile-cart-row__text\" id=\"mobileCartText\">0 items \xB7 \u20AA0.00</span>\n </div>\n </div>\n </div>\n \n <!-- Expanded Transcript Overlay -->\n <div class=\"mobile-transcript-overlay\" id=\"mobileTranscriptOverlay\" style=\"display: none;\">\n <div class=\"mobile-expanded-transcript\" id=\"mobileExpandedTranscript\">\n <!-- Header -->\n <div class=\"mobile-transcript-header\">\n <div class=\"mobile-header-left\">\n <div class=\"mobile-header-status\">\n <div class=\"mobile-header-status-dot\"></div>\n <span class=\"mobile-header-status-text\" id=\"mobileHeaderStatusText\">").concat(this.t('listening'), "</span>\n <span class=\"mobile-header-duration\" id=\"mobileHeaderDuration\">00:00</span>\n </div>\n <span class=\"mobile-transcript-label\">CONVERSATION</span>\n </div>\n <button type=\"button\" class=\"mobile-close-transcript-btn\" id=\"mobileCloseTranscriptBtn\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M18 6L6 18M6 6l12 12\"/>\n </svg>\n </button>\n </div>\n \n <!-- Messages Container -->\n <div class=\"mobile-messages-container\" id=\"mobileMessagesContainer\">\n <!-- Messages will be dynamically added here -->\n </div>\n \n <!-- Text Input Area -->\n <div class=\"mobile-input-area\">\n <div class=\"mobile-input-wrapper\">\n <input\n type=\"text\"\n placeholder=\"Type a message...\"\n id=\"mobileTextInput\"\n class=\"mobile-text-input\"\n />\n <button type=\"button\" class=\"mobile-send-btn\" id=\"mobileSendBtn\" disabled>\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M22 2L11 13M22 2l-7 20-4-9-9-4 20-7z\"/>\n </svg>\n </button>\n </div>\n <p class=\"mobile-input-hint\">\uD83C\uDF99\uFE0F ").concat(this.t('voiceActive') || 'Voice is still active', " \u2022 ").concat(this.t('typeOrSpeak') || 'Type or speak', "</p>\n </div>\n </div>\n </div>\n ");
35967
+ }).join(''), "\n </div>\n </div>\n \n <!-- Controls -->\n <div class=\"mobile-controls\">\n <button type=\"button\" class=\"mobile-control-btn\" id=\"mobileMuteBtn\" aria-label=\"Mute microphone\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-mic-icon\">\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\"/>\n </svg>\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-mic-off-icon\" style=\"display: none;\">\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\"/>\n <line x1=\"4\" y1=\"4\" x2=\"20\" y2=\"20\" stroke=\"#ef4444\" stroke-width=\"1.5\" opacity=\"0.85\"/>\n </svg>\n </button>\n \n <button type=\"button\" class=\"mobile-control-btn\" id=\"mobileSpeakerBtn\" aria-label=\"Toggle speaker\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-speaker-icon\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\"/>\n </svg>\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-speaker-off-icon\" style=\"display: none;\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\"/>\n <line x1=\"4\" y1=\"4\" x2=\"20\" y2=\"20\" stroke=\"#ef4444\" stroke-width=\"1.5\" opacity=\"0.85\"/>\n </svg>\n </button>\n \n <button type=\"button\" class=\"mobile-end-call-btn\" id=\"mobileEndCallBtn\" aria-label=\"End call\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M10.68 13.31a16 16 0 0 0 3.41 2.6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7 2 2 0 0 1 1.72 2v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.42 19.42 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.63A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91\"/>\n <line x1=\"22\" x2=\"2\" y1=\"2\" y2=\"22\"/>\n </svg>\n </button>\n </div>\n </div>\n \n <!-- Bottom Row: Transcript (expandable) -->\n <button type=\"button\" class=\"mobile-transcript-row\" id=\"mobileTranscriptRow\">\n <p class=\"mobile-transcript-text\" id=\"mobileTranscriptText\" dir=\"").concat(textDir, "\">").concat(this.t('transcriptWillAppear'), "</p>\n <div class=\"mobile-transcript-footer\">\n <span class=\"mobile-expand-hint\">tap to expand & type</span>\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"opacity: 0.6;\">\n <path d=\"M7 17L17 7M17 7H7M17 7V17\"/>\n </svg>\n </div>\n </button>\n\n <!-- Fly-to-cart target: always visible for animation (positioned where cart icon appears) -->\n <div id=\"ttpFlyToCartTarget\" class=\"ttp-fly-target\" aria-hidden=\"true\"></div>\n\n <!-- Cart Row - shown when items are in cart -->\n <div class=\"mobile-cart-row\" id=\"mobileCartRow\" style=\"display: none;\">\n <div class=\"mobile-cart-row__content\">\n <span class=\"mobile-cart-row__icon\" data-ttp-fly-target>\uD83D\uDED2</span>\n <span class=\"mobile-cart-row__text\" id=\"mobileCartText\">0 items \xB7 \u20AA0.00</span>\n </div>\n </div>\n </div>\n \n <!-- Expanded Transcript Overlay -->\n <div class=\"mobile-transcript-overlay\" id=\"mobileTranscriptOverlay\">\n <div class=\"mobile-expanded-transcript\" id=\"mobileExpandedTranscript\">\n <!-- Header -->\n <div class=\"mobile-transcript-header\">\n <div class=\"mobile-header-left\">\n <div class=\"mobile-header-status\">\n <div class=\"mobile-header-status-dot\"></div>\n <span class=\"mobile-header-status-text\" id=\"mobileHeaderStatusText\">").concat(this.t('listening'), "</span>\n <span class=\"mobile-header-duration\" id=\"mobileHeaderDuration\">00:00</span>\n </div>\n <span class=\"mobile-transcript-label\">CONVERSATION</span>\n </div>\n <button type=\"button\" class=\"mobile-close-transcript-btn\" id=\"mobileCloseTranscriptBtn\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M18 6L6 18M6 6l12 12\"/>\n </svg>\n </button>\n </div>\n \n <!-- Messages Container -->\n <div class=\"mobile-messages-container\" id=\"mobileMessagesContainer\">\n <!-- Messages will be dynamically added here -->\n </div>\n \n <!-- Text Input Area -->\n <div class=\"mobile-input-area\">\n <div class=\"mobile-input-wrapper\">\n <input\n type=\"text\"\n placeholder=\"Type a message...\"\n id=\"mobileTextInput\"\n class=\"mobile-text-input\"\n dir=\"").concat(textDir, "\"\n />\n <button type=\"button\" class=\"mobile-send-btn\" id=\"mobileSendBtn\" disabled>\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M22 2L11 13M22 2l-7 20-4-9-9-4 20-7z\"/>\n </svg>\n </button>\n </div>\n <p class=\"mobile-input-hint\">\uD83C\uDF99\uFE0F ").concat(this.t('voiceActive') || 'Voice is still active', " \u2022 ").concat(this.t('typeOrSpeak') || 'Type or speak', "</p>\n </div>\n </div>\n </div>\n ");
35727
35968
 
35728
35969
  // Append to body
35729
35970
  document.body.appendChild(container);
@@ -35857,7 +36098,7 @@ var Mobile = /*#__PURE__*/function () {
35857
36098
  var container = document.getElementById('mobile-voice-call-bar-container');
35858
36099
  var overlay = container === null || container === void 0 ? void 0 : container.querySelector('#mobileTranscriptOverlay');
35859
36100
  if (overlay) {
35860
- overlay.style.display = 'flex';
36101
+ overlay.classList.add('mobile-transcript-overlay--open');
35861
36102
  this.isTranscriptExpanded = true;
35862
36103
 
35863
36104
  // Focus input and sync send button state (container-scoped for Shopify)
@@ -35891,7 +36132,7 @@ var Mobile = /*#__PURE__*/function () {
35891
36132
  var container = document.getElementById('mobile-voice-call-bar-container');
35892
36133
  var overlay = container === null || container === void 0 ? void 0 : container.querySelector('#mobileTranscriptOverlay');
35893
36134
  if (overlay) {
35894
- overlay.style.display = 'none';
36135
+ overlay.classList.remove('mobile-transcript-overlay--open');
35895
36136
  this.isTranscriptExpanded = false;
35896
36137
  }
35897
36138
  }
@@ -35912,6 +36153,8 @@ var Mobile = /*#__PURE__*/function () {
35912
36153
  var customStatusText = this.config.statusText;
35913
36154
  var displayText = '';
35914
36155
  var dotColor = '#6b7280';
36156
+ var brandPrimary = this.config.primaryBtnGradient1 || this.config.startCallButtonColor || '#3b82f6';
36157
+ var brandSecondary = this.config.primaryBtnGradient2 || this.config.avatarGradient2 || brandPrimary;
35915
36158
  if (customStatusText) {
35916
36159
  // Use custom status text for all states
35917
36160
  displayText = customStatusText;
@@ -35920,13 +36163,13 @@ var Mobile = /*#__PURE__*/function () {
35920
36163
  // Use dynamic status based on state
35921
36164
  if (status === 'connecting') {
35922
36165
  displayText = this.t('connecting') || 'Connecting...';
35923
- dotColor = '#3b82f6'; // Blue for connecting
36166
+ dotColor = brandPrimary;
35924
36167
  } else if (status === 'listening' || status === 'recording') {
35925
36168
  displayText = this.t('listening') || 'Listening...';
35926
36169
  dotColor = '#22c55e';
35927
36170
  } else if (status === 'speaking') {
35928
36171
  displayText = this.t('speaking') || 'Speaking...';
35929
- dotColor = '#a855f7';
36172
+ dotColor = brandSecondary;
35930
36173
  } else {
35931
36174
  displayText = this.t('paused') || 'Paused';
35932
36175
  dotColor = '#facc15';
@@ -35958,6 +36201,7 @@ var Mobile = /*#__PURE__*/function () {
35958
36201
  // Render message
35959
36202
  var messageEl = document.createElement('div');
35960
36203
  messageEl.className = "mobile-message-bubble ".concat(type);
36204
+ messageEl.setAttribute('dir', this.config.direction === 'rtl' ? 'rtl' : 'ltr');
35961
36205
  messageEl.textContent = text;
35962
36206
  messagesContainer.appendChild(messageEl);
35963
36207
  messagesContainer.scrollTop = messagesContainer.scrollHeight;
@@ -36077,8 +36321,9 @@ var Styles = /*#__PURE__*/function () {
36077
36321
  var agentRoleColor = c.agentRoleColor || 'rgba(255,255,255,0.35)';
36078
36322
  var headlineColor = c.headlineColor || '#ffffff';
36079
36323
  var sublineColor = c.sublineColor || 'rgba(255,255,255,0.45)';
36080
- var primaryGrad1 = c.primaryBtnGradient1 || '#6d56f5';
36081
- var primaryGrad2 = c.primaryBtnGradient2 || '#9d8df8';
36324
+ var primaryGrad1 = c.primaryBtnGradient1 || c.startCallButtonColor || '#6d56f5';
36325
+ var primaryGrad2 = c.primaryBtnGradient2 || c.startCallButtonColor || '#9d8df8';
36326
+ var talkToPcFooterLink = c._talkToPcLinkColor || primaryGrad1;
36082
36327
  var primaryTextColor = c.startCallButtonTextColor || '#fff';
36083
36328
  var secondaryBg = c.secondaryBtnBg || 'rgba(255,255,255,0.05)';
36084
36329
  var secondaryBorder = c.secondaryBtnBorder || 'rgba(255,255,255,0.09)';
@@ -36086,7 +36331,8 @@ var Styles = /*#__PURE__*/function () {
36086
36331
  var panelBg = c.panelBackgroundColor || '#16161e';
36087
36332
  var endCallColor = c.endCallButtonColor || '#ef4444';
36088
36333
  var sendBtnColor = c.sendButtonColor || primaryGrad1;
36089
- return "\n /* Voice Interface - Dark Theme Desktop */\n .voice-interface {\n display: none".concat(important, ";\n flex: 1").concat(important, ";\n flex-direction: column").concat(important, ";\n align-items: stretch").concat(important, ";\n justify-content: flex-start").concat(important, ";\n padding: 0").concat(important, ";\n background: ").concat(panelBg, ";\n overflow: hidden").concat(important, ";\n min-height: 0").concat(important, ";\n height: 100%").concat(important, ";\n width: 100%").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n .voice-interface.active { display: flex").concat(important, "; }\n\n .voice-interface.active:has(#voiceIdleState:not([style*=\"display: none\"]):not([style*=\"display:none\"])) {\n background: transparent").concat(important, ";\n }\n\n /* Footer stays transparent so parent panel gradient (incl. Powered by) shows through on idle */\n .voice-interface.active ~ .ttp-footer {\n background: transparent").concat(important, ";\n border-top-color: rgba(255,255,255,0.06)").concat(important, ";\n }\n .voice-interface.active ~ .ttp-footer span { color: rgba(255,255,255,0.35)").concat(important, "; }\n .voice-interface.active ~ .ttp-footer a { color: #a78bfa").concat(important, "; }\n\n #voiceIdleState {\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n flex: 1").concat(important, ";\n min-height: 0").concat(important, ";\n width: 100%").concat(important, ";\n box-sizing: border-box").concat(important, ";\n background: transparent").concat(important, ";\n }\n #voiceIdleState[style*=\"display: none\"],\n #voiceIdleState[style*=\"display:none\"] {\n display: none !important;\n }\n\n #voiceActiveState {\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n width: 100%").concat(important, ";\n height: 100%").concat(important, ";\n min-height: 0").concat(important, ";\n overflow: hidden").concat(important, ";\n flex: 1").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n #voiceActiveState[style*=\"display: none\"],\n #voiceActiveState[style*=\"display:none\"] {\n display: none !important;\n }\n\n /* \u2500\u2500 IDLE HERO \u2014 transparent; gradient is on #voiceIdleState so hero + body share one surface \u2500\u2500 */\n .ttp-hero {\n position: relative").concat(important, ";\n padding: 24px 22px 22px").concat(important, ";\n background: transparent").concat(important, ";\n border-bottom: none").concat(important, ";\n overflow: hidden").concat(important, ";\n }\n .ttp-hero::after {\n content: ''").concat(important, ";\n position: absolute").concat(important, ";\n top: -40px").concat(important, "; right: -40px").concat(important, ";\n width: 140px").concat(important, "; height: 140px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background: radial-gradient(circle, ").concat(primaryGrad1, "2e 0%, transparent 70%);\n pointer-events: none").concat(important, ";\n }\n .ttp-header {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: space-between").concat(important, ";\n margin-bottom: 20px").concat(important, ";\n position: relative").concat(important, ";\n z-index: 1").concat(important, ";\n }\n .ttp-agent { display: flex").concat(important, "; align-items: center").concat(important, "; gap: 10px").concat(important, "; }\n .ttp-avatar-wrap { position: relative").concat(important, "; }\n .ttp-avatar {\n width: 36px").concat(important, "; height: 36px").concat(important, "; border-radius: 50%").concat(important, ";\n background: linear-gradient(135deg, ").concat(avatarGrad1, ", ").concat(avatarGrad2, ");\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n font-size: 14px").concat(important, "; font-weight: 500").concat(important, "; color: #fff").concat(important, ";\n }\n .ttp-online-dot {\n position: absolute").concat(important, "; bottom: 0").concat(important, "; right: 0").concat(important, ";\n width: 10px").concat(important, "; height: 10px").concat(important, "; border-radius: 50%").concat(important, ";\n background: ").concat(onlineDotColor, "; border: 2px solid ").concat(heroGrad2, ";\n }\n .ttp-agent-name { font-size: 14px").concat(important, "; font-weight: 500").concat(important, "; color: ").concat(agentNameColor, "; }\n .ttp-agent-role { font-size: 10px").concat(important, "; color: ").concat(agentRoleColor, "; margin-top: 1px").concat(important, "; }\n .ttp-close-btn {\n width: 26px").concat(important, "; height: 26px").concat(important, "; border-radius: 50%").concat(important, ";\n background: rgba(255,255,255,0.07)").concat(important, "; border: none").concat(important, "; cursor: pointer").concat(important, ";\n color: rgba(255,255,255,0.4)").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n transition: background 0.2s").concat(important, ";\n }\n .ttp-close-btn:hover { background: rgba(255,255,255,0.14)").concat(important, "; }\n .ttp-headline {\n font-size: 22px").concat(important, "; font-weight: 500").concat(important, "; color: ").concat(headlineColor, ";\n line-height: 1.2").concat(important, "; margin-bottom: 6px").concat(important, "; position: relative").concat(important, "; z-index: 1").concat(important, ";\n }\n .ttp-subline {\n font-size: 13px").concat(important, "; color: ").concat(sublineColor, ";\n line-height: 1.5").concat(important, "; position: relative").concat(important, "; z-index: 1").concat(important, ";\n }\n\n /* \u2500\u2500 DOMAIN ERROR CARD \u2500\u2500 */\n .ttp-domain-error-card {\n display: flex").concat(important, ";\n align-items: flex-start").concat(important, ";\n gap: 12px").concat(important, ";\n padding: 14px 16px").concat(important, ";\n border-radius: 12px").concat(important, ";\n background: rgba(239,68,68,0.08)").concat(important, ";\n border: 1px solid rgba(239,68,68,0.18)").concat(important, ";\n }\n .ttp-domain-error-icon {\n flex-shrink: 0").concat(important, ";\n margin-top: 1px").concat(important, ";\n }\n .ttp-domain-error-text {\n font-size: 12px").concat(important, ";\n line-height: 1.55").concat(important, ";\n color: rgba(252,165,165,0.85)").concat(important, ";\n }\n .ttp-domain-error-text strong {\n color: #fca5a5").concat(important, ";\n font-weight: 600").concat(important, ";\n }\n\n /* \u2500\u2500 IDLE BODY \u2500\u2500 */\n .ttp-body {\n padding: 10px 18px 14px").concat(important, ";\n display: flex").concat(important, "; flex-direction: column").concat(important, "; gap: 6px").concat(important, ";\n }\n .ttp-btn-primary {\n width: 100%").concat(important, "; padding: 11px").concat(important, "; border-radius: 12px").concat(important, ";\n background: linear-gradient(135deg, ").concat(primaryGrad1, ", ").concat(primaryGrad2, ");\n border: none").concat(important, "; cursor: pointer").concat(important, ";\n font-size: 13px").concat(important, "; font-weight: 500").concat(important, "; color: ").concat(primaryTextColor, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, "; gap: 8px").concat(important, ";\n box-shadow: 0 4px 18px ").concat(primaryGrad1, "59;\n transition: opacity 0.2s, transform 0.15s").concat(important, ";\n font-family: inherit").concat(important, ";\n }\n .ttp-btn-primary:hover { opacity: 0.9").concat(important, "; transform: translateY(-1px)").concat(important, "; }\n .ttp-btn-primary:disabled { cursor: not-allowed").concat(important, "; opacity: 0.6").concat(important, "; }\n .ttp-btn-secondary {\n width: 100%").concat(important, "; padding: 10px").concat(important, "; border-radius: 12px").concat(important, ";\n background: ").concat(secondaryBg, ";\n border: 1px solid ").concat(secondaryBorder, ";\n cursor: pointer").concat(important, "; font-size: 13px").concat(important, "; color: ").concat(secondaryTextColor, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, "; gap: 8px").concat(important, ";\n transition: background 0.2s").concat(important, "; font-family: inherit").concat(important, ";\n }\n .ttp-btn-secondary:hover { background: ").concat(secondaryBg, "; }\n\n /* WhatsApp button */\n .ttp-btn-wa {\n width: 100%").concat(important, "; padding: 10px").concat(important, "; border-radius: 12px").concat(important, ";\n background: rgba(37,211,102,0.08)").concat(important, ";\n border: 1px solid rgba(37,211,102,0.2)").concat(important, ";\n cursor: pointer").concat(important, "; font-size: 13px").concat(important, "; font-weight: 500").concat(important, "; color: #4ade80").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, "; gap: 8px").concat(important, ";\n transition: background 0.2s").concat(important, "; font-family: inherit").concat(important, ";\n text-decoration: none").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n .ttp-btn-wa:hover { background: rgba(37,211,102,0.14)").concat(important, "; }\n\n /* Connecting Spinner (reused from old design) */\n .connecting-spinner {\n display: inline-block").concat(important, ";\n width: 16px").concat(important, "; height: 16px").concat(important, ";\n border: 2px solid rgba(255,255,255,0.3)").concat(important, ";\n border-top-color: #fff").concat(important, ";\n border-radius: 50%").concat(important, ";\n animation: ttp-spin 1s linear infinite").concat(important, ";\n margin-right: 8px").concat(important, ";\n vertical-align: middle").concat(important, ";\n }\n @keyframes ttp-spin { to { transform: rotate(360deg); } }\n\n /* \u2500\u2500 ACTIVE CALL \u2500\u2500 */\n .ttp-call-hero {\n background: linear-gradient(160deg, ").concat(heroGrad1, " 0%, ").concat(heroGrad2, " 100%);\n padding: 22px 20px 18px").concat(important, ";\n border-bottom: 1px solid rgba(255,255,255,0.06)").concat(important, ";\n }\n .ttp-call-topbar {\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: space-between").concat(important, ";\n margin-bottom: 18px").concat(important, ";\n }\n .ttp-rec { display: flex").concat(important, "; align-items: center").concat(important, "; gap: 7px").concat(important, "; }\n .ttp-rec-dot {\n width: 7px").concat(important, "; height: 7px").concat(important, "; border-radius: 50%").concat(important, "; background: #f87171").concat(important, ";\n animation: ttp-pulse 1s ease-in-out infinite").concat(important, ";\n }\n ").concat(this.config.useShadowDOM === false ? "\n /* Regular DOM (e.g. Shopify): theme rules often strip span/div sizing \u2014 recording dot + pulse */\n #ttp-widget-container .ttp-call-topbar .ttp-rec,\n #text-chat-panel .ttp-call-topbar .ttp-rec {\n display: flex !important;\n align-items: center !important;\n gap: 7px !important;\n flex-shrink: 0 !important;\n }\n #ttp-widget-container .ttp-rec-dot,\n #ttp-widget-container .compact-timer .ttp-rec-dot,\n #text-chat-panel .ttp-rec-dot,\n #text-chat-panel .compact-timer .ttp-rec-dot {\n display: block !important;\n flex-shrink: 0 !important;\n box-sizing: content-box !important;\n width: 7px !important;\n height: 7px !important;\n min-width: 7px !important;\n min-height: 7px !important;\n max-width: none !important;\n max-height: none !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n border-radius: 50% !important;\n background: #f87171 !important;\n background-color: #f87171 !important;\n opacity: 1 !important;\n visibility: visible !important;\n -webkit-animation: ttp-pulse 1s ease-in-out infinite !important;\n animation: ttp-pulse 1s ease-in-out infinite !important;\n }\n #ttp-widget-container .ttp-transcript-hdr .ttp-dot,\n #text-chat-panel .ttp-transcript-hdr .ttp-dot {\n display: flex !important;\n width: 3px !important;\n height: 3px !important;\n min-width: 3px !important;\n min-height: 3px !important;\n border-radius: 50% !important;\n background: ".concat(avatarGrad2, " !important;\n background-color: ").concat(avatarGrad2, " !important;\n opacity: 1 !important;\n visibility: visible !important;\n -webkit-animation: ttp-pulse 0.8s ease-in-out infinite !important;\n animation: ttp-pulse 0.8s ease-in-out infinite !important;\n }\n /* Orb waveform: same motion as shadow DOM (ttp-wave keyframes). Do not set opacity !important\n on bars \u2014 it overrides keyframe opacity and changes the look. */\n #ttp-widget-container .ttp-wave,\n #text-chat-panel .ttp-wave {\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n gap: 3px !important;\n height: 26px !important;\n min-height: 26px !important;\n width: auto !important;\n min-width: 36px !important;\n overflow: visible !important;\n flex-shrink: 0 !important;\n }\n #ttp-widget-container .ttp-wave-bar,\n #text-chat-panel .ttp-wave-bar {\n display: block !important;\n box-sizing: content-box !important;\n width: 2.5px !important;\n min-width: 2.5px !important;\n max-width: none !important;\n flex-shrink: 0 !important;\n border-radius: 3px !important;\n background: rgba(255, 255, 255, 0.9) !important;\n background-color: rgba(255, 255, 255, 0.9) !important;\n visibility: visible !important;\n transform-origin: center center !important;\n -webkit-animation: ttp-wave 0.75s ease-in-out infinite alternate !important;\n animation: ttp-wave 0.75s ease-in-out infinite alternate !important;\n }\n #ttp-widget-container .ttp-orb,\n #text-chat-panel .ttp-orb {\n overflow: visible !important;\n }\n ") : '', "\n .ttp-timer { font-size: 11px").concat(important, "; color: rgba(255,255,255,0.4)").concat(important, "; letter-spacing: 0.05em").concat(important, "; }\n .ttp-call-label { font-size: 11px").concat(important, "; color: rgba(255,255,255,0.25)").concat(important, "; }\n\n /* \u2500\u2500 ORB \u2500\u2500 */\n .ttp-orb-wrap {\n display: flex").concat(important, "; flex-direction: column").concat(important, "; align-items: center").concat(important, ";\n gap: 12px").concat(important, "; padding: 8px 0").concat(important, ";\n }\n .ttp-orb-rings {\n position: relative").concat(important, "; width: 72px").concat(important, "; height: 72px").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n }\n .ttp-ring {\n position: absolute").concat(important, "; border-radius: 50%").concat(important, ";\n border: 1.5px solid ").concat(primaryGrad1, "33;\n animation: ttp-ring 2s ease-in-out infinite").concat(important, ";\n }\n .ttp-ring-1 { inset: -8px").concat(important, "; }\n .ttp-ring-2 { inset: -16px").concat(important, "; border-width: 1px").concat(important, "; border-color: ").concat(primaryGrad1, "1a; animation-delay: 0.5s").concat(important, "; }\n .ttp-orb {\n width: 72px").concat(important, "; height: 72px").concat(important, "; border-radius: 50%").concat(important, ";\n background: linear-gradient(135deg, ").concat(primaryGrad1, ", ").concat(primaryGrad2, ");\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n animation: ttp-orb-breathe 1.4s ease-in-out infinite").concat(important, ";\n box-shadow: 0 6px 24px ").concat(primaryGrad1, "66;\n }\n .ttp-wave { display: flex").concat(important, "; align-items: center").concat(important, "; gap: 3px").concat(important, "; height: 26px").concat(important, "; }\n .ttp-wave-bar {\n width: 2.5px").concat(important, "; border-radius: 3px").concat(important, "; background: rgba(255,255,255,0.9)").concat(important, ";\n animation: ttp-wave 0.75s ease-in-out infinite alternate").concat(important, ";\n }\n .ttp-listen-label { font-size: 12px").concat(important, "; color: rgba(255,255,255,0.4)").concat(important, "; }\n\n /* \u2500\u2500 CONTROLS \u2500\u2500 */\n .ttp-controls {\n padding: 16px 20px").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, "; gap: 14px").concat(important, ";\n }\n .ttp-ctrl-btn {\n width: 42px").concat(important, "; height: 42px").concat(important, "; border-radius: 50%").concat(important, ";\n background: rgba(255,255,255,0.06)").concat(important, ";\n border: 1px solid rgba(255,255,255,0.09)").concat(important, ";\n cursor: pointer").concat(important, "; display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n color: rgba(255,255,255,0.4)").concat(important, "; transition: background 0.2s").concat(important, ";\n position: relative").concat(important, ";\n }\n .ttp-ctrl-btn:hover { background: rgba(255,255,255,0.12)").concat(important, "; }\n .ttp-ctrl-btn.muted {\n background: rgba(239, 68, 68, 0.15)").concat(important, ";\n border-color: rgba(239, 68, 68, 0.3)").concat(important, ";\n }\n .ttp-end-btn {\n width: 52px").concat(important, "; height: 52px").concat(important, "; border-radius: 50%").concat(important, ";\n background: ").concat(endCallColor, "; border: none").concat(important, "; cursor: pointer").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n color: #fff").concat(important, "; transform: rotate(135deg)").concat(important, ";\n box-shadow: 0 4px 16px ").concat(endCallColor, "59;\n transition: background 0.2s").concat(important, ";\n }\n .ttp-end-btn:hover { background: ").concat(endCallColor, "; opacity: 0.85").concat(important, "; }\n\n /* Mute/speaker icon toggle */\n .desktop-mic-icon, .desktop-speaker-icon { display: block").concat(important, "; }\n .desktop-mic-off-icon, .desktop-speaker-off-icon {\n position: absolute").concat(important, "; top: 50%").concat(important, "; left: 50%").concat(important, ";\n transform: translate(-50%, -50%)").concat(important, ";\n width: 16px").concat(important, "; height: 16px").concat(important, "; z-index: 10").concat(important, ";\n }\n\n /* \u2500\u2500 DESKTOP VOICE SECTION WRAPPER \u2500\u2500 */\n .desktop-voice-section { flex-shrink: 0").concat(important, "; }\n\n /* \u2500\u2500 COMPACT VOICE SECTION (shown when items/rooms are visible) \u2500\u2500 */\n .compact-voice-section {\n padding: 10px 14px").concat(important, ";\n background: linear-gradient(180deg, ").concat(heroGrad1, " 0%, ").concat(primaryGrad1, "14 100%);\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: space-between").concat(important, ";\n flex-shrink: 0").concat(important, ";\n border-bottom: 1px solid rgba(255,255,255,0.06)").concat(important, ";\n }\n .compact-left { display: flex").concat(important, "; align-items: center").concat(important, "; gap: 10px").concat(important, "; }\n .compact-avatar {\n width: 42px").concat(important, "; height: 42px").concat(important, "; min-width: 42px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background: linear-gradient(135deg, ").concat(avatarGrad1, ", ").concat(avatarGrad2, ");\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n .compact-orb {\n width: 32px !important; height: 32px !important;\n border-radius: 50% !important;\n }\n .compact-info { display: flex").concat(important, "; flex-direction: column").concat(important, "; gap: 2px").concat(important, "; }\n .compact-timer {\n display: flex").concat(important, "; align-items: center").concat(important, "; gap: 5px").concat(important, ";\n font-size: 11px").concat(important, "; font-weight: 600").concat(important, "; color: #e8e4f0").concat(important, ";\n }\n .compact-status {\n font-size: 10px").concat(important, "; color: rgba(255,255,255,0.4)").concat(important, ";\n }\n .compact-controls { display: flex").concat(important, "; align-items: center").concat(important, "; gap: 6px").concat(important, "; }\n .compact-control-btn {\n width: 36px").concat(important, "; height: 36px").concat(important, "; min-width: 36px").concat(important, ";\n border-radius: 50%").concat(important, "; border: none").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n cursor: pointer").concat(important, "; transition: all 0.15s").concat(important, ";\n position: relative").concat(important, ";\n }\n .compact-control-btn svg { width: 16px").concat(important, "; height: 16px").concat(important, "; }\n .compact-control-btn .desktop-mic-off-icon,\n .compact-control-btn .desktop-speaker-off-icon {\n width: 16px").concat(important, "; height: 16px").concat(important, ";\n }\n .compact-control-btn.secondary {\n background: rgba(255,255,255,0.08)").concat(important, "; color: rgba(255,255,255,0.5)").concat(important, ";\n }\n .compact-control-btn.secondary:hover {\n background: rgba(255,255,255,0.14)").concat(important, "; color: rgba(255,255,255,0.7)").concat(important, ";\n }\n .compact-control-btn.secondary.muted {\n background: rgba(239, 68, 68, 0.15)").concat(important, "; color: #ef4444").concat(important, ";\n }\n .compact-control-btn.secondary.muted .desktop-mic-icon,\n .compact-control-btn.secondary.muted .desktop-speaker-icon {\n stroke: #ef4444").concat(important, ";\n }\n .compact-control-btn.secondary.muted .desktop-mic-off-icon,\n .compact-control-btn.secondary.muted .desktop-speaker-off-icon {\n width: 16px").concat(important, "; height: 16px").concat(important, ";\n }\n .compact-control-btn.danger {\n width: 40px").concat(important, "; height: 40px").concat(important, "; min-width: 40px").concat(important, ";\n background: #ef4444").concat(important, "; color: #fff").concat(important, ";\n box-shadow: 0 3px 10px rgba(239,68,68,0.35)").concat(important, ";\n }\n .compact-control-btn.danger:hover {\n transform: scale(1.05)").concat(important, ";\n box-shadow: 0 4px 14px rgba(239,68,68,0.45)").concat(important, ";\n }\n .compact-control-btn.danger svg { width: 18px").concat(important, "; height: 18px").concat(important, "; overflow: visible").concat(important, "; }\n\n /* \u2500\u2500 TRANSCRIPT \u2500\u2500 */\n .ttp-transcript {\n margin: 0 16px 16px").concat(important, ";\n padding: 12px 14px").concat(important, ";\n background: ").concat(primaryGrad1, "24;\n border: 1px solid ").concat(primaryGrad1, "4d;\n border-radius: 12px").concat(important, ";\n }\n .ttp-transcript-hdr {\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: space-between").concat(important, ";\n margin-bottom: 7px").concat(important, ";\n }\n .ttp-live-label {\n font-size: 10px").concat(important, "; color: ").concat(primaryGrad2, ";\n text-transform: uppercase").concat(important, "; letter-spacing: 0.1em").concat(important, ";\n font-weight: 600").concat(important, ";\n }\n .ttp-toggle-text {\n font-size: 10px").concat(important, "; color: rgba(255,255,255,0.35)").concat(important, ";\n cursor: pointer").concat(important, "; margin-left: auto").concat(important, "; margin-right: 8px").concat(important, ";\n transition: color 0.2s").concat(important, ";\n }\n .ttp-toggle-text:hover { color: ").concat(primaryGrad2, "; }\n .ttp-transcript-hdr { cursor: pointer").concat(important, "; }\n .ttp-dots { display: flex").concat(important, "; gap: 3px").concat(important, "; align-items: center").concat(important, "; }\n .ttp-dot {\n width: 3px").concat(important, "; height: 3px").concat(important, "; border-radius: 50%").concat(important, "; background: ").concat(primaryGrad2, ";\n animation: ttp-pulse 0.8s ease-in-out infinite").concat(important, ";\n }\n .ttp-dot:nth-child(2) { animation-delay: 0.2s").concat(important, "; }\n .ttp-dot:nth-child(3) { animation-delay: 0.4s").concat(important, "; }\n .ttp-transcript-text { font-size: 12px").concat(important, "; color: #e2e0f0").concat(important, "; line-height: 1.55").concat(important, "; }\n .ttp-transcript-text .name { color: #c4b5fd").concat(important, "; font-weight: 600").concat(important, "; }\n .ttp-cursor {\n display: inline-block").concat(important, "; width: 2px").concat(important, "; height: 12px").concat(important, ";\n background: ").concat(primaryGrad2, "; vertical-align: middle").concat(important, "; margin-left: 2px").concat(important, ";\n animation: ttp-blink 0.9s infinite").concat(important, ";\n }\n\n /* Transcript collapsed/expanded state */\n .live-transcript-collapsed { display: block").concat(important, "; }\n .conversation-history { display: none").concat(important, "; }\n\n .ttp-transcript.expanded {\n flex: 1").concat(important, ";\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n min-height: 0").concat(important, ";\n overflow: hidden").concat(important, ";\n }\n .ttp-transcript.expanded .live-transcript-collapsed { display: none").concat(important, "; }\n .ttp-transcript.expanded .conversation-history {\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n flex: 1").concat(important, ";\n min-height: 0").concat(important, ";\n overflow-y: auto").concat(important, ";\n max-height: 260px").concat(important, ";\n scrollbar-width: thin").concat(important, ";\n scrollbar-color: ").concat(primaryGrad1, "4d transparent;\n }\n .ttp-transcript.expanded .conversation-history::-webkit-scrollbar { width: 4px").concat(important, "; }\n .ttp-transcript.expanded .conversation-history::-webkit-scrollbar-track { background: transparent").concat(important, "; }\n .ttp-transcript.expanded .conversation-history::-webkit-scrollbar-thumb {\n background: ").concat(primaryGrad1, "4d; border-radius: 2px").concat(important, ";\n }\n\n /* Message rows in history */\n .conversation-messages { display: flex").concat(important, "; flex-direction: column").concat(important, "; gap: 8px").concat(important, "; padding-bottom: 4px").concat(important, "; }\n .message-row {\n display: flex").concat(important, "; align-items: flex-start").concat(important, "; gap: 8px").concat(important, ";\n animation: ttp-msg-in 0.2s ease-out").concat(important, ";\n }\n .message-row.user { flex-direction: row-reverse").concat(important, "; }\n .message-avatar {\n width: 26px").concat(important, "; height: 26px").concat(important, "; min-width: 26px").concat(important, ";\n border-radius: 50%").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n font-size: 10px").concat(important, "; font-weight: 600").concat(important, "; flex-shrink: 0").concat(important, ";\n }\n .message-avatar.user {\n background: rgba(255,255,255,0.12)").concat(important, "; color: rgba(255,255,255,0.6)").concat(important, ";\n }\n .message-avatar.assistant {\n background: linear-gradient(135deg, ").concat(avatarGrad1, ", ").concat(avatarGrad2, ");\n }\n .message-avatar .orb {\n width: 12px").concat(important, "; height: 12px").concat(important, "; border-radius: 50%").concat(important, ";\n background: rgba(255,255,255,0.9)").concat(important, ";\n }\n .message-bubble {\n padding: 8px 12px").concat(important, ";\n border-radius: 12px").concat(important, ";\n font-size: 12px").concat(important, "; line-height: 1.5").concat(important, ";\n max-width: 80%").concat(important, "; word-wrap: break-word").concat(important, ";\n }\n .message-row.assistant .message-bubble {\n background: rgba(255,255,255,0.08)").concat(important, ";\n color: #e2e0f0").concat(important, ";\n border-bottom-left-radius: 4px").concat(important, ";\n }\n .message-row.user .message-bubble {\n background: ").concat(primaryGrad1, "40;\n color: #e8e4f0").concat(important, ";\n border-bottom-right-radius: 4px").concat(important, ";\n }\n .live-message-row {\n display: flex").concat(important, "; align-items: flex-start").concat(important, "; gap: 8px").concat(important, ";\n margin-top: 6px").concat(important, ";\n }\n .live-message-row .message-bubble {\n position: relative").concat(important, ";\n padding: 14px 12px 8px").concat(important, ";\n border-radius: 12px").concat(important, ";\n font-size: 12px").concat(important, "; line-height: 1.5").concat(important, ";\n background: rgba(255,255,255,0.08)").concat(important, ";\n color: #e2e0f0").concat(important, ";\n max-width: 80%").concat(important, "; word-wrap: break-word").concat(important, ";\n }\n .live-message-row .live-badge {\n position: absolute").concat(important, "; top: 0").concat(important, "; left: 10px").concat(important, ";\n transform: translateY(-50%)").concat(important, ";\n background: ").concat(primaryGrad1, "; color: #fff").concat(important, ";\n font-size: 8px").concat(important, "; font-weight: 700").concat(important, ";\n padding: 2px 6px").concat(important, "; border-radius: 4px").concat(important, ";\n text-transform: uppercase").concat(important, "; letter-spacing: 0.05em").concat(important, ";\n }\n .typing-cursor {\n display: inline-block").concat(important, "; width: 2px").concat(important, "; height: 12px").concat(important, ";\n background: ").concat(primaryGrad2, "; vertical-align: middle").concat(important, "; margin-left: 2px").concat(important, ";\n animation: ttp-blink 0.9s infinite").concat(important, ";\n }\n @keyframes ttp-msg-in {\n from { opacity: 0; transform: translateY(4px); }\n to { opacity: 1; transform: translateY(0); }\n }\n\n /* \u2500\u2500 TYPE ROW \u2500\u2500 */\n .ttp-type-row { display: flex").concat(important, "; gap: 8px").concat(important, "; padding: 0 16px 16px").concat(important, "; flex-wrap: wrap").concat(important, "; }\n .ttp-input {\n flex: 1").concat(important, "; padding: 9px 12px").concat(important, ";\n background: rgba(255,255,255,0.05)").concat(important, ";\n border: 1px solid rgba(255,255,255,0.09)").concat(important, ";\n border-radius: 10px").concat(important, "; color: rgba(255,255,255,0.6)").concat(important, ";\n font-size: 12px").concat(important, "; outline: none").concat(important, "; font-family: inherit").concat(important, ";\n transition: border-color 0.2s").concat(important, ";\n }\n .ttp-input::placeholder { color: rgba(255,255,255,0.25)").concat(important, "; }\n .ttp-input:focus { border-color: ").concat(primaryGrad1, "80; }\n .ttp-send-btn {\n width: 34px").concat(important, "; height: 34px").concat(important, "; border-radius: 9px").concat(important, ";\n background: ").concat(sendBtnColor, "; border: none").concat(important, "; cursor: pointer").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, "; transition: background 0.2s").concat(important, ";\n }\n .ttp-send-btn:hover { background: ").concat(sendBtnColor, "; opacity: 0.85").concat(important, "; }\n\n /* \u2500\u2500 KEYFRAMES \u2500\u2500 */\n @keyframes ttp-pulse { 0%,100%{opacity:1} 50%{opacity:.3} }\n @keyframes ttp-blink { 0%,49%{opacity:1} 50%,100%{opacity:0} }\n @keyframes ttp-ring { 0%,100%{transform:scale(1);opacity:.6} 50%{transform:scale(1.22);opacity:0} }\n @keyframes ttp-orb-breathe { 0%,100%{transform:scale(1)} 50%{transform:scale(1.05)} }\n @keyframes ttp-wave { from{transform:scaleY(.15);opacity:.3} to{transform:scaleY(1);opacity:.9} }\n @keyframes ttp-pill-pulse { 0%,100%{box-shadow:0 0 0 0 ").concat(primaryGrad1, "80} 60%{box-shadow:0 0 0 7px ").concat(primaryGrad1, "00} }\n\n /* Mobile Voice Call UI - Shared styles (also used in generateMobileCSS) */\n ").concat(this._getSharedMobileCSS(important), "\n\n ");
36334
+ var callSurfaceGradient = "linear-gradient(160deg, ".concat(heroGrad1, " 0%, ").concat(heroGrad2, " 100%)");
36335
+ return "\n /* Voice Interface - Dark Theme Desktop */\n .voice-interface {\n display: none".concat(important, ";\n flex: 1").concat(important, ";\n flex-direction: column").concat(important, ";\n align-items: stretch").concat(important, ";\n justify-content: flex-start").concat(important, ";\n padding: 0").concat(important, ";\n background: ").concat(panelBg, ";\n overflow: hidden").concat(important, ";\n min-height: 0").concat(important, ";\n height: 100%").concat(important, ";\n width: 100%").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n .voice-interface.active {\n display: flex").concat(important, ";\n background: ").concat(callSurfaceGradient).concat(important, ";\n }\n\n .voice-interface.active:has(#voiceIdleState:not([style*=\"display: none\"]):not([style*=\"display:none\"])) {\n background: transparent").concat(important, ";\n }\n\n /* Footer: same in-call purple as voice area (parent also sets bg; this covers any layout gaps) */\n .voice-interface.active ~ .ttp-footer {\n background: ").concat(callSurfaceGradient).concat(important, ";\n border-top-color: rgba(255,255,255,0.06)").concat(important, ";\n }\n .voice-interface.active ~ .ttp-footer span { color: rgba(255,255,255,0.35)").concat(important, "; }\n .voice-interface.active ~ .ttp-footer a { color: ").concat(talkToPcFooterLink).concat(important, "; }\n\n #voiceIdleState {\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n flex: 1").concat(important, ";\n min-height: 0").concat(important, ";\n width: 100%").concat(important, ";\n box-sizing: border-box").concat(important, ";\n background: transparent").concat(important, ";\n }\n #voiceIdleState[style*=\"display: none\"],\n #voiceIdleState[style*=\"display:none\"] {\n display: none !important;\n }\n\n #voiceActiveState {\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n width: 100%").concat(important, ";\n height: 100%").concat(important, ";\n min-height: 0").concat(important, ";\n overflow: hidden").concat(important, ";\n flex: 1").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n #voiceActiveState[style*=\"display: none\"],\n #voiceActiveState[style*=\"display:none\"] {\n display: none !important;\n }\n\n /* \u2500\u2500 IDLE HERO \u2014 transparent; gradient is on #voiceIdleState so hero + body share one surface \u2500\u2500 */\n .ttp-hero {\n position: relative").concat(important, ";\n padding: 24px 22px 22px").concat(important, ";\n background: transparent").concat(important, ";\n border-bottom: none").concat(important, ";\n overflow: hidden").concat(important, ";\n }\n .ttp-hero::after {\n content: ''").concat(important, ";\n position: absolute").concat(important, ";\n top: -40px").concat(important, "; right: -40px").concat(important, ";\n width: 140px").concat(important, "; height: 140px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background: radial-gradient(circle, ").concat(primaryGrad1, "2e 0%, transparent 70%);\n pointer-events: none").concat(important, ";\n }\n .ttp-header {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: space-between").concat(important, ";\n margin-bottom: 20px").concat(important, ";\n position: relative").concat(important, ";\n z-index: 1").concat(important, ";\n }\n .ttp-agent { display: flex").concat(important, "; align-items: center").concat(important, "; gap: 10px").concat(important, "; }\n .ttp-avatar-wrap { position: relative").concat(important, "; }\n .ttp-avatar {\n width: 36px").concat(important, "; height: 36px").concat(important, "; border-radius: 50%").concat(important, ";\n background: linear-gradient(135deg, ").concat(avatarGrad1, ", ").concat(avatarGrad2, ");\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n font-size: 14px").concat(important, "; font-weight: 500").concat(important, "; color: #fff").concat(important, ";\n }\n .ttp-avatar.ttp-avatar--image {\n padding: 0").concat(important, ";\n overflow: hidden").concat(important, ";\n }\n .ttp-avatar-img {\n width: 100%").concat(important, ";\n height: 100%").concat(important, ";\n object-fit: cover").concat(important, ";\n display: block").concat(important, ";\n border-radius: 50%").concat(important, ";\n }\n .ttp-online-dot {\n position: absolute").concat(important, "; bottom: 0").concat(important, "; right: 0").concat(important, ";\n width: 10px").concat(important, "; height: 10px").concat(important, "; border-radius: 50%").concat(important, ";\n background: ").concat(onlineDotColor, "; border: 2px solid ").concat(heroGrad2, ";\n }\n .ttp-agent-name { font-size: 14px").concat(important, "; font-weight: 500").concat(important, "; color: ").concat(agentNameColor, "; }\n .ttp-agent-role { font-size: 10px").concat(important, "; color: ").concat(agentRoleColor, "; margin-top: 1px").concat(important, "; }\n .ttp-close-btn {\n width: 26px").concat(important, "; height: 26px").concat(important, "; border-radius: 50%").concat(important, ";\n background: rgba(255,255,255,0.07)").concat(important, "; border: none").concat(important, "; cursor: pointer").concat(important, ";\n color: rgba(255,255,255,0.4)").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n transition: background 0.2s").concat(important, ";\n }\n .ttp-close-btn:hover { background: rgba(255,255,255,0.14)").concat(important, "; }\n .ttp-headline {\n font-size: 22px").concat(important, "; font-weight: 500").concat(important, "; color: ").concat(headlineColor, ";\n line-height: 1.2").concat(important, "; margin-bottom: 6px").concat(important, "; position: relative").concat(important, "; z-index: 1").concat(important, ";\n }\n .ttp-subline {\n font-size: 13px").concat(important, "; color: ").concat(sublineColor, ";\n line-height: 1.5").concat(important, "; position: relative").concat(important, "; z-index: 1").concat(important, ";\n }\n\n /* \u2500\u2500 DOMAIN ERROR CARD \u2500\u2500 */\n .ttp-domain-error-card {\n display: flex").concat(important, ";\n align-items: flex-start").concat(important, ";\n gap: 12px").concat(important, ";\n padding: 14px 16px").concat(important, ";\n border-radius: 12px").concat(important, ";\n background: rgba(239,68,68,0.08)").concat(important, ";\n border: 1px solid rgba(239,68,68,0.18)").concat(important, ";\n }\n .ttp-domain-error-icon {\n flex-shrink: 0").concat(important, ";\n margin-top: 1px").concat(important, ";\n }\n .ttp-domain-error-text {\n font-size: 12px").concat(important, ";\n line-height: 1.55").concat(important, ";\n color: rgba(252,165,165,0.85)").concat(important, ";\n }\n .ttp-domain-error-text strong {\n color: #fca5a5").concat(important, ";\n font-weight: 600").concat(important, ";\n }\n\n /* \u2500\u2500 IDLE BODY \u2500\u2500 */\n .ttp-body {\n padding: 10px 18px 14px").concat(important, ";\n display: flex").concat(important, "; flex-direction: column").concat(important, "; gap: 6px").concat(important, ";\n }\n .ttp-btn-primary {\n width: 100%").concat(important, "; padding: 11px").concat(important, "; border-radius: 12px").concat(important, ";\n background: linear-gradient(135deg, ").concat(primaryGrad1, ", ").concat(primaryGrad2, ");\n border: none").concat(important, "; cursor: pointer").concat(important, ";\n font-size: 13px").concat(important, "; font-weight: 500").concat(important, "; color: ").concat(primaryTextColor, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, "; gap: 8px").concat(important, ";\n box-shadow: 0 4px 18px ").concat(primaryGrad1, "59;\n transition: opacity 0.2s, transform 0.15s").concat(important, ";\n font-family: inherit").concat(important, ";\n }\n .ttp-btn-primary:hover { opacity: 0.9").concat(important, "; transform: translateY(-1px)").concat(important, "; }\n .ttp-btn-primary:disabled { cursor: not-allowed").concat(important, "; opacity: 0.6").concat(important, "; }\n .ttp-btn-secondary {\n width: 100%").concat(important, "; padding: 10px").concat(important, "; border-radius: 12px").concat(important, ";\n background: ").concat(secondaryBg, ";\n border: 1px solid ").concat(secondaryBorder, ";\n cursor: pointer").concat(important, "; font-size: 13px").concat(important, "; color: ").concat(secondaryTextColor, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, "; gap: 8px").concat(important, ";\n transition: background 0.2s").concat(important, "; font-family: inherit").concat(important, ";\n }\n .ttp-btn-secondary:hover { background: ").concat(secondaryBg, "; }\n\n /* WhatsApp button */\n .ttp-btn-wa {\n width: 100%").concat(important, "; padding: 10px").concat(important, "; border-radius: 12px").concat(important, ";\n background: rgba(37,211,102,0.08)").concat(important, ";\n border: 1px solid rgba(37,211,102,0.2)").concat(important, ";\n cursor: pointer").concat(important, "; font-size: 13px").concat(important, "; font-weight: 500").concat(important, "; color: #4ade80").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, "; gap: 8px").concat(important, ";\n transition: background 0.2s").concat(important, "; font-family: inherit").concat(important, ";\n text-decoration: none").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n .ttp-btn-wa:hover { background: rgba(37,211,102,0.14)").concat(important, "; }\n\n /* Connecting Spinner (reused from old design) */\n .connecting-spinner {\n display: inline-block").concat(important, ";\n width: 16px").concat(important, "; height: 16px").concat(important, ";\n border: 2px solid rgba(255,255,255,0.3)").concat(important, ";\n border-top-color: #fff").concat(important, ";\n border-radius: 50%").concat(important, ";\n animation: ttp-spin 1s linear infinite").concat(important, ";\n margin-right: 8px").concat(important, ";\n vertical-align: middle").concat(important, ";\n }\n @keyframes ttp-spin { to { transform: rotate(360deg); } }\n\n /* \u2500\u2500 ACTIVE CALL \u2500\u2500 */\n .ttp-call-hero {\n background: transparent").concat(important, ";\n padding: 22px 20px 18px").concat(important, ";\n border-bottom: 1px solid rgba(255,255,255,0.06)").concat(important, ";\n }\n .ttp-call-topbar {\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: space-between").concat(important, ";\n margin-bottom: 18px").concat(important, ";\n }\n .ttp-rec { display: flex").concat(important, "; align-items: center").concat(important, "; gap: 7px").concat(important, "; }\n .ttp-rec-dot {\n width: 7px").concat(important, "; height: 7px").concat(important, "; border-radius: 50%").concat(important, "; background: #f87171").concat(important, ";\n animation: ttp-pulse 1s ease-in-out infinite").concat(important, ";\n }\n ").concat(this.config.useShadowDOM === false ? "\n /* Regular DOM (e.g. Shopify): theme rules often strip span/div sizing \u2014 recording dot + pulse */\n #ttp-widget-container .ttp-call-topbar .ttp-rec,\n #text-chat-panel .ttp-call-topbar .ttp-rec {\n display: flex !important;\n align-items: center !important;\n gap: 7px !important;\n flex-shrink: 0 !important;\n }\n #ttp-widget-container .ttp-rec-dot,\n #ttp-widget-container .compact-timer .ttp-rec-dot,\n #text-chat-panel .ttp-rec-dot,\n #text-chat-panel .compact-timer .ttp-rec-dot {\n display: block !important;\n flex-shrink: 0 !important;\n box-sizing: content-box !important;\n width: 7px !important;\n height: 7px !important;\n min-width: 7px !important;\n min-height: 7px !important;\n max-width: none !important;\n max-height: none !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n border-radius: 50% !important;\n background: #f87171 !important;\n background-color: #f87171 !important;\n opacity: 1 !important;\n visibility: visible !important;\n -webkit-animation: ttp-pulse 1s ease-in-out infinite !important;\n animation: ttp-pulse 1s ease-in-out infinite !important;\n }\n #ttp-widget-container .ttp-transcript-hdr .ttp-dot,\n #text-chat-panel .ttp-transcript-hdr .ttp-dot {\n display: flex !important;\n width: 3px !important;\n height: 3px !important;\n min-width: 3px !important;\n min-height: 3px !important;\n border-radius: 50% !important;\n background: ".concat(avatarGrad2, " !important;\n background-color: ").concat(avatarGrad2, " !important;\n opacity: 1 !important;\n visibility: visible !important;\n -webkit-animation: ttp-pulse 0.8s ease-in-out infinite !important;\n animation: ttp-pulse 0.8s ease-in-out infinite !important;\n }\n /* Orb waveform: same motion as shadow DOM (ttp-wave keyframes). Do not set opacity !important\n on bars \u2014 it overrides keyframe opacity and changes the look. */\n #ttp-widget-container .ttp-wave,\n #text-chat-panel .ttp-wave {\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n gap: 3px !important;\n height: 26px !important;\n min-height: 26px !important;\n width: auto !important;\n min-width: 36px !important;\n overflow: visible !important;\n flex-shrink: 0 !important;\n }\n #ttp-widget-container .ttp-wave-bar,\n #text-chat-panel .ttp-wave-bar {\n display: block !important;\n box-sizing: content-box !important;\n width: 2.5px !important;\n min-width: 2.5px !important;\n max-width: none !important;\n flex-shrink: 0 !important;\n border-radius: 3px !important;\n background: rgba(255, 255, 255, 0.9) !important;\n background-color: rgba(255, 255, 255, 0.9) !important;\n visibility: visible !important;\n transform-origin: center center !important;\n -webkit-animation: ttp-wave 0.75s ease-in-out infinite alternate !important;\n animation: ttp-wave 0.75s ease-in-out infinite alternate !important;\n }\n #ttp-widget-container .ttp-orb,\n #text-chat-panel .ttp-orb {\n overflow: visible !important;\n }\n ") : '', "\n .ttp-timer { font-size: 11px").concat(important, "; color: rgba(255,255,255,0.4)").concat(important, "; letter-spacing: 0.05em").concat(important, "; }\n .ttp-call-label { font-size: 11px").concat(important, "; color: rgba(255,255,255,0.25)").concat(important, "; }\n\n /* \u2500\u2500 ORB \u2500\u2500 */\n .ttp-orb-wrap {\n display: flex").concat(important, "; flex-direction: column").concat(important, "; align-items: center").concat(important, ";\n gap: 12px").concat(important, "; padding: 8px 0").concat(important, ";\n }\n .ttp-orb-rings {\n position: relative").concat(important, "; width: 72px").concat(important, "; height: 72px").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n }\n .ttp-ring {\n position: absolute").concat(important, "; border-radius: 50%").concat(important, ";\n border: 1.5px solid ").concat(primaryGrad1, "33;\n animation: ttp-ring 2s ease-in-out infinite").concat(important, ";\n }\n .ttp-ring-1 { inset: -8px").concat(important, "; }\n .ttp-ring-2 { inset: -16px").concat(important, "; border-width: 1px").concat(important, "; border-color: ").concat(primaryGrad1, "1a; animation-delay: 0.5s").concat(important, "; }\n .ttp-orb {\n width: 72px").concat(important, "; height: 72px").concat(important, "; border-radius: 50%").concat(important, ";\n background: linear-gradient(135deg, ").concat(primaryGrad1, ", ").concat(primaryGrad2, ");\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n animation: ttp-orb-breathe 1.4s ease-in-out infinite").concat(important, ";\n box-shadow: 0 6px 24px ").concat(primaryGrad1, "66;\n }\n .ttp-wave { display: flex").concat(important, "; align-items: center").concat(important, "; gap: 3px").concat(important, "; height: 26px").concat(important, "; }\n .ttp-wave-bar {\n width: 2.5px").concat(important, "; border-radius: 3px").concat(important, "; background: rgba(255,255,255,0.9)").concat(important, ";\n animation: ttp-wave 0.75s ease-in-out infinite alternate").concat(important, ";\n }\n .ttp-listen-label { font-size: 12px").concat(important, "; color: rgba(255,255,255,0.4)").concat(important, "; }\n\n /* \u2500\u2500 CONTROLS \u2500\u2500 */\n .ttp-controls {\n padding: 16px 20px").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, "; gap: 14px").concat(important, ";\n }\n .ttp-ctrl-btn {\n width: 42px").concat(important, "; height: 42px").concat(important, "; border-radius: 50%").concat(important, ";\n background: rgba(255,255,255,0.06)").concat(important, ";\n border: 1px solid rgba(255,255,255,0.09)").concat(important, ";\n cursor: pointer").concat(important, "; display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n color: rgba(255,255,255,0.4)").concat(important, "; transition: background 0.2s").concat(important, ";\n position: relative").concat(important, ";\n }\n .ttp-ctrl-btn:hover { background: rgba(255,255,255,0.12)").concat(important, "; }\n .ttp-ctrl-btn.muted {\n background: rgba(239, 68, 68, 0.15)").concat(important, ";\n border-color: rgba(239, 68, 68, 0.3)").concat(important, ";\n }\n .ttp-end-btn {\n width: 52px").concat(important, "; height: 52px").concat(important, "; border-radius: 50%").concat(important, ";\n background: ").concat(endCallColor, "; border: none").concat(important, "; cursor: pointer").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n color: #fff").concat(important, "; transform: rotate(135deg)").concat(important, ";\n box-shadow: 0 4px 16px ").concat(endCallColor, "59;\n transition: background 0.2s").concat(important, ";\n }\n .ttp-end-btn:hover { background: ").concat(endCallColor, "; opacity: 0.85").concat(important, "; }\n\n /* Mute/speaker icon toggle */\n .desktop-mic-icon, .desktop-speaker-icon { display: block").concat(important, "; }\n .desktop-mic-off-icon, .desktop-speaker-off-icon {\n position: absolute").concat(important, "; top: 50%").concat(important, "; left: 50%").concat(important, ";\n transform: translate(-50%, -50%)").concat(important, ";\n width: 16px").concat(important, "; height: 16px").concat(important, "; z-index: 10").concat(important, ";\n }\n\n /* \u2500\u2500 DESKTOP VOICE SECTION WRAPPER \u2500\u2500 */\n .desktop-voice-section { flex-shrink: 0").concat(important, "; }\n\n /* \u2500\u2500 COMPACT VOICE SECTION (shown when items/rooms are visible) \u2500\u2500 */\n .compact-voice-section {\n padding: 10px 14px").concat(important, ";\n background: transparent").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: space-between").concat(important, ";\n flex-shrink: 0").concat(important, ";\n border-bottom: 1px solid rgba(255,255,255,0.06)").concat(important, ";\n }\n .compact-left { display: flex").concat(important, "; align-items: center").concat(important, "; gap: 10px").concat(important, "; }\n .compact-avatar {\n width: 42px").concat(important, "; height: 42px").concat(important, "; min-width: 42px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background: linear-gradient(135deg, ").concat(avatarGrad1, ", ").concat(avatarGrad2, ");\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n .compact-orb {\n width: 32px !important; height: 32px !important;\n border-radius: 50% !important;\n }\n .compact-info { display: flex").concat(important, "; flex-direction: column").concat(important, "; gap: 2px").concat(important, "; }\n .compact-timer {\n display: flex").concat(important, "; align-items: center").concat(important, "; gap: 5px").concat(important, ";\n font-size: 11px").concat(important, "; font-weight: 600").concat(important, "; color: #e8e4f0").concat(important, ";\n }\n .compact-status {\n font-size: 10px").concat(important, "; color: rgba(255,255,255,0.4)").concat(important, ";\n }\n .compact-controls { display: flex").concat(important, "; align-items: center").concat(important, "; gap: 6px").concat(important, "; }\n .compact-control-btn {\n width: 36px").concat(important, "; height: 36px").concat(important, "; min-width: 36px").concat(important, ";\n border-radius: 50%").concat(important, "; border: none").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n cursor: pointer").concat(important, "; transition: all 0.15s").concat(important, ";\n position: relative").concat(important, ";\n }\n .compact-control-btn svg { width: 16px").concat(important, "; height: 16px").concat(important, "; }\n .compact-control-btn .desktop-mic-off-icon,\n .compact-control-btn .desktop-speaker-off-icon {\n width: 16px").concat(important, "; height: 16px").concat(important, ";\n }\n .compact-control-btn.secondary {\n background: rgba(255,255,255,0.08)").concat(important, "; color: rgba(255,255,255,0.5)").concat(important, ";\n }\n .compact-control-btn.secondary:hover {\n background: rgba(255,255,255,0.14)").concat(important, "; color: rgba(255,255,255,0.7)").concat(important, ";\n }\n .compact-control-btn.secondary.muted {\n background: rgba(239, 68, 68, 0.15)").concat(important, "; color: #ef4444").concat(important, ";\n }\n .compact-control-btn.secondary.muted .desktop-mic-icon,\n .compact-control-btn.secondary.muted .desktop-speaker-icon {\n stroke: #ef4444").concat(important, ";\n }\n .compact-control-btn.secondary.muted .desktop-mic-off-icon,\n .compact-control-btn.secondary.muted .desktop-speaker-off-icon {\n width: 16px").concat(important, "; height: 16px").concat(important, ";\n }\n .compact-control-btn.danger {\n width: 40px").concat(important, "; height: 40px").concat(important, "; min-width: 40px").concat(important, ";\n background: #ef4444").concat(important, "; color: #fff").concat(important, ";\n box-shadow: 0 3px 10px rgba(239,68,68,0.35)").concat(important, ";\n }\n .compact-control-btn.danger:hover {\n transform: scale(1.05)").concat(important, ";\n box-shadow: 0 4px 14px rgba(239,68,68,0.45)").concat(important, ";\n }\n .compact-control-btn.danger svg { width: 18px").concat(important, "; height: 18px").concat(important, "; overflow: visible").concat(important, "; }\n\n /* \u2500\u2500 TRANSCRIPT \u2500\u2500 */\n .ttp-transcript {\n margin: 0 16px 16px").concat(important, ";\n padding: 12px 14px").concat(important, ";\n background: ").concat(primaryGrad1, "24;\n border: 1px solid ").concat(primaryGrad1, "4d;\n border-radius: 12px").concat(important, ";\n }\n .ttp-transcript-hdr {\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: space-between").concat(important, ";\n margin-bottom: 7px").concat(important, ";\n }\n .ttp-live-label {\n font-size: 10px").concat(important, "; color: ").concat(primaryGrad2, ";\n text-transform: uppercase").concat(important, "; letter-spacing: 0.1em").concat(important, ";\n font-weight: 600").concat(important, ";\n }\n .ttp-toggle-text {\n font-size: 10px").concat(important, "; color: rgba(255,255,255,0.35)").concat(important, ";\n cursor: pointer").concat(important, "; margin-left: auto").concat(important, "; margin-right: 8px").concat(important, ";\n transition: color 0.2s").concat(important, ";\n }\n .ttp-toggle-text:hover { color: ").concat(primaryGrad2, "; }\n .ttp-transcript-hdr { cursor: pointer").concat(important, "; }\n .ttp-dots { display: flex").concat(important, "; gap: 3px").concat(important, "; align-items: center").concat(important, "; }\n .ttp-dot {\n width: 3px").concat(important, "; height: 3px").concat(important, "; border-radius: 50%").concat(important, "; background: ").concat(primaryGrad2, ";\n animation: ttp-pulse 0.8s ease-in-out infinite").concat(important, ";\n }\n .ttp-dot:nth-child(2) { animation-delay: 0.2s").concat(important, "; }\n .ttp-dot:nth-child(3) { animation-delay: 0.4s").concat(important, "; }\n .ttp-transcript-text {\n font-size: 12px").concat(important, "; color: #e2e0f0").concat(important, "; line-height: 1.55").concat(important, ";\n unicode-bidi: isolate").concat(important, ";\n text-align: start").concat(important, ";\n }\n .ttp-transcript-text .name { color: #c4b5fd").concat(important, "; font-weight: 600").concat(important, "; }\n .ttp-cursor {\n display: inline-block").concat(important, "; width: 2px").concat(important, "; height: 12px").concat(important, ";\n background: ").concat(primaryGrad2, "; vertical-align: middle").concat(important, "; margin-inline-start: 2px").concat(important, ";\n animation: ttp-blink 0.9s infinite").concat(important, ";\n }\n\n /* Transcript collapsed/expanded state */\n .live-transcript-collapsed { display: block").concat(important, "; }\n .conversation-history { display: none").concat(important, "; }\n\n .ttp-transcript.expanded {\n flex: 1").concat(important, ";\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n min-height: 0").concat(important, ";\n overflow: hidden").concat(important, ";\n }\n .ttp-transcript.expanded .live-transcript-collapsed { display: none").concat(important, "; }\n .ttp-transcript.expanded .conversation-history {\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n flex: 1").concat(important, ";\n min-height: 0").concat(important, ";\n overflow-y: auto").concat(important, ";\n max-height: 260px").concat(important, ";\n scrollbar-width: thin").concat(important, ";\n scrollbar-color: ").concat(primaryGrad1, "4d transparent;\n }\n .ttp-transcript.expanded .conversation-history::-webkit-scrollbar { width: 4px").concat(important, "; }\n .ttp-transcript.expanded .conversation-history::-webkit-scrollbar-track { background: transparent").concat(important, "; }\n .ttp-transcript.expanded .conversation-history::-webkit-scrollbar-thumb {\n background: ").concat(primaryGrad1, "4d; border-radius: 2px").concat(important, ";\n }\n\n /* Message rows in history */\n .conversation-messages { display: flex").concat(important, "; flex-direction: column").concat(important, "; gap: 8px").concat(important, "; padding-bottom: 4px").concat(important, "; }\n .message-row {\n display: flex").concat(important, "; align-items: flex-start").concat(important, "; gap: 8px").concat(important, ";\n animation: ttp-msg-in 0.2s ease-out").concat(important, ";\n }\n .message-row.user { flex-direction: row-reverse").concat(important, "; }\n .message-avatar {\n width: 26px").concat(important, "; height: 26px").concat(important, "; min-width: 26px").concat(important, ";\n border-radius: 50%").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n font-size: 10px").concat(important, "; font-weight: 600").concat(important, "; flex-shrink: 0").concat(important, ";\n }\n .message-avatar.user {\n background: rgba(255,255,255,0.12)").concat(important, "; color: rgba(255,255,255,0.6)").concat(important, ";\n }\n .message-avatar.assistant {\n background: linear-gradient(135deg, ").concat(avatarGrad1, ", ").concat(avatarGrad2, ");\n }\n .message-avatar .orb {\n width: 12px").concat(important, "; height: 12px").concat(important, "; border-radius: 50%").concat(important, ";\n background: rgba(255,255,255,0.9)").concat(important, ";\n }\n .message-bubble {\n padding: 8px 12px").concat(important, ";\n border-radius: 12px").concat(important, ";\n font-size: 12px").concat(important, "; line-height: 1.5").concat(important, ";\n max-width: 80%").concat(important, "; word-wrap: break-word").concat(important, ";\n unicode-bidi: plaintext").concat(important, ";\n text-align: start").concat(important, ";\n }\n .message-row.assistant .message-bubble {\n background: rgba(255,255,255,0.08)").concat(important, ";\n color: #e2e0f0").concat(important, ";\n border-bottom-left-radius: 4px").concat(important, ";\n }\n .message-row.user .message-bubble {\n background: ").concat(primaryGrad1, "40;\n color: #e8e4f0").concat(important, ";\n border-bottom-right-radius: 4px").concat(important, ";\n }\n .live-message-row {\n display: flex").concat(important, "; align-items: flex-start").concat(important, "; gap: 8px").concat(important, ";\n margin-top: 6px").concat(important, ";\n }\n .live-message-row .message-bubble {\n position: relative").concat(important, ";\n padding: 14px 12px 8px").concat(important, ";\n border-radius: 12px").concat(important, ";\n font-size: 12px").concat(important, "; line-height: 1.5").concat(important, ";\n background: rgba(255,255,255,0.08)").concat(important, ";\n color: #e2e0f0").concat(important, ";\n max-width: 80%").concat(important, "; word-wrap: break-word").concat(important, ";\n }\n .live-message-row .live-badge {\n position: absolute").concat(important, "; top: 0").concat(important, "; left: 10px").concat(important, ";\n transform: translateY(-50%)").concat(important, ";\n background: ").concat(primaryGrad1, "; color: #fff").concat(important, ";\n font-size: 8px").concat(important, "; font-weight: 700").concat(important, ";\n padding: 2px 6px").concat(important, "; border-radius: 4px").concat(important, ";\n text-transform: uppercase").concat(important, "; letter-spacing: 0.05em").concat(important, ";\n }\n .typing-cursor {\n display: inline-block").concat(important, "; width: 2px").concat(important, "; height: 12px").concat(important, ";\n background: ").concat(primaryGrad2, "; vertical-align: middle").concat(important, "; margin-inline-start: 2px").concat(important, ";\n animation: ttp-blink 0.9s infinite").concat(important, ";\n }\n @keyframes ttp-msg-in {\n from { opacity: 0; transform: translateY(4px); }\n to { opacity: 1; transform: translateY(0); }\n }\n\n /* \u2500\u2500 TYPE ROW \u2500\u2500 */\n .ttp-type-row { display: flex").concat(important, "; gap: 8px").concat(important, "; padding: 0 16px 16px").concat(important, "; flex-wrap: wrap").concat(important, "; }\n .ttp-input {\n flex: 1").concat(important, "; padding: 9px 12px").concat(important, ";\n background: rgba(255,255,255,0.05)").concat(important, ";\n border: 1px solid rgba(255,255,255,0.09)").concat(important, ";\n border-radius: 10px").concat(important, "; color: rgba(255,255,255,0.6)").concat(important, ";\n font-size: 12px").concat(important, "; outline: none").concat(important, "; font-family: inherit").concat(important, ";\n transition: border-color 0.2s").concat(important, ";\n text-align: start").concat(important, ";\n }\n .ttp-input::placeholder { color: rgba(255,255,255,0.25)").concat(important, "; }\n .ttp-input:focus { border-color: ").concat(primaryGrad1, "80; }\n .ttp-send-btn {\n width: 34px").concat(important, "; height: 34px").concat(important, "; border-radius: 9px").concat(important, ";\n background: ").concat(sendBtnColor, "; border: none").concat(important, "; cursor: pointer").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, "; transition: background 0.2s").concat(important, ";\n }\n .ttp-send-btn:hover { background: ").concat(sendBtnColor, "; opacity: 0.85").concat(important, "; }\n\n /* \u2500\u2500 KEYFRAMES \u2500\u2500 */\n @keyframes ttp-pulse { 0%,100%{opacity:1} 50%{opacity:.3} }\n @keyframes ttp-blink { 0%,49%{opacity:1} 50%,100%{opacity:0} }\n @keyframes ttp-ring { 0%,100%{transform:scale(1);opacity:.6} 50%{transform:scale(1.22);opacity:0} }\n @keyframes ttp-orb-breathe { 0%,100%{transform:scale(1)} 50%{transform:scale(1.05)} }\n @keyframes ttp-wave { from{transform:scaleY(.15);opacity:.3} to{transform:scaleY(1);opacity:.9} }\n @keyframes ttp-pill-pulse { 0%,100%{box-shadow:0 0 0 0 ").concat(primaryGrad1, "80} 60%{box-shadow:0 0 0 7px ").concat(primaryGrad1, "00} }\n\n /* Mobile Voice Call UI - Shared styles (also used in generateMobileCSS) */\n ").concat(this._getSharedMobileCSS(important), "\n\n ");
36090
36336
  }
36091
36337
 
36092
36338
  /**
@@ -36096,7 +36342,18 @@ var Styles = /*#__PURE__*/function () {
36096
36342
  }, {
36097
36343
  key: "_getSharedMobileCSS",
36098
36344
  value: function _getSharedMobileCSS(important) {
36099
- return "\n .mobile-duration-dot {\ndisplay: block !important;\n width: 6px".concat(important, ";\n height: 6px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background-color: #ef4444").concat(important, ";\n animation: mobilePulse 1.5s ease-in-out infinite").concat(important, ";\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").concat(important, ";\n flex-direction: column").concat(important, ";\n gap: 10px").concat(important, ";\n padding: 14px").concat(important, ";\n position: relative").concat(important, ";\n background: linear-gradient(135deg, #7c3aed 0%, #a855f7 50%, #c084fc 100%)").concat(important, ";\n border-radius: 24px 24px 0 0").concat(important, ";\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)").concat(important, ";\n width: 100% !important;\n max-width: 100% !important;\n pointer-events: auto").concat(important, ";\n overflow: hidden !important;\n margin: 0 !important;\n }\n\n .mobile-top-row {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: space-between").concat(important, ";\n position: relative").concat(important, ";\n }\n\n .mobile-status-indicator {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 5px").concat(important, ";\n min-width: 85px").concat(important, ";\n }\n\n .mobile-status-dot {\ndisplay: block !important;\n width: 7px").concat(important, ";\n height: 7px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background-color: #22c55e").concat(important, ";\n box-shadow: 0 0 8px #22c55e").concat(important, ";\n transition: all 0.3s ease").concat(important, ";\n }\n\n .mobile-status-text {\n font-size: 11px").concat(important, ";\n font-weight: 700").concat(important, ";\n color: rgba(255,255,255,0.95)").concat(important, ";\n text-transform: uppercase").concat(important, ";\n letter-spacing: 0.3px").concat(important, ";\n }\n\n .mobile-waveform-center {\n position: absolute !important;\n left: 50% !important;\n transform: translateX(-50%) !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n gap: 3px !important;\n height: 24px !important;\n visibility: visible !important;\n }\n\n .mobile-waveform-bars {\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n gap: 3px !important;\n }\n\n .mobile-waveform-bar {\n display: block !important;\n width: 4px !important;\n min-height: 4px !important;\n background-color: #fff !important;\n border-radius: 2px !important;\n transition: height 0.12s ease-out !important;\n box-shadow: 0 0 8px rgba(255,255,255,0.5) !important;\n visibility: visible !important;\n }\n\n .mobile-controls {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 6px").concat(important, ";\n pointer-events: auto").concat(important, ";\n touch-action: manipulation").concat(important, ";\n position: relative").concat(important, ";\n z-index: 120").concat(important, ";\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").concat(important, ";\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 .mobile-mic-icon,\n .mobile-control-btn .mobile-speaker-icon {\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-control-btn .mobile-mic-off-icon,\n .mobile-control-btn .mobile-speaker-off-icon {\n position: absolute").concat(important, ";\n top: 50%").concat(important, ";\n left: 50%").concat(important, ";\n transform: translate(-50%, -50%)").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-control-btn:not(.muted) .mobile-mic-off-icon,\n .mobile-control-btn:not(.muted) .mobile-speaker-off-icon {\n display: none !important;\n visibility: hidden !important;\n opacity: 0 !important;\n }\n\n .mobile-control-btn.muted .mobile-mic-icon,\n .mobile-control-btn.muted .mobile-speaker-icon {\n display: none !important;\n visibility: hidden !important;\n opacity: 0 !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 visibility: visible !important;\n opacity: 1 !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)").concat(important, ";\n transition: all 0.2s ease").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-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/Shopify 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 pointer-events: auto !important;\n touch-action: manipulation !important;\n -webkit-appearance: none !important;\n appearance: none !important;\n text-decoration: none !important;\n line-height: 1 !important;\n font-size: 0 !important;\n letter-spacing: 0 !important;\n text-indent: 0 !important;\n text-transform: none !important;\n color: transparent !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 .mobile-mic-icon,\n #mobileMuteBtn.mobile-control-btn .mobile-mic-off-icon,\n #mobileSpeakerBtn.mobile-control-btn .mobile-speaker-icon,\n #mobileSpeakerBtn.mobile-control-btn .mobile-speaker-off-icon,\n #mobileEndCallBtn.mobile-end-call-btn svg {\n width: 15px !important;\n height: 15px !important;\n max-width: 15px !important;\n max-height: 15px !important;\n margin: 0 !important;\n padding: 0 !important;\n pointer-events: none !important;\n overflow: visible !important;\n }\n\n #mobile-voice-call-bar-container svg path,\n #mobile-voice-call-bar-container svg line,\n #mobile-voice-call-bar-container svg polygon,\n #mobile-voice-call-bar-container svg circle {\n pointer-events: none !important;\n vector-effect: none !important;\n }\n\n .mobile-end-call-btn:hover {\n transform: scale(1.05)").concat(important, ";\n }\n\n .mobile-transcript-row {\n width: 100%").concat(important, ";\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n gap: 6px").concat(important, ";\n padding: 10px 12px").concat(important, ";\n background: rgba(255,255,255,0.18)").concat(important, ";\n border-radius: 14px").concat(important, ";\n border: none").concat(important, ";\n cursor: pointer").concat(important, ";\n text-align: left").concat(important, ";\n backdrop-filter: blur(4px)").concat(important, ";\n transition: background 0.2s ease").concat(important, ";\n pointer-events: auto !important;\n position: relative !important;\n z-index: 100 !important;\n }\n\n .mobile-transcript-row:hover {\n background: rgba(255,255,255,0.25)").concat(important, ";\n }\n\n .mobile-transcript-text {\n margin: 0").concat(important, ";\n font-size: 13px").concat(important, ";\n color: #fff").concat(important, ";\n line-height: 1.4").concat(important, ";\n font-weight: 500").concat(important, ";\n display: -webkit-box !important;\n -webkit-line-clamp: 2 !important;\n -webkit-box-orient: vertical !important;\n overflow: hidden !important;\n min-height: 2.8em !important;\n }\n\n .mobile-transcript-footer {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: space-between").concat(important, ";\n }\n\n .mobile-expand-hint {\n font-size: 10px").concat(important, ";\n color: rgba(255,255,255,0.6)").concat(important, ";\n text-transform: uppercase").concat(important, ";\n letter-spacing: 0.5px").concat(important, ";\n font-weight: 600").concat(important, ";\n }\n\n .mobile-transcript-overlay {\n position: fixed").concat(important, ";\n top: 0").concat(important, ";\n left: 0").concat(important, ";\n right: 0").concat(important, ";\n bottom: 0").concat(important, ";\n background-color: rgba(0,0,0,0.6)").concat(important, ";\n display: flex").concat(important, ";\n align-items: flex-end").concat(important, ";\n padding: 12px").concat(important, ";\n z-index: 2147483647").concat(important, ";\n pointer-events: auto").concat(important, ";\n }\n\n .mobile-expanded-transcript {\n width: 100%").concat(important, ";\n max-height: 75%").concat(important, ";\n background: #fff").concat(important, ";\n border-radius: 24px 24px 16px 16px").concat(important, ";\n overflow: hidden").concat(important, ";\n box-shadow: 0 -8px 40px rgba(0,0,0,0.3)").concat(important, ";\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n }\n\n .mobile-transcript-header {\n display: flex").concat(important, ";\n justify-content: space-between").concat(important, ";\n align-items: center").concat(important, ";\n padding: 14px 16px").concat(important, ";\n background: linear-gradient(135deg, #7c3aed 0%, #a855f7 100%)").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n\n .mobile-header-left {\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n gap: 2px").concat(important, ";\n }\n\n .mobile-header-status {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 6px").concat(important, ";\n }\n\n .mobile-header-status-dot {\ndisplay: block !important;\n width: 6px").concat(important, ";\n height: 6px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background-color: #22c55e").concat(important, ";\n box-shadow: 0 0 6px #22c55e").concat(important, ";\n }\n\n .mobile-header-status-text {\n font-size: 10px").concat(important, ";\n font-weight: 700").concat(important, ";\n color: rgba(255,255,255,0.9)").concat(important, ";\n text-transform: uppercase").concat(important, ";\n letter-spacing: 0.5px").concat(important, ";\n }\n\n .mobile-header-duration {\n font-size: 10px").concat(important, ";\n font-weight: 600").concat(important, ";\n color: rgba(255,255,255,0.7)").concat(important, ";\n margin-left: 8px").concat(important, ";\n }\n\n .mobile-transcript-label {\n font-size: 11px").concat(important, ";\n font-weight: 800").concat(important, ";\n color: rgba(255,255,255,0.7)").concat(important, ";\n letter-spacing: 1px").concat(important, ";\n }\n\n .mobile-close-transcript-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 border-radius: 50%").concat(important, ";\n border: none").concat(important, ";\n background: rgba(255,255,255,0.2)").concat(important, ";\n color: #fff").concat(important, ";\n cursor: pointer").concat(important, ";\n }\n\n .mobile-close-transcript-btn:hover {\n background: rgba(255,255,255,0.3)").concat(important, ";\n }\n\n .mobile-messages-container {\n flex: 1").concat(important, ";\n padding: 16px").concat(important, ";\n overflow-y: auto").concat(important, ";\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n gap: 12px").concat(important, ";\n }\n\n .mobile-message-bubble {\n max-width: 85%").concat(important, ";\n padding: 12px 16px").concat(important, ";\n border-radius: 18px").concat(important, ";\n font-size: 14px").concat(important, ";\n line-height: 1.5").concat(important, ";\n word-wrap: break-word").concat(important, ";\n }\n\n .mobile-message-bubble.assistant {\n align-self: flex-start").concat(important, ";\n background-color: #f3f4f6").concat(important, ";\n color: #374151").concat(important, ";\n border-bottom-left-radius: 4px").concat(important, ";\n }\n\n .mobile-message-bubble.user {\n align-self: flex-end").concat(important, ";\n background: linear-gradient(135deg, #7c3aed 0%, #a855f7 100%)").concat(important, ";\n color: #fff").concat(important, ";\n border-bottom-right-radius: 4px").concat(important, ";\n }\n\n .mobile-input-area {\n padding: 12px 16px 16px").concat(important, ";\n border-top: 1px solid #e5e7eb").concat(important, ";\n background: #f9fafb").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n\n .mobile-input-wrapper {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 8px").concat(important, ";\n padding: 4px 4px 4px 16px").concat(important, ";\n background: #fff").concat(important, ";\n border-radius: 24px").concat(important, ";\n border: 2px solid #e5e7eb").concat(important, ";\n }\n\n .mobile-text-input {\n flex: 1").concat(important, ";\n border: none").concat(important, ";\n outline: none").concat(important, ";\n font-size: 14px").concat(important, ";\n color: #374151").concat(important, ";\n background: transparent").concat(important, ";\n padding: 10px 0").concat(important, ";\n }\n\n .mobile-text-input::placeholder {\n color: #9ca3af").concat(important, ";\n }\n\n .mobile-send-btn {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n width: 40px").concat(important, ";\n height: 40px").concat(important, ";\n border-radius: 50%").concat(important, ";\n border: none").concat(important, ";\n background: linear-gradient(135deg, #7c3aed 0%, #a855f7 100%)").concat(important, ";\n color: #fff").concat(important, ";\n cursor: pointer").concat(important, ";\n transition: all 0.2s ease").concat(important, ";\n }\n\n .mobile-send-btn:hover:not(:disabled) {\n transform: scale(1.05)").concat(important, ";\n }\n\n .mobile-send-btn:disabled {\n opacity: 0.5").concat(important, ";\n cursor: not-allowed").concat(important, ";\n }\n\n .mobile-input-hint {\n margin: 8px 0 0").concat(important, ";\n font-size: 11px").concat(important, ";\n color: #9ca3af").concat(important, ";\n text-align: center").concat(important, ";\n transition: color 0.2s ease").concat(important, ";\n }\n\n /* Mobile text input status states */\n .mobile-input-hint--sending {\n color: #666").concat(important, ";\n }\n\n .mobile-input-hint--success {\n color: #28a745").concat(important, ";\n }\n\n .mobile-input-hint--queued {\n color: #ffc107").concat(important, ";\n }\n\n .mobile-input-hint--error {\n color: #dc3545").concat(important, ";\n }\n\n /* Disabled mobile input styling */\n #mobileTextInput:disabled {\n background-color: #f5f5f5").concat(important, ";\n cursor: not-allowed").concat(important, ";\n }\n\n #mobileSendBtn:disabled {\n opacity: 0.5").concat(important, ";\n cursor: not-allowed").concat(important, ";\n }\n ");
36345
+ var c = this.config;
36346
+ var avatarGrad1 = c.avatarGradient1 || '#6d56f5';
36347
+ var avatarGrad2 = c.avatarGradient2 || '#a78bfa';
36348
+ /* Match .ttp-mobile-landing / mobile FAB (TTPChatWidget pillGradient) — not desktop hero/call surface */
36349
+ var mobileLandingSurface = c.pillGradient || 'linear-gradient(135deg, #581c87, #312e81, #1e1b4b)';
36350
+ /* Primary = Start Call CTA — user bubbles + send only */
36351
+ var primaryGrad1 = c.primaryBtnGradient1 || c.startCallButtonColor || '#6d56f5';
36352
+ var primaryGrad2 = c.primaryBtnGradient2 || c.startCallButtonColor || '#9d8df8';
36353
+ var sendBtnColor = c.sendButtonColor || primaryGrad1;
36354
+ var endCallColor = c.endCallButtonColor || '#ef4444';
36355
+ var mobileAccentGradient = "linear-gradient(135deg, ".concat(sendBtnColor, ", ").concat(primaryGrad2, ")");
36356
+ return "\n /* Mobile voice idle: optional header image replaces \uD83E\uDD16 */\n .mobile-voice-interface #voiceIdleState .voice-avatar {\n width: 80px".concat(important, ";\n height: 80px").concat(important, ";\n margin: 12px auto 16px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background: linear-gradient(135deg, ").concat(avatarGrad1, ", ").concat(avatarGrad2, ")").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n font-size: 40px").concat(important, ";\n line-height: 1").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n .mobile-voice-interface #voiceIdleState .voice-avatar.voice-avatar--image {\n padding: 0").concat(important, ";\n overflow: hidden").concat(important, ";\n }\n .mobile-voice-interface #voiceIdleState .voice-avatar-img {\n width: 100%").concat(important, ";\n height: 100%").concat(important, ";\n object-fit: cover").concat(important, ";\n border-radius: 50%").concat(important, ";\n display: block").concat(important, ";\n }\n\n /* Idle hero copy: light text on dark / gradient panels (host themes often force dark body color) */\n .mobile-voice-interface #voiceIdleState .voice-status {\n text-align: center").concat(important, ";\n }\n .mobile-voice-interface #voiceIdleState .voice-status-title {\n color: rgba(255,255,255,0.96)").concat(important, ";\n }\n .mobile-voice-interface #voiceIdleState .voice-status-subtitle {\n color: rgba(255,255,255,0.78)").concat(important, ";\n }\n\n .mobile-duration-dot {\ndisplay: block !important;\n width: 6px").concat(important, ";\n height: 6px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background-color: #ef4444").concat(important, ";\n animation: mobilePulse 1.5s ease-in-out infinite").concat(important, ";\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").concat(important, ";\n flex-direction: column").concat(important, ";\n gap: 10px").concat(important, ";\n padding: 14px").concat(important, ";\n position: relative").concat(important, ";\n background: ").concat(mobileLandingSurface).concat(important, ";\n border-radius: 24px 24px 0 0").concat(important, ";\n box-shadow:\n 0 -8px 32px rgba(0, 0, 0, 0.3),\n 0 -2px 8px rgba(0, 0, 0, 0.35),\n inset 0 1px 0 rgba(255, 255, 255, 0.1)").concat(important, ";\n width: 100% !important;\n max-width: 100% !important;\n pointer-events: auto").concat(important, ";\n overflow: hidden !important;\n margin: 0 !important;\n }\n\n .mobile-top-row {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: space-between").concat(important, ";\n position: relative").concat(important, ";\n }\n\n .mobile-status-indicator {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 5px").concat(important, ";\n min-width: 85px").concat(important, ";\n }\n\n .mobile-status-dot {\ndisplay: block !important;\n width: 7px").concat(important, ";\n height: 7px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background-color: #22c55e").concat(important, ";\n box-shadow: 0 0 8px #22c55e").concat(important, ";\n transition: all 0.3s ease").concat(important, ";\n }\n\n .mobile-status-text {\n font-size: 11px").concat(important, ";\n font-weight: 700").concat(important, ";\n color: rgba(255,255,255,0.95)").concat(important, ";\n text-transform: uppercase").concat(important, ";\n letter-spacing: 0.3px").concat(important, ";\n }\n\n .mobile-waveform-center {\n position: absolute !important;\n left: 50% !important;\n transform: translateX(-50%) !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n gap: 3px !important;\n height: 24px !important;\n visibility: visible !important;\n }\n\n .mobile-waveform-bars {\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n gap: 3px !important;\n }\n\n .mobile-waveform-bar {\n display: block !important;\n width: 4px !important;\n min-height: 4px !important;\n background-color: #fff !important;\n border-radius: 2px !important;\n transition: height 0.12s ease-out !important;\n box-shadow: 0 0 8px rgba(255,255,255,0.5) !important;\n visibility: visible !important;\n }\n\n .mobile-controls {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 6px").concat(important, ";\n pointer-events: auto").concat(important, ";\n touch-action: manipulation").concat(important, ";\n position: relative").concat(important, ";\n z-index: 120").concat(important, ";\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").concat(important, ";\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 .mobile-mic-icon,\n .mobile-control-btn .mobile-speaker-icon {\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-control-btn .mobile-mic-off-icon,\n .mobile-control-btn .mobile-speaker-off-icon {\n position: absolute").concat(important, ";\n top: 50%").concat(important, ";\n left: 50%").concat(important, ";\n transform: translate(-50%, -50%)").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-control-btn:not(.muted) .mobile-mic-off-icon,\n .mobile-control-btn:not(.muted) .mobile-speaker-off-icon {\n display: none !important;\n visibility: hidden !important;\n opacity: 0 !important;\n }\n\n .mobile-control-btn.muted .mobile-mic-icon,\n .mobile-control-btn.muted .mobile-speaker-icon {\n display: none !important;\n visibility: hidden !important;\n opacity: 0 !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 visibility: visible !important;\n opacity: 1 !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: ").concat(endCallColor).concat(important, ";\n box-shadow: 0 4px 14px ").concat(endCallColor, "80").concat(important, ";\n transition: all 0.2s ease").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-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/Shopify 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 pointer-events: auto !important;\n touch-action: manipulation !important;\n -webkit-appearance: none !important;\n appearance: none !important;\n text-decoration: none !important;\n line-height: 1 !important;\n font-size: 0 !important;\n letter-spacing: 0 !important;\n text-indent: 0 !important;\n text-transform: none !important;\n color: transparent !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 .mobile-mic-icon,\n #mobileMuteBtn.mobile-control-btn .mobile-mic-off-icon,\n #mobileSpeakerBtn.mobile-control-btn .mobile-speaker-icon,\n #mobileSpeakerBtn.mobile-control-btn .mobile-speaker-off-icon,\n #mobileEndCallBtn.mobile-end-call-btn svg {\n width: 15px !important;\n height: 15px !important;\n max-width: 15px !important;\n max-height: 15px !important;\n margin: 0 !important;\n padding: 0 !important;\n pointer-events: none !important;\n overflow: visible !important;\n }\n\n #mobile-voice-call-bar-container svg path,\n #mobile-voice-call-bar-container svg line,\n #mobile-voice-call-bar-container svg polygon,\n #mobile-voice-call-bar-container svg circle {\n pointer-events: none !important;\n vector-effect: none !important;\n }\n\n .mobile-end-call-btn:hover {\n transform: scale(1.05)").concat(important, ";\n }\n\n .mobile-transcript-row {\n width: 100%").concat(important, ";\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n gap: 6px").concat(important, ";\n padding: 10px 12px").concat(important, ";\n background: rgba(255,255,255,0.18)").concat(important, ";\n border-radius: 14px").concat(important, ";\n border: none").concat(important, ";\n cursor: pointer").concat(important, ";\n text-align: start").concat(important, ";\n backdrop-filter: blur(4px)").concat(important, ";\n transition: background 0.2s ease").concat(important, ";\n pointer-events: auto !important;\n position: relative !important;\n z-index: 100 !important;\n }\n\n .mobile-transcript-row:hover {\n background: rgba(255,255,255,0.25)").concat(important, ";\n }\n\n .mobile-transcript-text {\n margin: 0").concat(important, ";\n font-size: 13px").concat(important, ";\n color: #fff").concat(important, ";\n line-height: 1.4").concat(important, ";\n font-weight: 500").concat(important, ";\n unicode-bidi: plaintext").concat(important, ";\n text-align: start").concat(important, ";\n display: -webkit-box !important;\n -webkit-line-clamp: 2 !important;\n -webkit-box-orient: vertical !important;\n overflow: hidden !important;\n min-height: 2.8em !important;\n }\n\n .mobile-transcript-footer {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: space-between").concat(important, ";\n }\n\n .mobile-expand-hint {\n font-size: 10px").concat(important, ";\n color: rgba(255,255,255,0.6)").concat(important, ";\n text-transform: uppercase").concat(important, ";\n letter-spacing: 0.5px").concat(important, ";\n font-weight: 600").concat(important, ";\n }\n\n /* Base: hidden. Inline display:none loses to display:flex!important \u2014 use modifier for open state */\n .mobile-transcript-overlay {\n position: fixed").concat(important, ";\n top: 0").concat(important, ";\n left: 0").concat(important, ";\n right: 0").concat(important, ";\n bottom: 0").concat(important, ";\n background-color: rgba(0,0,0,0.6)").concat(important, ";\n display: none").concat(important, ";\n padding: 12px").concat(important, ";\n z-index: 2147483647").concat(important, ";\n pointer-events: auto").concat(important, ";\n }\n\n .mobile-transcript-overlay.mobile-transcript-overlay--open {\n display: flex").concat(important, ";\n align-items: flex-end").concat(important, ";\n }\n\n .mobile-expanded-transcript {\n width: 100%").concat(important, ";\n max-height: 75%").concat(important, ";\n background: #fff").concat(important, ";\n border-radius: 24px 24px 16px 16px").concat(important, ";\n overflow: hidden").concat(important, ";\n box-shadow: 0 -8px 40px rgba(0,0,0,0.3)").concat(important, ";\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n }\n\n .mobile-transcript-header {\n display: flex").concat(important, ";\n justify-content: space-between").concat(important, ";\n align-items: center").concat(important, ";\n padding: 14px 16px").concat(important, ";\n background: ").concat(mobileLandingSurface).concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n\n .mobile-header-left {\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n gap: 2px").concat(important, ";\n }\n\n .mobile-header-status {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 6px").concat(important, ";\n }\n\n .mobile-header-status-dot {\ndisplay: block !important;\n width: 6px").concat(important, ";\n height: 6px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background-color: #22c55e").concat(important, ";\n box-shadow: 0 0 6px #22c55e").concat(important, ";\n }\n\n .mobile-header-status-text {\n font-size: 10px").concat(important, ";\n font-weight: 700").concat(important, ";\n color: rgba(255,255,255,0.9)").concat(important, ";\n text-transform: uppercase").concat(important, ";\n letter-spacing: 0.5px").concat(important, ";\n }\n\n .mobile-header-duration {\n font-size: 10px").concat(important, ";\n font-weight: 600").concat(important, ";\n color: rgba(255,255,255,0.7)").concat(important, ";\n margin-left: 8px").concat(important, ";\n }\n\n .mobile-transcript-label {\n font-size: 11px").concat(important, ";\n font-weight: 800").concat(important, ";\n color: rgba(255,255,255,0.7)").concat(important, ";\n letter-spacing: 1px").concat(important, ";\n }\n\n .mobile-close-transcript-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 border-radius: 50%").concat(important, ";\n border: none").concat(important, ";\n background: rgba(255,255,255,0.2)").concat(important, ";\n color: #fff").concat(important, ";\n cursor: pointer").concat(important, ";\n }\n\n .mobile-close-transcript-btn:hover {\n background: rgba(255,255,255,0.3)").concat(important, ";\n }\n\n .mobile-messages-container {\n flex: 1").concat(important, ";\n padding: 16px").concat(important, ";\n overflow-y: auto").concat(important, ";\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n gap: 12px").concat(important, ";\n }\n\n .mobile-message-bubble {\n max-width: 85%").concat(important, ";\n padding: 12px 16px").concat(important, ";\n border-radius: 18px").concat(important, ";\n font-size: 14px").concat(important, ";\n line-height: 1.5").concat(important, ";\n word-wrap: break-word").concat(important, ";\n unicode-bidi: plaintext").concat(important, ";\n text-align: start").concat(important, ";\n }\n\n .mobile-message-bubble.assistant {\n align-self: flex-start").concat(important, ";\n background-color: #f3f4f6").concat(important, ";\n color: #374151").concat(important, ";\n border-bottom-left-radius: 4px").concat(important, ";\n }\n\n .mobile-message-bubble.user {\n align-self: flex-end").concat(important, ";\n background: ").concat(mobileAccentGradient).concat(important, ";\n color: #fff").concat(important, ";\n border-bottom-right-radius: 4px").concat(important, ";\n }\n\n .mobile-input-area {\n padding: 12px 16px 16px").concat(important, ";\n border-top: 1px solid #e5e7eb").concat(important, ";\n background: #f9fafb").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n\n .mobile-input-wrapper {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 8px").concat(important, ";\n padding: 4px 4px 4px 16px").concat(important, ";\n background: #fff").concat(important, ";\n border-radius: 24px").concat(important, ";\n border: 2px solid #e5e7eb").concat(important, ";\n }\n\n .mobile-text-input {\n flex: 1").concat(important, ";\n border: none").concat(important, ";\n outline: none").concat(important, ";\n font-size: 14px").concat(important, ";\n color: #374151").concat(important, ";\n background: transparent").concat(important, ";\n padding: 10px 0").concat(important, ";\n text-align: start").concat(important, ";\n }\n\n .mobile-text-input::placeholder {\n color: #9ca3af").concat(important, ";\n }\n\n .mobile-send-btn {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n width: 40px").concat(important, ";\n height: 40px").concat(important, ";\n border-radius: 50%").concat(important, ";\n border: none").concat(important, ";\n background: ").concat(mobileAccentGradient).concat(important, ";\n color: #fff").concat(important, ";\n cursor: pointer").concat(important, ";\n transition: all 0.2s ease").concat(important, ";\n }\n\n .mobile-send-btn:hover:not(:disabled) {\n transform: scale(1.05)").concat(important, ";\n }\n\n .mobile-send-btn:disabled {\n opacity: 0.5").concat(important, ";\n cursor: not-allowed").concat(important, ";\n }\n\n .mobile-input-hint {\n margin: 8px 0 0").concat(important, ";\n font-size: 11px").concat(important, ";\n color: #9ca3af").concat(important, ";\n text-align: center").concat(important, ";\n transition: color 0.2s ease").concat(important, ";\n }\n\n /* Mobile text input status states */\n .mobile-input-hint--sending {\n color: #666").concat(important, ";\n }\n\n .mobile-input-hint--success {\n color: #28a745").concat(important, ";\n }\n\n .mobile-input-hint--queued {\n color: #ffc107").concat(important, ";\n }\n\n .mobile-input-hint--error {\n color: #dc3545").concat(important, ";\n }\n\n /* Disabled mobile input styling */\n #mobileTextInput:disabled {\n background-color: #f5f5f5").concat(important, ";\n cursor: not-allowed").concat(important, ";\n }\n\n #mobileSendBtn:disabled {\n opacity: 0.5").concat(important, ";\n cursor: not-allowed").concat(important, ";\n }\n ");
36100
36357
  }
36101
36358
 
36102
36359
  /**
@@ -36123,7 +36380,10 @@ var Styles = /*#__PURE__*/function () {
36123
36380
  "use strict";
36124
36381
  __webpack_require__.r(__webpack_exports__);
36125
36382
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
36126
- /* harmony export */ Templates: () => (/* binding */ Templates)
36383
+ /* harmony export */ Templates: () => (/* binding */ Templates),
36384
+ /* harmony export */ escapeHtmlAttr: () => (/* binding */ escapeHtmlAttr),
36385
+ /* harmony export */ resolveIdleHeaderAvatarUrl: () => (/* binding */ resolveIdleHeaderAvatarUrl),
36386
+ /* harmony export */ sanitizeHeaderAvatarImageUrl: () => (/* binding */ sanitizeHeaderAvatarImageUrl)
36127
36387
  /* harmony export */ });
36128
36388
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
36129
36389
  function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
@@ -36145,6 +36405,37 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
36145
36405
  * - None (stateless template generation)
36146
36406
  */
36147
36407
 
36408
+ /** Allow only http(s) absolute URLs for idle header avatar images. */
36409
+ function sanitizeHeaderAvatarImageUrl(raw) {
36410
+ var s = raw != null && String(raw).trim() || '';
36411
+ if (!s) return '';
36412
+ try {
36413
+ var u = new URL(s);
36414
+ if (u.protocol !== 'http:' && u.protocol !== 'https:') return '';
36415
+ return u.href;
36416
+ } catch (_unused) {
36417
+ return '';
36418
+ }
36419
+ }
36420
+ function escapeHtmlAttr(s) {
36421
+ return String(s).replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;');
36422
+ }
36423
+
36424
+ /**
36425
+ * Resolve idle header avatar URL from flat + nested voice config (and legacy / API aliases).
36426
+ * The idle UI shows the first letter of the agent name only when this returns ''.
36427
+ */
36428
+ function resolveIdleHeaderAvatarUrl(config) {
36429
+ if (!config) return '';
36430
+ var v = config.voice || {};
36431
+ var candidates = [config.headerAvatarImageUrl, v.headerAvatarImageUrl, config.header_avatar_image_url, v.header_avatar_image_url, v.avatarImageUrl, config.avatarImageUrl, v.avatar_image_url, config.avatar_image_url];
36432
+ for (var _i = 0, _candidates = candidates; _i < _candidates.length; _i++) {
36433
+ var raw = _candidates[_i];
36434
+ var u = sanitizeHeaderAvatarImageUrl(raw);
36435
+ if (u) return u;
36436
+ }
36437
+ return '';
36438
+ }
36148
36439
  var Templates = /*#__PURE__*/function () {
36149
36440
  function Templates(voiceInterface) {
36150
36441
  _classCallCheck(this, Templates);
@@ -36196,12 +36487,17 @@ var Templates = /*#__PURE__*/function () {
36196
36487
  }
36197
36488
 
36198
36489
  // Desktop UI - new dark theme design
36199
- var agentName = this.config.headerTitle || this.config.agentName || 'Sasha';
36490
+ // Prefer explicit agent name over header.title so the pill can use a separate CTA (header.pillTitle + header.title).
36491
+ var agentName = this.config.agentName != null && String(this.config.agentName).trim() !== '' ? String(this.config.agentName).trim() : 'Sasha';
36200
36492
  var agentRole = this.config.agentRole || 'AI Voice Assistant';
36201
36493
  var headline = this.config.headline || this.config.startCallTitle || 'Hi there 👋';
36202
36494
  var subline = this.config.subline || this.config.startCallSubtitle || 'Ask me anything — I respond instantly<br>in voice or text.';
36203
36495
  var avatarInitial = agentName.charAt(0).toUpperCase();
36204
- return "<div class=\"voice-interface\" id=\"voiceInterface\">\n <!-- Idle View -->\n <div id=\"voiceIdleState\">\n <div class=\"ttp-hero\">\n <div class=\"ttp-header\">\n <div class=\"ttp-agent\">\n <div class=\"ttp-avatar-wrap\">\n <div class=\"ttp-avatar\">".concat(avatarInitial, "</div>\n <div class=\"ttp-online-dot\"></div>\n </div>\n <div>\n <div class=\"ttp-agent-name\">").concat(agentName, "</div>\n <div class=\"ttp-agent-role\">").concat(agentRole, "</div>\n </div>\n </div>\n <button type=\"button\" class=\"ttp-close-btn\" id=\"ttpCloseIdle\" aria-label=\"Close widget\">\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 12 12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M10 2L2 10M2 2l8 8\"/>\n </svg>\n </button>\n </div>\n <div class=\"ttp-headline\">").concat(headline, "</div>\n <div class=\"ttp-subline\">").concat(subline, "</div>\n </div>\n\n <div class=\"ttp-body\">\n <button type=\"button\" class=\"ttp-btn-primary\" id=\"startCallBtn\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"").concat(this.config.startCallButtonTextColor || 'white', "\" stroke-width=\"2\">\n <path d=\"M12 2a3 3 0 0 1 3 3v7a3 3 0 0 1-6 0V5a3 3 0 0 1 3-3z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2M12 19v3M8 22h8\"/>\n </svg>\n ").concat(this.getText('startCallButtonText', 'startCall') || 'Start Voice Call', "\n </button>\n <button type=\"button\" class=\"ttp-btn-secondary\" id=\"startTextBtn\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"/>\n </svg>\n ").concat(this.config.sendMessageText || this.getText('sendMessageText', 'sendMessage') || 'Send a Message', "\n </button>\n ").concat((_this$config$whatsapp = this.config.whatsapp) !== null && _this$config$whatsapp !== void 0 && _this$config$whatsapp.number ? "\n <a class=\"ttp-btn-wa\" id=\"ttpWhatsAppBtn\"\n href=\"https://wa.me/".concat(this.config.whatsapp.number).concat(this.config.whatsapp.text ? '?text=' + encodeURIComponent(this.config.whatsapp.text) : '', "\"\n target=\"_blank\" rel=\"noopener\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"#25d366\">\n <path d=\"M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.655-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z\"/>\n </svg>\n WhatsApp\n </a>\n ") : '', "\n </div>\n </div>\n\n <!-- Active Call View -->\n <div id=\"voiceActiveState\" style=\"display: none;\">\n <!-- Full voice section (hidden when items/rooms are shown) -->\n <div class=\"desktop-voice-section\" id=\"desktopVoiceSection\">\n <div class=\"ttp-call-hero\">\n <div class=\"ttp-call-topbar\">\n <div class=\"ttp-rec\">\n <div class=\"ttp-rec-dot\"></div>\n <span class=\"ttp-timer\" id=\"desktopTimerText\">00:00</span>\n </div>\n <span class=\"ttp-call-label\">Voice call active</span>\n <button type=\"button\" class=\"ttp-close-btn\" id=\"ttpCloseActive\" aria-label=\"Close widget\">\n <svg width=\"9\" height=\"9\" viewBox=\"0 0 12 12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M10 2L2 10M2 2l8 8\"/>\n </svg>\n </button>\n </div>\n\n <div class=\"ttp-orb-wrap\">\n <div class=\"ttp-orb-rings\">\n <div class=\"ttp-ring ttp-ring-1\"></div>\n <div class=\"ttp-ring ttp-ring-2\"></div>\n <div class=\"ttp-orb\" id=\"desktopMainWaveform\">\n <div class=\"ttp-wave\" id=\"ttp-wave\"></div>\n </div>\n </div>\n <div class=\"ttp-listen-label\" id=\"desktopStatusText\">").concat(this.t('listening') || 'Listening to you...', "</div>\n </div>\n </div>\n\n <div class=\"ttp-controls\">\n <button type=\"button\" class=\"ttp-ctrl-btn\" id=\"desktopMuteBtn\" title=\"").concat(this.getTooltip('mute'), "\" aria-label=\"Mute microphone\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" class=\"desktop-mic-icon\">\n <path d=\"M12 1a3 3 0 0 1 3 3v7a3 3 0 0 1-6 0V4a3 3 0 0 1 3-3z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n </svg>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" class=\"desktop-mic-off-icon\" style=\"display: none; position: absolute;\">\n <path d=\"M12 1a3 3 0 0 1 3 3v7a3 3 0 0 1-6 0V4a3 3 0 0 1 3-3z\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <line x1=\"5\" y1=\"5\" x2=\"19\" y2=\"19\" stroke=\"#ef4444\" stroke-width=\"1.5\" stroke-linecap=\"round\" opacity=\"0.85\"/>\n </svg>\n </button>\n <button type=\"button\" class=\"ttp-end-btn\" id=\"desktopEndCallBtn\" title=\"").concat(this.getTooltip('endCall'), "\" aria-label=\"End call\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07A19.5 19.5 0 0 1 4.99 12 19.79 19.79 0 0 1 1.97 3.4 2 2 0 0 1 3.95 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z\"/>\n </svg>\n </button>\n <button type=\"button\" class=\"ttp-ctrl-btn\" id=\"desktopSpeakerBtn\" title=\"").concat(this.getTooltip('speaker'), "\" aria-label=\"Toggle speaker\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" class=\"desktop-speaker-icon\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\"/>\n </svg>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" class=\"desktop-speaker-off-icon\" style=\"display: none; position: absolute;\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <line x1=\"5\" y1=\"5\" x2=\"19\" y2=\"19\" stroke=\"#ef4444\" stroke-width=\"1.5\" stroke-linecap=\"round\" opacity=\"0.85\"/>\n </svg>\n </button>\n </div>\n </div>\n\n <!-- Compact voice section (shown when items/rooms are visible) -->\n <div class=\"compact-voice-section\" id=\"compactVoiceSection\" style=\"display: none;\">\n <div class=\"compact-left\">\n <div class=\"compact-avatar\" id=\"desktopAvatarCompact\">\n <div class=\"ttp-orb compact-orb\" id=\"desktopMainWaveformCompact\">\n <div class=\"ttp-wave\"></div>\n </div>\n </div>\n <div class=\"compact-info\">\n <div class=\"compact-timer\" id=\"desktopTimerCompact\">\n <span class=\"ttp-rec-dot\"></span>\n <span id=\"compactTimerText\">00:00</span>\n </div>\n <div class=\"compact-status\" id=\"desktopStatusCompact\">\n <span id=\"compactStatusText\">").concat(this.t('listening') || 'Listening...', "</span>\n </div>\n </div>\n </div>\n <div class=\"compact-controls\">\n <button type=\"button\" class=\"compact-control-btn secondary\" id=\"desktopMuteBtnCompact\" title=\"").concat(this.getTooltip('mute'), "\" aria-label=\"Mute microphone\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" class=\"desktop-mic-icon\">\n <path d=\"M12 1a3 3 0 0 1 3 3v7a3 3 0 0 1-6 0V4a3 3 0 0 1 3-3z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n </svg>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" class=\"desktop-mic-off-icon\" style=\"display: none; position: absolute;\">\n <path d=\"M12 1a3 3 0 0 1 3 3v7a3 3 0 0 1-6 0V4a3 3 0 0 1 3-3z\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <line x1=\"5\" y1=\"5\" x2=\"19\" y2=\"19\" stroke=\"#ef4444\" stroke-width=\"1.5\" stroke-linecap=\"round\" opacity=\"0.85\"/>\n </svg>\n </button>\n <button type=\"button\" class=\"compact-control-btn danger\" id=\"desktopEndCallBtnCompact\" title=\"").concat(this.getTooltip('endCall'), "\" aria-label=\"End call\">\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" style=\"overflow: visible;\">\n <path d=\"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07A19.5 19.5 0 0 1 4.99 12 19.79 19.79 0 0 1 1.97 3.4 2 2 0 0 1 3.95 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z\" transform=\"rotate(135 12 12)\"/>\n </svg>\n </button>\n <button type=\"button\" class=\"compact-control-btn secondary\" id=\"desktopSpeakerBtnCompact\" title=\"").concat(this.getTooltip('speaker'), "\" aria-label=\"Toggle speaker\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" class=\"desktop-speaker-icon\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\"/>\n </svg>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" class=\"desktop-speaker-off-icon\" style=\"display: none; position: absolute;\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <line x1=\"5\" y1=\"5\" x2=\"19\" y2=\"19\" stroke=\"#ef4444\" stroke-width=\"1.5\" stroke-linecap=\"round\" opacity=\"0.85\"/>\n </svg>\n </button>\n </div>\n </div>\n\n <!-- Transcript -->\n <div class=\"ttp-transcript desktop-conversation-panel\" id=\"desktopConversationPanel\">\n <div class=\"ttp-transcript-hdr\" id=\"conversationHeader\">\n <span class=\"ttp-live-label\">Live</span>\n <span class=\"ttp-toggle-text\" id=\"conversationToggleText\">Show history</span>\n <div class=\"ttp-dots\">\n <div class=\"ttp-dot\"></div>\n <div class=\"ttp-dot\"></div>\n <div class=\"ttp-dot\"></div>\n </div>\n </div>\n <div class=\"live-transcript-collapsed\" id=\"liveTranscriptCollapsed\">\n <div class=\"ttp-transcript-text\" id=\"liveTextCollapsed\">\n ").concat(this.t('transcriptWillAppear') || 'Transcript will appear here...', "<span class=\"ttp-cursor\"></span>\n </div>\n </div>\n <div class=\"conversation-history\" id=\"conversationHistory\">\n <div class=\"conversation-messages\" id=\"conversationMessages\"></div>\n <div class=\"live-message-row\" id=\"liveMessageRow\" style=\"display: none;\">\n <div class=\"message-bubble\">\n <span class=\"live-badge\">Live</span>\n <span id=\"liveMessageText\"></span><span class=\"ttp-cursor\"></span>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Type row -->\n <div class=\"ttp-type-row voice-text-input-area\">\n <input class=\"ttp-input\" type=\"text\" id=\"voiceTextInput\" placeholder=\"").concat(this.getText('inputPlaceholder', 'typeMessage') || 'Or type here…', "\" aria-label=\"Type a message\" />\n <button type=\"button\" class=\"ttp-send-btn\" id=\"voiceSendBtn\" aria-label=\"Send message\">\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"white\" stroke-width=\"2\">\n <line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"/>\n <polygon points=\"22 2 15 22 11 13 2 9 22 2\"/>\n </svg>\n </button>\n </div>\n </div>\n </div>");
36496
+ var headerAvatarUrl = resolveIdleHeaderAvatarUrl(this.config);
36497
+ var idleAvatarInner = headerAvatarUrl ? "<img src=\"".concat(escapeHtmlAttr(headerAvatarUrl), "\" alt=\"\" class=\"ttp-avatar-img\" />") : avatarInitial;
36498
+ var idleAvatarClass = headerAvatarUrl ? 'ttp-avatar ttp-avatar--image' : 'ttp-avatar';
36499
+ var textDir = this.config.direction === 'rtl' ? 'rtl' : 'ltr';
36500
+ return "<div class=\"voice-interface\" id=\"voiceInterface\">\n <!-- Idle View -->\n <div id=\"voiceIdleState\">\n <div class=\"ttp-hero\">\n <div class=\"ttp-header\">\n <div class=\"ttp-agent\">\n <div class=\"ttp-avatar-wrap\">\n <div class=\"".concat(idleAvatarClass, "\">").concat(idleAvatarInner, "</div>\n <div class=\"ttp-online-dot\"></div>\n </div>\n <div>\n <div class=\"ttp-agent-name\">").concat(agentName, "</div>\n <div class=\"ttp-agent-role\">").concat(agentRole, "</div>\n </div>\n </div>\n <button type=\"button\" class=\"ttp-close-btn\" id=\"ttpCloseIdle\" aria-label=\"Close widget\">\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 12 12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M10 2L2 10M2 2l8 8\"/>\n </svg>\n </button>\n </div>\n <div class=\"ttp-headline\">").concat(headline, "</div>\n <div class=\"ttp-subline\">").concat(subline, "</div>\n </div>\n\n <div class=\"ttp-body\">\n <button type=\"button\" class=\"ttp-btn-primary\" id=\"startCallBtn\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"").concat(this.config.startCallButtonTextColor || 'white', "\" stroke-width=\"2\">\n <path d=\"M12 2a3 3 0 0 1 3 3v7a3 3 0 0 1-6 0V5a3 3 0 0 1 3-3z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2M12 19v3M8 22h8\"/>\n </svg>\n ").concat(this.getText('startCallButtonText', 'startCall') || 'Start Voice Call', "\n </button>\n <button type=\"button\" class=\"ttp-btn-secondary\" id=\"startTextBtn\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"/>\n </svg>\n ").concat(this.config.sendMessageText || this.getText('sendMessageText', 'sendMessage') || 'Send a Message', "\n </button>\n ").concat((_this$config$whatsapp = this.config.whatsapp) !== null && _this$config$whatsapp !== void 0 && _this$config$whatsapp.number ? "\n <a class=\"ttp-btn-wa\" id=\"ttpWhatsAppBtn\"\n href=\"https://wa.me/".concat(this.config.whatsapp.number).concat(this.config.whatsapp.text ? '?text=' + encodeURIComponent(this.config.whatsapp.text) : '', "\"\n target=\"_blank\" rel=\"noopener\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"#25d366\">\n <path d=\"M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.655-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z\"/>\n </svg>\n WhatsApp\n </a>\n ") : '', "\n </div>\n </div>\n\n <!-- Active Call View -->\n <div id=\"voiceActiveState\" style=\"display: none;\">\n <!-- Full voice section (hidden when items/rooms are shown) -->\n <div class=\"desktop-voice-section\" id=\"desktopVoiceSection\">\n <div class=\"ttp-call-hero\">\n <div class=\"ttp-call-topbar\">\n <div class=\"ttp-rec\">\n <div class=\"ttp-rec-dot\"></div>\n <span class=\"ttp-timer\" id=\"desktopTimerText\">00:00</span>\n </div>\n <span class=\"ttp-call-label\">Voice call active</span>\n <button type=\"button\" class=\"ttp-close-btn\" id=\"ttpCloseActive\" aria-label=\"Close widget\">\n <svg width=\"9\" height=\"9\" viewBox=\"0 0 12 12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M10 2L2 10M2 2l8 8\"/>\n </svg>\n </button>\n </div>\n\n <div class=\"ttp-orb-wrap\">\n <div class=\"ttp-orb-rings\">\n <div class=\"ttp-ring ttp-ring-1\"></div>\n <div class=\"ttp-ring ttp-ring-2\"></div>\n <div class=\"ttp-orb\" id=\"desktopMainWaveform\">\n <div class=\"ttp-wave\" id=\"ttp-wave\"></div>\n </div>\n </div>\n <div class=\"ttp-listen-label\" id=\"desktopStatusText\">").concat(this.t('listening') || 'Listening to you...', "</div>\n </div>\n </div>\n\n <div class=\"ttp-controls\">\n <button type=\"button\" class=\"ttp-ctrl-btn\" id=\"desktopMuteBtn\" title=\"").concat(this.getTooltip('mute'), "\" aria-label=\"Mute microphone\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" class=\"desktop-mic-icon\">\n <path d=\"M12 1a3 3 0 0 1 3 3v7a3 3 0 0 1-6 0V4a3 3 0 0 1 3-3z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n </svg>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" class=\"desktop-mic-off-icon\" style=\"display: none; position: absolute;\">\n <path d=\"M12 1a3 3 0 0 1 3 3v7a3 3 0 0 1-6 0V4a3 3 0 0 1 3-3z\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <line x1=\"5\" y1=\"5\" x2=\"19\" y2=\"19\" stroke=\"#ef4444\" stroke-width=\"1.5\" stroke-linecap=\"round\" opacity=\"0.85\"/>\n </svg>\n </button>\n <button type=\"button\" class=\"ttp-end-btn\" id=\"desktopEndCallBtn\" title=\"").concat(this.getTooltip('endCall'), "\" aria-label=\"End call\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07A19.5 19.5 0 0 1 4.99 12 19.79 19.79 0 0 1 1.97 3.4 2 2 0 0 1 3.95 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z\"/>\n </svg>\n </button>\n <button type=\"button\" class=\"ttp-ctrl-btn\" id=\"desktopSpeakerBtn\" title=\"").concat(this.getTooltip('speaker'), "\" aria-label=\"Toggle speaker\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" class=\"desktop-speaker-icon\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\"/>\n </svg>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" class=\"desktop-speaker-off-icon\" style=\"display: none; position: absolute;\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <line x1=\"5\" y1=\"5\" x2=\"19\" y2=\"19\" stroke=\"#ef4444\" stroke-width=\"1.5\" stroke-linecap=\"round\" opacity=\"0.85\"/>\n </svg>\n </button>\n </div>\n </div>\n\n <!-- Compact voice section (shown when items/rooms are visible) -->\n <div class=\"compact-voice-section\" id=\"compactVoiceSection\" style=\"display: none;\">\n <div class=\"compact-left\">\n <div class=\"compact-avatar\" id=\"desktopAvatarCompact\">\n <div class=\"ttp-orb compact-orb\" id=\"desktopMainWaveformCompact\">\n <div class=\"ttp-wave\"></div>\n </div>\n </div>\n <div class=\"compact-info\">\n <div class=\"compact-timer\" id=\"desktopTimerCompact\">\n <span class=\"ttp-rec-dot\"></span>\n <span id=\"compactTimerText\">00:00</span>\n </div>\n <div class=\"compact-status\" id=\"desktopStatusCompact\">\n <span id=\"compactStatusText\">").concat(this.t('listening') || 'Listening...', "</span>\n </div>\n </div>\n </div>\n <div class=\"compact-controls\">\n <button type=\"button\" class=\"compact-control-btn secondary\" id=\"desktopMuteBtnCompact\" title=\"").concat(this.getTooltip('mute'), "\" aria-label=\"Mute microphone\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" class=\"desktop-mic-icon\">\n <path d=\"M12 1a3 3 0 0 1 3 3v7a3 3 0 0 1-6 0V4a3 3 0 0 1 3-3z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n </svg>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" class=\"desktop-mic-off-icon\" style=\"display: none; position: absolute;\">\n <path d=\"M12 1a3 3 0 0 1 3 3v7a3 3 0 0 1-6 0V4a3 3 0 0 1 3-3z\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <line x1=\"5\" y1=\"5\" x2=\"19\" y2=\"19\" stroke=\"#ef4444\" stroke-width=\"1.5\" stroke-linecap=\"round\" opacity=\"0.85\"/>\n </svg>\n </button>\n <button type=\"button\" class=\"compact-control-btn danger\" id=\"desktopEndCallBtnCompact\" title=\"").concat(this.getTooltip('endCall'), "\" aria-label=\"End call\">\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" style=\"overflow: visible;\">\n <path d=\"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07A19.5 19.5 0 0 1 4.99 12 19.79 19.79 0 0 1 1.97 3.4 2 2 0 0 1 3.95 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z\" transform=\"rotate(135 12 12)\"/>\n </svg>\n </button>\n <button type=\"button\" class=\"compact-control-btn secondary\" id=\"desktopSpeakerBtnCompact\" title=\"").concat(this.getTooltip('speaker'), "\" aria-label=\"Toggle speaker\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" class=\"desktop-speaker-icon\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\"/>\n </svg>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" class=\"desktop-speaker-off-icon\" style=\"display: none; position: absolute;\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <line x1=\"5\" y1=\"5\" x2=\"19\" y2=\"19\" stroke=\"#ef4444\" stroke-width=\"1.5\" stroke-linecap=\"round\" opacity=\"0.85\"/>\n </svg>\n </button>\n </div>\n </div>\n\n <!-- Transcript -->\n <div class=\"ttp-transcript desktop-conversation-panel\" id=\"desktopConversationPanel\" dir=\"").concat(textDir, "\">\n <div class=\"ttp-transcript-hdr\" id=\"conversationHeader\">\n <span class=\"ttp-live-label\">Live</span>\n <span class=\"ttp-toggle-text\" id=\"conversationToggleText\">Show history</span>\n <div class=\"ttp-dots\">\n <div class=\"ttp-dot\"></div>\n <div class=\"ttp-dot\"></div>\n <div class=\"ttp-dot\"></div>\n </div>\n </div>\n <div class=\"live-transcript-collapsed\" id=\"liveTranscriptCollapsed\">\n <div class=\"ttp-transcript-text\" id=\"liveTextCollapsed\">\n ").concat(this.t('transcriptWillAppear') || 'Transcript will appear here...', "<span class=\"ttp-cursor\"></span>\n </div>\n </div>\n <div class=\"conversation-history\" id=\"conversationHistory\">\n <div class=\"conversation-messages\" id=\"conversationMessages\"></div>\n <div class=\"live-message-row\" id=\"liveMessageRow\" style=\"display: none;\">\n <div class=\"message-bubble\" dir=\"").concat(textDir, "\">\n <span class=\"live-badge\">Live</span>\n <span id=\"liveMessageText\"></span><span class=\"ttp-cursor\"></span>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Type row -->\n <div class=\"ttp-type-row voice-text-input-area\">\n <input class=\"ttp-input\" type=\"text\" id=\"voiceTextInput\" dir=\"").concat(textDir, "\" placeholder=\"").concat(this.getText('inputPlaceholder', 'typeMessage') || 'Or type here…', "\" aria-label=\"Type a message\" />\n <button type=\"button\" class=\"ttp-send-btn\" id=\"voiceSendBtn\" aria-label=\"Send message\">\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"white\" stroke-width=\"2\">\n <line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"/>\n <polygon points=\"22 2 15 22 11 13 2 9 22 2\"/>\n </svg>\n </button>\n </div>\n </div>\n </div>");
36205
36501
  }
36206
36502
 
36207
36503
  /**
@@ -36211,9 +36507,13 @@ var Templates = /*#__PURE__*/function () {
36211
36507
  key: "generateMobileHTML",
36212
36508
  value: function generateMobileHTML() {
36213
36509
  // For mobile, idle state goes in widget, but active state will be appended to body
36214
- return "<div class=\"voice-interface mobile-voice-interface\" id=\"voiceInterface\">\n <!-- Before Call State (same as desktop) -->\n <div id=\"voiceIdleState\">\n <div class=\"voice-avatar\" id=\"voiceAvatar\">\uD83E\uDD16</div>\n <div class=\"voice-status\">\n <div class=\"voice-status-title\">".concat(this.getText('startCallTitle', 'clickToStartCall'), "</div>\n <div class=\"voice-status-subtitle\">").concat(this.getText('startCallSubtitle', 'realTimeVoice'), "</div>\n </div>\n <button type=\"button\" class=\"start-call-btn\" id=\"startCallBtn\">\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M20.01 15.38c-1.23 0-2.42-.2-3.53-.56-.35-.12-.74-.03-1.01.24l-1.57 1.97c-2.83-1.35-5.48-3.9-6.89-6.83l1.95-1.66c.27-.28.35-.67.24-1.02-.37-1.11-.56-2.3-.56-3.53 0-.54-.45-.99-.99-.99H4.19C3.65 3 3 3.24 3 3.99 3 13.28 10.73 21 20.01 21c.71 0 .99-.63.99-1.18v-3.45c0-.54-.45-.99-.99-.99z\"/>\n </svg>\n <span>").concat(this.getText('startCallButtonText', 'startCall'), "</span>\n </button>\n </div>\n \n <!-- Mobile Active Call State - Hidden placeholder (actual bar will be appended to body) -->\n <div id=\"voiceActiveState\" class=\"mobile-active-state\" style=\"display: none;\">\n <!-- Duration Badge -->\n <div class=\"mobile-duration-badge\" id=\"mobileDurationBadge\">\n <div class=\"mobile-duration-dot\"></div>\n <span id=\"mobileDurationText\">00:00</span>\n </div>\n \n <!-- Main Bar -->\n <div class=\"mobile-voice-bar\">\n <!-- Top Row: Status, Waveform, Controls -->\n <div class=\"mobile-top-row\">\n <!-- Status Indicator -->\n <div class=\"mobile-status-indicator\">\n <div class=\"mobile-status-dot\" id=\"mobileStatusDot\"></div>\n <span class=\"mobile-status-text\" id=\"mobileStatusText\">Listening...</span>\n </div>\n \n <!-- Centered Waveform -->\n <div class=\"mobile-waveform-center\" id=\"mobileWaveform\">\n ").concat(Array(8).fill(0).map(function (_, i) {
36510
+ var textDir = this.config.direction === 'rtl' ? 'rtl' : 'ltr';
36511
+ var headerAvatarUrl = resolveIdleHeaderAvatarUrl(this.config);
36512
+ var mobileAvatarInner = headerAvatarUrl ? "<img src=\"".concat(escapeHtmlAttr(headerAvatarUrl), "\" alt=\"\" class=\"voice-avatar-img\" />") : '🤖';
36513
+ var mobileAvatarClass = headerAvatarUrl ? 'voice-avatar voice-avatar--image' : 'voice-avatar';
36514
+ return "<div class=\"voice-interface mobile-voice-interface\" id=\"voiceInterface\" dir=\"".concat(textDir, "\">\n <!-- Before Call State (same as desktop) -->\n <div id=\"voiceIdleState\">\n <div class=\"").concat(mobileAvatarClass, "\" id=\"voiceAvatar\">").concat(mobileAvatarInner, "</div>\n <div class=\"voice-status\">\n <div class=\"voice-status-title\">").concat(this.getText('startCallTitle', 'clickToStartCall'), "</div>\n <div class=\"voice-status-subtitle\">").concat(this.getText('startCallSubtitle', 'realTimeVoice'), "</div>\n </div>\n <button type=\"button\" class=\"start-call-btn\" id=\"startCallBtn\">\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M20.01 15.38c-1.23 0-2.42-.2-3.53-.56-.35-.12-.74-.03-1.01.24l-1.57 1.97c-2.83-1.35-5.48-3.9-6.89-6.83l1.95-1.66c.27-.28.35-.67.24-1.02-.37-1.11-.56-2.3-.56-3.53 0-.54-.45-.99-.99-.99H4.19C3.65 3 3 3.24 3 3.99 3 13.28 10.73 21 20.01 21c.71 0 .99-.63.99-1.18v-3.45c0-.54-.45-.99-.99-.99z\"/>\n </svg>\n <span>").concat(this.getText('startCallButtonText', 'startCall'), "</span>\n </button>\n </div>\n \n <!-- Mobile Active Call State - Hidden placeholder (actual bar will be appended to body) -->\n <div id=\"voiceActiveState\" class=\"mobile-active-state\" style=\"display: none;\">\n <!-- Duration Badge -->\n <div class=\"mobile-duration-badge\" id=\"mobileDurationBadge\">\n <div class=\"mobile-duration-dot\"></div>\n <span id=\"mobileDurationText\">00:00</span>\n </div>\n \n <!-- Main Bar -->\n <div class=\"mobile-voice-bar\">\n <!-- Top Row: Status, Waveform, Controls -->\n <div class=\"mobile-top-row\">\n <!-- Status Indicator -->\n <div class=\"mobile-status-indicator\">\n <div class=\"mobile-status-dot\" id=\"mobileStatusDot\"></div>\n <span class=\"mobile-status-text\" id=\"mobileStatusText\">Listening...</span>\n </div>\n \n <!-- Centered Waveform -->\n <div class=\"mobile-waveform-center\" id=\"mobileWaveform\">\n ").concat(Array(8).fill(0).map(function (_, i) {
36215
36515
  return "<div class=\"mobile-waveform-bar\" data-index=\"".concat(i, "\"></div>");
36216
- }).join(''), "\n </div>\n \n <!-- Controls -->\n <div class=\"mobile-controls\">\n <button type=\"button\" class=\"mobile-control-btn\" id=\"mobileMuteBtn\" aria-label=\"Mute microphone\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-mic-icon\">\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\"/>\n </svg>\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-mic-off-icon\" style=\"display: none;\">\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\"/>\n <line x1=\"4\" y1=\"4\" x2=\"20\" y2=\"20\" stroke=\"#ef4444\" stroke-width=\"1.5\" opacity=\"0.85\"/>\n </svg>\n </button>\n \n <button type=\"button\" class=\"mobile-control-btn\" id=\"mobileSpeakerBtn\" aria-label=\"Toggle speaker\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-speaker-icon\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\"/>\n </svg>\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-speaker-off-icon\" style=\"display: none;\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\"/>\n <line x1=\"4\" y1=\"4\" x2=\"20\" y2=\"20\" stroke=\"#ef4444\" stroke-width=\"1.5\" opacity=\"0.85\"/>\n </svg>\n </button>\n \n <button type=\"button\" class=\"mobile-end-call-btn\" id=\"mobileEndCallBtn\" aria-label=\"End call\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M10.68 13.31a16 16 0 0 0 3.41 2.6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7 2 2 0 0 1 1.72 2v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.42 19.42 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.63A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91\"/>\n <line x1=\"22\" x2=\"2\" y1=\"2\" y2=\"22\"/>\n </svg>\n </button>\n </div>\n </div>\n \n <!-- Bottom Row: Transcript (expandable) -->\n <button type=\"button\" class=\"mobile-transcript-row\" id=\"mobileTranscriptRow\">\n <p class=\"mobile-transcript-text\" id=\"mobileTranscriptText\">").concat(this.t('transcriptWillAppear'), "</p>\n <div class=\"mobile-transcript-footer\">\n <span class=\"mobile-expand-hint\">tap to expand & type</span>\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"opacity: 0.6;\">\n <path d=\"M7 17L17 7M17 7H7M17 7V17\"/>\n </svg>\n </div>\n </button>\n </div>\n </div>\n \n <!-- Expanded Transcript Overlay -->\n <div class=\"mobile-transcript-overlay\" id=\"mobileTranscriptOverlay\" style=\"display: none;\">\n <div class=\"mobile-expanded-transcript\" id=\"mobileExpandedTranscript\">\n <!-- Header -->\n <div class=\"mobile-transcript-header\">\n <div class=\"mobile-header-left\">\n <div class=\"mobile-header-status\">\n <div class=\"mobile-header-status-dot\"></div>\n <span class=\"mobile-header-status-text\" id=\"mobileHeaderStatusText\">Listening...</span>\n <span class=\"mobile-header-duration\" id=\"mobileHeaderDuration\">00:00</span>\n </div>\n <span class=\"mobile-transcript-label\">CONVERSATION</span>\n </div>\n <button type=\"button\" class=\"mobile-close-transcript-btn\" id=\"mobileCloseTranscriptBtn\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M18 6L6 18M6 6l12 12\"/>\n </svg>\n </button>\n </div>\n \n <!-- Messages Container -->\n <div class=\"mobile-messages-container\" id=\"mobileMessagesContainer\">\n <!-- Messages will be dynamically added here -->\n </div>\n \n <!-- Text Input Area -->\n <div class=\"mobile-input-area\">\n <div class=\"mobile-input-wrapper\">\n <input\n type=\"text\"\n placeholder=\"Type a message...\"\n id=\"mobileTextInput\"\n class=\"mobile-text-input\"\n />\n <button type=\"button\" class=\"mobile-send-btn\" id=\"mobileSendBtn\" disabled>\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M22 2L11 13M22 2l-7 20-4-9-9-4 20-7z\"/>\n </svg>\n </button>\n </div>\n <p class=\"mobile-input-hint\">\uD83C\uDF99\uFE0F Voice is still active \u2022 Type or speak</p>\n </div>\n </div>\n </div>\n </div>");
36516
+ }).join(''), "\n </div>\n \n <!-- Controls -->\n <div class=\"mobile-controls\">\n <button type=\"button\" class=\"mobile-control-btn\" id=\"mobileMuteBtn\" aria-label=\"Mute microphone\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-mic-icon\">\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\"/>\n </svg>\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-mic-off-icon\" style=\"display: none;\">\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\"/>\n <line x1=\"4\" y1=\"4\" x2=\"20\" y2=\"20\" stroke=\"#ef4444\" stroke-width=\"1.5\" opacity=\"0.85\"/>\n </svg>\n </button>\n \n <button type=\"button\" class=\"mobile-control-btn\" id=\"mobileSpeakerBtn\" aria-label=\"Toggle speaker\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-speaker-icon\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\"/>\n </svg>\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-speaker-off-icon\" style=\"display: none;\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\"/>\n <line x1=\"4\" y1=\"4\" x2=\"20\" y2=\"20\" stroke=\"#ef4444\" stroke-width=\"1.5\" opacity=\"0.85\"/>\n </svg>\n </button>\n \n <button type=\"button\" class=\"mobile-end-call-btn\" id=\"mobileEndCallBtn\" aria-label=\"End call\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M10.68 13.31a16 16 0 0 0 3.41 2.6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7 2 2 0 0 1 1.72 2v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.42 19.42 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.63A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91\"/>\n <line x1=\"22\" x2=\"2\" y1=\"2\" y2=\"22\"/>\n </svg>\n </button>\n </div>\n </div>\n \n <!-- Bottom Row: Transcript (expandable) -->\n <button type=\"button\" class=\"mobile-transcript-row\" id=\"mobileTranscriptRow\">\n <p class=\"mobile-transcript-text\" id=\"mobileTranscriptText\" dir=\"").concat(textDir, "\">").concat(this.t('transcriptWillAppear'), "</p>\n <div class=\"mobile-transcript-footer\">\n <span class=\"mobile-expand-hint\">tap to expand & type</span>\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"opacity: 0.6;\">\n <path d=\"M7 17L17 7M17 7H7M17 7V17\"/>\n </svg>\n </div>\n </button>\n </div>\n </div>\n \n <!-- Expanded Transcript Overlay -->\n <div class=\"mobile-transcript-overlay\" id=\"mobileTranscriptOverlay\">\n <div class=\"mobile-expanded-transcript\" id=\"mobileExpandedTranscript\">\n <!-- Header -->\n <div class=\"mobile-transcript-header\">\n <div class=\"mobile-header-left\">\n <div class=\"mobile-header-status\">\n <div class=\"mobile-header-status-dot\"></div>\n <span class=\"mobile-header-status-text\" id=\"mobileHeaderStatusText\">Listening...</span>\n <span class=\"mobile-header-duration\" id=\"mobileHeaderDuration\">00:00</span>\n </div>\n <span class=\"mobile-transcript-label\">CONVERSATION</span>\n </div>\n <button type=\"button\" class=\"mobile-close-transcript-btn\" id=\"mobileCloseTranscriptBtn\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M18 6L6 18M6 6l12 12\"/>\n </svg>\n </button>\n </div>\n \n <!-- Messages Container -->\n <div class=\"mobile-messages-container\" id=\"mobileMessagesContainer\">\n <!-- Messages will be dynamically added here -->\n </div>\n \n <!-- Text Input Area -->\n <div class=\"mobile-input-area\">\n <div class=\"mobile-input-wrapper\">\n <input\n type=\"text\"\n placeholder=\"Type a message...\"\n id=\"mobileTextInput\"\n class=\"mobile-text-input\"\n dir=\"").concat(textDir, "\"\n />\n <button type=\"button\" class=\"mobile-send-btn\" id=\"mobileSendBtn\" disabled>\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M22 2L11 13M22 2l-7 20-4-9-9-4 20-7z\"/>\n </svg>\n </button>\n </div>\n <p class=\"mobile-input-hint\">\uD83C\uDF99\uFE0F Voice is still active \u2022 Type or speak</p>\n </div>\n </div>\n </div>\n </div>");
36217
36517
  }
36218
36518
  }]);
36219
36519
  }();
@@ -36979,10 +37279,11 @@ var Transcript = /*#__PURE__*/function () {
36979
37279
  messagesToRender = messagesToRender.slice(0, -1);
36980
37280
  }
36981
37281
  }
37282
+ var textDir = this.config.direction === 'rtl' ? 'rtl' : 'ltr';
36982
37283
  console.log('📝 [TRANSCRIPT] Rendering', messagesToRender.length, 'messages (live message excluded)');
36983
37284
  container.innerHTML = messagesToRender.map(function (msg) {
36984
37285
  var isUser = msg.role === 'user';
36985
- return "\n <div class=\"message-row ".concat(msg.role, "\">\n <div class=\"message-avatar ").concat(msg.role, "\">\n ").concat(isUser ? 'U' : '<div class="orb"></div>', "\n </div>\n <div class=\"message-bubble\">").concat(_this.escapeHtml(msg.content), "</div>\n </div>\n ");
37286
+ return "\n <div class=\"message-row ".concat(msg.role, "\">\n <div class=\"message-avatar ").concat(msg.role, "\">\n ").concat(isUser ? 'U' : '<div class="orb"></div>', "\n </div>\n <div class=\"message-bubble\" dir=\"").concat(textDir, "\">").concat(_this.escapeHtml(msg.content), "</div>\n </div>\n ");
36986
37287
  }).join('');
36987
37288
 
36988
37289
  // Scroll to bottom
@@ -37020,10 +37321,13 @@ __webpack_require__.r(__webpack_exports__);
37020
37321
  "startCall": "Start Call",
37021
37322
  "connecting": "Connecting...",
37022
37323
  "connectingSubtitle": "Please wait",
37324
+ "awaitingBrowserMic": "Waiting for microphone…",
37325
+ "awaitingBrowserMicDetail": "Allow access in your browser’s permission prompt.",
37023
37326
  "listening": "Listening...",
37024
37327
  "speakFreely": "Speak freely",
37025
37328
  "liveTranscript": "Live Transcript",
37026
37329
  "transcriptWillAppear": "Transcript will appear here during the call...",
37330
+ "userTranscriptPrefix": "You: ",
37027
37331
  "mute": "Mute",
37028
37332
  "speaker": "Speaker",
37029
37333
  "endCall": "End Call",
@@ -37032,6 +37336,7 @@ __webpack_require__.r(__webpack_exports__);
37032
37336
  "online": "Online",
37033
37337
  "newChat": "New Chat",
37034
37338
  "back": "Back",
37339
+ "backToModeChoice": "Voice or text",
37035
37340
  "close": "Close",
37036
37341
  "error": "Error",
37037
37342
  "typeMessage": "Type your message...",
@@ -37049,10 +37354,13 @@ __webpack_require__.r(__webpack_exports__);
37049
37354
  "startCall": "התחל שיחה",
37050
37355
  "connecting": "מתחבר...",
37051
37356
  "connectingSubtitle": "אנא המתן",
37357
+ "awaitingBrowserMic": "ממתין למיקרופון…",
37358
+ "awaitingBrowserMicDetail": "אשר גישה בחלון ההרשאות של הדפדפן.",
37052
37359
  "listening": "מקשיב...",
37053
37360
  "speakFreely": "דבר בחופשיות",
37054
37361
  "liveTranscript": "תמלול בזמן אמת",
37055
37362
  "transcriptWillAppear": "התמלול יופיע כאן במהלך השיחה...",
37363
+ "userTranscriptPrefix": "אתה: ",
37056
37364
  "mute": "השתק",
37057
37365
  "speaker": "רמקול",
37058
37366
  "endCall": "סיים שיחה",
@@ -37061,6 +37369,7 @@ __webpack_require__.r(__webpack_exports__);
37061
37369
  "online": "מקוון",
37062
37370
  "newChat": "צ'אט חדש",
37063
37371
  "back": "חזור",
37372
+ "backToModeChoice": "קול או טקסט",
37064
37373
  "close": "סגור",
37065
37374
  "error": "שגיאה",
37066
37375
  "typeMessage": "הקלד הודעה...",
@@ -37078,10 +37387,13 @@ __webpack_require__.r(__webpack_exports__);
37078
37387
  "startCall": "ابدأ المكالمة",
37079
37388
  "connecting": "جارٍ الاتصال...",
37080
37389
  "connectingSubtitle": "يرجى الانتظار",
37390
+ "awaitingBrowserMic": "في انتظار الميكروفون…",
37391
+ "awaitingBrowserMicDetail": "اسمح بالوصول في موجه أذونات المتصفح.",
37081
37392
  "listening": "الاستماع...",
37082
37393
  "speakFreely": "تكلم بحرية",
37083
37394
  "liveTranscript": "نص مباشر",
37084
37395
  "transcriptWillAppear": "سيظهر النص هنا أثناء المكالمة...",
37396
+ "userTranscriptPrefix": "أنت: ",
37085
37397
  "mute": "كتم الصوت",
37086
37398
  "speaker": "مكبر الصوت",
37087
37399
  "endCall": "إنهاء المكالمة",
@@ -37090,6 +37402,7 @@ __webpack_require__.r(__webpack_exports__);
37090
37402
  "online": "متصل",
37091
37403
  "newChat": "محادثة جديدة",
37092
37404
  "back": "رجوع",
37405
+ "backToModeChoice": "صوت أو نص",
37093
37406
  "close": "إغلاق",
37094
37407
  "error": "خطأ",
37095
37408
  "typeMessage": "اكتب رسالة...",
@@ -37107,10 +37420,13 @@ __webpack_require__.r(__webpack_exports__);
37107
37420
  "startCall": "Начать звонок",
37108
37421
  "connecting": "Подключение...",
37109
37422
  "connectingSubtitle": "Пожалуйста, подождите",
37423
+ "awaitingBrowserMic": "Ожидание микрофона…",
37424
+ "awaitingBrowserMicDetail": "Разрешите доступ в запросе браузера.",
37110
37425
  "listening": "Слушаю...",
37111
37426
  "speakFreely": "Говорите свободно",
37112
37427
  "liveTranscript": "Живая транскрипция",
37113
37428
  "transcriptWillAppear": "Транскрипция появится здесь во время звонка...",
37429
+ "userTranscriptPrefix": "Вы: ",
37114
37430
  "mute": "Отключить звук",
37115
37431
  "speaker": "Динамик",
37116
37432
  "endCall": "Завершить звонок",
@@ -37119,6 +37435,7 @@ __webpack_require__.r(__webpack_exports__);
37119
37435
  "online": "В сети",
37120
37436
  "newChat": "Новый чат",
37121
37437
  "back": "Назад",
37438
+ "backToModeChoice": "Голос или текст",
37122
37439
  "close": "Закрыть",
37123
37440
  "error": "Ошибка",
37124
37441
  "typeMessage": "Введите сообщение...",
@@ -37136,10 +37453,13 @@ __webpack_require__.r(__webpack_exports__);
37136
37453
  "startCall": "Iniciar llamada",
37137
37454
  "connecting": "Conectando...",
37138
37455
  "connectingSubtitle": "Por favor espere",
37456
+ "awaitingBrowserMic": "Esperando el micrófono…",
37457
+ "awaitingBrowserMicDetail": "Permita el acceso en el cuadro de permisos del navegador.",
37139
37458
  "listening": "Escuchando...",
37140
37459
  "speakFreely": "Habla libremente",
37141
37460
  "liveTranscript": "Transcripción en vivo",
37142
37461
  "transcriptWillAppear": "La transcripción aparecerá aquí durante la llamada...",
37462
+ "userTranscriptPrefix": "Tú: ",
37143
37463
  "mute": "Silenciar",
37144
37464
  "speaker": "Altavoz",
37145
37465
  "endCall": "Terminar llamada",
@@ -37148,6 +37468,7 @@ __webpack_require__.r(__webpack_exports__);
37148
37468
  "online": "En línea",
37149
37469
  "newChat": "Nuevo chat",
37150
37470
  "back": "Atrás",
37471
+ "backToModeChoice": "Voz o texto",
37151
37472
  "close": "Cerrar",
37152
37473
  "error": "Error",
37153
37474
  "typeMessage": "Escribe un mensaje...",
@@ -37165,10 +37486,13 @@ __webpack_require__.r(__webpack_exports__);
37165
37486
  "startCall": "Démarrer l'appel",
37166
37487
  "connecting": "Connexion...",
37167
37488
  "connectingSubtitle": "Veuillez patienter",
37489
+ "awaitingBrowserMic": "En attente du microphone…",
37490
+ "awaitingBrowserMicDetail": "Autorisez l’accès dans la fenêtre d’autorisation du navigateur.",
37168
37491
  "listening": "Écoute...",
37169
37492
  "speakFreely": "Parlez librement",
37170
37493
  "liveTranscript": "Transcripción en direct",
37171
37494
  "transcriptWillAppear": "La transcription apparaîtra ici pendant l'appel...",
37495
+ "userTranscriptPrefix": "Vous : ",
37172
37496
  "mute": "Muet",
37173
37497
  "speaker": "Haut-parleur",
37174
37498
  "endCall": "Terminer l'appel",
@@ -37177,6 +37501,7 @@ __webpack_require__.r(__webpack_exports__);
37177
37501
  "online": "En ligne",
37178
37502
  "newChat": "Nouveau chat",
37179
37503
  "back": "Retour",
37504
+ "backToModeChoice": "Voix ou texte",
37180
37505
  "close": "Fermer",
37181
37506
  "error": "Erreur",
37182
37507
  "typeMessage": "Tapez votre message...",
@@ -37194,10 +37519,13 @@ __webpack_require__.r(__webpack_exports__);
37194
37519
  "startCall": "Anruf starten",
37195
37520
  "connecting": "Verbinden...",
37196
37521
  "connectingSubtitle": "Bitte warten",
37522
+ "awaitingBrowserMic": "Warte auf Mikrofon…",
37523
+ "awaitingBrowserMicDetail": "Erlauben Sie den Zugriff in der Browser-Anfrage.",
37197
37524
  "listening": "Hören...",
37198
37525
  "speakFreely": "Sprechen Sie frei",
37199
37526
  "liveTranscript": "Live-Transkription",
37200
37527
  "transcriptWillAppear": "Die Transkription erscheint hier während des Anrufs...",
37528
+ "userTranscriptPrefix": "Sie: ",
37201
37529
  "mute": "Stumm",
37202
37530
  "speaker": "Lautsprecher",
37203
37531
  "endCall": "Anruf beenden",
@@ -37206,6 +37534,7 @@ __webpack_require__.r(__webpack_exports__);
37206
37534
  "online": "Online",
37207
37535
  "newChat": "Neuer Chat",
37208
37536
  "back": "Zurück",
37537
+ "backToModeChoice": "Sprache oder Text",
37209
37538
  "close": "Schließen",
37210
37539
  "error": "Fehler",
37211
37540
  "typeMessage": "Geben Sie eine Nachricht ein...",