@noodleseed/assistant 1.25.1 → 1.26.1

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.
Files changed (44) hide show
  1. package/README.md +54 -20
  2. package/dist/{app-view-element-BNkQab1B.d.ts → app-view-element-C_ATXseu.d.ts} +1 -1
  3. package/dist/{app-view-element-DhuiNW_x.d.cts → app-view-element-CiFVNIke.d.cts} +1 -1
  4. package/dist/app-view.cjs +5 -5
  5. package/dist/app-view.cjs.map +1 -1
  6. package/dist/app-view.d.cts +3 -3
  7. package/dist/app-view.d.ts +3 -3
  8. package/dist/app-view.js +2 -2
  9. package/dist/{appearance-B6vSg8Ub.d.cts → appearance-C24W6BRj.d.cts} +7 -3
  10. package/dist/{appearance-B6vSg8Ub.d.ts → appearance-C24W6BRj.d.ts} +7 -3
  11. package/dist/{chunk-5TYS2Q6S.js → chunk-5NBHHNI3.js} +2 -2
  12. package/dist/{chunk-7BQHW37I.js → chunk-FNXAVRL5.js} +7 -1
  13. package/dist/{chunk-7BQHW37I.js.map → chunk-FNXAVRL5.js.map} +1 -1
  14. package/dist/{chunk-FJYPE4GC.js → chunk-OZVDL77T.js} +713 -122
  15. package/dist/chunk-OZVDL77T.js.map +1 -0
  16. package/dist/{chunk-CF2SCDLF.js → chunk-XKTUXFGX.js} +6 -6
  17. package/dist/chunk-XKTUXFGX.js.map +1 -0
  18. package/dist/{client-BkogON2A.d.ts → client-BheCOERq.d.ts} +51 -2
  19. package/dist/{client-C07ppTU_.d.cts → client-BiMRVxjs.d.cts} +51 -2
  20. package/dist/client.cjs.map +1 -1
  21. package/dist/client.d.cts +2 -2
  22. package/dist/client.d.ts +2 -2
  23. package/dist/client.js +1 -1
  24. package/dist/embed.global.js +171 -89
  25. package/dist/index.cjs +720 -124
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.cts +6 -53
  28. package/dist/index.d.ts +6 -53
  29. package/dist/index.js +3 -3
  30. package/dist/react/client.cjs.map +1 -1
  31. package/dist/react/client.d.cts +2 -2
  32. package/dist/react/client.d.ts +2 -2
  33. package/dist/react/client.js +1 -1
  34. package/dist/react.cjs +720 -124
  35. package/dist/react.cjs.map +1 -1
  36. package/dist/react.d.cts +4 -4
  37. package/dist/react.d.ts +4 -4
  38. package/dist/react.js +4 -4
  39. package/dist/server.d.cts +1 -1
  40. package/dist/server.d.ts +1 -1
  41. package/package.json +1 -1
  42. package/dist/chunk-CF2SCDLF.js.map +0 -1
  43. package/dist/chunk-FJYPE4GC.js.map +0 -1
  44. /package/dist/{chunk-5TYS2Q6S.js.map → chunk-5NBHHNI3.js.map} +0 -0
