ttp-agent-sdk 2.35.0 → 2.36.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.
@@ -10949,6 +10949,8 @@ var TTPEcommerceWidget = /*#__PURE__*/function () {
10949
10949
  self._handleCartUpdatedFromServer(message);
10950
10950
  } else if (type === 'add_to_store_cart') {
10951
10951
  self._handleAddToStoreCart(message);
10952
+ } else if (type === 'get_store_cart') {
10953
+ self._handleGetStoreCart();
10952
10954
  }
10953
10955
  });
10954
10956
  console.log('[TTPEcommerceWidget] E-commerce message listener attached');
@@ -11048,26 +11050,101 @@ var TTPEcommerceWidget = /*#__PURE__*/function () {
11048
11050
  // ═══════════════════════════════════════════
11049
11051
 
11050
11052
  /**
11051
- * Handle add_to_store_cart message from the backend.
11052
- * Calls Shopify's /cart/add.js from the browser so the item goes into
11053
- * the store's session-based cart (not a headless Storefront API cart).
11054
- *
11055
- * We don't attempt to refresh the theme's cart UI (icon badge, drawer)
11056
- * because there's no universal mechanism — every theme is different.
11057
- * The user will see the updated cart when they navigate to /cart or refresh.
11058
- * Our own CartToast + CartSummary provide immediate visual feedback.
11053
+ * Fetch cart contents from Shopify's AJAX Cart API and send back to backend.
11054
+ * Triggered when the LLM calls get_cart for a Shopify store.
11055
+ * Only the browser can read the store's cart because it requires the session cookie.
11059
11056
  */
11060
11057
  }, {
11061
- key: "_handleAddToStoreCart",
11058
+ key: "_handleGetStoreCart",
11062
11059
  value: function () {
11063
- var _handleAddToStoreCart2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4(data) {
11064
- var variantId, quantity, productName, price, _cartResponse$items, _cartResponse$items2, response, cartResponse, cartData, _t3;
11060
+ var _handleGetStoreCart2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4() {
11061
+ var response, cart, _t3;
11065
11062
  return _regenerator().w(function (_context4) {
11066
11063
  while (1) switch (_context4.p = _context4.n) {
11067
11064
  case 0:
11068
- variantId = data.variantId, quantity = data.quantity, productName = data.productName, price = data.price;
11069
- _context4.p = 1;
11070
- _context4.n = 2;
11065
+ _context4.p = 0;
11066
+ _context4.n = 1;
11067
+ return fetch('/cart.js', {
11068
+ method: 'GET',
11069
+ headers: {
11070
+ 'Content-Type': 'application/json'
11071
+ }
11072
+ });
11073
+ case 1:
11074
+ response = _context4.v;
11075
+ if (response.ok) {
11076
+ _context4.n = 2;
11077
+ break;
11078
+ }
11079
+ console.error('[TTP Ecommerce] Failed to fetch /cart.js:', response.status);
11080
+ this._sendToVoiceSDK({
11081
+ t: 'cart_state_result',
11082
+ success: false,
11083
+ error: "Failed to fetch cart: HTTP ".concat(response.status)
11084
+ });
11085
+ return _context4.a(2);
11086
+ case 2:
11087
+ _context4.n = 3;
11088
+ return response.json();
11089
+ case 3:
11090
+ cart = _context4.v;
11091
+ this._sendToVoiceSDK({
11092
+ t: 'cart_state_result',
11093
+ success: true,
11094
+ items: (cart.items || []).map(function (item) {
11095
+ return {
11096
+ title: item.title,
11097
+ variant_title: item.variant_title,
11098
+ quantity: item.quantity,
11099
+ price: item.price,
11100
+ line_price: item.line_price,
11101
+ image: item.image,
11102
+ variant_id: item.variant_id,
11103
+ product_id: item.product_id
11104
+ };
11105
+ }),
11106
+ item_count: cart.item_count,
11107
+ total_price: cart.total_price,
11108
+ currency: cart.currency
11109
+ });
11110
+ console.log("[TTP Ecommerce] Cart state sent: ".concat(cart.item_count, " items, ").concat(cart.currency, " ").concat((cart.total_price / 100).toFixed(2)));
11111
+ _context4.n = 5;
11112
+ break;
11113
+ case 4:
11114
+ _context4.p = 4;
11115
+ _t3 = _context4.v;
11116
+ console.error('[TTP Ecommerce] Error fetching cart:', _t3);
11117
+ this._sendToVoiceSDK({
11118
+ t: 'cart_state_result',
11119
+ success: false,
11120
+ error: _t3.message || 'Failed to fetch cart'
11121
+ });
11122
+ case 5:
11123
+ return _context4.a(2);
11124
+ }
11125
+ }, _callee4, this, [[0, 4]]);
11126
+ }));
11127
+ function _handleGetStoreCart() {
11128
+ return _handleGetStoreCart2.apply(this, arguments);
11129
+ }
11130
+ return _handleGetStoreCart;
11131
+ }()
11132
+ /**
11133
+ * Add product to Shopify store cart via AJAX Cart API, then report result back to backend.
11134
+ * Must be done from the browser because only the browser has the store's session cookie.
11135
+ */
11136
+ }, {
11137
+ key: "_handleAddToStoreCart",
11138
+ value: (function () {
11139
+ var _handleAddToStoreCart2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5(data) {
11140
+ var variantId, quantity, productName, addResponse, errorText, addResult, cartResponse, cart, cartRefreshed, _t4;
11141
+ return _regenerator().w(function (_context5) {
11142
+ while (1) switch (_context5.p = _context5.n) {
11143
+ case 0:
11144
+ variantId = data.variantId, quantity = data.quantity;
11145
+ productName = '';
11146
+ _context5.p = 1;
11147
+ _context5.n = 2;
11071
11148
  return fetch('/cart/add.js', {
11072
11149
  method: 'POST',
11073
11150
  headers: {
@@ -11075,57 +11152,117 @@ var TTPEcommerceWidget = /*#__PURE__*/function () {
11075
11152
  },
11076
11153
  body: JSON.stringify({
11077
11154
  items: [{
11078
- id: parseInt(variantId, 10),
11155
+ id: parseInt(variantId),
11079
11156
  quantity: quantity || 1
11080
11157
  }]
11081
11158
  })
11082
11159
  });
11083
11160
  case 2:
11084
- response = _context4.v;
11085
- if (response.ok) {
11086
- _context4.n = 3;
11161
+ addResponse = _context5.v;
11162
+ if (addResponse.ok) {
11163
+ _context5.n = 4;
11087
11164
  break;
11088
11165
  }
11089
- console.error('[TTPEcommerceWidget] Failed to add to Shopify cart:', response.status, response.statusText);
11090
- return _context4.a(2);
11166
+ _context5.n = 3;
11167
+ return addResponse.text();
11091
11168
  case 3:
11092
- _context4.n = 4;
11093
- return response.json();
11094
- case 4:
11095
- cartResponse = _context4.v;
11096
- console.log('[TTPEcommerceWidget] Added to Shopify store cart:', cartResponse);
11097
- _context4.n = 5;
11098
- return fetch('/cart.js').then(function (r) {
11099
- return r.json();
11169
+ errorText = _context5.v;
11170
+ console.error('[TTP Ecommerce] /cart/add.js failed:', addResponse.status, errorText);
11171
+ this._sendToVoiceSDK({
11172
+ t: 'cart_add_result',
11173
+ success: false,
11174
+ error: "Cart add failed: HTTP ".concat(addResponse.status),
11175
+ productName: productName || String(variantId),
11176
+ quantity: quantity || 1
11100
11177
  });
11178
+ return _context5.a(2);
11179
+ case 4:
11180
+ _context5.n = 5;
11181
+ return addResponse.json();
11101
11182
  case 5:
11102
- cartData = _context4.v;
11183
+ addResult = _context5.v;
11184
+ if (addResult.items && addResult.items.length > 0) {
11185
+ productName = addResult.items[0].title || '';
11186
+ }
11187
+ _context5.n = 6;
11188
+ return fetch('/cart.js');
11189
+ case 6:
11190
+ cartResponse = _context5.v;
11191
+ _context5.n = 7;
11192
+ return cartResponse.json();
11193
+ case 7:
11194
+ cart = _context5.v;
11195
+ cartRefreshed = false;
11196
+ try {
11197
+ cartRefreshed = this._refreshCartCount(cart.item_count);
11198
+ } catch (e) {
11199
+ console.warn('[TTP Ecommerce] Cart count refresh failed (non-critical):', e);
11200
+ }
11103
11201
  this._handleCartUpdatedFromServer({
11104
11202
  action: 'added',
11105
11203
  product: {
11106
- id: variantId,
11107
- name: productName || ((_cartResponse$items = cartResponse.items) === null || _cartResponse$items === void 0 || (_cartResponse$items = _cartResponse$items[0]) === null || _cartResponse$items === void 0 ? void 0 : _cartResponse$items.title) || 'Product',
11108
- price: price || ((_cartResponse$items2 = cartResponse.items) === null || _cartResponse$items2 === void 0 || (_cartResponse$items2 = _cartResponse$items2[0]) === null || _cartResponse$items2 === void 0 ? void 0 : _cartResponse$items2.price) / 100 || 0
11204
+ name: productName,
11205
+ id: variantId
11109
11206
  },
11110
- cartTotal: cartData.total_price / 100,
11111
- cartItemCount: cartData.item_count
11207
+ cartTotal: cart.total_price / 100,
11208
+ cartItemCount: cart.item_count,
11209
+ currency: cart.currency
11112
11210
  });
11113
- _context4.n = 7;
11211
+ this._sendToVoiceSDK({
11212
+ t: 'cart_add_result',
11213
+ success: true,
11214
+ cartRefreshed: cartRefreshed,
11215
+ productName: productName,
11216
+ quantity: quantity || 1,
11217
+ cartTotal: cart.total_price,
11218
+ cartItemCount: cart.item_count,
11219
+ currency: cart.currency
11220
+ });
11221
+ console.log("[TTP Ecommerce] Cart add result sent: ".concat(productName, ", refreshed=").concat(cartRefreshed, ", ").concat(cart.item_count, " items"));
11222
+ _context5.n = 9;
11114
11223
  break;
11115
- case 6:
11116
- _context4.p = 6;
11117
- _t3 = _context4.v;
11118
- console.error('[TTPEcommerceWidget] Error adding to Shopify cart:', _t3);
11119
- case 7:
11120
- return _context4.a(2);
11224
+ case 8:
11225
+ _context5.p = 8;
11226
+ _t4 = _context5.v;
11227
+ console.error('[TTP Ecommerce] Error in _handleAddToStoreCart:', _t4);
11228
+ this._sendToVoiceSDK({
11229
+ t: 'cart_add_result',
11230
+ success: false,
11231
+ error: _t4.message || 'Failed to add to cart',
11232
+ productName: productName || String(variantId),
11233
+ quantity: quantity || 1
11234
+ });
11235
+ case 9:
11236
+ return _context5.a(2);
11121
11237
  }
11122
- }, _callee4, this, [[1, 6]]);
11238
+ }, _callee5, this, [[1, 8]]);
11123
11239
  }));
11124
11240
  function _handleAddToStoreCart(_x2) {
11125
11241
  return _handleAddToStoreCart2.apply(this, arguments);
11126
11242
  }
11127
11243
  return _handleAddToStoreCart;
11128
- }() // ═══════════════════════════════════════════
11244
+ }()
11245
+ /**
11246
+ * Simple cart count refresh — update common counter selectors.
11247
+ * Theme-specific refresh (Section Rendering API, etc.) can be added later per-theme.
11248
+ * @returns {boolean} Whether any element was updated
11249
+ */
11250
+ )
11251
+ }, {
11252
+ key: "_refreshCartCount",
11253
+ value: function _refreshCartCount(itemCount) {
11254
+ var refreshed = false;
11255
+ var selectors = ['.cart-count', '.cart-count-bubble', '[data-cart-count]', '.js-cart-count', '.cart-item-count', '#CartCount', '.site-header__cart-count', '.cart-count-tag'];
11256
+ selectors.forEach(function (selector) {
11257
+ document.querySelectorAll(selector).forEach(function (el) {
11258
+ el.textContent = itemCount;
11259
+ refreshed = true;
11260
+ });
11261
+ });
11262
+ return refreshed;
11263
+ }
11264
+
11265
+ // ═══════════════════════════════════════════
11129
11266
  // PRODUCT SELECTION (server manages cart)
11130
11267
  // ═══════════════════════════════════════════
11131
11268
  }, {
@@ -11181,45 +11318,45 @@ var TTPEcommerceWidget = /*#__PURE__*/function () {
11181
11318
  self.ecommerce.handleMessage(payload);
11182
11319
  },
11183
11320
  showProducts: function () {
11184
- var _showProducts = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5(query) {
11321
+ var _showProducts = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6(query) {
11185
11322
  var limit,
11186
11323
  sessionId,
11187
11324
  baseUrl,
11188
11325
  response,
11189
11326
  data,
11190
- _args5 = arguments,
11191
- _t4;
11192
- return _regenerator().w(function (_context5) {
11193
- while (1) switch (_context5.p = _context5.n) {
11327
+ _args6 = arguments,
11328
+ _t5;
11329
+ return _regenerator().w(function (_context6) {
11330
+ while (1) switch (_context6.p = _context6.n) {
11194
11331
  case 0:
11195
- limit = _args5.length > 1 && _args5[1] !== undefined ? _args5[1] : 5;
11196
- sessionId = _args5.length > 2 && _args5[2] !== undefined ? _args5[2] : 'test';
11332
+ limit = _args6.length > 1 && _args6[1] !== undefined ? _args6[1] : 5;
11333
+ sessionId = _args6.length > 2 && _args6[2] !== undefined ? _args6[2] : 'test';
11197
11334
  baseUrl = window.__TTP_MOCK_API__ || 'https://backend.talktopc.com';
11198
- _context5.p = 1;
11199
- _context5.n = 2;
11335
+ _context6.p = 1;
11336
+ _context6.n = 2;
11200
11337
  return fetch("".concat(baseUrl, "/api/partner/mock-store/products/search?q=").concat(encodeURIComponent(query), "&limit=").concat(limit, "&sessionId=").concat(encodeURIComponent(sessionId)));
11201
11338
  case 2:
11202
- response = _context5.v;
11203
- _context5.n = 3;
11339
+ response = _context6.v;
11340
+ _context6.n = 3;
11204
11341
  return response.json();
11205
11342
  case 3:
11206
- data = _context5.v;
11343
+ data = _context6.v;
11207
11344
  self.ecommerce.handleShowProducts({
11208
11345
  t: 'show_products',
11209
11346
  products: data.products,
11210
11347
  title: "".concat(data.totalCount, " results for \"").concat(query, "\""),
11211
11348
  layout: data.products.length <= 4 ? 'cards' : 'list'
11212
11349
  });
11213
- _context5.n = 5;
11350
+ _context6.n = 5;
11214
11351
  break;
11215
11352
  case 4:
11216
- _context5.p = 4;
11217
- _t4 = _context5.v;
11218
- console.error('[TTPEcommerceWidget] showProducts failed:', _t4);
11353
+ _context6.p = 4;
11354
+ _t5 = _context6.v;
11355
+ console.error('[TTPEcommerceWidget] showProducts failed:', _t5);
11219
11356
  case 5:
11220
- return _context5.a(2);
11357
+ return _context6.a(2);
11221
11358
  }
11222
- }, _callee5, null, [[1, 4]]);
11359
+ }, _callee6, null, [[1, 4]]);
11223
11360
  }));
11224
11361
  function showProducts(_x3) {
11225
11362
  return _showProducts.apply(this, arguments);
@@ -21150,6 +21287,9 @@ var TTPChatWidget = /*#__PURE__*/function () {
21150
21287
  // Callback to show error toast (for domain errors, etc.)
21151
21288
  onErrorToast: function onErrorToast(message, type) {
21152
21289
  _this.showErrorToast(message, type);
21290
+ },
21291
+ onMobileError: function onMobileError(message) {
21292
+ _this.showMobileLandingError(message);
21153
21293
  }
21154
21294
  });
21155
21295
  this.voiceInterface = new _VoiceInterface_js__WEBPACK_IMPORTED_MODULE_1__.VoiceInterface(voiceConfig);
@@ -21442,7 +21582,10 @@ var TTPChatWidget = /*#__PURE__*/function () {
21442
21582
  voiceCardIcon: cleanLandingConfig.voiceCardIcon || '🎤',
21443
21583
  textCardIcon: cleanLandingConfig.textCardIcon || '💬',
21444
21584
  voiceCardTitle: cleanLandingConfig.voiceCardTitle || null,
21445
- textCardTitle: cleanLandingConfig.textCardTitle || null
21585
+ textCardTitle: cleanLandingConfig.textCardTitle || null,
21586
+ callButtonText: cleanLandingConfig.callButtonText || null,
21587
+ chatButtonText: cleanLandingConfig.chatButtonText || null,
21588
+ statusText: cleanLandingConfig.statusText || null
21446
21589
  }, cleanLandingConfig);
21447
21590
  }(),
