jev-devtools 0.5.1 → 0.5.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.
@@ -104,10 +104,11 @@ const Card = memo(function Card({ node, status, decision, selected, bounds, onRe
104
104
  ? "Condition is false · finished"
105
105
  : `Up to ${loop.maxIterations} iteration${loop.maxIterations === 1 ? "" : "s"}` })) : (collection && (_jsxs("span", { children: [collection.items.filter((item) => item.status === "running")
106
106
  .length, " ", "running \u00B7", " ", collection.items.filter((item) => item.status === "waiting")
107
- .length, " ", "queued \u00B7 up to ", collection.concurrency, " concurrent"] }))), node.kind === "loop" && node.conditionRule && (_jsxs("code", { children: ["Continue while ", formatFlowCondition(node.conditionRule)] })), _jsxs("small", { children: ["Explore ", node.kind === "loop" ? "an iteration's" : "an item's", " ", "connected flow below"] })] })), (node.kind === "branch" || node.kind === "if") &&
108
- (node.conditionRule !== undefined || node.condition) && (_jsxs("span", { className: "flow-condition-rule", children: [inputs && inputs.length > 0 && (_jsxs("span", { className: "flow-condition-incoming", children: [_jsx("span", { className: "flow-condition-label", children: inputs.length === 1 ? "Incoming value" : "Incoming values" }), inputs.slice(0, 3).map((input) => (_jsxs("span", { className: "flow-condition-input", children: [_jsx("span", { children: input.name }), _jsx("b", { children: input.value })] }, input.reference))), inputs.length > 3 && (_jsxs("small", { children: [inputs.length - 3, " more inputs \u00B7 select to inspect"] }))] })), _jsx("span", { className: "flow-condition-label", children: "Requirement" }), _jsx("code", { children: node.conditionRule !== undefined
107
+ .length, " ", "queued \u00B7 up to ", collection.concurrency, " concurrent"] }))), node.kind === "loop" && node.conditionRule && (_jsxs("code", { title: "Full captured rule in step details", children: ["Continue while ", formatFlowCondition(node.conditionRule)] })), node.kind === "loop" &&
108
+ !!node.conditionCaptureWarnings?.length && (_jsxs("small", { className: "warning", children: ["Rule capture: ", node.conditionCaptureWarnings.join(" ")] })), _jsxs("small", { children: ["Explore ", node.kind === "loop" ? "an iteration's" : "an item's", " ", "connected flow below"] })] })), (node.kind === "branch" || node.kind === "if") &&
109
+ (node.conditionRule !== undefined || node.condition) && (_jsxs("span", { className: "flow-condition-rule", children: [inputs && inputs.length > 0 && (_jsxs("span", { className: "flow-condition-incoming", children: [_jsx("span", { className: "flow-condition-label", children: inputs.length === 1 ? "Incoming value" : "Incoming values" }), inputs.slice(0, 3).map((input) => (_jsxs("span", { className: "flow-condition-input", children: [_jsx("span", { children: input.name }), _jsx("b", { children: input.value })] }, input.reference))), inputs.length > 3 && (_jsxs("small", { children: [inputs.length - 3, " more inputs \u00B7 select to inspect"] }))] })), _jsx("span", { className: "flow-condition-label", children: "Requirement" }), _jsx("code", { title: "Full captured rule in step details", children: node.conditionRule !== undefined
109
110
  ? conditionRequirement(node.conditionRule, inputs ?? [])
110
- : node.condition })] })), join && (_jsxs(_Fragment, { children: [_jsxs("span", { className: "flow-join-summary", children: [joinTitle(lanes.length), " ", _jsxs("span", { children: [finished, "/", lanes.length] })] }), _jsxs("span", { className: "flow-lanes", children: [lanes.slice(0, 4).map((lane) => (_jsxs("span", { className: "flow-lane", "data-status": lane.status, children: [_jsxs("span", { children: [_jsx("span", { "aria-hidden": "true", children: lane.status === "completed"
111
+ : node.condition }), !!node.conditionCaptureWarnings?.length && (_jsxs("small", { className: "warning", children: ["Rule capture: ", node.conditionCaptureWarnings.join(" ")] }))] })), join && (_jsxs(_Fragment, { children: [_jsxs("span", { className: "flow-join-summary", children: [joinTitle(lanes.length), " ", _jsxs("span", { children: [finished, "/", lanes.length] })] }), _jsxs("span", { className: "flow-lanes", children: [lanes.slice(0, 4).map((lane) => (_jsxs("span", { className: "flow-lane", "data-status": lane.status, children: [_jsxs("span", { children: [_jsx("span", { "aria-hidden": "true", children: lane.status === "completed"
111
112
  ? "✓"
112
113
  : lane.status === "error"
113
114
  ? "!"
@@ -287,11 +288,9 @@ export const FlowOverview = memo(function FlowOverview({ definition, run, traces
287
288
  preserveCamera();
288
289
  setHeights((previous) => previous[id] === height ? previous : { ...previous, [id]: height });
289
290
  }, [preserveCamera]);
290
- const started = useRef(false);
291
291
  const changeCollection = useCallback((id, view) => {
292
292
  preserveCamera();
293
293
  setSelected(id);
294
- started.current = true;
295
294
  setCollectionViews((previous) => ({ ...previous, [id]: view }));
296
295
  }, [preserveCamera]);
297
296
  const resizeItem = useCallback((id, size) => {
@@ -301,15 +300,6 @@ export const FlowOverview = memo(function FlowOverview({ definition, run, traces
301
300
  ? previous
302
301
  : { ...previous, [id]: size });
303
302
  }, [preserveCamera]);
304
- useEffect(() => {
305
- if (inline || started.current)
306
- return;
307
- const first = layout.points.get(selected);
308
- if (first) {
309
- started.current = true;
310
- focusArea(first);
311
- }
312
- }, [layout, selected, focusArea, inline]);
313
303
  const selectStep = (id) => {
314
304
  setSelected(id);
315
305
  const bounds = layout.points.get(id);
@@ -321,51 +311,52 @@ export const FlowOverview = memo(function FlowOverview({ definition, run, traces
321
311
  const trace = step?.traceId
322
312
  ? traces.find((t) => t.id === step.traceId)
323
313
  : undefined;
324
- return (_jsx("div", { className: `flow-overview-stack ${inline ? "flow-inline-overview" : ""}`, style: inline ? { width: layout.width } : undefined, children: _jsxs("section", { className: "request-detail whole-flow", "aria-label": inline ? "Collection item flow" : "Whole flow", children: [!inline && (_jsxs("header", { className: "detail-header", children: [_jsxs("div", { children: [_jsxs("span", { className: "eyebrow", children: ["Flow run \u00B7 ", run.status] }), _jsx("h2", { children: run.name })] }), _jsxs("div", { className: "flow-run-summary", children: [run.outcome ? (_jsxs("strong", { children: ["Outcome: ", run.outcome] })) : (run.error ?? "Execution paths"), _jsx("small", { className: "muted", children: run.durationMs !== undefined
314
+ const stepSelection = (_jsxs("label", { className: "flow-step-select", children: ["Step", _jsxs("select", { "aria-label": "Flow step", value: selected, onChange: (e) => selectStep(e.target.value), children: [_jsx("option", { value: "", children: "Select a step" }), definition.nodes.map((n) => (_jsxs("option", { value: n.id, children: [n.title ? `${n.title} (${n.id})` : n.id, " \u00B7", " ", run.steps[n.id]?.status ?? "waiting"] }, n.id)))] })] }));
315
+ return (_jsx("div", { className: `flow-overview-stack ${inline ? "flow-inline-overview" : ""}`, style: inline ? { width: layout.width } : undefined, children: _jsxs("section", { className: "request-detail whole-flow", "aria-label": inline ? "Collection item flow" : "Whole flow", children: [!inline && (_jsxs("header", { className: "detail-header", children: [_jsxs("div", { children: [_jsxs("span", { className: "eyebrow", children: ["Flow run \u00B7 ", run.status] }), _jsx("h2", { children: run.name })] }), _jsxs("div", { className: "flow-run-summary", children: [run.outcome ? (_jsxs("strong", { children: ["Outcome: ", run.outcome] })) : ((run.error ?? "Execution paths")), _jsx("small", { className: "muted", children: run.durationMs !== undefined
325
316
  ? ` · ${Math.round(run.durationMs)} ms`
326
- : "" }), _jsx(CopyFixtureButton, { control: fixtureCopy })] })] })), !inline && _jsx(CopyFixtureReport, { control: fixtureCopy }), _jsxs("div", { className: "lab-flow-toolbar", children: [!inline && (_jsxs("div", { children: [_jsx("button", { "aria-label": "Zoom flow out", onClick: () => zoomBy(1 / 1.2), children: "\u2212" }), _jsxs("output", { "aria-label": "Flow zoom", children: [zoom, "%"] }), _jsx("button", { "aria-label": "Zoom flow in", onClick: () => zoomBy(1.2), children: "+" }), _jsx("button", { onClick: fit, children: "Fit flow" }), _jsx("button", { disabled: !selected, onClick: () => selectStep(selected), children: "Focus step" })] })), _jsxs("label", { children: ["Step", _jsxs("select", { "aria-label": "Flow step", value: selected, onChange: (e) => selectStep(e.target.value), children: [_jsx("option", { value: "", children: "Select a step" }), definition.nodes.map((n) => (_jsxs("option", { value: n.id, children: [n.title ? `${n.title} (${n.id})` : n.id, " \u00B7", " ", run.steps[n.id]?.status ?? "waiting"] }, n.id)))] })] })] }), _jsxs("div", { className: "flow-workspace", children: [_jsx("div", { className: inline
317
+ : "" }), _jsxs("div", { className: "flow-run-controls", children: [stepSelection, _jsx(CopyFixtureButton, { control: fixtureCopy })] })] })] })), !inline && _jsx(CopyFixtureReport, { control: fixtureCopy }), inline && _jsx("div", { className: "lab-flow-toolbar", children: stepSelection }), _jsxs("div", { className: "flow-workspace", children: [_jsxs("div", { className: inline
327
318
  ? "flow-inline-surface"
328
- : "flow-overview-viewport diagram-viewport", ref: inline ? undefined : viewport, style: inline ? { height: layout.height } : undefined, tabIndex: inline ? undefined : 0, "aria-label": inline ? "Item flow canvas" : "Flow canvas", role: "region", children: _jsxs("div", { ref: inline ? undefined : canvas, className: "flow-overview-canvas", style: {
329
- width: layout.width,
330
- height: layout.height,
331
- // Inline views have no camera to account for negative bounds.
332
- // Keep nested previews and their external arrows in the frame.
333
- transform: inline ? `translateX(${-layout.left}px)` : undefined,
334
- }, children: [_jsxs("svg", { width: layout.width, height: layout.height, "aria-hidden": "true", className: "flow-connections", children: [_jsx("defs", { children: _jsx("marker", { id: `arrow-${run.id}`, viewBox: "0 0 10 10", refX: "8", refY: "5", markerWidth: "5", markerHeight: "5", orient: "auto", children: _jsx("path", { d: "M0 0L10 5L0 10z", fill: "currentColor" }) }) }), definition.nodes.flatMap((n) => (links.get(n.id) ?? []).map((id) => {
335
- const a = layout.points.get(id), b = layout.points.get(n.id);
336
- if (!a || !b)
337
- return null;
338
- const decision = n.merge
339
- ? run.steps[n.merge.condition]?.decision
340
- : undefined;
341
- const active = ["running", "completed"].includes(run.steps[n.id]?.status) &&
342
- ["running", "completed"].includes(run.steps[id]?.status) &&
343
- (!n.merge ||
344
- (decision !== undefined &&
345
- id === n.merge[decision ? "then" : "else"]));
346
- return (_jsx("path", { d: `M${a.x + a.width},${a.y + a.height / 2} C${a.x + a.width + 80},${a.y + a.height / 2} ${b.x - 80},${b.y + b.height / 2} ${b.x},${b.y + b.height / 2}`, stroke: active ? "#E551BA" : "currentColor", opacity: active ? 1 : 0.35, fill: "none", strokeWidth: "2", markerEnd: `url(#arrow-${run.id})` }, `${id}-${n.id}`));
347
- })), [...layout.expansions].map(([id, area]) => {
348
- const card = layout.points.get(id);
349
- const x = card.x + card.width / 2;
350
- const endX = area.x + area.width / 2;
351
- const startY = card.y + card.height;
352
- const bendY = startY + (area.y - startY) / 2;
353
- return (_jsxs("g", { className: "flow-collection-link", children: [_jsx("path", { d: `M${x},${startY} C${x},${bendY} ${endX},${bendY} ${endX},${area.y}`, fill: "none", stroke: "#E551BA", strokeWidth: "2", strokeDasharray: "6 5", markerEnd: `url(#arrow-${run.id})` }), _jsxs("text", { x: endX + 14, y: area.y - 20, children: [definition.nodes.find((n) => n.id === id)?.kind ===
354
- "loop"
355
- ? "Selected iteration"
356
- : "Selected item", " ", (collectionViews[id]?.index ?? 0) + 1] })] }, id));
357
- })] }), definition.nodes.map((n) => {
358
- const p = layout.points.get(n.id);
359
- if (!p)
360
- return null;
361
- const captured = tracesById.get(run.steps[n.id]?.traceId ?? "");
362
- return n.kind === "jev" && captured ? (_jsx(RequestNode, { node: n, trace: captured, status: run.steps[n.id]?.status ?? "waiting", selected: selected === n.id, x: p.x, y: p.y, onSelect: setSelected, onResize: onResize }, n.id)) : (_jsx(Card, { node: n, status: run.steps[n.id]?.status ?? "waiting", decision: run.steps[n.id]?.decision, selected: selected === n.id, bounds: p, onResize: onResize, onSelect: setSelected, inputs: inputsByStep.get(n.id), data: run.steps[n.id]?.data, durationMs: run.steps[n.id]?.durationMs, lanes: parallelLanes.get(n.id) ?? [], collection: run.steps[n.id]?.collection, loop: run.steps[n.id]?.loop, collectionView: collectionViews[n.id], onCollectionChange: changeCollection, expansionId: `collection-${run.id}-${n.id}` }, n.id));
363
- }), [...layout.expansions].map(([id, bounds]) => {
364
- const collectionNode = definition.nodes.find((n) => n.id === id);
365
- const collection = run.steps[id].collection;
366
- const index = Math.min(collectionViews[id].index, collection.total - 1);
367
- return (_jsx(InlineItemFlow, { id: `collection-${run.id}-${id}`, node: collectionNode, collection: collection, index: index, bounds: bounds, traces: traces, onResize: resizeItem, onCollectionChange: changeCollection }, id));
368
- })] }) }), _jsxs(FlowDetailsPanel, { inline: inline, selection: node?.title ?? node?.id, onLayoutChange: preserveCamera, children: [_jsxs("div", { className: "flow-selection", children: [node && step ? (_jsxs(_Fragment, { children: [_jsxs("strong", { children: [node.title ?? node.id, " \u00B7 ", step.status] }), _jsx("span", { className: "muted", children: step.durationMs !== undefined
319
+ : "flow-overview-viewport diagram-viewport", ref: inline ? undefined : viewport, style: inline ? { height: layout.height } : undefined, tabIndex: inline ? undefined : 0, "aria-label": inline ? "Item flow canvas" : "Flow canvas", role: "region", children: [!inline && (_jsxs("div", { className: "flow-canvas-controls", role: "group", "aria-label": "Flow canvas controls", "data-diagram-controls": true, children: [_jsx("button", { "aria-label": "Zoom flow out", onClick: () => zoomBy(1 / 1.2), children: "\u2212" }), _jsxs("output", { "aria-label": "Flow zoom", children: [zoom, "%"] }), _jsx("button", { "aria-label": "Zoom flow in", onClick: () => zoomBy(1.2), children: "+" }), _jsx("button", { onClick: fit, children: "Fit flow" }), _jsx("button", { disabled: !selected, onClick: () => selectStep(selected), children: "Focus step" })] })), _jsxs("div", { ref: inline ? undefined : canvas, className: "flow-overview-canvas", style: {
320
+ width: layout.width,
321
+ height: layout.height,
322
+ // Inline views have no camera to account for negative bounds.
323
+ // Keep nested previews and their external arrows in the frame.
324
+ transform: inline ? `translateX(${-layout.left}px)` : undefined,
325
+ }, children: [_jsxs("svg", { width: layout.width, height: layout.height, "aria-hidden": "true", className: "flow-connections", children: [_jsx("defs", { children: _jsx("marker", { id: `arrow-${run.id}`, viewBox: "0 0 10 10", refX: "8", refY: "5", markerWidth: "5", markerHeight: "5", orient: "auto", children: _jsx("path", { d: "M0 0L10 5L0 10z", fill: "currentColor" }) }) }), definition.nodes.flatMap((n) => (links.get(n.id) ?? []).map((id) => {
326
+ const a = layout.points.get(id), b = layout.points.get(n.id);
327
+ if (!a || !b)
328
+ return null;
329
+ const decision = n.merge
330
+ ? run.steps[n.merge.condition]?.decision
331
+ : undefined;
332
+ const active = ["running", "completed"].includes(run.steps[n.id]?.status) &&
333
+ ["running", "completed"].includes(run.steps[id]?.status) &&
334
+ (!n.merge ||
335
+ (decision !== undefined &&
336
+ id === n.merge[decision ? "then" : "else"]));
337
+ return (_jsx("path", { d: `M${a.x + a.width},${a.y + a.height / 2} C${a.x + a.width + 80},${a.y + a.height / 2} ${b.x - 80},${b.y + b.height / 2} ${b.x},${b.y + b.height / 2}`, stroke: active ? "#E551BA" : "currentColor", opacity: active ? 1 : 0.35, fill: "none", strokeWidth: "2", markerEnd: `url(#arrow-${run.id})` }, `${id}-${n.id}`));
338
+ })), [...layout.expansions].map(([id, area]) => {
339
+ const card = layout.points.get(id);
340
+ const x = card.x + card.width / 2;
341
+ const endX = area.x + area.width / 2;
342
+ const startY = card.y + card.height;
343
+ const bendY = startY + (area.y - startY) / 2;
344
+ return (_jsxs("g", { className: "flow-collection-link", children: [_jsx("path", { d: `M${x},${startY} C${x},${bendY} ${endX},${bendY} ${endX},${area.y}`, fill: "none", stroke: "#E551BA", strokeWidth: "2", strokeDasharray: "6 5", markerEnd: `url(#arrow-${run.id})` }), _jsxs("text", { x: endX + 14, y: area.y - 20, children: [definition.nodes.find((n) => n.id === id)?.kind ===
345
+ "loop"
346
+ ? "Selected iteration"
347
+ : "Selected item", " ", (collectionViews[id]?.index ?? 0) + 1] })] }, id));
348
+ })] }), definition.nodes.map((n) => {
349
+ const p = layout.points.get(n.id);
350
+ if (!p)
351
+ return null;
352
+ const captured = tracesById.get(run.steps[n.id]?.traceId ?? "");
353
+ return n.kind === "jev" && captured ? (_jsx(RequestNode, { node: n, trace: captured, status: run.steps[n.id]?.status ?? "waiting", selected: selected === n.id, x: p.x, y: p.y, onSelect: setSelected, onResize: onResize }, n.id)) : (_jsx(Card, { node: n, status: run.steps[n.id]?.status ?? "waiting", decision: run.steps[n.id]?.decision, selected: selected === n.id, bounds: p, onResize: onResize, onSelect: setSelected, inputs: inputsByStep.get(n.id), data: run.steps[n.id]?.data, durationMs: run.steps[n.id]?.durationMs, lanes: parallelLanes.get(n.id) ?? [], collection: run.steps[n.id]?.collection, loop: run.steps[n.id]?.loop, collectionView: collectionViews[n.id], onCollectionChange: changeCollection, expansionId: `collection-${run.id}-${n.id}` }, n.id));
354
+ }), [...layout.expansions].map(([id, bounds]) => {
355
+ const collectionNode = definition.nodes.find((n) => n.id === id);
356
+ const collection = run.steps[id].collection;
357
+ const index = Math.min(collectionViews[id].index, collection.total - 1);
358
+ return (_jsx(InlineItemFlow, { id: `collection-${run.id}-${id}`, node: collectionNode, collection: collection, index: index, bounds: bounds, traces: traces, onResize: resizeItem, onCollectionChange: changeCollection }, id));
359
+ })] })] }), _jsxs(FlowDetailsPanel, { inline: inline, selection: node?.title ?? node?.id, onLayoutChange: preserveCamera, children: [_jsxs("div", { className: "flow-selection", children: [node && step ? (_jsxs(_Fragment, { children: [_jsxs("strong", { children: [node.title ?? node.id, " \u00B7 ", step.status] }), _jsx("span", { className: "muted", children: step.durationMs !== undefined
369
360
  ? ` · ${Math.round(step.durationMs)} ms`
370
361
  : "" }), node.description && _jsx("p", { children: node.description }), node.kind === "loop" && (_jsxs("div", { className: "flow-task-details", children: [_jsx("p", { children: step.loop?.stopReason === "limit"
371
362
  ? "Iteration limit reached. The final state is incomplete and downstream steps did not run."
@@ -387,7 +378,7 @@ export const FlowOverview = memo(function FlowOverview({ definition, run, traces
387
378
  ? step.data
388
379
  : node.kind === "merge"
389
380
  ? "No selected value captured yet."
390
- : "No function data captured yet." })), step.captureWarnings?.map((warning) => (_jsx("p", { className: "muted", children: warning }, warning)))] })), node.kind === "parallel" && (_jsxs("p", { children: ["These paths run at the same time:", " ", (node.lanes ?? node.dependencies).join(", "), ". The next step starts only after all finish successfully. This marker waits for their results; it does not make another Jev request."] })), node.kind === "parallel" && (_jsx("ul", { className: "flow-lane-details", children: parallelLanes.get(node.id)?.map((lane) => (_jsxs("li", { children: [lane.name, " \u00B7 ", lane.status] }, lane.name))) })), (inputsByStep.get(node.id)?.length ?? 0) > 0 && (_jsx("dl", { className: "flow-input-details", children: inputsByStep.get(node.id)?.map((input) => (_jsxs("div", { children: [_jsxs("dt", { children: [input.name, " ", _jsx("code", { children: input.reference })] }), _jsx("dd", { children: input.value })] }, input.reference))) })), (node.conditionRule !== undefined || node.condition) && (_jsxs("p", { children: [_jsx("code", { children: node.conditionRule !== undefined
381
+ : "No function data captured yet." }))] })), step.captureWarnings?.map((warning) => (_jsx("p", { className: "warning", children: warning }, warning))), node.kind === "parallel" && (_jsxs("p", { children: ["These paths run at the same time:", " ", (node.lanes ?? node.dependencies).join(", "), ". The next step starts only after all finish successfully. This marker waits for their results; it does not make another Jev request."] })), node.kind === "parallel" && (_jsx("ul", { className: "flow-lane-details", children: parallelLanes.get(node.id)?.map((lane) => (_jsxs("li", { children: [lane.name, " \u00B7 ", lane.status] }, lane.name))) })), (inputsByStep.get(node.id)?.length ?? 0) > 0 && (_jsx("dl", { className: "flow-input-details", children: inputsByStep.get(node.id)?.map((input) => (_jsxs("div", { children: [_jsxs("dt", { children: [input.name, " ", _jsx("code", { children: input.reference })] }), _jsx("dd", { children: input.value })] }, input.reference))) })), node.conditionCaptureWarnings?.map((warning) => (_jsxs("p", { className: "warning", children: ["Rule capture: ", warning] }, warning))), (node.conditionRule !== undefined || node.condition) && (_jsxs("p", { children: [_jsx("code", { children: node.conditionRule !== undefined
391
382
  ? formatFlowCondition(node.conditionRule)
392
383
  : node.condition }), " ", "\u00B7", " ", step.decision === undefined
393
384
  ? "Not evaluated"
@@ -400,7 +391,7 @@ export const FlowOverview = memo(function FlowOverview({ definition, run, traces
400
391
  : "Not met · else route"] })), _jsx("p", { className: "muted", children: node.path.length ? node.path.join(" / ") : "Main path" }), step.error && _jsx("p", { role: "alert", children: step.error }), node.kind === "jev" &&
401
392
  (trace ? (_jsx("button", { onClick: () => setDetails(!details), children: details ? "Hide request details" : "Inspect request" })) : (_jsx("p", { children: step.traceId
402
393
  ? "Request capture was cleared or evicted."
403
- : "No captured request linked yet. Use a client created by this inspector." })))] })) : (_jsx("p", { className: "muted", children: "Each request diagram shows its context, question and answer. Use its question picker for other answers. Lines between requests show execution dependencies." })), run.value !== undefined && (_jsxs("details", { children: [_jsx("summary", { children: "Captured outcome value" }), _jsx(JsonBlock, { value: run.value })] }))] }), details && trace && (_jsx("div", { className: "flow-request-detail", children: _jsx(RequestDetail, { trace: trace }) }))] })] })] }) }));
394
+ : "No captured request linked yet. Use a client created by this inspector." })))] })) : (_jsx("p", { className: "muted", children: "Each request diagram shows its context, question and answer. Use its question picker for other answers. Lines between requests show execution dependencies." })), run.value !== undefined && (_jsxs("details", { children: [_jsxs("summary", { children: ["Captured outcome value", !!run.captureWarnings?.length && (_jsx("span", { className: "warning", children: " \u00B7 Capture warnings" }))] }), run.captureWarnings?.map((warning) => (_jsx("p", { className: "warning", children: warning }, warning))), _jsx(JsonBlock, { value: run.value })] }))] }), details && trace && (_jsx("div", { className: "flow-request-detail", children: _jsx(RequestDetail, { trace: trace }) }))] })] })] }) }));
404
395
  });
405
396
  const InlineItemFlow = memo(function InlineItemFlow({ id, node, collection, index, bounds, traces, onResize, onCollectionChange, }) {
406
397
  const ref = useRef(null);
@@ -1,6 +1,6 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { emptyFlows } from "./flow-stream.js";
3
- import { lazy, memo, startTransition, Suspense, useMemo, useState, } from "react";
3
+ import { lazy, memo, startTransition, Suspense, useCallback, useEffect, useMemo, useRef, useState, } from "react";
4
4
  import { TraceDiagram } from "./TraceDiagram.js";
5
5
  import { JsonBlock, findImage } from "./TraceContent.js";
6
6
  const FlowOverview = lazy(() => import("./FlowOverview.js").then((module) => ({
@@ -15,7 +15,7 @@ const ms = (value) => value === undefined ? "—" : `${Math.round(value)} ms`;
15
15
  // Delta updates retain unchanged Trace references. Default shallow comparison
16
16
  // skips their render work while changed traces and selection still update.
17
17
  const RequestRow = memo(function RequestRow({ trace, selected, onSelect, }) {
18
- return (_jsxs("button", { className: `request-row ${selected ? "selected" : ""}`, onClick: () => onSelect(trace.id), children: [_jsx("span", { className: `status-dot ${trace.status}` }), _jsxs("span", { children: [_jsx("strong", { children: trace.label }), _jsxs("small", { children: [new Date(trace.startedAt).toLocaleTimeString(), " \u00B7 ", trace.source, " \u00B7", " ", ms(trace.durationMs)] })] }), _jsx("span", { className: "row-status", children: trace.status })] }));
18
+ return (_jsxs("button", { className: `request-row ${selected ? "selected" : ""}`, "aria-pressed": selected, onClick: () => onSelect(trace.id), children: [_jsx("span", { className: `status-dot ${trace.status}` }), _jsxs("span", { children: [_jsx("strong", { children: trace.label }), _jsxs("small", { children: [new Date(trace.startedAt).toLocaleTimeString(), " \u00B7 ", trace.source, " \u00B7", " ", ms(trace.durationMs)] })] }), _jsx("span", { className: "row-status", children: trace.status })] }));
19
19
  });
20
20
  export const RequestDetail = memo(function RequestDetail({ trace, }) {
21
21
  // Keep tab selection across request switches and clear, as before. Local tab
@@ -41,6 +41,29 @@ export function JevPanel({ traces, flows = emptyFlows, connection, onClear, }) {
41
41
  const run = flows.runs.find((r) => r.id === selectedRun) ?? flows.runs[0];
42
42
  const definition = flows.definitions.find((d) => d.id === run?.definitionId);
43
43
  const [selected, setSelected] = useState();
44
+ const [browsingRequests, setBrowsingRequests] = useState(true);
45
+ const requestList = useRef(null);
46
+ const backToRequests = useRef(null);
47
+ const moveRequestFocus = useRef(false);
48
+ const selectRequest = useCallback((id) => {
49
+ setSelected(id);
50
+ moveRequestFocus.current = true;
51
+ setBrowsingRequests(false);
52
+ }, []);
53
+ useEffect(() => {
54
+ if (!moveRequestFocus.current)
55
+ return;
56
+ moveRequestFocus.current = false;
57
+ // CSS owns the breakpoint; only move focus when mobile navigation is visible.
58
+ const back = backToRequests.current;
59
+ if (browsingRequests) {
60
+ requestList.current
61
+ ?.querySelector(".request-row.selected")
62
+ ?.focus();
63
+ }
64
+ else if (back?.getClientRects().length)
65
+ back.focus();
66
+ }, [browsingRequests]);
44
67
  const [search, setSearch] = useState("");
45
68
  const [status, setStatus] = useState("all");
46
69
  const [error, setError] = useState("");
@@ -50,13 +73,16 @@ export function JevPanel({ traces, flows = emptyFlows, connection, onClear, }) {
50
73
  `${t.label} ${t.request.model} ${t.id}`.toLowerCase().includes(query));
51
74
  }, [traces, search, status]);
52
75
  const trace = filtered.find((t) => t.id === selected) || filtered[0];
53
- return (_jsxs("div", { className: "jev-inspector", children: [_jsxs("aside", { className: "request-list", children: [_jsxs("header", { children: [_jsxs("h2", { children: [view === "requests" ? "Jev requests" : "Jev flows", " ", _jsx("span", { children: view === "requests" ? traces.length : flows.runs.length })] }), _jsx("button", { onClick: () => void onClear().catch((e) => setError(e.message)), disabled: !traces.length && !flows.runs.length, children: "Clear" })] }), (flows.runs.length > 0 || view === "flows") && (_jsxs("nav", { className: "detail-tabs", "aria-label": "History type", children: [_jsx("button", { "aria-pressed": view === "requests", onClick: () => setView("requests"), children: "Requests" }), _jsx("button", { "aria-pressed": view === "flows", onClick: () => {
76
+ return (_jsxs("div", { className: "jev-inspector", "data-mobile-view": view === "requests" ? (browsingRequests ? "list" : "detail") : undefined, children: [_jsxs("aside", { className: "request-list", children: [_jsxs("header", { children: [_jsxs("h2", { children: [view === "requests" ? "Jev requests" : "Jev flows", " ", _jsx("span", { children: view === "requests" ? traces.length : flows.runs.length })] }), _jsx("button", { onClick: () => void onClear().catch((e) => setError(e.message)), disabled: !traces.length && !flows.runs.length, children: "Clear" })] }), (flows.runs.length > 0 || view === "flows") && (_jsxs("nav", { className: "detail-tabs", "aria-label": "History type", children: [_jsx("button", { "aria-pressed": view === "requests", onClick: () => setView("requests"), children: "Requests" }), _jsx("button", { "aria-pressed": view === "flows", onClick: () => {
54
77
  setView("flows");
55
78
  if (run)
56
79
  setSelectedRun(run.id);
57
- }, children: "Flows" })] })), view === "requests" && (_jsxs("div", { className: "list-filters", children: [_jsx("input", { "aria-label": "Search requests", placeholder: "Search requests\u2026", value: search, onChange: (e) => setSearch(e.target.value) }), _jsx("select", { "aria-label": "Filter request status", value: status, onChange: (e) => setStatus(e.target.value), children: ["all", "pending", "success", "error", "cancelled"].map((s) => (_jsx("option", { children: s }, s))) })] })), _jsxs("div", { className: "request-items", children: [view === "flows"
80
+ }, children: "Flows" })] })), view === "requests" && (_jsxs("button", { ref: backToRequests, className: "request-navigation", onClick: () => {
81
+ moveRequestFocus.current = true;
82
+ setBrowsingRequests(true);
83
+ }, children: ["\u2190 All requests ", _jsx("span", { children: filtered.length })] })), view === "requests" && (_jsxs("div", { className: "list-filters", children: [_jsx("input", { "aria-label": "Search requests", placeholder: "Search requests\u2026", value: search, onChange: (e) => setSearch(e.target.value) }), _jsx("select", { "aria-label": "Filter request status", value: status, onChange: (e) => setStatus(e.target.value), children: ["all", "pending", "success", "error", "cancelled"].map((s) => (_jsx("option", { children: s }, s))) })] })), _jsxs("div", { className: "request-items", ref: requestList, children: [view === "flows"
58
84
  ? flows.runs.map((r) => (_jsxs("button", { className: `request-row ${run?.id === r.id ? "selected" : ""}`, onClick: () => setSelectedRun(r.id), children: [_jsx("span", { className: `status-dot ${r.status}` }), _jsxs("span", { children: [_jsx("strong", { children: r.name }), _jsxs("small", { children: [new Date(r.startedAt).toLocaleTimeString(), " \u00B7", " ", r.outcome ?? r.status] })] }), _jsx("span", { className: "row-status", children: r.status })] }, r.id)))
59
- : filtered.map((t) => (_jsx(RequestRow, { trace: t, selected: trace?.id === t.id, onSelect: setSelected }, t.id))), view === "requests" && !filtered.length && (_jsx("p", { className: "empty", children: traces.length
85
+ : filtered.map((t) => (_jsx(RequestRow, { trace: t, selected: trace?.id === t.id, onSelect: selectRequest }, t.id))), view === "requests" && !filtered.length && (_jsx("p", { className: "empty", children: traces.length
60
86
  ? "No matching requests."
61
87
  : "Run a scenario to capture your first request." }))] }), (connection !== "connected" || error) && (_jsxs("footer", { children: [connection !== "connected" && (_jsx("span", { role: "status", children: connection })), error && _jsx("p", { role: "alert", children: error })] }))] }), view === "flows" && run && definition ? (_jsx(Suspense, { fallback: _jsx("p", { role: "status", children: "Loading flow\u2026" }), children: _jsx(FlowOverview, { run: run, definition: definition, traces: traces }, run.id) })) : (_jsx(RequestDetail, { trace: trace }))] }));
62
88
  }
@@ -148,5 +148,5 @@ export function TraceDiagram({ trace, embedded = false, onHeightChange, }) {
148
148
  ...counts,
149
149
  [key]: (counts[key] ?? 0) + 3,
150
150
  }));
151
- }, children: "Show More" }), _jsxs("p", { className: "lab-small", children: [remaining, " remaining \u00B7 Add ", Math.min(3, remaining)] })] }))] }) }), !showProbabilities && !embedded && (_jsxs("p", { className: "muted lab-flow-caption", children: [_jsx("span", { className: "lab-gesture-hint", children: "Drag to pan \u00B7 Scroll or pinch to zoom \u00B7 0 to fit" }), entries.length, " parallel question", entries.length === 1 ? "" : "s", " in one request. Connections show data flow, not model timing. Application routes and thresholds are not captured. Full inputs and criteria are in Questions and Context."] }))] }));
151
+ }, children: "Show More" }), _jsxs("p", { className: "lab-small", children: [remaining, " remaining \u00B7 Add ", Math.min(3, remaining)] })] }))] }) }), !showProbabilities && !embedded && (_jsx("p", { className: "lab-flow-caption", children: "Drag to pan \u00B7 Scroll or pinch to zoom \u00B7 0 to fit" }))] }));
152
152
  }
@@ -35,6 +35,8 @@ export type FlowNode = FlowDisplay & {
35
35
  };
36
36
  /** Optional for older captures; Json allows redacted/truncated subtrees. */
37
37
  conditionRule?: Json | FlowCondition;
38
+ /** Capture limitations for conditionRule; absent in older captures. */
39
+ conditionCaptureWarnings?: string[];
38
40
  /** Named concurrent lanes; optional for older captures. */
39
41
  lanes?: string[];
40
42
  /** Reusable item program; map nesting is not supported in v1. */
@@ -83,6 +85,8 @@ export type FlowRun = {
83
85
  steps: Record<string, FlowStep>;
84
86
  outcome?: string;
85
87
  value?: Json;
88
+ /** Capture limitations for value, including observer failures; absent in older captures. */
89
+ captureWarnings?: string[];
86
90
  error?: string;
87
91
  };
88
92
  export type FlowUpdate = {
@@ -1 +1 @@
1
- export const inspectorStyles = "/* Important declarations in the inner shadow context beat page-authored host\n styles, including important ones. Keep the reset here instead of expanding\n the all shorthand into hundreds of inline properties on the host element.\n These qualified host selectors are inert in the public document stylesheet. */\n:host(jev-devtools-root) {\n all: initial !important;\n direction: ltr !important;\n unicode-bidi: isolate !important;\n position: fixed !important;\n inset: 0 !important;\n pointer-events: none !important;\n z-index: 2147483000 !important;\n}\n\n:host(jev-devtools-root)::before,\n:host(jev-devtools-root)::after {\n content: none !important;\n display: none !important;\n}\n\n.jev-devtools {\n all: initial;\n /* all does not reset custom properties. Establish our own inherited defaults;\n cameras and probability cards can still set local values below this root. */\n --diagram-grid-opacity: 1;\n --diagram-grid-weight: 1;\n --lab-noul-probability: 1;\n --flow-item-offset: 0px;\n display: block;\n direction: ltr;\n unicode-bidi: isolate;\n pointer-events: auto;\n color-scheme: dark;\n font:\n 12px system-ui,\n sans-serif;\n color: #eee8ed;\n line-height: 1.5;\n}\n.jev-devtools,\n.jev-devtools * {\n box-sizing: border-box;\n}\n.jev-devtools button,\n.jev-devtools input,\n.jev-devtools select,\n.jev-devtools textarea {\n font: inherit;\n color: inherit;\n border: 1px solid #3b303d;\n border-radius: 5px;\n background: #17121b;\n}\n.jev-devtools button {\n padding: 7px 11px;\n cursor: pointer;\n}\n.jev-devtools button:disabled {\n opacity: 0.45;\n cursor: default;\n}\n.jev-devtools input,\n.jev-devtools select {\n padding: 8px;\n width: 100%;\n}\n.jev-devtools button:hover:not(:disabled) {\n border-color: #e551ba;\n}\n.jev-devtools :is(button, input, select, textarea, summary):focus-visible {\n outline: 2px solid #e551ba;\n outline-offset: 3px;\n}\n.jev-devtools .eyebrow {\n font-size: 10px;\n letter-spacing: 0.12em;\n color: #bc9db5;\n text-transform: uppercase;\n}\n.jev-devtools .jev-inspector {\n height: 100%;\n display: flex;\n color: #eee8ed;\n background: #0d0a0f;\n font:\n 12px \"DM Sans\",\n sans-serif;\n min-height: 0;\n overflow: hidden;\n}\n.jev-devtools .jev-inspector h2 {\n font-size: 15px;\n margin: 0;\n font-weight: 600;\n}\n.jev-devtools .jev-inspector h3 {\n font-size: 13px;\n margin: 0 0 8px;\n}\n.jev-devtools .jev-inspector code,\n.jev-devtools .jev-inspector pre {\n font:\n 11px \"JetBrains Mono\",\n monospace;\n}\n.jev-devtools .jev-inspector pre {\n line-height: 1.7;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n max-height: 460px;\n overflow: auto;\n background: #100d13;\n padding: 16px;\n border: 1px solid #2e2533;\n border-radius: 5px;\n}\n.jev-devtools .jev-inspector .muted {\n color: #a89bac;\n font-size: 11px;\n line-height: 1.6;\n}\n.jev-devtools .request-list {\n flex: 0 0 300px;\n border-right: 1px solid #302634;\n display: flex;\n flex-direction: column;\n min-height: 0;\n}\n.jev-devtools .request-list > header {\n padding: 17px 14px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n.jev-devtools .request-list h2 span {\n font-size: 11px;\n color: #b796ad;\n margin-left: 5px;\n}\n.jev-devtools .request-list button {\n font-size: 11px;\n}\n.jev-devtools .list-filters {\n display: flex;\n gap: 7px;\n padding: 0 12px 12px;\n}\n.jev-devtools .list-filters input {\n min-width: 0;\n}\n.jev-devtools .list-filters select {\n width: 86px;\n font-size: 11px;\n}\n.jev-devtools .request-items {\n overflow: auto;\n flex: 1;\n}\n.jev-devtools .request-row {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n text-align: left;\n border: 0;\n border-top: 1px solid #251d2a;\n border-radius: 0;\n background: transparent;\n padding: 16px 12px;\n}\n.jev-devtools .request-row.selected {\n background: #251423;\n box-shadow: inset 2px 0 #e551ba;\n}\n.jev-devtools .request-row strong {\n display: block;\n font-size: 12px;\n font-weight: 500;\n}\n.jev-devtools .request-row small {\n display: block;\n font-size: 10px;\n color: #a99aac;\n margin-top: 6px;\n}\n.jev-devtools .row-status {\n font-size: 9px;\n color: #ad9bb0;\n margin-left: auto;\n}\n.jev-devtools .status-dot {\n width: 6px;\n height: 6px;\n display: inline-block;\n border-radius: 50%;\n background: #b09ab7;\n flex-shrink: 0;\n}\n.jev-devtools .status-dot.success {\n background: #b3c79c;\n}\n.jev-devtools .status-dot.pending {\n background: #e551ba;\n}\n.jev-devtools .status-dot.error {\n background: #ee8e85;\n}\n.jev-devtools .request-list footer {\n padding: 12px;\n color: #9e8ea5;\n border-top: 1px solid #302634;\n font-size: 10px;\n display: flex;\n gap: 7px;\n}\n.jev-devtools .request-detail {\n flex: 1;\n min-width: 0;\n min-height: 0;\n display: flex;\n flex-direction: column;\n}\n.jev-devtools .detail-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 20px;\n padding: 18px 24px 10px;\n}\n.jev-devtools .detail-header h2 {\n margin-top: 6px;\n}\n.jev-devtools .metrics {\n display: flex;\n gap: 24px;\n font:\n 12px \"JetBrains Mono\",\n monospace;\n white-space: nowrap;\n}\n.jev-devtools .metrics small {\n display: block;\n font:\n 9px \"DM Sans\",\n sans-serif;\n color: #97879f;\n margin-top: 6px;\n}\n.jev-devtools .detail-meta {\n display: flex;\n gap: 20px;\n flex-wrap: wrap;\n padding: 0 24px 14px;\n color: #a08aa5;\n}\n.jev-devtools .detail-meta code {\n font-size: 10px;\n}\n.jev-devtools .detail-tabs {\n display: flex;\n gap: 20px;\n border-bottom: 1px solid #302634;\n padding: 0 24px;\n}\n.jev-devtools .detail-tabs button {\n border: 0;\n border-radius: 0;\n background: none;\n padding: 10px 0;\n color: #a89bac;\n font-size: 11px;\n}\n.jev-devtools .detail-tabs button[aria-pressed=\"true\"] {\n box-shadow: inset 0 -2px #e551ba;\n color: #f5c1e6;\n}\n.jev-devtools .detail-body {\n overflow: auto;\n flex: 1;\n min-height: 0;\n padding: 16px 24px 28px;\n background-image: radial-gradient(#342337 0.6px, transparent 0.6px);\n background-size: 16px 16px;\n}\n.jev-devtools .question-node {\n position: relative;\n border: 1px solid #75516c;\n border-radius: 6px;\n padding: 15px;\n background: #110d14;\n min-width: 0;\n}\n/* Retain the legacy question connectors and standalone suppression together.\n Remove only after resolving the narrow-screen visual differences in\n https://github.com/diegoag64/jev-devtools/issues/57. */\n.jev-devtools .question-node:before {\n content: \"\";\n position: absolute;\n right: 100%;\n top: 50%;\n width: 21px;\n border-top: 1px solid #7f416d;\n}\n.jev-devtools .question-branches .question-node:not(:first-child):before {\n display: none;\n}\n.jev-devtools .question-node header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n}\n.jev-devtools .question-node header h3 {\n margin: 0;\n overflow-wrap: anywhere;\n}\n.jev-devtools .type {\n font:\n 9px \"JetBrains Mono\",\n monospace;\n color: #e59acc;\n border: 1px solid #5e3654;\n border-radius: 3px;\n padding: 3px 5px;\n}\n.jev-devtools .answer-value {\n display: block;\n font-size: 20px;\n font-weight: 500;\n margin: 15px 0;\n color: #f0c7e5;\n}\n.jev-devtools .answer-value small {\n font-size: 10px;\n color: #b5a1ba;\n}\n.jev-devtools .probability {\n margin: 10px 0;\n font-size: 10px;\n}\n.jev-devtools .probability > div:first-child {\n display: flex;\n justify-content: space-between;\n gap: 5px;\n margin-bottom: 5px;\n}\n.jev-devtools .probability b {\n font-weight: 400;\n color: #d8abc9;\n}\n.jev-devtools .bar {\n height: 4px;\n background: #302033;\n border-radius: 2px;\n overflow: hidden;\n}\n.jev-devtools .bar i {\n display: block;\n height: 100%;\n background: #e551ba;\n}\n.jev-devtools .confidence {\n font-size: 10px;\n color: #a68cac;\n border-top: 1px solid #302634;\n padding-top: 10px;\n display: flex;\n justify-content: space-between;\n}\n.jev-devtools .confidence b {\n color: #d1bad2;\n font-weight: 400;\n}\n.jev-devtools details {\n margin-top: 12px;\n font-size: 10px;\n color: #b7a0bd;\n}\n.jev-devtools summary {\n cursor: pointer;\n}\n.jev-devtools .standalone {\n margin-bottom: 14px;\n max-width: 750px;\n}\n.jev-devtools .standalone:before {\n display: none;\n}\n.jev-devtools .standalone .answer {\n max-width: 450px;\n}\n.jev-devtools .box-preview {\n position: relative;\n margin-top: 14px;\n min-height: 80px;\n background: #19121c;\n}\n.jev-devtools .box-preview img {\n width: 100%;\n display: block;\n}\n.jev-devtools .bounding-box {\n position: absolute;\n border: 1.5px solid #e551ba;\n background: #e551ba15;\n}\n.jev-devtools .coordinates {\n display: block;\n font-size: 9px !important;\n line-height: 1.5;\n margin-top: 8px;\n color: #ac93b0;\n}\n.jev-devtools .context-image {\n max-width: 400px;\n width: 100%;\n border: 1px solid #75516c;\n border-radius: 6px;\n}\n.jev-devtools .empty {\n padding: 20px;\n color: #a294a8;\n line-height: 1.7;\n}\n.jev-devtools .empty-detail {\n margin: auto;\n padding: 40px;\n text-align: center;\n color: #b2a0ba;\n}\n.jev-devtools .empty-symbol {\n font-size: 36px;\n color: #e551ba;\n display: block;\n margin-bottom: 20px;\n}\n.jev-devtools .empty-detail p {\n font-size: 12px;\n line-height: 1.8;\n}\n.jev-devtools .error-banner {\n border: 1px solid #874b50;\n background: #31191e;\n padding: 12px;\n line-height: 1.5;\n margin-bottom: 16px;\n}\n.jev-devtools .warning {\n color: #e2b97d;\n}\n.jev-devtools .jev-inspector table {\n border-collapse: collapse;\n width: 100%;\n text-align: left;\n}\n.jev-devtools .jev-inspector th,\n.jev-devtools .jev-inspector td {\n border-bottom: 1px solid #302634;\n padding: 14px;\n}\n@media (max-width: 1100px) {\n .jev-devtools .question-branches .question-node:not(:first-child):before {\n display: block;\n }\n .jev-devtools .metrics {\n gap: 12px;\n }\n .jev-devtools .request-list {\n flex-basis: 250px;\n }\n}\n@media (max-width: 700px) {\n .jev-devtools .jev-inspector {\n flex-direction: column;\n }\n .jev-devtools .request-list {\n flex-basis: 140px;\n flex-shrink: 0;\n border-right: 0;\n border-bottom: 1px solid #302634;\n }\n .jev-devtools .request-list > header {\n padding: 6px 12px;\n }\n .jev-devtools .request-list footer {\n display: none;\n }\n .jev-devtools .list-filters {\n padding-bottom: 6px;\n }\n .jev-devtools .request-items {\n display: flex;\n }\n .jev-devtools .request-row {\n min-width: 240px;\n padding: 8px 12px;\n }\n .jev-devtools .detail-header {\n padding: 12px;\n }\n .jev-devtools .detail-meta,\n .jev-devtools .detail-tabs {\n padding-left: 12px;\n padding-right: 12px;\n }\n .jev-devtools .detail-body {\n padding: 12px;\n }\n .jev-devtools .metrics {\n display: none;\n }\n .jev-devtools .question-node:before {\n width: 13px;\n }\n .jev-devtools .question-node {\n padding: 12px;\n }\n}\n.jev-devtools .question-node:before,\n.jev-devtools .question-branches .question-node:not(:first-child):before {\n display: block;\n right: auto;\n left: 50%;\n top: -21px;\n width: 0;\n height: 20px;\n border-top: 0;\n border-left: 1px solid #7f416d;\n}\n.jev-devtools .standalone:before {\n display: none;\n}\n@media (max-width: 900px) {\n .jev-devtools .question-node:before,\n .jev-devtools .question-branches .question-node:not(:first-child):before {\n height: 12px;\n top: -13px;\n }\n .jev-devtools .question-branches .question-node:first-child:before {\n height: 20px;\n top: -21px;\n }\n}\n\n.jev-devtools.jev-drawer {\n margin: 0;\n padding: 0;\n position: fixed;\n z-index: 1000;\n inset: auto 0 0;\n display: flex;\n flex-direction: column;\n background: #0d0a0f;\n color: #eee8ed;\n border-top: 1px solid #604058;\n box-shadow: 0 -12px 48px #0005;\n font:\n 12px \"DM Sans\",\n sans-serif;\n}\n.jev-devtools.jev-drawer[hidden],\n.jev-devtools.jev-drawer-trigger[hidden] {\n display: none;\n}\n.jev-devtools .jev-drawer-resize {\n position: absolute;\n z-index: 1;\n top: -6px;\n width: 100%;\n height: 12px;\n cursor: ns-resize;\n touch-action: none;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n.jev-devtools .jev-drawer-resize span {\n width: 42px;\n height: 3px;\n border-radius: 3px;\n background: #79506f;\n}\n.jev-devtools .jev-drawer-resize:hover span,\n.jev-devtools .jev-drawer-resize:focus-visible span {\n background: #e551ba;\n}\n.jev-devtools .jev-drawer-resize:focus-visible {\n outline: 2px solid #e551ba;\n outline-offset: -2px;\n}\n.jev-devtools .jev-drawer-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex: 0 0 46px;\n padding: 0 16px;\n border-bottom: 1px solid #302634;\n}\n.jev-devtools .jev-drawer-header strong {\n display: flex;\n align-items: center;\n gap: 9px;\n font-weight: 600;\n}\n.jev-devtools .jev-drawer-header > div {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n.jev-devtools .jev-drawer-header button {\n background: transparent;\n border-color: transparent;\n font-size: 11px;\n color: #c4afc8;\n}\n.jev-devtools .jev-drawer-header .jev-drawer-close {\n font-size: 22px;\n line-height: 1;\n padding: 4px 8px;\n}\n.jev-devtools .jev-drawer-content {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n.jev-devtools.jev-drawer-trigger {\n position: fixed;\n bottom: 18px;\n right: 18px;\n z-index: 1000;\n display: flex;\n align-items: center;\n gap: 9px;\n padding: 10px 16px;\n border: 1px solid #a24487;\n border-radius: 8px;\n cursor: pointer;\n background: #211321;\n color: #f1cbe6;\n font:\n 600 13px \"DM Sans\",\n sans-serif;\n box-shadow: 0 4px 20px #0005;\n}\n.jev-devtools.jev-drawer-trigger span {\n color: #e551ba;\n font-size: 20px;\n}\n/* Baseline cards and authored left-to-right composition from the lab's Jev presets. */\n.jev-devtools .detail-body.detail-body-flow {\n display: flex;\n padding: 0;\n overflow: hidden;\n}\n.jev-devtools .lab-flow {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-width: 0;\n min-height: 0;\n}\n.jev-devtools .lab-flow-toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n flex-shrink: 0;\n padding: 12px 16px;\n flex-wrap: wrap;\n}\n.jev-devtools .lab-flow-toolbar label {\n display: flex;\n gap: 10px;\n align-items: center;\n font-size: 11px;\n min-width: 0;\n}\n.jev-devtools .lab-flow-toolbar select {\n width: auto;\n max-width: 240px;\n font-size: 11px;\n}\n.jev-devtools .lab-flow-toolbar > div {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n.jev-devtools .lab-flow-toolbar button {\n font-size: 11px;\n}\n.jev-devtools .lab-flow-toolbar output {\n font-size: 11px;\n min-width: 35px;\n text-align: center;\n}\n.jev-devtools .lab-flow-viewport {\n position: relative;\n flex: 1;\n min-height: 100px;\n overflow: hidden;\n background-color: #0d0a0f;\n background-image: radial-gradient(\n rgb(70 52 73 / var(--diagram-grid-opacity, 1))\n calc(0.8px * var(--diagram-grid-weight, 1)),\n transparent calc(0.8px * var(--diagram-grid-weight, 1))\n );\n background-size: 20px 20px;\n border-block: 1px solid #302634;\n cursor: grab;\n touch-action: none;\n user-select: none;\n overscroll-behavior: contain;\n}\n.jev-devtools .lab-flow-viewport[data-panning] {\n cursor: grabbing;\n}\n.jev-devtools .lab-flow-viewport:focus-visible {\n outline: 2px solid #e551ba;\n outline-offset: -2px;\n}\n.jev-devtools .lab-flow-caption {\n flex-shrink: 0;\n padding: 8px 16px;\n margin: 0;\n}\n.jev-devtools .lab-gesture-hint {\n display: block;\n color: #c6a7bd;\n}\n.jev-devtools .lab-flow-canvas {\n position: absolute;\n inset: 0 auto auto 0;\n transform-origin: top left;\n will-change: transform;\n font-family: system-ui, sans-serif;\n color: #f5f3f6;\n}\n.jev-devtools .lab-connections {\n position: absolute;\n inset: 0;\n overflow: visible;\n}\n.jev-devtools .lab-connections path {\n fill: none;\n stroke: #645a68;\n stroke-width: 1;\n}\n.jev-devtools .lab-connections path.active {\n stroke: #968592;\n}\n.jev-devtools .lab-connections text {\n fill: #b7b1bc;\n font:\n 12px ui-monospace,\n monospace;\n}\n.jev-devtools .lab-flow-dot {\n fill: #e551ba;\n}\n.jev-devtools .lab-card {\n position: absolute;\n border: 1.3px solid #f5f3f6;\n border-radius: 14px;\n padding: 16px;\n background: #0d0a0f;\n overflow: hidden;\n}\n.jev-devtools .lab-eyebrow {\n display: block;\n color: #e551ba;\n font:\n 500 10px ui-monospace,\n monospace;\n letter-spacing: 1px;\n margin: 0 0 7px;\n}\n.jev-devtools .lab-card h3 {\n font-size: 16px;\n font-weight: 600;\n line-height: 1.3;\n letter-spacing: -0.2px;\n margin: 0 0 10px;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n.jev-devtools .lab-card p {\n font-size: 13px;\n line-height: 1.4;\n margin: 10px 0;\n}\n.jev-devtools .lab-copy {\n display: -webkit-box;\n -webkit-line-clamp: 5;\n -webkit-box-orient: vertical;\n overflow: hidden;\n overflow-wrap: anywhere;\n}\n.jev-devtools .lab-probability {\n margin: 17px 0;\n}\n.jev-devtools .lab-probability > div:first-child {\n display: flex;\n justify-content: space-between;\n gap: 10px;\n margin-bottom: 9px;\n font-size: 15px;\n}\n.jev-devtools .lab-probability span {\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n.jev-devtools .lab-probability code {\n font:\n 13px ui-monospace,\n monospace;\n}\n.jev-devtools .lab-track {\n height: 7px;\n border-radius: 4px;\n background: #f5f3f61a;\n overflow: hidden;\n}\n.jev-devtools .lab-track i {\n display: block;\n height: 100%;\n border-radius: 4px;\n background: #e551ba;\n}\n.jev-devtools .lab-track i.lab-alternative {\n opacity: 0.35;\n}\n.jev-devtools .lab-card .lab-result {\n font-size: 14px;\n margin-top: 24px;\n}\n.jev-devtools .lab-card .lab-small {\n font-size: 12px;\n color: #b7b1bc;\n margin-top: 20px;\n}\n.jev-devtools .lab-idle {\n opacity: 0.65;\n}\n.jev-devtools .lab-scale {\n position: relative;\n margin-top: 18px;\n border-top: 1px solid #b7b1bc;\n display: flex;\n justify-content: space-between;\n padding-top: 9px;\n}\n.jev-devtools .lab-scale > span {\n position: absolute;\n top: -5px;\n width: 9px;\n height: 9px;\n border-radius: 50%;\n background: #e551ba;\n transform: translateX(-50%);\n}\n.jev-devtools .lab-big {\n display: block;\n font-size: 36px;\n font-weight: 500;\n margin-top: 26px;\n}\n.jev-devtools .lab-endpoints {\n display: flex;\n justify-content: space-between;\n font-size: 12px;\n color: #b7b1bc;\n margin-top: 10px;\n}\n.jev-devtools .lab-image {\n position: relative;\n}\n.jev-devtools .lab-image img {\n display: block;\n width: 100%;\n}\n.jev-devtools .lab-box {\n position: absolute;\n border: 1.5px solid #e551ba;\n background: #e551ba15;\n}\n.jev-devtools .lab-source-image {\n width: 100%;\n max-height: 105px;\n object-fit: contain;\n}\n.jev-devtools .lab-coordinates {\n font-family: ui-monospace, monospace;\n}\n@media (prefers-reduced-motion: reduce) {\n .jev-devtools .lab-flow-dot {\n display: none;\n }\n}\n/* The public TypeSafe mark travels with the package, independent of host assets. */\n.jev-devtools .typesafe-mark {\n display: inline-block;\n flex: 0 0 23px;\n width: 23px;\n height: 32px;\n overflow: hidden;\n line-height: 0;\n}\n.jev-devtools .typesafe-mark img {\n display: block;\n height: 32px;\n width: auto;\n max-width: none;\n}\n\n.jev-devtools .detail-body-questions {\n display: flex;\n flex-direction: column;\n overflow: auto;\n}\n.jev-devtools .questions-list {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 180px;\n}\n.jev-devtools .questions-navigation {\n display: flex;\n align-items: end;\n gap: 8px;\n flex-wrap: wrap;\n flex-shrink: 0;\n}\n.jev-devtools .questions-navigation label {\n display: flex;\n align-items: center;\n gap: 8px;\n white-space: nowrap;\n flex: 1;\n min-width: 240px;\n max-width: 480px;\n font-size: 11px;\n color: #bc9db5;\n}\n.jev-devtools .questions-navigation select {\n display: block;\n min-width: 0;\n}\n.jev-devtools .questions-navigation > span {\n align-self: center;\n color: #a89bac;\n}\n.jev-devtools .questions-help {\n margin: 8px 0;\n flex-shrink: 0;\n}\n.jev-devtools .questions-viewport {\n flex: 1;\n min-height: 0;\n overflow: auto;\n overflow-anchor: none;\n scrollbar-gutter: stable;\n padding: 3px;\n}\n.jev-devtools .questions-spacer {\n position: relative;\n width: 100%;\n}\n.jev-devtools .questions-row {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n padding-bottom: 14px;\n}\n.jev-devtools .questions-row .standalone {\n margin-bottom: 0;\n}\n.jev-devtools .questions-viewport:focus-visible,\n.jev-devtools .questions-row article:focus-visible {\n outline: 2px solid #e551ba;\n outline-offset: -2px;\n}\n\n/* Reserve measured card geometry while rapid scrolling uses a light preview. */\n.jev-devtools .questions-row[data-preview=\"true\"] article {\n height: 100%;\n}\n.jev-devtools .question-scroll-preview p {\n margin-top: 16px;\n}\n\n/* The full distribution stays at reading size, outside the zoomable canvas. */\n.jev-devtools .lab-flow-viewport[hidden] {\n display: none;\n}\n.jev-devtools .lab-choice-browser {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n padding: 8px 16px;\n gap: 10px;\n}\n.jev-devtools .lab-choice-controls {\n display: flex;\n gap: 12px;\n align-items: end;\n flex-wrap: wrap;\n font-size: 12px;\n}\n.jev-devtools .lab-choice-controls label {\n display: grid;\n gap: 5px;\n}\n.jev-devtools .lab-choice-table-scroll {\n overflow: auto;\n overscroll-behavior: contain;\n min-height: 0;\n}\n.jev-devtools .lab-choice-browser table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n.jev-devtools .lab-choice-browser caption {\n text-align: left;\n padding: 8px 0;\n color: #aaa0af;\n}\n.jev-devtools .lab-choice-browser th,\n.jev-devtools .lab-choice-browser td {\n padding: 9px 12px;\n border-bottom: 1px solid #302634;\n text-align: left;\n}\n.jev-devtools .lab-choice-browser th {\n overflow-wrap: anywhere;\n max-width: 320px;\n}\n.jev-devtools .lab-choice-browser td {\n font-variant-numeric: tabular-nums;\n}\n.jev-devtools .lab-choice-browser code {\n white-space: normal;\n overflow-wrap: anywhere;\n}\n.jev-devtools .lab-choice-returned {\n display: block;\n font-size: 10px;\n color: #e551ba;\n}\n.jev-devtools .lab-choice-pagination {\n display: flex;\n align-items: center;\n gap: 12px;\n justify-content: space-between;\n font-size: 12px;\n}\n.jev-devtools .lab-choice-remainder button {\n margin-top: 7px;\n}\n\n.jev-devtools .lab-flow-compact .lab-output {\n padding: 12px;\n height: 104px;\n}\n.jev-devtools .lab-flow-compact .lab-output .lab-eyebrow {\n margin-bottom: 6px;\n}\n.jev-devtools .lab-flow-compact .lab-output h3 {\n font-size: 16px;\n margin-bottom: 8px;\n}\n.jev-devtools .lab-flow-compact .lab-output p {\n font-size: 12px;\n margin: 4px 0;\n}\n.jev-devtools .lab-flow-compact .lab-result {\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n overflow-wrap: anywhere;\n}\n.jev-devtools .lab-choice-remainder {\n padding: 12px;\n}\n.jev-devtools .lab-choice-remainder .lab-small {\n margin: 8px 0 0;\n font-size: 11px;\n}\n\n.jev-devtools .detail-body.detail-body-flow {\n flex-direction: column;\n}\n.jev-devtools .detail-body-flow > .warning,\n.jev-devtools .detail-body-flow > .error-banner {\n flex-shrink: 0;\n margin: 6px 16px;\n}\n.jev-devtools .lab-choice-browser {\n overflow: auto;\n}\n.jev-devtools .lab-choice-table-scroll {\n flex: 1 0 110px;\n}\n\n/* Only freshly revealed branches enter; pan/zoom remains on the canvas. */\n.jev-devtools .lab-card-enter {\n animation: jev-card-enter 280ms cubic-bezier(0.2, 0.8, 0.2, 1) backwards;\n}\n.jev-devtools .lab-branch-enter {\n stroke-dasharray: 1;\n animation: jev-branch-enter 280ms ease-out backwards;\n}\n@keyframes jev-card-enter {\n from {\n opacity: 0;\n transform: translateX(-16px) scale(0.96);\n }\n}\n@keyframes jev-branch-enter {\n from {\n opacity: 0;\n stroke-dashoffset: 1;\n }\n to {\n opacity: 1;\n stroke-dashoffset: 0;\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .jev-devtools .lab-card-enter,\n .jev-devtools .lab-branch-enter {\n animation: none;\n }\n}\n\n/* Connected requests share one camera and one opt-in full request detail.\n :where scopes these selectors without changing their existing specificity. */\n:where(.jev-devtools) .whole-flow {\n min-width: 0;\n overflow: hidden;\n}\n:where(.jev-devtools) .whole-flow > .detail-header,\n:where(.jev-devtools) .whole-flow > .lab-flow-toolbar {\n flex-shrink: 0;\n}\n:where(.jev-devtools) .flow-workspace {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n:where(.jev-devtools) .flow-details-panel {\n flex: none;\n min-width: 0;\n background: #130f17;\n border-top: 1px solid #342a38;\n}\n:where(.jev-devtools) .flow-details-bar {\n display: flex;\n align-items: center;\n gap: 12px;\n height: 36px;\n padding: 0 12px;\n}\n.jev-devtools .flow-details-bar button {\n flex: none;\n padding: 4px 8px;\n font-size: 11px;\n}\n:where(.jev-devtools) .flow-details-bar > span {\n color: #b5a6bc;\n font-size: 11px;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n:where(.jev-devtools) .flow-details-body {\n overflow: auto;\n overscroll-behavior: contain;\n scrollbar-gutter: stable;\n}\n:where(.jev-devtools) .flow-details-resize {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 8px;\n cursor: ns-resize;\n touch-action: none;\n user-select: none;\n}\n:where(.jev-devtools) .flow-details-resize span {\n width: 40px;\n height: 2px;\n border-radius: 2px;\n background: #6c5874;\n}\n:where(.jev-devtools) .flow-details-resize:hover,\n:where(.jev-devtools) .flow-details-resize:focus-visible {\n background: #392239;\n outline: 1px solid #e551ba;\n outline-offset: -1px;\n}\n:where(.jev-devtools) .flow-overview-viewport {\n position: relative;\n min-height: 0;\n flex: 1 1 0;\n overflow: hidden;\n touch-action: none;\n cursor: grab;\n background-image: radial-gradient(\n rgb(83 67 87 / var(--diagram-grid-opacity, 1))\n calc(1px * var(--diagram-grid-weight, 1)),\n transparent calc(1px * var(--diagram-grid-weight, 1))\n );\n background-size: 20px 20px;\n}\n:where(.jev-devtools) .flow-overview-viewport[data-panning] {\n cursor: grabbing;\n}\n:where(.jev-devtools) .flow-overview-canvas {\n position: absolute;\n transform-origin: 0 0;\n}\n:where(.jev-devtools) .flow-connections {\n position: absolute;\n inset: 0;\n overflow: visible;\n color: #c0b8c4;\n pointer-events: none;\n}\n:where(.jev-devtools) .flow-step {\n position: absolute;\n min-height: 172px;\n overflow-wrap: anywhere;\n display: flex;\n flex-direction: column;\n gap: 8px;\n text-align: left;\n padding: 14px;\n border: 1px solid #736476;\n border-radius: 12px;\n background: #151017;\n color: inherit;\n}\n:where(.jev-devtools) .flow-step strong {\n white-space: normal;\n width: 100%;\n}\n:where(.jev-devtools) .flow-step-description {\n overflow-wrap: anywhere;\n font-size: 12px;\n}\n:where(.jev-devtools) .flow-step.flow-request {\n display: block;\n padding: 0;\n background: #0d0a0f;\n /* Skip offscreen paint/layout while preserving each question/expansion state. */\n content-visibility: auto;\n contain-intrinsic-size: auto 640px;\n}\n:where(.jev-devtools) .flow-request-heading {\n width: 100%;\n min-height: 64px;\n gap: 20px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n text-align: left;\n padding: 12px 20px;\n border: 0;\n border-bottom: 1px solid #342a38;\n border-radius: 12px 12px 0 0;\n background: transparent;\n color: inherit;\n}\n:where(.jev-devtools) .flow-request-heading .eyebrow {\n display: block;\n margin-bottom: 4px;\n}\n.jev-devtools .lab-flow-embedded {\n width: 1120px;\n display: block;\n}\n.jev-devtools .lab-flow-surface {\n position: relative;\n width: 1120px;\n}\n.jev-devtools .lab-flow-surface[hidden] {\n display: none;\n}\n.jev-devtools .lab-flow-embedded .lab-flow-canvas {\n will-change: auto;\n}\n.jev-devtools .lab-flow-embedded .lab-choice-browser {\n height: 520px;\n}\n:where(.jev-devtools) .flow-step.selected {\n outline: 2px solid #e551ba;\n outline-offset: 3px;\n}\n:where(.jev-devtools) .flow-step[data-status=\"completed\"] {\n border-color: #e551ba;\n}\n:where(.jev-devtools) .flow-step[data-status=\"running\"] {\n border-color: #e551ba;\n background: #2b1728;\n}\n:where(.jev-devtools) .flow-step[data-status=\"untaken\"],\n:where(.jev-devtools) .flow-step[data-status=\"blocked\"] {\n color: #948797;\n border-color: #403746;\n background: #151017;\n}\n:where(.jev-devtools) .flow-step[data-status=\"error\"] {\n border-color: #f17c78;\n}\n:where(.jev-devtools) .flow-step[data-status=\"cancelled\"] {\n border-style: dashed;\n}\n:where(.jev-devtools) .flow-selection {\n padding: 12px 20px;\n border-top: 1px solid #342a38;\n}\n:where(.jev-devtools) .flow-selection p {\n margin: 6px 0;\n overflow-wrap: anywhere;\n}\n:where(.jev-devtools) .flow-request-detail {\n min-height: 450px;\n border-top: 1px solid #534357;\n}\n:where(.jev-devtools) .flow-request-detail > .request-detail {\n min-height: 450px;\n}\n\n:where(.jev-devtools) .flow-card-heading,\n:where(.jev-devtools) .flow-card-footer,\n:where(.jev-devtools) .flow-join-summary,\n:where(.jev-devtools) .flow-lane {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n width: 100%;\n}\n:where(.jev-devtools) .flow-card-heading {\n justify-content: flex-start;\n}\n:where(.jev-devtools) .flow-task .flow-kind-icon {\n border: 1px solid currentColor;\n border-radius: 6px;\n padding: 4px;\n}\n:where(.jev-devtools) .flow-task-preview {\n display: grid;\n gap: 8px;\n min-width: 0;\n}\n.jev-devtools .flow-task-preview .diagram-content {\n max-height: 280px;\n padding: 8px 10px;\n border: 1px solid #35283b;\n border-radius: 4px;\n background: #100c13;\n}\n:where(.jev-devtools) .flow-task-preview small {\n color: #a89bac;\n font-size: 11px;\n}\n:where(.jev-devtools) .flow-task-details {\n display: grid;\n gap: 12px;\n}\n:where(.jev-devtools) .flow-task-details details {\n min-width: 0;\n}\n:where(.jev-devtools) .flow-task-details summary {\n cursor: pointer;\n margin-bottom: 8px;\n}\n:where(.jev-devtools) .flow-task-details .diagram-content {\n max-height: 320px;\n overflow: auto;\n}\n:where(.jev-devtools) .flow-kind-icon {\n width: 26px;\n height: 26px;\n color: #e551ba;\n flex-shrink: 0;\n}\n:where(.jev-devtools) .flow-kind-icon svg {\n width: 100%;\n height: 100%;\n}\n:where(.jev-devtools) .flow-card-heading .eyebrow {\n font-size: 10px;\n}\n:where(.jev-devtools) .flow-status {\n margin-left: auto;\n font-size: 10px;\n border-radius: 20px;\n padding: 4px 8px;\n background: #342031;\n color: #f0b7e0;\n}\n:where(.jev-devtools) .flow-step[data-status=\"untaken\"] .flow-status {\n background: #241e28;\n color: #948797;\n}\n:where(.jev-devtools) .flow-step[data-status=\"untaken\"] .flow-kind-icon {\n color: #948797;\n}\n:where(.jev-devtools) .flow-card-body > strong {\n white-space: normal;\n font-size: 18px;\n line-height: 1.25;\n overflow-wrap: anywhere;\n}\n:where(.jev-devtools) .flow-step-description {\n line-height: 1.5;\n color: #b9aebf;\n white-space: pre-wrap;\n}\n:where(.jev-devtools) .flow-card-footer {\n margin-top: auto;\n padding-top: 10px;\n border-top: 1px solid #342a38;\n font-size: 10px;\n color: #a092a7;\n}\n:where(.jev-devtools) .flow-card-footer code {\n max-width: 45%;\n white-space: normal;\n overflow-wrap: anywhere;\n}\n:where(.jev-devtools) .flow-card-footer small {\n text-align: right;\n}\n:where(.jev-devtools) .flow-join-summary {\n margin-top: 4px;\n font-size: 11px;\n color: #c9b9cd;\n}\n:where(.jev-devtools) .flow-join-summary > span {\n color: #ef9ed9;\n font-variant-numeric: tabular-nums;\n}\n:where(.jev-devtools) .flow-lanes {\n display: flex;\n flex-direction: column;\n gap: 4px;\n width: 100%;\n}\n:where(.jev-devtools) .flow-lane {\n border-radius: 5px;\n background: #211923;\n padding: 6px 8px;\n font-size: 11px;\n min-height: 28px;\n}\n:where(.jev-devtools) .flow-lane > span {\n min-width: 0;\n overflow-wrap: anywhere;\n}\n:where(.jev-devtools) .flow-lane > span > span {\n color: #ef9ed9;\n margin-right: 4px;\n}\n:where(.jev-devtools) .flow-lane small {\n color: #b9aebf;\n}\n:where(.jev-devtools) .flow-lane-details {\n padding-left: 18px;\n font-size: 12px;\n}\n:where(.jev-devtools) .flow-request-heading > span:first-child {\n min-width: 0;\n max-width: 80%;\n}\n:where(.jev-devtools) .flow-request-description {\n display: block;\n white-space: pre-wrap;\n font-size: 12px;\n line-height: 1.5;\n color: #b9aebf;\n margin-top: 5px;\n overflow-wrap: anywhere;\n}\n\n/* Structured context stays within the card; its gestures never move the camera. */\n.jev-devtools .lab-content-card {\n display: flex;\n flex-direction: column;\n padding: 14px;\n}\n.jev-devtools .lab-content-card h3 {\n font-size: 14px;\n margin-bottom: 8px;\n flex-shrink: 0;\n}\n.jev-devtools .lab-content-card .lab-eyebrow {\n font-size: 9px;\n margin-bottom: 5px;\n flex-shrink: 0;\n}\n.jev-devtools .diagram-content {\n min-height: 0;\n flex: 1;\n overflow: auto;\n overscroll-behavior: contain;\n touch-action: pan-y;\n scrollbar-width: thin;\n scrollbar-color: #514256 transparent;\n padding-right: 4px;\n font-size: 12px;\n line-height: 1.5;\n color: #d5cdd9;\n cursor: auto;\n user-select: text;\n}\n.jev-devtools .diagram-content:focus-visible {\n outline: 1px solid #e551ba;\n outline-offset: -1px;\n border-radius: 3px;\n}\n.jev-devtools .diagram-property {\n display: flex;\n justify-content: space-between;\n align-items: baseline;\n gap: 8px;\n padding: 5px 0;\n border-bottom: 1px solid #261e2a;\n}\n.jev-devtools .diagram-property-text {\n display: block;\n}\n.jev-devtools .diagram-property-key {\n font:\n 10px/1.5 ui-monospace,\n monospace;\n color: #c8a8c8;\n overflow-wrap: anywhere;\n min-width: 0;\n}\n.jev-devtools .diagram-property-text > .diagram-property-key {\n display: block;\n margin-bottom: 2px;\n}\n.jev-devtools .diagram-text-value {\n display: block;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n.jev-devtools .diagram-text-preview {\n display: -webkit-box;\n -webkit-line-clamp: 3;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n.jev-devtools .diagram-value-number {\n color: #a6d6ca;\n font:\n 11px/1.5 ui-monospace,\n monospace;\n font-variant-numeric: tabular-nums;\n overflow-wrap: anywhere;\n}\n.jev-devtools .diagram-value-boolean {\n color: #c4b1ed;\n font:\n 11px/1.5 ui-monospace,\n monospace;\n}\n.jev-devtools .diagram-value-empty {\n color: #9c8ca4;\n font:\n 10px/1.5 ui-monospace,\n monospace;\n}\n.jev-devtools .diagram-property-disclosure {\n width: 100%;\n display: flex;\n align-items: baseline;\n gap: 5px;\n padding: 6px 0;\n border: 0;\n border-bottom: 1px solid #261e2a;\n border-radius: 0;\n background: transparent;\n text-align: left;\n color: inherit;\n}\n.jev-devtools .diagram-property-disclosure:hover {\n background: #211723;\n}\n.jev-devtools .diagram-property-caret {\n color: #ab8aab;\n flex-shrink: 0;\n}\n.jev-devtools .diagram-property-type {\n color: #9c8ca4;\n font:\n 10px/1.5 ui-monospace,\n monospace;\n margin-left: auto;\n flex-shrink: 0;\n}\n.jev-devtools .diagram-property-children {\n margin-left: 4px;\n padding-left: 9px;\n border-left: 1px solid #49324b;\n}\n.jev-devtools .diagram-content-toggle {\n display: block;\n padding: 3px 0;\n border: 0;\n border-radius: 0;\n background: transparent;\n color: #e9a4d7;\n font-size: 10px;\n text-align: left;\n}\n.jev-devtools .diagram-content-toggle:hover {\n color: #ffd9f3;\n text-decoration: underline;\n}\n\n/* Noul is a probability of true; its two outputs carry p and 1-p.\n Keep the fill opaque, with readable text even at zero probability. */\n.jev-devtools .lab-noul-output {\n border-color: rgb(\n 245 243 246 / calc(0.35 + 0.65 * var(--lab-noul-probability, 1))\n );\n}\n.jev-devtools .lab-noul-output > h3,\n.jev-devtools .lab-noul-output > p {\n opacity: calc(0.65 + 0.35 * var(--lab-noul-probability, 1));\n}\n\n:where(.jev-devtools) .flow-condition-rule {\n display: block;\n padding: 10px 12px;\n border: 1px solid #49324b;\n border-radius: 6px;\n background: #211723;\n width: 100%;\n}\n:where(.jev-devtools) .flow-condition-label {\n display: block;\n font-size: 10px;\n color: #ba9dbe;\n margin-bottom: 5px;\n}\n:where(.jev-devtools) .flow-condition-rule code {\n display: block;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n font:\n 12px/1.6 ui-monospace,\n monospace;\n color: #f2d7eb;\n}\n\n:where(.jev-devtools) .flow-condition-incoming {\n display: block;\n padding-bottom: 10px;\n margin-bottom: 10px;\n border-bottom: 1px solid #49324b;\n}\n:where(.jev-devtools) .flow-condition-input {\n display: flex;\n justify-content: space-between;\n align-items: baseline;\n gap: 12px;\n font-size: 12px;\n padding: 3px 0;\n}\n:where(.jev-devtools) .flow-condition-input > span {\n min-width: 0;\n overflow-wrap: anywhere;\n}\n:where(.jev-devtools) .flow-condition-input > b {\n font-size: 17px;\n font-weight: 600;\n color: #f2d7eb;\n overflow-wrap: anywhere;\n white-space: normal;\n max-width: 65%;\n}\n:where(.jev-devtools) .flow-input-details {\n font-size: 12px;\n}\n:where(.jev-devtools) .flow-input-details > div {\n display: flex;\n gap: 16px;\n margin: 6px 0;\n}\n:where(.jev-devtools) .flow-input-details code {\n color: #a092a7;\n margin-left: 8px;\n}\n:where(.jev-devtools) .flow-input-details dd {\n margin: 0;\n overflow-wrap: anywhere;\n}\n\n:where(.jev-devtools) .flow-overview-stack {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n min-width: 0;\n overflow: hidden;\n}\n:where(.jev-devtools) .flow-map-progress {\n display: grid;\n gap: 10px;\n font-size: 14px;\n line-height: 1.5;\n}\n:where(.jev-devtools) .flow-map-progress small {\n color: #b5a6bc;\n}\n\n.jev-devtools .flow-card-body {\n display: flex;\n flex-direction: column;\n gap: 8px;\n width: 100%;\n flex: 1;\n padding: 0;\n border: 0;\n border-radius: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n text-align: left;\n}\n.jev-devtools .flow-card-body:hover {\n background: transparent;\n}\n:where(.jev-devtools) .flow-collection-controls {\n display: flex;\n align-items: end;\n gap: 10px;\n border-top: 1px solid #49324b;\n margin-top: 4px;\n padding-top: 12px;\n}\n:where(.jev-devtools) .flow-collection-controls label {\n display: grid;\n gap: 6px;\n flex: 1;\n min-width: 0;\n color: #b9aebf;\n font-size: 11px;\n}\n.jev-devtools .flow-collection-controls select {\n width: 100%;\n min-width: 0;\n}\n.jev-devtools .flow-collection-controls button {\n flex: none;\n color: #efb1df;\n}\n:where(.jev-devtools) .flow-collection-expansion {\n position: absolute;\n width: max-content;\n}\n:where(.jev-devtools) .flow-item-frame {\n border: 1px solid #64415d;\n border-radius: 12px;\n background: #100c13;\n overflow: hidden;\n}\n:where(.jev-devtools) .flow-collection-heading {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 24px;\n padding: 16px 20px;\n border-bottom: 1px solid #49324b;\n background: #1c1220;\n}\n:where(.jev-devtools) .flow-collection-heading h3 {\n margin: 5px 0;\n font-size: 16px;\n}\n:where(.jev-devtools) .flow-collection-heading small {\n color: #b9aebf;\n}\n:where(.jev-devtools) .flow-collection-link text {\n fill: #ce9abd;\n font-size: 12px;\n}\n:where(.jev-devtools) .flow-item-placeholder {\n width: 600px;\n padding: 24px;\n line-height: 1.6;\n}\n:where(.jev-devtools) .flow-inline-overview,\n:where(.jev-devtools) .flow-inline-overview > .whole-flow,\n:where(.jev-devtools) .flow-inline-overview > .whole-flow > .flow-workspace {\n display: block;\n flex: none;\n}\n:where(.jev-devtools) .flow-inline-surface {\n position: relative;\n}\n\n:where(.jev-devtools) .flow-item-content {\n min-width: 0;\n animation: jev-flow-item-enter 240ms cubic-bezier(0.22, 1, 0.36, 1) both;\n}\n:where(.jev-devtools) .flow-item-forward {\n --flow-item-offset: 28px;\n}\n:where(.jev-devtools) .flow-item-backward {\n --flow-item-offset: -28px;\n}\n@keyframes jev-flow-item-enter {\n from {\n opacity: 0;\n transform: translateX(var(--flow-item-offset));\n }\n to {\n opacity: 1;\n transform: translateX(0);\n }\n}\n@media (prefers-reduced-motion: reduce) {\n :where(.jev-devtools) .flow-item-content {\n animation: none;\n }\n}\n.jev-devtools .flow-item-arrow {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n display: grid;\n place-items: center;\n width: 56px;\n height: 56px;\n padding: 12px;\n margin: 0 auto;\n border: 1px solid #64415d;\n border-radius: 6px;\n background: #211623;\n color: #efa7db;\n}\n.jev-devtools .flow-item-arrow:hover:not(:disabled) {\n background: #382035;\n border-color: #e551ba;\n}\n:where(.jev-devtools) .flow-item-arrow svg {\n width: 28px;\n height: 28px;\n}\n\n:where(.jev-devtools) .flow-item-previous {\n left: -76px;\n}\n:where(.jev-devtools) .flow-item-next {\n right: -76px;\n}\n.jev-devtools .flow-run-summary {\n text-align: right;\n}\n.jev-devtools .flow-fixture-button {\n display: block;\n margin: 6px 0 0 auto;\n /* Keep the header still when the shorter confirmation replaces the label. */\n min-width: 96px;\n font-size: 11px;\n transition: background-color 160ms ease, border-color 160ms ease;\n}\n.jev-devtools .flow-fixture-button[data-copied] {\n border-color: #e551ba;\n background: #382035;\n animation: jev-fixture-copied 200ms ease-out;\n}\n@keyframes jev-fixture-copied {\n from {\n transform: scale(0.96);\n }\n to {\n transform: scale(1);\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .jev-devtools .flow-fixture-button {\n transition: none;\n }\n .jev-devtools .flow-fixture-button[data-copied] {\n animation: none;\n }\n}\n.jev-devtools .flow-fixture {\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n flex-shrink: 0;\n gap: 4px;\n padding: 0 24px;\n text-align: right;\n}\n.jev-devtools .flow-fixture p {\n margin: 0;\n max-width: 360px;\n font-size: 11px;\n}\n.jev-devtools .flow-fixture details {\n max-width: 360px;\n font-size: 11px;\n}\n.jev-devtools .flow-fixture details ul {\n max-height: 120px;\n margin: 4px 0 0;\n padding: 0;\n overflow: auto;\n list-style: none;\n font-family: \"JetBrains Mono\", monospace;\n overflow-wrap: anywhere;\n}\n.jev-devtools .flow-fixture details ul:focus-visible {\n outline: 2px solid #e551ba;\n outline-offset: 2px;\n}\n.jev-devtools .flow-fixture textarea {\n width: 360px;\n max-width: 100%;\n height: 120px;\n padding: 8px;\n font:\n 11px \"JetBrains Mono\",\n monospace;\n text-align: left;\n}\n";
1
+ export const inspectorStyles = "/* Important declarations in the inner shadow context beat page-authored host\n styles, including important ones. Keep the reset here instead of expanding\n the all shorthand into hundreds of inline properties on the host element.\n These qualified host selectors are inert in the public document stylesheet. */\n:host(jev-devtools-root) {\n all: initial !important;\n direction: ltr !important;\n unicode-bidi: isolate !important;\n position: fixed !important;\n inset: 0 !important;\n pointer-events: none !important;\n z-index: 2147483000 !important;\n}\n\n:host(jev-devtools-root)::before,\n:host(jev-devtools-root)::after {\n content: none !important;\n display: none !important;\n}\n\n.jev-devtools {\n all: initial;\n /* all does not reset custom properties. Establish our own inherited defaults;\n cameras and probability cards can still set local values below this root. */\n --diagram-grid-opacity: 1;\n --diagram-grid-weight: 1;\n --lab-noul-probability: 1;\n --flow-item-offset: 0px;\n display: block;\n direction: ltr;\n unicode-bidi: isolate;\n pointer-events: auto;\n color-scheme: dark;\n font:\n 12px system-ui,\n sans-serif;\n color: #eee8ed;\n line-height: 1.5;\n}\n.jev-devtools,\n.jev-devtools * {\n box-sizing: border-box;\n}\n.jev-devtools button,\n.jev-devtools input,\n.jev-devtools select,\n.jev-devtools textarea {\n font: inherit;\n color: inherit;\n border: 1px solid #3b303d;\n border-radius: 5px;\n background: #17121b;\n}\n.jev-devtools button {\n padding: 7px 11px;\n cursor: pointer;\n}\n.jev-devtools button:disabled {\n opacity: 0.45;\n cursor: default;\n}\n.jev-devtools input,\n.jev-devtools select {\n padding: 8px;\n width: 100%;\n}\n.jev-devtools select {\n appearance: none;\n padding-right: 34px;\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='m4 6 4 4 4-4' stroke='%23bcadbf' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 10px center;\n background-size: 16px 16px;\n}\n@media (forced-colors: active) {\n .jev-devtools select {\n /* Let the system draw a visible arrow in high-contrast themes. */\n appearance: auto;\n background-image: none;\n }\n}\n.jev-devtools button:hover:not(:disabled) {\n border-color: #e551ba;\n}\n.jev-devtools :is(button, input, select, textarea, summary):focus-visible {\n outline: 2px solid #e551ba;\n outline-offset: 3px;\n}\n.jev-devtools .eyebrow {\n font-size: 10px;\n letter-spacing: 0.12em;\n color: #bc9db5;\n text-transform: uppercase;\n}\n.jev-devtools .jev-inspector {\n height: 100%;\n display: flex;\n color: #eee8ed;\n background: #0d0a0f;\n font:\n 12px \"DM Sans\",\n sans-serif;\n min-height: 0;\n overflow: hidden;\n}\n.jev-devtools .jev-inspector h2 {\n font-size: 15px;\n margin: 0;\n font-weight: 600;\n}\n.jev-devtools .jev-inspector h3 {\n font-size: 13px;\n margin: 0 0 8px;\n}\n.jev-devtools .jev-inspector code,\n.jev-devtools .jev-inspector pre {\n font:\n 11px \"JetBrains Mono\",\n monospace;\n}\n.jev-devtools .jev-inspector pre {\n line-height: 1.7;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n max-height: 460px;\n overflow: auto;\n background: #100d13;\n padding: 16px;\n border: 1px solid #2e2533;\n border-radius: 5px;\n}\n.jev-devtools .jev-inspector .muted {\n color: #a89bac;\n font-size: 11px;\n line-height: 1.6;\n}\n.jev-devtools .request-list {\n flex: 0 0 300px;\n border-right: 1px solid #302634;\n display: flex;\n flex-direction: column;\n min-height: 0;\n}\n.jev-devtools .request-list > header {\n padding: 17px 14px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n.jev-devtools .request-list h2 span {\n font-size: 11px;\n color: #b796ad;\n margin-left: 5px;\n}\n.jev-devtools .request-list button {\n font-size: 11px;\n}\n.jev-devtools .list-filters {\n display: flex;\n gap: 7px;\n padding: 0 12px 12px;\n}\n.jev-devtools .list-filters input {\n min-width: 0;\n}\n.jev-devtools .list-filters select {\n width: 100px;\n flex-shrink: 0;\n font-size: 11px;\n}\n.jev-devtools .request-items {\n overflow: auto;\n flex: 1;\n}\n.jev-devtools .request-navigation {\n display: none;\n}\n.jev-devtools .request-row {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n text-align: left;\n border: 0;\n border-top: 1px solid #251d2a;\n border-radius: 0;\n background: transparent;\n padding: 16px 12px;\n}\n.jev-devtools .request-row.selected {\n background: #251423;\n box-shadow: inset 2px 0 #e551ba;\n}\n.jev-devtools .request-row strong {\n display: block;\n font-size: 12px;\n font-weight: 500;\n}\n.jev-devtools .request-row small {\n display: block;\n font-size: 10px;\n color: #a99aac;\n margin-top: 6px;\n}\n.jev-devtools .row-status {\n font-size: 9px;\n color: #ad9bb0;\n margin-left: auto;\n}\n.jev-devtools .status-dot {\n width: 6px;\n height: 6px;\n display: inline-block;\n border-radius: 50%;\n background: #b09ab7;\n flex-shrink: 0;\n}\n.jev-devtools .status-dot.success {\n background: #b3c79c;\n}\n.jev-devtools .status-dot.pending {\n background: #e551ba;\n}\n.jev-devtools .status-dot.error {\n background: #ee8e85;\n}\n.jev-devtools .request-list footer {\n padding: 12px;\n color: #9e8ea5;\n border-top: 1px solid #302634;\n font-size: 10px;\n display: flex;\n gap: 7px;\n}\n.jev-devtools .request-detail {\n flex: 1;\n min-width: 0;\n min-height: 0;\n display: flex;\n flex-direction: column;\n}\n.jev-devtools .detail-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 20px;\n padding: 18px 24px 10px;\n}\n.jev-devtools .detail-header h2 {\n margin-top: 6px;\n}\n.jev-devtools .metrics {\n display: flex;\n gap: 24px;\n font:\n 12px \"JetBrains Mono\",\n monospace;\n white-space: nowrap;\n}\n.jev-devtools .metrics small {\n display: block;\n font:\n 9px \"DM Sans\",\n sans-serif;\n color: #97879f;\n margin-top: 6px;\n}\n.jev-devtools .detail-meta {\n display: flex;\n gap: 20px;\n flex-wrap: wrap;\n padding: 0 24px 14px;\n color: #a08aa5;\n}\n.jev-devtools .detail-meta code {\n font-size: 10px;\n}\n.jev-devtools .detail-tabs {\n display: flex;\n gap: 20px;\n border-bottom: 1px solid #302634;\n padding: 0 24px;\n}\n.jev-devtools .detail-tabs button {\n border: 0;\n border-radius: 0;\n background: none;\n padding: 10px 0;\n color: #a89bac;\n font-size: 11px;\n}\n.jev-devtools .detail-tabs button[aria-pressed=\"true\"] {\n box-shadow: inset 0 -2px #e551ba;\n color: #f5c1e6;\n}\n.jev-devtools .detail-body {\n overflow: auto;\n flex: 1;\n min-height: 0;\n padding: 16px 24px 28px;\n background-image: radial-gradient(#342337 0.6px, transparent 0.6px);\n background-size: 16px 16px;\n}\n.jev-devtools .question-node {\n position: relative;\n border: 1px solid #75516c;\n border-radius: 6px;\n padding: 15px;\n background: #110d14;\n min-width: 0;\n}\n/* Retain the legacy question connectors and standalone suppression together.\n Remove only after resolving the narrow-screen visual differences in\n https://github.com/diegoag64/jev-devtools/issues/57. */\n.jev-devtools .question-node:before {\n content: \"\";\n position: absolute;\n right: 100%;\n top: 50%;\n width: 21px;\n border-top: 1px solid #7f416d;\n}\n.jev-devtools .question-branches .question-node:not(:first-child):before {\n display: none;\n}\n.jev-devtools .question-node header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n}\n.jev-devtools .question-node header h3 {\n margin: 0;\n overflow-wrap: anywhere;\n}\n.jev-devtools .type {\n font:\n 9px \"JetBrains Mono\",\n monospace;\n color: #e59acc;\n border: 1px solid #5e3654;\n border-radius: 3px;\n padding: 3px 5px;\n}\n.jev-devtools .answer-value {\n display: block;\n font-size: 20px;\n font-weight: 500;\n margin: 15px 0;\n color: #f0c7e5;\n}\n.jev-devtools .answer-value small {\n font-size: 10px;\n color: #b5a1ba;\n}\n.jev-devtools .probability {\n margin: 10px 0;\n font-size: 10px;\n}\n.jev-devtools .probability > div:first-child {\n display: flex;\n justify-content: space-between;\n gap: 5px;\n margin-bottom: 5px;\n}\n.jev-devtools .probability b {\n font-weight: 400;\n color: #d8abc9;\n}\n.jev-devtools .bar {\n height: 4px;\n background: #302033;\n border-radius: 2px;\n overflow: hidden;\n}\n.jev-devtools .bar i {\n display: block;\n height: 100%;\n background: #e551ba;\n}\n.jev-devtools .confidence {\n font-size: 10px;\n color: #a68cac;\n border-top: 1px solid #302634;\n padding-top: 10px;\n display: flex;\n justify-content: space-between;\n}\n.jev-devtools .confidence b {\n color: #d1bad2;\n font-weight: 400;\n}\n.jev-devtools details {\n margin-top: 12px;\n font-size: 10px;\n color: #b7a0bd;\n}\n.jev-devtools summary {\n cursor: pointer;\n}\n.jev-devtools .standalone {\n margin-bottom: 14px;\n max-width: 750px;\n}\n.jev-devtools .standalone:before {\n display: none;\n}\n.jev-devtools .standalone .answer {\n max-width: 450px;\n}\n.jev-devtools .box-preview {\n position: relative;\n margin-top: 14px;\n min-height: 80px;\n background: #19121c;\n}\n.jev-devtools .box-preview img {\n width: 100%;\n display: block;\n}\n.jev-devtools .bounding-box {\n position: absolute;\n border: 1.5px solid #e551ba;\n background: #e551ba15;\n}\n.jev-devtools .coordinates {\n display: block;\n font-size: 9px !important;\n line-height: 1.5;\n margin-top: 8px;\n color: #ac93b0;\n}\n.jev-devtools .context-image {\n max-width: 400px;\n width: 100%;\n border: 1px solid #75516c;\n border-radius: 6px;\n}\n.jev-devtools .empty {\n padding: 20px;\n color: #a294a8;\n line-height: 1.7;\n}\n.jev-devtools .empty-detail {\n margin: auto;\n padding: 40px;\n text-align: center;\n color: #b2a0ba;\n}\n.jev-devtools .empty-symbol {\n font-size: 36px;\n color: #e551ba;\n display: block;\n margin-bottom: 20px;\n}\n.jev-devtools .empty-detail p {\n font-size: 12px;\n line-height: 1.8;\n}\n.jev-devtools .error-banner {\n border: 1px solid #874b50;\n background: #31191e;\n padding: 12px;\n line-height: 1.5;\n margin-bottom: 16px;\n}\n.jev-devtools .warning {\n color: #e2b97d;\n}\n.jev-devtools .jev-inspector table {\n border-collapse: collapse;\n width: 100%;\n text-align: left;\n}\n.jev-devtools .jev-inspector th,\n.jev-devtools .jev-inspector td {\n border-bottom: 1px solid #302634;\n padding: 14px;\n}\n@media (max-width: 1100px) {\n .jev-devtools .question-branches .question-node:not(:first-child):before {\n display: block;\n }\n .jev-devtools .metrics {\n gap: 12px;\n }\n .jev-devtools .request-list {\n flex-basis: 250px;\n }\n}\n@media (max-width: 700px) {\n .jev-devtools .jev-inspector {\n flex-direction: column;\n }\n .jev-devtools .request-list {\n flex-basis: 140px;\n flex-shrink: 0;\n border-right: 0;\n border-bottom: 1px solid #302634;\n }\n .jev-devtools .request-list > header {\n padding: 6px 12px;\n }\n .jev-devtools .request-list footer {\n display: none;\n }\n .jev-devtools .list-filters {\n padding-bottom: 6px;\n }\n .jev-devtools .request-items {\n display: flex;\n }\n .jev-devtools .request-row {\n min-width: 240px;\n padding: 8px 12px;\n }\n /* Requests use separate list/detail screens so history cannot collapse into\n the fixed-height strip used by flow runs. CSS keeps desktop split panes. */\n .jev-devtools .jev-inspector[data-mobile-view=\"list\"] > .request-list {\n flex: 1;\n }\n .jev-devtools .jev-inspector[data-mobile-view=\"list\"] > .request-detail,\n .jev-devtools .jev-inspector[data-mobile-view=\"detail\"] .list-filters,\n .jev-devtools .jev-inspector[data-mobile-view=\"detail\"] .request-items {\n display: none;\n }\n .jev-devtools .jev-inspector[data-mobile-view=\"detail\"] > .request-list {\n flex: none;\n }\n .jev-devtools .jev-inspector[data-mobile-view=\"detail\"] .request-navigation {\n display: flex;\n align-items: center;\n justify-content: space-between;\n min-height: 44px;\n margin: 6px 12px;\n text-align: left;\n }\n .jev-devtools .jev-inspector[data-mobile-view] .request-items {\n flex-direction: column;\n }\n .jev-devtools .jev-inspector[data-mobile-view] .request-row {\n flex: none;\n min-width: 0;\n min-height: 60px;\n padding: 12px;\n }\n .jev-devtools\n .jev-inspector[data-mobile-view]\n .request-row\n > span:nth-child(2) {\n min-width: 0;\n overflow-wrap: anywhere;\n }\n .jev-devtools .jev-inspector[data-mobile-view] > .request-detail {\n overflow: auto;\n }\n .jev-devtools\n .jev-inspector[data-mobile-view]\n > .request-detail\n > :is(.detail-header, .detail-meta, .detail-tabs) {\n flex: none;\n }\n .jev-devtools\n .jev-inspector[data-mobile-view]\n > .request-detail\n > .detail-body-flow {\n /* Let metadata scroll above the diagram instead of clipping its toolbar. */\n flex: 1 0 auto;\n min-height: min-content;\n }\n .jev-devtools .flow-details-bar > span {\n display: none;\n }\n .jev-devtools .detail-header {\n padding: 12px;\n }\n .jev-devtools .detail-meta,\n .jev-devtools .detail-tabs {\n padding-left: 12px;\n padding-right: 12px;\n }\n .jev-devtools .detail-tabs {\n overflow-x: auto;\n flex-shrink: 0;\n }\n .jev-devtools .detail-body {\n padding: 12px;\n }\n .jev-devtools .metrics {\n display: none;\n }\n .jev-devtools .question-node:before {\n width: 13px;\n }\n .jev-devtools .question-node {\n padding: 12px;\n }\n}\n.jev-devtools .question-node:before,\n.jev-devtools .question-branches .question-node:not(:first-child):before {\n display: block;\n right: auto;\n left: 50%;\n top: -21px;\n width: 0;\n height: 20px;\n border-top: 0;\n border-left: 1px solid #7f416d;\n}\n.jev-devtools .standalone:before {\n display: none;\n}\n@media (max-width: 900px) {\n .jev-devtools .question-node:before,\n .jev-devtools .question-branches .question-node:not(:first-child):before {\n height: 12px;\n top: -13px;\n }\n .jev-devtools .question-branches .question-node:first-child:before {\n height: 20px;\n top: -21px;\n }\n}\n\n.jev-devtools.jev-drawer {\n margin: 0;\n padding: 0;\n position: fixed;\n z-index: 1000;\n inset: auto 0 0;\n display: flex;\n flex-direction: column;\n background: #0d0a0f;\n color: #eee8ed;\n border-top: 1px solid #604058;\n box-shadow: 0 -12px 48px #0005;\n font:\n 12px \"DM Sans\",\n sans-serif;\n}\n.jev-devtools.jev-drawer[hidden],\n.jev-devtools.jev-drawer-trigger[hidden] {\n display: none;\n}\n.jev-devtools .jev-drawer-resize {\n position: absolute;\n z-index: 1;\n top: -6px;\n width: 100%;\n height: 12px;\n cursor: ns-resize;\n touch-action: none;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n.jev-devtools .jev-drawer-resize span {\n width: 42px;\n height: 3px;\n border-radius: 3px;\n background: #79506f;\n}\n.jev-devtools .jev-drawer-resize:hover span,\n.jev-devtools .jev-drawer-resize:focus-visible span {\n background: #e551ba;\n}\n.jev-devtools .jev-drawer-resize:focus-visible {\n outline: 2px solid #e551ba;\n outline-offset: -2px;\n}\n.jev-devtools .jev-drawer-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex: 0 0 46px;\n padding: 0 16px;\n border-bottom: 1px solid #302634;\n}\n.jev-devtools .jev-drawer-header strong {\n display: flex;\n align-items: center;\n gap: 9px;\n font-weight: 600;\n}\n.jev-devtools .jev-drawer-header > div {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n.jev-devtools .jev-drawer-header button {\n background: transparent;\n border-color: transparent;\n font-size: 11px;\n color: #c4afc8;\n}\n.jev-devtools .jev-drawer-header .jev-drawer-close {\n font-size: 22px;\n line-height: 1;\n padding: 4px 8px;\n}\n.jev-devtools .jev-drawer-content {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n.jev-devtools.jev-drawer-trigger {\n position: fixed;\n bottom: 18px;\n right: 18px;\n z-index: 1000;\n display: flex;\n align-items: center;\n gap: 9px;\n padding: 10px 16px;\n border: 1px solid #a24487;\n border-radius: 8px;\n cursor: pointer;\n background: #211321;\n color: #f1cbe6;\n font:\n 600 13px \"DM Sans\",\n sans-serif;\n box-shadow: 0 4px 20px #0005;\n}\n.jev-devtools.jev-drawer-trigger span {\n color: #e551ba;\n font-size: 20px;\n}\n/* Baseline cards and authored left-to-right composition from the lab's Jev presets. */\n.jev-devtools .detail-body.detail-body-flow {\n display: flex;\n padding: 0;\n overflow: hidden;\n}\n.jev-devtools .lab-flow {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-width: 0;\n min-height: 0;\n}\n.jev-devtools .lab-flow-toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n flex-shrink: 0;\n padding: 12px 16px;\n flex-wrap: wrap;\n}\n.jev-devtools .lab-flow-toolbar label,\n.jev-devtools .flow-step-select {\n display: flex;\n gap: 10px;\n align-items: center;\n font-size: 11px;\n min-width: 0;\n}\n.jev-devtools .lab-flow-toolbar select,\n.jev-devtools .flow-step-select select {\n width: auto;\n max-width: 240px;\n font-size: 11px;\n}\n.jev-devtools .lab-flow-toolbar > div {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n.jev-devtools .lab-flow-toolbar button,\n.jev-devtools .flow-canvas-controls button {\n font-size: 11px;\n}\n.jev-devtools .lab-flow-toolbar output,\n.jev-devtools .flow-canvas-controls output {\n font-size: 11px;\n min-width: 35px;\n text-align: center;\n}\n.jev-devtools .lab-flow-viewport {\n position: relative;\n flex: 1;\n min-height: 100px;\n overflow: hidden;\n background-color: #0d0a0f;\n background-image: radial-gradient(\n rgb(70 52 73 / var(--diagram-grid-opacity, 1))\n calc(0.8px * var(--diagram-grid-weight, 1)),\n transparent calc(0.8px * var(--diagram-grid-weight, 1))\n );\n background-size: 20px 20px;\n border-block: 1px solid #302634;\n cursor: grab;\n touch-action: none;\n user-select: none;\n overscroll-behavior: contain;\n}\n.jev-devtools .lab-flow-viewport[data-panning] {\n cursor: grabbing;\n}\n.jev-devtools .lab-flow-viewport:focus-visible {\n outline: 2px solid #e551ba;\n outline-offset: -2px;\n}\n.jev-devtools .lab-flow-caption {\n flex-shrink: 0;\n padding: 8px 16px;\n margin: 0;\n color: #c6a7bd;\n font-size: 11px;\n line-height: 1.6;\n}\n.jev-devtools .lab-flow-canvas {\n position: absolute;\n inset: 0 auto auto 0;\n transform-origin: top left;\n will-change: transform;\n font-family: system-ui, sans-serif;\n color: #f5f3f6;\n}\n.jev-devtools .lab-connections {\n position: absolute;\n inset: 0;\n overflow: visible;\n}\n.jev-devtools .lab-connections path {\n fill: none;\n stroke: #645a68;\n stroke-width: 1;\n}\n.jev-devtools .lab-connections path.active {\n stroke: #968592;\n}\n.jev-devtools .lab-connections text {\n fill: #b7b1bc;\n font:\n 12px ui-monospace,\n monospace;\n}\n.jev-devtools .lab-flow-dot {\n fill: #e551ba;\n}\n.jev-devtools .lab-card {\n position: absolute;\n border: 1.3px solid #f5f3f6;\n border-radius: 14px;\n padding: 16px;\n background: #0d0a0f;\n overflow: hidden;\n}\n.jev-devtools .lab-eyebrow {\n display: block;\n color: #e551ba;\n font:\n 500 10px ui-monospace,\n monospace;\n letter-spacing: 1px;\n margin: 0 0 7px;\n}\n.jev-devtools .lab-card h3 {\n font-size: 16px;\n font-weight: 600;\n line-height: 1.3;\n letter-spacing: -0.2px;\n margin: 0 0 10px;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n.jev-devtools .lab-card p {\n font-size: 13px;\n line-height: 1.4;\n margin: 10px 0;\n}\n.jev-devtools .lab-copy {\n display: -webkit-box;\n -webkit-line-clamp: 5;\n -webkit-box-orient: vertical;\n overflow: hidden;\n overflow-wrap: anywhere;\n}\n.jev-devtools .lab-probability {\n margin: 17px 0;\n}\n.jev-devtools .lab-probability > div:first-child {\n display: flex;\n justify-content: space-between;\n gap: 10px;\n margin-bottom: 9px;\n font-size: 15px;\n}\n.jev-devtools .lab-probability span {\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n.jev-devtools .lab-probability code {\n font:\n 13px ui-monospace,\n monospace;\n}\n.jev-devtools .lab-track {\n height: 7px;\n border-radius: 4px;\n background: #f5f3f61a;\n overflow: hidden;\n}\n.jev-devtools .lab-track i {\n display: block;\n height: 100%;\n border-radius: 4px;\n background: #e551ba;\n}\n.jev-devtools .lab-track i.lab-alternative {\n opacity: 0.35;\n}\n.jev-devtools .lab-card .lab-result {\n font-size: 14px;\n margin-top: 24px;\n}\n.jev-devtools .lab-card .lab-small {\n font-size: 12px;\n color: #b7b1bc;\n margin-top: 20px;\n}\n.jev-devtools .lab-idle {\n opacity: 0.65;\n}\n.jev-devtools .lab-scale {\n position: relative;\n margin-top: 18px;\n border-top: 1px solid #b7b1bc;\n display: flex;\n justify-content: space-between;\n padding-top: 9px;\n}\n.jev-devtools .lab-scale > span {\n position: absolute;\n top: -5px;\n width: 9px;\n height: 9px;\n border-radius: 50%;\n background: #e551ba;\n transform: translateX(-50%);\n}\n.jev-devtools .lab-big {\n display: block;\n font-size: 36px;\n font-weight: 500;\n margin-top: 26px;\n}\n.jev-devtools .lab-endpoints {\n display: flex;\n justify-content: space-between;\n font-size: 12px;\n color: #b7b1bc;\n margin-top: 10px;\n}\n.jev-devtools .lab-image {\n position: relative;\n}\n.jev-devtools .lab-image img {\n display: block;\n width: 100%;\n}\n.jev-devtools .lab-box {\n position: absolute;\n border: 1.5px solid #e551ba;\n background: #e551ba15;\n}\n.jev-devtools .lab-source-image {\n width: 100%;\n max-height: 105px;\n object-fit: contain;\n}\n.jev-devtools .lab-coordinates {\n font-family: ui-monospace, monospace;\n}\n@media (prefers-reduced-motion: reduce) {\n .jev-devtools .lab-flow-dot {\n display: none;\n }\n}\n/* The public TypeSafe mark travels with the package, independent of host assets. */\n.jev-devtools .typesafe-mark {\n display: inline-block;\n flex: 0 0 23px;\n width: 23px;\n height: 32px;\n overflow: hidden;\n line-height: 0;\n}\n.jev-devtools .typesafe-mark img {\n display: block;\n height: 32px;\n width: auto;\n max-width: none;\n}\n\n.jev-devtools .detail-body-questions {\n display: flex;\n flex-direction: column;\n overflow: auto;\n}\n.jev-devtools .questions-list {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 180px;\n}\n.jev-devtools .questions-navigation {\n display: flex;\n align-items: end;\n gap: 8px;\n flex-wrap: wrap;\n flex-shrink: 0;\n}\n.jev-devtools .questions-navigation label {\n display: flex;\n align-items: center;\n gap: 8px;\n white-space: nowrap;\n flex: 1;\n min-width: 240px;\n max-width: 480px;\n font-size: 11px;\n color: #bc9db5;\n}\n.jev-devtools .questions-navigation select {\n display: block;\n min-width: 0;\n}\n.jev-devtools .questions-navigation > span {\n align-self: center;\n color: #a89bac;\n}\n.jev-devtools .questions-help {\n margin: 8px 0;\n flex-shrink: 0;\n}\n.jev-devtools .questions-viewport {\n flex: 1;\n min-height: 0;\n overflow: auto;\n overflow-anchor: none;\n scrollbar-gutter: stable;\n padding: 3px;\n}\n.jev-devtools .questions-spacer {\n position: relative;\n width: 100%;\n}\n.jev-devtools .questions-row {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n padding-bottom: 14px;\n}\n.jev-devtools .questions-row .standalone {\n margin-bottom: 0;\n}\n.jev-devtools .questions-viewport:focus-visible,\n.jev-devtools .questions-row article:focus-visible {\n outline: 2px solid #e551ba;\n outline-offset: -2px;\n}\n\n/* Reserve measured card geometry while rapid scrolling uses a light preview. */\n.jev-devtools .questions-row[data-preview=\"true\"] article {\n height: 100%;\n}\n.jev-devtools .question-scroll-preview p {\n margin-top: 16px;\n}\n\n/* The full distribution stays at reading size, outside the zoomable canvas. */\n.jev-devtools .lab-flow-viewport[hidden] {\n display: none;\n}\n.jev-devtools .lab-choice-browser {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n padding: 8px 16px;\n gap: 10px;\n}\n.jev-devtools .lab-choice-controls {\n display: flex;\n gap: 12px;\n align-items: end;\n flex-wrap: wrap;\n font-size: 12px;\n}\n.jev-devtools .lab-choice-controls label {\n display: grid;\n gap: 5px;\n}\n.jev-devtools .lab-choice-table-scroll {\n overflow: auto;\n overscroll-behavior: contain;\n min-height: 0;\n}\n.jev-devtools .lab-choice-browser table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n.jev-devtools .lab-choice-browser caption {\n text-align: left;\n padding: 8px 0;\n color: #aaa0af;\n}\n.jev-devtools .lab-choice-browser th,\n.jev-devtools .lab-choice-browser td {\n padding: 9px 12px;\n border-bottom: 1px solid #302634;\n text-align: left;\n}\n.jev-devtools .lab-choice-browser th {\n overflow-wrap: anywhere;\n max-width: 320px;\n}\n.jev-devtools .lab-choice-browser td {\n font-variant-numeric: tabular-nums;\n}\n.jev-devtools .lab-choice-browser code {\n white-space: normal;\n overflow-wrap: anywhere;\n}\n.jev-devtools .lab-choice-returned {\n display: block;\n font-size: 10px;\n color: #e551ba;\n}\n.jev-devtools .lab-choice-pagination {\n display: flex;\n align-items: center;\n gap: 12px;\n justify-content: space-between;\n font-size: 12px;\n}\n.jev-devtools .lab-choice-remainder button {\n margin-top: 7px;\n}\n\n.jev-devtools .lab-flow-compact .lab-output {\n padding: 12px;\n height: 104px;\n}\n.jev-devtools .lab-flow-compact .lab-output .lab-eyebrow {\n margin-bottom: 6px;\n}\n.jev-devtools .lab-flow-compact .lab-output h3 {\n font-size: 16px;\n margin-bottom: 8px;\n}\n.jev-devtools .lab-flow-compact .lab-output p {\n font-size: 12px;\n margin: 4px 0;\n}\n.jev-devtools .lab-flow-compact .lab-result {\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n overflow-wrap: anywhere;\n}\n.jev-devtools .lab-choice-remainder {\n padding: 12px;\n}\n.jev-devtools .lab-choice-remainder .lab-small {\n margin: 8px 0 0;\n font-size: 11px;\n}\n\n.jev-devtools .detail-body.detail-body-flow {\n flex-direction: column;\n}\n.jev-devtools .detail-body-flow > .warning,\n.jev-devtools .detail-body-flow > .error-banner {\n flex-shrink: 0;\n margin: 6px 16px;\n}\n.jev-devtools .lab-choice-browser {\n overflow: auto;\n}\n.jev-devtools .lab-choice-table-scroll {\n flex: 1 0 110px;\n}\n\n/* Only freshly revealed branches enter; pan/zoom remains on the canvas. */\n.jev-devtools .lab-card-enter {\n animation: jev-card-enter 280ms cubic-bezier(0.2, 0.8, 0.2, 1) backwards;\n}\n.jev-devtools .lab-branch-enter {\n stroke-dasharray: 1;\n animation: jev-branch-enter 280ms ease-out backwards;\n}\n@keyframes jev-card-enter {\n from {\n opacity: 0;\n transform: translateX(-16px) scale(0.96);\n }\n}\n@keyframes jev-branch-enter {\n from {\n opacity: 0;\n stroke-dashoffset: 1;\n }\n to {\n opacity: 1;\n stroke-dashoffset: 0;\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .jev-devtools .lab-card-enter,\n .jev-devtools .lab-branch-enter {\n animation: none;\n }\n}\n\n/* Connected requests share one camera and one opt-in full request detail.\n :where scopes these selectors without changing their existing specificity. */\n:where(.jev-devtools) .whole-flow {\n min-width: 0;\n overflow: hidden;\n}\n:where(.jev-devtools)\n .flow-overview-stack:not(.flow-inline-overview)\n > .whole-flow {\n /* Short drawers must scroll metadata instead of clipping the canvas controls. */\n overflow: auto;\n}\n:where(.jev-devtools) .whole-flow > .detail-header {\n flex-wrap: wrap;\n flex-shrink: 0;\n}\n:where(.jev-devtools) .flow-workspace {\n display: flex;\n flex-direction: column;\n flex: 1 0 auto;\n min-height: 0;\n overflow: hidden;\n}\n:where(.jev-devtools) .flow-details-panel {\n flex: none;\n min-width: 0;\n background: #130f17;\n border-top: 1px solid #342a38;\n}\n:where(.jev-devtools) .flow-details-bar {\n display: flex;\n align-items: center;\n gap: 12px;\n height: 36px;\n padding: 0 12px;\n}\n.jev-devtools .flow-details-bar button {\n flex: none;\n padding: 4px 8px;\n font-size: 11px;\n}\n:where(.jev-devtools) .flow-details-bar > span {\n color: #b5a6bc;\n font-size: 11px;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n:where(.jev-devtools) .flow-details-body {\n overflow: auto;\n overscroll-behavior: contain;\n scrollbar-gutter: stable;\n}\n:where(.jev-devtools) .flow-details-resize {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 8px;\n cursor: ns-resize;\n touch-action: none;\n user-select: none;\n}\n:where(.jev-devtools) .flow-details-resize span {\n width: 40px;\n height: 2px;\n border-radius: 2px;\n background: #6c5874;\n}\n:where(.jev-devtools) .flow-details-resize:hover,\n:where(.jev-devtools) .flow-details-resize:focus-visible {\n background: #392239;\n outline: 1px solid #e551ba;\n outline-offset: -1px;\n}\n:where(.jev-devtools) .flow-overview-viewport {\n background-color: #08060a;\n position: relative;\n /* The panel's grid row reserves its actual height, including wrapped buttons. */\n display: grid;\n min-height: min-content;\n flex: 1 1 0;\n overflow: hidden;\n touch-action: none;\n cursor: grab;\n background-image: radial-gradient(\n rgb(83 67 87 / var(--diagram-grid-opacity, 1))\n calc(1px * var(--diagram-grid-weight, 1)),\n transparent calc(1px * var(--diagram-grid-weight, 1))\n );\n background-size: 20px 20px;\n}\n.jev-devtools .flow-canvas-controls {\n align-self: start;\n justify-self: end;\n margin: 12px;\n z-index: 1;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n max-width: calc(100% - 24px);\n padding: 8px;\n border: 1px solid #3b303d;\n border-radius: 10px;\n background: #17121b;\n box-shadow: 0 4px 16px #0006;\n cursor: default;\n}\n:where(.jev-devtools) .flow-overview-viewport[data-panning] {\n cursor: grabbing;\n}\n:where(.jev-devtools) .flow-overview-canvas {\n position: absolute;\n /* Keep camera coordinates at the viewport origin when the overlay uses grid. */\n top: 0;\n left: 0;\n transform-origin: 0 0;\n}\n:where(.jev-devtools) .flow-connections {\n position: absolute;\n inset: 0;\n overflow: visible;\n color: #c0b8c4;\n pointer-events: none;\n}\n:where(.jev-devtools) .flow-step {\n position: absolute;\n min-height: 172px;\n overflow-wrap: anywhere;\n display: flex;\n flex-direction: column;\n gap: 8px;\n text-align: left;\n padding: 14px;\n border: 1px solid #736476;\n border-radius: 12px;\n background: #151017;\n color: inherit;\n}\n:where(.jev-devtools) .flow-step strong {\n white-space: normal;\n width: 100%;\n}\n:where(.jev-devtools) .flow-step-description {\n overflow-wrap: anywhere;\n font-size: 12px;\n}\n:where(.jev-devtools) .flow-step.flow-request {\n display: block;\n padding: 0;\n background: #0d0a0f;\n /* Skip offscreen paint/layout while preserving each question/expansion state. */\n content-visibility: auto;\n contain-intrinsic-size: auto 640px;\n}\n:where(.jev-devtools) .flow-request-heading {\n width: 100%;\n min-height: 64px;\n gap: 20px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n text-align: left;\n padding: 12px 20px;\n border: 0;\n border-bottom: 1px solid #342a38;\n border-radius: 12px 12px 0 0;\n background: transparent;\n color: inherit;\n}\n:where(.jev-devtools) .flow-request-heading .eyebrow {\n display: block;\n margin-bottom: 4px;\n}\n.jev-devtools .lab-flow-embedded {\n width: 1120px;\n display: block;\n}\n.jev-devtools .lab-flow-surface {\n position: relative;\n width: 1120px;\n}\n.jev-devtools .lab-flow-surface[hidden] {\n display: none;\n}\n.jev-devtools .lab-flow-embedded .lab-flow-canvas {\n will-change: auto;\n}\n.jev-devtools .lab-flow-embedded .lab-choice-browser {\n height: 520px;\n}\n:where(.jev-devtools) .flow-step.selected {\n outline: 2px solid #e551ba;\n outline-offset: 3px;\n}\n:where(.jev-devtools) .flow-step[data-status=\"completed\"] {\n border-color: #e551ba;\n}\n:where(.jev-devtools) .flow-step[data-status=\"running\"] {\n border-color: #e551ba;\n background: #2b1728;\n}\n:where(.jev-devtools) .flow-step[data-status=\"untaken\"],\n:where(.jev-devtools) .flow-step[data-status=\"blocked\"] {\n color: #948797;\n border-color: #403746;\n background: #151017;\n}\n:where(.jev-devtools) .flow-step[data-status=\"error\"] {\n border-color: #f17c78;\n}\n:where(.jev-devtools) .flow-step[data-status=\"cancelled\"] {\n border-style: dashed;\n}\n:where(.jev-devtools) .flow-selection {\n padding: 12px 20px;\n border-top: 1px solid #342a38;\n}\n:where(.jev-devtools) .flow-selection p {\n margin: 6px 0;\n overflow-wrap: anywhere;\n}\n:where(.jev-devtools) .flow-request-detail {\n min-height: 450px;\n border-top: 1px solid #534357;\n}\n:where(.jev-devtools) .flow-request-detail > .request-detail {\n min-height: 450px;\n}\n\n:where(.jev-devtools) .flow-card-heading,\n:where(.jev-devtools) .flow-card-footer,\n:where(.jev-devtools) .flow-join-summary,\n:where(.jev-devtools) .flow-lane {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n width: 100%;\n}\n:where(.jev-devtools) .flow-card-heading {\n justify-content: flex-start;\n}\n:where(.jev-devtools) .flow-task .flow-kind-icon {\n border: 1px solid currentColor;\n border-radius: 6px;\n padding: 4px;\n}\n:where(.jev-devtools) .flow-task-preview {\n display: grid;\n gap: 8px;\n min-width: 0;\n}\n.jev-devtools .flow-task-preview .diagram-content {\n max-height: 280px;\n padding: 8px 10px;\n border: 1px solid #35283b;\n border-radius: 4px;\n background: #100c13;\n}\n:where(.jev-devtools) .flow-task-preview small {\n color: #a89bac;\n font-size: 11px;\n}\n:where(.jev-devtools) .flow-task-details {\n display: grid;\n gap: 12px;\n}\n:where(.jev-devtools) .flow-task-details details {\n min-width: 0;\n}\n:where(.jev-devtools) .flow-task-details summary {\n cursor: pointer;\n margin-bottom: 8px;\n}\n:where(.jev-devtools) .flow-task-details .diagram-content {\n max-height: 320px;\n overflow: auto;\n}\n:where(.jev-devtools) .flow-kind-icon {\n width: 26px;\n height: 26px;\n color: #e551ba;\n flex-shrink: 0;\n}\n:where(.jev-devtools) .flow-kind-icon svg {\n width: 100%;\n height: 100%;\n}\n:where(.jev-devtools) .flow-card-heading .eyebrow {\n font-size: 10px;\n}\n:where(.jev-devtools) .flow-status {\n margin-left: auto;\n font-size: 10px;\n border-radius: 20px;\n padding: 4px 8px;\n background: #342031;\n color: #f0b7e0;\n}\n:where(.jev-devtools) .flow-step[data-status=\"untaken\"] .flow-status {\n background: #241e28;\n color: #948797;\n}\n:where(.jev-devtools) .flow-step[data-status=\"untaken\"] .flow-kind-icon {\n color: #948797;\n}\n:where(.jev-devtools) .flow-card-body > strong {\n white-space: normal;\n font-size: 18px;\n line-height: 1.25;\n overflow-wrap: anywhere;\n}\n:where(.jev-devtools) .flow-step-description {\n line-height: 1.5;\n color: #b9aebf;\n white-space: pre-wrap;\n}\n:where(.jev-devtools) .flow-card-footer {\n margin-top: auto;\n padding-top: 10px;\n border-top: 1px solid #342a38;\n font-size: 10px;\n color: #a092a7;\n}\n:where(.jev-devtools) .flow-card-footer code {\n max-width: 45%;\n white-space: normal;\n overflow-wrap: anywhere;\n}\n:where(.jev-devtools) .flow-card-footer small {\n text-align: right;\n}\n:where(.jev-devtools) .flow-join-summary {\n margin-top: 4px;\n font-size: 11px;\n color: #c9b9cd;\n}\n:where(.jev-devtools) .flow-join-summary > span {\n color: #ef9ed9;\n font-variant-numeric: tabular-nums;\n}\n:where(.jev-devtools) .flow-lanes {\n display: flex;\n flex-direction: column;\n gap: 4px;\n width: 100%;\n}\n:where(.jev-devtools) .flow-lane {\n border-radius: 5px;\n background: #211923;\n padding: 6px 8px;\n font-size: 11px;\n min-height: 28px;\n}\n:where(.jev-devtools) .flow-lane > span {\n min-width: 0;\n overflow-wrap: anywhere;\n}\n:where(.jev-devtools) .flow-lane > span > span {\n color: #ef9ed9;\n margin-right: 4px;\n}\n:where(.jev-devtools) .flow-lane small {\n color: #b9aebf;\n}\n:where(.jev-devtools) .flow-lane-details {\n padding-left: 18px;\n font-size: 12px;\n}\n:where(.jev-devtools) .flow-request-heading > span:first-child {\n min-width: 0;\n max-width: 80%;\n}\n:where(.jev-devtools) .flow-request-description {\n display: block;\n white-space: pre-wrap;\n font-size: 12px;\n line-height: 1.5;\n color: #b9aebf;\n margin-top: 5px;\n overflow-wrap: anywhere;\n}\n\n/* Structured context stays within the card; its gestures never move the camera. */\n.jev-devtools .lab-content-card {\n display: flex;\n flex-direction: column;\n padding: 14px;\n}\n.jev-devtools .lab-content-card h3 {\n font-size: 14px;\n margin-bottom: 8px;\n flex-shrink: 0;\n}\n.jev-devtools .lab-content-card .lab-eyebrow {\n font-size: 9px;\n margin-bottom: 5px;\n flex-shrink: 0;\n}\n.jev-devtools .diagram-content {\n min-height: 0;\n flex: 1;\n overflow: auto;\n overscroll-behavior: contain;\n touch-action: pan-y;\n scrollbar-width: thin;\n scrollbar-color: #514256 transparent;\n padding-right: 4px;\n font-size: 12px;\n line-height: 1.5;\n color: #d5cdd9;\n cursor: auto;\n user-select: text;\n}\n.jev-devtools .diagram-content:focus-visible {\n outline: 1px solid #e551ba;\n outline-offset: -1px;\n border-radius: 3px;\n}\n.jev-devtools .diagram-property {\n display: flex;\n justify-content: space-between;\n align-items: baseline;\n gap: 8px;\n padding: 5px 0;\n border-bottom: 1px solid #261e2a;\n}\n.jev-devtools .diagram-property-text {\n display: block;\n}\n.jev-devtools .diagram-property-key {\n font:\n 10px/1.5 ui-monospace,\n monospace;\n color: #c8a8c8;\n overflow-wrap: anywhere;\n min-width: 0;\n}\n.jev-devtools .diagram-property-text > .diagram-property-key {\n display: block;\n margin-bottom: 2px;\n}\n.jev-devtools .diagram-text-value {\n display: block;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n.jev-devtools .diagram-text-preview {\n display: -webkit-box;\n -webkit-line-clamp: 3;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n.jev-devtools .diagram-value-number {\n color: #a6d6ca;\n font:\n 11px/1.5 ui-monospace,\n monospace;\n font-variant-numeric: tabular-nums;\n overflow-wrap: anywhere;\n}\n.jev-devtools .diagram-value-boolean {\n color: #c4b1ed;\n font:\n 11px/1.5 ui-monospace,\n monospace;\n}\n.jev-devtools .diagram-value-empty {\n color: #9c8ca4;\n font:\n 10px/1.5 ui-monospace,\n monospace;\n}\n.jev-devtools .diagram-property-disclosure {\n width: 100%;\n display: flex;\n align-items: baseline;\n gap: 5px;\n padding: 6px 0;\n border: 0;\n border-bottom: 1px solid #261e2a;\n border-radius: 0;\n background: transparent;\n text-align: left;\n color: inherit;\n}\n.jev-devtools .diagram-property-disclosure:hover {\n background: #211723;\n}\n.jev-devtools .diagram-property-caret {\n color: #ab8aab;\n flex-shrink: 0;\n}\n.jev-devtools .diagram-property-type {\n color: #9c8ca4;\n font:\n 10px/1.5 ui-monospace,\n monospace;\n margin-left: auto;\n flex-shrink: 0;\n}\n.jev-devtools .diagram-property-children {\n margin-left: 4px;\n padding-left: 9px;\n border-left: 1px solid #49324b;\n}\n.jev-devtools .diagram-content-toggle {\n display: block;\n padding: 3px 0;\n border: 0;\n border-radius: 0;\n background: transparent;\n color: #e9a4d7;\n font-size: 10px;\n text-align: left;\n}\n.jev-devtools .diagram-content-toggle:hover {\n color: #ffd9f3;\n text-decoration: underline;\n}\n\n/* Noul is a probability of true; its two outputs carry p and 1-p.\n Keep the fill opaque, with readable text even at zero probability. */\n.jev-devtools .lab-noul-output {\n border-color: rgb(\n 245 243 246 / calc(0.35 + 0.65 * var(--lab-noul-probability, 1))\n );\n}\n.jev-devtools .lab-noul-output > h3,\n.jev-devtools .lab-noul-output > p {\n opacity: calc(0.65 + 0.35 * var(--lab-noul-probability, 1));\n}\n\n:where(.jev-devtools) .flow-condition-rule {\n display: block;\n padding: 10px 12px;\n border: 1px solid #49324b;\n border-radius: 6px;\n background: #211723;\n width: 100%;\n}\n:where(.jev-devtools) .flow-condition-label {\n display: block;\n font-size: 10px;\n color: #ba9dbe;\n margin-bottom: 5px;\n}\n:where(.jev-devtools) .flow-condition-rule code {\n white-space: pre-wrap;\n font:\n 12px/1.6 ui-monospace,\n monospace;\n color: #f2d7eb;\n}\n/* Bound card previews so long captured literals cannot push warnings off-canvas.\n The complete captured rule remains available in selected-step details. */\n:where(.jev-devtools) .flow-condition-rule code,\n:where(.jev-devtools) .flow-map-progress > code {\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 4;\n overflow: hidden;\n overflow-wrap: anywhere;\n}\n\n:where(.jev-devtools) .flow-condition-incoming {\n display: block;\n padding-bottom: 10px;\n margin-bottom: 10px;\n border-bottom: 1px solid #49324b;\n}\n:where(.jev-devtools) .flow-condition-input {\n display: flex;\n justify-content: space-between;\n align-items: baseline;\n gap: 12px;\n font-size: 12px;\n padding: 3px 0;\n}\n:where(.jev-devtools) .flow-condition-input > span {\n min-width: 0;\n overflow-wrap: anywhere;\n}\n:where(.jev-devtools) .flow-condition-input > b {\n font-size: 17px;\n font-weight: 600;\n color: #f2d7eb;\n overflow-wrap: anywhere;\n white-space: normal;\n max-width: 65%;\n}\n:where(.jev-devtools) .flow-input-details {\n font-size: 12px;\n}\n:where(.jev-devtools) .flow-input-details > div {\n display: flex;\n gap: 16px;\n margin: 6px 0;\n}\n:where(.jev-devtools) .flow-input-details code {\n color: #a092a7;\n margin-left: 8px;\n}\n:where(.jev-devtools) .flow-input-details dd {\n margin: 0;\n overflow-wrap: anywhere;\n}\n\n:where(.jev-devtools) .flow-overview-stack {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n min-width: 0;\n overflow: hidden;\n}\n:where(.jev-devtools) .flow-map-progress {\n display: grid;\n gap: 10px;\n font-size: 14px;\n line-height: 1.5;\n}\n:where(.jev-devtools) .flow-map-progress small {\n color: #b5a6bc;\n}\n\n.jev-devtools .flow-card-body {\n display: flex;\n flex-direction: column;\n gap: 8px;\n width: 100%;\n flex: 1;\n padding: 0;\n border: 0;\n border-radius: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n text-align: left;\n}\n.jev-devtools .flow-card-body:hover {\n background: transparent;\n}\n:where(.jev-devtools) .flow-collection-controls {\n display: flex;\n align-items: end;\n gap: 10px;\n border-top: 1px solid #49324b;\n margin-top: 4px;\n padding-top: 12px;\n}\n:where(.jev-devtools) .flow-collection-controls label {\n display: grid;\n gap: 6px;\n flex: 1;\n min-width: 0;\n color: #b9aebf;\n font-size: 11px;\n}\n.jev-devtools .flow-collection-controls select {\n width: 100%;\n min-width: 0;\n}\n.jev-devtools .flow-collection-controls button {\n flex: none;\n color: #efb1df;\n}\n:where(.jev-devtools) .flow-collection-expansion {\n position: absolute;\n width: max-content;\n}\n:where(.jev-devtools) .flow-item-frame {\n border: 1px solid #64415d;\n border-radius: 12px;\n background: #100c13;\n overflow: hidden;\n}\n:where(.jev-devtools) .flow-collection-heading {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 24px;\n padding: 16px 20px;\n border-bottom: 1px solid #49324b;\n background: #1c1220;\n}\n:where(.jev-devtools) .flow-collection-heading h3 {\n margin: 5px 0;\n font-size: 16px;\n}\n:where(.jev-devtools) .flow-collection-heading small {\n color: #b9aebf;\n}\n:where(.jev-devtools) .flow-collection-link text {\n fill: #ce9abd;\n font-size: 12px;\n}\n:where(.jev-devtools) .flow-item-placeholder {\n width: 600px;\n padding: 24px;\n line-height: 1.6;\n}\n:where(.jev-devtools) .flow-inline-overview,\n:where(.jev-devtools) .flow-inline-overview > .whole-flow,\n:where(.jev-devtools) .flow-inline-overview > .whole-flow > .flow-workspace {\n display: block;\n flex: none;\n}\n:where(.jev-devtools) .flow-inline-surface {\n position: relative;\n}\n\n:where(.jev-devtools) .flow-item-content {\n min-width: 0;\n animation: jev-flow-item-enter 240ms cubic-bezier(0.22, 1, 0.36, 1) both;\n}\n:where(.jev-devtools) .flow-item-forward {\n --flow-item-offset: 28px;\n}\n:where(.jev-devtools) .flow-item-backward {\n --flow-item-offset: -28px;\n}\n@keyframes jev-flow-item-enter {\n from {\n opacity: 0;\n transform: translateX(var(--flow-item-offset));\n }\n to {\n opacity: 1;\n transform: translateX(0);\n }\n}\n@media (prefers-reduced-motion: reduce) {\n :where(.jev-devtools) .flow-item-content {\n animation: none;\n }\n}\n.jev-devtools .flow-item-arrow {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n display: grid;\n place-items: center;\n width: 56px;\n height: 56px;\n padding: 12px;\n margin: 0 auto;\n border: 1px solid #64415d;\n border-radius: 6px;\n background: #211623;\n color: #efa7db;\n}\n.jev-devtools .flow-item-arrow:hover:not(:disabled) {\n background: #382035;\n border-color: #e551ba;\n}\n:where(.jev-devtools) .flow-item-arrow svg {\n width: 28px;\n height: 28px;\n}\n\n:where(.jev-devtools) .flow-item-previous {\n left: -76px;\n}\n:where(.jev-devtools) .flow-item-next {\n right: -76px;\n}\n.jev-devtools .flow-run-summary {\n max-width: 100%;\n margin-left: auto;\n text-align: right;\n}\n.jev-devtools .flow-run-controls {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: flex-end;\n gap: 10px;\n margin-top: 6px;\n}\n.jev-devtools .flow-run-controls .flow-step-select {\n max-width: 100%;\n}\n.jev-devtools .flow-step-select select {\n min-width: 0;\n}\n.jev-devtools .flow-fixture-button {\n flex-shrink: 0;\n /* Keep the header still when the shorter confirmation replaces the label. */\n min-width: 96px;\n font-size: 11px;\n transition:\n background-color 160ms ease,\n border-color 160ms ease;\n}\n.jev-devtools .flow-fixture-button[data-copied] {\n border-color: #e551ba;\n background: #382035;\n animation: jev-fixture-copied 200ms ease-out;\n}\n@keyframes jev-fixture-copied {\n from {\n transform: scale(0.96);\n }\n to {\n transform: scale(1);\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .jev-devtools .flow-fixture-button {\n transition: none;\n }\n .jev-devtools .flow-fixture-button[data-copied] {\n animation: none;\n }\n}\n.jev-devtools .flow-fixture {\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n flex-shrink: 0;\n gap: 4px;\n padding: 0 24px;\n text-align: right;\n}\n.jev-devtools .flow-fixture p {\n margin: 0;\n max-width: 360px;\n font-size: 11px;\n}\n.jev-devtools .flow-fixture details {\n max-width: 360px;\n font-size: 11px;\n}\n.jev-devtools .flow-fixture details ul {\n max-height: 120px;\n margin: 4px 0 0;\n padding: 0;\n overflow: auto;\n list-style: none;\n font-family: \"JetBrains Mono\", monospace;\n overflow-wrap: anywhere;\n}\n.jev-devtools .flow-fixture details ul:focus-visible {\n outline: 2px solid #e551ba;\n outline-offset: 2px;\n}\n.jev-devtools .flow-fixture textarea {\n width: 360px;\n max-width: 100%;\n height: 120px;\n padding: 8px;\n font:\n 11px \"JetBrains Mono\",\n monospace;\n text-align: left;\n}\n";