@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/index.cjs CHANGED
@@ -15197,7 +15197,7 @@ __export(src_exports, {
15197
15197
  });
15198
15198
  module.exports = __toCommonJS(src_exports);
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) {
@@ -22343,7 +22343,7 @@ function updateAssistantAppTheme(card, theme) {
22343
22343
 
22344
22344
  // src/appearance.ts
22345
22345
  var common = {
22346
- fontFamily: "inherit",
22346
+ fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
22347
22347
  monoFontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
22348
22348
  baseFontSize: 15,
22349
22349
  messageFontSize: 15,
@@ -22354,7 +22354,7 @@ var common = {
22354
22354
  buttonRadius: 999,
22355
22355
  launcherRadius: 999,
22356
22356
  spacing: 8,
22357
- backdropBlur: 18,
22357
+ backdropBlur: 6,
22358
22358
  motionScale: 1
22359
22359
  };
22360
22360
  var DEFAULT_APPEARANCE = {
@@ -22374,7 +22374,7 @@ var DEFAULT_APPEARANCE = {
22374
22374
  accent: "#C2410C",
22375
22375
  accentText: "#FFFFFF",
22376
22376
  link: "#9A3412",
22377
- divider: "#E4E4E7",
22377
+ divider: "rgba(0, 0, 0, 0.1)",
22378
22378
  focus: "#C2410C",
22379
22379
  success: "#16835D",
22380
22380
  warning: "#A45B00",
@@ -22382,7 +22382,7 @@ var DEFAULT_APPEARANCE = {
22382
22382
  overlay: "#18181B66",
22383
22383
  code: "#F1F1F3",
22384
22384
  widgetFrame: "#E4E4E7",
22385
- shadow: "0 4px 16px rgba(0, 0, 0, 0.06), 0 24px 70px rgba(0, 0, 0, 0.10)"
22385
+ shadow: "0 4px 16px rgba(0, 0, 0, 0.06)"
22386
22386
  },
22387
22387
  dark: {
22388
22388
  ...common,
@@ -22397,7 +22397,7 @@ var DEFAULT_APPEARANCE = {
22397
22397
  accent: "#FB923C",
22398
22398
  accentText: "#1C0A02",
22399
22399
  link: "#FDBA74",
22400
- divider: "#292524",
22400
+ divider: "rgba(255, 255, 255, 0.1)",
22401
22401
  focus: "#FB923C",
22402
22402
  success: "#58C69A",
22403
22403
  warning: "#F2B45F",
@@ -22405,15 +22405,15 @@ var DEFAULT_APPEARANCE = {
22405
22405
  overlay: "#00000099",
22406
22406
  code: "#26262C",
22407
22407
  widgetFrame: "#34343B",
22408
- shadow: "0 8px 32px rgba(0, 0, 0, 0.48)"
22408
+ shadow: "0 8px 32px rgba(0, 0, 0, 0.4)"
22409
22409
  }
22410
22410
  },
22411
22411
  layout: {
22412
22412
  mode: "floating",
22413
- position: "bottom-right",
22414
- panelWidth: 520,
22415
- panelMinHeight: 540,
22416
- panelMaxHeight: 820,
22413
+ position: "bottom-center",
22414
+ panelWidth: 970,
22415
+ panelMinHeight: 0,
22416
+ panelMaxHeight: 1025,
22417
22417
  edgeOffset: 20,
22418
22418
  zIndex: 2147483e3,
22419
22419
  density: "comfortable",
@@ -22426,11 +22426,13 @@ var DEFAULT_APPEARANCE = {
22426
22426
  showLauncher: true,
22427
22427
  showHeader: true,
22428
22428
  showAvatars: true,
22429
- showTimestamps: false
22429
+ showTimestamps: false,
22430
+ showPoweredBy: true
22430
22431
  },
22431
22432
  labels: {
22432
- welcomeHeading: "How can I help?",
22433
+ welcomeHeading: "",
22433
22434
  welcomeMessage: "",
22435
+ launcherPlaceholder: "Chat with us",
22434
22436
  composerPlaceholder: "Ask a question\u2026",
22435
22437
  thinking: "Thinking",
22436
22438
  send: "Send",
@@ -22464,11 +22466,12 @@ var DEFAULT_APPEARANCE = {
22464
22466
  },
22465
22467
  presentation: {
22466
22468
  panel: {
22467
- surface: "glass",
22469
+ surface: "solid",
22468
22470
  elevation: "soft",
22469
22471
  border: "subtle"
22470
22472
  },
22471
22473
  launcher: {
22474
+ style: "pill",
22472
22475
  icon: "brand-mark",
22473
22476
  size: "md",
22474
22477
  status: "none",
@@ -22478,7 +22481,11 @@ var DEFAULT_APPEARANCE = {
22478
22481
  composer: { leadingIcon: "none", sendIcon: "arrow-up", shape: "pill" },
22479
22482
  messages: { userStyle: "bubble", assistantStyle: "plain" }
22480
22483
  },
22481
- suggestedPrompts: [],
22484
+ suggestedPrompts: [
22485
+ "What products do you have?",
22486
+ "Tell me about your business",
22487
+ "How can I get in touch?"
22488
+ ],
22482
22489
  locale: "en",
22483
22490
  direction: "auto"
22484
22491
  };
@@ -22494,7 +22501,7 @@ function resolveAppearance(input = {}) {
22494
22501
  mark: themedAsset(branding?.mark)
22495
22502
  },
22496
22503
  theme: {
22497
- defaultMode: branding?.colorScheme ?? DEFAULT_APPEARANCE.theme.defaultMode,
22504
+ defaultMode: assistant?.theme ?? branding?.colorScheme ?? DEFAULT_APPEARANCE.theme.defaultMode,
22498
22505
  light: resolveTheme("light", branding),
22499
22506
  dark: resolveTheme("dark", branding)
22500
22507
  },
@@ -22505,9 +22512,17 @@ function resolveAppearance(input = {}) {
22505
22512
  ...assistant?.layout?.edgeOffset === void 0 ? {} : { edgeOffset: boundedNumber(assistant.layout.edgeOffset, 0, 96) }
22506
22513
  },
22507
22514
  behavior: { ...DEFAULT_APPEARANCE.behavior, ...assistant?.behavior },
22508
- labels: { ...DEFAULT_APPEARANCE.labels, ...assistant?.labels },
22515
+ labels: {
22516
+ ...DEFAULT_APPEARANCE.labels,
22517
+ ...branding?.name ? { launcherPlaceholder: `Chat with ${branding.name}` } : {},
22518
+ ...assistant?.labels
22519
+ },
22509
22520
  presentation: resolvePresentation(assistant?.presentation),
22510
- suggestedPrompts: assistant?.suggestedPrompts ?? DEFAULT_APPEARANCE.suggestedPrompts,
22521
+ suggestedPrompts: assistant?.suggestedPrompts ?? (branding?.name ? [
22522
+ "What products do you have?",
22523
+ `Tell me about ${branding.name}`,
22524
+ "How can I get in touch?"
22525
+ ] : DEFAULT_APPEARANCE.suggestedPrompts),
22511
22526
  ...assistant?.privacyUrl ? { privacyUrl: assistant.privacyUrl } : {},
22512
22527
  ...assistant?.termsUrl ? { termsUrl: assistant.termsUrl } : {},
22513
22528
  locale: assistant?.locale ?? DEFAULT_APPEARANCE.locale,
@@ -24778,6 +24793,10 @@ async function resolve(value) {
24778
24793
  return Promise.resolve(value);
24779
24794
  }
24780
24795
 
24796
+ // ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/index.js
24797
+ init_external();
24798
+ init_external();
24799
+
24781
24800
  // ../../node_modules/.pnpm/ai@6.0.201_zod@4.4.3/node_modules/ai/dist/index.mjs
24782
24801
  init_v4();
24783
24802
  init_v4();
@@ -27520,6 +27539,11 @@ function isRecord3(value) {
27520
27539
  // src/session-source.ts
27521
27540
  var NOODLE_CLOUD_URL = "https://cloud.noodleseed.dev";
27522
27541
  var PUBLIC_SESSION_PATH = "/v1/assistant/public-sessions";
27542
+ var PUBLIC_CONFIGURATION_PATH = "/v1/assistant/public-configurations";
27543
+ function publicConfigurationUrl(serviceUrl, embedId) {
27544
+ const base = (serviceUrl || NOODLE_CLOUD_URL).replace(/\/+$/, "");
27545
+ return `${base}${PUBLIC_CONFIGURATION_PATH}/${encodeURIComponent(embedId)}`;
27546
+ }
27523
27547
  function resolveSessionSource(options) {
27524
27548
  const { sessionEndpoint, embedId, serviceUrl } = options;
27525
27549
  if (Boolean(embedId) === Boolean(sessionEndpoint)) {
@@ -29031,11 +29055,11 @@ function createDOMPurify() {
29031
29055
  const originalDocument = document2;
29032
29056
  const currentScript = originalDocument.currentScript;
29033
29057
  window2.DocumentFragment;
29034
- const HTMLTemplateElement = window2.HTMLTemplateElement, Node = window2.Node, Element = window2.Element, NodeFilter = window2.NodeFilter, _window$NamedNodeMap = window2.NamedNodeMap;
29058
+ const HTMLTemplateElement = window2.HTMLTemplateElement, Node = window2.Node, Element2 = window2.Element, NodeFilter = window2.NodeFilter, _window$NamedNodeMap = window2.NamedNodeMap;
29035
29059
  _window$NamedNodeMap === void 0 ? window2.NamedNodeMap || window2.MozNamedAttrMap : _window$NamedNodeMap;
29036
29060
  window2.HTMLFormElement;
29037
29061
  const DOMParser = window2.DOMParser, trustedTypes = window2.trustedTypes;
29038
- const ElementPrototype = Element.prototype;
29062
+ const ElementPrototype = Element2.prototype;
29039
29063
  const cloneNode = lookupGetter(ElementPrototype, "cloneNode");
29040
29064
  const remove = lookupGetter(ElementPrototype, "remove");
29041
29065
  const getNextSibling = lookupGetter(ElementPrototype, "nextSibling");
@@ -31685,19 +31709,40 @@ function queryRequired(root, selector) {
31685
31709
  if (!element) throw new Error(`assistant renderer is missing ${selector}`);
31686
31710
  return element;
31687
31711
  }
31688
- function assistantElementMarkup(appearance, open, styles) {
31712
+ function assistantElementMarkup(appearance, styles) {
31689
31713
  return `${styles}
31690
- <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>
31714
+ <div class="launcher">
31715
+ <slot name="launcher-icon"></slot>
31716
+ <span class="launcher-loader" aria-hidden="true"></span>
31717
+ <button class="launcher-trigger" type="button" aria-label="${escapeAttribute(appearance.labels.open)}" aria-controls="assistant-launcher-form" aria-expanded="false">
31718
+ <span class="launcher-label">${escapeAttribute(appearance.labels.launcherPlaceholder)}</span>
31719
+ <span class="launcher-arrow" aria-hidden="true"></span>
31720
+ </button>
31721
+ <form class="launcher-form" id="assistant-launcher-form" aria-hidden="true" autocomplete="off">
31722
+ <input class="launcher-input" type="text" aria-label="${escapeAttribute(appearance.labels.launcherPlaceholder)}" placeholder="${escapeAttribute(appearance.labels.launcherPlaceholder)}" tabindex="-1">
31723
+ <button class="launcher-send" type="submit" aria-label="${escapeAttribute(appearance.labels.send)}"></button>
31724
+ </form>
31725
+ <span class="visually-hidden" data-session-status aria-live="polite" hidden></span>
31726
+ </div>
31691
31727
  <section class="panel" id="assistant-panel" role="dialog" aria-label="${escapeAttribute(appearance.brand.name)}">
31692
31728
  <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>
31693
31729
  <div class="welcome"><slot name="empty-state"></slot></div>
31694
- <div class="suggested-prompts"></div>
31695
31730
  <div class="messages-region">
31696
31731
  <div class="messages" aria-live="polite"></div>
31697
31732
  <button class="new-messages" type="button" aria-label="${escapeAttribute(appearance.labels.newMessages)}" hidden></button>
31698
31733
  </div>
31699
- <form><slot name="composer-leading"></slot><textarea rows="1"></textarea><button class="send" type="submit"></button><slot name="composer-trailing"></slot></form>
31734
+ <div class="input-section">
31735
+ <div class="suggested-prompts"></div>
31736
+ <form class="composer"><slot name="composer-leading"></slot><textarea rows="1"></textarea><button class="send" type="submit"></button><slot name="composer-trailing"></slot></form>
31737
+ </div>
31700
31738
  <nav class="legal" aria-label="Legal"></nav>
31739
+ <div class="powered-by-row">
31740
+ <a class="powered-by" href="https://noodleseed.com" target="_blank" rel="noopener noreferrer">
31741
+ <span>Powered by</span>
31742
+ <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>
31743
+ <span class="powered-by-name">Noodle Seed</span>
31744
+ </a>
31745
+ </div>
31701
31746
  <slot name="conversation-footer"></slot>
31702
31747
  </section>`;
31703
31748
  }
@@ -31716,6 +31761,230 @@ function appendLegalLinks(legal, appearance) {
31716
31761
  }
31717
31762
  }
31718
31763
 
31764
+ // src/element-theme-resolution.ts
31765
+ function resolveAssistantTheme(input) {
31766
+ if (input.configured === "light" || input.configured === "dark") return input.configured;
31767
+ const hostMode = resolveHostTheme(input.host, input.media);
31768
+ return input.configured === "invert" ? opposite(hostMode) : hostMode;
31769
+ }
31770
+ function resolveHostTheme(host, media) {
31771
+ const view = host.ownerDocument.defaultView;
31772
+ for (let node = host.parentElement; node; node = node.parentElement) {
31773
+ const declared = declaredTheme(node);
31774
+ if (declared) return declared;
31775
+ const computed = computedTheme(view?.getComputedStyle(node).colorScheme);
31776
+ if (computed) return computed;
31777
+ }
31778
+ return media?.matches ? "dark" : "light";
31779
+ }
31780
+ function computedTheme(colorScheme) {
31781
+ const modes = colorScheme?.split(/\s+/) ?? [];
31782
+ if (modes.includes("dark") && !modes.includes("light")) return "dark";
31783
+ if (modes.includes("light") && !modes.includes("dark")) return "light";
31784
+ return void 0;
31785
+ }
31786
+ function declaredTheme(element) {
31787
+ const value = element.getAttribute("data-theme") ?? element.getAttribute("data-color-scheme") ?? element.getAttribute("data-mode");
31788
+ if (value === "dark" || value === "light") return value;
31789
+ if (element.classList.contains("dark")) return "dark";
31790
+ if (element.classList.contains("light")) return "light";
31791
+ return void 0;
31792
+ }
31793
+ function opposite(mode) {
31794
+ return mode === "dark" ? "light" : "dark";
31795
+ }
31796
+
31797
+ // src/element-host-environment-controller.ts
31798
+ var AssistantElementHostEnvironmentController = class {
31799
+ #host;
31800
+ #appearance;
31801
+ #applyTheme;
31802
+ #close;
31803
+ #media;
31804
+ #themeObserver;
31805
+ constructor(options) {
31806
+ this.#host = options.host;
31807
+ this.#appearance = options.appearance;
31808
+ this.#applyTheme = options.applyTheme;
31809
+ this.#close = options.close;
31810
+ }
31811
+ get media() {
31812
+ return this.#media;
31813
+ }
31814
+ resolvedTheme() {
31815
+ return resolveAssistantTheme({
31816
+ host: this.#host,
31817
+ configured: this.#host.getAttribute("theme") ?? this.#appearance().theme.defaultMode,
31818
+ ...this.#media ? { media: this.#media } : {}
31819
+ });
31820
+ }
31821
+ connect() {
31822
+ this.disconnect();
31823
+ this.#media = globalThis.matchMedia?.("(prefers-color-scheme: dark)");
31824
+ this.#media?.addEventListener("change", this.#applyTheme);
31825
+ this.#themeObserver = new MutationObserver(this.#applyTheme);
31826
+ for (let node = this.#host.parentElement; node; node = node.parentElement) {
31827
+ this.#themeObserver.observe(node, {
31828
+ attributes: true,
31829
+ attributeFilter: ["class", "data-theme", "data-color-scheme", "data-mode", "style"]
31830
+ });
31831
+ }
31832
+ document.addEventListener("keydown", this.#handleDocumentKeydown);
31833
+ document.addEventListener("pointerdown", this.#handleDocumentPointerDown);
31834
+ }
31835
+ disconnect() {
31836
+ this.#media?.removeEventListener("change", this.#applyTheme);
31837
+ this.#media = void 0;
31838
+ this.#themeObserver?.disconnect();
31839
+ this.#themeObserver = void 0;
31840
+ document.removeEventListener("keydown", this.#handleDocumentKeydown);
31841
+ document.removeEventListener("pointerdown", this.#handleDocumentPointerDown);
31842
+ }
31843
+ #handleDocumentKeydown = (event) => {
31844
+ if (event.key === "Escape" && this.#host.hasAttribute("open") && this.#appearance().behavior.closeOnEscape) {
31845
+ this.#close();
31846
+ }
31847
+ };
31848
+ #handleDocumentPointerDown = (event) => {
31849
+ if (this.#host.hasAttribute("open") && this.#appearance().behavior.closeOnOutsideClick && !event.composedPath().includes(this.#host)) {
31850
+ this.#close();
31851
+ }
31852
+ };
31853
+ };
31854
+
31855
+ // src/element-launcher-controller.ts
31856
+ var AssistantElementLauncherController = class {
31857
+ #host;
31858
+ #appearance;
31859
+ #openPanel;
31860
+ #sendMessage;
31861
+ #root;
31862
+ constructor(options) {
31863
+ this.#host = options.host;
31864
+ this.#appearance = options.appearance;
31865
+ this.#openPanel = options.openPanel;
31866
+ this.#sendMessage = options.sendMessage;
31867
+ }
31868
+ connect(root) {
31869
+ this.disconnect();
31870
+ this.#root = root;
31871
+ queryRequired(root, ".launcher").addEventListener(
31872
+ "click",
31873
+ this.#handleLauncherClick
31874
+ );
31875
+ queryRequired(root, ".launcher-trigger").addEventListener(
31876
+ "click",
31877
+ this.#handleTrigger
31878
+ );
31879
+ queryRequired(root, ".launcher-form").addEventListener(
31880
+ "submit",
31881
+ this.#handleSubmit
31882
+ );
31883
+ queryRequired(root, ".launcher-input").addEventListener(
31884
+ "keydown",
31885
+ this.#handleInputKeydown
31886
+ );
31887
+ document.addEventListener("pointerdown", this.#handleDocumentPointerDown);
31888
+ this.sync();
31889
+ }
31890
+ disconnect() {
31891
+ document.removeEventListener("pointerdown", this.#handleDocumentPointerDown);
31892
+ this.#root = void 0;
31893
+ }
31894
+ sync() {
31895
+ const root = this.#root;
31896
+ if (!root) return;
31897
+ const appearance = this.#appearance();
31898
+ const style = appearance.presentation.launcher.style;
31899
+ this.#host.dataset.launcherStyle = style;
31900
+ const trigger = queryRequired(root, ".launcher-trigger");
31901
+ const label = queryRequired(root, ".launcher-label");
31902
+ const input = queryRequired(root, ".launcher-input");
31903
+ label.textContent = appearance.labels.launcherPlaceholder;
31904
+ input.placeholder = appearance.labels.launcherPlaceholder;
31905
+ input.setAttribute("aria-label", appearance.labels.launcherPlaceholder);
31906
+ trigger.setAttribute("aria-label", appearance.labels.open);
31907
+ queryRequired(root, ".launcher-send").setAttribute(
31908
+ "aria-label",
31909
+ appearance.labels.send
31910
+ );
31911
+ queryRequired(root, ".launcher").hidden = !appearance.behavior.showLauncher;
31912
+ queryRequired(root, ".powered-by-row").hidden = !appearance.behavior.showPoweredBy;
31913
+ if (style === "bubble" || this.#host.hasAttribute("open")) this.collapse(true);
31914
+ }
31915
+ collapse(force = false) {
31916
+ const root = this.#root;
31917
+ if (!root) return;
31918
+ const input = queryRequired(root, ".launcher-input");
31919
+ if (!force && input.value.trim()) return;
31920
+ this.#host.removeAttribute("launcher-expanded");
31921
+ const form = queryRequired(root, ".launcher-form");
31922
+ const trigger = queryRequired(root, ".launcher-trigger");
31923
+ form.setAttribute("aria-hidden", "true");
31924
+ trigger.setAttribute("aria-expanded", "false");
31925
+ input.tabIndex = -1;
31926
+ input.blur();
31927
+ }
31928
+ focusTrigger() {
31929
+ this.#root?.querySelector(".launcher-trigger")?.focus();
31930
+ }
31931
+ #expand() {
31932
+ const root = this.#root;
31933
+ if (!root || this.#appearance().presentation.launcher.style === "bubble") return;
31934
+ this.#host.setAttribute("launcher-expanded", "");
31935
+ const form = queryRequired(root, ".launcher-form");
31936
+ const trigger = queryRequired(root, ".launcher-trigger");
31937
+ const input = queryRequired(root, ".launcher-input");
31938
+ form.setAttribute("aria-hidden", "false");
31939
+ trigger.setAttribute("aria-expanded", "true");
31940
+ input.tabIndex = 0;
31941
+ requestAnimationFrame(() => {
31942
+ if (this.#host.hasAttribute("launcher-expanded")) input.focus();
31943
+ });
31944
+ }
31945
+ #handleTrigger = () => {
31946
+ if (this.#appearance().presentation.launcher.style === "bubble") {
31947
+ this.#openPanel();
31948
+ return;
31949
+ }
31950
+ this.#expand();
31951
+ };
31952
+ #handleLauncherClick = (event) => {
31953
+ if (event.composedPath().some(
31954
+ (target) => target instanceof Element && target.matches(".launcher-trigger, .launcher-form")
31955
+ )) {
31956
+ return;
31957
+ }
31958
+ this.#handleTrigger();
31959
+ };
31960
+ #handleSubmit = (event) => {
31961
+ event.preventDefault();
31962
+ const input = this.#root?.querySelector(".launcher-input");
31963
+ const message = input?.value.trim() ?? "";
31964
+ if (input) input.value = "";
31965
+ this.#openPanel();
31966
+ if (message) this.#sendMessage(message);
31967
+ };
31968
+ #handleInputKeydown = (event) => {
31969
+ if (event.key === "Enter" && !event.isComposing) {
31970
+ event.preventDefault();
31971
+ this.#root?.querySelector(".launcher-form")?.requestSubmit();
31972
+ return;
31973
+ }
31974
+ if (event.key !== "Escape") return;
31975
+ event.preventDefault();
31976
+ event.stopPropagation();
31977
+ const input = this.#root?.querySelector(".launcher-input");
31978
+ if (input) input.value = "";
31979
+ this.collapse(true);
31980
+ this.focusTrigger();
31981
+ };
31982
+ #handleDocumentPointerDown = (event) => {
31983
+ if (event.composedPath().includes(this.#host)) return;
31984
+ this.collapse();
31985
+ };
31986
+ };
31987
+
31719
31988
  // src/element-page-context-controller.ts
31720
31989
  var AssistantElementPageContextController = class {
31721
31990
  #snapshot;
@@ -31769,10 +32038,12 @@ var AssistantElementPresentationGate = class {
31769
32038
  syncOpenState() {
31770
32039
  const open = this.#host.hasAttribute("open");
31771
32040
  const presentationReady = this.#host.hasAttribute("data-presentation-ready");
31772
- const launcher = this.#host.shadowRoot?.querySelector(".launcher");
31773
- launcher?.setAttribute("aria-expanded", String(open && presentationReady));
31774
- launcher?.setAttribute("aria-busy", String(open && !presentationReady));
31775
- if (launcher) launcher.disabled = open && !presentationReady;
32041
+ const publicConfigurationLoading = this.#host.hasAttribute("data-public-configuration-loading");
32042
+ const presentationBlocked = !presentationReady && (open || publicConfigurationLoading);
32043
+ const launcher = this.#host.shadowRoot?.querySelector(".launcher-trigger");
32044
+ launcher?.setAttribute("aria-busy", String(presentationBlocked));
32045
+ if (launcher) launcher.disabled = presentationBlocked;
32046
+ this.#host.shadowRoot?.querySelector(".panel")?.setAttribute("aria-hidden", String(!(open && presentationReady)));
31776
32047
  if (open && this.#host.isConnected) this.#primeSession();
31777
32048
  }
31778
32049
  reveal() {
@@ -31783,6 +32054,244 @@ var AssistantElementPresentationGate = class {
31783
32054
  }
31784
32055
  };
31785
32056
 
32057
+ // src/assistant-configuration-schema.ts
32058
+ var hexColorSchema = external_exports.string().regex(/^#[0-9A-Fa-f]{6}$/);
32059
+ var resolvedBorderColorSchema = external_exports.union([
32060
+ hexColorSchema,
32061
+ external_exports.string().max(64).refine(isBoundedRgbaColor, "must be a six-digit hex or bounded rgba color")
32062
+ ]);
32063
+ var browserAssetUrlSchema = external_exports.string().trim().url().refine(isSecureBrowserAssetUrl, "must use https (http is allowed only for loopback testing)");
32064
+ var httpsUrlSchema = external_exports.string().trim().url().refine(isHttpsUrl2, "must use https");
32065
+ var brandAssetSchema = external_exports.object({
32066
+ uri: browserAssetUrlSchema,
32067
+ darkUri: browserAssetUrlSchema.optional(),
32068
+ alt: external_exports.string().trim().min(1).max(240)
32069
+ }).strict();
32070
+ var brandThemeSchema = external_exports.object({
32071
+ surface: hexColorSchema.optional(),
32072
+ surfaceRaised: hexColorSchema.optional(),
32073
+ surfaceMuted: hexColorSchema.optional(),
32074
+ text: hexColorSchema.optional(),
32075
+ textMuted: hexColorSchema.optional(),
32076
+ accent: hexColorSchema.optional(),
32077
+ accentText: hexColorSchema.optional(),
32078
+ link: hexColorSchema.optional(),
32079
+ border: resolvedBorderColorSchema.optional(),
32080
+ borderStrong: resolvedBorderColorSchema.optional(),
32081
+ focus: hexColorSchema.optional(),
32082
+ success: hexColorSchema.optional(),
32083
+ warning: hexColorSchema.optional(),
32084
+ danger: hexColorSchema.optional(),
32085
+ code: hexColorSchema.optional()
32086
+ }).strict();
32087
+ var brandingSchema = external_exports.object({
32088
+ name: external_exports.string().trim().min(1).max(160).optional(),
32089
+ accent: hexColorSchema.optional(),
32090
+ surface: hexColorSchema.optional(),
32091
+ surfaceDark: hexColorSchema.optional(),
32092
+ logo: brandAssetSchema.optional(),
32093
+ mark: brandAssetSchema.optional(),
32094
+ avatar: brandAssetSchema.optional(),
32095
+ theme: external_exports.object({ light: brandThemeSchema.optional(), dark: brandThemeSchema.optional() }).strict().optional(),
32096
+ radius: external_exports.enum(["none", "sm", "md", "lg"]).optional(),
32097
+ density: external_exports.enum(["compact", "comfortable"]).optional(),
32098
+ typography: external_exports.enum(["system", "serif", "mono"]).optional(),
32099
+ colorScheme: external_exports.enum(["auto", "light", "dark"]).optional()
32100
+ }).strict();
32101
+ var labelsSchema = external_exports.object({
32102
+ welcomeHeading: external_exports.string().trim().min(1).max(160).optional(),
32103
+ welcomeMessage: external_exports.string().max(1e3).optional(),
32104
+ launcherPlaceholder: external_exports.string().trim().min(1).max(160).optional(),
32105
+ composerPlaceholder: external_exports.string().trim().min(1).max(160).optional(),
32106
+ thinking: external_exports.string().trim().min(1).max(80).optional(),
32107
+ send: external_exports.string().trim().min(1).max(80).optional(),
32108
+ stop: external_exports.string().trim().min(1).max(80).optional(),
32109
+ close: external_exports.string().trim().min(1).max(80).optional(),
32110
+ open: external_exports.string().trim().min(1).max(80).optional(),
32111
+ confirm: external_exports.string().trim().min(1).max(80).optional(),
32112
+ decline: external_exports.string().trim().min(1).max(80).optional(),
32113
+ cancel: external_exports.string().trim().min(1).max(80).optional(),
32114
+ confirmationHeading: external_exports.string().trim().min(1).max(120).optional(),
32115
+ additionalDetails: external_exports.string().trim().min(1).max(120).optional(),
32116
+ redacted: external_exports.string().trim().min(1).max(120).optional(),
32117
+ completed: external_exports.string().trim().min(1).max(80).optional(),
32118
+ stopped: external_exports.string().trim().min(1).max(80).optional(),
32119
+ copy: external_exports.string().trim().min(1).max(80).optional(),
32120
+ newMessages: external_exports.string().trim().min(1).max(80).optional(),
32121
+ reconnect: external_exports.string().trim().min(1).max(80).optional(),
32122
+ newConversation: external_exports.string().trim().min(1).max(80).optional(),
32123
+ retry: external_exports.string().trim().min(1).max(80).optional(),
32124
+ unavailable: external_exports.string().trim().min(1).max(240).optional(),
32125
+ sessionExpired: external_exports.string().trim().min(1).max(240).optional(),
32126
+ sessionIdle: external_exports.string().trim().min(1).max(120).optional(),
32127
+ sessionLoading: external_exports.string().trim().min(1).max(120).optional(),
32128
+ sessionReady: external_exports.string().trim().min(1).max(120).optional(),
32129
+ sessionError: external_exports.string().trim().min(1).max(120).optional(),
32130
+ signInHeading: external_exports.string().trim().min(1).max(120).optional(),
32131
+ signInBody: external_exports.string().max(240).optional(),
32132
+ signInAction: external_exports.string().trim().min(1).max(80).optional(),
32133
+ signUpAction: external_exports.string().trim().min(1).max(80).optional()
32134
+ }).strict();
32135
+ var presentationSchema = external_exports.object({
32136
+ panel: external_exports.object({
32137
+ surface: external_exports.enum(["solid", "glass"]).optional(),
32138
+ elevation: external_exports.enum(["soft", "dramatic"]).optional(),
32139
+ border: external_exports.enum(["subtle", "strong"]).optional(),
32140
+ radius: external_exports.number().int().min(0).max(64).optional()
32141
+ }).strict().optional(),
32142
+ launcher: external_exports.object({
32143
+ style: external_exports.enum(["pill", "bubble"]).optional(),
32144
+ icon: external_exports.enum(["brand-mark", "chat", "none"]).optional(),
32145
+ size: external_exports.enum(["md", "lg"]).optional(),
32146
+ status: external_exports.enum(["none", "session"]).optional(),
32147
+ effect: external_exports.enum(["none", "pulse"]).optional()
32148
+ }).strict().optional(),
32149
+ header: external_exports.object({
32150
+ mark: external_exports.enum(["none", "brand-mark", "status"]).optional(),
32151
+ badge: external_exports.object({
32152
+ text: external_exports.string().trim().min(1).max(80),
32153
+ tone: external_exports.enum(["neutral", "success", "warning", "danger"]).optional(),
32154
+ indicator: external_exports.boolean().optional()
32155
+ }).strict().optional()
32156
+ }).strict().optional(),
32157
+ composer: external_exports.object({
32158
+ leadingIcon: external_exports.enum(["none", "brand-mark"]).optional(),
32159
+ sendIcon: external_exports.enum(["arrow-up", "paper-plane"]).optional(),
32160
+ shape: external_exports.enum(["rounded", "pill"]).optional()
32161
+ }).strict().optional(),
32162
+ messages: external_exports.object({
32163
+ userStyle: external_exports.enum(["bubble", "accent"]).optional(),
32164
+ assistantStyle: external_exports.enum(["plain", "bubble"]).optional()
32165
+ }).strict().optional()
32166
+ }).strict();
32167
+ var assistantUiSchema = external_exports.object({
32168
+ theme: external_exports.enum(["auto", "light", "dark", "invert"]).optional(),
32169
+ layout: external_exports.object({
32170
+ mode: external_exports.enum(["floating", "inline", "drawer"]).optional(),
32171
+ position: external_exports.enum(["bottom-left", "bottom-center", "bottom-right"]).optional(),
32172
+ panelWidth: external_exports.number().int().min(280).max(1200).optional(),
32173
+ panelMinHeight: external_exports.number().int().min(240).max(1600).optional(),
32174
+ panelMaxHeight: external_exports.number().int().min(320).max(2400).optional(),
32175
+ edgeOffset: external_exports.number().int().min(0).max(96).optional(),
32176
+ zIndex: external_exports.number().int().min(0).max(2147483647).optional(),
32177
+ density: external_exports.enum(["compact", "comfortable"]).optional(),
32178
+ mobileFullscreen: external_exports.boolean().optional()
32179
+ }).strict().optional(),
32180
+ behavior: external_exports.object({
32181
+ startOpen: external_exports.boolean().optional(),
32182
+ closeOnEscape: external_exports.boolean().optional(),
32183
+ closeOnOutsideClick: external_exports.boolean().optional(),
32184
+ showLauncher: external_exports.boolean().optional(),
32185
+ showHeader: external_exports.boolean().optional(),
32186
+ showAvatars: external_exports.boolean().optional(),
32187
+ showTimestamps: external_exports.boolean().optional(),
32188
+ showPoweredBy: external_exports.boolean().optional()
32189
+ }).strict().optional(),
32190
+ labels: labelsSchema.optional(),
32191
+ presentation: presentationSchema.optional(),
32192
+ suggestedPrompts: external_exports.array(external_exports.string().trim().min(1).max(240)).max(8).optional(),
32193
+ privacyUrl: httpsUrlSchema.optional(),
32194
+ termsUrl: httpsUrlSchema.optional(),
32195
+ locale: external_exports.string().trim().min(2).max(35).optional(),
32196
+ direction: external_exports.enum(["ltr", "rtl", "auto"]).optional()
32197
+ }).strict();
32198
+ var assistantConfigurationSchema = external_exports.object({ branding: brandingSchema.optional(), assistant: assistantUiSchema.optional() }).strict();
32199
+ function parseAssistantConfiguration(value) {
32200
+ const parsed = assistantConfigurationSchema.safeParse(value);
32201
+ return parsed.success ? parsed.data : void 0;
32202
+ }
32203
+ function isHttpsUrl2(value) {
32204
+ try {
32205
+ return new URL(value).protocol === "https:";
32206
+ } catch {
32207
+ return false;
32208
+ }
32209
+ }
32210
+ function isSecureBrowserAssetUrl(value) {
32211
+ try {
32212
+ const url2 = new URL(value);
32213
+ if (url2.protocol === "https:") return true;
32214
+ if (url2.protocol !== "http:") return false;
32215
+ return url2.hostname === "localhost" || url2.hostname === "127.0.0.1" || url2.hostname === "[::1]";
32216
+ } catch {
32217
+ return false;
32218
+ }
32219
+ }
32220
+ function isBoundedRgbaColor(value) {
32221
+ 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(
32222
+ value
32223
+ );
32224
+ if (match === null) return false;
32225
+ return match.slice(1, 4).every((channel) => Number(channel) <= 255);
32226
+ }
32227
+
32228
+ // src/element-public-configuration-controller.ts
32229
+ var AssistantElementPublicConfigurationController = class {
32230
+ #source;
32231
+ #apply;
32232
+ #loadingChanged;
32233
+ #generation = 0;
32234
+ #bootstrap;
32235
+ #abort;
32236
+ constructor(source, apply2, loadingChanged) {
32237
+ this.#source = source;
32238
+ this.#apply = apply2;
32239
+ this.#loadingChanged = loadingChanged;
32240
+ }
32241
+ connect() {
32242
+ this.#restart();
32243
+ }
32244
+ refresh() {
32245
+ this.#restart();
32246
+ }
32247
+ disconnect() {
32248
+ this.#generation += 1;
32249
+ this.#abort?.abort();
32250
+ this.#abort = void 0;
32251
+ this.#bootstrap = void 0;
32252
+ }
32253
+ #restart() {
32254
+ this.disconnect();
32255
+ this.#prime();
32256
+ }
32257
+ #prime() {
32258
+ const source = this.#source();
32259
+ if (!source.embedId || this.#bootstrap) return;
32260
+ const generation = this.#generation;
32261
+ const abort = new AbortController();
32262
+ this.#abort = abort;
32263
+ const fetcher = source.fetch ?? ((input, init) => globalThis.fetch(input, init));
32264
+ this.#loadingChanged(true);
32265
+ const bootstrap = Promise.resolve().then(
32266
+ () => fetcher(publicConfigurationUrl(source.serviceUrl, source.embedId), {
32267
+ method: "GET",
32268
+ headers: { accept: "application/json" },
32269
+ credentials: "omit",
32270
+ cache: "no-cache",
32271
+ signal: abort.signal
32272
+ })
32273
+ ).then(async (response) => {
32274
+ if (!response.ok) return;
32275
+ const value = await response.json();
32276
+ if (generation !== this.#generation || !isRecord6(value)) {
32277
+ return;
32278
+ }
32279
+ const configuration = parseAssistantConfiguration(value.configuration);
32280
+ if (configuration !== void 0) this.#apply(configuration);
32281
+ }).catch(() => void 0).finally(() => {
32282
+ if (generation === this.#generation) this.#loadingChanged(false);
32283
+ if (this.#bootstrap === bootstrap) {
32284
+ this.#bootstrap = void 0;
32285
+ this.#abort = void 0;
32286
+ }
32287
+ });
32288
+ this.#bootstrap = bootstrap;
32289
+ }
32290
+ };
32291
+ function isRecord6(value) {
32292
+ return typeof value === "object" && value !== null && !Array.isArray(value);
32293
+ }
32294
+
31786
32295
  // src/element-scroll-controller.ts
31787
32296
  var AssistantElementScrollController = class {
31788
32297
  #region;
@@ -31912,44 +32421,69 @@ var ASSISTANT_ELEMENT_STYLES = `<style>
31912
32421
  *, *::before, *::after { box-sizing: border-box; }
31913
32422
  .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; }
31914
32423
  .visually-hidden[hidden] { display: none !important; }
31915
- :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; }
31916
- :host([data-mode="floating"]) { position: fixed; bottom: 20px; right: 20px; }
31917
- :host([data-mode="floating"][data-position="bottom-left"]) { right: auto; left: 20px; }
32424
+ :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; }
32425
+ :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; }
32426
+ :host([data-mode="floating"]) { position: fixed; }
32427
+ :host([data-mode="floating"][open]) { width: min(var(--ns-assistant-panel-width, var(--ns-assistant-default-panel-width)), 100vw); }
31918
32428
  button { font: inherit; }
31919
32429
  button, textarea, input, select { -webkit-tap-highlight-color: transparent; }
31920
- .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; }
31921
- .launcher:hover { transform: translateY(-2px) scale(1.03); box-shadow: 0 8px 26px rgba(0,0,0,.16); }
31922
- .launcher img { width: 28px; height: 28px; border-radius: 50%; object-fit: contain; }
31923
- .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; }
32430
+ .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; }
32431
+ :host([data-presentation-ready]) .launcher { padding: 10px 12px; }
32432
+ .launcher[hidden] { display: none; }
32433
+ .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); }
32434
+ .launcher-trigger, .launcher-form { min-width: 0; margin: 0; padding: 0; border: 0; background: transparent; font: inherit; }
32435
+ .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; }
32436
+ .launcher-label { padding-left: 6px; white-space: nowrap; font-size: 15px; line-height: 20px; }
32437
+ .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; }
32438
+ .launcher-arrow:hover, .launcher-send:hover { background: var(--ns-assistant-launcher-action-hover, var(--ns-assistant-halo-launcher-action-hover)); }
32439
+ .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; }
32440
+ .launcher-form { display: none; flex: 1; align-items: center; gap: 12px; opacity: 0; pointer-events: none; }
32441
+ .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; }
32442
+ .launcher-input::placeholder { color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); }
32443
+ :host([launcher-expanded]) .launcher { width: min(400px, calc(100vw - 40px)); justify-content: flex-start; }
32444
+ :host([launcher-expanded]) .launcher-trigger { display: none; }
32445
+ :host([launcher-expanded]) .launcher-form { display: flex; opacity: 1; pointer-events: auto; }
32446
+ :host([data-launcher-style="bubble"]) .launcher { gap: 0; min-height: 0; padding: 6px; cursor: pointer; }
32447
+ :host([data-launcher-style="bubble"]) .launcher-trigger { position: absolute; inset: 0; display: block; width: 100%; height: 100%; cursor: pointer; }
32448
+ :host([data-launcher-style="bubble"]) .launcher-label, :host([data-launcher-style="bubble"]) .launcher-arrow, :host([data-launcher-style="bubble"]) .launcher-form { display: none; }
32449
+ :host([data-launcher-style="bubble"]) .launcher-visual { width: 32px; height: 32px; flex-basis: 32px; }
32450
+ .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; }
32451
+ :host([data-session-state="loading"]:not([data-presentation-ready])) .launcher-loader, :host([data-public-configuration-loading]:not([data-presentation-ready])) .launcher-loader { display: block; }
32452
+ :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; }
32453
+ .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; }
32454
+ :host([data-mode="floating"][open]) .panel { width: calc(100% - 40px); margin-inline: 20px; }
31924
32455
  :host([open][data-presentation-ready]) .panel { display: flex; }
31925
32456
  .panel { position: relative; }
31926
32457
  :host([open][data-presentation-ready]) .launcher { display: none; }
31927
32458
  :host([open]:not([data-presentation-ready])) .launcher { cursor: progress; opacity: .72; transform: none; }
31928
- 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); }
32459
+ 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))); }
31929
32460
  header strong { flex: 1; font-size: 16px; font-weight: 600; letter-spacing: 0; }
31930
32461
  .brand-logo { display: block; max-width: 120px; max-height: 28px; object-fit: contain; }
31931
32462
  .close, .send { display: grid; place-items: center; border: 0; border-radius: var(--ns-assistant-button-radius, var(--ns-assistant-default-button-radius)); cursor: pointer; }
31932
- .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; }
31933
- .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; }
32463
+ .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; }
32464
+ .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; }
31934
32465
  .close:hover { color: var(--ns-assistant-text, var(--ns-assistant-default-text)); background: var(--ns-assistant-elevated, var(--ns-assistant-default-elevated)); }
31935
32466
  .close:active { transform: scale(.96); }
31936
- .welcome { flex: 0 0 auto; padding: 30px 22px 18px; }
32467
+ .welcome { flex: 0 0 auto; padding: 24px 20px 8px; }
31937
32468
  .welcome h2 { margin: 0; font-size: 1.35em; line-height: 1.25; letter-spacing: 0; }
31938
32469
  .welcome p { max-width: 42ch; margin: 7px 0 0; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); }
31939
- :host([has-messages]) .welcome, :host([has-messages]) .suggested-prompts { display: none; }
31940
- .suggested-prompts { display: flex; flex: 0 0 auto; flex-wrap: wrap; gap: 8px; padding: 0 20px 16px; }
32470
+ .welcome:has(.empty-state[hidden]) { display: none; }
32471
+ :host([has-messages]) .welcome { display: none; }
32472
+ .input-section { flex: 0 0 auto; padding: 8px 16px 16px; }
32473
+ .suggested-prompts { display: flex; flex: 0 0 auto; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
31941
32474
  .suggested-prompts:empty { display: none; }
31942
- .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; }
31943
- .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); }
32475
+ .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; }
32476
+ .suggested-prompts button::before { content: ''; position: absolute; inset: -6px -2px; }
32477
+ .suggested-prompts button:hover { color: var(--ns-assistant-text, var(--ns-assistant-default-text)); background: var(--ns-assistant-elevated, var(--ns-assistant-default-elevated)); }
31944
32478
  .messages-region { position: relative; display: flex; flex: 1 1 auto; min-height: 0; overflow: hidden; }
31945
32479
  .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; }
31946
32480
  .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); }
31947
32481
  .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); }
31948
32482
  .messages-region[data-can-scroll-up]::before, .messages-region[data-can-scroll-down]::after { opacity: 1; }
31949
- .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; }
32483
+ .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; }
31950
32484
  .messages::-webkit-scrollbar { width: 6px; }
31951
32485
  .messages::-webkit-scrollbar-thumb { background: var(--ns-assistant-divider, var(--ns-assistant-default-divider)); border-radius: 999px; }
31952
- .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; }
32486
+ .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; }
31953
32487
  .message > span, .message > .markdown { overflow-wrap: anywhere; }
31954
32488
  .message .avatar { float: left; width: 24px; height: 24px; margin-right: 9px; border-radius: 50%; object-fit: cover; }
31955
32489
  .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; }
@@ -31962,7 +32496,7 @@ var ASSISTANT_ELEMENT_STYLES = `<style>
31962
32496
  .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; }
31963
32497
  .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; }
31964
32498
  .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); }
31965
- .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; }
32499
+ .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; }
31966
32500
  .message.user time { margin-top: 0; }
31967
32501
  .markdown { white-space: normal; }
31968
32502
  .markdown p { margin: 0 0 8px; }
@@ -32012,31 +32546,39 @@ var ASSISTANT_ELEMENT_STYLES = `<style>
32012
32546
  .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)); }
32013
32547
  .input-request .proposal-actions { margin-top: 2px; }
32014
32548
  ${ASSISTANT_APP_VIEW_CSS}
32015
- 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; }
32016
- 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)); }
32549
+ .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; }
32550
+ .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); }
32017
32551
  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; }
32018
32552
  textarea::placeholder { color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); }
32019
32553
  textarea:focus, textarea:focus-visible { outline: none; box-shadow: none; }
32020
32554
  button:focus-visible { outline: 3px solid var(--ns-assistant-focus, var(--ns-assistant-default-focus)); outline-offset: 2px; }
32021
- .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; }
32022
- .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; }
32023
- .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%)); }
32555
+ .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; }
32556
+ .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%); }
32557
+ .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; }
32558
+ .send:hover::after { background: var(--ns-assistant-hover, var(--ns-assistant-default-hover)); }
32024
32559
  :host([busy]) .send::before { width: 13px; height: 13px; border-radius: 3px; -webkit-mask: none; mask: none; }
32025
32560
  .send:disabled, textarea:disabled { opacity: .55; cursor: not-allowed; }
32026
- .legal { display: flex; gap: 12px; justify-content: center; padding: 0 12px 9px; font-size: .75em; }
32561
+ .legal { display: flex; gap: 12px; justify-content: center; padding: 0 12px 8px; font-size: .75em; }
32027
32562
  .legal:empty { display: none; }
32028
32563
  .legal a { color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); text-underline-offset: 2px; }
32564
+ .powered-by-row { display: flex; flex: 0 0 auto; justify-content: center; padding-bottom: 12px; }
32565
+ .powered-by-row[hidden] { display: none; }
32566
+ .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; }
32567
+ .powered-by:hover { color: var(--ns-assistant-text, var(--ns-assistant-default-text)); opacity: 1; }
32568
+ .powered-by-icon { display: inline-flex; width: 14px; height: 14px; }
32569
+ .powered-by-name { font-weight: 500; }
32029
32570
  ::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; }
32030
- @keyframes halo-panel-in { from { opacity: 0; transform: translateY(14px) scale(.985); } to { opacity: 1; transform: none; } }
32571
+ @keyframes halo-panel-in { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: none; } }
32031
32572
  @keyframes halo-message-in { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: none; } }
32032
32573
  @keyframes halo-shimmer { from { background-position: 100% center; } to { background-position: 0 center; } }
32033
32574
  @keyframes halo-caret-blink { 50% { opacity: 0; } }
32575
+ @keyframes halo-spin { to { transform: rotate(360deg); } }
32034
32576
  :host([data-density="compact"]) .welcome { padding: 20px 18px 12px; }
32035
- @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)); } }
32577
+ @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)); } }
32036
32578
  @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; } }
32037
32579
  @media (forced-colors: active) { .message.thinking > span { color: CanvasText; background: none; } }
32038
32580
  @media (hover: none) { .message-copy { opacity: 1; } }
32039
- @media (max-width: 560px) { :host([data-mode="floating"]) { inset: auto 12px 12px; } :host([open]) .panel { width: calc(100vw - 24px); max-height: calc(100vh - 24px); } }
32581
+ @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); } }
32040
32582
  </style>`;
32041
32583
 
32042
32584
  // src/host-appearance.ts
@@ -32145,6 +32687,7 @@ function syncAssistantPresentation(host, root, appearance, mode, sessionState) {
32145
32687
  host.dataset.panelSurface = presentation.panel.surface;
32146
32688
  host.dataset.panelElevation = presentation.panel.elevation;
32147
32689
  host.dataset.panelBorder = presentation.panel.border;
32690
+ host.dataset.launcherStyle = presentation.launcher.style;
32148
32691
  host.dataset.launcherEffect = presentation.launcher.effect;
32149
32692
  host.dataset.messageUserStyle = presentation.messages.userStyle;
32150
32693
  host.dataset.messageAssistantStyle = presentation.messages.assistantStyle;
@@ -32157,11 +32700,11 @@ function syncAssistantPresentation(host, root, appearance, mode, sessionState) {
32157
32700
  }
32158
32701
  host.style.setProperty(
32159
32702
  "--ns-assistant-presentation-launcher-size",
32160
- presentation.launcher.size === "lg" ? "56px" : "48px"
32703
+ presentation.launcher.size === "lg" ? "56px" : "44px"
32161
32704
  );
32162
32705
  host.style.setProperty(
32163
32706
  "--ns-assistant-presentation-panel-background",
32164
- 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)"
32707
+ 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)"
32165
32708
  );
32166
32709
  host.style.setProperty(
32167
32710
  "--ns-assistant-presentation-shadow",
@@ -32169,7 +32712,7 @@ function syncAssistantPresentation(host, root, appearance, mode, sessionState) {
32169
32712
  );
32170
32713
  host.style.setProperty(
32171
32714
  "--ns-assistant-presentation-border",
32172
- panelBorder(presentation.panel.border)
32715
+ panelBorder(presentation.panel.border, mode)
32173
32716
  );
32174
32717
  replaceFallback(root, "launcher-icon", [launcherVisual(appearance, mode, sessionState)]);
32175
32718
  const accessibleStatus = root.querySelector("[data-session-status]");
@@ -32182,7 +32725,7 @@ function syncAssistantPresentation(host, root, appearance, mode, sessionState) {
32182
32725
  replaceFallback(root, "empty-state", [emptyState(appearance)]);
32183
32726
  replaceFallback(root, "composer-leading", composerLeading(appearance, mode));
32184
32727
  replaceFallback(root, "conversation-footer", []);
32185
- const form = root.querySelector("form");
32728
+ const form = root.querySelector(".composer");
32186
32729
  if (form) form.dataset.shape = presentation.composer.shape;
32187
32730
  const send = root.querySelector(".send");
32188
32731
  if (send) send.dataset.icon = presentation.composer.sendIcon;
@@ -32202,18 +32745,21 @@ function panelShadow(elevation) {
32202
32745
  }
32203
32746
  return "var(--ns-assistant-default-shadow)";
32204
32747
  }
32205
- function panelBorder(border) {
32748
+ function panelBorder(border, mode) {
32206
32749
  if (border === "strong") {
32207
32750
  return "1px solid var(--ns-assistant-divider, var(--ns-assistant-default-divider))";
32208
32751
  }
32209
- return "1px solid color-mix(in srgb, var(--ns-assistant-divider, var(--ns-assistant-default-divider)) 74%, transparent)";
32752
+ const opacity = mode === "light" ? 60 : 100;
32753
+ return `1px solid color-mix(in srgb, var(--ns-assistant-divider, var(--ns-assistant-default-divider)) ${opacity}%, transparent)`;
32210
32754
  }
32211
32755
  function launcherVisual(appearance, mode, sessionState) {
32212
32756
  const launcher = appearance.presentation.launcher;
32213
32757
  const visual = document.createElement("span");
32214
32758
  visual.className = "launcher-visual";
32215
32759
  visual.setAttribute("aria-hidden", "true");
32216
- visual.append(icon(launcher.icon, appearance, mode, "launcher-glyph"));
32760
+ const visualKind = launcher.icon === "brand-mark" && !(appearance.brand.mark[mode] ?? appearance.brand.logo[mode]) ? launcher.style === "bubble" ? "chat" : "none" : launcher.icon;
32761
+ visual.hidden = visualKind === "none";
32762
+ visual.append(icon(visualKind, appearance, mode, "launcher-glyph"));
32217
32763
  if (launcher.status === "session") {
32218
32764
  const status = document.createElement("span");
32219
32765
  status.className = "launcher-status";
@@ -32263,9 +32809,12 @@ function headerBadge(appearance) {
32263
32809
  function emptyState(appearance) {
32264
32810
  const section = document.createElement("section");
32265
32811
  section.className = "empty-state";
32266
- const heading = document.createElement("h2");
32267
- heading.textContent = appearance.labels.welcomeHeading;
32268
- section.append(heading);
32812
+ section.hidden = !appearance.labels.welcomeHeading && !appearance.labels.welcomeMessage;
32813
+ if (appearance.labels.welcomeHeading) {
32814
+ const heading = document.createElement("h2");
32815
+ heading.textContent = appearance.labels.welcomeHeading;
32816
+ section.append(heading);
32817
+ }
32269
32818
  const description = appearance.labels.welcomeMessage;
32270
32819
  if (description) {
32271
32820
  const paragraph = document.createElement("p");
@@ -32292,7 +32841,7 @@ function toneIndicator(tone) {
32292
32841
  return indicator;
32293
32842
  }
32294
32843
  function icon(kind, appearance, mode, className) {
32295
- const mark = appearance.brand.mark[mode];
32844
+ const mark = appearance.brand.mark[mode] ?? appearance.brand.logo[mode];
32296
32845
  if (kind === "brand-mark" && mark) {
32297
32846
  const image = document.createElement("img");
32298
32847
  image.className = className;
@@ -32344,11 +32893,17 @@ function applyAssistantElementTheme(input) {
32344
32893
  var presentationStyles = `<style>
32345
32894
  :host([data-mode="floating"]) {
32346
32895
  bottom: var(--ns-assistant-edge-offset, var(--ns-assistant-default-edge-offset));
32347
- right: var(--ns-assistant-edge-offset, var(--ns-assistant-default-edge-offset));
32896
+ left: 50%;
32897
+ transform: translateX(-50%);
32348
32898
  }
32349
32899
  :host([data-mode="floating"][data-position="bottom-left"]) {
32350
- right: auto;
32351
32900
  left: var(--ns-assistant-edge-offset, var(--ns-assistant-default-edge-offset));
32901
+ transform: none;
32902
+ }
32903
+ :host([data-mode="floating"][data-position="bottom-right"]) {
32904
+ right: var(--ns-assistant-edge-offset, var(--ns-assistant-default-edge-offset));
32905
+ left: auto;
32906
+ transform: none;
32352
32907
  }
32353
32908
  .panel {
32354
32909
  background: var(--ns-assistant-panel-background, var(--ns-assistant-presentation-panel-background));
@@ -32365,22 +32920,26 @@ var presentationStyles = `<style>
32365
32920
 
32366
32921
  .launcher {
32367
32922
  position: relative;
32368
- width: var(--ns-assistant-launcher-size, var(--ns-assistant-presentation-launcher-size));
32369
- height: var(--ns-assistant-launcher-size, var(--ns-assistant-presentation-launcher-size));
32370
32923
  border-radius: var(--ns-assistant-launcher-radius, var(--ns-assistant-default-launcher-radius));
32371
32924
  isolation: isolate;
32372
32925
  }
32926
+ :host([data-launcher-style="bubble"]) .launcher {
32927
+ width: var(--ns-assistant-launcher-size, var(--ns-assistant-presentation-launcher-size));
32928
+ height: var(--ns-assistant-launcher-size, var(--ns-assistant-presentation-launcher-size));
32929
+ }
32373
32930
  :host([data-launcher-effect="pulse"]) .launcher {
32374
32931
  animation: assistant-launcher-pulse 2s ease-in-out infinite;
32375
32932
  }
32376
32933
  .launcher-visual {
32377
32934
  position: relative;
32378
32935
  display: grid;
32379
- width: 100%;
32380
- height: 100%;
32936
+ width: 28px;
32937
+ height: 28px;
32938
+ flex: 0 0 28px;
32381
32939
  place-items: center;
32382
32940
  border-radius: inherit;
32383
32941
  }
32942
+ .launcher-visual[hidden] { display: none; }
32384
32943
  .launcher-glyph, .composer-leading-glyph {
32385
32944
  display: block;
32386
32945
  width: 18px;
@@ -32408,10 +32967,28 @@ var presentationStyles = `<style>
32408
32967
  -webkit-mask: none;
32409
32968
  mask: none;
32410
32969
  }
32970
+ .launcher-visual .launcher-glyph:is(img) {
32971
+ width: 28px;
32972
+ height: 28px;
32973
+ border-radius: 50%;
32974
+ filter: grayscale(100%);
32975
+ opacity: .6;
32976
+ 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);
32977
+ }
32978
+ .launcher:hover .launcher-glyph:is(img), :host([launcher-expanded]) .launcher-glyph:is(img) {
32979
+ filter: none;
32980
+ opacity: 1;
32981
+ }
32982
+ :host([data-launcher-style="bubble"]) .launcher-glyph:is(img) {
32983
+ width: 32px;
32984
+ height: 32px;
32985
+ filter: none;
32986
+ opacity: 1;
32987
+ }
32411
32988
  .launcher-status {
32412
32989
  position: absolute;
32413
- right: 1px;
32414
- bottom: 1px;
32990
+ right: -1px;
32991
+ bottom: -1px;
32415
32992
  width: 10px;
32416
32993
  height: 10px;
32417
32994
  border: 2px solid var(--ns-assistant-panel, var(--ns-assistant-default-panel));
@@ -32540,7 +33117,6 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32540
33117
  #conversationGeneration = 0;
32541
33118
  #messages;
32542
33119
  #thinking;
32543
- #media;
32544
33120
  #context;
32545
33121
  #modelContext;
32546
33122
  #pageContext;
@@ -32552,11 +33128,17 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32552
33128
  () => this.#primeSession(),
32553
33129
  () => this.focusComposer()
32554
33130
  );
33131
+ #publicConfiguration = new AssistantElementPublicConfigurationController(
33132
+ () => ({ embedId: this.embedId, serviceUrl: this.serviceUrl, fetch: this.#fetch }),
33133
+ (configuration) => this.#applyConfiguration(configuration),
33134
+ (loading) => this.#setPublicConfigurationLoading(loading)
33135
+ );
32555
33136
  #pendingUserEcho;
32556
33137
  #sessionState = "idle";
32557
33138
  #startOpenApplied = false;
32558
33139
  #readyDispatched = false;
32559
33140
  #turnInFlight = false;
33141
+ #fetch;
32560
33142
  #hostAppearance;
32561
33143
  #appearanceWarningKeys = /* @__PURE__ */ new Set();
32562
33144
  #appearanceStyleSnapshot = /* @__PURE__ */ new Map();
@@ -32566,6 +33148,17 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32566
33148
  embedId = "";
32567
33149
  /** Only for a dev or self-hosted service; the published snippet needs no origin. */
32568
33150
  serviceUrl = "";
33151
+ get fetch() {
33152
+ return this.#fetch;
33153
+ }
33154
+ set fetch(value) {
33155
+ if (this.#fetch === value) return;
33156
+ this.#fetch = value;
33157
+ if (this.#client) this.resetSession();
33158
+ if (!this.isConnected) return;
33159
+ if (this.embedId) this.#publicConfiguration.refresh();
33160
+ else this.#primeSession();
33161
+ }
32569
33162
  get appearance() {
32570
33163
  return this.#hostAppearance;
32571
33164
  }
@@ -32584,11 +33177,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32584
33177
  }
32585
33178
  return this.#appendMessage(role, text3);
32586
33179
  },
32587
- applyConfiguration: (configuration) => {
32588
- this.#appearance = resolveAppearance(configuration);
32589
- this.#syncAppearance();
32590
- this.#applyStartOpenPolicy();
32591
- },
33180
+ applyConfiguration: (configuration) => this.#applyConfiguration(configuration),
32592
33181
  labels: () => this.#appearance.labels,
32593
33182
  respond: (id, response) => this.respond(id, response),
32594
33183
  dispatchError: (detail) => this.#dispatchError(detail),
@@ -32604,7 +33193,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32604
33193
  client,
32605
33194
  sendMessage: (message) => this.sendMessage(message),
32606
33195
  updateModelContext: (update) => this.updateModelContext(update),
32607
- theme: this.#resolvedMode()
33196
+ theme: this.#environment.resolvedTheme()
32608
33197
  },
32609
33198
  {
32610
33199
  ...sandboxUrl === void 0 ? {} : { sandboxUrl },
@@ -32617,18 +33206,28 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32617
33206
  this.#revealLatest();
32618
33207
  }
32619
33208
  });
33209
+ #launcher = new AssistantElementLauncherController({
33210
+ host: this,
33211
+ appearance: () => this.#appearance,
33212
+ openPanel: () => this.open(),
33213
+ sendMessage: (message) => this.#sendGuarded(message)
33214
+ });
33215
+ #environment = new AssistantElementHostEnvironmentController({
33216
+ host: this,
33217
+ appearance: () => this.#appearance,
33218
+ applyTheme: () => this.#applyTheme(),
33219
+ close: () => this.#closeAndRestoreFocus()
33220
+ });
32620
33221
  connectedCallback() {
32621
33222
  if (!this.shadowRoot) this.attachShadow({ mode: "open" });
32622
33223
  if (!this.sessionEndpoint) this.sessionEndpoint = this.getAttribute("session-endpoint") ?? "";
32623
33224
  if (!this.embedId) this.embedId = this.getAttribute("embed-id") ?? "";
32624
33225
  if (!this.serviceUrl) this.serviceUrl = this.getAttribute("service-url") ?? "";
32625
33226
  if (!this.sessionEndpoint && !this.embedId) this.#presentationGate.reveal();
32626
- this.#media = globalThis.matchMedia?.("(prefers-color-scheme: dark)");
32627
- this.#media?.addEventListener("change", this.#handleSystemTheme);
32628
- document.addEventListener("keydown", this.#handleDocumentKeydown);
32629
- document.addEventListener("pointerdown", this.#handleDocumentPointerDown);
33227
+ this.#environment.connect();
32630
33228
  if (this.#appearance.behavior.startOpen) this.#applyStartOpenPolicy();
32631
33229
  this.#render();
33230
+ if (this.embedId) this.#publicConfiguration.connect();
32632
33231
  if (!this.#readyDispatched) {
32633
33232
  this.#readyDispatched = true;
32634
33233
  this.dispatchEvent(new CustomEvent("assistant-ready"));
@@ -32649,22 +33248,25 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32649
33248
  this.#clientEndpoint = "";
32650
33249
  this.#unsubscribeClient = void 0;
32651
33250
  this.#sessionBootstrap = void 0;
33251
+ this.#publicConfiguration.disconnect();
32652
33252
  this.#scroll.disconnect();
33253
+ this.#launcher.disconnect();
32653
33254
  this.#setBusy(false);
32654
- this.#media?.removeEventListener("change", this.#handleSystemTheme);
32655
- document.removeEventListener("keydown", this.#handleDocumentKeydown);
32656
- document.removeEventListener("pointerdown", this.#handleDocumentPointerDown);
33255
+ this.#environment.disconnect();
32657
33256
  }
32658
33257
  attributeChangedCallback(name21) {
32659
33258
  if (name21 === "theme") this.#applyTheme();
32660
33259
  if (name21 === "open") this.#presentationGate.syncOpenState();
32661
33260
  }
32662
33261
  open() {
33262
+ this.#launcher.collapse(true);
32663
33263
  this.setAttribute("open", "");
33264
+ if (this.hasAttribute("data-presentation-ready")) queueMicrotask(() => this.focusComposer());
32664
33265
  this.dispatchEvent(new CustomEvent("assistant-open"));
32665
33266
  }
32666
33267
  close() {
32667
33268
  this.removeAttribute("open");
33269
+ this.#launcher.collapse(true);
32668
33270
  this.dispatchEvent(new CustomEvent("assistant-close"));
32669
33271
  }
32670
33272
  toggle() {
@@ -32801,17 +33403,6 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32801
33403
  if (generation === this.#conversationGeneration) this.#setBusy(false);
32802
33404
  }
32803
33405
  }
32804
- #handleSystemTheme = () => this.#applyTheme();
32805
- #handleDocumentKeydown = (event) => {
32806
- if (event.key === "Escape" && this.hasAttribute("open") && this.#appearance.behavior.closeOnEscape) {
32807
- this.#closeAndRestoreFocus();
32808
- }
32809
- };
32810
- #handleDocumentPointerDown = (event) => {
32811
- if (this.hasAttribute("open") && this.#appearance.behavior.closeOnOutsideClick && !event.composedPath().includes(this)) {
32812
- this.close();
32813
- }
32814
- };
32815
33406
  #ensureClient() {
32816
33407
  const key = sessionSourceKey(this);
32817
33408
  if (this.#client && this.#clientEndpoint === key) return this.#client;
@@ -32827,8 +33418,13 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32827
33418
  const client = this.embedId ? createAssistantClient({
32828
33419
  embedId: this.embedId,
32829
33420
  ...this.serviceUrl ? { serviceUrl: this.serviceUrl } : {},
33421
+ ...this.#fetch ? { fetch: this.#fetch } : {},
33422
+ ...behavior
33423
+ }) : createAssistantClient({
33424
+ sessionEndpoint: this.sessionEndpoint,
33425
+ ...this.#fetch ? { fetch: this.#fetch } : {},
32830
33426
  ...behavior
32831
- }) : createAssistantClient({ sessionEndpoint: this.sessionEndpoint, ...behavior });
33427
+ });
32832
33428
  this.#client = client;
32833
33429
  this.#clientEndpoint = key;
32834
33430
  this.#unsubscribeClient = client.subscribe((event) => {
@@ -32857,6 +33453,8 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32857
33453
  this.dispatchEvent(new CustomEvent("assistant-event", { detail: event }));
32858
33454
  this.#events.handle(event);
32859
33455
  if (event.event === "session_started") {
33456
+ this.#publicConfiguration.disconnect();
33457
+ this.removeAttribute("data-public-configuration-loading");
32860
33458
  this.#presentationGate.reveal();
32861
33459
  this.#setSessionState("ready");
32862
33460
  this.#messages?.querySelector(".conversation-error")?.remove();
@@ -32906,10 +33504,10 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32906
33504
  if (!this.#messages) return void 0;
32907
33505
  const message = document.createElement("div");
32908
33506
  message.className = `message ${role}`;
32909
- if (role === "assistant" && this.#appearance.behavior.showAvatars && this.#appearance.brand.avatar[this.#resolvedMode()]) {
33507
+ if (role === "assistant" && this.#appearance.behavior.showAvatars && this.#appearance.brand.avatar[this.#environment.resolvedTheme()]) {
32910
33508
  const avatar = document.createElement("img");
32911
33509
  avatar.className = "avatar";
32912
- avatar.src = this.#appearance.brand.avatar[this.#resolvedMode()] ?? "";
33510
+ avatar.src = this.#appearance.brand.avatar[this.#environment.resolvedTheme()] ?? "";
32913
33511
  avatar.alt = "";
32914
33512
  message.append(avatar);
32915
33513
  }
@@ -32990,12 +33588,8 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32990
33588
  this.#primeSession();
32991
33589
  this.dispatchEvent(new CustomEvent("assistant-new-conversation"));
32992
33590
  }
32993
- #resolvedMode() {
32994
- const configured = this.getAttribute("theme") ?? this.#appearance.theme.defaultMode;
32995
- return configured === "auto" ? this.#media?.matches ? "dark" : "light" : configured;
32996
- }
32997
33591
  #applyTheme() {
32998
- const mode = this.#resolvedMode();
33592
+ const mode = this.#environment.resolvedTheme();
32999
33593
  for (const warning of applyAssistantElementTheme({
33000
33594
  host: this,
33001
33595
  root: this.shadowRoot,
@@ -33018,13 +33612,23 @@ var NoodleAssistantElement = class extends HTMLElementBase {
33018
33612
  updateAssistantAppTheme(app, mode);
33019
33613
  }
33020
33614
  }
33615
+ #applyConfiguration(configuration) {
33616
+ this.#appearance = resolveAppearance(configuration);
33617
+ this.#syncAppearance();
33618
+ this.#applyStartOpenPolicy();
33619
+ }
33620
+ #setPublicConfigurationLoading(loading) {
33621
+ this.toggleAttribute("data-public-configuration-loading", loading);
33622
+ if (loading) this.#presentationGate.syncOpenState();
33623
+ else this.#presentationGate.reveal();
33624
+ }
33021
33625
  #setSessionState(state) {
33022
33626
  this.#sessionState = state;
33023
33627
  syncAssistantSessionVisualState(this, this.shadowRoot, state, this.#appearance);
33024
33628
  }
33025
33629
  #closeAndRestoreFocus() {
33026
33630
  this.close();
33027
- this.shadowRoot?.querySelector(".launcher")?.focus();
33631
+ this.#launcher.focusTrigger();
33028
33632
  }
33029
33633
  #applyStartOpenPolicy() {
33030
33634
  if (this.#startOpenApplied) return;
@@ -33050,10 +33654,6 @@ var NoodleAssistantElement = class extends HTMLElementBase {
33050
33654
  textarea.placeholder = appearance.labels.composerPlaceholder;
33051
33655
  textarea.setAttribute("aria-label", appearance.labels.composerPlaceholder);
33052
33656
  queryRequired(this.shadowRoot, ".send").textContent = appearance.labels.send;
33053
- queryRequired(this.shadowRoot, ".launcher").setAttribute(
33054
- "aria-label",
33055
- appearance.labels.open
33056
- );
33057
33657
  queryRequired(this.shadowRoot, ".close").setAttribute(
33058
33658
  "aria-label",
33059
33659
  appearance.labels.close
@@ -33067,11 +33667,11 @@ var NoodleAssistantElement = class extends HTMLElementBase {
33067
33667
  button2.addEventListener("click", () => this.#sendGuarded(prompt));
33068
33668
  prompts.append(button2);
33069
33669
  }
33070
- queryRequired(this.shadowRoot, ".launcher").hidden = !appearance.behavior.showLauncher;
33071
33670
  queryRequired(this.shadowRoot, "header").hidden = !appearance.behavior.showHeader;
33072
33671
  const legal = queryRequired(this.shadowRoot, ".legal");
33073
33672
  legal.replaceChildren();
33074
33673
  appendLegalLinks(legal, this.#appearance);
33674
+ this.#launcher.sync();
33075
33675
  this.#applyTheme();
33076
33676
  }
33077
33677
  #render() {
@@ -33089,12 +33689,11 @@ var NoodleAssistantElement = class extends HTMLElementBase {
33089
33689
  this.toggleAttribute("mobile-fullscreen", appearance.layout.mobileFullscreen);
33090
33690
  this.shadowRoot.innerHTML = assistantElementMarkup(
33091
33691
  appearance,
33092
- this.hasAttribute("open"),
33093
33692
  `${ASSISTANT_ELEMENT_STYLES}${presentationStyles}`
33094
33693
  );
33095
33694
  queryRequired(this.shadowRoot, "strong").textContent = appearance.brand.name;
33096
33695
  const logo = queryRequired(this.shadowRoot, ".brand-logo");
33097
- const logoUrl = appearance.brand.logo[this.#resolvedMode()];
33696
+ const logoUrl = appearance.brand.logo[this.#environment.resolvedTheme()];
33098
33697
  if (logoUrl) {
33099
33698
  logo.src = logoUrl;
33100
33699
  logo.alt = appearance.brand.name;
@@ -33122,12 +33721,9 @@ var NoodleAssistantElement = class extends HTMLElementBase {
33122
33721
  this.#messages = this.shadowRoot.querySelector(".messages") ?? void 0;
33123
33722
  this.#messages?.append(...conversation);
33124
33723
  this.#thinking = this.#messages?.querySelector(".thinking") ?? void 0;
33125
- this.shadowRoot.querySelector(".launcher")?.addEventListener("click", () => {
33126
- this.open();
33127
- this.focusComposer();
33128
- });
33724
+ this.#launcher.connect(this.shadowRoot);
33129
33725
  this.shadowRoot.querySelector(".close")?.addEventListener("click", () => this.#closeAndRestoreFocus());
33130
- const form = queryRequired(this.shadowRoot, "form");
33726
+ const form = queryRequired(this.shadowRoot, ".composer");
33131
33727
  form.addEventListener("submit", (event) => {
33132
33728
  event.preventDefault();
33133
33729
  if (this.hasAttribute("busy")) {