21448
21591
  // Header Configuration (top of panel)
@@ -21472,7 +21615,8 @@ var TTPChatWidget = /*#__PURE__*/function () {
21472
21615
  backgroundColor: cleanHeaderConfig.backgroundColor || '#7C3AED',
21473
21616
  // Default purple
21474
21617
  textColor: cleanHeaderConfig.textColor || '#FFFFFF',
21475
- showCloseButton: cleanHeaderConfig.showCloseButton !== false
21618
+ showCloseButton: cleanHeaderConfig.showCloseButton !== false,
21619
+ mobileLabel: cleanHeaderConfig.mobileLabel || 'Chat'
21476
21620
  }, cleanHeaderConfig);
21477
21621
  return finalHeader;
21478
21622
  }(),
@@ -21678,10 +21822,10 @@ var TTPChatWidget = /*#__PURE__*/function () {
21678
21822
  var resetCSS = '';
21679
21823
  if (this.config.useShadowDOM) {
21680
21824
  // Shadow DOM mode - use :host selector
21681
- resetCSS = "\n :host {\n all: initial;\n display: block;\n pointer-events: none;\n }\n img {\n max-width: none !important;\n }\n #text-chat-button img {\n width: 28px !important;\n height: 28px !important;\n }\n #text-chat-button {\n pointer-events: auto;\n }\n #text-chat-panel {\n pointer-events: auto;\n }\n ";
21825
+ resetCSS = "\n :host {\n all: initial;\n display: block;\n pointer-events: none;\n }\n img {\n max-width: none !important;\n }\n #text-chat-button img {\n width: 28px !important;\n height: 28px !important;\n }\n #text-chat-button {\n pointer-events: auto;\n }\n #text-chat-panel {\n pointer-events: auto;\n }\n .ttp-mobile-fab {\n pointer-events: auto;\n }\n #ttpMobileLanding {\n pointer-events: auto;\n }\n ";
21682
21826
  } else {
21683
21827
  // Regular DOM mode - targeted reset without breaking widget styles
21684
- 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;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n }\n \n /* Prevent theme CSS from affecting images */\n #text-chat-button img,\n #text-chat-panel img {\n max-width: none !important;\n width: auto;\n height: auto;\n }\n \n #text-chat-button img {\n width: 28px !important;\n height: 28px !important;\n }\n \n /* Ensure button and panel can receive clicks */\n #text-chat-button,\n #text-chat-panel {\n pointer-events: auto;\n }\n \n /* Reset any inherited text styles that might break layout */\n #text-chat-panel {\n text-align: left;\n line-height: normal;\n letter-spacing: normal;\n word-spacing: normal;\n text-transform: none;\n text-indent: 0;\n text-shadow: none;\n white-space: normal;\n }\n \n /* Ensure flexbox works properly */\n #text-chat-panel .widget-shell,\n #text-chat-panel .panel-inner,\n #text-chat-panel .widget-container,\n #text-chat-panel .landing-screen,\n #text-chat-panel .voice-interface,\n #text-chat-panel .text-interface,\n #text-chat-panel .widget-header,\n #text-chat-panel .mode-selection {\n display: flex;\n }\n \n #text-chat-panel .widget-shell,\n #text-chat-panel .panel-inner,\n #text-chat-panel .widget-container,\n #text-chat-panel .landing-screen,\n #text-chat-panel .voice-interface,\n #text-chat-panel .text-interface {\n flex-direction: column;\n }\n \n #text-chat-panel .mode-selection {\n flex-direction: row;\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 ";
21828
+ 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;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n }\n \n /* Prevent theme CSS from affecting images */\n #text-chat-button img,\n #text-chat-panel img {\n max-width: none !important;\n width: auto;\n height: auto;\n }\n \n #text-chat-button img {\n width: 28px !important;\n height: 28px !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;\n }\n \n /* Reset any inherited text styles that might break layout */\n #text-chat-panel {\n text-align: left;\n line-height: normal;\n letter-spacing: normal;\n word-spacing: normal;\n text-transform: none;\n text-indent: 0;\n text-shadow: none;\n white-space: normal;\n }\n \n /* Ensure flexbox works properly */\n #text-chat-panel .widget-shell,\n #text-chat-panel .panel-inner,\n #text-chat-panel .widget-container,\n #text-chat-panel .landing-screen,\n #text-chat-panel .voice-interface,\n #text-chat-panel .text-interface,\n #text-chat-panel .widget-header,\n #text-chat-panel .mode-selection {\n display: flex;\n }\n \n #text-chat-panel .widget-shell,\n #text-chat-panel .panel-inner,\n #text-chat-panel .widget-container,\n #text-chat-panel .landing-screen,\n #text-chat-panel .voice-interface,\n #text-chat-panel .text-interface {\n flex-direction: column;\n }\n \n #text-chat-panel .mode-selection {\n flex-direction: row;\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 ";
21685
21829
  }
21686
21830
  var widgetHTML = this.generateWidgetHTML();
21687
21831
  if (this.config.useShadowDOM) {
@@ -21850,7 +21994,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
21850
21994
  isPromptEnabled: isPromptEnabled,
21851
21995
  willGenerateHTML: !!promptBubbleHTML
21852
21996
  });
