@blinq_ai/widget 0.1.1 → 0.1.2

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.
package/dist/browser.cjs CHANGED
@@ -573,6 +573,12 @@ function collectNormalizedPageContext() {
573
573
  }
574
574
 
575
575
  // src/page-tools.ts
576
+ var DEFAULT_ACTION_POLICY = {
577
+ actions_enabled: true,
578
+ action_mode: "execute_with_confirmation",
579
+ pointer_overlay_enabled: true
580
+ };
581
+ var GUIDANCE_SAFE_TOOL_NAMES = /* @__PURE__ */ new Set(["blinq.scroll_to_element"]);
576
582
  function isBrowser2() {
577
583
  return typeof window !== "undefined" && typeof document !== "undefined";
578
584
  }
@@ -669,6 +675,12 @@ function findTarget(selector) {
669
675
  }
670
676
  return target;
671
677
  }
678
+ function shouldRequestConfirmation(toolName, readOnly) {
679
+ if (readOnly) {
680
+ return false;
681
+ }
682
+ return !GUIDANCE_SAFE_TOOL_NAMES.has(toolName);
683
+ }
672
684
  function isDuplicateNativeToolError(error) {
673
685
  if (!(error instanceof Error)) {
674
686
  return false;
@@ -830,6 +842,15 @@ function buildSemanticToolDefinition(descriptor) {
830
842
  }
831
843
  return null;
832
844
  }
845
+ function selectorFromArguments(argumentsPayload) {
846
+ for (const key of ["selector", "field_selector", "submit_selector", "form_selector"]) {
847
+ const value = argumentsPayload[key];
848
+ if (typeof value === "string" && value.trim()) {
849
+ return value.trim();
850
+ }
851
+ }
852
+ return null;
853
+ }
833
854
  function detectNativeWebMcpSupport() {
834
855
  if (!isBrowser2() || !window.isSecureContext) {
835
856
  return false;
@@ -845,10 +866,17 @@ var PageToolRegistry = class {
845
866
  nativeToolsActive = false;
846
867
  highlightLayer = null;
847
868
  highlightTimer = null;
869
+ actionPolicy = { ...DEFAULT_ACTION_POLICY };
848
870
  constructor(confirmationHandler) {
849
871
  this.confirmationHandler = confirmationHandler;
850
872
  this.refreshToolCatalog();
851
873
  }
874
+ setActionPolicy(nextPolicy) {
875
+ this.actionPolicy = {
876
+ ...DEFAULT_ACTION_POLICY,
877
+ ...nextPolicy
878
+ };
879
+ }
852
880
  buildBaseTools() {
853
881
  const tools = /* @__PURE__ */ new Map();
854
882
  tools.set("blinq.read_visible_page_context", {
@@ -1022,7 +1050,7 @@ var PageToolRegistry = class {
1022
1050
  }
1023
1051
  getToolCapabilities() {
1024
1052
  this.refreshToolCatalog();
1025
- return Array.from(this.tools.values()).map((tool) => tool.capability);
1053
+ return Array.from(this.tools.values()).filter((tool) => this.isToolAllowed(tool)).map((tool) => tool.capability);
1026
1054
  }
1027
1055
  clearHighlights() {
1028
1056
  if (this.highlightTimer !== null) {
@@ -1048,13 +1076,52 @@ var PageToolRegistry = class {
1048
1076
  this.highlightLayer = layer;
1049
1077
  return layer;
1050
1078
  }
1079
+ ensureHighlightStyle() {
1080
+ if (document.getElementById("blinq-highlight-style")) {
1081
+ return;
1082
+ }
1083
+ const style = document.createElement("style");
1084
+ style.id = "blinq-highlight-style";
1085
+ style.textContent = `
1086
+ @keyframes blinq-highlight-pulse {
1087
+ 0%, 100% { opacity: 0.55; transform: scale(1); }
1088
+ 50% { opacity: 1; transform: scale(1.02); }
1089
+ }
1090
+
1091
+ @keyframes blinq-highlight-ripple {
1092
+ 0% { opacity: 0.36; transform: translate(-50%, -50%) scale(0.8); }
1093
+ 100% { opacity: 0; transform: translate(-50%, -50%) scale(1.7); }
1094
+ }
1095
+
1096
+ @keyframes blinq-pointer-bob {
1097
+ 0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
1098
+ 50% { transform: translate3d(0, -2px, 0) scale(1.03); }
1099
+ }
1100
+ `;
1101
+ document.head.appendChild(style);
1102
+ }
1051
1103
  highlightTargets(targets, options) {
1052
1104
  if (!isBrowser2() || targets.length === 0) {
1053
1105
  return false;
1054
1106
  }
1055
1107
  this.clearHighlights();
1056
1108
  const layer = this.ensureHighlightLayer();
1109
+ this.ensureHighlightStyle();
1057
1110
  let highlightedCount = 0;
1111
+ let primaryRect = null;
1112
+ const backdrop = document.createElement("div");
1113
+ Object.assign(backdrop.style, {
1114
+ position: "fixed",
1115
+ inset: "0",
1116
+ background: "rgba(15, 23, 42, 0.08)",
1117
+ backdropFilter: "blur(1.5px)",
1118
+ opacity: "0",
1119
+ transition: "opacity 180ms ease"
1120
+ });
1121
+ layer.appendChild(backdrop);
1122
+ window.requestAnimationFrame(() => {
1123
+ backdrop.style.opacity = "1";
1124
+ });
1058
1125
  for (const target of targets) {
1059
1126
  if (!target.selector) {
1060
1127
  continue;
@@ -1068,21 +1135,30 @@ var PageToolRegistry = class {
1068
1135
  if (!element) {
1069
1136
  continue;
1070
1137
  }
1138
+ if (!primaryRect) {
1139
+ element.scrollIntoView({
1140
+ block: "center",
1141
+ inline: "nearest"
1142
+ });
1143
+ }
1071
1144
  const rect = element.getBoundingClientRect();
1072
1145
  if (rect.width <= 0 || rect.height <= 0) {
1073
1146
  continue;
1074
1147
  }
1148
+ if (!primaryRect) {
1149
+ primaryRect = rect;
1150
+ }
1075
1151
  const frame = document.createElement("div");
1076
1152
  Object.assign(frame.style, {
1077
1153
  position: "fixed",
1078
- left: `${Math.max(rect.left - 6, 4)}px`,
1079
- top: `${Math.max(rect.top - 6, 4)}px`,
1080
- width: `${Math.max(rect.width + 12, 18)}px`,
1081
- height: `${Math.max(rect.height + 12, 18)}px`,
1082
- border: "2px solid rgba(17, 17, 17, 0.92)",
1083
- borderRadius: "16px",
1084
- background: "rgba(17, 17, 17, 0.05)",
1085
- boxShadow: "0 0 0 1px rgba(255, 255, 255, 0.85), 0 18px 38px rgba(17, 17, 17, 0.14)",
1154
+ left: `${Math.max(rect.left - 8, 4)}px`,
1155
+ top: `${Math.max(rect.top - 8, 4)}px`,
1156
+ width: `${Math.max(rect.width + 16, 24)}px`,
1157
+ height: `${Math.max(rect.height + 16, 24)}px`,
1158
+ border: "3px solid rgba(17, 17, 17, 0.94)",
1159
+ borderRadius: "18px",
1160
+ background: "rgba(255, 255, 255, 0.16)",
1161
+ boxShadow: "0 0 0 1px rgba(255, 255, 255, 0.9), 0 24px 48px rgba(15, 23, 42, 0.18)",
1086
1162
  opacity: "0",
1087
1163
  transform: "scale(0.985)",
1088
1164
  transition: "opacity 180ms ease, transform 180ms ease"
@@ -1090,9 +1166,9 @@ var PageToolRegistry = class {
1090
1166
  const glow = document.createElement("div");
1091
1167
  Object.assign(glow.style, {
1092
1168
  position: "absolute",
1093
- inset: "-8px",
1094
- borderRadius: "20px",
1095
- border: "1px solid rgba(17, 17, 17, 0.14)",
1169
+ inset: "-10px",
1170
+ borderRadius: "22px",
1171
+ border: "1px solid rgba(37, 99, 235, 0.22)",
1096
1172
  animation: "blinq-highlight-pulse 1.2s ease-in-out infinite"
1097
1173
  });
1098
1174
  frame.appendChild(glow);
@@ -1101,15 +1177,15 @@ var PageToolRegistry = class {
1101
1177
  badge.textContent = target.label;
1102
1178
  Object.assign(badge.style, {
1103
1179
  position: "absolute",
1104
- top: "-14px",
1180
+ top: "-16px",
1105
1181
  left: "10px",
1106
- maxWidth: "min(220px, 70vw)",
1107
- padding: "4px 10px",
1182
+ maxWidth: "min(260px, 70vw)",
1183
+ padding: "6px 12px",
1108
1184
  borderRadius: "999px",
1109
1185
  background: "#111111",
1110
1186
  color: "#ffffff",
1111
1187
  fontFamily: '"Inter", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
1112
- fontSize: "11px",
1188
+ fontSize: "12px",
1113
1189
  fontWeight: "600",
1114
1190
  lineHeight: "1.3",
1115
1191
  whiteSpace: "nowrap",
@@ -1126,16 +1202,57 @@ var PageToolRegistry = class {
1126
1202
  });
1127
1203
  highlightedCount += 1;
1128
1204
  }
1129
- if (!document.getElementById("blinq-highlight-style")) {
1130
- const style = document.createElement("style");
1131
- style.id = "blinq-highlight-style";
1132
- style.textContent = `
1133
- @keyframes blinq-highlight-pulse {
1134
- 0%, 100% { opacity: 0.55; transform: scale(1); }
1135
- 50% { opacity: 1; transform: scale(1.02); }
1136
- }
1205
+ if (this.actionPolicy.pointer_overlay_enabled && primaryRect) {
1206
+ const pointer = document.createElement("div");
1207
+ pointer.setAttribute("data-blinq-pointer", options?.interaction ?? "explain");
1208
+ pointer.innerHTML = `
1209
+ <div style="position:absolute;inset:0;border-radius:999px;background:rgba(255,255,255,0.92);box-shadow:0 14px 28px rgba(15,23,42,0.18);"></div>
1210
+ <svg viewBox="0 0 40 40" width="40" height="40" fill="none" aria-hidden="true" style="position:relative;z-index:1;">
1211
+ <path d="M8 5L28 22H18.4L23.2 34.8L17.8 36.8L13 24H6.6L8 5Z" fill="#111111"/>
1212
+ <path d="M8 5L28 22H18.4L23.2 34.8L17.8 36.8L13 24H6.6L8 5Z" stroke="#ffffff" stroke-width="1.4" stroke-linejoin="round"/>
1213
+ </svg>
1137
1214
  `;
1138
- document.head.appendChild(style);
1215
+ Object.assign(pointer.style, {
1216
+ position: "fixed",
1217
+ left: `${Math.max(primaryRect.left - 72, 12)}px`,
1218
+ top: `${Math.max(primaryRect.bottom + 44, 12)}px`,
1219
+ width: "40px",
1220
+ height: "40px",
1221
+ zIndex: "2147483647",
1222
+ opacity: "0",
1223
+ transform: "translate3d(0, 0, 0) scale(0.92)",
1224
+ transition: "left 380ms cubic-bezier(.22,1,.36,1), top 380ms cubic-bezier(.22,1,.36,1), opacity 180ms ease, transform 380ms cubic-bezier(.22,1,.36,1)",
1225
+ filter: "drop-shadow(0 16px 28px rgba(15, 23, 42, 0.2))",
1226
+ animation: "blinq-pointer-bob 1.1s ease-in-out infinite"
1227
+ });
1228
+ layer.appendChild(pointer);
1229
+ const pointerTargetLeft = Math.max(primaryRect.left + 14, 8);
1230
+ const pointerTargetTop = Math.max(primaryRect.top + 14, 8);
1231
+ window.requestAnimationFrame(() => {
1232
+ pointer.style.opacity = "1";
1233
+ pointer.style.left = `${pointerTargetLeft}px`;
1234
+ pointer.style.top = `${pointerTargetTop}px`;
1235
+ pointer.style.transform = "translate3d(0, 0, 0) scale(1)";
1236
+ });
1237
+ if (options?.interaction === "execute") {
1238
+ const ripple = document.createElement("div");
1239
+ Object.assign(ripple.style, {
1240
+ position: "fixed",
1241
+ left: `${primaryRect.left + Math.min(primaryRect.width, 32) / 2}px`,
1242
+ top: `${primaryRect.top + Math.min(primaryRect.height, 32) / 2}px`,
1243
+ width: "34px",
1244
+ height: "34px",
1245
+ borderRadius: "999px",
1246
+ border: "3px solid rgba(17, 17, 17, 0.58)",
1247
+ background: "rgba(17, 17, 17, 0.12)",
1248
+ pointerEvents: "none",
1249
+ opacity: "0",
1250
+ transform: "translate(-50%, -50%) scale(0.8)",
1251
+ animation: "blinq-highlight-ripple 560ms ease-out 1 forwards",
1252
+ animationDelay: "320ms"
1253
+ });
1254
+ layer.appendChild(ripple);
1255
+ }
1139
1256
  }
1140
1257
  if (highlightedCount === 0) {
1141
1258
  this.clearHighlights();
@@ -1146,8 +1263,38 @@ var PageToolRegistry = class {
1146
1263
  }, options?.durationMs ?? 2200);
1147
1264
  return true;
1148
1265
  }
1266
+ isToolAllowed(tool) {
1267
+ if (tool.capability.read_only) {
1268
+ return true;
1269
+ }
1270
+ if (GUIDANCE_SAFE_TOOL_NAMES.has(tool.capability.name)) {
1271
+ return this.actionPolicy.actions_enabled;
1272
+ }
1273
+ return this.actionPolicy.actions_enabled && this.actionPolicy.action_mode === "execute_with_confirmation";
1274
+ }
1275
+ async previewToolRequest(request, options) {
1276
+ const selector = selectorFromArguments(request.arguments);
1277
+ if (!selector) {
1278
+ return false;
1279
+ }
1280
+ const label = (request.target_summary || request.display_name || "").trim() || void 0;
1281
+ const highlighted = this.highlightTargets(
1282
+ [{ selector, label }],
1283
+ {
1284
+ durationMs: options?.durationMs ?? (options?.interaction === "execute" ? 1600 : 2200),
1285
+ interaction: options?.interaction ?? "explain"
1286
+ }
1287
+ );
1288
+ if (!highlighted) {
1289
+ return false;
1290
+ }
1291
+ await new Promise(
1292
+ (resolve) => window.setTimeout(resolve, options?.interaction === "execute" ? 520 : 240)
1293
+ );
1294
+ return true;
1295
+ }
1149
1296
  canExecuteWriteTools() {
1150
- return isBrowser2();
1297
+ return isBrowser2() && this.actionPolicy.actions_enabled && this.actionPolicy.action_mode === "execute_with_confirmation";
1151
1298
  }
1152
1299
  async executeTool(request) {
1153
1300
  let tool = this.tools.get(request.tool_name);
@@ -1163,7 +1310,22 @@ var PageToolRegistry = class {
1163
1310
  }
1164
1311
  const displayName = request.display_name ?? tool.capability.name;
1165
1312
  const targetSummary = request.target_summary ?? tool.describeTarget?.(request.arguments) ?? tool.capability.description;
1166
- const requiresConfirmation = request.requires_confirmation ?? !tool.capability.read_only;
1313
+ const requiresConfirmation = request.requires_confirmation ?? shouldRequestConfirmation(request.tool_name, tool.capability.read_only);
1314
+ if (request.tool_name !== "blinq.highlight_element") {
1315
+ await this.previewToolRequest(request, {
1316
+ interaction: tool.capability.read_only ? "explain" : "execute"
1317
+ });
1318
+ }
1319
+ if (!tool.capability.read_only && !this.isToolAllowed(tool)) {
1320
+ return {
1321
+ status: "success",
1322
+ result: {
1323
+ success: true,
1324
+ guided: true,
1325
+ preview_only: true
1326
+ }
1327
+ };
1328
+ }
1167
1329
  if (!tool.capability.read_only && requiresConfirmation) {
1168
1330
  const confirmed = await this.confirmationHandler({
1169
1331
  displayName,
@@ -1205,6 +1367,9 @@ var PageToolRegistry = class {
1205
1367
  this.refreshToolCatalog();
1206
1368
  this.unregisterNativeTools();
1207
1369
  for (const [toolName, tool] of this.tools) {
1370
+ if (!this.isToolAllowed(tool)) {
1371
+ continue;
1372
+ }
1208
1373
  const controller = new AbortController();
1209
1374
  try {
1210
1375
  modelContext.registerTool(
@@ -1247,6 +1412,7 @@ var PageToolRegistry = class {
1247
1412
 
1248
1413
  // src/embed-shell.tsx
1249
1414
  var React = __toESM(require("react"), 1);
1415
+ var import_lucide_react = require("lucide-react");
1250
1416
  var import_react = require("@assistant-ui/react");
1251
1417
  var import_jsx_runtime = require("react/jsx-runtime");
1252
1418
  function cn(...values) {
@@ -1303,87 +1469,44 @@ function Badge({
1303
1469
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: cn(badgeClassName(variant), className), ...props });
1304
1470
  }
1305
1471
  function LauncherIcon() {
1306
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1307
- "svg",
1308
- {
1309
- viewBox: "0 0 24 24",
1310
- width: "18",
1311
- height: "18",
1312
- fill: "none",
1313
- "aria-hidden": "true",
1314
- className: "blinq-launcher-agent",
1315
- children: [
1316
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { className: "blinq-agent-orbit", cx: "12", cy: "12", r: "9" }),
1317
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { className: "blinq-agent-spark", cx: "18.6", cy: "8.2", r: "1.2" }),
1318
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1319
- "path",
1320
- {
1321
- className: "blinq-agent-antenna",
1322
- d: "M12 4.8V6.8",
1323
- stroke: "currentColor",
1324
- strokeWidth: "1.6",
1325
- strokeLinecap: "round"
1326
- }
1327
- ),
1328
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { className: "blinq-agent-antenna-dot", cx: "12", cy: "4.1", r: "1.1", fill: "currentColor" }),
1329
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1330
- "rect",
1331
- {
1332
- className: "blinq-agent-head",
1333
- x: "7",
1334
- y: "7.4",
1335
- width: "10",
1336
- height: "9.2",
1337
- rx: "3.2",
1338
- fill: "currentColor"
1339
- }
1340
- ),
1341
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { className: "blinq-agent-eye", cx: "10.2", cy: "11.3", r: "0.9", fill: "#111111" }),
1342
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { className: "blinq-agent-eye", cx: "13.8", cy: "11.3", r: "0.9", fill: "#111111" }),
1343
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1344
- "path",
1345
- {
1346
- className: "blinq-agent-mouth",
1347
- d: "M10 14.2c.7.55 1.38.82 2 .82s1.3-.27 2-.82",
1348
- stroke: "#111111",
1349
- strokeWidth: "1.3",
1350
- strokeLinecap: "round"
1351
- }
1352
- ),
1353
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1354
- "path",
1355
- {
1356
- className: "blinq-agent-neck",
1357
- d: "M10.2 17.1h3.6",
1358
- stroke: "currentColor",
1359
- strokeWidth: "1.4",
1360
- strokeLinecap: "round"
1361
- }
1362
- )
1363
- ]
1364
- }
1365
- );
1472
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Bot, { "aria-hidden": "true", className: "blinq-launcher-icon", size: 30, strokeWidth: 1.7 });
1473
+ }
1474
+ function AssistantAvatar({
1475
+ avatarUrl,
1476
+ assistantName
1477
+ }) {
1478
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-avatar", "aria-hidden": "true", children: [
1479
+ avatarUrl ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: avatarUrl, alt: "", className: "blinq-avatar-image" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Bot, { className: "blinq-avatar-icon", size: 24, strokeWidth: 1.8 }),
1480
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "blinq-avatar-status" }),
1481
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "blinq-avatar-label", children: assistantName.slice(0, 1) })
1482
+ ] });
1366
1483
  }
1367
1484
  function CollapseIcon() {
1368
1485
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", width: "16", height: "16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M6 12h12", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" }) });
1369
1486
  }
1370
1487
  function MicrophoneIcon({ listening }) {
1371
1488
  if (listening) {
1372
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", width: "16", height: "16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "7", y: "7", width: "10", height: "10", rx: "2.5", fill: "currentColor" }) });
1489
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", width: "16", height: "16", fill: "none", "aria-hidden": "true", children: [
1490
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "8.25", stroke: "currentColor", strokeWidth: "1.65" }),
1491
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "9.1", y: "9.1", width: "5.8", height: "5.8", rx: "1.6", fill: "currentColor" })
1492
+ ] });
1373
1493
  }
1374
1494
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", width: "16", height: "16", fill: "none", "aria-hidden": "true", children: [
1375
1495
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1376
1496
  "path",
1377
1497
  {
1378
- d: "M12 3.75a2.75 2.75 0 0 1 2.75 2.75v5.25a2.75 2.75 0 1 1-5.5 0V6.5A2.75 2.75 0 0 1 12 3.75Z",
1379
- fill: "currentColor"
1498
+ d: "M12 4.35a3.05 3.05 0 0 1 3.05 3.05v4.7a3.05 3.05 0 1 1-6.1 0V7.4A3.05 3.05 0 0 1 12 4.35Z",
1499
+ stroke: "currentColor",
1500
+ strokeWidth: "1.7"
1380
1501
  }
1381
1502
  ),
1382
1503
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1383
1504
  "path",
1384
1505
  {
1385
- d: "M7.5 10.5a.75.75 0 0 1 .75.75a3.75 3.75 0 1 0 7.5 0a.75.75 0 0 1 1.5 0A5.25 5.25 0 0 1 12.75 16.4V18.5H15a.75.75 0 0 1 0 1.5H9a.75.75 0 0 1 0-1.5h2.25v-2.1A5.25 5.25 0 0 1 6.75 11.25a.75.75 0 0 1 .75-.75Z",
1386
- fill: "currentColor"
1506
+ d: "M7.95 11.35a4.05 4.05 0 1 0 8.1 0M12 16.45v3.2M9.2 19.65h5.6",
1507
+ stroke: "currentColor",
1508
+ strokeWidth: "1.7",
1509
+ strokeLinecap: "round"
1387
1510
  }
1388
1511
  )
1389
1512
  ] });
@@ -1392,7 +1515,7 @@ function SendIcon() {
1392
1515
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", width: "16", height: "16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1393
1516
  "path",
1394
1517
  {
1395
- d: "M5.5 12h11M12.5 5l6.5 7-6.5 7",
1518
+ d: "M5.5 18.5 18.5 5.5M8.25 5.5h10.25v10.25",
1396
1519
  stroke: "currentColor",
1397
1520
  strokeWidth: "1.8",
1398
1521
  strokeLinecap: "round",
@@ -1554,7 +1677,7 @@ function VoiceWaveform({
1554
1677
  const waveform = samples.length > 0 ? samples : [0.18];
1555
1678
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-recording-input", role: "status", "aria-live": "polite", children: [
1556
1679
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-recording-time", children: formatRecordingDuration(durationMs) }),
1557
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-recording-waveform", "aria-hidden": "true", children: waveform.map((sample, index) => {
1680
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-recording-wave-shell", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-recording-waveform", "aria-hidden": "true", children: waveform.map((sample, index) => {
1558
1681
  const scale = Math.max(0.16, Math.min(1, sample));
1559
1682
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1560
1683
  "span",
@@ -1564,9 +1687,21 @@ function VoiceWaveform({
1564
1687
  },
1565
1688
  `voice-wave-${index}`
1566
1689
  );
1567
- }) })
1690
+ }) }) })
1568
1691
  ] });
1569
1692
  }
1693
+ function planStepStatusLabel(step, isCurrent) {
1694
+ if (step.status === "completed") {
1695
+ return "\u0413\u043E\u0442\u043E\u0432\u043E";
1696
+ }
1697
+ if (step.status === "failed") {
1698
+ return "\u041E\u0448\u0438\u0431\u043A\u0430";
1699
+ }
1700
+ if (step.status === "cancelled") {
1701
+ return "\u041E\u0442\u043C\u0435\u043D\u0435\u043D\u043E";
1702
+ }
1703
+ return isCurrent ? "\u0421\u0435\u0439\u0447\u0430\u0441" : "\u0414\u0430\u043B\u0435\u0435";
1704
+ }
1570
1705
  function ActionCard({
1571
1706
  item,
1572
1707
  accentColor,
@@ -1596,9 +1731,6 @@ function ActionCard({
1596
1731
  {
1597
1732
  type: "button",
1598
1733
  onClick: onApprove,
1599
- style: {
1600
- background: accentColor
1601
- },
1602
1734
  children: "\u0412\u044B\u043F\u043E\u043B\u043D\u0438\u0442\u044C"
1603
1735
  }
1604
1736
  )
@@ -1614,17 +1746,17 @@ function PlanCard({
1614
1746
  onDecline
1615
1747
  }) {
1616
1748
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Card, { className: "blinq-action-card blinq-plan-card", children: [
1617
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center justify-between gap-3", children: [
1749
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-plan-header", children: [
1618
1750
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
1619
1751
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardTitle, { children: "\u041F\u043B\u0430\u043D" }),
1620
1752
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardDescription, { children: item.goal })
1621
1753
  ] }),
1622
1754
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { variant: item.status === "completed" ? "default" : item.status === "failed" ? "outline" : "soft", children: item.status === "completed" ? "\u0413\u043E\u0442\u043E\u0432\u043E" : item.status === "failed" ? "\u041E\u0448\u0438\u0431\u043A\u0430" : item.status === "awaiting_navigation" ? "\u041F\u0435\u0440\u0435\u0445\u043E\u0434" : "\u0412 \u0440\u0430\u0431\u043E\u0442\u0435" })
1623
1755
  ] }) }),
1624
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CardContent, { className: "space-y-3", children: [
1756
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CardContent, { className: "blinq-plan-content", children: [
1625
1757
  item.progressLabel ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-action-state", children: item.progressLabel }) : null,
1626
1758
  item.statusReason ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-card-description", children: item.statusReason }) : null,
1627
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "space-y-2", children: item.steps.map((step, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1759
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-plan-steps", children: item.steps.map((step, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1628
1760
  "div",
1629
1761
  {
1630
1762
  className: "blinq-plan-step",
@@ -1633,7 +1765,10 @@ function PlanCard({
1633
1765
  children: [
1634
1766
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "blinq-plan-step-index", children: index + 1 }),
1635
1767
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-plan-step-copy", children: [
1636
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: step.title }),
1768
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-plan-step-title-row", children: [
1769
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-plan-step-title", children: step.title }),
1770
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "blinq-plan-step-status-pill", children: planStepStatusLabel(step, index === item.currentStepIndex) })
1771
+ ] }),
1637
1772
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-plan-step-meta", children: step.status === "completed" ? "\u0412\u044B\u043F\u043E\u043B\u043D\u0435\u043D\u043E" : step.status === "failed" ? "\u041E\u0448\u0438\u0431\u043A\u0430" : step.status === "cancelled" ? "\u041E\u0442\u043C\u0435\u043D\u0435\u043D\u043E" : index === item.currentStepIndex ? "\u0422\u0435\u043A\u0443\u0449\u0438\u0439 \u0448\u0430\u0433" : "\u041E\u0436\u0438\u0434\u0430\u0435\u0442" })
1638
1773
  ] })
1639
1774
  ]
@@ -1647,6 +1782,53 @@ function PlanCard({
1647
1782
  ] })
1648
1783
  ] });
1649
1784
  }
1785
+ function GuideCard({
1786
+ guide,
1787
+ onStartGuide,
1788
+ onAdvanceGuide,
1789
+ onDismissGuide,
1790
+ onCompleteGuide,
1791
+ onRunGuideStep
1792
+ }) {
1793
+ const currentStep = guide.steps[Math.min(guide.currentStepIndex, Math.max(guide.steps.length - 1, 0))] ?? null;
1794
+ const isStarted = guide.state === "started";
1795
+ const isCompleted = guide.state === "completed";
1796
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Card, { className: "blinq-guide-card", children: [
1797
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-plan-header", children: [
1798
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
1799
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardTitle, { children: "Guide \u043D\u0430 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0435" }),
1800
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardDescription, { children: guide.summary || "\u041F\u043E\u0448\u0430\u0433\u043E\u0432\u0430\u044F \u043F\u043E\u043C\u043E\u0449\u044C \u043F\u043E \u0442\u0435\u043A\u0443\u0449\u0435\u043C\u0443 \u0438\u043D\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443." })
1801
+ ] }),
1802
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { variant: guide.source === "live" ? "soft" : "accent", children: guide.source === "live" ? "Live" : "Published" })
1803
+ ] }) }),
1804
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardContent, { className: "blinq-guide-content", children: !isStarted ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1805
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-card-description", children: "\u0410\u0441\u0441\u0438\u0441\u0442\u0435\u043D\u0442 \u0443\u0436\u0435 \u043F\u043E\u0434\u0433\u043E\u0442\u043E\u0432\u0438\u043B guide \u0434\u043B\u044F \u044D\u0442\u043E\u0439 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u044B \u0438 \u043C\u043E\u0436\u0435\u0442 \u043F\u0440\u043E\u0432\u0435\u0441\u0442\u0438 \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F \u043F\u043E \u0448\u0430\u0433\u0430\u043C." }),
1806
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-actions", children: [
1807
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { type: "button", variant: "outline", onClick: onDismissGuide, children: "\u0421\u043A\u0440\u044B\u0442\u044C" }),
1808
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { type: "button", onClick: onStartGuide, children: "\u041D\u0430\u0447\u0430\u0442\u044C guide" })
1809
+ ] })
1810
+ ] }) : currentStep && !isCompleted ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1811
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-guide-step-shell", children: [
1812
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-guide-step-meta", children: [
1813
+ "\u0428\u0430\u0433 ",
1814
+ Math.min(guide.currentStepIndex + 1, guide.totalSteps),
1815
+ " \u0438\u0437 ",
1816
+ guide.totalSteps
1817
+ ] }),
1818
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-guide-step-title", children: currentStep.title }),
1819
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-guide-step-copy", children: currentStep.body })
1820
+ ] }),
1821
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-actions", children: [
1822
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { type: "button", variant: "outline", onClick: onDismissGuide, children: "\u0421\u043A\u0440\u044B\u0442\u044C" }),
1823
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { type: "button", variant: "outline", onClick: onRunGuideStep, children: currentStep.actionKind ? "\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C / \u0432\u044B\u043F\u043E\u043B\u043D\u0438\u0442\u044C \u0448\u0430\u0433" : "\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u043D\u0430 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0435" }),
1824
+ guide.currentStepIndex + 1 >= guide.totalSteps ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { type: "button", onClick: onCompleteGuide, children: "\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044C" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { type: "button", onClick: onAdvanceGuide, children: "\u0414\u0430\u043B\u044C\u0448\u0435" })
1825
+ ] })
1826
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1827
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-card-description", children: "Guide \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043D. \u041C\u043E\u0436\u043D\u043E \u043F\u0440\u043E\u0434\u043E\u043B\u0436\u0438\u0442\u044C \u0440\u0430\u0431\u043E\u0442\u0443 \u043D\u0430 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0435 \u0441\u0430\u043C\u043E\u0441\u0442\u043E\u044F\u0442\u0435\u043B\u044C\u043D\u043E." }),
1828
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-actions", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { type: "button", onClick: onDismissGuide, children: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C" }) })
1829
+ ] }) })
1830
+ ] });
1831
+ }
1650
1832
  function AssistantConversationThread({
1651
1833
  items,
1652
1834
  showThinkingIndicator,
@@ -1723,34 +1905,52 @@ function WidgetEmbedShell({
1723
1905
  onApproveAction,
1724
1906
  onDeclineAction,
1725
1907
  onApprovePlan,
1726
- onDeclinePlan
1908
+ onDeclinePlan,
1909
+ onStartGuide,
1910
+ onAdvanceGuide,
1911
+ onDismissGuide,
1912
+ onCompleteGuide,
1913
+ onRunGuideStep
1727
1914
  }) {
1728
1915
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1729
1916
  "div",
1730
1917
  {
1731
1918
  className: "blinq-shell",
1732
1919
  "data-side": state.side,
1920
+ "data-theme": state.themeVariant,
1733
1921
  style: { ["--blinq-accent"]: state.accentColor },
1734
1922
  children: [
1735
1923
  !state.minimized ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-panel", children: [
1736
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-header", children: [
1737
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-header-row", children: [
1738
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-header-copy", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-heading", children: state.assistantName }) }),
1739
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1740
- Button,
1741
- {
1742
- type: "button",
1743
- size: "icon-sm",
1744
- variant: "ghost",
1745
- "aria-label": "\u0421\u0432\u0435\u0440\u043D\u0443\u0442\u044C \u0432\u0438\u0434\u0436\u0435\u0442",
1746
- title: "\u0421\u0432\u0435\u0440\u043D\u0443\u0442\u044C \u0432\u0438\u0434\u0436\u0435\u0442",
1747
- onClick: onCollapse,
1748
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CollapseIcon, {})
1749
- }
1750
- )
1924
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-header", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-header-row", children: [
1925
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AssistantAvatar, { avatarUrl: state.avatarUrl, assistantName: state.assistantName }),
1926
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-header-copy", children: [
1927
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-heading", children: state.assistantName }),
1928
+ state.statusText ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-status-line", children: state.statusText }) : null
1751
1929
  ] }),
1752
- state.statusText ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-status-line", children: state.statusText }) : null
1753
- ] }),
1930
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1931
+ Button,
1932
+ {
1933
+ type: "button",
1934
+ size: "icon-sm",
1935
+ variant: "ghost",
1936
+ "aria-label": "\u0421\u0432\u0435\u0440\u043D\u0443\u0442\u044C \u0432\u0438\u0434\u0436\u0435\u0442",
1937
+ title: "\u0421\u0432\u0435\u0440\u043D\u0443\u0442\u044C \u0432\u0438\u0434\u0436\u0435\u0442",
1938
+ onClick: onCollapse,
1939
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CollapseIcon, {})
1940
+ }
1941
+ )
1942
+ ] }) }),
1943
+ state.guide ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1944
+ GuideCard,
1945
+ {
1946
+ guide: state.guide,
1947
+ onStartGuide,
1948
+ onAdvanceGuide,
1949
+ onDismissGuide,
1950
+ onCompleteGuide,
1951
+ onRunGuideStep
1952
+ }
1953
+ ) : null,
1754
1954
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1755
1955
  AssistantConversationThread,
1756
1956
  {
@@ -1796,7 +1996,7 @@ function WidgetEmbedShell({
1796
1996
  Input,
1797
1997
  {
1798
1998
  value: state.inputValue,
1799
- placeholder: "\u041D\u0430\u043F\u0440\u0438\u043C\u0435\u0440: \u043D\u0430\u0439\u0434\u0438 \u043D\u0443\u0436\u043D\u0443\u044E \u043A\u043D\u043E\u043F\u043A\u0443 \u0438\u043B\u0438 \u0437\u0430\u043F\u043E\u043B\u043D\u0438 \u0444\u043E\u0440\u043C\u0443",
1999
+ placeholder: "Type a message...",
1800
2000
  onChange: (event) => onInputChange(event.currentTarget.value),
1801
2001
  disabled: state.isSending
1802
2002
  }
@@ -1815,7 +2015,8 @@ function WidgetEmbedShell({
1815
2015
  )
1816
2016
  ] }) })
1817
2017
  }
1818
- )
2018
+ ),
2019
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-powered", children: "POWERED BY BLINQ" })
1819
2020
  ] }) : null,
1820
2021
  state.minimized ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1821
2022
  Button,
@@ -1826,7 +2027,7 @@ function WidgetEmbedShell({
1826
2027
  "aria-label": `\u041E\u0442\u043A\u0440\u044B\u0442\u044C ${state.assistantName}`,
1827
2028
  title: `\u041E\u0442\u043A\u0440\u044B\u0442\u044C ${state.assistantName}`,
1828
2029
  onClick: onOpen,
1829
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "blinq-launcher-badge", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LauncherIcon, {}) })
2030
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LauncherIcon, {})
1830
2031
  }
1831
2032
  ) : null
1832
2033
  ]
@@ -2236,6 +2437,41 @@ var SESSION_STORAGE_PREFIX = "blinq-widget-session";
2236
2437
  var MAX_STORED_HISTORY = 30;
2237
2438
  var MAX_HISTORY_FOR_REQUEST = 12;
2238
2439
  var DEFAULT_GREETING = "Blinq \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0435\u043D. \u0421\u043F\u0440\u043E\u0441\u0438\u0442\u0435 \u043F\u0440\u043E \u0442\u0435\u043A\u0443\u0449\u0443\u044E \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0443, \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0443 \u043F\u043B\u0430\u0442\u0444\u043E\u0440\u043C\u044B \u0438\u043B\u0438 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0439 \u0448\u0430\u0433.";
2440
+ var PLAN_APPROVE_TEXTS = /* @__PURE__ */ new Set([
2441
+ "\u0434\u0430",
2442
+ "\u0430\u0433\u0430",
2443
+ "\u043E\u043A",
2444
+ "okay",
2445
+ "\u043E\u043A\u0435\u0439",
2446
+ "\u0445\u043E\u0440\u043E\u0448\u043E",
2447
+ "\u043B\u0430\u0434\u043D\u043E",
2448
+ "\u0434\u0435\u043B\u0430\u0439",
2449
+ "\u0441\u0434\u0435\u043B\u0430\u0439",
2450
+ "\u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u044E",
2451
+ "yes",
2452
+ "ok",
2453
+ "sure",
2454
+ "go ahead",
2455
+ "approve",
2456
+ "\u0438\u04D9",
2457
+ "\u0438\u044F",
2458
+ "\u0438\u0441\u0442\u0435",
2459
+ "\u0436\u0430\u0440\u0430\u0439\u0434\u044B",
2460
+ "\u043C\u0430\u049B\u04B1\u043B"
2461
+ ]);
2462
+ var PLAN_DECLINE_TEXTS = /* @__PURE__ */ new Set([
2463
+ "\u043D\u0435\u0442",
2464
+ "\u043D\u0435 \u043D\u0430\u0434\u043E",
2465
+ "\u043D\u0435 \u043D\u0443\u0436\u043D\u043E",
2466
+ "\u043E\u0442\u043C\u0435\u043D\u0430",
2467
+ "\u043E\u0442\u043C\u0435\u043D\u0438",
2468
+ "cancel",
2469
+ "no",
2470
+ "stop",
2471
+ "\u0436\u043E\u049B",
2472
+ "\u0442\u043E\u049B\u0442\u0430",
2473
+ "\u043A\u0435\u0440\u0435\u043A \u0435\u043C\u0435\u0441"
2474
+ ]);
2239
2475
  function isBrowser3() {
2240
2476
  return typeof window !== "undefined" && typeof document !== "undefined";
2241
2477
  }
@@ -2269,9 +2505,9 @@ function getOrCreateFingerprint() {
2269
2505
  }
2270
2506
  function runtimeMessage(mode) {
2271
2507
  if (mode === "read-only-fallback") {
2272
- return "\u0413\u043E\u0442\u043E\u0432 \u043E\u0431\u044A\u044F\u0441\u043D\u0438\u0442\u044C \u0442\u0435\u043A\u0443\u0449\u0443\u044E \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0443 \u0438 \u043F\u043E\u0434\u0441\u043A\u0430\u0437\u0430\u0442\u044C \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0439 \u0448\u0430\u0433.";
2508
+ return "\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044F \u043D\u0430 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0435 \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B. \u042F \u043C\u043E\u0433\u0443 \u043E\u0431\u044A\u044F\u0441\u043D\u044F\u0442\u044C \u0438\u043D\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0438 \u043E\u0442\u0432\u0435\u0447\u0430\u0442\u044C \u043F\u043E \u0431\u0430\u0437\u0435 \u0437\u043D\u0430\u043D\u0438\u0439.";
2273
2509
  }
2274
- return "\u0413\u043E\u0442\u043E\u0432 \u043F\u043E\u043C\u043E\u0447\u044C \u0441 \u043E\u043D\u0431\u043E\u0440\u0434\u0438\u043D\u0433\u043E\u043C \u0438 \u0432\u043E\u043F\u0440\u043E\u0441\u0430\u043C\u0438 \u043F\u043E \u043F\u043B\u0430\u0442\u0444\u043E\u0440\u043C\u0435.";
2510
+ return "\u0413\u043E\u0442\u043E\u0432 \u043F\u043E\u043C\u043E\u0433\u0430\u0442\u044C \u0441 \u0438\u043D\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043E\u043C, \u0437\u043D\u0430\u043D\u0438\u044F\u043C\u0438 \u0438 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u043C\u0438 \u0448\u0430\u0433\u0430\u043C\u0438.";
2275
2511
  }
2276
2512
  function normalizedRouteFromUrl(value) {
2277
2513
  try {
@@ -2348,7 +2584,7 @@ var BlinqWidget = class {
2348
2584
  minimized = false;
2349
2585
  isSending = false;
2350
2586
  inputValue = "";
2351
- statusText = "\u041F\u0440\u043E\u0432\u0435\u0440\u044F\u0435\u043C \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044F \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u044B.";
2587
+ statusText = "";
2352
2588
  voiceSupported = false;
2353
2589
  voiceListening = false;
2354
2590
  voiceWaveform = [];
@@ -2358,6 +2594,7 @@ var BlinqWidget = class {
2358
2594
  confirmResolve = null;
2359
2595
  confirmItemId = null;
2360
2596
  activeRun = null;
2597
+ activeGuide = null;
2361
2598
  pendingAssistantIndicator = false;
2362
2599
  executedToolCounts = /* @__PURE__ */ new Map();
2363
2600
  lastAutoResumeKey = null;
@@ -2387,12 +2624,34 @@ var BlinqWidget = class {
2387
2624
  },
2388
2625
  onDeclinePlan: () => {
2389
2626
  void this.respondToPlan(false);
2627
+ },
2628
+ onStartGuide: () => {
2629
+ void this.startGuide();
2630
+ },
2631
+ onAdvanceGuide: () => {
2632
+ void this.advanceGuide();
2633
+ },
2634
+ onDismissGuide: () => {
2635
+ void this.dismissGuide();
2636
+ },
2637
+ onCompleteGuide: () => {
2638
+ void this.completeGuide();
2639
+ },
2640
+ onRunGuideStep: () => {
2641
+ void this.runGuideStep();
2390
2642
  }
2391
2643
  };
2392
2644
  constructor(options) {
2393
2645
  this.options = options;
2394
2646
  this.apiBaseUrl = options.apiBaseUrl ?? DEFAULT_API_BASE_URL;
2395
2647
  }
2648
+ currentActionPolicy() {
2649
+ return this.runtimeStatus?.action_policy ?? {
2650
+ actions_enabled: this.widgetConfig?.actions_enabled ?? true,
2651
+ action_mode: this.widgetConfig?.action_mode ?? "execute_with_confirmation",
2652
+ pointer_overlay_enabled: this.widgetConfig?.pointer_overlay_enabled ?? true
2653
+ };
2654
+ }
2396
2655
  async init() {
2397
2656
  await this.startSession();
2398
2657
  if (isBrowser3()) {
@@ -2402,8 +2661,10 @@ var BlinqWidget = class {
2402
2661
  this.render();
2403
2662
  this.setupVoiceInput();
2404
2663
  this.registry = new PageToolRegistry(this.confirmToolExecution.bind(this));
2664
+ this.registry.setActionPolicy(this.currentActionPolicy());
2405
2665
  const nativeRegistered = await this.registry.registerNativeTools();
2406
2666
  this.syncRuntimeStatus(nativeRegistered);
2667
+ this.syncGuideHighlight();
2407
2668
  if (this.shouldAutoResumeActiveRun()) {
2408
2669
  window.setTimeout(() => {
2409
2670
  void this.continueActiveRun();
@@ -2428,18 +2689,21 @@ var BlinqWidget = class {
2428
2689
  currentState() {
2429
2690
  return {
2430
2691
  minimized: this.minimized,
2431
- assistantName: this.widgetConfig?.ai_persona_name ?? "Blinq \u0410\u0441\u0441\u0438\u0441\u0442\u0435\u043D\u0442",
2692
+ assistantName: this.widgetConfig?.name ?? "Blinq \u0410\u0441\u0441\u0438\u0441\u0442\u0435\u043D\u0442",
2693
+ avatarUrl: this.widgetConfig?.avatar_url ?? null,
2432
2694
  runtimeLabel: "webmcp://embedded",
2433
2695
  statusText: this.statusText,
2434
2696
  showThinkingIndicator: this.pendingAssistantIndicator,
2435
2697
  inputValue: this.inputValue,
2436
- accentColor: "#111111",
2698
+ accentColor: this.widgetConfig?.theme_color ?? "#111111",
2699
+ themeVariant: "light",
2437
2700
  side: this.widgetConfig?.position === "bottom-left" ? "left" : "right",
2438
2701
  isSending: this.isSending,
2439
2702
  voiceSupported: this.voiceSupported,
2440
2703
  voiceListening: this.voiceListening,
2441
2704
  voiceWaveform: this.voiceWaveform,
2442
2705
  voiceDurationMs: this.voiceDurationMs,
2706
+ guide: this.activeGuide,
2443
2707
  items: this.items
2444
2708
  };
2445
2709
  }
@@ -2482,6 +2746,7 @@ var BlinqWidget = class {
2482
2746
  this.sessionToken = payload.session_token;
2483
2747
  this.widgetConfig = payload.widget_config;
2484
2748
  this.activeRun = payload.active_run ?? null;
2749
+ this.activeGuide = this.normalizeGuidePayload(payload.active_guide ?? payload.guide_offer ?? null);
2485
2750
  this.runtimeStatus = {
2486
2751
  ...payload.runtime,
2487
2752
  message: runtimeMessage(payload.runtime.mode)
@@ -2725,6 +2990,62 @@ var BlinqWidget = class {
2725
2990
  this.upsertPlanItem(this.activeRun);
2726
2991
  }
2727
2992
  }
2993
+ normalizeGuideStep(step) {
2994
+ return {
2995
+ id: step.id,
2996
+ position: step.position,
2997
+ title: step.title,
2998
+ body: step.body,
2999
+ targetSelector: step.target_selector ?? null,
3000
+ targetLabel: step.target_label ?? null,
3001
+ actionKind: step.action_kind ?? null,
3002
+ actionPayload: step.action_payload ?? null,
3003
+ expectedRoute: step.expected_route ?? null,
3004
+ completionMode: step.completion_mode
3005
+ };
3006
+ }
3007
+ normalizeGuidePayload(payload) {
3008
+ if (!payload) {
3009
+ return null;
3010
+ }
3011
+ const guide = payload.guide;
3012
+ return {
3013
+ id: guide.id,
3014
+ state: payload.state,
3015
+ source: guide.source,
3016
+ route: guide.route,
3017
+ summary: guide.summary ?? null,
3018
+ currentStepIndex: payload.state === "started" ? Math.min(payload.current_step_index, Math.max(guide.steps.length - 1, 0)) : payload.state === "completed" ? guide.steps.length : 0,
3019
+ totalSteps: guide.steps.length,
3020
+ steps: guide.steps.map((step) => this.normalizeGuideStep(step))
3021
+ };
3022
+ }
3023
+ setGuideState(payload, options) {
3024
+ const normalized = this.normalizeGuidePayload(payload);
3025
+ if (options?.clearIfFinished !== false && normalized && (normalized.state === "dismissed" || normalized.state === "completed")) {
3026
+ this.activeGuide = null;
3027
+ } else {
3028
+ this.activeGuide = normalized;
3029
+ }
3030
+ this.renderReactApp();
3031
+ this.syncGuideHighlight();
3032
+ }
3033
+ currentGuideStep() {
3034
+ if (!this.activeGuide || this.activeGuide.state !== "started") {
3035
+ return null;
3036
+ }
3037
+ return this.activeGuide.steps[Math.min(this.activeGuide.currentStepIndex, Math.max(this.activeGuide.steps.length - 1, 0))] ?? null;
3038
+ }
3039
+ syncGuideHighlight() {
3040
+ const step = this.currentGuideStep();
3041
+ if (!step?.targetSelector || !this.registry) {
3042
+ return;
3043
+ }
3044
+ this.registry.highlightTargets(
3045
+ [{ selector: step.targetSelector, label: step.targetLabel || step.title }],
3046
+ { interaction: step.actionKind ? "execute" : "explain", durationMs: 2100 }
3047
+ );
3048
+ }
2728
3049
  updateActionState(id, state) {
2729
3050
  this.items = this.items.map(
2730
3051
  (item) => item.type === "action" && item.id === id ? { ...item, state } : item
@@ -2738,8 +3059,24 @@ var BlinqWidget = class {
2738
3059
  const existingPlanItem = this.items.find(
2739
3060
  (item) => item.type === "plan" && item.id === this.planItemId(run.id)
2740
3061
  );
2741
- if (this.activeRun?.id && this.activeRun.id !== run.id) {
3062
+ const isNewActiveRun = Boolean(this.activeRun?.id && this.activeRun.id !== run.id);
3063
+ if (isNewActiveRun) {
2742
3064
  this.executedToolCounts.clear();
3065
+ this.items = this.items.map((item) => {
3066
+ if (item.type !== "plan" || item.id === this.planItemId(run.id)) {
3067
+ return item;
3068
+ }
3069
+ if (item.status === "completed" || item.status === "failed" || item.status === "abandoned") {
3070
+ return item;
3071
+ }
3072
+ return {
3073
+ ...item,
3074
+ status: "abandoned",
3075
+ approvalState: "declined",
3076
+ progressLabel: item.progressLabel ?? "\u041F\u043B\u0430\u043D \u0437\u0430\u043C\u0435\u043D\u0451\u043D \u043D\u043E\u0432\u044B\u043C \u0437\u0430\u043F\u0440\u043E\u0441\u043E\u043C.",
3077
+ statusReason: item.statusReason ?? "\u041F\u043B\u0430\u043D \u0437\u0430\u043C\u0435\u043D\u0451\u043D \u043D\u043E\u0432\u044B\u043C \u0437\u0430\u043F\u0440\u043E\u0441\u043E\u043C."
3078
+ };
3079
+ });
2743
3080
  }
2744
3081
  this.activeRun = {
2745
3082
  ...run,
@@ -2823,7 +3160,7 @@ var BlinqWidget = class {
2823
3160
  if (!this.runtimeStatus) {
2824
3161
  return;
2825
3162
  }
2826
- const mode = nativeRegistered ? "native-webmcp-active" : this.registry?.canExecuteWriteTools() ? "blinq-page-tools-active" : "read-only-fallback";
3163
+ const mode = nativeRegistered ? "native-webmcp-active" : this.registry ? "blinq-page-tools-active" : "read-only-fallback";
2827
3164
  this.runtimeStatus = {
2828
3165
  ...this.runtimeStatus,
2829
3166
  mode,
@@ -2837,6 +3174,124 @@ var BlinqWidget = class {
2837
3174
  this.statusText = text;
2838
3175
  this.renderReactApp();
2839
3176
  }
3177
+ async guideRequest(path, body) {
3178
+ if (!this.sessionToken) {
3179
+ throw new Error("\u0421\u0435\u0441\u0441\u0438\u044F \u0432\u0438\u0434\u0436\u0435\u0442\u0430 \u0435\u0449\u0451 \u043D\u0435 \u0438\u043D\u0438\u0446\u0438\u0430\u043B\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u043D\u0430");
3180
+ }
3181
+ const response = await fetch(`${this.apiBaseUrl}${path}`, {
3182
+ method: "POST",
3183
+ headers: {
3184
+ "Content-Type": "application/json",
3185
+ Authorization: `Bearer ${this.sessionToken}`
3186
+ },
3187
+ body: JSON.stringify(body)
3188
+ });
3189
+ if (!response.ok) {
3190
+ const payload = await response.json().catch(() => ({}));
3191
+ throw new Error(payload.detail ?? "\u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u043E\u0431\u043D\u043E\u0432\u0438\u0442\u044C \u0441\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435 guide");
3192
+ }
3193
+ return await response.json();
3194
+ }
3195
+ async startGuide() {
3196
+ if (!this.sessionId || !this.activeGuide) {
3197
+ return;
3198
+ }
3199
+ const payload = await this.guideRequest("/pub/guide/start", {
3200
+ session_id: this.sessionId,
3201
+ guide_id: this.activeGuide.source === "published" ? this.activeGuide.id : null
3202
+ });
3203
+ this.setGuideState(payload, { clearIfFinished: false });
3204
+ this.setStatus("Guide \u0437\u0430\u043F\u0443\u0449\u0435\u043D.");
3205
+ }
3206
+ async advanceGuide() {
3207
+ if (!this.sessionId) {
3208
+ return;
3209
+ }
3210
+ const payload = await this.guideRequest("/pub/guide/advance", {
3211
+ session_id: this.sessionId
3212
+ });
3213
+ this.setGuideState(payload);
3214
+ this.setStatus(payload.state === "completed" ? "Guide \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043D." : "\u041F\u0435\u0440\u0435\u0445\u043E\u0434\u0438\u043C \u043A \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0435\u043C\u0443 \u0448\u0430\u0433\u0443.");
3215
+ }
3216
+ async dismissGuide() {
3217
+ if (!this.sessionId) {
3218
+ return;
3219
+ }
3220
+ const payload = await this.guideRequest("/pub/guide/dismiss", {
3221
+ session_id: this.sessionId
3222
+ });
3223
+ this.setGuideState(payload);
3224
+ this.setStatus("Guide \u0441\u043A\u0440\u044B\u0442.");
3225
+ }
3226
+ async completeGuide() {
3227
+ if (!this.sessionId) {
3228
+ return;
3229
+ }
3230
+ const payload = await this.guideRequest("/pub/guide/complete", {
3231
+ session_id: this.sessionId
3232
+ });
3233
+ this.setGuideState(payload);
3234
+ this.setStatus("Guide \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043D.");
3235
+ }
3236
+ async runGuideStep() {
3237
+ const step = this.currentGuideStep();
3238
+ if (!step || !this.registry) {
3239
+ return;
3240
+ }
3241
+ if (step.actionKind && step.actionPayload && this.currentActionPolicy().actions_enabled && this.currentActionPolicy().action_mode === "execute_with_confirmation") {
3242
+ const outcome = await this.registry.executeTool({
3243
+ tool_name: step.actionKind,
3244
+ display_name: step.title,
3245
+ target_summary: step.targetLabel || step.body,
3246
+ arguments: step.actionPayload
3247
+ });
3248
+ if (outcome.status === "success") {
3249
+ this.setStatus("\u0428\u0430\u0433 \u0432\u044B\u043F\u043E\u043B\u043D\u0435\u043D \u043D\u0430 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0435.");
3250
+ const deferredNavigationHref = outcome.result && typeof outcome.result.href === "string" && outcome.result.deferred_navigation ? outcome.result.href : null;
3251
+ await this.advanceGuide();
3252
+ if (deferredNavigationHref) {
3253
+ window.location.assign(deferredNavigationHref);
3254
+ }
3255
+ } else if (outcome.status === "cancelled") {
3256
+ this.setStatus("\u0412\u044B\u043F\u043E\u043B\u043D\u0435\u043D\u0438\u0435 \u0448\u0430\u0433\u0430 \u043E\u0442\u043C\u0435\u043D\u0435\u043D\u043E.");
3257
+ } else {
3258
+ await this.healGuideStep();
3259
+ }
3260
+ return;
3261
+ }
3262
+ if (step.targetSelector) {
3263
+ const highlighted = this.registry.highlightTargets(
3264
+ [{ selector: step.targetSelector, label: step.targetLabel || step.title }],
3265
+ { interaction: "explain", durationMs: 2200 }
3266
+ );
3267
+ if (highlighted) {
3268
+ this.setStatus("\u041F\u043E\u043A\u0430\u0437\u0430\u043B, \u043A\u0443\u0434\u0430 \u043D\u0430\u0436\u0430\u0442\u044C \u043D\u0430 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0435.");
3269
+ } else {
3270
+ await this.healGuideStep();
3271
+ }
3272
+ }
3273
+ }
3274
+ async healGuideStep() {
3275
+ if (!this.sessionId || !this.activeGuide || !this.registry) {
3276
+ return;
3277
+ }
3278
+ this.setStatus("\u041A\u0430\u0436\u0435\u0442\u0441\u044F \u044D\u043B\u0435\u043C\u0435\u043D\u0442 \u043F\u0435\u0440\u0435\u0435\u0445\u0430\u043B. \u0418\u0449\u0443 \u043D\u043E\u0432\u044B\u0435 \u0441\u043F\u043E\u0441\u043E\u0431\u044B \u0441 \u043F\u043E\u043C\u043E\u0449\u044C\u044E \u0418\u0418...");
3279
+ const pageContext = this.registry.collectPageContext();
3280
+ try {
3281
+ const payload = await this.guideRequest("/pub/guide/heal", {
3282
+ session_id: this.sessionId,
3283
+ step_index: this.activeGuide.currentStepIndex,
3284
+ page_context: pageContext
3285
+ });
3286
+ this.setGuideState(payload, { clearIfFinished: false });
3287
+ this.setStatus("\u0421\u0446\u0435\u043D\u0430\u0440\u0438\u0439 \u043F\u0435\u0440\u0435\u0441\u0442\u0440\u043E\u0435\u043D. \u041F\u0440\u043E\u0434\u043E\u043B\u0436\u0430\u044E...");
3288
+ window.setTimeout(() => {
3289
+ void this.runGuideStep();
3290
+ }, 1500);
3291
+ } catch (e) {
3292
+ this.setStatus("\u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u043F\u0435\u0440\u0435\u0441\u0442\u0440\u043E\u0438\u0442\u044C \u0448\u0430\u0433.");
3293
+ }
3294
+ }
2840
3295
  appendMessage(text, role, options) {
2841
3296
  const id = createConversationId("message");
2842
3297
  this.items = [
@@ -2897,6 +3352,19 @@ var BlinqWidget = class {
2897
3352
  currentRoute() {
2898
3353
  return normalizedRouteFromUrl(window.location.href);
2899
3354
  }
3355
+ normalizedUserPlanDecision(message) {
3356
+ const normalized = message.trim().toLowerCase();
3357
+ if (!normalized || !this.activeRun?.requires_approval) {
3358
+ return null;
3359
+ }
3360
+ if (PLAN_APPROVE_TEXTS.has(normalized)) {
3361
+ return true;
3362
+ }
3363
+ if (PLAN_DECLINE_TEXTS.has(normalized)) {
3364
+ return false;
3365
+ }
3366
+ return null;
3367
+ }
2900
3368
  shouldAutoResumeActiveRun() {
2901
3369
  if (!this.activeRun || this.activeRun.status !== "awaiting_navigation") {
2902
3370
  return false;
@@ -2995,7 +3463,13 @@ var BlinqWidget = class {
2995
3463
  }
2996
3464
  if (event === "highlight") {
2997
3465
  const highlight = JSON.parse(data);
2998
- this.registry?.highlightTargets(highlight.targets ?? []);
3466
+ this.registry?.highlightTargets(highlight.targets ?? [], { interaction: "explain" });
3467
+ }
3468
+ if (event === "guide") {
3469
+ this.hideThinkingIndicator();
3470
+ this.setGuideState(JSON.parse(data), {
3471
+ clearIfFinished: false
3472
+ });
2999
3473
  }
3000
3474
  if (event === "delta" && payload.text) {
3001
3475
  const normalizedChunk = normalizeAssistantStreamChunk(finalText, payload.text);
@@ -3077,6 +3551,18 @@ var BlinqWidget = class {
3077
3551
  let responseMessageId = null;
3078
3552
  try {
3079
3553
  this.appendMessage(message, "user");
3554
+ const directPlanDecision = this.normalizedUserPlanDecision(message);
3555
+ if (directPlanDecision !== null) {
3556
+ const finalText2 = await this.respondToPlan(directPlanDecision, {
3557
+ appendAssistantMessage: false,
3558
+ manageSendingState: false
3559
+ });
3560
+ if (finalText2.trim()) {
3561
+ this.finalizeAssistantMessage(finalText2, { persist: false });
3562
+ this.rememberMessage({ role: "assistant", text: finalText2 });
3563
+ }
3564
+ return finalText2;
3565
+ }
3080
3566
  const finalText = await this.streamChatStep(
3081
3567
  "/pub/chat",
3082
3568
  {
@@ -3137,16 +3623,19 @@ var BlinqWidget = class {
3137
3623
  this.renderReactApp();
3138
3624
  }
3139
3625
  }
3140
- async respondToPlan(approved) {
3626
+ async respondToPlan(approved, options) {
3141
3627
  if (!this.sessionId || !this.sessionToken || !this.activeRun) {
3142
- return;
3628
+ return "";
3143
3629
  }
3144
- if (this.isSending) {
3145
- return;
3630
+ const manageSendingState = options?.manageSendingState ?? true;
3631
+ if (manageSendingState && this.isSending) {
3632
+ return "";
3633
+ }
3634
+ if (manageSendingState) {
3635
+ this.isSending = true;
3636
+ this.showThinkingIndicator();
3637
+ this.renderReactApp();
3146
3638
  }
3147
- this.isSending = true;
3148
- this.showThinkingIndicator();
3149
- this.renderReactApp();
3150
3639
  try {
3151
3640
  const finalText = await this.streamChatStep(
3152
3641
  "/pub/plan/approve",
@@ -3158,14 +3647,17 @@ var BlinqWidget = class {
3158
3647
  },
3159
3648
  null
3160
3649
  );
3161
- if (finalText.trim()) {
3650
+ if (options?.appendAssistantMessage !== false && finalText.trim()) {
3162
3651
  this.finalizeAssistantMessage(finalText, { persist: false });
3163
3652
  this.rememberMessage({ role: "assistant", text: finalText });
3164
3653
  }
3654
+ return finalText;
3165
3655
  } finally {
3166
- this.hideThinkingIndicator();
3167
- this.isSending = false;
3168
- this.renderReactApp();
3656
+ if (manageSendingState) {
3657
+ this.hideThinkingIndicator();
3658
+ this.isSending = false;
3659
+ this.renderReactApp();
3660
+ }
3169
3661
  }
3170
3662
  }
3171
3663
  async endSession() {
@@ -3219,27 +3711,41 @@ var EMBED_WIDGET_STYLES = `
3219
3711
  display: flex;
3220
3712
  flex-direction: column;
3221
3713
  gap: 12px;
3222
- width: 420px;
3714
+ width: 432px;
3223
3715
  max-width: calc(100vw - 24px);
3224
- font-family:
3225
- "Inter", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
3226
- "Segoe UI", sans-serif;
3227
3716
  pointer-events: none;
3717
+ font-family:
3718
+ "SF Pro Display",
3719
+ "SF Pro Text",
3720
+ "Inter",
3721
+ ui-sans-serif,
3722
+ system-ui,
3723
+ -apple-system,
3724
+ BlinkMacSystemFont,
3725
+ "Segoe UI",
3726
+ sans-serif;
3228
3727
  --blinq-accent: #111111;
3229
- --blinq-background: #ffffff;
3230
- --blinq-panel: rgba(255, 255, 255, 0.98);
3231
- --blinq-panel-soft: #fafafa;
3232
- --blinq-surface: #ffffff;
3233
- --blinq-surface-soft: #f5f5f5;
3234
- --blinq-surface-muted: #ededed;
3235
- --blinq-border: rgba(17, 17, 17, 0.08);
3236
- --blinq-border-strong: rgba(17, 17, 17, 0.18);
3237
- --blinq-text: #111111;
3238
- --blinq-text-soft: #262626;
3239
- --blinq-text-muted: #737373;
3240
- --blinq-user-bubble: #111111;
3241
- --blinq-user-text: #ffffff;
3242
- --blinq-shadow: 0 24px 60px rgba(17, 17, 17, 0.12);
3728
+ --blinq-text: rgba(18, 18, 20, 0.96);
3729
+ --blinq-text-soft: rgba(32, 34, 38, 0.82);
3730
+ --blinq-text-muted: rgba(56, 60, 66, 0.58);
3731
+ --blinq-glass-fill: linear-gradient(180deg, rgba(255, 255, 255, 0.78), rgba(240, 243, 248, 0.52));
3732
+ --blinq-glass-fill-strong: linear-gradient(180deg, rgba(255, 255, 255, 0.88), rgba(245, 247, 250, 0.62));
3733
+ --blinq-glass-fill-dense: linear-gradient(180deg, rgba(249, 250, 252, 0.92), rgba(231, 235, 241, 0.66));
3734
+ --blinq-glass-stroke: rgba(255, 255, 255, 0.68);
3735
+ --blinq-glass-stroke-soft: rgba(255, 255, 255, 0.5);
3736
+ --blinq-glass-edge: rgba(100, 109, 123, 0.14);
3737
+ --blinq-shadow:
3738
+ 0 28px 80px rgba(155, 164, 180, 0.22),
3739
+ 0 10px 30px rgba(174, 182, 193, 0.18);
3740
+ --blinq-shadow-soft:
3741
+ 0 14px 40px rgba(170, 177, 189, 0.18),
3742
+ 0 4px 14px rgba(202, 208, 216, 0.18);
3743
+ --blinq-inner-highlight: inset 0 1px 0 rgba(255, 255, 255, 0.92);
3744
+ --blinq-blur: blur(28px) saturate(170%);
3745
+ --blinq-radius-panel: 32px;
3746
+ --blinq-radius-pill: 999px;
3747
+ --blinq-radius-bubble: 28px;
3748
+ --blinq-radius-card: 30px;
3243
3749
  }
3244
3750
 
3245
3751
  .blinq-shell[data-side="left"] {
@@ -3257,397 +3763,170 @@ var EMBED_WIDGET_STYLES = `
3257
3763
  pointer-events: auto;
3258
3764
  }
3259
3765
 
3260
- .blinq-launcher {
3261
- display: inline-flex;
3262
- align-items: center;
3263
- justify-content: center;
3264
- gap: 12px;
3265
- min-height: 58px;
3266
- padding: 0 18px;
3267
- border: 1px solid var(--blinq-border);
3268
- border-radius: 20px;
3269
- background: #ffffff;
3270
- color: var(--blinq-text);
3271
- box-shadow: 0 18px 40px rgba(17, 17, 17, 0.12);
3272
- backdrop-filter: blur(18px);
3273
- -webkit-backdrop-filter: blur(18px);
3274
- transition:
3275
- transform 180ms ease,
3276
- box-shadow 180ms ease,
3277
- border-color 180ms ease;
3766
+ .blinq-shell {
3767
+ width: 520px;
3278
3768
  }
3279
3769
 
3280
- .blinq-launcher:hover {
3281
- transform: translateY(-2px);
3282
- border-color: rgba(17, 17, 17, 0.16);
3283
- box-shadow: 0 22px 46px rgba(17, 17, 17, 0.16);
3284
- }
3285
-
3286
- .blinq-launcher-badge {
3287
- display: grid;
3288
- place-items: center;
3289
- width: 34px;
3290
- height: 34px;
3291
- border-radius: 12px;
3292
- background: #111111;
3293
- color: #ffffff;
3294
- transition:
3295
- transform 180ms ease,
3296
- box-shadow 180ms ease;
3770
+ .blinq-panel {
3771
+ position: relative;
3772
+ width: 100%;
3773
+ max-width: 432px;
3774
+ overflow: hidden;
3775
+ border-radius: var(--blinq-radius-panel);
3776
+ border: 1px solid var(--blinq-glass-stroke);
3777
+ background: var(--blinq-glass-fill);
3778
+ box-shadow: var(--blinq-shadow);
3779
+ backdrop-filter: var(--blinq-blur);
3780
+ -webkit-backdrop-filter: var(--blinq-blur);
3297
3781
  }
3298
3782
 
3299
- .blinq-launcher:hover .blinq-launcher-badge {
3300
- transform: scale(1.06);
3301
- box-shadow: 0 10px 24px rgba(17, 17, 17, 0.22);
3783
+ .blinq-panel::before,
3784
+ .blinq-launcher::before {
3785
+ content: "";
3786
+ position: absolute;
3787
+ inset: 0;
3788
+ pointer-events: none;
3789
+ border-radius: inherit;
3790
+ box-shadow: var(--blinq-inner-highlight);
3302
3791
  }
3303
3792
 
3304
- .blinq-launcher-icon-only {
3305
- width: 58px;
3306
- min-width: 58px;
3307
- padding: 0;
3308
- border-radius: 18px;
3793
+ .blinq-launcher::after {
3794
+ content: "";
3795
+ position: absolute;
3796
+ inset: 1px;
3797
+ pointer-events: none;
3798
+ border-radius: inherit;
3799
+ background:
3800
+ radial-gradient(circle at 28% 22%, rgba(255, 255, 255, 0.82), transparent 32%),
3801
+ linear-gradient(135deg, rgba(255, 255, 255, 0.46), transparent 55%);
3802
+ opacity: 0.88;
3803
+ transition:
3804
+ opacity 180ms ease;
3309
3805
  }
3310
3806
 
3311
- .blinq-launcher-agent {
3312
- overflow: visible;
3807
+ .blinq-panel::after {
3808
+ content: "";
3809
+ position: absolute;
3810
+ inset: 0;
3811
+ pointer-events: none;
3812
+ border-radius: inherit;
3813
+ background:
3814
+ radial-gradient(circle at top left, rgba(255, 255, 255, 0.72), transparent 34%),
3815
+ radial-gradient(circle at bottom center, rgba(255, 255, 255, 0.26), transparent 38%);
3816
+ opacity: 0.95;
3313
3817
  }
3314
3818
 
3315
- .blinq-agent-orbit {
3316
- stroke: rgba(255, 255, 255, 0.42);
3317
- stroke-width: 1.3;
3318
- stroke-dasharray: 2.6 2.6;
3319
- transform-origin: center;
3320
- transition: opacity 180ms ease;
3819
+ .blinq-header,
3820
+ .blinq-thread,
3821
+ .blinq-composer {
3822
+ position: relative;
3823
+ z-index: 1;
3321
3824
  }
3322
3825
 
3323
- .blinq-agent-spark,
3324
- .blinq-agent-head,
3325
- .blinq-agent-antenna,
3326
- .blinq-agent-antenna-dot,
3327
- .blinq-agent-neck {
3328
- transform-origin: center;
3826
+ .blinq-header {
3827
+ display: flex;
3828
+ flex-direction: column;
3829
+ gap: 12px;
3830
+ padding: 18px 18px 10px;
3329
3831
  }
3330
3832
 
3331
- .blinq-launcher:hover .blinq-agent-orbit {
3332
- animation: blinq-agent-spin 2.2s linear infinite;
3833
+ .blinq-header-row {
3834
+ display: flex;
3835
+ align-items: flex-start;
3836
+ justify-content: space-between;
3837
+ gap: 12px;
3333
3838
  }
3334
3839
 
3335
- .blinq-launcher:hover .blinq-agent-spark {
3336
- animation: blinq-agent-spark 1.1s ease-in-out infinite;
3337
- }
3338
-
3339
- .blinq-launcher:hover .blinq-agent-head,
3340
- .blinq-launcher:hover .blinq-agent-neck,
3341
- .blinq-launcher:hover .blinq-agent-antenna,
3342
- .blinq-launcher:hover .blinq-agent-antenna-dot {
3343
- animation: blinq-agent-bob 1.35s ease-in-out infinite;
3344
- }
3345
-
3346
- .blinq-launcher-copy {
3840
+ .blinq-header-copy {
3347
3841
  display: flex;
3348
3842
  flex-direction: column;
3349
- align-items: flex-start;
3350
- line-height: 1.1;
3351
- }
3352
-
3353
- .blinq-launcher-label {
3354
- font-size: 11px;
3355
- font-weight: 700;
3356
- letter-spacing: 0.08em;
3357
- text-transform: uppercase;
3358
- color: var(--blinq-text-muted);
3359
- }
3360
-
3361
- .blinq-launcher-title {
3362
- margin-top: 3px;
3363
- font-size: 14px;
3364
- font-weight: 600;
3365
- color: var(--blinq-text);
3366
- }
3367
-
3368
- .blinq-panel {
3369
- width: 100%;
3370
- max-width: 420px;
3371
- border: 1px solid var(--blinq-border);
3372
- border-radius: 28px;
3373
- overflow: hidden;
3374
- background: #ffffff;
3375
- box-shadow: var(--blinq-shadow);
3376
- backdrop-filter: blur(24px);
3377
- -webkit-backdrop-filter: blur(24px);
3378
- }
3379
-
3380
- .blinq-header {
3381
- padding: 16px;
3382
- border-bottom: 1px solid var(--blinq-border);
3383
- background: #ffffff;
3384
- }
3385
-
3386
- .blinq-status-line {
3387
- margin-top: 10px;
3388
- font-size: 12px;
3389
- line-height: 1.45;
3390
- color: var(--blinq-text-muted);
3391
- }
3392
-
3393
- .blinq-header-row {
3394
- display: flex;
3395
- align-items: center;
3396
- justify-content: space-between;
3397
- gap: 12px;
3398
- }
3399
-
3400
- .blinq-header-copy {
3843
+ gap: 8px;
3401
3844
  min-width: 0;
3402
3845
  flex: 1;
3403
3846
  }
3404
3847
 
3405
- .blinq-header-badges {
3406
- display: flex;
3407
- flex-wrap: wrap;
3408
- gap: 8px;
3409
- }
3410
-
3411
- .blinq-heading-row {
3412
- margin-top: 14px;
3413
- display: flex;
3414
- align-items: flex-start;
3415
- justify-content: space-between;
3416
- gap: 12px;
3417
- }
3418
-
3419
3848
  .blinq-heading {
3420
- font-size: 16px;
3421
- font-weight: 700;
3422
- letter-spacing: -0.02em;
3849
+ font-size: 17px;
3850
+ line-height: 1.15;
3851
+ font-weight: 600;
3852
+ letter-spacing: -0.03em;
3423
3853
  color: var(--blinq-text);
3424
3854
  }
3425
3855
 
3426
- .blinq-subheading {
3427
- margin-top: 6px;
3428
- max-width: 320px;
3429
- font-size: 13px;
3430
- line-height: 1.45;
3431
- color: var(--blinq-text-muted);
3432
- }
3433
-
3434
- .blinq-statusbar {
3435
- margin-top: 14px;
3436
- display: flex;
3437
- align-items: center;
3438
- justify-content: space-between;
3439
- gap: 10px;
3440
- flex-wrap: wrap;
3441
- }
3442
-
3443
- .blinq-status {
3856
+ .blinq-status-line {
3444
3857
  display: inline-flex;
3445
3858
  align-items: center;
3446
- min-height: 34px;
3859
+ gap: 8px;
3860
+ max-width: fit-content;
3861
+ min-height: 32px;
3447
3862
  padding: 0 12px;
3448
- border-radius: 999px;
3449
- border: 1px solid var(--blinq-border);
3450
- background: #f8f8f8;
3863
+ border-radius: var(--blinq-radius-pill);
3864
+ border: 1px solid var(--blinq-glass-stroke-soft);
3865
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.72), rgba(242, 244, 248, 0.46));
3451
3866
  color: var(--blinq-text-soft);
3452
3867
  font-size: 12px;
3453
- line-height: 1.45;
3868
+ line-height: 1.35;
3869
+ box-shadow: var(--blinq-shadow-soft);
3870
+ backdrop-filter: blur(22px) saturate(170%);
3871
+ -webkit-backdrop-filter: blur(22px) saturate(170%);
3454
3872
  }
3455
3873
 
3456
- .blinq-runtime-chip {
3457
- display: inline-flex;
3458
- align-items: center;
3459
- min-height: 34px;
3460
- padding: 0 12px;
3874
+ .blinq-status-line::before {
3875
+ content: "";
3876
+ width: 7px;
3877
+ height: 7px;
3461
3878
  border-radius: 999px;
3462
- background: #111111;
3463
- border: 1px solid #111111;
3464
- color: #ffffff;
3465
- font-size: 12px;
3466
- font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
3467
- }
3468
-
3469
- .blinq-workspace {
3470
- display: grid;
3471
- grid-template-columns: 112px minmax(0, 1fr);
3472
- min-height: 430px;
3473
- }
3474
-
3475
- .blinq-sidebar {
3476
- display: flex;
3477
- flex-direction: column;
3478
- gap: 14px;
3479
- padding: 16px;
3480
- border-right: 1px solid var(--blinq-border);
3481
- background: #fafafa;
3482
- }
3483
-
3484
- .blinq-sidebar-group {
3485
- display: flex;
3486
- flex-direction: column;
3487
- gap: 8px;
3488
- }
3489
-
3490
- .blinq-tab-trigger {
3491
- display: flex;
3492
- align-items: center;
3493
- gap: 10px;
3494
- width: 100%;
3495
- min-height: 56px;
3496
- padding: 10px;
3497
- border: 1px solid transparent;
3498
- border-radius: 18px;
3499
- background: transparent;
3500
- color: var(--blinq-text-soft);
3501
- cursor: pointer;
3502
- transition:
3503
- background 120ms ease,
3504
- border-color 120ms ease,
3505
- color 120ms ease,
3506
- transform 120ms ease;
3507
- }
3508
-
3509
- .blinq-tab-trigger:hover {
3510
- background: rgba(255,255,255,0.9);
3511
- border-color: var(--blinq-border);
3512
- }
3513
-
3514
- .blinq-tab-trigger-active {
3515
- background: #ffffff;
3516
- border-color: rgba(17, 17, 17, 0.16);
3517
- box-shadow: 0 10px 24px rgba(17, 17, 17, 0.08);
3518
- color: var(--blinq-text);
3519
- }
3520
-
3521
- .blinq-tab-icon {
3522
- display: grid;
3523
- place-items: center;
3524
- width: 32px;
3525
- height: 32px;
3526
- border-radius: 12px;
3527
- background: rgba(15, 23, 42, 0.04);
3528
- color: currentColor;
3529
- flex: 0 0 auto;
3530
- }
3531
-
3532
- .blinq-tab-copy {
3533
- display: flex;
3534
- flex-direction: column;
3535
- min-width: 0;
3536
- align-items: flex-start;
3537
- text-align: left;
3538
- }
3539
-
3540
- .blinq-tab-label {
3541
- font-size: 13px;
3542
- font-weight: 600;
3543
- }
3544
-
3545
- .blinq-tab-caption {
3546
- margin-top: 2px;
3547
- font-size: 11px;
3548
- color: var(--blinq-text-muted);
3879
+ background: rgba(17, 17, 17, 0.74);
3880
+ box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.34);
3881
+ flex: none;
3549
3882
  }
3550
3883
 
3551
- .blinq-tab-count {
3552
- margin-left: auto;
3553
- min-width: 22px;
3554
- height: 22px;
3555
- padding: 0 6px;
3884
+ .blinq-launcher {
3885
+ position: relative;
3556
3886
  display: inline-flex;
3557
3887
  align-items: center;
3558
3888
  justify-content: center;
3889
+ width: 76px;
3890
+ min-width: 76px;
3891
+ height: 76px;
3892
+ padding: 0;
3559
3893
  border-radius: 999px;
3560
- background: rgba(15, 23, 42, 0.06);
3561
- color: var(--blinq-text-soft);
3562
- font-size: 11px;
3563
- font-weight: 700;
3564
- }
3565
-
3566
- .blinq-separator {
3567
- height: 1px;
3568
- background: var(--blinq-border);
3569
- }
3570
-
3571
- .blinq-sidebar-card {
3572
- gap: 12px;
3573
- border-radius: 18px;
3574
- background: rgba(255,255,255,0.94);
3575
- box-shadow: 0 12px 30px rgba(15, 23, 42, 0.06);
3576
- }
3577
-
3578
- .blinq-sidebar-card-header {
3579
- padding: 14px 14px 0;
3580
- }
3581
-
3582
- .blinq-sidebar-card-content {
3583
- padding: 0 14px 14px;
3584
- display: flex;
3585
- flex-direction: column;
3586
- gap: 10px;
3587
- }
3588
-
3589
- .blinq-stat-line {
3590
- display: flex;
3591
- align-items: center;
3592
- justify-content: space-between;
3593
- gap: 8px;
3594
- font-size: 12px;
3595
- color: var(--blinq-text-muted);
3596
- }
3597
-
3598
- .blinq-stat-line strong {
3894
+ border: 1px solid var(--blinq-glass-stroke);
3895
+ background: var(--blinq-glass-fill-strong);
3896
+ box-shadow: var(--blinq-shadow-soft);
3897
+ backdrop-filter: blur(26px) saturate(175%);
3898
+ -webkit-backdrop-filter: blur(26px) saturate(175%);
3599
3899
  color: var(--blinq-text);
3600
- font-size: 12px;
3601
- }
3602
-
3603
- .blinq-main {
3604
- display: flex;
3605
- flex-direction: column;
3606
- min-width: 0;
3607
- background: transparent;
3900
+ isolation: isolate;
3608
3901
  }
3609
3902
 
3610
- .blinq-main-toolbar {
3611
- padding: 16px 18px 12px;
3612
- display: flex;
3613
- flex-direction: column;
3614
- gap: 10px;
3903
+ .blinq-launcher:hover {
3904
+ border-color: var(--blinq-glass-stroke);
3905
+ box-shadow: var(--blinq-shadow-soft);
3615
3906
  }
3616
3907
 
3617
- .blinq-toolbar-label {
3618
- font-size: 11px;
3619
- font-weight: 700;
3620
- letter-spacing: 0.08em;
3621
- text-transform: uppercase;
3622
- color: var(--blinq-text-muted);
3908
+ .blinq-launcher-icon-only {
3909
+ border-radius: 999px;
3623
3910
  }
3624
3911
 
3625
- .blinq-prompt-row {
3626
- display: flex;
3627
- gap: 8px;
3628
- flex-wrap: wrap;
3912
+ .blinq-launcher-icon {
3913
+ position: relative;
3914
+ z-index: 1;
3915
+ width: 30px;
3916
+ height: 30px;
3917
+ color: rgba(17, 17, 17, 0.96);
3918
+ opacity: 1;
3919
+ filter:
3920
+ drop-shadow(0 1px 0 rgba(255, 255, 255, 0.66))
3921
+ drop-shadow(0 2px 6px rgba(17, 17, 17, 0.08));
3629
3922
  }
3630
3923
 
3631
- .blinq-prompt-chip {
3632
- padding: 8px 12px;
3633
- border-radius: 999px;
3634
- border: 1px solid var(--blinq-border);
3635
- background: rgba(255,255,255,0.95);
3636
- color: var(--blinq-text-soft);
3637
- font-size: 12px;
3638
- font-weight: 600;
3639
- cursor: pointer;
3640
- transition:
3641
- background 120ms ease,
3642
- border-color 120ms ease,
3643
- color 120ms ease,
3644
- transform 120ms ease;
3924
+ .blinq-thread {
3925
+ min-height: 0;
3645
3926
  }
3646
3927
 
3647
- .blinq-prompt-chip:hover {
3648
- border-color: rgba(17, 17, 17, 0.16);
3649
- color: #111111;
3650
- background: #f7f7f7;
3928
+ .blinq-thread-viewport {
3929
+ width: 100%;
3651
3930
  }
3652
3931
 
3653
3932
  .blinq-scroll {
@@ -3655,65 +3934,69 @@ var EMBED_WIDGET_STYLES = `
3655
3934
  flex-direction: column;
3656
3935
  gap: 12px;
3657
3936
  min-height: 0;
3658
- height: 100%;
3659
- max-height: 420px;
3660
- padding: 16px;
3937
+ max-height: 432px;
3938
+ padding: 6px 18px 14px;
3661
3939
  overflow-y: auto;
3662
3940
  }
3663
3941
 
3664
- .blinq-thread {
3665
- min-height: 0;
3666
- }
3667
-
3668
- .blinq-thread-viewport {
3669
- width: 100%;
3670
- }
3671
-
3672
- .blinq-scroll-actions,
3673
- .blinq-scroll-context {
3674
- padding-top: 18px;
3675
- }
3676
-
3677
3942
  .blinq-scroll::-webkit-scrollbar {
3678
3943
  width: 8px;
3679
3944
  }
3680
3945
 
3681
3946
  .blinq-scroll::-webkit-scrollbar-thumb {
3682
- background: rgba(148, 163, 184, 0.25);
3947
+ background: rgba(144, 151, 162, 0.22);
3683
3948
  border-radius: 999px;
3684
3949
  }
3685
3950
 
3686
3951
  .blinq-message {
3952
+ position: relative;
3687
3953
  max-width: 88%;
3688
- border-radius: 20px;
3689
- padding: 13px 14px;
3954
+ padding: 14px 16px;
3955
+ border-radius: var(--blinq-radius-bubble);
3956
+ border: 1px solid var(--blinq-glass-stroke-soft);
3957
+ background: var(--blinq-glass-fill-strong);
3958
+ color: var(--blinq-text);
3690
3959
  font-size: 14px;
3691
3960
  line-height: 1.55;
3692
3961
  white-space: pre-wrap;
3693
- border: 1px solid var(--blinq-border);
3694
- box-shadow: 0 12px 30px rgba(15, 23, 42, 0.05);
3962
+ box-shadow: var(--blinq-shadow-soft);
3963
+ backdrop-filter: blur(24px) saturate(170%);
3964
+ -webkit-backdrop-filter: blur(24px) saturate(170%);
3965
+ }
3966
+
3967
+ .blinq-message::before {
3968
+ content: "";
3969
+ position: absolute;
3970
+ inset: 0;
3971
+ border-radius: inherit;
3972
+ pointer-events: none;
3973
+ box-shadow: var(--blinq-inner-highlight);
3695
3974
  }
3696
3975
 
3697
3976
  .blinq-message[data-role="assistant"] {
3698
3977
  align-self: flex-start;
3699
- background: rgba(255,255,255,0.98);
3700
- color: var(--blinq-text);
3978
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.86), rgba(241, 244, 249, 0.58));
3979
+ }
3980
+
3981
+ .blinq-message[data-role="user"] {
3982
+ align-self: flex-end;
3983
+ background: linear-gradient(180deg, rgba(249, 250, 252, 0.94), rgba(227, 232, 238, 0.66));
3984
+ border-color: rgba(255, 255, 255, 0.74);
3701
3985
  }
3702
3986
 
3703
3987
  .blinq-message[data-kind="artifact"] {
3704
- max-width: 100%;
3705
3988
  width: 100%;
3989
+ max-width: 100%;
3706
3990
  padding: 0;
3707
3991
  border: 0;
3708
3992
  background: transparent;
3709
3993
  box-shadow: none;
3994
+ backdrop-filter: none;
3995
+ -webkit-backdrop-filter: none;
3710
3996
  }
3711
3997
 
3712
- .blinq-message[data-role="user"] {
3713
- align-self: flex-end;
3714
- background: var(--blinq-user-bubble);
3715
- border-color: rgba(17, 17, 17, 0.22);
3716
- color: var(--blinq-user-text);
3998
+ .blinq-message[data-kind="artifact"]::before {
3999
+ display: none;
3717
4000
  }
3718
4001
 
3719
4002
  .blinq-message-copy {
@@ -3721,28 +4004,21 @@ var EMBED_WIDGET_STYLES = `
3721
4004
  }
3722
4005
 
3723
4006
  .blinq-message-copy-reveal {
3724
- animation: blinq-blur-in 220ms cubic-bezier(0.16, 1, 0.3, 1);
3725
- will-change: opacity, transform, filter;
4007
+ animation: blinq-copy-reveal 240ms cubic-bezier(0.16, 1, 0.3, 1);
4008
+ will-change: opacity, transform;
3726
4009
  }
3727
4010
 
3728
4011
  .blinq-thinking-card {
3729
- align-self: flex-start;
3730
- background: rgba(255,255,255,0.98);
3731
- color: var(--blinq-text);
4012
+ max-width: fit-content;
4013
+ padding-right: 18px;
3732
4014
  }
3733
4015
 
3734
4016
  .blinq-thinking {
3735
4017
  display: inline-flex;
3736
4018
  align-items: center;
3737
4019
  gap: 10px;
3738
- min-height: 20px;
4020
+ color: var(--blinq-text-soft);
3739
4021
  font-size: 13px;
3740
- color: var(--blinq-text-muted);
3741
- opacity: 1;
3742
- transform: translateY(0);
3743
- transition:
3744
- opacity 180ms ease,
3745
- transform 180ms ease;
3746
4022
  }
3747
4023
 
3748
4024
  .blinq-thinking-dots {
@@ -3755,45 +4031,49 @@ var EMBED_WIDGET_STYLES = `
3755
4031
  width: 6px;
3756
4032
  height: 6px;
3757
4033
  border-radius: 999px;
3758
- background: #111111;
3759
- animation: blinq-thinking-pulse 1.1s ease-in-out infinite;
4034
+ background: rgba(17, 17, 17, 0.74);
4035
+ animation: blinq-thinking-pulse 1.2s ease-in-out infinite;
3760
4036
  }
3761
4037
 
3762
4038
  .blinq-thinking-dots > span:nth-child(2) {
3763
- animation-delay: 120ms;
4039
+ animation-delay: 100ms;
3764
4040
  }
3765
4041
 
3766
4042
  .blinq-thinking-dots > span:nth-child(3) {
3767
- animation-delay: 240ms;
4043
+ animation-delay: 200ms;
3768
4044
  }
3769
4045
 
3770
4046
  .blinq-card {
3771
4047
  display: flex;
3772
4048
  flex-direction: column;
3773
- gap: 14px;
3774
- border: 1px solid var(--blinq-border);
3775
- border-radius: 20px;
3776
- background: var(--blinq-surface);
4049
+ gap: 12px;
4050
+ border-radius: var(--blinq-radius-card);
4051
+ border: 1px solid var(--blinq-glass-stroke-soft);
4052
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.78), rgba(240, 243, 248, 0.52));
3777
4053
  color: var(--blinq-text);
3778
- box-shadow: 0 16px 36px rgba(15, 23, 42, 0.06);
4054
+ box-shadow: var(--blinq-shadow-soft);
4055
+ backdrop-filter: blur(26px) saturate(170%);
4056
+ -webkit-backdrop-filter: blur(26px) saturate(170%);
3779
4057
  }
3780
4058
 
3781
4059
  .blinq-card-header {
3782
4060
  display: flex;
3783
4061
  flex-direction: column;
3784
- gap: 7px;
4062
+ gap: 8px;
3785
4063
  padding: 16px 16px 0;
3786
4064
  }
3787
4065
 
3788
4066
  .blinq-card-title {
3789
4067
  font-size: 15px;
3790
- font-weight: 700;
4068
+ line-height: 1.2;
4069
+ font-weight: 600;
4070
+ letter-spacing: -0.02em;
3791
4071
  color: var(--blinq-text);
3792
4072
  }
3793
4073
 
3794
4074
  .blinq-card-description {
3795
4075
  font-size: 13px;
3796
- line-height: 1.5;
4076
+ line-height: 1.45;
3797
4077
  color: var(--blinq-text-muted);
3798
4078
  }
3799
4079
 
@@ -3801,37 +4081,84 @@ var EMBED_WIDGET_STYLES = `
3801
4081
  padding: 0 16px 16px;
3802
4082
  }
3803
4083
 
3804
- .blinq-action-card {
4084
+ .blinq-action-card,
4085
+ .blinq-plan-card,
4086
+ .blinq-guide-card {
3805
4087
  align-self: stretch;
3806
- gap: 0;
3807
4088
  }
3808
4089
 
3809
- .blinq-plan-card {
3810
- border-color: var(--blinq-border-strong);
4090
+ .blinq-guide-content {
4091
+ display: flex;
4092
+ flex-direction: column;
4093
+ gap: 12px;
3811
4094
  }
3812
4095
 
3813
- .blinq-plan-step {
4096
+ .blinq-guide-step-shell {
3814
4097
  display: flex;
3815
- align-items: flex-start;
3816
- gap: 10px;
3817
- padding: 10px 0;
3818
- border-top: 1px solid rgba(17, 17, 17, 0.06);
4098
+ flex-direction: column;
4099
+ gap: 8px;
4100
+ padding: 14px;
4101
+ border-radius: 22px;
4102
+ border: 1px solid rgba(255, 255, 255, 0.64);
4103
+ background:
4104
+ radial-gradient(circle at top left, rgba(255, 255, 255, 0.8), transparent 42%),
4105
+ linear-gradient(180deg, rgba(255, 255, 255, 0.82), rgba(242, 245, 249, 0.56));
4106
+ box-shadow:
4107
+ inset 0 1px 0 rgba(255, 255, 255, 0.94),
4108
+ 0 10px 22px rgba(183, 191, 201, 0.13);
4109
+ }
4110
+
4111
+ .blinq-guide-step-meta {
4112
+ font-size: 11px;
4113
+ font-weight: 600;
4114
+ letter-spacing: 0.08em;
4115
+ text-transform: uppercase;
4116
+ color: var(--blinq-text-soft);
3819
4117
  }
3820
4118
 
3821
- .blinq-plan-step:first-child {
3822
- border-top: 0;
3823
- padding-top: 0;
3824
- }
4119
+ .blinq-guide-step-title {
4120
+ font-size: 14px;
4121
+ line-height: 1.35;
4122
+ font-weight: 600;
4123
+ color: var(--blinq-text);
4124
+ }
4125
+
4126
+ .blinq-guide-step-copy {
4127
+ font-size: 13px;
4128
+ line-height: 1.5;
4129
+ color: var(--blinq-text-muted);
4130
+ }
4131
+
4132
+ .blinq-plan-step {
4133
+ display: flex;
4134
+ align-items: flex-start;
4135
+ gap: 12px;
4136
+ padding: 12px 13px;
4137
+ margin-top: 10px;
4138
+ border-radius: 24px;
4139
+ border: 1px solid rgba(255, 255, 255, 0.62);
4140
+ background:
4141
+ radial-gradient(circle at top left, rgba(255, 255, 255, 0.72), transparent 38%),
4142
+ linear-gradient(180deg, rgba(255, 255, 255, 0.76), rgba(238, 242, 247, 0.54));
4143
+ box-shadow:
4144
+ inset 0 1px 0 rgba(255, 255, 255, 0.94),
4145
+ 0 8px 20px rgba(189, 196, 206, 0.12);
4146
+ }
4147
+
4148
+ .blinq-plan-step:first-child {
4149
+ margin-top: 0;
4150
+ }
3825
4151
 
3826
4152
  .blinq-plan-step-index {
3827
4153
  display: inline-flex;
3828
4154
  align-items: center;
3829
4155
  justify-content: center;
3830
- width: 22px;
3831
- height: 22px;
4156
+ width: 26px;
4157
+ height: 26px;
3832
4158
  border-radius: 999px;
3833
- background: #111111;
3834
- color: #ffffff;
4159
+ border: 1px solid rgba(255, 255, 255, 0.7);
4160
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.86), rgba(240, 243, 247, 0.62));
4161
+ color: rgba(17, 17, 17, 0.82);
3835
4162
  font-size: 11px;
3836
4163
  font-weight: 700;
3837
4164
  flex: none;
@@ -3841,9 +4168,62 @@ var EMBED_WIDGET_STYLES = `
3841
4168
  min-width: 0;
3842
4169
  display: flex;
3843
4170
  flex-direction: column;
3844
- gap: 3px;
3845
- font-size: 13px;
4171
+ gap: 6px;
3846
4172
  color: var(--blinq-text);
4173
+ font-size: 13px;
4174
+ flex: 1;
4175
+ }
4176
+
4177
+ .blinq-plan-header {
4178
+ display: flex;
4179
+ align-items: flex-start;
4180
+ justify-content: space-between;
4181
+ gap: 12px;
4182
+ }
4183
+
4184
+ .blinq-plan-content {
4185
+ display: flex;
4186
+ flex-direction: column;
4187
+ gap: 12px;
4188
+ }
4189
+
4190
+ .blinq-plan-steps {
4191
+ display: flex;
4192
+ flex-direction: column;
4193
+ gap: 0;
4194
+ }
4195
+
4196
+ .blinq-plan-step-title-row {
4197
+ display: flex;
4198
+ align-items: flex-start;
4199
+ justify-content: space-between;
4200
+ gap: 10px;
4201
+ }
4202
+
4203
+ .blinq-plan-step-title {
4204
+ min-width: 0;
4205
+ font-size: 13px;
4206
+ line-height: 1.4;
4207
+ font-weight: 600;
4208
+ letter-spacing: -0.01em;
4209
+ }
4210
+
4211
+ .blinq-plan-step-status-pill {
4212
+ display: inline-flex;
4213
+ align-items: center;
4214
+ justify-content: center;
4215
+ min-height: 24px;
4216
+ padding: 0 10px;
4217
+ border-radius: 999px;
4218
+ border: 1px solid rgba(255, 255, 255, 0.58);
4219
+ background: rgba(255, 255, 255, 0.58);
4220
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.88);
4221
+ color: var(--blinq-text-soft);
4222
+ font-size: 11px;
4223
+ font-weight: 600;
4224
+ line-height: 1;
4225
+ letter-spacing: 0.01em;
4226
+ white-space: nowrap;
3847
4227
  }
3848
4228
 
3849
4229
  .blinq-plan-step-meta {
@@ -3851,17 +4231,36 @@ var EMBED_WIDGET_STYLES = `
3851
4231
  color: var(--blinq-text-muted);
3852
4232
  }
3853
4233
 
4234
+ .blinq-plan-step[data-current="true"] {
4235
+ background:
4236
+ radial-gradient(circle at top left, rgba(255, 255, 255, 0.82), transparent 40%),
4237
+ linear-gradient(180deg, rgba(255, 255, 255, 0.88), rgba(243, 246, 250, 0.64));
4238
+ border-color: rgba(255, 255, 255, 0.74);
4239
+ box-shadow:
4240
+ inset 0 1px 0 rgba(255, 255, 255, 0.96),
4241
+ 0 12px 26px rgba(183, 191, 201, 0.15);
4242
+ }
4243
+
3854
4244
  .blinq-plan-step[data-current="true"] .blinq-plan-step-index {
3855
- box-shadow: 0 0 0 4px rgba(17, 17, 17, 0.08);
4245
+ box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.48);
4246
+ }
4247
+
4248
+ .blinq-plan-step[data-current="true"] .blinq-plan-step-status-pill {
4249
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.82), rgba(240, 243, 247, 0.66));
4250
+ color: var(--blinq-text);
3856
4251
  }
3857
4252
 
3858
4253
  .blinq-plan-step[data-status="completed"] .blinq-plan-step-index {
3859
- background: #111111;
4254
+ background: rgba(227, 232, 237, 0.88);
3860
4255
  }
3861
4256
 
3862
- .blinq-plan-step[data-status="failed"] .blinq-plan-step-index,
3863
- .blinq-plan-step[data-status="cancelled"] .blinq-plan-step-index {
3864
- background: #525252;
4257
+ .blinq-plan-step[data-status="completed"] .blinq-plan-step-status-pill {
4258
+ background: rgba(244, 246, 249, 0.78);
4259
+ }
4260
+
4261
+ .blinq-plan-step[data-status="failed"],
4262
+ .blinq-plan-step[data-status="cancelled"] {
4263
+ opacity: 0.72;
3865
4264
  }
3866
4265
 
3867
4266
  .blinq-action-meta-row {
@@ -3877,11 +4276,18 @@ var EMBED_WIDGET_STYLES = `
3877
4276
  }
3878
4277
 
3879
4278
  .blinq-action-details > summary {
3880
- cursor: pointer;
4279
+ display: inline-flex;
4280
+ align-items: center;
4281
+ min-height: 34px;
4282
+ padding: 0 12px;
4283
+ border-radius: 999px;
4284
+ border: 1px solid rgba(255, 255, 255, 0.56);
4285
+ background: rgba(255, 255, 255, 0.46);
4286
+ color: var(--blinq-text-soft);
3881
4287
  font-size: 12px;
3882
4288
  font-weight: 600;
3883
- color: #111111;
3884
4289
  list-style: none;
4290
+ cursor: pointer;
3885
4291
  }
3886
4292
 
3887
4293
  .blinq-action-details > summary::-webkit-details-marker {
@@ -3890,29 +4296,26 @@ var EMBED_WIDGET_STYLES = `
3890
4296
 
3891
4297
  .blinq-code {
3892
4298
  margin-top: 10px;
3893
- padding: 10px 12px;
3894
- border-radius: 14px;
3895
- background: var(--blinq-surface-soft);
3896
- border: 1px solid var(--blinq-border);
4299
+ padding: 12px 14px;
4300
+ border-radius: 20px;
4301
+ border: 1px solid rgba(255, 255, 255, 0.56);
4302
+ background: rgba(255, 255, 255, 0.52);
4303
+ color: var(--blinq-text-soft);
3897
4304
  font-size: 12px;
3898
- line-height: 1.45;
4305
+ line-height: 1.5;
3899
4306
  white-space: pre-wrap;
3900
- color: var(--blinq-text-soft);
3901
4307
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
3902
4308
  }
3903
4309
 
3904
- .blinq-code-compact {
3905
- margin-top: 12px;
3906
- }
3907
-
3908
4310
  .blinq-action-state {
3909
4311
  margin-top: 12px;
3910
4312
  font-size: 12px;
4313
+ line-height: 1.4;
3911
4314
  color: var(--blinq-text-muted);
3912
4315
  }
3913
4316
 
3914
4317
  .blinq-action-state[data-state="approved"] {
3915
- color: #111111;
4318
+ color: var(--blinq-text-soft);
3916
4319
  }
3917
4320
 
3918
4321
  .blinq-action-state[data-state="declined"] {
@@ -3929,97 +4332,147 @@ var EMBED_WIDGET_STYLES = `
3929
4332
  flex: 1;
3930
4333
  }
3931
4334
 
3932
- .blinq-context-grid {
3933
- display: grid;
3934
- grid-template-columns: repeat(2, minmax(0, 1fr));
3935
- gap: 12px;
3936
- }
3937
-
3938
- .blinq-context-card {
3939
- min-height: 150px;
3940
- }
3941
-
3942
- .blinq-context-card-wide {
3943
- grid-column: 1 / -1;
3944
- }
3945
-
3946
- .blinq-context-copy {
3947
- font-size: 13px;
3948
- line-height: 1.5;
3949
- color: var(--blinq-text-soft);
3950
- }
3951
-
3952
- .blinq-empty-card {
3953
- min-height: 180px;
3954
- justify-content: center;
3955
- }
3956
-
3957
4335
  .blinq-badge-pill {
3958
4336
  display: inline-flex;
3959
4337
  align-items: center;
3960
4338
  justify-content: center;
3961
- min-height: 28px;
3962
- padding: 0 10px;
4339
+ min-height: 30px;
4340
+ padding: 0 12px;
3963
4341
  border-radius: 999px;
4342
+ border: 1px solid rgba(255, 255, 255, 0.54);
4343
+ background: rgba(255, 255, 255, 0.46);
3964
4344
  font-size: 11px;
3965
- font-weight: 700;
3966
- letter-spacing: 0.06em;
3967
- text-transform: uppercase;
4345
+ font-weight: 600;
4346
+ letter-spacing: 0.02em;
4347
+ color: var(--blinq-text-soft);
4348
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.82);
3968
4349
  }
3969
4350
 
3970
4351
  .blinq-badge-pill-default {
3971
- background: rgba(15, 23, 42, 0.05);
3972
- color: var(--blinq-text-soft);
4352
+ background: rgba(255, 255, 255, 0.5);
3973
4353
  }
3974
4354
 
3975
4355
  .blinq-badge-pill-outline {
3976
- border: 1px solid var(--blinq-border);
4356
+ background: rgba(247, 248, 250, 0.34);
3977
4357
  color: var(--blinq-text-muted);
3978
- background: rgba(255,255,255,0.84);
3979
4358
  }
3980
4359
 
3981
4360
  .blinq-badge-pill-soft {
3982
- background: #f5f5f5;
3983
- color: #111111;
4361
+ background: rgba(255, 255, 255, 0.68);
4362
+ color: var(--blinq-text-soft);
3984
4363
  }
3985
4364
 
3986
4365
  .blinq-badge-pill-accent {
3987
- background: #111111;
3988
- color: #ffffff;
4366
+ background: rgba(243, 245, 249, 0.84);
4367
+ color: var(--blinq-text);
3989
4368
  }
3990
4369
 
3991
4370
  .blinq-composer {
3992
- display: flex;
3993
- flex-direction: column;
3994
- gap: 10px;
3995
- padding: 0 16px 16px;
3996
- border-top: 1px solid var(--blinq-border);
3997
- background: #ffffff;
4371
+ padding: 8px 18px 18px;
3998
4372
  }
3999
4373
 
4000
- .blinq-composer-copy {
4374
+ .blinq-composer-controls {
4001
4375
  display: flex;
4002
- flex-direction: column;
4003
- gap: 4px;
4004
4376
  }
4005
4377
 
4006
- .blinq-composer-title {
4007
- font-size: 12px;
4008
- font-weight: 700;
4009
- letter-spacing: 0.08em;
4010
- text-transform: uppercase;
4011
- color: var(--blinq-text-muted);
4378
+ .blinq-input-shell {
4379
+ position: relative;
4380
+ width: 100%;
4012
4381
  }
4013
4382
 
4014
- .blinq-composer-hint {
4383
+ .blinq-input,
4384
+ .blinq-recording-input {
4385
+ width: 100%;
4386
+ min-width: 0;
4387
+ height: 58px;
4388
+ padding: 0 54px 0 54px;
4389
+ border-radius: 999px;
4390
+ border: 1px solid var(--blinq-glass-stroke);
4391
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.82), rgba(239, 242, 247, 0.54));
4392
+ color: var(--blinq-text);
4393
+ box-shadow:
4394
+ var(--blinq-inner-highlight),
4395
+ 0 10px 26px rgba(183, 189, 198, 0.16);
4015
4396
  font-size: 13px;
4016
- line-height: 1.45;
4397
+ outline: none;
4398
+ backdrop-filter: blur(22px) saturate(170%);
4399
+ -webkit-backdrop-filter: blur(22px) saturate(170%);
4400
+ }
4401
+
4402
+ .blinq-input::placeholder {
4017
4403
  color: var(--blinq-text-muted);
4018
4404
  }
4019
4405
 
4020
- .blinq-composer-controls {
4406
+ .blinq-recording-input {
4407
+ display: flex;
4408
+ align-items: center;
4409
+ gap: 12px;
4410
+ }
4411
+
4412
+ .blinq-recording-time {
4413
+ flex: none;
4414
+ min-width: 42px;
4415
+ font-size: 12px;
4416
+ font-weight: 600;
4417
+ letter-spacing: 0.04em;
4418
+ color: var(--blinq-text-soft);
4419
+ font-variant-numeric: tabular-nums;
4420
+ }
4421
+
4422
+ .blinq-recording-wave-shell {
4423
+ position: relative;
4021
4424
  display: flex;
4022
- padding-top: 14px;
4425
+ align-items: center;
4426
+ flex: 1 1 auto;
4427
+ min-width: 0;
4428
+ height: 30px;
4429
+ padding: 0 10px;
4430
+ border-radius: 999px;
4431
+ border: 1px solid rgba(255, 255, 255, 0.54);
4432
+ background:
4433
+ linear-gradient(180deg, rgba(255, 255, 255, 0.54), rgba(242, 245, 248, 0.34));
4434
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.84);
4435
+ overflow: hidden;
4436
+ }
4437
+
4438
+ .blinq-recording-wave-shell::before {
4439
+ content: "";
4440
+ position: absolute;
4441
+ left: 10px;
4442
+ right: 10px;
4443
+ top: 50%;
4444
+ height: 1px;
4445
+ border-radius: 999px;
4446
+ background: linear-gradient(90deg, transparent, rgba(17, 17, 17, 0.12), transparent);
4447
+ transform: translateY(-50%);
4448
+ pointer-events: none;
4449
+ }
4450
+
4451
+ .blinq-recording-waveform {
4452
+ position: relative;
4453
+ display: flex;
4454
+ align-items: center;
4455
+ gap: 4px;
4456
+ flex: 1;
4457
+ min-width: 0;
4458
+ height: 100%;
4459
+ overflow: hidden;
4460
+ }
4461
+
4462
+ .blinq-recording-waveform-bar {
4463
+ width: 4px;
4464
+ min-width: 4px;
4465
+ height: 62%;
4466
+ border-radius: 999px;
4467
+ background: linear-gradient(180deg, rgba(17, 17, 17, 0.14), rgba(17, 17, 17, 0.36));
4468
+ transform-origin: center;
4469
+ transition:
4470
+ transform 120ms ease,
4471
+ opacity 160ms ease;
4472
+ opacity: 0.92;
4473
+ box-shadow:
4474
+ 0 0 0 1px rgba(255, 255, 255, 0.26),
4475
+ 0 2px 8px rgba(17, 17, 17, 0.08);
4023
4476
  }
4024
4477
 
4025
4478
  .blinq-button {
@@ -4027,64 +4480,71 @@ var EMBED_WIDGET_STYLES = `
4027
4480
  align-items: center;
4028
4481
  justify-content: center;
4029
4482
  gap: 8px;
4030
- border-radius: 14px;
4031
4483
  border: 1px solid transparent;
4484
+ border-radius: 999px;
4485
+ color: var(--blinq-text);
4032
4486
  font-size: 14px;
4033
4487
  font-weight: 600;
4488
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.72), rgba(236, 239, 244, 0.5));
4489
+ box-shadow: var(--blinq-shadow-soft);
4490
+ backdrop-filter: blur(20px) saturate(170%);
4491
+ -webkit-backdrop-filter: blur(20px) saturate(170%);
4034
4492
  transition:
4035
- background 120ms ease,
4036
- border-color 120ms ease,
4037
- color 120ms ease,
4038
- opacity 120ms ease,
4039
- transform 120ms ease;
4493
+ transform 160ms ease,
4494
+ box-shadow 180ms ease,
4495
+ border-color 180ms ease,
4496
+ background 180ms ease,
4497
+ opacity 120ms ease;
4040
4498
  cursor: pointer;
4041
4499
  outline: none;
4042
4500
  }
4043
4501
 
4044
- .blinq-button:disabled {
4045
- opacity: 0.55;
4046
- cursor: not-allowed;
4502
+ .blinq-button:hover:not(:disabled) {
4503
+ transform: translateY(-1px);
4504
+ border-color: rgba(255, 255, 255, 0.82);
4505
+ box-shadow:
4506
+ 0 14px 28px rgba(175, 181, 191, 0.22),
4507
+ 0 4px 10px rgba(189, 195, 204, 0.16);
4047
4508
  }
4048
4509
 
4049
- .blinq-button:focus-visible,
4050
- .blinq-input:focus-visible,
4051
- .blinq-tab-trigger:focus-visible,
4052
- .blinq-prompt-chip:focus-visible {
4053
- box-shadow: 0 0 0 3px rgba(17, 17, 17, 0.12);
4054
- outline: none;
4510
+ .blinq-input-mic:hover:not(:disabled),
4511
+ .blinq-input-send:hover:not(:disabled) {
4512
+ transform: translateY(-50%);
4513
+ border-color: rgba(255, 255, 255, 0.82);
4514
+ box-shadow:
4515
+ 0 14px 28px rgba(175, 181, 191, 0.16),
4516
+ 0 4px 10px rgba(189, 195, 204, 0.12);
4055
4517
  }
4056
4518
 
4057
- .blinq-button-default {
4058
- background: #111111;
4059
- color: white;
4060
- box-shadow: 0 12px 24px rgba(17, 17, 17, 0.16);
4519
+ .blinq-button:disabled {
4520
+ opacity: 0.52;
4521
+ cursor: not-allowed;
4061
4522
  }
4062
4523
 
4063
- .blinq-button-default:hover:not(:disabled) {
4064
- filter: brightness(1.04);
4524
+ .blinq-button:focus-visible,
4525
+ .blinq-input:focus-visible {
4526
+ box-shadow:
4527
+ 0 0 0 3px rgba(255, 255, 255, 0.68),
4528
+ 0 0 0 6px rgba(17, 17, 17, 0.08);
4065
4529
  }
4066
4530
 
4067
- .blinq-button-outline {
4068
- border-color: var(--blinq-border-strong);
4069
- background: #ffffff;
4531
+ .blinq-button-default {
4532
+ border-color: rgba(255, 255, 255, 0.74);
4533
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.84), rgba(237, 241, 247, 0.66));
4070
4534
  color: var(--blinq-text);
4071
4535
  }
4072
4536
 
4073
- .blinq-button-outline:hover:not(:disabled),
4074
- .blinq-button-ghost:hover:not(:disabled) {
4075
- background: var(--blinq-surface-soft);
4076
- }
4077
-
4537
+ .blinq-button-outline,
4078
4538
  .blinq-button-ghost {
4079
- border-color: var(--blinq-border);
4080
- background: rgba(255,255,255,0.76);
4539
+ border-color: rgba(255, 255, 255, 0.58);
4540
+ background: rgba(255, 255, 255, 0.42);
4081
4541
  color: var(--blinq-text-soft);
4082
4542
  }
4083
4543
 
4084
4544
  .blinq-button-destructive {
4085
- background: #111111;
4086
- border-color: #111111;
4087
- color: #ffffff;
4545
+ border-color: rgba(255, 255, 255, 0.58);
4546
+ background: linear-gradient(180deg, rgba(248, 249, 251, 0.7), rgba(230, 233, 239, 0.54));
4547
+ color: var(--blinq-text);
4088
4548
  }
4089
4549
 
4090
4550
  .blinq-button-md {
@@ -4093,118 +4553,274 @@ var EMBED_WIDGET_STYLES = `
4093
4553
  }
4094
4554
 
4095
4555
  .blinq-button-sm {
4096
- height: 36px;
4097
- padding: 0 12px;
4556
+ height: 38px;
4557
+ padding: 0 13px;
4098
4558
  font-size: 13px;
4099
4559
  }
4100
4560
 
4101
4561
  .blinq-button-icon {
4102
- width: 44px;
4103
- height: 44px;
4562
+ width: 48px;
4563
+ height: 48px;
4104
4564
  padding: 0;
4105
4565
  }
4106
4566
 
4107
4567
  .blinq-button-icon-sm {
4108
- width: 36px;
4109
- height: 36px;
4568
+ width: 38px;
4569
+ height: 38px;
4110
4570
  padding: 0;
4111
- border-radius: 12px;
4112
4571
  }
4113
4572
 
4114
- .blinq-input {
4115
- width: 100%;
4116
- min-width: 0;
4117
- height: 52px;
4118
- border-radius: 18px;
4119
- border: 1px solid var(--blinq-border-strong);
4120
- padding: 0 48px 0 44px;
4573
+ .blinq-input-mic,
4574
+ .blinq-input-send {
4575
+ position: absolute;
4576
+ top: 50%;
4577
+ z-index: 2;
4578
+ width: 42px;
4579
+ height: 42px;
4580
+ min-width: 42px;
4581
+ transform: translateY(-50%);
4582
+ }
4583
+
4584
+ .blinq-input-mic {
4585
+ left: 8px;
4586
+ }
4587
+
4588
+ .blinq-input-send {
4589
+ right: 8px;
4590
+ }
4591
+
4592
+ .blinq-panel {
4593
+ display: flex;
4594
+ flex-direction: column;
4595
+ height: min(720px, calc(100vh - 64px));
4596
+ max-width: 520px;
4597
+ border: 1px solid rgba(226, 232, 240, 0.96);
4598
+ border-radius: 30px;
4121
4599
  background: #ffffff;
4122
- color: var(--blinq-text);
4123
- outline: none;
4124
- box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.8);
4600
+ box-shadow:
4601
+ 0 28px 80px rgba(15, 23, 42, 0.14),
4602
+ 0 10px 28px rgba(15, 23, 42, 0.08);
4603
+ backdrop-filter: none;
4604
+ -webkit-backdrop-filter: none;
4125
4605
  }
4126
4606
 
4127
- .blinq-input-shell {
4607
+ .blinq-panel::before,
4608
+ .blinq-panel::after,
4609
+ .blinq-message::before,
4610
+ .blinq-status-line::before {
4611
+ display: none;
4612
+ }
4613
+
4614
+ .blinq-header {
4615
+ flex: none;
4616
+ gap: 0;
4617
+ padding: 22px 24px 18px;
4618
+ border-bottom: 1px solid rgba(226, 232, 240, 0.86);
4619
+ background: #ffffff;
4620
+ }
4621
+
4622
+ .blinq-header-row {
4623
+ align-items: center;
4624
+ gap: 14px;
4625
+ }
4626
+
4627
+ .blinq-header-copy {
4628
+ gap: 5px;
4629
+ }
4630
+
4631
+ .blinq-heading {
4632
+ font-size: 22px;
4633
+ line-height: 1.05;
4634
+ font-weight: 700;
4635
+ letter-spacing: -0.04em;
4636
+ color: #111827;
4637
+ }
4638
+
4639
+ .blinq-status-line {
4640
+ display: block;
4641
+ max-width: 100%;
4642
+ min-height: 0;
4643
+ padding: 0;
4644
+ border: 0;
4645
+ background: transparent;
4646
+ box-shadow: none;
4647
+ color: #6b7280;
4648
+ font-size: 13px;
4649
+ line-height: 1.35;
4650
+ backdrop-filter: none;
4651
+ -webkit-backdrop-filter: none;
4652
+ }
4653
+
4654
+ .blinq-avatar {
4128
4655
  position: relative;
4656
+ display: inline-flex;
4657
+ align-items: center;
4658
+ justify-content: center;
4659
+ width: 64px;
4660
+ min-width: 64px;
4661
+ height: 64px;
4662
+ overflow: visible;
4663
+ border: 1px solid rgba(226, 232, 240, 0.95);
4664
+ border-radius: 999px;
4665
+ background:
4666
+ radial-gradient(circle at 30% 20%, rgba(255, 255, 255, 0.98), rgba(248, 250, 252, 0.86)),
4667
+ #ffffff;
4668
+ box-shadow:
4669
+ 0 14px 26px rgba(15, 23, 42, 0.08),
4670
+ inset 0 1px 0 rgba(255, 255, 255, 0.9);
4671
+ color: #111827;
4672
+ flex: none;
4673
+ }
4674
+
4675
+ .blinq-avatar-image {
4129
4676
  width: 100%;
4677
+ height: 100%;
4678
+ border-radius: inherit;
4679
+ object-fit: cover;
4130
4680
  }
4131
4681
 
4132
- .blinq-recording-input {
4682
+ .blinq-avatar-icon {
4683
+ color: #111827;
4684
+ }
4685
+
4686
+ .blinq-avatar-status {
4687
+ position: absolute;
4688
+ right: 5px;
4689
+ bottom: 6px;
4690
+ width: 11px;
4691
+ height: 11px;
4692
+ border: 2px solid #ffffff;
4693
+ border-radius: 999px;
4694
+ background: #21d262;
4695
+ box-shadow: 0 0 0 1px rgba(15, 23, 42, 0.04);
4696
+ }
4697
+
4698
+ .blinq-avatar-label {
4699
+ display: none;
4700
+ }
4701
+
4702
+ .blinq-thread {
4133
4703
  display: flex;
4134
- align-items: center;
4704
+ flex: 1 1 auto;
4705
+ min-height: 0;
4706
+ background: #ffffff;
4707
+ }
4708
+
4709
+ .blinq-thread-viewport {
4710
+ flex: 1 1 auto;
4711
+ height: 100%;
4712
+ }
4713
+
4714
+ .blinq-scroll {
4715
+ flex: 1 1 auto;
4135
4716
  gap: 12px;
4136
- width: 100%;
4137
- min-width: 0;
4138
- height: 52px;
4139
- padding: 0 48px 0 44px;
4717
+ max-height: none;
4718
+ min-height: 0;
4719
+ padding: 30px 24px 20px;
4720
+ background: #ffffff;
4721
+ }
4722
+
4723
+ .blinq-message {
4724
+ max-width: 82%;
4725
+ padding: 10px 15px;
4726
+ border: 1px solid rgba(226, 232, 240, 0.96);
4140
4727
  border-radius: 18px;
4141
- border: 1px solid var(--blinq-border-strong);
4142
4728
  background: #ffffff;
4143
- color: var(--blinq-text);
4144
- box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.8);
4729
+ box-shadow: none;
4730
+ color: #111827;
4731
+ font-size: 15px;
4732
+ line-height: 1.48;
4733
+ backdrop-filter: none;
4734
+ -webkit-backdrop-filter: none;
4145
4735
  }
4146
4736
 
4147
- .blinq-recording-time {
4148
- flex: 0 0 auto;
4149
- min-width: 42px;
4150
- font-size: 12px;
4151
- font-weight: 700;
4152
- letter-spacing: 0.04em;
4153
- color: var(--blinq-text-soft);
4154
- font-variant-numeric: tabular-nums;
4737
+ .blinq-message[data-role="assistant"] {
4738
+ background: #ffffff;
4155
4739
  }
4156
4740
 
4157
- .blinq-recording-waveform {
4158
- display: flex;
4159
- align-items: flex-end;
4160
- gap: 3px;
4161
- flex: 1 1 auto;
4162
- min-width: 0;
4163
- height: 24px;
4164
- overflow: hidden;
4741
+ .blinq-message[data-role="user"] {
4742
+ border-color: rgba(209, 213, 219, 0.96);
4743
+ background: #f8fafc;
4165
4744
  }
4166
4745
 
4167
- .blinq-recording-waveform-bar {
4168
- width: 3px;
4169
- min-width: 3px;
4170
- height: 100%;
4746
+ .blinq-card,
4747
+ .blinq-guide-step-shell,
4748
+ .blinq-plan-step {
4749
+ border-color: rgba(226, 232, 240, 0.92);
4750
+ background: #ffffff;
4751
+ box-shadow: none;
4752
+ backdrop-filter: none;
4753
+ -webkit-backdrop-filter: none;
4754
+ }
4755
+
4756
+ .blinq-composer {
4757
+ flex: none;
4758
+ padding: 18px 24px 8px;
4759
+ border-top: 1px solid rgba(226, 232, 240, 0.86);
4760
+ background: #ffffff;
4761
+ }
4762
+
4763
+ .blinq-input,
4764
+ .blinq-recording-input {
4765
+ height: 56px;
4766
+ padding: 0 60px 0 54px;
4767
+ border: 1px solid rgba(209, 213, 219, 0.92);
4171
4768
  border-radius: 999px;
4172
- background: rgba(17, 17, 17, 0.22);
4173
- transform-origin: center bottom;
4174
- transition:
4175
- transform 110ms ease,
4176
- background 110ms ease;
4769
+ background: #ffffff;
4770
+ box-shadow: none;
4771
+ color: #111827;
4772
+ font-size: 15px;
4773
+ backdrop-filter: none;
4774
+ -webkit-backdrop-filter: none;
4775
+ }
4776
+
4777
+ .blinq-input::placeholder {
4778
+ color: #9ca3af;
4177
4779
  }
4178
4780
 
4179
4781
  .blinq-input-mic {
4180
- position: absolute;
4181
- left: 8px;
4182
- top: 50%;
4183
- transform: translateY(-50%);
4184
- z-index: 2;
4782
+ left: 7px;
4783
+ width: 42px;
4784
+ min-width: 42px;
4785
+ height: 42px;
4786
+ border: 0;
4787
+ background: transparent;
4788
+ box-shadow: none;
4789
+ color: #6b7280;
4185
4790
  }
4186
4791
 
4187
4792
  .blinq-input-send {
4188
- position: absolute;
4189
- right: 8px;
4190
- top: 50%;
4793
+ right: 7px;
4794
+ width: 42px;
4795
+ min-width: 42px;
4796
+ height: 42px;
4797
+ border: 0;
4798
+ background: #6b6f76;
4799
+ box-shadow: none;
4800
+ color: #ffffff;
4801
+ }
4802
+
4803
+ .blinq-input-send:hover:not(:disabled) {
4191
4804
  transform: translateY(-50%);
4192
- z-index: 2;
4193
- width: 36px;
4194
- height: 36px;
4195
- min-width: 36px;
4196
- border-radius: 12px;
4805
+ background: #4b5563;
4806
+ box-shadow: none;
4197
4807
  }
4198
4808
 
4199
- .blinq-text-animate {
4200
- display: block;
4809
+ .blinq-button-ghost {
4810
+ border-color: transparent;
4811
+ background: transparent;
4812
+ box-shadow: none;
4201
4813
  }
4202
4814
 
4203
- .blinq-text-animate-blur-in .blinq-text-segment {
4204
- display: inline-block;
4205
- opacity: 0;
4206
- filter: blur(8px);
4207
- animation: blinq-blur-in 420ms cubic-bezier(0.16, 1, 0.3, 1) forwards;
4815
+ .blinq-powered {
4816
+ flex: none;
4817
+ padding: 0 24px 18px;
4818
+ color: #c0c4ca;
4819
+ font-size: 10px;
4820
+ font-weight: 800;
4821
+ letter-spacing: 0.16em;
4822
+ line-height: 1;
4823
+ text-align: center;
4208
4824
  }
4209
4825
 
4210
4826
  @keyframes blinq-thinking-pulse {
@@ -4215,65 +4831,59 @@ var EMBED_WIDGET_STYLES = `
4215
4831
 
4216
4832
  50% {
4217
4833
  opacity: 1;
4218
- transform: translateY(-2px);
4834
+ transform: translateY(-1.5px);
4219
4835
  }
4220
4836
  }
4221
4837
 
4222
- @keyframes blinq-agent-spin {
4223
- from {
4224
- transform: rotate(0deg);
4838
+ @keyframes blinq-copy-reveal {
4839
+ 0% {
4840
+ opacity: 0;
4841
+ transform: translateY(3px);
4225
4842
  }
4226
4843
 
4227
- to {
4228
- transform: rotate(360deg);
4844
+ 100% {
4845
+ opacity: 1;
4846
+ transform: translateY(0);
4229
4847
  }
4230
4848
  }
4231
4849
 
4232
- @keyframes blinq-agent-bob {
4233
- 0%, 100% {
4234
- transform: translateY(0);
4850
+ @keyframes blinq-orbit-drift {
4851
+ from {
4852
+ transform: rotate(0deg);
4235
4853
  }
4236
4854
 
4237
- 50% {
4238
- transform: translateY(-0.8px);
4855
+ to {
4856
+ transform: rotate(360deg);
4239
4857
  }
4240
4858
  }
4241
4859
 
4242
- @keyframes blinq-agent-spark {
4860
+ @keyframes blinq-orbit-pulse {
4243
4861
  0%, 100% {
4244
4862
  transform: scale(1);
4245
- opacity: 0.72;
4863
+ opacity: 0.9;
4246
4864
  }
4247
4865
 
4248
4866
  50% {
4249
- transform: scale(1.25);
4867
+ transform: scale(1.16);
4250
4868
  opacity: 1;
4251
4869
  }
4252
4870
  }
4253
4871
 
4254
- @keyframes blinq-blur-in {
4255
- 0% {
4256
- opacity: 0;
4257
- filter: blur(8px);
4258
- transform: translateY(4px);
4872
+ @keyframes blinq-core-breathe {
4873
+ 0%, 100% {
4874
+ transform: scale(1);
4259
4875
  }
4260
4876
 
4261
- 100% {
4262
- opacity: 1;
4263
- filter: blur(0);
4264
- transform: translateY(0);
4877
+ 50% {
4878
+ transform: scale(1.04);
4265
4879
  }
4266
4880
  }
4267
4881
 
4268
- .blinq-input::placeholder {
4269
- color: var(--blinq-text-muted);
4270
- }
4271
-
4272
4882
  @media (max-width: 720px) {
4273
4883
  .blinq-shell {
4274
- bottom: 12px;
4275
- left: 12px;
4276
4884
  right: 12px;
4885
+ left: 12px;
4886
+ bottom: 12px;
4277
4887
  width: auto;
4278
4888
  max-width: none;
4279
4889
  align-items: stretch;
@@ -4281,43 +4891,212 @@ var EMBED_WIDGET_STYLES = `
4281
4891
 
4282
4892
  .blinq-shell[data-side="left"],
4283
4893
  .blinq-shell[data-side="right"] {
4284
- left: 12px;
4285
4894
  right: 12px;
4895
+ left: 12px;
4286
4896
  align-items: stretch;
4287
4897
  }
4288
4898
 
4289
4899
  .blinq-panel,
4290
4900
  .blinq-launcher {
4291
- max-width: none;
4292
4901
  width: 100%;
4902
+ max-width: none;
4293
4903
  }
4294
4904
 
4295
- .blinq-workspace {
4296
- grid-template-columns: 1fr;
4905
+ .blinq-launcher {
4906
+ width: 76px;
4907
+ min-width: 76px;
4908
+ height: 76px;
4909
+ align-self: flex-end;
4297
4910
  }
4298
4911
 
4299
- .blinq-sidebar {
4300
- border-right: none;
4301
- border-bottom: 1px solid var(--blinq-border);
4912
+ .blinq-message {
4913
+ max-width: 92%;
4302
4914
  }
4303
4915
 
4304
- .blinq-sidebar-group {
4305
- flex-direction: row;
4306
- overflow-x: auto;
4916
+ .blinq-actions {
4917
+ flex-direction: column;
4307
4918
  }
4308
4919
 
4309
- .blinq-tab-trigger {
4310
- min-width: 116px;
4920
+ .blinq-input,
4921
+ .blinq-recording-input {
4922
+ height: 56px;
4311
4923
  }
4312
4924
 
4313
- .blinq-context-grid {
4314
- grid-template-columns: 1fr;
4925
+ .blinq-panel {
4926
+ height: min(700px, calc(100vh - 24px));
4315
4927
  }
4316
4928
  }
4317
4929
  `;
4318
4930
 
4319
4931
  // src/browser.ts
4320
4932
  var EMBED_TAG_NAME = "blinq-widget";
4933
+ var TRAINER_PARAM = "blinqTrainer";
4934
+ function isTrainerMode() {
4935
+ if (typeof window === "undefined") {
4936
+ return false;
4937
+ }
4938
+ return new URLSearchParams(window.location.search).get(TRAINER_PARAM) === "1";
4939
+ }
4940
+ function trainerParentOrigin() {
4941
+ if (typeof window === "undefined") {
4942
+ return "*";
4943
+ }
4944
+ if (!document.referrer) {
4945
+ return window.location.origin;
4946
+ }
4947
+ try {
4948
+ return new URL(document.referrer).origin;
4949
+ } catch {
4950
+ return window.location.origin;
4951
+ }
4952
+ }
4953
+ function isLikelyAuthRoute(pathname) {
4954
+ const normalized = pathname.toLowerCase();
4955
+ return normalized.includes("/login") || normalized.includes("/signin") || normalized.includes("/sign-in") || normalized.includes("/signup") || normalized.includes("/sign-up") || normalized.includes("/auth");
4956
+ }
4957
+ function postTrainerEvent(eventType, payload) {
4958
+ if (typeof window === "undefined" || window.parent === window) {
4959
+ return;
4960
+ }
4961
+ window.parent.postMessage(
4962
+ {
4963
+ source: "blinq-trainer",
4964
+ kind: "event",
4965
+ event_type: eventType,
4966
+ payload
4967
+ },
4968
+ trainerParentOrigin()
4969
+ );
4970
+ }
4971
+ function defineGenericTrainerBridge() {
4972
+ if (typeof window === "undefined" || window.parent === window || !isTrainerMode() || window.__blinqTrainerBridgeInstalled) {
4973
+ return;
4974
+ }
4975
+ window.__blinqTrainerBridgeInstalled = true;
4976
+ let cancelled = false;
4977
+ const registry = new PageToolRegistry(async () => false);
4978
+ registry.setActionPolicy({
4979
+ actions_enabled: true,
4980
+ action_mode: "execute_with_confirmation",
4981
+ pointer_overlay_enabled: true
4982
+ });
4983
+ let nativeRegistered = false;
4984
+ const parentOrigin = trainerParentOrigin();
4985
+ const sendReady = async () => {
4986
+ nativeRegistered = await registry.registerNativeTools().catch(() => false);
4987
+ postTrainerEvent("runner_ready", {
4988
+ url: window.location.href,
4989
+ secure_context: window.isSecureContext,
4990
+ native_webmcp_supported: detectNativeWebMcpSupport(),
4991
+ native_webmcp_registered: nativeRegistered,
4992
+ runtime_mode: nativeRegistered ? "native-webmcp-active" : "read-only-fallback"
4993
+ });
4994
+ };
4995
+ const handleCommand = (event) => {
4996
+ if (event.origin !== parentOrigin) {
4997
+ return;
4998
+ }
4999
+ const data = event.data;
5000
+ if (data?.source !== "blinq-suggestions" || data?.type !== "command" || !data.name) {
5001
+ return;
5002
+ }
5003
+ if (data.name === "collect_context") {
5004
+ postTrainerEvent("page_context", {
5005
+ url: window.location.href,
5006
+ authenticated: !isLikelyAuthRoute(window.location.pathname),
5007
+ secure_context: window.isSecureContext,
5008
+ native_webmcp_supported: detectNativeWebMcpSupport(),
5009
+ native_webmcp_registered: nativeRegistered,
5010
+ page_context: collectNormalizedPageContext()
5011
+ });
5012
+ return;
5013
+ }
5014
+ if (data.name === "execute_tool") {
5015
+ const toolName = typeof data.payload?.tool_name === "string" ? data.payload.tool_name : "";
5016
+ const displayName = typeof data.payload?.display_name === "string" ? data.payload.display_name : void 0;
5017
+ const targetSummary = typeof data.payload?.target_summary === "string" ? data.payload.target_summary : void 0;
5018
+ const requiresConfirmation = Boolean(data.payload?.requires_confirmation);
5019
+ const argumentsPayload = data.payload?.arguments && typeof data.payload.arguments === "object" && !Array.isArray(data.payload.arguments) ? data.payload.arguments : {};
5020
+ if (!toolName) {
5021
+ postTrainerEvent("tool_result", {
5022
+ status: "error",
5023
+ error: "\u041D\u0435 \u043F\u0435\u0440\u0435\u0434\u0430\u043D tool_name \u0434\u043B\u044F \u0442\u0440\u0435\u043D\u0438\u0440\u043E\u0432\u043A\u0438.",
5024
+ current_url: window.location.href
5025
+ });
5026
+ return;
5027
+ }
5028
+ void (async () => {
5029
+ const outcome = await registry.executeTool({
5030
+ tool_name: toolName,
5031
+ display_name: displayName,
5032
+ target_summary: targetSummary,
5033
+ requires_confirmation: requiresConfirmation,
5034
+ arguments: argumentsPayload
5035
+ });
5036
+ const result = outcome.status === "success" && outcome.result && typeof outcome.result === "object" ? outcome.result : null;
5037
+ postTrainerEvent("tool_result", {
5038
+ status: outcome.status,
5039
+ result,
5040
+ error: outcome.error,
5041
+ current_url: window.location.href,
5042
+ page_context: result && typeof result === "object" && result.deferred_navigation ? null : collectNormalizedPageContext()
5043
+ });
5044
+ if (outcome.status === "success" && result && typeof result === "object" && result.deferred_navigation && typeof result.href === "string" && result.href.trim()) {
5045
+ window.setTimeout(() => {
5046
+ window.location.href = result.href;
5047
+ }, 40);
5048
+ }
5049
+ })();
5050
+ return;
5051
+ }
5052
+ if (data.name !== "preview_targets") {
5053
+ return;
5054
+ }
5055
+ const rawTargets = Array.isArray(data.payload?.targets) ? data.payload.targets : [];
5056
+ const targets = [];
5057
+ for (const target of rawTargets) {
5058
+ if (!target || typeof target !== "object") {
5059
+ continue;
5060
+ }
5061
+ const selector = typeof target.selector === "string" ? target.selector.trim() : "";
5062
+ const label = typeof target.label === "string" ? target.label.trim() : void 0;
5063
+ if (!selector) {
5064
+ continue;
5065
+ }
5066
+ targets.push({ selector, label: label || void 0 });
5067
+ }
5068
+ void (async () => {
5069
+ for (const target of targets) {
5070
+ if (cancelled) {
5071
+ return;
5072
+ }
5073
+ registry.highlightTargets([target], {
5074
+ interaction: "explain",
5075
+ durationMs: 1500
5076
+ });
5077
+ await new Promise((resolve) => window.setTimeout(resolve, 1120));
5078
+ }
5079
+ if (cancelled) {
5080
+ return;
5081
+ }
5082
+ postTrainerEvent("preview_complete", {
5083
+ url: window.location.href
5084
+ });
5085
+ })();
5086
+ };
5087
+ sendReady();
5088
+ window.setTimeout(() => void sendReady(), 180);
5089
+ window.setTimeout(() => void sendReady(), 560);
5090
+ window.addEventListener("message", handleCommand);
5091
+ window.addEventListener(
5092
+ "beforeunload",
5093
+ () => {
5094
+ cancelled = true;
5095
+ registry.destroy();
5096
+ },
5097
+ { once: true }
5098
+ );
5099
+ }
4321
5100
  function shadowRootStyles() {
4322
5101
  return EMBED_WIDGET_STYLES;
4323
5102
  }
@@ -4329,6 +5108,10 @@ var BlinqWidgetElement = class extends HTMLElement {
4329
5108
  if (this.widget || this.widgetPromise) {
4330
5109
  return;
4331
5110
  }
5111
+ if (isTrainerMode()) {
5112
+ this.style.display = "none";
5113
+ return;
5114
+ }
4332
5115
  const publicToken = this.getAttribute("public-token")?.trim();
4333
5116
  if (!publicToken) {
4334
5117
  console.error("Blinq widget: missing required public-token attribute.");
@@ -4376,6 +5159,7 @@ function defineBlinqWidgetElement() {
4376
5159
  }
4377
5160
  if (typeof window !== "undefined") {
4378
5161
  defineBlinqWidgetElement();
5162
+ defineGenericTrainerBridge();
4379
5163
  window.BlinqWidget = {
4380
5164
  init,
4381
5165
  initFromConfig