diff --git a/Makefile b/Makefile index 6c9552f..c9d6073 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,8 @@ # WatcherBridge make targets. Go targets use the module cache; UI # targets run inside ui/ with the pinned Node toolchain (.nvmrc). # `make ui-check` is the Step 22 gate: lint (a11y warnings fatal), -# committed-dist build, and the 200 KiB gzip budget. +# no-inline-style guard, committed-dist build, and the 200 KiB gzip +# budget. .PHONY: ui ui-check ui-drift @@ -9,7 +10,7 @@ ui: cd ui && npm ci --no-audit --no-fund && npm run build ui-check: - cd ui && npm ci --no-audit --no-fund && npm run lint && npm run build && npm run smoke && npm run size + cd ui && npm ci --no-audit --no-fund && npm run lint && npm run styleguard && npm run build && npm run smoke && npm run size # ui-drift rebuilds the bundle and fails when the committed output # differs: internal/viewer/web/dist must always match ui/ sources. diff --git a/docs/index.html b/docs/index.html index fa562ab..1731303 100644 --- a/docs/index.html +++ b/docs/index.html @@ -97,7 +97,12 @@

Follow a report.

Storage
Local SQLite
Evidence
Original signed report
Identity
Scanner-reported
-

03 / Optional AI

Explain the change.

Local rules set the priority floor. If configured, AI can explain the change using redacted context and may suggest a one-level increase up to high. A final leak check guards provider requests. If the model fails, the bridge stores a marked fallback.

+
+

03 / Optional AI

+

Explain the change.

+

Local rules set the priority floor. If configured, AI can explain the change using redacted context and may suggest a one-level increase up to high. A final leak check guards provider requests. If the model fails, the bridge stores a marked fallback.

+

When enabled, the AI investigator can use read-only tools to look up retained scanner reports about host history, services, and similar changes. The briefing can cite supporting evidence and show where lookups were incomplete.

+
Example finding
Scanner reported a host appearance
Suggested check
Confirm against your asset inventory
Model context
Redacted by default
@@ -112,8 +117,8 @@

Follow a report.

02 / Review workflow

-

From one report
to the bigger picture.

-

The local dashboard brings together scanner evidence, priority reasoning, and operator decisions.

+

From report to decision.

+

Review what the scanner reported, see why it was prioritized, and record your decision in the local dashboard.

@@ -121,9 +126,21 @@

From one report
to the bigger picture.

Briefing detail / Synthetic demonstration data
-
01

Review related changes together

Qualifying appearance or disappearance briefings from the same source and target can form one incident with links to its members.

-
02

Turn repeat decisions into policy

By default, three matching, eligible “expected” decisions can produce a rule proposal for operator approval.

-
03

See where coverage is uncertain

The overview pairs an Act, Review, or Quiet verdict with per-source coverage. Liveness stays unknown until heartbeat capability is established.

+
+ +

Review related changes

+

WatcherBridge groups qualifying appearance or disappearance reports into incidents. Optional AI summaries for closed incidents show how many briefings were sampled or omitted, label hypotheses, and can cite member briefings.

+
+
+ +

Approve review rules

+

By default, three matching, eligible “expected” decisions can trigger a rule proposal. An operator decides whether to approve it.

+
+
+ +

Check scanner coverage

+

See the Act, Review, or Quiet verdict beside each source’s coverage. A source’s liveness stays unknown until it sends a heartbeat.

+
diff --git a/docs/landing.css b/docs/landing.css index de5dd5a..e92c302 100644 --- a/docs/landing.css +++ b/docs/landing.css @@ -70,8 +70,8 @@ nav a:hover, .text-link:hover { text-decoration: underline; text-underline-offse .architecture, .review { padding-block: clamp(54px, 8vw, 102px); } .architecture { background: #e6ede1; border-block: 1px solid var(--line); } -.section-heading { display: grid; grid-template-columns: 1.18fr 1fr; align-items: end; gap: 18px 40px; margin-block: 13px 32px; } -.section-heading > p { max-width: 41ch; color: var(--muted); font-size: 1.06rem; } +.section-heading { margin-block: 13px 32px; } +.section-heading > p { max-width: 60ch; margin-top: 12px; color: var(--muted); font-size: 1.06rem; } .lab { background: var(--dark); color: #edf7ee; padding: clamp(16px, 3vw, 36px); border-radius: 18px; } .lab-header { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-bottom: 20px; } .lab .indicator { background: var(--lime); } @@ -96,11 +96,13 @@ nav a:hover, .text-link:hover { text-decoration: underline; text-underline-offse .readout dd { color: var(--lime); overflow-wrap: anywhere; } @keyframes reveal { from { opacity: .35; transform: translateY(5px); } to { opacity: 1; transform: none; } } -.review-grid { display: grid; grid-template-columns: 1.65fr 1fr; align-items: start; gap: clamp(24px, 4vw, 56px); } +.review-grid { display: grid; gap: clamp(28px, 4vw, 48px); } .product-shot img { display: block; width: 100%; height: auto; border: 1px solid var(--line); border-radius: 12px; box-shadow: 0 14px 32px #14282214; } .product-shot figcaption { margin-top: 12px; color: var(--muted); font: .72rem/1.5 var(--mono); } -.features article { display: grid; grid-template-columns: 30px 1fr; gap: 10px; padding-block: 19px; border-top: 1px solid var(--line); } +.features { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(16px, 2.5vw, 32px); } +.features article { padding-top: 16px; border-top: 1px solid var(--line); } .features article > span { color: #32654f; font: 700 .8rem/1.5 var(--mono); } +.features h3 { margin-top: 8px; line-height: 1.15; } .features p { margin-top: 8px; color: var(--muted); } .closing { padding-block: 54px; background: var(--dark); color: #edf7ee; } .closing-inner { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 24px; } @@ -110,12 +112,16 @@ nav a:hover, .text-link:hover { text-decoration: underline; text-underline-offse .site-footer { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 12px; padding-block: 22px; color: var(--muted); font-size: .82rem; } @media (max-width: 820px) { - .hero, .section-heading, .review-grid { grid-template-columns: 1fr; } + .hero { grid-template-columns: 1fr; } .hero h1 { font-size: clamp(3.4rem, 10vw, 6rem); } .signal { width: min(100%, 590px); } .stage { grid-template-columns: 1fr; } } +@media (max-width: 720px) { + .features { grid-template-columns: 1fr; } +} + @media (max-width: 520px) { .wrap { width: calc(100% - 32px); } .site-header { align-items: flex-start; flex-direction: column; padding-block: 14px; gap: 12px; } diff --git a/internal/viewer/web/dist/assets/index.css b/internal/viewer/web/dist/assets/index.css index 141c84a..937926f 100644 --- a/internal/viewer/web/dist/assets/index.css +++ b/internal/viewer/web/dist/assets/index.css @@ -1 +1 @@ -.decision-card.svelte-38cs4v{background:var(--surface);border:1px solid var(--border);overflow-wrap:anywhere;border-radius:16px;padding:26px}.decision-card.svelte-38cs4v h3:where(.svelte-38cs4v){letter-spacing:-.4px;margin-bottom:10px;font-size:20px}.decision-status.svelte-38cs4v{margin-bottom:20px}.decision-card.svelte-38cs4v .decision-status:where(.svelte-38cs4v) .pill:where(.svelte-38cs4v){padding:5px 11px;font-size:12px}.decision-card.svelte-38cs4v [data-review=unreviewed]:where(.svelte-38cs4v),.decision-card.svelte-38cs4v [data-review=snooze]:where(.svelte-38cs4v){color:var(--warning);border-color:var(--warning-border);background:var(--warning-bg)}.decision-card.svelte-38cs4v [data-review=expected]:where(.svelte-38cs4v){color:var(--success);border-color:var(--success-border);background:var(--success-bg)}.decision-card.svelte-38cs4v [data-review=not_expected]:where(.svelte-38cs4v){color:var(--danger);border-color:var(--danger-border);background:var(--danger-bg)}.decision-card.svelte-38cs4v fieldset:where(.svelte-38cs4v){border:1px solid var(--border);border-radius:11px;gap:0;min-width:0;margin:0 0 12px;padding:6px 0;display:grid}.decision-card.svelte-38cs4v fieldset:where(.svelte-38cs4v) label:where(.svelte-38cs4v){cursor:pointer;grid-template-columns:20px minmax(0,1fr);align-items:center;gap:2px 12px;min-height:66px;margin:0;padding:12px 16px;display:grid}.decision-card.svelte-38cs4v fieldset:where(.svelte-38cs4v) label:where(.svelte-38cs4v):hover{background:var(--subtle)}.decision-card.svelte-38cs4v fieldset:where(.svelte-38cs4v) label.selected:where(.svelte-38cs4v){background:var(--accent-soft)}.decision-card.svelte-38cs4v fieldset:where(.svelte-38cs4v) input:where(.svelte-38cs4v){width:18px;height:18px;accent-color:var(--accent);grid-row:1/span 2;margin:0;padding:0}.decision-label.svelte-38cs4v{font-weight:600}.decision-hint.svelte-38cs4v{color:var(--muted);grid-column:2;font-size:12px}.decision-card.svelte-38cs4v button[type=submit]:where(.svelte-38cs4v){width:100%;color:var(--surface);background:var(--text);border-color:var(--text);margin-top:8px;font-weight:700}.decision-card.svelte-38cs4v button[type=submit]:where(.svelte-38cs4v):disabled{opacity:.45}.decision-card.svelte-38cs4v .history-heading:where(.svelte-38cs4v){border-top:1px solid var(--border);text-transform:uppercase;letter-spacing:.07em;color:var(--muted);margin:24px 0 12px;padding-top:20px;font-size:11px}.empty-history.svelte-38cs4v{color:var(--muted);margin-bottom:0;font-size:13px}.decision-card.svelte-38cs4v .trail:where(.svelte-38cs4v){padding-left:0;list-style:none}.decision-card.svelte-38cs4v .trail:where(.svelte-38cs4v) li:where(.svelte-38cs4v){flex-wrap:wrap;align-items:center;gap:8px;display:flex}.decision-card.svelte-38cs4v .trail:where(.svelte-38cs4v) time:where(.svelte-38cs4v){color:var(--muted);font-size:11px}.decision-card.svelte-38cs4v .trail:where(.svelte-38cs4v) .text:where(.svelte-38cs4v){flex-basis:100%}.decision-card.svelte-38cs4v .trail:where(.svelte-38cs4v) button:where(.svelte-38cs4v){min-height:32px;padding:4px 8px;font-size:12px}.wb-clipboard-buffer{opacity:0;pointer-events:none;position:fixed}.copy-btn.svelte-ba0p1p{min-height:32px;color:var(--accent);background:var(--accent-soft);padding:4px 10px;font-size:12px}.report-card.svelte-43cneo{border:1px solid var(--border);background:var(--surface);overflow-wrap:anywhere;border-radius:11px;margin:12px 0 0;padding:0 16px}summary.svelte-43cneo{padding:16px 0}.report-heading.svelte-43cneo{vertical-align:top;flex-wrap:wrap;align-items:center;gap:8px;max-width:100%;display:inline-flex}.report-id.svelte-43cneo{font-weight:600}.report-time.svelte-43cneo{color:var(--muted);margin:7px 0 0 16px;font-size:12px;font-weight:400;display:block}.report-body.svelte-43cneo{border-top:1px solid var(--border);padding:16px 0 6px}.report-view.svelte-43cneo{border-top:1px solid var(--border);margin:16px 0;padding:16px 0 0}.report-view.svelte-43cneo h4:where(.svelte-43cneo){font-size:14px}.report-view.svelte-43cneo .report-identity:where(.svelte-43cneo){grid-template-columns:repeat(auto-fit,minmax(min(100%,180px),1fr));gap:14px;margin:0 0 16px;display:grid}.report-identity.svelte-43cneo dt:where(.svelte-43cneo){text-transform:uppercase;letter-spacing:.05em;margin-bottom:4px;font-size:11px}.report-identity.svelte-43cneo dd:where(.svelte-43cneo){margin:0}.confidence-note.svelte-43cneo{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.attributes.svelte-43cneo{border:0;padding:0}.attributes.svelte-43cneo summary:where(.svelte-43cneo){color:var(--accent);font-size:12px}.profile-chip.svelte-43cneo{border:1px solid var(--border);background:var(--accent-soft);border-radius:9px;flex-wrap:wrap;gap:5px 12px;padding:10px 12px;font-size:13px;text-decoration:none;display:flex}.mono.svelte-43cneo{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}li.svelte-6r3uui{border-top:1px solid var(--border);padding:12px 0;list-style:none}.tool-name.svelte-6r3uui{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;font-weight:600}p.svelte-6r3uui{margin:8px 0}.dossier.svelte-90l7ri{max-width:1400px;margin:0 auto;container-type:inline-size}.dossier-back.svelte-90l7ri{margin:0 0 20px}.dossier-back.svelte-90l7ri a:where(.svelte-90l7ri){text-decoration:none}.dossier-layout.svelte-90l7ri{grid-template-columns:minmax(0,1fr) minmax(300px,.48fr);align-items:start;gap:20px 24px;display:grid}.dossier-layout.svelte-90l7ri>:where(.svelte-90l7ri):not(.dossier-side){grid-column:1;min-width:0}.dossier-card.svelte-90l7ri{border:1px solid var(--border);background:var(--surface);overflow-wrap:anywhere;border-radius:16px;margin:0;padding:26px}.dossier-side.svelte-90l7ri{border-radius:16px;grid-area:1/2/span 7;max-height:calc(100dvh - 40px);position:sticky;top:20px;overflow:auto}.dossier.svelte-90l7ri .briefing-heading:where(.svelte-90l7ri){flex-wrap:wrap;align-items:flex-start;margin-bottom:16px}.dossier.svelte-90l7ri .briefing-heading:where(.svelte-90l7ri) h2:where(.svelte-90l7ri){letter-spacing:-.7px;flex:260px;font-size:clamp(23px,2.1vw,30px);line-height:1.22}.dossier.svelte-90l7ri .briefing-heading:where(.svelte-90l7ri) .priority:where(.svelte-90l7ri){text-transform:uppercase;letter-spacing:.06em;padding:5px 12px;font-weight:700}.dossier.svelte-90l7ri .briefing-description:where(.svelte-90l7ri){margin-bottom:24px;font-size:16px;line-height:1.65}.dossier.svelte-90l7ri .identity-grid:where(.svelte-90l7ri){border-top:1px solid var(--border);grid-template-columns:repeat(2,minmax(0,1fr));gap:22px 28px;margin:0;padding-top:22px;display:grid}.identity-grid.svelte-90l7ri>div:where(.svelte-90l7ri){min-width:0}.identity-grid.svelte-90l7ri dt:where(.svelte-90l7ri){text-transform:uppercase;letter-spacing:.08em;margin-bottom:7px;font-size:11px}.identity-grid.svelte-90l7ri dd:where(.svelte-90l7ri){flex-wrap:wrap;align-items:center;gap:6px 10px;margin:0;font-size:15px;font-weight:600;display:flex}.mono.svelte-90l7ri{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.identity-group.svelte-90l7ri{grid-column:1/-1}.identity-group.svelte-90l7ri p:where(.svelte-90l7ri){margin:5px 0 0}.evidence-index.svelte-90l7ri{border-top:1px solid var(--border);color:var(--muted);flex-wrap:wrap;justify-content:space-between;align-items:center;gap:4px 12px;margin-top:24px;padding-top:14px;font-size:13px;display:flex}.snapshot-note.svelte-90l7ri{border:1px solid var(--accent);color:var(--accent);background:var(--accent-soft);border-radius:12px;gap:12px;padding:15px 18px;display:flex}.snapshot-note.svelte-90l7ri p:where(.svelte-90l7ri){margin:0}.info-mark.svelte-90l7ri{border:1.5px solid;border-radius:50%;flex:none;place-items:center;width:19px;height:19px;margin-top:2px;font-size:12px;font-weight:700;display:inline-grid}.dossier.svelte-90l7ri h3:where(.svelte-90l7ri){letter-spacing:-.3px;margin-bottom:12px;font-size:18px}.section-heading.svelte-90l7ri{align-items:flex-start;gap:12px;display:flex}.section-heading.svelte-90l7ri h3:where(.svelte-90l7ri){margin-bottom:5px}.section-heading.svelte-90l7ri .section-note:where(.svelte-90l7ri){margin:0}.spread.svelte-90l7ri{flex-wrap:wrap;justify-content:space-between;margin-bottom:12px}.section-icon.svelte-90l7ri{background:var(--accent-soft);width:34px;height:34px;color:var(--accent);border-radius:9px;flex:none;place-items:center;font-size:23px;display:grid}.recommended-action.svelte-90l7ri{border:1px solid var(--border);border-left:3px solid var(--accent);border-radius:9px;margin:18px 0;padding:16px;font-size:15px;line-height:1.7}.copy-row.svelte-90l7ri{flex-wrap:wrap;align-items:center;gap:10px;display:flex}.copy-chip.svelte-90l7ri{border:1px solid var(--border);background:var(--subtle);overflow-wrap:anywhere;border-radius:8px;flex-wrap:wrap;align-items:center;gap:8px;min-width:0;padding:5px 8px 5px 10px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;display:inline-flex}.priority-rule.svelte-90l7ri{flex-wrap:wrap;align-items:center;gap:10px;margin-bottom:10px;display:flex}.priority-rule.svelte-90l7ri code:where(.svelte-90l7ri){background:var(--subtle);border:1px solid var(--border);border-radius:6px;padding:4px 8px}.priority-comparison.svelte-90l7ri,.context-links.svelte-90l7ri{border:0;border-top:1px solid var(--border);border-radius:0;margin:16px 0 0;padding:0}.priority-comparison.svelte-90l7ri summary:where(.svelte-90l7ri),.context-links.svelte-90l7ri summary:where(.svelte-90l7ri){color:var(--accent);font-size:13px}.hypothesis.svelte-90l7ri,.context-text.svelte-90l7ri{line-height:1.7}.context-limit.svelte-90l7ri{border:1px solid var(--warning-border);background:var(--warning-bg);color:var(--warning);border-radius:9px;padding:12px 14px;font-size:13px}.lookup-receipts.svelte-90l7ri{margin:0;padding:0;list-style:none}.lookup-receipts.svelte-90l7ri li:where(.svelte-90l7ri){border-top:1px solid var(--border);align-items:flex-start;gap:12px;padding:12px 0;display:flex}.receipt-steps.svelte-90l7ri{flex-wrap:wrap;gap:4px 16px;display:flex}.lookup-receipts.svelte-90l7ri p:where(.svelte-90l7ri){margin:0;font-size:13px}.receipt-mark.svelte-90l7ri{color:var(--muted);font-weight:700}.text-link.svelte-90l7ri{color:var(--accent);text-align:left;background:0 0;border:0;min-height:36px;padding:6px 0;font-size:13px}.text-link.svelte-90l7ri:hover{background:0 0;text-decoration:underline}.citation-row.svelte-90l7ri{flex-wrap:wrap;align-items:center;gap:8px;margin-top:16px;display:flex}.citation.svelte-90l7ri{color:var(--accent);background:var(--accent-soft);min-height:32px;padding:4px 9px;font-size:12px}.tech-block.svelte-90l7ri{padding:0 24px}.tech-block.svelte-90l7ri>summary:where(.svelte-90l7ri){padding:20px 0;font-size:15px}.tech-block.svelte-90l7ri>summary:where(.svelte-90l7ri) span:where(.svelte-90l7ri){margin-left:10px;font-weight:400}.tech-body.svelte-90l7ri{border-top:1px solid var(--border);padding:18px 0 8px}.trace-list.svelte-90l7ri{margin:0 0 20px;padding:0}.embedded.svelte-90l7ri .dossier-layout:where(.svelte-90l7ri){flex-direction:column;gap:16px;display:flex}.embedded.svelte-90l7ri .dossier-layout:where(.svelte-90l7ri)>:where(.svelte-90l7ri){width:100%}.embedded.svelte-90l7ri .dossier-side:where(.svelte-90l7ri){order:1;max-height:none;position:static;overflow:visible}.embedded.svelte-90l7ri .recommended-card:where(.svelte-90l7ri){order:0}.embedded.svelte-90l7ri .dossier-card:where(.svelte-90l7ri):not(.briefing-summary,.recommended-card),.embedded.svelte-90l7ri .tech-block:where(.svelte-90l7ri){order:2}.embedded.svelte-90l7ri .dossier-card:where(.svelte-90l7ri){padding:20px}@container (width<=840px){.dossier-layout.svelte-90l7ri{flex-direction:column;display:flex}.dossier-layout.svelte-90l7ri>:where(.svelte-90l7ri){width:100%}.dossier-side.svelte-90l7ri{order:1;max-height:none;position:static;overflow:visible}.dossier-card.svelte-90l7ri:not(.briefing-summary,.recommended-card),.tech-block.svelte-90l7ri{order:2}}@container (width<=500px){.dossier.svelte-90l7ri .identity-grid:where(.svelte-90l7ri){grid-template-columns:minmax(0,1fr);gap:18px}.dossier-card.svelte-90l7ri{padding:20px}.tech-block.svelte-90l7ri{padding:0 20px}}.app-header.svelte-1n46o8q{background:var(--surface);border-bottom:1px solid var(--border);flex-wrap:wrap;align-items:center;gap:12px 28px;padding:12px 28px;display:flex}.brand.svelte-1n46o8q{color:var(--text);letter-spacing:-.5px;align-items:center;gap:10px;font-size:18px;font-weight:700;text-decoration:none;display:inline-flex}.brand-mark.svelte-1n46o8q{background:var(--text);width:30px;height:30px;color:var(--surface);border-radius:8px;place-items:center;font-size:17px;display:grid}nav.svelte-1n46o8q{flex-wrap:wrap;gap:4px;display:flex}nav.svelte-1n46o8q a:where(.svelte-1n46o8q),nav.svelte-1n46o8q button:where(.svelte-1n46o8q){min-height:44px;color:var(--muted);background:0 0;border:0;border-radius:8px;align-items:center;padding:8px 14px;text-decoration:none;display:inline-flex}nav.svelte-1n46o8q a[aria-current=page]:where(.svelte-1n46o8q){background:var(--accent-soft);color:var(--accent);font-weight:650}main.svelte-1n46o8q{max-width:1500px;min-height:calc(100dvh - 160px);margin:0 auto;padding:28px}main.svelte-1n46o8q:focus{outline:none}.app-footer.svelte-1n46o8q{border-top:1px solid var(--border);color:var(--muted);flex-wrap:wrap;justify-content:space-between;gap:8px;padding:16px 28px;font-size:12px;display:flex}.skip-link.svelte-1n46o8q{z-index:10;background:var(--surface);padding:12px;position:fixed;top:-100px;left:16px}.skip-link.svelte-1n46o8q:focus{top:12px}section[aria-label=Keyboard\ shortcuts].svelte-1n46o8q{background:var(--surface);border:1px solid var(--border);border-radius:12px;margin:16px 28px;padding:20px}@media (width<=640px){.app-header.svelte-1n46o8q{gap:10px;padding:12px 16px}nav.svelte-1n46o8q{order:3;width:100%}nav.svelte-1n46o8q a:where(.svelte-1n46o8q),nav.svelte-1n46o8q button:where(.svelte-1n46o8q){padding:8px 10px}main.svelte-1n46o8q,.app-footer.svelte-1n46o8q{padding:16px}}:root{color:var(--text);background:var(--canvas);--canvas:#f4f5f7;--surface:#fff;--subtle:#f8f9fb;--text:#14171c;--muted:#535d6b;--border:#d9dde3;--accent:#1b4f9c;--accent-soft:#e8eef7;--success:#225b38;--success-bg:#e8f3ec;--success-border:#9ec4aa;--warning:#6b4700;--warning-bg:#fff4d6;--warning-border:#d9b94f;--danger:#9e302c;--danger-bg:#fcecea;--danger-border:#dea49d;--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light dark;font:14px/1.5 -apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}@media (prefers-color-scheme:dark){:root{--lightningcss-light: ;--lightningcss-dark:initial}}*{box-sizing:border-box}body{margin:0}a{color:var(--accent);text-underline-offset:3px}a:hover{text-decoration:underline}button,input,select,textarea{font:inherit;color:inherit;border:1px solid var(--border);background:var(--surface);border-radius:8px;padding:9px 12px}button,select{min-height:44px}button{cursor:pointer;font-weight:550}button:hover{background:var(--accent-soft);border-color:var(--accent)}button:disabled{cursor:default;opacity:.6}input,select,textarea{max-width:100%}input:not([type=checkbox],[type=radio]),textarea{min-height:44px}textarea{resize:vertical;width:100%;min-height:96px;display:block}:focus-visible{outline:3px solid var(--accent);outline-offset:3px}h1,h2,h3,h4,p,dl,ul,ol{margin-top:0}h2{letter-spacing:-.6px;overflow-wrap:anywhere;margin-bottom:12px;font-size:26px;line-height:1.25}h3{margin-bottom:12px;font-size:16px;font-weight:650}h4{margin-bottom:12px;font-size:14px}p{margin-bottom:14px}section,article{min-width:0}section+section{margin-top:24px}code,pre,kbd{overflow-wrap:anywhere;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}pre{white-space:pre-wrap;background:var(--subtle);border-radius:8px;padding:12px}kbd{border:1px solid var(--border);background:var(--surface);border-bottom-width:2px;border-radius:4px;padding:1px 5px}time{font-variant-numeric:tabular-nums}[role=alert],.coverage-note,[role=note]{border:1px solid var(--warning-border);background:var(--warning-bg);color:var(--warning);overflow-wrap:anywhere;border-radius:8px;padding:12px 16px}[role=status]:not(.conn){color:var(--muted)}.eyebrow{text-transform:uppercase;letter-spacing:.08em;color:var(--muted);font-size:11px;font-weight:650}.section-note,.help{color:var(--muted);font-size:13px}.pill{border:1px solid var(--border);background:var(--subtle);color:var(--muted);vertical-align:middle;border-radius:999px;align-items:center;gap:4px;padding:2px 9px;font-size:12px;display:inline-flex}.pill[data-state=ok],.priority[data-priority=low]{color:var(--success);background:var(--success-bg);border-color:var(--success-border)}.pill[data-state=degraded],.priority[data-priority=medium]{color:var(--warning);background:var(--warning-bg);border-color:var(--warning-border)}.pill[data-state=blind],.priority[data-priority=high],.priority[data-priority=critical]{color:var(--danger);background:var(--danger-bg);border-color:var(--danger-border)}.priority{text-transform:uppercase;letter-spacing:.03em;border-radius:5px;font-weight:650}.conn{color:var(--muted);align-items:center;gap:7px;margin:0 0 0 auto;font-size:12px;display:flex}.dot{background:var(--muted);border-radius:50%;flex-shrink:0;width:8px;height:8px}.conn[data-state=live] .dot{background:var(--success)}.conn[data-state=retrying] .dot{background:var(--warning)}.verdict{border:1px solid var(--border);background:var(--surface);border-radius:12px;margin-bottom:24px;padding:22px 24px}.verdict[data-verdict=review]{background:var(--warning-bg);border-color:var(--warning-border)}.verdict[data-verdict=act]{background:var(--danger-bg);border-color:var(--danger-border)}.verdict[data-verdict=quiet]{border-color:var(--success-border)}.verdict-heading{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;margin:8px 0 16px;display:flex}.verdict h2{margin:0;font-size:30px}.verdict-scale{border:1px solid var(--border);background:var(--surface);border-radius:999px;margin:0;padding:0;list-style:none;display:flex;overflow:hidden}.verdict-scale li{text-transform:capitalize;color:var(--muted);padding:6px 16px;font-size:12px}.verdict-scale [aria-current=true]{background:var(--text);color:var(--surface);font-weight:650}.pills{flex-wrap:wrap;gap:8px;margin:0 0 12px;padding:0;list-style:none;display:flex}.context{color:var(--muted);margin:0;font-size:12px}.reasons{font-size:13px}.review-workspace{grid-template-columns:minmax(0,.8fr) minmax(0,1.2fr);align-items:start;gap:24px;display:grid}.review-list,.detail-pane{scrollbar-gutter:stable;max-height:calc(100dvh - 120px);padding:3px;overflow:auto}.review-list>section{margin-bottom:24px}.attention{gap:8px;margin:0;padding:0;list-style:none;display:grid}.attention-row{background:var(--surface);border:1px solid var(--border);text-align:left;width:100%;color:var(--text);border-radius:10px;align-items:flex-start;gap:12px;padding:16px;font-weight:400;text-decoration:none;display:flex}.attention-row:hover,.host-list a:hover{background:var(--subtle);border-color:var(--accent);text-decoration:none}.attention-row[aria-current=true]{background:var(--accent-soft);border-color:var(--accent);box-shadow:inset 3px 0 var(--accent)}.attention>li>button:not(.attention-row){margin:8px 0}.row-main{overflow-wrap:anywhere;flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.row-main code{color:var(--muted);font-size:11px}.row-meta{color:var(--muted);text-align:right;flex-direction:column;align-items:flex-end;gap:6px;font-size:11px;display:flex}.detail-pane{background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:24px;position:sticky;top:20px}.pane-heading{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;margin-bottom:20px;font-size:12px;display:flex}.pane-heading .eyebrow{margin-right:auto}.empty-detail{text-align:center;max-width:340px;min-height:310px;color:var(--muted);flex-direction:column;justify-content:center;align-items:center;margin:auto;display:flex}.empty-detail h2{color:var(--text);font-size:20px}.empty-mark{border:1px solid var(--border);background:var(--subtle);border-radius:12px;place-items:center;width:48px;height:48px;margin-bottom:20px;font-size:24px;display:grid}.digest{grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin:0;display:grid}.digest>div{border:1px solid var(--border);background:var(--surface);border-radius:10px;padding:14px}.digest dt{color:var(--muted);font-size:12px;font-weight:500}.digest dd{margin:8px 0 0;font-size:26px;font-weight:600}.expected{color:var(--muted);font-size:11px;font-weight:400;display:block}.sources{margin:0;padding:0;list-style:none}.sources>li{background:var(--surface);border:1px solid var(--border);border-radius:10px;flex-wrap:wrap;align-items:center;gap:8px 12px;margin-bottom:8px;padding:14px 16px;font-size:12px;display:flex}.sources>li>span:not(.pill){color:var(--muted)}.host-list{gap:8px;margin:20px 0;padding:0;list-style:none;display:grid}.host-list a{border:1px solid var(--border);background:var(--surface);color:var(--text);border-radius:10px;align-items:center;gap:16px;padding:18px 20px;text-decoration:none;display:flex}.host-list .row-main>span{color:var(--muted);font-size:12px}.host-icon{color:var(--accent);background:var(--accent-soft);border-radius:8px;padding:8px 12px}main>article{max-width:1050px;margin:0 auto}article>section,article>dl,main>section[aria-label=Health]>section{background:var(--surface);border:1px solid var(--border);border-radius:12px;margin-bottom:20px;padding:20px 24px}.detail-pane article>section{border:0;border-bottom:1px solid var(--border);border-radius:0;margin:0 0 16px;padding:0 0 16px}.detail-pane article>section>:last-child{margin-bottom:0}.briefing-heading{justify-content:space-between;align-items:center;gap:12px;margin-bottom:12px;display:flex}.briefing-heading h2{letter-spacing:-.3px;margin:0;font-size:20px}.briefing-description{max-width:75ch;font-size:15px;line-height:1.6}.briefing-meta{color:var(--muted);overflow-wrap:anywhere;flex-wrap:wrap;align-items:baseline;gap:8px 16px;font-size:12px;display:flex}.briefing-meta>span{min-width:0}.briefing-host{color:var(--text)}.briefing .stepper{border:1px solid var(--border);background:var(--subtle);border-radius:8px;grid-template-columns:repeat(3,minmax(0,1fr));gap:0;margin-bottom:10px;display:grid}.briefing .stepper li{color:var(--muted);background:0 0;border:0;border-radius:0;padding:10px 12px}.briefing .stepper li+li{border-left:1px solid var(--border)}.briefing .stepper strong{color:var(--text);margin-top:3px;font-size:14px}.priority-note span{display:block}article h2{font-size:23px}article p,article li{overflow-wrap:anywhere}dl:not(.digest,.health-metrics){grid-template-columns:minmax(110px,.35fr) minmax(0,1fr);gap:10px 20px;display:grid}dt{color:var(--muted);font-size:13px;font-weight:600}dd{overflow-wrap:anywhere;margin:0}details{border:1px solid var(--border);background:var(--surface);border-radius:10px;margin-bottom:10px;padding:0 18px}summary{cursor:pointer;min-height:48px;padding:13px 0;font-weight:600}details>dl{padding:12px 0}details>section{border-top:1px solid var(--border);padding:16px 0}.health-metrics{grid-template-columns:repeat(5,minmax(0,1fr));gap:12px;margin-bottom:0;display:grid}.health-metrics>div{background:var(--subtle);border:1px solid var(--border);border-radius:8px;padding:16px}.health-metrics dd{margin-top:10px;font-size:26px}.health-metrics small{color:var(--muted);font-size:13px}.stepper{flex-wrap:wrap;gap:8px;padding:0;list-style:none;display:flex}.stepper li{background:var(--subtle);border:1px solid var(--border);border-radius:8px;flex:130px;padding:12px;font-size:12px}.stepper strong{font-size:15px;display:block}fieldset{border:1px solid var(--border);border-radius:10px;margin:12px 0;padding:12px 16px}label{margin:10px 0;font-size:13px;display:block}label input:not([type=checkbox],[type=radio]),label select,label textarea{margin-top:4px}.trail{padding:0;list-style:none}.trail li{border-top:1px solid var(--border);padding:12px 0;font-size:13px}.trail .text{overflow-wrap:anywhere}.trail .until{color:var(--muted);font-size:12px}@media (width<=1050px){.review-workspace{grid-template-columns:minmax(0,1fr)}.review-list,.detail-pane{max-height:none;overflow:visible}.detail-pane{position:static}.health-metrics{grid-template-columns:repeat(3,minmax(0,1fr))}}@media (width<=640px){.briefing .stepper{grid-template-columns:minmax(0,1fr)}.briefing .stepper li{justify-content:space-between;align-items:baseline;gap:12px;display:flex}.briefing .stepper li+li{border-left:0;border-top:1px solid var(--border)}h2{font-size:23px}.verdict{padding:18px}.verdict h2{font-size:26px}.digest{grid-template-columns:repeat(2,minmax(0,1fr))}.attention-row,.host-list a{flex-wrap:wrap;gap:10px;padding:14px}.row-meta{text-align:left;flex-direction:row;justify-content:space-between;align-items:center;width:100%}.host-icon{display:none}.detail-pane,article>section,article>dl{padding:16px}dl:not(.digest,.health-metrics){grid-template-columns:minmax(0,1fr);gap:4px}dd{margin-bottom:10px}.health-metrics{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (prefers-color-scheme:dark){:root{--canvas:#15191f;--surface:#1e242d;--subtle:#252c36;--text:#edf0f5;--muted:#b4bfce;--border:#414b5a;--accent:#9dc2ff;--accent-soft:#293c58;--success:#abd7b8;--success-bg:#213b2b;--success-border:#4e7a5d;--warning:#f1d38e;--warning-bg:#3d321e;--warning-border:#8c7237;--danger:#f3b3ad;--danger-bg:#422b2b;--danger-border:#9e625b}}@media (prefers-reduced-motion:reduce){*,:before,:after{scroll-behavior:auto!important;transition:none!important;animation:none!important}}.sr-only{clip-path:inset(50%);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.review-workspace[data-empty=true]{grid-template-columns:minmax(0,1fr);max-width:900px;margin:0 auto} +._pill_awt79_1{border:1px solid var(--border);background:var(--subtle);color:var(--muted);vertical-align:middle;border-radius:999px;align-items:center;gap:4px;padding:2px 9px;font-size:12px;display:inline-flex}._pill_awt79_1._large_awt79_14{padding:5px 11px}._pill_awt79_1[data-state=ok],._priority_awt79_19[data-priority=low]{color:var(--success);background:var(--success-bg);border-color:var(--success-border)}._pill_awt79_1[data-state=degraded],._priority_awt79_19[data-priority=medium]{color:var(--warning);background:var(--warning-bg);border-color:var(--warning-border)}._pill_awt79_1[data-state=blind],._priority_awt79_19[data-priority=high],._priority_awt79_19[data-priority=critical]{color:var(--danger);background:var(--danger-bg);border-color:var(--danger-border)}._priority_awt79_19{text-transform:uppercase;letter-spacing:.03em;border-radius:5px;font-weight:650}._pill_awt79_1[data-review=unreviewed],._pill_awt79_1[data-review=snooze]{color:var(--warning);background:var(--warning-bg);border-color:var(--warning-border)}._pill_awt79_1[data-review=expected]{color:var(--success);background:var(--success-bg);border-color:var(--success-border)}._pill_awt79_1[data-review=not_expected]{color:var(--danger);background:var(--danger-bg);border-color:var(--danger-border)}._list_18cpf_1{flex-wrap:wrap;gap:8px;margin:0 0 12px;padding:0;list-style:none;display:flex}.wb-clipboard-buffer{opacity:0;pointer-events:none;position:fixed}._copyBtn_1lk9i_7{min-height:32px;color:var(--accent);background:var(--accent-soft);padding:4px 10px;font-size:12px}._card_1sfyz_1{border:1px solid var(--border);background:var(--surface);overflow-wrap:anywhere;border-radius:11px;margin:12px 0 0;padding:0 16px}._card_1sfyz_1 summary{padding:16px 0}._heading_1sfyz_14{vertical-align:top;flex-wrap:wrap;align-items:center;gap:8px;max-width:100%;display:inline-flex}._reportId_1sfyz_23{font-weight:600}._reportTime_1sfyz_27{color:var(--muted);margin:7px 0 0 16px;font-size:12px;font-weight:400;display:block}._body_1sfyz_35{border-top:1px solid var(--border);padding:16px 0 6px}._view_1sfyz_40{border-top:1px solid var(--border);margin:16px 0;padding:16px 0 0}._view_1sfyz_40 h4{font-size:14px}._identity_1sfyz_50{grid-template-columns:repeat(auto-fit,minmax(min(100%,180px),1fr));gap:14px;margin:0 0 16px;display:grid}._identity_1sfyz_50 dt{text-transform:uppercase;letter-spacing:.05em;margin-bottom:4px;font-size:11px}._identity_1sfyz_50 dd{margin:0}._confidence_1sfyz_68{flex-wrap:wrap;align-items:center;gap:8px;display:flex}._attributes_1sfyz_75{border:0;padding:0}._attributes_1sfyz_75 summary{color:var(--accent);font-size:12px}._profileChip_1sfyz_85{border:1px solid var(--border);background:var(--accent-soft);border-radius:9px;flex-wrap:wrap;gap:5px 12px;padding:10px 12px;font-size:13px;text-decoration:none;display:flex}._step_hvx5m_1{border-top:1px solid var(--border);padding:12px 0;list-style:none}._toolName_hvx5m_7{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;font-weight:600}._step_hvx5m_1 p{margin:8px 0}._title_85c58_1{letter-spacing:-.4px;margin-bottom:10px;font-size:20px}._status_85c58_7{margin-bottom:20px}._composer_1b5ih_1{display:contents}._composer_1b5ih_1 fieldset{border:1px solid var(--border);border-radius:11px;gap:0;min-width:0;margin:0 0 12px;padding:6px 0;display:grid}._composer_1b5ih_1 fieldset label{cursor:pointer;grid-template-columns:20px minmax(0,1fr);align-items:center;gap:2px 12px;min-height:66px;margin:0;padding:12px 16px;display:grid}._composer_1b5ih_1 fieldset label:hover{background:var(--subtle)}._composer_1b5ih_1 fieldset label._selected_1b5ih_30{background:var(--accent-soft)}._composer_1b5ih_1 fieldset input{width:18px;height:18px;accent-color:var(--accent);grid-row:1/span 2;margin:0;padding:0}._decisionLabel_1b5ih_43{font-weight:600}._decisionHint_1b5ih_47{color:var(--muted);grid-column:2;font-size:12px}._composer_1b5ih_1 button[type=submit]{width:100%;color:var(--surface);background:var(--text);border-color:var(--text);margin-top:8px;font-weight:700}._composer_1b5ih_1 button[type=submit]:disabled{opacity:.45}._historyHeading_tgnl4_1{border-top:1px solid var(--border);text-transform:uppercase;letter-spacing:.07em;color:var(--muted);margin:24px 0 12px;padding-top:20px;font-size:11px}._emptyHistory_tgnl4_11{color:var(--muted);margin-bottom:0;font-size:13px}._trail_tgnl4_17{padding:0;list-style:none}._trail_tgnl4_17 li{border-top:1px solid var(--border);flex-wrap:wrap;align-items:center;gap:8px;padding:12px 0;font-size:13px;display:flex}._trail_tgnl4_17 time{color:var(--muted);font-size:11px}._trail_tgnl4_17 ._text_tgnl4_37{overflow-wrap:anywhere;flex-basis:100%}._trail_tgnl4_17 ._until_tgnl4_42{color:var(--muted);font-size:12px}._trail_tgnl4_17 button{min-height:32px;padding:4px 8px;font-size:12px}._card_1nnbv_1{background:var(--surface);border:1px solid var(--border);overflow-wrap:anywhere;border-radius:16px;padding:26px}._metrics_1i28o_1{grid-template-columns:repeat(5,minmax(0,1fr));gap:12px;margin-bottom:0;display:grid}._metrics_1i28o_1>div{background:var(--subtle);border:1px solid var(--border);border-radius:8px;padding:16px}._metrics_1i28o_1 dd{margin-top:10px;font-size:26px}._metrics_1i28o_1 small{color:var(--muted);font-size:13px}@media (width<=1050px){._metrics_1i28o_1{grid-template-columns:repeat(3,minmax(0,1fr))}}@media (width<=640px){._metrics_1i28o_1{grid-template-columns:repeat(2,minmax(0,1fr))}}._skip_1y3rk_1{z-index:10;background:var(--surface);padding:12px;position:fixed;top:-100px;left:16px}._skip_1y3rk_1:focus{top:12px}._header_pqrrf_1{background:var(--surface);border-bottom:1px solid var(--border);flex-wrap:wrap;align-items:center;gap:12px 28px;padding:12px 28px;display:flex}._brand_pqrrf_11{color:var(--text);letter-spacing:-.5px;align-items:center;gap:10px;font-size:18px;font-weight:700;text-decoration:none;display:inline-flex}._brandMark_pqrrf_22{background:var(--text);width:30px;height:30px;color:var(--surface);border-radius:8px;place-items:center;font-size:17px;display:grid}._header_pqrrf_1 nav{flex-wrap:wrap;gap:4px;display:flex}._header_pqrrf_1 nav a,._header_pqrrf_1 nav button{min-height:44px;color:var(--muted);background:0 0;border:0;border-radius:8px;align-items:center;padding:8px 14px;text-decoration:none;display:inline-flex}._header_pqrrf_1 nav a[aria-current=page]{background:var(--accent-soft);color:var(--accent);font-weight:650}@media (width<=640px){._header_pqrrf_1{gap:10px;padding:12px 16px}._header_pqrrf_1 nav{order:3;width:100%}._header_pqrrf_1 nav a,._header_pqrrf_1 nav button{padding:8px 10px}}._footer_1op89_1{border-top:1px solid var(--border);color:var(--muted);flex-wrap:wrap;justify-content:space-between;gap:8px;padding:16px 28px;font-size:12px;display:flex}@media (width<=640px){._footer_1op89_1{padding:16px}}._help_1powj_1{background:var(--surface);border:1px solid var(--border);border-radius:12px;margin:16px 28px;padding:20px}:root{color:var(--text);background:var(--canvas);--canvas:#f4f5f7;--surface:#fff;--subtle:#f8f9fb;--text:#14171c;--muted:#535d6b;--border:#d9dde3;--accent:#1b4f9c;--accent-soft:#e8eef7;--success:#225b38;--success-bg:#e8f3ec;--success-border:#9ec4aa;--warning:#6b4700;--warning-bg:#fff4d6;--warning-border:#d9b94f;--danger:#9e302c;--danger-bg:#fcecea;--danger-border:#dea49d;--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light dark;font:14px/1.5 -apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}@media (prefers-color-scheme:dark){:root{--lightningcss-light: ;--lightningcss-dark:initial;--canvas:#15191f;--surface:#1e242d;--subtle:#252c36;--text:#edf0f5;--muted:#b4bfce;--border:#414b5a;--accent:#9dc2ff;--accent-soft:#293c58;--success:#abd7b8;--success-bg:#213b2b;--success-border:#4e7a5d;--warning:#f1d38e;--warning-bg:#3d321e;--warning-border:#8c7237;--danger:#f3b3ad;--danger-bg:#422b2b;--danger-border:#9e625b}}@media (prefers-reduced-motion:reduce){*,:before,:after{scroll-behavior:auto!important;transition:none!important;animation:none!important}}*{box-sizing:border-box}body{margin:0}a{color:var(--accent);text-underline-offset:3px}a:hover{text-decoration:underline}button,input,select,textarea{font:inherit;color:inherit;border:1px solid var(--border);background:var(--surface);border-radius:8px;padding:9px 12px}button,select{min-height:44px}button{cursor:pointer;font-weight:550}button:hover{background:var(--accent-soft);border-color:var(--accent)}button:disabled{cursor:default;opacity:.6}input,select,textarea{max-width:100%}input:not([type=checkbox],[type=radio]),textarea{min-height:44px}textarea{resize:vertical;width:100%;min-height:96px;display:block}:focus-visible{outline:3px solid var(--accent);outline-offset:3px}h1,h2,h3,h4,p,dl,ul,ol{margin-top:0}h2{letter-spacing:-.6px;overflow-wrap:anywhere;margin-bottom:12px;font-size:26px;line-height:1.25}h3{margin-bottom:12px;font-size:16px;font-weight:650}h4{margin-bottom:12px;font-size:14px}p{margin-bottom:14px}section,article{min-width:0}section+section{margin-top:24px}code,pre,kbd{overflow-wrap:anywhere;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}pre{white-space:pre-wrap;background:var(--subtle);border-radius:8px;padding:12px}kbd{border:1px solid var(--border);background:var(--surface);border-bottom-width:2px;border-radius:4px;padding:1px 5px}time{font-variant-numeric:tabular-nums}[role=alert],.coverage-note,[role=note]{border:1px solid var(--warning-border);background:var(--warning-bg);color:var(--warning);overflow-wrap:anywhere;border-radius:8px;padding:12px 16px}[role=status]:not(.conn){color:var(--muted)}.eyebrow{text-transform:uppercase;letter-spacing:.08em;color:var(--muted);font-size:11px;font-weight:650}.section-note,.help{color:var(--muted);font-size:13px}.conn{color:var(--muted);align-items:center;gap:7px;margin:0 0 0 auto;font-size:12px;display:flex}.dot{background:var(--muted);border-radius:50%;flex-shrink:0;width:8px;height:8px}.conn[data-state=live] .dot{background:var(--success)}.conn[data-state=retrying] .dot{background:var(--warning)}.verdict{border:1px solid var(--border);background:var(--surface);border-radius:12px;margin-bottom:24px;padding:22px 24px}.verdict[data-verdict=review]{background:var(--warning-bg);border-color:var(--warning-border)}.verdict[data-verdict=act]{background:var(--danger-bg);border-color:var(--danger-border)}.verdict[data-verdict=quiet]{border-color:var(--success-border)}.verdict-heading{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;margin:8px 0 16px;display:flex}.verdict h2{margin:0;font-size:30px}.verdict-scale{border:1px solid var(--border);background:var(--surface);border-radius:999px;margin:0;padding:0;list-style:none;display:flex;overflow:hidden}.verdict-scale li{text-transform:capitalize;color:var(--muted);padding:6px 16px;font-size:12px}.verdict-scale [aria-current=true]{background:var(--text);color:var(--surface);font-weight:650}.context{color:var(--muted);margin:0;font-size:12px}.reasons{font-size:13px}.review-workspace{grid-template-columns:minmax(0,.8fr) minmax(0,1.2fr);align-items:start;gap:24px;display:grid}.review-list,.detail-pane{scrollbar-gutter:stable;max-height:calc(100dvh - 120px);padding:3px;overflow:auto}.review-list>section{margin-bottom:24px}.attention{gap:8px;margin:0;padding:0;list-style:none;display:grid}.attention-row{background:var(--surface);border:1px solid var(--border);text-align:left;width:100%;color:var(--text);border-radius:10px;align-items:flex-start;gap:12px;padding:16px;font-weight:400;text-decoration:none;display:flex}.attention-row:hover,.host-list a:hover{background:var(--subtle);border-color:var(--accent);text-decoration:none}.attention-row[aria-current=true]{background:var(--accent-soft);border-color:var(--accent);box-shadow:inset 3px 0 var(--accent)}.attention>li>button:not(.attention-row){margin:8px 0}.row-main{overflow-wrap:anywhere;flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.row-main code{color:var(--muted);font-size:11px}.row-meta{color:var(--muted);text-align:right;flex-direction:column;align-items:flex-end;gap:6px;font-size:11px;display:flex}.detail-pane{background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:24px;position:sticky;top:20px}.pane-heading{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;margin-bottom:20px;font-size:12px;display:flex}.pane-heading .eyebrow{margin-right:auto}.empty-detail{text-align:center;max-width:340px;min-height:310px;color:var(--muted);flex-direction:column;justify-content:center;align-items:center;margin:auto;display:flex}.empty-detail h2{color:var(--text);font-size:20px}.empty-mark{border:1px solid var(--border);background:var(--subtle);border-radius:12px;place-items:center;width:48px;height:48px;margin-bottom:20px;font-size:24px;display:grid}.digest{grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin:0;display:grid}.digest>div{border:1px solid var(--border);background:var(--surface);border-radius:10px;padding:14px}.digest dt{color:var(--muted);font-size:12px;font-weight:500}.digest dd{margin:8px 0 0;font-size:26px;font-weight:600}.expected{color:var(--muted);font-size:11px;font-weight:400;display:block}.sources{margin:0;padding:0;list-style:none}.sources>li{background:var(--surface);border:1px solid var(--border);border-radius:10px;flex-wrap:wrap;align-items:center;gap:8px 12px;margin-bottom:8px;padding:14px 16px;font-size:12px;display:flex}.sources>li>span:not(.pill){color:var(--muted)}.host-list{gap:8px;margin:20px 0;padding:0;list-style:none;display:grid}.host-list a{border:1px solid var(--border);background:var(--surface);color:var(--text);border-radius:10px;align-items:center;gap:16px;padding:18px 20px;text-decoration:none;display:flex}.host-list .row-main>span{color:var(--muted);font-size:12px}.host-icon{color:var(--accent);background:var(--accent-soft);border-radius:8px;padding:8px 12px}main>article{max-width:1050px;margin:0 auto}article>section,article>dl,main>section[aria-label=Health]>section{background:var(--surface);border:1px solid var(--border);border-radius:12px;margin-bottom:20px;padding:20px 24px}.detail-pane article>section{border:0;border-bottom:1px solid var(--border);border-radius:0;margin:0 0 16px;padding:0 0 16px}.detail-pane article>section>:last-child{margin-bottom:0}.briefing-heading{justify-content:space-between;align-items:center;gap:12px;margin-bottom:12px;display:flex}.briefing-heading h2{letter-spacing:-.3px;margin:0;font-size:20px}.briefing-description{max-width:75ch;font-size:15px;line-height:1.6}.briefing-meta{color:var(--muted);overflow-wrap:anywhere;flex-wrap:wrap;align-items:baseline;gap:8px 16px;font-size:12px;display:flex}.briefing-meta>span{min-width:0}.briefing-host{color:var(--text)}.briefing .stepper{border:1px solid var(--border);background:var(--subtle);border-radius:8px;grid-template-columns:repeat(3,minmax(0,1fr));gap:0;margin-bottom:10px;display:grid}.briefing .stepper li{color:var(--muted);background:0 0;border:0;border-radius:0;padding:10px 12px}.briefing .stepper li+li{border-left:1px solid var(--border)}.briefing .stepper strong{color:var(--text);margin-top:3px;font-size:14px}.priority-note span{display:block}article h2{font-size:23px}article p,article li{overflow-wrap:anywhere}dl:not(.digest,.health-metrics){grid-template-columns:minmax(110px,.35fr) minmax(0,1fr);gap:10px 20px;display:grid}dt{color:var(--muted);font-size:13px;font-weight:600}dd{overflow-wrap:anywhere;margin:0}details{border:1px solid var(--border);background:var(--surface);border-radius:10px;margin-bottom:10px;padding:0 18px}summary{cursor:pointer;min-height:48px;padding:13px 0;font-weight:600}details>dl{padding:12px 0}details>section{border-top:1px solid var(--border);padding:16px 0}.stepper{flex-wrap:wrap;gap:8px;padding:0;list-style:none;display:flex}.stepper li{background:var(--subtle);border:1px solid var(--border);border-radius:8px;flex:130px;padding:12px;font-size:12px}.stepper strong{font-size:15px;display:block}fieldset{border:1px solid var(--border);border-radius:10px;margin:12px 0;padding:12px 16px}label{margin:10px 0;font-size:13px;display:block}label input:not([type=checkbox],[type=radio]),label select,label textarea{margin-top:4px}@media (width<=1050px){.review-workspace{grid-template-columns:minmax(0,1fr)}.review-list,.detail-pane{max-height:none;overflow:visible}.detail-pane{position:static}}@media (width<=640px){.briefing .stepper{grid-template-columns:minmax(0,1fr)}.briefing .stepper li{justify-content:space-between;align-items:baseline;gap:12px;display:flex}.briefing .stepper li+li{border-left:0;border-top:1px solid var(--border)}h2{font-size:23px}.verdict{padding:18px}.verdict h2{font-size:26px}.digest{grid-template-columns:repeat(2,minmax(0,1fr))}.attention-row,.host-list a{flex-wrap:wrap;gap:10px;padding:14px}.row-meta{text-align:left;flex-direction:row;justify-content:space-between;align-items:center;width:100%}.host-icon{display:none}.detail-pane,article>section,article>dl{padding:16px}dl:not(.digest,.health-metrics){grid-template-columns:minmax(0,1fr);gap:4px}dd{margin-bottom:10px}}.review-workspace[data-empty=true]{grid-template-columns:minmax(0,1fr);max-width:900px;margin:0 auto}.sr-only{clip-path:inset(50%);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.mono{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.dossier{max-width:1400px;margin:0 auto;container-type:inline-size}.dossier-back{margin:0 0 20px}.dossier-back a{text-decoration:none}.dossier-layout{grid-template-columns:minmax(0,1fr) minmax(300px,.48fr);align-items:start;gap:20px 24px;display:grid}.dossier-layout>:not(.dossier-side){grid-column:1;min-width:0}.dossier-card{border:1px solid var(--border);background:var(--surface);overflow-wrap:anywhere;border-radius:16px;margin:0;padding:26px}.dossier-side{border-radius:16px;grid-area:1/2/span 7;max-height:calc(100dvh - 40px);position:sticky;top:20px;overflow:auto}.dossier .briefing-heading{flex-wrap:wrap;align-items:flex-start;margin-bottom:16px}.dossier .briefing-heading h2{letter-spacing:-.7px;flex:260px;font-size:clamp(23px,2.1vw,30px);line-height:1.22}.dossier .briefing-heading .priority{text-transform:uppercase;letter-spacing:.06em;padding:5px 12px;font-weight:700}.dossier .briefing-description{margin-bottom:24px;font-size:16px;line-height:1.65}.dossier .identity-grid{border-top:1px solid var(--border);grid-template-columns:repeat(2,minmax(0,1fr));gap:22px 28px;margin:0;padding-top:22px;display:grid}.identity-grid>div{min-width:0}.identity-grid dt{text-transform:uppercase;letter-spacing:.08em;margin-bottom:7px;font-size:11px}.identity-grid dd{flex-wrap:wrap;align-items:center;gap:6px 10px;margin:0;font-size:15px;font-weight:600;display:flex}.identity-group{grid-column:1/-1}.identity-group p{margin:5px 0 0}.evidence-index{border-top:1px solid var(--border);color:var(--muted);flex-wrap:wrap;justify-content:space-between;align-items:center;gap:4px 12px;margin-top:24px;padding-top:14px;font-size:13px;display:flex}.snapshot-note{border:1px solid var(--accent);color:var(--accent);background:var(--accent-soft);border-radius:12px;gap:12px;padding:15px 18px;display:flex}.snapshot-note p{margin:0}.info-mark{border:1.5px solid;border-radius:50%;flex:none;place-items:center;width:19px;height:19px;margin-top:2px;font-size:12px;font-weight:700;display:inline-grid}.dossier h3{letter-spacing:-.3px;margin-bottom:12px;font-size:18px}.section-heading{align-items:flex-start;gap:12px;display:flex}.section-heading h3{margin-bottom:5px}.section-heading .section-note{margin:0}.spread{flex-wrap:wrap;justify-content:space-between;margin-bottom:12px}.section-icon{background:var(--accent-soft);width:34px;height:34px;color:var(--accent);border-radius:9px;flex:none;place-items:center;font-size:23px;display:grid}.recommended-action{border:1px solid var(--border);border-left:3px solid var(--accent);border-radius:9px;margin:18px 0;padding:16px;font-size:15px;line-height:1.7}.copy-row{flex-wrap:wrap;align-items:center;gap:10px;display:flex}.copy-chip{border:1px solid var(--border);background:var(--subtle);overflow-wrap:anywhere;border-radius:8px;flex-wrap:wrap;align-items:center;gap:8px;min-width:0;padding:5px 8px 5px 10px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;display:inline-flex}.priority-rule{flex-wrap:wrap;align-items:center;gap:10px;margin-bottom:10px;display:flex}.priority-rule code{background:var(--subtle);border:1px solid var(--border);border-radius:6px;padding:4px 8px}.priority-comparison,.context-links{border:0;border-top:1px solid var(--border);border-radius:0;margin:16px 0 0;padding:0}.priority-comparison summary,.context-links summary{color:var(--accent);font-size:13px}.hypothesis,.context-text{line-height:1.7}.context-limit{border:1px solid var(--warning-border);background:var(--warning-bg);color:var(--warning);border-radius:9px;padding:12px 14px;font-size:13px}.lookup-receipts{margin:0;padding:0;list-style:none}.lookup-receipts li{border-top:1px solid var(--border);align-items:flex-start;gap:12px;padding:12px 0;display:flex}.receipt-steps{flex-wrap:wrap;gap:4px 16px;display:flex}.lookup-receipts p{margin:0;font-size:13px}.receipt-mark{color:var(--muted);font-weight:700}.text-link{color:var(--accent);text-align:left;background:0 0;border:0;min-height:36px;padding:6px 0;font-size:13px}.text-link:hover{background:0 0;text-decoration:underline}.citation-row{flex-wrap:wrap;align-items:center;gap:8px;margin-top:16px;display:flex}.citation{color:var(--accent);background:var(--accent-soft);min-height:32px;padding:4px 9px;font-size:12px}.tech-block{padding:0 24px}.tech-block>summary{padding:20px 0;font-size:15px}.tech-block>summary span{margin-left:10px;font-weight:400}.tech-body{border-top:1px solid var(--border);padding:18px 0 8px}.trace-list{margin:0 0 20px;padding:0}[data-layout=embedded] .dossier-layout{flex-direction:column;gap:16px;display:flex}[data-layout=embedded] .dossier-layout>*{width:100%}[data-layout=embedded] .dossier-side{order:1;max-height:none;position:static;overflow:visible}[data-layout=embedded] .recommended-card{order:0}[data-layout=embedded] .dossier-card:not(.briefing-summary,.recommended-card),[data-layout=embedded] .tech-block{order:2}[data-layout=embedded] .dossier-card{padding:20px}@container (width<=840px){.dossier-layout{flex-direction:column;display:flex}.dossier-layout>*{width:100%}.dossier-side{order:1;max-height:none;position:static;overflow:visible}.dossier-card:not(.briefing-summary,.recommended-card),.tech-block{order:2}}@container (width<=500px){.dossier .identity-grid{grid-template-columns:minmax(0,1fr);gap:18px}.dossier-card{padding:20px}.tech-block{padding:0 20px}}.shell-main{max-width:1500px;min-height:calc(100dvh - 160px);margin:0 auto;padding:28px}.shell-main:focus{outline:none}@media (width<=640px){.shell-main{padding:16px}} diff --git a/internal/viewer/web/dist/assets/index.js b/internal/viewer/web/dist/assets/index.js index e06d0d5..85a339c 100644 --- a/internal/viewer/web/dist/assets/index.js +++ b/internal/viewer/web/dist/assets/index.js @@ -1,6 +1,6 @@ -(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var e=Array.isArray,t=Array.prototype.indexOf,n=Array.prototype.includes,r=Array.from,i=Object.defineProperty,a=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyDescriptors,s=Object.prototype,c=Array.prototype,l=Object.getPrototypeOf,u=Object.isExtensible,d=()=>{};function f(e){for(var t=0;t{e=n,t=r}),resolve:e,reject:t}}function m(e,t){if(Array.isArray(e))return e;if(t===void 0||!(Symbol.iterator in e))return Array.from(e);let n=[];for(let r of e)if(n.push(r),n.length===t)break;return n}var h=1024,g=2048,_=4096,v=8192,y=16384,b=32768,x=1<<25,S=65536,C=1<<19,w=1<<20,T=1<<25,ee=1<<21,te=1<<22,E=1<<23,D=Symbol(`$state`),ne=Symbol(`component`),re=Symbol(`legacy props`),ie=Symbol(``),O=Symbol(`attributes`),ae=Symbol(`class`),oe=Symbol(`style`),se=Symbol(`text`),ce=Symbol(`form reset`),le=new class extends Error{name=`StaleReactionError`;message="The reaction that called `getAbortSignal()` was re-run or destroyed"},ue=!!globalThis.document?.contentType&&globalThis.document.contentType.includes(`xml`),de={},k=Symbol(`uninitialized`),fe=`http://www.w3.org/1999/xhtml`;function pe(){console.warn(`https://svelte.dev/e/derived_inert`)}function me(e){console.warn(`https://svelte.dev/e/hydration_mismatch`)}function he(){console.warn(`https://svelte.dev/e/svelte_boundary_reset_noop`)}var A=!1;function ge(e){A=e}var j;function _e(e){if(e===null)throw me(),de;return j=e}function ve(){return _e(Zt(j))}function M(e){if(A){if(Zt(j)!==null)throw me(),de;j=e}}function ye(e=1){if(A){for(var t=e,n=j;t--;)n=Zt(n);j=n}}function be(e=!0){for(var t=0,n=j;;){if(n.nodeType===8){var r=n.data;if(r===`]`){if(t===0)return n;--t}else(r===`[`||r===`[!`||r[0]===`[`&&!isNaN(Number(r.slice(1))))&&(t+=1)}var i=Zt(n);e&&n.remove(),n=i}}function xe(e){if(!e||e.nodeType!==8)throw me(),de;return e.data}function Se(e){return e===this.v}function Ce(e,t){return e==e?e!==t||typeof e==`object`&&!!e||typeof e==`function`:t==t}function we(e){return!Ce(e,this.v)}function Te(e){throw Error(`https://svelte.dev/e/lifecycle_outside_component`)}function Ee(){throw Error(`https://svelte.dev/e/async_derived_orphan`)}function De(e,t,n){throw Error(`https://svelte.dev/e/each_key_duplicate`)}function Oe(e){throw Error(`https://svelte.dev/e/effect_in_teardown`)}function ke(){throw Error(`https://svelte.dev/e/effect_in_unowned_derived`)}function Ae(e){throw Error(`https://svelte.dev/e/effect_orphan`)}function je(){throw Error(`https://svelte.dev/e/effect_update_depth_exceeded`)}function Me(e){throw Error(`https://svelte.dev/e/props_invalid_value`)}function Ne(){throw Error(`https://svelte.dev/e/state_descriptors_fixed`)}function Pe(){throw Error(`https://svelte.dev/e/state_prototype_fixed`)}function Fe(){throw Error(`https://svelte.dev/e/state_unsafe_mutation`)}function Ie(){throw Error(`https://svelte.dev/e/svelte_boundary_reset_onerror`)}var Le=null;function Re(e){Le=e}function ze(e,t=!1,n){Le={p:Le,i:!1,c:null,e:null,s:e,x:null,r:W,l:null}}function Be(e){var t=Le,n=t.e;if(n!==null){t.e=null;for(var r of n)dn(r)}return e!==void 0&&(t.x=e),t.i=!0,Le=t.p,Ve(e)}function Ve(e={}){return i(e,ne,{value:!0}),e}function He(){return!0}var Ue=[];function We(){var e=Ue;Ue=[],f(e)}function Ge(e){if(Ue.length===0&&!vt){var t=Ue;queueMicrotask(()=>{t===Ue&&We()})}Ue.push(e)}function Ke(){for(;Ue.length>0;)We()}var qe=~(g|_|h);function N(e,t){e.f=e.f&qe|t}function Je(e){e.f&512||e.deps===null?N(e,h):N(e,_)}function Ye(e,t){e.f&2048?t.set(e,g):e.f&4096&&t.get(e)!==2048&&t.set(e,_),N(e,h)}function Xe(e){A&&Xt(e)!==null&&Qt(e)}var Ze=!1;function Qe(){Ze||(Ze=!0,document.addEventListener(`reset`,e=>{Promise.resolve().then(()=>{if(!e.defaultPrevented)for(let t of e.target.elements)t[ce]?.()})},{capture:!0}))}function $e(e){var t=U,n=W;Nn(null),Pn(null);try{return e()}finally{Nn(t),Pn(n)}}function et(e,t,n,r=n){e.addEventListener(t,()=>$e(n));let i=e[ce];e[ce]=i?()=>{i(),r(!0)}:()=>r(!0),Qe()}function tt(e,t,n,r){let i=He()?at:ct;var a=e.filter(e=>!e.settled),o=t.map(i);if(n.length===0&&a.length===0){r(o);return}var s=W,c=nt(),l=a.length===1?a[0].promise:a.length>1?Promise.all(a.map(e=>e.promise)):null;function u(e){if(!(s.f&16384)){c();try{r([...o,...e])}catch(e){rn(e,s)}rt()}}var d=it();if(n.length===0){l.then(()=>u([])).finally(d);return}function f(){Promise.all(n.map(e=>st(e))).then(u).catch(e=>rn(e,s)).finally(d)}l?l.then(()=>{s.f&16384?d():(c(),f(),rt())}):f()}function nt(){var e=W,t=U,n=Le,r=F;return function(i=!0){Pn(e),Nn(t),Re(n),i&&!(e.f&16384)&&(r?.activate(),r?.apply())}}function rt(e=!0){Pn(null),Nn(null),Re(null),e&&F?.deactivate()}function it(){var e=W,t=e.b,n=F,r=!!t?.is_rendered();return t?.update_pending_count(1,n),n.increment(r,e),()=>{t?.update_pending_count(-1,n),n.decrement(r,e)}}function at(e){var t=2|g;return W!==null&&(W.f|=C),{ctx:Le,deps:null,effects:null,equals:Se,f:t,fn:e,reactions:null,rv:0,v:k,wv:0,parent:W,ac:null}}var ot=Symbol(`obsolete`);function st(e,t,n){let r=W;r===null&&Ee();var i=void 0,a=Ft(k),o=!U,s=new Set;return mn(()=>{var t=W,n=p();i=n.promise;try{Promise.resolve(e()).then(n.resolve,e=>{e!==le&&n.reject(e)}).finally(rt)}catch(e){n.reject(e),rt()}var c=F;if(o){if(t.f&32768)var l=it();if(r.b?.is_rendered())c.async_deriveds.get(t)?.reject(ot);else for(let e of s.values())e.reject(ot);s.add(n),c.async_deriveds.set(t,n)}let u=(e,t=void 0)=>{l?.(),s.delete(n),t!==ot&&(c.activate(),t?(a.f|=E,zt(a,t)):(a.f&8388608&&(a.f^=E),zt(a,e)),c.deactivate())};n.promise.then(u,e=>u(null,e||`unknown`))}),ln(()=>{for(let e of s)e.reject(ot)}),new Promise(e=>{function t(n){function r(){n===i?e(a):t(i)}n.then(r,r)}t(i)})}function P(e){let t=at(e);return In(t),t}function ct(e){let t=at(e);return t.equals=we,t}function lt(e){var t=e.effects;if(t!==null){e.effects=null;for(var n=0;n{t.ac.abort(le),t.ac=null}),t.fn!==null&&(t.teardown=d),Zn(t,0),yn(t))}function pt(e){if(e.effects!==null)for(let t of e.effects)t.teardown&&t.fn!==null&&Qn(t)}var mt=null,F=null,ht=null,gt=null,_t=null,vt=!1,yt=!1,bt=null,xt=null,St=0,Ct=1,wt=class e{id=Ct++;started=!1;linked=!0;prev=null;next=null;async_deriveds=new Map;current=new Map;previous=new Map;#e=new Set;#t=new Set;#n=0;#r=new Map;#i=null;#a=[];#o=[];#s=new Map;#c=new Map;#l=new Set;is_fork=!1;#u=!1;constructor(){mt===null?mt=this:(mt.next=this,this.prev=mt),mt=this}#d(){if(this.is_fork)return!0;for(let e of this.#r.keys())if(!this.#f(e))return!0;return!1}#f(e){for(var t=e;t!==null;t=t.parent)if(this.#c.has(t))return!0;return!1}skip_effect(e){this.#c.has(e)||this.#c.set(e,{d:[],m:[]}),this.#l.delete(e)}unskip_effect(e,t=e=>this.schedule(e)){var n=this.#c.get(e);if(n){this.#c.delete(e);for(var r of n.d)N(r,g),t(r);for(r of n.m)N(r,_),t(r)}this.#l.add(e)}#p(){var e=[];for(let i of this.#a)if(!(i.f&16384||!(i.f&6144))){for(var t=i,n=!1;t.parent!==null;){t=t.parent;var r=t.f;if(r&96){if(!(r&1024)){n=!0;break}t.f^=h}}n||e.push(t)}return this.#a=[],e}#m(){this.started=!0;for(let[e,t]of this.#s)N(e,t),this.schedule(e);this.apply();for(var t=bt=[],n=[],r=xt=[];this.#a.length>0;){St++>1e3&&(this.#b(),Et());for(let e of this.#p())try{this.#h(e,t,n)}catch(t){throw jt(e),this.#d()||this.discard(),t}}if(F=null,r.length>0){var i=e.ensure();for(let e of r)i.schedule(e)}if(bt=null,xt=null,this.#d()){this.#y(n),this.#y(t);for(let[e,t]of this.#c)At(e,t);r.length>0&&F.#m();return}let a=this.#g();if(a)this.#y(n),this.#y(t),a.#v(this);else{this.#s.clear();for(let e of this.#e)e(this);this.#e.clear(),ht=this,Ot(n),Ot(t),ht=null,this.#i?.resolve();var o=F;this.#n===0&&(this.#a.length===0||o!==null)&&this.#b(),o!==null&&(Nt.clear(),o.#m())}}#h(e,t,n){e.f^=h;for(var r=e.first;r!==null;){var i=r.f,a=!!(i&96);if(!(a&&i&1024||i&8192||this.#c.has(r))&&r.fn!==null){a?r.f^=h:i&4?t.push(r):Kn(r)&&(i&16&&this.add_dirty_reaction(r,_),Qn(r));var o=r.first;if(o!==null){r=o;continue}}for(;r!==null;){var s=r.next;if(s!==null){r=s;break}r=r.parent}}}#g(){for(var e=this.prev;e!==null;e=e.prev)if(!e.is_fork&&this.#_(e))return e;return null}#_(e){for(let[t,[,n]]of this.current)if(!n&&e.current.has(t))return!0;return!1}#v(e){for(let[t,n]of e.current)!this.previous.has(t)&&e.previous.has(t)&&this.previous.set(t,e.previous.get(t)),this.current.set(t,n);for(let[t,n]of e.async_deriveds){let e=this.async_deriveds.get(t);e&&n.promise.then(e.resolve).catch(e.reject)}e.async_deriveds.clear(),this.transfer_reactions(e.#s);let t=e=>{var n=e.reactions;if(n!==null&&!(e.f&2&&!(e.f&6144)))for(let e of n){var r=e.f;if(r&2)t(e);else{var i=e;r&4194320&&!this.async_deriveds.has(i)&&(this.#s.delete(i),N(i,g),this.schedule(i))}}};for(let e of this.current.keys())t(e);this.oncommit(()=>e.discard()),e.#b(),F=this,this.#m()}#y(e){for(var t=0;t{this.#u=!1,this.linked&&this.flush()}))}transfer_reactions(e){for(let[t,n]of e)this.add_dirty_reaction(t,n);e.clear()}add_dirty_reaction(e,t){(t===2048||this.#s.get(e)!==2048)&&this.#s.set(e,t)}oncommit(e){this.#e.add(e)}ondiscard(e){this.#t.add(e)}settled(){return(this.#i??=p()).promise}static ensure(){if(F===null){let t=F=new e;!yt&&!vt&&Ge(()=>{t.started||t.flush()})}return F}apply(){gt=null}schedule(e){_t=e,e.b?.is_pending&&e.f&16777228&&!(e.f&32768)?e.b.defer_effect(e):this.#a.push(e)}#b(){if(this.linked){var e=this.prev,t=this.next;e===null||(e.next=t),t===null?mt=e:t.prev=e,this.linked=!1}}};function Tt(e){var t=vt,n=ht;ht=null,vt=!0;try{var r;for(e&&(Tt(),r=e());;){if(Ke(),F===null)return r;F.flush()}}finally{vt=t,ht=n}}function Et(){try{je()}catch(e){rn(e,_t)}}var Dt=null;function Ot(e){var t=e.length;if(t!==0){for(var n=0;n0)){Nt.clear();for(let e of Dt){if(e.f&24576)continue;let t=[e],n=e.parent;for(;n!==null;)Dt.has(n)&&(Dt.delete(n),t.push(n)),n=n.parent;for(let e=t.length-1;e>=0;e--){let n=t[e];n.f&24576||Qn(n)}}Dt.clear()}}Dt=null}}function kt(e){F.schedule(e)}function At(e,t){if(!(e.f&32&&e.f&1024)){e.f&2048?t.d.push(e):e.f&4096&&t.m.push(e),N(e,h);for(var n=e.first;n!==null;)At(n,t),n=n.next}}function jt(e){N(e,h);for(var t=e.first;t!==null;)jt(t),t=t.next}var Mt=new Set,Nt=new Map,Pt=!1;function Ft(e,t){return{f:0,v:e,reactions:null,equals:Se,rv:0,wv:0}}function I(e,t){let n=Ft(e,t);return In(n),n}function It(e,t=!1,n=!0){let r=Ft(e);return t||(r.equals=we),r}function L(e,t,n=!1){return U!==null&&(!Mn||U.f&131072)&&He()&&U.f&4325394&&(Fn===null||!Fn.has(e))&&Fe(),zt(e,n?Ut(t):t,xt)}var Lt=null,Rt=0;function zt(e,t,n=null){if(!e.equals(t)){An?Nt.set(e,t):Nt.has(e)||Nt.set(e,e.v);var r=wt.ensure();if(r.capture(e,t),e.f&2){let t=e;e.f&2048&&ut(t),gt===null&&Je(t)}e.wv=Gn(),Lt=null,Rt=0,Ht(e,g,n),Lt=null,He()&&W!==null&&W.f&1024&&!(W.f&96)&&(zn===null?Bn([e]):zn.push(e)),!r.is_fork&&Mt.size>0&&!Pt&&Bt()}return t}function Bt(){Pt=!1;for(let e of Mt){e.f&1024&&N(e,_);let t;try{t=Kn(e)}catch{t=!0}t&&Qn(e)}Mt.clear()}function Vt(e){L(e,e.v+1)}function Ht(e,t,n){var r=e.reactions;if(r!==null){var i=He(),a=r.length;if(Rt+=a,Rt>1e5&&Lt===null&&(Lt=new Set),Lt!==null){if(Lt.has(e))return;Lt.add(e)}for(var o=0;o{if(Un===d)return e();var t=U,n=Un;Nn(null),Wn(d);var r=e();return Nn(t),Wn(n),r};return i&&r.set(`length`,I(t.length,u)),new Proxy(t,{defineProperty(e,t,n){`value`in n&&n.configurable!==!1&&n.enumerable!==!1&&n.writable!==!1||Ne();var i=r.get(t);return i===void 0?f(()=>{var e=I(n.value,u);return r.set(t,e),e}):L(i,n.value,!0),!0},deleteProperty(e,t){var n=r.get(t);if(n===void 0){if(t in e){let e=f(()=>I(k,u));r.set(t,e),Vt(o)}}else L(n,k),Vt(o);return!0},get(e,n,i){if(n===D)return t;var o=r.get(n),s=n in e;if(o===void 0&&(!s||a(e,n)?.writable)&&(o=f(()=>I(Ut(s?e[n]:k),u)),r.set(n,o)),o!==void 0){var c=G(o);return c===k?void 0:c}return Reflect.get(e,n,i)},getOwnPropertyDescriptor(e,t){this.has?.(e,t);var n=Reflect.getOwnPropertyDescriptor(e,t),i=r.get(t);if(i!==void 0){var a=G(i);if(a===k)return;if(n&&`value`in n)n.value=a;else return{enumerable:!0,configurable:!0,value:a,writable:!0}}return n},has(e,t){if(t===D)return!0;var n=r.get(t),i=n!==void 0&&n.v!==k||Reflect.has(e,t);return(n!==void 0||(W!==null||U!==null)&&(!i||a(e,t)?.writable))&&(n===void 0&&(n=f(()=>I(i?Ut(e[t]):k,u)),r.set(t,n)),G(n)===k)?!1:i},set(e,t,n,s){var c=r.get(t),l=t in e;if(i&&t===`length`)for(var d=n;dI(k,u)),r.set(d+``,p)):L(p,k)}if(c===void 0)(!l||a(e,t)?.writable)&&(c=f(()=>I(void 0,u)),L(c,Ut(n)),r.set(t,c));else{l=c.v!==k;var m=f(()=>Ut(n));L(c,m)}var h=Reflect.getOwnPropertyDescriptor(e,t);if(h?.set&&h.set.call(s,n),!l){if(i&&typeof t==`string`){var g=r.get(`length`),_=Number(t);Number.isInteger(_)&&_>=g.v&&L(g,_+1)}Vt(o)}return!0},ownKeys(e){G(o);var t=Reflect.ownKeys(e).filter(e=>{var t=r.get(e);return t===void 0||t.v!==k});for(var[n,i]of r)i.v!==k&&!(n in e)&&t.push(n);return t},setPrototypeOf(){Pe()}})}var Wt,Gt,Kt,qt;function Jt(){if(Wt===void 0){Wt=window,Gt=/Firefox/.test(navigator.userAgent);var e=Element.prototype,t=Node.prototype,n=Text.prototype;Kt=a(t,`firstChild`).get,qt=a(t,`nextSibling`).get,u(e)&&(e[ae]=void 0,e[O]=null,e[oe]=void 0,e.__e=void 0),u(n)&&(n[se]=void 0)}}function Yt(e=``){return document.createTextNode(e)}function Xt(e){return Kt.call(e)}function Zt(e){return qt.call(e)}function R(e,t){if(!A)return Xt(e);var n=Xt(j);if(n===null)n=j.appendChild(Yt());else if(t&&n.nodeType!==3){var r=Yt();return n?.before(r),_e(r),r}return t&&tn(n),_e(n),n}function z(e,t=!1){if(!A){var n=Xt(e);return n instanceof Comment&&n.data===``?Zt(n):n}if(t){if(j?.nodeType!==3){var r=Yt();return j?.before(r),_e(r),r}tn(j)}return j}function B(e,t=!1){if(!A)return Xt(e);var n=R(e,t);return M(e),n}function V(e,t=1,n=!1){let r=A?j:e;for(var i;t--;)i=r,r=Zt(r);if(!A)return r;if(n){if(r?.nodeType!==3){var a=Yt();return r===null?i?.after(a):r.before(a),_e(a),a}tn(r)}return _e(r),r}function Qt(e){e.textContent=``}function $t(){return!1}function en(e,t,n){return t==null||t===`http://www.w3.org/1999/xhtml`?n?document.createElement(e,{is:n}):document.createElement(e):n?document.createElementNS(t,e,{is:n}):document.createElementNS(t,e)}function tn(e){if(e.nodeValue.length<65536)return;let t=e.nextSibling;for(;t!==null&&t.nodeType===3;)t.remove(),e.nodeValue+=t.nodeValue,t=e.nextSibling}function nn(e){var t=W;if(t===null)return U.f|=E,e;if(!(t.f&32768)&&!(t.f&4))throw e;rn(e,t)}function rn(e,t){if(e===de)throw e;if(!(t!==null&&t.f&16384)){for(;t!==null;){if(t.f&128&&!(t.f&33570816)){if(!(t.f&32768))throw e;try{t.b.error(e);return}catch(t){e=t}}t=t.parent}throw e}}function an(e){W===null&&(U===null&&Ae(e),ke()),An&&Oe(e)}function on(e,t){var n=t.last;n===null?t.last=t.first=e:(n.next=e,e.prev=n,t.last=e)}function sn(e,t){var n=W;n!==null&&n.f&8192&&(e|=v);var r={ctx:Le,deps:null,nodes:null,f:e|g|512,first:null,fn:t,last:null,next:null,parent:n,b:n&&n.b,prev:null,teardown:null,wv:0,ac:null};F?.register_created_effect(r);var i=r;if(e&4)bt===null?wt.ensure().schedule(r):bt.push(r);else if(t!==null){try{Qn(r)}catch(e){throw xn(r),e}i.deps===null&&i.teardown===null&&i.nodes===null&&i.first===i.last&&!(i.f&524288)&&(i=i.first,e&16&&e&65536&&i!==null&&(i.f|=S))}if(i!==null&&(i.parent=n,n!==null&&on(i,n),U!==null&&U.f&2&&!(e&64))){var a=U;(a.effects??=[]).push(i)}return r}function cn(){return U!==null&&!Mn}function ln(e){let t=sn(8,null);return N(t,h),t.teardown=e,t}function un(e){an(`$effect`);var t=W.f;if(!U&&t&32&&Le!==null&&!Le.i){var n=Le;(n.e??=[]).push(e)}else return dn(e)}function dn(e){return sn(4|w,e)}function fn(e){wt.ensure();let t=sn(64|C,e);return(e={})=>new Promise(n=>{e.outro?wn(t,()=>{xn(t),n(void 0)}):(xn(t),n(void 0))})}function pn(e){return sn(4,e)}function mn(e){return sn(te|C,e)}function hn(e,t=0){return sn(8|t,e)}function H(e,t=[],n=[],r=[]){tt(r,t,n,t=>{sn(8,()=>{e(...t.map(G))})})}function gn(e,t=0){return sn(16|t,e)}function _n(e){return sn(32|C,e)}function vn(e){var t=e.teardown;if(t!==null){let n=An,r=U;jn(!0),Nn(null);try{t.call(null)}catch(t){rn(t,e.parent)}finally{jn(n),Nn(r)}}}function yn(e,t=!1){var n=e.first;for(e.first=e.last=null;n!==null;){let e=n.ac;e!==null&&$e(()=>{e.abort(le)});var r=n.next;n.f&64?n.parent=null:xn(n,t),n=r}}function bn(e){for(var t=e.first;t!==null;){var n=t.next;t.f&32||xn(t),t=n}}function xn(e,t=!0){var n=!1;(t||e.f&262144)&&e.nodes!==null&&e.nodes.end!==null&&(Sn(e.nodes.start,e.nodes.end),n=!0),e.f|=x,yn(e,t&&!n),Zn(e,0);var r=e.nodes&&e.nodes.t;if(r!==null)for(let e of r)e.stop();vn(e),e.f^=x,e.f|=y;var i=e.parent;i!==null&&i.first!==null&&Cn(e),e.next=e.prev=e.teardown=e.ctx=e.deps=e.fn=e.nodes=e.ac=e.b=null}function Sn(e,t){for(;e!==null;){var n=e===t?null:Zt(e);e.remove(),e=n}}function Cn(e){var t=e.parent,n=e.prev,r=e.next;n!==null&&(n.next=r),r!==null&&(r.prev=n),t!==null&&(t.first===e&&(t.first=r),t.last===e&&(t.last=n))}function wn(e,t,n=!0){var r=[];e.f|=256,Tn(e,r,!0);var i=()=>{n&&xn(e),t&&t()},a=r.length;if(a>0){var o=()=>--a||i();for(var s of r)s.out(o)}else i()}function Tn(e,t,n){if(!(e.f&8192)){e.f^=v;var r=e.nodes&&e.nodes.t;if(r!==null)for(let e of r)(e.is_global||n)&&t.push(e);for(var i=e.first;i!==null;){var a=i.next;if(!(i.f&64)){var o=!!(i.f&65536)||!!(i.f&32)&&!!(e.f&16);Tn(i,t,o?n:!1)}i=a}}}function En(e){e.f&=-257,Dn(e,!0)}function Dn(e,t){if(!(e.f&256)&&e.f&8192){e.f^=v,e.f&1024||(N(e,g),wt.ensure().schedule(e));for(var n=e.first;n!==null;){var r=n.next,i=!!(n.f&65536)||!!(n.f&32);Dn(n,i?t:!1),n=r}var a=e.nodes&&e.nodes.t;if(a!==null)for(let e of a)(e.is_global||t)&&e.in()}}function On(e,t){if(e.nodes)for(var n=e.nodes.start,r=e.nodes.end;n!==null;){var i=n===r?null:Zt(n);t.append(n),n=i}}var kn=null,An=!1;function jn(e){An=e}var U=null,Mn=!1;function Nn(e){U=e}var W=null;function Pn(e){W=e}var Fn=null;function In(e){U!==null&&(U.f&2097152||U.f&2)&&(Fn??=new Set).add(e)}var Ln=null,Rn=0,zn=null;function Bn(e){zn=e}var Vn=1,Hn=0,Un=Hn;function Wn(e){Un=e}function Gn(){return++Vn}function Kn(e){var t=e.f;if(t&2048)return!0;if(t&4096){for(var n=e.deps,r=n.length,i=0;ie.wv)return!0}t&512&>===null&&N(e,h)}return!1}function qn(e,t,n=!0){var r=e.reactions;if(r!==null&&!(Fn!==null&&Fn.has(e)))for(var i=0;i{e.ac.abort(le)}),e.ac=null);try{e.f|=ee;var u=e.fn,d=u();e.f|=b;var f=Yn(e);if(He()&&zn!==null&&!Mn&&f!==null&&!(e.f&6146))for(var p=0;p0)for(t.length=Rn+Ln.length,r=0;r{s.ac.abort(le),s.ac=null,N(s,g)}),ft(s),Zn(s,0)}}function Zn(e,t){var n=e.deps;if(n!==null)for(var r=t;rn?.call(this,e))}return e.startsWith(`pointer`)||e.startsWith(`touch`)||e===`wheel`?(i.__removed=!1,Ge(()=>{i.__removed||t.addEventListener(e,i,r)})):t.addEventListener(e,i,r),i}function lr(e,t,n,r,i){var a={capture:r,passive:i},o=cr(e,t,n,a);(t===document.body||t===window||t===document||t instanceof HTMLMediaElement)&&ln(()=>{o.__removed=!0,t.removeEventListener(e,o,a)})}function K(e,t,n){(t[ar]??={})[e]=n}function ur(e){for(var t=0;t{fr=!1,dr=null}));var s=0,c=dr===e&&e[ar];if(c){var l=a.indexOf(c);if(l!==-1&&(t===document||t===window)){e[ar]=t;return}var u=a.indexOf(t);if(u===-1)return;l<=u&&(s=l)}if(o=a[s]||e.target,o!==t){i(e,`currentTarget`,{configurable:!0,get(){return o||n}});var d=U,f=W;Nn(null),Pn(null);try{for(var p,m=[];o!==null&&o!==t;){try{var h=o[ar]?.[r];h==null||o.disabled&&e.target!==o||h.call(o,e)}catch(e){p?m.push(e):p=e}if(e.cancelBubble)break;s++,o=s{throw e});throw p}}finally{e[ar]=t,delete e.currentTarget,Nn(d),Pn(f)}}}var mr=globalThis?.window?.trustedTypes&&globalThis.window.trustedTypes.createPolicy(`svelte-trusted-html`,{createHTML:e=>e});function hr(e){return mr?.createHTML(e)??e}function gr(e){var t=en(`template`);return t.innerHTML=hr(e.replaceAll(``,``)),t.content}function _r(e,t){var n=W;n.nodes===null&&(n.nodes={start:e,end:t,a:null,t:null})}function q(e,t){var n=!!(t&1),r=!!(t&2),i,a=!e.startsWith(``);return()=>{if(A)return _r(j,null),j;i===void 0&&(i=gr(a?e:``+e),n||(i=Xt(i)));var t=r||Gt?document.importNode(i,!0):i.cloneNode(!0);if(n){var o=Xt(t),s=t.lastChild;_r(o,s)}else _r(t,t);return t}}function vr(e=``){if(!A){var t=Yt(e+``);return _r(t,t),t}var n=j;return n.nodeType===3?tn(n):(n.before(n=Yt()),_e(n)),_r(n,n),n}function yr(){if(A)return _r(j,null),j;var e=document.createDocumentFragment(),t=document.createComment(``),n=Yt();return e.append(t,n),_r(t,n),e}function J(e,t){if(A){var n=W;n.f&32768&&n.nodes.end!==null||(n.nodes.end=j),ve()}else e!==null&&e.before(t)}function br(e){let t=0,n=Ft(0),r;return()=>{cn()&&(G(n),hn(()=>(t===0&&(r=nr(()=>e(()=>Vt(n)))),t+=1,()=>{Ge(()=>{--t,t===0&&(r?.(),r=void 0,Vt(n))})})))}}var xr=S|C;function Sr(e,t,n,r){new Cr(e,t,n,r)}var Cr=class{parent;is_pending=!1;transform_error;#e;#t=A?j:null;#n;#r;#i;#a=null;#o=null;#s=null;#c=null;#l=0;#u=0;#d=!1;#f=new Map;#p=null;#m=br(()=>(this.#p=Ft(this.#l),()=>{this.#p=null}));constructor(e,t,n,r){this.#e=e,this.#n=t,this.#r=e=>{var t=W;t.b=this,t.f|=128,n(e)},this.parent=W.b,this.transform_error=r??this.parent?.transform_error??(e=>e),this.#i=gn(()=>{if(A){let e=xe(this.#t);ve();let t=e===`[!`;if(e.startsWith(`[?`)){let t=JSON.parse(e.slice(2));this.#g(t)}else t?this.#y():this.#h()}else this.#b()},xr),A&&(this.#e=j)}#h(){try{this.#a=_n(()=>this.#r(this.#e))}catch(e){this.error(e)}}#g(e){let t=this.#n.failed,{reset:n,invoke_onerror:r}=this.#_(e);Ge(r),t&&(this.#s=_n(()=>{t(this.#e,()=>e,()=>n)}))}#_(e){var t=!1,n=!1;let r=()=>{this.#v()||(t?he():(t=!0,n&&Ie(),this.#s!==null&&wn(this.#s,()=>{this.#s=null}),this.#S(()=>{this.#b()})))};return{reset:r,invoke_onerror:()=>{if(!this.#v())try{n=!0,this.#n.onerror?.(e,r),n=!1}catch(e){rn(e,this.#i&&this.#i.parent)}}}}#v(){return(this.#i.f&(y|x))!==0}#y(){let e=this.#n.pending;e&&(this.is_pending=!0,this.#o=_n(()=>e(this.#e)),Ge(()=>{if(!this.#v()){var e=this.#c=document.createDocumentFragment(),t=Yt(),n=!1;e.append(t),this.#a=this.#S(()=>{try{return _n(()=>this.#r(t))}catch(e){try{this.error(e),n=!0}catch(e){rn(e,this.#i.parent)}return null}}),this.#a===null?(this.#c=null,n&&this.#x(F)):this.#u===0&&(this.#e.before(e),this.#c=null,wn(this.#o,()=>{this.#o=null}),this.#x(F))}}))}#b(){try{if(this.is_pending=this.has_pending_snippet(),this.#u=0,this.#l=0,this.#a=_n(()=>{this.#r(this.#e)}),this.#u>0){var e=this.#c=document.createDocumentFragment();On(this.#a,e);let t=this.#n.pending;this.#o=_n(()=>t(this.#e))}else this.#x(F)}catch(e){this.error(e)}}#x(e){this.is_pending=!1,e.transfer_reactions(this.#f)}defer_effect(e){Ye(e,this.#f)}is_rendered(){return!this.is_pending&&(!this.parent||this.parent.is_rendered())}has_pending_snippet(){return!!this.#n.pending}#S(e){var t=W,n=U,r=Le;Pn(this.#i),Nn(this.#i),Re(this.#i.ctx);try{return wt.ensure(),e()}finally{Pn(t),Nn(n),Re(r)}}#C(e,t){this.has_pending_snippet()?(this.#u+=e,this.#u===0&&(this.#x(t),this.#o&&wn(this.#o,()=>{this.#o=null}),this.#c&&=(this.#e.before(this.#c),null))):this.parent&&this.parent.#C(e,t)}update_pending_count(e,t){this.#C(e,t),this.#l+=e,!this.#p||this.#d||(this.#d=!0,Ge(()=>{this.#d=!1,this.#p&&zt(this.#p,this.#l)}))}get_effect_pending(){return this.#m(),G(this.#p)}error(e){if(e===de||!this.#n.onerror&&!this.#n.failed)throw e;F?.is_fork?(this.#a&&F.skip_effect(this.#a),this.#o&&F.skip_effect(this.#o),this.#s&&F.skip_effect(this.#s),F.oncommit(()=>{this.#v()||this.#w(e)})):this.#w(e)}#w(e){this.#a&&=(xn(this.#a),null),this.#o&&=(xn(this.#o),null),this.#s&&=(xn(this.#s),null),A&&(_e(this.#t),ye(),_e(be()));let t=this.#n.failed,n=e=>{if(this.#v())return;let{reset:n,invoke_onerror:r}=this.#_(e);r(),t&&!this.#v()&&(this.#s=this.#S(()=>{try{return _n(()=>{var r=W;r.b=this,r.f|=128,t(this.#e,()=>e,()=>n)})}catch(e){return rn(e,this.#i.parent),null}}))};Ge(()=>{if(!this.#v()){var t;try{t=this.transform_error(e)}catch(e){rn(e,this.#i&&this.#i.parent);return}typeof t==`object`&&t&&typeof t.then==`function`?t.then(n,e=>rn(e,this.#i&&this.#i.parent)):n(t)}})}};function Y(e,t){var n=t==null?``:typeof t==`object`?`${t}`:t;n!==(e[se]??=e.nodeValue)&&(e[se]=n,e.nodeValue=`${n}`)}function wr(e,t){return Er(e,t)}var Tr=new Map;function Er(e,{target:t,anchor:n,props:i={},events:a,context:o,intro:s=!0,transformError:c}){Jt();var l=void 0,u=fn(()=>{var s=n??t.appendChild(Yt());Sr(s,{pending:()=>{}},t=>{ze({});var n=Le;if(o&&(n.c=o),a&&(i.$$events=a),A&&_r(t,null),l=e(t,i)||Ve(),A&&(W.nodes.end=j,j===null||j.nodeType!==8||j.data!==`]`))throw me(),de;Be()},c);var u=new Set,d=e=>{for(var n=0;n{for(var e of u)for(let n of[t,document]){var r=Tr.get(n),i=r.get(e);--i==0?(n.removeEventListener(e,pr),r.delete(e),r.size===0&&Tr.delete(n)):r.set(e,i)}sr.delete(d),s!==n&&s.parentNode?.removeChild(s)}});return Dr.set(l,u),l}var Dr=new WeakMap,Or=class{anchor;#e=new Map;#t=new Map;#n=new Map;#r=new Set;#i=!0;constructor(e,t=!0){this.anchor=e,this.#i=t}#a=e=>{if(this.#e.has(e)){var t=this.#e.get(e),n=this.#t.get(t);if(n)En(n),this.#r.delete(t);else{var r=this.#n.get(t);r&&(En(r.effect),this.#t.set(t,r.effect),this.#n.delete(t),r.fragment.lastChild.remove(),this.anchor.before(r.fragment),n=r.effect)}for(let[t,n]of this.#e){if(this.#e.delete(t),t===e)break;let r=this.#n.get(n);r&&(xn(r.effect),this.#n.delete(n))}for(let[e,r]of this.#t){if(e===t||this.#r.has(e))continue;let i=()=>{if(Array.from(this.#e.values()).includes(e)){var t=document.createDocumentFragment();On(r,t),t.append(Yt()),this.#n.set(e,{effect:r,fragment:t})}else xn(r);this.#r.delete(e),this.#t.delete(e)};this.#i||!n?(this.#r.add(e),wn(r,i,!1)):i()}}};#o=e=>{this.#e.delete(e);let t=Array.from(this.#e.values());for(let[e,n]of this.#n)t.includes(e)||(xn(n.effect),this.#n.delete(e))};ensure(e,t){var n=F,r=$t();if(t&&!this.#t.has(e)&&!this.#n.has(e)){if(r){var i=document.createDocumentFragment(),a=Yt();i.append(a),this.#n.set(e,{effect:_n(()=>t(a)),fragment:i})}else this.#t.set(e,_n(()=>t(this.anchor)))}if(this.#e.set(n,e),r){for(let[t,r]of this.#t)t===e?n.unskip_effect(r):n.skip_effect(r);for(let[t,r]of this.#n)t===e?n.unskip_effect(r.effect):n.skip_effect(r.effect);n.oncommit(this.#a),n.ondiscard(this.#o)}else A&&(this.anchor=j),this.#a(n)}};function X(e,t,n=!1){var r;A&&(r=j,ve());var i=new Or(e),a=n?S:0;function o(e,t){if(A){var n=xe(r);if(e!==parseInt(n.substring(1))){var a=be();_e(a),i.anchor=a,ge(!1),i.ensure(e,t),ge(!0);return}}i.ensure(e,t)}gn(()=>{var e=!1;t((t,n=0)=>{e=!0,o(n,t)}),e||o(-1,null)},a)}var kr=Symbol(`NaN`);function Ar(e,t,n){A&&ve();var r=new Or(e),i=!He();gn(()=>{var e=t();e!==e&&(e=kr),i&&typeof e==`object`&&e&&(e={}),r.ensure(e,n)})}function jr(e,t){return t}function Mr(e,t,n){for(var i=[],a=t.length,o,s=t.length,c=0;c{if(o){if(o.pending.delete(n),o.done.add(n),o.pending.size===0){var t=e.outrogroups;Nr(e,r(o.done)),t.delete(o),t.size===0&&(e.outrogroups=null)}}else--s},!1)}if(s===0){var l=i.length===0&&n!==null&&e.pending.size===0;if(l){var u=n,d=u.parentNode;Qt(d),d.append(u),e.items.clear()}Nr(e,t,!l)}else o={pending:new Set(t),done:new Set},(e.outrogroups??=new Set).add(o)}function Nr(e,t,n=!0){var r;if(e.pending.size>0){r=new Set;for(let t of e.pending.values())for(let n of t)r.add(e.items.get(n).e)}for(var i=0;i{var t=i();return e(t)?t:t==null?[]:r(t)}),p=new Map,m=!0;function h(e){if(!(_.effect.f&16384)){_.pending.delete(e);var t=G(f);_.fallback=d,Ir(_,t,c,n,a),d!==null&&(t.length===0?d.f&33554432?(d.f^=T,Rr(d,null,c)):En(d):wn(d,()=>{d=null}))}}function g(e){_.pending.delete(e)}var _={effect:gn(()=>{var e=G(f),t=e.length;let r=!1;A&&xe(c)===`[!`!=(t===0)&&(c=be(),_e(c),ge(!1),r=!0);for(var u=new Set,_=F,v=$t(),y=0;ys(c)):(d=_n(()=>s(Pr??=Yt())),d.f|=T)),t>u.size&&De(``,``,``),A&&t>0&&_e(be()),!m){if(p.set(_,u),v){for(let[e,t]of l)u.has(e)||_.skip_effect(t.e);_.oncommit(h),_.ondiscard(g)}else h(_)}r&&ge(!0),G(f)}),flags:n,items:l,pending:p,outrogroups:null,fallback:d};m=!1,A&&(c=j)}function Fr(e){for(;e!==null&&!(e.f&32);)e=e.next;return e}function Ir(e,t,n,i,a){var o=!!(i&8),s=t.length,c=e.items,l=Fr(e.effect.first),u,d=null,f,p=[],m=[],h,g,_,v;if(o)for(v=0;v0){var te=i&4&&s===0?n:null;if(o){for(v=0;v{if(f!==void 0)for(_ of f)_.nodes?.a?.apply()})}function Lr(e,t,n,r,i,a,o,s){var c=o&1?o&16?Ft(n):It(n,!1,!1):null,l=o&2?Ft(i):null;return{v:c,i:l,e:_n(()=>(a(t,c??n,l??i,s),()=>{e.delete(r)}))}}function Rr(e,t,n){if(e.nodes)for(var r=e.nodes.start,i=e.nodes.end,a=t&&!(t.f&33554432)?t.nodes.start:n;r!==null;){var o=Zt(r);if(a.before(r),r===i)return;r=o}}function zr(e,t,n){t===null?e.effect.first=n:t.next=n,n===null?e.effect.last=t:n.prev=t}var Br=[...` -\r\f\xA0\v`];function Vr(e,t,n){var r=e==null?``:``+e;if(t&&(r=r?r+` `+t:t),n){for(var i of Object.keys(n))if(n[i])r=r?r+` `+i:i;else if(r.length)for(var a=i.length,o=0;(o=r.indexOf(i,o))>=0;){var s=o+a;(o===0||Br.includes(r[o-1]))&&(s===r.length||Br.includes(r[s]))?r=(o===0?``:r.substring(0,o))+r.substring(s+1):o=s}}return r===``?null:r}function Hr(e,t,n,r,i,a){var o=e[ae];if(A||o!==n||o===void 0){var s=Vr(n,r,a);A&&s===e.getAttribute(`class`)||(s==null?e.removeAttribute(`class`):t?e.className=s:e.setAttribute(`class`,s)),e[ae]=n}else if(a&&i!==a)for(var c in a){var l=!!a[c];(i==null||l!==!!i[c])&&e.classList.toggle(c,l)}return a}var Ur=Symbol(`is custom element`),Wr=Symbol(`is html`),Gr=ue?`link`:`LINK`,Kr=ue?`progress`:`PROGRESS`;function qr(e){if(A){var t=!1,n=()=>{if(!t){if(t=!0,e.hasAttribute(`value`)){var n=e.value;Q(e,`value`,null),e.value=n}if(e.hasAttribute(`checked`)){var r=e.checked;Q(e,`checked`,null),e.checked=r}}};e[ce]=n,Ge(n),Qe()}}function Jr(e,t){var n=Xr(e);n.value!==(n.value=t??void 0)&&(e.value!==t||t===0&&e.nodeName===Kr)&&(e.value=t??``)}function Yr(e,t){var n=Xr(e);n.checked!==(n.checked=t??void 0)&&(e.checked=t)}function Q(e,t,n,r){var i=Xr(e);if(!(A&&(i[t]=e.getAttribute(t),t===`src`||t===`srcset`||t===`href`&&e.nodeName===Gr))){var a=i[t];a!==(i[t]=n)&&(t===`loading`&&(e[ie]=n),n==null?e.removeAttribute(t):typeof n!=`string`&&Qr(e).has(t)?e[t]=n:(!A||typeof n!=`number`&&typeof n!=`boolean`||a!==String(n))&&e.setAttribute(t,n))}}function Xr(e){return e[O]??={[Ur]:e.nodeName.includes(`-`),[Wr]:e.namespaceURI===fe}}var Zr=new Map;function Qr(e){var t=e.getAttribute(`is`)||e.nodeName,n=Zr.get(t);if(n)return n;Zr.set(t,n=new Set);for(var r,i=e,a=Element.prototype;a!==i;){for(var s in r=o(i),r)r[s].set&&s!==`innerHTML`&&s!==`textContent`&&s!==`innerText`&&n.add(s);i=l(i)}return n}function $r(e,t,n=t){var r=new WeakSet;et(e,`input`,async i=>{var a=i?e.defaultValue:e.value;if(a=ti(e)?ni(a):a,n(a),F!==null&&r.add(F),await $n(),a!==(a=t())){var o=e.selectionStart,s=e.selectionEnd,c=e.value.length;if(e.value=a??``,s!==null){var l=e.value.length;o===s&&s===c&&l>c?(e.selectionStart=l,e.selectionEnd=l):(e.selectionStart=o,e.selectionEnd=Math.min(s,l))}}}),(A&&e.defaultValue!==e.value||nr(t)==null&&e.value)&&(n(ti(e)?ni(e.value):e.value),F!==null&&r.add(F)),hn(()=>{var n=t();if(e===document.activeElement){var i=F;if(r.has(i))return}ti(e)&&n===ni(e.value)||(e.type!==`date`||n||e.value)&&n!==e.value&&(e.value=n??``)})}function ei(e,t,n=t){et(e,`change`,t=>{n(t?e.defaultChecked:e.checked)}),(A&&e.defaultChecked!==e.checked||nr(t)==null)&&n(e.checked),hn(()=>{e.checked=!!t()})}function ti(e){var t=e.type;return t===`number`||t===`range`}function ni(e){return e===``?null:+e}function ri(e,t){return e===t||e?.[D]===t}function ii(e=Ve(),t,n,r){var i=Le.r,a=W;return pn(()=>{var o,s;return hn(()=>{o=s,s=r?.()||[],nr(()=>{ri(n(...s),e)||(t(e,...s),o&&ri(n(...o),e)&&t(null,...o))})}),()=>{let r=a;for(;r!==i&&r.parent!==null&&r.parent.f&33554432;)r=r.parent;let o=()=>{s&&ri(n(...s),e)&&t(null,...s)},c=r.teardown;r.teardown=()=>{o(),c?.()}}}),e}var ai=!1;function oi(e){var t=ai;try{return ai=!1,[e(),ai]}finally{ai=t}}function $(e,t,n,r){var i=!0,o=!!(n&8),s=!!(n&16),c=r,l=!0,u=void 0,d=()=>s&&i?(u??=at(r),G(u)):(l&&(l=!1,c=s?nr(r):r),c);let f;if(o){var p=D in e||re in e;f=a(e,t)?.set??(p&&t in e?n=>e[t]=n:void 0)}var m,h=!1;o?[m,h]=oi(()=>e[t]):m=e[t],m===void 0&&r!==void 0&&(m=d(),f&&(i&&Me(t),f(m)));var g=i?()=>{var n=e[t];return n===void 0?d():(l=!0,n)}:()=>{var n=e[t];return n!==void 0&&(c=void 0),n===void 0?c:n};if(i&&!(n&4))return g;if(f){var _=e.$$legacy;return(function(e,t){return arguments.length>0?((!i||!t||_||h)&&f(t?g():e),e):g()})}var v=!1,y=(n&1?at:ct)(()=>(v=!1,g()));o&&G(y);var b=W;return(function(e,t){if(arguments.length>0){let n=t?G(y):i&&o?Ut(e):e;return L(y,n),v=!0,c!==void 0&&(c=n),e}return An&&v||b.f&16384?y.v:G(y)})}function si(e){Le===null&&Te(`onMount`),un(()=>{let t=nr(e);if(typeof t==`function`)return t})}function ci(e){Le===null&&Te(`onDestroy`),si(()=>()=>nr(e))}typeof window<`u`&&((window.__svelte??={}).v??=new Set).add(`5`);async function li(){let e=await fetch(`/api/overview`);if(!e.ok)throw Error(`overview ${e.status}`);return e.json()}async function ui(e,t){let n=await fetch(e);if(!n.ok)throw Error(`${t} ${n.status}`);return n.json()}function di(e){return ui(`/api/briefing?id=${encodeURIComponent(e)}`,`briefing`)}async function fi(e){let t={subject_kind:e.subjectKind,subject_id:e.subjectId,kind:e.kind,request_id:e.requestId};e.until!==void 0&&(t.until=e.until),e.text!==void 0&&(t.text=e.text),e.includeMembers!==void 0&&(t.include_members=e.includeMembers);let n=await fetch(`/api/decisions`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)});if(!n.ok)throw Error(`decision ${n.status}: ${await n.text()}`);return n.json()}function pi(e,t,n={}){let r=new URLSearchParams({subject_kind:e,subject_id:t});return n.limit!==void 0&&r.set(`limit`,String(n.limit)),n.before!==void 0&&r.set(`before`,n.before),ui(`/api/decisions?${r.toString()}`,`decisions`)}async function mi(e,t){let n=await fetch(`/api/decisions/${encodeURIComponent(e)}/undo`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({request_id:t})});if(!n.ok)throw Error(`undo ${n.status}: ${await n.text()}`);return n.json()}function hi(e,t){let n=new URLSearchParams({after:String(t),limit:`200`});return ui(`/api/decisions/${encodeURIComponent(e)}/members?${n}`,`member decisions`)}function gi(e=``){return ui(`/api/devices${e===``?``:`?after=${encodeURIComponent(e)}`}`,`devices`)}function _i(e,t=``){let n=t===``?``:`?history_after=${encodeURIComponent(t)}`;return ui(`/api/devices/${encodeURIComponent(e)}${n}`,`device`)}function vi(){return ui(`/api/health`,`health`)}function yi(e){return ui(`/api/incidents/${encodeURIComponent(e)}`,`incident`)}function bi(){let e=0,t=0;return{start(){return e+=1,{id:e,stream:t}},streamed(){t+=1},invalidate(){e+=1},current(n){return n.id===e&&n.stream===t}}}function xi(e){let t=document.activeElement,n=t?.closest?.(`[data-rows]`);if(!n)return!1;let r=[...n.querySelectorAll(`[data-row]`)];if(r.length===0)return!1;let i=r.indexOf(t);return i===-1&&(i=e===1?-1:0),(r[i+e]??(e===1?r[0]:r[r.length-1])).focus(),!0}function Si(e){let t=e.target;if(t===null||t.isContentEditable)return!0;let n=t.tagName;return n===`INPUT`||n===`TEXTAREA`||n===`SELECT`}function Ci(e){let t=new Date(e??``);return Number.isNaN(t.getTime())?{local:`unknown`,utc:`unknown`}:{local:t.toLocaleString(),utc:t.toISOString()}}function wi(e){switch(e){case`rules`:return`Deterministic rules`;case`model`:return`Model suggestion`;case`agent`:return`Investigator agent`;case`fallback`:return`Deterministic fallback`;case`legacy`:return`Earlier version (source unknown)`;default:return`Unknown source`}}function Ti(e){switch(e){case`reported_device`:return`Reported device`;case`address`:return`Address context — not a device identity`;case`event`:return`Unresolved events — not a device identity`;case`legacy`:return`Legacy profile`;default:return`Unknown class`}}function Ei(e){return{weak_appearance:`Weak sightings`,weak_disappearance:`Weak disappearances`,port_closed:`Ports closed`,hostname_change:`Hostname changes`,os_refinement:`OS refinements`,other:`Other changes`}[e]??e}function Di(e,t=[],n=[]){if(e!==`other`)return Ei(e);let r=new Map([[`low`,0],[`medium`,1],[`high`,2]]),i=new Map;for(let e of t)e.view_role===`previous`&&e.event_id&&i.set(e.event_id,r.get(e.attributes?.identity_confidence));for(let e of t){if(e.view_role!==`current`)continue;let t=i.get(e.event_id),n=r.get(e.attributes?.identity_confidence);if(t!==void 0&&n!==void 0&&ne.event_type));if(a.size===1){if(a.has(`host.appeared`))return`New host reported`;if(a.has(`host.disappeared`))return`Host disappearance reported`;if(a.has(`host.changed`))return`Reported host details changed`}return a.size>1?`Reported network changes`:`Reported details changed`}function Oi(e){let t=/^(\d+)h0m0s$/.exec(e);return t?`${t[1]} hours`:e}function ki(e=[]){let t=(e??[]).map(e=>new Date(e.occurred_at??``)).filter(e=>!Number.isNaN(e.getTime())).sort((e,t)=>e-t);if(t.length===0)return null;let n=t.length!==e.length,r=Ci(t[0].toISOString());if(t.length===1)return{...r,partial:n};let i=Ci(t[t.length-1].toISOString());return{local:`${r.local} – ${i.local}`,utc:`${r.utc} – ${i.utc}`,partial:n}}function Ai(e=[]){if(e.length!==1)return null;let t=(e??[]).filter(e=>e.view_role===`host`||e.view_role===`current`),n=new Set(t.map(e=>e.event_id));if(t.length!==1||n.size!==1)return null;let r=t[0].attributes??{},i=e=>typeof e==`string`&&e!==``?e:null;return{event_id:t[0].event_id,view_role:t[0].view_role,hostname:i(r.hostname),ip:i(r.ip),mac:i(r.mac),randomized:typeof r.randomized==`boolean`?r.randomized:null,identity_confidence:i(r.identity_confidence)??`unknown`,identity_source:i(r.identity_source)??`unknown`}}function ji(e){return e===!0?`Randomized (scanner-reported)`:e===!1?`Not randomized (scanner-reported)`:`Randomization unknown`}function Mi(e,t){return{parentId:e,count:Array.isArray(t.generated_decision_ids)?t.generated_decision_ids.length:0,next:t.generated_next??0,members:[]}}function Ni(e){return`Undone. ${e.next?`At least ${e.count}`:String(e.count)} member decision${e.count===1?` was`:`s were`} generated; incident undo does not undo them. Review them on their briefing pages.`}async function Pi(e,t){let n=await t(e.parentId,e.next),r=n.next??0;if(r!==0&&r<=e.next)throw Error(`Member decision page did not advance. Try again.`);return{parentId:e.parentId,count:e.count+n.members.length,next:r,members:n.members}}var Fi=q(` `),Ii=q(``),Li=q(``),Ri=q(`

`),zi=q(``),Bi=q(``),Vi=q(`

`),Hi=q(`
  • `),Ui=q(`
      `),Wi=q(``),Gi=q(`

      `,1),Ki=q(`

      Recorded decisions

      `),qi=q(`

      No decisions recorded.

      `),Ji=q(`undone`),Yi=q(` `),Xi=q(` `),Zi=q(``),Qi=q(`
    • `),$i=q(``),ea=q(`

      `),ta=q(`
        `,1),na=q(`

        Choose a decision

        `);function ra(e,t){ze(t,!0);let n=$(t,`kinds`,19,()=>[]),r=$(t,`decisions`,19,()=>[]),i=$(t,`effective`,3,null),a=$(t,`preset`,3,null),o=$(t,`reload`,3,async()=>{}),s=$(t,`memberScope`,3,!1),c=$(t,`memberCount`,3,0),l=$(t,`kindHelp`,19,()=>({})),u=$(t,`requireChoice`,3,!1),d={expected:`No further action needed.`,not_expected:`Flag for follow-up: this briefing still needs a check.`,snooze:`Hide from attention until a time. Empty keeps the server default (24h).`,note:`Free-text note, kept with the audit (max 2000 characters).`,label:`Your label for this profile, never identity (max 256 characters).`},f=I(null),p=P(()=>u()?G(f):G(f)??n()[0]??`note`),m=I(``),h=I(``),g=I(!1),_=I(null),v=I(null),y=I(null),b=I(Ut(crypto.randomUUID())),x=I(!1),S=I(null),C=I(null),w=I(!1),T=I(null),ee=I(null),te=I(Ut({})),E=!0;ci(()=>{E=!1});let D=0,ne=P(()=>r().length===0?`empty`:`${r()[0].decision_id}:${r().length}`),re=I(Ut([])),ie=I(``),O=I(Ut([])),ae=I(!1),oe=I(!1),se=I(``),ce=I(null),le=I(``),ue=P(()=>G(ie)===G(ne)&&G(re).length>0?[...r(),...G(re)]:r()),de=P(()=>G(oe)&&G(se)===G(ne)),k=P(()=>G(le)===G(ne)?G(ce):null),fe=P(()=>G(p)===`note`||G(p)===`label`),pe=P(()=>G(p)===`label`?256:2e3),me=P(()=>G(p)!==null&&n().includes(G(p))&&(!G(fe)||G(h).trim()!==``));un(()=>{a()!==null&&n().includes(a().kind)&&(L(f,a().kind,!0),G(ee)?.focus())});function he(){return i()===null||i()===void 0?`No operator review`:i().kind===`snooze`?`Snoozed${i().until?` until ${i().until}`:``}`:i().kind===`expected`?`Reviewed: expected`:`Flagged: ${i().kind.replace(`_`,` `)}`}async function A(e){if(e.preventDefault(),!G(g)&&(!u()||G(me))&&G(p)!==null){L(g,!0),L(v,null);try{let e={subjectKind:t.subjectKind,subjectId:t.subjectId,kind:G(p),requestId:G(b)};if(G(p)===`snooze`&&G(m)!==``){let t=new Date(G(m));if(Number.isNaN(t.getTime()))throw Error(`snooze time is not a date`);e.until=t.toISOString()}G(fe)&&(e.text=G(h)),s()&&(e.includeMembers=G(x));let n=await fi(e);L(b,crypto.randomUUID(),!0),L(f,null),L(m,``),L(h,``),L(x,!1),L(S,null),L(C,null),L(T,null),L(re,[],!0),L(ie,``),L(O,[],!0),L(oe,!1),L(ce,null),D+=1,n.applied===!1?L(v,`Already recorded (${n.reason??`duplicate`}).`):Array.isArray(n.members)&&n.members.length>0&&L(S,`Recorded on the incident and ${n.members.length} member briefing${n.members.length===1?``:`s`}.`),await o()()}catch(e){L(v,e instanceof Error?e.message:String(e),!0)}finally{L(g,!1)}}}async function ge(e){if(G(_)===null){L(_,e,!0),L(y,null),L(S,null),L(C,null),L(T,null);try{G(te)[e]??=crypto.randomUUID();let t=await mi(e,G(te)[e]);((t.generated_decision_ids?.length??0)>0||t.generated_next)&&L(C,Mi(e,t),!0);let n={...G(te)};delete n[e],L(te,n,!0),L(re,[],!0),L(ie,``),L(O,[],!0),L(oe,!1),L(ce,null),D+=1,await o()()}catch(e){L(y,e instanceof Error?e.message:String(e),!0)}finally{L(_,null)}}}async function j(){if(G(w)||!G(C)?.next)return;let e=G(C);L(w,!0),L(T,null);try{let t=await Pi(e,hi);E&&G(C)===e&&L(C,t,!0)}catch(t){E&&G(C)===e&&L(T,t instanceof Error?t.message:String(t),!0)}finally{E&&L(w,!1)}}async function _e(){if(G(ae)||G(de)||G(ue).length===0)return;let e=D,n=G(ne),r=G(ue)[G(ue).length-1].cursor;L(ae,!0),L(y,null);try{let i=await pi(t.subjectKind,t.subjectId,{limit:50,before:r});if(!E||e!==D||n!==G(ne))return;if(i.length===0){L(oe,!0),L(se,n,!0);return}G(ie)===n&&G(re).length>0&&(G(O).push({rows:G(re),key:G(ie)}),G(O).length>4&&(G(O).shift(),L(ce,`Earlier pages dropped from this view; the full audit remains available through the API.`),L(le,n,!0))),L(re,i,!0),L(ie,n,!0),L(oe,i.length<50),L(se,n,!0)}catch(t){if(!E||e!==D||n!==G(ne))return;L(y,t instanceof Error?t.message:String(t),!0)}finally{E&&L(ae,!1)}}function ve(){for(;G(O).length>0&&G(O)[G(O).length-1].key!==G(ne);)G(O).pop();let e=G(O).pop();e===void 0?(L(re,[],!0),L(ie,``)):(L(re,e.rows,!0),L(ie,e.key,!0)),L(oe,!1),L(se,G(ne),!0)}var ye=na();let be;var xe=R(ye),Se=B(xe,!0),Ce=V(xe,2),we=R(Ce),Te=B(we);M(Ce);var Ee=V(Ce,2),De=R(Ee),Oe=R(De);let ke;Z(V(Oe,2),16,n,e=>e,(e,n)=>{var r=Ii();let i;var a=R(r);qr(a);var o=V(a,2),s=B(o,!0),c=V(o,2),l=e=>{var t=Fi(),r=B(t,!0);H(()=>Y(r,{expected:`no further action`,not_expected:`investigate`,snooze:`hide until later`,note:`annotation only`}[n])),J(e,t)};X(c,e=>{u()&&e(l)}),M(r),H(e=>{i=Hr(r,1,`svelte-38cs4v`,null,i,{selected:G(p)===n}),Q(a,`name`,`decision-kind-${t.subjectId}`),Jr(a,n),Yr(a,G(p)===n),Y(s,e)},[()=>n===`not_expected`?`Not expected`:n.charAt(0).toUpperCase()+n.slice(1)]),K(`change`,a,()=>L(f,n,!0)),J(e,r)}),M(De);var Ae=V(De,2),je=B(Ae,!0),Me=V(Ae,2),Ne=e=>{var t=Li(),n=R(t);qr(n);var r=V(n);M(t),H(()=>Y(r,` Also apply to the ${c()??``} member briefing${c()===1?``:`s`} (snapshot now; later joiners stay untouched)`)),ei(n,()=>G(x),e=>L(x,e)),J(e,t)};X(Me,e=>{s()&&e(Ne)});var Pe=V(Me,2),Fe=e=>{var t=Ri(),n=B(t,!0);H(()=>Y(n,G(S))),J(e,t)};X(Pe,e=>{G(S)!==null&&e(Fe)});var Ie=V(Pe,2),Le=e=>{var t=zi(),n=V(R(t));qr(n),M(t),$r(n,()=>G(m),e=>L(m,e)),J(e,t)};X(Ie,e=>{G(p)===`snooze`&&e(Le)});var Re=V(Ie,2),Ve=e=>{var t=Bi(),n=R(t),r=V(n);Xe(r),M(t),H(()=>{Y(n,`${G(p)===`label`?`Label`:`Note`} `),Q(r,`maxlength`,G(pe))}),$r(r,()=>G(h),e=>L(h,e)),J(e,t)};X(Re,e=>{G(fe)&&e(Ve)});var He=V(Re,2),Ue=e=>{var t=Vi(),n=B(t,!0);H(()=>Y(n,G(v))),J(e,t)};X(He,e=>{G(v)!==null&&e(Ue)});var We=V(He,2),Ge=B(We,!0);ii(We,e=>L(ee,e),()=>G(ee)),M(Ee);var Ke=V(Ee,2),qe=e=>{var t=Gi(),n=z(t),r=B(n,!0),i=V(n,2),a=e=>{var t=Ui();Z(t,21,()=>G(C).members,e=>e.decision_id,(e,t)=>{var n=Hi(),r=R(n),i=B(r,!0),a=V(r);M(n),H((e,n)=>{Q(r,`href`,e),Y(i,G(t).subject_id),Y(a,` — ${n??``}`)},[()=>`#/briefing/${encodeURIComponent(G(t).subject_id)}`,()=>G(t).kind.replace(`_`,` `)]),J(e,n)}),M(t),J(e,t)};X(i,e=>{G(C).members.length>0&&e(a)});var o=V(i,2),s=e=>{var t=Wi(),n=B(t,!0);H(()=>{t.disabled=G(w),Y(n,G(w)?`Loading…`:G(T)?`Retry remaining member decisions`:`Show remaining member decisions`)}),K(`click`,t,j),J(e,t)};X(o,e=>{G(C).next&&e(s)});var c=V(o,2),l=e=>{var t=Vi(),n=B(t,!0);H(()=>Y(n,G(T))),J(e,t)};X(c,e=>{G(T)!==null&&e(l)}),H(e=>Y(r,e),[()=>Ni(G(C))]),J(e,t)};X(Ke,e=>{G(C)!==null&&e(qe)});var N=V(Ke,2),Je=e=>{J(e,Ki())};X(N,e=>{u()&&e(Je)});var Ye=V(N,2),Ze=e=>{J(e,qi())},Qe=e=>{var t=ta(),n=z(t);Z(n,21,()=>G(ue),e=>e.decision_id,(e,t)=>{var n=Qi(),r=R(n),i=B(r,!0),a=V(r,2),o=e=>{J(e,Ji())};X(a,e=>{G(t).undone&&e(o)});var s=V(a,2),c=e=>{var n=Yi(),r=B(n,!0);H(()=>Y(r,G(t).text)),J(e,n)};X(s,e=>{G(t).text&&e(c)});var l=V(s,2),u=e=>{var n=Xi(),r=B(n);H(()=>Y(r,`until ${G(t).until??``}`)),J(e,n)};X(l,e=>{G(t).until&&e(u)});var d=V(l,2),f=B(d,!0),p=V(d,2),m=e=>{var n=Zi(),r=B(n,!0);H(()=>{n.disabled=G(_)!==null,Y(r,G(_)===G(t).decision_id?`Undoing…`:`Undo`)}),K(`click`,n,()=>ge(G(t).decision_id)),J(e,n)};X(p,e=>{!G(t).undone&&G(t).kind!==`undo`&&e(m)}),M(n),H((e,n)=>{Y(i,e),Q(d,`datetime`,G(t).created_at),Y(f,n)},[()=>G(t).kind.replace(`_`,` `),()=>new Date(G(t).created_at).toLocaleString()]),J(e,n)}),M(n);var r=V(n,2),i=e=>{var t=Wi(),n=B(t,!0);H(()=>{t.disabled=G(ae),Y(n,G(ae)?`Loading…`:`Show older decisions`)}),K(`click`,t,_e),J(e,t)};X(r,e=>{G(de)||e(i)});var a=V(r,2),o=e=>{var t=$i();H(()=>t.disabled=G(ae)),K(`click`,t,ve),J(e,t)};X(a,e=>{G(ie)===G(ne)&&G(re).length>0&&e(o)});var s=V(a,2),c=e=>{var t=ea(),n=B(t,!0);H(()=>Y(n,G(k))),J(e,t)};X(s,e=>{G(k)!==null&&e(c)}),J(e,t)};X(Ye,e=>{G(ue).length===0?e(Ze):e(Qe,-1)});var $e=V(Ye,2),et=e=>{var t=Vi(),n=B(t,!0);H(()=>Y(n,G(y))),J(e,t)};X($e,e=>{G(y)!==null&&e(et)}),M(ye),H(e=>{be=Hr(ye,1,`svelte-38cs4v`,null,be,{"decision-card":u()}),Y(Se,u()?`Your decision`:`Operator decisions`),Q(we,`data-review`,i()?.kind??`unreviewed`),Y(Te,`Status: ${e??``}`),ke=Hr(Oe,1,``,null,ke,{"sr-only":u()}),Y(je,G(p)===null?`Choose a verdict to record it.`:l()[G(p)]??d[G(p)]??``),We.disabled=u()?G(g)||!G(me):G(g),Y(Ge,G(g)?`Recording…`:`Record decision`)},[()=>he()]),lr(`submit`,Ee,A),J(e,ye),Be()}ur([`change`,`click`]);var ia=q(` `),aa=q(` `,1);function oa(e,t){ze(t,!0);let n=$(t,`name`,3,`value`),r=I(`idle`),i=I(null),a=!0;ci(()=>{a=!1,G(i)!==null&&clearTimeout(G(i))});async function o(){G(i)!==null&&(clearTimeout(G(i)),L(i,null)),L(r,`idle`);try{if(navigator.clipboard?.writeText!==void 0)await navigator.clipboard.writeText(t.value);else{let e=document.createElement(`textarea`);e.value=t.value,e.className=`wb-clipboard-buffer`,document.body.appendChild(e);let n=document.activeElement,r=!1;try{e.select(),r=document.execCommand(`copy`)}finally{e.remove(),n instanceof HTMLElement&&n.focus({preventScroll:!0})}if(!r)throw Error(`copy rejected`)}if(!a)return;L(r,`copied`),L(i,setTimeout(()=>{L(r,`idle`),L(i,null)},1500),!0)}catch{a&&L(r,`failed`)}}var s=aa(),c=z(s),l=B(c,!0),u=V(c,2),d=e=>{var t=ia(),r=B(t);H(()=>Y(r,`Could not copy the ${n()??``}; select and copy it manually.`)),J(e,t)};X(u,e=>{G(r)===`failed`&&e(d)}),H(()=>{Q(c,`aria-label`,`Copy ${n()}`),Y(l,G(r)===`copied`?`Copied`:G(r)===`failed`?`Copy failed`:`Copy`)}),K(`click`,c,o),J(e,s),Be()}ur([`click`]);var sa=q(`

        No retained observation for this event. Its reference is retained, but a saved scanner view is unavailable.

        `),ca=q(`
        Reported vendor
        `),la=q(`
        Reported OS
        `),ua=q(`
        Reported device
        `),da=q(`

        Some reported fields were truncated at ingest.

        `),fa=q(`
      1. `),pa=q(`
          `),ma=q(`Open reported context → `),ha=q(`

          No linked profile is available for this saved view.

          `),ga=q(`

          Hostname
          IP address
          MAC address

          Saved report view · technical attributes
           

          `),_a=q(`
          Reported

          Reported scan target:
          Received

          `);function va(e,t){ze(t,!0);let n=$(t,`views`,19,()=>[]),r=$(t,`profileLinks`,19,()=>[]),i=P(()=>Ci(t.ref.occurred_at)),a=P(()=>Ci(t.ref.received_at)),o=e=>typeof e==`string`&&e.trim()!==``?e:`Not reported`;var s=_a(),c=R(s),l=R(c),u=R(l),d=B(u,!0),f=B(V(u),!0);M(l);var p=V(l,2),m=V(R(p)),h=B(m,!0);M(p),M(c);var g=V(c,2),_=R(g),v=V(R(_)),y=B(v,!0),b=V(v),x=e=>{J(e,vr(`(truncated)`))};X(b,e=>{t.ref.target_truncated&&e(x)});var S=V(b,3),C=B(S,!0);M(_);var w=V(_,2),T=e=>{J(e,sa())},ee=e=>{var t=yr();Z(z(t),17,n,e=>`${e.event_id}:${e.view_role}`,(e,t)=>{let n=P(()=>G(t).attributes??{});var i=ga(),a=R(i),s=B(a,!0),c=V(a,2),l=R(c),u=B(V(R(l)),!0);M(l);var d=V(l,2),f=B(V(R(d)),!0);M(d);var p=V(d,2),m=B(V(R(p)),!0);M(p);var h=V(p,2),g=e=>{var t=ca(),r=B(V(R(t)),!0);M(t),H(()=>Y(r,G(n).vendor)),J(e,t)};X(h,e=>{G(n).vendor&&e(g)});var _=V(h,2),v=e=>{var t=la(),r=B(V(R(t)),!0);M(t),H(()=>Y(r,G(n).os)),J(e,t)};X(_,e=>{G(n).os&&e(v)});var y=V(_,2),b=e=>{var t=ua(),r=B(V(R(t)),!0);M(t),H(()=>Y(r,G(n).device)),J(e,t)};X(y,e=>{G(n).device&&e(b)}),M(c);var x=V(c,2),S=R(x),C=B(S),w=B(V(S));M(x);var T=V(x,2),ee=B(T,!0),te=V(T,2),E=e=>{J(e,da())};X(te,e=>{G(n).attributes_truncated&&e(E)});var D=V(te,2),ne=B(V(R(D)),!0);M(D);var re=V(D,2),ie=B(re),O=V(re,2),ae=e=>{var n=pa();Z(n,21,()=>G(t).ports,e=>`${e.proto}/${e.port}`,(e,t)=>{var n=fa(),r=B(n);H(()=>Y(r,`${G(t).proto??``}/${G(t).port??``} ${G(t).state??``}${G(t).service?` (${G(t).service})`:``}`)),J(e,n)}),M(n),J(e,n)};X(O,e=>{(G(t).ports??[]).length>0&&e(ae)});var oe=V(O,2),se=e=>{var n=ma(),i=B(V(R(n)));M(n),H((e,t,r)=>{Q(n,`href`,e),Y(i,`${t??``} · ${r??``}`)},[()=>`#/devices/${encodeURIComponent(G(t).profile_id)}`,()=>Ti(G(t).reference_class),()=>r().find(e=>e.profile_id===G(t).profile_id)?.role??G(t).view_role]),J(e,n)},ce=e=>{J(e,ha())};X(oe,e=>{G(t).profile_id?e(se):e(ce,-1)}),M(i),H((e,r,a,o,c)=>{Q(i,`aria-label`,`${G(t).view_role} view`),Y(s,G(t).view_role===`previous`?`Before the reported change`:G(t).view_role===`current`?`After the reported change`:`Reported host`),Y(u,e),Y(f,r),Y(m,a),Y(C,`Scanner-reported identity confidence: ${(G(n).identity_confidence||`unknown`)??``}`),Y(w,`Identity source: ${(G(n).identity_source||`unknown`)??``}`),Y(ee,o),Y(ne,c),Y(ie,`Snapshot covers ${G(t).ports_total??``} ports${G(t).ports_truncated?` (truncated)`:``}.`)},[()=>o(G(n).hostname),()=>o(G(n).ip),()=>o(G(n).mac),()=>ji(G(n).randomized),()=>JSON.stringify(G(n),null,2)]),J(e,i)}),J(e,t)};X(w,e=>{n().length===0?e(T):e(ee,-1)}),M(g),M(s),H(()=>{Q(s,`data-evidence`,`event:${t.ref.event_id}`),Q(s,`aria-label`,`Saved report ${t.ref.event_id}`),Y(d,t.ref.event_id),Y(f,t.ref.event_type),Q(m,`datetime`,t.ref.occurred_at),Q(m,`title`,G(i).utc),Y(h,G(i).local),Y(y,t.ref.target||`Not reported`),Q(S,`datetime`,t.ref.received_at),Q(S,`title`,G(a).utc),Y(C,G(a).local)}),J(e,s),Be()}var ya=q(` `),ba=q(`
        • Arguments and tokenized result
           
           
        • `);function xa(e,t){ze(t,!0);let n=P(()=>`step-${t.step.step}`),r=P(()=>t.step.summary??(t.step.outcome===`unknown_subject`?`The investigator could not resolve this lookup to a permitted reported subject; history remains unknown.`:t.step.status===`blocked`?`Redaction blocked this result; the lookup did not complete.`:t.step.status===`error`?`Tool execution failed; result unavailable.`:`No interpreted result is available.`));var i=ba(),a=R(i),o=B(a,!0),s=V(a,2),c=e=>{var n=ya(),r=B(n,!0);H(e=>Y(r,e),[()=>t.step.outcome.replaceAll(`_`,` `)]),J(e,n)};X(s,e=>{t.step.outcome&&e(c)});var l=V(s,2),u=B(l),d=V(l,2),f=B(d,!0),p=V(d,2),m=V(R(p),2),h=B(m),g=B(V(m,2));M(p),M(i),H(()=>{Q(i,`id`,G(n)),Q(i,`data-evidence`,`step:${t.step.step}`),Y(o,t.step.tool),Y(u,`step ${t.step.step??``} · ${t.step.status??``} · ${t.step.duration_ms??``} ms`),Y(f,G(r)),Y(h,`Args: ${t.step.args??``}`),Y(g,`Result: ${t.step.result??``}`)}),J(e,i),Be()}function Sa(e,t){if(!e)return!1;let n=Array.from(e.querySelectorAll(`[data-evidence]`)).find(e=>e.dataset.evidence===t);if(!n)return!1;for(let t=n;t&&t!==e;t=t.parentElement)t.tagName===`DETAILS`&&(t.open=!0);return n.scrollIntoView({block:`nearest`}),n.focus({preventScroll:!0}),!0}var Ca=q(`

          Briefing unavailable

          `),wa=q(`

          Loading briefing…

          `),Ta=q(`

          ← Back to Home

          `),Ea=q(`

          The saved view could not be refreshed. Your last loaded report is still shown.

          `),Da=q(`
          Reported host
          IP address
          MAC address
          `,1),Oa=q(`
          Reported identities
          See the individual report views below

          `),ka=q(`(truncated)`),Aa=q(` `),ja=q(``),Ma=q(``),Na=q(` `),Pa=q(`
          Copy for your investigation
          `),Fa=q(` `),Ia=q(`

          Suggestion adjusted to respect the baseline floor and one-step raise limit.

          `),La=q(`

          Deterministic fallback text: the model path did not produce this briefing.

          `),Ra=q(`

          No referenced events retained.

          `),za=q(`

          More referenced events exist than shown.

          `),Ba=q(`

          More observations exist than shown; some saved views are omitted.

          `),Va=q(`

          Possible explanation:

          `),Ha=q(`

          `),Ua=q(`

          Investigation has limits. Some lookups could not establish retained context. Missing lookup results do not prove this host has no history.

          `),Wa=q(``),Ga=q(`
        • `),Ka=q(`

          What the investigator could establish

            `,1),qa=q(``),Ja=q(`
            Cited evidence
            `),Ya=q(`
          • Open reported context
          • `),Xa=q(``),Za=q(`

            No profile links persisted for this briefing.

            `),Qa=q(`

            More profile links exist than shown.

            `),$a=q(`
              `),eo=q(`

              No agent trace is available for this briefing.

              `),to=q(`

              Model accounting

              `,1),no=q(`

              Reported scan target
              Analysis source

              Reported at the time shown. Network conditions may have changed since this report.

              Why this priority

              How the priority was computed
              1. Baseline floor
              2. Model suggestion
              3. Final priority

              Saved at report time

              Open a report to see what the scanner supplied, with its linked context.

              Technical details Tool calls, accounting and provenance

              Executed tool steps

              Provenance

              Briefing
              Group
              Grouping version
              Sequence
              Created
              Grouping anchor
              `);function ro(e,t){ze(t,!0);let n=$(t,`initial`,3,null),r=$(t,`embedded`,3,!1),i=$(t,`ontitle`,3,null),a=bi();ci(()=>a.invalidate());let o=I(null),s=I(null),c=I(null),l=I(null),u=0,d=P(()=>G(s)??n()),f=P(()=>G(d)===null?``:Di(G(d).kind,G(d).observations,G(d).referenced_events));un(()=>{if(G(d)!==null&&i()){let e=G(d).briefing_id,t=G(f);nr(()=>i()(e,t))}});async function p(){a.invalidate();let e=a.start();L(c,null);try{let n=await di(t.id);a.current(e)&&L(s,n,!0)}catch(t){a.current(e)&&L(c,t instanceof Error?t.message:String(t),!0)}}un(()=>{if(n()!==null)return;let e=t.id;a.invalidate();let r=a.start();L(c,null),di(e).then(e=>{a.current(r)&&L(s,e,!0)},e=>{a.current(r)&&L(c,e instanceof Error?e.message:String(e),!0)})});let m=P(()=>G(d)===null?null:Ci(G(d).created_at)),h=P(()=>G(d)===null?null:ki(G(d).referenced_events)),g=P(()=>G(d)===null?null:Ai(G(d).observations)),_=P(()=>G(d)!==null&&(G(d).clamped||G(d).baseline!==G(d).priority||(G(d).model_suggestion??G(d).baseline)!==G(d).priority)),v=P(()=>G(d)?.referenced_events.length===1?G(d).referenced_events[0]:null),y=P(()=>G(d)!==null&&!G(d).observations_truncated&&!G(d).referenced_truncated),b=P(()=>(G(d)?.traces??[]).filter(e=>[`unknown_subject`,`blocked`,`error`,`unavailable`,`truncated`].includes(e.outcome))),x=P(()=>{let e=[];for(let t of G(d)?.traces??[]){let n=t.summary||`step:${t.step}`,r=e.find(e=>e.key===n);r||(r={key:n,summary:t.summary,steps:[]},e.push(r)),r.steps.push(t.step)}return e});function S(e){Sa(G(o),e)}function C(e){return(G(d)?.observations??[]).filter(t=>t.event_id===e)}function w(e){if(Si(e)||e.metaKey||e.ctrlKey||e.altKey)return;let t={e:`expected`,s:`snooze`,x:`not_expected`}[e.key];t!==void 0&&G(d)!==null&&(u+=1,L(l,{kind:t,seq:u},!0))}si(()=>(window.addEventListener(`keydown`,w),()=>{window.removeEventListener(`keydown`,w)}));var T=yr(),ee=z(T),te=e=>{var t=Ca(),n=V(R(t),2),r=B(n),i=V(n,2);M(t),H(()=>Y(r,`The bridge did not return this briefing (${G(c)??``}).`)),K(`click`,i,p),J(e,t)},E=e=>{J(e,wa())},D=e=>{var t=no();let n;var i=R(t),a=e=>{J(e,Ta())};X(i,e=>{r()||e(a)});var s=V(i,2),u=e=>{var t=Ea(),n=V(R(t));M(t),K(`click`,n,p),J(e,t)};X(s,e=>{G(c)!==null&&e(u)});var w=V(s,2),T=R(w),ee=R(T),te=R(ee),E=B(te,!0),D=V(te,2),ne=B(D);M(ee);var re=V(ee,2),ie=B(re,!0),O=V(re,2),ae=R(O),oe=e=>{var t=Da(),n=z(t),r=B(V(R(n)),!0);M(n);var i=V(n,2),a=V(R(i)),o=R(a,!0),s=V(o),c=e=>{oa(e,{get value(){return G(g).ip},name:`IP address`})};X(s,e=>{G(g).ip!==null&&e(c)}),M(a),M(i);var l=V(i,2),u=V(R(l)),d=R(u,!0),f=V(d),p=e=>{oa(e,{get value(){return G(g).mac},name:`MAC address`})};X(f,e=>{G(g).mac!==null&&e(p)}),M(u),M(l),H(()=>{Y(r,G(g).hostname??`Not reported`),Y(o,G(g).ip??`Not reported`),Y(d,G(g).mac??`Not reported`)}),J(e,t)},se=e=>{var t=Oa(),n=V(R(t)),r=B(V(R(n)),!0);M(n),M(t),H(()=>Y(r,G(y)?`Grouped changes can describe different host views.`:`Only part of the retained evidence is shown.`)),J(e,t)};X(ae,e=>{G(g)!==null&&G(y)?e(oe):e(se,-1)});var ce=V(ae,2),le=V(R(ce)),ue=R(le,!0),de=V(ue),k=e=>{J(e,ka())};X(de,e=>{G(v)?.target_truncated&&e(k)}),M(le),M(ce);var fe=V(ce,2),pe=R(fe),me=B(pe,!0),he=V(pe),A=R(he),ge=e=>{var t=Aa(),n=B(t,!0);H(()=>{Q(t,`title`,G(h).utc),Y(n,G(h).local)}),J(e,t)},j=e=>{J(e,vr(`Not reported`))};X(A,e=>{G(h)===null?e(j,-1):e(ge)}),M(he),M(fe);var _e=V(fe,2),ve=B(V(R(_e)),!0);M(_e),M(O);var be=V(O,2),xe=R(be),Se=B(xe),Ce=V(xe,2),we=e=>{var t=ja();K(`click`,t,()=>S(`event:${G(v).event_id}`)),J(e,t)},Te=e=>{var t=Ma();K(`click`,t,()=>S(`reports`)),J(e,t)};X(Ce,e=>{G(v)?e(we):G(d).referenced_events.length>0&&e(Te,1)}),M(be),M(T);var Ee=V(T,4),De=V(R(Ee),2),Oe=B(De,!0),ke=V(De,2),Ae=e=>{var t=Pa(),n=V(R(t),2),r=e=>{var t=Na(),n=R(t);oa(V(n),{get value(){return G(g).ip},name:`IP address`}),M(t),H(()=>Y(n,`${G(g).ip??``} `)),J(e,t)};X(n,e=>{G(g).ip!==null&&e(r)});var i=V(n,2),a=e=>{var t=Na(),n=R(t);oa(V(n),{get value(){return G(g).mac},name:`MAC address`}),M(t),H(()=>Y(n,`${G(g).mac??``} `)),J(e,t)};X(i,e=>{G(g).mac!==null&&e(a)}),M(t),J(e,t)};X(ke,e=>{G(g)!==null&&G(y)&&(G(g).ip!==null||G(g).mac!==null)&&e(Ae)}),M(Ee);var je=V(Ee,2),Me=R(je);{let e=P(()=>G(d).decisions??[]),t=P(()=>G(d).effective_review??null);ra(Me,{subjectKind:`briefing`,get subjectId(){return G(d).briefing_id},kinds:[`expected`,`not_expected`,`snooze`,`note`],get decisions(){return G(e)},get effective(){return G(t)},get preset(){return G(l)},reload:p,requireChoice:!0})}M(je);var Ne=V(je,2),Pe=V(R(Ne),2),Fe=B(Pe,!0),Ie=V(Pe,2),Le=R(Ie),Re=B(Le),ze=V(Le),Be=e=>{var t=Fa(),n=B(t,!0);H(()=>Y(n,G(d).baseline_rule)),J(e,t)};X(ze,e=>{G(d).baseline_rule&&e(Be)}),M(Ie);var Ve=V(Ie,2),He=V(R(Ve),2),Ue=R(He),We=B(V(R(Ue)),!0);M(Ue);var Ge=V(Ue,2),Ke=B(V(R(Ge)),!0);M(Ge);var qe=V(Ge,2),N=B(V(R(qe)),!0);M(qe),M(He);var Je=V(He,2),Ye=e=>{J(e,Ia())};X(Je,e=>{G(d).clamped&&e(Ye)}),M(Ve);var Xe=V(Ve,2),Ze=e=>{J(e,La())};X(Xe,e=>{G(d).fallback_used&&e(Ze)}),M(Ne);var Qe=V(Ne,2),$e=R(Qe),et=B(R($e));ye(),M($e);var tt=V($e,4),nt=e=>{J(e,Ra())},rt=e=>{var t=yr();Z(z(t),17,()=>G(d).referenced_events,e=>e.event_id,(e,t)=>{{let n=P(()=>C(G(t).event_id));va(e,{get ref(){return G(t)},get views(){return G(n)},get profileLinks(){return G(d).profiles}})}}),J(e,t)};X(tt,e=>{G(d).referenced_events.length===0?e(nt):e(rt,-1)});var it=V(tt,2),at=e=>{J(e,za())};X(it,e=>{G(d).referenced_truncated&&e(at)});var ot=V(it,2),st=e=>{J(e,Ba())};X(ot,e=>{G(d).observations_truncated&&e(st)}),M(Qe);var ct=V(Qe,2),lt=R(ct),ut=B(lt,!0),dt=V(lt,2),ft=e=>{var t=Va(),n=V(R(t));M(t),H(()=>Y(n,` ${G(d).likely_explanation??``}`)),J(e,t)};X(dt,e=>{G(d).likely_explanation&&e(ft)});var pt=V(dt,2),mt=e=>{var t=Ha(),n=B(R(t));M(t),H(()=>Y(n,`Explanation confidence (model self-assessment): ${G(d).confidence??``}`)),J(e,t)};X(pt,e=>{G(d).confidence&&e(mt)});var F=V(pt,2),ht=e=>{J(e,Ua())};X(F,e=>{G(b).length>0&&e(ht)});var gt=V(F,2),_t=B(gt,!0),vt=V(gt,2),yt=e=>{var t=Ka(),n=V(z(t),2);Z(n,21,()=>G(x),jr,(e,t)=>{var n=Ga(),r=V(R(n)),i=R(r),a=B(i,!0),o=V(i);Z(o,20,()=>G(t).steps,e=>e,(e,t)=>{var n=Wa(),r=B(n);H(()=>Y(r,`View step ${t??``}`)),K(`click`,n,()=>S(`step:${t}`)),J(e,n)}),M(o),M(r),M(n),H(()=>Y(a,G(t).summary||`No interpreted result is available. Open the tool step to inspect the saved response.`)),J(e,n)}),M(n),J(e,t)};X(vt,e=>{G(d).traces?.length&&e(yt)});var bt=V(vt,2),xt=e=>{var t=Ja();Z(V(R(t),2),19,()=>G(d).evidence_refs,(e,t)=>`${e.event_id??e.tool_step}:${t}`,(e,t)=>{var n=qa(),r=B(n,!0);H(()=>Y(r,G(t).event_id?`Event ${G(t).event_id}`:`Tool step ${G(t).tool_step}`)),K(`click`,n,()=>S(G(t).event_id?`event:${G(t).event_id}`:`step:${G(t).tool_step}`)),J(e,n)}),M(t),J(e,t)};X(bt,e=>{G(d).evidence_refs?.length&&e(xt)});var St=V(bt,2),Ct=e=>{var t=Xa(),n=V(R(t));Z(n,21,()=>G(d).profiles,e=>`${e.profile_id}:${e.role}`,(e,t)=>{var n=Ya(),r=R(n),i=B(V(r,2));M(n),H(e=>{Q(r,`href`,e),Y(i,`${G(t).profile_id??``} (${G(t).role??``})`)},[()=>`#/devices/${encodeURIComponent(G(t).profile_id)}`]),J(e,n)}),M(n),M(t),J(e,t)},wt=e=>{J(e,Za())};X(St,e=>{G(d).profiles.length>0?e(Ct):e(wt,-1)});var Tt=V(St,2),Et=e=>{J(e,Qa())};X(Tt,e=>{G(d).profiles_truncated&&e(Et)}),M(ct);var Dt=V(ct,2),Ot=V(R(Dt),2),kt=V(R(Ot),2),At=e=>{var t=$a();Z(t,21,()=>G(d).traces,e=>e.step,(e,t)=>{xa(e,{get step(){return G(t)}})}),M(t),J(e,t)},jt=e=>{J(e,eo())};X(kt,e=>{G(d).traces?.length?e(At):e(jt,-1)});var Mt=V(kt,2),Nt=e=>{var t=to(),n=B(V(z(t)));H(()=>Y(n,`${G(d).input_tokens??`Unknown`??``} input tokens · ${G(d).output_tokens??`Unknown`??``} output tokens · ${G(d).cost_usd==null?`Cost unknown`:`$${G(d).cost_usd}`}`)),J(e,t)};X(Mt,e=>{(G(d).input_tokens!=null||G(d).output_tokens!=null||G(d).cost_usd!=null)&&e(Nt)});var Pt=V(Mt,3),Ft=V(R(Pt)),I=B(Ft,!0),It=V(Ft,2),Lt=B(It,!0),Rt=V(It,3),zt=B(Rt,!0),Bt=V(Rt,2),Vt=B(Bt,!0),Ht=V(Bt,3),Ut=R(Ht),Wt=B(Ut,!0);M(Ht);var Gt=B(V(Ht,3),!0);M(Pt),M(Ot),M(Dt),M(w),M(t),ii(t,e=>L(o,e),()=>G(o)),H(e=>{n=Hr(t,1,`briefing dossier svelte-90l7ri`,null,n,{embedded:r()}),Y(E,G(f)),Q(D,`data-priority`,G(d).priority),Q(D,`aria-label`,`Priority: ${G(d).priority}`),Y(ne,`${G(d).priority??``} priority`),Y(ie,G(d).what_changed),Y(ue,G(v)?.target||(G(d).referenced_events.length>1?`Shown per report below`:`Not reported`)),Y(me,G(h)?.partial||G(d).referenced_truncated?`Available report times`:G(d).referenced_events.length>1?`Report time range`:`Report time`),Y(ve,e),Y(Se,`${G(d).referenced_events.length??``}${G(d).referenced_truncated?`+`:``} source report${G(d).referenced_events.length===1?``:`s`}`),Y(Oe,G(d).recommended_check),Y(Fe,G(d).priority_reason),Q(Le,`data-priority`,G(d).priority),Y(Re,`Final priority: ${G(d).priority??``}`),Ve.open=G(_),Y(We,G(d).baseline),Y(Ke,G(d).model_suggestion??`No model suggestion — baseline stands`),Y(N,G(d).priority),Y(et,`Scanner snapshot${G(d).referenced_events.length===1?``:`s`}`),Y(ut,G(d).source===`agent`?`Investigator notes`:`Analysis and retained context`),Y(_t,G(d).context),Y(I,G(d).briefing_id),Y(Lt,G(d).group_id),Y(zt,G(d).grouping_version),Y(Vt,G(d).seq),Q(Ut,`datetime`,G(d).created_at),Q(Ut,`title`,G(m)?.utc),Y(Wt,G(m)?.local),Y(Gt,G(d).host)},[()=>wi(G(d).source)]),J(e,t)};X(ee,e=>{G(c)!==null&&G(d)===null?e(te):G(d)===null?e(E,1):e(D,-1)}),J(e,T),Be()}ur([`click`]);var io=q(`

              `),ao=q(`

              Loading incident…

              `),oo=q(`Closed `),so=q(`Open since `),co=q(`

              Some members share identity evidence; only distinct qualified references count toward the burst threshold.

              `),lo=q(`

              More members exist than shown.

              `),uo=q(`

              No member evidence retained.

              `),fo=q(`
            1. `),po=q(`
                `),mo=q(`

                `),ho=q(`

                Hypothesis:

                `),go=q(`
              1. `),_o=q(`

                Cited reports:

                  `,1),vo=q(`

                  Summary

                  `),yo=q(`

                  Scope

                  Window start: · Last member:

                  Evidence

                  `,1),bo=q(`

                  Back to overview

                  `,1);function xo(e,t){ze(t,!0);let n=$(t,`initial`,3,null),r=bi();ci(()=>{r.invalidate(),typeof window<`u`&&window.removeEventListener(`watcherbridge:incident`,c)});let i=I(null),a=I(null),o=P(()=>G(i)??n());async function s(){r.invalidate();let e=r.start();L(a,null);try{let n=await yi(t.id);r.current(e)&&L(i,n,!0)}catch(t){r.current(e)&&L(a,t instanceof Error?t.message:String(t),!0)}}function c(){s()}si(()=>{n()===null&&s(),window.addEventListener(`watcherbridge:incident`,c)});let l={burst_appearance:`Burst appearance`,burst_disappearance:`Burst disappearance`},u={expected:`Mark reviewed: this incident needs no further action. Members stay untouched unless included below.`,not_expected:`Flag for follow-up: this incident still needs a check.`,snooze:`Hide until a time. Empty keeps the server default (24h).`,note:`Free-text note, kept with the audit (max 2000 characters).`};function d(e){return`${`${e.member_count} member report${e.member_count===1?``:`s`}`} · ${`${e.qualified_refs} qualified upstream reference${e.qualified_refs===1?``:`s`}`}`}var f=bo(),p=V(z(f),2),m=e=>{var t=io(),n=R(t),r=V(n);M(t),H(()=>Y(n,`Refresh failed: ${G(a)??``} `)),K(`click`,r,c),J(e,t)};X(p,e=>{G(a)!==null&&e(m)});var h=V(p,2),g=e=>{J(e,ao())},_=e=>{let t=P(()=>G(o).incident),n=P(()=>Ci(G(t).opened_at)),r=P(()=>Ci(G(t).closed_at)),i=P(()=>Ci(G(t).window_start)),a=P(()=>Ci(G(t).last_member_at));var c=yo(),f=z(c),p=B(f,!0),m=V(f,2),h=R(m),g=B(h,!0),_=V(h,2),v=B(_),y=V(_,2),b=e=>{var n=oo(),i=V(R(n)),a=B(i,!0);M(n),H(()=>{Q(i,`datetime`,G(t).closed_at),Q(i,`title`,G(r).utc),Y(a,G(r).local)}),J(e,n)},x=e=>{var r=so(),i=V(R(r)),a=B(i,!0);M(r),H(()=>{Q(i,`datetime`,G(t).opened_at),Q(i,`title`,G(n).utc),Y(a,G(n).local)}),J(e,r)};X(y,e=>{G(t).status===`closed`&&G(t).closed_at?e(b):e(x,-1)}),M(m);var S=V(m,2),C=V(R(S),2),w=B(C),T=V(C,2),ee=B(T),te=V(T,2),E=V(R(te)),D=B(E,!0),ne=V(E,2),re=B(ne,!0);M(te),M(S);var ie=V(S,2),O=V(R(ie),2),ae=B(O,!0),oe=V(O,2),se=e=>{J(e,co())};X(oe,e=>{G(t).qualified_refs{J(e,lo())};X(ce,e=>{G(o).truncated&&e(le)});var ue=V(ce,2),de=e=>{J(e,uo())},k=e=>{var t=po();Z(t,21,()=>G(o).members,e=>e.briefing_id,(e,t)=>{let n=P(()=>Ci(G(t).created_at));var r=fo(),i=R(r),a=B(i,!0),o=V(i,2),s=B(o,!0),c=V(o,2),l=B(c,!0),u=B(V(c,2));M(r),H(()=>{Q(i,`href`,`#/briefing/${G(t).briefing_id}`),Y(a,G(t).briefing_id),Y(s,G(t).priority),Q(c,`datetime`,G(t).created_at),Q(c,`title`,G(n).utc),Y(l,G(n).local),Y(u,`${G(t).refs.length??``} qualified reference${G(t).refs.length===1?``:`s`}`)}),J(e,r)}),M(t),J(e,t)};X(ue,e=>{G(o).members.length===0?e(de):e(k,-1)}),M(ie);var fe=V(ie,2),pe=e=>{let t=P(()=>G(o).summary);var n=vo(),r=V(R(n),2),i=B(R(r));M(r);var a=V(r,2),s=e=>{var n=mo(),r=B(n,!0);H(()=>Y(r,G(t).summary)),J(e,n)};X(a,e=>{G(t).summary&&e(s)});var c=V(a,2),l=e=>{var n=ho(),r=V(R(n));M(n),H(()=>Y(r,` ${G(t).hypothesis??``}`)),J(e,n)};X(c,e=>{G(t).hypothesis&&e(l)});var u=V(c,2),d=e=>{var n=mo(),r=B(n);H(()=>Y(r,`Display confidence: ${G(t).confidence??``}`)),J(e,n)};X(u,e=>{G(t).confidence&&e(d)});var f=V(u,2),p=B(f),m=V(f,2),h=e=>{var n=mo(),r=B(n);H(()=>Y(r,`Priority explanation: ${G(t).reason??``}`)),J(e,n)};X(m,e=>{G(t).reason&&e(h)});var g=V(m,2),_=B(g),v=V(g,2),y=e=>{var n=_o(),r=V(z(n),2);Z(r,21,()=>G(t).citations,e=>e.member,(e,t)=>{var n=go(),r=R(n),i=V(r),a=B(i,!0);M(n),H(()=>{Y(r,`${G(t).member??``}: `),Q(i,`href`,`#/briefing/${G(t).briefing_id}`),Y(a,G(t).briefing_id)}),J(e,n)}),M(r),J(e,n)};X(v,e=>{G(t).citations.length&&e(y)});var b=V(v,2),x=e=>{var n=mo(),r=B(n,!0);H(()=>Y(r,G(t).error)),J(e,n)};X(b,e=>{G(t).error&&e(x)}),M(n),H(()=>{Y(i,`Summary status: ${G(t).status??``}`),Y(p,`Priority floor: ${G(t).floor??``}. Resolved priority: ${G(t).final_priority??``}${G(t).suggestion?` (suggested ${G(t).suggestion}${G(t).clamped?`, clamped`:``})`:` (no model raise)`}`),Y(_,`Evidence coverage: ${G(t).sampled??``} sampled member reports; ${G(t).omitted??``} omitted. The sample may not represent every member.`)}),J(e,n)};X(fe,e=>{G(o).summary&&e(pe)});var me=V(fe,2);{let e=P(()=>G(o).decisions??[]),n=P(()=>G(o).effective_review??null);ra(me,{subjectKind:`incident`,get subjectId(){return G(t).incident_id},kinds:[`expected`,`not_expected`,`snooze`,`note`],get decisions(){return G(e)},get effective(){return G(n)},memberScope:!0,get memberCount(){return G(t).member_count},get kindHelp(){return u},reload:s})}H(e=>{Y(p,l[G(t).kind]??G(t).kind),Y(g,G(t).status),Y(v,`Floor: ${G(t).floor??``}`),Y(w,`Source: ${G(t).source_scope??``}`),Y(ee,`Target: ${G(t).target??``}`),Q(E,`datetime`,G(t).window_start),Q(E,`title`,G(i).utc),Y(D,G(i).local),Q(ne,`datetime`,G(t).last_member_at),Q(ne,`title`,G(a).utc),Y(re,G(a).local),Y(ae,e)},[()=>d(G(t))]),J(e,c)};X(h,e=>{G(o)===null?e(g):e(_,-1)}),J(e,f),Be()}ur([`click`]);var So=q(`
                • `),Co=q(`
                    `),wo=q(`, last - change `,1),To=q(`

                      `);function Eo(e,t){ze(t,!0);let n=$(t,`reasons`,19,()=>[]);var r=To(),i=R(r),a=B(i),o=V(i,2),s=R(o),c=B(s,!0),l=V(s,2);Z(l,20,()=>[`quiet`,`review`,`act`],e=>e,(e,n)=>{var r=So(),i=B(r,!0);H(()=>{Q(r,`aria-current`,t.verdict===n?`true`:void 0),Y(i,n)}),J(e,r)}),M(l),M(o);var u=V(o,2),d=R(u),f=B(d),p=V(d,2),m=B(p),h=B(V(p,2));M(u);var g=V(u,2),_=e=>{var t=Co();Z(t,20,n,e=>e,(e,t)=>{var n=So(),r=B(n,!0);H(()=>Y(r,t)),J(e,n)}),M(t),J(e,t)};X(g,e=>{n().length>0&&e(_)});var v=V(g,2),y=R(v),b=V(y),x=e=>{var n=wo(),r=V(z(n)),i=B(r,!0);H(e=>{Q(r,`datetime`,t.lastChange),Q(r,`title`,t.lastChange),Y(i,e)},[()=>new Date(t.lastChange).toLocaleString()]),J(e,n)};X(b,e=>{t.lastChange&&e(x)}),M(v),M(r),H((e,n)=>{Q(r,`data-verdict`,t.verdict),Y(a,`Review overview · last ${e??``}`),Y(c,t.headline),Y(f,`Verdict: ${t.verdict??``}`),Q(p,`data-state`,t.coverage),Y(m,`Coverage: ${t.coverage??``}`),Y(h,`Liveness: ${t.liveness??``}`),Y(y,`${t.receipts??``} ${t.receipts===1?`receipt`:`receipts`} in the last ${n??``}`)},[()=>Oi(t.window),()=>Oi(t.window)]),J(e,r),Be()}var Do=q(`

                      Nothing flagged. New briefings appear here when the bridge reports them.

                      `),Oo=q(` `,1),ko=q(``),Ao=q(``),jo=q(`
                      `),Mo=q(`

                      `),No=q(`
                    1. `),Po=q(`
                        `),Fo=q(` `,1),Io=q(`
                      1. `),Lo=q(`
                          `),Ro=q(`

                          `);function zo(e,t){ze(t,!0);let n=$(t,`items`,19,()=>[]),r=$(t,`selectedId`,3,null),i=$(t,`titles`,19,()=>({})),a=$(t,`onselect`,3,null),o=I(Ut({})),s=I(Ut({})),c=I(Ut({})),l=I(Ut({})),u=!0,d=0;si(()=>(window.addEventListener(`watcherbridge:incident`,f),()=>window.removeEventListener(`watcherbridge:incident`,f)));function f(){d++,L(s,{},!0),L(c,{},!0),L(l,{},!0),L(o,Object.fromEntries(n().filter(e=>e.kind===`incident`&&G(o)[e.id]).map(e=>[e.id,!0])),!0);for(let e of Object.keys(G(o)))m(e)}ci(()=>{u=!1});async function p(e){G(o)[e]?G(o)[e]=!1:(G(o)[e]=!0,G(s)[e]!==void 0||G(l)[e]||await m(e))}async function m(e){let t=d;delete G(c)[e],G(l)[e]=!0;try{let n=await yi(e);u&&t===d&&(G(s)[e]=n.members)}catch(n){u&&t===d&&(G(c)[e]=n instanceof Error?n.message:String(n))}finally{u&&t===d&&(G(l)[e]=!1)}}var h=Ro(),g=R(h),_=B(g),v=V(g,2),y=e=>{J(e,Do())},b=e=>{var t=Lo();Z(t,21,n,e=>e.id,(e,t)=>{var n=Io();{let e=e=>{var n=Oo(),r=z(n),a=B(r,!0),o=V(r,2),s=R(o),c=B(s),l=B(V(s),!0);M(o);var u=V(o,2),d=R(u),f=B(d,!0),p=V(d),m=B(p,!0);M(u),H((e,n)=>{Q(r,`data-priority`,G(t).priority),Q(r,`aria-label`,`Priority: ${G(t).priority}`),Y(a,G(t).priority),Y(c,`${G(t).kind===`incident`?`Incident · `:``}${e??``}`),Y(l,G(t).id),Y(f,G(t).status),Q(p,`datetime`,G(t).created_at),Q(p,`title`,G(t).created_at),Y(m,n)},[()=>G(t).kind===`briefing`?i()[G(t).id]??Di(G(t).change_kind):Ei(G(t).change_kind),()=>new Date(G(t).created_at).toLocaleString()]),J(e,n)};var u=R(n),d=n=>{var i=yr(),o=z(i),s=n=>{var i=ko(),o=R(i);e(o),M(i),H(()=>Q(i,`aria-current`,r()===G(t).id?`true`:void 0)),K(`click`,i,()=>a()(G(t))),J(n,i)},c=n=>{var r=Ao(),i=R(r);e(i),M(r),H(()=>Q(r,`href`,G(t).kind===`briefing`?`#/briefing/${G(t).id}`:`#/incidents/${G(t).id}`)),J(n,r)};X(o,e=>{a()?e(s):e(c,-1)}),J(n,i)},f=t=>{var n=jo(),r=R(n);e(r),M(n),J(t,n)};X(u,e=>{G(t).kind===`briefing`||G(t).kind===`incident`?e(d):e(f,-1)});var m=V(u,2),h=e=>{var n=Fo(),r=z(n),i=B(r,!0),a=V(r,2),u=e=>{var n=Mo(),r=B(n,!0);H(()=>Y(r,G(c)[G(t).id])),J(e,n)};X(a,e=>{G(c)[G(t).id]!==void 0&&e(u)});var d=V(a,2),f=e=>{var n=Po();Z(n,21,()=>G(s)[G(t).id],e=>e.briefing_id,(e,t)=>{var n=No(),r=R(n),i=B(r,!0),a=B(V(r,2),!0);M(n),H(()=>{Q(r,`href`,`#/briefing/${G(t).briefing_id}`),Y(i,G(t).briefing_id),Y(a,G(t).priority)}),J(e,n)}),M(n),J(e,n)};X(d,e=>{(G(o)[G(t).id]??!1)&&G(s)[G(t).id]!==void 0&&e(f)}),H(()=>{Q(r,`aria-expanded`,G(o)[G(t).id]??!1),r.disabled=G(l)[G(t).id]??!1,Y(i,G(o)[G(t).id]?`Hide members`:G(l)[G(t).id]?`Loading members…`:`Show members`)}),K(`click`,r,()=>p(G(t).id)),J(e,n)};X(m,e=>{G(t).kind===`incident`&&e(h)}),M(n)}H(()=>Q(n,`data-status`,G(t).status)),J(e,n)}),M(t),J(e,t)};X(v,e=>{n().length===0?e(y):e(b,-1)}),M(h),H(()=>Y(_,`Needs attention (${n().length??``})`)),J(e,h),Be()}ur([`click`]);var Bo=q(`
                          `),Vo=q(`

                          Reported changes

                          Counts in this review window. Expected means explicitly marked by you.

                          `);function Ho(e,t){ze(t,!0);let n=[`weak_appearance`,`weak_disappearance`,`port_closed`,`hostname_change`,`os_refinement`,`other`],r=$(t,`digest`,19,()=>({})),i=$(t,`explained`,19,()=>({}));var a=Vo(),o=V(R(a),4);Z(o,20,()=>n,e=>e,(e,t)=>{var n=Bo(),a=R(n),o=B(a,!0),s=V(a,2),c=R(s),l=B(V(c));M(s),M(n),H(e=>{Y(o,e),Y(c,`${r()[t]??0??``} `),Y(l,`expected ${i()[t]??0??``}`)},[()=>Ei(t)]),J(e,n)}),M(o),M(a),J(e,a),Be()}var Uo=q(`

                          No sources registered yet.

                          `),Wo=q(`Last report `),Go=q(`
                        1. `),Ko=q(`
                            `),qo=q(`
                          • `),Jo=q(`
                              `),Yo=q(`

                              `);function Xo(e,t){ze(t,!0);let n=$(t,`sources`,19,()=>[]);var r=Yo(),i=R(r),a=B(i),o=V(i,2),s=e=>{J(e,Uo())},c=e=>{var t=Jo();Z(t,21,n,e=>e.scope,(e,t)=>{var n=qo(),r=R(n),i=B(r,!0),a=V(r,2),o=B(a),s=V(a,2),c=B(s),l=V(s,2),u=e=>{var n=Wo(),r=V(R(n)),i=B(r,!0);M(n),H(e=>{Q(r,`datetime`,G(t).last_report_at),Q(r,`title`,G(t).last_report_at),Y(i,e)},[()=>new Date(G(t).last_report_at).toLocaleString()]),J(e,n)};X(l,e=>{G(t).last_report_at&&e(u)});var d=V(l,2),f=e=>{var n=Ko();Z(n,20,()=>G(t).reasons,e=>e,(e,t)=>{var n=Go(),r=B(n,!0);H(()=>Y(r,t)),J(e,n)}),M(n),J(e,n)};X(d,e=>{G(t).reasons.length>0&&e(f)}),M(n),H(()=>{Y(i,G(t).scope),Y(o,`Status: ${G(t).status??``}`),Y(c,`Liveness: ${G(t).liveness??``}`)}),J(e,n)}),M(t),J(e,t)};X(o,e=>{n().length===0?e(s):e(c,-1)}),M(r),H(()=>Y(a,`Sources (${n().length??``})`)),J(e,r),Be()}var Zo=q(`

                              Overview unavailable

                              `),Qo=q(`

                              Loading overview…

                              `),$o=q(`

                              `),es=q(``),ts=q(`

                              Jump to selected review ↓

                              `),ns=q(`
                              Selected review Open full page →
                              `,1),rs=q(`

                              Select a review

                              Choose an item in Needs attention to read its evidence and recommended check, and record your decision.

                              New reports update the list automatically.

                              `),is=q(`
                              `),as=q(`

                              j k move between rows · Enter select · ? shortcuts

                              `,1);function os(e,t){ze(t,!0);let n=$(t,`overview`,3,null),r=$(t,`loadError`,3,null),i=$(t,`selected`,15,null),a=P(()=>i()?.id??null),o=I(Ut({}));function s(e,t){G(o)[e]!==t&&L(o,Object.fromEntries([...Object.entries(G(o)),[e,t]].slice(-32)),!0)}function c(e){i({id:e.id,kind:e.kind})}function l(){i(null),document.getElementById(`review-list`)?.focus()}let u=P(()=>n()!==null&&(n().coverage===`degraded`||n().coverage===`blind`));var d=yr(),f=z(d),p=e=>{var t=Zo(),n=B(V(R(t),2));M(t),H(()=>Y(n,`The bridge did not return an overview (${r()??``}). The connection retries automatically.`)),J(e,t)},m=e=>{J(e,Qo())},h=e=>{var t=as(),r=z(t),d=e=>{var t=$o(),r=B(t);H(()=>Y(r,`No receipts in the last ${n().window??``} — quiet here means no data, not a secure network.`)),J(e,t)};X(r,e=>{n().receipts===0&&e(d)});var f=V(r,2),p=e=>{var t=es(),r=B(t);H(()=>Y(r,`Coverage is ${n().coverage??``}. Treat quiet results with caution until the reasons below clear.`)),J(e,t)};X(f,e=>{G(u)&&e(p)});var m=V(f,2);{let e=P(()=>n().reasons??[]);Eo(m,{get verdict(){return n().verdict},get headline(){return n().headline},get coverage(){return n().coverage},get liveness(){return n().liveness},get reasons(){return G(e)},get receipts(){return n().receipts},get window(){return n().window},get lastChange(){return n().last_change}})}var h=V(m,2),g=R(h),_=R(g);zo(_,{get items(){return n().attention},get selectedId(){return G(a)},get titles(){return G(o)},onselect:c});var v=V(_,2),y=e=>{var t=ts();K(`click`,B(t),e=>{e.preventDefault(),document.getElementById(`selected-review`)?.focus()}),J(e,t)};X(v,e=>{i()&&e(y)});var b=V(v,2);{let e=P(()=>n().explained??{});Ho(b,{get digest(){return n().digest},get explained(){return G(e)}})}Xo(V(b,2),{get sources(){return n().sources}}),ye(2),M(g);var x=V(g,2),S=e=>{var t=is(),n=R(t),r=e=>{var t=ns(),n=z(t),r=V(R(n),2),a=V(r,2);M(n),Ar(V(n,2),()=>i().id,e=>{var t=yr(),n=z(t),r=e=>{ro(e,{get id(){return i().id},embedded:!0,ontitle:s})},a=e=>{xo(e,{get id(){return i().id}})};X(n,e=>{i().kind===`briefing`?e(r):e(a,-1)}),J(e,t)}),H(()=>Q(r,`href`,i().kind===`briefing`?`#/briefing/${i().id}`:`#/incidents/${i().id}`)),K(`click`,a,l),J(e,t)},a=e=>{J(e,rs())};X(n,e=>{i()?e(r):e(a,-1)}),M(t),J(e,t)};X(x,e=>{(i()!==null||n().attention.length>0)&&e(S)}),M(h),H(()=>Q(h,`data-empty`,n().attention.length===0&&i()===null)),J(e,t)};X(f,e=>{r()!==null&&n()===null?e(p):n()===null?e(m,1):e(h,-1)}),J(e,d),Be()}ur([`click`]);function ss(e,t,n){let r=()=>{t.dispatchEvent(new Event(`watcherbridge:incident`)),n()},i=[`open`,`incident`,`resync`];for(let t of i)e.addEventListener(t,r);return()=>{for(let t of i)e.removeEventListener(t,r)}}function cs(e,t,n,r){let i=new Set(e.map(n)),a=[];for(let o of t){if(e.length+a.length>=r)break;i.has(n(o))||(i.add(n(o)),a.push(o))}return a}var ls=q(`

                              Loading reported hosts…

                              `),us=q(`

                              `,1),ds=q(`

                              Connection recovered — this list may miss new reports.

                              `),fs=q(`

                              No reported subjects retained.

                              `),ps=q(`
                            • Last report
                            • `),ms=q(`
                                `),hs=q(`

                                `),gs=q(`

                                `),_s=q(``),vs=q(`

                                End of retained list.

                                `),ys=q(` `,1),bs=q(`

                                Reported hosts

                                Scanner-reported subjects. Classes distinguish device references, address context, unresolved events and legacy profiles.

                                `);function xs(e,t){ze(t,!0);let n=$(t,`initial`,3,null),r=bi();ci(()=>r.invalidate());let i=I(Ut([])),a=I(null),o=I(!1),s=I(null),c=I(!0),l=I(!1),u=I(!1),d=P(()=>G(o)?[]:n()?.devices??[]),f=P(()=>[...G(d),...G(i)]),p=P(()=>G(a)??(G(o)?``:n()?.next_after??``)),m=P(()=>G(p)===``),h=P(()=>!G(m)&&G(f).length>=200),g=!1;un(()=>{let e=t.stream===`live`,n=e&&!g&&G(f).length>0;g=e,n&&L(l,!0)});function _(){L(c,!0),L(u,!0),v(!0)}async function v(e=!1){let t=r.start(),n=e?``:G(p);L(s,null);try{let s=await gi(n);if(!r.current(t))return;let d=cs(e?[]:G(f),s.devices,e=>e.profile_id,200);e?(L(o,!0),L(i,d,!0),L(l,!1)):L(i,[...G(i),...d],!0),L(a,s.next_after??``,!0),L(c,!1),L(u,!1)}catch(e){r.current(t)&&(L(s,e instanceof Error?e.message:String(e),!0),L(c,!1))}}si(()=>{n()===null?v():L(c,!1)});var y=bs(),b=V(R(y),4),x=e=>{J(e,ls())},S=e=>{var t=us(),n=z(t),r=B(n),i=V(n,2);H(()=>Y(r,`The bridge did not return reported hosts (${G(s)??``}).`)),K(`click`,i,()=>v()),J(e,t)},C=e=>{var t=ys(),n=z(t),r=e=>{var t=ds(),n=V(R(t));M(t),K(`click`,n,_),J(e,t)};X(n,e=>{G(l)&&e(r)});var i=V(n,2),a=e=>{J(e,fs())},o=e=>{var t=ms();Z(t,21,()=>G(f),e=>e.profile_id,(e,t)=>{let n=P(()=>Ci(G(t).last_report_at));var r=ps(),i=R(r),a=V(R(i),2),o=R(a),s=B(o,!0),c=V(o),l=B(c,!0),u=B(V(c),!0);M(a);var d=V(a,2),f=V(R(d)),p=B(f,!0);M(d),ye(2),M(i),M(r),H(e=>{Q(i,`href`,`#/devices/${G(t).profile_id}`),Y(s,G(t).operator_label||G(t).reported_id||`Unlabelled subject`),Y(l,G(t).profile_id),Y(u,e),Q(f,`datetime`,G(t).last_report_at),Q(f,`title`,G(n).utc),Y(p,G(n).local)},[()=>Ti(G(t).class)]),J(e,r)}),M(t),J(e,t)};X(i,e=>{G(f).length===0?e(a):e(o,-1)});var c=V(i,2),d=e=>{var t=hs(),n=R(t),r=V(n);M(t),H(()=>Y(n,`Page failed (${G(s)??``}) — earlier rows kept. `)),K(`click`,r,()=>v(G(u))),J(e,t)};X(c,e=>{G(s)!==null&&e(d)});var p=V(c,2),g=e=>{var t=gs();t.textContent=`List capped at 200 rows; use the API for the full set.`,J(e,t)},y=e=>{var t=_s();K(`click`,t,()=>v()),J(e,t)},b=e=>{J(e,vs())};X(p,e=>{G(h)?e(g):G(m)?e(b,-1):e(y,1)}),J(e,t)};X(b,e=>{G(c)&&G(f).length===0?e(x):G(s)!==null&&G(f).length===0?e(S,1):e(C,-1)}),M(y),J(e,y),Be()}ur([`click`]);var Ss=q(`

                                Reported host unavailable

                                Back to reported hosts

                                `),Cs=q(`

                                Loading reported host…

                                `),ws=q(`

                                Connection recovered — this page may miss new reports.

                                `),Ts=q(`

                                `),Es=q(`

                                Earlier bridge-inferred association; not used for current identity.

                                `),Ds=q(`

                                `),Os=q(`
                                Your label
                                `,1),ks=q(`

                                No retained observation.

                                `),As=q(`
                                `,1),js=q(`
                              • `),Ms=q(`
                                  `),Ns=q(`

                                  Reported

                                  `,1),Ps=q(`

                                  No retained reports in this window.

                                  `),Fs=q(`
                                • `),Is=q(`
                                    `),Ls=q(`

                                    `),Rs=q(``),zs=q(`

                                    End of retained history. Retention policy lives on the Health screen.

                                    `),Bs=q(`

                                    Back to reported hosts

                                    Source scope
                                    Upstream reference
                                    Reported by
                                    Association
                                    First report
                                    Last report

                                    Latest evidence

                                    History

                                    `);function Vs(e,t){ze(t,!0);let n=$(t,`initial`,3,null),r=bi();ci(()=>r.invalidate());let i=I(null),a=I(Ut([])),o=I(null),s=I(!1),c=I(null),l=I(null),u=I(null),d=I(!1),f=P(()=>G(i)??n()),p=P(()=>G(s)?[]:n()?.history??[]),h=P(()=>[...G(p),...G(a)]),g=P(()=>G(o)??(G(s)?``:n()?.history_next_after??``)),_=P(()=>G(f)!==null&&G(g)===``),v=P(()=>!G(_)&&G(h).length>=200),y=!1;un(()=>{let e=t.stream===`live`,n=e&&!y&&G(f)!==null;y=e,n&&L(d,!0)});async function b(){r.invalidate();let e=r.start();L(l,null),L(u,null);try{let n=await _i(t.id);if(!r.current(e))return;L(i,n,!0),L(s,!0),L(a,n.history??[],!0),L(o,n.history_next_after??``,!0),L(c,null),L(d,!1)}catch(t){if(r.current(e)){let e=t instanceof Error?t.message:String(t);G(f)===null?L(l,e,!0):L(u,e,!0)}}}async function x(){let e=r.start(),n=G(g);L(c,null);try{let i=await _i(t.id,n);if(!r.current(e))return;L(a,[...G(a),...cs(G(h),i.history,e=>e.observation_id,200)],!0),L(o,i.history_next_after??``,!0)}catch(t){r.current(e)&&L(c,t instanceof Error?t.message:String(t),!0)}}si(()=>{n()===null&&b()});let S=P(()=>G(f)===null?null:Ci(G(f).first_report_at)),C=P(()=>G(f)===null?null:Ci(G(f).last_report_at));var w=yr(),T=z(w),ee=e=>{var t=Ss(),n=V(R(t),2),r=B(n),i=V(n,2),a=V(R(i),2);M(i),M(t),H(()=>Y(r,`The bridge did not return this profile (${G(l)??``}).`)),K(`click`,a,b),J(e,t)},te=e=>{J(e,Cs())},E=e=>{let t=P(()=>G(f).latest===null?null:Ci(G(f).latest.reported_at));var n=Bs(),r=V(R(n),2),i=e=>{var t=ws(),n=V(R(t));M(t),K(`click`,n,b),J(e,t)};X(r,e=>{G(d)&&e(i)});var a=V(r,2),o=e=>{var t=Ts(),n=R(t),r=V(n);M(t),H(()=>Y(n,`Refresh failed (${G(u)??``}) — showing retained data. `)),K(`click`,r,b),J(e,t)};X(a,e=>{G(u)!==null&&e(o)});var s=V(a,2),l=B(s),p=V(s,2),g=e=>{J(e,Es())},y=e=>{var t=Ds(),n=B(t);H(()=>Y(n,`This page describes ${G(f).class===`address`?`address context`:`unresolved events`}, not a device.`)),J(e,t)};X(p,e=>{G(f).class===`legacy`?e(g):(G(f).class===`address`||G(f).class===`event`)&&e(y,1)});var w=V(p,2),T=V(R(w),2),ee=B(T,!0),te=V(T,4),E=B(te,!0),D=V(te,4),ne=B(D),re=V(D,4),ie=B(re,!0),O=V(re,2),ae=e=>{var t=Os(),n=B(V(z(t),2),!0);H(()=>Y(n,G(f).operator_label)),J(e,t)};X(O,e=>{G(f).operator_label!==null&&G(f).operator_label!==void 0&&e(ae)});var oe=V(O,4),se=R(oe),ce=B(se,!0);M(oe);var le=V(oe,4),ue=R(le),de=B(ue,!0);M(le),M(w);var k=V(w,2);{let e=P(()=>G(f).decisions??[]);ra(k,{subjectKind:`reported_subject`,get subjectId(){return G(f).profile_id},kinds:[`note`,`label`],get decisions(){return G(e)},reload:b})}var fe=V(k,2),pe=V(R(fe),2),me=e=>{J(e,ks())},he=e=>{var n=Ns(),r=z(n),i=V(R(r)),a=B(i,!0),o=V(i);M(r);var s=V(r,2);Z(s,21,()=>Object.entries(G(f).latest.attributes??{}),([e,t])=>e,(e,t)=>{var n=P(()=>m(G(t),2));let r=()=>G(n)[0],i=()=>G(n)[1];var a=As(),o=z(a),s=B(o,!0),c=B(V(o,2),!0);H(e=>{Y(s,r()),Y(c,e)},[()=>JSON.stringify(i())]),J(e,a)}),M(s);var c=V(s,2),l=e=>{var t=Ms();Z(t,21,()=>G(f).latest.ports,e=>`${e.proto}/${e.port}`,(e,t)=>{var n=js(),r=B(n);H(()=>Y(r,`${G(t).proto??``}/${G(t).port??``} ${G(t).state??``}${G(t).service?` (${G(t).service})`:``}`)),J(e,n)}),M(t),J(e,t)};X(c,e=>{(G(f).latest.ports??[]).length>0&&e(l)});var u=B(V(c,2));H(()=>{Q(i,`datetime`,G(f).latest.reported_at),Q(i,`title`,G(t)?.utc),Y(a,G(t)?.local),Y(o,` (${G(f).latest.view_role??``}).`),Y(u,`Snapshot covers ${G(f).latest.ports_total??``} ports${G(f).latest.ports_truncated?` (truncated)`:``}.`)}),J(e,n)};X(pe,e=>{G(f).latest===null?e(me):e(he,-1)}),M(fe);var A=V(fe,2),ge=V(R(A),2),j=e=>{J(e,Ps())},_e=e=>{var t=Is();Z(t,21,()=>G(h),e=>e.observation_id,(e,t)=>{let n=P(()=>Ci(G(t).reported_at));var r=Fs(),i=R(r),a=V(i),o=B(a,!0),s=V(a);M(r),H(()=>{Y(i,`${G(t).event_id??``} (${G(t).view_role??``}) — `),Q(a,`datetime`,G(t).reported_at),Q(a,`title`,G(n).utc),Y(o,G(n).local),Y(s,`, - ${G(t).ports_total??``} ports${G(t).ports_truncated?` (truncated)`:``}`)}),J(e,r)}),M(t),J(e,t)};X(ge,e=>{G(h).length===0?e(j):e(_e,-1)});var ve=V(ge,2),ye=e=>{var t=Ts(),n=R(t),r=V(n);M(t),H(()=>Y(n,`Older page failed (${G(c)??``}). `)),K(`click`,r,x),J(e,t)};X(ve,e=>{G(c)!==null&&e(ye)});var be=V(ve,2),xe=e=>{var t=Ls();t.textContent=`History capped at 200 rows; use the API for the full set.`,J(e,t)},Se=e=>{var t=Rs();K(`click`,t,x),J(e,t)},Ce=e=>{J(e,zs())};X(be,e=>{G(v)?e(xe):G(_)?e(Ce,-1):e(Se,1)}),M(A),M(n),H(e=>{Y(l,`${G(f).profile_id??``} — ${e??``}`),Y(ee,G(f).source_scope),Y(E,G(f).reported_id),Y(ne,`${G(f).reported_source??``} (confidence: ${(G(f).reported_confidence||`unknown`)??``})`),Y(ie,G(f).association_status),Q(se,`datetime`,G(f).first_report_at),Q(se,`title`,G(S)?.utc),Y(ce,G(S)?.local),Q(ue,`datetime`,G(f).last_report_at),Q(ue,`title`,G(C)?.utc),Y(de,G(C)?.local)},[()=>Ti(G(f).class)]),J(e,n)};X(T,e=>{G(l)!==null&&G(f)===null?e(ee):G(f)===null?e(te,1):e(E,-1)}),J(e,w),Be()}ur([`click`]);function Hs(e){return e==null?!1:e.status!==`completed`||(e.error??``)!==``}var Us=q(`

                                    `,1),Ws=q(`

                                    Loading health…

                                    `),Gs=q(`
                                  1. `),Ks=q(`
                                      `),qs=q(`

                                      `),Js=q(`

                                      `),Ys=q(`

                                      No sources registered.

                                      `),Xs=q(`
                                      Last completed scan
                                      Scan result
                                      Reported host records
                                      Signing clock offset
                                      `,1),Zs=q(`
                                      Last report
                                      `,1),Qs=q(`
                                      Delivery
                                      `,1),$s=q(`

                                      Liveness
                                      Identity namespace
                                      Identity capability
                                      Heartbeat
                                      `),ec=q(`
                                      `,1),tc=q(`

                                      ; - policy only — it never proves a per-profile boundary. Ask the API for per-profile history.

                                      `),nc=q(`

                                      `),rc=q(`

                                      No fully successful purge recorded yet.

                                      `),ic=q(`
                                      Publisher
                                      Posted
                                      Dropped
                                      Failed
                                      `),ac=q(`

                                      Summary

                                      Coverage
                                      Fallback briefings · 1h
                                      Awaiting operator
                                      Forward errors · 1h
                                      Ingest queue
                                      Pipeline (process lifetime)
                                      Started
                                      Ingest accepted
                                      Ingest duplicates
                                      Ingest rejected
                                      Ingest saturated
                                      Provider calls
                                      Provider fallbacks
                                      Redaction blocked
                                      Writer saturated
                                      Purge
                                      `,1),oc=q(`

                                      Health

                                      Source coverage, processing, and retention. Liveness describes the source, not host presence.

                                      `);function sc(e,t){ze(t,!0);let n=$(t,`initial`,3,null),r=bi();ci(()=>r.invalidate());let i=I(null),a=I(null),o=I(null),s=P(()=>G(i)??n());async function c(){r.invalidate();let e=r.start();L(a,null),L(o,null);try{let t=await vi();r.current(e)&&L(i,t,!0)}catch(t){if(r.current(e)){let e=t instanceof Error?t.message:String(t);G(s)===null?L(a,e,!0):L(o,e,!0)}}}si(()=>{n()===null&&c()});let l=!1;un(()=>{let e=t.stream===`live`,n=e&&!l&&G(i)!==null;l=e,n&&c()});function u(e){return`${Math.floor(e/86400)} days`}var d=oc(),f=V(R(d),4),p=e=>{var t=Us(),n=z(t),r=B(n),i=V(n,2);H(()=>Y(r,`The bridge did not return health (${G(a)??``}).`)),K(`click`,i,c),J(e,t)},h=e=>{J(e,Ws())},g=e=>{var t=ac(),n=z(t),r=V(R(n),2),i=R(r),a=V(R(i)),l=R(a),d=B(l,!0);M(a),M(i);var f=V(i,2),p=V(R(f)),h=R(p),g=B(V(h));M(p),M(f);var _=V(f,2),v=B(V(R(_)),!0);M(_);var y=V(_,2),b=B(V(R(y)),!0);M(y);var x=V(y,2),S=V(R(x)),C=R(S),w=B(V(C));M(S),M(x),M(r);var T=V(r,2),ee=e=>{var t=Ks();Z(t,20,()=>G(s).coverage_reasons,e=>e,(e,t)=>{var n=Gs(),r=B(n,!0);H(()=>Y(r,t)),J(e,n)}),M(t),J(e,t)};X(T,e=>{(G(s).coverage_reasons??[]).length>0&&e(ee)});var te=V(T,2),E=e=>{let t=P(()=>Ci(G(s).purge.last.finished_at??G(s).purge.last.started_at));var n=qs(),r=B(n);H(()=>Y(r,`Latest purge run ${G(s).purge.last.status??``} - (${G(t).local??``})${G(s).purge.last.error?`: ${G(s).purge.last.error}`:``}.`)),J(e,n)},D=P(()=>Hs(G(s).purge.last));X(te,e=>{G(D)&&e(E)});var ne=V(te,2),re=e=>{var t=Js(),n=R(t),r=V(n);M(t),H(()=>Y(n,`Refresh failed (${G(o)??``}) — showing retained data. `)),K(`click`,r,c),J(e,t)};X(ne,e=>{G(o)!==null&&e(re)}),M(n);var ie=V(n,2),O=R(ie),ae=B(O),oe=V(O,2),se=e=>{J(e,Ys())},ce=e=>{var t=yr();Z(z(t),17,()=>G(s).sources,e=>e.scope,(e,t)=>{var n=$s(),r=R(n),i=B(r),a=V(r,2),o=V(R(a),2),s=B(o),c=V(o,4),l=B(c,!0),u=V(c,4),d=B(u,!0),f=V(u,4),p=R(f),m=V(p),h=e=>{var n=vr();H(e=>Y(n,`— last at ${e??``}`),[()=>Ci(G(t).last_heartbeat_at).local]),J(e,n)};X(m,e=>{G(t).last_heartbeat_at&&e(h)}),M(f);var g=V(f,2),_=e=>{let n=P(()=>Ci(G(t).heartbeat.completed_at));var r=Xs(),i=V(z(r),2),a=R(i),o=B(a,!0);M(i);var s=V(i,4),c=B(s),l=V(s,4),u=B(l),d=B(V(l,4));H(()=>{Q(a,`datetime`,G(t).heartbeat.completed_at),Q(a,`title`,G(n).utc),Y(o,G(n).local),Y(c,`${G(t).heartbeat.status??``}, ${G(t).heartbeat.issue_count??``} ${G(t).heartbeat.issue_count===1?`issue`:`issues`}, ${G(t).heartbeat.duration_ms??``} ms`),Y(u,`${G(t).heartbeat.hosts_seen??``} — scan records, not a current inventory or device count`),Y(d,`${G(t).heartbeat.clock_skew_seconds??``} seconds (includes delivery delay)`)}),J(e,r)};X(g,e=>{G(t).heartbeat&&e(_)});var v=V(g,2),y=e=>{let n=P(()=>Ci(G(t).last_report_at));var r=Zs(),i=V(z(r),2),a=R(i),o=B(a,!0);M(i),H(()=>{Q(a,`datetime`,G(t).last_report_at),Q(a,`title`,G(n).utc),Y(o,G(n).local)}),J(e,r)};X(v,e=>{G(t).last_report_at&&e(y)});var b=V(v,2),x=e=>{var n=Qs(),r=B(V(z(n),2),!0);H(()=>Y(r,G(t).delivery_status)),J(e,n)};X(b,e=>{G(t).delivery_status&&e(x)}),M(a);var S=V(a,2),C=e=>{var n=Ks();Z(n,20,()=>G(t).reasons,e=>e,(e,t)=>{var n=Gs(),r=B(n,!0);H(()=>Y(r,t)),J(e,n)}),M(n),J(e,n)};X(S,e=>{(G(t).reasons??[]).length>0&&e(C)}),M(n),H(()=>{Q(n,`aria-label`,`Source ${G(t).scope}`),Y(i,`${G(t).scope??``} — ${G(t).status??``}`),Y(s,`${G(t).liveness??``}${G(t).liveness===`unknown`?` (no heartbeat capability; silence is not absence)`:``}`),Y(l,G(t).identity_namespace||`unknown — stable identity contract unavailable`),Y(d,G(t).capabilities||`not reported — heartbeat is not identity proof`),Y(p,`${G(t).heartbeat_enabled?`enabled (delivery opt-in, not identity proof)`:`disabled`} `)}),J(e,n)}),J(e,t)};X(oe,e=>{G(s).sources.length===0?e(se):e(ce,-1)}),M(ie);var le=V(ie,2),ue=V(R(le),2),de=V(R(ue),2),k=B(de,!0),fe=V(de,4),pe=B(fe,!0),me=V(fe,4),he=B(me,!0),A=V(me,4),ge=B(A,!0),j=V(A,4),_e=B(j,!0),ve=V(j,4),be=B(ve,!0),xe=V(ve,4),Se=B(xe,!0),Ce=V(xe,4),we=B(Ce,!0),Te=B(V(Ce,4),!0);M(ue),M(le);var Ee=V(le,2),De=V(R(Ee),2);Z(De,21,()=>Object.entries(G(s).purge.totals??{}),([e,t])=>e,(e,t)=>{var n=P(()=>m(G(t),2));let r=()=>G(n)[0],i=()=>G(n)[1];var a=ec(),o=z(a),s=B(o,!0),c=B(V(o,2),!0);H(()=>{Y(s,r()),Y(c,i())}),J(e,a)}),M(De);var Oe=V(De,2),ke=e=>{var t=tc(),n=R(t),r=V(n),i=e=>{var t=vr();H(e=>Y(t,`, ${e??``} for subjects`),[()=>u(G(s).retention.subjects_seconds)]),J(e,t)};X(r,e=>{G(s).retention.subjects_seconds!==void 0&&e(i)}),ye(),M(t),H(e=>Y(n,`Configured retention: ${e??``} for reports`),[()=>u(G(s).retention.reports_seconds)]),J(e,t)};X(Oe,e=>{G(s).retention&&e(ke)});var Ae=V(Oe,2),je=e=>{let t=P(()=>Ci(G(s).purge.last_success.finished_at??G(s).purge.last_success.started_at));var n=nc(),r=B(n);H(()=>Y(r,`Latest fully successful purge: ${G(t).local??``}.`)),J(e,n)},Me=e=>{J(e,rc())};X(Ae,e=>{G(s).purge.last_success?e(je):e(Me,-1)}),M(Ee);var Ne=V(Ee,2),Pe=e=>{var t=ic(),n=V(R(t),2),r=V(R(n),2),i=B(r,!0),a=V(r,4),o=B(a,!0),c=B(V(a,4),!0);M(n),M(t),H(()=>{Y(i,G(s).publisher.posted),Y(o,G(s).publisher.dropped),Y(c,G(s).publisher.failed)}),J(e,t)};X(Ne,e=>{G(s).publisher&&e(Pe)}),H(e=>{Q(l,`data-state`,G(s).coverage),Y(d,G(s).coverage),Y(h,`${G(s).fallback_1h.used??``} `),Y(g,`of ${G(s).fallback_1h.total??``}`),Y(v,G(s).parked_groups),Y(b,G(s).forward_errors_1h),Y(C,`${G(s).queue_depth??``} `),Y(w,`of ${G(s).queue_cap??``}`),Y(ae,`Sources (${G(s).sources.length??``})`),Y(k,e),Y(pe,G(s).process.ingest_accepted),Y(he,G(s).process.ingest_duplicates),Y(ge,G(s).process.ingest_rejected),Y(_e,G(s).process.ingest_saturated),Y(be,G(s).process.provider_calls),Y(Se,G(s).process.provider_fallbacks),Y(we,G(s).process.redaction_blocked),Y(Te,G(s).process.writer_saturated)},[()=>Ci(G(s).process.started_at).local]),J(e,t)};X(f,e=>{G(a)!==null&&G(s)===null?e(p):G(s)===null?e(h,1):e(g,-1)}),M(d),J(e,d),Be()}ur([`click`]);var cc=q(`

                                      `);function lc(e,t){let n={connecting:`Connecting…`,live:`Live briefing stream`,retrying:`Connection lost — retrying automatically…`};var r=cc(),i=V(R(r));M(r),H(()=>{Q(r,`data-state`,t.state),Y(i,` ${n[t.state]??t.state??``}`)}),J(e,r)}var uc=q(`

                                      Keyboard shortcuts

                                      • j / k — move between rows in a list
                                      • g then h — Home
                                      • g then d — Reported hosts
                                      • ? — toggle this list
                                      • e / s / x — on a briefing: preset expected / snooze / not-expected, then confirm

                                      Shortcuts stay silent while typing. Briefing keys preset the composer; nothing submits on its own.

                                      `),dc=q(`
                                      WatcherBridge

                                      WatcherBridge · Local review workspaceScanner reports are evidence, not a live inventory.
                                      `,1);function fc(e,t){ze(t,!0);let n=I(Ut(window.location.hash||`#/`)),r=I(null),i=I(null),a=I(`connecting`),o=I(!1),s=null,c=0,l=!1,u=0,d=bi();function f(e){let t=e||`#/`,n=t.match(/^#\/briefing\/(.+)$/);return n?{name:`briefing`,id:decodeURIComponent(n[1])}:(n=t.match(/^#\/incidents\/(.+)$/),n?{name:`incident`,id:decodeURIComponent(n[1])}:(n=t.match(/^#\/devices\/(.+)$/),n?{name:`device`,id:decodeURIComponent(n[1])}:t===`#/devices`||t===`#/devices/`?{name:`devices`}:t===`#/health`?{name:`health`}:{name:`home`}))}let p=P(()=>f(G(n)));async function m(){let e=d.start();try{let t=await li();d.current(e)&&(L(r,t,!0),L(i,null))}catch(t){d.current(e)&&G(r)===null&&L(i,t instanceof Error?t.message:String(t),!0)}}let h=()=>{};function g(){L(a,`connecting`),s=new EventSource(`/events`),h=ss(s,window,m),s.onopen=()=>{L(a,`live`)},s.addEventListener(`overview`,e=>{try{L(r,JSON.parse(e.data),!0),d.streamed(),L(i,null)}catch{}}),s.onerror=()=>{h(),L(a,`retrying`),s?.close(),s=null,c=window.setTimeout(g,2e3)}}function _(e){e.key===`?`&&!Si(e)?(L(o,!G(o)),e.preventDefault()):Si(e)?l=!1:l?(l=!1,window.clearTimeout(u),e.key===`h`?window.location.hash=`#/`:e.key===`d`&&(window.location.hash=`#/devices`)):e.key===`g`?(l=!0,window.clearTimeout(u),u=window.setTimeout(()=>{l=!1},1e3)):(e.key===`j`||e.key===`k`)&&xi(e.key===`j`?1:-1)&&e.preventDefault()}si(()=>{let e=()=>{L(n,window.location.hash||`#/`,!0)};return window.addEventListener(`hashchange`,e),window.addEventListener(`keydown`,_),L(n,window.location.hash||`#/`,!0),m(),g(),()=>{window.removeEventListener(`hashchange`,e),window.removeEventListener(`keydown`,_),window.clearTimeout(c),window.clearTimeout(u),h(),s?.close(),s=null}});var v=dc(),y=z(v),b=V(y,2),x=R(b),S=V(R(x),2),C=R(S),w=V(C,2),T=V(w,2),ee=V(T,2);M(S),lc(V(S,2),{get state(){return G(a)}}),M(x);var te=V(x,2),E=e=>{J(e,uc())};X(te,e=>{G(o)&&e(E)});var D=V(te,2),ne=R(D),re=B(ne,!0);Ar(V(ne,2),()=>G(n),e=>{var t=yr(),n=z(t),o=e=>{os(e,{get overview(){return G(r)},get loadError(){return G(i)}})},s=e=>{ro(e,{get id(){return G(p).id}})},c=e=>{xo(e,{get id(){return G(p).id}})},l=e=>{xs(e,{get stream(){return G(a)}})},u=e=>{Vs(e,{get id(){return G(p).id},get stream(){return G(a)}})},d=e=>{sc(e,{get stream(){return G(a)}})};X(n,e=>{G(p).name===`home`?e(o):G(p).name===`briefing`?e(s,1):G(p).name===`incident`?e(c,2):G(p).name===`devices`?e(l,3):G(p).name===`device`?e(u,4):G(p).name===`health`&&e(d,5)}),J(e,t)}),M(D),ye(2),M(b),H(()=>{Q(C,`aria-current`,G(p).name===`home`?`page`:void 0),Q(w,`aria-current`,G(p).name===`devices`||G(p).name===`device`?`page`:void 0),Q(T,`aria-current`,G(p).name===`health`?`page`:void 0),Q(ee,`aria-expanded`,G(o)),Y(re,{home:`Review overview`,devices:`Reported hosts`,device:`Reported host detail`,briefing:`Briefing`,incident:`Incident`,health:`Health`}[G(p).name])}),K(`click`,y,e=>{e.preventDefault(),document.getElementById(`content`)?.focus()}),K(`click`,ee,()=>L(o,!G(o))),J(e,v),Be()}ur([`click`]);var pc=document.getElementById(`app`);pc&&wr(fc,{target:pc}); \ No newline at end of file +(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var e=Array.isArray,t=Array.prototype.indexOf,n=Array.prototype.includes,r=Array.from,i=Object.defineProperty,a=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyDescriptors,s=Object.prototype,c=Array.prototype,l=Object.getPrototypeOf,u=Object.isExtensible,d=()=>{};function f(e){for(var t=0;t{e=n,t=r}),resolve:e,reject:t}}function m(e,t){if(Array.isArray(e))return e;if(t===void 0||!(Symbol.iterator in e))return Array.from(e);let n=[];for(let r of e)if(n.push(r),n.length===t)break;return n}var h=1<<24,g=1024,_=2048,v=4096,y=8192,b=16384,x=32768,S=1<<25,C=65536,w=1<<19,T=1<<20,E=1<<25,ee=1<<21,te=1<<22,ne=1<<23,re=Symbol(`$state`),ie=Symbol(`component`),ae=Symbol(`legacy props`),oe=Symbol(``),se=Symbol(`attributes`),ce=Symbol(`class`),le=Symbol(`style`),ue=Symbol(`text`),de=Symbol(`form reset`),fe=new class extends Error{name=`StaleReactionError`;message="The reaction that called `getAbortSignal()` was re-run or destroyed"},pe=!!globalThis.document?.contentType&&globalThis.document.contentType.includes(`xml`),me={},he=Symbol(`uninitialized`),ge=`http://www.w3.org/1999/xhtml`;function _e(){console.warn(`https://svelte.dev/e/derived_inert`)}function ve(e){console.warn(`https://svelte.dev/e/hydration_mismatch`)}function ye(){console.warn(`https://svelte.dev/e/select_multiple_invalid_value`)}function be(){console.warn(`https://svelte.dev/e/svelte_boundary_reset_noop`)}var D=!1;function xe(e){D=e}var O;function Se(e){if(e===null)throw ve(),me;return O=e}function Ce(){return Se(cn(O))}function k(e){if(D){if(cn(O)!==null)throw ve(),me;O=e}}function A(e=1){if(D){for(var t=e,n=O;t--;)n=cn(n);O=n}}function we(e=!0){for(var t=0,n=O;;){if(n.nodeType===8){var r=n.data;if(r===`]`){if(t===0)return n;--t}else(r===`[`||r===`[!`||r[0]===`[`&&!isNaN(Number(r.slice(1))))&&(t+=1)}var i=cn(n);e&&n.remove(),n=i}}function Te(e){if(!e||e.nodeType!==8)throw ve(),me;return e.data}function Ee(e){return e===this.v}function De(e,t){return e==e?e!==t||typeof e==`object`&&!!e||typeof e==`function`:t==t}function Oe(e){return!De(e,this.v)}function ke(e){throw Error(`https://svelte.dev/e/lifecycle_outside_component`)}function Ae(){throw Error(`https://svelte.dev/e/async_derived_orphan`)}function je(e,t,n){throw Error(`https://svelte.dev/e/each_key_duplicate`)}function Me(e){throw Error(`https://svelte.dev/e/effect_in_teardown`)}function Ne(){throw Error(`https://svelte.dev/e/effect_in_unowned_derived`)}function Pe(e){throw Error(`https://svelte.dev/e/effect_orphan`)}function Fe(){throw Error(`https://svelte.dev/e/effect_update_depth_exceeded`)}function Ie(e){throw Error(`https://svelte.dev/e/props_invalid_value`)}function Le(){throw Error(`https://svelte.dev/e/state_descriptors_fixed`)}function Re(){throw Error(`https://svelte.dev/e/state_prototype_fixed`)}function ze(){throw Error(`https://svelte.dev/e/state_unsafe_mutation`)}function Be(){throw Error(`https://svelte.dev/e/svelte_boundary_reset_onerror`)}function Ve(e){let t=e.p;for(;t!==null&&t.c===null;)t=t.p;return t?.c??null}function He(e,t){return e===null&&ke(t),e.c??=new Map(Ve(e)||void 0)}var Ue=null;function We(e){Ue=e}function Ge(e){return He(Ue,`getContext`).get(e)}function Ke(e,t){return He(Ue,`setContext`).set(e,t),t}function j(e,t=!1,n){Ue={p:Ue,i:!1,c:null,e:null,s:e,x:null,r:U,l:null}}function M(e){var t=Ue,n=t.e;if(n!==null){t.e=null;for(var r of n)xn(r)}return e!==void 0&&(t.x=e),t.i=!0,Ue=t.p,qe(e)}function qe(e={}){return i(e,ie,{value:!0}),e}function Je(){return!0}var Ye=[];function Xe(){var e=Ye;Ye=[],f(e)}function Ze(e){if(Ye.length===0&&!Et){var t=Ye;queueMicrotask(()=>{t===Ye&&Xe()})}Ye.push(e)}function Qe(){for(;Ye.length>0;)Xe()}var $e=~(_|v|g);function et(e,t){e.f=e.f&$e|t}function tt(e){e.f&512||e.deps===null?et(e,g):et(e,v)}function nt(e,t){e.f&2048?t.set(e,_):e.f&4096&&t.get(e)!==2048&&t.set(e,v),et(e,g)}function rt(e,t){if(t){let t=document.body;e.autofocus=!0,Ze(()=>{document.activeElement===t&&e.focus()})}}function it(e){D&&sn(e)!==null&&ln(e)}var at=!1;function ot(){at||(at=!0,document.addEventListener(`reset`,e=>{Promise.resolve().then(()=>{if(!e.defaultPrevented)for(let t of e.target.elements)t[de]?.()})},{capture:!0}))}function st(e){var t=H,n=U;Wn(null),Gn(null);try{return e()}finally{Wn(t),Gn(n)}}function ct(e,t,n,r=n){e.addEventListener(t,()=>st(n));let i=e[de];e[de]=i?()=>{i(),r(!0)}:()=>r(!0),ot()}function lt(e,t,n,r){let i=Je()?pt:gt;var a=e.filter(e=>!e.settled),o=t.map(i);if(n.length===0&&a.length===0){r(o);return}var s=U,c=ut(),l=a.length===1?a[0].promise:a.length>1?Promise.all(a.map(e=>e.promise)):null;function u(e){if(!(s.f&16384)){c();try{r([...o,...e])}catch(e){mn(e,s)}dt()}}var d=ft();if(n.length===0){l.then(()=>u([])).finally(d);return}function f(){Promise.all(n.map(e=>ht(e))).then(u).catch(e=>mn(e,s)).finally(d)}l?l.then(()=>{s.f&16384?d():(c(),f(),dt())}):f()}function ut(){var e=U,t=H,n=Ue,r=P;return function(i=!0){Gn(e),Wn(t),We(n),i&&!(e.f&16384)&&(r?.activate(),r?.apply())}}function dt(e=!0){Gn(null),Wn(null),We(null),e&&P?.deactivate()}function ft(){var e=U,t=e.b,n=P,r=!!t?.is_rendered();return t?.update_pending_count(1,n),n.increment(r,e),()=>{t?.update_pending_count(-1,n),n.decrement(r,e)}}function pt(e){var t=2|_;return U!==null&&(U.f|=w),{ctx:Ue,deps:null,effects:null,equals:Ee,f:t,fn:e,reactions:null,rv:0,v:he,wv:0,parent:U,ac:null}}var mt=Symbol(`obsolete`);function ht(e,t,n){let r=U;r===null&&Ae();var i=void 0,a=Ut(he),o=!H,s=new Set;return wn(()=>{var t=U,n=p();i=n.promise;try{Promise.resolve(e()).then(n.resolve,e=>{e!==fe&&n.reject(e)}).finally(dt)}catch(e){n.reject(e),dt()}var c=P;if(o){if(t.f&32768)var l=ft();if(r.b?.is_rendered())c.async_deriveds.get(t)?.reject(mt);else for(let e of s.values())e.reject(mt);s.add(n),c.async_deriveds.set(t,n)}let u=(e,t=void 0)=>{l?.(),s.delete(n),t!==mt&&(c.activate(),t?(a.f|=ne,qt(a,t)):(a.f&8388608&&(a.f^=ne),qt(a,e)),c.deactivate())};n.promise.then(u,e=>u(null,e||`unknown`))}),yn(()=>{for(let e of s)e.reject(mt)}),new Promise(e=>{function t(n){function r(){n===i?e(a):t(i)}n.then(r,r)}t(i)})}function N(e){let t=pt(e);return qn(t),t}function gt(e){let t=pt(e);return t.equals=Oe,t}function _t(e){var t=e.effects;if(t!==null){e.effects=null;for(var n=0;n{t.ac.abort(fe),t.ac=null}),t.fn!==null&&(t.teardown=d),cr(t,0),An(t))}function xt(e){if(e.effects!==null)for(let t of e.effects)t.teardown&&t.fn!==null&&lr(t)}var St=null,P=null,Ct=null,wt=null,Tt=null,Et=!1,Dt=!1,Ot=null,kt=null,At=0,jt=1,Mt=class e{id=jt++;started=!1;linked=!0;prev=null;next=null;async_deriveds=new Map;current=new Map;previous=new Map;#e=new Set;#t=new Set;#n=0;#r=new Map;#i=null;#a=[];#o=[];#s=new Map;#c=new Map;#l=new Set;is_fork=!1;#u=!1;constructor(){St===null?St=this:(St.next=this,this.prev=St),St=this}#d(){if(this.is_fork)return!0;for(let e of this.#r.keys())if(!this.#f(e))return!0;return!1}#f(e){for(var t=e;t!==null;t=t.parent)if(this.#c.has(t))return!0;return!1}skip_effect(e){this.#c.has(e)||this.#c.set(e,{d:[],m:[]}),this.#l.delete(e)}unskip_effect(e,t=e=>this.schedule(e)){var n=this.#c.get(e);if(n){this.#c.delete(e);for(var r of n.d)et(r,_),t(r);for(r of n.m)et(r,v),t(r)}this.#l.add(e)}#p(){var e=[];for(let i of this.#a)if(!(i.f&16384||!(i.f&6144))){for(var t=i,n=!1;t.parent!==null;){t=t.parent;var r=t.f;if(r&96){if(!(r&1024)){n=!0;break}t.f^=g}}n||e.push(t)}return this.#a=[],e}#m(){this.started=!0;for(let[e,t]of this.#s)et(e,t),this.schedule(e);this.apply();for(var t=Ot=[],n=[],r=kt=[];this.#a.length>0;){At++>1e3&&(this.#b(),Pt());for(let e of this.#p())try{this.#h(e,t,n)}catch(t){throw zt(e),this.#d()||this.discard(),t}}if(P=null,r.length>0){var i=e.ensure();for(let e of r)i.schedule(e)}if(Ot=null,kt=null,this.#d()){this.#y(n),this.#y(t);for(let[e,t]of this.#c)Rt(e,t);r.length>0&&P.#m();return}let a=this.#g();if(a)this.#y(n),this.#y(t),a.#v(this);else{this.#s.clear();for(let e of this.#e)e(this);this.#e.clear(),Ct=this,It(n),It(t),Ct=null,this.#i?.resolve();var o=P;this.#n===0&&(this.#a.length===0||o!==null)&&this.#b(),o!==null&&(Vt.clear(),o.#m())}}#h(e,t,n){e.f^=g;for(var r=e.first;r!==null;){var i=r.f,a=!!(i&96);if(!(a&&i&1024||i&8192||this.#c.has(r))&&r.fn!==null){a?r.f^=g:i&4?t.push(r):rr(r)&&(i&16&&this.add_dirty_reaction(r,v),lr(r));var o=r.first;if(o!==null){r=o;continue}}for(;r!==null;){var s=r.next;if(s!==null){r=s;break}r=r.parent}}}#g(){for(var e=this.prev;e!==null;e=e.prev)if(!e.is_fork&&this.#_(e))return e;return null}#_(e){for(let[t,[,n]]of this.current)if(!n&&e.current.has(t))return!0;return!1}#v(e){for(let[t,n]of e.current)!this.previous.has(t)&&e.previous.has(t)&&this.previous.set(t,e.previous.get(t)),this.current.set(t,n);for(let[t,n]of e.async_deriveds){let e=this.async_deriveds.get(t);e&&n.promise.then(e.resolve).catch(e.reject)}e.async_deriveds.clear(),this.transfer_reactions(e.#s);let t=e=>{var n=e.reactions;if(n!==null&&!(e.f&2&&!(e.f&6144)))for(let e of n){var r=e.f;if(r&2)t(e);else{var i=e;r&4194320&&!this.async_deriveds.has(i)&&(this.#s.delete(i),et(i,_),this.schedule(i))}}};for(let e of this.current.keys())t(e);this.oncommit(()=>e.discard()),e.#b(),P=this,this.#m()}#y(e){for(var t=0;t{this.#u=!1,this.linked&&this.flush()}))}transfer_reactions(e){for(let[t,n]of e)this.add_dirty_reaction(t,n);e.clear()}add_dirty_reaction(e,t){(t===2048||this.#s.get(e)!==2048)&&this.#s.set(e,t)}oncommit(e){this.#e.add(e)}ondiscard(e){this.#t.add(e)}settled(){return(this.#i??=p()).promise}static ensure(){if(P===null){let t=P=new e;!Dt&&!Et&&Ze(()=>{t.started||t.flush()})}return P}apply(){wt=null}schedule(e){Tt=e,e.b?.is_pending&&e.f&16777228&&!(e.f&32768)?e.b.defer_effect(e):this.#a.push(e)}#b(){if(this.linked){var e=this.prev,t=this.next;e===null||(e.next=t),t===null?St=e:t.prev=e,this.linked=!1}}};function Nt(e){var t=Et,n=Ct;Ct=null,Et=!0;try{var r;for(e&&(Nt(),r=e());;){if(Qe(),P===null)return r;P.flush()}}finally{Et=t,Ct=n}}function Pt(){try{Fe()}catch(e){mn(e,Tt)}}var Ft=null;function It(e){var t=e.length;if(t!==0){for(var n=0;n0)){Vt.clear();for(let e of Ft){if(e.f&24576)continue;let t=[e],n=e.parent;for(;n!==null;)Ft.has(n)&&(Ft.delete(n),t.push(n)),n=n.parent;for(let e=t.length-1;e>=0;e--){let n=t[e];n.f&24576||lr(n)}}Ft.clear()}}Ft=null}}function Lt(e){P.schedule(e)}function Rt(e,t){if(!(e.f&32&&e.f&1024)){e.f&2048?t.d.push(e):e.f&4096&&t.m.push(e),et(e,g);for(var n=e.first;n!==null;)Rt(n,t),n=n.next}}function zt(e){et(e,g);for(var t=e.first;t!==null;)zt(t),t=t.next}var Bt=new Set,Vt=new Map,Ht=!1;function Ut(e,t){return{f:0,v:e,reactions:null,equals:Ee,rv:0,wv:0}}function F(e,t){let n=Ut(e,t);return qn(n),n}function Wt(e,t=!1,n=!0){let r=Ut(e);return t||(r.equals=Oe),r}function I(e,t,n=!1){return H!==null&&(!Un||H.f&131072)&&Je()&&H.f&4325394&&(Kn===null||!Kn.has(e))&&ze(),qt(e,n?Zt(t):t,kt)}var Gt=null,Kt=0;function qt(e,t,n=null){if(!e.equals(t)){Vn?Vt.set(e,t):Vt.has(e)||Vt.set(e,e.v);var r=Mt.ensure();if(r.capture(e,t),e.f&2){let t=e;e.f&2048&&vt(t),wt===null&&tt(t)}e.wv=nr(),Gt=null,Kt=0,Xt(e,_,n),Gt=null,Je()&&U!==null&&U.f&1024&&!(U.f&96)&&(Xn===null?Zn([e]):Xn.push(e)),!r.is_fork&&Bt.size>0&&!Ht&&Jt()}return t}function Jt(){Ht=!1;for(let e of Bt){e.f&1024&&et(e,v);let t;try{t=rr(e)}catch{t=!0}t&&lr(e)}Bt.clear()}function Yt(e){I(e,e.v+1)}function Xt(e,t,n){var r=e.reactions;if(r!==null){var i=Je(),a=r.length;if(Kt+=a,Kt>1e5&&Gt===null&&(Gt=new Set),Gt!==null){if(Gt.has(e))return;Gt.add(e)}for(var o=0;o{if(er===d)return e();var t=H,n=er;Wn(null),tr(d);var r=e();return Wn(t),tr(n),r};return i&&r.set(`length`,F(t.length,u)),new Proxy(t,{defineProperty(e,t,n){`value`in n&&n.configurable!==!1&&n.enumerable!==!1&&n.writable!==!1||Le();var i=r.get(t);return i===void 0?f(()=>{var e=F(n.value,u);return r.set(t,e),e}):I(i,n.value,!0),!0},deleteProperty(e,t){var n=r.get(t);if(n===void 0){if(t in e){let e=f(()=>F(he,u));r.set(t,e),Yt(o)}}else I(n,he),Yt(o);return!0},get(e,n,i){if(n===re)return t;var o=r.get(n),s=n in e;if(o===void 0&&(!s||a(e,n)?.writable)&&(o=f(()=>F(Zt(s?e[n]:he),u)),r.set(n,o)),o!==void 0){var c=W(o);return c===he?void 0:c}return Reflect.get(e,n,i)},getOwnPropertyDescriptor(e,t){this.has?.(e,t);var n=Reflect.getOwnPropertyDescriptor(e,t),i=r.get(t);if(i!==void 0){var a=W(i);if(a===he)return;if(n&&`value`in n)n.value=a;else return{enumerable:!0,configurable:!0,value:a,writable:!0}}return n},has(e,t){if(t===re)return!0;var n=r.get(t),i=n!==void 0&&n.v!==he||Reflect.has(e,t);return(n!==void 0||(U!==null||H!==null)&&(!i||a(e,t)?.writable))&&(n===void 0&&(n=f(()=>F(i?Zt(e[t]):he,u)),r.set(t,n)),W(n)===he)?!1:i},set(e,t,n,s){var c=r.get(t),l=t in e;if(i&&t===`length`)for(var d=n;dF(he,u)),r.set(d+``,p)):I(p,he)}if(c===void 0)(!l||a(e,t)?.writable)&&(c=f(()=>F(void 0,u)),I(c,Zt(n)),r.set(t,c));else{l=c.v!==he;var m=f(()=>Zt(n));I(c,m)}var h=Reflect.getOwnPropertyDescriptor(e,t);if(h?.set&&h.set.call(s,n),!l){if(i&&typeof t==`string`){var g=r.get(`length`),_=Number(t);Number.isInteger(_)&&_>=g.v&&I(g,_+1)}Yt(o)}return!0},ownKeys(e){W(o);var t=Reflect.ownKeys(e).filter(e=>{var t=r.get(e);return t===void 0||t.v!==he});for(var[n,i]of r)i.v!==he&&!(n in e)&&t.push(n);return t},setPrototypeOf(){Re()}})}function Qt(e){try{if(typeof e==`object`&&e&&re in e)return e[re]}catch{}return e}function $t(e,t){return Object.is(Qt(e),Qt(t))}var en,tn,nn,rn;function an(){if(en===void 0){en=window,tn=/Firefox/.test(navigator.userAgent);var e=Element.prototype,t=Node.prototype,n=Text.prototype;nn=a(t,`firstChild`).get,rn=a(t,`nextSibling`).get,u(e)&&(e[ce]=void 0,e[se]=null,e[le]=void 0,e.__e=void 0),u(n)&&(n[ue]=void 0)}}function on(e=``){return document.createTextNode(e)}function sn(e){return nn.call(e)}function cn(e){return rn.call(e)}function L(e,t){if(!D)return sn(e);var n=sn(O);if(n===null)n=O.appendChild(on());else if(t&&n.nodeType!==3){var r=on();return n?.before(r),Se(r),r}return t&&fn(n),Se(n),n}function R(e,t=!1){if(!D){var n=sn(e);return n instanceof Comment&&n.data===``?cn(n):n}if(t){if(O?.nodeType!==3){var r=on();return O?.before(r),Se(r),r}fn(O)}return O}function z(e,t=!1){if(!D)return sn(e);var n=L(e,t);return k(e),n}function B(e,t=1,n=!1){let r=D?O:e;for(var i;t--;)i=r,r=cn(r);if(!D)return r;if(n){if(r?.nodeType!==3){var a=on();return r===null?i?.after(a):r.before(a),Se(a),a}fn(r)}return Se(r),r}function ln(e){e.textContent=``}function un(){return!1}function dn(e,t,n){return t==null||t===`http://www.w3.org/1999/xhtml`?n?document.createElement(e,{is:n}):document.createElement(e):n?document.createElementNS(t,e,{is:n}):document.createElementNS(t,e)}function fn(e){if(e.nodeValue.length<65536)return;let t=e.nextSibling;for(;t!==null&&t.nodeType===3;)t.remove(),e.nodeValue+=t.nodeValue,t=e.nextSibling}function pn(e){var t=U;if(t===null)return H.f|=ne,e;if(!(t.f&32768)&&!(t.f&4))throw e;mn(e,t)}function mn(e,t){if(e===me)throw e;if(!(t!==null&&t.f&16384)){for(;t!==null;){if(t.f&128&&!(t.f&33570816)){if(!(t.f&32768))throw e;try{t.b.error(e);return}catch(t){e=t}}t=t.parent}throw e}}function hn(e){U===null&&(H===null&&Pe(e),Ne()),Vn&&Me(e)}function gn(e,t){var n=t.last;n===null?t.last=t.first=e:(n.next=e,e.prev=n,t.last=e)}function _n(e,t){var n=U;n!==null&&n.f&8192&&(e|=y);var r={ctx:Ue,deps:null,nodes:null,f:e|_|512,first:null,fn:t,last:null,next:null,parent:n,b:n&&n.b,prev:null,teardown:null,wv:0,ac:null};P?.register_created_effect(r);var i=r;if(e&4)Ot===null?Mt.ensure().schedule(r):Ot.push(r);else if(t!==null){try{lr(r)}catch(e){throw Mn(r),e}i.deps===null&&i.teardown===null&&i.nodes===null&&i.first===i.last&&!(i.f&524288)&&(i=i.first,e&16&&e&65536&&i!==null&&(i.f|=C))}if(i!==null&&(i.parent=n,n!==null&&gn(i,n),H!==null&&H.f&2&&!(e&64))){var a=H;(a.effects??=[]).push(i)}return r}function vn(){return H!==null&&!Un}function yn(e){let t=_n(8,null);return et(t,g),t.teardown=e,t}function bn(e){hn(`$effect`);var t=U.f;if(!H&&t&32&&Ue!==null&&!Ue.i){var n=Ue;(n.e??=[]).push(e)}else return xn(e)}function xn(e){return _n(4|T,e)}function Sn(e){Mt.ensure();let t=_n(64|w,e);return(e={})=>new Promise(n=>{e.outro?Fn(t,()=>{Mn(t),n(void 0)}):(Mn(t),n(void 0))})}function Cn(e){return _n(4,e)}function wn(e){return _n(te|w,e)}function Tn(e,t=0){return _n(8|t,e)}function V(e,t=[],n=[],r=[]){lt(r,t,n,t=>{_n(8,()=>{e(...t.map(W))})})}function En(e,t=0){return _n(16|t,e)}function Dn(e,t=0){return _n(h|t,e)}function On(e){return _n(32|w,e)}function kn(e){var t=e.teardown;if(t!==null){let n=Vn,r=H;Hn(!0),Wn(null);try{t.call(null)}catch(t){mn(t,e.parent)}finally{Hn(n),Wn(r)}}}function An(e,t=!1){var n=e.first;for(e.first=e.last=null;n!==null;){let e=n.ac;e!==null&&st(()=>{e.abort(fe)});var r=n.next;n.f&64?n.parent=null:Mn(n,t),n=r}}function jn(e){for(var t=e.first;t!==null;){var n=t.next;t.f&32||Mn(t),t=n}}function Mn(e,t=!0){var n=!1;(t||e.f&262144)&&e.nodes!==null&&e.nodes.end!==null&&(Nn(e.nodes.start,e.nodes.end),n=!0),e.f|=S,An(e,t&&!n),cr(e,0);var r=e.nodes&&e.nodes.t;if(r!==null)for(let e of r)e.stop();kn(e),e.f^=S,e.f|=b;var i=e.parent;i!==null&&i.first!==null&&Pn(e),e.next=e.prev=e.teardown=e.ctx=e.deps=e.fn=e.nodes=e.ac=e.b=null}function Nn(e,t){for(;e!==null;){var n=e===t?null:cn(e);e.remove(),e=n}}function Pn(e){var t=e.parent,n=e.prev,r=e.next;n!==null&&(n.next=r),r!==null&&(r.prev=n),t!==null&&(t.first===e&&(t.first=r),t.last===e&&(t.last=n))}function Fn(e,t,n=!0){var r=[];e.f|=256,In(e,r,!0);var i=()=>{n&&Mn(e),t&&t()},a=r.length;if(a>0){var o=()=>--a||i();for(var s of r)s.out(o)}else i()}function In(e,t,n){if(!(e.f&8192)){e.f^=y;var r=e.nodes&&e.nodes.t;if(r!==null)for(let e of r)(e.is_global||n)&&t.push(e);for(var i=e.first;i!==null;){var a=i.next;if(!(i.f&64)){var o=!!(i.f&65536)||!!(i.f&32)&&!!(e.f&16);In(i,t,o?n:!1)}i=a}}}function Ln(e){e.f&=-257,Rn(e,!0)}function Rn(e,t){if(!(e.f&256)&&e.f&8192){e.f^=y,e.f&1024||(et(e,_),Mt.ensure().schedule(e));for(var n=e.first;n!==null;){var r=n.next,i=!!(n.f&65536)||!!(n.f&32);Rn(n,i?t:!1),n=r}var a=e.nodes&&e.nodes.t;if(a!==null)for(let e of a)(e.is_global||t)&&e.in()}}function zn(e,t){if(e.nodes)for(var n=e.nodes.start,r=e.nodes.end;n!==null;){var i=n===r?null:cn(n);t.append(n),n=i}}var Bn=null,Vn=!1;function Hn(e){Vn=e}var H=null,Un=!1;function Wn(e){H=e}var U=null;function Gn(e){U=e}var Kn=null;function qn(e){H!==null&&(H.f&2097152||H.f&2)&&(Kn??=new Set).add(e)}var Jn=null,Yn=0,Xn=null;function Zn(e){Xn=e}var Qn=1,$n=0,er=$n;function tr(e){er=e}function nr(){return++Qn}function rr(e){var t=e.f;if(t&2048)return!0;if(t&4096){for(var n=e.deps,r=n.length,i=0;ie.wv)return!0}t&512&&wt===null&&et(e,g)}return!1}function ir(e,t,n=!0){var r=e.reactions;if(r!==null&&!(Kn!==null&&Kn.has(e)))for(var i=0;i{e.ac.abort(fe)}),e.ac=null);try{e.f|=ee;var u=e.fn,d=u();e.f|=x;var f=or(e);if(Je()&&Xn!==null&&!Un&&f!==null&&!(e.f&6146))for(var p=0;p0)for(t.length=Yn+Jn.length,r=0;r{s.ac.abort(fe),s.ac=null,et(s,_)}),bt(s),cr(s,0)}}function cr(e,t){var n=e.deps;if(n!==null)for(var r=t;rn?.call(this,e))}return e.startsWith(`pointer`)||e.startsWith(`touch`)||e===`wheel`?(i.__removed=!1,Ze(()=>{i.__removed||t.addEventListener(e,i,r)})):t.addEventListener(e,i,r),i}function Er(e,t,n,r,i){var a={capture:r,passive:i},o=Tr(e,t,n,a);(t===document.body||t===window||t===document||t instanceof HTMLMediaElement)&&yn(()=>{o.__removed=!0,t.removeEventListener(e,o,a)})}function Dr(e,t,n){(t[Sr]??={})[e]=n}function Or(e){for(var t=0;t{Ar=!1,kr=null}));var s=0,c=kr===e&&e[Sr];if(c){var l=a.indexOf(c);if(l!==-1&&(t===document||t===window)){e[Sr]=t;return}var u=a.indexOf(t);if(u===-1)return;l<=u&&(s=l)}if(o=a[s]||e.target,o!==t){i(e,`currentTarget`,{configurable:!0,get(){return o||n}});var d=H,f=U;Wn(null),Gn(null);try{for(var p,m=[];o!==null&&o!==t;){try{var h=o[Sr]?.[r];h==null||o.disabled&&e.target!==o||h.call(o,e)}catch(e){p?m.push(e):p=e}if(e.cancelBubble)break;s++,o=s{throw e});throw p}}finally{e[Sr]=t,delete e.currentTarget,Wn(d),Gn(f)}}}var Mr=globalThis?.window?.trustedTypes&&globalThis.window.trustedTypes.createPolicy(`svelte-trusted-html`,{createHTML:e=>e});function Nr(e){return Mr?.createHTML(e)??e}function Pr(e){var t=dn(`template`);return t.innerHTML=Nr(e.replaceAll(``,``)),t.content}function Fr(e,t){var n=U;n.nodes===null&&(n.nodes={start:e,end:t,a:null,t:null})}function G(e,t){var n=!!(t&1),r=!!(t&2),i,a=!e.startsWith(``);return()=>{if(D)return Fr(O,null),O;i===void 0&&(i=Pr(a?e:``+e),n||(i=sn(i)));var t=r||tn?document.importNode(i,!0):i.cloneNode(!0);if(n){var o=sn(t),s=t.lastChild;Fr(o,s)}else Fr(t,t);return t}}function K(e=``){if(!D){var t=on(e+``);return Fr(t,t),t}var n=O;return n.nodeType===3?fn(n):(n.before(n=on()),Se(n)),Fr(n,n),n}function Ir(){if(D)return Fr(O,null),O;var e=document.createDocumentFragment(),t=document.createComment(``),n=on();return e.append(t,n),Fr(t,n),e}function q(e,t){if(D){var n=U;n.f&32768&&n.nodes.end!==null||(n.nodes.end=O),Ce()}else e!==null&&e.before(t)}function Lr(e){let t=0,n=Ut(0),r;return()=>{vn()&&(W(n),Tn(()=>(t===0&&(r=pr(()=>e(()=>Yt(n)))),t+=1,()=>{Ze(()=>{--t,t===0&&(r?.(),r=void 0,Yt(n))})})))}}var Rr=C|w;function zr(e,t,n,r){new Br(e,t,n,r)}var Br=class{parent;is_pending=!1;transform_error;#e;#t=D?O:null;#n;#r;#i;#a=null;#o=null;#s=null;#c=null;#l=0;#u=0;#d=!1;#f=new Map;#p=null;#m=Lr(()=>(this.#p=Ut(this.#l),()=>{this.#p=null}));constructor(e,t,n,r){this.#e=e,this.#n=t,this.#r=e=>{var t=U;t.b=this,t.f|=128,n(e)},this.parent=U.b,this.transform_error=r??this.parent?.transform_error??(e=>e),this.#i=En(()=>{if(D){let e=Te(this.#t);Ce();let t=e===`[!`;if(e.startsWith(`[?`)){let t=JSON.parse(e.slice(2));this.#g(t)}else t?this.#y():this.#h()}else this.#b()},Rr),D&&(this.#e=O)}#h(){try{this.#a=On(()=>this.#r(this.#e))}catch(e){this.error(e)}}#g(e){let t=this.#n.failed,{reset:n,invoke_onerror:r}=this.#_(e);Ze(r),t&&(this.#s=On(()=>{t(this.#e,()=>e,()=>n)}))}#_(e){var t=!1,n=!1;let r=()=>{this.#v()||(t?be():(t=!0,n&&Be(),this.#s!==null&&Fn(this.#s,()=>{this.#s=null}),this.#S(()=>{this.#b()})))};return{reset:r,invoke_onerror:()=>{if(!this.#v())try{n=!0,this.#n.onerror?.(e,r),n=!1}catch(e){mn(e,this.#i&&this.#i.parent)}}}}#v(){return(this.#i.f&(b|S))!==0}#y(){let e=this.#n.pending;e&&(this.is_pending=!0,this.#o=On(()=>e(this.#e)),Ze(()=>{if(!this.#v()){var e=this.#c=document.createDocumentFragment(),t=on(),n=!1;e.append(t),this.#a=this.#S(()=>{try{return On(()=>this.#r(t))}catch(e){try{this.error(e),n=!0}catch(e){mn(e,this.#i.parent)}return null}}),this.#a===null?(this.#c=null,n&&this.#x(P)):this.#u===0&&(this.#e.before(e),this.#c=null,Fn(this.#o,()=>{this.#o=null}),this.#x(P))}}))}#b(){try{if(this.is_pending=this.has_pending_snippet(),this.#u=0,this.#l=0,this.#a=On(()=>{this.#r(this.#e)}),this.#u>0){var e=this.#c=document.createDocumentFragment();zn(this.#a,e);let t=this.#n.pending;this.#o=On(()=>t(this.#e))}else this.#x(P)}catch(e){this.error(e)}}#x(e){this.is_pending=!1,e.transfer_reactions(this.#f)}defer_effect(e){nt(e,this.#f)}is_rendered(){return!this.is_pending&&(!this.parent||this.parent.is_rendered())}has_pending_snippet(){return!!this.#n.pending}#S(e){var t=U,n=H,r=Ue;Gn(this.#i),Wn(this.#i),We(this.#i.ctx);try{return Mt.ensure(),e()}finally{Gn(t),Wn(n),We(r)}}#C(e,t){this.has_pending_snippet()?(this.#u+=e,this.#u===0&&(this.#x(t),this.#o&&Fn(this.#o,()=>{this.#o=null}),this.#c&&=(this.#e.before(this.#c),null))):this.parent&&this.parent.#C(e,t)}update_pending_count(e,t){this.#C(e,t),this.#l+=e,!this.#p||this.#d||(this.#d=!0,Ze(()=>{this.#d=!1,this.#p&&qt(this.#p,this.#l)}))}get_effect_pending(){return this.#m(),W(this.#p)}error(e){if(e===me||!this.#n.onerror&&!this.#n.failed)throw e;P?.is_fork?(this.#a&&P.skip_effect(this.#a),this.#o&&P.skip_effect(this.#o),this.#s&&P.skip_effect(this.#s),P.oncommit(()=>{this.#v()||this.#w(e)})):this.#w(e)}#w(e){this.#a&&=(Mn(this.#a),null),this.#o&&=(Mn(this.#o),null),this.#s&&=(Mn(this.#s),null),D&&(Se(this.#t),A(),Se(we()));let t=this.#n.failed,n=e=>{if(this.#v())return;let{reset:n,invoke_onerror:r}=this.#_(e);r(),t&&!this.#v()&&(this.#s=this.#S(()=>{try{return On(()=>{var r=U;r.b=this,r.f|=128,t(this.#e,()=>e,()=>n)})}catch(e){return mn(e,this.#i.parent),null}}))};Ze(()=>{if(!this.#v()){var t;try{t=this.transform_error(e)}catch(e){mn(e,this.#i&&this.#i.parent);return}typeof t==`object`&&t&&typeof t.then==`function`?t.then(n,e=>mn(e,this.#i&&this.#i.parent)):n(t)}})}};function J(e,t){var n=t==null?``:typeof t==`object`?`${t}`:t;n!==(e[ue]??=e.nodeValue)&&(e[ue]=n,e.nodeValue=`${n}`)}function Vr(e,t){return Ur(e,t)}var Hr=new Map;function Ur(e,{target:t,anchor:n,props:i={},events:a,context:o,intro:s=!0,transformError:c}){an();var l=void 0,u=Sn(()=>{var s=n??t.appendChild(on());zr(s,{pending:()=>{}},t=>{j({});var n=Ue;if(o&&(n.c=o),a&&(i.$$events=a),D&&Fr(t,null),l=e(t,i)||qe(),D&&(U.nodes.end=O,O===null||O.nodeType!==8||O.data!==`]`))throw ve(),me;M()},c);var u=new Set,d=e=>{for(var n=0;n{for(var e of u)for(let n of[t,document]){var r=Hr.get(n),i=r.get(e);--i==0?(n.removeEventListener(e,jr),r.delete(e),r.size===0&&Hr.delete(n)):r.set(e,i)}wr.delete(d),s!==n&&s.parentNode?.removeChild(s)}});return Wr.set(l,u),l}var Wr=new WeakMap,Gr=class{anchor;#e=new Map;#t=new Map;#n=new Map;#r=new Set;#i=!0;constructor(e,t=!0){this.anchor=e,this.#i=t}#a=e=>{if(this.#e.has(e)){var t=this.#e.get(e),n=this.#t.get(t);if(n)Ln(n),this.#r.delete(t);else{var r=this.#n.get(t);r&&(Ln(r.effect),this.#t.set(t,r.effect),this.#n.delete(t),r.fragment.lastChild.remove(),this.anchor.before(r.fragment),n=r.effect)}for(let[t,n]of this.#e){if(this.#e.delete(t),t===e)break;let r=this.#n.get(n);r&&(Mn(r.effect),this.#n.delete(n))}for(let[e,r]of this.#t){if(e===t||this.#r.has(e))continue;let i=()=>{if(Array.from(this.#e.values()).includes(e)){var t=document.createDocumentFragment();zn(r,t),t.append(on()),this.#n.set(e,{effect:r,fragment:t})}else Mn(r);this.#r.delete(e),this.#t.delete(e)};this.#i||!n?(this.#r.add(e),Fn(r,i,!1)):i()}}};#o=e=>{this.#e.delete(e);let t=Array.from(this.#e.values());for(let[e,n]of this.#n)t.includes(e)||(Mn(n.effect),this.#n.delete(e))};ensure(e,t){var n=P,r=un();if(t&&!this.#t.has(e)&&!this.#n.has(e)){if(r){var i=document.createDocumentFragment(),a=on();i.append(a),this.#n.set(e,{effect:On(()=>t(a)),fragment:i})}else this.#t.set(e,On(()=>t(this.anchor)))}if(this.#e.set(n,e),r){for(let[t,r]of this.#t)t===e?n.unskip_effect(r):n.skip_effect(r);for(let[t,r]of this.#n)t===e?n.unskip_effect(r.effect):n.skip_effect(r.effect);n.oncommit(this.#a),n.ondiscard(this.#o)}else D&&(this.anchor=O),this.#a(n)}};function Y(e,t,n=!1){var r;D&&(r=O,Ce());var i=new Gr(e),a=n?C:0;function o(e,t){if(D){var n=Te(r);if(e!==parseInt(n.substring(1))){var a=we();Se(a),i.anchor=a,xe(!1),i.ensure(e,t),xe(!0);return}}i.ensure(e,t)}En(()=>{var e=!1;t((t,n=0)=>{e=!0,o(n,t)}),e||o(-1,null)},a)}var Kr=Symbol(`NaN`);function qr(e,t,n){D&&Ce();var r=new Gr(e),i=!Je();En(()=>{var e=t();e!==e&&(e=Kr),i&&typeof e==`object`&&e&&(e={}),r.ensure(e,n)})}function Jr(e,t){return t}function Yr(e,t,n){for(var i=[],a=t.length,o,s=t.length,c=0;c{if(o){if(o.pending.delete(n),o.done.add(n),o.pending.size===0){var t=e.outrogroups;Xr(e,r(o.done)),t.delete(o),t.size===0&&(e.outrogroups=null)}}else--s},!1)}if(s===0){var l=i.length===0&&n!==null&&e.pending.size===0;if(l){var u=n,d=u.parentNode;ln(d),d.append(u),e.items.clear()}Xr(e,t,!l)}else o={pending:new Set(t),done:new Set},(e.outrogroups??=new Set).add(o)}function Xr(e,t,n=!0){var r;if(e.pending.size>0){r=new Set;for(let t of e.pending.values())for(let n of t)r.add(e.items.get(n).e)}for(var i=0;i{var t=i();return e(t)?t:t==null?[]:r(t)}),p=new Map,m=!0;function h(e){if(!(_.effect.f&16384)){_.pending.delete(e);var t=W(f);_.fallback=d,ei(_,t,c,n,a),d!==null&&(t.length===0?d.f&33554432?(d.f^=E,ni(d,null,c)):Ln(d):Fn(d,()=>{d=null}))}}function g(e){_.pending.delete(e)}var _={effect:En(()=>{var e=W(f),t=e.length;let r=!1;D&&Te(c)===`[!`!=(t===0)&&(c=we(),Se(c),xe(!1),r=!0);for(var u=new Set,_=P,v=un(),y=0;ys(c)):(d=On(()=>s(Zr??=on())),d.f|=E)),t>u.size&&je(``,``,``),D&&t>0&&Se(we()),!m){if(p.set(_,u),v){for(let[e,t]of l)u.has(e)||_.skip_effect(t.e);_.oncommit(h),_.ondiscard(g)}else h(_)}r&&xe(!0),W(f)}),flags:n,items:l,pending:p,outrogroups:null,fallback:d};m=!1,D&&(c=O)}function $r(e){for(;e!==null&&!(e.f&32);)e=e.next;return e}function ei(e,t,n,i,a){var o=!!(i&8),s=t.length,c=e.items,l=$r(e.effect.first),u,d=null,f,p=[],m=[],h,g,_,v;if(o)for(v=0;v0){var ee=i&4&&s===0?n:null;if(o){for(v=0;v{if(f!==void 0)for(_ of f)_.nodes?.a?.apply()})}function ti(e,t,n,r,i,a,o,s){var c=o&1?o&16?Ut(n):Wt(n,!1,!1):null,l=o&2?Ut(i):null;return{v:c,i:l,e:On(()=>(a(t,c??n,l??i,s),()=>{e.delete(r)}))}}function ni(e,t,n){if(e.nodes)for(var r=e.nodes.start,i=e.nodes.end,a=t&&!(t.f&33554432)?t.nodes.start:n;r!==null;){var o=cn(r);if(a.before(r),r===i)return;r=o}}function ri(e,t,n){t===null?e.effect.first=n:t.next=n,n===null?e.effect.last=t:n.prev=t}function ii(e,t,...n){var r=new Gr(e);En(()=>{let e=t()??null;r.ensure(e,e&&(t=>e(t,...n)))},C)}function ai(e,t){var n=void 0,r;Dn(()=>{n!==(n=t())&&(r&&=(Mn(r),null),n&&(r=On(()=>{Cn(()=>n(e))})))})}function oi(e){var t,n,r=``;if(typeof e==`string`||typeof e==`number`)r+=e;else if(typeof e==`object`){if(Array.isArray(e)){var i=e.length;for(t=0;t=0;){var s=o+a;(o===0||ci.includes(r[o-1]))&&(s===r.length||ci.includes(r[s]))?r=(o===0?``:r.substring(0,o))+r.substring(s+1):o=s}}return r===``?null:r}function ui(e,t=!1){var n=t?` !important;`:`;`,r=``;for(var i of Object.keys(e)){var a=e[i];a!=null&&a!==``&&(r+=` `+i+`: `+a+n)}return r}function di(e){return e[0]!==`-`||e[1]!==`-`?e.toLowerCase():e}function fi(e,t){if(t){var n=``,r,i;if(Array.isArray(t)?(r=t[0],i=t[1]):r=t,e){e=String(e).replaceAll(/\/\*.*?\*\//g,``).trim();var a=!1,o=0,s=!1,c=[];r&&c.push(...Object.keys(r).map(di)),i&&c.push(...Object.keys(i).map(di));var l=0,u=-1;let t=e.length;for(var d=0;d{t.every(xi)||(`__defaultValue`in e&&_i(e,!1),`__value`in e&&vi(e,e.__value))});t.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:[`value`]}),yn(()=>{t.disconnect()})}function bi(e){return`__value`in e?e.__value:e.value}function xi(e){if(e.target.closest(`selectedcontent`)!==null)return!0;if(e.type===`childList`){var t=[...e.addedNodes,...e.removedNodes];return t.length>0&&t.every(e=>e.nodeName===`SELECTEDCONTENT`)}return!1}var Si=Symbol(`class`),Ci=Symbol(`style`),wi=Symbol(`is custom element`),Ti=Symbol(`is html`),Ei=pe?`link`:`LINK`,Di=pe?`input`:`INPUT`,Oi=pe?`option`:`OPTION`,ki=pe?`select`:`SELECT`,Ai=pe?`progress`:`PROGRESS`;function ji(e){if(D){var t=!1,n=()=>{if(!t){if(t=!0,e.hasAttribute(`value`)){var n=e.value;Q(e,`value`,null),e.value=n}if(e.hasAttribute(`checked`)){var r=e.checked;Q(e,`checked`,null),e.checked=r}}};e[de]=n,Ze(n),ot()}}function Mi(e,t){var n=Ii(e);n.value!==(n.value=t??void 0)&&(e.value!==t||t===0&&e.nodeName===Ai)&&(e.value=t??``)}function Ni(e,t){var n=Ii(e);n.checked!==(n.checked=t??void 0)&&(e.checked=t)}function Q(e,t,n,r){var i=Ii(e);if(!(D&&(i[t]=e.getAttribute(t),t===`src`||t===`srcset`||t===`href`&&e.nodeName===Ei))){var a=i[t];a!==(i[t]=n)&&(t===`loading`&&(e[oe]=n),n==null?e.removeAttribute(t):typeof n!=`string`&&Ri(e).has(t)?e[t]=n:(!D||typeof n!=`number`&&typeof n!=`boolean`||a!==String(n))&&e.setAttribute(t,n))}}function Pi(e,t,n,r,i=!1,a=!1){D&&i&&e.nodeName===Di&&(`defaultValue`in n||`defaultChecked`in n||ji(e));var o=Ii(e),s=o[wi],c=!o[Ti];let l=D&&s;l&&xe(!1);var u=t||{},d=e.nodeName===Oi,f=e.nodeName===ki;try{for(var p in t)!(p in n)&&p[0]+p[1]!==`$$`&&(n[p]=null);n.class?n.class=X(n.class):(r||n[Si])&&(n.class=null),n[Ci]&&(n.style??=null);var m=Ri(e);if(e.nodeName===Di&&`type`in n&&(`value`in n||`__value`in n)){var h=n.type;(h!==u.type||h===void 0&&e.hasAttribute(`type`))&&(u.type=h,Q(e,`type`,h,a))}for(let i in n){let l=n[i];if(d&&i===`value`&&l==null)e.value=e.__value=``,u[i]=l;else if(i===`class`)Z(e,e.namespaceURI===`http://www.w3.org/1999/xhtml`,l,r,t?.[Si],n[Si]),u[i]=l,u[Si]=n[Si];else if(i===`style`)mi(e,l,t?.[Ci],n[Ci]),u[i]=l,u[Ci]=n[Ci];else{var g=u[i];if(l!==g||l===void 0&&e.hasAttribute(i)){u[i]=l;var _=i[0]+i[1];if(_!==`$$`){if(_===`on`){let t={},n=`$$`+i,r=i.slice(2);var v=gr(r);if(mr(r)&&(r=r.slice(0,-7),t.capture=!0),!v&&g){if(l!=null)continue;e.removeEventListener(r,u[n],t),u[n]=null}if(v)Dr(r,e,l),Or([r]);else if(l!=null){function a(e){u[i].call(this,e)}u[n]=Tr(r,e,a,t)}}else if(i===`style`)Q(e,i,l);else if(i===`autofocus`)rt(e,!!l);else if(!s&&(i===`__value`||i===`value`&&l!=null))e.__value=l,(g==null||e.value!==l||l===0&&e.nodeName===Ai)&&(e.value=l);else if(i===`selected`&&d)hi(e,l);else{var y=i;c||(y=yr(y));var b=y===`defaultValue`||y===`defaultChecked`;if(f&&y===`defaultValue`)continue;if(l==null&&!s&&!b){if(o[i]=null,y===`value`||y===`checked`){let n=e,r=t===void 0;if(y===`value`){let e=n.defaultValue;n.removeAttribute(y),n.defaultValue=e,n.value=n.__value=r?e:null}else{let e=n.defaultChecked;n.removeAttribute(y),n.defaultChecked=e,n.checked=r?e:!1}}else e.removeAttribute(i)}else b||(s||typeof l!=`string`)&&m.has(y)?(e[y]=l,y in o&&(o[y]=he)):typeof l!=`function`&&Q(e,y,l,a)}}}}}}finally{l&&xe(!0)}return u}function Fi(e,t,n=[],r=[],i=[],a,o=!1,s=!1){lt(i,n,r,n=>{var r=void 0,i={},c=e.nodeName===ki,l=!1;if(Dn(()=>{var u=t(...n.map(W)),d=Pi(e,r,u,a,o,s);if(l&&c){var f=e;`defaultValue`in u&&gi(f,u.defaultValue),`value`in u&&vi(f,u.value)}for(let e of Object.getOwnPropertySymbols(i))u[e]||Mn(i[e]);for(let t of Object.getOwnPropertySymbols(u)){var p=u[t];t.description!==`@attach`||r&&p===r[t]||(i[t]&&Mn(i[t]),i[t]=On(()=>ai(e,()=>p))),d[t]=p}r=d}),c){var u=e;Cn(()=>{var e=r;`defaultValue`in e&&gi(u,e.defaultValue),vi(u,e.value,!0),yi(u)})}l=!0})}function Ii(e){return e[se]??={[wi]:e.nodeName.includes(`-`),[Ti]:e.namespaceURI===ge}}var Li=new Map;function Ri(e){var t=e.getAttribute(`is`)||e.nodeName,n=Li.get(t);if(n)return n;Li.set(t,n=new Set);for(var r,i=e,a=Element.prototype;a!==i;){for(var s in r=o(i),r)r[s].set&&s!==`innerHTML`&&s!==`textContent`&&s!==`innerText`&&n.add(s);i=l(i)}return n}function zi(e,t,n=t){var r=new WeakSet;ct(e,`input`,async i=>{var a=i?e.defaultValue:e.value;if(a=Vi(e)?Hi(a):a,n(a),P!==null&&r.add(P),await ur(),a!==(a=t())){var o=e.selectionStart,s=e.selectionEnd,c=e.value.length;if(e.value=a??``,s!==null){var l=e.value.length;o===s&&s===c&&l>c?(e.selectionStart=l,e.selectionEnd=l):(e.selectionStart=o,e.selectionEnd=Math.min(s,l))}}}),(D&&e.defaultValue!==e.value||pr(t)==null&&e.value)&&(n(Vi(e)?Hi(e.value):e.value),P!==null&&r.add(P)),Tn(()=>{var n=t();if(e===document.activeElement){var i=P;if(r.has(i))return}Vi(e)&&n===Hi(e.value)||(e.type!==`date`||n||e.value)&&n!==e.value&&(e.value=n??``)})}function Bi(e,t,n=t){ct(e,`change`,t=>{n(t?e.defaultChecked:e.checked)}),(D&&e.defaultChecked!==e.checked||pr(t)==null)&&n(e.checked),Tn(()=>{e.checked=!!t()})}function Vi(e){var t=e.type;return t===`number`||t===`range`}function Hi(e){return e===``?null:+e}function Ui(e,t){return e===t||e?.[re]===t}function Wi(e=qe(),t,n,r){var i=Ue.r,a=U;return Cn(()=>{var o,s;return Tn(()=>{o=s,s=r?.()||[],pr(()=>{Ui(n(...s),e)||(t(e,...s),o&&Ui(n(...o),e)&&t(null,...o))})}),()=>{let r=a;for(;r!==i&&r.parent!==null&&r.parent.f&33554432;)r=r.parent;let o=()=>{s&&Ui(n(...s),e)&&t(null,...s)},c=r.teardown;r.teardown=()=>{o(),c?.()}}}),e}function Gi(e,t,n){if(e==null)return t(void 0),n&&n(void 0),d;let r=pr(()=>e.subscribe(t,n));return r.unsubscribe?()=>r.unsubscribe():r}var Ki=[];function qi(e,t){return{subscribe:Ji(e,t).subscribe}}function Ji(e,t=d){let n=null,r=new Set;function i(t){if(De(e,t)&&(e=t,n)){let t=!Ki.length;for(let t of r)t[1](),Ki.push(t,e);if(t){for(let e=0;e{r.delete(c),r.size===0&&n&&(n(),n=null)}}return{set:i,update:a,subscribe:o}}function Yi(e,t,n){let r=!Array.isArray(e),i=r?[e]:e;if(!i.every(Boolean))throw Error(`derived() expects stores as input, got a falsy value`);let a=t.length<2;return qi(n,(e,n)=>{let o=!1,s=[],c=0,l=d,u=()=>{if(c)return;l();let i=t(r?s[0]:s,e,n);a?e(i):l=typeof i==`function`?i:d},p=i.map((e,t)=>Gi(e,e=>{s[t]=e,c&=~(1<{c|=1<t=e)(),t}var Zi=!1,Qi=Symbol(`unmounted`);function $i(e,t,n){let r=n[t]??={store:null,source:Wt(void 0),unsubscribe:d};if(r.store!==e&&!(Qi in n)){if(r.unsubscribe(),r.store=e??null,e==null)r.source.v=void 0,r.unsubscribe=d;else{var i=!0;r.unsubscribe=Gi(e,e=>{i?r.source.v=e:I(r.source,e)}),i=!1}}return e&&Qi in n?Xi(e):W(r.source)}function ea(e,t,n){let r=n[t];return r&&r.store!==e&&(r.unsubscribe(),r.unsubscribe=d),e}function ta(){let e={};function t(){yn(()=>{for(var t in e)e[t].unsubscribe();i(e,Qi,{enumerable:!1,value:!0})})}return[e,t]}function na(e){var t=Zi;try{return Zi=!1,[e(),Zi]}finally{Zi=t}}var ra={get(e,t){if(!e.exclude.has(t))return e.props[t]},set(e,t){return!1},getOwnPropertyDescriptor(e,t){if(!e.exclude.has(t)&&t in e.props)return{enumerable:!0,configurable:!0,value:e.props[t]}},has(e,t){return!e.exclude.has(t)&&t in e.props},ownKeys(e){return Reflect.ownKeys(e.props).filter(t=>!e.exclude.has(t))}};function ia(e,t,n){return new Proxy({props:e,exclude:t},ra)}function $(e,t,n,r){var i=!0,o=!!(n&8),s=!!(n&16),c=r,l=!0,u=void 0,d=()=>s&&i?(u??=pt(r),W(u)):(l&&(l=!1,c=s?pr(r):r),c);let f;if(o){var p=re in e||ae in e;f=a(e,t)?.set??(p&&t in e?n=>e[t]=n:void 0)}var m,h=!1;o?[m,h]=na(()=>e[t]):m=e[t],m===void 0&&r!==void 0&&(m=d(),f&&(i&&Ie(t),f(m)));var g=i?()=>{var n=e[t];return n===void 0?d():(l=!0,n)}:()=>{var n=e[t];return n!==void 0&&(c=void 0),n===void 0?c:n};if(i&&!(n&4))return g;if(f){var _=e.$$legacy;return(function(e,t){return arguments.length>0?((!i||!t||_||h)&&f(t?g():e),e):g()})}var v=!1,y=(n&1?pt:gt)(()=>(v=!1,g()));o&&W(y);var b=U;return(function(e,t){if(arguments.length>0){let n=t?W(y):i&&o?Zt(e):e;return I(y,n),v=!0,c!==void 0&&(c=n),e}return Vn&&v||b.f&16384?y.v:W(y)})}function aa(e){Ue===null&&ke(`onMount`),bn(()=>{let t=pr(e);if(typeof t==`function`)return t})}function oa(e){Ue===null&&ke(`onDestroy`),aa(()=>()=>pr(e))}typeof window<`u`&&((window.__svelte??={}).v??=new Set).add(`5`);async function sa(){let e=await fetch(`/api/overview`);if(!e.ok)throw Error(`overview ${e.status}`);return e.json()}async function ca(e,t){let n=await fetch(e);if(!n.ok)throw Error(`${t} ${n.status}`);return n.json()}function la(e){return ca(`/api/briefing?id=${encodeURIComponent(e)}`,`briefing`)}async function ua(e){let t={subject_kind:e.subjectKind,subject_id:e.subjectId,kind:e.kind,request_id:e.requestId};e.until!==void 0&&(t.until=e.until),e.text!==void 0&&(t.text=e.text),e.includeMembers!==void 0&&(t.include_members=e.includeMembers);let n=await fetch(`/api/decisions`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)});if(!n.ok)throw Error(`decision ${n.status}: ${await n.text()}`);return n.json()}function da(e,t,n={}){let r=new URLSearchParams({subject_kind:e,subject_id:t});return n.limit!==void 0&&r.set(`limit`,String(n.limit)),n.before!==void 0&&r.set(`before`,n.before),ca(`/api/decisions?${r.toString()}`,`decisions`)}async function fa(e,t){let n=await fetch(`/api/decisions/${encodeURIComponent(e)}/undo`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({request_id:t})});if(!n.ok)throw Error(`undo ${n.status}: ${await n.text()}`);return n.json()}function pa(e,t){let n=new URLSearchParams({after:String(t),limit:`200`});return ca(`/api/decisions/${encodeURIComponent(e)}/members?${n}`,`member decisions`)}function ma(e=``){return ca(`/api/devices${e===``?``:`?after=${encodeURIComponent(e)}`}`,`devices`)}function ha(e,t=``){let n=t===``?``:`?history_after=${encodeURIComponent(t)}`;return ca(`/api/devices/${encodeURIComponent(e)}${n}`,`device`)}function ga(){return ca(`/api/health`,`health`)}function _a(e){return ca(`/api/incidents/${encodeURIComponent(e)}`,`incident`)}function va(){let e=0,t=0;return{start(){return e+=1,{id:e,stream:t}},streamed(){t+=1},invalidate(){e+=1},current(n){return n.id===e&&n.stream===t}}}var ya=[`open`,`incident`,`resync`];function ba({url:e=`/events`,retryMs:t=3e3,createSource:n=e=>new EventSource(e),schedule:r=(e,t)=>setTimeout(e,t),cancelSchedule:i=e=>clearTimeout(e),onOverview:a=()=>{},onIncident:o=()=>{}}={}){let s=Ji(`connecting`),c=Ji(0),l=null,u=null,d=0;function f(){if(d+=1,u!==null&&(i(u),u=null),l!==null){l.onopen=null,l.onmessage=null,l.onerror=null;for(let e of[...ya,`overview`])l.removeEventListener?.(e,p[e]);l.close(),l=null}}let p={};for(let e of ya)p[e]=()=>{c.update(e=>e+1),o(e)};p.overview=e=>{try{a(JSON.parse(e.data))}catch{}};function m(){f();let i=d;s.set(`connecting`);let a=n(e);l=a,a.onopen=()=>{i===d&&s.set(`live`)};for(let e of[...ya,`overview`])a.addEventListener(e,p[e]);a.onerror=()=>{if(i===d){if(a.readyState===2){f(),s.set(`retrying`);let e=d;u=r(()=>{e===d&&m()},t)}else s.set(`retrying`)}}}function h(){f()}return{connection:s,incidentRevision:c,connect:m,disconnect:h}}var xa=Symbol(`watcherbridge.connection`);function Sa(e){Ke(xa,e)}function Ca(){return Ge(xa)}function wa(){try{return Ca()}catch{return null}}function Ta(e){let t=document.activeElement,n=t?.closest?.(`[data-rows]`);if(!n)return!1;let r=[...n.querySelectorAll(`[data-row]`)];if(r.length===0)return!1;let i=r.indexOf(t);return i===-1&&(i=e===1?-1:0),(r[i+e]??(e===1?r[0]:r[r.length-1])).focus(),!0}function Ea(e){let t=e.target;if(t===null||t.isContentEditable)return!0;let n=t.tagName;return n===`INPUT`||n===`TEXTAREA`||n===`SELECT`}function Da(){let e=new Map;function t(t,n,r,i){e.has(t)||e.set(t,new Map),e.get(t).set(n,{label:r,handler:i})}function n(t,n){if(Ea(n)||n.metaKey||n.ctrlKey||n.altKey)return!1;let r=e.get(t)?.get(n.key);return r?(r.handler(n),!0):!1}function r(t){return[...e.get(t)?.entries()??[]].map(([e,t])=>({key:e,label:t.label}))}return{register:t,dispatch:n,describe:r}}var Oa=[{name:`briefing`,pattern:/^#\/briefing\/(.+)$/},{name:`incident`,pattern:/^#\/incidents\/(.+)$/},{name:`device`,pattern:/^#\/devices\/(.+)$/},{name:`devices`,pattern:/^#\/devices\/?$/},{name:`health`,pattern:/^#\/health$/}],ka={home:`Review overview`,devices:`Reported hosts`,device:`Reported host detail`,briefing:`Briefing`,incident:`Incident`,health:`Health`};function Aa(e){let t=e||`#/`;for(let e of Oa){let n=t.match(e.pattern);if(n)return n[1]===void 0?{name:e.name}:{name:e.name,id:decodeURIComponent(n[1])}}return{name:`home`}}function ja(e){return ka[e]??ka.home}var Ma=G(``),Na=G(`

                                      `);function Pa(e,t){let n=$(t,`kind`,3,`status`),r=$(t,`actionLabel`,3,null),i=$(t,`onAction`,3,null),a=$(t,`class`,3,``);var o=Na(),s=L(o);ii(s,()=>t.children);var c=B(s,2),l=e=>{var t=Ma(),n=z(t,!0);V(()=>J(n,r())),Dr(`click`,t,function(...e){i()?.apply(this,e)}),q(e,t)};Y(c,e=>{r()!==null&&e(l)}),k(o),V(()=>{Q(o,`role`,n()),Z(o,1,X(a()||void 0))}),q(e,o)}Or([`click`]);var Fa={pill:`_pill_awt79_1`,large:`_large_awt79_14`,priority:`_priority_awt79_19`},Ia=new Set([`$$slots`,`$$events`,`$$legacy`,`priority`,`large`,`children`]),La=G(``);function Ra(e,t){j(t,!0);let n=$(t,`priority`,3,!1),r=$(t,`large`,3,!1),i=ia(t,Ia);var a=La();Fi(a,()=>({class:`${Fa.pill}${n()?` ${Fa.priority}`:``}${r()?` ${Fa.large}`:``}`,...i})),ii(L(a),()=>t.children),k(a),q(e,a),M()}function za(e){let t=new Date(e??``);return Number.isNaN(t.getTime())?{local:`unknown`,utc:`unknown`}:{local:t.toLocaleString(),utc:t.toISOString()}}function Ba(e){switch(e){case`rules`:return`Deterministic rules`;case`model`:return`Model suggestion`;case`agent`:return`Investigator agent`;case`fallback`:return`Deterministic fallback`;case`legacy`:return`Earlier version (source unknown)`;default:return`Unknown source`}}function Va(e){switch(e){case`reported_device`:return`Reported device`;case`address`:return`Address context — not a device identity`;case`event`:return`Unresolved events — not a device identity`;case`legacy`:return`Legacy profile`;default:return`Unknown class`}}function Ha(e){return{weak_appearance:`Weak sightings`,weak_disappearance:`Weak disappearances`,port_closed:`Ports closed`,hostname_change:`Hostname changes`,os_refinement:`OS refinements`,other:`Other changes`}[e]??e}function Ua(e,t=[],n=[]){if(e!==`other`)return Ha(e);let r=new Map([[`low`,0],[`medium`,1],[`high`,2]]),i=new Map;for(let e of t)e.view_role===`previous`&&e.event_id&&i.set(e.event_id,r.get(e.attributes?.identity_confidence));for(let e of t){if(e.view_role!==`current`)continue;let t=i.get(e.event_id),n=r.get(e.attributes?.identity_confidence);if(t!==void 0&&n!==void 0&&ne.event_type));if(a.size===1){if(a.has(`host.appeared`))return`New host reported`;if(a.has(`host.disappeared`))return`Host disappearance reported`;if(a.has(`host.changed`))return`Reported host details changed`}return a.size>1?`Reported network changes`:`Reported details changed`}function Wa(e){let t=/^(\d+)h0m0s$/.exec(e);return t?`${t[1]} hours`:e}function Ga(e=[]){let t=(e??[]).map(e=>new Date(e.occurred_at??``)).filter(e=>!Number.isNaN(e.getTime())).sort((e,t)=>e-t);if(t.length===0)return null;let n=t.length!==e.length,r=za(t[0].toISOString());if(t.length===1)return{...r,partial:n};let i=za(t[t.length-1].toISOString());return{local:`${r.local} – ${i.local}`,utc:`${r.utc} – ${i.utc}`,partial:n}}function Ka(e=[]){if(e.length!==1)return null;let t=(e??[]).filter(e=>e.view_role===`host`||e.view_role===`current`),n=new Set(t.map(e=>e.event_id));if(t.length!==1||n.size!==1)return null;let r=t[0].attributes??{},i=e=>typeof e==`string`&&e!==``?e:null;return{event_id:t[0].event_id,view_role:t[0].view_role,hostname:i(r.hostname),ip:i(r.ip),mac:i(r.mac),randomized:typeof r.randomized==`boolean`?r.randomized:null,identity_confidence:i(r.identity_confidence)??`unknown`,identity_source:i(r.identity_source)??`unknown`}}function qa(e){return e===!0?`Randomized (scanner-reported)`:e===!1?`Not randomized (scanner-reported)`:`Randomization unknown`}var Ja=G(`

                                      Nothing flagged. New briefings appear here when the bridge reports them.

                                      `),Ya=G(` `,1),Xa=G(``),Za=G(``),Qa=G(`
                                      `),$a=G(` `,1),eo=G(`
                                    • `),to=G(`
                                        `),no=G(`

                                        `);function ro(e,t){j(t,!0);let n=$(t,`items`,19,()=>[]),r=$(t,`selectedId`,3,null),i=$(t,`titles`,19,()=>({})),a=$(t,`onselect`,3,null),o=$(t,`members`,3,null),s=Zt({});var c=no(),l=L(c),u=z(l),f=B(l,2),p=e=>{q(e,Ja())},m=e=>{var t=to();Qr(t,21,n,e=>e.id,(e,t)=>{var n=eo();{let e=e=>{var n=Ya(),r=R(n);{let e=N(()=>`Priority: ${W(t).priority}`);Ra(r,{priority:!0,get"data-priority"(){return W(t).priority},get"aria-label"(){return W(e)},children:(e,n)=>{A();var r=K();V(()=>J(r,W(t).priority)),q(e,r)},$$slots:{default:!0}})}var a=B(r,2),o=L(a),s=z(o),c=z(B(o),!0);k(a);var l=B(a,2),u=L(l);Ra(u,{children:(e,n)=>{A();var r=K();V(()=>J(r,W(t).status)),q(e,r)},$$slots:{default:!0}});var d=B(u),f=z(d,!0);k(l),V((e,n)=>{J(s,`${W(t).kind===`incident`?`Incident · `:``}${e??``}`),J(c,W(t).id),Q(d,`datetime`,W(t).created_at),Q(d,`title`,W(t).created_at),J(f,n)},[()=>W(t).kind===`briefing`?i()[W(t).id]??Ua(W(t).change_kind):Ha(W(t).change_kind),()=>new Date(W(t).created_at).toLocaleString()]),q(e,n)};var c=L(n),l=n=>{var i=Ir(),o=R(i),s=n=>{var i=Xa(),o=L(i);e(o),k(i),V(()=>Q(i,`aria-current`,r()===W(t).id?`true`:void 0)),Dr(`click`,i,()=>a()(W(t))),q(n,i)},c=n=>{var r=Za(),i=L(r);e(i),k(r),V(()=>Q(r,`href`,W(t).kind===`briefing`?`#/briefing/${W(t).id}`:`#/incidents/${W(t).id}`)),q(n,r)};Y(o,e=>{a()?e(s):e(c,-1)}),q(n,i)},u=t=>{var n=Qa(),r=L(n);e(r),k(n),q(t,n)};Y(c,e=>{W(t).kind===`briefing`||W(t).kind===`incident`?e(l):e(u,-1)});var f=B(c,2),p=e=>{let n=N(()=>s[W(t).id]??!1);var r=$a(),i=R(r),a=z(i,!0);ii(B(i,2),()=>o()??d,()=>W(t).id,()=>W(n)),V(()=>{Q(i,`aria-expanded`,W(n)),J(a,W(n)?`Hide members`:`Show members`)}),Dr(`click`,i,()=>{s[W(t).id]=!W(n)}),q(e,r)};Y(f,e=>{W(t).kind===`incident`&&e(p)}),k(n)}V(()=>Q(n,`data-status`,W(t).status)),q(e,n)}),k(t),q(e,t)};Y(f,e=>{n().length===0?e(p):e(m,-1)}),k(c),V(()=>J(u,`Needs attention (${n().length??``})`)),q(e,c),M()}Or([`click`]);var io={list:`_list_18cpf_1`},ao=G(`
                                      1. `),oo=G(`
                                          `),so=G(`, last + change `,1),co=G(`

                                            `);function lo(e,t){j(t,!0);let n=$(t,`reasons`,19,()=>[]);var r=co(),i=L(r),a=z(i),o=B(i,2),s=L(o),c=z(s,!0),l=B(s,2);Qr(l,20,()=>[`quiet`,`review`,`act`],e=>e,(e,n)=>{var r=ao(),i=z(r,!0);V(()=>{Q(r,`aria-current`,t.verdict===n?`true`:void 0),J(i,n)}),q(e,r)}),k(l),k(o);var u=B(o,2),d=L(u);Ra(L(d),{children:(e,n)=>{A();var r=K();V(()=>J(r,`Verdict: ${t.verdict??``}`)),q(e,r)},$$slots:{default:!0}}),k(d);var f=B(d,2);Ra(L(f),{get"data-state"(){return t.coverage},children:(e,n)=>{A();var r=K();V(()=>J(r,`Coverage: ${t.coverage??``}`)),q(e,r)},$$slots:{default:!0}}),k(f);var p=B(f,2);Ra(L(p),{children:(e,n)=>{A();var r=K();V(()=>J(r,`Liveness: ${t.liveness??``}`)),q(e,r)},$$slots:{default:!0}}),k(p),k(u);var m=B(u,2),h=e=>{var t=oo();Qr(t,20,n,e=>e,(e,t)=>{var n=ao(),r=z(n,!0);V(()=>J(r,t)),q(e,n)}),k(t),q(e,t)};Y(m,e=>{n().length>0&&e(h)});var g=B(m,2),_=L(g),v=B(_),y=e=>{var n=so(),r=B(R(n)),i=z(r,!0);V(e=>{Q(r,`datetime`,t.lastChange),Q(r,`title`,t.lastChange),J(i,e)},[()=>new Date(t.lastChange).toLocaleString()]),q(e,n)};Y(v,e=>{t.lastChange&&e(y)}),k(g),k(r),V((e,n)=>{Q(r,`data-verdict`,t.verdict),J(a,`Review overview · last ${e??``}`),J(c,t.headline),Z(u,1,X(io.list)),J(_,`${t.receipts??``} ${t.receipts===1?`receipt`:`receipts`} in the last ${n??``}`)},[()=>Wa(t.window),()=>Wa(t.window)]),q(e,r),M()}var uo=G(`
                                            `),fo=G(`

                                            Reported changes

                                            Counts in this review window. Expected means explicitly marked by you.

                                            `);function po(e,t){j(t,!0);let n=[`weak_appearance`,`weak_disappearance`,`port_closed`,`hostname_change`,`os_refinement`,`other`],r=$(t,`digest`,19,()=>({})),i=$(t,`explained`,19,()=>({}));var a=fo(),o=B(L(a),4);Qr(o,20,()=>n,e=>e,(e,t)=>{var n=uo(),a=L(n),o=z(a,!0),s=B(a,2),c=L(s),l=z(B(c));k(s),k(n),V(e=>{J(o,e),J(c,`${r()[t]??0??``} `),J(l,`expected ${i()[t]??0??``}`)},[()=>Ha(t)]),q(e,n)}),k(o),k(a),q(e,a),M()}var mo=G(`

                                            No sources registered yet.

                                            `),ho=G(`Last report `),go=G(`
                                          1. `),_o=G(`
                                              `),vo=G(`
                                            • `),yo=G(`
                                                `),bo=G(`

                                                `);function xo(e,t){j(t,!0);let n=$(t,`sources`,19,()=>[]);var r=bo(),i=L(r),a=z(i),o=B(i,2),s=e=>{q(e,mo())},c=e=>{var t=yo();Qr(t,21,n,e=>e.scope,(e,t)=>{var n=vo(),r=L(n),i=z(r,!0),a=B(r,2);Ra(a,{children:(e,n)=>{A();var r=K();V(()=>J(r,`Status: ${W(t).status??``}`)),q(e,r)},$$slots:{default:!0}});var o=B(a,2);Ra(o,{children:(e,n)=>{A();var r=K();V(()=>J(r,`Liveness: ${W(t).liveness??``}`)),q(e,r)},$$slots:{default:!0}});var s=B(o,2),c=e=>{var n=ho(),r=B(L(n)),i=z(r,!0);k(n),V(e=>{Q(r,`datetime`,W(t).last_report_at),Q(r,`title`,W(t).last_report_at),J(i,e)},[()=>new Date(W(t).last_report_at).toLocaleString()]),q(e,n)};Y(s,e=>{W(t).last_report_at&&e(c)});var l=B(s,2),u=e=>{var n=_o();Qr(n,20,()=>W(t).reasons,e=>e,(e,t)=>{var n=go(),r=z(n,!0);V(()=>J(r,t)),q(e,n)}),k(n),q(e,n)};Y(l,e=>{W(t).reasons.length>0&&e(u)}),k(n),V(()=>J(i,W(t).scope)),q(e,n)}),k(t),q(e,t)};Y(o,e=>{n().length===0?e(s):e(c,-1)}),k(r),V(()=>J(a,`Sources (${n().length??``})`)),q(e,r),M()}var So=G(`

                                                Overview unavailable

                                                `),Co=G(`

                                                `),wo=G(`

                                                Jump to selected review ↓

                                                `),To=G(`
                                                Selected review Open full page →
                                                `,1),Eo=G(`

                                                Select a review

                                                Choose an item in Needs attention to read its evidence and recommended check, and record your decision.

                                                New reports update the list automatically.

                                                `),Do=G(`
                                                `),Oo=G(`

                                                j k move between rows · Enter select · ? shortcuts

                                                `,1);function ko(e,t){j(t,!0);let n=$(t,`overview`,3,null),r=$(t,`loadError`,3,null),i=$(t,`selected`,15,null),a=$(t,`members`,3,null),o=$(t,`pane`,3,null),s=N(()=>i()?.id??null),c=F(Zt({}));function l(e,t){W(c)[e]!==t&&I(c,Object.fromEntries([...Object.entries(W(c)),[e,t]].slice(-32)),!0)}function u(e){i({id:e.id,kind:e.kind})}function f(){i(null),document.getElementById(`review-list`)?.focus()}let p=N(()=>n()!==null&&(n().coverage===`degraded`||n().coverage===`blind`));var m=Ir(),h=R(m),g=e=>{var t=So(),n=z(B(L(t),2));k(t),V(()=>J(n,`The bridge did not return an overview (${r()??``}). The connection retries automatically.`)),q(e,t)},_=e=>{Pa(e,{children:(e,t)=>{A(),q(e,K(`Loading overview…`))},$$slots:{default:!0}})},v=e=>{var t=Oo(),r=R(t),m=e=>{var t=Co(),r=z(t);V(()=>J(r,`No receipts in the last ${n().window??``} — quiet here means no data, not a secure network.`)),q(e,t)};Y(r,e=>{n().receipts===0&&e(m)});var h=B(r,2),g=e=>{Pa(e,{kind:`alert`,class:`coverage-note`,children:(e,t)=>{A();var r=K();V(()=>J(r,`Coverage is ${n().coverage??``}. Treat quiet results with caution until the reasons below clear.`)),q(e,r)},$$slots:{default:!0}})};Y(h,e=>{W(p)&&e(g)});var _=B(h,2);{let e=N(()=>n().reasons??[]);lo(_,{get verdict(){return n().verdict},get headline(){return n().headline},get coverage(){return n().coverage},get liveness(){return n().liveness},get reasons(){return W(e)},get receipts(){return n().receipts},get window(){return n().window},get lastChange(){return n().last_change}})}var v=B(_,2),y=L(v),b=L(y);ro(b,{get items(){return n().attention},get selectedId(){return W(s)},get titles(){return W(c)},onselect:u,get members(){return a()}});var x=B(b,2),S=e=>{var t=wo();Dr(`click`,z(t),e=>{e.preventDefault(),document.getElementById(`selected-review`)?.focus()}),q(e,t)};Y(x,e=>{i()&&e(S)});var C=B(x,2);{let e=N(()=>n().explained??{});po(C,{get digest(){return n().digest},get explained(){return W(e)}})}xo(B(C,2),{get sources(){return n().sources}}),A(2),k(y);var w=B(y,2),T=e=>{var t=Do(),n=L(t),r=e=>{var t=To(),n=R(t),r=B(L(n),2),a=B(r,2);k(n),qr(B(n,2),()=>i().id,e=>{var t=Ir();ii(R(t),()=>o()??d,i,()=>l),q(e,t)}),V(()=>Q(r,`href`,i().kind===`briefing`?`#/briefing/${i().id}`:`#/incidents/${i().id}`)),Dr(`click`,a,f),q(e,t)},a=e=>{q(e,Eo())};Y(n,e=>{i()?e(r):e(a,-1)}),k(t),q(e,t)};Y(w,e=>{(i()!==null||n().attention.length>0)&&e(T)}),k(v),V(()=>Q(v,`data-empty`,n().attention.length===0&&i()===null)),q(e,t)};Y(h,e=>{r()!==null&&n()===null?e(g):n()===null?e(_,1):e(v,-1)}),q(e,m),M()}Or([`click`]);var Ao=G(`
                                              • `),jo=G(`
                                                  `);function Mo(e,t){j(t,!0);let n=()=>$i(d,`$incidentRevision`,r),[r,i]=ta(),a=$(t,`expanded`,3,!1),o=F(void 0),s=F(void 0),c=F(!1),l=!0,u=0,d=wa()?.incidentRevision??null,f=-1;bn(()=>{if(!d)return;let e=n();f===-1?f=e:e!==f&&(f=e,p())}),aa(()=>{if(!d)return window.addEventListener(`watcherbridge:incident`,p),()=>window.removeEventListener(`watcherbridge:incident`,p)});function p(){a()&&(I(o,void 0),I(s,void 0),m())}oa(()=>{l=!1}),bn(()=>{a()&&l&&W(o)===void 0&&W(s)===void 0&&!W(c)&&m()});async function m(){let e=++u;I(s,void 0),I(c,!0);try{let n=await _a(t.incidentId);l&&e===u&&I(o,n.members,!0)}catch(t){l&&e===u&&I(s,t instanceof Error?t.message:String(t),!0)}finally{l&&e===u&&I(c,!1)}}var h=Ir(),g=R(h),_=e=>{var t=Ir(),n=R(t),r=e=>{Pa(e,{children:(e,t)=>{A(),q(e,K(`Loading members…`))},$$slots:{default:!0}})},i=e=>{Pa(e,{kind:`alert`,children:(e,t)=>{A();var n=K();V(()=>J(n,W(s))),q(e,n)},$$slots:{default:!0}})},a=e=>{var t=jo();Qr(t,21,()=>W(o),e=>e.briefing_id,(e,t)=>{var n=Ao(),r=L(n),i=z(r,!0);Ra(B(r,2),{children:(e,n)=>{A();var r=K();V(()=>J(r,W(t).priority)),q(e,r)},$$slots:{default:!0}}),k(n),V(()=>{Q(r,`href`,`#/briefing/${W(t).briefing_id}`),J(i,W(t).briefing_id)}),q(e,n)}),k(t),q(e,t)};Y(n,e=>{W(c)&&W(o)===void 0?e(r):W(s)===void 0?W(o)!==void 0&&e(a,2):e(i,1)}),q(e,t)};Y(g,e=>{a()&&e(_)}),q(e,h),M(),i()}function No(e){let t=Ji(null),n=Ji(null),r=Ji(null),i=Ji(!1),a={gen:0};async function o(){let o=a.gen+=1;r.set(null),Xi(t)===null&&(n.set(null),i.set(!0));try{let i=await e();return o===a.gen?(t.set(i),n.set(null),r.set(null),`applied`):`stale`}catch(e){if(o!==a.gen)return`stale`;let i=e instanceof Error?e.message:String(e);return Xi(t)===null?n.set(i):r.set(i),`failed`}finally{o===a.gen&&i.set(!1)}}function s(){a.gen+=1,i.set(!1)}return{data:t,error:n,refreshError:r,loading:i,refresh:o,invalidate:s}}function Po({data:e=null,initial:t=null,error:n=null,refreshError:r=null}={}){return(e??t)===null?null:r??(e===null?n:null)}function Fo(e){return e!==null&&(e.clamped||e.baseline!==e.priority||(e.model_suggestion??e.baseline)!==e.priority)}function Io(e){return(e??[]).filter(e=>[`unknown_subject`,`blocked`,`error`,`unavailable`,`truncated`].includes(e.outcome))}function Lo(e){let t=[];for(let n of e??[]){let e=n.summary||`step:${n.step}`,r=t.find(t=>t.key===e);r||(r={key:e,summary:n.summary,steps:[]},t.push(r)),r.steps.push(n.step)}return t}function Ro(e){return e!==null&&!e.observations_truncated&&!e.referenced_truncated}function zo(e,t){if(!e)return!1;let n=Array.from(e.querySelectorAll(`[data-evidence]`)).find(e=>e.dataset.evidence===t);if(!n)return!1;for(let t=n;t&&t!==e;t=t.parentElement)t.tagName===`DETAILS`&&(t.open=!0);return n.scrollIntoView({block:`nearest`}),n.focus({preventScroll:!0}),!0}var Bo={copyBtn:`_copyBtn_1lk9i_7`},Vo=G(` `),Ho=G(` `,1);function Uo(e,t){j(t,!0);let n=$(t,`name`,3,`value`),r=F(`idle`),i=F(null),a=!0;oa(()=>{a=!1,W(i)!==null&&clearTimeout(W(i))});async function o(){W(i)!==null&&(clearTimeout(W(i)),I(i,null)),I(r,`idle`);try{if(navigator.clipboard?.writeText!==void 0)await navigator.clipboard.writeText(t.value);else{let e=document.createElement(`textarea`);e.value=t.value,e.className=`wb-clipboard-buffer`,document.body.appendChild(e);let n=document.activeElement,r=!1;try{e.select(),r=document.execCommand(`copy`)}finally{e.remove(),n instanceof HTMLElement&&n.focus({preventScroll:!0})}if(!r)throw Error(`copy rejected`)}if(!a)return;I(r,`copied`),I(i,setTimeout(()=>{I(r,`idle`),I(i,null)},1500),!0)}catch{a&&I(r,`failed`)}}var s=Ho(),c=R(s),l=z(c,!0),u=B(c,2),d=e=>{var t=Vo(),r=z(t);V(()=>J(r,`Could not copy the ${n()??``}; select and copy it manually.`)),q(e,t)};Y(u,e=>{W(r)===`failed`&&e(d)}),V(()=>{Z(c,1,X(Bo.copyBtn)),Q(c,`aria-label`,`Copy ${n()}`),J(l,W(r)===`copied`?`Copied`:W(r)===`failed`?`Copy failed`:`Copy`)}),Dr(`click`,c,o),q(e,s),M()}Or([`click`]);var Wo=G(`
                                                  Reported host
                                                  IP address
                                                  MAC address
                                                  `,1),Go=G(`
                                                  Reported identities
                                                  See the individual report views below

                                                  `),Ko=G(`(truncated)`),qo=G(` `),Jo=G(`
                                                  Reported scan target
                                                  Analysis source
                                                  `);function Yo(e,t){j(t,!0);let n=$(t,`identity`,3,null),r=$(t,`identityComplete`,3,!1),i=$(t,`primaryEvent`,3,null),a=$(t,`eventCount`,3,0),o=$(t,`range`,3,null),s=$(t,`referencedTruncated`,3,!1);var c=Jo(),l=L(c),u=e=>{var t=Wo(),r=R(t),i=z(B(L(r)),!0);k(r);var a=B(r,2),o=B(L(a)),s=L(o,!0),c=B(s),l=e=>{Uo(e,{get value(){return n().ip},name:`IP address`})};Y(c,e=>{n().ip!==null&&e(l)}),k(o),k(a);var u=B(a,2),d=B(L(u)),f=L(d,!0),p=B(f),m=e=>{Uo(e,{get value(){return n().mac},name:`MAC address`})};Y(p,e=>{n().mac!==null&&e(m)}),k(d),k(u),V(()=>{J(i,n().hostname??`Not reported`),J(s,n().ip??`Not reported`),J(f,n().mac??`Not reported`)}),q(e,t)},d=e=>{var t=Go(),n=B(L(t)),i=z(B(L(n)),!0);k(n),k(t),V(()=>J(i,r()?`Grouped changes can describe different host views.`:`Only part of the retained evidence is shown.`)),q(e,t)};Y(l,e=>{n()!==null&&r()?e(u):e(d,-1)});var f=B(l,2),p=B(L(f)),m=L(p,!0),h=B(m),g=e=>{q(e,Ko())};Y(h,e=>{i()?.target_truncated&&e(g)}),k(p),k(f);var _=B(f,2),v=L(_),y=z(v,!0),b=B(v),x=L(b),S=e=>{var t=qo(),n=z(t,!0);V(()=>{Q(t,`title`,o().utc),J(n,o().local)}),q(e,t)},C=e=>{q(e,K(`Not reported`))};Y(x,e=>{o()===null?e(C,-1):e(S)}),k(b),k(_);var w=B(_,2),T=z(B(L(w)),!0);k(w),k(c),V(e=>{J(m,i()?.target||(a()>1?`Shown per report below`:`Not reported`)),J(y,o()?.partial||s()?`Available report times`:a()>1?`Report time range`:`Report time`),J(T,e)},[()=>Ba(t.source)]),q(e,c),M()}var Xo=`reports`;function Zo(e){return`event:${e}`}function Qo(e){return`step:${e}`}var $o=G(``),es=G(``),ts=G(`

                                                  `);function ns(e,t){j(t,!0);let n=$(t,`identity`,3,null),r=$(t,`identityComplete`,3,!1),i=$(t,`primaryEvent`,3,null),a=$(t,`eventCount`,3,0),o=$(t,`eventsTruncated`,3,!1),s=$(t,`range`,3,null),c=$(t,`referencedTruncated`,3,!1),l=$(t,`onJump`,3,()=>{});var u=ts(),d=L(u),f=L(d),p=z(f,!0),m=B(f,2);{let e=N(()=>`Priority: ${t.priority}`);Ra(m,{priority:!0,get"data-priority"(){return t.priority},get"aria-label"(){return W(e)},children:(e,n)=>{A();var r=K();V(()=>J(r,`${t.priority??``} priority`)),q(e,r)},$$slots:{default:!0}})}k(d);var h=B(d,2),g=z(h,!0),_=B(h,2);Yo(_,{get identity(){return n()},get identityComplete(){return r()},get primaryEvent(){return i()},get eventCount(){return a()},get range(){return s()},get referencedTruncated(){return c()},get source(){return t.source}});var v=B(_,2),y=L(v),b=z(y),x=B(y,2),S=e=>{var t=$o();Dr(`click`,t,()=>l()(Zo(i().event_id))),q(e,t)},C=e=>{var t=es();Dr(`click`,t,()=>l()(Xo)),q(e,t)};Y(x,e=>{i()?e(S):a()>0&&e(C,1)}),k(v),k(u),V(()=>{J(p,t.title),J(g,t.description),J(b,`${a()??``}${o()?`+`:``} source report${a()===1?``:`s`}`)}),q(e,u),M()}Or([`click`]);var rs=G(`

                                                  Reported at the time shown. Network conditions may have changed since this report.

                                                  `);function is(e){q(e,rs())}var as=G(` `),os=G(`
                                                  Copy for your investigation
                                                  `),ss=G(``);function cs(e,t){j(t,!0);let n=$(t,`identity`,3,null),r=$(t,`identityComplete`,3,!1);var i=ss(),a=B(L(i),2),o=z(a,!0),s=B(a,2),c=e=>{var t=os(),r=B(L(t),2),i=e=>{var t=as(),r=L(t);Uo(B(r),{get value(){return n().ip},name:`IP address`}),k(t),V(()=>J(r,`${n().ip??``} `)),q(e,t)};Y(r,e=>{n().ip!==null&&e(i)});var a=B(r,2),o=e=>{var t=as(),r=L(t);Uo(B(r),{get value(){return n().mac},name:`MAC address`}),k(t),V(()=>J(r,`${n().mac??``} `)),q(e,t)};Y(a,e=>{n().mac!==null&&e(o)}),k(t),q(e,t)};Y(s,e=>{n()!==null&&r()&&(n().ip!==null||n().mac!==null)&&e(c)}),k(i),V(()=>J(o,t.check)),q(e,i),M()}var ls=G(` `),us=G(`

                                                  Suggestion adjusted to respect the baseline floor and one-step raise limit.

                                                  `),ds=G(`

                                                  Deterministic fallback text: the model path did not produce this briefing.

                                                  `),fs=G(`

                                                  Why this priority

                                                  How the priority was computed
                                                  1. Baseline floor
                                                  2. Model suggestion
                                                  3. Final priority
                                                  `);function ps(e,t){let n=$(t,`baselineRule`,3,null),r=$(t,`modelSuggestion`,3,null),i=$(t,`clamped`,3,!1),a=$(t,`fallbackUsed`,3,!1),o=$(t,`differs`,3,!1);var s=fs(),c=B(L(s),2),l=z(c,!0),u=B(c,2),d=L(u);Ra(d,{priority:!0,get"data-priority"(){return t.priority},children:(e,n)=>{A();var r=K();V(()=>J(r,`Final priority: ${t.priority??``}`)),q(e,r)},$$slots:{default:!0}});var f=B(d),p=e=>{var t=ls(),r=z(t,!0);V(()=>J(r,n())),q(e,t)};Y(f,e=>{n()&&e(p)}),k(u);var m=B(u,2),h=B(L(m),2),g=L(h),_=z(B(L(g)),!0);k(g);var v=B(g,2),y=z(B(L(v)),!0);k(v);var b=B(v,2),x=z(B(L(b)),!0);k(b),k(h);var S=B(h,2),C=e=>{q(e,us())};Y(S,e=>{i()&&e(C)}),k(m);var w=B(m,2),T=e=>{q(e,ds())};Y(w,e=>{a()&&e(T)}),k(s),V(()=>{J(l,t.priorityReason),m.open=o(),J(_,t.baseline),J(y,r()??`No model suggestion — baseline stands`),J(x,t.priority)}),q(e,s)}var ms=G(``);function hs(e,t){j(t,!0);let n=N(()=>za(t.iso));var r=ms(),i=z(r,!0);V(()=>{Q(r,`datetime`,t.iso),Q(r,`title`,W(n).utc),J(i,W(n).local)}),q(e,r),M()}var gs={card:`_card_1sfyz_1`,heading:`_heading_1sfyz_14`,reportId:`_reportId_1sfyz_23`,reportTime:`_reportTime_1sfyz_27`,body:`_body_1sfyz_35`,view:`_view_1sfyz_40`,identity:`_identity_1sfyz_50`,confidence:`_confidence_1sfyz_68`,attributes:`_attributes_1sfyz_75`,profileChip:`_profileChip_1sfyz_85`},_s=G(`

                                                  No retained observation for this event. Its reference is retained, but a saved scanner view is unavailable.

                                                  `),vs=G(`
                                                  Reported vendor
                                                  `),ys=G(`
                                                  Reported OS
                                                  `),bs=G(`
                                                  Reported device
                                                  `),xs=G(`

                                                  Some reported fields were truncated at ingest.

                                                  `),Ss=G(`
                                                1. `),Cs=G(`
                                                    `),ws=G(`Open reported context → `),Ts=G(`

                                                    No linked profile is available for this saved view.

                                                    `),Es=G(`

                                                    Hostname
                                                    IP address
                                                    MAC address

                                                    Saved report view · technical attributes
                                                     

                                                    `),Ds=G(`
                                                    Reported

                                                    Reported scan target:
                                                    Received

                                                    `);function Os(e,t){j(t,!0);let n=$(t,`views`,19,()=>[]),r=$(t,`profileLinks`,19,()=>[]),i=e=>typeof e==`string`&&e.trim()!==``?e:`Not reported`;var a=Ds(),o=L(a),s=L(o),c=L(s),l=z(c,!0);Ra(B(c),{children:(e,n)=>{A();var r=K();V(()=>J(r,t.ref.event_type)),q(e,r)},$$slots:{default:!0}}),k(s);var u=B(s,2);hs(B(L(u)),{get iso(){return t.ref.occurred_at}}),k(u),k(o);var d=B(o,2),f=L(d),p=B(L(f)),m=z(p,!0),h=B(p),g=e=>{q(e,K(`(truncated)`))};Y(h,e=>{t.ref.target_truncated&&e(g)}),hs(B(h,3),{get iso(){return t.ref.received_at}}),k(f);var _=B(f,2),v=e=>{q(e,_s())},y=e=>{var t=Ir();Qr(R(t),17,n,e=>`${e.event_id}:${e.view_role}`,(e,t)=>{let n=N(()=>W(t).attributes??{});var a=Es(),o=L(a),s=z(o,!0),c=B(o,2),l=L(c),u=z(B(L(l)),!0);k(l);var d=B(l,2),f=z(B(L(d)),!0);k(d);var p=B(d,2),m=z(B(L(p)),!0);k(p);var h=B(p,2),g=e=>{var t=vs(),r=z(B(L(t)),!0);k(t),V(()=>J(r,W(n).vendor)),q(e,t)};Y(h,e=>{W(n).vendor&&e(g)});var _=B(h,2),v=e=>{var t=ys(),r=z(B(L(t)),!0);k(t),V(()=>J(r,W(n).os)),q(e,t)};Y(_,e=>{W(n).os&&e(v)});var y=B(_,2),b=e=>{var t=bs(),r=z(B(L(t)),!0);k(t),V(()=>J(r,W(n).device)),q(e,t)};Y(y,e=>{W(n).device&&e(b)}),k(c);var x=B(c,2),S=L(x);Ra(S,{children:(e,t)=>{A();var r=K();V(()=>J(r,`Scanner-reported identity confidence: ${(W(n).identity_confidence||`unknown`)??``}`)),q(e,r)},$$slots:{default:!0}});var C=z(B(S));k(x);var w=B(x,2),T=z(w,!0),E=B(w,2),ee=e=>{q(e,xs())};Y(E,e=>{W(n).attributes_truncated&&e(ee)});var te=B(E,2),ne=z(B(L(te)),!0);k(te);var re=B(te,2),ie=z(re),ae=B(re,2),oe=e=>{var n=Cs();Qr(n,21,()=>W(t).ports,e=>`${e.proto}/${e.port}`,(e,t)=>{var n=Ss(),r=z(n);V(()=>J(r,`${W(t).proto??``}/${W(t).port??``} ${W(t).state??``}${W(t).service?` (${W(t).service})`:``}`)),q(e,n)}),k(n),q(e,n)};Y(ae,e=>{(W(t).ports??[]).length>0&&e(oe)});var se=B(ae,2),ce=e=>{var n=ws(),i=z(B(L(n)));k(n),V((e,t,r)=>{Z(n,1,X(gs.profileChip)),Q(n,`href`,e),J(i,`${t??``} · ${r??``}`)},[()=>`#/devices/${encodeURIComponent(W(t).profile_id)}`,()=>Va(W(t).reference_class),()=>r().find(e=>e.profile_id===W(t).profile_id)?.role??W(t).view_role]),q(e,n)},le=e=>{q(e,Ts())};Y(se,e=>{W(t).profile_id?e(ce):e(le,-1)}),k(a),V((e,r,i,o,l)=>{Z(a,1,X(gs.view)),Q(a,`aria-label`,`${W(t).view_role} view`),J(s,W(t).view_role===`previous`?`Before the reported change`:W(t).view_role===`current`?`After the reported change`:`Reported host`),Z(c,1,X(gs.identity)),J(u,e),J(f,r),J(m,i),Z(x,1,X(gs.confidence)),J(C,`Identity source: ${(W(n).identity_source||`unknown`)??``}`),J(T,o),Z(te,1,X(gs.attributes)),J(ne,l),J(ie,`Snapshot covers ${W(t).ports_total??``} ports${W(t).ports_truncated?` (truncated)`:``}.`)},[()=>i(W(n).hostname),()=>i(W(n).ip),()=>i(W(n).mac),()=>qa(W(n).randomized),()=>JSON.stringify(W(n),null,2)]),q(e,a)}),q(e,t)};Y(_,e=>{n().length===0?e(v):e(y,-1)}),k(d),k(a),V(()=>{Z(a,1,X(gs.card)),Q(a,`data-evidence`,`event:${t.ref.event_id}`),Q(a,`aria-label`,`Saved report ${t.ref.event_id}`),Z(s,1,X(gs.heading)),Z(c,1,`mono ${gs.reportId}`),J(l,t.ref.event_id),Z(u,1,X(gs.reportTime)),Z(d,1,X(gs.body)),J(m,t.ref.target||`Not reported`)}),q(e,a),M()}var ks=G(`

                                                    No referenced events retained.

                                                    `),As=G(`

                                                    More referenced events exist than shown.

                                                    `),js=G(`

                                                    More observations exist than shown; some saved views are omitted.

                                                    `),Ms=G(`

                                                    Open a report to see what the scanner supplied, with its linked context.

                                                    `);function Ns(e,t){j(t,!0);let n=$(t,`events`,19,()=>[]),r=$(t,`viewsFor`,3,()=>[]),i=$(t,`profiles`,19,()=>[]),a=$(t,`referencedTruncated`,3,!1),o=$(t,`observationsTruncated`,3,!1);var s=Ms(),c=L(s),l=L(c),u=z(l);Ra(B(l),{children:(e,t)=>{A(),q(e,K(`Saved at report time`))},$$slots:{default:!0}}),k(c);var d=B(c,4),f=e=>{q(e,ks())},p=e=>{var t=Ir();Qr(R(t),17,n,e=>e.event_id,(e,t)=>{{let n=N(()=>r()(W(t).event_id));Os(e,{get ref(){return W(t)},get views(){return W(n)},get profileLinks(){return i()}})}}),q(e,t)};Y(d,e=>{n().length===0?e(f):e(p,-1)});var m=B(d,2),h=e=>{q(e,As())};Y(m,e=>{a()&&e(h)});var g=B(m,2),_=e=>{q(e,js())};Y(g,e=>{o()&&e(_)}),k(s),V(()=>J(u,`Scanner snapshot${n().length===1?``:`s`}`)),q(e,s),M()}var Ps=G(``),Fs=G(`
                                                  • `),Is=G(`

                                                    What the investigator could establish

                                                      `,1);function Ls(e,t){j(t,!0);let n=$(t,`receipts`,19,()=>[]),r=$(t,`onJump`,3,()=>{});var i=Ir(),a=R(i),o=e=>{var t=Is(),i=B(R(t),2);Qr(i,21,n,Jr,(e,t)=>{var n=Fs(),i=B(L(n)),a=L(i),o=z(a,!0),s=B(a);Qr(s,20,()=>W(t).steps,e=>e,(e,t)=>{var n=Ps(),i=z(n);V(()=>J(i,`View step ${t??``}`)),Dr(`click`,n,()=>r()(Qo(t))),q(e,n)}),k(s),k(i),k(n),V(()=>J(o,W(t).summary||`No interpreted result is available. Open the tool step to inspect the saved response.`)),q(e,n)}),k(i),q(e,t)};Y(a,e=>{n()?.length&&e(o)}),q(e,i),M()}Or([`click`]);var Rs=G(`

                                                      Possible explanation:

                                                      `),zs=G(`

                                                      `),Bs=G(`

                                                      Investigation has limits. Some lookups could not establish retained context. Missing lookup results do not prove this host has no history.

                                                      `),Vs=G(``),Hs=G(`
                                                      Cited evidence
                                                      `),Us=G(`
                                                    • Open reported context
                                                    • `),Ws=G(``),Gs=G(`

                                                      No profile links persisted for this briefing.

                                                      `),Ks=G(`

                                                      More profile links exist than shown.

                                                      `),qs=G(`

                                                      `);function Js(e,t){j(t,!0);let n=$(t,`likelyExplanation`,3,null),r=$(t,`confidence`,3,null),i=$(t,`limited`,3,!1),a=$(t,`receipts`,19,()=>[]),o=$(t,`evidenceRefs`,19,()=>[]),s=$(t,`profiles`,19,()=>[]),c=$(t,`profilesTruncated`,3,!1),l=$(t,`onJump`,3,()=>{});var u=qs(),d=L(u),f=z(d,!0),p=B(d,2),m=e=>{var t=Rs(),r=B(L(t));k(t),V(()=>J(r,` ${n()??``}`)),q(e,t)};Y(p,e=>{n()&&e(m)});var h=B(p,2),g=e=>{var t=zs();Ra(L(t),{children:(e,t)=>{A();var n=K();V(()=>J(n,`Explanation confidence (model self-assessment): ${r()??``}`)),q(e,n)},$$slots:{default:!0}}),k(t),q(e,t)};Y(h,e=>{r()&&e(g)});var _=B(h,2),v=e=>{q(e,Bs())};Y(_,e=>{i()&&e(v)});var y=B(_,2),b=z(y,!0),x=B(y,2);Ls(x,{get receipts(){return a()},get onJump(){return l()}});var S=B(x,2),C=e=>{var t=Hs();Qr(B(L(t),2),19,o,(e,t)=>`${e.event_id??e.tool_step}:${t}`,(e,t)=>{var n=Vs(),r=z(n,!0);V(()=>J(r,W(t).event_id?`Event ${W(t).event_id}`:`Tool step ${W(t).tool_step}`)),Dr(`click`,n,()=>l()(W(t).event_id?Zo(W(t).event_id):Qo(W(t).tool_step))),q(e,n)}),k(t),q(e,t)};Y(S,e=>{o()?.length&&e(C)});var w=B(S,2),T=e=>{var t=Ws(),n=B(L(t));Qr(n,21,s,e=>`${e.profile_id}:${e.role}`,(e,t)=>{var n=Us(),r=L(n),i=z(B(r,2));k(n),V(e=>{Q(r,`href`,e),J(i,`${W(t).profile_id??``} (${W(t).role??``})`)},[()=>`#/devices/${encodeURIComponent(W(t).profile_id)}`]),q(e,n)}),k(n),k(t),q(e,t)},E=e=>{q(e,Gs())};Y(w,e=>{s().length>0?e(T):e(E,-1)});var ee=B(w,2),te=e=>{q(e,Ks())};Y(ee,e=>{c()&&e(te)}),k(u),V(()=>{J(f,t.source===`agent`?`Investigator notes`:`Analysis and retained context`),J(b,t.context)}),q(e,u),M()}Or([`click`]);var Ys={step:`_step_hvx5m_1`,toolName:`_toolName_hvx5m_7`},Xs=G(`
                                                    • Arguments and tokenized result
                                                       
                                                       
                                                    • `);function Zs(e,t){j(t,!0);let n=N(()=>`step-${t.step.step}`),r=N(()=>t.step.summary??(t.step.outcome===`unknown_subject`?`The investigator could not resolve this lookup to a permitted reported subject; history remains unknown.`:t.step.status===`blocked`?`Redaction blocked this result; the lookup did not complete.`:t.step.status===`error`?`Tool execution failed; result unavailable.`:`No interpreted result is available.`));var i=Xs(),a=L(i),o=z(a,!0),s=B(a,2),c=e=>{Ra(e,{children:(e,n)=>{A();var r=K();V(e=>J(r,e),[()=>t.step.outcome.replaceAll(`_`,` `)]),q(e,r)},$$slots:{default:!0}})};Y(s,e=>{t.step.outcome&&e(c)});var l=B(s,2),u=z(l),d=B(l,2),f=z(d,!0),p=B(d,2),m=B(L(p),2),h=z(m),g=z(B(m,2));k(p),k(i),V(()=>{Z(i,1,X(Ys.step)),Q(i,`id`,W(n)),Q(i,`data-evidence`,`step:${t.step.step}`),Z(a,1,`mono ${Ys.toolName}`),J(o,t.step.tool),J(u,`step ${t.step.step??``} · ${t.step.status??``} · ${t.step.duration_ms??``} ms`),J(f,W(r)),J(h,`Args: ${t.step.args??``}`),J(g,`Result: ${t.step.result??``}`)}),q(e,i),M()}var Qs=G(`
                                                        `),$s=G(`

                                                        No agent trace is available for this briefing.

                                                        `),ec=G(`

                                                        Model accounting

                                                        `,1),tc=G(`
                                                        Technical details Tool calls, accounting and provenance

                                                        Executed tool steps

                                                        Provenance

                                                        Briefing
                                                        Group
                                                        Grouping version
                                                        Sequence
                                                        Created
                                                        Grouping anchor
                                                        `);function nc(e,t){j(t,!0);let n=$(t,`traces`,19,()=>[]),r=$(t,`inputTokens`,3,null),i=$(t,`outputTokens`,3,null),a=$(t,`costUsd`,3,null);var o=tc(),s=B(L(o),2),c=B(L(s),2),l=e=>{var t=Qs();Qr(t,21,n,e=>e.step,(e,t)=>{Zs(e,{get step(){return W(t)}})}),k(t),q(e,t)},u=e=>{q(e,$s())};Y(c,e=>{n()?.length?e(l):e(u,-1)});var d=B(c,2),f=e=>{var t=ec(),n=z(B(R(t)));V(()=>J(n,`${r()??`Unknown`??``} input tokens · ${i()??`Unknown`??``} output tokens · ${a()==null?`Cost unknown`:`$${a()}`}`)),q(e,t)};Y(d,e=>{(r()!=null||i()!=null||a()!=null)&&e(f)});var p=B(d,3),m=B(L(p)),h=z(m,!0),g=B(m,2),_=z(g,!0),v=B(g,3),y=z(v,!0),b=B(v,2),x=z(b,!0),S=B(b,3);hs(L(S),{get iso(){return t.createdAt}}),k(S);var C=z(B(S,3),!0);k(p),k(s),k(o),V(()=>{J(h,t.briefingId),J(_,t.groupId),J(y,t.groupingVersion),J(x,t.seq),J(C,t.host)}),q(e,o),M()}function rc(e,t){return{parentId:e,count:Array.isArray(t.generated_decision_ids)?t.generated_decision_ids.length:0,next:t.generated_next??0,members:[]}}function ic(e){return`Undone. ${e.next?`At least ${e.count}`:String(e.count)} member decision${e.count===1?` was`:`s were`} generated; incident undo does not undo them. Review them on their briefing pages.`}async function ac(e,t){let n=await t(e.parentId,e.next),r=n.next??0;if(r!==0&&r<=e.next)throw Error(`Member decision page did not advance. Try again.`);return{parentId:e.parentId,count:e.count+n.members.length,next:r,members:n.members}}function oc(e,t){if(e.kind===`snooze`&&(e.untilText??``)!==``){let n=new Date(e.untilText);return Number.isNaN(n.getTime())?{error:`snooze time is not a date`}:{payload:{...sc(t,e),until:n.toISOString()}}}let n=sc(t,e);return(e.kind===`note`||e.kind===`label`)&&(n.text=e.text??``),t.memberScope&&(n.includeMembers=e.includeMembers??!1),{payload:n}}function sc(e,t){return{subjectKind:e.subjectKind,subjectId:e.subjectId,kind:t.kind,requestId:e.requestId}}var cc={title:`_title_85c58_1`,status:`_status_85c58_7`},lc=G(`

                                                        `,1);function uc(e,t){j(t,!0);let n=$(t,`effective`,3,null),r=$(t,`card`,3,!1);function i(){return n()===null||n()===void 0?`No operator review`:n().kind===`snooze`?`Snoozed${n().until?` until ${n().until}`:``}`:n().kind===`expected`?`Reviewed: expected`:`Flagged: ${n().kind.replace(`_`,` `)}`}var a=lc(),o=R(a),s=z(o,!0),c=B(o,2),l=L(c);{let e=N(()=>n()?.kind??`unreviewed`);Ra(l,{get large(){return r()},get"data-review"(){return W(e)},children:(e,t)=>{A();var n=K();V(e=>J(n,`Status: ${e??``}`),[()=>i()]),q(e,n)},$$slots:{default:!0}})}k(c),V(()=>{Z(o,1,X(r()?cc.title:void 0)),J(s,t.title),Z(c,1,X(cc.status))}),q(e,a),M()}var dc={composer:`_composer_1b5ih_1`,selected:`_selected_1b5ih_30`,decisionLabel:`_decisionLabel_1b5ih_43`,decisionHint:`_decisionHint_1b5ih_47`},fc=G(` `),pc=G(``),mc=G(``),hc=G(``),gc=G(``),_c=G(`
                                                        Choose a decision

                                                        `);function vc(e,t){j(t,!0);let n=$(t,`kinds`,19,()=>[]),r=$(t,`kindHelp`,19,()=>({})),i=$(t,`memberScope`,3,!1),a=$(t,`memberCount`,3,0),o=$(t,`variant`,3,`plain`),s=$(t,`defaultKind`,3,null),c=$(t,`pending`,3,!1),l=$(t,`formError`,3,null),u=$(t,`outcomeNote`,3,null),d=$(t,`onSubmit`,3,async()=>{}),f=N(()=>o()===`card`),p={expected:`No further action needed.`,not_expected:`Flag for follow-up: this briefing still needs a check.`,snooze:`Hide from attention until a time. Empty keeps the server default (24h).`,note:`Free-text note, kept with the audit (max 2000 characters).`,label:`Your label for this profile, never identity (max 256 characters).`},m=F(null),h=N(()=>W(m)??s()),g=F(``),_=F(``),v=F(!1),y=F(null),b=N(()=>W(h)===`note`||W(h)===`label`),x=N(()=>W(h)===`label`?256:2e3),S=N(()=>W(h)!==null&&n().includes(W(h))&&(!W(b)||W(_).trim()!==``));async function C(e){n().includes(e)&&(I(m,e,!0),await ur(),W(y)?.focus())}async function w(e){e.preventDefault(),c()||(!W(f)||W(S))&&W(h)!==null&&await d()({kind:W(h),untilText:W(g),text:W(_),includeMembers:W(v)})===`ok`&&(I(m,null),I(g,``),I(_,``),I(v,!1))}var T={applyPreset:C},E=_c(),ee=L(E),te=L(ee);let ne;Qr(B(te,2),16,n,e=>e,(e,n)=>{var r=pc(),i=L(r);ji(i);var a=B(i,2),o=z(a,!0),s=B(a,2),c=e=>{var t=fc(),r=z(t,!0);V(()=>{Z(t,1,X(dc.decisionHint)),J(r,{expected:`no further action`,not_expected:`investigate`,snooze:`hide until later`,note:`annotation only`}[n])}),q(e,t)};Y(s,e=>{W(f)&&e(c)}),k(r),V(e=>{Z(r,1,X(W(h)===n?dc.selected:void 0)),Q(i,`name`,`decision-kind-${t.subjectId}`),Mi(i,n),Ni(i,W(h)===n),Z(a,1,X(dc.decisionLabel)),J(o,e)},[()=>n===`not_expected`?`Not expected`:n.charAt(0).toUpperCase()+n.slice(1)]),Dr(`change`,i,()=>I(m,n,!0)),q(e,r)}),k(ee);var re=B(ee,2),ie=z(re,!0),ae=B(re,2),oe=e=>{var t=mc(),n=L(t);ji(n);var r=B(n);k(t),V(()=>J(r,` Also apply to the ${a()??``} member briefing${a()===1?``:`s`} (snapshot now; later joiners stay untouched)`)),Bi(n,()=>W(v),e=>I(v,e)),q(e,t)};Y(ae,e=>{i()&&e(oe)});var se=B(ae,2),ce=e=>{Pa(e,{children:(e,t)=>{A();var n=K();V(()=>J(n,u())),q(e,n)},$$slots:{default:!0}})};Y(se,e=>{u()!==null&&e(ce)});var le=B(se,2),ue=e=>{var t=hc(),n=B(L(t));ji(n),k(t),zi(n,()=>W(g),e=>I(g,e)),q(e,t)};Y(le,e=>{W(h)===`snooze`&&e(ue)});var de=B(le,2),fe=e=>{var t=gc(),n=L(t),r=B(n);it(r),k(t),V(()=>{J(n,`${W(h)===`label`?`Label`:`Note`} `),Q(r,`maxlength`,W(x))}),zi(r,()=>W(_),e=>I(_,e)),q(e,t)};Y(de,e=>{W(b)&&e(fe)});var pe=B(de,2),me=e=>{Pa(e,{kind:`alert`,children:(e,t)=>{A();var n=K();V(()=>J(n,l())),q(e,n)},$$slots:{default:!0}})};Y(pe,e=>{l()!==null&&e(me)});var he=B(pe,2),ge=z(he,!0);return Wi(he,e=>I(y,e),()=>W(y)),k(E),V(()=>{Z(E,1,X(W(f)?dc.composer:void 0)),ne=Z(te,1,``,null,ne,{"sr-only":W(f)}),J(ie,W(h)===null?`Choose a verdict to record it.`:r()[W(h)]??p[W(h)]??``),he.disabled=W(f)?c()||!W(S):c(),J(ge,c()?`Recording…`:`Record decision`)}),Er(`submit`,E,w),q(e,E),M(T)}Or([`change`]);var yc={historyHeading:`_historyHeading_tgnl4_1`,emptyHistory:`_emptyHistory_tgnl4_11`,trail:`_trail_tgnl4_17`,text:`_text_tgnl4_37`,until:`_until_tgnl4_42`},bc=G(`

                                                        Recorded decisions

                                                        `),xc=G(`

                                                        No decisions recorded.

                                                        `),Sc=G(` `),Cc=G(``),wc=G(`
                                                      1. `),Tc=G(``),Ec=G(`
                                                          `,1),Dc=G(` `,1);function Oc(e,t){j(t,!0);let n=$(t,`trail`,19,()=>[]),r=$(t,`exhausted`,3,!1),i=$(t,`showNewer`,3,!1),a=$(t,`note`,3,null),o=$(t,`listError`,3,null),s=$(t,`paging`,3,!1),c=$(t,`undoPending`,3,null),l=$(t,`card`,3,!1),u=$(t,`onUndo`,3,async()=>{}),d=$(t,`onOlder`,3,async()=>{}),f=$(t,`onNewer`,3,()=>{});var p=Dc(),m=R(p),h=e=>{var t=bc();V(()=>Z(t,1,X(yc.historyHeading))),q(e,t)};Y(m,e=>{l()&&e(h)});var g=B(m,2),_=e=>{var t=xc();V(()=>Z(t,1,X(yc.emptyHistory))),q(e,t)},v=e=>{var t=Ec(),o=R(t);Qr(o,21,n,e=>e.decision_id,(e,t)=>{var n=wc(),r=L(n);Ra(r,{children:(e,n)=>{A();var r=K();V(e=>J(r,e),[()=>W(t).kind.replace(`_`,` `)]),q(e,r)},$$slots:{default:!0}});var i=B(r,2),a=e=>{Ra(e,{children:(e,t)=>{A(),q(e,K(`undone`))},$$slots:{default:!0}})};Y(i,e=>{W(t).undone&&e(a)});var o=B(i,2),s=e=>{var n=Sc(),r=z(n,!0);V(()=>{Z(n,1,X(yc.text)),J(r,W(t).text)}),q(e,n)};Y(o,e=>{W(t).text&&e(s)});var l=B(o,2),d=e=>{var n=Sc(),r=z(n);V(()=>{Z(n,1,X(yc.until)),J(r,`until ${W(t).until??``}`)}),q(e,n)};Y(l,e=>{W(t).until&&e(d)});var f=B(l,2),p=z(f,!0),m=B(f,2),h=e=>{var n=Cc(),r=z(n,!0);V(()=>{n.disabled=c()!==null,J(r,c()===W(t).decision_id?`Undoing…`:`Undo`)}),Dr(`click`,n,()=>u()(W(t).decision_id)),q(e,n)};Y(m,e=>{!W(t).undone&&W(t).kind!==`undo`&&e(h)}),k(n),V(e=>{Q(f,`datetime`,W(t).created_at),J(p,e)},[()=>new Date(W(t).created_at).toLocaleString()]),q(e,n)}),k(o);var l=B(o,2),p=e=>{var t=Cc(),n=z(t,!0);V(()=>{t.disabled=s(),J(n,s()?`Loading…`:`Show older decisions`)}),Dr(`click`,t,function(...e){d()?.apply(this,e)}),q(e,t)};Y(l,e=>{r()||e(p)});var m=B(l,2),h=e=>{var t=Tc();V(()=>t.disabled=s()),Dr(`click`,t,function(...e){f()?.apply(this,e)}),q(e,t)};Y(m,e=>{i()&&e(h)});var g=B(m,2),_=e=>{Pa(e,{kind:`note`,children:(e,t)=>{A();var n=K();V(()=>J(n,a())),q(e,n)},$$slots:{default:!0}})};Y(g,e=>{a()!==null&&e(_)}),V(()=>Z(o,1,X(yc.trail))),q(e,t)};Y(g,e=>{n().length===0?e(_):e(v,-1)});var y=B(g,2),b=e=>{Pa(e,{kind:`alert`,children:(e,t)=>{A();var n=K();V(()=>J(n,o())),q(e,n)},$$slots:{default:!0}})};Y(y,e=>{o()!==null&&e(b)}),q(e,p),M()}Or([`click`]);var kc=G(`
                                                        1. `),Ac=G(`
                                                            `),jc=G(``),Mc=G(` `,1);function Nc(e,t){j(t,!0);let n=$(t,`paging`,3,!1),r=$(t,`error`,3,null),i=$(t,`onMore`,3,async()=>{});var a=Mc(),o=R(a);Pa(o,{children:(e,n)=>{A();var r=K();V(e=>J(r,e),[()=>ic(t.review)]),q(e,r)},$$slots:{default:!0}});var s=B(o,2),c=e=>{var n=Ac();Qr(n,21,()=>t.review.members,e=>e.decision_id,(e,t)=>{var n=kc(),r=L(n),i=z(r,!0),a=B(r);k(n),V((e,n)=>{Q(r,`href`,e),J(i,W(t).subject_id),J(a,` — ${n??``}`)},[()=>`#/briefing/${encodeURIComponent(W(t).subject_id)}`,()=>W(t).kind.replace(`_`,` `)]),q(e,n)}),k(n),q(e,n)};Y(s,e=>{t.review.members.length>0&&e(c)});var l=B(s,2),u=e=>{var t=jc(),a=z(t,!0);V(()=>{t.disabled=n(),J(a,n()?`Loading…`:r()?`Retry remaining member decisions`:`Show remaining member decisions`)}),Dr(`click`,t,function(...e){i()?.apply(this,e)}),q(e,t)};Y(l,e=>{t.review.next&&e(u)});var d=B(l,2),f=e=>{Pa(e,{kind:`alert`,children:(e,t)=>{A();var n=K();V(()=>J(n,r())),q(e,n)},$$slots:{default:!0}})};Y(d,e=>{r()!==null&&e(f)}),q(e,a),M()}Or([`click`]);var Pc={card:`_card_1nnbv_1`},Fc=G(`
                                                            `);function Ic(e,t){j(t,!0);let n=$(t,`kinds`,19,()=>[]),r=$(t,`decisions`,19,()=>[]),i=$(t,`effective`,3,null),a=$(t,`memberScope`,3,!1),o=$(t,`memberCount`,3,0),s=$(t,`kindHelp`,19,()=>({})),c=$(t,`preselect`,3,null),l=$(t,`variant`,3,`plain`),u=$(t,`ondecided`,3,null),d=N(()=>l()===`card`),f=N(()=>c()??(W(d)?null:n()[0]??`note`)),p=F(null),m=F(null),h=F(!1),g=F(null),_=F(Zt(crypto.randomUUID())),v=F(null),y=F(null),b=F(!1),x=F(null),S=F(Zt({})),C=!0;oa(()=>{C=!1});let w=0,T=N(()=>r().length===0?`empty`:`${r()[0].decision_id}:${r().length}`),E=F(Zt([])),ee=F(``),te=F(Zt([])),ne=F(!1),re=F(!1),ie=F(``),ae=F(null),oe=F(``),se=N(()=>W(ee)===W(T)&&W(E).length>0?[...r(),...W(E)]:r()),ce=N(()=>W(re)&&W(ie)===W(T)),le=N(()=>W(oe)===W(T)?W(ae):null),ue=F(null);function de(e){W(ue)?.applyPreset(e)}async function fe({kind:e,untilText:n,text:r,includeMembers:i}){I(h,!0),I(p,null);try{let o=oc({kind:e,untilText:n,text:r,includeMembers:i},{subjectKind:t.subjectKind,subjectId:t.subjectId,requestId:W(_),memberScope:a()});if(o.error)return I(p,o.error,!0),`error`;let s=await ua(o.payload);return I(_,crypto.randomUUID(),!0),I(v,null),I(y,null),I(x,null),I(E,[],!0),I(ee,``),I(te,[],!0),I(re,!1),I(ae,null),w+=1,s.applied===!1?I(p,`Already recorded (${s.reason??`duplicate`}).`):Array.isArray(s.members)&&s.members.length>0&&I(v,`Recorded on the incident and ${s.members.length} member briefing${s.members.length===1?``:`s`}.`),await u()?.(),`ok`}catch(e){return I(p,e instanceof Error?e.message:String(e),!0),`error`}finally{I(h,!1)}}async function pe(e){if(W(g)===null){I(g,e,!0),I(m,null),I(v,null),I(y,null),I(x,null);try{W(S)[e]??=crypto.randomUUID();let t=await fa(e,W(S)[e]);((t.generated_decision_ids?.length??0)>0||t.generated_next)&&I(y,rc(e,t),!0);let n={...W(S)};delete n[e],I(S,n,!0),I(E,[],!0),I(ee,``),I(te,[],!0),I(re,!1),I(ae,null),w+=1,await u()?.()}catch(e){I(m,e instanceof Error?e.message:String(e),!0)}finally{I(g,null)}}}async function me(){if(W(b)||!W(y)?.next)return;let e=W(y);I(b,!0),I(x,null);try{let t=await ac(e,pa);C&&W(y)===e&&I(y,t,!0)}catch(t){C&&W(y)===e&&I(x,t instanceof Error?t.message:String(t),!0)}finally{C&&I(b,!1)}}async function he(){if(W(ne)||W(ce)||W(se).length===0)return;let e=w,n=W(T),r=W(se)[W(se).length-1].cursor;I(ne,!0),I(m,null);try{let i=await da(t.subjectKind,t.subjectId,{limit:50,before:r});if(!C||e!==w||n!==W(T))return;if(i.length===0){I(re,!0),I(ie,n,!0);return}W(ee)===n&&W(E).length>0&&(W(te).push({rows:W(E),key:W(ee)}),W(te).length>4&&(W(te).shift(),I(ae,`Earlier pages dropped from this view; the full audit remains available through the API.`),I(oe,n,!0))),I(E,i,!0),I(ee,n,!0),I(re,i.length<50),I(ie,n,!0)}catch(t){if(!C||e!==w||n!==W(T))return;I(m,t instanceof Error?t.message:String(t),!0)}finally{C&&I(ne,!1)}}function ge(){for(;W(te).length>0&&W(te)[W(te).length-1].key!==W(T);)W(te).pop();let e=W(te).pop();e===void 0?(I(E,[],!0),I(ee,``)):(I(E,e.rows,!0),I(ee,e.key,!0)),I(re,!1),I(ie,W(T),!0)}var _e={applyPreset:de},ve=Fc(),ye=L(ve);{let e=N(()=>W(d)?`Your decision`:`Operator decisions`);uc(ye,{get title(){return W(e)},get effective(){return i()},get card(){return W(d)}})}var be=B(ye,2);Wi(vc(be,{get kinds(){return n()},get subjectId(){return t.subjectId},get kindHelp(){return s()},get memberScope(){return a()},get memberCount(){return o()},get variant(){return l()},get defaultKind(){return W(f)},get pending(){return W(h)},get formError(){return W(p)},get outcomeNote(){return W(v)},onSubmit:fe}),e=>I(ue,e,!0),()=>W(ue));var D=B(be,2),xe=e=>{Nc(e,{get review(){return W(y)},get paging(){return W(b)},get error(){return W(x)},onMore:me})};Y(D,e=>{W(y)!==null&&e(xe)});var O=B(D,2);{let e=N(()=>W(ee)===W(T)&&W(E).length>0);Oc(O,{get trail(){return W(se)},get exhausted(){return W(ce)},get showNewer(){return W(e)},get note(){return W(le)},get listError(){return W(m)},get paging(){return W(ne)},get undoPending(){return W(g)},get card(){return W(d)},onUndo:pe,onOlder:he,onNewer:ge})}return k(ve),V(()=>Z(ve,1,X(W(d)?Pc.card:void 0))),q(e,ve),M(_e)}var Lc=G(`

                                                            Briefing unavailable

                                                            `),Rc=G(`

                                                            ← Back to Home

                                                            `),zc=G(`
                                                            `);function Bc(e,t){j(t,!0);let n=()=>$i(W(f),`$resource`,r),[r,i]=ta(),a=$(t,`initial`,3,null),o=$(t,`layout`,3,`page`),s=$(t,`ontitle`,3,null),c=$(t,`shortcuts`,3,null),l=N(()=>c()??Da()),u=F(null),d=F(null),f=F(null),p=N(()=>n()?.data??a()),m=N(()=>n()?.error??n()?.refreshError??null);bn(()=>{let e=t.id,n=No(()=>la(e));return ea(I(f,n,!0),`$resource`,r),a()===null&&n.refresh(),()=>n.invalidate()});function h(){W(f)?.refresh()}let g=N(()=>W(p)===null?``:Ua(W(p).kind,W(p).observations,W(p).referenced_events));bn(()=>{if(W(p)!==null&&s()){let e=W(p).briefing_id,t=W(g);pr(()=>s()(e,t))}});let _=N(()=>W(p)===null?null:Ga(W(p).referenced_events)),v=N(()=>W(p)===null?null:Ka(W(p).observations)),y=N(()=>Ro(W(p))),b=N(()=>Fo(W(p))),x=N(()=>Io(W(p)?.traces)),S=N(()=>Lo(W(p)?.traces)),C=N(()=>W(p)?.referenced_events.length===1?W(p).referenced_events[0]:null);function w(e){zo(W(u),e)}function T(e){return(W(p)?.observations??[]).filter(t=>t.event_id===e)}aa(()=>{W(l).register(`briefing`,`e`,`preset expected`,()=>W(d)?.applyPreset(`expected`)),W(l).register(`briefing`,`s`,`preset snooze`,()=>W(d)?.applyPreset(`snooze`)),W(l).register(`briefing`,`x`,`preset not-expected`,()=>W(d)?.applyPreset(`not_expected`));let e=e=>{W(l).dispatch(`briefing`,e)};return window.addEventListener(`keydown`,e),()=>{window.removeEventListener(`keydown`,e)}});var E=Ir(),ee=R(E),te=e=>{var t=Lc(),n=B(L(t),2),r=z(n),i=B(n,2);k(t),V(()=>J(r,`The bridge did not return this briefing (${W(m)??``}).`)),Dr(`click`,i,h),q(e,t)},ne=e=>{Pa(e,{children:(e,t)=>{A(),q(e,K(`Loading briefing…`))},$$slots:{default:!0}})},re=e=>{var t=zc(),n=L(t),r=e=>{q(e,Rc())};Y(n,e=>{o()===`page`&&e(r)});var i=B(n,2),a=e=>{Pa(e,{kind:`alert`,actionLabel:`Retry refresh`,onAction:h,children:(e,t)=>{A(),q(e,K(`The saved view could not be refreshed. Your last loaded report is still shown.`))},$$slots:{default:!0}})};Y(i,e=>{W(m)!==null&&e(a)});var s=B(i,2),c=L(s);ns(c,{get title(){return W(g)},get priority(){return W(p).priority},get description(){return W(p).what_changed},get identity(){return W(v)},get identityComplete(){return W(y)},get primaryEvent(){return W(C)},get eventCount(){return W(p).referenced_events.length},get eventsTruncated(){return W(p).referenced_truncated},get range(){return W(_)},get referencedTruncated(){return W(p).referenced_truncated},get source(){return W(p).source},onJump:w});var l=B(c,2);is(l,{});var f=B(l,2);cs(f,{get check(){return W(p).recommended_check},get identity(){return W(v)},get identityComplete(){return W(y)}});var E=B(f,2),ee=L(E);{let e=N(()=>W(p).decisions??[]),t=N(()=>W(p).effective_review??null);Wi(Ic(ee,{subjectKind:`briefing`,get subjectId(){return W(p).briefing_id},kinds:[`expected`,`not_expected`,`snooze`,`note`],get decisions(){return W(e)},get effective(){return W(t)},ondecided:h,variant:`card`}),e=>I(d,e,!0),()=>W(d))}k(E);var te=B(E,2);ps(te,{get priority(){return W(p).priority},get priorityReason(){return W(p).priority_reason},get baseline(){return W(p).baseline},get baselineRule(){return W(p).baseline_rule},get modelSuggestion(){return W(p).model_suggestion},get clamped(){return W(p).clamped},get fallbackUsed(){return W(p).fallback_used},get differs(){return W(b)}});var ne=B(te,2);Ns(ne,{get events(){return W(p).referenced_events},viewsFor:T,get profiles(){return W(p).profiles},get referencedTruncated(){return W(p).referenced_truncated},get observationsTruncated(){return W(p).observations_truncated},onJump:w});var re=B(ne,2);{let e=N(()=>W(x).length>0);Js(re,{get source(){return W(p).source},get likelyExplanation(){return W(p).likely_explanation},get confidence(){return W(p).confidence},get limited(){return W(e)},get context(){return W(p).context},get receipts(){return W(S)},get evidenceRefs(){return W(p).evidence_refs},get profiles(){return W(p).profiles},get profilesTruncated(){return W(p).profiles_truncated},onJump:w})}nc(B(re,2),{get traces(){return W(p).traces},get inputTokens(){return W(p).input_tokens},get outputTokens(){return W(p).output_tokens},get costUsd(){return W(p).cost_usd},get briefingId(){return W(p).briefing_id},get groupId(){return W(p).group_id},get groupingVersion(){return W(p).grouping_version},get seq(){return W(p).seq},get createdAt(){return W(p).created_at},get host(){return W(p).host}}),k(s),k(t),Wi(t,e=>I(u,e),()=>W(u)),V(()=>Q(t,`data-layout`,o())),q(e,t)};Y(ee,e=>{W(m)!==null&&W(p)===null?e(te):W(p)===null?e(ne,1):e(re,-1)}),q(e,E),M(),i()}Or([`click`]);var Vc=G(`Closed `),Hc=G(`Open since `),Uc=G(`

                                                            `,1);function Wc(e,t){j(t,!0);let n={burst_appearance:`Burst appearance`,burst_disappearance:`Burst disappearance`};var r=Uc(),i=R(r),a=z(i,!0),o=B(i,2),s=L(o);Ra(s,{children:(e,n)=>{A();var r=K();V(()=>J(r,t.incident.status)),q(e,r)},$$slots:{default:!0}});var c=B(s,2);Ra(c,{children:(e,n)=>{A();var r=K();V(()=>J(r,`Floor: ${t.incident.floor??``}`)),q(e,r)},$$slots:{default:!0}});var l=B(c,2),u=e=>{var n=Vc();hs(B(L(n)),{get iso(){return t.incident.closed_at}}),k(n),q(e,n)},d=e=>{var n=Hc();hs(B(L(n)),{get iso(){return t.incident.opened_at}}),k(n),q(e,n)};Y(l,e=>{t.incident.status===`closed`&&t.incident.closed_at?e(u):e(d,-1)}),k(o),V(()=>J(a,n[t.incident.kind]??t.incident.kind)),q(e,r),M()}var Gc=G(`

                                                            Scope

                                                            Window start: · Last member:

                                                            `);function Kc(e,t){j(t,!0);var n=Gc(),r=B(L(n),2),i=z(r),a=B(r,2),o=z(a),s=B(a,2),c=B(L(s));hs(c,{get iso(){return t.incident.window_start}}),hs(B(c,2),{get iso(){return t.incident.last_member_at}}),k(s),k(n),V(()=>{J(i,`Source: ${t.incident.source_scope??``}`),J(o,`Target: ${t.incident.target??``}`)}),q(e,n),M()}var qc=G(`

                                                            Some members share identity evidence; only distinct qualified references count toward the burst threshold.

                                                            `),Jc=G(`

                                                            More members exist than shown.

                                                            `),Yc=G(`

                                                            No member evidence retained.

                                                            `),Xc=G(`
                                                          • `),Zc=G(`
                                                              `),Qc=G(`

                                                              Evidence

                                                              `);function $c(e,t){j(t,!0);let n=$(t,`members`,19,()=>[]),r=$(t,`truncated`,3,!1);function i(e){return`${`${e.member_count} member report${e.member_count===1?``:`s`}`} · ${`${e.qualified_refs} qualified upstream reference${e.qualified_refs===1?``:`s`}`}`}var a=Qc(),o=B(L(a),2),s=z(o,!0),c=B(o,2),l=e=>{q(e,qc())};Y(c,e=>{t.incident.qualified_refs{q(e,Jc())};Y(u,e=>{r()&&e(d)});var f=B(u,2),p=e=>{q(e,Yc())},m=e=>{var t=Zc();Qr(t,21,n,e=>e.briefing_id,(e,t)=>{var n=Xc(),r=L(n),i=z(r,!0),a=B(r,2);Ra(a,{children:(e,n)=>{A();var r=K();V(()=>J(r,W(t).priority)),q(e,r)},$$slots:{default:!0}});var o=B(a,2);hs(o,{get iso(){return W(t).created_at}});var s=z(B(o,2));k(n),V(()=>{Q(r,`href`,`#/briefing/${W(t).briefing_id}`),J(i,W(t).briefing_id),J(s,`${W(t).refs.length??``} qualified reference${W(t).refs.length===1?``:`s`}`)}),q(e,n)}),k(t),q(e,t)};Y(f,e=>{n().length===0?e(p):e(m,-1)}),k(a),V(e=>J(s,e),[()=>i(t.incident)]),q(e,a),M()}var el=G(`

                                                              `),tl=G(`

                                                              Hypothesis:

                                                              `),nl=G(`
                                                            1. `),rl=G(`

                                                              Cited reports:

                                                                `,1),il=G(`

                                                                Summary

                                                                `);function al(e,t){j(t,!0);var n=il(),r=B(L(n),2);Ra(L(r),{children:(e,n)=>{A();var r=K();V(()=>J(r,`Summary status: ${t.summary.status??``}`)),q(e,r)},$$slots:{default:!0}}),k(r);var i=B(r,2),a=e=>{var n=el(),r=z(n,!0);V(()=>J(r,t.summary.summary)),q(e,n)};Y(i,e=>{t.summary.summary&&e(a)});var o=B(i,2),s=e=>{var n=tl(),r=B(L(n));k(n),V(()=>J(r,` ${t.summary.hypothesis??``}`)),q(e,n)};Y(o,e=>{t.summary.hypothesis&&e(s)});var c=B(o,2),l=e=>{var n=el(),r=z(n);V(()=>J(r,`Display confidence: ${t.summary.confidence??``}`)),q(e,n)};Y(c,e=>{t.summary.confidence&&e(l)});var u=B(c,2),d=z(u),f=B(u,2),p=e=>{var n=el(),r=z(n);V(()=>J(r,`Priority explanation: ${t.summary.reason??``}`)),q(e,n)};Y(f,e=>{t.summary.reason&&e(p)});var m=B(f,2),h=z(m),g=B(m,2),_=e=>{var n=rl(),r=B(R(n),2);Qr(r,21,()=>t.summary.citations,e=>e.member,(e,t)=>{var n=nl(),r=L(n),i=B(r),a=z(i,!0);k(n),V(()=>{J(r,`${W(t).member??``}: `),Q(i,`href`,`#/briefing/${W(t).briefing_id}`),J(a,W(t).briefing_id)}),q(e,n)}),k(r),q(e,n)};Y(g,e=>{t.summary.citations.length&&e(_)});var v=B(g,2),y=e=>{var n=el(),r=z(n,!0);V(()=>J(r,t.summary.error)),q(e,n)};Y(v,e=>{t.summary.error&&e(y)}),k(n),V(()=>{J(d,`Priority floor: ${t.summary.floor??``}. Resolved priority: ${t.summary.final_priority??``}${t.summary.suggestion?` (suggested ${t.summary.suggestion}${t.summary.clamped?`, clamped`:``})`:` (no model raise)`}`),J(h,`Evidence coverage: ${t.summary.sampled??``} sampled member reports; ${t.summary.omitted??``} omitted. The sample may not represent every member.`)}),q(e,n),M()}var ol=G(`

                                                                Loading incident…

                                                                `),sl=G(` `,1),cl=G(`

                                                                Back to overview

                                                                `,1);function ll(e,t){j(t,!0);let n=()=>$i(l,`$incidentRevision`,o),r=()=>$i(f,`$data`,o),i=()=>$i(p,`$error`,o),a=()=>$i(m,`$refreshError`,o),[o,s]=ta(),c=$(t,`initial`,3,null),l=wa()?.incidentRevision??null,u=-1;bn(()=>{if(!l)return;let e=n();u===-1?u=e:e!==u&&(u=e,v())});let d=No(()=>_a(t.id)),{data:f,error:p,refreshError:m}=d,h=N(()=>r()??c()),g=N(()=>i()??a()),_={expected:`Mark reviewed: this incident needs no further action. Members stay untouched unless included below.`,not_expected:`Flag for follow-up: this incident still needs a check.`,snooze:`Hide until a time. Empty keeps the server default (24h).`,note:`Free-text note, kept with the audit (max 2000 characters).`};function v(){d.refresh()}aa(()=>{if(c()===null&&v(),!l)return window.addEventListener(`watcherbridge:incident`,v),()=>window.removeEventListener(`watcherbridge:incident`,v)}),oa(()=>{d.invalidate()});var y=cl(),b=B(R(y),2),x=e=>{Pa(e,{kind:`alert`,actionLabel:`Retry`,onAction:v,children:(e,t)=>{A();var n=K();V(()=>J(n,`Refresh failed: ${W(g)??``}`)),q(e,n)},$$slots:{default:!0}})};Y(b,e=>{W(g)!==null&&e(x)});var S=B(b,2),C=e=>{q(e,ol())},w=e=>{let t=N(()=>W(h).incident);var n=sl(),r=R(n);Wc(r,{get incident(){return W(t)}});var i=B(r,2);Kc(i,{get incident(){return W(t)}});var a=B(i,2);$c(a,{get incident(){return W(t)},get members(){return W(h).members},get truncated(){return W(h).truncated}});var o=B(a,2),s=e=>{al(e,{get summary(){return W(h).summary}})};Y(o,e=>{W(h).summary&&e(s)});var c=B(o,2);{let e=N(()=>W(h).decisions??[]),n=N(()=>W(h).effective_review??null);Ic(c,{subjectKind:`incident`,get subjectId(){return W(t).incident_id},kinds:[`expected`,`not_expected`,`snooze`,`note`],get decisions(){return W(e)},get effective(){return W(n)},memberScope:!0,get memberCount(){return W(t).member_count},get kindHelp(){return _},ondecided:v})}q(e,n)};Y(S,e=>{W(h)===null?e(C):e(w,-1)}),q(e,y),M(),s()}function ul(e,t,n,r){let i=new Set(e.map(n)),a=[];for(let o of t){if(e.length+a.length>=r)break;i.has(n(o))||(i.add(n(o)),a.push(o))}return a}function dl({fetchPage:e,keyOf:t,cap:n,initial:r=null}){let i=typeof r==`function`?r():r,a=Ji(i?[...i.rows]:[]),o=Ji(i?i.nextAfter??``:``),s=Ji(i!==null),c=Ji(null),l=Yi(c,e=>e?.message??null),u=Ji(!1),d=Yi([o,s],([e,t])=>t&&e===``),f=Yi([a,o],([e,t])=>t!==``&&e.length>=n),p=0,m=0;async function h(r=!1){let i=r?p+=1:m+=1,l=()=>r?p:m;c.set(null),u.set(!0);try{let u=await e(r?``:Xi(o));if(i!==l())return`stale`;let d=r?[]:Xi(a),f=ul(d,u.rows,t,n);return a.set(r?f:[...d,...f]),o.set(u.nextAfter??``),s.set(!0),r&&(c.set(null),m+=1),`applied`}catch(e){return i===l()?(c.set({message:e instanceof Error?e.message:String(e),reset:r}),`failed`):`stale`}finally{i===l()&&u.set(!1)}}function g(){return h(!0)}function _(e,t=``){p+=1,m+=1,c.set(null),u.set(!1),a.set([...e]),o.set(t??``),s.set(!0)}return{rows:a,cursor:o,started:s,exhausted:d,capped:f,failure:c,error:l,loadingMore:u,loadMore:h,reset:g,replace:_}}var fl=G(`
                                                              • Last report
                                                              • `);function pl(e,t){j(t,!0);var n=fl(),r=L(n),i=B(L(r),2),a=L(i),o=z(a,!0),s=B(a),c=z(s,!0),l=z(B(s),!0);k(i);var u=B(i,2);hs(B(L(u)),{get iso(){return t.dev.last_report_at}}),k(u),A(2),k(r),k(n),V(e=>{Q(r,`href`,`#/devices/${t.dev.profile_id}`),J(o,t.dev.operator_label||t.dev.reported_id||`Unlabelled subject`),J(c,t.dev.profile_id),J(l,e)},[()=>Va(t.dev.class)]),q(e,n),M()}var ml=G(`

                                                                No reported subjects retained.

                                                                `),hl=G(`
                                                                  `),gl=G(`

                                                                  `),_l=G(``),vl=G(`

                                                                  End of retained list.

                                                                  `),yl=G(` `,1);function bl(e,t){j(t,!0);let n=$(t,`devices`,19,()=>[]),r=$(t,`stale`,3,!1),i=$(t,`error`,3,null),a=$(t,`exhausted`,3,!1),o=$(t,`capped`,3,!1),s=$(t,`cap`,3,200),c=$(t,`onReload`,3,()=>{}),l=$(t,`onLoadMore`,3,()=>{}),u=$(t,`onRetry`,3,()=>{});var d=yl(),f=R(d),p=e=>{Pa(e,{actionLabel:`Reload`,get onAction(){return c()},children:(e,t)=>{A(),q(e,K(`Connection recovered — this list may miss new reports.`))},$$slots:{default:!0}})};Y(f,e=>{r()&&e(p)});var m=B(f,2),h=e=>{q(e,ml())},g=e=>{var t=hl();Qr(t,21,n,e=>e.profile_id,(e,t)=>{pl(e,{get dev(){return W(t)}})}),k(t),q(e,t)};Y(m,e=>{n().length===0?e(h):e(g,-1)});var _=B(m,2),v=e=>{Pa(e,{kind:`alert`,actionLabel:`Retry`,get onAction(){return u()},children:(e,t)=>{A();var n=K();V(()=>J(n,`Page failed (${i()??``}) — earlier rows kept.`)),q(e,n)},$$slots:{default:!0}})};Y(_,e=>{i()!==null&&e(v)});var y=B(_,2),b=e=>{var t=gl(),n=z(t);V(()=>J(n,`List capped at ${s()??``} rows; use the API for the full set.`)),q(e,t)},x=e=>{var t=_l();Dr(`click`,t,function(...e){l()?.apply(this,e)}),q(e,t)},S=e=>{q(e,vl())};Y(y,e=>{o()?e(b):a()?e(S,-1):e(x,1)}),q(e,d),M()}Or([`click`]);var xl=G(` `,1),Sl=G(`

                                                                  Reported hosts

                                                                  Scanner-reported subjects. Classes distinguish device references, address context, unresolved events and legacy profiles.

                                                                  `);function Cl(e,t){j(t,!0);let n=()=>$i(p,`$rows`,c),r=()=>$i(m,`$started`,c),i=()=>$i(h,`$error`,c),a=()=>$i(g,`$failure`,c),o=()=>$i(_,`$exhausted`,c),s=()=>$i(v,`$capped`,c),[c,l]=ta(),u=$(t,`initial`,3,null),d=wa(),f=dl({fetchPage:async e=>{let t=await ma(e);return{rows:t.devices,nextAfter:t.next_after??``}},keyOf:e=>e.profile_id,cap:200,initial:()=>u()?{rows:u().devices??[],nextAfter:u().next_after??``}:null}),{rows:p,started:m,error:h,failure:g,exhausted:_,capped:v}=f,y=N(()=>n().length===0),b=N(()=>!r()&&W(y)&&i()===null),x=F(!1);async function S(){await f.reset()===`applied`&&I(x,!1)}async function C(){await f.loadMore()}function w(){a()?.reset===!0?S():a()?.reset===!1&&C()}aa(()=>{u()===null&&S()});let T=!1;bn(()=>{if(d)return d.connection.subscribe(e=>{let t=e===`live`,r=t&&!T&&n().length>0;T=t,r&&I(x,!0)})});var E=Sl(),ee=B(L(E),4),te=e=>{Pa(e,{children:(e,t)=>{A(),q(e,K(`Loading reported hosts…`))},$$slots:{default:!0}})},ne=e=>{var t=xl(),n=R(t);Pa(n,{kind:`alert`,children:(e,t)=>{A();var n=K();V(()=>J(n,`The bridge did not return reported hosts (${i()??``}).`)),q(e,n)},$$slots:{default:!0}}),Dr(`click`,B(n,2),w),q(e,t)},re=e=>{bl(e,{get devices(){return n()},get stale(){return W(x)},get error(){return i()},get exhausted(){return o()},get capped(){return s()},cap:200,onReload:S,onLoadMore:C,onRetry:w})};Y(ee,e=>{W(b)?e(te):i()!==null&&W(y)?e(ne,1):e(re,-1)}),k(E),q(e,E),M(),l()}Or([`click`]);var wl=G(`

                                                                  `),Tl=G(`
                                                                  Your label
                                                                  `,1),El=G(`

                                                                  Source scope
                                                                  Upstream reference
                                                                  Reported by
                                                                  Association
                                                                  First report
                                                                  Last report
                                                                  `,1);function Dl(e,t){j(t,!0);var n=El(),r=R(n),i=z(r),a=B(r,2),o=e=>{Pa(e,{kind:`note`,children:(e,t)=>{A(),q(e,K(`Earlier bridge-inferred association; not used for current identity.`))},$$slots:{default:!0}})},s=e=>{var n=wl(),r=z(n);V(()=>J(r,`This page describes ${t.profile.class===`address`?`address context`:`unresolved events`}, not a device.`)),q(e,n)};Y(a,e=>{t.profile.class===`legacy`?e(o):(t.profile.class===`address`||t.profile.class===`event`)&&e(s,1)});var c=B(a,2),l=B(L(c),2),u=z(l,!0),d=B(l,4),f=z(d,!0),p=B(d,4),m=z(p),h=B(p,4),g=z(h,!0),_=B(h,2),v=e=>{var n=Tl(),r=z(B(R(n),2),!0);V(()=>J(r,t.profile.operator_label)),q(e,n)};Y(_,e=>{t.profile.operator_label!==null&&t.profile.operator_label!==void 0&&e(v)});var y=B(_,4);hs(L(y),{get iso(){return t.profile.first_report_at}}),k(y);var b=B(y,4);hs(L(b),{get iso(){return t.profile.last_report_at}}),k(b),k(c),V(e=>{J(i,`${t.profile.profile_id??``} — ${e??``}`),J(u,t.profile.source_scope),J(f,t.profile.reported_id),J(m,`${t.profile.reported_source??``} (confidence: ${(t.profile.reported_confidence||`unknown`)??``})`),J(g,t.profile.association_status)},[()=>Va(t.profile.class)]),q(e,n),M()}var Ol=G(`

                                                                  No retained observation.

                                                                  `),kl=G(`
                                                                  `,1),Al=G(`
                                                                • `),jl=G(`
                                                                    `),Ml=G(`

                                                                    Reported

                                                                    `,1),Nl=G(`

                                                                    Latest evidence

                                                                    `);function Pl(e,t){j(t,!0);var n=Nl(),r=B(L(n),2),i=e=>{q(e,Ol())},a=e=>{var n=Ml(),r=R(n),i=B(L(r));hs(i,{get iso(){return t.latest.reported_at}});var a=B(i);k(r);var o=B(r,2);Qr(o,21,()=>Object.entries(t.latest.attributes??{}),([e,t])=>e,(e,t)=>{var n=N(()=>m(W(t),2));let r=()=>W(n)[0],i=()=>W(n)[1];var a=kl(),o=R(a),s=z(o,!0),c=z(B(o,2),!0);V(e=>{J(s,r()),J(c,e)},[()=>JSON.stringify(i())]),q(e,a)}),k(o);var s=B(o,2),c=e=>{var n=jl();Qr(n,21,()=>t.latest.ports,e=>`${e.proto}/${e.port}`,(e,t)=>{var n=Al(),r=z(n);V(()=>J(r,`${W(t).proto??``}/${W(t).port??``} ${W(t).state??``}${W(t).service?` (${W(t).service})`:``}`)),q(e,n)}),k(n),q(e,n)};Y(s,e=>{(t.latest.ports??[]).length>0&&e(c)});var l=z(B(s,2));V(()=>{J(a,` (${t.latest.view_role??``}).`),J(l,`Snapshot covers ${t.latest.ports_total??``} ports${t.latest.ports_truncated?` (truncated)`:``}.`)}),q(e,n)};Y(r,e=>{t.latest===null?e(i):e(a,-1)}),k(n),q(e,n),M()}var Fl=G(`

                                                                    No retained reports in this window.

                                                                    `),Il=G(`
                                                                  • `),Ll=G(`
                                                                      `),Rl=G(`

                                                                      `),zl=G(``),Bl=G(`

                                                                      End of retained history. Retention policy lives on the Health screen.

                                                                      `),Vl=G(`

                                                                      History

                                                                      `);function Hl(e,t){j(t,!0);let n=$(t,`observations`,19,()=>[]),r=$(t,`historyError`,3,null),i=$(t,`exhausted`,3,!1),a=$(t,`capped`,3,!1),o=$(t,`cap`,3,200),s=$(t,`onOlder`,3,()=>{}),c=$(t,`onRetry`,3,()=>{});var l=Vl(),u=B(L(l),2),d=e=>{q(e,Fl())},f=e=>{var t=Ll();Qr(t,21,n,e=>e.observation_id,(e,t)=>{var n=Il(),r=L(n),i=B(r);hs(i,{get iso(){return W(t).reported_at}});var a=B(i);k(n),V(()=>{J(r,`${W(t).event_id??``} (${W(t).view_role??``}) — `),J(a,`, + ${W(t).ports_total??``} ports${W(t).ports_truncated?` (truncated)`:``}`)}),q(e,n)}),k(t),q(e,t)};Y(u,e=>{n().length===0?e(d):e(f,-1)});var p=B(u,2),m=e=>{Pa(e,{kind:`alert`,actionLabel:`Retry`,get onAction(){return c()},children:(e,t)=>{A();var n=K();V(()=>J(n,`Older page failed (${r()??``}).`)),q(e,n)},$$slots:{default:!0}})};Y(p,e=>{r()!==null&&e(m)});var h=B(p,2),g=e=>{var t=Rl(),n=z(t);V(()=>J(n,`History capped at ${o()??``} rows; use the API for the full set.`)),q(e,t)},_=e=>{var t=zl();Dr(`click`,t,function(...e){s()?.apply(this,e)}),q(e,t)},v=e=>{q(e,Bl())};Y(h,e=>{a()?e(g):i()?e(v,-1):e(_,1)}),k(l),q(e,l),M()}Or([`click`]);var Ul=G(`

                                                                      Reported host unavailable

                                                                      Back to reported hosts

                                                                      `),Wl=G(``);function Gl(e,t){j(t,!0);let n=()=>$i(m,`$data`,l),r=()=>$i(h,`$error`,l),i=()=>$i(g,`$refreshError`,l),a=()=>$i(b,`$historyRows`,l),o=()=>$i(x,`$historyLoadError`,l),s=()=>$i(S,`$historyExhausted`,l),c=()=>$i(C,`$historyCapped`,l),[l,u]=ta(),d=$(t,`initial`,3,null),f=wa(),p=No(()=>ha(t.id)),{data:m,error:h,refreshError:g}=p,_=N(()=>n()??d()),v=N(()=>Po({data:n(),initial:d(),error:r(),refreshError:i()})),y=dl({fetchPage:async e=>{let n=await ha(t.id,e);return{rows:n.history??[],nextAfter:n.history_next_after??``}},keyOf:e=>e.observation_id,cap:200,initial:()=>d()?{rows:d().history??[],nextAfter:d().history_next_after??``}:null}),{rows:b,error:x,exhausted:S,capped:C}=y,w=F(!1);async function T(){if(await p.refresh()===`applied`){let e=Xi(m);y.replace(e?.history??[],e?.history_next_after??``),I(w,!1)}}async function E(){await y.loadMore()}aa(()=>{d()===null&&T()});let ee=!1;bn(()=>{if(f)return f.connection.subscribe(e=>{let t=e===`live`,n=t&&!ee&&W(_)!==null;ee=t,n&&I(w,!0)})});var te=Ir(),ne=R(te),re=e=>{var t=Ul(),n=B(L(t),2),i=z(n),a=B(n,2),o=B(L(a),2);k(a),k(t),V(()=>J(i,`The bridge did not return this profile (${r()??``}).`)),Dr(`click`,o,T),q(e,t)},ie=e=>{Pa(e,{children:(e,t)=>{A(),q(e,K(`Loading reported host…`))},$$slots:{default:!0}})},ae=e=>{var t=Wl(),n=B(L(t),2),r=e=>{Pa(e,{actionLabel:`Reload`,onAction:T,children:(e,t)=>{A(),q(e,K(`Connection recovered — this page may miss new reports.`))},$$slots:{default:!0}})};Y(n,e=>{W(w)&&e(r)});var i=B(n,2),l=e=>{Pa(e,{kind:`alert`,actionLabel:`Retry`,onAction:T,children:(e,t)=>{A();var n=K();V(()=>J(n,`Refresh failed (${W(v)??``}) — showing retained data.`)),q(e,n)},$$slots:{default:!0}})};Y(i,e=>{W(v)!==null&&e(l)});var u=B(i,2);Dl(u,{get profile(){return W(_)}});var d=B(u,2);{let e=N(()=>W(_).decisions??[]);Ic(d,{subjectKind:`reported_subject`,get subjectId(){return W(_).profile_id},kinds:[`note`,`label`],get decisions(){return W(e)},ondecided:T})}var f=B(d,2);Pl(f,{get latest(){return W(_).latest}}),Hl(B(f,2),{get observations(){return a()},get historyError(){return o()},get exhausted(){return s()},get capped(){return c()},cap:200,onOlder:E,onRetry:E}),k(t),q(e,t)};Y(ne,e=>{r()!==null&&W(_)===null?e(re):W(_)===null?e(ie,1):e(ae,-1)}),q(e,te),M(),u()}Or([`click`]);function Kl({live:e,wasLive:t,data:n,initial:r}){return e&&!t&&(n??r)!==null}function ql(e){return e==null?!1:e.status!==`completed`||(e.error??``)!==``}var Jl={metrics:`_metrics_1i28o_1`},Yl=G(`
                                                                    1. `),Xl=G(`
                                                                        `),Zl=G(` `,1),Ql=G(`

                                                                        Summary

                                                                        Coverage
                                                                        Fallback briefings · 1h
                                                                        Awaiting operator
                                                                        Forward errors · 1h
                                                                        Ingest queue
                                                                        `);function $l(e,t){j(t,!0);let n=$(t,`refreshError`,3,null),r=$(t,`onRetry`,3,()=>{});var i=Ql(),a=B(L(i),2),o=L(a),s=B(L(o));Ra(L(s),{get"data-state"(){return t.health.coverage},children:(e,n)=>{A();var r=K();V(()=>J(r,t.health.coverage)),q(e,r)},$$slots:{default:!0}}),k(s),k(o);var c=B(o,2),l=B(L(c)),u=L(l),d=z(B(u));k(l),k(c);var f=B(c,2),p=z(B(L(f)),!0);k(f);var m=B(f,2),h=z(B(L(m)),!0);k(m);var g=B(m,2),_=B(L(g)),v=L(_),y=z(B(v));k(_),k(g),k(a);var b=B(a,2),x=e=>{var n=Xl();Qr(n,20,()=>t.health.coverage_reasons,e=>e,(e,t)=>{var n=Yl(),r=z(n,!0);V(()=>J(r,t)),q(e,n)}),k(n),q(e,n)};Y(b,e=>{(t.health.coverage_reasons??[]).length>0&&e(x)});var S=B(b,2),C=e=>{Pa(e,{kind:`alert`,children:(e,n)=>{A();var r=Zl(),i=R(r),a=B(i);{let e=N(()=>t.health.purge.last.finished_at??t.health.purge.last.started_at);hs(a,{get iso(){return W(e)}})}var o=B(a);V(()=>{J(i,`Latest purge run ${t.health.purge.last.status??``} + (`),J(o,`)${t.health.purge.last.error?`: ${t.health.purge.last.error}`:``}.`)}),q(e,r)},$$slots:{default:!0}})},w=N(()=>ql(t.health.purge.last));Y(S,e=>{W(w)&&e(C)});var T=B(S,2),E=e=>{Pa(e,{kind:`alert`,actionLabel:`Retry`,get onAction(){return r()},children:(e,t)=>{A();var r=K();V(()=>J(r,`Refresh failed (${n()??``}) — showing retained data.`)),q(e,r)},$$slots:{default:!0}})};Y(T,e=>{n()!==null&&e(E)}),k(i),V(()=>{Z(a,1,`health-metrics ${Jl.metrics??``}`),J(u,`${t.health.fallback_1h.used??``} `),J(d,`of ${t.health.fallback_1h.total??``}`),J(p,t.health.parked_groups),J(h,t.health.forward_errors_1h),J(v,`${t.health.queue_depth??``} `),J(y,`of ${t.health.queue_cap??``}`)}),q(e,i),M()}var eu=G(`— last at `,1),tu=G(`
                                                                        Last completed scan
                                                                        Scan result
                                                                        Reported host records
                                                                        Signing clock offset
                                                                        `,1),nu=G(`
                                                                        Last report
                                                                        `,1),ru=G(`
                                                                        Delivery
                                                                        `,1),iu=G(`
                                                                      • `),au=G(`
                                                                          `),ou=G(`

                                                                          Liveness
                                                                          Identity namespace
                                                                          Identity capability
                                                                          Heartbeat
                                                                          `);function su(e,t){j(t,!0);var n=ou(),r=L(n),i=z(r),a=B(r,2),o=B(L(a),2),s=z(o),c=B(o,4),l=z(c,!0),u=B(c,4),d=z(u,!0),f=B(u,4),p=L(f),m=B(p),h=e=>{var n=eu();hs(B(R(n)),{get iso(){return t.source.last_heartbeat_at}}),q(e,n)};Y(m,e=>{t.source.last_heartbeat_at&&e(h)}),k(f);var g=B(f,2),_=e=>{var n=tu(),r=B(R(n),2);hs(L(r),{get iso(){return t.source.heartbeat.completed_at}}),k(r);var i=B(r,4),a=z(i),o=B(i,4),s=z(o),c=z(B(o,4));V(()=>{J(a,`${t.source.heartbeat.status??``}, ${t.source.heartbeat.issue_count??``} ${t.source.heartbeat.issue_count===1?`issue`:`issues`}, ${t.source.heartbeat.duration_ms??``} ms`),J(s,`${t.source.heartbeat.hosts_seen??``} — scan records, not a current inventory or device count`),J(c,`${t.source.heartbeat.clock_skew_seconds??``} seconds (includes delivery delay)`)}),q(e,n)};Y(g,e=>{t.source.heartbeat&&e(_)});var v=B(g,2),y=e=>{var n=nu(),r=B(R(n),2);hs(L(r),{get iso(){return t.source.last_report_at}}),k(r),q(e,n)};Y(v,e=>{t.source.last_report_at&&e(y)});var b=B(v,2),x=e=>{var n=ru(),r=z(B(R(n),2),!0);V(()=>J(r,t.source.delivery_status)),q(e,n)};Y(b,e=>{t.source.delivery_status&&e(x)}),k(a);var S=B(a,2),C=e=>{var n=au();Qr(n,20,()=>t.source.reasons,e=>e,(e,t)=>{var n=iu(),r=z(n,!0);V(()=>J(r,t)),q(e,n)}),k(n),q(e,n)};Y(S,e=>{(t.source.reasons??[]).length>0&&e(C)}),k(n),V(()=>{Q(n,`aria-label`,`Source ${t.source.scope}`),J(i,`${t.source.scope??``} — ${t.source.status??``}`),J(s,`${t.source.liveness??``}${t.source.liveness===`unknown`?` (no heartbeat capability; silence is not absence)`:``}`),J(l,t.source.identity_namespace||`unknown — stable identity contract unavailable`),J(d,t.source.capabilities||`not reported — heartbeat is not identity proof`),J(p,`${t.source.heartbeat_enabled?`enabled (delivery opt-in, not identity proof)`:`disabled`} `)}),q(e,n),M()}var cu=G(`

                                                                          No sources registered.

                                                                          `),lu=G(`
                                                                          `);function uu(e,t){j(t,!0);let n=$(t,`sources`,19,()=>[]);var r=lu(),i=L(r),a=z(i),o=B(i,2),s=e=>{q(e,cu())},c=e=>{var t=Ir();Qr(R(t),17,n,e=>e.scope,(e,t)=>{su(e,{get source(){return W(t)}})}),q(e,t)};Y(o,e=>{n().length===0?e(s):e(c,-1)}),k(r),V(()=>J(a,`Sources (${n().length??``})`)),q(e,r),M()}var du=G(`
                                                                          Pipeline (process lifetime)
                                                                          Started
                                                                          Ingest accepted
                                                                          Ingest duplicates
                                                                          Ingest rejected
                                                                          Ingest saturated
                                                                          Provider calls
                                                                          Provider fallbacks
                                                                          Redaction blocked
                                                                          Writer saturated
                                                                          `);function fu(e,t){j(t,!0);var n=du(),r=B(L(n),2),i=B(L(r),2);hs(L(i),{get iso(){return t.process.started_at}}),k(i);var a=B(i,4),o=z(a,!0),s=B(a,4),c=z(s,!0),l=B(s,4),u=z(l,!0),d=B(l,4),f=z(d,!0),p=B(d,4),m=z(p,!0),h=B(p,4),g=z(h,!0),_=B(h,4),v=z(_,!0),y=z(B(_,4),!0);k(r),k(n),V(()=>{J(o,t.process.ingest_accepted),J(c,t.process.ingest_duplicates),J(u,t.process.ingest_rejected),J(f,t.process.ingest_saturated),J(m,t.process.provider_calls),J(g,t.process.provider_fallbacks),J(v,t.process.redaction_blocked),J(y,t.process.writer_saturated)}),q(e,n),M()}var pu=G(`
                                                                          `,1),mu=G(`

                                                                          ; + policy only — it never proves a per-profile boundary. Ask the API for per-profile history.

                                                                          `),hu=G(`

                                                                          Latest fully successful purge: .

                                                                          `),gu=G(`

                                                                          No fully successful purge recorded yet.

                                                                          `),_u=G(`
                                                                          Purge
                                                                          `);function vu(e,t){j(t,!0);let n=$(t,`retention`,3,null);function r(e){return`${Math.floor(e/86400)} days`}var i=_u(),a=B(L(i),2);Qr(a,21,()=>Object.entries(t.purge.totals??{}),([e,t])=>e,(e,t)=>{var n=N(()=>m(W(t),2));let r=()=>W(n)[0],i=()=>W(n)[1];var a=pu(),o=R(a),s=z(o,!0),c=z(B(o,2),!0);V(()=>{J(s,r()),J(c,i())}),q(e,a)}),k(a);var o=B(a,2),s=e=>{var t=mu(),i=L(t),a=B(i),o=e=>{var t=K();V(e=>J(t,`, ${e??``} for subjects`),[()=>r(n().subjects_seconds)]),q(e,t)};Y(a,e=>{n().subjects_seconds!==void 0&&e(o)}),A(),k(t),V(e=>J(i,`Configured retention: ${e??``} for reports`),[()=>r(n().reports_seconds)]),q(e,t)};Y(o,e=>{n()&&e(s)});var c=B(o,2),l=e=>{var n=hu(),r=B(L(n));{let e=N(()=>t.purge.last_success.finished_at??t.purge.last_success.started_at);hs(r,{get iso(){return W(e)}})}A(),k(n),q(e,n)},u=e=>{q(e,gu())};Y(c,e=>{t.purge.last_success?e(l):e(u,-1)}),k(i),q(e,i),M()}var yu=G(`
                                                                          Publisher
                                                                          Posted
                                                                          Dropped
                                                                          Failed
                                                                          `);function bu(e,t){j(t,!0);var n=yu(),r=B(L(n),2),i=B(L(r),2),a=z(i,!0),o=B(i,4),s=z(o,!0),c=z(B(o,4),!0);k(r),k(n),V(()=>{J(a,t.publisher.posted),J(s,t.publisher.dropped),J(c,t.publisher.failed)}),q(e,n),M()}var xu=G(` `,1),Su=G(` `,1),Cu=G(`

                                                                          Health

                                                                          Source coverage, processing, and retention. Liveness describes the source, not host presence.

                                                                          `);function wu(e,t){j(t,!0);let n=()=>$i(u,`$data`,a),r=()=>$i(d,`$error`,a),i=()=>$i(f,`$refreshError`,a),[a,o]=ta(),s=$(t,`initial`,3,null),c=wa(),l=No(ga),{data:u,error:d,refreshError:f}=l,p=N(()=>n()??s()),m=N(()=>Po({data:n(),initial:s(),error:r(),refreshError:i()}));aa(()=>{s()===null&&l.refresh()});let h=!1;bn(()=>{if(c)return c.connection.subscribe(e=>{let t=e===`live`,r=Kl({live:t,wasLive:h,data:n(),initial:s()});h=t,r&&l.refresh()})});var g=Cu(),_=B(L(g),4),v=e=>{var t=xu(),n=R(t);Pa(n,{kind:`alert`,children:(e,t)=>{A();var n=K();V(()=>J(n,`The bridge did not return health (${r()??``}).`)),q(e,n)},$$slots:{default:!0}}),Dr(`click`,B(n,2),()=>l.refresh()),q(e,t)},y=e=>{Pa(e,{children:(e,t)=>{A(),q(e,K(`Loading health…`))},$$slots:{default:!0}})},b=e=>{var t=Su(),n=R(t);$l(n,{get health(){return W(p)},get refreshError(){return W(m)},onRetry:()=>l.refresh()});var r=B(n,2);uu(r,{get sources(){return W(p).sources}});var i=B(r,2);fu(i,{get process(){return W(p).process}});var a=B(i,2);vu(a,{get purge(){return W(p).purge},get retention(){return W(p).retention}});var o=B(a,2),s=e=>{bu(e,{get publisher(){return W(p).publisher}})};Y(o,e=>{W(p).publisher&&e(s)}),q(e,t)};Y(_,e=>{r()!==null&&W(p)===null?e(v):W(p)===null?e(y,1):e(b,-1)}),k(g),q(e,g),M(),o()}Or([`click`]);var Tu={skip:`_skip_1y3rk_1`},Eu=G(`Skip to content`);function Du(e,t){j(t,!0);var n=Eu();V(()=>Z(n,1,X(Tu.skip))),Dr(`click`,n,e=>{e.preventDefault(),document.getElementById(`content`)?.focus()}),q(e,n),M()}Or([`click`]);var Ou=G(`

                                                                          `);function ku(e,t){let n={connecting:`Connecting…`,live:`Live briefing stream`,retrying:`Connection lost — retrying automatically…`};var r=Ou(),i=B(L(r));k(r),V(()=>{Q(r,`data-state`,t.state),J(i,` ${n[t.state]??t.state??``}`)}),q(e,r)}var Au={header:`_header_pqrrf_1`,brand:`_brand_pqrrf_11`,brandMark:`_brandMark_pqrrf_22`},ju=G(`
                                                                          WatcherBridge
                                                                          `);function Mu(e,t){j(t,!0);let n=$(t,`helpOpen`,3,!1),r=$(t,`connectionState`,3,`connecting`),i=$(t,`onToggleHelp`,3,()=>{});var a=ju(),o=L(a),s=L(o);A(),k(o);var c=B(o,2),l=L(c),u=B(l,2),d=B(u,2),f=B(d,2);k(c),ku(B(c,2),{get state(){return r()}}),k(a),V(()=>{Z(a,1,X(Au.header)),Z(o,1,X(Au.brand)),Z(s,1,X(Au.brandMark)),Q(l,`aria-current`,t.routeName===`home`?`page`:void 0),Q(u,`aria-current`,t.routeName===`devices`||t.routeName===`device`?`page`:void 0),Q(d,`aria-current`,t.routeName===`health`?`page`:void 0),Q(f,`aria-expanded`,n())}),Dr(`click`,f,function(...e){i()?.apply(this,e)}),q(e,a),M()}Or([`click`]);var Nu={footer:`_footer_1op89_1`},Pu=G(`
                                                                          WatcherBridge · Local review workspaceScanner reports are evidence, not a live inventory.
                                                                          `);function Fu(e,t){j(t,!0);var n=Pu();V(()=>Z(n,1,X(Nu.footer))),q(e,n),M()}var Iu={help:`_help_1powj_1`},Lu=G(`
                                                                        • `),Ru=G(`

                                                                          Keyboard shortcuts

                                                                          • g then h — Home
                                                                          • g then d — Reported hosts

                                                                          Shortcuts stay silent while typing. Briefing keys preset the composer; nothing submits on its own.

                                                                          `);function zu(e,t){j(t,!0);let n=N(()=>t.shortcuts.describe(`global`)),r=N(()=>t.shortcuts.describe(`briefing`));var i=Ru(),a=B(L(i),2),o=L(a);Qr(o,17,()=>W(n),e=>e.key,(e,t)=>{var n=Lu(),r=L(n),i=z(r,!0),a=B(r);k(n),V(()=>{J(i,W(t).key),J(a,` — ${W(t).label??``}`)}),q(e,n)}),Qr(B(o,6),17,()=>W(r),e=>e.key,(e,t)=>{var n=Lu(),r=L(n),i=z(r,!0),a=B(r);k(n),V(()=>{J(i,W(t).key),J(a,` — on a briefing: ${W(t).label??``}, then confirm`)}),q(e,n)}),k(a),A(2),k(i),V(()=>Z(i,1,X(Iu.help))),q(e,i),M()}var Bu=G(`

                                                                          `,1);function Vu(e,t){j(t,!0);let n=()=>$i(h,`$connectionState`,r),[r,i]=ta(),a=F(Zt(window.location.hash||`#/`)),o=F(null),s=F(null),c=F(!1),l=!1,u=0,f=va(),p=Da(),m=ba({onOverview:e=>{I(o,e,!0),f.streamed(),I(s,null)},onIncident:()=>{_()}});Sa(m);let{connection:h}=m;p.register(`global`,`?`,`Toggle this shortcut list`,e=>{I(c,!W(c)),e.preventDefault()}),p.register(`global`,`j`,`Move between rows in a list`,e=>{Ta(1)&&e.preventDefault()}),p.register(`global`,`k`,`Move between rows in a list`,e=>{Ta(-1)&&e.preventDefault()});let g=N(()=>Aa(W(a)));async function _(){let e=f.start();try{let t=await sa();f.current(e)&&(I(o,t,!0),I(s,null))}catch(t){f.current(e)&&W(o)===null&&I(s,t instanceof Error?t.message:String(t),!0)}}function v(e){Ea(e)?l=!1:e.key===`g`&&!e.metaKey&&!e.ctrlKey&&!e.altKey?(l=!0,window.clearTimeout(u),u=window.setTimeout(()=>{l=!1},1e3)):l?(l=!1,window.clearTimeout(u),e.key===`h`?window.location.hash=`#/`:e.key===`d`&&(window.location.hash=`#/devices`)):p.dispatch(`global`,e)}aa(()=>{let e=()=>{I(a,window.location.hash||`#/`,!0)};return window.addEventListener(`hashchange`,e),window.addEventListener(`keydown`,v),I(a,window.location.hash||`#/`,!0),_(),m.connect(),()=>{window.removeEventListener(`hashchange`,e),window.removeEventListener(`keydown`,v),window.clearTimeout(u),m.disconnect()}});var y=Bu(),b=R(y);Du(b,{});var x=B(b,2),S=L(x);Mu(S,{get routeName(){return W(g).name},get helpOpen(){return W(c)},get connectionState(){return n()},onToggleHelp:()=>I(c,!W(c))});var C=B(S,2),w=e=>{zu(e,{get shortcuts(){return p}})};Y(C,e=>{W(c)&&e(w)});var T=B(C,2),E=L(T),ee=z(E,!0);qr(B(E,2),()=>W(a),e=>{var t=Ir(),n=R(t),r=e=>{ko(e,{get overview(){return W(o)},get loadError(){return W(s)},members:(e,t=d,n=d)=>{Mo(e,{get incidentId(){return t()},get expanded(){return n()}})},pane:(e,t=d,n=d)=>{var r=Ir(),i=R(r),a=e=>{Bc(e,{get id(){return t().id},layout:`embedded`,get ontitle(){return n()},get shortcuts(){return p}})},o=e=>{ll(e,{get id(){return t().id}})};Y(i,e=>{t().kind===`briefing`?e(a):e(o,-1)}),q(e,r)},$$slots:{members:!0,pane:!0}})},i=e=>{Bc(e,{get id(){return W(g).id},get shortcuts(){return p}})},a=e=>{ll(e,{get id(){return W(g).id}})},c=e=>{Cl(e,{})},l=e=>{Gl(e,{get id(){return W(g).id}})},u=e=>{wu(e,{})};Y(n,e=>{W(g).name===`home`?e(r):W(g).name===`briefing`?e(i,1):W(g).name===`incident`?e(a,2):W(g).name===`devices`?e(c,3):W(g).name===`device`?e(l,4):W(g).name===`health`&&e(u,5)}),q(e,t)}),k(T),Fu(B(T,2),{}),k(x),V(e=>J(ee,e),[()=>ja(W(g).name)]),q(e,y),M(),i()}var Hu=document.getElementById(`app`);Hu&&Vr(Vu,{target:Hu}); \ No newline at end of file diff --git a/ui/CONVENTIONS.md b/ui/CONVENTIONS.md new file mode 100644 index 0000000..7722a4d --- /dev/null +++ b/ui/CONVENTIONS.md @@ -0,0 +1,105 @@ +# UI conventions — folder split + +How the Svelte viewer is organized, and the rules every change must hold. +Governing contracts: [Designv9 §8](../.innerdoc/Designv9.md#8-svelte-viewer-and-product-language) +(dependency allowlist, JS only, 200 KiB gzip, hash routing), +[CONTRIBUTING](../CONTRIBUTING.md) (committed `dist`, `make ui-check`). + +## Roles + +| | `containers/` | `components/` | +|---|---|---| +| Role | Smart: fetch, hold state, subscribe, post, wire everything together | Dumb: render props, emit callbacks | +| May import | `@/api`, `@/lib`, components, context | Other components, `@/lib` pure helpers (e.g. `format.js`) | +| May not import | Other containers (`App` alone composes pages) | `@/api`, `@/containers`, context, `window` listeners | +| Local state | Only what orchestration needs | UI-only state (open/closed, a form draft, a copied flag) | + +Enforced by `eslint.config.js` (`no-restricted-imports`); `App` has its own +override as the single composer. `src/lib` holds no markup or CSS and never +imports UI layers. + +Shared-widget exception (plan step 33): screens may embed +`DecisionsContainer` — a subject-parameterized review widget with no page +coupling — through a targeted `eslint-disable-next-line` at the import. +Page containers (Home, Devices, Device, Incident, Briefing) stay +App-composed; embedded full pages still arrive through App snippets. + +## Layout + +Every unit lives in its own folder — components included — so styles, +tests and the entry point travel together: + +``` +components// Name.svelte Name.module.css index.js +containers// Name.svelte (Name.css only when the container has its own markup) +``` + +`src/lib` is flat: every helper is one `lib/*.js` module, no +subfolders, no barrels. `Pill`, `TimeStamp` and `Notice` own badges, +timestamps and status/alert banners, so no global class remains for +them — transitional globals are deleted, not parked. + +Component props: data in, `on` callbacks out (`onselect`, +`ondecided`). No `reload` callback props — containers own refetching. +Appearance variants ride on props (`variant`, `layout`), never on +parent selectors reaching into children. Shared derivation lives in +`@/lib/*` helpers with plain-node unit coverage, not inside components. + +## CSS + +- CSS Modules (`*.module.css`), Vite-native. No `svelte-preprocess`: + it is outside the Design §8.1 allowlist, and without it ` diff --git a/ui/src/components/AppFooter/AppFooter.module.css b/ui/src/components/AppFooter/AppFooter.module.css new file mode 100644 index 0000000..883ca46 --- /dev/null +++ b/ui/src/components/AppFooter/AppFooter.module.css @@ -0,0 +1,16 @@ +.footer { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + gap: 8px; + padding: 16px 28px; + border-top: 1px solid var(--border); + font-size: 12px; + color: var(--muted); +} + +@media (max-width: 640px) { + .footer { + padding: 16px; + } +} diff --git a/ui/src/components/AppFooter/AppFooter.svelte b/ui/src/components/AppFooter/AppFooter.svelte new file mode 100644 index 0000000..7d54f79 --- /dev/null +++ b/ui/src/components/AppFooter/AppFooter.svelte @@ -0,0 +1,7 @@ + + +
                                                                          + WatcherBridge · Local review workspaceScanner reports are evidence, not a live inventory. +
                                                                          diff --git a/ui/src/components/AppFooter/index.js b/ui/src/components/AppFooter/index.js new file mode 100644 index 0000000..b9b7c0a --- /dev/null +++ b/ui/src/components/AppFooter/index.js @@ -0,0 +1 @@ +export { default } from './AppFooter.svelte'; diff --git a/ui/src/components/AppHeader/AppHeader.module.css b/ui/src/components/AppHeader/AppHeader.module.css new file mode 100644 index 0000000..dbd9780 --- /dev/null +++ b/ui/src/components/AppHeader/AppHeader.module.css @@ -0,0 +1,73 @@ +.header { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 12px 28px; + padding: 12px 28px; + background: var(--surface); + border-bottom: 1px solid var(--border); +} + +.brand { + display: inline-flex; + align-items: center; + gap: 10px; + color: var(--text); + font-size: 18px; + font-weight: 700; + text-decoration: none; + letter-spacing: -0.5px; +} + +.brandMark { + display: grid; + place-items: center; + width: 30px; + height: 30px; + border-radius: 8px; + background: var(--text); + color: var(--surface); + font-size: 17px; +} + +.header nav { + display: flex; + flex-wrap: wrap; + gap: 4px; +} + +.header nav a, +.header nav button { + display: inline-flex; + align-items: center; + padding: 8px 14px; + min-height: 44px; + border: 0; + border-radius: 8px; + background: transparent; + text-decoration: none; + color: var(--muted); +} + +.header nav a[aria-current='page'] { + background: var(--accent-soft); + color: var(--accent); + font-weight: 650; +} + +@media (max-width: 640px) { + .header { + padding: 12px 16px; + gap: 10px; + } + + .header nav { + order: 3; + width: 100%; + } + + .header nav a, + .header nav button { + padding: 8px 10px; + } +} diff --git a/ui/src/components/AppHeader/AppHeader.svelte b/ui/src/components/AppHeader/AppHeader.svelte new file mode 100644 index 0000000..91d9b31 --- /dev/null +++ b/ui/src/components/AppHeader/AppHeader.svelte @@ -0,0 +1,16 @@ + + +
                                                                          + WatcherBridge + + +
                                                                          diff --git a/ui/src/components/AppHeader/index.js b/ui/src/components/AppHeader/index.js new file mode 100644 index 0000000..3b4156c --- /dev/null +++ b/ui/src/components/AppHeader/index.js @@ -0,0 +1 @@ +export { default } from './AppHeader.svelte'; diff --git a/ui/src/components/AttentionList/AttentionList.svelte b/ui/src/components/AttentionList/AttentionList.svelte new file mode 100644 index 0000000..b0f7da6 --- /dev/null +++ b/ui/src/components/AttentionList/AttentionList.svelte @@ -0,0 +1,60 @@ + + +
                                                                          +

                                                                          Needs attention ({items.length})

                                                                          + {#if items.length === 0} +

                                                                          Nothing flagged. New briefings appear here when the bridge reports them.

                                                                          + {:else} +
                                                                            + {#each items as item (item.id)} +
                                                                          1. + {#snippet row()} + {item.priority} + {item.kind === 'incident' ? 'Incident · ' : ''}{item.kind === 'briefing' ? (titles[item.id] ?? reviewTitle(item.change_kind)) : changeLabel(item.change_kind)}{item.id} + {item.status} + {/snippet} + {#if item.kind === 'briefing' || item.kind === 'incident'} + {#if onselect} + + {:else} + {@render row()} + {/if} + {:else} +
                                                                            {@render row()}
                                                                            + {/if} + {#if item.kind === 'incident'} + {@const open = expanded[item.id] ?? false} + + {@render members?.(item.id, open)} + {/if} +
                                                                          2. + {/each} +
                                                                          + {/if} +
                                                                          diff --git a/ui/src/components/AttentionList/index.js b/ui/src/components/AttentionList/index.js new file mode 100644 index 0000000..77931d3 --- /dev/null +++ b/ui/src/components/AttentionList/index.js @@ -0,0 +1 @@ +export { default } from './AttentionList.svelte'; diff --git a/ui/src/components/BriefingSummary/BriefingSummary.svelte b/ui/src/components/BriefingSummary/BriefingSummary.svelte new file mode 100644 index 0000000..0412811 --- /dev/null +++ b/ui/src/components/BriefingSummary/BriefingSummary.svelte @@ -0,0 +1,40 @@ + + +
                                                                          +
                                                                          +

                                                                          {title}

                                                                          + {priority} priority +
                                                                          +

                                                                          {description}

                                                                          + +
                                                                          + {eventCount}{eventsTruncated ? '+' : ''} source report{eventCount === 1 ? '' : 's'} + {#if primaryEvent} + + {:else if eventCount > 0} + + {/if} +
                                                                          +
                                                                          diff --git a/ui/src/components/BriefingSummary/index.js b/ui/src/components/BriefingSummary/index.js new file mode 100644 index 0000000..7b22186 --- /dev/null +++ b/ui/src/components/BriefingSummary/index.js @@ -0,0 +1 @@ +export { default } from './BriefingSummary.svelte'; diff --git a/ui/src/lib/ConnectionStatus.svelte b/ui/src/components/ConnectionStatus/ConnectionStatus.svelte similarity index 100% rename from ui/src/lib/ConnectionStatus.svelte rename to ui/src/components/ConnectionStatus/ConnectionStatus.svelte diff --git a/ui/src/components/ConnectionStatus/index.js b/ui/src/components/ConnectionStatus/index.js new file mode 100644 index 0000000..1ae2e09 --- /dev/null +++ b/ui/src/components/ConnectionStatus/index.js @@ -0,0 +1 @@ +export { default } from './ConnectionStatus.svelte'; diff --git a/ui/src/components/CopyValue/CopyValue.module.css b/ui/src/components/CopyValue/CopyValue.module.css new file mode 100644 index 0000000..f9af96c --- /dev/null +++ b/ui/src/components/CopyValue/CopyValue.module.css @@ -0,0 +1,13 @@ +:global(.wb-clipboard-buffer) { + position: fixed; + opacity: 0; + pointer-events: none; +} + +.copyBtn { + font-size: 12px; + padding: 4px 10px; + min-height: 32px; + color: var(--accent); + background: var(--accent-soft); +} diff --git a/ui/src/lib/CopyValue.svelte b/ui/src/components/CopyValue/CopyValue.svelte similarity index 82% rename from ui/src/lib/CopyValue.svelte rename to ui/src/components/CopyValue/CopyValue.svelte index a79521c..a429174 100644 --- a/ui/src/lib/CopyValue.svelte +++ b/ui/src/components/CopyValue/CopyValue.svelte @@ -1,5 +1,6 @@ - {#if state === 'failed'} Could not copy the {name}; select and copy it manually. {/if} - diff --git a/ui/src/components/CopyValue/index.js b/ui/src/components/CopyValue/index.js new file mode 100644 index 0000000..bf88580 --- /dev/null +++ b/ui/src/components/CopyValue/index.js @@ -0,0 +1 @@ +export { default } from './CopyValue.svelte'; diff --git a/ui/src/components/DecisionComposer/DecisionComposer.module.css b/ui/src/components/DecisionComposer/DecisionComposer.module.css new file mode 100644 index 0000000..2948fb2 --- /dev/null +++ b/ui/src/components/DecisionComposer/DecisionComposer.module.css @@ -0,0 +1,64 @@ +.composer { + display: contents; +} + +.composer fieldset { + display: grid; + gap: 0; + border: 1px solid var(--border); + border-radius: 11px; + padding: 6px 0; + margin: 0 0 12px; + min-width: 0; +} + +.composer fieldset label { + display: grid; + grid-template-columns: 20px minmax(0,1fr); + align-items: center; + gap: 2px 12px; + padding: 12px 16px; + margin: 0; + cursor: pointer; + min-height: 66px; +} + +.composer fieldset label:hover { + background: var(--subtle); +} + +.composer fieldset label.selected { + background: var(--accent-soft); +} + +.composer fieldset input { + grid-row: 1 / span 2; + width: 18px; + height: 18px; + padding: 0; + margin: 0; + accent-color: var(--accent); +} + +.decisionLabel { + font-weight: 600; +} + +.decisionHint { + grid-column: 2; + font-size: 12px; + color: var(--muted); +} + +.composer button[type=submit] { + width: 100%; + margin-top: 8px; + color: var(--surface); + background: var(--text); + border-color: var(--text); + font-weight: 700; +} + +.composer button[type=submit]:disabled { + opacity: .45; +} diff --git a/ui/src/components/DecisionComposer/DecisionComposer.svelte b/ui/src/components/DecisionComposer/DecisionComposer.svelte new file mode 100644 index 0000000..f9b71d0 --- /dev/null +++ b/ui/src/components/DecisionComposer/DecisionComposer.svelte @@ -0,0 +1,141 @@ + + +
                                                                          +
                                                                          + Choose a decision + {#each kinds as k (k)} + + {/each} +
                                                                          +

                                                                          {kind === null ? 'Choose a verdict to record it.' : (kindHelp[kind] ?? KIND_HELP[kind] ?? '')}

                                                                          + {#if memberScope} + + {/if} + {#if outcomeNote !== null} + {outcomeNote} + {/if} + {#if kind === 'snooze'} + + {/if} + {#if needsText} + + {/if} + {#if formError !== null} + {formError} + {/if} + +
                                                                          diff --git a/ui/src/components/DecisionComposer/index.js b/ui/src/components/DecisionComposer/index.js new file mode 100644 index 0000000..a0c6c7b --- /dev/null +++ b/ui/src/components/DecisionComposer/index.js @@ -0,0 +1 @@ +export { default } from './DecisionComposer.svelte'; diff --git a/ui/src/components/DecisionStatus/DecisionStatus.module.css b/ui/src/components/DecisionStatus/DecisionStatus.module.css new file mode 100644 index 0000000..ce157ef --- /dev/null +++ b/ui/src/components/DecisionStatus/DecisionStatus.module.css @@ -0,0 +1,9 @@ +.title { + font-size: 20px; + margin-bottom: 10px; + letter-spacing: -.4px; +} + +.status { + margin-bottom: 20px; +} diff --git a/ui/src/components/DecisionStatus/DecisionStatus.svelte b/ui/src/components/DecisionStatus/DecisionStatus.svelte new file mode 100644 index 0000000..62105ba --- /dev/null +++ b/ui/src/components/DecisionStatus/DecisionStatus.svelte @@ -0,0 +1,26 @@ + + +

                                                                          {title}

                                                                          +

                                                                          Status: {statusLine()}

                                                                          diff --git a/ui/src/components/DecisionStatus/index.js b/ui/src/components/DecisionStatus/index.js new file mode 100644 index 0000000..4574547 --- /dev/null +++ b/ui/src/components/DecisionStatus/index.js @@ -0,0 +1 @@ +export { default } from './DecisionStatus.svelte'; diff --git a/ui/src/components/DecisionTrail/DecisionTrail.module.css b/ui/src/components/DecisionTrail/DecisionTrail.module.css new file mode 100644 index 0000000..187f78a --- /dev/null +++ b/ui/src/components/DecisionTrail/DecisionTrail.module.css @@ -0,0 +1,51 @@ +.historyHeading { + margin: 24px 0 12px; + padding-top: 20px; + border-top: 1px solid var(--border); + text-transform: uppercase; + letter-spacing: .07em; + font-size: 11px; + color: var(--muted); +} + +.emptyHistory { + color: var(--muted); + font-size: 13px; + margin-bottom: 0; +} + +.trail { + padding: 0; + list-style: none; +} + +.trail li { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 8px; + border-top: 1px solid var(--border); + padding: 12px 0; + font-size: 13px; +} + +.trail time { + color: var(--muted); + font-size: 11px; +} + +.trail .text { + flex-basis: 100%; + overflow-wrap: anywhere; +} + +.trail .until { + color: var(--muted); + font-size: 12px; +} + +.trail button { + min-height: 32px; + padding: 4px 8px; + font-size: 12px; +} diff --git a/ui/src/components/DecisionTrail/DecisionTrail.svelte b/ui/src/components/DecisionTrail/DecisionTrail.svelte new file mode 100644 index 0000000..d9a06e9 --- /dev/null +++ b/ui/src/components/DecisionTrail/DecisionTrail.svelte @@ -0,0 +1,63 @@ + + +{#if card}

                                                                          Recorded decisions

                                                                          {/if} +{#if trail.length === 0} +

                                                                          No decisions recorded.

                                                                          +{:else} +
                                                                            + {#each trail as d (d.decision_id)} +
                                                                          1. + {d.kind.replace('_', ' ')} + {#if d.undone}undone{/if} + {#if d.text}{d.text}{/if} + {#if d.until}until {d.until}{/if} + + {#if !d.undone && d.kind !== 'undo'} + + {/if} +
                                                                          2. + {/each} +
                                                                          + {#if !exhausted} + + {/if} + {#if showNewer} + + {/if} + {#if note !== null} + {note} + {/if} +{/if} +{#if listError !== null} + {listError} +{/if} diff --git a/ui/src/components/DecisionTrail/index.js b/ui/src/components/DecisionTrail/index.js new file mode 100644 index 0000000..b23db20 --- /dev/null +++ b/ui/src/components/DecisionTrail/index.js @@ -0,0 +1 @@ +export { default } from './DecisionTrail.svelte'; diff --git a/ui/src/components/DeviceList/DeviceList.svelte b/ui/src/components/DeviceList/DeviceList.svelte new file mode 100644 index 0000000..337c2e5 --- /dev/null +++ b/ui/src/components/DeviceList/DeviceList.svelte @@ -0,0 +1,44 @@ + + +{#if stale} + Connection recovered — this list may miss new reports. +{/if} +{#if devices.length === 0} +

                                                                          No reported subjects retained.

                                                                          +{:else} +
                                                                            + {#each devices as dev (dev.profile_id)} + + {/each} +
                                                                          +{/if} +{#if error !== null} + Page failed ({error}) — earlier rows kept. +{/if} +{#if capped} +

                                                                          List capped at {cap} rows; use the API for the full set.

                                                                          +{:else if !exhausted} + +{:else} +

                                                                          End of retained list.

                                                                          +{/if} diff --git a/ui/src/components/DeviceList/index.js b/ui/src/components/DeviceList/index.js new file mode 100644 index 0000000..7e0ca6e --- /dev/null +++ b/ui/src/components/DeviceList/index.js @@ -0,0 +1 @@ +export { default } from './DeviceList.svelte'; diff --git a/ui/src/components/DeviceProfile/DeviceProfile.svelte b/ui/src/components/DeviceProfile/DeviceProfile.svelte new file mode 100644 index 0000000..8d91e9e --- /dev/null +++ b/ui/src/components/DeviceProfile/DeviceProfile.svelte @@ -0,0 +1,35 @@ + + +

                                                                          {profile.profile_id} — {classLabel(profile.class)}

                                                                          +{#if profile.class === 'legacy'} + Earlier bridge-inferred association; not used for current identity. +{:else if profile.class === 'address' || profile.class === 'event'} +

                                                                          This page describes {profile.class === 'address' ? 'address context' : 'unresolved events'}, not a device.

                                                                          +{/if} +
                                                                          +
                                                                          Source scope
                                                                          +
                                                                          {profile.source_scope}
                                                                          +
                                                                          Upstream reference
                                                                          +
                                                                          {profile.reported_id}
                                                                          +
                                                                          Reported by
                                                                          +
                                                                          {profile.reported_source} (confidence: {profile.reported_confidence || 'unknown'})
                                                                          +
                                                                          Association
                                                                          +
                                                                          {profile.association_status}
                                                                          + {#if profile.operator_label !== null && profile.operator_label !== undefined} +
                                                                          Your label
                                                                          +
                                                                          {profile.operator_label}
                                                                          + {/if} +
                                                                          First report
                                                                          +
                                                                          +
                                                                          Last report
                                                                          +
                                                                          +
                                                                          diff --git a/ui/src/components/DeviceProfile/index.js b/ui/src/components/DeviceProfile/index.js new file mode 100644 index 0000000..d97ed8d --- /dev/null +++ b/ui/src/components/DeviceProfile/index.js @@ -0,0 +1 @@ +export { default } from './DeviceProfile.svelte'; diff --git a/ui/src/components/DeviceRow/DeviceRow.svelte b/ui/src/components/DeviceRow/DeviceRow.svelte new file mode 100644 index 0000000..370f41b --- /dev/null +++ b/ui/src/components/DeviceRow/DeviceRow.svelte @@ -0,0 +1,17 @@ + + +
                                                                        • + + + {dev.operator_label || dev.reported_id || 'Unlabelled subject'}{dev.profile_id}{classLabel(dev.class)} + Last report + + +
                                                                        • diff --git a/ui/src/components/DeviceRow/index.js b/ui/src/components/DeviceRow/index.js new file mode 100644 index 0000000..e798bf5 --- /dev/null +++ b/ui/src/components/DeviceRow/index.js @@ -0,0 +1 @@ +export { default } from './DeviceRow.svelte'; diff --git a/ui/src/lib/DigestBar.svelte b/ui/src/components/DigestBar/DigestBar.svelte similarity index 95% rename from ui/src/lib/DigestBar.svelte rename to ui/src/components/DigestBar/DigestBar.svelte index ec73b99..9c264ae 100644 --- a/ui/src/lib/DigestBar.svelte +++ b/ui/src/components/DigestBar/DigestBar.svelte @@ -1,5 +1,5 @@ + +
                                                                          +

                                                                          Summary

                                                                          + +
                                                                          +
                                                                          Coverage
                                                                          {health.coverage}
                                                                          +
                                                                          Fallback briefings · 1h
                                                                          {health.fallback_1h.used} of {health.fallback_1h.total}
                                                                          +
                                                                          Awaiting operator
                                                                          {health.parked_groups}
                                                                          +
                                                                          Forward errors · 1h
                                                                          {health.forward_errors_1h}
                                                                          +
                                                                          Ingest queue
                                                                          {health.queue_depth} of {health.queue_cap}
                                                                          +
                                                                          + {#if (health.coverage_reasons ?? []).length > 0} +
                                                                            + {#each health.coverage_reasons as reason (reason)} +
                                                                          • {reason}
                                                                          • + {/each} +
                                                                          + {/if} + {#if latestRunNeedsAttention(health.purge.last)} + + Latest purge run {health.purge.last.status} + (){health.purge.last.error ? `: ${health.purge.last.error}` : ''}. + + {/if} + {#if refreshError !== null} + Refresh failed ({refreshError}) — showing retained data. + {/if} +
                                                                          diff --git a/ui/src/components/HealthSummary/index.js b/ui/src/components/HealthSummary/index.js new file mode 100644 index 0000000..095e05b --- /dev/null +++ b/ui/src/components/HealthSummary/index.js @@ -0,0 +1 @@ +export { default } from './HealthSummary.svelte'; diff --git a/ui/src/components/HistoryList/HistoryList.svelte b/ui/src/components/HistoryList/HistoryList.svelte new file mode 100644 index 0000000..9b20179 --- /dev/null +++ b/ui/src/components/HistoryList/HistoryList.svelte @@ -0,0 +1,45 @@ + + +
                                                                          +

                                                                          History

                                                                          + {#if observations.length === 0} +

                                                                          No retained reports in this window.

                                                                          + {:else} +
                                                                            + {#each observations as obs (obs.observation_id)} +
                                                                          1. + {obs.event_id} ({obs.view_role}) — + , + {obs.ports_total} ports{obs.ports_truncated ? ' (truncated)' : ''} +
                                                                          2. + {/each} +
                                                                          + {/if} + {#if historyError !== null} + Older page failed ({historyError}). + {/if} + {#if capped} +

                                                                          History capped at {cap} rows; use the API for the full set.

                                                                          + {:else if !exhausted} + + {:else} +

                                                                          End of retained history. Retention policy lives on the Health screen.

                                                                          + {/if} +
                                                                          diff --git a/ui/src/components/HistoryList/index.js b/ui/src/components/HistoryList/index.js new file mode 100644 index 0000000..1d4f70c --- /dev/null +++ b/ui/src/components/HistoryList/index.js @@ -0,0 +1 @@ +export { default } from './HistoryList.svelte'; diff --git a/ui/src/components/IdentityGrid/IdentityGrid.svelte b/ui/src/components/IdentityGrid/IdentityGrid.svelte new file mode 100644 index 0000000..c20691c --- /dev/null +++ b/ui/src/components/IdentityGrid/IdentityGrid.svelte @@ -0,0 +1,30 @@ + + +
                                                                          + {#if identity !== null && identityComplete} +
                                                                          Reported host
                                                                          {identity.hostname ?? 'Not reported'}
                                                                          +
                                                                          IP address
                                                                          {identity.ip ?? 'Not reported'}{#if identity.ip !== null}{/if}
                                                                          +
                                                                          MAC address
                                                                          {identity.mac ?? 'Not reported'}{#if identity.mac !== null}{/if}
                                                                          + {:else} +
                                                                          Reported identities
                                                                          See the individual report views below

                                                                          {identityComplete ? 'Grouped changes can describe different host views.' : 'Only part of the retained evidence is shown.'}

                                                                          + {/if} +
                                                                          Reported scan target
                                                                          {primaryEvent?.target || (eventCount > 1 ? 'Shown per report below' : 'Not reported')}{#if primaryEvent?.target_truncated} (truncated){/if}
                                                                          +
                                                                          {range?.partial || referencedTruncated ? 'Available report times' : eventCount > 1 ? 'Report time range' : 'Report time'}
                                                                          {#if range !== null}{range.local}{:else}Not reported{/if}
                                                                          +
                                                                          Analysis source
                                                                          {sourceLabel(source)}
                                                                          +
                                                                          diff --git a/ui/src/components/IdentityGrid/index.js b/ui/src/components/IdentityGrid/index.js new file mode 100644 index 0000000..f894b98 --- /dev/null +++ b/ui/src/components/IdentityGrid/index.js @@ -0,0 +1 @@ +export { default } from './IdentityGrid.svelte'; diff --git a/ui/src/components/IncidentEvidence/IncidentEvidence.svelte b/ui/src/components/IncidentEvidence/IncidentEvidence.svelte new file mode 100644 index 0000000..242f8ed --- /dev/null +++ b/ui/src/components/IncidentEvidence/IncidentEvidence.svelte @@ -0,0 +1,40 @@ + + +
                                                                          +

                                                                          Evidence

                                                                          +

                                                                          {countLine(incident)}

                                                                          + {#if incident.qualified_refs < incident.member_count} +

                                                                          Some members share identity evidence; only distinct qualified references count toward the burst threshold.

                                                                          + {/if} + {#if truncated} +

                                                                          More members exist than shown.

                                                                          + {/if} + {#if members.length === 0} +

                                                                          No member evidence retained.

                                                                          + {:else} +
                                                                            + {#each members as m (m.briefing_id)} +
                                                                          1. + {m.briefing_id} + {m.priority} + + {m.refs.length} qualified reference{m.refs.length === 1 ? '' : 's'} +
                                                                          2. + {/each} +
                                                                          + {/if} +
                                                                          diff --git a/ui/src/components/IncidentEvidence/index.js b/ui/src/components/IncidentEvidence/index.js new file mode 100644 index 0000000..a6292cd --- /dev/null +++ b/ui/src/components/IncidentEvidence/index.js @@ -0,0 +1 @@ +export { default } from './IncidentEvidence.svelte'; diff --git a/ui/src/components/IncidentHeader/IncidentHeader.svelte b/ui/src/components/IncidentHeader/IncidentHeader.svelte new file mode 100644 index 0000000..6845d15 --- /dev/null +++ b/ui/src/components/IncidentHeader/IncidentHeader.svelte @@ -0,0 +1,25 @@ + + +

                                                                          {KIND_LABEL[incident.kind] ?? incident.kind}

                                                                          +

                                                                          + {incident.status} + Floor: {incident.floor} + {#if incident.status === 'closed' && incident.closed_at} + Closed + {:else} + Open since + {/if} +

                                                                          diff --git a/ui/src/components/IncidentHeader/index.js b/ui/src/components/IncidentHeader/index.js new file mode 100644 index 0000000..df254c3 --- /dev/null +++ b/ui/src/components/IncidentHeader/index.js @@ -0,0 +1 @@ +export { default } from './IncidentHeader.svelte'; diff --git a/ui/src/components/IncidentScope/IncidentScope.svelte b/ui/src/components/IncidentScope/IncidentScope.svelte new file mode 100644 index 0000000..81e4ea7 --- /dev/null +++ b/ui/src/components/IncidentScope/IncidentScope.svelte @@ -0,0 +1,14 @@ + + +
                                                                          +

                                                                          Scope

                                                                          +

                                                                          Source: {incident.source_scope}

                                                                          +

                                                                          Target: {incident.target}

                                                                          +

                                                                          Window start: · Last member:

                                                                          +
                                                                          diff --git a/ui/src/components/IncidentScope/index.js b/ui/src/components/IncidentScope/index.js new file mode 100644 index 0000000..906cc1f --- /dev/null +++ b/ui/src/components/IncidentScope/index.js @@ -0,0 +1 @@ +export { default } from './IncidentScope.svelte'; diff --git a/ui/src/components/IncidentSummary/IncidentSummary.svelte b/ui/src/components/IncidentSummary/IncidentSummary.svelte new file mode 100644 index 0000000..21e5a8c --- /dev/null +++ b/ui/src/components/IncidentSummary/IncidentSummary.svelte @@ -0,0 +1,22 @@ + + +
                                                                          +

                                                                          Summary

                                                                          +

                                                                          Summary status: {summary.status}

                                                                          + {#if summary.summary}

                                                                          {summary.summary}

                                                                          {/if} + {#if summary.hypothesis}

                                                                          Hypothesis: {summary.hypothesis}

                                                                          {/if} + {#if summary.confidence}

                                                                          Display confidence: {summary.confidence}

                                                                          {/if} +

                                                                          Priority floor: {summary.floor}. Resolved priority: {summary.final_priority}{summary.suggestion ? ` (suggested ${summary.suggestion}${summary.clamped ? ', clamped' : ''})` : ' (no model raise)'}

                                                                          + {#if summary.reason}

                                                                          Priority explanation: {summary.reason}

                                                                          {/if} +

                                                                          Evidence coverage: {summary.sampled} sampled member reports; {summary.omitted} omitted. The sample may not represent every member.

                                                                          + {#if summary.citations.length} +

                                                                          Cited reports:

                                                                          + + {/if} + {#if summary.error}

                                                                          {summary.error}

                                                                          {/if} +
                                                                          diff --git a/ui/src/components/IncidentSummary/index.js b/ui/src/components/IncidentSummary/index.js new file mode 100644 index 0000000..4d71241 --- /dev/null +++ b/ui/src/components/IncidentSummary/index.js @@ -0,0 +1 @@ +export { default } from './IncidentSummary.svelte'; diff --git a/ui/src/components/InvestigatorNotes/InvestigatorNotes.svelte b/ui/src/components/InvestigatorNotes/InvestigatorNotes.svelte new file mode 100644 index 0000000..a881478 --- /dev/null +++ b/ui/src/components/InvestigatorNotes/InvestigatorNotes.svelte @@ -0,0 +1,42 @@ + + +
                                                                          +

                                                                          {source === 'agent' ? 'Investigator notes' : 'Analysis and retained context'}

                                                                          + {#if likelyExplanation}

                                                                          Possible explanation: {likelyExplanation}

                                                                          {/if} + {#if confidence}

                                                                          Explanation confidence (model self-assessment): {confidence}

                                                                          {/if} + {#if limited}

                                                                          Investigation has limits. Some lookups could not establish retained context. Missing lookup results do not prove this host has no history.

                                                                          {/if} +

                                                                          {context}

                                                                          + + {#if evidenceRefs?.length} +
                                                                          Cited evidence + {#each evidenceRefs as ref, i (`${ref.event_id ?? ref.tool_step}:${i}`)} + + {/each} +
                                                                          + {/if} + {#if profiles.length > 0} + + {:else}

                                                                          No profile links persisted for this briefing.

                                                                          {/if} + {#if profilesTruncated}

                                                                          More profile links exist than shown.

                                                                          {/if} +
                                                                          diff --git a/ui/src/components/InvestigatorNotes/index.js b/ui/src/components/InvestigatorNotes/index.js new file mode 100644 index 0000000..9546152 --- /dev/null +++ b/ui/src/components/InvestigatorNotes/index.js @@ -0,0 +1 @@ +export { default } from './InvestigatorNotes.svelte'; diff --git a/ui/src/components/LatestEvidence/LatestEvidence.svelte b/ui/src/components/LatestEvidence/LatestEvidence.svelte new file mode 100644 index 0000000..ac6c55a --- /dev/null +++ b/ui/src/components/LatestEvidence/LatestEvidence.svelte @@ -0,0 +1,30 @@ + + +
                                                                          +

                                                                          Latest evidence

                                                                          + {#if latest === null} +

                                                                          No retained observation.

                                                                          + {:else} +

                                                                          Reported ({latest.view_role}).

                                                                          +
                                                                          + {#each Object.entries(latest.attributes ?? {}) as [key, value] (key)} +
                                                                          {key}
                                                                          +
                                                                          {JSON.stringify(value)}
                                                                          + {/each} +
                                                                          + {#if (latest.ports ?? []).length > 0} +
                                                                            + {#each latest.ports as port (`${port.proto}/${port.port}`)} +
                                                                          • {port.proto}/{port.port} {port.state}{port.service ? ` (${port.service})` : ''}
                                                                          • + {/each} +
                                                                          + {/if} +

                                                                          Snapshot covers {latest.ports_total} ports{latest.ports_truncated ? ' (truncated)' : ''}.

                                                                          + {/if} +
                                                                          diff --git a/ui/src/components/LatestEvidence/index.js b/ui/src/components/LatestEvidence/index.js new file mode 100644 index 0000000..8c1e945 --- /dev/null +++ b/ui/src/components/LatestEvidence/index.js @@ -0,0 +1 @@ +export { default } from './LatestEvidence.svelte'; diff --git a/ui/src/components/LookupReceipts/LookupReceipts.svelte b/ui/src/components/LookupReceipts/LookupReceipts.svelte new file mode 100644 index 0000000..2aa7a0b --- /dev/null +++ b/ui/src/components/LookupReceipts/LookupReceipts.svelte @@ -0,0 +1,16 @@ + + +{#if receipts?.length} +

                                                                          What the investigator could establish

                                                                          +
                                                                            + {#each receipts as receipt, i (i)} +
                                                                          • {receipt.summary || 'No interpreted result is available. Open the tool step to inspect the saved response.'}

                                                                            {#each receipt.steps as step (step)}{/each}
                                                                          • + {/each} +
                                                                          +{/if} diff --git a/ui/src/components/LookupReceipts/index.js b/ui/src/components/LookupReceipts/index.js new file mode 100644 index 0000000..2f26e19 --- /dev/null +++ b/ui/src/components/LookupReceipts/index.js @@ -0,0 +1 @@ +export { default } from './LookupReceipts.svelte'; diff --git a/ui/src/components/MemberUndoReview/MemberUndoReview.svelte b/ui/src/components/MemberUndoReview/MemberUndoReview.svelte new file mode 100644 index 0000000..a970bcf --- /dev/null +++ b/ui/src/components/MemberUndoReview/MemberUndoReview.svelte @@ -0,0 +1,23 @@ + + +{memberUndoNote(review)} +{#if review.members.length > 0} +
                                                                            + {#each review.members as m (m.decision_id)} +
                                                                          • {m.subject_id} — {m.kind.replace('_', ' ')}
                                                                          • + {/each} +
                                                                          +{/if} +{#if review.next} + +{/if} +{#if error !== null}{error}{/if} diff --git a/ui/src/components/MemberUndoReview/index.js b/ui/src/components/MemberUndoReview/index.js new file mode 100644 index 0000000..f64fe7b --- /dev/null +++ b/ui/src/components/MemberUndoReview/index.js @@ -0,0 +1 @@ +export { default } from './MemberUndoReview.svelte'; diff --git a/ui/src/components/Notice/Notice.svelte b/ui/src/components/Notice/Notice.svelte new file mode 100644 index 0000000..9a53abc --- /dev/null +++ b/ui/src/components/Notice/Notice.svelte @@ -0,0 +1,14 @@ + + +

                                                                          + {@render children()} + {#if actionLabel !== null} + + {/if} +

                                                                          diff --git a/ui/src/components/Notice/index.js b/ui/src/components/Notice/index.js new file mode 100644 index 0000000..78f2761 --- /dev/null +++ b/ui/src/components/Notice/index.js @@ -0,0 +1 @@ +export { default } from './Notice.svelte'; diff --git a/ui/src/components/Pill/Pill.module.css b/ui/src/components/Pill/Pill.module.css new file mode 100644 index 0000000..791b1f0 --- /dev/null +++ b/ui/src/components/Pill/Pill.module.css @@ -0,0 +1,64 @@ +.pill { + display: inline-flex; + align-items: center; + gap: 4px; + border: 1px solid var(--border); + border-radius: 999px; + padding: 2px 9px; + background: var(--subtle); + font-size: 12px; + color: var(--muted); + vertical-align: middle; +} + +.pill.large { + padding: 5px 11px; +} + +.pill[data-state=ok], +.priority[data-priority=low] { + color: var(--success); + background: var(--success-bg); + border-color: var(--success-border); +} + +.pill[data-state=degraded], +.priority[data-priority=medium] { + color: var(--warning); + background: var(--warning-bg); + border-color: var(--warning-border); +} + +.pill[data-state=blind], +.priority[data-priority=high], +.priority[data-priority=critical] { + color: var(--danger); + background: var(--danger-bg); + border-color: var(--danger-border); +} + +.priority { + text-transform: uppercase; + border-radius: 5px; + font-weight: 650; + letter-spacing: .03em; +} + +.pill[data-review=unreviewed], +.pill[data-review=snooze] { + color: var(--warning); + background: var(--warning-bg); + border-color: var(--warning-border); +} + +.pill[data-review=expected] { + color: var(--success); + background: var(--success-bg); + border-color: var(--success-border); +} + +.pill[data-review=not_expected] { + color: var(--danger); + background: var(--danger-bg); + border-color: var(--danger-border); +} diff --git a/ui/src/components/Pill/Pill.svelte b/ui/src/components/Pill/Pill.svelte new file mode 100644 index 0000000..f3c6b19 --- /dev/null +++ b/ui/src/components/Pill/Pill.svelte @@ -0,0 +1,10 @@ + + +{@render children()} diff --git a/ui/src/components/Pill/index.js b/ui/src/components/Pill/index.js new file mode 100644 index 0000000..f93ed98 --- /dev/null +++ b/ui/src/components/Pill/index.js @@ -0,0 +1 @@ +export { default } from './Pill.svelte'; diff --git a/ui/src/components/PipelineDetails/PipelineDetails.svelte b/ui/src/components/PipelineDetails/PipelineDetails.svelte new file mode 100644 index 0000000..c5de091 --- /dev/null +++ b/ui/src/components/PipelineDetails/PipelineDetails.svelte @@ -0,0 +1,31 @@ + + +
                                                                          + Pipeline (process lifetime) +
                                                                          +
                                                                          Started
                                                                          +
                                                                          +
                                                                          Ingest accepted
                                                                          +
                                                                          {process.ingest_accepted}
                                                                          +
                                                                          Ingest duplicates
                                                                          +
                                                                          {process.ingest_duplicates}
                                                                          +
                                                                          Ingest rejected
                                                                          +
                                                                          {process.ingest_rejected}
                                                                          +
                                                                          Ingest saturated
                                                                          +
                                                                          {process.ingest_saturated}
                                                                          +
                                                                          Provider calls
                                                                          +
                                                                          {process.provider_calls}
                                                                          +
                                                                          Provider fallbacks
                                                                          +
                                                                          {process.provider_fallbacks}
                                                                          +
                                                                          Redaction blocked
                                                                          +
                                                                          {process.redaction_blocked}
                                                                          +
                                                                          Writer saturated
                                                                          +
                                                                          {process.writer_saturated}
                                                                          +
                                                                          +
                                                                          diff --git a/ui/src/components/PipelineDetails/index.js b/ui/src/components/PipelineDetails/index.js new file mode 100644 index 0000000..6983583 --- /dev/null +++ b/ui/src/components/PipelineDetails/index.js @@ -0,0 +1 @@ +export { default } from './PipelineDetails.svelte'; diff --git a/ui/src/components/PriorityExplanation/PriorityExplanation.svelte b/ui/src/components/PriorityExplanation/PriorityExplanation.svelte new file mode 100644 index 0000000..2c9740c --- /dev/null +++ b/ui/src/components/PriorityExplanation/PriorityExplanation.svelte @@ -0,0 +1,32 @@ + + +
                                                                          +

                                                                          Why this priority

                                                                          +

                                                                          {priorityReason}

                                                                          +
                                                                          Final priority: {priority}{#if baselineRule}{baselineRule}{/if}
                                                                          +
                                                                          + How the priority was computed +
                                                                            +
                                                                          1. Baseline floor {baseline}
                                                                          2. +
                                                                          3. Model suggestion {modelSuggestion ?? 'No model suggestion — baseline stands'}
                                                                          4. +
                                                                          5. Final priority {priority}
                                                                          6. +
                                                                          + {#if clamped}

                                                                          Suggestion adjusted to respect the baseline floor and one-step raise limit.

                                                                          {/if} +
                                                                          + {#if fallbackUsed}

                                                                          Deterministic fallback text: the model path did not produce this briefing.

                                                                          {/if} +
                                                                          diff --git a/ui/src/components/PriorityExplanation/index.js b/ui/src/components/PriorityExplanation/index.js new file mode 100644 index 0000000..f460ff4 --- /dev/null +++ b/ui/src/components/PriorityExplanation/index.js @@ -0,0 +1 @@ +export { default } from './PriorityExplanation.svelte'; diff --git a/ui/src/components/PublisherDetails/PublisherDetails.svelte b/ui/src/components/PublisherDetails/PublisherDetails.svelte new file mode 100644 index 0000000..44f584f --- /dev/null +++ b/ui/src/components/PublisherDetails/PublisherDetails.svelte @@ -0,0 +1,17 @@ + + +
                                                                          + Publisher +
                                                                          +
                                                                          Posted
                                                                          +
                                                                          {publisher.posted}
                                                                          +
                                                                          Dropped
                                                                          +
                                                                          {publisher.dropped}
                                                                          +
                                                                          Failed
                                                                          +
                                                                          {publisher.failed}
                                                                          +
                                                                          +
                                                                          diff --git a/ui/src/components/PublisherDetails/index.js b/ui/src/components/PublisherDetails/index.js new file mode 100644 index 0000000..f6e0828 --- /dev/null +++ b/ui/src/components/PublisherDetails/index.js @@ -0,0 +1 @@ +export { default } from './PublisherDetails.svelte'; diff --git a/ui/src/components/PurgeDetails/PurgeDetails.svelte b/ui/src/components/PurgeDetails/PurgeDetails.svelte new file mode 100644 index 0000000..b553e9a --- /dev/null +++ b/ui/src/components/PurgeDetails/PurgeDetails.svelte @@ -0,0 +1,34 @@ + + +
                                                                          + Purge +
                                                                          + {#each Object.entries(purge.totals ?? {}) as [table, count] (table)} +
                                                                          {table}
                                                                          +
                                                                          {count}
                                                                          + {/each} +
                                                                          + {#if retention} +

                                                                          + Configured retention: {days(retention.reports_seconds)} for reports{#if retention.subjects_seconds !== undefined}, {days(retention.subjects_seconds)} for subjects{/if}; + policy only — it never proves a per-profile boundary. Ask the API for per-profile history. +

                                                                          + {/if} + {#if purge.last_success} +

                                                                          Latest fully successful purge: .

                                                                          + {:else} +

                                                                          No fully successful purge recorded yet.

                                                                          + {/if} +
                                                                          diff --git a/ui/src/components/PurgeDetails/index.js b/ui/src/components/PurgeDetails/index.js new file mode 100644 index 0000000..5b91e89 --- /dev/null +++ b/ui/src/components/PurgeDetails/index.js @@ -0,0 +1 @@ +export { default } from './PurgeDetails.svelte'; diff --git a/ui/src/components/RecommendedCheck/RecommendedCheck.svelte b/ui/src/components/RecommendedCheck/RecommendedCheck.svelte new file mode 100644 index 0000000..8cfdb36 --- /dev/null +++ b/ui/src/components/RecommendedCheck/RecommendedCheck.svelte @@ -0,0 +1,19 @@ + + + diff --git a/ui/src/components/RecommendedCheck/index.js b/ui/src/components/RecommendedCheck/index.js new file mode 100644 index 0000000..0dbb119 --- /dev/null +++ b/ui/src/components/RecommendedCheck/index.js @@ -0,0 +1 @@ +export { default } from './RecommendedCheck.svelte'; diff --git a/ui/src/components/ReportView/ReportView.module.css b/ui/src/components/ReportView/ReportView.module.css new file mode 100644 index 0000000..4b15291 --- /dev/null +++ b/ui/src/components/ReportView/ReportView.module.css @@ -0,0 +1,95 @@ +.card { + border: 1px solid var(--border); + border-radius: 11px; + padding: 0 16px; + margin: 12px 0 0; + background: var(--surface); + overflow-wrap: anywhere; +} + +.card summary { + padding: 16px 0; +} + +.heading { + display: inline-flex; + flex-wrap: wrap; + align-items: center; + gap: 8px; + max-width: 100%; + vertical-align: top; +} + +.reportId { + font-weight: 600; +} + +.reportTime { + display: block; + font-size: 12px; + font-weight: 400; + color: var(--muted); + margin: 7px 0 0 16px; +} + +.body { + padding: 16px 0 6px; + border-top: 1px solid var(--border); +} + +.view { + border-top: 1px solid var(--border); + padding: 16px 0 0; + margin: 16px 0; +} + +.view h4 { + font-size: 14px; +} + +.identity { + display: grid; + grid-template-columns: repeat(auto-fit,minmax(min(100%,180px),1fr)); + gap: 14px; + margin: 0 0 16px; +} + +.identity dt { + font-size: 11px; + text-transform: uppercase; + letter-spacing: .05em; + margin-bottom: 4px; +} + +.identity dd { + margin: 0; +} + +.confidence { + display: flex; + gap: 8px; + align-items: center; + flex-wrap: wrap; +} + +.attributes { + padding: 0; + border: 0; +} + +.attributes summary { + font-size: 12px; + color: var(--accent); +} + +.profileChip { + display: flex; + flex-wrap: wrap; + gap: 5px 12px; + border: 1px solid var(--border); + background: var(--accent-soft); + border-radius: 9px; + padding: 10px 12px; + text-decoration: none; + font-size: 13px; +} diff --git a/ui/src/components/ReportView/ReportView.svelte b/ui/src/components/ReportView/ReportView.svelte new file mode 100644 index 0000000..592b433 --- /dev/null +++ b/ui/src/components/ReportView/ReportView.svelte @@ -0,0 +1,47 @@ + + +
                                                                          + + {ref.event_id}{ref.event_type} + Reported + +
                                                                          +

                                                                          Reported scan target: {ref.target || 'Not reported'}{#if ref.target_truncated} (truncated){/if}
                                                                          Received

                                                                          + {#if views.length === 0} +

                                                                          No retained observation for this event. Its reference is retained, but a saved scanner view is unavailable.

                                                                          + {:else} + {#each views as view (`${view.event_id}:${view.view_role}`)} + {@const attrs = view.attributes ?? {}} +
                                                                          +

                                                                          {view.view_role === 'previous' ? 'Before the reported change' : view.view_role === 'current' ? 'After the reported change' : 'Reported host'}

                                                                          +
                                                                          +
                                                                          Hostname
                                                                          {value(attrs.hostname)}
                                                                          +
                                                                          IP address
                                                                          {value(attrs.ip)}
                                                                          +
                                                                          MAC address
                                                                          {value(attrs.mac)}
                                                                          + {#if attrs.vendor}
                                                                          Reported vendor
                                                                          {attrs.vendor}
                                                                          {/if} + {#if attrs.os}
                                                                          Reported OS
                                                                          {attrs.os}
                                                                          {/if} + {#if attrs.device}
                                                                          Reported device
                                                                          {attrs.device}
                                                                          {/if} +
                                                                          +

                                                                          Scanner-reported identity confidence: {attrs.identity_confidence || 'unknown'}Identity source: {attrs.identity_source || 'unknown'}

                                                                          +

                                                                          {randomizedLabel(attrs.randomized)}

                                                                          + {#if attrs.attributes_truncated}

                                                                          Some reported fields were truncated at ingest.

                                                                          {/if} +
                                                                          Saved report view · technical attributes
                                                                          {JSON.stringify(attrs, null, 2)}
                                                                          +

                                                                          Snapshot covers {view.ports_total} ports{view.ports_truncated ? ' (truncated)' : ''}.

                                                                          + {#if (view.ports ?? []).length > 0} +
                                                                            {#each view.ports as port (`${port.proto}/${port.port}`)}
                                                                          • {port.proto}/{port.port} {port.state}{port.service ? ` (${port.service})` : ''}
                                                                          • {/each}
                                                                          + {/if} + {#if view.profile_id} + Open reported context →{classLabel(view.reference_class)} · {profileLinks.find((link) => link.profile_id === view.profile_id)?.role ?? view.view_role} + {:else}

                                                                          No linked profile is available for this saved view.

                                                                          {/if} +
                                                                          + {/each} + {/if} +
                                                                          +
                                                                          diff --git a/ui/src/components/ReportView/index.js b/ui/src/components/ReportView/index.js new file mode 100644 index 0000000..3a4fa63 --- /dev/null +++ b/ui/src/components/ReportView/index.js @@ -0,0 +1 @@ +export { default } from './ReportView.svelte'; diff --git a/ui/src/components/ScannerReports/ScannerReports.svelte b/ui/src/components/ScannerReports/ScannerReports.svelte new file mode 100644 index 0000000..5b27418 --- /dev/null +++ b/ui/src/components/ScannerReports/ScannerReports.svelte @@ -0,0 +1,23 @@ + + +
                                                                          +

                                                                          Scanner snapshot{events.length === 1 ? '' : 's'}

                                                                          Saved at report time
                                                                          +

                                                                          Open a report to see what the scanner supplied, with its linked context.

                                                                          + {#if events.length === 0}

                                                                          No referenced events retained.

                                                                          + {:else}{#each events as ref (ref.event_id)}{/each}{/if} + {#if referencedTruncated}

                                                                          More referenced events exist than shown.

                                                                          {/if} + {#if observationsTruncated}

                                                                          More observations exist than shown; some saved views are omitted.

                                                                          {/if} +
                                                                          diff --git a/ui/src/components/ScannerReports/index.js b/ui/src/components/ScannerReports/index.js new file mode 100644 index 0000000..33eab3d --- /dev/null +++ b/ui/src/components/ScannerReports/index.js @@ -0,0 +1 @@ +export { default } from './ScannerReports.svelte'; diff --git a/ui/src/components/ShortcutsHelp/ShortcutsHelp.module.css b/ui/src/components/ShortcutsHelp/ShortcutsHelp.module.css new file mode 100644 index 0000000..d73ac1b --- /dev/null +++ b/ui/src/components/ShortcutsHelp/ShortcutsHelp.module.css @@ -0,0 +1,7 @@ +.help { + margin: 16px 28px; + padding: 20px; + background: var(--surface); + border: 1px solid var(--border); + border-radius: 12px; +} diff --git a/ui/src/components/ShortcutsHelp/ShortcutsHelp.svelte b/ui/src/components/ShortcutsHelp/ShortcutsHelp.svelte new file mode 100644 index 0000000..29534a6 --- /dev/null +++ b/ui/src/components/ShortcutsHelp/ShortcutsHelp.svelte @@ -0,0 +1,25 @@ + + +
                                                                          +

                                                                          Keyboard shortcuts

                                                                          +
                                                                            + {#each globalKeys as binding (binding.key)} +
                                                                          • {binding.key} — {binding.label}
                                                                          • + {/each} +
                                                                          • g then h — Home
                                                                          • +
                                                                          • g then d — Reported hosts
                                                                          • + {#each briefingKeys as binding (binding.key)} +
                                                                          • {binding.key} — on a briefing: {binding.label}, then confirm
                                                                          • + {/each} +
                                                                          +

                                                                          Shortcuts stay silent while typing. Briefing keys preset the composer; nothing submits on its own.

                                                                          +
                                                                          diff --git a/ui/src/components/ShortcutsHelp/index.js b/ui/src/components/ShortcutsHelp/index.js new file mode 100644 index 0000000..4081759 --- /dev/null +++ b/ui/src/components/ShortcutsHelp/index.js @@ -0,0 +1 @@ +export { default } from './ShortcutsHelp.svelte'; diff --git a/ui/src/components/SkipLink/SkipLink.module.css b/ui/src/components/SkipLink/SkipLink.module.css new file mode 100644 index 0000000..bf4c8f4 --- /dev/null +++ b/ui/src/components/SkipLink/SkipLink.module.css @@ -0,0 +1,12 @@ +.skip { + position: fixed; + left: 16px; + top: -100px; + z-index: 10; + padding: 12px; + background: var(--surface); +} + +.skip:focus { + top: 12px; +} diff --git a/ui/src/components/SkipLink/SkipLink.svelte b/ui/src/components/SkipLink/SkipLink.svelte new file mode 100644 index 0000000..20fbdd4 --- /dev/null +++ b/ui/src/components/SkipLink/SkipLink.svelte @@ -0,0 +1,8 @@ + + + { event.preventDefault(); document.getElementById('content')?.focus(); }}>Skip to content diff --git a/ui/src/components/SkipLink/index.js b/ui/src/components/SkipLink/index.js new file mode 100644 index 0000000..add57cc --- /dev/null +++ b/ui/src/components/SkipLink/index.js @@ -0,0 +1 @@ +export { default } from './SkipLink.svelte'; diff --git a/ui/src/components/SnapshotNote/SnapshotNote.svelte b/ui/src/components/SnapshotNote/SnapshotNote.svelte new file mode 100644 index 0000000..121a887 --- /dev/null +++ b/ui/src/components/SnapshotNote/SnapshotNote.svelte @@ -0,0 +1,3 @@ + +

                                                                          Reported at the time shown. Network conditions may have changed since this report.

                                                                          diff --git a/ui/src/components/SnapshotNote/index.js b/ui/src/components/SnapshotNote/index.js new file mode 100644 index 0000000..7d99db1 --- /dev/null +++ b/ui/src/components/SnapshotNote/index.js @@ -0,0 +1 @@ +export { default } from './SnapshotNote.svelte'; diff --git a/ui/src/components/SourceCard/SourceCard.svelte b/ui/src/components/SourceCard/SourceCard.svelte new file mode 100644 index 0000000..414c7f3 --- /dev/null +++ b/ui/src/components/SourceCard/SourceCard.svelte @@ -0,0 +1,50 @@ + + +
                                                                          +

                                                                          {source.scope} — {source.status}

                                                                          +
                                                                          +
                                                                          Liveness
                                                                          +
                                                                          {source.liveness}{source.liveness === 'unknown' ? ' (no heartbeat capability; silence is not absence)' : ''}
                                                                          +
                                                                          Identity namespace
                                                                          +
                                                                          {source.identity_namespace || 'unknown — stable identity contract unavailable'}
                                                                          +
                                                                          Identity capability
                                                                          +
                                                                          {source.capabilities || 'not reported — heartbeat is not identity proof'}
                                                                          +
                                                                          Heartbeat
                                                                          +
                                                                          + {source.heartbeat_enabled ? 'enabled (delivery opt-in, not identity proof)' : 'disabled'} + {#if source.last_heartbeat_at}— last at {/if} +
                                                                          + {#if source.heartbeat} +
                                                                          Last completed scan
                                                                          +
                                                                          +
                                                                          Scan result
                                                                          +
                                                                          {source.heartbeat.status}, {source.heartbeat.issue_count} {source.heartbeat.issue_count === 1 ? 'issue' : 'issues'}, {source.heartbeat.duration_ms} ms
                                                                          +
                                                                          Reported host records
                                                                          +
                                                                          {source.heartbeat.hosts_seen} — scan records, not a current inventory or device count
                                                                          +
                                                                          Signing clock offset
                                                                          +
                                                                          {source.heartbeat.clock_skew_seconds} seconds (includes delivery delay)
                                                                          + {/if} + {#if source.last_report_at} +
                                                                          Last report
                                                                          +
                                                                          + {/if} + {#if source.delivery_status} +
                                                                          Delivery
                                                                          +
                                                                          {source.delivery_status}
                                                                          + {/if} +
                                                                          + {#if (source.reasons ?? []).length > 0} +
                                                                            + {#each source.reasons as reason (reason)} +
                                                                          • {reason}
                                                                          • + {/each} +
                                                                          + {/if} +
                                                                          diff --git a/ui/src/components/SourceCard/index.js b/ui/src/components/SourceCard/index.js new file mode 100644 index 0000000..e92eb36 --- /dev/null +++ b/ui/src/components/SourceCard/index.js @@ -0,0 +1 @@ +export { default } from './SourceCard.svelte'; diff --git a/ui/src/lib/SourceCoverage.svelte b/ui/src/components/SourceCoverage/SourceCoverage.svelte similarity index 88% rename from ui/src/lib/SourceCoverage.svelte rename to ui/src/components/SourceCoverage/SourceCoverage.svelte index 93e2a86..6ce3cc8 100644 --- a/ui/src/lib/SourceCoverage.svelte +++ b/ui/src/components/SourceCoverage/SourceCoverage.svelte @@ -1,4 +1,5 @@ + +
                                                                          + Sources ({sources.length}) + {#if sources.length === 0} +

                                                                          No sources registered.

                                                                          + {:else} + {#each sources as source (source.scope)} + + {/each} + {/if} +
                                                                          diff --git a/ui/src/components/SourceList/index.js b/ui/src/components/SourceList/index.js new file mode 100644 index 0000000..e328c96 --- /dev/null +++ b/ui/src/components/SourceList/index.js @@ -0,0 +1 @@ +export { default } from './SourceList.svelte'; diff --git a/ui/src/components/TechnicalDetails/TechnicalDetails.svelte b/ui/src/components/TechnicalDetails/TechnicalDetails.svelte new file mode 100644 index 0000000..51f533c --- /dev/null +++ b/ui/src/components/TechnicalDetails/TechnicalDetails.svelte @@ -0,0 +1,36 @@ + + +
                                                                          + Technical details Tool calls, accounting and provenance +

                                                                          Executed tool steps

                                                                          + {#if traces?.length}
                                                                            {#each traces as step (step.step)}{/each}
                                                                          {:else}

                                                                          No agent trace is available for this briefing.

                                                                          {/if} + {#if inputTokens != null || outputTokens != null || costUsd != null} +

                                                                          Model accounting

                                                                          {inputTokens ?? 'Unknown'} input tokens · {outputTokens ?? 'Unknown'} output tokens · {costUsd == null ? 'Cost unknown' : `$${costUsd}`}

                                                                          + {/if} +

                                                                          Provenance

                                                                          +
                                                                          Briefing
                                                                          {briefingId}
                                                                          Group
                                                                          {groupId}
                                                                          +
                                                                          Grouping version
                                                                          {groupingVersion}
                                                                          Sequence
                                                                          {seq}
                                                                          +
                                                                          Created
                                                                          +
                                                                          Grouping anchor
                                                                          {host}
                                                                          +
                                                                          +
                                                                          +
                                                                          diff --git a/ui/src/components/TechnicalDetails/index.js b/ui/src/components/TechnicalDetails/index.js new file mode 100644 index 0000000..86ad10d --- /dev/null +++ b/ui/src/components/TechnicalDetails/index.js @@ -0,0 +1 @@ +export { default } from './TechnicalDetails.svelte'; diff --git a/ui/src/components/TimeStamp/TimeStamp.svelte b/ui/src/components/TimeStamp/TimeStamp.svelte new file mode 100644 index 0000000..2f93042 --- /dev/null +++ b/ui/src/components/TimeStamp/TimeStamp.svelte @@ -0,0 +1,10 @@ + + + diff --git a/ui/src/components/TimeStamp/index.js b/ui/src/components/TimeStamp/index.js new file mode 100644 index 0000000..a0074d4 --- /dev/null +++ b/ui/src/components/TimeStamp/index.js @@ -0,0 +1 @@ +export { default } from './TimeStamp.svelte'; diff --git a/ui/src/components/TraceStep/TraceStep.module.css b/ui/src/components/TraceStep/TraceStep.module.css new file mode 100644 index 0000000..68a0cbb --- /dev/null +++ b/ui/src/components/TraceStep/TraceStep.module.css @@ -0,0 +1,15 @@ +.step { + list-style: none; + border-top: 1px solid var(--border); + padding: 12px 0; +} + +.toolName { + font-family: ui-monospace, SFMono-Regular, Menlo, monospace; + font-size: 12px; + font-weight: 600; +} + +.step p { + margin: 8px 0; +} diff --git a/ui/src/lib/TraceStep.svelte b/ui/src/components/TraceStep/TraceStep.svelte similarity index 71% rename from ui/src/lib/TraceStep.svelte rename to ui/src/components/TraceStep/TraceStep.svelte index 90ff04a..e406d8b 100644 --- a/ui/src/lib/TraceStep.svelte +++ b/ui/src/components/TraceStep/TraceStep.svelte @@ -1,4 +1,6 @@ -
                                                                        • - {step.tool} - {#if step.outcome}{step.outcome.replaceAll('_', ' ')}{/if} +
                                                                        • + {step.tool} + {#if step.outcome}{step.outcome.replaceAll('_', ' ')}{/if} step {step.step} · {step.status} · {step.duration_ms} ms

                                                                          {headline}

                                                                          @@ -31,18 +33,3 @@
                                                                        • - diff --git a/ui/src/components/TraceStep/index.js b/ui/src/components/TraceStep/index.js new file mode 100644 index 0000000..52e3e71 --- /dev/null +++ b/ui/src/components/TraceStep/index.js @@ -0,0 +1 @@ +export { default } from './TraceStep.svelte'; diff --git a/ui/src/components/VerdictHeader/VerdictHeader.module.css b/ui/src/components/VerdictHeader/VerdictHeader.module.css new file mode 100644 index 0000000..eebdec5 --- /dev/null +++ b/ui/src/components/VerdictHeader/VerdictHeader.module.css @@ -0,0 +1,8 @@ +.list { + list-style: none; + display: flex; + flex-wrap: wrap; + gap: 8px; + padding: 0; + margin: 0 0 12px; +} diff --git a/ui/src/lib/VerdictHeader.svelte b/ui/src/components/VerdictHeader/VerdictHeader.svelte similarity index 79% rename from ui/src/lib/VerdictHeader.svelte rename to ui/src/components/VerdictHeader/VerdictHeader.svelte index 1cf10a4..4d5620b 100644 --- a/ui/src/lib/VerdictHeader.svelte +++ b/ui/src/components/VerdictHeader/VerdictHeader.svelte @@ -1,5 +1,7 @@ + +{#if notice !== null && shown === null} +
                                                                          +

                                                                          Briefing unavailable

                                                                          +

                                                                          The bridge did not return this briefing ({notice}).

                                                                          + +
                                                                          +{:else if shown === null} + Loading briefing… +{:else} +
                                                                          + {#if layout === 'page'}

                                                                          ← Back to Home

                                                                          {/if} + {#if notice !== null} + The saved view could not be refreshed. Your last loaded report is still shown. + {/if} + +
                                                                          + + + + + + + + + + + + + 0} + context={shown.context} + receipts={receipts} + evidenceRefs={shown.evidence_refs} + profiles={shown.profiles} + profilesTruncated={shown.profiles_truncated} + onJump={jumpTo} + /> + + +
                                                                          +
                                                                          +{/if} diff --git a/ui/src/containers/BriefingContainer/index.js b/ui/src/containers/BriefingContainer/index.js new file mode 100644 index 0000000..3365d9d --- /dev/null +++ b/ui/src/containers/BriefingContainer/index.js @@ -0,0 +1 @@ +export { default } from './BriefingContainer.svelte'; diff --git a/ui/src/containers/DecisionsContainer/DecisionsContainer.module.css b/ui/src/containers/DecisionsContainer/DecisionsContainer.module.css new file mode 100644 index 0000000..f710152 --- /dev/null +++ b/ui/src/containers/DecisionsContainer/DecisionsContainer.module.css @@ -0,0 +1,7 @@ +.card { + padding: 26px; + background: var(--surface); + border: 1px solid var(--border); + border-radius: 16px; + overflow-wrap: anywhere; +} diff --git a/ui/src/containers/DecisionsContainer/DecisionsContainer.svelte b/ui/src/containers/DecisionsContainer/DecisionsContainer.svelte new file mode 100644 index 0000000..93f773a --- /dev/null +++ b/ui/src/containers/DecisionsContainer/DecisionsContainer.svelte @@ -0,0 +1,293 @@ + + +
                                                                          + + + {#if memberReview !== null} + + {/if} + 0} + {note} + {listError} + {paging} + {undoPending} + {card} + onUndo={undo} + onOlder={older} + onNewer={newer} + /> +
                                                                          diff --git a/ui/src/containers/DecisionsContainer/index.js b/ui/src/containers/DecisionsContainer/index.js new file mode 100644 index 0000000..8598db5 --- /dev/null +++ b/ui/src/containers/DecisionsContainer/index.js @@ -0,0 +1 @@ +export { default } from './DecisionsContainer.svelte'; diff --git a/ui/src/containers/DeviceContainer/DeviceContainer.svelte b/ui/src/containers/DeviceContainer/DeviceContainer.svelte new file mode 100644 index 0000000..79874f0 --- /dev/null +++ b/ui/src/containers/DeviceContainer/DeviceContainer.svelte @@ -0,0 +1,127 @@ + + +{#if $error !== null && profile === null} +
                                                                          +

                                                                          Reported host unavailable

                                                                          +

                                                                          The bridge did not return this profile ({$error}).

                                                                          +

                                                                          Back to reported hosts

                                                                          +
                                                                          +{:else if profile === null} + Loading reported host… +{:else} +
                                                                          +

                                                                          Back to reported hosts

                                                                          + {#if stale} + Connection recovered — this page may miss new reports. + {/if} + {#if notice !== null} + Refresh failed ({notice}) — showing retained data. + {/if} + + + + +
                                                                          +{/if} diff --git a/ui/src/containers/DeviceContainer/index.js b/ui/src/containers/DeviceContainer/index.js new file mode 100644 index 0000000..de9b3a1 --- /dev/null +++ b/ui/src/containers/DeviceContainer/index.js @@ -0,0 +1 @@ +export { default } from './DeviceContainer.svelte'; diff --git a/ui/src/containers/DevicesContainer/DevicesContainer.svelte b/ui/src/containers/DevicesContainer/DevicesContainer.svelte new file mode 100644 index 0000000..82210f3 --- /dev/null +++ b/ui/src/containers/DevicesContainer/DevicesContainer.svelte @@ -0,0 +1,105 @@ + + +
                                                                          +

                                                                          Reported hosts

                                                                          +

                                                                          Scanner-reported subjects. Classes distinguish device references, address context, unresolved events and legacy profiles.

                                                                          + {#if loading} + Loading reported hosts… + {:else if $error !== null && empty} + The bridge did not return reported hosts ({$error}). + + {:else} + + {/if} +
                                                                          diff --git a/ui/src/containers/DevicesContainer/index.js b/ui/src/containers/DevicesContainer/index.js new file mode 100644 index 0000000..2412d16 --- /dev/null +++ b/ui/src/containers/DevicesContainer/index.js @@ -0,0 +1 @@ +export { default } from './DevicesContainer.svelte'; diff --git a/ui/src/containers/HealthContainer/HealthContainer.svelte b/ui/src/containers/HealthContainer/HealthContainer.svelte new file mode 100644 index 0000000..60af62e --- /dev/null +++ b/ui/src/containers/HealthContainer/HealthContainer.svelte @@ -0,0 +1,78 @@ + + +
                                                                          +

                                                                          Health

                                                                          +

                                                                          Source coverage, processing, and retention. Liveness describes the source, not host presence.

                                                                          + {#if $error !== null && shown === null} + The bridge did not return health ({$error}). + + {:else if shown === null} + Loading health… + {:else} + resource.refresh()} /> + + + + {#if shown.publisher} + + {/if} + {/if} +
                                                                          diff --git a/ui/src/containers/HealthContainer/index.js b/ui/src/containers/HealthContainer/index.js new file mode 100644 index 0000000..57056b5 --- /dev/null +++ b/ui/src/containers/HealthContainer/index.js @@ -0,0 +1 @@ +export { default } from './HealthContainer.svelte'; diff --git a/ui/src/lib/Home.svelte b/ui/src/containers/HomeContainer/HomeContainer.svelte similarity index 69% rename from ui/src/lib/Home.svelte rename to ui/src/containers/HomeContainer/HomeContainer.svelte index 8774a32..f09ae41 100644 --- a/ui/src/lib/Home.svelte +++ b/ui/src/containers/HomeContainer/HomeContainer.svelte @@ -1,19 +1,24 @@ + +

                                                                          Back to overview

                                                                          + +{#if notice !== null} + Refresh failed: {notice} +{/if} +{#if shown === null} +

                                                                          Loading incident…

                                                                          +{:else} + {@const inc = shown.incident} + + + + {#if shown.summary} + + {/if} + + +{/if} diff --git a/ui/src/containers/IncidentContainer/index.js b/ui/src/containers/IncidentContainer/index.js new file mode 100644 index 0000000..b06203d --- /dev/null +++ b/ui/src/containers/IncidentContainer/index.js @@ -0,0 +1 @@ +export { default } from './IncidentContainer.svelte'; diff --git a/ui/src/containers/IncidentMembersContainer/IncidentMembersContainer.svelte b/ui/src/containers/IncidentMembersContainer/IncidentMembersContainer.svelte new file mode 100644 index 0000000..7388fbd --- /dev/null +++ b/ui/src/containers/IncidentMembersContainer/IncidentMembersContainer.svelte @@ -0,0 +1,109 @@ + + +{#if expanded} + {#if loading && members === undefined} + Loading members… + {:else if loadError !== undefined} + {loadError} + {:else if members !== undefined} +
                                                                            + {#each members as m (m.briefing_id)} +
                                                                          1. + {m.briefing_id} + {m.priority} +
                                                                          2. + {/each} +
                                                                          + {/if} +{/if} diff --git a/ui/src/containers/IncidentMembersContainer/index.js b/ui/src/containers/IncidentMembersContainer/index.js new file mode 100644 index 0000000..a316e8e --- /dev/null +++ b/ui/src/containers/IncidentMembersContainer/index.js @@ -0,0 +1 @@ +export { default } from './IncidentMembersContainer.svelte'; diff --git a/ui/src/lib/AttentionList.svelte b/ui/src/lib/AttentionList.svelte deleted file mode 100644 index 5d1c3f1..0000000 --- a/ui/src/lib/AttentionList.svelte +++ /dev/null @@ -1,121 +0,0 @@ - - -
                                                                          -

                                                                          Needs attention ({items.length})

                                                                          - {#if items.length === 0} -

                                                                          Nothing flagged. New briefings appear here when the bridge reports them.

                                                                          - {:else} -
                                                                            - {#each items as item (item.id)} -
                                                                          1. - {#snippet row()} - {item.priority} - {item.kind === 'incident' ? 'Incident · ' : ''}{item.kind === 'briefing' ? (titles[item.id] ?? reviewTitle(item.change_kind)) : changeLabel(item.change_kind)}{item.id} - {item.status} - {/snippet} - {#if item.kind === 'briefing' || item.kind === 'incident'} - {#if onselect} - - {:else} - {@render row()} - {/if} - {:else} -
                                                                            {@render row()}
                                                                            - {/if} - {#if item.kind === 'incident'} - - {#if expandError[item.id] !== undefined} -

                                                                            {expandError[item.id]}

                                                                            - {/if} - {#if (expanded[item.id] ?? false) && memberCache[item.id] !== undefined} -
                                                                              - {#each memberCache[item.id] as m (m.briefing_id)} -
                                                                            1. - {m.briefing_id} - {m.priority} -
                                                                            2. - {/each} -
                                                                            - {/if} - {/if} -
                                                                          2. - {/each} -
                                                                          - {/if} -
                                                                          diff --git a/ui/src/lib/DecisionPanel.svelte b/ui/src/lib/DecisionPanel.svelte deleted file mode 100644 index 624bba4..0000000 --- a/ui/src/lib/DecisionPanel.svelte +++ /dev/null @@ -1,445 +0,0 @@ - - -
                                                                          -

                                                                          {requireChoice ? 'Your decision' : 'Operator decisions'}

                                                                          -

                                                                          Status: {statusLine()}

                                                                          - -
                                                                          -
                                                                          - Choose a decision - {#each kinds as k (k)} - - {/each} -
                                                                          -

                                                                          {kind === null ? 'Choose a verdict to record it.' : (kindHelp[kind] ?? KIND_HELP[kind] ?? '')}

                                                                          - {#if memberScope} - - {/if} - {#if outcomeNote !== null} -

                                                                          {outcomeNote}

                                                                          - {/if} - {#if kind === 'snooze'} - - {/if} - {#if needsText} - - {/if} - {#if formError !== null} -

                                                                          {formError}

                                                                          - {/if} - -
                                                                          - - {#if memberReview !== null} -

                                                                          {memberUndoNote(memberReview)}

                                                                          - {#if memberReview.members.length > 0} -
                                                                            - {#each memberReview.members as m (m.decision_id)} -
                                                                          • {m.subject_id} — {m.kind.replace('_', ' ')}
                                                                          • - {/each} -
                                                                          - {/if} - {#if memberReview.next} - - {/if} - {#if memberError !== null}

                                                                          {memberError}

                                                                          {/if} - {/if} - - {#if requireChoice}

                                                                          Recorded decisions

                                                                          {/if} - {#if trail.length === 0} -

                                                                          No decisions recorded.

                                                                          - {:else} -
                                                                            - {#each trail as d (d.decision_id)} -
                                                                          1. - {d.kind.replace('_', ' ')} - {#if d.undone}undone{/if} - {#if d.text}{d.text}{/if} - {#if d.until}until {d.until}{/if} - - {#if !d.undone && d.kind !== 'undo'} - - {/if} -
                                                                          2. - {/each} -
                                                                          - {#if !exhausted} - - {/if} - {#if extraKey === headKey && extra.length > 0} - - {/if} - {#if note !== null} -

                                                                          {note}

                                                                          - {/if} - {/if} - {#if listError !== null} -

                                                                          {listError}

                                                                          - {/if} -
                                                                          - - diff --git a/ui/src/lib/Detail.svelte b/ui/src/lib/Detail.svelte deleted file mode 100644 index f2deeb9..0000000 --- a/ui/src/lib/Detail.svelte +++ /dev/null @@ -1,353 +0,0 @@ - - -{#if error !== null && shown === null} -
                                                                          -

                                                                          Briefing unavailable

                                                                          -

                                                                          The bridge did not return this briefing ({error}).

                                                                          - -
                                                                          -{:else if shown === null} -

                                                                          Loading briefing…

                                                                          -{:else} -
                                                                          - {#if !embedded}

                                                                          ← Back to Home

                                                                          {/if} - {#if error !== null} -

                                                                          The saved view could not be refreshed. Your last loaded report is still shown.

                                                                          - {/if} - -
                                                                          -
                                                                          -
                                                                          -

                                                                          {title}

                                                                          - {shown.priority} priority -
                                                                          -

                                                                          {shown.what_changed}

                                                                          -
                                                                          - {#if identity !== null && identityComplete} -
                                                                          Reported host
                                                                          {identity.hostname ?? 'Not reported'}
                                                                          -
                                                                          IP address
                                                                          {identity.ip ?? 'Not reported'}{#if identity.ip !== null}{/if}
                                                                          -
                                                                          MAC address
                                                                          {identity.mac ?? 'Not reported'}{#if identity.mac !== null}{/if}
                                                                          - {:else} -
                                                                          Reported identities
                                                                          See the individual report views below

                                                                          {identityComplete ? 'Grouped changes can describe different host views.' : 'Only part of the retained evidence is shown.'}

                                                                          - {/if} -
                                                                          Reported scan target
                                                                          {primaryEvent?.target || (shown.referenced_events.length > 1 ? 'Shown per report below' : 'Not reported')}{#if primaryEvent?.target_truncated} (truncated){/if}
                                                                          -
                                                                          {range?.partial || shown.referenced_truncated ? 'Available report times' : shown.referenced_events.length > 1 ? 'Report time range' : 'Report time'}
                                                                          {#if range !== null}{range.local}{:else}Not reported{/if}
                                                                          -
                                                                          Analysis source
                                                                          {sourceLabel(shown.source)}
                                                                          -
                                                                          -
                                                                          - {shown.referenced_events.length}{shown.referenced_truncated ? '+' : ''} source report{shown.referenced_events.length === 1 ? '' : 's'} - {#if primaryEvent} - - {:else if shown.referenced_events.length > 0} - - {/if} -
                                                                          -
                                                                          - -

                                                                          Reported at the time shown. Network conditions may have changed since this report.

                                                                          - - - - - -
                                                                          -

                                                                          Why this priority

                                                                          -

                                                                          {shown.priority_reason}

                                                                          -
                                                                          Final priority: {shown.priority}{#if shown.baseline_rule}{shown.baseline_rule}{/if}
                                                                          -
                                                                          - How the priority was computed -
                                                                            -
                                                                          1. Baseline floor {shown.baseline}
                                                                          2. -
                                                                          3. Model suggestion {shown.model_suggestion ?? 'No model suggestion — baseline stands'}
                                                                          4. -
                                                                          5. Final priority {shown.priority}
                                                                          6. -
                                                                          - {#if shown.clamped}

                                                                          Suggestion adjusted to respect the baseline floor and one-step raise limit.

                                                                          {/if} -
                                                                          - {#if shown.fallback_used}

                                                                          Deterministic fallback text: the model path did not produce this briefing.

                                                                          {/if} -
                                                                          - -
                                                                          -

                                                                          Scanner snapshot{shown.referenced_events.length === 1 ? '' : 's'}

                                                                          Saved at report time
                                                                          -

                                                                          Open a report to see what the scanner supplied, with its linked context.

                                                                          - {#if shown.referenced_events.length === 0}

                                                                          No referenced events retained.

                                                                          - {:else}{#each shown.referenced_events as ref (ref.event_id)}{/each}{/if} - {#if shown.referenced_truncated}

                                                                          More referenced events exist than shown.

                                                                          {/if} - {#if shown.observations_truncated}

                                                                          More observations exist than shown; some saved views are omitted.

                                                                          {/if} -
                                                                          - -
                                                                          -

                                                                          {shown.source === 'agent' ? 'Investigator notes' : 'Analysis and retained context'}

                                                                          - {#if shown.likely_explanation}

                                                                          Possible explanation: {shown.likely_explanation}

                                                                          {/if} - {#if shown.confidence}

                                                                          Explanation confidence (model self-assessment): {shown.confidence}

                                                                          {/if} - {#if lookupLimits.length > 0}

                                                                          Investigation has limits. Some lookups could not establish retained context. Missing lookup results do not prove this host has no history.

                                                                          {/if} -

                                                                          {shown.context}

                                                                          - {#if shown.traces?.length} -

                                                                          What the investigator could establish

                                                                          -
                                                                            - {#each lookupReceipts as receipt, i (i)} -
                                                                          • {receipt.summary || 'No interpreted result is available. Open the tool step to inspect the saved response.'}

                                                                            {#each receipt.steps as step (step)}{/each}
                                                                          • - {/each} -
                                                                          - {/if} - {#if shown.evidence_refs?.length} -
                                                                          Cited evidence - {#each shown.evidence_refs as ref, i (`${ref.event_id ?? ref.tool_step}:${i}`)} - - {/each} -
                                                                          - {/if} - {#if shown.profiles.length > 0} - - {:else}

                                                                          No profile links persisted for this briefing.

                                                                          {/if} - {#if shown.profiles_truncated}

                                                                          More profile links exist than shown.

                                                                          {/if} -
                                                                          - -
                                                                          - Technical details Tool calls, accounting and provenance -

                                                                          Executed tool steps

                                                                          - {#if shown.traces?.length}
                                                                            {#each shown.traces as step (step.step)}{/each}
                                                                          {:else}

                                                                          No agent trace is available for this briefing.

                                                                          {/if} - {#if shown.input_tokens != null || shown.output_tokens != null || shown.cost_usd != null} -

                                                                          Model accounting

                                                                          {shown.input_tokens ?? 'Unknown'} input tokens · {shown.output_tokens ?? 'Unknown'} output tokens · {shown.cost_usd == null ? 'Cost unknown' : `$${shown.cost_usd}`}

                                                                          - {/if} -

                                                                          Provenance

                                                                          -
                                                                          Briefing
                                                                          {shown.briefing_id}
                                                                          Group
                                                                          {shown.group_id}
                                                                          -
                                                                          Grouping version
                                                                          {shown.grouping_version}
                                                                          Sequence
                                                                          {shown.seq}
                                                                          -
                                                                          Created
                                                                          -
                                                                          Grouping anchor
                                                                          {shown.host}
                                                                          -
                                                                          -
                                                                          -
                                                                          -
                                                                          -
                                                                          -{/if} - - diff --git a/ui/src/lib/Device.svelte b/ui/src/lib/Device.svelte deleted file mode 100644 index afc786d..0000000 --- a/ui/src/lib/Device.svelte +++ /dev/null @@ -1,215 +0,0 @@ - - -{#if error !== null && profile === null} -
                                                                          -

                                                                          Reported host unavailable

                                                                          -

                                                                          The bridge did not return this profile ({error}).

                                                                          -

                                                                          Back to reported hosts

                                                                          -
                                                                          -{:else if profile === null} -

                                                                          Loading reported host…

                                                                          -{:else} - {@const latestTime = profile.latest === null ? null : displayTime(profile.latest.reported_at)} -
                                                                          -

                                                                          Back to reported hosts

                                                                          - {#if stale} -

                                                                          Connection recovered — this page may miss new reports.

                                                                          - {/if} - {#if refreshError !== null} -

                                                                          Refresh failed ({refreshError}) — showing retained data.

                                                                          - {/if} -

                                                                          {profile.profile_id} — {classLabel(profile.class)}

                                                                          - {#if profile.class === 'legacy'} -

                                                                          Earlier bridge-inferred association; not used for current identity.

                                                                          - {:else if profile.class === 'address' || profile.class === 'event'} -

                                                                          This page describes {profile.class === 'address' ? 'address context' : 'unresolved events'}, not a device.

                                                                          - {/if} -
                                                                          -
                                                                          Source scope
                                                                          -
                                                                          {profile.source_scope}
                                                                          -
                                                                          Upstream reference
                                                                          -
                                                                          {profile.reported_id}
                                                                          -
                                                                          Reported by
                                                                          -
                                                                          {profile.reported_source} (confidence: {profile.reported_confidence || 'unknown'})
                                                                          -
                                                                          Association
                                                                          -
                                                                          {profile.association_status}
                                                                          - {#if profile.operator_label !== null && profile.operator_label !== undefined} -
                                                                          Your label
                                                                          -
                                                                          {profile.operator_label}
                                                                          - {/if} -
                                                                          First report
                                                                          -
                                                                          -
                                                                          Last report
                                                                          -
                                                                          -
                                                                          - - - -
                                                                          -

                                                                          Latest evidence

                                                                          - {#if profile.latest === null} -

                                                                          No retained observation.

                                                                          - {:else} -

                                                                          Reported ({profile.latest.view_role}).

                                                                          -
                                                                          - {#each Object.entries(profile.latest.attributes ?? {}) as [key, value] (key)} -
                                                                          {key}
                                                                          -
                                                                          {JSON.stringify(value)}
                                                                          - {/each} -
                                                                          - {#if (profile.latest.ports ?? []).length > 0} -
                                                                            - {#each profile.latest.ports as port (`${port.proto}/${port.port}`)} -
                                                                          • {port.proto}/{port.port} {port.state}{port.service ? ` (${port.service})` : ''}
                                                                          • - {/each} -
                                                                          - {/if} -

                                                                          Snapshot covers {profile.latest.ports_total} ports{profile.latest.ports_truncated ? ' (truncated)' : ''}.

                                                                          - {/if} -
                                                                          - -
                                                                          -

                                                                          History

                                                                          - {#if history.length === 0} -

                                                                          No retained reports in this window.

                                                                          - {:else} -
                                                                            - {#each history as obs (obs.observation_id)} - {@const at = displayTime(obs.reported_at)} -
                                                                          1. - {obs.event_id} ({obs.view_role}) — - , - {obs.ports_total} ports{obs.ports_truncated ? ' (truncated)' : ''} -
                                                                          2. - {/each} -
                                                                          - {/if} - {#if historyError !== null} -

                                                                          Older page failed ({historyError}).

                                                                          - {/if} - {#if historyCapped} -

                                                                          History capped at {HISTORY_CAP} rows; use the API for the full set.

                                                                          - {:else if !historyExhausted} - - {:else} -

                                                                          End of retained history. Retention policy lives on the Health screen.

                                                                          - {/if} -
                                                                          -
                                                                          -{/if} diff --git a/ui/src/lib/Devices.svelte b/ui/src/lib/Devices.svelte deleted file mode 100644 index 1f2344d..0000000 --- a/ui/src/lib/Devices.svelte +++ /dev/null @@ -1,146 +0,0 @@ - - -
                                                                          -

                                                                          Reported hosts

                                                                          -

                                                                          Scanner-reported subjects. Classes distinguish device references, address context, unresolved events and legacy profiles.

                                                                          - {#if loading && devices.length === 0} -

                                                                          Loading reported hosts…

                                                                          - {:else if error !== null && devices.length === 0} -

                                                                          The bridge did not return reported hosts ({error}).

                                                                          - - {:else} - {#if stale} -

                                                                          Connection recovered — this list may miss new reports.

                                                                          - {/if} - {#if devices.length === 0} -

                                                                          No reported subjects retained.

                                                                          - {:else} - - {/if} - {#if error !== null} -

                                                                          Page failed ({error}) — earlier rows kept.

                                                                          - {/if} - {#if capped} -

                                                                          List capped at {ROW_CAP} rows; use the API for the full set.

                                                                          - {:else if !exhausted} - - {:else} -

                                                                          End of retained list.

                                                                          - {/if} - {/if} -
                                                                          diff --git a/ui/src/lib/Health.svelte b/ui/src/lib/Health.svelte deleted file mode 100644 index 30b5b02..0000000 --- a/ui/src/lib/Health.svelte +++ /dev/null @@ -1,225 +0,0 @@ - - -
                                                                          -

                                                                          Health

                                                                          -

                                                                          Source coverage, processing, and retention. Liveness describes the source, not host presence.

                                                                          - {#if error !== null && shown === null} -

                                                                          The bridge did not return health ({error}).

                                                                          - - {:else if shown === null} -

                                                                          Loading health…

                                                                          - {:else} -
                                                                          -

                                                                          Summary

                                                                          -
                                                                          -
                                                                          Coverage
                                                                          {shown.coverage}
                                                                          -
                                                                          Fallback briefings · 1h
                                                                          {shown.fallback_1h.used} of {shown.fallback_1h.total}
                                                                          -
                                                                          Awaiting operator
                                                                          {shown.parked_groups}
                                                                          -
                                                                          Forward errors · 1h
                                                                          {shown.forward_errors_1h}
                                                                          -
                                                                          Ingest queue
                                                                          {shown.queue_depth} of {shown.queue_cap}
                                                                          -
                                                                          - {#if (shown.coverage_reasons ?? []).length > 0} -
                                                                            - {#each shown.coverage_reasons as reason (reason)} -
                                                                          • {reason}
                                                                          • - {/each} -
                                                                          - {/if} - {#if latestRunNeedsAttention(shown.purge.last)} - {@const finished = displayTime(shown.purge.last.finished_at ?? shown.purge.last.started_at)} -

                                                                          - Latest purge run {shown.purge.last.status} - ({finished.local}){shown.purge.last.error ? `: ${shown.purge.last.error}` : ''}. -

                                                                          - {/if} - {#if refreshError !== null} -

                                                                          Refresh failed ({refreshError}) — showing retained data.

                                                                          - {/if} -
                                                                          - -
                                                                          - Sources ({shown.sources.length}) - {#if shown.sources.length === 0} -

                                                                          No sources registered.

                                                                          - {:else} - {#each shown.sources as src (src.scope)} -
                                                                          -

                                                                          {src.scope} — {src.status}

                                                                          -
                                                                          -
                                                                          Liveness
                                                                          -
                                                                          {src.liveness}{src.liveness === 'unknown' ? ' (no heartbeat capability; silence is not absence)' : ''}
                                                                          -
                                                                          Identity namespace
                                                                          -
                                                                          {src.identity_namespace || 'unknown — stable identity contract unavailable'}
                                                                          -
                                                                          Identity capability
                                                                          -
                                                                          {src.capabilities || 'not reported — heartbeat is not identity proof'}
                                                                          -
                                                                          Heartbeat
                                                                          -
                                                                          - {src.heartbeat_enabled ? 'enabled (delivery opt-in, not identity proof)' : 'disabled'} - {#if src.last_heartbeat_at}— last at {displayTime(src.last_heartbeat_at).local}{/if} -
                                                                          - {#if src.heartbeat} - {@const scan = displayTime(src.heartbeat.completed_at)} -
                                                                          Last completed scan
                                                                          -
                                                                          -
                                                                          Scan result
                                                                          -
                                                                          {src.heartbeat.status}, {src.heartbeat.issue_count} {src.heartbeat.issue_count === 1 ? 'issue' : 'issues'}, {src.heartbeat.duration_ms} ms
                                                                          -
                                                                          Reported host records
                                                                          -
                                                                          {src.heartbeat.hosts_seen} — scan records, not a current inventory or device count
                                                                          -
                                                                          Signing clock offset
                                                                          -
                                                                          {src.heartbeat.clock_skew_seconds} seconds (includes delivery delay)
                                                                          - {/if} - {#if src.last_report_at} - {@const at = displayTime(src.last_report_at)} -
                                                                          Last report
                                                                          -
                                                                          - {/if} - {#if src.delivery_status} -
                                                                          Delivery
                                                                          -
                                                                          {src.delivery_status}
                                                                          - {/if} -
                                                                          - {#if (src.reasons ?? []).length > 0} -
                                                                            - {#each src.reasons as reason (reason)} -
                                                                          • {reason}
                                                                          • - {/each} -
                                                                          - {/if} -
                                                                          - {/each} - {/if} -
                                                                          - -
                                                                          - Pipeline (process lifetime) -
                                                                          -
                                                                          Started
                                                                          -
                                                                          {displayTime(shown.process.started_at).local}
                                                                          -
                                                                          Ingest accepted
                                                                          -
                                                                          {shown.process.ingest_accepted}
                                                                          -
                                                                          Ingest duplicates
                                                                          -
                                                                          {shown.process.ingest_duplicates}
                                                                          -
                                                                          Ingest rejected
                                                                          -
                                                                          {shown.process.ingest_rejected}
                                                                          -
                                                                          Ingest saturated
                                                                          -
                                                                          {shown.process.ingest_saturated}
                                                                          -
                                                                          Provider calls
                                                                          -
                                                                          {shown.process.provider_calls}
                                                                          -
                                                                          Provider fallbacks
                                                                          -
                                                                          {shown.process.provider_fallbacks}
                                                                          -
                                                                          Redaction blocked
                                                                          -
                                                                          {shown.process.redaction_blocked}
                                                                          -
                                                                          Writer saturated
                                                                          -
                                                                          {shown.process.writer_saturated}
                                                                          -
                                                                          -
                                                                          - -
                                                                          - Purge -
                                                                          - {#each Object.entries(shown.purge.totals ?? {}) as [table, count] (table)} -
                                                                          {table}
                                                                          -
                                                                          {count}
                                                                          - {/each} -
                                                                          - {#if shown.retention} -

                                                                          - Configured retention: {days(shown.retention.reports_seconds)} for reports{#if shown.retention.subjects_seconds !== undefined}, {days(shown.retention.subjects_seconds)} for subjects{/if}; - policy only — it never proves a per-profile boundary. Ask the API for per-profile history. -

                                                                          - {/if} - {#if shown.purge.last_success} - {@const ok = displayTime(shown.purge.last_success.finished_at ?? shown.purge.last_success.started_at)} -

                                                                          Latest fully successful purge: {ok.local}.

                                                                          - {:else} -

                                                                          No fully successful purge recorded yet.

                                                                          - {/if} -
                                                                          - - {#if shown.publisher} -
                                                                          - Publisher -
                                                                          -
                                                                          Posted
                                                                          -
                                                                          {shown.publisher.posted}
                                                                          -
                                                                          Dropped
                                                                          -
                                                                          {shown.publisher.dropped}
                                                                          -
                                                                          Failed
                                                                          -
                                                                          {shown.publisher.failed}
                                                                          -
                                                                          -
                                                                          - {/if} - {/if} -
                                                                          diff --git a/ui/src/lib/Incident.svelte b/ui/src/lib/Incident.svelte deleted file mode 100644 index de0785f..0000000 --- a/ui/src/lib/Incident.svelte +++ /dev/null @@ -1,170 +0,0 @@ - - -

                                                                          Back to overview

                                                                          - -{#if error !== null} -

                                                                          Refresh failed: {error}

                                                                          -{/if} -{#if shown === null} -

                                                                          Loading incident…

                                                                          -{:else} - {@const inc = shown.incident} - {@const opened = displayTime(inc.opened_at)} - {@const closed = displayTime(inc.closed_at)} - {@const start = displayTime(inc.window_start)} - {@const last = displayTime(inc.last_member_at)} -

                                                                          {KIND_LABEL[inc.kind] ?? inc.kind}

                                                                          -

                                                                          - {inc.status} - Floor: {inc.floor} - {#if inc.status === 'closed' && inc.closed_at} - Closed - {:else} - Open since - {/if} -

                                                                          - -
                                                                          -

                                                                          Scope

                                                                          -

                                                                          Source: {inc.source_scope}

                                                                          -

                                                                          Target: {inc.target}

                                                                          -

                                                                          Window start: · Last member:

                                                                          -
                                                                          - -
                                                                          -

                                                                          Evidence

                                                                          -

                                                                          {countLine(inc)}

                                                                          - {#if inc.qualified_refs < inc.member_count} -

                                                                          Some members share identity evidence; only distinct qualified references count toward the burst threshold.

                                                                          - {/if} - {#if shown.truncated} -

                                                                          More members exist than shown.

                                                                          - {/if} - {#if shown.members.length === 0} -

                                                                          No member evidence retained.

                                                                          - {:else} -
                                                                            - {#each shown.members as m (m.briefing_id)} - {@const reported = displayTime(m.created_at)} -
                                                                          1. - {m.briefing_id} - {m.priority} - - {m.refs.length} qualified reference{m.refs.length === 1 ? '' : 's'} -
                                                                          2. - {/each} -
                                                                          - {/if} -
                                                                          - - {#if shown.summary} - {@const summary = shown.summary} -
                                                                          -

                                                                          Summary

                                                                          -

                                                                          Summary status: {summary.status}

                                                                          - {#if summary.summary}

                                                                          {summary.summary}

                                                                          {/if} - {#if summary.hypothesis}

                                                                          Hypothesis: {summary.hypothesis}

                                                                          {/if} - {#if summary.confidence}

                                                                          Display confidence: {summary.confidence}

                                                                          {/if} -

                                                                          Priority floor: {summary.floor}. Resolved priority: {summary.final_priority}{summary.suggestion ? ` (suggested ${summary.suggestion}${summary.clamped ? ', clamped' : ''})` : ' (no model raise)'}

                                                                          - {#if summary.reason}

                                                                          Priority explanation: {summary.reason}

                                                                          {/if} -

                                                                          Evidence coverage: {summary.sampled} sampled member reports; {summary.omitted} omitted. The sample may not represent every member.

                                                                          - {#if summary.citations.length} -

                                                                          Cited reports:

                                                                          - - {/if} - {#if summary.error}

                                                                          {summary.error}

                                                                          {/if} -
                                                                          - {/if} - - -{/if} diff --git a/ui/src/lib/ReportView.svelte b/ui/src/lib/ReportView.svelte deleted file mode 100644 index 86052d4..0000000 --- a/ui/src/lib/ReportView.svelte +++ /dev/null @@ -1,65 +0,0 @@ - - -
                                                                          - - {ref.event_id}{ref.event_type} - Reported - -
                                                                          -

                                                                          Reported scan target: {ref.target || 'Not reported'}{#if ref.target_truncated} (truncated){/if}
                                                                          Received

                                                                          - {#if views.length === 0} -

                                                                          No retained observation for this event. Its reference is retained, but a saved scanner view is unavailable.

                                                                          - {:else} - {#each views as view (`${view.event_id}:${view.view_role}`)} - {@const attrs = view.attributes ?? {}} -
                                                                          -

                                                                          {view.view_role === 'previous' ? 'Before the reported change' : view.view_role === 'current' ? 'After the reported change' : 'Reported host'}

                                                                          -
                                                                          -
                                                                          Hostname
                                                                          {value(attrs.hostname)}
                                                                          -
                                                                          IP address
                                                                          {value(attrs.ip)}
                                                                          -
                                                                          MAC address
                                                                          {value(attrs.mac)}
                                                                          - {#if attrs.vendor}
                                                                          Reported vendor
                                                                          {attrs.vendor}
                                                                          {/if} - {#if attrs.os}
                                                                          Reported OS
                                                                          {attrs.os}
                                                                          {/if} - {#if attrs.device}
                                                                          Reported device
                                                                          {attrs.device}
                                                                          {/if} -
                                                                          -

                                                                          Scanner-reported identity confidence: {attrs.identity_confidence || 'unknown'}Identity source: {attrs.identity_source || 'unknown'}

                                                                          -

                                                                          {randomizedLabel(attrs.randomized)}

                                                                          - {#if attrs.attributes_truncated}

                                                                          Some reported fields were truncated at ingest.

                                                                          {/if} -
                                                                          Saved report view · technical attributes
                                                                          {JSON.stringify(attrs, null, 2)}
                                                                          -

                                                                          Snapshot covers {view.ports_total} ports{view.ports_truncated ? ' (truncated)' : ''}.

                                                                          - {#if (view.ports ?? []).length > 0} -
                                                                            {#each view.ports as port (`${port.proto}/${port.port}`)}
                                                                          • {port.proto}/{port.port} {port.state}{port.service ? ` (${port.service})` : ''}
                                                                          • {/each}
                                                                          - {/if} - {#if view.profile_id} - Open reported context →{classLabel(view.reference_class)} · {profileLinks.find((link) => link.profile_id === view.profile_id)?.role ?? view.view_role} - {:else}

                                                                          No linked profile is available for this saved view.

                                                                          {/if} -
                                                                          - {/each} - {/if} -
                                                                          -
                                                                          - - diff --git a/ui/src/lib/briefingView.js b/ui/src/lib/briefingView.js new file mode 100644 index 0000000..a2b88ee --- /dev/null +++ b/ui/src/lib/briefingView.js @@ -0,0 +1,54 @@ +// Pure briefing dossier derivations (Designv9 §8.2). No markup, no +// fetch: BriefingContainer calls these, and scripts/characterize.mjs +// covers them in plain node. + +/** + * The priority comparison opens when the reader needs it: equal + * baseline, suggestion and final stay collapsed; a difference or a + * clamp opens the detail. + * @param {{clamped?: boolean, baseline?: string, priority?: string, model_suggestion?: string|null}|null} shown + */ +export function priorityDiffers(shown) { + return shown !== null && + (shown.clamped || shown.baseline !== shown.priority || + (shown.model_suggestion ?? shown.baseline) !== shown.priority); +} + +/** + * Lookup steps that could not establish retained context: unknown + * subjects, blocked or failed lookups stay explicit limitations. + * @param {Array<{outcome?: string}>} traces + */ +export function lookupLimits(traces) { + return (traces ?? []).filter((step) => + ['unknown_subject', 'blocked', 'error', 'unavailable', 'truncated'].includes(step.outcome)); +} + +/** + * Group tool steps into lookup receipts by their summary, preserving + * first-seen order. + * @param {Array<{summary?: string, step?: number}>} traces + */ +export function lookupReceipts(traces) { + const groups = []; + for (const step of traces ?? []) { + const key = step.summary || `step:${step.step}`; + let group = groups.find((receipt) => receipt.key === key); + if (!group) { + group = { key, summary: step.summary, steps: [] }; + groups.push(group); + } + group.steps.push(step.step); + } + return groups; +} + +/** + * The single-view identity grid renders only when every observation + * and event is retained; a truncated dossier falls back to per-report + * views with an explicit notice. + * @param {{observations_truncated?: boolean, referenced_truncated?: boolean}|null} shown + */ +export function identityComplete(shown) { + return shown !== null && !shown.observations_truncated && !shown.referenced_truncated; +} diff --git a/ui/src/lib/context.js b/ui/src/lib/context.js new file mode 100644 index 0000000..ebe897a --- /dev/null +++ b/ui/src/lib/context.js @@ -0,0 +1,34 @@ +// Svelte context glue for the single event stream. The store object +// itself is framework-free (`./stream.js`); this file only publishes +// it to the component tree. Call `setConnection` once in App setup, +// `getConnection` in any screen — never a module-level singleton, so +// prerender stays connection-free. + +import { setContext, getContext } from 'svelte'; + +const KEY = Symbol('watcherbridge.connection'); + +/** @param {ReturnType} stream */ +export function setConnection(stream) { + setContext(KEY, stream); +} + +/** @returns {ReturnType} */ +export function getConnection() { + return getContext(KEY); +} + +/** + * The connection, or null when rendered outside App (SSR harness, + * standalone screens). Screens use this to read connection state and + * the incident revision from context instead of prop drilling; the + * null path keeps direct renders working without a provider. + * @returns {ReturnType|null} + */ +export function getConnectionOrNull() { + try { + return getConnection(); + } catch { + return null; + } +} diff --git a/ui/src/lib/evidence.js b/ui/src/lib/evidence.js new file mode 100644 index 0000000..13a1786 --- /dev/null +++ b/ui/src/lib/evidence.js @@ -0,0 +1,17 @@ +// Evidence navigation keys: the contract between dossier sections +// and revealEvidence (../evidenceNavigation.js). Sections tag targets +// with data-evidence keys; buttons jump by key without changing the +// hash route. Keys are `event:`, `step:` or the +// literal reports key for the scanner-reports section. + +export const REPORTS_KEY = 'reports'; + +/** @param {string} eventId */ +export function eventKey(eventId) { + return `event:${eventId}`; +} + +/** @param {number|string} step */ +export function stepKey(step) { + return `step:${step}`; +} diff --git a/ui/src/lib/incidentEvents.js b/ui/src/lib/incidentEvents.js deleted file mode 100644 index 87dc473..0000000 --- a/ui/src/lib/incidentEvents.js +++ /dev/null @@ -1,17 +0,0 @@ -// Incident updates have no replay cursor. An opened connection and a -// resync invalidate local incident state just like a live update does. -export function forwardIncidentEvents(source, target, refreshOverview) { - const refresh = () => { - target.dispatchEvent(new Event('watcherbridge:incident')); - refreshOverview(); - }; - const events = ['open', 'incident', 'resync']; - for (const event of events) { - source.addEventListener(event, refresh); - } - return () => { - for (const event of events) { - source.removeEventListener(event, refresh); - } - }; -} diff --git a/ui/src/lib/latestOnly.js b/ui/src/lib/latestOnly.js new file mode 100644 index 0000000..7d2607a --- /dev/null +++ b/ui/src/lib/latestOnly.js @@ -0,0 +1,26 @@ +// Latest-wins guard for one async operation. Each operation (reload, +// load-more, decision page, …) owns an instance, so intents never +// cancel each other — the flaw BUG-1 pins in screens that share a +// single guard. Stream-frame fencing lives in lib/stream.js, not here. + +/** + * @returns {{start: () => number, current: (token: number) => boolean, invalidate: () => void}} + */ +export function latestOnly() { + let gen = 0; + return { + // Call when starting work; keep the token for completion. + start() { + gen += 1; + return gen; + }, + // True only when no newer work started (or invalidated) since. + current(token) { + return token === gen; + }, + // Void every in-flight token: unmounts, route changes, resets. + invalidate() { + gen += 1; + } + }; +} diff --git a/ui/src/lib/pager.js b/ui/src/lib/pager.js new file mode 100644 index 0000000..0dcedae --- /dev/null +++ b/ui/src/lib/pager.js @@ -0,0 +1,92 @@ +// Cursor pager with merge-by-key, a row cap and per-operation fencing. +// resetGen orders reloads; pageGen invalidates appends. A reload +// landing after a page start still applies (the BUG-1 case), but a +// committed reset retires every older append, so a late page cannot +// reopen an exhausted list. Only a successful commit clears the error +// slot and voids pending appends: a failed reset changes nothing, so +// a pending append against the still-valid cursor lands normally. +// +// Unlike createResource, the pager seeds from the mount-time snapshot: +// cursor and merge live here, so the container passes `initial` once and +// never rewrites it. A reset retires the snapshot by replacing rows. +// `initial` also accepts a thunk returning the snapshot: .svelte callers +// must read the prop inside a closure, or the compiler's init-capture +// rule treats it as a stale local capture. + +import { writable, derived, get } from 'svelte/store'; +import { nextPageRows } from '@/lib/paging.js'; + +/** + * @template T + * @param {{fetchPage: (cursor: string) => Promise<{rows: T[], nextAfter: string}>, keyOf: (row: T) => string|number, cap: number, initial?: {rows: T[], nextAfter: string}|(() => ({rows: T[], nextAfter: string}|null))|null}} options + */ +export function createPager({ fetchPage, keyOf, cap, initial = null }) { + const snap = typeof initial === 'function' ? initial() : initial; + const rows = writable(snap ? [...snap.rows] : []); + const cursor = writable(snap ? (snap.nextAfter ?? '') : ''); + const started = writable(snap !== null); + const failure = writable(/** @type {{message: string, reset: boolean}|null} */ (null)); + const error = derived(failure, ($failure) => $failure?.message ?? null); + const loadingMore = writable(false); + const exhausted = derived([cursor, started], ([$cursor, $started]) => $started && $cursor === ''); + const capped = derived([rows, cursor], ([$rows, $cursor]) => $cursor !== '' && $rows.length >= cap); + let resetGen = 0; + let pageGen = 0; + + async function loadMore(reset = false) { + const my = reset ? (resetGen += 1) : (pageGen += 1); + const gen = () => (reset ? resetGen : pageGen); + failure.set(null); + loadingMore.set(true); + try { + const page = await fetchPage(reset ? '' : get(cursor)); + if (my !== gen()) { + return 'stale'; + } + const base = reset ? [] : get(rows); + const fresh = nextPageRows(base, page.rows, keyOf, cap); + rows.set(reset ? fresh : [...base, ...fresh]); + cursor.set(page.nextAfter ?? ''); + started.set(true); + if (reset) { + // A committed reset owns the list now: clear the error slot + // (a previous page failure refers to the old state) and retire + // every append requested against an older cursor, so a late + // page cannot reopen an exhausted list. Appends requested after + // this commit use the new cursor and are unaffected. + failure.set(null); + pageGen += 1; + } + return 'applied'; + } catch (err) { + if (my !== gen()) { + return 'stale'; + } + failure.set({ message: err instanceof Error ? err.message : String(err), reset }); + return 'failed'; + } finally { + if (my === gen()) { + loadingMore.set(false); + } + } + } + + function reset() { + return loadMore(true); + } + + // Replace every row outright (profile reload with embedded history): + // voids in-flight pages, clears the error and restarts from the new + // cursor. Failures never reach here — only applied data replaces. + function replace(nextRows, nextAfter = '') { + resetGen += 1; + pageGen += 1; + failure.set(null); + loadingMore.set(false); + rows.set([...nextRows]); + cursor.set(nextAfter ?? ''); + started.set(true); + } + + return { rows, cursor, started, exhausted, capped, failure, error, loadingMore, loadMore, reset, replace }; +} diff --git a/ui/src/lib/payload.js b/ui/src/lib/payload.js new file mode 100644 index 0000000..b6969fb --- /dev/null +++ b/ui/src/lib/payload.js @@ -0,0 +1,36 @@ +// Decision submission payloads (Designv9 §5.1). The container owns +// the post; this pure step shapes and validates the draft so plain +// node covers the error paths the harness cannot mount: a bad snooze +// date never reaches the network, and text/member rules are explicit. + +/** + * @param {{kind: string, untilText?: string, text?: string, includeMembers?: boolean}} draft + * @param {{subjectKind: string, subjectId: string, requestId: string, memberScope?: boolean}} ctx + * @returns {{payload?: Record, error?: string}} + */ +export function buildDecisionPayload(draft, ctx) { + if (draft.kind === 'snooze' && (draft.untilText ?? '') !== '') { + const at = new Date(draft.untilText); + if (Number.isNaN(at.getTime())) { + return { error: 'snooze time is not a date' }; + } + return { payload: { ...base(ctx, draft), until: at.toISOString() } }; + } + const payload = base(ctx, draft); + if (draft.kind === 'note' || draft.kind === 'label') { + payload.text = draft.text ?? ''; + } + if (ctx.memberScope) { + payload.includeMembers = draft.includeMembers ?? false; + } + return { payload }; +} + +function base(ctx, draft) { + return { + subjectKind: ctx.subjectKind, + subjectId: ctx.subjectId, + kind: draft.kind, + requestId: ctx.requestId + }; +} diff --git a/ui/src/lib/reconnect.js b/ui/src/lib/reconnect.js new file mode 100644 index 0000000..5315b0a --- /dev/null +++ b/ui/src/lib/reconnect.js @@ -0,0 +1,11 @@ +// Reconnect-edge decision: refresh when the stream comes (back) live +// and there is rendered content — fetched data or a mounted snapshot. +// A snapshot is renderable state, not a reason to stay stale. Pure so +// it is unit-tested; the container owns the wasLive tracking. + +/** + * @param {{live: boolean, wasLive: boolean, data: unknown, initial: unknown}} state + */ +export function shouldRefreshOnReconnect({ live, wasLive, data, initial }) { + return live && !wasLive && (data ?? initial) !== null; +} diff --git a/ui/src/lib/registry.js b/ui/src/lib/registry.js new file mode 100644 index 0000000..942e072 --- /dev/null +++ b/ui/src/lib/registry.js @@ -0,0 +1,50 @@ +// Scoped keyboard shortcut registry. Screens register their keys with +// a human label; the help panel is generated from the same table, so +// documented and working shortcuts cannot drift apart. Dispatch stays +// silent while typing and never claims modifier combos. Multi-key +// sequences (`g h`, `g d`) stay in the App shell — they are navigation, +// not screen actions. + +import { typingTarget } from '@/lib/roving.js'; + +export function createShortcutRegistry() { + // scope -> key -> { label, handler } + const bindings = new Map(); + + /** + * @param {string} scope e.g. 'global', 'briefing' + * @param {string} key single-key value, e.g. 'j', '?', 'e' + * @param {string} label help-panel wording + * @param {(ev: KeyboardEvent) => void} handler + */ + function register(scope, key, label, handler) { + if (!bindings.has(scope)) { + bindings.set(scope, new Map()); + } + bindings.get(scope).set(key, { label, handler }); + } + + /** + * @param {string} scope + * @param {KeyboardEvent} ev + * @returns {boolean} true when a binding handled the event + */ + function dispatch(scope, ev) { + if (typingTarget(ev) || ev.metaKey || ev.ctrlKey || ev.altKey) { + return false; + } + const binding = bindings.get(scope)?.get(ev.key); + if (!binding) { + return false; + } + binding.handler(ev); + return true; + } + + /** @param {string} scope */ + function describe(scope) { + return [...(bindings.get(scope)?.entries() ?? [])].map(([key, binding]) => ({ key, label: binding.label })); + } + + return { register, dispatch, describe }; +} diff --git a/ui/src/lib/resource.js b/ui/src/lib/resource.js new file mode 100644 index 0000000..c00bb50 --- /dev/null +++ b/ui/src/lib/resource.js @@ -0,0 +1,82 @@ +// Single-item async resource with snapshot support. Replaces the +// initial/retired plumbing in screens: a snapshot fills `data` until +// (or instead of) a fetch, a failed refresh keeps data with a notice, +// and only a data-less failure becomes an error. One guard per +// resource; concurrent refreshes are latest-wins. +// +// Plain JS over svelte/store (no runes, no .svelte.js): the stores run +// uncompiled, so scripts/characterize.mjs covers this in plain node +// with no test runner. Components subscribe with `$data` as usual. + +import { writable, get } from 'svelte/store'; + +/** + * Fetch-owned data with a failed-refresh notice. The mount-time + * snapshot (if any) stays a container concern: containers render + * `data ?? snapshot`, so the resource never captures props at init. + * @template T + * @param {() => Promise} fetcher + */ +export function createResource(fetcher) { + const data = writable(null); + const error = writable(null); + const refreshError = writable(null); + const loading = writable(false); + const guard = { gen: 0 }; + + async function refresh() { + const my = (guard.gen += 1); + refreshError.set(null); + if (get(data) === null) { + error.set(null); + loading.set(true); + } + try { + const fresh = await fetcher(); + if (my !== guard.gen) { + return 'stale'; + } + data.set(fresh); + error.set(null); + refreshError.set(null); + return 'applied'; + } catch (err) { + if (my !== guard.gen) { + return 'stale'; + } + const message = err instanceof Error ? err.message : String(err); + if (get(data) === null) { + error.set(message); + } else { + refreshError.set(message); + } + return 'failed'; + } finally { + if (my === guard.gen) { + loading.set(false); + } + } + } + + function invalidate() { + guard.gen += 1; + loading.set(false); + } + + return { data, error, refreshError, loading, refresh, invalidate }; +} + +/** + * Which failure (if any) is visible next to rendered content. A + * data-less failure renders as the error state, never a notice; a + * snapshot counts as rendered content, so its failures must surface + * too — otherwise a failed refresh on a snapshot screen is silent. + * @param {{data: unknown, initial: unknown, error: string|null, refreshError: string|null}} state + * @returns {string|null} notice text, or null when nothing may show + */ +export function failureNotice({ data = null, initial = null, error = null, refreshError = null } = {}) { + if ((data ?? initial) === null) { + return null; + } + return refreshError ?? (data === null ? error : null); +} diff --git a/ui/src/lib/routes.js b/ui/src/lib/routes.js new file mode 100644 index 0000000..45d4659 --- /dev/null +++ b/ui/src/lib/routes.js @@ -0,0 +1,41 @@ +// Hash route table. Single source of truth for route names, patterns +// and document titles — replaces App's inline parseRoute and title +// map. Matching behavior is unchanged: first match wins, briefing and +// incident IDs are decoded, anything unrecognized is home. + +const routes = [ + { name: 'briefing', pattern: /^#\/briefing\/(.+)$/ }, + { name: 'incident', pattern: /^#\/incidents\/(.+)$/ }, + { name: 'device', pattern: /^#\/devices\/(.+)$/ }, + { name: 'devices', pattern: /^#\/devices\/?$/ }, + { name: 'health', pattern: /^#\/health$/ } +]; + +const titles = { + home: 'Review overview', + devices: 'Reported hosts', + device: 'Reported host detail', + briefing: 'Briefing', + incident: 'Incident', + health: 'Health' +}; + +/** + * @param {string|null|undefined} hash + * @returns {{name: string, id?: string}} + */ +export function parseRoute(hash) { + const h = hash || '#/'; + for (const route of routes) { + const m = h.match(route.pattern); + if (m) { + return m[1] === undefined ? { name: route.name } : { name: route.name, id: decodeURIComponent(m[1]) }; + } + } + return { name: 'home' }; +} + +/** @param {string} name */ +export function routeTitle(name) { + return titles[name] ?? titles.home; +} diff --git a/ui/src/lib/stream.js b/ui/src/lib/stream.js new file mode 100644 index 0000000..73a7aa8 --- /dev/null +++ b/ui/src/lib/stream.js @@ -0,0 +1,133 @@ +// SSE connection lifecycle for GET /events. Transport only: connection +// state, overview frames and an incident revision counter. Parsing +// failures degrade to the next frame; refresh ownership stays with the +// screens, which subscribe to `incidentRevision` for refetch/markStale. +// No module singletons: App creates one instance and shares it through +// `./context.js`, so prerender never connects. +// +// `open`/`incident`/`resync` all mean "incident state may have +// changed". Screens subscribe to `incidentRevision` from context, so +// no window-event bus remains. +// +// Reconnects are native while the source is still connecting: on a +// mid-stream drop the source stays open and the browser retries with +// Last-Event-ID, so the server resumes bounded replay instead of +// restarting the stream. A rejected handshake (non-200, e.g. the 503 +// subscriber cap) moves the source to CLOSED, where native retry is +// dead — that path gets an explicit reconnect after 3s. Closing and +// recreating a live source would drop the cursor (a fresh EventSource +// sends no Last-Event-ID). + +import { writable } from 'svelte/store'; + +export const INCIDENT_KINDS = ['open', 'incident', 'resync']; + +/** + * @param {object} [options] + * @param {string} [options.url] stream URL + * @param {number} [options.retryMs] explicit reconnect delay after a rejected handshake (CLOSED) + * @param {(url: string) => EventSource} [options.createSource] transport factory (fake in tests) + * @param {(fn: () => void, ms: number) => unknown} [options.schedule] retry scheduler (manual in tests) + * @param {(t: unknown) => void} [options.cancelSchedule] + * @param {(overview: unknown) => void} [options.onOverview] valid overview frames only + * @param {(kind: string) => void} [options.onIncident] every open/incident/resync frame + */ +export function createEventStream({ + url = '/events', + retryMs = 3000, + createSource = (u) => new EventSource(u), + schedule = (fn, ms) => setTimeout(fn, ms), + cancelSchedule = (t) => clearTimeout(t), + onOverview = () => {}, + onIncident = () => {} +} = {}) { + const connection = writable('connecting'); + const incidentRevision = writable(0); + let source = null; + let timer = null; + // Generation fences late callbacks after disconnect/reconnect, the + // same stale-continuation rule screens apply to fetches. + let gen = 0; + + function cleanup() { + gen += 1; + if (timer !== null) { + cancelSchedule(timer); + timer = null; + } + if (source !== null) { + source.onopen = null; + source.onmessage = null; + source.onerror = null; + for (const kind of [...INCIDENT_KINDS, 'overview']) { + source.removeEventListener?.(kind, listeners[kind]); + } + source.close(); + source = null; + } + } + + // Named listeners so cleanup removes exactly what connect added. + const listeners = {}; + for (const kind of INCIDENT_KINDS) { + listeners[kind] = () => { + incidentRevision.update((n) => n + 1); + onIncident(kind); + }; + } + listeners.overview = (/** @type {MessageEvent} */ ev) => { + try { + onOverview(JSON.parse(ev.data)); + } catch { + // Malformed frame degrades to the next refresh, never a crash. + } + }; + + function connect() { + cleanup(); + const my = gen; + connection.set('connecting'); + const next = createSource(url); + source = next; + next.onopen = () => { + if (my === gen) { + connection.set('live'); + } + }; + for (const kind of [...INCIDENT_KINDS, 'overview']) { + next.addEventListener(kind, listeners[kind]); + } + next.onerror = () => { + if (my !== gen) { + return; + } + if (next.readyState === 2 /* CLOSED: handshake rejected, e.g. the 503 cap */) { + // Native retry is dead on a closed source, so reconnect + // explicitly after the specified delay. The fresh handshake + // carries no Last-Event-ID; the server answers that with a + // fresh snapshot and overview, and the client loads state as + // on first load. + cleanup(); + connection.set('retrying'); + const mine = gen; + timer = schedule(() => { + if (mine === gen) { + connect(); + } + }, retryMs); + return; + } + // Still connecting (mid-stream drop): leave the source open so + // the browser's native retry carries Last-Event-ID and the + // server resumes instead of restarting. The next onopen flips + // back to live; disconnect() still closes explicitly. + connection.set('retrying'); + }; + } + + function disconnect() { + cleanup(); + } + + return { connection, incidentRevision, connect, disconnect }; +} diff --git a/ui/src/main.js b/ui/src/main.js index 2d09e34..9f19042 100644 --- a/ui/src/main.js +++ b/ui/src/main.js @@ -1,6 +1,10 @@ import { mount } from 'svelte'; import App from './App.svelte'; -import './style.css'; +import './styles/tokens.css'; +import './styles/base.css'; +import './styles/utilities.css'; +import './styles/dossier.css'; +import './styles/shell.css'; // Step 22 entry: mounts the shell only. Hash routes and screens land // in Steps 23-24; the entry shape stays stable so they slot in here. diff --git a/ui/src/style.css b/ui/src/styles/base.css similarity index 78% rename from ui/src/style.css rename to ui/src/styles/base.css index 24aefed..1c244b7 100644 --- a/ui/src/style.css +++ b/ui/src/styles/base.css @@ -1,27 +1,6 @@ +/* Global element defaults. Component classes move out in Phases 3-5; see inventory in the Phase 1 report. */ /* Shared local-only viewer styles; no remote fonts or inline assets. */ -:root { - font: 14px/1.5 -apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif; - color: var(--text); - background: var(--canvas); - --canvas: #f4f5f7; - --surface: #fff; - --subtle: #f8f9fb; - --text: #14171c; - --muted: #535d6b; - --border: #d9dde3; - --accent: #1b4f9c; - --accent-soft: #e8eef7; - --success: #225b38; - --success-bg: #e8f3ec; - --success-border: #9ec4aa; - --warning: #6b4700; - --warning-bg: #fff4d6; - --warning-border: #d9b94f; - --danger: #9e302c; - --danger-bg: #fcecea; - --danger-border: #dea49d; - color-scheme: light dark; -} + * { box-sizing: border-box; } @@ -145,39 +124,8 @@ time { color: var(--muted); font-size: 13px; } -.pill { - display: inline-flex; - align-items: center; - gap: 4px; - border: 1px solid var(--border); - border-radius: 999px; - padding: 2px 9px; - background: var(--subtle); - font-size: 12px; - color: var(--muted); - vertical-align: middle; -} -.pill[data-state=ok],.priority[data-priority=low] { - color: var(--success); - background: var(--success-bg); - border-color: var(--success-border); -} -.pill[data-state=degraded],.priority[data-priority=medium] { - color: var(--warning); - background: var(--warning-bg); - border-color: var(--warning-border); -} -.pill[data-state=blind],.priority[data-priority=high],.priority[data-priority=critical] { - color: var(--danger); - background: var(--danger-bg); - border-color: var(--danger-border); -} -.priority { - text-transform: uppercase; - border-radius: 5px; - font-weight: 650; - letter-spacing: .03em; -} +/* Pill badges live in components/Pill (Pill.module.css owns the base, + priority and data-* variants). */ .conn { margin: 0 0 0 auto; display: flex; @@ -250,14 +198,7 @@ time { color: var(--surface); font-weight: 650; } -.pills { - list-style: none; - display: flex; - flex-wrap: wrap; - gap: 8px; - padding: 0; - margin: 0 0 12px; -} +/* Verdict pills live in components/VerdictHeader (VerdictHeader.module.css). */ .context { font-size: 12px; color: var(--muted); @@ -410,6 +351,9 @@ time { font-weight: 400; color: var(--muted); } +/* TRANSITIONAL: .sources transfers to components/SourceCard when its + last global consumer migrates — find them with: + grep -rn 'class="[^"]*\bsources\b' src. New screens use their own module. */ .sources { list-style: none; padding: 0; @@ -578,26 +522,9 @@ details>section { padding: 16px 0; border-top: 1px solid var(--border); } -.health-metrics { - display: grid; - grid-template-columns: repeat(5,minmax(0,1fr)); - gap: 12px; - margin-bottom: 0; -} -.health-metrics>div { - background: var(--subtle); - border: 1px solid var(--border); - border-radius: 8px; - padding: 16px; -} -.health-metrics dd { - font-size: 26px; - margin-top: 10px; -} -.health-metrics small { - font-size: 13px; - color: var(--muted); -} +/* .health-metrics moved to components/HealthSummary/HealthSummary.module.css + (sole consumer). The `health-metrics` hook class stays on the element so + `dl:not(.digest,…)` below keeps excluding it. */ .stepper { display: flex; flex-wrap: wrap; @@ -631,22 +558,9 @@ label { label input:not([type=checkbox],[type=radio]),label select,label textarea { margin-top: 4px; } -.trail { - list-style: none; - padding: 0; -} -.trail li { - border-top: 1px solid var(--border); - padding: 12px 0; - font-size: 13px; -} -.trail .text { - overflow-wrap: anywhere; -} -.trail .until { - color: var(--muted); - font-size: 12px; -} +/* The decision trail moved to components/DecisionTrail with its own + module (transitional global rules removed once the last global + consumer migrated). */ @media(max-width:1050px) { .review-workspace { grid-template-columns: minmax(0,1fr); @@ -658,9 +572,6 @@ label input:not([type=checkbox],[type=radio]),label select,label textarea { .detail-pane { position: static; } - .health-metrics { - grid-template-columns: repeat(3,minmax(0,1fr)); - } } @media(max-width:640px) { .briefing .stepper { @@ -713,50 +624,8 @@ label input:not([type=checkbox],[type=radio]),label select,label textarea { dd { margin-bottom: 10px; } - .health-metrics { - grid-template-columns: repeat(2,minmax(0,1fr)); - } -} -@media(prefers-color-scheme:dark) { - :root { - --canvas: #15191f; - --surface: #1e242d; - --subtle: #252c36; - --text: #edf0f5; - --muted: #b4bfce; - --border: #414b5a; - --accent: #9dc2ff; - --accent-soft: #293c58; - --success: #abd7b8; - --success-bg: #213b2b; - --success-border: #4e7a5d; - --warning: #f1d38e; - --warning-bg: #3d321e; - --warning-border: #8c7237; - --danger: #f3b3ad; - --danger-bg: #422b2b; - --danger-border: #9e625b; - } -} -@media(prefers-reduced-motion:reduce) { - *,*::before,*::after { - animation: none!important; - transition: none!important; - scroll-behavior: auto!important; - } } -.sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip-path: inset(50%); - white-space: nowrap; - border: 0; -} .review-workspace[data-empty='true'] { grid-template-columns: minmax(0, 1fr); diff --git a/ui/src/styles/dossier.css b/ui/src/styles/dossier.css new file mode 100644 index 0000000..8cc3da0 --- /dev/null +++ b/ui/src/styles/dossier.css @@ -0,0 +1,80 @@ +/* Briefing dossier page shell (plan step 34). Moved verbatim from the + old Detail screen's scoped