21853
- return "\n ".concat(styleTag, "\n \n ").concat(this.config.behavior.hidden ? '' : "\n <div id=\"text-chat-button-container\">\n ".concat(promptBubbleHTML, "\n ").concat(isPromptEnabled && promptConfig.showPulseRings !== false ? this.generatePulseRingsHTML(promptConfig) : '', "\n <button id=\"text-chat-button\" \n aria-label=\"").concat(this.config.accessibility.ariaLabel, "\"\n aria-description=\"").concat(this.config.accessibility.ariaDescription, "\">\n ").concat(iconHTML, "\n </button>\n </div>\n "), "\n \n <div id=\"text-chat-panel\">\n <div class=\"widget-shell\">\n <div class=\"panel-inner widget-container\" style=\"direction: ").concat(this.config.direction, ";\">\n <div class=\"widget-header\" style=\"background: ").concat(header.backgroundColor || '#7C3AED', " !important; color: ").concat(header.textColor || '#FFFFFF', " !important;\">\n <div>\n ").concat(header.showTitle ? "<div class=\"header-title\">".concat(header.title, "</div>") : '', "\n <div class=\"header-status\" style=\"color: ").concat(header.onlineIndicatorColor || 'rgba(255,255,255,0.7)', " !important;\">\n <span class=\"status-dot\" style=\"background: ").concat(header.onlineIndicatorDotColor || '#10b981', " !important;\"></span>\n <span>").concat(header.onlineIndicatorText !== undefined && header.onlineIndicatorText !== null ? header.onlineIndicatorText : t('online'), "</span>\n </div>\n </div>\n \n <div style=\"display: flex; gap: 6px; align-items: center; position: relative; z-index: 1;\">\n <!-- New Chat Button (hide on landing screen, show otherwise) -->\n <button class=\"header-icon new-chat-btn\" id=\"newChatBtn\" title=\"").concat(getTooltip('newChat'), "\" style=\"").concat(showLanding ? 'display: none;' : '', "\">\n <span style=\"font-size: 18px; font-weight: bold;\">+</span>\n </button>\n \n <!-- Back Button (only show in unified mode) -->\n ").concat(widgetMode === 'unified' ? "<button class=\"header-icon back-btn\" id=\"backBtn\" title=\"".concat(getTooltip('back'), "\" style=\"display: none;\">\n <span style=\"font-size: 16px;\">\u2039</span>\n </button>") : '', "\n \n <!-- Close Button -->\n ").concat(header.showCloseButton ? '<button class="header-icon close-btn" id="closeBtn" title="' + getTooltip('close') + '">' + '<span style="font-size: 18px; font-weight: bold;">×</span>' + '</button>' : '', "\n </div>\n </div>\n\n ").concat(showLanding && this.landingScreen ? this.landingScreen.generateHTML() : '', "\n\n ").concat(showVoice ? this.voiceInterface.generateHTML() : '', "\n ").concat(showText ? this.textInterface.generateHTML() : '', "\n ").concat(this.generateFooterHTML(), "\n </div>\n </div>\n </div>\n ");
21997
+ return "\n ".concat(styleTag, "\n \n ").concat(this.config.behavior.hidden ? '' : "\n <div id=\"text-chat-button-container\">\n ".concat(promptBubbleHTML, "\n ").concat(isPromptEnabled && promptConfig.showPulseRings !== false ? this.generatePulseRingsHTML(promptConfig) : '', "\n <button id=\"text-chat-button\" \n aria-label=\"").concat(this.config.accessibility.ariaLabel, "\"\n aria-description=\"").concat(this.config.accessibility.ariaDescription, "\">\n ").concat(iconHTML, "\n </button>\n <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 <div class=\"widget-header\" style=\"background: ").concat(header.backgroundColor || '#7C3AED', " !important; color: ").concat(header.textColor || '#FFFFFF', " !important;\">\n <div>\n ").concat(header.showTitle ? "<div class=\"header-title\">".concat(header.title, "</div>") : '', "\n <div class=\"header-status\" style=\"color: ").concat(header.onlineIndicatorColor || 'rgba(255,255,255,0.7)', " !important;\">\n <span class=\"status-dot\" style=\"background: ").concat(header.onlineIndicatorDotColor || '#10b981', " !important;\"></span>\n <span>").concat(header.onlineIndicatorText !== undefined && header.onlineIndicatorText !== null ? header.onlineIndicatorText : t('online'), "</span>\n </div>\n </div>\n \n <div style=\"display: flex; gap: 6px; align-items: center; position: relative; z-index: 1;\">\n <!-- New Chat Button (hide on landing screen, show otherwise) -->\n <button class=\"header-icon new-chat-btn\" id=\"newChatBtn\" title=\"").concat(getTooltip('newChat'), "\" style=\"").concat(showLanding ? 'display: none;' : '', "\">\n <span style=\"font-size: 18px; font-weight: bold;\">+</span>\n </button>\n \n <!-- Back Button (only show in unified mode) -->\n ").concat(widgetMode === 'unified' ? "<button class=\"header-icon back-btn\" id=\"backBtn\" title=\"".concat(getTooltip('back'), "\" style=\"display: none;\">\n <span style=\"font-size: 16px;\">\u2039</span>\n </button>") : '', "\n \n <!-- Close Button -->\n ").concat(header.showCloseButton ? '<button class="header-icon close-btn" id="closeBtn" title="' + getTooltip('close') + '">' + '<span style="font-size: 18px; font-weight: bold;">×</span>' + '</button>' : '', "\n </div>\n </div>\n\n ").concat(showLanding && this.landingScreen ? this.landingScreen.generateHTML() : '', "\n\n ").concat(showVoice ? this.voiceInterface.generateHTML() : '', "\n ").concat(showText ? this.textInterface.generateHTML() : '', "\n ").concat(this.generateFooterHTML(), "\n </div>\n </div>\n </div>\n ");
21854
21998
  }
21855
21999
 
