@copilotkit/web-inspector 1.79.2-canary.1792172552 → 1.80.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/learning-view.cjs +145 -10
- package/dist/components/learning-view.cjs.map +1 -1
- package/dist/components/learning-view.mjs +145 -10
- package/dist/components/learning-view.mjs.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +150 -12
- package/dist/index.umd.js.map +1 -1
- package/dist/lib/telemetry.cjs.map +1 -1
- package/dist/lib/telemetry.mjs.map +1 -1
- package/dist/package.cjs +1 -1
- package/dist/package.mjs +1 -1
- package/package.json +5 -5
|
@@ -1,6 +1,52 @@
|
|
|
1
1
|
let lit = require("lit");
|
|
2
2
|
|
|
3
3
|
//#region src/components/learning-view.ts
|
|
4
|
+
const plural = (count, singular, pluralForm) => `${count} ${count === 1 ? singular : pluralForm}`;
|
|
5
|
+
/** Rows shown per evidence kind before the panel asks to show more. */
|
|
6
|
+
const EVIDENCE_PREVIEW_LIMIT = 10;
|
|
7
|
+
const EVIDENCE_NOUNS = {
|
|
8
|
+
threads: ["Thread", "Threads"],
|
|
9
|
+
trajectories: ["Trajectory", "Trajectories"]
|
|
10
|
+
};
|
|
11
|
+
const trajectoryTimeFormat = new Intl.DateTimeFormat(void 0, {
|
|
12
|
+
month: "short",
|
|
13
|
+
day: "numeric",
|
|
14
|
+
hour: "numeric",
|
|
15
|
+
minute: "2-digit"
|
|
16
|
+
});
|
|
17
|
+
/**
|
|
18
|
+
* Reads the creation time from a UUIDv7 Trajectory id, whose first 48 bits
|
|
19
|
+
* are Unix milliseconds. Returns null for ids of any other version.
|
|
20
|
+
*/
|
|
21
|
+
const trajectoryCreatedAt = (trajectoryId) => {
|
|
22
|
+
const hex = trajectoryId.replace(/-/g, "");
|
|
23
|
+
if (!/^[0-9a-f]{12}7[0-9a-f]{19}$/i.test(hex)) return null;
|
|
24
|
+
return new Date(Number.parseInt(hex.slice(0, 12), 16));
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* "Showing 100 of 412 Trajectories" for each kind the response shortened,
|
|
28
|
+
* or null when every cited source is listed.
|
|
29
|
+
*/
|
|
30
|
+
function evidenceCoverageLabel(insight) {
|
|
31
|
+
if (!insight.evidenceTruncated) return null;
|
|
32
|
+
const parts = [];
|
|
33
|
+
if (insight.evidence.length < insight.totalThreadCount) parts.push(`${insight.evidence.length} of ${plural(insight.totalThreadCount, ...EVIDENCE_NOUNS.threads)}`);
|
|
34
|
+
const trajectoriesShown = insight.trajectoryEvidence?.length ?? 0;
|
|
35
|
+
if (insight.totalTrajectoryCount !== void 0 && trajectoriesShown < insight.totalTrajectoryCount) parts.push(`${trajectoriesShown} of ${plural(insight.totalTrajectoryCount, ...EVIDENCE_NOUNS.trajectories)}`);
|
|
36
|
+
return parts.length === 0 ? null : `Showing ${parts.join(" · ")}`;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Labels the sources an Insight cites. Trajectories are named only when
|
|
40
|
+
* cited, so Thread-only Insights and older Intelligence versions read as
|
|
41
|
+
* before.
|
|
42
|
+
*/
|
|
43
|
+
function evidenceCountLabel(insight) {
|
|
44
|
+
const threads = plural(insight.totalThreadCount, "Thread", "Threads");
|
|
45
|
+
const trajectoryCount = insight.totalTrajectoryCount ?? insight.trajectoryEvidence?.length ?? 0;
|
|
46
|
+
if (trajectoryCount === 0) return threads;
|
|
47
|
+
const trajectories = plural(trajectoryCount, "Trajectory", "Trajectories");
|
|
48
|
+
return insight.totalThreadCount === 0 ? trajectories : `${threads} · ${trajectories}`;
|
|
49
|
+
}
|
|
4
50
|
function deriveLearningViewState(input) {
|
|
5
51
|
if (!input.supported) return input.setupActive ? "setup" : "landing";
|
|
6
52
|
if (!input.snapshot && input.loading) return "loading";
|
|
@@ -32,6 +78,7 @@ var CpkLearningView = class extends lit.LitElement {
|
|
|
32
78
|
this.promptTrigger = null;
|
|
33
79
|
this.expandedSkillId = null;
|
|
34
80
|
this.selectedInsightId = null;
|
|
81
|
+
this.expandedEvidence = /* @__PURE__ */ new Set();
|
|
35
82
|
this.skillPageKey = "";
|
|
36
83
|
this.handlePromptKeydown = (event) => {
|
|
37
84
|
if (event.key === "Escape") {
|
|
@@ -789,7 +836,9 @@ var CpkLearningView = class extends lit.LitElement {
|
|
|
789
836
|
text-align: left;
|
|
790
837
|
}
|
|
791
838
|
.evidence-link {
|
|
839
|
+
box-sizing: border-box;
|
|
792
840
|
width: 100%;
|
|
841
|
+
text-decoration: none;
|
|
793
842
|
cursor: pointer;
|
|
794
843
|
}
|
|
795
844
|
.evidence-link span {
|
|
@@ -800,6 +849,40 @@ var CpkLearningView = class extends lit.LitElement {
|
|
|
800
849
|
color: var(--learning-muted-strong);
|
|
801
850
|
font-style: italic;
|
|
802
851
|
}
|
|
852
|
+
.evidence-coverage {
|
|
853
|
+
margin: 12px 0 0;
|
|
854
|
+
color: var(--learning-muted-strong);
|
|
855
|
+
font-size: 11px;
|
|
856
|
+
}
|
|
857
|
+
.evidence-group-heading {
|
|
858
|
+
margin: 6px 0 0;
|
|
859
|
+
color: var(--learning-muted-strong);
|
|
860
|
+
font-size: 10px;
|
|
861
|
+
font-weight: 800;
|
|
862
|
+
letter-spacing: 0.06em;
|
|
863
|
+
text-transform: uppercase;
|
|
864
|
+
}
|
|
865
|
+
.evidence-group-heading:first-child {
|
|
866
|
+
margin-top: 0;
|
|
867
|
+
}
|
|
868
|
+
.evidence-id {
|
|
869
|
+
color: var(--learning-muted-strong);
|
|
870
|
+
font:
|
|
871
|
+
10px ui-monospace,
|
|
872
|
+
SFMono-Regular,
|
|
873
|
+
Menlo,
|
|
874
|
+
monospace;
|
|
875
|
+
}
|
|
876
|
+
.evidence-more {
|
|
877
|
+
justify-self: start;
|
|
878
|
+
padding: 2px 0;
|
|
879
|
+
color: var(--learning-purple-dark);
|
|
880
|
+
background: none;
|
|
881
|
+
border: 0;
|
|
882
|
+
font-size: 11px;
|
|
883
|
+
font-weight: 700;
|
|
884
|
+
cursor: pointer;
|
|
885
|
+
}
|
|
803
886
|
.pagination {
|
|
804
887
|
display: flex;
|
|
805
888
|
align-items: center;
|
|
@@ -1115,6 +1198,10 @@ var CpkLearningView = class extends lit.LitElement {
|
|
|
1115
1198
|
</nav>`;
|
|
1116
1199
|
}
|
|
1117
1200
|
renderEvidence(insight) {
|
|
1201
|
+
const threads = insight.evidence;
|
|
1202
|
+
const trajectories = insight.trajectoryEvidence ?? [];
|
|
1203
|
+
const mixed = threads.length > 0 && trajectories.length > 0;
|
|
1204
|
+
const coverage = evidenceCoverageLabel(insight);
|
|
1118
1205
|
return lit.html`<section class="detail-panel" aria-label="Insight evidence">
|
|
1119
1206
|
<div class="detail-head">
|
|
1120
1207
|
<div>
|
|
@@ -1133,12 +1220,11 @@ var CpkLearningView = class extends lit.LitElement {
|
|
|
1133
1220
|
×
|
|
1134
1221
|
</button>
|
|
1135
1222
|
</div>
|
|
1223
|
+
${coverage ? lit.html`<p class="evidence-coverage">${coverage}</p>` : lit.nothing}
|
|
1136
1224
|
<div class="evidence-list">
|
|
1137
|
-
${
|
|
1225
|
+
${threads.length === 0 && trajectories.length === 0 ? lit.html`
|
|
1138
1226
|
<div class="evidence-unavailable">Evidence is no longer available</div>
|
|
1139
|
-
` :
|
|
1140
|
-
<div class="evidence-unavailable">Evidence is no longer available</div>
|
|
1141
|
-
` : lit.html`<button
|
|
1227
|
+
` : lit.html`${this.renderEvidenceGroup(insight.id, "threads", threads, mixed, (evidence) => lit.html`<button
|
|
1142
1228
|
class="evidence-link"
|
|
1143
1229
|
type="button"
|
|
1144
1230
|
@click=${() => this.emit("learning-open-evidence", {
|
|
@@ -1149,12 +1235,63 @@ var CpkLearningView = class extends lit.LitElement {
|
|
|
1149
1235
|
⌁
|
|
1150
1236
|
${evidence.threadName ?? `Thread ${evidence.threadId.slice(0, 8)}`}
|
|
1151
1237
|
<span>Open Thread →</span>
|
|
1152
|
-
</button>`)}
|
|
1238
|
+
</button>`)}${this.renderEvidenceGroup(insight.id, "trajectories", trajectories, mixed, (evidence) => this.renderTrajectoryEvidence(evidence))}`}
|
|
1153
1239
|
</div>
|
|
1154
|
-
${insight.evidenceTruncated ? lit.html`
|
|
1240
|
+
${insight.evidenceTruncated && !coverage ? lit.html`
|
|
1155
1241
|
<p class="supporting-unavailable">Evidence response shortened</p>
|
|
1156
1242
|
` : lit.nothing}
|
|
1157
1243
|
</section>`;
|
|
1244
|
+
}
|
|
1245
|
+
/**
|
|
1246
|
+
* Lists one kind of evidence: the first rows with a toggle for the rest,
|
|
1247
|
+
* then one line counting the sources that are no longer available.
|
|
1248
|
+
*/
|
|
1249
|
+
renderEvidenceGroup(insightId, kind, entries, showHeading, renderRow) {
|
|
1250
|
+
if (entries.length === 0) return lit.nothing;
|
|
1251
|
+
const available = entries.filter((entry) => entry.status === "available");
|
|
1252
|
+
const unavailable = entries.length - available.length;
|
|
1253
|
+
const key = `${insightId}:${kind}`;
|
|
1254
|
+
const expanded = this.expandedEvidence.has(key);
|
|
1255
|
+
const hidden = Math.max(0, available.length - EVIDENCE_PREVIEW_LIMIT);
|
|
1256
|
+
const [singular, pluralForm] = EVIDENCE_NOUNS[kind];
|
|
1257
|
+
return lit.html`
|
|
1258
|
+
${showHeading ? lit.html`<h4 class="evidence-group-heading">${pluralForm}</h4>` : lit.nothing}
|
|
1259
|
+
${(expanded ? available : available.slice(0, EVIDENCE_PREVIEW_LIMIT)).map(renderRow)}
|
|
1260
|
+
${hidden > 0 ? lit.html`<button
|
|
1261
|
+
class="evidence-more"
|
|
1262
|
+
type="button"
|
|
1263
|
+
aria-expanded=${expanded}
|
|
1264
|
+
@click=${() => {
|
|
1265
|
+
if (expanded) this.expandedEvidence.delete(key);
|
|
1266
|
+
else this.expandedEvidence.add(key);
|
|
1267
|
+
this.requestUpdate();
|
|
1268
|
+
}}
|
|
1269
|
+
>
|
|
1270
|
+
${expanded ? `Show fewer ${pluralForm}` : `Show ${plural(hidden, `more ${singular}`, `more ${pluralForm}`)}`}
|
|
1271
|
+
</button>` : lit.nothing}
|
|
1272
|
+
${unavailable > 0 ? lit.html`<div class="evidence-unavailable">
|
|
1273
|
+
${plural(unavailable, singular, pluralForm)}
|
|
1274
|
+
${unavailable === 1 ? "is" : "are"} no longer available
|
|
1275
|
+
</div>` : lit.nothing}
|
|
1276
|
+
`;
|
|
1277
|
+
}
|
|
1278
|
+
renderTrajectoryEvidence(evidence) {
|
|
1279
|
+
const createdAt = trajectoryCreatedAt(evidence.trajectoryId);
|
|
1280
|
+
const idTail = evidence.trajectoryId.slice(-8);
|
|
1281
|
+
return lit.html`<a
|
|
1282
|
+
class="evidence-link"
|
|
1283
|
+
href=${evidence.url}
|
|
1284
|
+
target="_blank"
|
|
1285
|
+
rel="noopener noreferrer"
|
|
1286
|
+
title=${evidence.trajectoryId}
|
|
1287
|
+
@click=${() => this.emit("learning-web-link", { category: "trajectory" })}
|
|
1288
|
+
>
|
|
1289
|
+
⌁
|
|
1290
|
+
${createdAt ? `Trajectory · ${trajectoryTimeFormat.format(createdAt)}` : `Trajectory ${idTail}`}
|
|
1291
|
+
· ${plural(evidence.eventCount, "cited event", "cited events")}
|
|
1292
|
+
${createdAt ? lit.html`<small class="evidence-id">${idTail}</small>` : lit.nothing}
|
|
1293
|
+
<span>Open Trajectory ↗</span>
|
|
1294
|
+
</a>`;
|
|
1158
1295
|
}
|
|
1159
1296
|
selectInsight(insight) {
|
|
1160
1297
|
this.selectedInsightId = insight.id;
|
|
@@ -1198,8 +1335,7 @@ var CpkLearningView = class extends lit.LitElement {
|
|
|
1198
1335
|
@click=${() => this.selectInsight(skill.sourceInsight)}
|
|
1199
1336
|
>
|
|
1200
1337
|
${this.supportingInsightLabel(skill.sourceInsight.statement)}<small
|
|
1201
|
-
>${skill.sourceInsight
|
|
1202
|
-
${skill.sourceInsight.totalThreadCount === 1 ? "Thread" : "Threads"}</small
|
|
1338
|
+
>${evidenceCountLabel(skill.sourceInsight)}</small
|
|
1203
1339
|
>
|
|
1204
1340
|
</button>` : lit.html`
|
|
1205
1341
|
<div class="supporting-unavailable">Supporting Insight unavailable</div>
|
|
@@ -1254,8 +1390,7 @@ var CpkLearningView = class extends lit.LitElement {
|
|
|
1254
1390
|
<p>${insight.impact}</p>
|
|
1255
1391
|
</div>
|
|
1256
1392
|
<span class="evidence-count"
|
|
1257
|
-
>${insight
|
|
1258
|
-
${insight.totalThreadCount === 1 ? "Thread" : "Threads"}</span
|
|
1393
|
+
>${evidenceCountLabel(insight)}</span
|
|
1259
1394
|
>
|
|
1260
1395
|
</button>`)}
|
|
1261
1396
|
</div>`}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"learning-view.cjs","names":["LitElement","nothing"],"sources":["../../src/components/learning-view.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from \"lit\";\nimport type {\n InspectorLearningInsight,\n InspectorLearningSnapshotV1,\n} from \"@copilotkit/shared\";\n\nexport type LearningViewState =\n | \"loading\"\n | \"error\"\n | \"selection_required\"\n | \"invalid\"\n | \"results\"\n | \"first_run\"\n | \"ready\"\n | \"empty\"\n | \"setup\"\n | \"landing\";\n\nexport function deriveLearningViewState(input: {\n readonly supported: boolean;\n readonly loading: boolean;\n readonly error: string | null;\n readonly snapshot: InspectorLearningSnapshotV1 | null;\n readonly setupActive: boolean;\n}): LearningViewState {\n // A Runtime that has not opted into Learning is still a valid product\n // onboarding state. The parent Inspector renders the Learning preview for\n // `landing`; after the setup prompt is copied, keep the user in the setup\n // flow while the Runtime is updated and reconnects.\n if (!input.supported) return input.setupActive ? \"setup\" : \"landing\";\n if (!input.snapshot && input.loading) return \"loading\";\n if (!input.snapshot && input.error) return \"error\";\n const snapshot = input.snapshot;\n if (!snapshot) return \"loading\";\n if (snapshot.configuration.state === \"selection_required\")\n return \"selection_required\";\n if (snapshot.configuration.state === \"invalid\") return \"invalid\";\n const hasResults =\n snapshot.skillsPage.total > 0 || snapshot.insightsPage.total > 0;\n if (hasResults || snapshot.pendingCandidateCount > 0) return \"results\";\n if (snapshot.run.hasActiveRun) return \"first_run\";\n if (snapshot.run.hasEverSucceeded && snapshot.pendingThreadCount === 0)\n return \"empty\";\n if (\n snapshot.configuration.state === \"configured\" &&\n snapshot.pendingThreadCount > 0\n )\n return \"ready\";\n if (input.setupActive || snapshot.configuration.state === \"configured\")\n return \"setup\";\n return \"landing\";\n}\n\nexport class CpkLearningView extends LitElement {\n static properties = {\n supported: { type: Boolean },\n loading: { type: Boolean },\n refreshing: { type: Boolean },\n error: { attribute: false },\n snapshot: { attribute: false },\n setupActive: { type: Boolean },\n copyState: { attribute: false },\n recopyState: { attribute: false },\n setupPrompt: { attribute: false },\n };\n\n supported = false;\n loading = false;\n refreshing = false;\n error: string | null = null;\n snapshot: InspectorLearningSnapshotV1 | null = null;\n setupActive = false;\n copyState: \"idle\" | \"copied\" | \"error\" = \"idle\";\n recopyState: \"idle\" | \"copied\" | \"error\" = \"idle\";\n setupPrompt = \"\";\n private promptOpen = false;\n private promptTrigger: HTMLElement | null = null;\n private expandedSkillId: string | null = null;\n private selectedInsightId: string | null = null;\n private skillPageKey = \"\";\n\n static styles = css`\n :host {\n --learning-ink: #202127;\n --learning-muted: #64656f;\n --learning-muted-strong: #858690;\n --learning-line: #dcdce4;\n --learning-line-secondary: #cfcfd7;\n --learning-line-accent: #dcd9ff;\n --learning-soft: #f7f7fa;\n --learning-canvas: #fff;\n --learning-surface: #fff;\n --learning-surface-subtle: #fbfbfd;\n --learning-surface-muted: #f8f8fb;\n --learning-surface-hover: #fafaff;\n --learning-purple: #7567ff;\n --learning-purple-dark: #5549e8;\n --learning-soft-purple: #f0edff;\n --learning-purple-border: #cfc8ff;\n --learning-green: #168b69;\n --learning-soft-green: #f7fbf9;\n --learning-green-border: #b9dfd1;\n --learning-soft-danger: #fff4f4;\n --learning-soft-danger-alt: #fff8f8;\n --learning-danger: #7e2929;\n --learning-danger-muted: #8c4a4a;\n --learning-danger-border: #efc7c7;\n --learning-danger-step-border: #d96a6a;\n --learning-track: #e9edf5;\n --learning-step-number: #edf0f5;\n --learning-step-number-ink: #555661;\n --learning-primary: #202127;\n --learning-primary-ink: #fff;\n --learning-secondary: #fff;\n --learning-secondary-ink: #31323a;\n --learning-disabled: #e5e5ea;\n --learning-disabled-ink: #9a9ba3;\n --learning-on-accent: #fff;\n --learning-outcome: #888993;\n --learning-outcome-dash: #cfd0d8;\n --learning-outcome-arrow: #b0b1b9;\n --learning-code: #34353d;\n --learning-dialog-line: #d9d9e1;\n --learning-skeleton-edge: #eeeef2;\n --learning-skeleton-center: #f8f8fa;\n display: block;\n height: 100%;\n overflow: auto;\n color: var(--learning-ink);\n background: var(--learning-canvas);\n font-family: Inter, ui-sans-serif, system-ui, sans-serif;\n }\n :host([data-color-scheme=\"dark\"]) {\n color-scheme: dark;\n --learning-ink: #f3f4f8;\n --learning-muted: #b0b3be;\n --learning-muted-strong: #b8bbc5;\n --learning-line: #3a3e4b;\n --learning-line-secondary: #4c5161;\n --learning-line-accent: #625f95;\n --learning-soft: #20232d;\n --learning-canvas: #15171e;\n --learning-surface: #1a1d25;\n --learning-surface-subtle: #1d2029;\n --learning-surface-muted: #20232d;\n --learning-surface-hover: #252837;\n --learning-purple: #a296ff;\n --learning-purple-dark: #c4baff;\n --learning-soft-purple: #2a2940;\n --learning-purple-border: #625f95;\n --learning-green: #4dc69d;\n --learning-soft-green: #172923;\n --learning-green-border: #28604d;\n --learning-soft-danger: #321f25;\n --learning-soft-danger-alt: #2d2026;\n --learning-danger: #ffabab;\n --learning-danger-muted: #f2b5ba;\n --learning-danger-border: #7a424e;\n --learning-danger-step-border: #a95464;\n --learning-track: #303440;\n --learning-step-number: #303440;\n --learning-step-number-ink: #d8dae4;\n --learning-primary: #f3f4f8;\n --learning-primary-ink: #16181f;\n --learning-secondary: #20232d;\n --learning-secondary-ink: #edf0f6;\n --learning-disabled: #363a46;\n --learning-disabled-ink: #a4a8b5;\n --learning-on-accent: #171920;\n --learning-outcome: #b0b3be;\n --learning-outcome-dash: #545969;\n --learning-outcome-arrow: #858a99;\n --learning-code: #e2e4ec;\n --learning-dialog-line: #484c5a;\n --learning-skeleton-edge: #2a2d38;\n --learning-skeleton-center: #333744;\n }\n * {\n box-sizing: border-box;\n }\n button,\n a,\n summary {\n font: inherit;\n }\n button:focus-visible,\n a:focus-visible,\n summary:focus-visible {\n outline: 2px solid var(--learning-purple);\n outline-offset: 2px;\n }\n .pane-inner {\n max-width: 880px;\n min-height: 100%;\n margin: 0 auto;\n padding: 32px 36px 70px;\n }\n .pane-heading {\n display: flex;\n align-items: start;\n justify-content: space-between;\n gap: 24px;\n margin-bottom: 24px;\n }\n .pane-heading h1 {\n margin: 0 0 7px;\n font-size: 25px;\n line-height: 1.2;\n letter-spacing: -0.035em;\n }\n .pane-heading p {\n max-width: 630px;\n margin: 0;\n color: var(--learning-muted);\n font-size: 14px;\n line-height: 1.5;\n }\n .pane-actions {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n .refreshing {\n color: var(--learning-muted-strong);\n font-size: 11px;\n }\n .setup-card,\n .analysis-card,\n .content-card {\n border: 1px solid var(--learning-line);\n border-radius: 10px;\n background: var(--learning-surface);\n }\n .setup-card {\n padding: 24px;\n background: var(--learning-surface-subtle);\n }\n .setup-top {\n display: flex;\n align-items: start;\n justify-content: space-between;\n gap: 20px;\n }\n .setup-top h2,\n .analysis-card h2 {\n margin: 0;\n font-size: 19px;\n line-height: 1.25;\n letter-spacing: -0.02em;\n }\n .progress-count {\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 13px;\n font-weight: 750;\n white-space: nowrap;\n }\n .progress-track {\n height: 8px;\n margin: 20px 0 18px;\n overflow: hidden;\n background: var(--learning-track);\n border-radius: 999px;\n }\n .progress-fill {\n height: 100%;\n background: var(--learning-purple);\n border-radius: inherit;\n }\n .steps {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 10px;\n margin: 0;\n padding: 0;\n list-style: none;\n }\n .step {\n min-height: 142px;\n padding: 15px;\n background: var(--learning-surface);\n border: 1px solid var(--learning-line);\n border-radius: 8px;\n }\n .step.current {\n background: var(--learning-soft-purple);\n border-color: var(--learning-purple);\n }\n .step.error {\n background: var(--learning-soft-danger);\n border-color: var(--learning-danger-step-border);\n }\n .step.complete {\n background: var(--learning-soft-green);\n border-color: var(--learning-green-border);\n }\n .step-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 18px;\n }\n .step-number {\n display: grid;\n place-items: center;\n width: 26px;\n height: 26px;\n color: var(--learning-step-number-ink);\n background: var(--learning-step-number);\n border-radius: 50%;\n font-size: 12px;\n font-weight: 800;\n }\n .step.current .step-number {\n color: var(--learning-on-accent);\n background: var(--learning-purple);\n }\n .step.complete .step-number {\n color: var(--learning-on-accent);\n background: var(--learning-green);\n }\n .step-state {\n color: var(--learning-danger);\n font-size: 9px;\n font-weight: 850;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n }\n .step h3 {\n margin: 0 0 7px;\n font-size: 14px;\n }\n .step p {\n margin: 0;\n color: var(--learning-muted);\n font-size: 12px;\n line-height: 1.45;\n }\n .copy-again {\n margin-top: 12px;\n padding: 0;\n color: var(--learning-secondary-ink);\n background: none;\n border: 0;\n font-size: 11px;\n font-weight: 750;\n text-decoration: underline;\n cursor: pointer;\n }\n .setup-support {\n margin-top: 14px;\n }\n .collection-panel {\n padding: 15px;\n background: var(--learning-surface);\n border: 1px solid var(--learning-line);\n border-radius: 8px;\n }\n .support-heading {\n margin-bottom: 12px;\n }\n .support-heading h3 {\n margin: 0;\n font-size: 13px;\n }\n .error-alert {\n margin-bottom: 10px;\n padding: 11px 12px;\n color: var(--learning-danger);\n background: var(--learning-soft-danger);\n border: 1px solid var(--learning-danger-border);\n border-radius: 6px;\n }\n .error-alert p {\n margin: 0;\n color: var(--learning-danger-muted);\n font-size: 11px;\n line-height: 1.45;\n }\n .prompt-link {\n display: inline-block;\n margin-top: 7px;\n padding: 0;\n color: var(--learning-danger);\n background: none;\n border: 0;\n font-size: 11px;\n font-weight: 750;\n text-decoration: underline;\n cursor: pointer;\n }\n .collection-summary {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n padding: 10px;\n background: var(--learning-soft);\n border-radius: 6px;\n }\n .collection-stat {\n display: flex;\n min-width: 0;\n align-items: center;\n gap: 9px;\n }\n .captured-count {\n color: var(--learning-ink);\n font-size: 28px;\n line-height: 1;\n }\n .collection-stat span {\n font-size: 12px;\n font-weight: 700;\n }\n .technical-details {\n margin-top: 10px;\n color: var(--learning-muted);\n font-size: 10px;\n }\n .technical-details summary {\n cursor: pointer;\n font-weight: 700;\n }\n .technical-details dl {\n display: grid;\n grid-template-columns: auto 1fr;\n gap: 5px 12px;\n margin: 9px 0 0;\n padding: 10px;\n background: var(--learning-soft);\n border-radius: 5px;\n }\n .technical-details dt {\n color: var(--learning-muted-strong);\n }\n .technical-details dd {\n margin: 0;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n overflow-wrap: anywhere;\n }\n .primary,\n .secondary {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-height: 36px;\n padding: 0 14px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 750;\n text-decoration: none;\n cursor: pointer;\n }\n .primary {\n color: var(--learning-primary-ink);\n background: var(--learning-primary);\n border: 1px solid var(--learning-primary);\n }\n .secondary {\n color: var(--learning-secondary-ink);\n background: var(--learning-secondary);\n border: 1px solid var(--learning-line-secondary);\n }\n .primary:disabled,\n .primary[aria-disabled=\"true\"] {\n color: var(--learning-disabled-ink);\n background: var(--learning-disabled);\n border-color: var(--learning-disabled);\n cursor: not-allowed;\n pointer-events: none;\n }\n .setup-cta:not(:disabled),\n .results-cta {\n min-width: 170px;\n min-height: 40px;\n padding: 0 18px;\n box-shadow: 0 6px 14px rgba(23, 23, 27, 0.2);\n }\n .outcome-preview {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n margin-top: 16px;\n color: var(--learning-outcome);\n font-size: 11px;\n }\n .outcome-preview span {\n padding: 6px 9px;\n background: var(--learning-surface);\n border: 1px dashed var(--learning-outcome-dash);\n border-radius: 5px;\n }\n .outcome-preview b {\n color: var(--learning-outcome-arrow);\n }\n .analysis-card {\n padding: 18px 20px;\n background: var(--learning-surface-muted);\n }\n .analysis-card.ready {\n background: var(--learning-soft-purple);\n border-color: var(--learning-purple-border);\n }\n .analysis-card.error {\n background: var(--learning-soft-danger-alt);\n border-color: var(--learning-danger-border);\n }\n .analysis-row {\n display: flex;\n align-items: center;\n gap: 20px;\n }\n .analysis-copy {\n flex: 1;\n }\n .analysis-card h2 {\n margin-bottom: 7px;\n }\n .analysis-card p {\n margin: 0;\n color: var(--learning-muted);\n font-size: 13px;\n line-height: 1.5;\n }\n .eyebrow {\n margin: 0 0 6px !important;\n color: var(--learning-purple-dark) !important;\n font-size: 10px !important;\n font-weight: 850;\n letter-spacing: 0.09em;\n text-transform: uppercase;\n }\n .retry-strip {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n margin-bottom: 12px;\n padding: 11px 12px;\n color: var(--learning-danger);\n background: var(--learning-soft-danger);\n border: 1px solid var(--learning-danger-border);\n border-radius: 6px;\n font-size: 11px;\n }\n .result-section {\n margin-top: 14px;\n }\n .result-section-heading {\n display: flex;\n align-items: baseline;\n gap: 6px;\n margin-bottom: 10px;\n }\n .result-section-heading h2 {\n margin: 0;\n font-size: 14px;\n }\n .result-count {\n color: var(--learning-muted-strong);\n font-size: 10px;\n font-weight: 700;\n }\n .review-link {\n margin-left: auto;\n color: var(--learning-purple-dark);\n font-size: 11px;\n font-weight: 750;\n text-decoration: none;\n }\n .quiet-link {\n display: inline-flex;\n margin-top: 12px;\n color: var(--learning-purple-dark);\n font-size: 11px;\n font-weight: 750;\n text-decoration: none;\n }\n .quiet-link:hover,\n .review-link:hover {\n text-decoration: underline;\n }\n .content-card {\n overflow: hidden;\n }\n .empty-card {\n padding: 24px;\n color: var(--learning-muted);\n background: var(--learning-surface-subtle);\n border: 1px solid var(--learning-line);\n border-radius: 8px;\n }\n .empty-card.compact {\n padding: 15px 16px;\n }\n .empty-card h3 {\n margin: 0 0 6px;\n color: var(--learning-ink);\n font-size: 14px;\n }\n .empty-card p {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n }\n .active-skill {\n padding: 16px;\n }\n .active-skill + .active-skill {\n border-top: 1px solid var(--learning-line);\n }\n .active-skill h3 {\n margin: 0 0 6px;\n font-size: 14px;\n }\n .active-skill > p {\n margin: 0;\n color: var(--learning-muted);\n font-size: 12px;\n line-height: 1.45;\n }\n .skill-lineage {\n margin-top: 10px;\n padding: 10px 12px;\n background: var(--learning-surface-muted);\n border: 1px solid var(--learning-line);\n border-radius: 6px;\n }\n .skill-lineage > span {\n display: block;\n margin-bottom: 5px;\n color: var(--learning-muted-strong);\n font-size: 9px;\n font-weight: 800;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n }\n .skill-lineage button {\n display: flex;\n width: 100%;\n align-items: start;\n justify-content: space-between;\n gap: 14px;\n padding: 0;\n color: var(--learning-ink);\n background: none;\n border: 0;\n text-align: left;\n font-size: 11px;\n font-weight: 700;\n line-height: 1.4;\n cursor: pointer;\n }\n .skill-lineage button small {\n flex: 0 0 auto;\n color: var(--learning-purple-dark);\n font-size: 10px;\n font-weight: 750;\n }\n .supporting-unavailable {\n color: var(--learning-muted-strong);\n font-size: 11px;\n font-style: italic;\n }\n .skill-source {\n margin-top: 10px;\n }\n .skill-source summary {\n width: fit-content;\n color: var(--learning-purple-dark);\n cursor: pointer;\n font-size: 11px;\n font-weight: 750;\n }\n .skill-source pre {\n margin: 10px 0 0;\n padding: 12px;\n color: var(--learning-code);\n background: var(--learning-soft);\n border: 1px solid var(--learning-line);\n border-radius: 6px;\n font:\n 11px/1.5 ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n monospace;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n }\n .list-header {\n display: flex;\n align-items: center;\n padding: 10px 14px;\n color: var(--learning-muted-strong);\n background: var(--learning-surface-muted);\n border-bottom: 1px solid var(--learning-line);\n font-size: 10px;\n font-weight: 800;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n }\n .list-header span:last-child {\n margin-left: auto;\n }\n .insight-row {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n gap: 18px;\n width: 100%;\n padding: 16px;\n color: inherit;\n background: var(--learning-surface);\n border: 0;\n border-bottom: 1px solid var(--learning-line);\n text-align: left;\n cursor: pointer;\n }\n .insight-row:last-child {\n border-bottom: 0;\n }\n .insight-row:hover,\n .insight-row[data-selected=\"true\"] {\n background: var(--learning-surface-hover);\n }\n .insight-row h3 {\n margin: 0 0 6px;\n font-size: 14px;\n line-height: 1.35;\n }\n .insight-row p {\n margin: 0;\n color: var(--learning-muted);\n font-size: 12px;\n line-height: 1.45;\n }\n .evidence-count {\n min-width: 90px;\n color: var(--learning-purple-dark);\n font-size: 11px;\n font-weight: 750;\n text-align: right;\n }\n .detail-panel {\n margin-top: 14px;\n padding: 18px;\n background: var(--learning-surface-hover);\n border: 1px solid var(--learning-line-accent);\n border-radius: 8px;\n }\n .detail-head {\n display: flex;\n align-items: start;\n gap: 14px;\n }\n .detail-head div {\n flex: 1;\n }\n .detail-head h3 {\n margin: 0 0 5px;\n font-size: 14px;\n }\n .detail-head p {\n margin: 0;\n color: var(--learning-muted);\n font-size: 12px;\n line-height: 1.45;\n }\n .close-detail {\n width: 28px;\n height: 28px;\n color: var(--learning-muted);\n background: var(--learning-surface);\n border: 1px solid var(--learning-line);\n border-radius: 5px;\n cursor: pointer;\n }\n .evidence-list {\n display: grid;\n gap: 7px;\n margin-top: 14px;\n }\n .evidence-link,\n .evidence-unavailable {\n display: flex;\n align-items: center;\n gap: 10px;\n min-height: 38px;\n padding: 10px;\n color: var(--learning-code);\n background: var(--learning-surface);\n border: 1px solid var(--learning-line);\n border-radius: 6px;\n font-size: 11px;\n text-align: left;\n }\n .evidence-link {\n width: 100%;\n cursor: pointer;\n }\n .evidence-link span {\n margin-left: auto;\n color: var(--learning-muted-strong);\n }\n .evidence-unavailable {\n color: var(--learning-muted-strong);\n font-style: italic;\n }\n .pagination {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 8px;\n margin-top: 10px;\n }\n .pagination span {\n margin-right: auto;\n color: var(--learning-muted);\n font-size: 11px;\n }\n .pagination button {\n min-height: 30px;\n padding: 0 10px;\n color: var(--learning-ink);\n background: var(--learning-surface);\n border: 1px solid var(--learning-line);\n border-radius: 5px;\n font-size: 11px;\n font-weight: 700;\n cursor: pointer;\n }\n .pagination button:disabled {\n color: var(--learning-disabled-ink);\n background: var(--learning-surface-muted);\n cursor: default;\n }\n .skeleton {\n display: grid;\n gap: 10px;\n }\n .skeleton span {\n height: 74px;\n background: linear-gradient(\n 90deg,\n var(--learning-skeleton-edge),\n var(--learning-skeleton-center),\n var(--learning-skeleton-edge)\n );\n background-size: 200% 100%;\n border-radius: 8px;\n animation: shimmer 1.3s infinite;\n }\n @keyframes shimmer {\n to {\n background-position: -200% 0;\n }\n }\n .dialog-backdrop {\n position: fixed;\n z-index: 50;\n inset: 0;\n display: grid;\n place-items: center;\n padding: 24px;\n background: rgba(15, 15, 20, 0.42);\n }\n .dialog {\n display: flex;\n width: min(620px, 100%);\n max-height: min(680px, 90vh);\n flex-direction: column;\n background: var(--learning-surface);\n border: 1px solid var(--learning-dialog-line);\n border-radius: 13px;\n box-shadow: 0 22px 70px rgba(0, 0, 0, 0.22);\n }\n .dialog header {\n display: flex;\n align-items: start;\n justify-content: space-between;\n padding: 18px 19px 13px;\n }\n .dialog h2 {\n margin: 0;\n font-size: 16px;\n }\n .dialog header p {\n margin: 4px 0 0;\n color: var(--learning-muted);\n font-size: 11px;\n }\n .dialog-close {\n color: var(--learning-muted);\n background: transparent;\n border: 0;\n font-size: 20px;\n cursor: pointer;\n }\n .dialog pre {\n max-height: 420px;\n overflow: auto;\n margin: 0 19px;\n padding: 12px;\n background: var(--learning-soft);\n border: 1px solid var(--learning-line);\n border-radius: 6px;\n font:\n 11px/1.5 ui-monospace,\n SFMono-Regular,\n Menlo,\n monospace;\n white-space: pre-wrap;\n }\n .dialog footer {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n padding: 14px 19px 18px;\n }\n .copy-error {\n margin: 10px 19px 0;\n color: var(--learning-danger);\n font-size: 11px;\n }\n @media (max-width: 900px) {\n .steps {\n grid-template-columns: 1fr;\n }\n .step {\n min-height: auto;\n }\n }\n @media (max-width: 640px) {\n .pane-inner {\n padding: 24px 18px 60px;\n }\n .analysis-row,\n .collection-summary {\n align-items: flex-start;\n flex-wrap: wrap;\n }\n .insight-row {\n grid-template-columns: 1fr;\n gap: 8px;\n }\n .evidence-count {\n text-align: left;\n }\n .review-link {\n width: 100%;\n margin: 4px 0 0;\n }\n }\n `;\n\n private emit(name: string, detail?: unknown) {\n this.dispatchEvent(\n new CustomEvent(name, { detail, bubbles: true, composed: true }),\n );\n }\n\n private externalLink(\n url: string | null,\n label: string,\n className = \"primary\",\n category: \"learning\" | \"runs\" | \"candidates\" = \"learning\",\n ) {\n return url\n ? html`<a\n class=${className}\n href=${url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n @click=${() => this.emit(\"learning-web-link\", { category })}\n >${label}</a\n >`\n : nothing;\n }\n\n private openPrompt(event?: Event) {\n const trigger = event?.currentTarget;\n this.promptTrigger = trigger instanceof HTMLElement ? trigger : null;\n this.promptOpen = true;\n this.requestUpdate();\n void this.updateComplete.then(() => {\n this.renderRoot\n .querySelector<HTMLButtonElement>(\".dialog-close\")\n ?.focus();\n });\n }\n\n private closePrompt(): void {\n this.promptOpen = false;\n this.requestUpdate();\n void this.updateComplete.then(() => this.promptTrigger?.focus());\n }\n\n private handlePromptKeydown = (event: KeyboardEvent): void => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n this.closePrompt();\n return;\n }\n if (event.key !== \"Tab\") return;\n const dialog = event.currentTarget;\n if (!(dialog instanceof HTMLElement)) return;\n const root = dialog.getRootNode();\n const activeElement =\n root instanceof ShadowRoot ? root.activeElement : document.activeElement;\n const focusable = [\n ...dialog.querySelectorAll<HTMLElement>(\n 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])',\n ),\n ];\n const first = focusable[0];\n const last = focusable.at(-1);\n if (!first || !last) return;\n if (event.shiftKey && activeElement === first) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && activeElement === last) {\n event.preventDefault();\n first.focus();\n }\n };\n\n private setupPromptButton(label = \"Copy the setup prompt\") {\n return html`<button\n class=\"primary\"\n type=\"button\"\n @click=${(event: Event) =>\n label === \"Open the setup prompt\"\n ? this.openPrompt(event)\n : this.emit(\"learning-copy-setup\")}\n >\n ${this.copyState === \"copied\" ? \"Prompt copied\" : label}\n </button>`;\n }\n\n private renderSetupProgress(\n mode: \"setup\" | \"ready\" | \"running\" | \"attention\",\n ) {\n const ready = mode === \"ready\";\n const running = mode === \"running\";\n const attention = mode === \"attention\";\n const waitingForLearningSetup =\n mode === \"setup\" &&\n this.setupActive &&\n (this.snapshot === null ||\n this.snapshot.configuration.state === \"not_configured\");\n const completedSteps = ready || running ? 2 : 1;\n const pendingThreads = ready ? (this.snapshot?.pendingThreadCount ?? 0) : 0;\n const title = attention\n ? \"Learning setup needs attention\"\n : mode === \"setup\"\n ? waitingForLearningSetup\n ? \"Waiting for Automatic Learning setup\"\n : \"Waiting for the first Thread\"\n : ready\n ? \"Threads ready to analyze\"\n : \"Analysis is running in the web app.\";\n const container =\n this.snapshot?.configuration.state === \"configured\"\n ? this.snapshot.configuration.container\n : null;\n\n return html`<section\n class=\"setup-card\"\n aria-labelledby=\"learning-setup-title\"\n >\n <div class=\"setup-top\">\n <h2 id=\"learning-setup-title\">Set up Automatic Learning</h2>\n <span class=\"progress-count\">${completedSteps} of 3 steps</span>\n </div>\n <div class=\"progress-track\" aria-hidden=\"true\">\n <div\n class=\"progress-fill\"\n style=\"width: ${(completedSteps / 3) * 100}%\"\n ></div>\n </div>\n <ol class=\"steps\">\n <li class=\"step complete\">\n <div class=\"step-header\"><span class=\"step-number\">✓</span></div>\n <h3>Copy the setup prompt</h3>\n <p>Nice work. You’ve completed the first step.</p>\n <button\n class=\"copy-again\"\n type=\"button\"\n aria-live=\"polite\"\n @click=${() => this.emit(\"learning-recopy-setup\")}\n >\n ${\n this.recopyState === \"copied\"\n ? \"✓ Copied!\"\n : this.recopyState === \"error\"\n ? \"Try copying again\"\n : \"Copy prompt again\"\n }\n </button>\n </li>\n <li\n class=\"step ${\n attention\n ? \"error current\"\n : mode === \"setup\"\n ? \"current\"\n : \"complete\"\n }\"\n >\n <div class=\"step-header\">\n <span class=\"step-number\">${ready || running ? \"✓\" : \"2\"}</span>\n ${\n attention\n ? html`\n <span class=\"step-state\">Needs attention</span>\n `\n : nothing\n }\n </div>\n <h3>\n ${\n waitingForLearningSetup\n ? \"Set up Automatic Learning\"\n : \"Create your first Thread\"\n }\n </h3>\n <p>\n ${\n waitingForLearningSetup\n ? \"Run the copied prompt in your coding agent. This page will continue when Automatic Learning is ready.\"\n : \"Open Checkout Assistant and complete a conversation.\"\n }\n </p>\n </li>\n <li class=\"step ${ready || running ? \"current\" : \"\"}\">\n <div class=\"step-header\"><span class=\"step-number\">3</span></div>\n <h3>Analyze Threads</h3>\n <p>We'll find patterns and turn them into insights and skills</p>\n </li>\n </ol>\n <div class=\"setup-support\">\n <section class=\"collection-panel\">\n <div class=\"support-heading\"><h3>${title}</h3></div>\n ${\n attention\n ? html`<div class=\"error-alert\" role=\"alert\">\n <p>\n Inspector did not find the Learning Space or app\n instrumentation. Open the setup prompt, run it in your coding\n agent, then try again.\n </p>\n <button\n class=\"prompt-link\"\n type=\"button\"\n @click=${(event: Event) => this.openPrompt(event)}\n >\n Open the setup prompt ↗\n </button>\n </div>`\n : html`<div class=\"collection-summary\">\n <div class=\"collection-stat\">\n <strong class=\"captured-count\">${pendingThreads}</strong>\n <span>New Threads</span>\n </div>\n ${\n ready || running\n ? this.externalLink(\n this.snapshot?.links.runs ?? null,\n \"Open in web app\",\n \"primary setup-cta\",\n \"runs\",\n )\n : html`\n <button class=\"primary setup-cta\" disabled>Analyze Threads</button>\n `\n }\n </div>`\n }\n ${\n attention\n ? nothing\n : html`<details class=\"technical-details\">\n <summary>Technical details</summary>\n <dl>\n <dt>Learning Space</dt>\n <dd>${container?.id ?? \"Waiting for setup\"}</dd>\n <dt>Status</dt>\n <dd>\n ${\n ready\n ? \"Threads available\"\n : running\n ? \"Analysis running\"\n : waitingForLearningSetup\n ? \"Waiting for Automatic Learning setup\"\n : \"Waiting for first Thread\"\n }\n </dd>\n </dl>\n </details>`\n }\n </section>\n </div>\n <div class=\"outcome-preview\" aria-label=\"Learning flow\">\n <span>Threads</span><b>→</b><span>Insights</span><b>→</b\n ><span>Skills</span>\n </div>\n </section>`;\n }\n\n private renderPagination(\n section: \"skills\" | \"insights\",\n page: number,\n totalPages: number,\n ) {\n if (totalPages <= 1) return nothing;\n return html`<nav class=\"pagination\" aria-label=\"${section} pages\">\n <span aria-live=\"polite\">Page ${page} of ${totalPages}</span>\n <button\n ?disabled=${page <= 1}\n @click=${() => this.emit(\"learning-page\", { section, page: page - 1 })}\n >\n Previous\n </button>\n <button\n ?disabled=${page >= totalPages}\n @click=${() => this.emit(\"learning-page\", { section, page: page + 1 })}\n >\n Next\n </button>\n </nav>`;\n }\n\n private renderEvidence(insight: InspectorLearningInsight) {\n return html`<section class=\"detail-panel\" aria-label=\"Insight evidence\">\n <div class=\"detail-head\">\n <div>\n <h3>Evidence</h3>\n <p>${insight.statement}</p>\n </div>\n <button\n class=\"close-detail\"\n type=\"button\"\n aria-label=\"Close evidence\"\n @click=${() => {\n this.selectedInsightId = null;\n this.requestUpdate();\n }}\n >\n ×\n </button>\n </div>\n <div class=\"evidence-list\">\n ${\n insight.evidence.length === 0\n ? html`\n <div class=\"evidence-unavailable\">Evidence is no longer available</div>\n `\n : insight.evidence.map((evidence) =>\n evidence.status === \"unavailable\"\n ? html`\n <div class=\"evidence-unavailable\">Evidence is no longer available</div>\n `\n : html`<button\n class=\"evidence-link\"\n type=\"button\"\n @click=${() =>\n this.emit(\"learning-open-evidence\", {\n threadId: evidence.threadId,\n messageId: evidence.messageIds[0],\n })}\n >\n ⌁\n ${\n evidence.threadName ??\n `Thread ${evidence.threadId.slice(0, 8)}`\n }\n <span>Open Thread →</span>\n </button>`,\n )\n }\n </div>\n ${\n insight.evidenceTruncated\n ? html`\n <p class=\"supporting-unavailable\">Evidence response shortened</p>\n `\n : nothing\n }\n </section>`;\n }\n\n private selectInsight(insight: InspectorLearningInsight) {\n this.selectedInsightId = insight.id;\n this.emit(\"learning-evidence-opened\");\n this.requestUpdate();\n }\n\n private supportingInsightLabel(statement: string): string {\n const firstStop = statement.indexOf(\".\");\n return firstStop === -1 ? statement : statement.slice(0, firstStop + 1);\n }\n\n private renderSkills(snapshot: InspectorLearningSnapshotV1) {\n const containerId =\n snapshot.configuration.state === \"configured\"\n ? snapshot.configuration.container.id\n : \"\";\n const skillPageKey = `${snapshot.projectKey}|${containerId}|${snapshot.skillsPage.page}|${snapshot.skillsPage.items.map((skill) => skill.id).join(\",\")}`;\n if (skillPageKey !== this.skillPageKey) {\n this.skillPageKey = skillPageKey;\n this.expandedSkillId = null;\n }\n return html`<section class=\"result-section\" aria-labelledby=\"skills-title\">\n <div class=\"result-section-heading\">\n <h2 id=\"skills-title\">Skills in registry</h2>\n <span class=\"result-count\">${snapshot.skillsPage.total}</span>\n ${\n snapshot.pendingCandidateCount > 0\n ? this.externalLink(\n snapshot.links.candidates,\n `${snapshot.pendingCandidateCount} ${snapshot.pendingCandidateCount === 1 ? \"Skill\" : \"Skills\"} for review in web app ↗`,\n \"review-link\",\n \"candidates\",\n )\n : nothing\n }\n </div>\n ${\n snapshot.skillsPage.items.length === 0\n ? html`\n <div class=\"empty-card compact\">\n <h3>No Skills in registry yet</h3>\n <p>\n No Insight has produced a Skill that was approved into the registry yet.\n </p>\n </div>\n `\n : html`<div class=\"content-card\">\n ${snapshot.skillsPage.items.map((skill) => {\n const open = this.expandedSkillId === skill.id;\n return html`<article class=\"active-skill\">\n <h3>${skill.name}</h3>\n <p>${skill.description}</p>\n <div class=\"skill-lineage\">\n <span>Supporting Insight</span>\n ${\n skill.sourceInsight\n ? html`<button\n type=\"button\"\n @click=${() => this.selectInsight(skill.sourceInsight!)}\n >\n ${this.supportingInsightLabel(\n skill.sourceInsight.statement,\n )}<small\n >${skill.sourceInsight.totalThreadCount}\n ${\n skill.sourceInsight.totalThreadCount === 1\n ? \"Thread\"\n : \"Threads\"\n }</small\n >\n </button>`\n : html`\n <div class=\"supporting-unavailable\">Supporting Insight unavailable</div>\n `\n }\n </div>\n <details\n class=\"skill-source\"\n ?open=${open}\n @toggle=${(event: Event) => {\n const nextOpen = (event.currentTarget as HTMLDetailsElement)\n .open;\n if (nextOpen === open) return;\n this.expandedSkillId = nextOpen ? skill.id : \"\";\n this.emit(\"learning-skill-toggle\", {\n action: nextOpen ? \"expanded\" : \"collapsed\",\n });\n this.requestUpdate();\n }}\n >\n <summary>View SKILL.md</summary>\n <pre>${skill.skillMd}</pre>\n </details>\n </article>`;\n })}\n </div>`\n }\n ${this.renderPagination(\n \"skills\",\n snapshot.skillsPage.page,\n snapshot.skillsPage.totalPages,\n )}\n </section>`;\n }\n\n private renderInsights(snapshot: InspectorLearningSnapshotV1) {\n const selected = snapshot.insightsPage.items.find(\n (insight) => insight.id === this.selectedInsightId,\n );\n return html`<section\n class=\"result-section\"\n aria-labelledby=\"insights-title\"\n >\n <div class=\"result-section-heading\">\n <h2 id=\"insights-title\">\n ${snapshot.skillsPage.total > 0 ? \"More Insights\" : \"Insights\"}\n </h2>\n <span class=\"result-count\">${snapshot.insightsPage.total}</span>\n </div>\n ${\n snapshot.insightsPage.items.length === 0\n ? html`\n <div class=\"empty-card compact\"><h3>No active Insights</h3></div>\n `\n : html`<div class=\"content-card\">\n <div class=\"list-header\">\n <span>Pattern</span><span>Evidence</span>\n </div>\n ${snapshot.insightsPage.items.map(\n (insight) => html`<button\n class=\"insight-row\"\n data-selected=${selected?.id === insight.id}\n type=\"button\"\n @click=${() =>\n selected?.id === insight.id\n ? ((this.selectedInsightId = null), this.requestUpdate())\n : this.selectInsight(insight)}\n >\n <div>\n <h3>${insight.statement}</h3>\n <p>${insight.impact}</p>\n </div>\n <span class=\"evidence-count\"\n >${insight.totalThreadCount}\n ${insight.totalThreadCount === 1 ? \"Thread\" : \"Threads\"}</span\n >\n </button>`,\n )}\n </div>`\n }\n ${selected ? this.renderEvidence(selected) : nothing}\n ${this.renderPagination(\n \"insights\",\n snapshot.insightsPage.page,\n snapshot.insightsPage.totalPages,\n )}\n </section>`;\n }\n\n private renderResults(snapshot: InspectorLearningSnapshotV1) {\n const sourceInsight = snapshot.skillsPage.items\n .map((skill) => skill.sourceInsight)\n .find((insight) => insight?.id === this.selectedInsightId);\n return html`\n ${\n snapshot.pendingThreadCount > 0\n ? html`<section class=\"analysis-card ready\">\n <div class=\"analysis-row\">\n <div class=\"analysis-copy\">\n <h2>Find new Insights and Skills</h2>\n <p>You have new threads ready to be analyzed.</p>\n </div>\n ${this.externalLink(\n snapshot.links.runs,\n \"Open in web app\",\n \"primary results-cta\",\n \"runs\",\n )}\n </div>\n </section>`\n : nothing\n }\n ${this.renderSkills(snapshot)}\n ${sourceInsight ? this.renderEvidence(sourceInsight) : nothing}\n ${this.renderInsights(snapshot)}\n `;\n }\n\n private renderRetryStrip() {\n if (!this.error) return nothing;\n return html`<div class=\"retry-strip\" role=\"status\">\n <span>${this.error}</span>\n <button\n class=\"secondary\"\n type=\"button\"\n @click=${() => this.emit(\"learning-retry\")}\n >\n Retry\n </button>\n </div>`;\n }\n\n private renderEmptyResults(snapshot: InspectorLearningSnapshotV1) {\n return html`<section class=\"analysis-card\">\n <div class=\"analysis-row\">\n <div class=\"analysis-copy\">\n <p class=\"eyebrow\">Analysis complete</p>\n <h2>No new Insights or Skills</h2>\n <p>\n Create more Threads with Checkout Assistant. You can run Automatic Learning\n again when new Threads are available.\n </p>\n </div>\n </div>\n </section>\n <section class=\"result-section\">\n <div class=\"result-section-heading\">\n <h2>Skills in registry</h2><span class=\"result-count\">0</span>\n </div>\n <div class=\"empty-card\">\n <h3>No Skills from this analysis</h3>\n <p>Automatic Learning did not generate a Skill for review.</p>\n </div>\n </section>\n <section class=\"result-section\">\n <div class=\"result-section-heading\">\n <h2>Insights</h2><span class=\"result-count\">0</span>\n </div>\n <div class=\"empty-card\">\n <h3>No Insights from this analysis</h3>\n <p>Automatic Learning did not find a useful pattern in these Threads.</p>\n </div>\n </section>\n ${this.externalLink(\n snapshot.links.learning,\n \"Open in web app ↗\",\n \"quiet-link\",\n \"learning\",\n )}`;\n }\n\n private renderCompactState(input: {\n readonly title: string;\n readonly copy?: string;\n readonly action?: unknown;\n readonly error?: boolean;\n }) {\n return html`<section class=\"analysis-card ${input.error ? \"error\" : \"\"}\">\n <div class=\"analysis-row\">\n <div class=\"analysis-copy\">\n <h2>${input.title}</h2>\n ${input.copy ? html`<p>${input.copy}</p>` : nothing}\n </div>\n ${input.action ?? nothing}\n </div>\n </section>`;\n }\n\n render() {\n const state = deriveLearningViewState({\n supported: this.supported,\n loading: this.loading,\n error: this.error,\n snapshot: this.snapshot,\n setupActive: this.setupActive,\n });\n let content: unknown;\n if (state === \"loading\") {\n content = html`\n <div class=\"skeleton\" aria-label=\"Loading Automatic Learning\">\n <span></span><span></span><span></span>\n </div>\n `;\n } else if (state === \"error\") {\n content = this.renderCompactState({\n title: \"Automatic Learning data is unavailable\",\n copy: this.error ?? undefined,\n error: true,\n action: html`<button\n class=\"secondary\"\n type=\"button\"\n @click=${() => this.emit(\"learning-retry\")}\n >\n Retry\n </button>`,\n });\n } else if (state === \"selection_required\") {\n content = this.renderCompactState({\n title: \"Inspector cannot choose a Learning Space for this agent.\",\n action: this.externalLink(\n this.snapshot!.links.learning,\n \"Open in web app\",\n \"primary\",\n \"learning\",\n ),\n });\n } else if (state === \"invalid\") {\n content = this.renderSetupProgress(\"attention\");\n } else if (state === \"landing\") {\n // The parent Inspector preserves the existing locked-feature marketing\n // surface for Landing. The v5 pane begins only after its copy action.\n content = nothing;\n } else if (state === \"setup\") {\n content = this.renderSetupProgress(\"setup\");\n } else if (state === \"first_run\") {\n content = this.renderSetupProgress(\"running\");\n } else if (state === \"ready\") {\n content = this.renderSetupProgress(\"ready\");\n } else if (state === \"empty\") {\n content = this.renderEmptyResults(this.snapshot!);\n } else {\n content = this.renderResults(this.snapshot!);\n }\n\n const retry =\n state === \"error\" || !this.snapshot ? nothing : this.renderRetryStrip();\n\n return html`<main class=\"pane-inner\" data-learning-state=${state}>\n <header class=\"pane-heading\">\n <div>\n <h1>Automatic Learning</h1>\n <p>Intelligence finds patterns in Rich Threads and proposes reusable Skills.</p>\n ${this.snapshot?.configuration.state === \"configured\" ? html`<p style=\"font-size:12px;margin-top:10px\">Learning Space <strong>${this.snapshot.configuration.container.name}</strong></p>` : nothing}\n </div>\n <div class=\"pane-actions\">\n ${\n state === \"results\"\n ? this.externalLink(\n this.snapshot!.webAppOrigin,\n \"Open Intelligence ↗\",\n \"secondary\",\n )\n : nothing\n }\n ${\n state === \"setup\" && this.setupActive\n ? html`<button\n class=\"secondary\"\n type=\"button\"\n @click=${() => this.emit(\"learning-go-back\")}\n >\n ← Go back\n </button>`\n : nothing\n }\n ${\n this.refreshing\n ? html`\n <span class=\"refreshing\" role=\"status\">Refreshing</span>\n `\n : nothing\n }\n </div>\n </header>\n ${retry}\n ${content}\n </main>\n ${\n this.promptOpen\n ? html`<div class=\"dialog-backdrop\">\n <section\n class=\"dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"learning-prompt-title\"\n @keydown=${this.handlePromptKeydown}\n >\n <header>\n <div>\n <h2 id=\"learning-prompt-title\">Set up Rich Threads</h2>\n <p>Paste this prompt into your coding agent.</p>\n </div>\n <button\n class=\"dialog-close\"\n aria-label=\"Close setup prompt\"\n @click=${() => this.closePrompt()}\n >\n ×\n </button>\n </header>\n <pre>${this.setupPrompt}</pre>\n ${\n this.copyState === \"error\"\n ? html`\n <p class=\"copy-error\" role=\"alert\">\n Clipboard access failed. Retry to continue.\n </p>\n `\n : nothing\n }\n <footer>\n <button\n class=\"secondary\"\n @click=${() => this.closePrompt()}\n >\n Close\n </button>\n <button\n class=\"primary\"\n @click=${() => this.emit(\"learning-copy-setup\")}\n >\n ${\n this.copyState === \"copied\"\n ? \"Prompt copied\"\n : \"Copy the setup prompt\"\n }\n </button>\n </footer>\n </section>\n </div>`\n : nothing\n }`;\n }\n}\n\nif (!customElements.get(\"cpk-learning-view\")) {\n customElements.define(\"cpk-learning-view\", CpkLearningView);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"learning-view.cjs","names":["LitElement","nothing"],"sources":["../../src/components/learning-view.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from \"lit\";\nimport type {\n InspectorLearningInsight,\n InspectorLearningSnapshotV1,\n InspectorLearningTrajectoryEvidence,\n} from \"@copilotkit/shared\";\n\nexport type LearningViewState =\n | \"loading\"\n | \"error\"\n | \"selection_required\"\n | \"invalid\"\n | \"results\"\n | \"first_run\"\n | \"ready\"\n | \"empty\"\n | \"setup\"\n | \"landing\";\n\nconst plural = (count: number, singular: string, pluralForm: string) =>\n `${count} ${count === 1 ? singular : pluralForm}`;\n\n/** Rows shown per evidence kind before the panel asks to show more. */\nconst EVIDENCE_PREVIEW_LIMIT = 10;\n\ntype EvidenceKind = \"threads\" | \"trajectories\";\n\nconst EVIDENCE_NOUNS: Record<EvidenceKind, readonly [string, string]> = {\n threads: [\"Thread\", \"Threads\"],\n trajectories: [\"Trajectory\", \"Trajectories\"],\n};\n\nconst trajectoryTimeFormat = new Intl.DateTimeFormat(undefined, {\n month: \"short\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"2-digit\",\n});\n\n/**\n * Reads the creation time from a UUIDv7 Trajectory id, whose first 48 bits\n * are Unix milliseconds. Returns null for ids of any other version.\n */\nconst trajectoryCreatedAt = (trajectoryId: string): Date | null => {\n const hex = trajectoryId.replace(/-/g, \"\");\n if (!/^[0-9a-f]{12}7[0-9a-f]{19}$/i.test(hex)) return null;\n return new Date(Number.parseInt(hex.slice(0, 12), 16));\n};\n\n/**\n * \"Showing 100 of 412 Trajectories\" for each kind the response shortened,\n * or null when every cited source is listed.\n */\nfunction evidenceCoverageLabel(\n insight: InspectorLearningInsight,\n): string | null {\n if (!insight.evidenceTruncated) return null;\n const parts: string[] = [];\n if (insight.evidence.length < insight.totalThreadCount) {\n parts.push(\n `${insight.evidence.length} of ${plural(insight.totalThreadCount, ...EVIDENCE_NOUNS.threads)}`,\n );\n }\n const trajectoriesShown = insight.trajectoryEvidence?.length ?? 0;\n if (\n insight.totalTrajectoryCount !== undefined &&\n trajectoriesShown < insight.totalTrajectoryCount\n ) {\n parts.push(\n `${trajectoriesShown} of ${plural(insight.totalTrajectoryCount, ...EVIDENCE_NOUNS.trajectories)}`,\n );\n }\n return parts.length === 0 ? null : `Showing ${parts.join(\" · \")}`;\n}\n\n/**\n * Labels the sources an Insight cites. Trajectories are named only when\n * cited, so Thread-only Insights and older Intelligence versions read as\n * before.\n */\nfunction evidenceCountLabel(insight: InspectorLearningInsight): string {\n const threads = plural(insight.totalThreadCount, \"Thread\", \"Threads\");\n const trajectoryCount =\n insight.totalTrajectoryCount ?? insight.trajectoryEvidence?.length ?? 0;\n if (trajectoryCount === 0) return threads;\n const trajectories = plural(trajectoryCount, \"Trajectory\", \"Trajectories\");\n return insight.totalThreadCount === 0\n ? trajectories\n : `${threads} · ${trajectories}`;\n}\n\nexport function deriveLearningViewState(input: {\n readonly supported: boolean;\n readonly loading: boolean;\n readonly error: string | null;\n readonly snapshot: InspectorLearningSnapshotV1 | null;\n readonly setupActive: boolean;\n}): LearningViewState {\n // A Runtime that has not opted into Learning is still a valid product\n // onboarding state. The parent Inspector renders the Learning preview for\n // `landing`; after the setup prompt is copied, keep the user in the setup\n // flow while the Runtime is updated and reconnects.\n if (!input.supported) return input.setupActive ? \"setup\" : \"landing\";\n if (!input.snapshot && input.loading) return \"loading\";\n if (!input.snapshot && input.error) return \"error\";\n const snapshot = input.snapshot;\n if (!snapshot) return \"loading\";\n if (snapshot.configuration.state === \"selection_required\")\n return \"selection_required\";\n if (snapshot.configuration.state === \"invalid\") return \"invalid\";\n const hasResults =\n snapshot.skillsPage.total > 0 || snapshot.insightsPage.total > 0;\n if (hasResults || snapshot.pendingCandidateCount > 0) return \"results\";\n if (snapshot.run.hasActiveRun) return \"first_run\";\n if (snapshot.run.hasEverSucceeded && snapshot.pendingThreadCount === 0)\n return \"empty\";\n if (\n snapshot.configuration.state === \"configured\" &&\n snapshot.pendingThreadCount > 0\n )\n return \"ready\";\n if (input.setupActive || snapshot.configuration.state === \"configured\")\n return \"setup\";\n return \"landing\";\n}\n\nexport class CpkLearningView extends LitElement {\n static properties = {\n supported: { type: Boolean },\n loading: { type: Boolean },\n refreshing: { type: Boolean },\n error: { attribute: false },\n snapshot: { attribute: false },\n setupActive: { type: Boolean },\n copyState: { attribute: false },\n recopyState: { attribute: false },\n setupPrompt: { attribute: false },\n };\n\n supported = false;\n loading = false;\n refreshing = false;\n error: string | null = null;\n snapshot: InspectorLearningSnapshotV1 | null = null;\n setupActive = false;\n copyState: \"idle\" | \"copied\" | \"error\" = \"idle\";\n recopyState: \"idle\" | \"copied\" | \"error\" = \"idle\";\n setupPrompt = \"\";\n private promptOpen = false;\n private promptTrigger: HTMLElement | null = null;\n private expandedSkillId: string | null = null;\n private selectedInsightId: string | null = null;\n /** Evidence groups showing every row, keyed by Insight id and kind. */\n private readonly expandedEvidence = new Set<string>();\n private skillPageKey = \"\";\n\n static styles = css`\n :host {\n --learning-ink: #202127;\n --learning-muted: #64656f;\n --learning-muted-strong: #858690;\n --learning-line: #dcdce4;\n --learning-line-secondary: #cfcfd7;\n --learning-line-accent: #dcd9ff;\n --learning-soft: #f7f7fa;\n --learning-canvas: #fff;\n --learning-surface: #fff;\n --learning-surface-subtle: #fbfbfd;\n --learning-surface-muted: #f8f8fb;\n --learning-surface-hover: #fafaff;\n --learning-purple: #7567ff;\n --learning-purple-dark: #5549e8;\n --learning-soft-purple: #f0edff;\n --learning-purple-border: #cfc8ff;\n --learning-green: #168b69;\n --learning-soft-green: #f7fbf9;\n --learning-green-border: #b9dfd1;\n --learning-soft-danger: #fff4f4;\n --learning-soft-danger-alt: #fff8f8;\n --learning-danger: #7e2929;\n --learning-danger-muted: #8c4a4a;\n --learning-danger-border: #efc7c7;\n --learning-danger-step-border: #d96a6a;\n --learning-track: #e9edf5;\n --learning-step-number: #edf0f5;\n --learning-step-number-ink: #555661;\n --learning-primary: #202127;\n --learning-primary-ink: #fff;\n --learning-secondary: #fff;\n --learning-secondary-ink: #31323a;\n --learning-disabled: #e5e5ea;\n --learning-disabled-ink: #9a9ba3;\n --learning-on-accent: #fff;\n --learning-outcome: #888993;\n --learning-outcome-dash: #cfd0d8;\n --learning-outcome-arrow: #b0b1b9;\n --learning-code: #34353d;\n --learning-dialog-line: #d9d9e1;\n --learning-skeleton-edge: #eeeef2;\n --learning-skeleton-center: #f8f8fa;\n display: block;\n height: 100%;\n overflow: auto;\n color: var(--learning-ink);\n background: var(--learning-canvas);\n font-family: Inter, ui-sans-serif, system-ui, sans-serif;\n }\n :host([data-color-scheme=\"dark\"]) {\n color-scheme: dark;\n --learning-ink: #f3f4f8;\n --learning-muted: #b0b3be;\n --learning-muted-strong: #b8bbc5;\n --learning-line: #3a3e4b;\n --learning-line-secondary: #4c5161;\n --learning-line-accent: #625f95;\n --learning-soft: #20232d;\n --learning-canvas: #15171e;\n --learning-surface: #1a1d25;\n --learning-surface-subtle: #1d2029;\n --learning-surface-muted: #20232d;\n --learning-surface-hover: #252837;\n --learning-purple: #a296ff;\n --learning-purple-dark: #c4baff;\n --learning-soft-purple: #2a2940;\n --learning-purple-border: #625f95;\n --learning-green: #4dc69d;\n --learning-soft-green: #172923;\n --learning-green-border: #28604d;\n --learning-soft-danger: #321f25;\n --learning-soft-danger-alt: #2d2026;\n --learning-danger: #ffabab;\n --learning-danger-muted: #f2b5ba;\n --learning-danger-border: #7a424e;\n --learning-danger-step-border: #a95464;\n --learning-track: #303440;\n --learning-step-number: #303440;\n --learning-step-number-ink: #d8dae4;\n --learning-primary: #f3f4f8;\n --learning-primary-ink: #16181f;\n --learning-secondary: #20232d;\n --learning-secondary-ink: #edf0f6;\n --learning-disabled: #363a46;\n --learning-disabled-ink: #a4a8b5;\n --learning-on-accent: #171920;\n --learning-outcome: #b0b3be;\n --learning-outcome-dash: #545969;\n --learning-outcome-arrow: #858a99;\n --learning-code: #e2e4ec;\n --learning-dialog-line: #484c5a;\n --learning-skeleton-edge: #2a2d38;\n --learning-skeleton-center: #333744;\n }\n * {\n box-sizing: border-box;\n }\n button,\n a,\n summary {\n font: inherit;\n }\n button:focus-visible,\n a:focus-visible,\n summary:focus-visible {\n outline: 2px solid var(--learning-purple);\n outline-offset: 2px;\n }\n .pane-inner {\n max-width: 880px;\n min-height: 100%;\n margin: 0 auto;\n padding: 32px 36px 70px;\n }\n .pane-heading {\n display: flex;\n align-items: start;\n justify-content: space-between;\n gap: 24px;\n margin-bottom: 24px;\n }\n .pane-heading h1 {\n margin: 0 0 7px;\n font-size: 25px;\n line-height: 1.2;\n letter-spacing: -0.035em;\n }\n .pane-heading p {\n max-width: 630px;\n margin: 0;\n color: var(--learning-muted);\n font-size: 14px;\n line-height: 1.5;\n }\n .pane-actions {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n .refreshing {\n color: var(--learning-muted-strong);\n font-size: 11px;\n }\n .setup-card,\n .analysis-card,\n .content-card {\n border: 1px solid var(--learning-line);\n border-radius: 10px;\n background: var(--learning-surface);\n }\n .setup-card {\n padding: 24px;\n background: var(--learning-surface-subtle);\n }\n .setup-top {\n display: flex;\n align-items: start;\n justify-content: space-between;\n gap: 20px;\n }\n .setup-top h2,\n .analysis-card h2 {\n margin: 0;\n font-size: 19px;\n line-height: 1.25;\n letter-spacing: -0.02em;\n }\n .progress-count {\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 13px;\n font-weight: 750;\n white-space: nowrap;\n }\n .progress-track {\n height: 8px;\n margin: 20px 0 18px;\n overflow: hidden;\n background: var(--learning-track);\n border-radius: 999px;\n }\n .progress-fill {\n height: 100%;\n background: var(--learning-purple);\n border-radius: inherit;\n }\n .steps {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 10px;\n margin: 0;\n padding: 0;\n list-style: none;\n }\n .step {\n min-height: 142px;\n padding: 15px;\n background: var(--learning-surface);\n border: 1px solid var(--learning-line);\n border-radius: 8px;\n }\n .step.current {\n background: var(--learning-soft-purple);\n border-color: var(--learning-purple);\n }\n .step.error {\n background: var(--learning-soft-danger);\n border-color: var(--learning-danger-step-border);\n }\n .step.complete {\n background: var(--learning-soft-green);\n border-color: var(--learning-green-border);\n }\n .step-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 18px;\n }\n .step-number {\n display: grid;\n place-items: center;\n width: 26px;\n height: 26px;\n color: var(--learning-step-number-ink);\n background: var(--learning-step-number);\n border-radius: 50%;\n font-size: 12px;\n font-weight: 800;\n }\n .step.current .step-number {\n color: var(--learning-on-accent);\n background: var(--learning-purple);\n }\n .step.complete .step-number {\n color: var(--learning-on-accent);\n background: var(--learning-green);\n }\n .step-state {\n color: var(--learning-danger);\n font-size: 9px;\n font-weight: 850;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n }\n .step h3 {\n margin: 0 0 7px;\n font-size: 14px;\n }\n .step p {\n margin: 0;\n color: var(--learning-muted);\n font-size: 12px;\n line-height: 1.45;\n }\n .copy-again {\n margin-top: 12px;\n padding: 0;\n color: var(--learning-secondary-ink);\n background: none;\n border: 0;\n font-size: 11px;\n font-weight: 750;\n text-decoration: underline;\n cursor: pointer;\n }\n .setup-support {\n margin-top: 14px;\n }\n .collection-panel {\n padding: 15px;\n background: var(--learning-surface);\n border: 1px solid var(--learning-line);\n border-radius: 8px;\n }\n .support-heading {\n margin-bottom: 12px;\n }\n .support-heading h3 {\n margin: 0;\n font-size: 13px;\n }\n .error-alert {\n margin-bottom: 10px;\n padding: 11px 12px;\n color: var(--learning-danger);\n background: var(--learning-soft-danger);\n border: 1px solid var(--learning-danger-border);\n border-radius: 6px;\n }\n .error-alert p {\n margin: 0;\n color: var(--learning-danger-muted);\n font-size: 11px;\n line-height: 1.45;\n }\n .prompt-link {\n display: inline-block;\n margin-top: 7px;\n padding: 0;\n color: var(--learning-danger);\n background: none;\n border: 0;\n font-size: 11px;\n font-weight: 750;\n text-decoration: underline;\n cursor: pointer;\n }\n .collection-summary {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n padding: 10px;\n background: var(--learning-soft);\n border-radius: 6px;\n }\n .collection-stat {\n display: flex;\n min-width: 0;\n align-items: center;\n gap: 9px;\n }\n .captured-count {\n color: var(--learning-ink);\n font-size: 28px;\n line-height: 1;\n }\n .collection-stat span {\n font-size: 12px;\n font-weight: 700;\n }\n .technical-details {\n margin-top: 10px;\n color: var(--learning-muted);\n font-size: 10px;\n }\n .technical-details summary {\n cursor: pointer;\n font-weight: 700;\n }\n .technical-details dl {\n display: grid;\n grid-template-columns: auto 1fr;\n gap: 5px 12px;\n margin: 9px 0 0;\n padding: 10px;\n background: var(--learning-soft);\n border-radius: 5px;\n }\n .technical-details dt {\n color: var(--learning-muted-strong);\n }\n .technical-details dd {\n margin: 0;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n overflow-wrap: anywhere;\n }\n .primary,\n .secondary {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-height: 36px;\n padding: 0 14px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 750;\n text-decoration: none;\n cursor: pointer;\n }\n .primary {\n color: var(--learning-primary-ink);\n background: var(--learning-primary);\n border: 1px solid var(--learning-primary);\n }\n .secondary {\n color: var(--learning-secondary-ink);\n background: var(--learning-secondary);\n border: 1px solid var(--learning-line-secondary);\n }\n .primary:disabled,\n .primary[aria-disabled=\"true\"] {\n color: var(--learning-disabled-ink);\n background: var(--learning-disabled);\n border-color: var(--learning-disabled);\n cursor: not-allowed;\n pointer-events: none;\n }\n .setup-cta:not(:disabled),\n .results-cta {\n min-width: 170px;\n min-height: 40px;\n padding: 0 18px;\n box-shadow: 0 6px 14px rgba(23, 23, 27, 0.2);\n }\n .outcome-preview {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n margin-top: 16px;\n color: var(--learning-outcome);\n font-size: 11px;\n }\n .outcome-preview span {\n padding: 6px 9px;\n background: var(--learning-surface);\n border: 1px dashed var(--learning-outcome-dash);\n border-radius: 5px;\n }\n .outcome-preview b {\n color: var(--learning-outcome-arrow);\n }\n .analysis-card {\n padding: 18px 20px;\n background: var(--learning-surface-muted);\n }\n .analysis-card.ready {\n background: var(--learning-soft-purple);\n border-color: var(--learning-purple-border);\n }\n .analysis-card.error {\n background: var(--learning-soft-danger-alt);\n border-color: var(--learning-danger-border);\n }\n .analysis-row {\n display: flex;\n align-items: center;\n gap: 20px;\n }\n .analysis-copy {\n flex: 1;\n }\n .analysis-card h2 {\n margin-bottom: 7px;\n }\n .analysis-card p {\n margin: 0;\n color: var(--learning-muted);\n font-size: 13px;\n line-height: 1.5;\n }\n .eyebrow {\n margin: 0 0 6px !important;\n color: var(--learning-purple-dark) !important;\n font-size: 10px !important;\n font-weight: 850;\n letter-spacing: 0.09em;\n text-transform: uppercase;\n }\n .retry-strip {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n margin-bottom: 12px;\n padding: 11px 12px;\n color: var(--learning-danger);\n background: var(--learning-soft-danger);\n border: 1px solid var(--learning-danger-border);\n border-radius: 6px;\n font-size: 11px;\n }\n .result-section {\n margin-top: 14px;\n }\n .result-section-heading {\n display: flex;\n align-items: baseline;\n gap: 6px;\n margin-bottom: 10px;\n }\n .result-section-heading h2 {\n margin: 0;\n font-size: 14px;\n }\n .result-count {\n color: var(--learning-muted-strong);\n font-size: 10px;\n font-weight: 700;\n }\n .review-link {\n margin-left: auto;\n color: var(--learning-purple-dark);\n font-size: 11px;\n font-weight: 750;\n text-decoration: none;\n }\n .quiet-link {\n display: inline-flex;\n margin-top: 12px;\n color: var(--learning-purple-dark);\n font-size: 11px;\n font-weight: 750;\n text-decoration: none;\n }\n .quiet-link:hover,\n .review-link:hover {\n text-decoration: underline;\n }\n .content-card {\n overflow: hidden;\n }\n .empty-card {\n padding: 24px;\n color: var(--learning-muted);\n background: var(--learning-surface-subtle);\n border: 1px solid var(--learning-line);\n border-radius: 8px;\n }\n .empty-card.compact {\n padding: 15px 16px;\n }\n .empty-card h3 {\n margin: 0 0 6px;\n color: var(--learning-ink);\n font-size: 14px;\n }\n .empty-card p {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n }\n .active-skill {\n padding: 16px;\n }\n .active-skill + .active-skill {\n border-top: 1px solid var(--learning-line);\n }\n .active-skill h3 {\n margin: 0 0 6px;\n font-size: 14px;\n }\n .active-skill > p {\n margin: 0;\n color: var(--learning-muted);\n font-size: 12px;\n line-height: 1.45;\n }\n .skill-lineage {\n margin-top: 10px;\n padding: 10px 12px;\n background: var(--learning-surface-muted);\n border: 1px solid var(--learning-line);\n border-radius: 6px;\n }\n .skill-lineage > span {\n display: block;\n margin-bottom: 5px;\n color: var(--learning-muted-strong);\n font-size: 9px;\n font-weight: 800;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n }\n .skill-lineage button {\n display: flex;\n width: 100%;\n align-items: start;\n justify-content: space-between;\n gap: 14px;\n padding: 0;\n color: var(--learning-ink);\n background: none;\n border: 0;\n text-align: left;\n font-size: 11px;\n font-weight: 700;\n line-height: 1.4;\n cursor: pointer;\n }\n .skill-lineage button small {\n flex: 0 0 auto;\n color: var(--learning-purple-dark);\n font-size: 10px;\n font-weight: 750;\n }\n .supporting-unavailable {\n color: var(--learning-muted-strong);\n font-size: 11px;\n font-style: italic;\n }\n .skill-source {\n margin-top: 10px;\n }\n .skill-source summary {\n width: fit-content;\n color: var(--learning-purple-dark);\n cursor: pointer;\n font-size: 11px;\n font-weight: 750;\n }\n .skill-source pre {\n margin: 10px 0 0;\n padding: 12px;\n color: var(--learning-code);\n background: var(--learning-soft);\n border: 1px solid var(--learning-line);\n border-radius: 6px;\n font:\n 11px/1.5 ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n monospace;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n }\n .list-header {\n display: flex;\n align-items: center;\n padding: 10px 14px;\n color: var(--learning-muted-strong);\n background: var(--learning-surface-muted);\n border-bottom: 1px solid var(--learning-line);\n font-size: 10px;\n font-weight: 800;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n }\n .list-header span:last-child {\n margin-left: auto;\n }\n .insight-row {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n gap: 18px;\n width: 100%;\n padding: 16px;\n color: inherit;\n background: var(--learning-surface);\n border: 0;\n border-bottom: 1px solid var(--learning-line);\n text-align: left;\n cursor: pointer;\n }\n .insight-row:last-child {\n border-bottom: 0;\n }\n .insight-row:hover,\n .insight-row[data-selected=\"true\"] {\n background: var(--learning-surface-hover);\n }\n .insight-row h3 {\n margin: 0 0 6px;\n font-size: 14px;\n line-height: 1.35;\n }\n .insight-row p {\n margin: 0;\n color: var(--learning-muted);\n font-size: 12px;\n line-height: 1.45;\n }\n .evidence-count {\n min-width: 90px;\n color: var(--learning-purple-dark);\n font-size: 11px;\n font-weight: 750;\n text-align: right;\n }\n .detail-panel {\n margin-top: 14px;\n padding: 18px;\n background: var(--learning-surface-hover);\n border: 1px solid var(--learning-line-accent);\n border-radius: 8px;\n }\n .detail-head {\n display: flex;\n align-items: start;\n gap: 14px;\n }\n .detail-head div {\n flex: 1;\n }\n .detail-head h3 {\n margin: 0 0 5px;\n font-size: 14px;\n }\n .detail-head p {\n margin: 0;\n color: var(--learning-muted);\n font-size: 12px;\n line-height: 1.45;\n }\n .close-detail {\n width: 28px;\n height: 28px;\n color: var(--learning-muted);\n background: var(--learning-surface);\n border: 1px solid var(--learning-line);\n border-radius: 5px;\n cursor: pointer;\n }\n .evidence-list {\n display: grid;\n gap: 7px;\n margin-top: 14px;\n }\n .evidence-link,\n .evidence-unavailable {\n display: flex;\n align-items: center;\n gap: 10px;\n min-height: 38px;\n padding: 10px;\n color: var(--learning-code);\n background: var(--learning-surface);\n border: 1px solid var(--learning-line);\n border-radius: 6px;\n font-size: 11px;\n text-align: left;\n }\n .evidence-link {\n box-sizing: border-box;\n width: 100%;\n text-decoration: none;\n cursor: pointer;\n }\n .evidence-link span {\n margin-left: auto;\n color: var(--learning-muted-strong);\n }\n .evidence-unavailable {\n color: var(--learning-muted-strong);\n font-style: italic;\n }\n .evidence-coverage {\n margin: 12px 0 0;\n color: var(--learning-muted-strong);\n font-size: 11px;\n }\n .evidence-group-heading {\n margin: 6px 0 0;\n color: var(--learning-muted-strong);\n font-size: 10px;\n font-weight: 800;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n }\n .evidence-group-heading:first-child {\n margin-top: 0;\n }\n .evidence-id {\n color: var(--learning-muted-strong);\n font:\n 10px ui-monospace,\n SFMono-Regular,\n Menlo,\n monospace;\n }\n .evidence-more {\n justify-self: start;\n padding: 2px 0;\n color: var(--learning-purple-dark);\n background: none;\n border: 0;\n font-size: 11px;\n font-weight: 700;\n cursor: pointer;\n }\n .pagination {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 8px;\n margin-top: 10px;\n }\n .pagination span {\n margin-right: auto;\n color: var(--learning-muted);\n font-size: 11px;\n }\n .pagination button {\n min-height: 30px;\n padding: 0 10px;\n color: var(--learning-ink);\n background: var(--learning-surface);\n border: 1px solid var(--learning-line);\n border-radius: 5px;\n font-size: 11px;\n font-weight: 700;\n cursor: pointer;\n }\n .pagination button:disabled {\n color: var(--learning-disabled-ink);\n background: var(--learning-surface-muted);\n cursor: default;\n }\n .skeleton {\n display: grid;\n gap: 10px;\n }\n .skeleton span {\n height: 74px;\n background: linear-gradient(\n 90deg,\n var(--learning-skeleton-edge),\n var(--learning-skeleton-center),\n var(--learning-skeleton-edge)\n );\n background-size: 200% 100%;\n border-radius: 8px;\n animation: shimmer 1.3s infinite;\n }\n @keyframes shimmer {\n to {\n background-position: -200% 0;\n }\n }\n .dialog-backdrop {\n position: fixed;\n z-index: 50;\n inset: 0;\n display: grid;\n place-items: center;\n padding: 24px;\n background: rgba(15, 15, 20, 0.42);\n }\n .dialog {\n display: flex;\n width: min(620px, 100%);\n max-height: min(680px, 90vh);\n flex-direction: column;\n background: var(--learning-surface);\n border: 1px solid var(--learning-dialog-line);\n border-radius: 13px;\n box-shadow: 0 22px 70px rgba(0, 0, 0, 0.22);\n }\n .dialog header {\n display: flex;\n align-items: start;\n justify-content: space-between;\n padding: 18px 19px 13px;\n }\n .dialog h2 {\n margin: 0;\n font-size: 16px;\n }\n .dialog header p {\n margin: 4px 0 0;\n color: var(--learning-muted);\n font-size: 11px;\n }\n .dialog-close {\n color: var(--learning-muted);\n background: transparent;\n border: 0;\n font-size: 20px;\n cursor: pointer;\n }\n .dialog pre {\n max-height: 420px;\n overflow: auto;\n margin: 0 19px;\n padding: 12px;\n background: var(--learning-soft);\n border: 1px solid var(--learning-line);\n border-radius: 6px;\n font:\n 11px/1.5 ui-monospace,\n SFMono-Regular,\n Menlo,\n monospace;\n white-space: pre-wrap;\n }\n .dialog footer {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n padding: 14px 19px 18px;\n }\n .copy-error {\n margin: 10px 19px 0;\n color: var(--learning-danger);\n font-size: 11px;\n }\n @media (max-width: 900px) {\n .steps {\n grid-template-columns: 1fr;\n }\n .step {\n min-height: auto;\n }\n }\n @media (max-width: 640px) {\n .pane-inner {\n padding: 24px 18px 60px;\n }\n .analysis-row,\n .collection-summary {\n align-items: flex-start;\n flex-wrap: wrap;\n }\n .insight-row {\n grid-template-columns: 1fr;\n gap: 8px;\n }\n .evidence-count {\n text-align: left;\n }\n .review-link {\n width: 100%;\n margin: 4px 0 0;\n }\n }\n `;\n\n private emit(name: string, detail?: unknown) {\n this.dispatchEvent(\n new CustomEvent(name, { detail, bubbles: true, composed: true }),\n );\n }\n\n private externalLink(\n url: string | null,\n label: string,\n className = \"primary\",\n category: \"learning\" | \"runs\" | \"candidates\" = \"learning\",\n ) {\n return url\n ? html`<a\n class=${className}\n href=${url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n @click=${() => this.emit(\"learning-web-link\", { category })}\n >${label}</a\n >`\n : nothing;\n }\n\n private openPrompt(event?: Event) {\n const trigger = event?.currentTarget;\n this.promptTrigger = trigger instanceof HTMLElement ? trigger : null;\n this.promptOpen = true;\n this.requestUpdate();\n void this.updateComplete.then(() => {\n this.renderRoot\n .querySelector<HTMLButtonElement>(\".dialog-close\")\n ?.focus();\n });\n }\n\n private closePrompt(): void {\n this.promptOpen = false;\n this.requestUpdate();\n void this.updateComplete.then(() => this.promptTrigger?.focus());\n }\n\n private handlePromptKeydown = (event: KeyboardEvent): void => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n this.closePrompt();\n return;\n }\n if (event.key !== \"Tab\") return;\n const dialog = event.currentTarget;\n if (!(dialog instanceof HTMLElement)) return;\n const root = dialog.getRootNode();\n const activeElement =\n root instanceof ShadowRoot ? root.activeElement : document.activeElement;\n const focusable = [\n ...dialog.querySelectorAll<HTMLElement>(\n 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])',\n ),\n ];\n const first = focusable[0];\n const last = focusable.at(-1);\n if (!first || !last) return;\n if (event.shiftKey && activeElement === first) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && activeElement === last) {\n event.preventDefault();\n first.focus();\n }\n };\n\n private setupPromptButton(label = \"Copy the setup prompt\") {\n return html`<button\n class=\"primary\"\n type=\"button\"\n @click=${(event: Event) =>\n label === \"Open the setup prompt\"\n ? this.openPrompt(event)\n : this.emit(\"learning-copy-setup\")}\n >\n ${this.copyState === \"copied\" ? \"Prompt copied\" : label}\n </button>`;\n }\n\n private renderSetupProgress(\n mode: \"setup\" | \"ready\" | \"running\" | \"attention\",\n ) {\n const ready = mode === \"ready\";\n const running = mode === \"running\";\n const attention = mode === \"attention\";\n const waitingForLearningSetup =\n mode === \"setup\" &&\n this.setupActive &&\n (this.snapshot === null ||\n this.snapshot.configuration.state === \"not_configured\");\n const completedSteps = ready || running ? 2 : 1;\n const pendingThreads = ready ? (this.snapshot?.pendingThreadCount ?? 0) : 0;\n const title = attention\n ? \"Learning setup needs attention\"\n : mode === \"setup\"\n ? waitingForLearningSetup\n ? \"Waiting for Automatic Learning setup\"\n : \"Waiting for the first Thread\"\n : ready\n ? \"Threads ready to analyze\"\n : \"Analysis is running in the web app.\";\n const container =\n this.snapshot?.configuration.state === \"configured\"\n ? this.snapshot.configuration.container\n : null;\n\n return html`<section\n class=\"setup-card\"\n aria-labelledby=\"learning-setup-title\"\n >\n <div class=\"setup-top\">\n <h2 id=\"learning-setup-title\">Set up Automatic Learning</h2>\n <span class=\"progress-count\">${completedSteps} of 3 steps</span>\n </div>\n <div class=\"progress-track\" aria-hidden=\"true\">\n <div\n class=\"progress-fill\"\n style=\"width: ${(completedSteps / 3) * 100}%\"\n ></div>\n </div>\n <ol class=\"steps\">\n <li class=\"step complete\">\n <div class=\"step-header\"><span class=\"step-number\">✓</span></div>\n <h3>Copy the setup prompt</h3>\n <p>Nice work. You’ve completed the first step.</p>\n <button\n class=\"copy-again\"\n type=\"button\"\n aria-live=\"polite\"\n @click=${() => this.emit(\"learning-recopy-setup\")}\n >\n ${\n this.recopyState === \"copied\"\n ? \"✓ Copied!\"\n : this.recopyState === \"error\"\n ? \"Try copying again\"\n : \"Copy prompt again\"\n }\n </button>\n </li>\n <li\n class=\"step ${\n attention\n ? \"error current\"\n : mode === \"setup\"\n ? \"current\"\n : \"complete\"\n }\"\n >\n <div class=\"step-header\">\n <span class=\"step-number\">${ready || running ? \"✓\" : \"2\"}</span>\n ${\n attention\n ? html`\n <span class=\"step-state\">Needs attention</span>\n `\n : nothing\n }\n </div>\n <h3>\n ${\n waitingForLearningSetup\n ? \"Set up Automatic Learning\"\n : \"Create your first Thread\"\n }\n </h3>\n <p>\n ${\n waitingForLearningSetup\n ? \"Run the copied prompt in your coding agent. This page will continue when Automatic Learning is ready.\"\n : \"Open Checkout Assistant and complete a conversation.\"\n }\n </p>\n </li>\n <li class=\"step ${ready || running ? \"current\" : \"\"}\">\n <div class=\"step-header\"><span class=\"step-number\">3</span></div>\n <h3>Analyze Threads</h3>\n <p>We'll find patterns and turn them into insights and skills</p>\n </li>\n </ol>\n <div class=\"setup-support\">\n <section class=\"collection-panel\">\n <div class=\"support-heading\"><h3>${title}</h3></div>\n ${\n attention\n ? html`<div class=\"error-alert\" role=\"alert\">\n <p>\n Inspector did not find the Learning Space or app\n instrumentation. Open the setup prompt, run it in your coding\n agent, then try again.\n </p>\n <button\n class=\"prompt-link\"\n type=\"button\"\n @click=${(event: Event) => this.openPrompt(event)}\n >\n Open the setup prompt ↗\n </button>\n </div>`\n : html`<div class=\"collection-summary\">\n <div class=\"collection-stat\">\n <strong class=\"captured-count\">${pendingThreads}</strong>\n <span>New Threads</span>\n </div>\n ${\n ready || running\n ? this.externalLink(\n this.snapshot?.links.runs ?? null,\n \"Open in web app\",\n \"primary setup-cta\",\n \"runs\",\n )\n : html`\n <button class=\"primary setup-cta\" disabled>Analyze Threads</button>\n `\n }\n </div>`\n }\n ${\n attention\n ? nothing\n : html`<details class=\"technical-details\">\n <summary>Technical details</summary>\n <dl>\n <dt>Learning Space</dt>\n <dd>${container?.id ?? \"Waiting for setup\"}</dd>\n <dt>Status</dt>\n <dd>\n ${\n ready\n ? \"Threads available\"\n : running\n ? \"Analysis running\"\n : waitingForLearningSetup\n ? \"Waiting for Automatic Learning setup\"\n : \"Waiting for first Thread\"\n }\n </dd>\n </dl>\n </details>`\n }\n </section>\n </div>\n <div class=\"outcome-preview\" aria-label=\"Learning flow\">\n <span>Threads</span><b>→</b><span>Insights</span><b>→</b\n ><span>Skills</span>\n </div>\n </section>`;\n }\n\n private renderPagination(\n section: \"skills\" | \"insights\",\n page: number,\n totalPages: number,\n ) {\n if (totalPages <= 1) return nothing;\n return html`<nav class=\"pagination\" aria-label=\"${section} pages\">\n <span aria-live=\"polite\">Page ${page} of ${totalPages}</span>\n <button\n ?disabled=${page <= 1}\n @click=${() => this.emit(\"learning-page\", { section, page: page - 1 })}\n >\n Previous\n </button>\n <button\n ?disabled=${page >= totalPages}\n @click=${() => this.emit(\"learning-page\", { section, page: page + 1 })}\n >\n Next\n </button>\n </nav>`;\n }\n\n private renderEvidence(insight: InspectorLearningInsight) {\n const threads = insight.evidence;\n const trajectories = insight.trajectoryEvidence ?? [];\n const mixed = threads.length > 0 && trajectories.length > 0;\n const coverage = evidenceCoverageLabel(insight);\n return html`<section class=\"detail-panel\" aria-label=\"Insight evidence\">\n <div class=\"detail-head\">\n <div>\n <h3>Evidence</h3>\n <p>${insight.statement}</p>\n </div>\n <button\n class=\"close-detail\"\n type=\"button\"\n aria-label=\"Close evidence\"\n @click=${() => {\n this.selectedInsightId = null;\n this.requestUpdate();\n }}\n >\n ×\n </button>\n </div>\n ${coverage ? html`<p class=\"evidence-coverage\">${coverage}</p>` : nothing}\n <div class=\"evidence-list\">\n ${\n threads.length === 0 && trajectories.length === 0\n ? html`\n <div class=\"evidence-unavailable\">Evidence is no longer available</div>\n `\n : html`${this.renderEvidenceGroup(\n insight.id,\n \"threads\",\n threads,\n mixed,\n (evidence) =>\n html`<button\n class=\"evidence-link\"\n type=\"button\"\n @click=${() =>\n this.emit(\"learning-open-evidence\", {\n threadId: evidence.threadId,\n messageId: evidence.messageIds[0],\n })}\n >\n ⌁\n ${\n evidence.threadName ??\n `Thread ${evidence.threadId.slice(0, 8)}`\n }\n <span>Open Thread →</span>\n </button>`,\n )}${this.renderEvidenceGroup(\n insight.id,\n \"trajectories\",\n trajectories,\n mixed,\n (evidence) => this.renderTrajectoryEvidence(evidence),\n )}`\n }\n </div>\n ${\n insight.evidenceTruncated && !coverage\n ? html`\n <p class=\"supporting-unavailable\">Evidence response shortened</p>\n `\n : nothing\n }\n </section>`;\n }\n\n /**\n * Lists one kind of evidence: the first rows with a toggle for the rest,\n * then one line counting the sources that are no longer available.\n */\n private renderEvidenceGroup<\n T extends { readonly status: \"available\" | \"unavailable\" },\n >(\n insightId: string,\n kind: EvidenceKind,\n entries: readonly T[],\n showHeading: boolean,\n renderRow: (entry: Extract<T, { status: \"available\" }>) => unknown,\n ) {\n if (entries.length === 0) return nothing;\n const available = entries.filter(\n (entry): entry is Extract<T, { status: \"available\" }> =>\n entry.status === \"available\",\n );\n const unavailable = entries.length - available.length;\n const key = `${insightId}:${kind}`;\n const expanded = this.expandedEvidence.has(key);\n const hidden = Math.max(0, available.length - EVIDENCE_PREVIEW_LIMIT);\n const [singular, pluralForm] = EVIDENCE_NOUNS[kind];\n return html`\n ${\n showHeading\n ? html`<h4 class=\"evidence-group-heading\">${pluralForm}</h4>`\n : nothing\n }\n ${(expanded ? available : available.slice(0, EVIDENCE_PREVIEW_LIMIT)).map(\n renderRow,\n )}\n ${\n hidden > 0\n ? html`<button\n class=\"evidence-more\"\n type=\"button\"\n aria-expanded=${expanded}\n @click=${() => {\n if (expanded) this.expandedEvidence.delete(key);\n else this.expandedEvidence.add(key);\n this.requestUpdate();\n }}\n >\n ${\n expanded\n ? `Show fewer ${pluralForm}`\n : `Show ${plural(hidden, `more ${singular}`, `more ${pluralForm}`)}`\n }\n </button>`\n : nothing\n }\n ${\n unavailable > 0\n ? html`<div class=\"evidence-unavailable\">\n ${plural(unavailable, singular, pluralForm)}\n ${unavailable === 1 ? \"is\" : \"are\"} no longer available\n </div>`\n : nothing\n }\n `;\n }\n\n private renderTrajectoryEvidence(\n evidence: Extract<\n InspectorLearningTrajectoryEvidence,\n { status: \"available\" }\n >,\n ) {\n const createdAt = trajectoryCreatedAt(evidence.trajectoryId);\n const idTail = evidence.trajectoryId.slice(-8);\n return html`<a\n class=\"evidence-link\"\n href=${evidence.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n title=${evidence.trajectoryId}\n @click=${() => this.emit(\"learning-web-link\", { category: \"trajectory\" })}\n >\n ⌁\n ${\n createdAt\n ? `Trajectory · ${trajectoryTimeFormat.format(createdAt)}`\n : `Trajectory ${idTail}`\n }\n · ${plural(evidence.eventCount, \"cited event\", \"cited events\")}\n ${createdAt ? html`<small class=\"evidence-id\">${idTail}</small>` : nothing}\n <span>Open Trajectory ↗</span>\n </a>`;\n }\n\n private selectInsight(insight: InspectorLearningInsight) {\n this.selectedInsightId = insight.id;\n this.emit(\"learning-evidence-opened\");\n this.requestUpdate();\n }\n\n private supportingInsightLabel(statement: string): string {\n const firstStop = statement.indexOf(\".\");\n return firstStop === -1 ? statement : statement.slice(0, firstStop + 1);\n }\n\n private renderSkills(snapshot: InspectorLearningSnapshotV1) {\n const containerId =\n snapshot.configuration.state === \"configured\"\n ? snapshot.configuration.container.id\n : \"\";\n const skillPageKey = `${snapshot.projectKey}|${containerId}|${snapshot.skillsPage.page}|${snapshot.skillsPage.items.map((skill) => skill.id).join(\",\")}`;\n if (skillPageKey !== this.skillPageKey) {\n this.skillPageKey = skillPageKey;\n this.expandedSkillId = null;\n }\n return html`<section class=\"result-section\" aria-labelledby=\"skills-title\">\n <div class=\"result-section-heading\">\n <h2 id=\"skills-title\">Skills in registry</h2>\n <span class=\"result-count\">${snapshot.skillsPage.total}</span>\n ${\n snapshot.pendingCandidateCount > 0\n ? this.externalLink(\n snapshot.links.candidates,\n `${snapshot.pendingCandidateCount} ${snapshot.pendingCandidateCount === 1 ? \"Skill\" : \"Skills\"} for review in web app ↗`,\n \"review-link\",\n \"candidates\",\n )\n : nothing\n }\n </div>\n ${\n snapshot.skillsPage.items.length === 0\n ? html`\n <div class=\"empty-card compact\">\n <h3>No Skills in registry yet</h3>\n <p>\n No Insight has produced a Skill that was approved into the registry yet.\n </p>\n </div>\n `\n : html`<div class=\"content-card\">\n ${snapshot.skillsPage.items.map((skill) => {\n const open = this.expandedSkillId === skill.id;\n return html`<article class=\"active-skill\">\n <h3>${skill.name}</h3>\n <p>${skill.description}</p>\n <div class=\"skill-lineage\">\n <span>Supporting Insight</span>\n ${\n skill.sourceInsight\n ? html`<button\n type=\"button\"\n @click=${() => this.selectInsight(skill.sourceInsight!)}\n >\n ${this.supportingInsightLabel(\n skill.sourceInsight.statement,\n )}<small\n >${evidenceCountLabel(skill.sourceInsight)}</small\n >\n </button>`\n : html`\n <div class=\"supporting-unavailable\">Supporting Insight unavailable</div>\n `\n }\n </div>\n <details\n class=\"skill-source\"\n ?open=${open}\n @toggle=${(event: Event) => {\n const nextOpen = (event.currentTarget as HTMLDetailsElement)\n .open;\n if (nextOpen === open) return;\n this.expandedSkillId = nextOpen ? skill.id : \"\";\n this.emit(\"learning-skill-toggle\", {\n action: nextOpen ? \"expanded\" : \"collapsed\",\n });\n this.requestUpdate();\n }}\n >\n <summary>View SKILL.md</summary>\n <pre>${skill.skillMd}</pre>\n </details>\n </article>`;\n })}\n </div>`\n }\n ${this.renderPagination(\n \"skills\",\n snapshot.skillsPage.page,\n snapshot.skillsPage.totalPages,\n )}\n </section>`;\n }\n\n private renderInsights(snapshot: InspectorLearningSnapshotV1) {\n const selected = snapshot.insightsPage.items.find(\n (insight) => insight.id === this.selectedInsightId,\n );\n return html`<section\n class=\"result-section\"\n aria-labelledby=\"insights-title\"\n >\n <div class=\"result-section-heading\">\n <h2 id=\"insights-title\">\n ${snapshot.skillsPage.total > 0 ? \"More Insights\" : \"Insights\"}\n </h2>\n <span class=\"result-count\">${snapshot.insightsPage.total}</span>\n </div>\n ${\n snapshot.insightsPage.items.length === 0\n ? html`\n <div class=\"empty-card compact\"><h3>No active Insights</h3></div>\n `\n : html`<div class=\"content-card\">\n <div class=\"list-header\">\n <span>Pattern</span><span>Evidence</span>\n </div>\n ${snapshot.insightsPage.items.map(\n (insight) => html`<button\n class=\"insight-row\"\n data-selected=${selected?.id === insight.id}\n type=\"button\"\n @click=${() =>\n selected?.id === insight.id\n ? ((this.selectedInsightId = null), this.requestUpdate())\n : this.selectInsight(insight)}\n >\n <div>\n <h3>${insight.statement}</h3>\n <p>${insight.impact}</p>\n </div>\n <span class=\"evidence-count\"\n >${evidenceCountLabel(insight)}</span\n >\n </button>`,\n )}\n </div>`\n }\n ${selected ? this.renderEvidence(selected) : nothing}\n ${this.renderPagination(\n \"insights\",\n snapshot.insightsPage.page,\n snapshot.insightsPage.totalPages,\n )}\n </section>`;\n }\n\n private renderResults(snapshot: InspectorLearningSnapshotV1) {\n const sourceInsight = snapshot.skillsPage.items\n .map((skill) => skill.sourceInsight)\n .find((insight) => insight?.id === this.selectedInsightId);\n return html`\n ${\n snapshot.pendingThreadCount > 0\n ? html`<section class=\"analysis-card ready\">\n <div class=\"analysis-row\">\n <div class=\"analysis-copy\">\n <h2>Find new Insights and Skills</h2>\n <p>You have new threads ready to be analyzed.</p>\n </div>\n ${this.externalLink(\n snapshot.links.runs,\n \"Open in web app\",\n \"primary results-cta\",\n \"runs\",\n )}\n </div>\n </section>`\n : nothing\n }\n ${this.renderSkills(snapshot)}\n ${sourceInsight ? this.renderEvidence(sourceInsight) : nothing}\n ${this.renderInsights(snapshot)}\n `;\n }\n\n private renderRetryStrip() {\n if (!this.error) return nothing;\n return html`<div class=\"retry-strip\" role=\"status\">\n <span>${this.error}</span>\n <button\n class=\"secondary\"\n type=\"button\"\n @click=${() => this.emit(\"learning-retry\")}\n >\n Retry\n </button>\n </div>`;\n }\n\n private renderEmptyResults(snapshot: InspectorLearningSnapshotV1) {\n return html`<section class=\"analysis-card\">\n <div class=\"analysis-row\">\n <div class=\"analysis-copy\">\n <p class=\"eyebrow\">Analysis complete</p>\n <h2>No new Insights or Skills</h2>\n <p>\n Create more Threads with Checkout Assistant. You can run Automatic Learning\n again when new Threads are available.\n </p>\n </div>\n </div>\n </section>\n <section class=\"result-section\">\n <div class=\"result-section-heading\">\n <h2>Skills in registry</h2><span class=\"result-count\">0</span>\n </div>\n <div class=\"empty-card\">\n <h3>No Skills from this analysis</h3>\n <p>Automatic Learning did not generate a Skill for review.</p>\n </div>\n </section>\n <section class=\"result-section\">\n <div class=\"result-section-heading\">\n <h2>Insights</h2><span class=\"result-count\">0</span>\n </div>\n <div class=\"empty-card\">\n <h3>No Insights from this analysis</h3>\n <p>Automatic Learning did not find a useful pattern in these Threads.</p>\n </div>\n </section>\n ${this.externalLink(\n snapshot.links.learning,\n \"Open in web app ↗\",\n \"quiet-link\",\n \"learning\",\n )}`;\n }\n\n private renderCompactState(input: {\n readonly title: string;\n readonly copy?: string;\n readonly action?: unknown;\n readonly error?: boolean;\n }) {\n return html`<section class=\"analysis-card ${input.error ? \"error\" : \"\"}\">\n <div class=\"analysis-row\">\n <div class=\"analysis-copy\">\n <h2>${input.title}</h2>\n ${input.copy ? html`<p>${input.copy}</p>` : nothing}\n </div>\n ${input.action ?? nothing}\n </div>\n </section>`;\n }\n\n render() {\n const state = deriveLearningViewState({\n supported: this.supported,\n loading: this.loading,\n error: this.error,\n snapshot: this.snapshot,\n setupActive: this.setupActive,\n });\n let content: unknown;\n if (state === \"loading\") {\n content = html`\n <div class=\"skeleton\" aria-label=\"Loading Automatic Learning\">\n <span></span><span></span><span></span>\n </div>\n `;\n } else if (state === \"error\") {\n content = this.renderCompactState({\n title: \"Automatic Learning data is unavailable\",\n copy: this.error ?? undefined,\n error: true,\n action: html`<button\n class=\"secondary\"\n type=\"button\"\n @click=${() => this.emit(\"learning-retry\")}\n >\n Retry\n </button>`,\n });\n } else if (state === \"selection_required\") {\n content = this.renderCompactState({\n title: \"Inspector cannot choose a Learning Space for this agent.\",\n action: this.externalLink(\n this.snapshot!.links.learning,\n \"Open in web app\",\n \"primary\",\n \"learning\",\n ),\n });\n } else if (state === \"invalid\") {\n content = this.renderSetupProgress(\"attention\");\n } else if (state === \"landing\") {\n // The parent Inspector preserves the existing locked-feature marketing\n // surface for Landing. The v5 pane begins only after its copy action.\n content = nothing;\n } else if (state === \"setup\") {\n content = this.renderSetupProgress(\"setup\");\n } else if (state === \"first_run\") {\n content = this.renderSetupProgress(\"running\");\n } else if (state === \"ready\") {\n content = this.renderSetupProgress(\"ready\");\n } else if (state === \"empty\") {\n content = this.renderEmptyResults(this.snapshot!);\n } else {\n content = this.renderResults(this.snapshot!);\n }\n\n const retry =\n state === \"error\" || !this.snapshot ? nothing : this.renderRetryStrip();\n\n return html`<main class=\"pane-inner\" data-learning-state=${state}>\n <header class=\"pane-heading\">\n <div>\n <h1>Automatic Learning</h1>\n <p>Intelligence finds patterns in Rich Threads and proposes reusable Skills.</p>\n ${this.snapshot?.configuration.state === \"configured\" ? html`<p style=\"font-size:12px;margin-top:10px\">Learning Space <strong>${this.snapshot.configuration.container.name}</strong></p>` : nothing}\n </div>\n <div class=\"pane-actions\">\n ${\n state === \"results\"\n ? this.externalLink(\n this.snapshot!.webAppOrigin,\n \"Open Intelligence ↗\",\n \"secondary\",\n )\n : nothing\n }\n ${\n state === \"setup\" && this.setupActive\n ? html`<button\n class=\"secondary\"\n type=\"button\"\n @click=${() => this.emit(\"learning-go-back\")}\n >\n ← Go back\n </button>`\n : nothing\n }\n ${\n this.refreshing\n ? html`\n <span class=\"refreshing\" role=\"status\">Refreshing</span>\n `\n : nothing\n }\n </div>\n </header>\n ${retry}\n ${content}\n </main>\n ${\n this.promptOpen\n ? html`<div class=\"dialog-backdrop\">\n <section\n class=\"dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"learning-prompt-title\"\n @keydown=${this.handlePromptKeydown}\n >\n <header>\n <div>\n <h2 id=\"learning-prompt-title\">Set up Rich Threads</h2>\n <p>Paste this prompt into your coding agent.</p>\n </div>\n <button\n class=\"dialog-close\"\n aria-label=\"Close setup prompt\"\n @click=${() => this.closePrompt()}\n >\n ×\n </button>\n </header>\n <pre>${this.setupPrompt}</pre>\n ${\n this.copyState === \"error\"\n ? html`\n <p class=\"copy-error\" role=\"alert\">\n Clipboard access failed. Retry to continue.\n </p>\n `\n : nothing\n }\n <footer>\n <button\n class=\"secondary\"\n @click=${() => this.closePrompt()}\n >\n Close\n </button>\n <button\n class=\"primary\"\n @click=${() => this.emit(\"learning-copy-setup\")}\n >\n ${\n this.copyState === \"copied\"\n ? \"Prompt copied\"\n : \"Copy the setup prompt\"\n }\n </button>\n </footer>\n </section>\n </div>`\n : nothing\n }`;\n }\n}\n\nif (!customElements.get(\"cpk-learning-view\")) {\n customElements.define(\"cpk-learning-view\", CpkLearningView);\n}\n"],"mappings":";;;AAmBA,MAAM,UAAU,OAAe,UAAkB,eAC/C,GAAG,MAAM,GAAG,UAAU,IAAI,WAAW;;AAGvC,MAAM,yBAAyB;AAI/B,MAAM,iBAAkE;CACtE,SAAS,CAAC,UAAU,UAAU;CAC9B,cAAc,CAAC,cAAc,eAAe;CAC7C;AAED,MAAM,uBAAuB,IAAI,KAAK,eAAe,QAAW;CAC9D,OAAO;CACP,KAAK;CACL,MAAM;CACN,QAAQ;CACT,CAAC;;;;;AAMF,MAAM,uBAAuB,iBAAsC;CACjE,MAAM,MAAM,aAAa,QAAQ,MAAM,GAAG;AAC1C,KAAI,CAAC,+BAA+B,KAAK,IAAI,CAAE,QAAO;AACtD,QAAO,IAAI,KAAK,OAAO,SAAS,IAAI,MAAM,GAAG,GAAG,EAAE,GAAG,CAAC;;;;;;AAOxD,SAAS,sBACP,SACe;AACf,KAAI,CAAC,QAAQ,kBAAmB,QAAO;CACvC,MAAM,QAAkB,EAAE;AAC1B,KAAI,QAAQ,SAAS,SAAS,QAAQ,iBACpC,OAAM,KACJ,GAAG,QAAQ,SAAS,OAAO,MAAM,OAAO,QAAQ,kBAAkB,GAAG,eAAe,QAAQ,GAC7F;CAEH,MAAM,oBAAoB,QAAQ,oBAAoB,UAAU;AAChE,KACE,QAAQ,yBAAyB,UACjC,oBAAoB,QAAQ,qBAE5B,OAAM,KACJ,GAAG,kBAAkB,MAAM,OAAO,QAAQ,sBAAsB,GAAG,eAAe,aAAa,GAChG;AAEH,QAAO,MAAM,WAAW,IAAI,OAAO,WAAW,MAAM,KAAK,MAAM;;;;;;;AAQjE,SAAS,mBAAmB,SAA2C;CACrE,MAAM,UAAU,OAAO,QAAQ,kBAAkB,UAAU,UAAU;CACrE,MAAM,kBACJ,QAAQ,wBAAwB,QAAQ,oBAAoB,UAAU;AACxE,KAAI,oBAAoB,EAAG,QAAO;CAClC,MAAM,eAAe,OAAO,iBAAiB,cAAc,eAAe;AAC1E,QAAO,QAAQ,qBAAqB,IAChC,eACA,GAAG,QAAQ,KAAK;;AAGtB,SAAgB,wBAAwB,OAMlB;AAKpB,KAAI,CAAC,MAAM,UAAW,QAAO,MAAM,cAAc,UAAU;AAC3D,KAAI,CAAC,MAAM,YAAY,MAAM,QAAS,QAAO;AAC7C,KAAI,CAAC,MAAM,YAAY,MAAM,MAAO,QAAO;CAC3C,MAAM,WAAW,MAAM;AACvB,KAAI,CAAC,SAAU,QAAO;AACtB,KAAI,SAAS,cAAc,UAAU,qBACnC,QAAO;AACT,KAAI,SAAS,cAAc,UAAU,UAAW,QAAO;AAGvD,KADE,SAAS,WAAW,QAAQ,KAAK,SAAS,aAAa,QAAQ,KAC/C,SAAS,wBAAwB,EAAG,QAAO;AAC7D,KAAI,SAAS,IAAI,aAAc,QAAO;AACtC,KAAI,SAAS,IAAI,oBAAoB,SAAS,uBAAuB,EACnE,QAAO;AACT,KACE,SAAS,cAAc,UAAU,gBACjC,SAAS,qBAAqB,EAE9B,QAAO;AACT,KAAI,MAAM,eAAe,SAAS,cAAc,UAAU,aACxD,QAAO;AACT,QAAO;;AAGT,IAAa,kBAAb,cAAqCA,eAAW;;;mBAalC;iBACF;oBACG;eACU;kBACwB;qBACjC;mBAC2B;qBACE;qBAC7B;oBACO;uBACuB;yBACH;2BACE;0CAEP,IAAI,KAAa;sBAC9B;8BA47BQ,UAA+B;AAC5D,OAAI,MAAM,QAAQ,UAAU;AAC1B,UAAM,gBAAgB;AACtB,SAAK,aAAa;AAClB;;AAEF,OAAI,MAAM,QAAQ,MAAO;GACzB,MAAM,SAAS,MAAM;AACrB,OAAI,EAAE,kBAAkB,aAAc;GACtC,MAAM,OAAO,OAAO,aAAa;GACjC,MAAM,gBACJ,gBAAgB,aAAa,KAAK,gBAAgB,SAAS;GAC7D,MAAM,YAAY,CAChB,GAAG,OAAO,iBACR,6IACD,CACF;GACD,MAAM,QAAQ,UAAU;GACxB,MAAM,OAAO,UAAU,GAAG,GAAG;AAC7B,OAAI,CAAC,SAAS,CAAC,KAAM;AACrB,OAAI,MAAM,YAAY,kBAAkB,OAAO;AAC7C,UAAM,gBAAgB;AACtB,SAAK,OAAO;cACH,CAAC,MAAM,YAAY,kBAAkB,MAAM;AACpD,UAAM,gBAAgB;AACtB,UAAM,OAAO;;;;;oBAh/BG;GAClB,WAAW,EAAE,MAAM,SAAS;GAC5B,SAAS,EAAE,MAAM,SAAS;GAC1B,YAAY,EAAE,MAAM,SAAS;GAC7B,OAAO,EAAE,WAAW,OAAO;GAC3B,UAAU,EAAE,WAAW,OAAO;GAC9B,aAAa,EAAE,MAAM,SAAS;GAC9B,WAAW,EAAE,WAAW,OAAO;GAC/B,aAAa,EAAE,WAAW,OAAO;GACjC,aAAa,EAAE,WAAW,OAAO;GAClC;;;gBAmBe,OAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAg5BnB,AAAQ,KAAK,MAAc,QAAkB;AAC3C,OAAK,cACH,IAAI,YAAY,MAAM;GAAE;GAAQ,SAAS;GAAM,UAAU;GAAM,CAAC,CACjE;;CAGH,AAAQ,aACN,KACA,OACA,YAAY,WACZ,WAA+C,YAC/C;AACA,SAAO,MACH,QAAI;kBACM,UAAU;iBACX,IAAI;;;yBAGI,KAAK,KAAK,qBAAqB,EAAE,UAAU,CAAC,CAAC;aACzD,MAAM;aAEXC;;CAGN,AAAQ,WAAW,OAAe;EAChC,MAAM,UAAU,OAAO;AACvB,OAAK,gBAAgB,mBAAmB,cAAc,UAAU;AAChE,OAAK,aAAa;AAClB,OAAK,eAAe;AACpB,EAAK,KAAK,eAAe,WAAW;AAClC,QAAK,WACF,cAAiC,gBAAgB,EAChD,OAAO;IACX;;CAGJ,AAAQ,cAAoB;AAC1B,OAAK,aAAa;AAClB,OAAK,eAAe;AACpB,EAAK,KAAK,eAAe,WAAW,KAAK,eAAe,OAAO,CAAC;;CAgClE,AAAQ,kBAAkB,QAAQ,yBAAyB;AACzD,SAAO,QAAI;;;gBAGC,UACR,UAAU,0BACN,KAAK,WAAW,MAAM,GACtB,KAAK,KAAK,sBAAsB,CAAC;;QAErC,KAAK,cAAc,WAAW,kBAAkB,MAAM;;;CAI5D,AAAQ,oBACN,MACA;EACA,MAAM,QAAQ,SAAS;EACvB,MAAM,UAAU,SAAS;EACzB,MAAM,YAAY,SAAS;EAC3B,MAAM,0BACJ,SAAS,WACT,KAAK,gBACJ,KAAK,aAAa,QACjB,KAAK,SAAS,cAAc,UAAU;EAC1C,MAAM,iBAAiB,SAAS,UAAU,IAAI;EAC9C,MAAM,iBAAiB,QAAS,KAAK,UAAU,sBAAsB,IAAK;EAC1E,MAAM,QAAQ,YACV,mCACA,SAAS,UACP,0BACE,yCACA,iCACF,QACE,6BACA;EACR,MAAM,YACJ,KAAK,UAAU,cAAc,UAAU,eACnC,KAAK,SAAS,cAAc,YAC5B;AAEN,SAAO,QAAI;;;;;;uCAMwB,eAAe;;;;;0BAK3B,iBAAiB,IAAK,IAAI;;;;;;;;;;;;2BAY1B,KAAK,KAAK,wBAAwB,CAAC;;cAGhD,KAAK,gBAAgB,WACjB,cACA,KAAK,gBAAgB,UACnB,sBACA,oBACP;;;;wBAKD,YACI,kBACA,SAAS,UACP,YACA,WACP;;;wCAG6B,SAAS,UAAU,MAAM,IAAI;cAEvD,YACI,QAAI;;sBAGJA,YACL;;;cAIC,0BACI,8BACA,2BACL;;;cAIC,0BACI,0GACA,uDACL;;;0BAGa,SAAS,UAAU,YAAY,GAAG;;;;;;;;6CAQf,MAAM;YAEvC,YACI,QAAI;;;;;;;;;4BASQ,UAAiB,KAAK,WAAW,MAAM,CAAC;;;;wBAKpD,QAAI;;mDAE+B,eAAe;;;kBAIhD,SAAS,UACL,KAAK,aACH,KAAK,UAAU,MAAM,QAAQ,MAC7B,mBACA,qBACA,OACD,GACD,QAAI;;wBAGT;sBAEN;YAEC,YACIA,cACA,QAAI;;;;wBAII,WAAW,MAAM,oBAAoB;;;sBAIvC,QACI,sBACA,UACE,qBACA,0BACE,yCACA,2BACT;;;0BAIV;;;;;;;;;CAUT,AAAQ,iBACN,SACA,MACA,YACA;AACA,MAAI,cAAc,EAAG,QAAOA;AAC5B,SAAO,QAAI,uCAAuC,QAAQ;sCACxB,KAAK,MAAM,WAAW;;oBAExC,QAAQ,EAAE;uBACP,KAAK,KAAK,iBAAiB;GAAE;GAAS,MAAM,OAAO;GAAG,CAAC,CAAC;;;;;oBAK3D,QAAQ,WAAW;uBAChB,KAAK,KAAK,iBAAiB;GAAE;GAAS,MAAM,OAAO;GAAG,CAAC,CAAC;;;;;;CAO7E,AAAQ,eAAe,SAAmC;EACxD,MAAM,UAAU,QAAQ;EACxB,MAAM,eAAe,QAAQ,sBAAsB,EAAE;EACrD,MAAM,QAAQ,QAAQ,SAAS,KAAK,aAAa,SAAS;EAC1D,MAAM,WAAW,sBAAsB,QAAQ;AAC/C,SAAO,QAAI;;;;eAIA,QAAQ,UAAU;;;;;;yBAMR;AACb,QAAK,oBAAoB;AACzB,QAAK,eAAe;IACpB;;;;;QAKJ,WAAW,QAAI,gCAAgC,SAAS,QAAQA,YAAQ;;UAGtE,QAAQ,WAAW,KAAK,aAAa,WAAW,IAC5C,QAAI;;kBAGJ,QAAI,GAAG,KAAK,oBACV,QAAQ,IACR,WACA,SACA,QACC,aACC,QAAI;;;mCAIA,KAAK,KAAK,0BAA0B;GAClC,UAAU,SAAS;GACnB,WAAW,SAAS,WAAW;GAChC,CAAC,CAAC;;;sBAIH,SAAS,cACT,UAAU,SAAS,SAAS,MAAM,GAAG,EAAE,GACxC;;6BAGN,GAAG,KAAK,oBACP,QAAQ,IACR,gBACA,cACA,QACC,aAAa,KAAK,yBAAyB,SAAS,CACtD,GACN;;QAGD,QAAQ,qBAAqB,CAAC,WAC1B,QAAI;;gBAGJA,YACL;;;;;;;CAQL,AAAQ,oBAGN,WACA,MACA,SACA,aACA,WACA;AACA,MAAI,QAAQ,WAAW,EAAG,QAAOA;EACjC,MAAM,YAAY,QAAQ,QACvB,UACC,MAAM,WAAW,YACpB;EACD,MAAM,cAAc,QAAQ,SAAS,UAAU;EAC/C,MAAM,MAAM,GAAG,UAAU,GAAG;EAC5B,MAAM,WAAW,KAAK,iBAAiB,IAAI,IAAI;EAC/C,MAAM,SAAS,KAAK,IAAI,GAAG,UAAU,SAAS,uBAAuB;EACrE,MAAM,CAAC,UAAU,cAAc,eAAe;AAC9C,SAAO,QAAI;QAEP,cACI,QAAI,sCAAsC,WAAW,SACrDA,YACL;SACE,WAAW,YAAY,UAAU,MAAM,GAAG,uBAAuB,EAAE,IACpE,UACD,CAAC;QAEA,SAAS,IACL,QAAI;;;8BAGc,SAAS;6BACV;AACb,OAAI,SAAU,MAAK,iBAAiB,OAAO,IAAI;OAC1C,MAAK,iBAAiB,IAAI,IAAI;AACnC,QAAK,eAAe;IACpB;;gBAGA,WACI,cAAc,eACd,QAAQ,OAAO,QAAQ,QAAQ,YAAY,QAAQ,aAAa,GACrE;yBAEHA,YACL;QAEC,cAAc,IACV,QAAI;gBACA,OAAO,aAAa,UAAU,WAAW,CAAC;gBAC1C,gBAAgB,IAAI,OAAO,MAAM;sBAErCA,YACL;;;CAIL,AAAQ,yBACN,UAIA;EACA,MAAM,YAAY,oBAAoB,SAAS,aAAa;EAC5D,MAAM,SAAS,SAAS,aAAa,MAAM,GAAG;AAC9C,SAAO,QAAI;;aAEF,SAAS,IAAI;;;cAGZ,SAAS,aAAa;qBACf,KAAK,KAAK,qBAAqB,EAAE,UAAU,cAAc,CAAC,CAAC;;;QAIxE,YACI,gBAAgB,qBAAqB,OAAO,UAAU,KACtD,cAAc,SACnB;UACG,OAAO,SAAS,YAAY,eAAe,eAAe,CAAC;QAC7D,YAAY,QAAI,8BAA8B,OAAO,YAAYA,YAAQ;;;;CAK/E,AAAQ,cAAc,SAAmC;AACvD,OAAK,oBAAoB,QAAQ;AACjC,OAAK,KAAK,2BAA2B;AACrC,OAAK,eAAe;;CAGtB,AAAQ,uBAAuB,WAA2B;EACxD,MAAM,YAAY,UAAU,QAAQ,IAAI;AACxC,SAAO,cAAc,KAAK,YAAY,UAAU,MAAM,GAAG,YAAY,EAAE;;CAGzE,AAAQ,aAAa,UAAuC;EAC1D,MAAM,cACJ,SAAS,cAAc,UAAU,eAC7B,SAAS,cAAc,UAAU,KACjC;EACN,MAAM,eAAe,GAAG,SAAS,WAAW,GAAG,YAAY,GAAG,SAAS,WAAW,KAAK,GAAG,SAAS,WAAW,MAAM,KAAK,UAAU,MAAM,GAAG,CAAC,KAAK,IAAI;AACtJ,MAAI,iBAAiB,KAAK,cAAc;AACtC,QAAK,eAAe;AACpB,QAAK,kBAAkB;;AAEzB,SAAO,QAAI;;;qCAGsB,SAAS,WAAW,MAAM;UAErD,SAAS,wBAAwB,IAC7B,KAAK,aACH,SAAS,MAAM,YACf,GAAG,SAAS,sBAAsB,GAAG,SAAS,0BAA0B,IAAI,UAAU,SAAS,2BAC/F,eACA,aACD,GACDA,YACL;;QAGD,SAAS,WAAW,MAAM,WAAW,IACjC,QAAI;;;;;;;gBAQJ,QAAI;cACF,SAAS,WAAW,MAAM,KAAK,UAAU;GACzC,MAAM,OAAO,KAAK,oBAAoB,MAAM;AAC5C,UAAO,QAAI;sBACH,MAAM,KAAK;qBACZ,MAAM,YAAY;;;oBAInB,MAAM,gBACF,QAAI;;uCAEW,KAAK,cAAc,MAAM,cAAe,CAAC;;0BAEtD,KAAK,uBACL,MAAM,cAAc,UACrB,CAAC;6BACG,mBAAmB,MAAM,cAAc,CAAC;;mCAG7C,QAAI;;0BAGT;;;;0BAIO,KAAK;6BACF,UAAiB;IAC1B,MAAM,WAAY,MAAM,cACrB;AACH,QAAI,aAAa,KAAM;AACvB,SAAK,kBAAkB,WAAW,MAAM,KAAK;AAC7C,SAAK,KAAK,yBAAyB,EACjC,QAAQ,WAAW,aAAa,aACjC,CAAC;AACF,SAAK,eAAe;KACpB;;;yBAGK,MAAM,QAAQ;;;IAGzB,CAAC;kBAER;QACC,KAAK,iBACL,UACA,SAAS,WAAW,MACpB,SAAS,WAAW,WACrB,CAAC;;;CAIN,AAAQ,eAAe,UAAuC;EAC5D,MAAM,WAAW,SAAS,aAAa,MAAM,MAC1C,YAAY,QAAQ,OAAO,KAAK,kBAClC;AACD,SAAO,QAAI;;;;;;YAMH,SAAS,WAAW,QAAQ,IAAI,kBAAkB,WAAW;;qCAEpC,SAAS,aAAa,MAAM;;QAGzD,SAAS,aAAa,MAAM,WAAW,IACnC,QAAI;;gBAGJ,QAAI;;;;cAIF,SAAS,aAAa,MAAM,KAC3B,YAAY,QAAI;;gCAEC,UAAU,OAAO,QAAQ,GAAG;;+BAG1C,UAAU,OAAO,QAAQ,MACnB,KAAK,oBAAoB,MAAO,KAAK,eAAe,IACtD,KAAK,cAAc,QAAQ,CAAC;;;wBAG1B,QAAQ,UAAU;uBACnB,QAAQ,OAAO;;;qBAGjB,mBAAmB,QAAQ,CAAC;;yBAGpC,CAAC;kBAEP;QACC,WAAW,KAAK,eAAe,SAAS,GAAGA,YAAQ;QACnD,KAAK,iBACL,YACA,SAAS,aAAa,MACtB,SAAS,aAAa,WACvB,CAAC;;;CAIN,AAAQ,cAAc,UAAuC;EAC3D,MAAM,gBAAgB,SAAS,WAAW,MACvC,KAAK,UAAU,MAAM,cAAc,CACnC,MAAM,YAAY,SAAS,OAAO,KAAK,kBAAkB;AAC5D,SAAO,QAAI;QAEP,SAAS,qBAAqB,IAC1B,QAAI;;;;;;gBAMA,KAAK,aACL,SAAS,MAAM,MACf,mBACA,uBACA,OACD,CAAC;;wBAGJA,YACL;QACC,KAAK,aAAa,SAAS,CAAC;QAC5B,gBAAgB,KAAK,eAAe,cAAc,GAAGA,YAAQ;QAC7D,KAAK,eAAe,SAAS,CAAC;;;CAIpC,AAAQ,mBAAmB;AACzB,MAAI,CAAC,KAAK,MAAO,QAAOA;AACxB,SAAO,QAAI;cACD,KAAK,MAAM;;;;uBAIF,KAAK,KAAK,iBAAiB,CAAC;;;;;;CAOjD,AAAQ,mBAAmB,UAAuC;AAChE,SAAO,QAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA8BP,KAAK,aACL,SAAS,MAAM,UACf,qBACA,cACA,WACD;;CAGL,AAAQ,mBAAmB,OAKxB;AACD,SAAO,QAAI,iCAAiC,MAAM,QAAQ,UAAU,GAAG;;;gBAG3D,MAAM,MAAM;YAChB,MAAM,OAAO,QAAI,MAAM,MAAM,KAAK,QAAQA,YAAQ;;UAEpD,MAAM,UAAUA,YAAQ;;;;CAKhC,SAAS;EACP,MAAM,QAAQ,wBAAwB;GACpC,WAAW,KAAK;GAChB,SAAS,KAAK;GACd,OAAO,KAAK;GACZ,UAAU,KAAK;GACf,aAAa,KAAK;GACnB,CAAC;EACF,IAAI;AACJ,MAAI,UAAU,UACZ,WAAU,QAAI;;;;;WAKL,UAAU,QACnB,WAAU,KAAK,mBAAmB;GAChC,OAAO;GACP,MAAM,KAAK,SAAS;GACpB,OAAO;GACP,QAAQ,QAAI;;;yBAGK,KAAK,KAAK,iBAAiB,CAAC;;;;GAI9C,CAAC;WACO,UAAU,qBACnB,WAAU,KAAK,mBAAmB;GAChC,OAAO;GACP,QAAQ,KAAK,aACX,KAAK,SAAU,MAAM,UACrB,mBACA,WACA,WACD;GACF,CAAC;WACO,UAAU,UACnB,WAAU,KAAK,oBAAoB,YAAY;WACtC,UAAU,UAGnB,WAAUA;WACD,UAAU,QACnB,WAAU,KAAK,oBAAoB,QAAQ;WAClC,UAAU,YACnB,WAAU,KAAK,oBAAoB,UAAU;WACpC,UAAU,QACnB,WAAU,KAAK,oBAAoB,QAAQ;WAClC,UAAU,QACnB,WAAU,KAAK,mBAAmB,KAAK,SAAU;MAEjD,WAAU,KAAK,cAAc,KAAK,SAAU;EAG9C,MAAM,QACJ,UAAU,WAAW,CAAC,KAAK,WAAWA,cAAU,KAAK,kBAAkB;AAEzE,SAAO,QAAI,gDAAgD,MAAM;;;;;cAKvD,KAAK,UAAU,cAAc,UAAU,eAAe,QAAI,oEAAoE,KAAK,SAAS,cAAc,UAAU,KAAK,iBAAiBA,YAAQ;;;cAIlM,UAAU,YACN,KAAK,aACH,KAAK,SAAU,cACf,uBACA,YACD,GACDA,YACL;cAEC,UAAU,WAAW,KAAK,cACtB,QAAI;;;mCAGa,KAAK,KAAK,mBAAmB,CAAC;;;+BAI/CA,YACL;cAEC,KAAK,aACD,QAAI;;sBAGJA,YACL;;;UAGH,MAAM;UACN,QAAQ;;QAGV,KAAK,aACD,QAAI;;;;;;yBAMS,KAAK,oBAAoB;;;;;;;;;;iCAUjB,KAAK,aAAa,CAAC;;;;;qBAK/B,KAAK,YAAY;gBAEtB,KAAK,cAAc,UACf,QAAI;;;;wBAKJA,YACL;;;;iCAIkB,KAAK,aAAa,CAAC;;;;;;iCAMnB,KAAK,KAAK,sBAAsB,CAAC;;oBAG9C,KAAK,cAAc,WACf,kBACA,wBACL;;;;oBAKPA;;;AAKZ,IAAI,CAAC,eAAe,IAAI,oBAAoB,CAC1C,gBAAe,OAAO,qBAAqB,gBAAgB"}
|