package/dist/react.cjs CHANGED
@@ -15197,7 +15197,7 @@ __export(react_exports, {
15197
15197
  module.exports = __toCommonJS(react_exports);
15198
15198
  var import_react2 = require("react");
15199
15199
 
15200
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_supports-color@7.2.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js
15200
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js
15201
15201
  init_v4();
15202
15202
  var RELATED_TASK_META_KEY = "io.modelcontextprotocol/related-task";
15203
15203
  var JSONRPC_VERSION = "2.0";
@@ -20594,7 +20594,7 @@ var pipelineType = ZodPipeline.create;
20594
20594
  // ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/mini/parse.js
20595
20595
  init_core2();
20596
20596
 
20597
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_supports-color@7.2.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js
20597
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js
20598
20598
  function isZ4Schema(s2) {
20599
20599
  const schema = s2;
20600
20600
  return !!schema._zod;
@@ -20657,7 +20657,7 @@ function getLiteralValue(schema) {
20657
20657
  return void 0;
20658
20658
  }
20659
20659
 
20660
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_supports-color@7.2.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/interfaces.js
20660
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/interfaces.js
20661
20661
  function isTerminal(status) {
20662
20662
  return status === "completed" || status === "failed" || status === "cancelled";
20663
20663
  }
@@ -20665,7 +20665,7 @@ function isTerminal(status) {
20665
20665
  // ../../node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@4.4.3/node_modules/zod-to-json-schema/dist/esm/parsers/string.js
20666
20666
  var ALPHA_NUMERIC = new Set("ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvxyz0123456789");
20667
20667
 
20668
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_supports-color@7.2.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-json-schema-compat.js
20668
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-json-schema-compat.js
20669
20669
  function getMethodLiteral(schema) {
20670
20670
  const shape = getObjectShape(schema);
20671
20671
  const methodSchema = shape?.method;
@@ -20686,7 +20686,7 @@ function parseWithCompat(schema, data) {
20686
20686
  return result.data;
20687
20687
  }
20688
20688
 
20689
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_supports-color@7.2.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js
20689
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js
20690
20690
  var DEFAULT_REQUEST_TIMEOUT_MSEC = 6e4;
20691
20691
  var Protocol = class {
20692
20692
  constructor(_options) {
@@ -22346,7 +22346,7 @@ function unmountAssistantApp(card) {
22346
22346
 
22347
22347
  // src/appearance.ts
22348
22348
  var common = {
22349
- fontFamily: "inherit",
22349
+ fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
22350
22350
  monoFontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
22351
22351
  baseFontSize: 15,
22352
22352
  messageFontSize: 15,
@@ -22357,7 +22357,7 @@ var common = {
22357
22357
  buttonRadius: 999,
22358
22358
  launcherRadius: 999,
22359
22359
  spacing: 8,
22360
- backdropBlur: 18,
22360
+ backdropBlur: 6,
22361
22361
  motionScale: 1
22362
22362
  };
22363
22363
  var DEFAULT_APPEARANCE = {
@@ -22377,7 +22377,7 @@ var DEFAULT_APPEARANCE = {
22377
22377
  accent: "#C2410C",
22378
22378
  accentText: "#FFFFFF",
22379
22379
  link: "#9A3412",
22380
- divider: "#E4E4E7",
22380
+ divider: "rgba(0, 0, 0, 0.1)",
22381
22381
  focus: "#C2410C",
22382
22382
  success: "#16835D",
22383
22383
  warning: "#A45B00",
@@ -22385,7 +22385,7 @@ var DEFAULT_APPEARANCE = {
22385
22385
  overlay: "#18181B66",
22386
22386
  code: "#F1F1F3",
22387
22387
  widgetFrame: "#E4E4E7",
22388
- shadow: "0 4px 16px rgba(0, 0, 0, 0.06), 0 24px 70px rgba(0, 0, 0, 0.10)"
22388
+ shadow: "0 4px 16px rgba(0, 0, 0, 0.06)"
22389
22389
  },
22390
22390
  dark: {
22391
22391
  ...common,
@@ -22400,7 +22400,7 @@ var DEFAULT_APPEARANCE = {
22400
22400
  accent: "#FB923C",
22401
22401
  accentText: "#1C0A02",
22402
22402
  link: "#FDBA74",
22403
- divider: "#292524",
22403
+ divider: "rgba(255, 255, 255, 0.1)",
22404
22404
  focus: "#FB923C",
22405
22405
  success: "#58C69A",
22406
22406
  warning: "#F2B45F",
@@ -22408,15 +22408,15 @@ var DEFAULT_APPEARANCE = {
22408
22408
  overlay: "#00000099",
22409
22409
  code: "#26262C",
22410
22410
  widgetFrame: "#34343B",
22411
- shadow: "0 8px 32px rgba(0, 0, 0, 0.48)"
22411
+ shadow: "0 8px 32px rgba(0, 0, 0, 0.4)"
22412
22412
  }
22413
22413
  },
22414
22414
  layout: {
22415
22415
  mode: "floating",
22416
- position: "bottom-right",
22417
- panelWidth: 520,
22418
- panelMinHeight: 540,
22419
- panelMaxHeight: 820,
22416
+ position: "bottom-center",
22417
+ panelWidth: 970,
22418
+ panelMinHeight: 0,
22419
+ panelMaxHeight: 1025,
22420
22420
  edgeOffset: 20,
22421
22421
  zIndex: 2147483e3,
22422
22422
  density: "comfortable",
@@ -22429,11 +22429,13 @@ var DEFAULT_APPEARANCE = {
22429
22429
  showLauncher: true,
22430
22430
  showHeader: true,
22431
22431
  showAvatars: true,
22432
- showTimestamps: false
22432
+ showTimestamps: false,
22433
+ showPoweredBy: true
22433
22434
  },
22434
22435
  labels: {
22435
- welcomeHeading: "How can I help?",
22436
+ welcomeHeading: "",
22436
22437
  welcomeMessage: "",
22438
+ launcherPlaceholder: "Chat with us",
22437
22439
  composerPlaceholder: "Ask a question\u2026",
22438
22440
  thinking: "Thinking",
22439
22441
  send: "Send",
@@ -22467,11 +22469,12 @@ var DEFAULT_APPEARANCE = {
22467
22469
  },
22468
22470
  presentation: {
22469
22471
  panel: {
22470
- surface: "glass",
22472
+ surface: "solid",
22471
22473
  elevation: "soft",
22472
22474
  border: "subtle"
22473
22475
  },
22474
22476
  launcher: {
22477
+ style: "pill",
22475
22478
  icon: "brand-mark",
22476
22479
  size: "md",
22477
22480
  status: "none",
@@ -22481,7 +22484,11 @@ var DEFAULT_APPEARANCE = {
22481
22484
  composer: { leadingIcon: "none", sendIcon: "arrow-up", shape: "pill" },
22482
22485
  messages: { userStyle: "bubble", assistantStyle: "plain" }
22483
22486
  },
22484
- suggestedPrompts: [],
22487
+ suggestedPrompts: [
22488
+ "What products do you have?",
22489
+ "Tell me about your business",
22490
+ "How can I get in touch?"
22491
+ ],
22485
22492
  locale: "en",
22486
22493
  direction: "auto"
22487
22494
  };
@@ -22497,7 +22504,7 @@ function resolveAppearance(input = {}) {
22497
22504
  mark: themedAsset(branding?.mark)
22498
22505
  },
22499
22506
  theme: {
22500
- defaultMode: branding?.colorScheme ?? DEFAULT_APPEARANCE.theme.defaultMode,
22507
+ defaultMode: assistant?.theme ?? branding?.colorScheme ?? DEFAULT_APPEARANCE.theme.defaultMode,
22501
22508
  light: resolveTheme("light", branding),
22502
22509
  dark: resolveTheme("dark", branding)
22503
22510
  },
@@ -22508,9 +22515,17 @@ function resolveAppearance(input = {}) {
22508
22515
  ...assistant?.layout?.edgeOffset === void 0 ? {} : { edgeOffset: boundedNumber(assistant.layout.edgeOffset, 0, 96) }
22509
22516
  },
22510
22517
  behavior: { ...DEFAULT_APPEARANCE.behavior, ...assistant?.behavior },
22511
- labels: { ...DEFAULT_APPEARANCE.labels, ...assistant?.labels },
22518
+ labels: {
22519
+ ...DEFAULT_APPEARANCE.labels,
22520
+ ...branding?.name ? { launcherPlaceholder: `Chat with ${branding.name}` } : {},
22521
+ ...assistant?.labels
22522
+ },
22512
22523
  presentation: resolvePresentation(assistant?.presentation),
22513
- suggestedPrompts: assistant?.suggestedPrompts ?? DEFAULT_APPEARANCE.suggestedPrompts,
22524
+ suggestedPrompts: assistant?.suggestedPrompts ?? (branding?.name ? [
22525
+ "What products do you have?",
22526
+ `Tell me about ${branding.name}`,
22527
+ "How can I get in touch?"
22528
+ ] : DEFAULT_APPEARANCE.suggestedPrompts),
22514
22529
  ...assistant?.privacyUrl ? { privacyUrl: assistant.privacyUrl } : {},
22515
22530
  ...assistant?.termsUrl ? { termsUrl: assistant.termsUrl } : {},
22516
22531
  locale: assistant?.locale ?? DEFAULT_APPEARANCE.locale,
@@ -24781,6 +24796,10 @@ async function resolve(value) {
24781
24796
  return Promise.resolve(value);
24782
24797
  }
24783
24798
 
24799
+ // ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/index.js
24800
+ init_external();
24801
+ init_external();
24802
+
24784
24803
  // ../../node_modules/.pnpm/ai@6.0.201_zod@4.4.3/node_modules/ai/dist/index.mjs
24785
24804
  init_v4();
24786
24805
  init_v4();
@@ -27523,6 +27542,11 @@ function isRecord3(value) {
27523
27542
  // src/session-source.ts
27524
27543
  var NOODLE_CLOUD_URL = "https://cloud.noodleseed.dev";
27525
27544
  var PUBLIC_SESSION_PATH = "/v1/assistant/public-sessions";
27545
+ var PUBLIC_CONFIGURATION_PATH = "/v1/assistant/public-configurations";
27546
+ function publicConfigurationUrl(serviceUrl, embedId) {
27547
+ const base = (serviceUrl || NOODLE_CLOUD_URL).replace(/\/+$/, "");
27548
+ return `${base}${PUBLIC_CONFIGURATION_PATH}/${encodeURIComponent(embedId)}`;
27549
+ }
27526
27550
  function resolveSessionSource(options) {
27527
27551
  const { sessionEndpoint, embedId, serviceUrl } = options;
27528
27552
  if (Boolean(embedId) === Boolean(sessionEndpoint)) {
@@ -29034,11 +29058,11 @@ function createDOMPurify() {
29034
29058
  const originalDocument = document2;
29035
29059
  const currentScript = originalDocument.currentScript;
29036
29060
  window2.DocumentFragment;
29037
- const HTMLTemplateElement = window2.HTMLTemplateElement, Node = window2.Node, Element = window2.Element, NodeFilter = window2.NodeFilter, _window$NamedNodeMap = window2.NamedNodeMap;
29061
+ const HTMLTemplateElement = window2.HTMLTemplateElement, Node = window2.Node, Element2 = window2.Element, NodeFilter = window2.NodeFilter, _window$NamedNodeMap = window2.NamedNodeMap;
29038
29062
  _window$NamedNodeMap === void 0 ? window2.NamedNodeMap || window2.MozNamedAttrMap : _window$NamedNodeMap;
29039
29063
  window2.HTMLFormElement;
29040
29064
  const DOMParser = window2.DOMParser, trustedTypes = window2.trustedTypes;
29041
- const ElementPrototype = Element.prototype;
29065
+ const ElementPrototype = Element2.prototype;
29042
29066
  const cloneNode = lookupGetter(ElementPrototype, "cloneNode");
29043
29067
  const remove = lookupGetter(ElementPrototype, "remove");
29044
29068
  const getNextSibling = lookupGetter(ElementPrototype, "nextSibling");
@@ -31688,19 +31712,40 @@ function queryRequired(root, selector) {
31688
31712
  if (!element) throw new Error(`assistant renderer is missing ${selector}`);
31689
31713
  return element;
31690
31714
  }
31691
- function assistantElementMarkup(appearance, open, styles) {
31715
+ function assistantElementMarkup(appearance, styles) {
31692
31716
  return `${styles}
31693
- <button class="launcher" type="button" aria-label="${escapeAttribute(appearance.labels.open)}" aria-controls="assistant-panel" aria-expanded="${String(open)}"><slot name="launcher-icon"></slot><span class="visually-hidden" data-session-status aria-live="polite" hidden></span></button>
31717
+ <div class="launcher">
31718
+ <slot name="launcher-icon"></slot>
31719
+ <span class="launcher-loader" aria-hidden="true"></span>
31720
+ <button class="launcher-trigger" type="button" aria-label="${escapeAttribute(appearance.labels.open)}" aria-controls="assistant-launcher-form" aria-expanded="false">
31721
+ <span class="launcher-label">${escapeAttribute(appearance.labels.launcherPlaceholder)}</span>
31722
+ <span class="launcher-arrow" aria-hidden="true"></span>
31723
+ </button>
31724
+ <form class="launcher-form" id="assistant-launcher-form" aria-hidden="true" autocomplete="off">
31725
+ <input class="launcher-input" type="text" aria-label="${escapeAttribute(appearance.labels.launcherPlaceholder)}" placeholder="${escapeAttribute(appearance.labels.launcherPlaceholder)}" tabindex="-1">
31726
+ <button class="launcher-send" type="submit" aria-label="${escapeAttribute(appearance.labels.send)}"></button>
31727
+ </form>
31728
+ <span class="visually-hidden" data-session-status aria-live="polite" hidden></span>
31729
+ </div>
31694
31730
  <section class="panel" id="assistant-panel" role="dialog" aria-label="${escapeAttribute(appearance.brand.name)}">
31695
31731
  <header><slot name="header-leading"></slot><img class="brand-logo" alt=""><strong></strong><slot name="header-actions"></slot><button class="close" type="button" aria-label="${escapeAttribute(appearance.labels.close)}"></button></header>
31696
31732
  <div class="welcome"><slot name="empty-state"></slot></div>
31697
- <div class="suggested-prompts"></div>
31698
31733
  <div class="messages-region">
31699
31734
  <div class="messages" aria-live="polite"></div>
31700
31735
  <button class="new-messages" type="button" aria-label="${escapeAttribute(appearance.labels.newMessages)}" hidden></button>
31701
31736
  </div>
31702
- <form><slot name="composer-leading"></slot><textarea rows="1"></textarea><button class="send" type="submit"></button><slot name="composer-trailing"></slot></form>
31737
+ <div class="input-section">
31738
+ <div class="suggested-prompts"></div>
31739
+ <form class="composer"><slot name="composer-leading"></slot><textarea rows="1"></textarea><button class="send" type="submit"></button><slot name="composer-trailing"></slot></form>
31740
+ </div>
31703
31741
  <nav class="legal" aria-label="Legal"></nav>
31742
+ <div class="powered-by-row">
31743
+ <a class="powered-by" href="https://noodleseed.com" target="_blank" rel="noopener noreferrer">
31744
+ <span>Powered by</span>
31745
+ <span class="powered-by-icon" aria-hidden="true"><svg width="14" height="14" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><rect width="16" height="16" rx="8" fill="currentColor" fill-opacity="0.12"></rect><path d="M8.58023 12.8485C6.27833 12.8463 4.41315 11.0141 4.42117 8.75681L4.43588 4.61714L8.66254 4.62118C10.9644 4.62339 12.8296 6.45561 12.8216 8.71287C12.8135 10.9975 10.9128 12.8507 8.58023 12.8485Z" fill="currentColor"></path><path d="M8.82627 4.76869C11.1282 4.7709 12.9933 6.60312 12.9853 8.86038L12.9706 13L8.74395 12.996C6.44206 12.9938 4.57687 11.1616 4.5849 8.90432C4.59302 6.6197 6.49364 4.76646 8.82627 4.76869Z" fill="currentColor"></path><ellipse cx="3.69536" cy="3.68106" rx="0.695363" ry="0.681056" fill="currentColor"></ellipse></svg></span>
31746
+ <span class="powered-by-name">Noodle Seed</span>
31747
+ </a>
31748
+ </div>
31704
31749
  <slot name="conversation-footer"></slot>
31705
31750
  </section>`;
31706
31751
  }
@@ -31719,6 +31764,230 @@ function appendLegalLinks(legal, appearance) {
31719
31764
  }
31720
31765
  }
31721
31766
 
31767
+ // src/element-theme-resolution.ts
31768
+ function resolveAssistantTheme(input) {
31769
+ if (input.configured === "light" || input.configured === "dark") return input.configured;
31770
+ const hostMode = resolveHostTheme(input.host, input.media);
31771
+ return input.configured === "invert" ? opposite(hostMode) : hostMode;
31772
+ }
31773
+ function resolveHostTheme(host, media) {
31774
+ const view = host.ownerDocument.defaultView;
31775
+ for (let node = host.parentElement; node; node = node.parentElement) {
31776
+ const declared = declaredTheme(node);
31777
+ if (declared) return declared;
31778
+ const computed = computedTheme(view?.getComputedStyle(node).colorScheme);
31779
+ if (computed) return computed;
31780
+ }
31781
+ return media?.matches ? "dark" : "light";
31782
+ }
31783
+ function computedTheme(colorScheme) {
31784
+ const modes = colorScheme?.split(/\s+/) ?? [];
31785
+ if (modes.includes("dark") && !modes.includes("light")) return "dark";
31786
+ if (modes.includes("light") && !modes.includes("dark")) return "light";
31787
+ return void 0;
31788
+ }
31789
+ function declaredTheme(element) {
31790
+ const value = element.getAttribute("data-theme") ?? element.getAttribute("data-color-scheme") ?? element.getAttribute("data-mode");
31791
+ if (value === "dark" || value === "light") return value;
31792
+ if (element.classList.contains("dark")) return "dark";
31793
+ if (element.classList.contains("light")) return "light";
31794
+ return void 0;
31795
+ }
31796
+ function opposite(mode) {
31797
+ return mode === "dark" ? "light" : "dark";
31798
+ }
31799
+
31800
+ // src/element-host-environment-controller.ts
31801
+ var AssistantElementHostEnvironmentController = class {
31802
+ #host;
31803
+ #appearance;
31804
+ #applyTheme;
31805
+ #close;
31806
+ #media;
31807
+ #themeObserver;
31808
+ constructor(options) {
31809
+ this.#host = options.host;
31810
+ this.#appearance = options.appearance;
31811
+ this.#applyTheme = options.applyTheme;
31812
+ this.#close = options.close;
31813
+ }
31814
+ get media() {
31815
+ return this.#media;
31816
+ }
31817
+ resolvedTheme() {
31818
+ return resolveAssistantTheme({
31819
+ host: this.#host,
31820
+ configured: this.#host.getAttribute("theme") ?? this.#appearance().theme.defaultMode,
31821
+ ...this.#media ? { media: this.#media } : {}
31822
+ });
31823
+ }
31824
+ connect() {
31825
+ this.disconnect();
31826
+ this.#media = globalThis.matchMedia?.("(prefers-color-scheme: dark)");
31827
+ this.#media?.addEventListener("change", this.#applyTheme);
31828
+ this.#themeObserver = new MutationObserver(this.#applyTheme);
31829
+ for (let node = this.#host.parentElement; node; node = node.parentElement) {
31830
+ this.#themeObserver.observe(node, {
31831
+ attributes: true,
31832
+ attributeFilter: ["class", "data-theme", "data-color-scheme", "data-mode", "style"]
31833
+ });
31834
+ }
31835
+ document.addEventListener("keydown", this.#handleDocumentKeydown);
31836
+ document.addEventListener("pointerdown", this.#handleDocumentPointerDown);
31837
+ }
31838
+ disconnect() {
31839
+ this.#media?.removeEventListener("change", this.#applyTheme);
31840
+ this.#media = void 0;
31841
+ this.#themeObserver?.disconnect();
31842
+ this.#themeObserver = void 0;
31843
+ document.removeEventListener("keydown", this.#handleDocumentKeydown);
31844
+ document.removeEventListener("pointerdown", this.#handleDocumentPointerDown);
31845
+ }
31846
+ #handleDocumentKeydown = (event) => {
31847
+ if (event.key === "Escape" && this.#host.hasAttribute("open") && this.#appearance().behavior.closeOnEscape) {
31848
+ this.#close();
31849
+ }
31850
+ };
31851
+ #handleDocumentPointerDown = (event) => {
31852
+ if (this.#host.hasAttribute("open") && this.#appearance().behavior.closeOnOutsideClick && !event.composedPath().includes(this.#host)) {
31853
+ this.#close();
31854
+ }
31855
+ };
31856
+ };
31857
+
31858
+ // src/element-launcher-controller.ts
31859
+ var AssistantElementLauncherController = class {
31860
+ #host;
31861
+ #appearance;
31862
+ #openPanel;
31863
+ #sendMessage;
31864
+ #root;
31865
+ constructor(options) {
31866
+ this.#host = options.host;
31867
+ this.#appearance = options.appearance;
31868
+ this.#openPanel = options.openPanel;
31869
+ this.#sendMessage = options.sendMessage;
31870
+ }
31871
+ connect(root) {
31872
+ this.disconnect();
31873
+ this.#root = root;
31874
+ queryRequired(root, ".launcher").addEventListener(
31875
+ "click",
31876
+ this.#handleLauncherClick
31877
+ );
31878
+ queryRequired(root, ".launcher-trigger").addEventListener(
31879
+ "click",
31880
+ this.#handleTrigger
31881
+ );
31882
+ queryRequired(root, ".launcher-form").addEventListener(
31883
+ "submit",
31884
+ this.#handleSubmit
31885
+ );
31886
+ queryRequired(root, ".launcher-input").addEventListener(
31887
+ "keydown",
31888
+ this.#handleInputKeydown
31889
+ );
31890
+ document.addEventListener("pointerdown", this.#handleDocumentPointerDown);
31891
+ this.sync();
31892
+ }
31893
+ disconnect() {
31894
+ document.removeEventListener("pointerdown", this.#handleDocumentPointerDown);
31895
+ this.#root = void 0;
31896
+ }
31897
+ sync() {
31898
+ const root = this.#root;
31899
+ if (!root) return;
31900
+ const appearance = this.#appearance();
31901
+ const style = appearance.presentation.launcher.style;
31902
+ this.#host.dataset.launcherStyle = style;
31903
+ const trigger = queryRequired(root, ".launcher-trigger");
31904
+ const label = queryRequired(root, ".launcher-label");
31905
+ const input = queryRequired(root, ".launcher-input");
31906
+ label.textContent = appearance.labels.launcherPlaceholder;
31907
+ input.placeholder = appearance.labels.launcherPlaceholder;
31908
+ input.setAttribute("aria-label", appearance.labels.launcherPlaceholder);
31909
+ trigger.setAttribute("aria-label", appearance.labels.open);
31910
+ queryRequired(root, ".launcher-send").setAttribute(
31911
+ "aria-label",
31912
+ appearance.labels.send
31913
+ );
31914
+ queryRequired(root, ".launcher").hidden = !appearance.behavior.showLauncher;
31915
+ queryRequired(root, ".powered-by-row").hidden = !appearance.behavior.showPoweredBy;
31916
+ if (style === "bubble" || this.#host.hasAttribute("open")) this.collapse(true);
31917
+ }
31918
+ collapse(force = false) {
31919
+ const root = this.#root;
31920
+ if (!root) return;
31921
+ const input = queryRequired(root, ".launcher-input");
31922
+ if (!force && input.value.trim()) return;
31923
+ this.#host.removeAttribute("launcher-expanded");
31924
+ const form = queryRequired(root, ".launcher-form");
31925
+ const trigger = queryRequired(root, ".launcher-trigger");
31926
+ form.setAttribute("aria-hidden", "true");
31927
+ trigger.setAttribute("aria-expanded", "false");
31928
+ input.tabIndex = -1;
31929
+ input.blur();
31930
+ }
31931
+ focusTrigger() {
31932
+ this.#root?.querySelector(".launcher-trigger")?.focus();
31933
+ }
31934
+ #expand() {
31935
+ const root = this.#root;
31936
+ if (!root || this.#appearance().presentation.launcher.style === "bubble") return;
31937
+ this.#host.setAttribute("launcher-expanded", "");
31938
+ const form = queryRequired(root, ".launcher-form");
31939
+ const trigger = queryRequired(root, ".launcher-trigger");
31940
+ const input = queryRequired(root, ".launcher-input");
31941
+ form.setAttribute("aria-hidden", "false");
31942
+ trigger.setAttribute("aria-expanded", "true");
31943
+ input.tabIndex = 0;
31944
+ requestAnimationFrame(() => {
31945
+ if (this.#host.hasAttribute("launcher-expanded")) input.focus();
31946
+ });
31947
+ }
31948
+ #handleTrigger = () => {
31949
+ if (this.#appearance().presentation.launcher.style === "bubble") {
31950
+ this.#openPanel();
31951
+ return;
31952
+ }
31953
+ this.#expand();
31954
+ };
31955
+ #handleLauncherClick = (event) => {
31956
+ if (event.composedPath().some(
31957
+ (target) => target instanceof Element && target.matches(".launcher-trigger, .launcher-form")
31958
+ )) {
31959
+ return;
31960
+ }
31961
+ this.#handleTrigger();
31962
+ };
31963
+ #handleSubmit = (event) => {
31964
+ event.preventDefault();
31965
+ const input = this.#root?.querySelector(".launcher-input");
31966
+ const message = input?.value.trim() ?? "";
31967
+ if (input) input.value = "";
31968
+ this.#openPanel();
31969
+ if (message) this.#sendMessage(message);
31970
+ };
31971
+ #handleInputKeydown = (event) => {
31972
+ if (event.key === "Enter" && !event.isComposing) {
31973
+ event.preventDefault();
31974
+ this.#root?.querySelector(".launcher-form")?.requestSubmit();
31975
+ return;
31976
+ }
31977
+ if (event.key !== "Escape") return;
31978
+ event.preventDefault();
31979
+ event.stopPropagation();
31980
+ const input = this.#root?.querySelector(".launcher-input");
31981
+ if (input) input.value = "";
31982
+ this.collapse(true);
31983
+ this.focusTrigger();
31984
+ };
31985
+ #handleDocumentPointerDown = (event) => {
31986
+ if (event.composedPath().includes(this.#host)) return;
31987
+ this.collapse();
31988
+ };
31989
+ };
31990
+
31722
31991
  // src/element-page-context-controller.ts
31723
31992
  var AssistantElementPageContextController = class {
31724
31993
  #snapshot;
@@ -31772,10 +32041,12 @@ var AssistantElementPresentationGate = class {
31772
32041
  syncOpenState() {
31773
32042
  const open = this.#host.hasAttribute("open");
31774
32043
  const presentationReady = this.#host.hasAttribute("data-presentation-ready");
31775
- const launcher = this.#host.shadowRoot?.querySelector(".launcher");
31776
- launcher?.setAttribute("aria-expanded", String(open && presentationReady));
31777
- launcher?.setAttribute("aria-busy", String(open && !presentationReady));
31778
- if (launcher) launcher.disabled = open && !presentationReady;
32044
+ const publicConfigurationLoading = this.#host.hasAttribute("data-public-configuration-loading");
32045
+ const presentationBlocked = !presentationReady && (open || publicConfigurationLoading);
32046
+ const launcher = this.#host.shadowRoot?.querySelector(".launcher-trigger");
32047
+ launcher?.setAttribute("aria-busy", String(presentationBlocked));
32048
+ if (launcher) launcher.disabled = presentationBlocked;
32049
+ this.#host.shadowRoot?.querySelector(".panel")?.setAttribute("aria-hidden", String(!(open && presentationReady)));
31779
32050
  if (open && this.#host.isConnected) this.#primeSession();
31780
32051
  }
31781
32052
  reveal() {
@@ -31786,6 +32057,244 @@ var AssistantElementPresentationGate = class {
31786
32057
  }
31787
32058
  };
31788
32059
 
32060
+ // src/assistant-configuration-schema.ts
32061
+ var hexColorSchema = external_exports.string().regex(/^#[0-9A-Fa-f]{6}$/);
32062
+ var resolvedBorderColorSchema = external_exports.union([
32063
+ hexColorSchema,
32064
+ external_exports.string().max(64).refine(isBoundedRgbaColor, "must be a six-digit hex or bounded rgba color")
32065
+ ]);
32066
+ var browserAssetUrlSchema = external_exports.string().trim().url().refine(isSecureBrowserAssetUrl, "must use https (http is allowed only for loopback testing)");
32067
+ var httpsUrlSchema = external_exports.string().trim().url().refine(isHttpsUrl2, "must use https");
32068
+ var brandAssetSchema = external_exports.object({
32069
+ uri: browserAssetUrlSchema,
32070
+ darkUri: browserAssetUrlSchema.optional(),
32071
+ alt: external_exports.string().trim().min(1).max(240)
32072
+ }).strict();
32073
+ var brandThemeSchema = external_exports.object({
32074
+ surface: hexColorSchema.optional(),
32075
+ surfaceRaised: hexColorSchema.optional(),
32076
+ surfaceMuted: hexColorSchema.optional(),
32077
+ text: hexColorSchema.optional(),
32078
+ textMuted: hexColorSchema.optional(),
32079
+ accent: hexColorSchema.optional(),
32080
+ accentText: hexColorSchema.optional(),
32081
+ link: hexColorSchema.optional(),
32082
+ border: resolvedBorderColorSchema.optional(),
32083
+ borderStrong: resolvedBorderColorSchema.optional(),
32084
+ focus: hexColorSchema.optional(),
32085
+ success: hexColorSchema.optional(),
32086
+ warning: hexColorSchema.optional(),
32087
+ danger: hexColorSchema.optional(),
32088
+ code: hexColorSchema.optional()
32089
+ }).strict();
32090
+ var brandingSchema = external_exports.object({
32091
+ name: external_exports.string().trim().min(1).max(160).optional(),
32092
+ accent: hexColorSchema.optional(),
32093
+ surface: hexColorSchema.optional(),
32094
+ surfaceDark: hexColorSchema.optional(),
32095
+ logo: brandAssetSchema.optional(),
32096
+ mark: brandAssetSchema.optional(),
32097
+ avatar: brandAssetSchema.optional(),
32098
+ theme: external_exports.object({ light: brandThemeSchema.optional(), dark: brandThemeSchema.optional() }).strict().optional(),
32099
+ radius: external_exports.enum(["none", "sm", "md", "lg"]).optional(),
32100
+ density: external_exports.enum(["compact", "comfortable"]).optional(),
32101
+ typography: external_exports.enum(["system", "serif", "mono"]).optional(),
32102
+ colorScheme: external_exports.enum(["auto", "light", "dark"]).optional()
32103
+ }).strict();
32104
+ var labelsSchema = external_exports.object({
32105
+ welcomeHeading: external_exports.string().trim().min(1).max(160).optional(),
32106
+ welcomeMessage: external_exports.string().max(1e3).optional(),
32107
+ launcherPlaceholder: external_exports.string().trim().min(1).max(160).optional(),
32108
+ composerPlaceholder: external_exports.string().trim().min(1).max(160).optional(),
32109
+ thinking: external_exports.string().trim().min(1).max(80).optional(),
32110
+ send: external_exports.string().trim().min(1).max(80).optional(),
32111
+ stop: external_exports.string().trim().min(1).max(80).optional(),
32112
+ close: external_exports.string().trim().min(1).max(80).optional(),
32113
+ open: external_exports.string().trim().min(1).max(80).optional(),
32114
+ confirm: external_exports.string().trim().min(1).max(80).optional(),
32115
+ decline: external_exports.string().trim().min(1).max(80).optional(),
32116
+ cancel: external_exports.string().trim().min(1).max(80).optional(),
32117
+ confirmationHeading: external_exports.string().trim().min(1).max(120).optional(),
32118
+ additionalDetails: external_exports.string().trim().min(1).max(120).optional(),
32119
+ redacted: external_exports.string().trim().min(1).max(120).optional(),
32120
+ completed: external_exports.string().trim().min(1).max(80).optional(),
32121
+ stopped: external_exports.string().trim().min(1).max(80).optional(),
32122
+ copy: external_exports.string().trim().min(1).max(80).optional(),
32123
+ newMessages: external_exports.string().trim().min(1).max(80).optional(),
32124
+ reconnect: external_exports.string().trim().min(1).max(80).optional(),
32125
+ newConversation: external_exports.string().trim().min(1).max(80).optional(),
32126
+ retry: external_exports.string().trim().min(1).max(80).optional(),
32127
+ unavailable: external_exports.string().trim().min(1).max(240).optional(),
32128
+ sessionExpired: external_exports.string().trim().min(1).max(240).optional(),
32129
+ sessionIdle: external_exports.string().trim().min(1).max(120).optional(),
32130
+ sessionLoading: external_exports.string().trim().min(1).max(120).optional(),
32131
+ sessionReady: external_exports.string().trim().min(1).max(120).optional(),
32132
+ sessionError: external_exports.string().trim().min(1).max(120).optional(),
32133
+ signInHeading: external_exports.string().trim().min(1).max(120).optional(),
32134
+ signInBody: external_exports.string().max(240).optional(),
32135
+ signInAction: external_exports.string().trim().min(1).max(80).optional(),
32136
+ signUpAction: external_exports.string().trim().min(1).max(80).optional()
32137
+ }).strict();
32138
+ var presentationSchema = external_exports.object({
32139
+ panel: external_exports.object({
32140
+ surface: external_exports.enum(["solid", "glass"]).optional(),
32141
+ elevation: external_exports.enum(["soft", "dramatic"]).optional(),
32142
+ border: external_exports.enum(["subtle", "strong"]).optional(),
32143
+ radius: external_exports.number().int().min(0).max(64).optional()
32144
+ }).strict().optional(),
32145
+ launcher: external_exports.object({
32146
+ style: external_exports.enum(["pill", "bubble"]).optional(),
32147
+ icon: external_exports.enum(["brand-mark", "chat", "none"]).optional(),
32148
+ size: external_exports.enum(["md", "lg"]).optional(),
32149
+ status: external_exports.enum(["none", "session"]).optional(),
32150
+ effect: external_exports.enum(["none", "pulse"]).optional()
32151
+ }).strict().optional(),
32152
+ header: external_exports.object({
32153
+ mark: external_exports.enum(["none", "brand-mark", "status"]).optional(),
32154
+ badge: external_exports.object({
32155
+ text: external_exports.string().trim().min(1).max(80),
32156
+ tone: external_exports.enum(["neutral", "success", "warning", "danger"]).optional(),
32157
+ indicator: external_exports.boolean().optional()
32158
+ }).strict().optional()
32159
+ }).strict().optional(),
32160
+ composer: external_exports.object({
32161
+ leadingIcon: external_exports.enum(["none", "brand-mark"]).optional(),
32162
+ sendIcon: external_exports.enum(["arrow-up", "paper-plane"]).optional(),
32163
+ shape: external_exports.enum(["rounded", "pill"]).optional()
32164
+ }).strict().optional(),
32165
+ messages: external_exports.object({
32166
+ userStyle: external_exports.enum(["bubble", "accent"]).optional(),
32167
+ assistantStyle: external_exports.enum(["plain", "bubble"]).optional()
32168
+ }).strict().optional()
32169
+ }).strict();
32170
+ var assistantUiSchema = external_exports.object({
32171
+ theme: external_exports.enum(["auto", "light", "dark", "invert"]).optional(),
32172
+ layout: external_exports.object({
32173
+ mode: external_exports.enum(["floating", "inline", "drawer"]).optional(),
32174
+ position: external_exports.enum(["bottom-left", "bottom-center", "bottom-right"]).optional(),
32175
+ panelWidth: external_exports.number().int().min(280).max(1200).optional(),
32176
+ panelMinHeight: external_exports.number().int().min(240).max(1600).optional(),
32177
+ panelMaxHeight: external_exports.number().int().min(320).max(2400).optional(),
32178
+ edgeOffset: external_exports.number().int().min(0).max(96).optional(),
32179
+ zIndex: external_exports.number().int().min(0).max(2147483647).optional(),
32180
+ density: external_exports.enum(["compact", "comfortable"]).optional(),
32181
+ mobileFullscreen: external_exports.boolean().optional()
32182
+ }).strict().optional(),
32183
+ behavior: external_exports.object({
32184
+ startOpen: external_exports.boolean().optional(),
32185
+ closeOnEscape: external_exports.boolean().optional(),
32186
+ closeOnOutsideClick: external_exports.boolean().optional(),
32187
+ showLauncher: external_exports.boolean().optional(),
32188
+ showHeader: external_exports.boolean().optional(),
32189
+ showAvatars: external_exports.boolean().optional(),
32190
+ showTimestamps: external_exports.boolean().optional(),
32191
+ showPoweredBy: external_exports.boolean().optional()
32192
+ }).strict().optional(),
32193
+ labels: labelsSchema.optional(),
32194
+ presentation: presentationSchema.optional(),
32195
+ suggestedPrompts: external_exports.array(external_exports.string().trim().min(1).max(240)).max(8).optional(),
32196
+ privacyUrl: httpsUrlSchema.optional(),
32197
+ termsUrl: httpsUrlSchema.optional(),
32198
+ locale: external_exports.string().trim().min(2).max(35).optional(),
32199
+ direction: external_exports.enum(["ltr", "rtl", "auto"]).optional()
32200
+ }).strict();
32201
+ var assistantConfigurationSchema = external_exports.object({ branding: brandingSchema.optional(), assistant: assistantUiSchema.optional() }).strict();
32202
+ function parseAssistantConfiguration(value) {
32203
+ const parsed = assistantConfigurationSchema.safeParse(value);
32204
+ return parsed.success ? parsed.data : void 0;
32205
+ }
32206
+ function isHttpsUrl2(value) {
32207
+ try {
32208
+ return new URL(value).protocol === "https:";
32209
+ } catch {
32210
+ return false;
32211
+ }
32212
+ }
32213
+ function isSecureBrowserAssetUrl(value) {
32214
+ try {
32215
+ const url2 = new URL(value);
32216
+ if (url2.protocol === "https:") return true;
32217
+ if (url2.protocol !== "http:") return false;
32218
+ return url2.hostname === "localhost" || url2.hostname === "127.0.0.1" || url2.hostname === "[::1]";
32219
+ } catch {
32220
+ return false;
32221
+ }
32222
+ }
32223
+ function isBoundedRgbaColor(value) {
32224
+ const match = /^rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(0(?:\.\d{1,6})?|1(?:\.0{1,6})?)\s*\)$/.exec(
32225
+ value
32226
+ );
32227
+ if (match === null) return false;
32228
+ return match.slice(1, 4).every((channel) => Number(channel) <= 255);
32229
+ }
32230
+
32231
+ // src/element-public-configuration-controller.ts
32232
+ var AssistantElementPublicConfigurationController = class {
32233
+ #source;
32234
+ #apply;
32235
+ #loadingChanged;
32236
+ #generation = 0;
32237
+ #bootstrap;
32238
+ #abort;
32239
+ constructor(source, apply2, loadingChanged) {
32240
+ this.#source = source;
32241
+ this.#apply = apply2;
32242
+ this.#loadingChanged = loadingChanged;
32243
+ }
32244
+ connect() {
32245
+ this.#restart();
32246
+ }
32247
+ refresh() {
32248
+ this.#restart();
32249
+ }
32250
+ disconnect() {
32251
+ this.#generation += 1;
32252
+ this.#abort?.abort();
32253
+ this.#abort = void 0;
32254
+ this.#bootstrap = void 0;
32255
+ }
32256
+ #restart() {
32257
+ this.disconnect();
32258
+ this.#prime();
32259
+ }
32260
+ #prime() {
32261
+ const source = this.#source();
32262
+ if (!source.embedId || this.#bootstrap) return;
32263
+ const generation = this.#generation;
32264
+ const abort = new AbortController();
32265
+ this.#abort = abort;
32266
+ const fetcher = source.fetch ?? ((input, init) => globalThis.fetch(input, init));
32267
+ this.#loadingChanged(true);
32268
+ const bootstrap = Promise.resolve().then(
32269
+ () => fetcher(publicConfigurationUrl(source.serviceUrl, source.embedId), {
32270
+ method: "GET",
32271
+ headers: { accept: "application/json" },
32272
+ credentials: "omit",
32273
+ cache: "no-cache",
32274
+ signal: abort.signal
32275
+ })
32276
+ ).then(async (response) => {
32277
+ if (!response.ok) return;
32278
+ const value = await response.json();
32279
+ if (generation !== this.#generation || !isRecord6(value)) {
32280
+ return;
32281
+ }
32282
+ const configuration = parseAssistantConfiguration(value.configuration);
32283
+ if (configuration !== void 0) this.#apply(configuration);
32284
+ }).catch(() => void 0).finally(() => {
32285
+ if (generation === this.#generation) this.#loadingChanged(false);
32286
+ if (this.#bootstrap === bootstrap) {
32287
+ this.#bootstrap = void 0;
32288
+ this.#abort = void 0;
32289
+ }
32290
+ });
32291
+ this.#bootstrap = bootstrap;
32292
+ }
32293
+ };
32294
+ function isRecord6(value) {
32295
+ return typeof value === "object" && value !== null && !Array.isArray(value);
32296
+ }
32297
+
31789
32298
  // src/element-scroll-controller.ts
31790
32299
  var AssistantElementScrollController = class {
31791
32300
  #region;
@@ -31915,44 +32424,69 @@ var ASSISTANT_ELEMENT_STYLES = `<style>
31915
32424
  *, *::before, *::after { box-sizing: border-box; }
31916
32425
  .visually-hidden { position: absolute !important; width: 1px !important; height: 1px !important; padding: 0 !important; margin: -1px !important; overflow: hidden !important; clip: rect(0, 0, 0, 0) !important; white-space: nowrap !important; border: 0 !important; }
31917
32426
  .visually-hidden[hidden] { display: none !important; }
31918
- :host { color-scheme: light dark; font-family: var(--ns-assistant-font-family, var(--ns-assistant-default-font-family)); font-size: var(--ns-assistant-base-font-size, var(--ns-assistant-default-base-font-size)); line-height: var(--ns-assistant-line-height, var(--ns-assistant-default-line-height)); z-index: var(--ns-assistant-z-index, var(--ns-assistant-default-z-index)); -webkit-font-smoothing: antialiased; }
31919
- :host([data-mode="floating"]) { position: fixed; bottom: 20px; right: 20px; }
31920
- :host([data-mode="floating"][data-position="bottom-left"]) { right: auto; left: 20px; }
32427
+ :host { --ns-assistant-halo-launcher-action: #f4f4f5; --ns-assistant-halo-launcher-action-hover: #e4e4e7; --ns-assistant-halo-launcher-border: rgba(0,0,0,.04); --ns-assistant-halo-launcher-shadow: 0 1px 8px rgba(0,0,0,.04); --ns-assistant-halo-launcher-shadow-hover: 0 2px 12px rgba(0,0,0,.06); --ns-assistant-halo-send-button: #e4e4e7; --ns-assistant-halo-send-button-text: #09090b; box-sizing: border-box; color-scheme: light dark; font-family: var(--ns-assistant-font-family, var(--ns-assistant-default-font-family)); font-size: var(--ns-assistant-base-font-size, var(--ns-assistant-default-base-font-size)); line-height: var(--ns-assistant-line-height, var(--ns-assistant-default-line-height)); z-index: var(--ns-assistant-z-index, var(--ns-assistant-default-z-index)); -webkit-font-smoothing: antialiased; }
32428
+ :host([data-theme="dark"]) { --ns-assistant-halo-launcher-action: #3f3f46; --ns-assistant-halo-launcher-action-hover: #52525b; --ns-assistant-halo-launcher-border: rgba(255,255,255,.1); --ns-assistant-halo-launcher-shadow: 0 4px 20px rgba(0,0,0,.3); --ns-assistant-halo-launcher-shadow-hover: 0 6px 24px rgba(0,0,0,.4); --ns-assistant-halo-send-button: #3f3f46; --ns-assistant-halo-send-button-text: #fff; }
32429
+ :host([data-mode="floating"]) { position: fixed; }
32430
+ :host([data-mode="floating"][open]) { width: min(var(--ns-assistant-panel-width, var(--ns-assistant-default-panel-width)), 100vw); }
31921
32431
  button { font: inherit; }
31922
32432
  button, textarea, input, select { -webkit-tap-highlight-color: transparent; }
31923
- .launcher { display: grid; place-items: center; width: 48px; height: 48px; border: 1px solid var(--ns-assistant-launcher-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); border-radius: 999px; color: var(--ns-assistant-launcher-text, var(--ns-assistant-text, var(--ns-assistant-default-text))); background: var(--ns-assistant-launcher, var(--ns-assistant-panel, var(--ns-assistant-default-panel))); box-shadow: 0 8px 28px rgba(0,0,0,.14); cursor: pointer; transition: transform .24s cubic-bezier(.25,1,.5,1), box-shadow .2s ease; }
31924
- .launcher:hover { transform: translateY(-2px) scale(1.03); box-shadow: 0 8px 26px rgba(0,0,0,.16); }
31925
- .launcher img { width: 28px; height: 28px; border-radius: 50%; object-fit: contain; }
31926
- .panel { display: none; flex-direction: column; width: min(var(--ns-assistant-panel-width, var(--ns-assistant-default-panel-width)), calc(100vw - 40px)); min-height: var(--ns-assistant-min-height, var(--ns-assistant-default-min-height)); max-height: min(var(--ns-assistant-max-height, var(--ns-assistant-default-max-height)), calc(100vh - 40px)); overflow: hidden; color: var(--ns-assistant-panel-text, var(--ns-assistant-text, var(--ns-assistant-default-text))); background: var(--ns-assistant-panel, var(--ns-assistant-default-panel)); border: 1px solid var(--ns-assistant-panel-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); border-radius: var(--ns-assistant-panel-radius, var(--ns-assistant-default-panel-radius)); box-shadow: var(--ns-assistant-shadow, var(--ns-assistant-default-shadow)); transform-origin: bottom right; isolation: isolate; animation: halo-panel-in .28s cubic-bezier(.23,1,.32,1) both; }
32433
+ .launcher { display: flex; align-items: center; justify-content: center; gap: 12px; width: max-content; min-height: 44px; padding: 10px 14px; color: var(--ns-assistant-launcher-text, var(--ns-assistant-text, var(--ns-assistant-default-text))); background: var(--ns-assistant-launcher, color-mix(in srgb, var(--ns-assistant-panel, var(--ns-assistant-default-panel)) 50%, transparent)); border: 1px solid var(--ns-assistant-launcher-border, var(--ns-assistant-halo-launcher-border)); border-radius: 999px; box-shadow: var(--ns-assistant-halo-launcher-shadow), -6px 0 18px color-mix(in srgb, var(--ns-assistant-accent, var(--ns-assistant-default-accent)) 20%, transparent), 6px 0 18px color-mix(in srgb, var(--ns-assistant-accent, var(--ns-assistant-default-accent)) 20%, transparent), 0 0 40px color-mix(in srgb, var(--ns-assistant-accent, var(--ns-assistant-default-accent)) 10%, transparent); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); transition: width .5s cubic-bezier(.25,1,.5,1), height .5s cubic-bezier(.25,1,.5,1), padding .5s cubic-bezier(.25,1,.5,1), gap .35s cubic-bezier(.25,1,.5,1), transform .6s cubic-bezier(.25,1,.5,1), background-color .3s ease, box-shadow .3s ease; }
32434
+ :host([data-presentation-ready]) .launcher { padding: 10px 12px; }
32435
+ .launcher[hidden] { display: none; }
32436
+ .launcher:hover { transform: scale(1.02); box-shadow: var(--ns-assistant-halo-launcher-shadow-hover), -6px 0 18px color-mix(in srgb, var(--ns-assistant-accent, var(--ns-assistant-default-accent)) 20%, transparent), 6px 0 18px color-mix(in srgb, var(--ns-assistant-accent, var(--ns-assistant-default-accent)) 20%, transparent); }
32437
+ .launcher-trigger, .launcher-form { min-width: 0; margin: 0; padding: 0; border: 0; background: transparent; font: inherit; }
32438
+ .launcher-trigger { display: flex; align-items: center; gap: 12px; min-height: 28px; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); cursor: text; }
32439
+ .launcher-label { padding-left: 6px; white-space: nowrap; font-size: 15px; line-height: 20px; }
32440
+ .launcher-arrow, .launcher-send { position: relative; display: grid; width: 28px; height: 28px; flex: 0 0 28px; place-items: center; border: 0; border-radius: 50%; color: var(--ns-assistant-text, var(--ns-assistant-default-text)); background: var(--ns-assistant-launcher-action, var(--ns-assistant-halo-launcher-action)); cursor: pointer; }
32441
+ .launcher-arrow:hover, .launcher-send:hover { background: var(--ns-assistant-launcher-action-hover, var(--ns-assistant-halo-launcher-action-hover)); }
32442
+ .launcher-arrow::before, .launcher-send::before { content: ''; width: 16px; height: 16px; background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 19V5M5 12l7-7 7 7' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 19V5M5 12l7-7 7 7' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; }
32443
+ .launcher-form { display: none; flex: 1; align-items: center; gap: 12px; opacity: 0; pointer-events: none; }
32444
+ .launcher-input { width: 100%; min-width: 0; height: 28px; padding: 0 0 0 6px; color: var(--ns-assistant-text, var(--ns-assistant-default-text)); background: transparent; border: 0; outline: 0; box-shadow: none; appearance: none; font: inherit; font-size: 16px; line-height: 20px; }
32445
+ .launcher-input::placeholder { color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); }
32446
+ :host([launcher-expanded]) .launcher { width: min(400px, calc(100vw - 40px)); justify-content: flex-start; }
32447
+ :host([launcher-expanded]) .launcher-trigger { display: none; }
32448
+ :host([launcher-expanded]) .launcher-form { display: flex; opacity: 1; pointer-events: auto; }
32449
+ :host([data-launcher-style="bubble"]) .launcher { gap: 0; min-height: 0; padding: 6px; cursor: pointer; }
32450
+ :host([data-launcher-style="bubble"]) .launcher-trigger { position: absolute; inset: 0; display: block; width: 100%; height: 100%; cursor: pointer; }
32451
+ :host([data-launcher-style="bubble"]) .launcher-label, :host([data-launcher-style="bubble"]) .launcher-arrow, :host([data-launcher-style="bubble"]) .launcher-form { display: none; }
32452
+ :host([data-launcher-style="bubble"]) .launcher-visual { width: 32px; height: 32px; flex-basis: 32px; }
32453
+ .launcher-loader { display: none; width: 16px; height: 16px; flex: 0 0 16px; border: 2px solid var(--ns-assistant-divider, var(--ns-assistant-default-divider)); border-top-color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); border-radius: 50%; animation: halo-spin .8s linear infinite; }
32454
+ :host([data-session-state="loading"]:not([data-presentation-ready])) .launcher-loader, :host([data-public-configuration-loading]:not([data-presentation-ready])) .launcher-loader { display: block; }
32455
+ :host([data-session-state="loading"]:not([data-presentation-ready])) .launcher > :not(.launcher-loader):not([data-session-status]), :host([data-public-configuration-loading]:not([data-presentation-ready])) .launcher > :not(.launcher-loader):not([data-session-status]) { display: none; }
32456
+ .panel { display: none; flex-direction: column; width: 100%; max-width: 970px; height: min(85dvh, var(--ns-assistant-max-height, var(--ns-assistant-default-max-height)), calc(100dvh - 40px)); min-height: min(var(--ns-assistant-min-height, var(--ns-assistant-default-min-height)), calc(100dvh - 40px)); max-height: min(var(--ns-assistant-max-height, var(--ns-assistant-default-max-height)), calc(100dvh - 40px)); overflow: hidden; color: var(--ns-assistant-panel-text, var(--ns-assistant-text, var(--ns-assistant-default-text))); background: var(--ns-assistant-panel, var(--ns-assistant-default-panel)); border: 1px solid var(--ns-assistant-panel-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); border-radius: var(--ns-assistant-panel-radius, var(--ns-assistant-default-panel-radius)); box-shadow: var(--ns-assistant-shadow, var(--ns-assistant-default-shadow)); transform-origin: bottom center; isolation: isolate; animation: halo-panel-in .3s ease both; }
32457
+ :host([data-mode="floating"][open]) .panel { width: calc(100% - 40px); margin-inline: 20px; }
31927
32458
  :host([open][data-presentation-ready]) .panel { display: flex; }
31928
32459
  .panel { position: relative; }
31929
32460
  :host([open][data-presentation-ready]) .launcher { display: none; }
31930
32461
  :host([open]:not([data-presentation-ready])) .launcher { cursor: progress; opacity: .72; transform: none; }
31931
- header { display: flex; flex: 0 0 auto; gap: 10px; align-items: center; min-height: 64px; padding: 12px 18px; color: var(--ns-assistant-header-text, inherit); background: var(--ns-assistant-header, transparent); border-bottom: 1px solid color-mix(in srgb, var(--ns-assistant-header-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))) 78%, transparent); }
32462
+ header { display: flex; flex: 0 0 auto; gap: 10px; align-items: center; min-height: 64px; padding: 16px 20px; color: var(--ns-assistant-header-text, inherit); background: var(--ns-assistant-header, transparent); border-bottom: 1px solid var(--ns-assistant-header-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); }
31932
32463
  header strong { flex: 1; font-size: 16px; font-weight: 600; letter-spacing: 0; }
31933
32464
  .brand-logo { display: block; max-width: 120px; max-height: 28px; object-fit: contain; }
31934
32465
  .close, .send { display: grid; place-items: center; border: 0; border-radius: var(--ns-assistant-button-radius, var(--ns-assistant-default-button-radius)); cursor: pointer; }
31935
- .close { position: relative; width: 44px; height: 44px; padding: 0; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); background: transparent; transition: background .15s ease, color .15s ease, transform .15s ease; }
31936
- .close::before { content: ''; width: 18px; height: 18px; background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m6 6 12 12M18 6 6 18' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m6 6 12 12M18 6 6 18' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat; }
32466
+ .close { position: relative; width: 44px; height: 44px; margin: -6px; padding: 0; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); background: transparent; transition: background .15s ease, color .15s ease, transform .15s ease; }
32467
+ .close::before { content: ''; width: 20px; height: 20px; background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m6 6 12 12M18 6 6 18' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m6 6 12 12M18 6 6 18' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat; }
31937
32468
  .close:hover { color: var(--ns-assistant-text, var(--ns-assistant-default-text)); background: var(--ns-assistant-elevated, var(--ns-assistant-default-elevated)); }
31938
32469
  .close:active { transform: scale(.96); }
31939
- .welcome { flex: 0 0 auto; padding: 30px 22px 18px; }
32470
+ .welcome { flex: 0 0 auto; padding: 24px 20px 8px; }
31940
32471
  .welcome h2 { margin: 0; font-size: 1.35em; line-height: 1.25; letter-spacing: 0; }
31941
32472
  .welcome p { max-width: 42ch; margin: 7px 0 0; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); }
31942
- :host([has-messages]) .welcome, :host([has-messages]) .suggested-prompts { display: none; }
31943
- .suggested-prompts { display: flex; flex: 0 0 auto; flex-wrap: wrap; gap: 8px; padding: 0 20px 16px; }
32473
+ .welcome:has(.empty-state[hidden]) { display: none; }
32474
+ :host([has-messages]) .welcome { display: none; }
32475
+ .input-section { flex: 0 0 auto; padding: 8px 16px 16px; }
32476
+ .suggested-prompts { display: flex; flex: 0 0 auto; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
31944
32477
  .suggested-prompts:empty { display: none; }
31945
- .suggested-prompts button { min-height: 44px; padding: 8px 14px; color: var(--ns-assistant-suggestion-text, var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text))); background: var(--ns-assistant-suggestion, color-mix(in srgb, var(--ns-assistant-input, var(--ns-assistant-default-input)) 58%, transparent)); border: 1px solid var(--ns-assistant-suggestion-border, color-mix(in srgb, var(--ns-assistant-divider, var(--ns-assistant-default-divider)) 82%, transparent)); border-radius: 999px; cursor: pointer; font-size: .86em; transition: background .2s ease, color .2s ease, border-color .2s ease, transform .2s ease; }
31946
- .suggested-prompts button:hover { color: var(--ns-assistant-text, var(--ns-assistant-default-text)); background: var(--ns-assistant-elevated, var(--ns-assistant-default-elevated)); transform: translateY(-1px); }
32478
+ .suggested-prompts button { position: relative; display: inline-flex; align-items: center; padding: 6px 12px; color: var(--ns-assistant-suggestion-text, var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text))); background: var(--ns-assistant-suggestion, transparent); border: 1px solid var(--ns-assistant-suggestion-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); border-radius: 999px; cursor: pointer; font-size: 12px; white-space: nowrap; transition: background .2s ease, color .2s ease; }
32479
+ .suggested-prompts button::before { content: ''; position: absolute; inset: -6px -2px; }
32480
+ .suggested-prompts button:hover { color: var(--ns-assistant-text, var(--ns-assistant-default-text)); background: var(--ns-assistant-elevated, var(--ns-assistant-default-elevated)); }
31947
32481
  .messages-region { position: relative; display: flex; flex: 1 1 auto; min-height: 0; overflow: hidden; }
31948
32482
  .messages-region::before, .messages-region::after { content: ''; position: absolute; right: 0; left: 0; z-index: 1; height: 18px; pointer-events: none; opacity: 0; transition: opacity .18s ease; }
31949
32483
  .messages-region::before { top: 0; background: linear-gradient(to bottom, color-mix(in srgb, var(--ns-assistant-panel, var(--ns-assistant-default-panel)) 92%, transparent), transparent); }
31950
32484
  .messages-region::after { bottom: 0; background: linear-gradient(to top, color-mix(in srgb, var(--ns-assistant-panel, var(--ns-assistant-default-panel)) 92%, transparent), transparent); }
31951
32485
  .messages-region[data-can-scroll-up]::before, .messages-region[data-can-scroll-down]::after { opacity: 1; }
31952
- .messages { flex: 1 1 auto; width: 100%; min-height: 0; padding: 18px 20px 24px; overflow-y: auto; background: var(--ns-assistant-canvas, transparent); overscroll-behavior: contain; scroll-behavior: smooth; }
32486
+ .messages { flex: 1 1 auto; width: 100%; min-height: 0; padding: 16px 20px; overflow-y: auto; background: var(--ns-assistant-canvas, transparent); overscroll-behavior: contain; scroll-behavior: smooth; }
31953
32487
  .messages::-webkit-scrollbar { width: 6px; }
31954
32488
  .messages::-webkit-scrollbar-thumb { background: var(--ns-assistant-divider, var(--ns-assistant-default-divider)); border-radius: 999px; }
31955
- .message { width: fit-content; max-width: 88%; margin: 0 0 14px; padding: 0; border-radius: var(--ns-assistant-card-radius, var(--ns-assistant-default-card-radius)); background: transparent; white-space: pre-wrap; animation: halo-message-in .2s ease both; }
32489
+ .message { width: fit-content; max-width: 88%; margin: 0 0 12px; padding: 0; border-radius: var(--ns-assistant-card-radius, var(--ns-assistant-default-card-radius)); background: transparent; white-space: pre-wrap; animation: halo-message-in .2s ease both; }
31956
32490
  .message > span, .message > .markdown { overflow-wrap: anywhere; }
31957
32491
  .message .avatar { float: left; width: 24px; height: 24px; margin-right: 9px; border-radius: 50%; object-fit: cover; }
31958
32492
  .message time { display: block; margin-top: 4px; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); font-size: .75em; line-height: 1.2; }
@@ -31965,7 +32499,7 @@ var ASSISTANT_ELEMENT_STYLES = `<style>
31965
32499
  .new-messages { position: absolute; left: 50%; bottom: 14px; z-index: 2; width: 44px; height: 44px; padding: 0; color: var(--ns-assistant-secondary-button-text, var(--ns-assistant-text, var(--ns-assistant-default-text))); background: var(--ns-assistant-secondary-button, color-mix(in srgb, var(--ns-assistant-input, var(--ns-assistant-default-input)) 92%, transparent)); border: 1px solid var(--ns-assistant-secondary-button-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); border-radius: var(--ns-assistant-button-radius, var(--ns-assistant-default-button-radius)); box-shadow: 0 8px 24px rgba(0,0,0,.12); transform: translateX(-50%); cursor: pointer; }
31966
32500
  .new-messages::before { content: ''; display: block; width: 18px; height: 18px; margin: auto; background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m6 9 6 6 6-6' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m6 9 6 6 6-6' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; }
31967
32501
  .message.assistant { max-width: 100%; color: var(--ns-assistant-assistant-message-text, inherit); background: var(--ns-assistant-assistant-message, transparent); border: 1px solid var(--ns-assistant-assistant-message-border, transparent); }
31968
- .message.user { display: grid; max-width: 85%; justify-items: start; gap: 3px; margin-left: auto; padding: 10px 16px 8px; color: var(--ns-assistant-user-message-text, var(--ns-assistant-text, var(--ns-assistant-default-text))); background: var(--ns-assistant-user-message, var(--ns-assistant-elevated, var(--ns-assistant-default-elevated))); border: 1px solid var(--ns-assistant-user-message-border, transparent); border-radius: var(--ns-assistant-card-radius, var(--ns-assistant-default-card-radius)); font-size: .94em; }
32502
+ .message.user { display: grid; max-width: 85%; justify-items: start; gap: 3px; margin-left: auto; padding: 10px 16px; color: var(--ns-assistant-user-message-text, var(--ns-assistant-text, var(--ns-assistant-default-text))); background: var(--ns-assistant-user-message, var(--ns-assistant-elevated, var(--ns-assistant-default-elevated))); border: 1px solid var(--ns-assistant-user-message-border, transparent); border-radius: var(--ns-assistant-card-radius, var(--ns-assistant-default-card-radius)); font-size: 14px; }
31969
32503
  .message.user time { margin-top: 0; }
31970
32504
  .markdown { white-space: normal; }
31971
32505
  .markdown p { margin: 0 0 8px; }
@@ -32015,31 +32549,39 @@ var ASSISTANT_ELEMENT_STYLES = `<style>
32015
32549
  .input-request input:focus-visible, .input-request select:focus-visible { border-color: var(--ns-assistant-focus, var(--ns-assistant-default-focus)); box-shadow: 0 0 0 2px var(--ns-assistant-focus, var(--ns-assistant-default-focus)); }
32016
32550
  .input-request .proposal-actions { margin-top: 2px; }
32017
32551
  ${ASSISTANT_APP_VIEW_CSS}
32018
- form { display: flex; flex: 0 0 auto; gap: 8px; align-items: center; min-height: 56px; margin: 8px 16px 16px; padding: 6px 6px 6px 16px; color: var(--ns-assistant-composer-text, inherit); border: 1px solid var(--ns-assistant-composer-border, color-mix(in srgb, var(--ns-assistant-divider, var(--ns-assistant-default-divider)) 86%, transparent)); border-radius: var(--ns-assistant-input-radius, var(--ns-assistant-default-input-radius)); background: var(--ns-assistant-composer, color-mix(in srgb, var(--ns-assistant-input, var(--ns-assistant-default-input)) 92%, transparent)); box-shadow: 0 1px 2px rgba(0,0,0,.04), 0 8px 24px rgba(0,0,0,.035); transition: border-color .15s ease, box-shadow .15s ease; }
32019
- form:focus-within { box-shadow: inset 0 0 0 1px var(--ns-assistant-focus, var(--ns-assistant-default-focus)), 0 0 0 2px var(--ns-assistant-focus, var(--ns-assistant-default-focus)); }
32552
+ .composer { display: flex; flex: 0 0 auto; gap: 8px; align-items: center; min-height: 44px; margin: 0; padding: 8px 8px 8px 16px; color: var(--ns-assistant-composer-text, inherit); border: 1px solid var(--ns-assistant-composer-border, transparent); border-radius: var(--ns-assistant-input-radius, var(--ns-assistant-default-input-radius)); background: var(--ns-assistant-composer, var(--ns-assistant-input, var(--ns-assistant-default-input))); transition: border-color .15s ease, box-shadow .15s ease; }
32553
+ .composer:focus-within { border-color: var(--ns-assistant-focus, var(--ns-assistant-default-focus)); box-shadow: 0 0 0 2px color-mix(in srgb, var(--ns-assistant-focus, var(--ns-assistant-default-focus)) 32%, transparent); }
32020
32554
  textarea { flex: 1; min-height: 24px; max-height: 120px; resize: none; padding: 0; color: var(--ns-assistant-text, var(--ns-assistant-default-text)); background: transparent; border: 0; border-radius: 0; outline: 0; box-shadow: none; appearance: none; -webkit-appearance: none; font: inherit; font-size: 16px; line-height: 24px; }
32021
32555
  textarea::placeholder { color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); }
32022
32556
  textarea:focus, textarea:focus-visible { outline: none; box-shadow: none; }
32023
32557
  button:focus-visible { outline: 3px solid var(--ns-assistant-focus, var(--ns-assistant-default-focus)); outline-offset: 2px; }
32024
- .send { position: relative; display: block; width: 44px; height: 44px; flex: 0 0 44px; padding: 0; overflow: hidden; color: transparent; border-radius: 999px; background: var(--ns-assistant-primary-button, var(--ns-assistant-accent, var(--ns-assistant-default-accent))); font-size: 0; line-height: 0; transition: transform .15s ease, background .15s ease; }
32025
- .send::before { content: ''; position: absolute; top: 50%; left: 50%; width: 17px; height: 17px; background: var(--ns-assistant-primary-button-text, var(--ns-assistant-accent-text, var(--ns-assistant-default-accent-text))); transform: translate(-50%, -50%); -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 19V5M5 12l7-7 7 7' fill='none' stroke='black' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 19V5M5 12l7-7 7 7' fill='none' stroke='black' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; }
32026
- .send:hover { transform: scale(1.05); background: var(--ns-assistant-hover, color-mix(in srgb, var(--ns-assistant-primary-button, var(--ns-assistant-accent, var(--ns-assistant-default-accent))) 88%, var(--ns-assistant-primary-button-text, var(--ns-assistant-accent-text, var(--ns-assistant-default-accent-text))) 12%)); }
32558
+ .send { position: relative; display: block; width: 44px; height: 44px; flex: 0 0 44px; margin: -8px; padding: 0; overflow: visible; color: var(--ns-assistant-primary-button-text, var(--ns-assistant-halo-send-button-text)); border-radius: 999px; background: transparent; font-size: 0; line-height: 0; }
32559
+ .send::after { content: ''; position: absolute; top: 50%; left: 50%; z-index: 0; width: 28px; height: 28px; border-radius: 50%; background: var(--ns-assistant-primary-button, var(--ns-assistant-halo-send-button)); transform: translate(-50%, -50%); }
32560
+ .send::before { content: ''; position: absolute; top: 50%; left: 50%; z-index: 1; width: 16px; height: 16px; background: currentColor; transform: translate(-50%, -50%); -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 19V5M5 12l7-7 7 7' fill='none' stroke='black' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 19V5M5 12l7-7 7 7' fill='none' stroke='black' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; }
32561
+ .send:hover::after { background: var(--ns-assistant-hover, var(--ns-assistant-default-hover)); }
32027
32562
  :host([busy]) .send::before { width: 13px; height: 13px; border-radius: 3px; -webkit-mask: none; mask: none; }
32028
32563
  .send:disabled, textarea:disabled { opacity: .55; cursor: not-allowed; }
32029
- .legal { display: flex; gap: 12px; justify-content: center; padding: 0 12px 9px; font-size: .75em; }
32564
+ .legal { display: flex; gap: 12px; justify-content: center; padding: 0 12px 8px; font-size: .75em; }
32030
32565
  .legal:empty { display: none; }
32031
32566
  .legal a { color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); text-underline-offset: 2px; }
32567
+ .powered-by-row { display: flex; flex: 0 0 auto; justify-content: center; padding-bottom: 12px; }
32568
+ .powered-by-row[hidden] { display: none; }
32569
+ .powered-by { display: inline-flex; align-items: center; gap: 6px; margin: 0 auto 12px; padding: 0 16px; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); font-size: 11px; line-height: 1; text-decoration: none; opacity: .7; transition: opacity .12s ease, color .12s ease; }
32570
+ .powered-by:hover { color: var(--ns-assistant-text, var(--ns-assistant-default-text)); opacity: 1; }
32571
+ .powered-by-icon { display: inline-flex; width: 14px; height: 14px; }
32572
+ .powered-by-name { font-weight: 500; }
32032
32573
  ::slotted([slot="conversation-footer"]) { display: block; padding: 0 16px 12px; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); font-size: 11px; text-align: center; }
32033
- @keyframes halo-panel-in { from { opacity: 0; transform: translateY(14px) scale(.985); } to { opacity: 1; transform: none; } }
32574
+ @keyframes halo-panel-in { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: none; } }
32034
32575
  @keyframes halo-message-in { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: none; } }
32035
32576
  @keyframes halo-shimmer { from { background-position: 100% center; } to { background-position: 0 center; } }
32036
32577
  @keyframes halo-caret-blink { 50% { opacity: 0; } }
32578
+ @keyframes halo-spin { to { transform: rotate(360deg); } }
32037
32579
  :host([data-density="compact"]) .welcome { padding: 20px 18px 12px; }
32038
- @media (max-width: 640px) { :host([mobile-fullscreen][open]) { inset: 0; } :host([mobile-fullscreen][open]) .panel { width: 100vw; min-height: 100vh; max-height: 100vh; border: 0; border-radius: 0; } :host([mobile-fullscreen]) header { padding-top: max(12px, env(safe-area-inset-top)); padding-right: max(18px, env(safe-area-inset-right)); padding-left: max(18px, env(safe-area-inset-left)); } :host([mobile-fullscreen]) form { margin-right: max(16px, env(safe-area-inset-right)); margin-bottom: max(16px, env(safe-area-inset-bottom)); margin-left: max(16px, env(safe-area-inset-left)); } :host([mobile-fullscreen]) .legal, :host([mobile-fullscreen]) ::slotted([slot="conversation-footer"]) { padding-bottom: max(10px, env(safe-area-inset-bottom)); } }
32580
+ @media (max-width: 640px) { :host([mobile-fullscreen][open]) { inset: 0; width: 100vw; transform: none; } :host([mobile-fullscreen][open]) .panel { width: 100vw; max-width: none; height: 100dvh; min-height: 100dvh; max-height: 100dvh; margin: 0; border: 0; border-radius: 0; } :host([mobile-fullscreen]) header { padding-top: calc(16px + env(safe-area-inset-top)); padding-right: calc(20px + env(safe-area-inset-right)); padding-left: calc(20px + env(safe-area-inset-left)); } :host([mobile-fullscreen]) .messages { padding-right: calc(20px + env(safe-area-inset-right)); padding-left: calc(20px + env(safe-area-inset-left)); } :host([mobile-fullscreen]) .input-section { padding-right: calc(16px + env(safe-area-inset-right)); padding-bottom: calc(16px + env(safe-area-inset-bottom)); padding-left: calc(16px + env(safe-area-inset-left)); } :host([mobile-fullscreen]) .legal, :host([mobile-fullscreen]) ::slotted([slot="conversation-footer"]) { padding-bottom: max(10px, env(safe-area-inset-bottom)); } }
32039
32581
  @media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition-duration: .01ms !important; animation-duration: .01ms !important; } .messages { scroll-behavior: auto; } .message.assistant.streaming .markdown::after { animation: none; } }
32040
32582
  @media (forced-colors: active) { .message.thinking > span { color: CanvasText; background: none; } }
32041
32583
  @media (hover: none) { .message-copy { opacity: 1; } }
32042
- @media (max-width: 560px) { :host([data-mode="floating"]) { inset: auto 12px 12px; } :host([open]) .panel { width: calc(100vw - 24px); max-height: calc(100vh - 24px); } }
32584
+ @media (max-width: 560px) { :host([data-mode="floating"]:not([open])) { bottom: 20px; } :host([open]:not([mobile-fullscreen])) .panel { width: calc(100vw - 40px); max-height: calc(100dvh - 40px); } }
32043
32585
  </style>`;
32044
32586
 
32045
32587
  // src/host-appearance.ts
@@ -32148,6 +32690,7 @@ function syncAssistantPresentation(host, root, appearance, mode, sessionState) {
32148
32690
  host.dataset.panelSurface = presentation.panel.surface;
32149
32691
  host.dataset.panelElevation = presentation.panel.elevation;
32150
32692
  host.dataset.panelBorder = presentation.panel.border;
32693
+ host.dataset.launcherStyle = presentation.launcher.style;
32151
32694
  host.dataset.launcherEffect = presentation.launcher.effect;
32152
32695
  host.dataset.messageUserStyle = presentation.messages.userStyle;
32153
32696
  host.dataset.messageAssistantStyle = presentation.messages.assistantStyle;
@@ -32160,11 +32703,11 @@ function syncAssistantPresentation(host, root, appearance, mode, sessionState) {
32160
32703
  }
32161
32704
  host.style.setProperty(
32162
32705
  "--ns-assistant-presentation-launcher-size",
32163
- presentation.launcher.size === "lg" ? "56px" : "48px"
32706
+ presentation.launcher.size === "lg" ? "56px" : "44px"
32164
32707
  );
32165
32708
  host.style.setProperty(
32166
32709
  "--ns-assistant-presentation-panel-background",
32167
- presentation.panel.surface === "solid" ? "var(--ns-assistant-panel, var(--ns-assistant-default-panel))" : "color-mix(in srgb, var(--ns-assistant-panel, var(--ns-assistant-default-panel)) 88%, transparent)"
32710
+ presentation.panel.surface === "solid" ? "var(--ns-assistant-panel, var(--ns-assistant-default-panel))" : "color-mix(in srgb, var(--ns-assistant-panel, var(--ns-assistant-default-panel)) 50%, transparent)"
32168
32711
  );
32169
32712
  host.style.setProperty(
32170
32713
  "--ns-assistant-presentation-shadow",
@@ -32172,7 +32715,7 @@ function syncAssistantPresentation(host, root, appearance, mode, sessionState) {
32172
32715
  );
32173
32716
  host.style.setProperty(
32174
32717
  "--ns-assistant-presentation-border",
32175
- panelBorder(presentation.panel.border)
32718
+ panelBorder(presentation.panel.border, mode)
32176
32719
  );
32177
32720
  replaceFallback(root, "launcher-icon", [launcherVisual(appearance, mode, sessionState)]);
32178
32721
  const accessibleStatus = root.querySelector("[data-session-status]");
@@ -32185,7 +32728,7 @@ function syncAssistantPresentation(host, root, appearance, mode, sessionState) {
32185
32728
  replaceFallback(root, "empty-state", [emptyState(appearance)]);
32186
32729
  replaceFallback(root, "composer-leading", composerLeading(appearance, mode));
32187
32730
  replaceFallback(root, "conversation-footer", []);
32188
- const form = root.querySelector("form");
32731
+ const form = root.querySelector(".composer");
32189
32732
  if (form) form.dataset.shape = presentation.composer.shape;
32190
32733
  const send = root.querySelector(".send");
32191
32734
  if (send) send.dataset.icon = presentation.composer.sendIcon;
@@ -32205,18 +32748,21 @@ function panelShadow(elevation) {
32205
32748
  }
32206
32749
  return "var(--ns-assistant-default-shadow)";
32207
32750
  }
32208
- function panelBorder(border) {
32751
+ function panelBorder(border, mode) {
32209
32752
  if (border === "strong") {
32210
32753
  return "1px solid var(--ns-assistant-divider, var(--ns-assistant-default-divider))";
32211
32754
  }
32212
- return "1px solid color-mix(in srgb, var(--ns-assistant-divider, var(--ns-assistant-default-divider)) 74%, transparent)";
32755
+ const opacity = mode === "light" ? 60 : 100;
32756
+ return `1px solid color-mix(in srgb, var(--ns-assistant-divider, var(--ns-assistant-default-divider)) ${opacity}%, transparent)`;
32213
32757
  }
32214
32758
  function launcherVisual(appearance, mode, sessionState) {
32215
32759
  const launcher = appearance.presentation.launcher;
32216
32760
  const visual = document.createElement("span");
32217
32761
  visual.className = "launcher-visual";
32218
32762
  visual.setAttribute("aria-hidden", "true");
32219
- visual.append(icon(launcher.icon, appearance, mode, "launcher-glyph"));
32763
+ const visualKind = launcher.icon === "brand-mark" && !(appearance.brand.mark[mode] ?? appearance.brand.logo[mode]) ? launcher.style === "bubble" ? "chat" : "none" : launcher.icon;
32764
+ visual.hidden = visualKind === "none";
32765
+ visual.append(icon(visualKind, appearance, mode, "launcher-glyph"));
32220
32766
  if (launcher.status === "session") {
32221
32767
  const status = document.createElement("span");
32222
32768
  status.className = "launcher-status";
@@ -32266,9 +32812,12 @@ function headerBadge(appearance) {
32266
32812
  function emptyState(appearance) {
32267
32813
  const section = document.createElement("section");
32268
32814
  section.className = "empty-state";
32269
- const heading = document.createElement("h2");
32270
- heading.textContent = appearance.labels.welcomeHeading;
32271
- section.append(heading);
32815
+ section.hidden = !appearance.labels.welcomeHeading && !appearance.labels.welcomeMessage;
32816
+ if (appearance.labels.welcomeHeading) {
32817
+ const heading = document.createElement("h2");
32818
+ heading.textContent = appearance.labels.welcomeHeading;
32819
+ section.append(heading);
32820
+ }
32272
32821
  const description = appearance.labels.welcomeMessage;
32273
32822
  if (description) {
32274
32823
  const paragraph = document.createElement("p");
@@ -32295,7 +32844,7 @@ function toneIndicator(tone) {
32295
32844
  return indicator;
32296
32845
  }
32297
32846
  function icon(kind, appearance, mode, className) {
32298
- const mark = appearance.brand.mark[mode];
32847
+ const mark = appearance.brand.mark[mode] ?? appearance.brand.logo[mode];
32299
32848
  if (kind === "brand-mark" && mark) {
32300
32849
  const image = document.createElement("img");
32301
32850
  image.className = className;
@@ -32347,11 +32896,17 @@ function applyAssistantElementTheme(input) {
32347
32896
  var presentationStyles = `<style>
32348
32897
  :host([data-mode="floating"]) {
32349
32898
  bottom: var(--ns-assistant-edge-offset, var(--ns-assistant-default-edge-offset));
32350
- right: var(--ns-assistant-edge-offset, var(--ns-assistant-default-edge-offset));
32899
+ left: 50%;
32900
+ transform: translateX(-50%);
32351
32901
  }
32352
32902
  :host([data-mode="floating"][data-position="bottom-left"]) {
32353
- right: auto;
32354
32903
  left: var(--ns-assistant-edge-offset, var(--ns-assistant-default-edge-offset));
32904
+ transform: none;
32905
+ }
32906
+ :host([data-mode="floating"][data-position="bottom-right"]) {
32907
+ right: var(--ns-assistant-edge-offset, var(--ns-assistant-default-edge-offset));
32908
+ left: auto;
32909
+ transform: none;
32355
32910
  }
32356
32911
  .panel {
32357
32912
  background: var(--ns-assistant-panel-background, var(--ns-assistant-presentation-panel-background));
@@ -32368,22 +32923,26 @@ var presentationStyles = `<style>
32368
32923
 
32369
32924
  .launcher {
32370
32925
  position: relative;
32371
- width: var(--ns-assistant-launcher-size, var(--ns-assistant-presentation-launcher-size));
32372
- height: var(--ns-assistant-launcher-size, var(--ns-assistant-presentation-launcher-size));
32373
32926
  border-radius: var(--ns-assistant-launcher-radius, var(--ns-assistant-default-launcher-radius));
32374
32927
  isolation: isolate;
32375
32928
  }
32929
+ :host([data-launcher-style="bubble"]) .launcher {
32930
+ width: var(--ns-assistant-launcher-size, var(--ns-assistant-presentation-launcher-size));
32931
+ height: var(--ns-assistant-launcher-size, var(--ns-assistant-presentation-launcher-size));
32932
+ }
32376
32933
  :host([data-launcher-effect="pulse"]) .launcher {
32377
32934
  animation: assistant-launcher-pulse 2s ease-in-out infinite;
32378
32935
  }
32379
32936
  .launcher-visual {
32380
32937
  position: relative;
32381
32938
  display: grid;
32382
- width: 100%;
32383
- height: 100%;
32939
+ width: 28px;
32940
+ height: 28px;
32941
+ flex: 0 0 28px;
32384
32942
  place-items: center;
32385
32943
  border-radius: inherit;
32386
32944
  }
32945
+ .launcher-visual[hidden] { display: none; }
32387
32946
  .launcher-glyph, .composer-leading-glyph {
32388
32947
  display: block;
32389
32948
  width: 18px;
@@ -32411,10 +32970,28 @@ var presentationStyles = `<style>
32411
32970
  -webkit-mask: none;
32412
32971
  mask: none;
32413
32972
  }
32973
+ .launcher-visual .launcher-glyph:is(img) {
32974
+ width: 28px;
32975
+ height: 28px;
32976
+ border-radius: 50%;
32977
+ filter: grayscale(100%);
32978
+ opacity: .6;
32979
+ transition: width .5s cubic-bezier(.25,1,.5,1), height .5s cubic-bezier(.25,1,.5,1), filter .5s cubic-bezier(.25,1,.5,1), opacity .5s cubic-bezier(.25,1,.5,1);
32980
+ }
32981
+ .launcher:hover .launcher-glyph:is(img), :host([launcher-expanded]) .launcher-glyph:is(img) {
32982
+ filter: none;
32983
+ opacity: 1;
32984
+ }
32985
+ :host([data-launcher-style="bubble"]) .launcher-glyph:is(img) {
32986
+ width: 32px;
32987
+ height: 32px;
32988
+ filter: none;
32989
+ opacity: 1;
32990
+ }
32414
32991
  .launcher-status {
32415
32992
  position: absolute;
32416
- right: 1px;
32417
- bottom: 1px;
32993
+ right: -1px;
32994
+ bottom: -1px;
32418
32995
  width: 10px;
32419
32996
  height: 10px;
32420
32997
  border: 2px solid var(--ns-assistant-panel, var(--ns-assistant-default-panel));
@@ -32543,7 +33120,6 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32543
33120
  #conversationGeneration = 0;
32544
33121
  #messages;
32545
33122
  #thinking;
32546
- #media;
32547
33123
  #context;
32548
33124
  #modelContext;
32549
33125
  #pageContext;
@@ -32555,11 +33131,17 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32555
33131
  () => this.#primeSession(),
32556
33132
  () => this.focusComposer()
32557
33133
  );
33134
+ #publicConfiguration = new AssistantElementPublicConfigurationController(
33135
+ () => ({ embedId: this.embedId, serviceUrl: this.serviceUrl, fetch: this.#fetch }),
33136
+ (configuration) => this.#applyConfiguration(configuration),
33137
+ (loading) => this.#setPublicConfigurationLoading(loading)
33138
+ );
32558
33139
  #pendingUserEcho;
32559
33140
  #sessionState = "idle";
32560
33141
  #startOpenApplied = false;
32561
33142
  #readyDispatched = false;
32562
33143
  #turnInFlight = false;
33144
+ #fetch;
32563
33145
  #hostAppearance;
32564
33146
  #appearanceWarningKeys = /* @__PURE__ */ new Set();
32565
33147
  #appearanceStyleSnapshot = /* @__PURE__ */ new Map();
@@ -32569,6 +33151,17 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32569
33151
  embedId = "";
32570
33152
  /** Only for a dev or self-hosted service; the published snippet needs no origin. */
32571
33153
  serviceUrl = "";
33154
+ get fetch() {
33155
+ return this.#fetch;
33156
+ }
33157
+ set fetch(value) {
33158
+ if (this.#fetch === value) return;
33159
+ this.#fetch = value;
33160
+ if (this.#client) this.resetSession();
33161
+ if (!this.isConnected) return;
33162
+ if (this.embedId) this.#publicConfiguration.refresh();
33163
+ else this.#primeSession();
33164
+ }
32572
33165
  get appearance() {
32573
33166
  return this.#hostAppearance;
32574
33167
  }
@@ -32587,11 +33180,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32587
33180
  }
32588
33181
  return this.#appendMessage(role, text3);
32589
33182
  },
32590
- applyConfiguration: (configuration) => {
32591
- this.#appearance = resolveAppearance(configuration);
32592
- this.#syncAppearance();
32593
- this.#applyStartOpenPolicy();
32594
- },
33183
+ applyConfiguration: (configuration) => this.#applyConfiguration(configuration),
32595
33184
  labels: () => this.#appearance.labels,
32596
33185
  respond: (id, response) => this.respond(id, response),
32597
33186
  dispatchError: (detail) => this.#dispatchError(detail),
@@ -32607,7 +33196,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32607
33196
  client,
32608
33197
  sendMessage: (message) => this.sendMessage(message),
32609
33198
  updateModelContext: (update) => this.updateModelContext(update),
32610
- theme: this.#resolvedMode()
33199
+ theme: this.#environment.resolvedTheme()
32611
33200
  },
32612
33201
  {
32613
33202
  ...sandboxUrl === void 0 ? {} : { sandboxUrl },
@@ -32620,18 +33209,28 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32620
33209
  this.#revealLatest();
32621
33210
  }
32622
33211
  });
33212
+ #launcher = new AssistantElementLauncherController({
33213
+ host: this,
33214
+ appearance: () => this.#appearance,
33215
+ openPanel: () => this.open(),
33216
+ sendMessage: (message) => this.#sendGuarded(message)
33217
+ });
33218
+ #environment = new AssistantElementHostEnvironmentController({
33219
+ host: this,
33220
+ appearance: () => this.#appearance,
33221
+ applyTheme: () => this.#applyTheme(),
33222
+ close: () => this.#closeAndRestoreFocus()
33223
+ });
32623
33224
  connectedCallback() {
32624
33225
  if (!this.shadowRoot) this.attachShadow({ mode: "open" });
32625
33226
  if (!this.sessionEndpoint) this.sessionEndpoint = this.getAttribute("session-endpoint") ?? "";
32626
33227
  if (!this.embedId) this.embedId = this.getAttribute("embed-id") ?? "";
32627
33228
  if (!this.serviceUrl) this.serviceUrl = this.getAttribute("service-url") ?? "";
32628
33229
  if (!this.sessionEndpoint && !this.embedId) this.#presentationGate.reveal();
32629
- this.#media = globalThis.matchMedia?.("(prefers-color-scheme: dark)");
32630
- this.#media?.addEventListener("change", this.#handleSystemTheme);
32631
- document.addEventListener("keydown", this.#handleDocumentKeydown);
32632
- document.addEventListener("pointerdown", this.#handleDocumentPointerDown);
33230
+ this.#environment.connect();
32633
33231
  if (this.#appearance.behavior.startOpen) this.#applyStartOpenPolicy();
32634
33232
  this.#render();
33233
+ if (this.embedId) this.#publicConfiguration.connect();
32635
33234
  if (!this.#readyDispatched) {
32636
33235
  this.#readyDispatched = true;
32637
33236
  this.dispatchEvent(new CustomEvent("assistant-ready"));
@@ -32652,22 +33251,25 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32652
33251
  this.#clientEndpoint = "";
32653
33252
  this.#unsubscribeClient = void 0;
32654
33253
  this.#sessionBootstrap = void 0;
33254
+ this.#publicConfiguration.disconnect();
32655
33255
  this.#scroll.disconnect();
33256
+ this.#launcher.disconnect();
32656
33257
  this.#setBusy(false);
32657
- this.#media?.removeEventListener("change", this.#handleSystemTheme);
32658
- document.removeEventListener("keydown", this.#handleDocumentKeydown);
32659
- document.removeEventListener("pointerdown", this.#handleDocumentPointerDown);
33258
+ this.#environment.disconnect();
32660
33259
  }
32661
33260
  attributeChangedCallback(name21) {
32662
33261
  if (name21 === "theme") this.#applyTheme();
32663
33262
  if (name21 === "open") this.#presentationGate.syncOpenState();
32664
33263
  }
32665
33264
  open() {
33265
+ this.#launcher.collapse(true);
32666
33266
  this.setAttribute("open", "");
33267
+ if (this.hasAttribute("data-presentation-ready")) queueMicrotask(() => this.focusComposer());
32667
33268
  this.dispatchEvent(new CustomEvent("assistant-open"));
32668
33269
  }
32669
33270
  close() {
32670
33271
  this.removeAttribute("open");
33272
+ this.#launcher.collapse(true);
32671
33273
  this.dispatchEvent(new CustomEvent("assistant-close"));
32672
33274
  }
32673
33275
  toggle() {
@@ -32804,17 +33406,6 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32804
33406
  if (generation === this.#conversationGeneration) this.#setBusy(false);
32805
33407
  }
32806
33408
  }
32807
- #handleSystemTheme = () => this.#applyTheme();
32808
- #handleDocumentKeydown = (event) => {
32809
- if (event.key === "Escape" && this.hasAttribute("open") && this.#appearance.behavior.closeOnEscape) {
32810
- this.#closeAndRestoreFocus();
32811
- }
32812
- };
32813
- #handleDocumentPointerDown = (event) => {
32814
- if (this.hasAttribute("open") && this.#appearance.behavior.closeOnOutsideClick && !event.composedPath().includes(this)) {
32815
- this.close();
32816
- }
32817
- };
32818
33409
  #ensureClient() {
32819
33410
  const key = sessionSourceKey(this);
32820
33411
  if (this.#client && this.#clientEndpoint === key) return this.#client;
@@ -32830,8 +33421,13 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32830
33421
  const client = this.embedId ? createAssistantClient({
32831
33422
  embedId: this.embedId,
32832
33423
  ...this.serviceUrl ? { serviceUrl: this.serviceUrl } : {},
33424
+ ...this.#fetch ? { fetch: this.#fetch } : {},
33425
+ ...behavior
33426
+ }) : createAssistantClient({
33427
+ sessionEndpoint: this.sessionEndpoint,
33428
+ ...this.#fetch ? { fetch: this.#fetch } : {},
32833
33429
  ...behavior
32834
- }) : createAssistantClient({ sessionEndpoint: this.sessionEndpoint, ...behavior });
33430
+ });
32835
33431
  this.#client = client;
32836
33432
  this.#clientEndpoint = key;
32837
33433
  this.#unsubscribeClient = client.subscribe((event) => {
@@ -32860,6 +33456,8 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32860
33456
  this.dispatchEvent(new CustomEvent("assistant-event", { detail: event }));
32861
33457
  this.#events.handle(event);
32862
33458
  if (event.event === "session_started") {
33459
+ this.#publicConfiguration.disconnect();
33460
+ this.removeAttribute("data-public-configuration-loading");
32863
33461
  this.#presentationGate.reveal();
32864
33462
  this.#setSessionState("ready");
32865
33463
  this.#messages?.querySelector(".conversation-error")?.remove();
@@ -32909,10 +33507,10 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32909
33507
  if (!this.#messages) return void 0;
32910
33508
  const message = document.createElement("div");
32911
33509
  message.className = `message ${role}`;
32912
- if (role === "assistant" && this.#appearance.behavior.showAvatars && this.#appearance.brand.avatar[this.#resolvedMode()]) {
33510
+ if (role === "assistant" && this.#appearance.behavior.showAvatars && this.#appearance.brand.avatar[this.#environment.resolvedTheme()]) {
32913
33511
  const avatar = document.createElement("img");
32914
33512
  avatar.className = "avatar";
32915
- avatar.src = this.#appearance.brand.avatar[this.#resolvedMode()] ?? "";
33513
+ avatar.src = this.#appearance.brand.avatar[this.#environment.resolvedTheme()] ?? "";
32916
33514
  avatar.alt = "";
32917
33515
  message.append(avatar);
32918
33516
  }
@@ -32993,12 +33591,8 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32993
33591
  this.#primeSession();
32994
33592
  this.dispatchEvent(new CustomEvent("assistant-new-conversation"));
32995
33593
  }
32996
- #resolvedMode() {
32997
- const configured = this.getAttribute("theme") ?? this.#appearance.theme.defaultMode;
32998
- return configured === "auto" ? this.#media?.matches ? "dark" : "light" : configured;
32999
- }
33000
33594
  #applyTheme() {
33001
- const mode = this.#resolvedMode();
33595
+ const mode = this.#environment.resolvedTheme();
33002
33596
  for (const warning of applyAssistantElementTheme({
33003
33597
  host: this,
33004
33598
  root: this.shadowRoot,
@@ -33021,13 +33615,23 @@ var NoodleAssistantElement = class extends HTMLElementBase {
33021
33615
  updateAssistantAppTheme(app, mode);
33022
33616
  }
33023
33617
  }
33618
+ #applyConfiguration(configuration) {
33619
+ this.#appearance = resolveAppearance(configuration);
33620
+ this.#syncAppearance();
33621
+ this.#applyStartOpenPolicy();
33622
+ }
33623
+ #setPublicConfigurationLoading(loading) {
33624
+ this.toggleAttribute("data-public-configuration-loading", loading);
33625
+ if (loading) this.#presentationGate.syncOpenState();
33626
+ else this.#presentationGate.reveal();
33627
+ }
33024
33628
  #setSessionState(state) {
33025
33629
  this.#sessionState = state;
33026
33630
  syncAssistantSessionVisualState(this, this.shadowRoot, state, this.#appearance);
33027
33631
  }
33028
33632
  #closeAndRestoreFocus() {
33029
33633
  this.close();
33030
- this.shadowRoot?.querySelector(".launcher")?.focus();
33634
+ this.#launcher.focusTrigger();
33031
33635
  }
33032
33636
  #applyStartOpenPolicy() {
33033
33637
  if (this.#startOpenApplied) return;
@@ -33053,10 +33657,6 @@ var NoodleAssistantElement = class extends HTMLElementBase {
33053
33657
  textarea.placeholder = appearance.labels.composerPlaceholder;
33054
33658
  textarea.setAttribute("aria-label", appearance.labels.composerPlaceholder);
33055
33659
  queryRequired(this.shadowRoot, ".send").textContent = appearance.labels.send;
33056
- queryRequired(this.shadowRoot, ".launcher").setAttribute(
33057
- "aria-label",
33058
- appearance.labels.open
33059
- );
33060
33660
  queryRequired(this.shadowRoot, ".close").setAttribute(
33061
33661
  "aria-label",
33062
33662
  appearance.labels.close
@@ -33070,11 +33670,11 @@ var NoodleAssistantElement = class extends HTMLElementBase {
33070
33670
  button2.addEventListener("click", () => this.#sendGuarded(prompt));
33071
33671
  prompts.append(button2);
33072
33672
  }
33073
- queryRequired(this.shadowRoot, ".launcher").hidden = !appearance.behavior.showLauncher;
33074
33673
  queryRequired(this.shadowRoot, "header").hidden = !appearance.behavior.showHeader;
33075
33674
  const legal = queryRequired(this.shadowRoot, ".legal");
33076
33675
  legal.replaceChildren();
33077
33676
  appendLegalLinks(legal, this.#appearance);
33677
+ this.#launcher.sync();
33078
33678
  this.#applyTheme();
33079
33679
  }
33080
33680
  #render() {
@@ -33092,12 +33692,11 @@ var NoodleAssistantElement = class extends HTMLElementBase {
33092
33692
  this.toggleAttribute("mobile-fullscreen", appearance.layout.mobileFullscreen);
33093
33693
  this.shadowRoot.innerHTML = assistantElementMarkup(
33094
33694
  appearance,
33095
- this.hasAttribute("open"),
33096
33695
  `${ASSISTANT_ELEMENT_STYLES}${presentationStyles}`
33097
33696
  );
33098
33697
  queryRequired(this.shadowRoot, "strong").textContent = appearance.brand.name;
33099
33698
  const logo = queryRequired(this.shadowRoot, ".brand-logo");
33100
- const logoUrl = appearance.brand.logo[this.#resolvedMode()];
33699
+ const logoUrl = appearance.brand.logo[this.#environment.resolvedTheme()];
33101
33700
  if (logoUrl) {
33102
33701
  logo.src = logoUrl;
33103
33702
  logo.alt = appearance.brand.name;
@@ -33125,12 +33724,9 @@ var NoodleAssistantElement = class extends HTMLElementBase {
33125
33724
  this.#messages = this.shadowRoot.querySelector(".messages") ?? void 0;
33126
33725
  this.#messages?.append(...conversation);
33127
33726
  this.#thinking = this.#messages?.querySelector(".thinking") ?? void 0;
33128
- this.shadowRoot.querySelector(".launcher")?.addEventListener("click", () => {
33129
- this.open();
33130
- this.focusComposer();
33131
- });
33727
+ this.#launcher.connect(this.shadowRoot);
33132
33728
  this.shadowRoot.querySelector(".close")?.addEventListener("click", () => this.#closeAndRestoreFocus());
33133
- const form = queryRequired(this.shadowRoot, "form");
33729
+ const form = queryRequired(this.shadowRoot, ".composer");
33134
33730
  form.addEventListener("submit", (event) => {
33135
33731
  event.preventDefault();
33136
33732
  if (this.hasAttribute("busy")) {