21856
22000
  /**
@@ -21976,7 +22120,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
21976
22120
  // Note: Removed headerColor variable - landing screen colors now use explicit defaults
21977
22121
  // to prevent buttons from inheriting header backgroundColor
21978
22122
 
21979
- return "\n /* MOBILE FIRST - Default styles for all devices */\n #text-chat-widget {\n position: fixed !important;\n z-index: 10000;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n /* Mobile defaults */\n right: 10px;\n bottom: 10px;\n left: auto;\n top: auto;\n }\n \n /* Desktop positioning (only on larger screens) */\n @media (min-width: 769px) {\n #text-chat-widget {\n ".concat(positionStyles, "\n right: ").concat(this.config.position.horizontal === 'right' ? '20px' : 'auto', ";\n left: ").concat(this.config.position.horizontal === 'left' ? '20px' : 'auto', ";\n bottom: ").concat(this.config.position.vertical === 'bottom' ? '20px' : 'auto', ";\n top: ").concat(this.config.position.vertical === 'top' ? '20px' : 'auto', ";\n }\n }\n \n /* Mobile override (force mobile positioning) */\n @media (max-width: 768px) {\n #text-chat-widget {\n right: 10px !important;\n bottom: 10px !important;\n left: auto !important;\n top: auto !important;\n transform: none !important;\n }\n }\n \n @media (max-width: 480px) {\n #text-chat-widget {\n right: 8px !important;\n bottom: 8px !important;\n left: auto !important;\n top: auto !important;\n }\n }\n \n #text-chat-button {\n position: relative;\n width: ").concat(buttonSize, "px;\n height: ").concat(buttonSize, "px;\n margin: 0;\n flex-shrink: 0;\n border-radius: ").concat(btn.shape === 'circle' ? '50%' : btn.shape === 'square' ? '0' : '12px', ";\n background: ").concat(btn.backgroundColor || icon.backgroundColor || '#7C3AED', ";\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all ").concat(anim.duration, "s ease;\n box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);\n touch-action: manipulation;\n -webkit-tap-highlight-color: transparent;\n -webkit-touch-callout: none;\n user-select: none;\n min-width: 44px;\n min-height: 44px;\n z-index: 1;\n }\n \n @media (max-width: 768px) {\n #text-chat-widget {\n right: 10px !important;\n bottom: 10px !important;\n left: auto !important;\n top: auto !important;\n transform: none !important;\n }\n \n #text-chat-button-container {\n width: 56px !important;\n height: 56px !important;\n }\n \n #text-chat-button {\n width: 56px !important;\n height: 56px !important;\n min-width: 56px !important;\n min-height: 56px !important;\n max-width: 56px !important;\n max-height: 56px !important;\n }\n \n #text-chat-panel {\n position: fixed !important;\n left: 10px !important;\n right: 10px !important;\n bottom: 92px !important; /* 56px button + 20px gap + 16px footer */\n top: 60px !important; /* Add top spacing */\n width: auto !important;\n max-width: none !important;\n height: auto !important; /* Change from max-height to auto */\n max-height: none !important; /* Remove max-height */\n transform: none !important;\n margin: 0 !important;\n }\n \n #text-chat-panel .widget-header {\n padding: 10px 14px;\n min-height: 56px;\n }\n \n #text-chat-panel .header-title {\n font-size: 15px;\n }\n \n #text-chat-panel .header-icon {\n width: 40px;\n height: 40px;\n min-width: 40px;\n min-height: 40px;\n }\n \n #text-chat-input {\n font-size: 16px !important; /* Prevents iOS zoom on focus */\n padding: 12px 16px !important;\n min-height: 48px !important;\n }\n \n #text-chat-send {\n min-width: 48px !important;\n min-height: 48px !important;\n width: 48px !important;\n height: 48px !important;\n }\n \n .landing-screen {\n padding: 16px;\n }\n \n .landing-logo {\n font-size: 40px;\n }\n \n .landing-title {\n font-size: 18px;\n margin-bottom: 16px;\n }\n \n .mode-selection {\n flex-direction: column;\n gap: 12px;\n align-items: center;\n }\n \n .mode-card {\n max-width: 100%;\n width: 100%;\n padding: 16px;\n }\n \n .mode-card-icon {\n width: 50px;\n height: 50px;\n font-size: 28px;\n }\n \n .mode-card-title {\n font-size: 14px;\n }\n }\n \n @media (max-width: 480px) {\n #text-chat-widget {\n right: 8px !important;\n bottom: 8px !important;\n left: auto !important;\n top: auto !important;\n }\n \n #text-chat-button-container {\n width: 54px !important;\n height: 54px !important;\n }\n \n #text-chat-button {\n width: 54px !important;\n height: 54px !important;\n min-width: 54px !important;\n min-height: 54px !important;\n }\n \n #text-chat-panel {\n left: 8px !important;\n right: 8px !important;\n bottom: 86px !important; /* 54px button + 20px gap + 12px footer */\n top: 50px !important; /* Add top spacing for very small screens */\n height: auto !important;\n max-height: none !important;\n }\n \n #text-chat-panel .widget-header {\n padding: 8px 12px;\n min-height: 52px;\n }\n \n #text-chat-panel .header-title {\n font-size: 14px;\n }\n \n .landing-logo {\n font-size: 36px;\n }\n \n .landing-title {\n font-size: 16px;\n }\n }\n \n ").concat(anim.enableHover ? "\n #text-chat-button:hover {\n ".concat(btn.hoverColor ? "background: ".concat(btn.hoverColor, ";") : '', "\n transform: scale(1.05);\n box-shadow: 0 8px 20px rgba(102, 126, 234, 0.5);\n }\n ") : '', "\n \n /* Prompt Animation Keyframes */\n @keyframes widget-shimmer {\n 0% { transform: translateX(-100%); }\n 100% { transform: translateX(200%); }\n }\n \n @keyframes widget-ripple {\n 0% { transform: scale(1); opacity: 0.6; }\n 100% { transform: scale(2.5); opacity: 0; }\n }\n \n @keyframes widget-float {\n 0%, 100% { transform: translateX(-50%) translateY(0); }\n 50% { transform: translateX(-50%) translateY(-8px); }\n }\n \n @keyframes widget-bounce {\n 0%, 100% { transform: translateX(-50%) translateY(0); }\n 50% { transform: translateX(-50%) translateY(-10px); }\n }\n \n @keyframes widget-pulse-ring {\n 0% { transform: scale(1); opacity: 0.4; }\n 100% { transform: scale(1.8); opacity: 0; }\n }\n \n /* Prompt Bubble Container */\n #text-chat-button-container {\n position: fixed;\n ").concat(this.config.position.vertical === 'bottom' ? "bottom: ".concat(((_this$config$position = this.config.position.offset) === null || _this$config$position === void 0 ? void 0 : _this$config$position.y) || 20, "px;") : "top: ".concat(((_this$config$position2 = this.config.position.offset) === null || _this$config$position2 === void 0 ? void 0 : _this$config$position2.y) || 20, "px;"), "\n ").concat(this.config.position.horizontal === 'right' ? "right: ".concat(((_this$config$position3 = this.config.position.offset) === null || _this$config$position3 === void 0 ? void 0 : _this$config$position3.x) || 20, "px;") : "left: ".concat(((_this$config$position4 = this.config.position.offset) === null || _this$config$position4 === void 0 ? void 0 : _this$config$position4.x) || 20, "px;"), "\n width: ").concat(buttonSize, "px;\n height: ").concat(buttonSize, "px;\n z-index: 10001;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n \n @media (max-width: 768px) {\n #text-chat-button-container {\n right: 10px !important;\n bottom: 10px !important;\n left: auto !important;\n top: auto !important;\n }\n }\n \n @media (max-width: 480px) {\n #text-chat-button-container {\n right: 8px !important;\n bottom: 8px !important;\n left: auto !important;\n top: auto !important;\n }\n }\n \n /* Prompt Bubble Styles */\n .prompt-bubble {\n position: absolute;\n z-index: 10002;\n pointer-events: none;\n white-space: nowrap;\n }\n \n .prompt-bubble.top {\n bottom: calc(100% + 18px);\n left: 50%;\n transform: translateX(-50%);\n }\n \n .prompt-bubble.left {\n right: calc(100% + 12px);\n top: 50%;\n transform: translateY(-50%);\n }\n \n .prompt-bubble.right {\n left: calc(100% + 12px);\n top: 50%;\n transform: translateY(-50%);\n }\n \n /* Ensure animations preserve horizontal centering for top position */\n .prompt-bubble.top.animation-bounce {\n animation: widget-bounce 1s ease-in-out infinite;\n transform: translateX(-50%); /* Keep centering */\n }\n \n .prompt-bubble.top.animation-float {\n animation: widget-float 2s ease-in-out infinite;\n transform: translateX(-50%); /* Keep centering */\n }\n \n .prompt-bubble.top.animation-pulse {\n animation: pulse 2s ease-in-out infinite;\n transform: translateX(-50%); /* Keep centering */\n }\n \n .prompt-bubble-content {\n position: relative;\n padding: 8px 16px;\n border-radius: 20px;\n font-weight: 500;\n font-size: 14px;\n box-shadow: 0 4px 15px rgba(124, 58, 237, 0.3);\n overflow: hidden;\n }\n \n .prompt-bubble-shimmer {\n position: absolute;\n inset: 0;\n background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.25), transparent);\n animation: widget-shimmer 2s infinite;\n }\n \n .prompt-bubble.animation-bounce {\n animation: widget-bounce 1s ease-in-out infinite;\n }\n \n .prompt-bubble.animation-pulse {\n animation: pulse 2s ease-in-out infinite;\n }\n \n .prompt-bubble.animation-float {\n animation: widget-float 2s ease-in-out infinite;\n }\n \n /* Ensure top-positioned bubbles maintain horizontal centering during animations */\n .prompt-bubble.top.animation-bounce,\n .prompt-bubble.top.animation-float,\n .prompt-bubble.top.animation-pulse {\n /* Animation keyframes already include translateX(-50%) for centering */\n }\n \n /* Prompt Bubble Arrow */\n .prompt-bubble-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border: 8px solid transparent;\n }\n \n .prompt-bubble.top .prompt-bubble-arrow {\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n border-top-color: var(--prompt-bubble-bg-color, #7c3aed);\n border-bottom: none;\n margin-left: 0;\n }\n \n .prompt-bubble.left .prompt-bubble-arrow {\n left: 100%;\n top: 50%;\n transform: translateY(-50%);\n border-left-color: var(--prompt-bubble-bg-color, #7c3aed);\n border-right: none;\n }\n \n .prompt-bubble.right .prompt-bubble-arrow {\n right: 100%;\n top: 50%;\n transform: translateY(-50%);\n border-right-color: var(--prompt-bubble-bg-color, #7c3aed);\n border-left: none;\n }\n \n /* Pulse Rings */\n .prompt-pulse-rings {\n position: absolute;\n inset: 0;\n border-radius: 50%;\n pointer-events: none;\n }\n \n .prompt-pulse-ring {\n position: absolute;\n inset: 0;\n border-radius: 50%;\n animation: widget-pulse-ring 2s ease-out infinite;\n }\n \n .prompt-pulse-ring:nth-child(2) {\n animation-delay: 0.5s;\n }\n \n /* Mobile adjustments for prompt bubble */\n @media (max-width: 768px) {\n .prompt-bubble-content {\n font-size: 12px;\n padding: 6px 12px;\n }\n \n .prompt-bubble.top {\n bottom: calc(100% + 14px);\n }\n \n .prompt-bubble.left,\n .prompt-bubble.right {\n display: none; /* Hide side prompts on mobile */\n }\n }\n \n #text-chat-panel {\n display: none").concat(important, ";\n position: fixed;\n bottom: calc(").concat(buttonSize, "px + 20px + 20px); /* Button + gap + reduced footer offset */\n ").concat(this.config.position.horizontal === 'right' ? 'right: 20px;' : 'left: 20px;', "\n width: ").concat(panel.width, "px;\n max-width: calc(100vw - 40px);\n height: ").concat(panel.height, "px;\n max-height: calc(100vh - ").concat(buttonSize, "px - 40px - 20px); /* Account for footer height */\n background: transparent;\n border-radius: ").concat(panel.borderRadius, "px;\n border: none;\n flex-direction: column;\n overflow: hidden;\n ").concat(panel.backdropFilter ? "backdrop-filter: ".concat(panel.backdropFilter, ";") : '', "\n ").concat(anim.enableSlide ? "transition: all ".concat(anim.duration, "s ease;") : '', "\n box-sizing: border-box;\n }\n \n #text-chat-panel.open {\n display: flex").concat(important, ";\n ").concat(anim.enableSlide ? 'transform: translateY(0); opacity: 1;' : '', "\n }\n\n /* Shell for gradient border/background */\n .widget-shell { width: 100%; height: 100%; padding: 0; border-radius: ").concat(panel.borderRadius, "px; background: transparent; box-shadow: 0 20px 60px rgba(0,0,0,0.15); overflow: hidden; display: flex; flex-direction: column; box-sizing: border-box; }\n .panel-inner { width: 100%; height: 100%; background: #ffffff; border-radius: ").concat(panel.borderRadius, "px; border: ").concat(panel.border, "; overflow: hidden; display:flex; flex-direction: column; padding: 0; box-sizing: border-box; max-width: 100%; }\n\n /* New structure styles matching provided design */\n #text-chat-panel .widget-container {\n width: 100%; height: 100%; background: #FFFFFF; overflow: visible; display: flex; flex-direction: column; border-radius: ").concat(panel.borderRadius, "px;\n container-type: size;\n }\n \n /* Ensure content areas can scroll when height is constrained */\n #text-chat-panel .widget-container > .landing-screen,\n #text-chat-panel .widget-container > .voice-interface,\n #text-chat-panel .widget-container > .text-interface {\n flex: 1;\n overflow-y: auto;\n overflow-x: visible; /* Change from hidden to visible */\n }\n \n /* Header should not scroll */\n #text-chat-panel .widget-header {\n padding: 14px 16px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n border-top-left-radius: ").concat(panel.borderRadius, "px;\n border-top-right-radius: ").concat(panel.borderRadius, "px;\n flex-shrink: 0;\n box-sizing: border-box;\n position: relative;\n overflow: hidden;\n background: ").concat(header.backgroundColor || '#7C3AED').concat(important, ";\n color: ").concat(header.textColor || '#FFFFFF').concat(important, ";\n }\n \n #text-chat-panel .widget-header::before {\n content: '';\n position: absolute;\n top: -50%;\n right: -20%;\n width: 180px;\n height: 180px;\n background: radial-gradient(circle, rgba(255,255,255,0.08) 0%, transparent 70%);\n pointer-events: none;\n }\n \n #text-chat-panel .widget-header > div:first-child {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 4px;\n position: relative;\n z-index: 1;\n }\n \n #text-chat-panel .header-title { font-size: 15px; font-weight: 600; margin: 0; }\n #text-chat-panel .header-status { display: flex; align-items: center; gap: 5px; font-size: 12px; margin: 0; }\n #text-chat-panel .status-dot { width: 6px; height: 6px; border-radius: 50%; animation: pulse 2s ease-in-out infinite; }\n /* Online indicator customization - inline styles take precedence */\n @keyframes pulse { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.15); opacity: 0.8; } }\n /* Header icon buttons */\n .header-icon {\n background: rgba(255, 255, 255, 0.1);\n border: none;\n color: white;\n width: 34px;\n height: 34px;\n min-width: 34px;\n min-height: 34px;\n border-radius: 10px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.2s;\n flex-shrink: 0;\n font-size: 16px;\n padding: 0;\n box-sizing: border-box;\n position: relative;\n z-index: 1;\n }\n \n .header-icon:hover {\n background: rgba(255, 255, 255, 0.2);\n }\n \n .header-icon svg {\n pointer-events: none;\n stroke: white;\n fill: none;\n }\n \n .back-btn.visible {\n display: flex !important;\n }\n\n ").concat(showLanding && this.landingScreen ? this.landingScreen.generateCSS() : '', "\n\n ").concat(showVoice ? this.voiceInterface.generateCSS() : '', "\n ").concat(showText ? this.textInterface.generateCSS() : '', "\n \n /* Footer Branding */\n .widget-footer {\n box-sizing: border-box;\n }\n \n .footer-brand-link {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n }\n \n .footer-brand-link:hover {\n opacity: 0.9;\n }\n \n @media (max-width: 768px) {\n .widget-footer {\n height: 32px;\n }\n .widget-footer span {\n font-size: 10px;\n }\n .widget-footer span:last-child {\n font-size: 8px;\n }\n }\n \n #text-chat-send-hint {\n text-align: center;\n line-height: 1.4;\n }\n \n .agent-thinking {\n font-style: italic;\n color: #6B7280;\n }\n ");
22123
+ return "\n /* MOBILE FIRST - Default styles for all devices */\n #text-chat-widget {\n position: fixed !important;\n z-index: 10000;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n /* Mobile defaults */\n right: 10px;\n bottom: 10px;\n left: auto;\n top: auto;\n }\n \n /* Desktop positioning (only on larger screens) */\n @media (min-width: 769px) {\n #text-chat-widget {\n ".concat(positionStyles, "\n right: ").concat(this.config.position.horizontal === 'right' ? '20px' : 'auto', ";\n left: ").concat(this.config.position.horizontal === 'left' ? '20px' : 'auto', ";\n bottom: ").concat(this.config.position.vertical === 'bottom' ? '20px' : 'auto', ";\n top: ").concat(this.config.position.vertical === 'top' ? '20px' : 'auto', ";\n }\n }\n \n /* Mobile override (force mobile positioning) */\n @media (max-width: 768px) {\n #text-chat-widget {\n right: 10px !important;\n bottom: 10px !important;\n left: auto !important;\n top: auto !important;\n transform: none !important;\n }\n }\n \n @media (max-width: 480px) {\n #text-chat-widget {\n right: 8px !important;\n bottom: 8px !important;\n left: auto !important;\n top: auto !important;\n }\n }\n \n #text-chat-button {\n position: relative;\n width: ").concat(buttonSize, "px;\n height: ").concat(buttonSize, "px;\n margin: 0;\n flex-shrink: 0;\n border-radius: ").concat(btn.shape === 'circle' ? '50%' : btn.shape === 'square' ? '0' : '12px', ";\n background: ").concat(btn.backgroundColor || icon.backgroundColor || '#7C3AED', ";\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all ").concat(anim.duration, "s ease;\n box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);\n touch-action: manipulation;\n -webkit-tap-highlight-color: transparent;\n -webkit-touch-callout: none;\n user-select: none;\n min-width: 44px;\n min-height: 44px;\n z-index: 1;\n }\n \n @media (max-width: 768px) {\n #text-chat-widget {\n right: 10px !important;\n bottom: 10px !important;\n left: auto !important;\n top: auto !important;\n transform: none !important;\n }\n \n #text-chat-button-container {\n width: 56px !important;\n height: 56px !important;\n }\n \n #text-chat-button {\n width: 56px !important;\n height: 56px !important;\n min-width: 56px !important;\n min-height: 56px !important;\n max-width: 56px !important;\n max-height: 56px !important;\n }\n \n #text-chat-panel {\n position: fixed !important;\n left: 10px !important;\n right: 10px !important;\n bottom: 92px !important; /* 56px button + 20px gap + 16px footer */\n top: 60px !important; /* Add top spacing */\n width: auto !important;\n max-width: none !important;\n height: auto !important; /* Change from max-height to auto */\n max-height: none !important; /* Remove max-height */\n transform: none !important;\n margin: 0 !important;\n }\n \n #text-chat-panel .widget-header {\n padding: 10px 14px;\n min-height: 56px;\n }\n \n #text-chat-panel .header-title {\n font-size: 15px;\n }\n \n #text-chat-panel .header-icon {\n width: 40px;\n height: 40px;\n min-width: 40px;\n min-height: 40px;\n }\n \n #text-chat-input {\n font-size: 16px !important; /* Prevents iOS zoom on focus */\n padding: 12px 16px !important;\n min-height: 48px !important;\n }\n \n #text-chat-send {\n min-width: 48px !important;\n min-height: 48px !important;\n width: 48px !important;\n height: 48px !important;\n }\n \n .landing-screen {\n padding: 16px;\n }\n \n .landing-logo {\n font-size: 40px;\n }\n \n .landing-title {\n font-size: 18px;\n margin-bottom: 16px;\n }\n \n .mode-selection {\n flex-direction: column;\n gap: 12px;\n align-items: center;\n }\n \n .mode-card {\n max-width: 100%;\n width: 100%;\n padding: 16px;\n }\n \n .mode-card-icon {\n width: 50px;\n height: 50px;\n font-size: 28px;\n }\n \n .mode-card-title {\n font-size: 14px;\n }\n }\n \n @media (max-width: 480px) {\n #text-chat-widget {\n right: 8px !important;\n bottom: 8px !important;\n left: auto !important;\n top: auto !important;\n }\n \n #text-chat-button-container {\n width: 54px !important;\n height: 54px !important;\n }\n \n #text-chat-button {\n width: 54px !important;\n height: 54px !important;\n min-width: 54px !important;\n min-height: 54px !important;\n }\n \n #text-chat-panel {\n left: 8px !important;\n right: 8px !important;\n bottom: 86px !important; /* 54px button + 20px gap + 12px footer */\n top: 50px !important; /* Add top spacing for very small screens */\n height: auto !important;\n max-height: none !important;\n }\n \n #text-chat-panel .widget-header {\n padding: 8px 12px;\n min-height: 52px;\n }\n \n #text-chat-panel .header-title {\n font-size: 14px;\n }\n \n .landing-logo {\n font-size: 36px;\n }\n \n .landing-title {\n font-size: 16px;\n }\n }\n \n ").concat(anim.enableHover ? "\n #text-chat-button:hover {\n ".concat(btn.hoverColor ? "background: ".concat(btn.hoverColor, ";") : '', "\n transform: scale(1.05);\n box-shadow: 0 8px 20px rgba(102, 126, 234, 0.5);\n }\n ") : '', "\n \n /* Prompt Animation Keyframes */\n @keyframes widget-shimmer {\n 0% { transform: translateX(-100%); }\n 100% { transform: translateX(200%); }\n }\n \n @keyframes widget-ripple {\n 0% { transform: scale(1); opacity: 0.6; }\n 100% { transform: scale(2.5); opacity: 0; }\n }\n \n @keyframes widget-float {\n 0%, 100% { transform: translateX(-50%) translateY(0); }\n 50% { transform: translateX(-50%) translateY(-8px); }\n }\n \n @keyframes widget-bounce {\n 0%, 100% { transform: translateX(-50%) translateY(0); }\n 50% { transform: translateX(-50%) translateY(-10px); }\n }\n \n @keyframes widget-pulse-ring {\n 0% { transform: scale(1); opacity: 0.4; }\n 100% { transform: scale(1.8); opacity: 0; }\n }\n \n /* Prompt Bubble Container */\n #text-chat-button-container {\n position: fixed;\n ").concat(this.config.position.vertical === 'bottom' ? "bottom: ".concat(((_this$config$position = this.config.position.offset) === null || _this$config$position === void 0 ? void 0 : _this$config$position.y) || 20, "px;") : "top: ".concat(((_this$config$position2 = this.config.position.offset) === null || _this$config$position2 === void 0 ? void 0 : _this$config$position2.y) || 20, "px;"), "\n ").concat(this.config.position.horizontal === 'right' ? "right: ".concat(((_this$config$position3 = this.config.position.offset) === null || _this$config$position3 === void 0 ? void 0 : _this$config$position3.x) || 20, "px;") : "left: ".concat(((_this$config$position4 = this.config.position.offset) === null || _this$config$position4 === void 0 ? void 0 : _this$config$position4.x) || 20, "px;"), "\n width: ").concat(buttonSize, "px;\n height: ").concat(buttonSize, "px;\n z-index: 10001;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n \n @media (max-width: 768px) {\n #text-chat-button-container {\n right: 10px !important;\n bottom: 10px !important;\n left: auto !important;\n top: auto !important;\n }\n }\n \n @media (max-width: 480px) {\n #text-chat-button-container {\n right: 8px !important;\n bottom: 8px !important;\n left: auto !important;\n top: auto !important;\n }\n }\n \n /* Prompt Bubble Styles */\n .prompt-bubble {\n position: absolute;\n z-index: 10002;\n pointer-events: none;\n white-space: nowrap;\n }\n \n .prompt-bubble.top {\n bottom: calc(100% + 18px);\n left: 50%;\n transform: translateX(-50%);\n }\n \n .prompt-bubble.left {\n right: calc(100% + 12px);\n top: 50%;\n transform: translateY(-50%);\n }\n \n .prompt-bubble.right {\n left: calc(100% + 12px);\n top: 50%;\n transform: translateY(-50%);\n }\n \n /* Ensure animations preserve horizontal centering for top position */\n .prompt-bubble.top.animation-bounce {\n animation: widget-bounce 1s ease-in-out infinite;\n transform: translateX(-50%); /* Keep centering */\n }\n \n .prompt-bubble.top.animation-float {\n animation: widget-float 2s ease-in-out infinite;\n transform: translateX(-50%); /* Keep centering */\n }\n \n .prompt-bubble.top.animation-pulse {\n animation: pulse 2s ease-in-out infinite;\n transform: translateX(-50%); /* Keep centering */\n }\n \n .prompt-bubble-content {\n position: relative;\n padding: 8px 16px;\n border-radius: 20px;\n font-weight: 500;\n font-size: 14px;\n box-shadow: 0 4px 15px rgba(124, 58, 237, 0.3);\n overflow: hidden;\n }\n \n .prompt-bubble-shimmer {\n position: absolute;\n inset: 0;\n background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.25), transparent);\n animation: widget-shimmer 2s infinite;\n }\n \n .prompt-bubble.animation-bounce {\n animation: widget-bounce 1s ease-in-out infinite;\n }\n \n .prompt-bubble.animation-pulse {\n animation: pulse 2s ease-in-out infinite;\n }\n \n .prompt-bubble.animation-float {\n animation: widget-float 2s ease-in-out infinite;\n }\n \n /* Ensure top-positioned bubbles maintain horizontal centering during animations */\n .prompt-bubble.top.animation-bounce,\n .prompt-bubble.top.animation-float,\n .prompt-bubble.top.animation-pulse {\n /* Animation keyframes already include translateX(-50%) for centering */\n }\n \n /* Prompt Bubble Arrow */\n .prompt-bubble-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border: 8px solid transparent;\n }\n \n .prompt-bubble.top .prompt-bubble-arrow {\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n border-top-color: var(--prompt-bubble-bg-color, #7c3aed);\n border-bottom: none;\n margin-left: 0;\n }\n \n .prompt-bubble.left .prompt-bubble-arrow {\n left: 100%;\n top: 50%;\n transform: translateY(-50%);\n border-left-color: var(--prompt-bubble-bg-color, #7c3aed);\n border-right: none;\n }\n \n .prompt-bubble.right .prompt-bubble-arrow {\n right: 100%;\n top: 50%;\n transform: translateY(-50%);\n border-right-color: var(--prompt-bubble-bg-color, #7c3aed);\n border-left: none;\n }\n \n /* Pulse Rings */\n .prompt-pulse-rings {\n position: absolute;\n inset: 0;\n border-radius: 50%;\n pointer-events: none;\n }\n \n .prompt-pulse-ring {\n position: absolute;\n inset: 0;\n border-radius: 50%;\n animation: widget-pulse-ring 2s ease-out infinite;\n }\n \n .prompt-pulse-ring:nth-child(2) {\n animation-delay: 0.5s;\n }\n \n /* Mobile adjustments for prompt bubble */\n @media (max-width: 768px) {\n .prompt-bubble-content {\n font-size: 12px;\n padding: 6px 12px;\n }\n \n .prompt-bubble.top {\n bottom: calc(100% + 14px);\n }\n \n .prompt-bubble.left,\n .prompt-bubble.right {\n display: none; /* Hide side prompts on mobile */\n }\n }\n \n #text-chat-panel {\n display: none").concat(important, ";\n position: fixed;\n bottom: calc(").concat(buttonSize, "px + 20px + 20px); /* Button + gap + reduced footer offset */\n ").concat(this.config.position.horizontal === 'right' ? 'right: 20px;' : 'left: 20px;', "\n width: ").concat(panel.width, "px;\n max-width: calc(100vw - 40px);\n height: ").concat(panel.height, "px;\n max-height: calc(100vh - ").concat(buttonSize, "px - 40px - 20px); /* Account for footer height */\n background: transparent;\n border-radius: ").concat(panel.borderRadius, "px;\n border: none;\n flex-direction: column;\n overflow: hidden;\n ").concat(panel.backdropFilter ? "backdrop-filter: ".concat(panel.backdropFilter, ";") : '', "\n ").concat(anim.enableSlide ? "transition: all ".concat(anim.duration, "s ease;") : '', "\n box-sizing: border-box;\n }\n \n #text-chat-panel.open {\n display: flex").concat(important, ";\n ").concat(anim.enableSlide ? 'transform: translateY(0); opacity: 1;' : '', "\n }\n\n /* Shell for gradient border/background */\n .widget-shell { width: 100%; height: 100%; padding: 0; border-radius: ").concat(panel.borderRadius, "px; background: transparent; box-shadow: 0 20px 60px rgba(0,0,0,0.15); overflow: hidden; display: flex; flex-direction: column; box-sizing: border-box; }\n .panel-inner { width: 100%; height: 100%; background: #ffffff; border-radius: ").concat(panel.borderRadius, "px; border: ").concat(panel.border, "; overflow: hidden; display:flex; flex-direction: column; padding: 0; box-sizing: border-box; max-width: 100%; }\n\n /* New structure styles matching provided design */\n #text-chat-panel .widget-container {\n width: 100%; height: 100%; background: #FFFFFF; overflow: visible; display: flex; flex-direction: column; border-radius: ").concat(panel.borderRadius, "px;\n container-type: size;\n }\n \n /* Ensure content areas can scroll when height is constrained */\n #text-chat-panel .widget-container > .landing-screen,\n #text-chat-panel .widget-container > .voice-interface,\n #text-chat-panel .widget-container > .text-interface {\n flex: 1;\n overflow-y: auto;\n overflow-x: visible; /* Change from hidden to visible */\n }\n \n /* Header should not scroll */\n #text-chat-panel .widget-header {\n padding: 14px 16px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n border-top-left-radius: ").concat(panel.borderRadius, "px;\n border-top-right-radius: ").concat(panel.borderRadius, "px;\n flex-shrink: 0;\n box-sizing: border-box;\n position: relative;\n overflow: hidden;\n background: ").concat(header.backgroundColor || '#7C3AED').concat(important, ";\n color: ").concat(header.textColor || '#FFFFFF').concat(important, ";\n }\n \n #text-chat-panel .widget-header::before {\n content: '';\n position: absolute;\n top: -50%;\n right: -20%;\n width: 180px;\n height: 180px;\n background: radial-gradient(circle, rgba(255,255,255,0.08) 0%, transparent 70%);\n pointer-events: none;\n }\n \n #text-chat-panel .widget-header > div:first-child {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 4px;\n position: relative;\n z-index: 1;\n }\n \n #text-chat-panel .header-title { font-size: 15px; font-weight: 600; margin: 0; }\n #text-chat-panel .header-status { display: flex; align-items: center; gap: 5px; font-size: 12px; margin: 0; }\n #text-chat-panel .status-dot { width: 6px; height: 6px; border-radius: 50%; animation: pulse 2s ease-in-out infinite; }\n /* Online indicator customization - inline styles take precedence */\n @keyframes pulse { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.15); opacity: 0.8; } }\n /* Header icon buttons */\n .header-icon {\n background: rgba(255, 255, 255, 0.1);\n border: none;\n color: white;\n width: 34px;\n height: 34px;\n min-width: 34px;\n min-height: 34px;\n border-radius: 10px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.2s;\n flex-shrink: 0;\n font-size: 16px;\n padding: 0;\n box-sizing: border-box;\n position: relative;\n z-index: 1;\n }\n \n .header-icon:hover {\n background: rgba(255, 255, 255, 0.2);\n }\n \n .header-icon svg {\n pointer-events: none;\n stroke: white;\n fill: none;\n }\n \n .back-btn.visible {\n display: flex !important;\n }\n\n ").concat(showLanding && this.landingScreen ? this.landingScreen.generateCSS() : '', "\n\n ").concat(showVoice ? this.voiceInterface.generateCSS() : '', "\n ").concat(showText ? this.textInterface.generateCSS() : '', "\n \n /* Footer Branding */\n .widget-footer {\n box-sizing: border-box;\n }\n \n .footer-brand-link {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n }\n \n .footer-brand-link:hover {\n opacity: 0.9;\n }\n \n @media (max-width: 768px) {\n .widget-footer {\n height: 32px;\n }\n .widget-footer span {\n font-size: 10px;\n }\n .widget-footer span:last-child {\n font-size: 8px;\n }\n }\n \n #text-chat-send-hint {\n text-align: center;\n line-height: 1.4;\n }\n \n .agent-thinking {\n font-style: italic;\n color: #6B7280;\n }\n\n /* ========================================\n MOBILE PILL BUTTON & LANDING OVERLAY\n Hidden on desktop, shown on mobile only\n ======================================== */\n .ttp-mobile-fab {\n display: none;\n }\n\n .ttp-mobile-landing {\n display: none;\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 circle 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;\n align-items: center;\n gap: 10px;\n padding: 10px 16px 10px 12px;\n background: linear-gradient(135deg, #581c87, ").concat(header.backgroundColor || '#7C3AED', ");\n border: none;\n border-radius: 24px;\n cursor: pointer;\n box-shadow: 0 8px 24px rgba(88, 28, 135, 0.4);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n z-index: 1;\n font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, sans-serif;\n touch-action: manipulation;\n -webkit-tap-highlight-color: transparent;\n }\n\n .ttp-mobile-fab:hover {\n transform: translateY(-3px);\n box-shadow: 0 12px 32px rgba(88, 28, 135, 0.5);\n }\n\n .ttp-mobile-fab__icon-wrap {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.15);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n }\n\n .ttp-mobile-fab__waveform {\n display: flex;\n align-items: center;\n gap: 2px;\n height: 16px;\n }\n\n .ttp-mobile-fab__waveform .bar {\n width: 2px;\n background: #fff;\n border-radius: 1px;\n animation: ttpWaveAnimation 0.8s ease-in-out infinite;\n }\n\n .ttp-mobile-fab__waveform .bar:nth-child(1) { height: 5px; animation-delay: 0s; }\n .ttp-mobile-fab__waveform .bar:nth-child(2) { height: 10px; animation-delay: 0.1s; }\n .ttp-mobile-fab__waveform .bar:nth-child(3) { height: 16px; animation-delay: 0.2s; }\n .ttp-mobile-fab__waveform .bar:nth-child(4) { height: 8px; animation-delay: 0.3s; }\n .ttp-mobile-fab__waveform .bar:nth-child(5) { height: 12px; animation-delay: 0.4s; }\n\n .ttp-mobile-fab__label-wrap {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 1px;\n }\n\n .ttp-mobile-fab__label {\n color: #fff;\n font-size: 14px;\n font-weight: 600;\n line-height: 1.2;\n }\n\n .ttp-mobile-fab__status {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n color: rgba(255, 255, 255, 0.7);\n line-height: 1.2;\n }\n\n .ttp-mobile-fab__dot {\n width: 6px;\n height: 6px;\n background: ").concat(header.onlineIndicatorDotColor || '#10b981', ";\n border-radius: 50%;\n box-shadow: 0 0 6px rgba(16, 185, 129, 0.6);\n }\n\n /* ---- Mobile Landing Overlay ---- */\n .ttp-mobile-landing.active {\n display: block;\n position: fixed;\n bottom: 16px;\n left: 12px;\n right: 12px;\n background: linear-gradient(135deg, #581c87 0%, ").concat(header.backgroundColor || '#7C3AED', " 100%);\n border-radius: 20px;\n overflow: hidden;\n box-shadow:\n 0 10px 40px rgba(88, 28, 135, 0.4),\n 0 0 0 1px rgba(255, 255, 255, 0.1) inset;\n z-index: 10002;\n font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, sans-serif;\n }\n\n .ttp-mobile-landing::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 1px;\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;\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .ttp-mobile-landing__avatar {\n width: 44px;\n height: 44px;\n border-radius: 12px;\n background: rgba(255, 255, 255, 0.15);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n }\n\n .ttp-mobile-landing__waveform {\n display: flex;\n align-items: center;\n gap: 3px;\n height: 20px;\n }\n\n .ttp-mobile-landing__waveform .bar {\n width: 3px;\n background: rgba(255, 255, 255, 0.9);\n border-radius: 2px;\n animation: ttpWaveAnimation 0.8s ease-in-out infinite;\n }\n\n .ttp-mobile-landing__waveform .bar:nth-child(1) { height: 6px; animation-delay: 0s; }\n .ttp-mobile-landing__waveform .bar:nth-child(2) { height: 12px; animation-delay: 0.1s; }\n .ttp-mobile-landing__waveform .bar:nth-child(3) { height: 20px; animation-delay: 0.2s; }\n .ttp-mobile-landing__waveform .bar:nth-child(4) { height: 10px; animation-delay: 0.3s; }\n .ttp-mobile-landing__waveform .bar:nth-child(5) { height: 16px; animation-delay: 0.4s; }\n\n .ttp-mobile-landing__info {\n flex: 1;\n min-width: 0;\n }\n\n .ttp-mobile-landing__name {\n color: #fff;\n font-size: 15px;\n font-weight: 600;\n margin-bottom: 2px;\n }\n\n .ttp-mobile-landing__status {\n color: rgba(255, 255, 255, 0.7);\n font-size: 12px;\n display: flex;\n align-items: center;\n gap: 5px;\n }\n\n .ttp-mobile-landing__dot {\n width: 6px;\n height: 6px;\n background: ").concat(header.onlineIndicatorDotColor || '#10b981', ";\n border-radius: 50%;\n animation: ttpPulseAnimation 2s ease-in-out infinite;\n }\n\n .ttp-mobile-landing__close {\n width: 32px;\n height: 32px;\n border-radius: 10px;\n background: rgba(255, 255, 255, 0.1);\n border: none;\n color: rgba(255, 255, 255, 0.7);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.2s;\n flex-shrink: 0;\n }\n\n .ttp-mobile-landing__close:hover {\n background: rgba(255, 255, 255, 0.2);\n color: #fff;\n }\n\n .ttp-mobile-landing__error {\n margin: 0 14px 10px;\n padding: 10px 12px;\n background: #fef2f2;\n border: 1px solid #fecaca;\n border-radius: 10px;\n display: flex;\n align-items: flex-start;\n gap: 8px;\n color: #b91c1c;\n font-size: 13px;\n line-height: 1.4;\n }\n .ttp-mobile-landing__error svg {\n flex-shrink: 0;\n margin-top: 1px;\n stroke: #dc2626;\n }\n\n .ttp-mobile-landing__actions {\n padding: 0 14px 14px;\n display: flex;\n gap: 10px;\n }\n\n .ttp-mobile-landing__btn {\n flex: 1;\n padding: 14px;\n border-radius: 12px;\n border: none;\n cursor: pointer;\n font-family: inherit;\n font-size: 14px;\n font-weight: 600;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 10px;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n touch-action: manipulation;\n -webkit-tap-highlight-color: transparent;\n }\n\n .ttp-mobile-landing__btn svg {\n width: 20px;\n height: 20px;\n flex-shrink: 0;\n }\n\n .ttp-mobile-landing__btn--call {\n background: #fff;\n color: ").concat(header.backgroundColor || '#7C3AED', ";\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n }\n\n .ttp-mobile-landing__btn--call:hover {\n transform: translateY(-2px);\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);\n }\n\n .ttp-mobile-landing__btn--text {\n background: rgba(255, 255, 255, 0.15);\n color: #fff;\n border: 1px solid rgba(255, 255, 255, 0.1);\n }\n\n .ttp-mobile-landing__btn--text:hover {\n background: rgba(255, 255, 255, 0.2);\n border-color: rgba(255, 255, 255, 0.2);\n }\n\n .ttp-mobile-landing__footer {\n padding: 10px 16px;\n display: flex;\n justify-content: center;\n border-top: 1px solid rgba(255, 255, 255, 0.08);\n }\n\n .ttp-mobile-landing__powered {\n color: rgba(255, 255, 255, 0.4);\n font-size: 11px;\n display: flex;\n align-items: center;\n gap: 4px;\n }\n\n .ttp-mobile-landing__powered svg {\n width: 10px;\n height: 10px;\n color: #f59e0b;\n }\n\n .ttp-mobile-landing__powered a {\n color: rgba(255, 255, 255, 0.6);\n text-decoration: none;\n }\n\n .ttp-mobile-landing__powered a:hover {\n color: #fff;\n }\n }\n ");
21980
22124
  }
