@absolutejs/voice 0.0.22-beta.528 → 0.0.22-beta.529

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.
@@ -203,6 +203,9 @@ var createVoiceCampaignDialerProofStore = (path = "/api/voice/campaigns/dialer-p
203
203
 
204
204
  // src/svelte/createVoiceCampaignDialerProof.ts
205
205
  var createVoiceCampaignDialerProof = (path = "/api/voice/campaigns/dialer-proof", options = {}) => createVoiceCampaignDialerProofStore(path, options);
206
+ // src/internal/html.ts
207
+ var escapeHtml = (value) => String(value).replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
208
+
206
209
  // src/client/callPlayer.ts
207
210
  var cloneState = (state) => ({
208
211
  ...state
@@ -354,7 +357,6 @@ var formatVoiceCallPlayerTimestamp = (ms) => {
354
357
  };
355
358
 
356
359
  // src/svelte/createVoiceCallPlayer.ts
357
- var escapeHtml = (text) => text.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
358
360
  var renderVoiceCallPlayerHTML = (state, options = {}) => {
359
361
  const title = options.title ?? "Call replay";
360
362
  const transcripts = options.transcripts ?? [];
@@ -1888,7 +1890,6 @@ var createVoiceWidgetViewModel = (input) => {
1888
1890
  title: input.title ?? "Voice"
1889
1891
  };
1890
1892
  };
1891
- var escapeHtml2 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
1892
1893
  var resolveRadius = (radius) => typeof radius === "number" ? `${radius}px` : radius;
1893
1894
  var renderVoiceWidgetHTML = (model) => {
1894
1895
  const t = model.theme;
@@ -1896,23 +1897,23 @@ var renderVoiceWidgetHTML = (model) => {
1896
1897
  const dotStyle = `background:${model.errorMessage ? t.errorAccent : model.agentState === "idle" ? "rgba(148,163,184,0.6)" : t.accent};border-radius:50%;height:10px;width:10px;`;
1897
1898
  const buttons = [];
1898
1899
  if (model.controls.canStart) {
1899
- buttons.push(`<button type="button" data-action="start" style="background:${t.accent};border:none;border-radius:12px;color:${t.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${escapeHtml2(model.labels.startCall)}</button>`);
1900
+ buttons.push(`<button type="button" data-action="start" style="background:${t.accent};border:none;border-radius:12px;color:${t.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${escapeHtml(model.labels.startCall)}</button>`);
1900
1901
  }
1901
1902
  if (model.controls.canMute) {
1902
- buttons.push(`<button type="button" data-action="mute" style="background:transparent;border:1px solid rgba(255,255,255,0.18);border-radius:12px;color:${t.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${escapeHtml2(model.labels.mute)}</button>`);
1903
+ buttons.push(`<button type="button" data-action="mute" style="background:transparent;border:1px solid rgba(255,255,255,0.18);border-radius:12px;color:${t.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${escapeHtml(model.labels.mute)}</button>`);
1903
1904
  }
1904
1905
  if (model.controls.canEnd) {
1905
- buttons.push(`<button type="button" data-action="end" style="background:${t.errorAccent};border:none;border-radius:12px;color:${t.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${escapeHtml2(model.labels.endCall)}</button>`);
1906
+ buttons.push(`<button type="button" data-action="end" style="background:${t.errorAccent};border:none;border-radius:12px;color:${t.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${escapeHtml(model.labels.endCall)}</button>`);
1906
1907
  }
1907
- return `<div role="region" aria-live="polite" data-agent-state="${model.agentState}" class="${escapeHtml2(model.classes.container)}" style="${containerStyle}">
1908
+ return `<div role="region" aria-live="polite" data-agent-state="${model.agentState}" class="${escapeHtml(model.classes.container)}" style="${containerStyle}">
1908
1909
  <div style="align-items:center;display:flex;gap:10px;margin-bottom:12px;">
1909
- <span aria-hidden="true" class="${escapeHtml2(model.classes.dot)}" style="${dotStyle}"></span>
1910
- <strong style="font-size:15px;">${escapeHtml2(model.title)}</strong>
1911
- <span style="font-size:13px;margin-left:auto;opacity:0.7;">${escapeHtml2(model.statusLabel)}</span>
1910
+ <span aria-hidden="true" class="${escapeHtml(model.classes.dot)}" style="${dotStyle}"></span>
1911
+ <strong style="font-size:15px;">${escapeHtml(model.title)}</strong>
1912
+ <span style="font-size:13px;margin-left:auto;opacity:0.7;">${escapeHtml(model.statusLabel)}</span>
1912
1913
  </div>
1913
- ${model.partial ? `<p style="font-size:13px;margin:8px 0 12px;opacity:0.85;word-break:break-word;">\u201C${escapeHtml2(model.partial)}\u201D</p>` : ""}
1914
+ ${model.partial ? `<p style="font-size:13px;margin:8px 0 12px;opacity:0.85;word-break:break-word;">\u201C${escapeHtml(model.partial)}\u201D</p>` : ""}
1914
1915
  <div style="display:flex;gap:10px;">${buttons.join("")}</div>
1915
- ${model.errorMessage ? `<p style="color:${t.errorAccent};font-size:12px;margin-top:12px;">${escapeHtml2(model.errorMessage)}</p>` : ""}
1916
+ ${model.errorMessage ? `<p style="color:${t.errorAccent};font-size:12px;margin-top:12px;">${escapeHtml(model.errorMessage)}</p>` : ""}
1916
1917
  </div>`;
1917
1918
  };
1918
1919
 
@@ -2250,24 +2251,23 @@ var createLiveAgentConsole = (options) => {
2250
2251
  };
2251
2252
 
2252
2253
  // src/svelte/createVoiceLiveAgentConsole.ts
2253
- var escapeHtml3 = (text) => text.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2254
2254
  var renderVoiceLiveAgentConsoleHTML = (state, options = {}) => {
2255
2255
  const title = options.title ?? "Live agent console";
2256
2256
  const buttonLabel = options.takeoverButtonLabel ?? "Take over";
2257
2257
  const callerBlock = state.caller ? `<div style="background:rgba(255,255,255,0.06);border-radius:12px;font-size:13px;margin:0 0 12px;padding:12px;">
2258
2258
  <div style="font-size:11px;opacity:0.7;text-transform:uppercase;">Caller</div>
2259
- <div style="margin-top:4px;">${escapeHtml3(state.caller.summary)}</div>
2259
+ <div style="margin-top:4px;">${escapeHtml(state.caller.summary)}</div>
2260
2260
  </div>` : "";
2261
- const button = state.hasTakeover ? `<button type="button" data-action="release" style="background:rgba(255,255,255,0.08);border:1px solid rgba(255,255,255,0.18);border-radius:12px;color:#f8fafc;cursor:pointer;font-size:13px;padding:8px 14px;">Release back to agent</button>` : `<button type="button" data-action="takeover" style="background:#ef4444;border:none;border-radius:12px;color:#f8fafc;cursor:pointer;font-size:13px;padding:8px 14px;">${escapeHtml3(buttonLabel)}</button>`;
2261
+ const button = state.hasTakeover ? `<button type="button" data-action="release" style="background:rgba(255,255,255,0.08);border:1px solid rgba(255,255,255,0.18);border-radius:12px;color:#f8fafc;cursor:pointer;font-size:13px;padding:8px 14px;">Release back to agent</button>` : `<button type="button" data-action="takeover" style="background:#ef4444;border:none;border-radius:12px;color:#f8fafc;cursor:pointer;font-size:13px;padding:8px 14px;">${escapeHtml(buttonLabel)}</button>`;
2262
2262
  const items = state.recentTimeline.map((event) => `<li style="align-items:center;display:flex;font-size:13px;gap:12px;padding-left:8px;">
2263
- <strong>${escapeHtml3(event.title)}</strong>
2264
- ${event.detail ? `<span style="opacity:0.85;">${escapeHtml3(event.detail)}</span>` : ""}
2263
+ <strong>${escapeHtml(event.title)}</strong>
2264
+ ${event.detail ? `<span style="opacity:0.85;">${escapeHtml(event.detail)}</span>` : ""}
2265
2265
  </li>`).join("");
2266
2266
  return `<section aria-label="voice-live-agent-console" class="absolute-voice-live-agent-console" data-takeover="${state.hasTakeover ? "true" : "false"}" style="background:#0f172a;border-radius:16px;color:#f8fafc;font-family:ui-sans-serif,system-ui,sans-serif;padding:20px;">
2267
2267
  <header style="align-items:center;display:flex;gap:12px;margin-bottom:12px;">
2268
- <strong style="font-size:16px;">${escapeHtml3(title)}</strong>
2268
+ <strong style="font-size:16px;">${escapeHtml(title)}</strong>
2269
2269
  <span style="background:${state.hasTakeover ? "rgba(239,68,68,0.18)" : "rgba(59,130,246,0.18)"};border-radius:999px;font-size:11px;padding:3px 10px;text-transform:uppercase;">${state.hasTakeover ? "Human" : "Agent"}</span>
2270
- <span style="font-size:13px;margin-left:auto;opacity:0.7;">${escapeHtml3(state.view.sessionId)}</span>
2270
+ <span style="font-size:13px;margin-left:auto;opacity:0.7;">${escapeHtml(state.view.sessionId)}</span>
2271
2271
  </header>
2272
2272
  ${callerBlock}
2273
2273
  <div style="display:flex;gap:10px;margin-bottom:12px;">${button}</div>
@@ -2556,7 +2556,6 @@ var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", opt
2556
2556
  // src/client/deliveryRuntimeWidget.ts
2557
2557
  var DEFAULT_TITLE = "Voice Delivery Runtime";
2558
2558
  var DEFAULT_DESCRIPTION = "Audit and trace delivery worker health from your AbsoluteJS voice app.";
2559
- var escapeHtml4 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2560
2559
  var createSurface = (id, summary) => {
2561
2560
  if (!summary) {
2562
2561
  return {
@@ -2605,26 +2604,26 @@ var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
2605
2604
  };
2606
2605
  var renderVoiceDeliveryRuntimeHTML = (snapshot, options = {}) => {
2607
2606
  const model = createVoiceDeliveryRuntimeViewModel(snapshot, options);
2608
- const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${escapeHtml4(surface.status)}">
2609
- <span>${escapeHtml4(surface.label)}</span>
2610
- <strong>${escapeHtml4(surface.detail)}</strong>
2607
+ const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${escapeHtml(surface.status)}">
2608
+ <span>${escapeHtml(surface.label)}</span>
2609
+ <strong>${escapeHtml(surface.detail)}</strong>
2611
2610
  <small>${String(surface.failed)} failed &middot; ${String(surface.deadLettered)} dead-lettered</small>
2612
2611
  </li>`).join("");
2613
2612
  const actions = options.includeActions === false ? "" : `<div class="absolute-voice-delivery-runtime__actions">
2614
2613
  <button type="button" data-absolute-voice-delivery-runtime-action="tick">${model.actionStatus === "running" ? "Working..." : "Tick workers"}</button>
2615
2614
  <button type="button" data-absolute-voice-delivery-runtime-action="requeue-dead-letters"${model.surfaces.some((surface) => surface.deadLettered > 0) ? "" : " disabled"}>Requeue dead letters</button>
2616
2615
  </div>`;
2617
- const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml4(model.actionError)}</p>` : "";
2618
- return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${escapeHtml4(model.status)}">
2616
+ const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml(model.actionError)}</p>` : "";
2617
+ return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${escapeHtml(model.status)}">
2619
2618
  <header class="absolute-voice-delivery-runtime__header">
2620
- <span class="absolute-voice-delivery-runtime__eyebrow">${escapeHtml4(model.title)}</span>
2621
- <strong class="absolute-voice-delivery-runtime__label">${escapeHtml4(model.label)}</strong>
2619
+ <span class="absolute-voice-delivery-runtime__eyebrow">${escapeHtml(model.title)}</span>
2620
+ <strong class="absolute-voice-delivery-runtime__label">${escapeHtml(model.label)}</strong>
2622
2621
  </header>
2623
- <p class="absolute-voice-delivery-runtime__description">${escapeHtml4(model.description)}</p>
2622
+ <p class="absolute-voice-delivery-runtime__description">${escapeHtml(model.description)}</p>
2624
2623
  <ul class="absolute-voice-delivery-runtime__surfaces">${surfaces}</ul>
2625
2624
  ${actions}
2626
2625
  ${actionError}
2627
- ${model.error ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml4(model.error)}</p>` : ""}
2626
+ ${model.error ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml(model.error)}</p>` : ""}
2628
2627
  </section>`;
2629
2628
  };
2630
2629
  var getVoiceDeliveryRuntimeCSS = () => `.absolute-voice-delivery-runtime{border:1px solid #c9d8cf;border-radius:20px;background:#f6fff9;color:#0d1b12;padding:18px;box-shadow:0 18px 40px rgba(19,55,35,.12);font-family:inherit}.absolute-voice-delivery-runtime--warn,.absolute-voice-delivery-runtime--error{border-color:#f2b56b;background:#fff9ed}.absolute-voice-delivery-runtime__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-delivery-runtime__eyebrow{color:#4e6b59;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-delivery-runtime__label{font-size:28px;line-height:1}.absolute-voice-delivery-runtime__description{color:#33483b;margin:12px 0 0}.absolute-voice-delivery-runtime__surfaces{display:grid;gap:8px;list-style:none;margin:16px 0 0;padding:0}.absolute-voice-delivery-runtime__surface{background:#fff;border:1px solid #d9eadf;border-radius:14px;display:grid;gap:4px;padding:10px 12px}.absolute-voice-delivery-runtime__surface--warn{border-color:#f2b56b}.absolute-voice-delivery-runtime__surface--disabled{opacity:.72}.absolute-voice-delivery-runtime__surface span,.absolute-voice-delivery-runtime__surface small{color:#587063}.absolute-voice-delivery-runtime__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}.absolute-voice-delivery-runtime__actions button{background:#134e2d;border:0;border-radius:999px;color:#f6fff9;cursor:pointer;font:inherit;font-weight:800;padding:8px 12px}.absolute-voice-delivery-runtime__actions button:disabled{cursor:not-allowed;opacity:.48}.absolute-voice-delivery-runtime__error{color:#9f1239;font-weight:700}`;
@@ -2889,7 +2888,6 @@ var createVoiceOpsActionCenterStore = (options = {}) => {
2889
2888
  // src/client/opsActionCenterWidget.ts
2890
2889
  var DEFAULT_TITLE2 = "Voice Ops Action Center";
2891
2890
  var DEFAULT_DESCRIPTION2 = "Run production voice proofs and operator actions from one primitive panel.";
2892
- var escapeHtml5 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2893
2891
  var createVoiceOpsActionCenterViewModel = (snapshot, options = {}) => {
2894
2892
  const status = snapshot.error ? "error" : snapshot.isRunning ? "running" : snapshot.lastResult ? "completed" : "ready";
2895
2893
  return {
@@ -2911,18 +2909,18 @@ var createVoiceOpsActionCenterViewModel = (snapshot, options = {}) => {
2911
2909
  };
2912
2910
  var renderVoiceOpsActionCenterHTML = (snapshot, options = {}) => {
2913
2911
  const model = createVoiceOpsActionCenterViewModel(snapshot, options);
2914
- const actions = model.actions.map((action) => `<button type="button" data-absolute-voice-ops-action="${escapeHtml5(action.id)}"${action.disabled ? " disabled" : ""}>
2915
- ${escapeHtml5(action.isRunning ? "Working..." : action.label)}
2912
+ const actions = model.actions.map((action) => `<button type="button" data-absolute-voice-ops-action="${escapeHtml(action.id)}"${action.disabled ? " disabled" : ""}>
2913
+ ${escapeHtml(action.isRunning ? "Working..." : action.label)}
2916
2914
  </button>`).join("");
2917
- return `<section class="absolute-voice-ops-action-center absolute-voice-ops-action-center--${escapeHtml5(model.status)}">
2915
+ return `<section class="absolute-voice-ops-action-center absolute-voice-ops-action-center--${escapeHtml(model.status)}">
2918
2916
  <header class="absolute-voice-ops-action-center__header">
2919
- <span class="absolute-voice-ops-action-center__eyebrow">${escapeHtml5(model.title)}</span>
2920
- <strong class="absolute-voice-ops-action-center__label">${escapeHtml5(model.label)}</strong>
2917
+ <span class="absolute-voice-ops-action-center__eyebrow">${escapeHtml(model.title)}</span>
2918
+ <strong class="absolute-voice-ops-action-center__label">${escapeHtml(model.label)}</strong>
2921
2919
  </header>
2922
- <p class="absolute-voice-ops-action-center__description">${escapeHtml5(model.description)}</p>
2920
+ <p class="absolute-voice-ops-action-center__description">${escapeHtml(model.description)}</p>
2923
2921
  <div class="absolute-voice-ops-action-center__actions">${actions}</div>
2924
- <p class="absolute-voice-ops-action-center__result">${escapeHtml5(model.lastResultLabel)}</p>
2925
- ${model.error ? `<p class="absolute-voice-ops-action-center__error">${escapeHtml5(model.error)}</p>` : ""}
2922
+ <p class="absolute-voice-ops-action-center__result">${escapeHtml(model.lastResultLabel)}</p>
2923
+ ${model.error ? `<p class="absolute-voice-ops-action-center__error">${escapeHtml(model.error)}</p>` : ""}
2926
2924
  </section>`;
2927
2925
  };
2928
2926
  var getVoiceOpsActionCenterCSS = () => `.absolute-voice-ops-action-center{border:1px solid #d5cbb8;border-radius:20px;background:#fffaf1;color:#17130b;padding:18px;box-shadow:0 18px 40px rgba(58,42,16,.12);font-family:inherit}.absolute-voice-ops-action-center--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-ops-action-center__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-ops-action-center__eyebrow{color:#725d37;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-ops-action-center__label{font-size:28px;line-height:1}.absolute-voice-ops-action-center__description,.absolute-voice-ops-action-center__result{color:#5b4b2f;margin:12px 0 0}.absolute-voice-ops-action-center__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}.absolute-voice-ops-action-center__actions button{background:#7c4a03;border:0;border-radius:999px;color:#fff8e8;cursor:pointer;font:inherit;font-weight:800;padding:8px 12px}.absolute-voice-ops-action-center__actions button:disabled{cursor:not-allowed;opacity:.5}.absolute-voice-ops-action-center__error{color:#9f1239;font-weight:700}`;
@@ -3751,7 +3749,6 @@ var exportVoiceTrace = async (input) => {
3751
3749
  };
3752
3750
  };
3753
3751
  var toNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : 0;
3754
- var escapeHtml6 = (value) => value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
3755
3752
  var formatTraceValue = (value) => {
3756
3753
  if (value === undefined || value === null) {
3757
3754
  return "";
@@ -4035,10 +4032,10 @@ var renderVoiceTraceHTML = (events, options = {}) => {
4035
4032
  const offset = summary.startedAt === undefined ? event.at : Math.max(0, event.at - summary.startedAt);
4036
4033
  return [
4037
4034
  "<tr>",
4038
- `<td>${escapeHtml6(String(offset))}</td>`,
4039
- `<td>${escapeHtml6(event.type)}</td>`,
4040
- `<td>${escapeHtml6(event.turnId ?? "")}</td>`,
4041
- `<td><code>${escapeHtml6(JSON.stringify(event.payload))}</code></td>`,
4035
+ `<td>${escapeHtml(String(offset))}</td>`,
4036
+ `<td>${escapeHtml(event.type)}</td>`,
4037
+ `<td>${escapeHtml(event.turnId ?? "")}</td>`,
4038
+ `<td><code>${escapeHtml(JSON.stringify(event.payload))}</code></td>`,
4042
4039
  "</tr>"
4043
4040
  ].join("");
4044
4041
  }).join(`
@@ -4049,7 +4046,7 @@ var renderVoiceTraceHTML = (events, options = {}) => {
4049
4046
  "<head>",
4050
4047
  '<meta charset="utf-8" />',
4051
4048
  '<meta name="viewport" content="width=device-width, initial-scale=1" />',
4052
- `<title>${escapeHtml6(options.title ?? "Voice Trace")}</title>`,
4049
+ `<title>${escapeHtml(options.title ?? "Voice Trace")}</title>`,
4053
4050
  "<style>",
4054
4051
  "body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;line-height:1.45;background:#f8f7f2;color:#181713}",
4055
4052
  "main{max-width:1100px;margin:auto}",
@@ -4063,7 +4060,7 @@ var renderVoiceTraceHTML = (events, options = {}) => {
4063
4060
  "</style>",
4064
4061
  "</head>",
4065
4062
  "<body><main>",
4066
- `<h1>${escapeHtml6(options.title ?? `Voice Trace ${summary.sessionId ?? ""}`.trim())}</h1>`,
4063
+ `<h1>${escapeHtml(options.title ?? `Voice Trace ${summary.sessionId ?? ""}`.trim())}</h1>`,
4067
4064
  `<p class="${evaluation.pass ? "pass" : "fail"}">QA: ${evaluation.pass ? "pass" : "fail"}</p>`,
4068
4065
  '<section class="summary">',
4069
4066
  `<div class="card"><strong>Events</strong><br>${summary.eventCount}</div>`,
@@ -4077,7 +4074,7 @@ var renderVoiceTraceHTML = (events, options = {}) => {
4077
4074
  eventRows,
4078
4075
  "</tbody></table>",
4079
4076
  "<h2>Markdown Export</h2>",
4080
- `<pre>${escapeHtml6(markdown)}</pre>`,
4077
+ `<pre>${escapeHtml(markdown)}</pre>`,
4081
4078
  "</main></body></html>"
4082
4079
  ].join(`
4083
4080
  `);
@@ -4433,7 +4430,6 @@ var ACTION_LABELS = {
4433
4430
  "resume-assistant": "Resume assistant",
4434
4431
  tag: "Tag"
4435
4432
  };
4436
- var escapeHtml7 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
4437
4433
  var createVoiceLiveOpsInput = (action, input) => ({
4438
4434
  action,
4439
4435
  assignee: input.assignee,
@@ -4444,17 +4440,17 @@ var createVoiceLiveOpsInput = (action, input) => ({
4444
4440
  var renderVoiceLiveOpsHTML = (snapshot, options = {}) => {
4445
4441
  const sessionId = options.getSessionId?.() ?? "";
4446
4442
  const disabled = snapshot.isRunning || !sessionId;
4447
- const actions = VOICE_LIVE_OPS_ACTIONS.map((action) => `<button type="button" data-absolute-voice-live-ops-action="${escapeHtml7(action)}"${disabled ? " disabled" : ""}>${escapeHtml7(snapshot.runningAction === action ? "Running..." : ACTION_LABELS[action])}</button>`).join("");
4448
- const result = snapshot.error ? `<p class="absolute-voice-live-ops__error">${escapeHtml7(snapshot.error)}</p>` : snapshot.lastResult ? `<p class="absolute-voice-live-ops__result">Recorded ${escapeHtml7(snapshot.lastResult.action)}. Control: ${escapeHtml7(snapshot.lastResult.control.status)}.</p>` : '<p class="absolute-voice-live-ops__result">No live ops action has run yet.</p>';
4443
+ const actions = VOICE_LIVE_OPS_ACTIONS.map((action) => `<button type="button" data-absolute-voice-live-ops-action="${escapeHtml(action)}"${disabled ? " disabled" : ""}>${escapeHtml(snapshot.runningAction === action ? "Running..." : ACTION_LABELS[action])}</button>`).join("");
4444
+ const result = snapshot.error ? `<p class="absolute-voice-live-ops__error">${escapeHtml(snapshot.error)}</p>` : snapshot.lastResult ? `<p class="absolute-voice-live-ops__result">Recorded ${escapeHtml(snapshot.lastResult.action)}. Control: ${escapeHtml(snapshot.lastResult.control.status)}.</p>` : '<p class="absolute-voice-live-ops__result">No live ops action has run yet.</p>';
4449
4445
  return `<section class="absolute-voice-live-ops">
4450
4446
  <header class="absolute-voice-live-ops__header">
4451
- <span>${escapeHtml7(options.title ?? "Live Ops")}</span>
4452
- <strong>${escapeHtml7(sessionId || "No active session")}</strong>
4447
+ <span>${escapeHtml(options.title ?? "Live Ops")}</span>
4448
+ <strong>${escapeHtml(sessionId || "No active session")}</strong>
4453
4449
  </header>
4454
- <p class="absolute-voice-live-ops__description">${escapeHtml7(options.description ?? "Pause, resume, take over, force handoff, or inject operator instructions during a live voice session.")}</p>
4455
- <label><span>Operator</span><input data-absolute-voice-live-ops-assignee value="${escapeHtml7(options.defaultAssignee ?? "operator")}" /></label>
4456
- <label><span>Tag / handoff target</span><input data-absolute-voice-live-ops-tag value="${escapeHtml7(options.defaultTag ?? "live-ops")}" /></label>
4457
- <label><span>Detail / instruction</span><input data-absolute-voice-live-ops-detail value="${escapeHtml7(options.defaultDetail ?? "Operator marked this live session.")}" /></label>
4450
+ <p class="absolute-voice-live-ops__description">${escapeHtml(options.description ?? "Pause, resume, take over, force handoff, or inject operator instructions during a live voice session.")}</p>
4451
+ <label><span>Operator</span><input data-absolute-voice-live-ops-assignee value="${escapeHtml(options.defaultAssignee ?? "operator")}" /></label>
4452
+ <label><span>Tag / handoff target</span><input data-absolute-voice-live-ops-tag value="${escapeHtml(options.defaultTag ?? "live-ops")}" /></label>
4453
+ <label><span>Detail / instruction</span><input data-absolute-voice-live-ops-detail value="${escapeHtml(options.defaultDetail ?? "Operator marked this live session.")}" /></label>
4458
4454
  <div class="absolute-voice-live-ops__actions">${actions}</div>
4459
4455
  ${result}
4460
4456
  </section>`;
@@ -4642,7 +4638,6 @@ var SURFACE_LABELS = {
4642
4638
  sessions: "Sessions",
4643
4639
  workflows: "Workflows"
4644
4640
  };
4645
- var escapeHtml8 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
4646
4641
  var readNumber = (value, key) => value && typeof value === "object" && (key in value) ? Number(value[key] ?? 0) : 0;
4647
4642
  var surfaceDetail = (surface) => {
4648
4643
  const total = readNumber(surface, "total");
@@ -4697,24 +4692,24 @@ var createVoiceOpsStatusViewModel = (snapshot, options = {}) => {
4697
4692
  };
4698
4693
  var renderVoiceOpsStatusHTML = (snapshot, options = {}) => {
4699
4694
  const model = createVoiceOpsStatusViewModel(snapshot, options);
4700
- const surfaces = model.surfaces.length ? model.surfaces.map((surface) => `<li class="absolute-voice-ops-status__surface absolute-voice-ops-status__surface--${escapeHtml8(surface.status)}">
4701
- <span>${escapeHtml8(surface.label)}</span>
4702
- <strong>${escapeHtml8(surface.detail)}</strong>
4695
+ const surfaces = model.surfaces.length ? model.surfaces.map((surface) => `<li class="absolute-voice-ops-status__surface absolute-voice-ops-status__surface--${escapeHtml(surface.status)}">
4696
+ <span>${escapeHtml(surface.label)}</span>
4697
+ <strong>${escapeHtml(surface.detail)}</strong>
4703
4698
  </li>`).join("") : '<li class="absolute-voice-ops-status__surface"><span>Status</span><strong>Waiting for first check</strong></li>';
4704
- const links = model.links.length ? `<nav class="absolute-voice-ops-status__links">${model.links.slice(0, 4).map((link) => `<a href="${escapeHtml8(link.href)}">${escapeHtml8(link.label)}</a>`).join("")}</nav>` : "";
4705
- return `<section class="absolute-voice-ops-status absolute-voice-ops-status--${escapeHtml8(model.status)}">
4699
+ const links = model.links.length ? `<nav class="absolute-voice-ops-status__links">${model.links.slice(0, 4).map((link) => `<a href="${escapeHtml(link.href)}">${escapeHtml(link.label)}</a>`).join("")}</nav>` : "";
4700
+ return `<section class="absolute-voice-ops-status absolute-voice-ops-status--${escapeHtml(model.status)}">
4706
4701
  <header class="absolute-voice-ops-status__header">
4707
- <span class="absolute-voice-ops-status__eyebrow">${escapeHtml8(model.title)}</span>
4708
- <strong class="absolute-voice-ops-status__label">${escapeHtml8(model.label)}</strong>
4702
+ <span class="absolute-voice-ops-status__eyebrow">${escapeHtml(model.title)}</span>
4703
+ <strong class="absolute-voice-ops-status__label">${escapeHtml(model.label)}</strong>
4709
4704
  </header>
4710
- <p class="absolute-voice-ops-status__description">${escapeHtml8(model.description)}</p>
4705
+ <p class="absolute-voice-ops-status__description">${escapeHtml(model.description)}</p>
4711
4706
  <div class="absolute-voice-ops-status__summary">
4712
4707
  <span>${model.passed} passing</span>
4713
4708
  <span>${Math.max(model.total - model.passed, 0)} failing</span>
4714
4709
  <span>${model.total} checks</span>
4715
4710
  </div>
4716
4711
  <ul class="absolute-voice-ops-status__surfaces">${surfaces}</ul>
4717
- ${model.error ? `<p class="absolute-voice-ops-status__error">${escapeHtml8(model.error)}</p>` : ""}
4712
+ ${model.error ? `<p class="absolute-voice-ops-status__error">${escapeHtml(model.error)}</p>` : ""}
4718
4713
  ${links}
4719
4714
  </section>`;
4720
4715
  };
@@ -5111,7 +5106,6 @@ var createVoiceCallDebuggerStore = (path, options = {}) => {
5111
5106
  var DEFAULT_TITLE4 = "Call Debugger";
5112
5107
  var DEFAULT_DESCRIPTION4 = "Open the latest call artifact with snapshot, operations record, failure replay, provider path, transcript, and incident markdown.";
5113
5108
  var DEFAULT_LINK_LABEL = "Open debugger";
5114
- var escapeHtml9 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
5115
5109
  var defaultHref = (path, report) => {
5116
5110
  if (path.startsWith("/api/voice-call-debugger/")) {
5117
5111
  return path.replace("/api/voice-call-debugger/", "/voice-call-debugger/");
@@ -5164,18 +5158,18 @@ var createVoiceCallDebuggerLaunchViewModel = (path, state, options = {}) => {
5164
5158
  var renderVoiceCallDebuggerLaunchHTML = (path, state, options = {}) => {
5165
5159
  const model = createVoiceCallDebuggerLaunchViewModel(path, state, options);
5166
5160
  const rows = model.rows.length ? `<dl>${model.rows.map((row) => `<div>
5167
- <dt>${escapeHtml9(row.label)}</dt>
5168
- <dd>${escapeHtml9(row.value)}</dd>
5161
+ <dt>${escapeHtml(row.label)}</dt>
5162
+ <dd>${escapeHtml(row.value)}</dd>
5169
5163
  </div>`).join("")}</dl>` : '<p class="absolute-voice-call-debugger-launch__empty">Load a call debugger report to see the latest support artifact.</p>';
5170
- return `<section class="absolute-voice-call-debugger-launch absolute-voice-call-debugger-launch--${escapeHtml9(model.status)}">
5164
+ return `<section class="absolute-voice-call-debugger-launch absolute-voice-call-debugger-launch--${escapeHtml(model.status)}">
5171
5165
  <header class="absolute-voice-call-debugger-launch__header">
5172
- <span class="absolute-voice-call-debugger-launch__eyebrow">${escapeHtml9(model.title)}</span>
5173
- <strong class="absolute-voice-call-debugger-launch__label">${escapeHtml9(model.label)}</strong>
5166
+ <span class="absolute-voice-call-debugger-launch__eyebrow">${escapeHtml(model.title)}</span>
5167
+ <strong class="absolute-voice-call-debugger-launch__label">${escapeHtml(model.label)}</strong>
5174
5168
  </header>
5175
- <p class="absolute-voice-call-debugger-launch__description">${escapeHtml9(model.description)}</p>
5176
- <a class="absolute-voice-call-debugger-launch__link" href="${escapeHtml9(model.href)}">${escapeHtml9(options.linkLabel ?? DEFAULT_LINK_LABEL)}</a>
5169
+ <p class="absolute-voice-call-debugger-launch__description">${escapeHtml(model.description)}</p>
5170
+ <a class="absolute-voice-call-debugger-launch__link" href="${escapeHtml(model.href)}">${escapeHtml(options.linkLabel ?? DEFAULT_LINK_LABEL)}</a>
5177
5171
  ${rows}
5178
- ${model.error ? `<p class="absolute-voice-call-debugger-launch__error">${escapeHtml9(model.error)}</p>` : ""}
5172
+ ${model.error ? `<p class="absolute-voice-call-debugger-launch__error">${escapeHtml(model.error)}</p>` : ""}
5179
5173
  </section>`;
5180
5174
  };
5181
5175
  var mountVoiceCallDebuggerLaunch = (element, path, options = {}) => {
@@ -5323,7 +5317,6 @@ var createVoiceSessionSnapshotStore = (path, options = {}) => {
5323
5317
  var DEFAULT_TITLE5 = "Session Snapshot";
5324
5318
  var DEFAULT_DESCRIPTION5 = "Portable call artifact with media graph, provider routing, proof, quality, and telephony evidence.";
5325
5319
  var DEFAULT_DOWNLOAD_LABEL = "Download snapshot";
5326
- var escapeHtml10 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
5327
5320
  var formatStatus = (status) => status ?? "n/a";
5328
5321
  var createVoiceSessionSnapshotViewModel = (state, options = {}) => {
5329
5322
  const snapshot = state.snapshot;
@@ -5373,23 +5366,23 @@ var createVoiceSessionSnapshotViewModel = (state, options = {}) => {
5373
5366
  var renderVoiceSessionSnapshotHTML = (state, options = {}) => {
5374
5367
  const model = createVoiceSessionSnapshotViewModel(state, options);
5375
5368
  const rows = model.rows.length ? `<dl>${model.rows.map((row) => `<div>
5376
- <dt>${escapeHtml10(row.label)}</dt>
5377
- <dd>${escapeHtml10(row.value)}</dd>
5369
+ <dt>${escapeHtml(row.label)}</dt>
5370
+ <dd>${escapeHtml(row.value)}</dd>
5378
5371
  </div>`).join("")}</dl>` : '<p class="absolute-voice-session-snapshot__empty">Load a session snapshot to see support diagnostics.</p>';
5379
5372
  const artifacts = model.artifacts.length ? `<div class="absolute-voice-session-snapshot__artifacts">${model.artifacts.map((artifact) => {
5380
- const body = `<strong>${escapeHtml10(artifact.label)}</strong><span>${escapeHtml10(artifact.status)}</span>`;
5381
- return artifact.href ? `<a href="${escapeHtml10(artifact.href)}">${body}</a>` : `<div>${body}</div>`;
5373
+ const body = `<strong>${escapeHtml(artifact.label)}</strong><span>${escapeHtml(artifact.status)}</span>`;
5374
+ return artifact.href ? `<a href="${escapeHtml(artifact.href)}">${body}</a>` : `<div>${body}</div>`;
5382
5375
  }).join("")}</div>` : "";
5383
- return `<section class="absolute-voice-session-snapshot absolute-voice-session-snapshot--${escapeHtml10(model.status)}">
5376
+ return `<section class="absolute-voice-session-snapshot absolute-voice-session-snapshot--${escapeHtml(model.status)}">
5384
5377
  <header class="absolute-voice-session-snapshot__header">
5385
- <span class="absolute-voice-session-snapshot__eyebrow">${escapeHtml10(model.title)}</span>
5386
- <strong class="absolute-voice-session-snapshot__label">${escapeHtml10(model.label)}</strong>
5378
+ <span class="absolute-voice-session-snapshot__eyebrow">${escapeHtml(model.title)}</span>
5379
+ <strong class="absolute-voice-session-snapshot__label">${escapeHtml(model.label)}</strong>
5387
5380
  </header>
5388
- <p class="absolute-voice-session-snapshot__description">${escapeHtml10(model.description)}</p>
5389
- ${model.showDownload ? `<button class="absolute-voice-session-snapshot__download" data-absolute-voice-session-snapshot-download type="button">${escapeHtml10(options.downloadLabel ?? DEFAULT_DOWNLOAD_LABEL)}</button>` : ""}
5381
+ <p class="absolute-voice-session-snapshot__description">${escapeHtml(model.description)}</p>
5382
+ ${model.showDownload ? `<button class="absolute-voice-session-snapshot__download" data-absolute-voice-session-snapshot-download type="button">${escapeHtml(options.downloadLabel ?? DEFAULT_DOWNLOAD_LABEL)}</button>` : ""}
5390
5383
  ${rows}
5391
5384
  ${artifacts}
5392
- ${model.error ? `<p class="absolute-voice-session-snapshot__error">${escapeHtml10(model.error)}</p>` : ""}
5385
+ ${model.error ? `<p class="absolute-voice-session-snapshot__error">${escapeHtml(model.error)}</p>` : ""}
5393
5386
  </section>`;
5394
5387
  };
5395
5388
  var downloadBlob = (blob, filename) => {
@@ -5544,7 +5537,6 @@ var createVoiceSessionObservabilityStore = (path, options = {}) => {
5544
5537
  // src/client/sessionObservabilityWidget.ts
5545
5538
  var DEFAULT_TITLE6 = "Session Observability";
5546
5539
  var DEFAULT_DESCRIPTION6 = "One support/debug report for a voice call across traces, provider recovery, tools, handoffs, guardrails, turn waterfalls, and incident handoff.";
5547
- var escapeHtml11 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
5548
5540
  var formatMs = (value) => typeof value === "number" ? `${value}ms` : "n/a";
5549
5541
  var createVoiceSessionObservabilityViewModel = (snapshot, options = {}) => {
5550
5542
  const report = snapshot.report;
@@ -5566,20 +5558,20 @@ var createVoiceSessionObservabilityViewModel = (snapshot, options = {}) => {
5566
5558
  updatedAt: snapshot.updatedAt
5567
5559
  };
5568
5560
  };
5569
- var renderLinks = (links) => links.length ? `<p class="absolute-voice-session-observability__actions">${links.map((link) => `<a href="${escapeHtml11(link.href)}">${escapeHtml11(link.label)}</a>`).join("")}</p>` : "";
5561
+ var renderLinks = (links) => links.length ? `<p class="absolute-voice-session-observability__actions">${links.map((link) => `<a href="${escapeHtml(link.href)}">${escapeHtml(link.label)}</a>`).join("")}</p>` : "";
5570
5562
  var renderVoiceSessionObservabilityHTML = (snapshot, options = {}) => {
5571
5563
  const model = createVoiceSessionObservabilityViewModel(snapshot, options);
5572
- const turns = model.turns.length ? `<div class="absolute-voice-session-observability__turns">${model.turns.map((turn) => `<article class="absolute-voice-session-observability__turn"><header><strong>${escapeHtml11(turn.turnId)}</strong><span>${escapeHtml11(turn.durationLabel)}</span></header><p>${escapeHtml11(turn.label)}</p></article>`).join("")}</div>` : '<p class="absolute-voice-session-observability__empty">Open a voice session to see turn waterfalls.</p>';
5573
- return `<section class="absolute-voice-session-observability absolute-voice-session-observability--${escapeHtml11(model.status)}">
5564
+ const turns = model.turns.length ? `<div class="absolute-voice-session-observability__turns">${model.turns.map((turn) => `<article class="absolute-voice-session-observability__turn"><header><strong>${escapeHtml(turn.turnId)}</strong><span>${escapeHtml(turn.durationLabel)}</span></header><p>${escapeHtml(turn.label)}</p></article>`).join("")}</div>` : '<p class="absolute-voice-session-observability__empty">Open a voice session to see turn waterfalls.</p>';
5565
+ return `<section class="absolute-voice-session-observability absolute-voice-session-observability--${escapeHtml(model.status)}">
5574
5566
  <header class="absolute-voice-session-observability__header">
5575
- <span class="absolute-voice-session-observability__eyebrow">${escapeHtml11(model.title)}</span>
5576
- <strong class="absolute-voice-session-observability__label">${escapeHtml11(model.label)}</strong>
5567
+ <span class="absolute-voice-session-observability__eyebrow">${escapeHtml(model.title)}</span>
5568
+ <strong class="absolute-voice-session-observability__label">${escapeHtml(model.label)}</strong>
5577
5569
  </header>
5578
- <p class="absolute-voice-session-observability__description">${escapeHtml11(model.description)}</p>
5579
- ${model.sessionId ? `<p class="absolute-voice-session-observability__session">${escapeHtml11(model.sessionId)}</p>` : ""}
5570
+ <p class="absolute-voice-session-observability__description">${escapeHtml(model.description)}</p>
5571
+ ${model.sessionId ? `<p class="absolute-voice-session-observability__session">${escapeHtml(model.sessionId)}</p>` : ""}
5580
5572
  ${renderLinks(model.links)}
5581
5573
  ${turns}
5582
- ${model.error ? `<p class="absolute-voice-session-observability__error">${escapeHtml11(model.error)}</p>` : ""}
5574
+ ${model.error ? `<p class="absolute-voice-session-observability__error">${escapeHtml(model.error)}</p>` : ""}
5583
5575
  </section>`;
5584
5576
  };
5585
5577
  var getVoiceSessionObservabilityCSS = () => `.absolute-voice-session-observability{border:1px solid #c8d9bf;border-radius:20px;background:#fbfff3;color:#18220d;padding:18px;box-shadow:0 18px 40px rgba(24,34,13,.12);font-family:inherit}.absolute-voice-session-observability--error,.absolute-voice-session-observability--failed{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-session-observability--warning{border-color:#fbbf24;background:#fffaf0}.absolute-voice-session-observability__header,.absolute-voice-session-observability__turn header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-session-observability__eyebrow{color:#4d7c0f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-session-observability__label{font-size:24px;line-height:1}.absolute-voice-session-observability__description,.absolute-voice-session-observability__turn p,.absolute-voice-session-observability__empty,.absolute-voice-session-observability__session{color:#4b5f3e}.absolute-voice-session-observability__actions{display:flex;flex-wrap:wrap;gap:10px;margin:14px 0}.absolute-voice-session-observability__actions a{color:#3f6212;font-weight:800}.absolute-voice-session-observability__turns{display:grid;gap:12px;margin-top:14px}.absolute-voice-session-observability__turn{background:#fff;border:1px solid #dcebcf;border-radius:16px;padding:14px}.absolute-voice-session-observability__turn p{margin:10px 0 0}.absolute-voice-session-observability__empty{margin:14px 0 0}.absolute-voice-session-observability__error{color:#9f1239;font-weight:700}`;
@@ -5881,7 +5873,6 @@ var createVoiceProviderSimulationControlsStore = (options) => {
5881
5873
  };
5882
5874
 
5883
5875
  // src/client/providerSimulationControlsWidget.ts
5884
- var escapeHtml12 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
5885
5876
  var formatKind = (kind) => (kind ?? "stt").toUpperCase();
5886
5877
  var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
5887
5878
  const configuredProviders = options.providers.filter((provider) => provider.configured !== false);
@@ -5901,18 +5892,18 @@ var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
5901
5892
  };
5902
5893
  var renderVoiceProviderSimulationControlsHTML = (snapshot, options) => {
5903
5894
  const model = createVoiceProviderSimulationControlsViewModel(snapshot, options);
5904
- const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${escapeHtml12(provider.provider)}"${!model.canSimulateFailure || snapshot.isRunning ? " disabled" : ""}>Simulate ${escapeHtml12(provider.provider)} ${escapeHtml12(formatKind(options.kind))} failure</button>`).join("");
5905
- const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${escapeHtml12(provider.provider)}"${snapshot.isRunning ? " disabled" : ""}>Mark ${escapeHtml12(provider.provider)} recovered</button>`).join("");
5895
+ const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${escapeHtml(provider.provider)}"${!model.canSimulateFailure || snapshot.isRunning ? " disabled" : ""}>Simulate ${escapeHtml(provider.provider)} ${escapeHtml(formatKind(options.kind))} failure</button>`).join("");
5896
+ const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${escapeHtml(provider.provider)}"${snapshot.isRunning ? " disabled" : ""}>Mark ${escapeHtml(provider.provider)} recovered</button>`).join("");
5906
5897
  return `<section class="absolute-voice-provider-simulation absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}">
5907
5898
  <header class="absolute-voice-provider-simulation__header">
5908
- <span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml12(model.title)}</span>
5909
- <strong class="absolute-voice-provider-simulation__label">${escapeHtml12(model.label)}</strong>
5899
+ <span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml(model.title)}</span>
5900
+ <strong class="absolute-voice-provider-simulation__label">${escapeHtml(model.label)}</strong>
5910
5901
  </header>
5911
- <p class="absolute-voice-provider-simulation__description">${escapeHtml12(model.description)}</p>
5912
- ${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${escapeHtml12(options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure.")}</p>`}
5902
+ <p class="absolute-voice-provider-simulation__description">${escapeHtml(model.description)}</p>
5903
+ ${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${escapeHtml(options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure.")}</p>`}
5913
5904
  <div class="absolute-voice-provider-simulation__actions">${failureButtons}${recoveryButtons}</div>
5914
- ${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${escapeHtml12(snapshot.error)}</p>` : ""}
5915
- ${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${escapeHtml12(model.resultText)}</pre>` : ""}
5905
+ ${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${escapeHtml(snapshot.error)}</p>` : ""}
5906
+ ${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${escapeHtml(model.resultText)}</pre>` : ""}
5916
5907
  </section>`;
5917
5908
  };
5918
5909
  var bindVoiceProviderSimulationControls = (element, store) => {
@@ -6069,7 +6060,6 @@ var createVoiceProviderCapabilitiesStore = (path = "/api/provider-capabilities",
6069
6060
  // src/client/providerCapabilitiesWidget.ts
6070
6061
  var DEFAULT_TITLE7 = "Provider Capabilities";
6071
6062
  var DEFAULT_DESCRIPTION7 = "Configured, selected, and healthy voice providers for this deployment.";
6072
- var escapeHtml13 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
6073
6063
  var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
6074
6064
  var formatKind2 = (kind) => kind.toUpperCase();
6075
6065
  var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
@@ -6124,25 +6114,25 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
6124
6114
  };
6125
6115
  var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
6126
6116
  const model = createVoiceProviderCapabilitiesViewModel(snapshot, options);
6127
- const capabilities = model.capabilities.length ? `<div class="absolute-voice-provider-capabilities__providers">${model.capabilities.map((capability) => `<article class="absolute-voice-provider-capabilities__provider absolute-voice-provider-capabilities__provider--${escapeHtml13(capability.status)}">
6117
+ const capabilities = model.capabilities.length ? `<div class="absolute-voice-provider-capabilities__providers">${model.capabilities.map((capability) => `<article class="absolute-voice-provider-capabilities__provider absolute-voice-provider-capabilities__provider--${escapeHtml(capability.status)}">
6128
6118
  <header>
6129
- <strong>${escapeHtml13(capability.label)}</strong>
6130
- <span>${escapeHtml13(formatStatus2(capability.status))}</span>
6119
+ <strong>${escapeHtml(capability.label)}</strong>
6120
+ <span>${escapeHtml(formatStatus2(capability.status))}</span>
6131
6121
  </header>
6132
- <p>${escapeHtml13(capability.detail)}</p>
6122
+ <p>${escapeHtml(capability.detail)}</p>
6133
6123
  <dl>${capability.rows.map((row) => `<div>
6134
- <dt>${escapeHtml13(row.label)}</dt>
6135
- <dd>${escapeHtml13(row.value)}</dd>
6124
+ <dt>${escapeHtml(row.label)}</dt>
6125
+ <dd>${escapeHtml(row.value)}</dd>
6136
6126
  </div>`).join("")}</dl>
6137
6127
  </article>`).join("")}</div>` : '<p class="absolute-voice-provider-capabilities__empty">Configure provider capabilities to see deployment coverage.</p>';
6138
- return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml13(model.status)}">
6128
+ return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml(model.status)}">
6139
6129
  <header class="absolute-voice-provider-capabilities__header">
6140
- <span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml13(model.title)}</span>
6141
- <strong class="absolute-voice-provider-capabilities__label">${escapeHtml13(model.label)}</strong>
6130
+ <span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml(model.title)}</span>
6131
+ <strong class="absolute-voice-provider-capabilities__label">${escapeHtml(model.label)}</strong>
6142
6132
  </header>
6143
- <p class="absolute-voice-provider-capabilities__description">${escapeHtml13(model.description)}</p>
6133
+ <p class="absolute-voice-provider-capabilities__description">${escapeHtml(model.description)}</p>
6144
6134
  ${capabilities}
6145
- ${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml13(model.error)}</p>` : ""}
6135
+ ${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml(model.error)}</p>` : ""}
6146
6136
  </section>`;
6147
6137
  };
6148
6138
  var getVoiceProviderCapabilitiesCSS = () => `.absolute-voice-provider-capabilities{border:1px solid #bfd7ea;border-radius:20px;background:#f6fbff;color:#08131f;padding:18px;box-shadow:0 18px 40px rgba(14,51,78,.12);font-family:inherit}.absolute-voice-provider-capabilities--error,.absolute-voice-provider-capabilities--warning{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-provider-capabilities__header,.absolute-voice-provider-capabilities__provider header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-provider-capabilities__eyebrow{color:#255f85;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-provider-capabilities__label{font-size:24px;line-height:1}.absolute-voice-provider-capabilities__description,.absolute-voice-provider-capabilities__provider p,.absolute-voice-provider-capabilities__provider dt,.absolute-voice-provider-capabilities__empty{color:#405467}.absolute-voice-provider-capabilities__providers{display:grid;gap:12px;margin-top:14px}.absolute-voice-provider-capabilities__provider{background:#fff;border:1px solid #d7e7f3;border-radius:16px;padding:14px}.absolute-voice-provider-capabilities__provider--selected,.absolute-voice-provider-capabilities__provider--healthy{border-color:#86efac}.absolute-voice-provider-capabilities__provider--degraded,.absolute-voice-provider-capabilities__provider--rate-limited,.absolute-voice-provider-capabilities__provider--suppressed,.absolute-voice-provider-capabilities__provider--unconfigured{border-color:#f2a7a7}.absolute-voice-provider-capabilities__provider p{margin:10px 0}.absolute-voice-provider-capabilities__provider dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-provider-capabilities__provider div{background:#f6fbff;border:1px solid #d7e7f3;border-radius:12px;padding:8px}.absolute-voice-provider-capabilities__provider dt{font-size:12px}.absolute-voice-provider-capabilities__provider dd{font-weight:800;margin:4px 0 0}.absolute-voice-provider-capabilities__empty{margin:14px 0 0}.absolute-voice-provider-capabilities__error{color:#9f1239;font-weight:700}`;
@@ -6270,7 +6260,6 @@ var createVoiceProviderContractsStore = (path = "/api/provider-contracts", optio
6270
6260
  // src/client/providerContractsWidget.ts
6271
6261
  var DEFAULT_TITLE8 = "Provider Contracts";
6272
6262
  var DEFAULT_DESCRIPTION8 = "Production contract coverage for provider env, latency, fallback, streaming, and capabilities.";
6273
- var escapeHtml14 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
6274
6263
  var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
6275
6264
  var formatStatus3 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
6276
6265
  var contractDetail = (row) => {
@@ -6314,26 +6303,26 @@ var createVoiceProviderContractsViewModel = (snapshot, options = {}) => {
6314
6303
  };
6315
6304
  var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
6316
6305
  const model = createVoiceProviderContractsViewModel(snapshot, options);
6317
- const rows = model.rows.length ? `<div class="absolute-voice-provider-contracts__rows">${model.rows.map((row) => `<article class="absolute-voice-provider-contracts__row absolute-voice-provider-contracts__row--${escapeHtml14(row.status)}">
6306
+ const rows = model.rows.length ? `<div class="absolute-voice-provider-contracts__rows">${model.rows.map((row) => `<article class="absolute-voice-provider-contracts__row absolute-voice-provider-contracts__row--${escapeHtml(row.status)}">
6318
6307
  <header>
6319
- <strong>${escapeHtml14(row.label)}</strong>
6320
- <span>${escapeHtml14(formatStatus3(row.status))}</span>
6308
+ <strong>${escapeHtml(row.label)}</strong>
6309
+ <span>${escapeHtml(formatStatus3(row.status))}</span>
6321
6310
  </header>
6322
- <p>${escapeHtml14(row.detail)}</p>
6323
- ${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${escapeHtml14(remediation.href)}">${escapeHtml14(remediation.label)}</a>` : `<strong>${escapeHtml14(remediation.label)}</strong>`}<span>${escapeHtml14(remediation.detail)}</span></li>`).join("")}</ul>` : ""}
6311
+ <p>${escapeHtml(row.detail)}</p>
6312
+ ${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${escapeHtml(remediation.href)}">${escapeHtml(remediation.label)}</a>` : `<strong>${escapeHtml(remediation.label)}</strong>`}<span>${escapeHtml(remediation.detail)}</span></li>`).join("")}</ul>` : ""}
6324
6313
  <dl>${row.rows.map((item) => `<div>
6325
- <dt>${escapeHtml14(item.label)}</dt>
6326
- <dd>${escapeHtml14(item.value)}</dd>
6314
+ <dt>${escapeHtml(item.label)}</dt>
6315
+ <dd>${escapeHtml(item.value)}</dd>
6327
6316
  </div>`).join("")}</dl>
6328
6317
  </article>`).join("")}</div>` : '<p class="absolute-voice-provider-contracts__empty">Configure provider contracts to see production coverage.</p>';
6329
- return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${escapeHtml14(model.status)}">
6318
+ return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${escapeHtml(model.status)}">
6330
6319
  <header class="absolute-voice-provider-contracts__header">
6331
- <span class="absolute-voice-provider-contracts__eyebrow">${escapeHtml14(model.title)}</span>
6332
- <strong class="absolute-voice-provider-contracts__label">${escapeHtml14(model.label)}</strong>
6320
+ <span class="absolute-voice-provider-contracts__eyebrow">${escapeHtml(model.title)}</span>
6321
+ <strong class="absolute-voice-provider-contracts__label">${escapeHtml(model.label)}</strong>
6333
6322
  </header>
6334
- <p class="absolute-voice-provider-contracts__description">${escapeHtml14(model.description)}</p>
6323
+ <p class="absolute-voice-provider-contracts__description">${escapeHtml(model.description)}</p>
6335
6324
  ${rows}
6336
- ${model.error ? `<p class="absolute-voice-provider-contracts__error">${escapeHtml14(model.error)}</p>` : ""}
6325
+ ${model.error ? `<p class="absolute-voice-provider-contracts__error">${escapeHtml(model.error)}</p>` : ""}
6337
6326
  </section>`;
6338
6327
  };
6339
6328
  var getVoiceProviderContractsCSS = () => `.absolute-voice-provider-contracts{border:1px solid #b8dcc7;border-radius:20px;background:#f7fff9;color:#09140d;padding:18px;box-shadow:0 18px 40px rgba(21,83,45,.12);font-family:inherit}.absolute-voice-provider-contracts--error,.absolute-voice-provider-contracts--warning{border-color:#f2a7a7;background:#fff7f4}.absolute-voice-provider-contracts__header,.absolute-voice-provider-contracts__row header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-provider-contracts__eyebrow{color:#166534;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-provider-contracts__label{font-size:24px;line-height:1}.absolute-voice-provider-contracts__description,.absolute-voice-provider-contracts__row p,.absolute-voice-provider-contracts__row dt,.absolute-voice-provider-contracts__empty{color:#405448}.absolute-voice-provider-contracts__rows{display:grid;gap:12px;margin-top:14px}.absolute-voice-provider-contracts__row{background:#fff;border:1px solid #d6eadb;border-radius:16px;padding:14px}.absolute-voice-provider-contracts__row--pass{border-color:#86efac}.absolute-voice-provider-contracts__row--warn,.absolute-voice-provider-contracts__row--fail{border-color:#f2a7a7}.absolute-voice-provider-contracts__row p{margin:10px 0}.absolute-voice-provider-contracts__remediations{display:grid;gap:8px;list-style:none;margin:0 0 10px;padding:0}.absolute-voice-provider-contracts__remediations li{background:#fff7ed;border:1px solid #fed7aa;border-radius:12px;display:grid;gap:3px;padding:8px}.absolute-voice-provider-contracts__remediations a,.absolute-voice-provider-contracts__remediations strong{color:#9a3412}.absolute-voice-provider-contracts__remediations span{color:#7c2d12}.absolute-voice-provider-contracts__row dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-provider-contracts__row div{background:#f7fff9;border:1px solid #d6eadb;border-radius:12px;padding:8px}.absolute-voice-provider-contracts__row dt{font-size:12px}.absolute-voice-provider-contracts__row dd{font-weight:800;margin:4px 0 0}.absolute-voice-provider-contracts__error{color:#9f1239;font-weight:700}`;
@@ -6468,7 +6457,6 @@ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {
6468
6457
  // src/client/providerStatusWidget.ts
6469
6458
  var DEFAULT_TITLE9 = "Voice Providers";
6470
6459
  var DEFAULT_DESCRIPTION9 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
6471
- var escapeHtml15 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
6472
6460
  var formatProvider3 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
6473
6461
  var formatStatus4 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
6474
6462
  var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
@@ -6524,25 +6512,25 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
6524
6512
  };
6525
6513
  var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
6526
6514
  const model = createVoiceProviderStatusViewModel(snapshot, options);
6527
- const providers = model.providers.length ? `<div class="absolute-voice-provider-status__providers">${model.providers.map((provider) => `<article class="absolute-voice-provider-status__provider absolute-voice-provider-status__provider--${escapeHtml15(provider.status)}">
6515
+ const providers = model.providers.length ? `<div class="absolute-voice-provider-status__providers">${model.providers.map((provider) => `<article class="absolute-voice-provider-status__provider absolute-voice-provider-status__provider--${escapeHtml(provider.status)}">
6528
6516
  <header>
6529
- <strong>${escapeHtml15(provider.label)}</strong>
6530
- <span>${escapeHtml15(formatStatus4(provider.status))}</span>
6517
+ <strong>${escapeHtml(provider.label)}</strong>
6518
+ <span>${escapeHtml(formatStatus4(provider.status))}</span>
6531
6519
  </header>
6532
- <p>${escapeHtml15(provider.detail)}</p>
6520
+ <p>${escapeHtml(provider.detail)}</p>
6533
6521
  <dl>${provider.rows.map((row) => `<div>
6534
- <dt>${escapeHtml15(row.label)}</dt>
6535
- <dd>${escapeHtml15(row.value)}</dd>
6522
+ <dt>${escapeHtml(row.label)}</dt>
6523
+ <dd>${escapeHtml(row.value)}</dd>
6536
6524
  </div>`).join("")}</dl>
6537
6525
  </article>`).join("")}</div>` : '<p class="absolute-voice-provider-status__empty">Run voice traffic to see provider health.</p>';
6538
- return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml15(model.status)}">
6526
+ return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml(model.status)}">
6539
6527
  <header class="absolute-voice-provider-status__header">
6540
- <span class="absolute-voice-provider-status__eyebrow">${escapeHtml15(model.title)}</span>
6541
- <strong class="absolute-voice-provider-status__label">${escapeHtml15(model.label)}</strong>
6528
+ <span class="absolute-voice-provider-status__eyebrow">${escapeHtml(model.title)}</span>
6529
+ <strong class="absolute-voice-provider-status__label">${escapeHtml(model.label)}</strong>
6542
6530
  </header>
6543
- <p class="absolute-voice-provider-status__description">${escapeHtml15(model.description)}</p>
6531
+ <p class="absolute-voice-provider-status__description">${escapeHtml(model.description)}</p>
6544
6532
  ${providers}
6545
- ${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml15(model.error)}</p>` : ""}
6533
+ ${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml(model.error)}</p>` : ""}
6546
6534
  </section>`;
6547
6535
  };
6548
6536
  var getVoiceProviderStatusCSS = () => `.absolute-voice-provider-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-provider-status--error,.absolute-voice-provider-status--warning{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-provider-status__header,.absolute-voice-provider-status__provider header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-provider-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-provider-status__label{font-size:24px;line-height:1}.absolute-voice-provider-status__description,.absolute-voice-provider-status__provider p,.absolute-voice-provider-status__provider dt,.absolute-voice-provider-status__empty{color:#514733}.absolute-voice-provider-status__providers{display:grid;gap:12px;margin-top:14px}.absolute-voice-provider-status__provider{background:#fff;border:1px solid #eee4d2;border-radius:16px;padding:14px}.absolute-voice-provider-status__provider--degraded,.absolute-voice-provider-status__provider--rate-limited,.absolute-voice-provider-status__provider--suppressed{border-color:#f2a7a7}.absolute-voice-provider-status__provider--recoverable{border-color:#fbbf24}.absolute-voice-provider-status__provider p{margin:10px 0}.absolute-voice-provider-status__provider dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-provider-status__provider div{background:#fffaf0;border:1px solid #eee4d2;border-radius:12px;padding:8px}.absolute-voice-provider-status__provider dt{font-size:12px}.absolute-voice-provider-status__provider dd{font-weight:800;margin:4px 0 0}.absolute-voice-provider-status__empty{margin:14px 0 0}.absolute-voice-provider-status__error{color:#9f1239;font-weight:700}`;
@@ -6675,7 +6663,6 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
6675
6663
  // src/client/routingStatusWidget.ts
6676
6664
  var DEFAULT_TITLE10 = "Voice Routing";
6677
6665
  var DEFAULT_DESCRIPTION10 = "Latest provider routing decision from the self-hosted trace store.";
6678
- var escapeHtml16 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
6679
6666
  var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
6680
6667
  var formatProviderRoutes = (routes) => routes && typeof routes === "object" ? Object.entries(routes).map(([role, provider]) => `${role}: ${formatValue(provider)}`).join(", ") || "None" : "None";
6681
6668
  var getProviderRoute = (routes, role) => routes && typeof routes === "object" ? formatValue(routes[role], "Not configured") : "Not configured";
@@ -6757,22 +6744,22 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
6757
6744
  var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
6758
6745
  const model = createVoiceRoutingStatusViewModel(snapshot, options);
6759
6746
  const activeStack = model.activeStack.length ? `<div class="absolute-voice-routing-status__stack" aria-label="Active voice stack">${model.activeStack.map((item) => `<div>
6760
- <span>${escapeHtml16(item.label)}</span>
6761
- <strong>${escapeHtml16(item.value)}</strong>
6747
+ <span>${escapeHtml(item.label)}</span>
6748
+ <strong>${escapeHtml(item.value)}</strong>
6762
6749
  </div>`).join("")}</div>` : "";
6763
6750
  const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
6764
- <span>${escapeHtml16(row.label)}</span>
6765
- <strong>${escapeHtml16(row.value)}</strong>
6751
+ <span>${escapeHtml(row.label)}</span>
6752
+ <strong>${escapeHtml(row.value)}</strong>
6766
6753
  </div>`).join("")}</div>` : '<p class="absolute-voice-routing-status__empty">Start a voice session to see the selected provider.</p>';
6767
- return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml16(model.status)}">
6754
+ return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml(model.status)}">
6768
6755
  <header class="absolute-voice-routing-status__header">
6769
- <span class="absolute-voice-routing-status__eyebrow">${escapeHtml16(model.title)}</span>
6770
- <strong class="absolute-voice-routing-status__label">${escapeHtml16(model.label)}</strong>
6756
+ <span class="absolute-voice-routing-status__eyebrow">${escapeHtml(model.title)}</span>
6757
+ <strong class="absolute-voice-routing-status__label">${escapeHtml(model.label)}</strong>
6771
6758
  </header>
6772
- <p class="absolute-voice-routing-status__description">${escapeHtml16(model.description)}</p>
6759
+ <p class="absolute-voice-routing-status__description">${escapeHtml(model.description)}</p>
6773
6760
  ${activeStack}
6774
6761
  ${rows}
6775
- ${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml16(model.error)}</p>` : ""}
6762
+ ${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml(model.error)}</p>` : ""}
6776
6763
  </section>`;
6777
6764
  };
6778
6765
  var getVoiceRoutingStatusCSS = () => `.absolute-voice-routing-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-routing-status--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-routing-status__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-routing-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-routing-status__label{font-size:24px;line-height:1}.absolute-voice-routing-status__description{color:#514733;margin:12px 0 0}.absolute-voice-routing-status__stack{background:linear-gradient(135deg,#16130d,#49391f);border-radius:18px;color:#fff;display:grid;gap:8px;grid-template-columns:repeat(5,minmax(0,1fr));margin-top:14px;padding:12px}.absolute-voice-routing-status__stack div{border-left:1px solid rgba(255,255,255,.18);padding-left:10px}.absolute-voice-routing-status__stack div:first-child{border-left:0;padding-left:0}.absolute-voice-routing-status__stack span{color:#e9d9b8;display:block;font-size:11px;font-weight:800;letter-spacing:.08em;margin-bottom:5px;text-transform:uppercase}.absolute-voice-routing-status__stack strong{display:block;font-size:13px;line-height:1.25;overflow-wrap:anywhere}.absolute-voice-routing-status__grid{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin-top:14px}.absolute-voice-routing-status__grid div{background:#fff;border:1px solid #eee4d2;border-radius:14px;padding:10px 12px}.absolute-voice-routing-status__grid span{color:#655944;display:block;font-size:12px;margin-bottom:4px}.absolute-voice-routing-status__grid strong{overflow-wrap:anywhere}.absolute-voice-routing-status__empty{color:#655944;margin:14px 0 0}.absolute-voice-routing-status__error{color:#9f1239;font-weight:700}@media (max-width:760px){.absolute-voice-routing-status__stack{grid-template-columns:repeat(2,minmax(0,1fr))}.absolute-voice-routing-status__stack div{border-left:0;border-top:1px solid rgba(255,255,255,.18);padding-left:0;padding-top:8px}.absolute-voice-routing-status__stack div:first-child{border-top:0;padding-top:0}}`;
@@ -6905,7 +6892,6 @@ var createVoiceTraceTimelineStore = (path = "/api/voice-traces", options = {}) =
6905
6892
  // src/client/traceTimelineWidget.ts
6906
6893
  var DEFAULT_TITLE11 = "Voice Traces";
6907
6894
  var DEFAULT_DESCRIPTION11 = "Latest call timelines with provider latency, fallbacks, handoffs, and errors from your self-hosted trace store.";
6908
- var escapeHtml17 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
6909
6895
  var formatMs2 = (value) => typeof value === "number" ? `${value}ms` : "n/a";
6910
6896
  var formatProviders = (session) => session.providers.length ? session.providers.map((provider) => provider.provider).join(", ") : "No providers";
6911
6897
  var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
@@ -6935,27 +6921,27 @@ var renderVoiceTraceTimelineWidgetHTML = (snapshot, options = {}) => {
6935
6921
  const model = createVoiceTraceTimelineViewModel(snapshot, options);
6936
6922
  const sessions = model.sessions.length ? `<div class="absolute-voice-trace-timeline__sessions">${model.sessions.map((session) => {
6937
6923
  const supportLinks = [
6938
- `<a href="${escapeHtml17(session.detailHref)}">Open timeline</a>`,
6939
- session.operationsRecordHref ? `<a href="${escapeHtml17(session.operationsRecordHref)}">Open operations record</a>` : undefined,
6940
- session.incidentBundleHref ? `<a href="${escapeHtml17(session.incidentBundleHref)}">Export incident bundle</a>` : undefined
6924
+ `<a href="${escapeHtml(session.detailHref)}">Open timeline</a>`,
6925
+ session.operationsRecordHref ? `<a href="${escapeHtml(session.operationsRecordHref)}">Open operations record</a>` : undefined,
6926
+ session.incidentBundleHref ? `<a href="${escapeHtml(session.incidentBundleHref)}">Export incident bundle</a>` : undefined
6941
6927
  ].filter(Boolean).join("");
6942
- return `<article class="absolute-voice-trace-timeline__session absolute-voice-trace-timeline__session--${escapeHtml17(session.status)}">
6928
+ return `<article class="absolute-voice-trace-timeline__session absolute-voice-trace-timeline__session--${escapeHtml(session.status)}">
6943
6929
  <header>
6944
- <strong>${escapeHtml17(session.sessionId)}</strong>
6945
- <span>${escapeHtml17(session.status)}</span>
6930
+ <strong>${escapeHtml(session.sessionId)}</strong>
6931
+ <span>${escapeHtml(session.status)}</span>
6946
6932
  </header>
6947
- <p>${escapeHtml17(session.label)} \xB7 ${escapeHtml17(session.durationLabel)} \xB7 ${escapeHtml17(session.providerLabel)}</p>
6933
+ <p>${escapeHtml(session.label)} \xB7 ${escapeHtml(session.durationLabel)} \xB7 ${escapeHtml(session.providerLabel)}</p>
6948
6934
  <p class="absolute-voice-trace-timeline__actions">${supportLinks}</p>
6949
6935
  </article>`;
6950
6936
  }).join("")}</div>` : '<p class="absolute-voice-trace-timeline__empty">Run a voice session to see call timelines.</p>';
6951
- return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml17(model.status)}">
6937
+ return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml(model.status)}">
6952
6938
  <header class="absolute-voice-trace-timeline__header">
6953
- <span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml17(model.title)}</span>
6954
- <strong class="absolute-voice-trace-timeline__label">${escapeHtml17(model.label)}</strong>
6939
+ <span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml(model.title)}</span>
6940
+ <strong class="absolute-voice-trace-timeline__label">${escapeHtml(model.label)}</strong>
6955
6941
  </header>
6956
- <p class="absolute-voice-trace-timeline__description">${escapeHtml17(model.description)}</p>
6942
+ <p class="absolute-voice-trace-timeline__description">${escapeHtml(model.description)}</p>
6957
6943
  ${sessions}
6958
- ${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml17(model.error)}</p>` : ""}
6944
+ ${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml(model.error)}</p>` : ""}
6959
6945
  </section>`;
6960
6946
  };
6961
6947
  var getVoiceTraceTimelineCSS = () => `.absolute-voice-trace-timeline{border:1px solid #bad7d3;border-radius:20px;background:#f3fffb;color:#09201c;padding:18px;box-shadow:0 18px 40px rgba(9,32,28,.12);font-family:inherit}.absolute-voice-trace-timeline--error,.absolute-voice-trace-timeline--failed{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-trace-timeline--warning{border-color:#fbbf24;background:#fffaf0}.absolute-voice-trace-timeline__header,.absolute-voice-trace-timeline__session header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-trace-timeline__eyebrow{color:#17665b;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-trace-timeline__label{font-size:24px;line-height:1}.absolute-voice-trace-timeline__description,.absolute-voice-trace-timeline__session p,.absolute-voice-trace-timeline__empty{color:#35544f}.absolute-voice-trace-timeline__sessions{display:grid;gap:12px;margin-top:14px}.absolute-voice-trace-timeline__session{background:#fff;border:1px solid #cfe7e2;border-radius:16px;padding:14px}.absolute-voice-trace-timeline__session--failed{border-color:#f2a7a7}.absolute-voice-trace-timeline__session--warning{border-color:#fbbf24}.absolute-voice-trace-timeline__session p{margin:10px 0}.absolute-voice-trace-timeline__actions{display:flex;flex-wrap:wrap;gap:10px}.absolute-voice-trace-timeline__session a{color:#0f766e;font-weight:800}.absolute-voice-trace-timeline__empty{margin:14px 0 0}.absolute-voice-trace-timeline__error{color:#9f1239;font-weight:700}`;
@@ -7087,7 +7073,6 @@ var createVoiceAgentSquadStatusStore = (path = "/api/voice-traces", options = {}
7087
7073
  // src/client/agentSquadStatusWidget.ts
7088
7074
  var DEFAULT_TITLE12 = "Voice Agent Squad";
7089
7075
  var DEFAULT_DESCRIPTION12 = "Current specialist and recent handoffs from your self-hosted voice traces.";
7090
- var escapeHtml18 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
7091
7076
  var labelFor = (current) => {
7092
7077
  if (!current)
7093
7078
  return "Waiting for specialist activity";
@@ -7114,24 +7099,24 @@ var renderVoiceAgentSquadStatusHTML = (snapshot, options = {}) => {
7114
7099
  const model = createVoiceAgentSquadStatusViewModel(snapshot, options);
7115
7100
  const current = model.current;
7116
7101
  const rows = model.sessions.length ? model.sessions.slice(0, 5).map((session) => `<li>
7117
- <span>${escapeHtml18(session.sessionId)}</span>
7118
- <strong>${escapeHtml18(session.targetAgentId ?? "none")}</strong>
7119
- <em>${escapeHtml18(session.status)}</em>
7120
- ${session.summary || session.reason ? `<p>${escapeHtml18(session.summary ?? session.reason ?? "")}</p>` : ""}
7102
+ <span>${escapeHtml(session.sessionId)}</span>
7103
+ <strong>${escapeHtml(session.targetAgentId ?? "none")}</strong>
7104
+ <em>${escapeHtml(session.status)}</em>
7105
+ ${session.summary || session.reason ? `<p>${escapeHtml(session.summary ?? session.reason ?? "")}</p>` : ""}
7121
7106
  </li>`).join("") : "<li><span>No squad traces yet.</span><strong>Waiting</strong></li>";
7122
7107
  return `<section class="absolute-voice-agent-squad-status">
7123
7108
  <header>
7124
- <span>${escapeHtml18(model.title)}</span>
7125
- <strong>${escapeHtml18(model.label)}</strong>
7109
+ <span>${escapeHtml(model.title)}</span>
7110
+ <strong>${escapeHtml(model.label)}</strong>
7126
7111
  </header>
7127
- <p>${escapeHtml18(model.description)}</p>
7112
+ <p>${escapeHtml(model.description)}</p>
7128
7113
  <div>
7129
- <span>Session</span><strong>${escapeHtml18(current?.sessionId ?? "n/a")}</strong>
7130
- <span>From</span><strong>${escapeHtml18(current?.fromAgentId ?? "n/a")}</strong>
7131
- <span>Status</span><strong>${escapeHtml18(current?.status ?? "idle")}</strong>
7114
+ <span>Session</span><strong>${escapeHtml(current?.sessionId ?? "n/a")}</strong>
7115
+ <span>From</span><strong>${escapeHtml(current?.fromAgentId ?? "n/a")}</strong>
7116
+ <span>Status</span><strong>${escapeHtml(current?.status ?? "idle")}</strong>
7132
7117
  </div>
7133
7118
  <ul>${rows}</ul>
7134
- ${model.error ? `<p class="absolute-voice-agent-squad-status__error">${escapeHtml18(model.error)}</p>` : ""}
7119
+ ${model.error ? `<p class="absolute-voice-agent-squad-status__error">${escapeHtml(model.error)}</p>` : ""}
7135
7120
  </section>`;
7136
7121
  };
7137
7122
  var getVoiceAgentSquadStatusCSS = () => `.absolute-voice-agent-squad-status{border:1px solid #38bdf866;border-radius:20px;background:#0f172a;color:#f8fafc;padding:18px;font-family:inherit}.absolute-voice-agent-squad-status header{display:grid;gap:4px}.absolute-voice-agent-squad-status header span{color:#7dd3fc;font-size:12px;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-agent-squad-status header strong{font-size:20px}.absolute-voice-agent-squad-status p{color:#cbd5e1}.absolute-voice-agent-squad-status div{display:grid;gap:6px;grid-template-columns:max-content 1fr;margin:14px 0}.absolute-voice-agent-squad-status div span{color:#94a3b8}.absolute-voice-agent-squad-status ul{display:grid;gap:8px;list-style:none;margin:0;padding:0}.absolute-voice-agent-squad-status li{background:#020617;border:1px solid #1e293b;border-radius:14px;padding:10px}.absolute-voice-agent-squad-status li span{color:#94a3b8;display:block;font-size:12px}.absolute-voice-agent-squad-status li strong{display:block}.absolute-voice-agent-squad-status li em{color:#7dd3fc;font-style:normal}.absolute-voice-agent-squad-status__error{color:#fecaca;font-weight:800}`;
@@ -7294,7 +7279,6 @@ var createVoiceTurnLatencyStore = (path = "/api/turn-latency", options = {}) =>
7294
7279
  var DEFAULT_TITLE13 = "Turn Latency";
7295
7280
  var DEFAULT_DESCRIPTION13 = "Per-turn timing from first transcript to commit and assistant response start.";
7296
7281
  var DEFAULT_PROOF_LABEL = "Run latency proof";
7297
- var escapeHtml19 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
7298
7282
  var formatMs3 = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
7299
7283
  var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
7300
7284
  const turns = (snapshot.report?.turns ?? []).map((turn) => ({
@@ -7322,25 +7306,25 @@ var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
7322
7306
  };
7323
7307
  var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
7324
7308
  const model = createVoiceTurnLatencyViewModel(snapshot, options);
7325
- const turns = model.turns.length ? `<div class="absolute-voice-turn-latency__turns">${model.turns.map((turn) => `<article class="absolute-voice-turn-latency__turn absolute-voice-turn-latency__turn--${escapeHtml19(turn.status)}">
7309
+ const turns = model.turns.length ? `<div class="absolute-voice-turn-latency__turns">${model.turns.map((turn) => `<article class="absolute-voice-turn-latency__turn absolute-voice-turn-latency__turn--${escapeHtml(turn.status)}">
7326
7310
  <header>
7327
- <strong>${escapeHtml19(turn.label)}</strong>
7328
- <span>${escapeHtml19(turn.status)}</span>
7311
+ <strong>${escapeHtml(turn.label)}</strong>
7312
+ <span>${escapeHtml(turn.status)}</span>
7329
7313
  </header>
7330
7314
  <dl>${turn.rows.map((row) => `<div>
7331
- <dt>${escapeHtml19(row.label)}</dt>
7332
- <dd>${escapeHtml19(row.value)}</dd>
7315
+ <dt>${escapeHtml(row.label)}</dt>
7316
+ <dd>${escapeHtml(row.value)}</dd>
7333
7317
  </div>`).join("")}</dl>
7334
7318
  </article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
7335
- return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml19(model.status)}">
7319
+ return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml(model.status)}">
7336
7320
  <header class="absolute-voice-turn-latency__header">
7337
- <span class="absolute-voice-turn-latency__eyebrow">${escapeHtml19(model.title)}</span>
7338
- <strong class="absolute-voice-turn-latency__label">${escapeHtml19(model.label)}</strong>
7321
+ <span class="absolute-voice-turn-latency__eyebrow">${escapeHtml(model.title)}</span>
7322
+ <strong class="absolute-voice-turn-latency__label">${escapeHtml(model.label)}</strong>
7339
7323
  </header>
7340
- <p class="absolute-voice-turn-latency__description">${escapeHtml19(model.description)}</p>
7341
- ${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml19(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
7324
+ <p class="absolute-voice-turn-latency__description">${escapeHtml(model.description)}</p>
7325
+ ${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
7342
7326
  ${turns}
7343
- ${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml19(model.error)}</p>` : ""}
7327
+ ${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml(model.error)}</p>` : ""}
7344
7328
  </section>`;
7345
7329
  };
7346
7330
  var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
@@ -7481,7 +7465,6 @@ var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) =>
7481
7465
  // src/client/turnQualityWidget.ts
7482
7466
  var DEFAULT_TITLE14 = "Turn Quality";
7483
7467
  var DEFAULT_DESCRIPTION14 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
7484
- var escapeHtml20 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
7485
7468
  var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
7486
7469
  var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
7487
7470
  var getTurnDetail = (turn) => {
@@ -7537,25 +7520,25 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
7537
7520
  };
7538
7521
  var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
7539
7522
  const model = createVoiceTurnQualityViewModel(snapshot, options);
7540
- const turns = model.turns.length ? `<div class="absolute-voice-turn-quality__turns">${model.turns.map((turn) => `<article class="absolute-voice-turn-quality__turn absolute-voice-turn-quality__turn--${escapeHtml20(turn.status)}">
7523
+ const turns = model.turns.length ? `<div class="absolute-voice-turn-quality__turns">${model.turns.map((turn) => `<article class="absolute-voice-turn-quality__turn absolute-voice-turn-quality__turn--${escapeHtml(turn.status)}">
7541
7524
  <header>
7542
- <strong>${escapeHtml20(turn.label)}</strong>
7543
- <span>${escapeHtml20(turn.status)}</span>
7525
+ <strong>${escapeHtml(turn.label)}</strong>
7526
+ <span>${escapeHtml(turn.status)}</span>
7544
7527
  </header>
7545
- <p>${escapeHtml20(turn.detail)}</p>
7528
+ <p>${escapeHtml(turn.detail)}</p>
7546
7529
  <dl>${turn.rows.map((row) => `<div>
7547
- <dt>${escapeHtml20(row.label)}</dt>
7548
- <dd>${escapeHtml20(row.value)}</dd>
7530
+ <dt>${escapeHtml(row.label)}</dt>
7531
+ <dd>${escapeHtml(row.value)}</dd>
7549
7532
  </div>`).join("")}</dl>
7550
7533
  </article>`).join("")}</div>` : '<p class="absolute-voice-turn-quality__empty">Complete a voice turn to see STT quality diagnostics.</p>';
7551
- return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml20(model.status)}">
7534
+ return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml(model.status)}">
7552
7535
  <header class="absolute-voice-turn-quality__header">
7553
- <span class="absolute-voice-turn-quality__eyebrow">${escapeHtml20(model.title)}</span>
7554
- <strong class="absolute-voice-turn-quality__label">${escapeHtml20(model.label)}</strong>
7536
+ <span class="absolute-voice-turn-quality__eyebrow">${escapeHtml(model.title)}</span>
7537
+ <strong class="absolute-voice-turn-quality__label">${escapeHtml(model.label)}</strong>
7555
7538
  </header>
7556
- <p class="absolute-voice-turn-quality__description">${escapeHtml20(model.description)}</p>
7539
+ <p class="absolute-voice-turn-quality__description">${escapeHtml(model.description)}</p>
7557
7540
  ${turns}
7558
- ${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml20(model.error)}</p>` : ""}
7541
+ ${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml(model.error)}</p>` : ""}
7559
7542
  </section>`;
7560
7543
  };
7561
7544
  var getVoiceTurnQualityCSS = () => `.absolute-voice-turn-quality{border:1px solid #e4d1a3;border-radius:20px;background:#fff9eb;color:#17120a;padding:18px;box-shadow:0 18px 40px rgba(73,48,14,.12);font-family:inherit}.absolute-voice-turn-quality--error,.absolute-voice-turn-quality--warning{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-turn-quality__header,.absolute-voice-turn-quality__turn header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-turn-quality__eyebrow{color:#8a5a0a;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-turn-quality__label{font-size:24px;line-height:1}.absolute-voice-turn-quality__description,.absolute-voice-turn-quality__turn p,.absolute-voice-turn-quality__turn dt,.absolute-voice-turn-quality__empty{color:#5a4930}.absolute-voice-turn-quality__turns{display:grid;gap:12px;margin-top:14px}.absolute-voice-turn-quality__turn{background:#fff;border:1px solid #f0dfba;border-radius:16px;padding:14px}.absolute-voice-turn-quality__turn--pass{border-color:#86efac}.absolute-voice-turn-quality__turn--warn,.absolute-voice-turn-quality__turn--unknown{border-color:#fbbf24}.absolute-voice-turn-quality__turn--fail{border-color:#f2a7a7}.absolute-voice-turn-quality__turn p{margin:10px 0}.absolute-voice-turn-quality__turn dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-turn-quality__turn div{background:#fff9eb;border:1px solid #f0dfba;border-radius:12px;padding:8px}.absolute-voice-turn-quality__turn dt{font-size:12px}.absolute-voice-turn-quality__turn dd{font-weight:800;margin:4px 0 0}.absolute-voice-turn-quality__empty{margin:14px 0 0}.absolute-voice-turn-quality__error{color:#9f1239;font-weight:700}`;