ttp-agent-sdk 2.45.4 → 2.45.7

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.
@@ -10642,14 +10642,14 @@ __webpack_require__.r(__webpack_exports__);
10642
10642
  /* harmony export */ ClientScriptManager: () => (/* binding */ ClientScriptManager)
10643
10643
  /* harmony export */ });
10644
10644
  /* harmony import */ var _ecommerce_PartnerScriptRunner_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../ecommerce/PartnerScriptRunner.js */ "./src/ecommerce/PartnerScriptRunner.js");
10645
- 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 }; })(); }
10646
- 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); }
10647
10645
  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); }
10648
- 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); }
10649
- 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); }); }; }
10650
10646
  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; }
10651
10647
  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; }
10652
10648
  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; }
10649
+ 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 }; })(); }
10650
+ 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); }
10651
+ 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); }
10652
+ 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); }); }; }
10653
10653
  function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
10654
10654
  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); } }
10655
10655
  function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
@@ -10728,8 +10728,115 @@ var ClientScriptManager = /*#__PURE__*/function () {
10728
10728
  * @returns {boolean}
10729
10729
  */
10730
10730
  return _createClass(ClientScriptManager, [{
10731
- key: "setBundle",
10732
- value:
10731
+ key: "handleClientToolCall",
10732
+ value: (
10733
+ /**
10734
+ * Execute a `client_tool_call` partner-script dispatch (see
10735
+ * {@link isClientToolsToolCall}) against the client-tool runner and answer
10736
+ * with the standard `client_tool_result` / `client_tool_error` envelopes —
10737
+ * the exact shapes ClientToolsRegistry sends, since the backend awaits the
10738
+ * reply keyed by `toolCallId`. Enforces the 50KB result cap.
10739
+ *
10740
+ * @param {object} message { toolCallId, toolName, parameters:{ action, args, partner_id } }
10741
+ * @param {string|null} conversationId the SDK's current conversation id
10742
+ */
10743
+ function () {
10744
+ var _handleClientToolCall = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(message) {
10745
+ var _this2 = this;
10746
+ var conversationId,
10747
+ _ref2,
10748
+ toolCallId,
10749
+ toolName,
10750
+ _ref3,
10751
+ action,
10752
+ args,
10753
+ startedAt,
10754
+ sendError,
10755
+ raw,
10756
+ result,
10757
+ serializedSize,
10758
+ sizeKB,
10759
+ limitKB,
10760
+ _args = arguments,
10761
+ _t;
10762
+ return _regenerator().w(function (_context) {
10763
+ while (1) switch (_context.p = _context.n) {
10764
+ case 0:
10765
+ conversationId = _args.length > 1 && _args[1] !== undefined ? _args[1] : null;
10766
+ _ref2 = message || {}, toolCallId = _ref2.toolCallId, toolName = _ref2.toolName;
10767
+ _ref3 = message && message.parameters || {}, action = _ref3.action, args = _ref3.args;
10768
+ startedAt = Date.now();
10769
+ console.log("".concat(LOG).concat(this._tag(), " client_tool_call dispatch action=").concat(action, " toolCallId=").concat(toolCallId));
10770
+ sendError = function sendError(error, errorCode) {
10771
+ _this2._send({
10772
+ t: 'client_tool_error',
10773
+ toolCallId: toolCallId,
10774
+ toolName: toolName,
10775
+ conversationId: conversationId,
10776
+ error: error,
10777
+ errorCode: errorCode,
10778
+ executionTimeMs: Date.now() - startedAt
10779
+ });
10780
+ };
10781
+ if (action) {
10782
+ _context.n = 1;
10783
+ break;
10784
+ }
10785
+ sendError('run_partner_script missing action', 'EXECUTION_ERROR');
10786
+ return _context.a(2);
10787
+ case 1:
10788
+ _context.p = 1;
10789
+ _context.n = 2;
10790
+ return this.runner.runAdapter(action, args || {});
10791
+ case 2:
10792
+ raw = _context.v;
10793
+ // A void script (side-effect only, no return) is a success — undefined
10794
+ // would be dropped from the JSON envelope and confuse the backend parse.
10795
+ result = raw === undefined ? {
10796
+ ok: true
10797
+ } : raw;
10798
+ serializedSize = 0;
10799
+ try {
10800
+ serializedSize = JSON.stringify(result).length;
10801
+ } catch (_unused) {
10802
+ serializedSize = 0;
10803
+ }
10804
+ if (!(serializedSize > MAX_RESULT_SIZE)) {
10805
+ _context.n = 3;
10806
+ break;
10807
+ }
10808
+ sizeKB = Math.round(serializedSize / 1024);
10809
+ limitKB = Math.round(MAX_RESULT_SIZE / 1024);
10810
+ console.error("".concat(LOG).concat(this._tag(), " result for '").concat(action, "' exceeds size limit (").concat(sizeKB, "KB > ").concat(limitKB, "KB)"));
10811
+ sendError("Result too large: ".concat(sizeKB, "KB exceeds ").concat(limitKB, "KB limit"), 'RESULT_TOO_LARGE');
10812
+ return _context.a(2);
10813
+ case 3:
10814
+ console.log("".concat(LOG).concat(this._tag(), " client_tool_call done action=").concat(action, " toolCallId=").concat(toolCallId, " (").concat(Date.now() - startedAt, "ms)"));
10815
+ this._send({
10816
+ t: 'client_tool_result',
10817
+ toolCallId: toolCallId,
10818
+ toolName: toolName,
10819
+ conversationId: conversationId,
10820
+ result: result,
10821
+ executionTimeMs: Date.now() - startedAt
10822
+ });
10823
+ _context.n = 5;
10824
+ break;
10825
+ case 4:
10826
+ _context.p = 4;
10827
+ _t = _context.v;
10828
+ console.error("".concat(LOG).concat(this._tag(), " client_tool_call threw action=").concat(action, " toolCallId=").concat(toolCallId, ":"), _t);
10829
+ sendError(_t && _t.message || 'Unknown error', 'EXECUTION_ERROR');
10830
+ case 5:
10831
+ return _context.a(2);
10832
+ }
10833
+ }, _callee, this, [[1, 4]]);
10834
+ }));
10835
+ function handleClientToolCall(_x) {
10836
+ return _handleClientToolCall.apply(this, arguments);
10837
+ }
10838
+ return handleClientToolCall;
10839
+ }()
10733
10840
  /**
10734
10841
  * Handle a `partner_bundle` for `__client_tools__`. Mirrors
10735
10842
  * EcommerceFlavor's bundle handling: merge autoRun entries into the adapters
@@ -10738,12 +10845,15 @@ var ClientScriptManager = /*#__PURE__*/function () {
10738
10845
  * entry exactly once.
10739
10846
  * @param {object} data the partner_bundle message
10740
10847
  */
10741
- function setBundle(data) {
10742
- var _this2 = this;
10848
+ )
10849
+ }, {
10850
+ key: "setBundle",
10851
+ value: function setBundle(data) {
10852
+ var _this3 = this;
10743
10853
  // emit callback is wired in the constructor and survives bundle reloads;
10744
10854
  // re-assert it here so it is always fresh for the active SDK instance.
10745
10855
  this.runner.setEmitCallback(function (msg) {
10746
- return _this2._send(msg);
10856
+ return _this3._send(msg);
10747
10857
  });
10748
10858
  var merged = _objectSpread(_objectSpread({}, data), {}, {
10749
10859
  adapters: _objectSpread(_objectSpread({}, (data === null || data === void 0 ? void 0 : data.adapters) || {}), (data === null || data === void 0 ? void 0 : data.autoRun) || {})
@@ -10751,10 +10861,10 @@ var ClientScriptManager = /*#__PURE__*/function () {
10751
10861
  this.runner.setBundle(merged);
10752
10862
  var _loop = function _loop() {
10753
10863
  var action = _Object$keys[_i];
10754
- _this2.runner.runAdapter(action, {}).then(function (r) {
10755
- return console.log("".concat(LOG).concat(_this2._tag(), " auto-run '").concat(action, "':"), r);
10864
+ _this3.runner.runAdapter(action, {}).then(function (r) {
10865
+ return console.log("".concat(LOG).concat(_this3._tag(), " auto-run '").concat(action, "':"), r);
10756
10866
  }).catch(function (e) {
10757
- return console.warn("".concat(LOG).concat(_this2._tag(), " auto-run '").concat(action, "' failed:"), e);
10867
+ return console.warn("".concat(LOG).concat(_this3._tag(), " auto-run '").concat(action, "' failed:"), e);
10758
10868
  });
10759
10869
  };
10760
10870
  for (var _i = 0, _Object$keys = Object.keys((data === null || data === void 0 ? void 0 : data.autoRun) || {}); _i < _Object$keys.length; _i++) {
@@ -10776,37 +10886,37 @@ var ClientScriptManager = /*#__PURE__*/function () {
10776
10886
  }, {
10777
10887
  key: "handleRunPartnerScript",
10778
10888
  value: (function () {
10779
- var _handleRunPartnerScript = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(message) {
10780
- var _ref2, requestId, partnerId, action, args, startedAt, result, elapsedMs, ok, serializedSize, sizeKB, limitKB, reason, _elapsedMs, _t;
10781
- return _regenerator().w(function (_context) {
10782
- while (1) switch (_context.p = _context.n) {
10889
+ var _handleRunPartnerScript = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(message) {
10890
+ var _ref4, requestId, partnerId, action, args, startedAt, result, elapsedMs, ok, serializedSize, sizeKB, limitKB, reason, _elapsedMs, _t2;
10891
+ return _regenerator().w(function (_context2) {
10892
+ while (1) switch (_context2.p = _context2.n) {
10783
10893
  case 0:
10784
- _ref2 = message || {}, requestId = _ref2.requestId, partnerId = _ref2.partnerId, action = _ref2.action;
10894
+ _ref4 = message || {}, requestId = _ref4.requestId, partnerId = _ref4.partnerId, action = _ref4.action;
10785
10895
  args = message && message.args || {};
10786
10896
  if (requestId) {
10787
- _context.n = 1;
10897
+ _context2.n = 1;
10788
10898
  break;
10789
10899
  }
10790
10900
  console.warn("".concat(LOG).concat(this._tag(), " run_partner_script missing requestId; dropping"), message);
10791
- return _context.a(2);
10901
+ return _context2.a(2);
10792
10902
  case 1:
10793
10903
  startedAt = Date.now();
10794
10904
  console.log("".concat(LOG).concat(this._tag(), " run_partner_script dispatch partner=").concat(partnerId, " action=").concat(action, " requestId=").concat(requestId));
10795
- _context.p = 2;
10796
- _context.n = 3;
10905
+ _context2.p = 2;
10906
+ _context2.n = 3;
10797
10907
  return this.runner.runAdapter(action, args);
10798
10908
  case 3:
10799
- result = _context.v;
10909
+ result = _context2.v;
10800
10910
  elapsedMs = Date.now() - startedAt;
10801
10911
  ok = result && _typeof(result) === 'object' && 'ok' in result ? !!result.ok : true; // 50KB result-size cap (mirror ClientToolsRegistry.MAX_RESULT_SIZE).
10802
10912
  serializedSize = 0;
10803
10913
  try {
10804
10914
  serializedSize = JSON.stringify(result).length;
10805
- } catch (_unused) {
10915
+ } catch (_unused2) {
10806
10916
  serializedSize = 0;
10807
10917
  }
10808
10918
  if (!(serializedSize > MAX_RESULT_SIZE)) {
10809
- _context.n = 4;
10919
+ _context2.n = 4;
10810
10920
  break;
10811
10921
  }
10812
10922
  sizeKB = Math.round(serializedSize / 1024);
@@ -10820,7 +10930,7 @@ var ClientScriptManager = /*#__PURE__*/function () {
10820
10930
  ok: false,
10821
10931
  error: 'RESULT_TOO_LARGE'
10822
10932
  });
10823
- return _context.a(2);
10933
+ return _context2.a(2);
10824
10934
  case 4:
10825
10935
  if (ok) {
10826
10936
  console.log("".concat(LOG).concat(this._tag(), " run_partner_script ok partner=").concat(partnerId, " action=").concat(action, " requestId=").concat(requestId, " (").concat(elapsedMs, "ms)"));
@@ -10836,27 +10946,27 @@ var ClientScriptManager = /*#__PURE__*/function () {
10836
10946
  ok: ok,
10837
10947
  result: result
10838
10948
  });
10839
- _context.n = 6;
10949
+ _context2.n = 6;
10840
10950
  break;
10841
10951
  case 5:
10842
- _context.p = 5;
10843
- _t = _context.v;
10952
+ _context2.p = 5;
10953
+ _t2 = _context2.v;
10844
10954
  _elapsedMs = Date.now() - startedAt;
10845
- console.error("".concat(LOG).concat(this._tag(), " run_partner_script threw partner=").concat(partnerId, " action=").concat(action, " requestId=").concat(requestId, " (").concat(_elapsedMs, "ms):"), _t);
10955
+ console.error("".concat(LOG).concat(this._tag(), " run_partner_script threw partner=").concat(partnerId, " action=").concat(action, " requestId=").concat(requestId, " (").concat(_elapsedMs, "ms):"), _t2);
10846
10956
  this._send({
10847
10957
  t: 'run_partner_script_result',
10848
10958
  requestId: requestId,
10849
10959
  partnerId: partnerId,
10850
10960
  action: action,
10851
10961
  ok: false,
10852
- error: _t && _t.message || String(_t)
10962
+ error: _t2 && _t2.message || String(_t2)
10853
10963
  });
10854
10964
  case 6:
10855
- return _context.a(2);
10965
+ return _context2.a(2);
10856
10966
  }
10857
- }, _callee, this, [[2, 5]]);
10967
+ }, _callee2, this, [[2, 5]]);
10858
10968
  }));
10859
- function handleRunPartnerScript(_x) {
10969
+ function handleRunPartnerScript(_x2) {
10860
10970
  return _handleRunPartnerScript.apply(this, arguments);
10861
10971
  }
10862
10972
  return handleRunPartnerScript;
@@ -10882,6 +10992,24 @@ var ClientScriptManager = /*#__PURE__*/function () {
10882
10992
  value: function isClientToolsScript(message) {
10883
10993
  return !!message && message.partnerId === CLIENT_TOOLS_PARTNER_ID;
10884
10994
  }
10995
+
10996
+ /**
10997
+ * True when this `client_tool_call` envelope is actually a partner-script
10998
+ * dispatch for the sentinel partner id. The backend's sync path
10999
+ * (PartnerScriptDispatcher.executeAdapter → executeClientToolAwait) sends
11000
+ * scripts as `client_tool_call` with `toolName:'run_partner_script'` and
11001
+ * `parameters.partner_id` — normally answered by the ecommerce flavor's
11002
+ * registered 'run_partner_script' tool handler. With no flavor loaded there
11003
+ * is no such handler, so both SDKs use this predicate to route the call here
11004
+ * BEFORE the ClientToolsRegistry lookup (which would NO_HANDLER it).
11005
+ * @param {object} message a client_tool_call message
11006
+ * @returns {boolean}
11007
+ */
11008
+ }, {
11009
+ key: "isClientToolsToolCall",
11010
+ value: function isClientToolsToolCall(message) {
11011
+ return !!message && message.toolName === 'run_partner_script' && !!message.parameters && message.parameters.partner_id === CLIENT_TOOLS_PARTNER_ID;
11012
+ }
10885
11013
  }]);
10886
11014
  }();
10887
11015
 
@@ -11444,6 +11572,15 @@ var TextChatSDK = /*#__PURE__*/function (_EventEmitter) {
11444
11572
  // which executes the registered handler and sends client_tool_result
11445
11573
  // back through this WebSocket.
11446
11574
  if (data.t === 'client_tool_call') {
11575
+ // Partner-script dispatch for the sentinel __client_tools__ partner
11576
+ // id rides on client_tool_call (toolName 'run_partner_script') —
11577
+ // route it to the flavor-independent ClientScriptManager instead of
11578
+ // the registry (which would NO_HANDLER it when no flavor is loaded).
11579
+ if (_ClientScriptManager_js__WEBPACK_IMPORTED_MODULE_2__.ClientScriptManager.isClientToolsToolCall(data)) {
11580
+ _this2.clientScriptManager.handleClientToolCall(data, _this2.config.conversationId);
11581
+ _this2.emit('message', data);
11582
+ return;
11583
+ }
11447
11584
  _this2.clientToolsRegistry.handleToolCall(data);
11448
11585
  _this2.emit('message', data);
11449
11586
  return;
@@ -11810,7 +11947,7 @@ var TextChatSDK = /*#__PURE__*/function (_EventEmitter) {
11810
11947
 
11811
11948
  // SDK build time for debugging
11812
11949
  if (true) {
11813
- helloMessage.lastBuildTime = "2026-06-12T20:23:48.560Z";
11950
+ helloMessage.lastBuildTime = "2026-06-14T07:18:03.004Z";
11814
11951
  }
11815
11952
  try {
11816
11953
  this.ws.send(JSON.stringify(helloMessage));
@@ -19976,8 +20113,8 @@ var VoiceSDK = _v2_VoiceSDK_js__WEBPACK_IMPORTED_MODULE_0__["default"];
19976
20113
 
19977
20114
 
19978
20115
  // Version - injected at build time from package.json via webpack DefinePlugin
19979
- var VERSION = "2.45.2";
19980
- var BUILD_TIME = "2026-06-12T20:23:48.560Z";
20116
+ var VERSION = "2.45.7";
20117
+ var BUILD_TIME = "2026-06-14T07:18:03.004Z";
19981
20118
  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;');
19982
20119
 
19983
20120
  // Named exports
@@ -22902,208 +23039,300 @@ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r)
22902
23039
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
22903
23040
  /**
22904
23041
  * DOM Context Extraction
22905
- *
22906
- * Extracts structured information about interactive elements on the page
22907
- * to provide context to the LLM for visual assistance.
23042
+ *
23043
+ * Extracts the actual readable content of the page — text, headings, code
23044
+ * blocks, lists plus interactive elements (buttons, forms, links) for
23045
+ * navigation and action context.
22908
23046
  */
22909
23047
 
22910
23048
 
22911
-
22912
- // Default limits to prevent token explosion
22913
23049
  var DEFAULT_LIMITS = {
23050
+ maxContentLength: 8000,
23051
+ // chars of main text content
23052
+ maxCodeBlockLength: 600,
23053
+ // chars per code block
22914
23054
  buttons: 20,
22915
23055
  links: 30,
22916
23056
  forms: 5,
22917
23057
  fieldsPerForm: 15,
22918
- sections: 10,
22919
- headings: 15,
22920
- maxTextLength: 100,
22921
- maxSummaryLength: 150
23058
+ maxTextLength: 100 // per interactive element label
22922
23059
  };
22923
23060
 
22924
- /**
22925
- * Generate a unique, stable CSS selector for an element
22926
- * Prioritizes stable attributes over auto-generated IDs
22927
- *
22928
- * @param {HTMLElement} element - The element to generate selector for
22929
- * @returns {string} - CSS selector string
22930
- */
22931
- function generateSelector(element) {
22932
- var _element$dataset, _element$dataset2;
22933
- if (!element || !element.tagName) return null;
22934
-
22935
- // Priority 1: data-testid (designed to be stable)
22936
- if ((_element$dataset = element.dataset) !== null && _element$dataset !== void 0 && _element$dataset.testid) {
22937
- return "[data-testid=\"".concat(element.dataset.testid, "\"]");
22938
- }
22939
-
22940
- // Priority 2: data-cy (Cypress test attribute)
22941
- if ((_element$dataset2 = element.dataset) !== null && _element$dataset2 !== void 0 && _element$dataset2.cy) {
22942
- return "[data-cy=\"".concat(element.dataset.cy, "\"]");
22943
- }
22944
-
22945
- // Priority 3: aria-label (accessibility, usually stable)
22946
- var ariaLabel = element.getAttribute('aria-label');
22947
- if (ariaLabel && ariaLabel.length < 50) {
22948
- return "[aria-label=\"".concat(ariaLabel.replace(/"/g, '\\"'), "\"]");
22949
- }
22950
-
22951
- // Priority 4: Stable ID (not auto-generated)
22952
- if (element.id && !isAutoGeneratedId(element.id)) {
22953
- return "#".concat(CSS.escape(element.id));
22954
- }
22955
-
22956
- // Priority 5: name attribute (for form fields)
22957
- if (element.name) {
22958
- var tag = element.tagName.toLowerCase();
22959
- return "".concat(tag, "[name=\"").concat(element.name, "\"]");
22960
- }
23061
+ // ─── Noise exclusion ────────────────────────────────────────────────────────
23062
+
23063
+ var NOISE_TAGS = new Set(['nav', 'header', 'footer', 'aside', 'script', 'style', 'noscript', 'svg', 'canvas', 'iframe']);
23064
+ var NOISE_ROLES = new Set(['navigation', 'banner', 'complementary', 'search']);
23065
+ function isNoise(el) {
23066
+ if (NOISE_TAGS.has(el.tagName.toLowerCase())) return true;
23067
+ var role = el.getAttribute('role');
23068
+ if (role && NOISE_ROLES.has(role)) return true;
23069
+ var cls = el.className || '';
23070
+ // Common sidebar/nav class patterns
23071
+ if (/\b(sidebar|navbar|topbar|breadcrumb|cookie|toast|modal-backdrop)\b/i.test(cls)) return true;
23072
+ return false;
23073
+ }
22961
23074
 
22962
- // Priority 6: Unique text content for buttons/links
22963
- if (['BUTTON', 'A'].includes(element.tagName)) {
22964
- var _element$innerText;
22965
- var text = (_element$innerText = element.innerText) === null || _element$innerText === void 0 ? void 0 : _element$innerText.trim();
22966
- if (text && text.length < 30 && text.length > 0) {
22967
- var _tag = element.tagName.toLowerCase();
22968
- // Check if this text is unique on the page
22969
- var matches = document.querySelectorAll("".concat(_tag));
22970
- var sameTextCount = Array.from(matches).filter(function (el) {
22971
- var _el$innerText;
22972
- return ((_el$innerText = el.innerText) === null || _el$innerText === void 0 ? void 0 : _el$innerText.trim()) === text;
22973
- }).length;
22974
- if (sameTextCount === 1) {
22975
- return "".concat(_tag, ":contains(\"").concat(text.replace(/"/g, '\\"'), "\")");
22976
- }
22977
- }
22978
- }
23075
+ // ─── Visibility ──────────────────────────────────────────────────────────────
22979
23076
 
22980
- // Priority 7: Build path from stable ancestors
22981
- return buildPathSelector(element);
23077
+ function isVisible(el) {
23078
+ if (!el) return false;
23079
+ var style = window.getComputedStyle(el);
23080
+ return style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0' && el.offsetWidth > 0 && el.offsetHeight > 0;
23081
+ }
23082
+ function isInViewport(el) {
23083
+ var buffer = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 500;
23084
+ var rect = el.getBoundingClientRect();
23085
+ return rect.bottom >= -buffer && rect.top <= window.innerHeight + buffer && rect.right >= 0 && rect.left <= window.innerWidth;
22982
23086
  }
22983
23087
 
22984
- /**
22985
- * Check if an ID looks auto-generated (React, Angular, Vue, etc.)
22986
- */
23088
+ // ─── Selector generation (kept for interactive elements) ─────────────────────
23089
+
22987
23090
  function isAutoGeneratedId(id) {
22988
- var autoGenPatterns = [/^:r[0-9a-z]+:$/,
22989
- // React 18+ useId
22990
- /^react-/i,
22991
- // React
22992
- /^ng-/i,
22993
- // Angular
22994
- /^vue-/i,
22995
- // Vue
22996
- /^ember[0-9]+/i,
22997
- // Ember
22998
- /^_[a-z0-9]{8,}$/i,
22999
- // Generic hash IDs
23000
- /^[a-f0-9]{8}-[a-f0-9]{4}/i,
23001
- // UUID-like
23002
- /^uid-/i,
23003
- // Generic UID
23004
- /^id[0-9]+$/i // Generic numbered IDs
23005
- ];
23006
- return autoGenPatterns.some(function (pattern) {
23007
- return pattern.test(id);
23091
+ return /^(:r[0-9a-z]+:|react-|ng-|vue-|ember[0-9]+|_[a-z0-9]{8,}|[a-f0-9]{8}-[a-f0-9]{4}|uid-|id[0-9]+$)/i.test(id);
23092
+ }
23093
+ function getMeaningfulClass(el) {
23094
+ var utilityPatterns = [/^(flex|grid|block|inline|hidden)$/, /^(m|p|w|h|min|max)-/, /^(text|font|bg|border)-/, /^(col|row)-/, /^(sm|md|lg|xl|2xl):/, /^hover:|focus:|active:/, /^[a-z]{1,3}-[0-9]+$/];
23095
+ var classes = Array.from(el.classList || []);
23096
+ var meaningful = classes.filter(function (cls) {
23097
+ return !utilityPatterns.some(function (p) {
23098
+ return p.test(cls);
23099
+ }) && cls.length > 2 && cls.length < 30;
23008
23100
  });
23101
+ return meaningful[0] || null;
23009
23102
  }
23010
-
23011
- /**
23012
- * Build a selector path from ancestors
23013
- */
23014
- function buildPathSelector(element) {
23103
+ function buildPathSelector(el) {
23015
23104
  var maxDepth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 3;
23016
23105
  var path = [];
23017
- var current = element;
23106
+ var cur = el;
23018
23107
  var depth = 0;
23019
- while (current && current !== document.body && depth < maxDepth) {
23020
- var tag = current.tagName.toLowerCase();
23021
-
23022
- // Try to add distinguishing info
23023
- if (current.id && !isAutoGeneratedId(current.id)) {
23024
- path.unshift("#".concat(CSS.escape(current.id)));
23025
- break; // ID is unique, stop here
23026
- }
23027
-
23028
- // Add class if it seems meaningful
23029
- var meaningfulClass = getMeaningfulClass(current);
23030
- if (meaningfulClass) {
23031
- path.unshift("".concat(tag, ".").concat(meaningfulClass));
23108
+ while (cur && cur !== document.body && depth < maxDepth) {
23109
+ var tag = cur.tagName.toLowerCase();
23110
+ if (cur.id && !isAutoGeneratedId(cur.id)) {
23111
+ path.unshift("#".concat(CSS.escape(cur.id)));
23112
+ break;
23113
+ }
23114
+ var cls = getMeaningfulClass(cur);
23115
+ if (cls) {
23116
+ path.unshift("".concat(tag, ".").concat(cls));
23032
23117
  } else {
23033
- var _current$parentElemen;
23034
- // Add nth-child if needed
23035
- var siblings = (_current$parentElemen = current.parentElement) === null || _current$parentElemen === void 0 ? void 0 : _current$parentElemen.children;
23118
+ var _cur$parentElement;
23119
+ var siblings = (_cur$parentElement = cur.parentElement) === null || _cur$parentElement === void 0 ? void 0 : _cur$parentElement.children;
23036
23120
  if (siblings && siblings.length > 1) {
23037
- var index = Array.from(siblings).indexOf(current) + 1;
23038
- path.unshift("".concat(tag, ":nth-child(").concat(index, ")"));
23121
+ var idx = Array.from(siblings).indexOf(cur) + 1;
23122
+ path.unshift("".concat(tag, ":nth-child(").concat(idx, ")"));
23039
23123
  } else {
23040
23124
  path.unshift(tag);
23041
23125
  }
23042
23126
  }
23043
- current = current.parentElement;
23127
+ cur = cur.parentElement;
23044
23128
  depth++;
23045
23129
  }
23046
23130
  return path.join(' > ');
23047
23131
  }
23132
+ function generateSelector(el) {
23133
+ var _el$dataset, _el$dataset2;
23134
+ if (!el || !el.tagName) return null;
23135
+ if ((_el$dataset = el.dataset) !== null && _el$dataset !== void 0 && _el$dataset.testid) return "[data-testid=\"".concat(el.dataset.testid, "\"]");
23136
+ if ((_el$dataset2 = el.dataset) !== null && _el$dataset2 !== void 0 && _el$dataset2.cy) return "[data-cy=\"".concat(el.dataset.cy, "\"]");
23137
+ var aria = el.getAttribute('aria-label');
23138
+ if (aria && aria.length < 50) return "[aria-label=\"".concat(aria.replace(/"/g, '\\"'), "\"]");
23139
+ if (el.id && !isAutoGeneratedId(el.id)) return "#".concat(CSS.escape(el.id));
23140
+ if (el.name) return "".concat(el.tagName.toLowerCase(), "[name=\"").concat(el.name, "\"]");
23141
+ if (['BUTTON', 'A'].includes(el.tagName)) {
23142
+ var _el$innerText;
23143
+ var text = (_el$innerText = el.innerText) === null || _el$innerText === void 0 ? void 0 : _el$innerText.trim();
23144
+ if (text && text.length < 30) {
23145
+ var tag = el.tagName.toLowerCase();
23146
+ var matches = document.querySelectorAll(tag);
23147
+ if (Array.from(matches).filter(function (e) {
23148
+ var _e$innerText;
23149
+ return ((_e$innerText = e.innerText) === null || _e$innerText === void 0 ? void 0 : _e$innerText.trim()) === text;
23150
+ }).length === 1) {
23151
+ return "".concat(tag, ":contains(\"").concat(text.replace(/"/g, '\\"'), "\")");
23152
+ }
23153
+ }
23154
+ }
23155
+ return buildPathSelector(el);
23156
+ }
23157
+
23158
+ // ─── Main content extraction ─────────────────────────────────────────────────
23048
23159
 
23049
23160
  /**
23050
- * Get a meaningful class name (not utility classes)
23161
+ * Find the best container element that holds the page's primary content.
23162
+ * Tries progressively wider selectors; falls back to document.body.
23051
23163
  */
23052
- function getMeaningfulClass(element) {
23053
- var classes = Array.from(element.classList || []);
23054
-
23055
- // Skip utility class patterns (Tailwind, Bootstrap, etc.)
23056
- var utilityPatterns = [/^(flex|grid|block|inline|hidden)$/, /^(m|p|w|h|min|max)-/,
23057
- // Spacing/sizing
23058
- /^(text|font|bg|border)-/,
23059
- // Typography/colors
23060
- /^(col|row)-/,
23061
- // Grid
23062
- /^(sm|md|lg|xl|2xl):/,
23063
- // Responsive
23064
- /^hover:|focus:|active:/,
23065
- // States
23066
- /^[a-z]{1,3}-[0-9]+$/ // Generic utilities
23067
- ];
23068
- var meaningfulClasses = classes.filter(function (cls) {
23069
- return !utilityPatterns.some(function (pattern) {
23070
- return pattern.test(cls);
23071
- }) && cls.length > 2 && cls.length < 30;
23072
- });
23073
- return meaningfulClasses[0] || null;
23164
+ function findContentRoot() {
23165
+ var candidates = ['article', '[role="article"]', 'main', '[role="main"]', '.prose', '.markdown-body', '.content', '#content', '#main-content', '#main'];
23166
+ for (var _i = 0, _candidates = candidates; _i < _candidates.length; _i++) {
23167
+ var sel = _candidates[_i];
23168
+ try {
23169
+ var el = document.querySelector(sel);
23170
+ if (el && isVisible(el)) return el;
23171
+ } catch (_unused) {}
23172
+ }
23173
+ return document.body;
23074
23174
  }
23075
23175
 
23076
23176
  /**
23077
- * Check if element is in or near viewport
23177
+ * Walk the content root and emit structured content items.
23178
+ * Skips noise elements (nav, header, aside…).
23179
+ *
23180
+ * Returns an array of items:
23181
+ * { type: 'heading', level: 'h2', text: '...' }
23182
+ * { type: 'text', text: '...' }
23183
+ * { type: 'code', lang: 'bash', text: '...' }
23184
+ * { type: 'listItem', text: '...' }
23078
23185
  */
23079
- function isInViewport(element) {
23080
- var buffer = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 500;
23081
- var rect = element.getBoundingClientRect();
23082
- return rect.bottom >= -buffer && rect.top <= window.innerHeight + buffer && rect.right >= 0 && rect.left <= window.innerWidth;
23186
+ function walkContent(root, limits) {
23187
+ var items = [];
23188
+ var charCount = 0;
23189
+ var BLOCK_TAGS = new Set(['p', 'li', 'dt', 'dd', 'td', 'th', 'blockquote', 'figcaption']);
23190
+ var HEADING_TAGS = new Set(['h1', 'h2', 'h3', 'h4', 'h5', 'h6']);
23191
+ function walk(node) {
23192
+ if (charCount >= limits.maxContentLength) return;
23193
+ if (node.nodeType !== Node.ELEMENT_NODE) return;
23194
+ var tag = node.tagName.toLowerCase();
23195
+
23196
+ // Skip noise subtrees entirely
23197
+ if (isNoise(node)) return;
23198
+ if (!isVisible(node)) return;
23199
+
23200
+ // Heading → new section marker
23201
+ if (HEADING_TAGS.has(tag)) {
23202
+ var text = (node.innerText || '').trim();
23203
+ if (text) {
23204
+ items.push({
23205
+ type: 'heading',
23206
+ level: tag,
23207
+ text: text
23208
+ });
23209
+ charCount += text.length;
23210
+ }
23211
+ return; // don't recurse — heading text already captured
23212
+ }
23213
+
23214
+ // Code block
23215
+ if (tag === 'pre') {
23216
+ var codeEl = node.querySelector('code');
23217
+ var raw = (codeEl || node).innerText || '';
23218
+ var _text = raw.trim().substring(0, limits.maxCodeBlockLength);
23219
+ if (_text) {
23220
+ var _match;
23221
+ var lang = ((_match = ((codeEl === null || codeEl === void 0 ? void 0 : codeEl.className) || '').match(/language-(\w+)/)) === null || _match === void 0 ? void 0 : _match[1]) || '';
23222
+ items.push({
23223
+ type: 'code',
23224
+ lang: lang,
23225
+ text: _text
23226
+ });
23227
+ charCount += _text.length;
23228
+ }
23229
+ return;
23230
+ }
23231
+
23232
+ // Inline code (not inside pre)
23233
+ if (tag === 'code' && node.closest('pre') === null) {
23234
+ // Let the parent block pick it up via innerText
23235
+ return;
23236
+ }
23237
+
23238
+ // Block-level text elements
23239
+ if (BLOCK_TAGS.has(tag)) {
23240
+ var _node$parentElement;
23241
+ // Skip if nested inside another block (e.g. <p> inside <blockquote> handled by blockquote)
23242
+ var parentTag = (_node$parentElement = node.parentElement) === null || _node$parentElement === void 0 ? void 0 : _node$parentElement.tagName.toLowerCase();
23243
+ if (tag !== 'blockquote' && BLOCK_TAGS.has(parentTag) && parentTag !== 'li') return;
23244
+ var _text2 = (node.innerText || '').trim();
23245
+ if (_text2) {
23246
+ var type = tag === 'li' ? 'listItem' : 'text';
23247
+ var truncated = _text2.substring(0, 400);
23248
+ items.push({
23249
+ type: type,
23250
+ text: truncated
23251
+ });
23252
+ charCount += truncated.length;
23253
+ }
23254
+ return; // innerText already captures children
23255
+ }
23256
+
23257
+ // Container — recurse into children
23258
+ var _iterator = _createForOfIteratorHelper(node.children),
23259
+ _step;
23260
+ try {
23261
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
23262
+ var child = _step.value;
23263
+ if (charCount >= limits.maxContentLength) break;
23264
+ walk(child);
23265
+ }
23266
+ } catch (err) {
23267
+ _iterator.e(err);
23268
+ } finally {
23269
+ _iterator.f();
23270
+ }
23271
+ }
23272
+ walk(root);
23273
+ return items;
23083
23274
  }
23084
23275
 
23085
23276
  /**
23086
- * Check if element is visible (not hidden)
23277
+ * Convert structured content items into a readable flat string,
23278
+ * organised by heading sections.
23087
23279
  */
23088
- function isVisible(element) {
23089
- if (!element) return false;
23090
- var style = window.getComputedStyle(element);
23091
- return style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0' && element.offsetWidth > 0 && element.offsetHeight > 0;
23280
+ function itemsToText(items) {
23281
+ var text = '';
23282
+ var _iterator2 = _createForOfIteratorHelper(items),
23283
+ _step2;
23284
+ try {
23285
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
23286
+ var item = _step2.value;
23287
+ switch (item.type) {
23288
+ case 'heading':
23289
+ text += "\n".concat('#'.repeat(parseInt(item.level[1])), " ").concat(item.text, "\n");
23290
+ break;
23291
+ case 'text':
23292
+ text += "".concat(item.text, "\n");
23293
+ break;
23294
+ case 'listItem':
23295
+ text += "\u2022 ".concat(item.text, "\n");
23296
+ break;
23297
+ case 'code':
23298
+ text += "```".concat(item.lang, "\n").concat(item.text, "\n```\n");
23299
+ break;
23300
+ }
23301
+ }
23302
+ } catch (err) {
23303
+ _iterator2.e(err);
23304
+ } finally {
23305
+ _iterator2.f();
23306
+ }
23307
+ return text.trim();
23092
23308
  }
23093
23309
 
23094
23310
  /**
23095
- * Extract buttons from the page
23311
+ * Extract the main readable content of the page.
23096
23312
  */
23097
- function extractButtons() {
23098
- var limits = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_LIMITS;
23313
+ function extractMainContent(limits) {
23314
+ var root = findContentRoot();
23315
+ var items = walkContent(root, limits);
23316
+ var text = itemsToText(items);
23317
+ var truncated = text.length >= limits.maxContentLength;
23318
+ return {
23319
+ text: text,
23320
+ items: items,
23321
+ truncated: truncated,
23322
+ sourceElement: root.tagName.toLowerCase() + (root.id ? "#".concat(root.id) : '') + (getMeaningfulClass(root) ? ".".concat(getMeaningfulClass(root)) : '')
23323
+ };
23324
+ }
23325
+
23326
+ // ─── Interactive elements ─────────────────────────────────────────────────────
23327
+
23328
+ function extractButtons(limits) {
23099
23329
  var buttons = [];
23100
- var selector = 'button, [type="submit"], [type="button"], [role="button"], .btn, .button';
23101
- var elements = document.querySelectorAll(selector);
23102
- var _iterator = _createForOfIteratorHelper(elements),
23103
- _step;
23330
+ var els = document.querySelectorAll('button, [type="submit"], [type="button"], [role="button"], .btn, .button');
23331
+ var _iterator3 = _createForOfIteratorHelper(els),
23332
+ _step3;
23104
23333
  try {
23105
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
23106
- var el = _step.value;
23334
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
23335
+ var el = _step3.value;
23107
23336
  if (buttons.length >= limits.buttons) break;
23108
23337
  if (!isVisible(el)) continue;
23109
23338
  var text = (el.innerText || el.value || el.getAttribute('aria-label') || '').trim();
@@ -23117,101 +23346,76 @@ function extractButtons() {
23117
23346
  });
23118
23347
  }
23119
23348
  } catch (err) {
23120
- _iterator.e(err);
23349
+ _iterator3.e(err);
23121
23350
  } finally {
23122
- _iterator.f();
23351
+ _iterator3.f();
23123
23352
  }
23124
23353
  return buttons;
23125
23354
  }
23126
-
23127
- /**
23128
- * Extract links from the page
23129
- */
23130
- function extractLinks() {
23131
- var limits = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_LIMITS;
23355
+ function extractLinks(limits) {
23132
23356
  var links = [];
23133
- var elements = document.querySelectorAll('a[href]');
23134
- var currentOrigin = window.location.origin;
23135
- var _iterator2 = _createForOfIteratorHelper(elements),
23136
- _step2;
23357
+ var els = document.querySelectorAll('a[href]');
23358
+ var origin = window.location.origin;
23359
+ var _iterator4 = _createForOfIteratorHelper(els),
23360
+ _step4;
23137
23361
  try {
23138
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
23139
- var el = _step2.value;
23362
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
23363
+ var el = _step4.value;
23140
23364
  if (links.length >= limits.links) break;
23141
23365
  if (!isVisible(el)) continue;
23142
23366
  var text = (el.innerText || el.getAttribute('aria-label') || '').trim();
23143
23367
  if (!text || text.length < 2) continue;
23144
-
23145
- // Skip anchor links and javascript:void
23146
23368
  var href = el.href;
23147
23369
  if (!href || href.startsWith('javascript:') || href === '#') continue;
23148
- var isInternal = false;
23370
+ var internal = false;
23149
23371
  try {
23150
- isInternal = new URL(href).origin === currentOrigin;
23151
- } catch (_unused) {}
23372
+ internal = new URL(href).origin === origin;
23373
+ } catch (_unused2) {}
23152
23374
  links.push({
23153
23375
  selector: generateSelector(el),
23154
23376
  text: text.substring(0, limits.maxTextLength),
23155
23377
  href: href,
23156
- internal: isInternal,
23378
+ internal: internal,
23157
23379
  inViewport: isInViewport(el, 0)
23158
23380
  });
23159
23381
  }
23160
23382
  } catch (err) {
23161
- _iterator2.e(err);
23383
+ _iterator4.e(err);
23162
23384
  } finally {
23163
- _iterator2.f();
23385
+ _iterator4.f();
23164
23386
  }
23165
23387
  return links;
23166
23388
  }
23167
-
23168
- /**
23169
- * Extract forms from the page (with sensitive field filtering)
23170
- */
23171
- function extractForms() {
23172
- var limits = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_LIMITS;
23389
+ function extractForms(limits) {
23173
23390
  var forms = [];
23174
- var elements = document.querySelectorAll('form');
23175
23391
  var sensitiveCount = 0;
23176
- var _iterator3 = _createForOfIteratorHelper(elements),
23177
- _step3;
23392
+ var _iterator5 = _createForOfIteratorHelper(document.querySelectorAll('form')),
23393
+ _step5;
23178
23394
  try {
23179
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
23180
- var form = _step3.value;
23395
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
23396
+ var form = _step5.value;
23181
23397
  if (forms.length >= limits.forms) break;
23182
23398
  if (!isVisible(form)) continue;
23183
23399
  var fields = [];
23184
- var fieldElements = form.querySelectorAll('input, textarea, select');
23185
- var _iterator4 = _createForOfIteratorHelper(fieldElements),
23186
- _step4;
23400
+ var _iterator6 = _createForOfIteratorHelper(form.querySelectorAll('input, textarea, select')),
23401
+ _step6;
23187
23402
  try {
23188
- for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
23403
+ for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
23189
23404
  var _label, _field$placeholder;
23190
- var field = _step4.value;
23405
+ var field = _step6.value;
23191
23406
  if (fields.length >= limits.fieldsPerForm) break;
23192
-
23193
- // Skip hidden fields
23194
23407
  if (field.type === 'hidden') continue;
23195
-
23196
- // IMPORTANT: Filter sensitive fields
23197
23408
  if ((0,_sensitive_filter_js__WEBPACK_IMPORTED_MODULE_0__.isSensitiveField)(field)) {
23198
23409
  sensitiveCount++;
23199
23410
  continue;
23200
23411
  }
23201
-
23202
- // Get label
23203
23412
  var label = null;
23204
23413
  if (field.id) {
23205
- var _labelEl$innerText;
23206
- var labelEl = document.querySelector("label[for=\"".concat(field.id, "\"]"));
23207
- label = labelEl === null || labelEl === void 0 || (_labelEl$innerText = labelEl.innerText) === null || _labelEl$innerText === void 0 ? void 0 : _labelEl$innerText.trim();
23208
- }
23209
- if (!label && field.getAttribute('aria-label')) {
23210
- label = field.getAttribute('aria-label');
23211
- }
23212
- if (!label && field.placeholder) {
23213
- label = field.placeholder;
23414
+ var _lEl$innerText;
23415
+ var lEl = document.querySelector("label[for=\"".concat(field.id, "\"]"));
23416
+ label = lEl === null || lEl === void 0 || (_lEl$innerText = lEl.innerText) === null || _lEl$innerText === void 0 ? void 0 : _lEl$innerText.trim();
23214
23417
  }
23418
+ label = label || field.getAttribute('aria-label') || field.placeholder || null;
23215
23419
  fields.push({
23216
23420
  selector: generateSelector(field),
23217
23421
  name: field.name || null,
@@ -23219,15 +23423,14 @@ function extractForms() {
23219
23423
  label: ((_label = label) === null || _label === void 0 ? void 0 : _label.substring(0, 50)) || null,
23220
23424
  placeholder: ((_field$placeholder = field.placeholder) === null || _field$placeholder === void 0 ? void 0 : _field$placeholder.substring(0, 50)) || null,
23221
23425
  required: field.required || false
23222
- // NEVER include value for security
23223
23426
  });
23224
23427
  }
23225
23428
  } catch (err) {
23226
- _iterator4.e(err);
23429
+ _iterator6.e(err);
23227
23430
  } finally {
23228
- _iterator4.f();
23431
+ _iterator6.f();
23229
23432
  }
23230
- if (fields.length === 0) continue;
23433
+ if (!fields.length) continue;
23231
23434
  forms.push({
23232
23435
  selector: generateSelector(form),
23233
23436
  id: form.id || null,
@@ -23237,9 +23440,9 @@ function extractForms() {
23237
23440
  });
23238
23441
  }
23239
23442
  } catch (err) {
23240
- _iterator3.e(err);
23443
+ _iterator5.e(err);
23241
23444
  } finally {
23242
- _iterator3.f();
23445
+ _iterator5.f();
23243
23446
  }
23244
23447
  return {
23245
23448
  forms: forms,
@@ -23247,143 +23450,56 @@ function extractForms() {
23247
23450
  };
23248
23451
  }
23249
23452
 
23250
- /**
23251
- * Extract sections/landmarks from the page
23252
- */
23253
- function extractSections() {
23254
- var limits = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_LIMITS;
23255
- var sections = [];
23256
- var selector = 'section, article, main, [role="main"], [role="region"], .section';
23257
- var elements = document.querySelectorAll(selector);
23258
- var _iterator5 = _createForOfIteratorHelper(elements),
23259
- _step5;
23260
- try {
23261
- for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
23262
- var _heading$innerText, _firstP$innerText, _el$innerText2;
23263
- var el = _step5.value;
23264
- if (sections.length >= limits.sections) break;
23265
- if (!isVisible(el)) continue;
23266
-
23267
- // Get a summary of the section content
23268
- var heading = el.querySelector('h1, h2, h3');
23269
- var headingText = (heading === null || heading === void 0 || (_heading$innerText = heading.innerText) === null || _heading$innerText === void 0 ? void 0 : _heading$innerText.trim()) || '';
23270
-
23271
- // Get first paragraph or first N characters
23272
- var firstP = el.querySelector('p');
23273
- var summary = headingText || (firstP === null || firstP === void 0 || (_firstP$innerText = firstP.innerText) === null || _firstP$innerText === void 0 ? void 0 : _firstP$innerText.trim().substring(0, limits.maxSummaryLength)) || ((_el$innerText2 = el.innerText) === null || _el$innerText2 === void 0 ? void 0 : _el$innerText2.trim().substring(0, limits.maxSummaryLength)) || '';
23274
- sections.push({
23275
- selector: generateSelector(el),
23276
- id: el.id || null,
23277
- tagName: el.tagName.toLowerCase(),
23278
- summary: summary.substring(0, limits.maxSummaryLength),
23279
- inViewport: isInViewport(el, 0)
23280
- });
23281
- }
23282
- } catch (err) {
23283
- _iterator5.e(err);
23284
- } finally {
23285
- _iterator5.f();
23286
- }
23287
- return sections;
23288
- }
23289
-
23290
- /**
23291
- * Extract headings from the page
23292
- */
23293
- function extractHeadings() {
23294
- var limits = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_LIMITS;
23295
- var headings = [];
23296
- var elements = document.querySelectorAll('h1, h2, h3');
23297
- var _iterator6 = _createForOfIteratorHelper(elements),
23298
- _step6;
23299
- try {
23300
- for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
23301
- var _el$innerText3;
23302
- var el = _step6.value;
23303
- if (headings.length >= limits.headings) break;
23304
- if (!isVisible(el)) continue;
23305
- var text = (_el$innerText3 = el.innerText) === null || _el$innerText3 === void 0 ? void 0 : _el$innerText3.trim();
23306
- if (!text) continue;
23307
- headings.push({
23308
- selector: generateSelector(el),
23309
- level: el.tagName.toLowerCase(),
23310
- text: text.substring(0, limits.maxTextLength),
23311
- inViewport: isInViewport(el, 0)
23312
- });
23313
- }
23314
- } catch (err) {
23315
- _iterator6.e(err);
23316
- } finally {
23317
- _iterator6.f();
23318
- }
23319
- return headings;
23320
- }
23453
+ // ─── Public API ───────────────────────────────────────────────────────────────
23321
23454
 
23322
23455
  /**
23323
- * Main function: Extract full DOM context
23324
- *
23325
- * @param {Object} options - Extraction options
23326
- * @param {Object} options.limits - Override default limits
23327
- * @returns {Object} - Structured DOM context
23456
+ * Main extraction function called by the read_page tool handler.
23457
+ *
23458
+ * Returns:
23459
+ * content — flat readable text of the page (most important)
23460
+ * contentItems — structured array of { type, text, level?, lang? }
23461
+ * contentTruncated — true if content was cut at maxContentLength
23462
+ * url, title, language, viewport
23463
+ * buttons, links, forms — interactive elements for navigation / actions
23464
+ * metadata
23328
23465
  */
23329
23466
  function extractDOMContext() {
23330
23467
  return _extractDOMContext.apply(this, arguments);
23331
23468
  }
23332
23469
 
23333
23470
  /**
23334
- * Extract minimal context (for re-extraction after navigation)
23471
+ * Minimal context snapshot used on reconnect / navigation events.
23335
23472
  */
23336
23473
  function _extractDOMContext() {
23337
23474
  _extractDOMContext = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
23338
23475
  var _document$querySelect;
23339
23476
  var options,
23340
23477
  limits,
23478
+ mainContent,
23341
23479
  buttons,
23342
23480
  links,
23343
23481
  _extractForms,
23344
23482
  forms,
23345
23483
  sensitiveCount,
23346
- sections,
23347
- headings,
23348
- totalElements,
23349
- visibleInViewport,
23350
23484
  htmlLang,
23351
- browserLang,
23352
23485
  language,
23353
23486
  _args = arguments;
23354
23487
  return _regenerator().w(function (_context) {
23355
23488
  while (1) switch (_context.n) {
23356
23489
  case 0:
23357
23490
  options = _args.length > 0 && _args[0] !== undefined ? _args[0] : {};
23358
- limits = _objectSpread(_objectSpread({}, DEFAULT_LIMITS), options.limits); // Extract all elements
23491
+ limits = _objectSpread(_objectSpread({}, DEFAULT_LIMITS), options.limits);
23492
+ mainContent = extractMainContent(limits);
23359
23493
  buttons = extractButtons(limits);
23360
23494
  links = extractLinks(limits);
23361
23495
  _extractForms = extractForms(limits), forms = _extractForms.forms, sensitiveCount = _extractForms.sensitiveCount;
23362
- sections = extractSections(limits);
23363
- headings = extractHeadings(limits); // Count totals
23364
- totalElements = buttons.length + links.length + forms.reduce(function (sum, f) {
23365
- return sum + f.fields.length;
23366
- }, 0) + sections.length + headings.length;
23367
- visibleInViewport = buttons.filter(function (b) {
23368
- return b.inViewport;
23369
- }).length + links.filter(function (l) {
23370
- return l.inViewport;
23371
- }).length + sections.filter(function (s) {
23372
- return s.inViewport;
23373
- }).length + headings.filter(function (h) {
23374
- return h.inViewport;
23375
- }).length; // Detect site language
23376
- // Priority: HTML lang attribute > browser language
23377
23496
  htmlLang = document.documentElement.lang || ((_document$querySelect = document.querySelector('html')) === null || _document$querySelect === void 0 ? void 0 : _document$querySelect.getAttribute('lang')) || null;
23378
- browserLang = navigator.language || navigator.languages && navigator.languages[0] || null;
23379
- language = htmlLang || browserLang || null;
23497
+ language = htmlLang || navigator.language || navigator.languages && navigator.languages[0] || null;
23380
23498
  return _context.a(2, {
23381
23499
  url: window.location.href,
23382
23500
  title: document.title,
23383
23501
  timestamp: Date.now(),
23384
23502
  language: language,
23385
- // Site language (from HTML lang attribute or browser)
23386
-
23387
23503
  viewport: {
23388
23504
  width: window.innerWidth,
23389
23505
  height: window.innerHeight,
@@ -23391,14 +23507,20 @@ function _extractDOMContext() {
23391
23507
  scrollY: window.scrollY,
23392
23508
  pageHeight: document.documentElement.scrollHeight
23393
23509
  },
23510
+ // ── Primary: actual page content ──────────────────────────────────────
23511
+ content: mainContent.text,
23512
+ contentItems: mainContent.items,
23513
+ contentTruncated: mainContent.truncated,
23514
+ contentSource: mainContent.sourceElement,
23515
+ // ── Secondary: interactive elements ───────────────────────────────────
23394
23516
  buttons: buttons,
23395
23517
  links: links,
23396
23518
  forms: forms,
23397
- sections: sections,
23398
- headings: headings,
23399
23519
  metadata: {
23400
- totalElements: totalElements,
23401
- visibleInViewport: visibleInViewport,
23520
+ totalContentChars: mainContent.text.length,
23521
+ contentItemCount: mainContent.items.length,
23522
+ buttonsCount: buttons.length,
23523
+ linksCount: links.length,
23402
23524
  formsCount: forms.length,
23403
23525
  sensitiveFieldsFiltered: sensitiveCount
23404
23526
  }
@@ -23414,14 +23536,12 @@ function extractMinimalContext() {
23414
23536
  function _extractMinimalContext() {
23415
23537
  _extractMinimalContext = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
23416
23538
  var _document$querySelect2;
23417
- var htmlLang, browserLang, language;
23539
+ var htmlLang, language;
23418
23540
  return _regenerator().w(function (_context2) {
23419
23541
  while (1) switch (_context2.n) {
23420
23542
  case 0:
23421
- // Detect site language
23422
23543
  htmlLang = document.documentElement.lang || ((_document$querySelect2 = document.querySelector('html')) === null || _document$querySelect2 === void 0 ? void 0 : _document$querySelect2.getAttribute('lang')) || null;
23423
- browserLang = navigator.language || navigator.languages && navigator.languages[0] || null;
23424
- language = htmlLang || browserLang || null;
23544
+ language = htmlLang || navigator.language || navigator.languages && navigator.languages[0] || null;
23425
23545
  return _context2.a(2, {
23426
23546
  url: window.location.href,
23427
23547
  title: document.title,
@@ -23902,16 +24022,19 @@ function registerVisualTools(registry) {
23902
24022
  while (1) switch (_context.n) {
23903
24023
  case 0:
23904
24024
  params = _args.length > 0 && _args[0] !== undefined ? _args[0] : {};
23905
- console.log('[TTP] 📋 Reading page structure...');
24025
+ console.log('[TTP] 📋 Reading page content...');
23906
24026
  _context.n = 1;
23907
24027
  return (0,_dom_context_js__WEBPACK_IMPORTED_MODULE_0__.extractDOMContext)(params);
23908
24028
  case 1:
23909
24029
  context = _context.v;
23910
- console.log('[TTP] ✅ Page structure extracted:', {
23911
- buttons: context.buttons.length,
23912
- links: context.links.length,
23913
- forms: context.forms.length,
23914
- headings: context.headings.length
24030
+ console.log('[TTP] ✅ Page content extracted:', {
24031
+ contentChars: context.metadata.totalContentChars,
24032
+ contentItems: context.metadata.contentItemCount,
24033
+ truncated: context.contentTruncated,
24034
+ source: context.contentSource,
24035
+ buttons: context.metadata.buttonsCount,
24036
+ links: context.metadata.linksCount,
24037
+ forms: context.metadata.formsCount
23915
24038
  });
23916
24039
  return _context.a(2, context);
23917
24040
  }
@@ -24130,12 +24253,12 @@ function _extractPageContext() {
24130
24253
  timestamp: domContext.timestamp,
24131
24254
  language: domContext.language,
24132
24255
  viewport: domContext.viewport,
24256
+ content: domContext.content,
24257
+ contentTruncated: domContext.contentTruncated,
24133
24258
  dom: {
24134
24259
  buttons: domContext.buttons,
24135
24260
  links: domContext.links,
24136
24261
  forms: domContext.forms,
24137
- sections: domContext.sections,
24138
- headings: domContext.headings,
24139
24262
  metadata: domContext.metadata
24140
24263
  }
24141
24264
  });
@@ -27479,7 +27602,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
27479
27602
 
27480
27603
  // Include SDK build time for debugging
27481
27604
  if (true) {
27482
- helloMessage.lastBuildTime = "2026-06-12T20:23:48.560Z";
27605
+ helloMessage.lastBuildTime = "2026-06-14T07:18:03.004Z";
27483
27606
  }
27484
27607
 
27485
27608
  // Page context is intentionally NOT attached to the hello message.
@@ -27656,6 +27779,17 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
27656
27779
  this.emit('message', message);
27657
27780
  break;
27658
27781
  case 'client_tool_call':
27782
+ // Partner-script dispatch for the sentinel __client_tools__ partner id
27783
+ // rides on client_tool_call (toolName 'run_partner_script'). Route it
27784
+ // to the flavor-independent ClientScriptManager — with no flavor
27785
+ // loaded there is no registered 'run_partner_script' handler and the
27786
+ // registry would NO_HANDLER it. Every other tool call (including
27787
+ // partner-id'd run_partner_script for the ecommerce flavor) keeps
27788
+ // going through the registry untouched.
27789
+ if (_core_ClientScriptManager_js__WEBPACK_IMPORTED_MODULE_5__.ClientScriptManager.isClientToolsToolCall(message)) {
27790
+ this.clientScriptManager.handleClientToolCall(message, this.conversationId);
27791
+ break;
27792
+ }
27659
27793
  this.clientToolsRegistry.handleToolCall(message);
27660
27794
  break;
27661
27795
  case 'run_partner_script':
@@ -33327,7 +33461,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
33327
33461
  var callActivePanelBg = callSurfaceGradient;
33328
33462
  var voiceIdleVisibleSelector = '#voiceInterface.active #voiceIdleState:not([style*="display: none"]):not([style*="display:none"])';
33329
33463
  var voiceActiveVisibleSelector = '#voiceInterface.active #voiceActiveState:not([style*="display: none"]):not([style*="display:none"])';
33330
- 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 /* Shared panel chrome; size/position differ \u2014 desktop card vs mobile sheet (see @media blocks earlier) */\n #text-chat-panel {\n display: none").concat(important, ";\n position: fixed").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 opacity: 0").concat(important, ";\n pointer-events: none").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n\n /* Desktop / tablet: floating 340px card anchored to launcher */\n @media (min-width: 769px) {\n #text-chat-panel {\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 transform-origin: bottom right").concat(important, ";\n }\n /* Text chat: fixed height so the message list scrolls instead of growing the panel per message */\n #text-chat-panel:has(.text-interface.active) {\n height: min(520px, calc(100vh - 100px))").concat(important, ";\n }\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 ").concat(textUsesVoiceTheme ? "\n /* Text chat with voice theme: same hero surface as voice idle; inner shells transparent */\n #text-chat-panel.open:has(.text-interface.active) {\n background: ".concat(callSurfaceGradient).concat(important, ";\n }\n #text-chat-panel.open:has(.text-interface.active) .widget-shell,\n #text-chat-panel.open:has(.text-interface.active) .panel-inner,\n #text-chat-panel.open:has(.text-interface.active) .widget-container {\n background: transparent").concat(important, ";\n }\n #text-chat-panel.open:has(.text-interface.active) .ttp-footer {\n background: transparent").concat(important, ";\n border-top-color: rgba(255,255,255,0.06)").concat(important, ";\n }\n #text-chat-panel.open:has(.text-interface.active) .ttp-footer span {\n color: rgba(255,255,255,0.35)").concat(important, ";\n }\n #text-chat-panel.open:has(.text-interface.active) .ttp-footer a {\n color: ").concat(footerLinkOnDarkHero).concat(important, ";\n }\n ") : '', "\n \n /* Voice may scroll as a whole; text chat keeps a fixed shell and scrolls #messagesContainer only */\n #text-chat-panel .widget-container > .voice-interface {\n flex: 1").concat(important, ";\n min-height: 0").concat(important, ";\n overflow-y: auto").concat(important, ";\n overflow-x: visible").concat(important, ";\n }\n #text-chat-panel .widget-container > .text-interface {\n flex: 1").concat(important, ";\n min-height: 0").concat(important, ";\n overflow: hidden").concat(important, ";\n overflow-x: visible").concat(important, ";\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 ");
33464
+ 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 right: 10px !important;\n left: auto !important;\n bottom: 92px !important; /* 56px button + 20px gap + 16px footer */\n top: auto !important;\n width: 340px !important;\n max-width: calc(100vw - 20px) !important;\n height: auto !important;\n max-height: calc(100vh - 130px) !important;\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 right: 8px !important;\n left: auto !important;\n bottom: 86px !important; /* 54px button + 20px gap + 12px footer */\n top: auto !important;\n width: 340px !important;\n max-width: calc(100vw - 16px) !important;\n height: auto !important;\n max-height: calc(100vh - 120px) !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 /* Shared panel chrome; size/position differ \u2014 desktop card vs mobile sheet (see @media blocks earlier) */\n #text-chat-panel {\n display: none").concat(important, ";\n position: fixed").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 opacity: 0").concat(important, ";\n pointer-events: none").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n\n /* Desktop / tablet: floating 340px card anchored to launcher */\n @media (min-width: 769px) {\n #text-chat-panel {\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 transform-origin: bottom right").concat(important, ";\n }\n /* Text chat: fixed height so the message list scrolls instead of growing the panel per message */\n #text-chat-panel:has(.text-interface.active) {\n height: min(520px, calc(100vh - 100px))").concat(important, ";\n }\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 ").concat(textUsesVoiceTheme ? "\n /* Text chat with voice theme: same hero surface as voice idle; inner shells transparent */\n #text-chat-panel.open:has(.text-interface.active) {\n background: ".concat(callSurfaceGradient).concat(important, ";\n }\n #text-chat-panel.open:has(.text-interface.active) .widget-shell,\n #text-chat-panel.open:has(.text-interface.active) .panel-inner,\n #text-chat-panel.open:has(.text-interface.active) .widget-container {\n background: transparent").concat(important, ";\n }\n #text-chat-panel.open:has(.text-interface.active) .ttp-footer {\n background: transparent").concat(important, ";\n border-top-color: rgba(255,255,255,0.06)").concat(important, ";\n }\n #text-chat-panel.open:has(.text-interface.active) .ttp-footer span {\n color: rgba(255,255,255,0.35)").concat(important, ";\n }\n #text-chat-panel.open:has(.text-interface.active) .ttp-footer a {\n color: ").concat(footerLinkOnDarkHero).concat(important, ";\n }\n ") : '', "\n \n /* Voice may scroll as a whole; text chat keeps a fixed shell and scrolls #messagesContainer only */\n #text-chat-panel .widget-container > .voice-interface {\n flex: 1").concat(important, ";\n min-height: 0").concat(important, ";\n overflow-y: auto").concat(important, ";\n overflow-x: visible").concat(important, ";\n }\n #text-chat-panel .widget-container > .text-interface {\n flex: 1").concat(important, ";\n min-height: 0").concat(important, ";\n overflow: hidden").concat(important, ";\n overflow-x: visible").concat(important, ";\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 ");
33331
33465
  }
33332
33466
  }, {
33333
33467
  key: "setupWidgetEvents",
@@ -33675,6 +33809,38 @@ var TTPChatWidget = /*#__PURE__*/function () {
33675
33809
  closeMobileLanding();
33676
33810
  }
33677
33811
  });
33812
+
33813
+ // Responsive breakpoint handler: keep desktop panel and mobile FAB/landing mutually exclusive
33814
+ var _prevIsMobile = window.innerWidth <= 768;
33815
+ var _resizeTimer = null;
33816
+ window.addEventListener('resize', function () {
33817
+ clearTimeout(_resizeTimer);
33818
+ _resizeTimer = setTimeout(function () {
33819
+ var nowMobile = window.innerWidth <= 768;
33820
+ if (nowMobile === _prevIsMobile) return;
33821
+ _prevIsMobile = nowMobile;
33822
+ if (nowMobile) {
33823
+ // Switched desktop → mobile: close desktop panel so only mobile FAB shows
33824
+ if (_this0.isOpen) {
33825
+ var _this0$shadowRoot, _this0$shadowRoot2;
33826
+ var panel = (_this0$shadowRoot = _this0.shadowRoot) === null || _this0$shadowRoot === void 0 ? void 0 : _this0$shadowRoot.getElementById('text-chat-panel');
33827
+ if (panel) {
33828
+ panel.classList.remove('open');
33829
+ _this0.isOpen = false;
33830
+ }
33831
+ var pill = (_this0$shadowRoot2 = _this0.shadowRoot) === null || _this0$shadowRoot2 === void 0 ? void 0 : _this0$shadowRoot2.getElementById('text-chat-button');
33832
+ if (pill) pill.classList.remove('open');
33833
+ }
33834
+ } else {
33835
+ // Switched mobile → desktop: close mobile landing/FAB so only desktop pill shows
33836
+ if (_this0.isMobileLandingOpen) {
33837
+ closeMobileLanding();
33838
+ }
33839
+ // Ensure mobile FAB is reset to CSS-controlled state (media query hides it on desktop)
33840
+ if (mobileFab) mobileFab.style.removeProperty('display');
33841
+ }
33842
+ }, 150);
33843
+ });
33678
33844
  }
33679
33845
  }, {
33680
33846
  key: "setupKeyboardNavigation",