21981
22125
  }, {
21982
22126
  key: "setupWidgetEvents",
@@ -22047,7 +22191,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
22047
22191
  this.landingScreen.setupEventHandlers({
22048
22192
  onSelectVoice: function () {
22049
22193
  var _onSelectVoice = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
22050
- var _this6$voiceInterface4, _this6$voiceInterface8, _this6$shadowRoot, _this6$voiceInterface5, _this6$shadowRoot2, _this6$voiceInterface6, panel, idleState, floatingButton, _this6$voiceInterface7, _this6$voiceInterface9, _this6$voiceInterface1, _this6$config$behavio, _idleState, isDomainError, statusTitle, _this6$voiceInterface0, titleText, domainErrorTitle, _widgetMode, _this6$voiceInterface11, _this6$voiceInterface12, _this6$config$behavio2, _this6$voiceInterface10, _this6$voiceInterface13, _this6$shadowRoot3, existingBar, _floatingButton, _widgetMode2, _t;
22194
+ var _this6$voiceInterface4, _this6$voiceInterface8, _this6$shadowRoot, _this6$voiceInterface5, _this6$shadowRoot2, _this6$shadowRoot3, _this6$voiceInterface6, panel, idleState, floatingButton, mobileFab, _this6$voiceInterface7, _this6$voiceInterface9, _this6$voiceInterface1, _this6$config$behavio, _idleState, isDomainError, statusTitle, _this6$voiceInterface0, titleText, domainErrorTitle, _widgetMode, _this6$voiceInterface11, _this6$voiceInterface12, _this6$config$behavio2, _this6$voiceInterface10, _this6$voiceInterface13, _this6$shadowRoot4, _this6$shadowRoot5, existingBar, _floatingButton, _mobileFab, _widgetMode2, _t;
22051
22195
  return _regenerator().w(function (_context) {
22052
22196
  while (1) switch (_context.p = _context.n) {
22053
22197
  case 0:
@@ -22097,6 +22241,10 @@ var TTPChatWidget = /*#__PURE__*/function () {
22097
22241
  if (floatingButton) {
22098
22242
  floatingButton.style.display = 'none';
22099
22243
  }
22244
+ mobileFab = (_this6$shadowRoot3 = _this6.shadowRoot) === null || _this6$shadowRoot3 === void 0 ? void 0 : _this6$shadowRoot3.querySelector('.ttp-mobile-fab');
22245
+ if (mobileFab) {
22246
+ mobileFab.style.display = 'none';
22247
+ }
22100
22248
  // Create minimized bar with connecting state
22101
22249
  if (!((_this6$voiceInterface6 = _this6.voiceInterface) !== null && _this6$voiceInterface6 !== void 0 && _this6$voiceInterface6.createMobileMinimizedBar)) {
22102
22250
  _context.n = 3;
@@ -22206,10 +22354,14 @@ var TTPChatWidget = /*#__PURE__*/function () {
22206
22354
  _this6.voiceInterface.removeMobileMinimizedBar();
22207
22355
  }
22208
22356
  // Restore floating button if it was hidden
22209
- _floatingButton = ((_this6$shadowRoot3 = _this6.shadowRoot) === null || _this6$shadowRoot3 === void 0 ? void 0 : _this6$shadowRoot3.getElementById('text-chat-button')) || document.getElementById('text-chat-button');
22357
+ _floatingButton = ((_this6$shadowRoot4 = _this6.shadowRoot) === null || _this6$shadowRoot4 === void 0 ? void 0 : _this6$shadowRoot4.getElementById('text-chat-button')) || document.getElementById('text-chat-button');
22210
22358
  if (_floatingButton) {
22211
22359
  _floatingButton.style.display = '';
22212
22360
  }
22361
+ _mobileFab = (_this6$shadowRoot5 = _this6.shadowRoot) === null || _this6$shadowRoot5 === void 0 ? void 0 : _this6$shadowRoot5.querySelector('.ttp-mobile-fab');
22362
+ if (_mobileFab) {
22363
+ _mobileFab.style.display = '';
22364
+ }
22213
22365
  }
22214
22366
 
22215
22367
  // Show user-friendly error message (unless it's a user cancellation)
@@ -22302,6 +22454,9 @@ var TTPChatWidget = /*#__PURE__*/function () {
22302
22454
  }
22303
22455
  }
22304
22456
 
22457
+ // Mobile floating button & landing overlay
22458
+ this.setupMobileWidgetEvents();
22459
+
22305
22460
  // Keyboard navigation
22306
22461
  if (this.config.accessibility.keyboardNavigation) {
22307
22462
  this.setupKeyboardNavigation();
@@ -22385,13 +22540,83 @@ var TTPChatWidget = /*#__PURE__*/function () {
22385
22540
  // Hide new chat button on voice interface (not applicable)
22386
22541
  if (newChatBtn) newChatBtn.style.display = 'none';
22387
22542
  }
22543
+ }, {
22544
+ key: "setupMobileWidgetEvents",
22545
+ value: function setupMobileWidgetEvents() {
22546
+ var _this7 = this;
22547
+ if (!this.shadowRoot) return;
22548
+ var mobileFab = this.shadowRoot.querySelector('.ttp-mobile-fab');
22549
+ var mobileLanding = this.shadowRoot.getElementById('ttpMobileLanding');
22550
+ if (!mobileFab || !mobileLanding) return;
22551
+ var closeMobileLanding = function closeMobileLanding() {
22552
+ mobileLanding.classList.remove('active');
22553
+ mobileFab.style.display = '';
22554
+ _this7.isMobileLandingOpen = false;
22555
+ };
22556
+ var openMobileLanding = function openMobileLanding() {
22557
+ if (_this7.config.promptAnimation.hideAfterClick) {
22558
+ _this7.hidePrompt();
22559
+ }
22560
+ // Clear any previous error banner
22561
+ var errorBanner = _this7.shadowRoot.getElementById('ttpMobileLandingError');
22562
+ if (errorBanner) errorBanner.style.display = 'none';
22563
+ mobileFab.style.display = 'none';
22564
+ mobileLanding.classList.add('active');
22565
+ _this7.isMobileLandingOpen = true;
22566
+ };
22567
+ mobileFab.onclick = openMobileLanding;
22568
+ var mobileClose = mobileLanding.querySelector('.ttp-mobile-landing__close');
22569
+ if (mobileClose) {
22570
+ mobileClose.onclick = closeMobileLanding;
22571
+ }
22572
+ var mobileCallBtn = this.shadowRoot.getElementById('ttpMobileCallBtn');
22573
+ if (mobileCallBtn) {
22574
+ mobileCallBtn.onclick = function () {
22575
+ closeMobileLanding();
22576
+ var desktopVoiceCard = _this7.shadowRoot.getElementById('mode-card-voice');
22577
+ if (desktopVoiceCard) {
22578
+ desktopVoiceCard.click();
22579
+ } else {
22580
+ _this7.showVoice();
22581
+ }
22582
+ };
22583
+ }
22584
+ var mobileChatBtn = this.shadowRoot.getElementById('ttpMobileChatBtn');
22585
+ if (mobileChatBtn) {
22586
+ mobileChatBtn.onclick = function () {
22587
+ closeMobileLanding();
22588
+ var desktopTextCard = _this7.shadowRoot.getElementById('mode-card-text');
22589
+ if (desktopTextCard) {
22590
+ desktopTextCard.click();
22591
+ } else {
22592
+ _this7.showText();
22593
+ }
22594
+ };
22595
+ }
22596
+
22597
+ // Close mobile landing on outside click
22598
+ document.addEventListener('click', function (e) {
22599
+ if (!_this7.isMobileLandingOpen) return;
22600
+ var path = e.composedPath();
22601
+ if (!path.includes(mobileLanding) && !path.includes(mobileFab)) {
22602
+ closeMobileLanding();
22603
+ }
22604
+ });
22605
+
22606
+ // Close mobile landing on Escape
22607
+ document.addEventListener('keydown', function (e) {
22608
+ if (e.key === 'Escape' && _this7.isMobileLandingOpen) {
22609
+ closeMobileLanding();
22610
+ }
22611
+ });
22612
+ }
22388
22613
  }, {
22389
22614
  key: "setupKeyboardNavigation",
22390
22615
  value: function setupKeyboardNavigation() {
22391
- var _this7 = this;
22616
+ var _this8 = this;
22392
22617
  document.addEventListener('keydown', function (e) {
22393
- if (e.key === 'Escape' && _this7.isOpen) {
22394
- _this7.togglePanel();
22618
+ if (e.key === 'Escape' && _this8.isOpen) {
22619
+ _this8.togglePanel();
22395
22620
  }
22396
22621
  });
22397
22622
  }
@@ -22402,7 +22627,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
22402
22627
  }, {
22403
22628
  key: "setupPromptAnimation",
22404
22629
  value: function setupPromptAnimation() {
22405
- var _this8 = this;
22630
+ var _this9 = this;
22406
22631
  if (!this.shadowRoot) return;
22407
22632
  var promptConfig = this.config.promptAnimation || {};
22408
22633
  // Default to disabled if not specified (enabled === true means explicitly enabled)
@@ -22432,7 +22657,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
22432
22657
  // Auto-hide after configured seconds (only if widget is closed)
22433
22658
  if (!this.isOpen && promptConfig.hideAfterSeconds !== null && promptConfig.hideAfterSeconds > 0) {
22434
22659
  this.promptAutoHideTimer = setTimeout(function () {
22435
- _this8.hidePrompt();
22660
+ _this9.hidePrompt();
22436
22661
  }, promptConfig.hideAfterSeconds * 1000);
22437
22662
  }
22438
22663
 
@@ -22444,7 +22669,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
22444
22669
  // Wrap the callback to also hide pulse rings
22445
22670
  this.config.onConversationStart = function () {
22446
22671
  // Hide pulse rings when call starts
22447
- var pulseRings = _this8.shadowRoot.getElementById('prompt-pulse-rings');
22672
+ var pulseRings = _this9.shadowRoot.getElementById('prompt-pulse-rings');
22448
22673
  if (pulseRings) pulseRings.style.display = 'none';
22449
22674
 
22450
22675
  // Call original callback if it exists
@@ -22456,7 +22681,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
22456
22681
  // Also listen to recordingStarted event from SDK if available
22457
22682
  if (this.voiceInterface.sdk.voiceSDK) {
22458
22683
  this.voiceInterface.sdk.voiceSDK.on('recordingStarted', function () {
22459
- var pulseRings = _this8.shadowRoot.getElementById('prompt-pulse-rings');
22684
+ var pulseRings = _this9.shadowRoot.getElementById('prompt-pulse-rings');
22460
22685
  if (pulseRings) pulseRings.style.display = 'none';
22461
22686
  });
22462
22687
  }
@@ -22504,7 +22729,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
22504
22729
  }, {
22505
22730
  key: "showPrompt",
22506
22731
  value: function showPrompt() {
22507
- var _this9 = this;
22732
+ var _this0 = this;
22508
22733
  if (!this.shadowRoot) return;
22509
22734
  var promptConfig = this.config.promptAnimation || {};
22510
22735
  // Default to enabled if not specified
@@ -22524,8 +22749,8 @@ var TTPChatWidget = /*#__PURE__*/function () {
22524
22749
  // Function to actually show the elements
22525
22750
  var doShow = function doShow() {
22526
22751
  // Show prompt bubble (check both shadow root and document for compatibility)
22527
- var promptBubble = _this9.shadowRoot.getElementById('prompt-bubble');
22528
- if (!promptBubble && _this9.shadowRoot !== document) {
22752
+ var promptBubble = _this0.shadowRoot.getElementById('prompt-bubble');
22753
+ if (!promptBubble && _this0.shadowRoot !== document) {
22529
22754
  promptBubble = document.getElementById('prompt-bubble');
22530
22755
  }
22531
22756
  if (promptBubble) {
@@ -22539,8 +22764,8 @@ var TTPChatWidget = /*#__PURE__*/function () {
22539
22764
 
22540
22765
  // Show pulse rings if enabled
22541
22766
  if (promptConfig.showPulseRings !== false) {
22542
- var _pulseRings = _this9.shadowRoot.getElementById('prompt-pulse-rings');
22543
- if (!_pulseRings && _this9.shadowRoot !== document) {
22767
+ var _pulseRings = _this0.shadowRoot.getElementById('prompt-pulse-rings');
22768
+ if (!_pulseRings && _this0.shadowRoot !== document) {
22544
22769
  _pulseRings = document.getElementById('prompt-pulse-rings');
22545
22770
  }
22546
22771
  if (_pulseRings) {
@@ -22577,7 +22802,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
22577
22802
  }
22578
22803
  // Start new timer
22579
22804
  this.promptAutoHideTimer = setTimeout(function () {
22580
- _this9.hidePrompt();
22805
+ _this0.hidePrompt();
22581
22806
  }, promptConfig.hideAfterSeconds * 1000);
22582
22807
  }
22583
22808
  }
@@ -22593,7 +22818,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
22593
22818
  }, {
22594
22819
  key: "_doTogglePanel",
22595
22820
  value: function _doTogglePanel() {
22596
- var _this0 = this;
22821
+ var _this1 = this;
22597
22822
  if (!this.shadowRoot) return;
22598
22823
  this.isOpen = !this.isOpen;
22599
22824
  var panel = this.shadowRoot.getElementById('text-chat-panel');
@@ -22606,7 +22831,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
22606
22831
  // Panel is opening - hide prompt
22607
22832
  this.hidePrompt();
22608
22833
  setTimeout(function () {
22609
- var input = _this0.shadowRoot.getElementById('messageInput');
22834
+ var input = _this1.shadowRoot.getElementById('messageInput');
22610
22835
  if (input) input.focus();
22611
22836
  }, 100);
22612
22837
  } else {
@@ -22614,14 +22839,14 @@ var TTPChatWidget = /*#__PURE__*/function () {
22614
22839
  // Call showPrompt immediately, then also retry after a delay to ensure it's visible
22615
22840
  this.showPrompt();
22616
22841
  setTimeout(function () {
22617
- var _this0$config$promptA;
22842
+ var _this1$config$promptA;
22618
22843
  // Double-check and ensure prompt is visible
22619
- var promptBubble = _this0.shadowRoot.getElementById('prompt-bubble');
22844
+ var promptBubble = _this1.shadowRoot.getElementById('prompt-bubble');
22620
22845
  if (promptBubble && promptBubble.style.display === 'none') {
22621
22846
  promptBubble.style.display = 'block';
22622
22847
  }
22623
- var pulseRings = _this0.shadowRoot.getElementById('prompt-pulse-rings');
22624
- if (pulseRings && ((_this0$config$promptA = _this0.config.promptAnimation) === null || _this0$config$promptA === void 0 ? void 0 : _this0$config$promptA.showPulseRings) !== false) {
22848
+ var pulseRings = _this1.shadowRoot.getElementById('prompt-pulse-rings');
22849
+ if (pulseRings && ((_this1$config$promptA = _this1.config.promptAnimation) === null || _this1$config$promptA === void 0 ? void 0 : _this1$config$promptA.showPulseRings) !== false) {
22625
22850
  if (pulseRings.style.display === 'none') {
22626
22851
  pulseRings.style.display = 'block';
22627
22852
  }
@@ -22661,13 +22886,14 @@ var TTPChatWidget = /*#__PURE__*/function () {
22661
22886
  padding: '12px 24px',
22662
22887
  borderRadius: '8px',
22663
22888
  boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
22664
- zIndex: '10000',
22889
+ zIndex: '10003',
22665
22890
  fontSize: '14px',
22666
22891
  fontWeight: '500',
22667
22892
  maxWidth: '90%',
22668
22893
  textAlign: 'center',
22669
22894
  animation: 'slideUp 0.3s ease-out',
22670
- fontFamily: 'inherit'
22895
+ fontFamily: 'inherit',
22896
+ pointerEvents: 'auto'
22671
22897
  });
22672
22898
 
22673
22899
  // Add CSS animation if not already added
@@ -22692,6 +22918,25 @@ var TTPChatWidget = /*#__PURE__*/function () {
22692
22918
  }, 300);
22693
22919
  }, 4000);
22694
22920
  }
22921
+ }, {
22922
+ key: "showMobileLandingError",
22923
+ value: function showMobileLandingError(message) {
22924
+ if (!this.shadowRoot) return;
22925
+ var mobileLanding = this.shadowRoot.getElementById('ttpMobileLanding');
22926
+ var mobileFab = this.shadowRoot.querySelector('.ttp-mobile-fab');
22927
+ var errorBanner = this.shadowRoot.getElementById('ttpMobileLandingError');
22928
+ if (!mobileLanding || !errorBanner) return;
22929
+
22930
+ // Set error text
22931
+ var errorText = errorBanner.querySelector('.ttp-mobile-landing__error-text');
22932
+ if (errorText) errorText.textContent = message;
22933
+ errorBanner.style.display = 'flex';
22934
+
22935
+ // Show the mobile landing overlay with the error
22936
+ mobileLanding.classList.add('active');
22937
+ if (mobileFab) mobileFab.style.display = 'none';
22938
+ this.isMobileLandingOpen = true;
22939
+ }
22695
22940
 
22696
22941
  /**
22697
22942
  * Show confirmation modal (reusing modal pattern)
@@ -23366,12 +23611,12 @@ var TTPChatWidget = /*#__PURE__*/function () {
23366
23611
  key: "_flushPendingClientTools",
23367
23612
  value: function _flushPendingClientTools() {
23368
23613
  var _this$voiceInterface1,
23369
- _this1 = this;
23614
+ _this10 = this;
23370
23615
  if (this._pendingClientTools && (_this$voiceInterface1 = this.voiceInterface) !== null && _this$voiceInterface1 !== void 0 && _this$voiceInterface1.sdk) {
23371
23616
  this._pendingClientTools.forEach(function (_ref2) {
23372
23617
  var name = _ref2.name,
23373
23618
  handler = _ref2.handler;
23374
- _this1.voiceInterface.sdk.registerToolHandler(name, handler);
23619
+ _this10.voiceInterface.sdk.registerToolHandler(name, handler);
23375
23620
  });
23376
23621
  this._pendingClientTools = null;
23377
23622
  console.log('TTPChatWidget: Flushed pending client tools');
@@ -24560,7 +24805,7 @@ var VoiceInterface = /*#__PURE__*/function () {
24560
24805
  value: (function () {
24561
24806
  var _proceedWithVoiceCall = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5() {
24562
24807
  var _this3 = this;
24563
- var isResumeCall, panel, header, toggleText, _voiceInterface, originalSection, compactSection, idleState, _panel, fallbackPanel, sampleRate, mediaStream, floatingButton, fallbackButton, existingBar, _floatingButton, _fallbackButton, _idleState, _panel2, _fallbackPanel, deviceInfo, _idleState2, activeState, voiceInterface, connected, serverRejected, originalOnError, originalOnDisconnected, attempts, _this$sdk$voiceSDK, error, _existingBar, _existingBar2, _idleState3, _panel3, _fallbackPanel2, _floatingButton2, _fallbackButton2, updateTimer, _existingBar3, _existingBar4, _idleState4, _panel4, _fallbackPanel3, _floatingButton3, _fallbackButton3, _updateTimer, _deviceInfo, _t2, _t3, _t4, _t5, _t6, _t7;
24808
+ var isResumeCall, panel, header, toggleText, _voiceInterface, originalSection, compactSection, idleState, _panel, fallbackPanel, sampleRate, mediaStream, floatingButton, fallbackButton, mobileFabGrant, existingBar, _floatingButton, _fallbackButton, mobileFabDeny, _idleState, _panel2, _fallbackPanel, deviceInfo, _idleState2, activeState, voiceInterface, connected, serverRejected, originalOnError, originalOnDisconnected, attempts, _this$sdk$voiceSDK, error, _existingBar, _existingBar2, _idleState3, _panel3, _fallbackPanel2, _floatingButton2, _fallbackButton2, updateTimer, _existingBar3, _existingBar4, _idleState4, _panel4, _fallbackPanel3, _floatingButton3, _fallbackButton3, _updateTimer, _deviceInfo, _t2, _t3, _t4, _t5, _t6, _t7;
24564
24809
  return _regenerator().w(function (_context5) {
24565
24810
  while (1) switch (_context5.p = _context5.n) {
24566
24811
  case 0:
@@ -24667,6 +24912,8 @@ var VoiceInterface = /*#__PURE__*/function () {
24667
24912
  console.log('✅ Floating button hidden (permission granted, fallback)');
24668
24913
  }
24669
24914
  }
24915
+ mobileFabGrant = this.shadowRoot.querySelector('.ttp-mobile-fab');
24916
+ if (mobileFabGrant) mobileFabGrant.style.display = 'none';
24670
24917
  _context5.n = 4;
24671
24918
  break;
24672
24919
  case 3:
@@ -24692,6 +24939,8 @@ var VoiceInterface = /*#__PURE__*/function () {
24692
24939
  _fallbackButton.style.display = '';
24693
24940
  }
24694
24941
  }
24942
+ mobileFabDeny = this.shadowRoot.querySelector('.ttp-mobile-fab');
24943
+ if (mobileFabDeny) mobileFabDeny.style.display = '';
24695
24944
  _idleState = this.shadowRoot.getElementById('voiceIdleState');
24696
24945
  if (_idleState) {
24697
24946
  _idleState.style.display = 'flex';
@@ -25262,7 +25511,7 @@ var VoiceInterface = /*#__PURE__*/function () {
25262
25511
  key: "endCallOnServerRejection",
25263
25512
  value: (function () {
25264
25513
  var _endCallOnServerRejection = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6() {
25265
- var voiceInterfaceEl, landingScreen, _this$sdk$voiceSDK2, _this$sdk$voiceSDK3, audioRecorder, isRecording, _this$sdk$voiceSDK4, activeState, idleState, panel, fallbackPanel, floatingButton, fallbackButton, _t8, _t9, _t0, _t1, _t10;
25514
+ 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;
25266
25515
  return _regenerator().w(function (_context6) {
25267
25516
  while (1) switch (_context6.p = _context6.n) {
25268
25517
  case 0:
@@ -25475,7 +25724,7 @@ var VoiceInterface = /*#__PURE__*/function () {
25475
25724
  console.log('🚫 showDomainError() completed, isShowingDomainError:', this.isShowingDomainError);
25476
25725
  }
25477
25726
 
25478
- // Mobile: restore panel visibility
25727
+ // Mobile: restore panel visibility and show error toast
25479
25728
  if (this.isMobile) {
25480
25729
  panel = this.shadowRoot.getElementById('text-chat-panel');
25481
25730
  if (panel) {
@@ -25497,10 +25746,20 @@ var VoiceInterface = /*#__PURE__*/function () {
25497
25746
  fallbackButton.style.display = '';
25498
25747
  }
25499
25748
  }
25749
+ mobileFabEnd = this.shadowRoot.querySelector('.ttp-mobile-fab');
25750
+ if (mobileFabEnd) mobileFabEnd.style.display = '';
25500
25751
 
25501
25752
  // Remove mobile minimized bar if it exists
25502
25753
  this.removeMobileMinimizedBar();
25503
25754
  this.stopWaveformAnimation();
25755
+
25756
+ // Show error in mobile landing overlay since the panel isn't visible
25757
+ errorMsg = this.t('domainNotValidated') || 'Domain not whitelisted. Please contact support.';
25758
+ if (this.config.onMobileError) {
25759
+ this.config.onMobileError(errorMsg);
25760
+ } else if (this.config.onErrorToast) {
25761
+ this.config.onErrorToast(errorMsg, 'error');
25762
+ }
25504
25763
  }
25505
25764
  case 23:
25506
25765
  return _context6.a(2);