import { Component, Input, ViewEncapsulation } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { buildCompareMetricRows, deriveCompareColumns, } from '../predictive-studio.view-models';
import * as i0 from "@angular/core";
import * as i1 from "@angular/forms";
const _forTrack0 = ($index, $item) => $item.id;
const _forTrack1 = ($index, $item) => $item.key;
const _forTrack2 = ($index, $item) => $item.label;
function PSCompareComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 1)(1, "span", 2);
    i0.ɵɵelement(2, "i", 3);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(3, "h3");
    i0.ɵɵtext(4, "Nothing to compare yet");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(5, "p");
    i0.ɵɵtext(6, "Run an experiment with at least two scored iterations and you'll be able to line up their metrics side-by-side here to pick a winner.");
    i0.ɵɵelementEnd()();
} }
function PSCompareComponent_Conditional_2_For_6_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "option", 7);
    i0.ɵɵtext(1);
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const s_r3 = ctx.$implicit;
    i0.ɵɵproperty("value", s_r3.id);
    i0.ɵɵadvance();
    i0.ɵɵtextInterpolate2("", s_r3.name, " \u00B7 ", s_r3.scoredCount, " scored");
} }
function PSCompareComponent_Conditional_2_Conditional_10_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 10);
    i0.ɵɵelement(1, "i", 11);
    i0.ɵɵelementStart(2, "div", 12);
    i0.ɵɵtext(3, "This session has fewer than two scored iterations \u2014 pick another session to compare.");
    i0.ɵɵelementEnd()();
} }
function PSCompareComponent_Conditional_2_Conditional_11_For_11_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 20)(1, "div", 21);
    i0.ɵɵtext(2);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(3, "div", 15);
    i0.ɵɵtext(4);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(5, "span", 22);
    i0.ɵɵtext(6);
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const r_r4 = ctx.$implicit;
    i0.ɵɵstyleProp("border-top-color", r_r4.color);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(r_r4.label);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate2("", r_r4.algorithm, " \u00B7 ", r_r4.descriptor);
    i0.ɵɵadvance();
    i0.ɵɵclassMap(r_r4.isBest ? "green" : "gray");
    i0.ɵɵadvance();
    i0.ɵɵtextInterpolate(r_r4.isBest ? "Top scorer" : r_r4.status);
} }
function PSCompareComponent_Conditional_2_Conditional_11_For_13_For_6_Conditional_3_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "span", 28);
    i0.ɵɵtext(1, "BEST");
    i0.ɵɵelementEnd();
} }
function PSCompareComponent_Conditional_2_Conditional_11_For_13_For_6_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 26)(1, "span", 27);
    i0.ɵɵtext(2);
    i0.ɵɵelementEnd();
    i0.ɵɵconditionalCreate(3, PSCompareComponent_Conditional_2_Conditional_11_For_13_For_6_Conditional_3_Template, 2, 0, "span", 28);
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const v_r5 = ctx.$implicit;
    const $index_r6 = ctx.$index;
    const row_r7 = i0.ɵɵnextContext().$implicit;
    i0.ɵɵclassProp("best", $index_r6 === row_r7.bestIndex);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(v_r5);
    i0.ɵɵadvance();
    i0.ɵɵconditional($index_r6 === row_r7.bestIndex ? 3 : -1);
} }
function PSCompareComponent_Conditional_2_Conditional_11_For_13_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 23)(1, "span");
    i0.ɵɵtext(2);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(3, "span", 24);
    i0.ɵɵtext(4);
    i0.ɵɵelementEnd()();
    i0.ɵɵrepeaterCreate(5, PSCompareComponent_Conditional_2_Conditional_11_For_13_For_6_Template, 4, 4, "div", 25, i0.ɵɵrepeaterTrackByIndex);
} if (rf & 2) {
    const row_r7 = ctx.$implicit;
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(row_r7.label);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(row_r7.qualifier);
    i0.ɵɵadvance();
    i0.ɵɵrepeater(row_r7.values);
} }
function PSCompareComponent_Conditional_2_Conditional_11_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 13)(1, "div", 14)(2, "h3");
    i0.ɵɵtext(3, "Side-by-side comparison");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(4, "span", 15);
    i0.ɵɵtext(5, "Best value in each row highlighted");
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(6, "div", 16)(7, "div", 17)(8, "div", 18);
    i0.ɵɵtext(9, "Run / Metric");
    i0.ɵɵelementEnd();
    i0.ɵɵrepeaterCreate(10, PSCompareComponent_Conditional_2_Conditional_11_For_11_Template, 7, 8, "div", 19, _forTrack1);
    i0.ɵɵrepeaterCreate(12, PSCompareComponent_Conditional_2_Conditional_11_For_13_Template, 7, 2, null, null, _forTrack2);
    i0.ɵɵelementEnd()()();
    i0.ɵɵelementStart(14, "div", 10);
    i0.ɵɵelement(15, "i", 11);
    i0.ɵɵelementStart(16, "div", 12)(17, "strong");
    i0.ɵɵtext(18);
    i0.ɵɵelementEnd()()();
} if (rf & 2) {
    const ctx_r1 = i0.ɵɵnextContext(2);
    i0.ɵɵadvance(7);
    i0.ɵɵstyleProp("grid-template-columns", ctx_r1.gridTemplate);
    i0.ɵɵadvance(3);
    i0.ɵɵrepeater(ctx_r1.runs);
    i0.ɵɵadvance(2);
    i0.ɵɵrepeater(ctx_r1.metricRows);
    i0.ɵɵadvance(6);
    i0.ɵɵtextInterpolate(ctx_r1.verdict);
} }
function PSCompareComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
    const _r1 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "div", 4)(1, "div", 5)(2, "label");
    i0.ɵɵtext(3, "Session to compare");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(4, "select", 6);
    i0.ɵɵtwoWayListener("ngModelChange", function PSCompareComponent_Conditional_2_Template_select_ngModelChange_4_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.selectedSessionId, $event) || (ctx_r1.selectedSessionId = $event); return i0.ɵɵresetView($event); });
    i0.ɵɵlistener("ngModelChange", function PSCompareComponent_Conditional_2_Template_select_ngModelChange_4_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.rebuild()); });
    i0.ɵɵrepeaterCreate(5, PSCompareComponent_Conditional_2_For_6_Template, 2, 3, "option", 7, _forTrack0);
    i0.ɵɵelementEnd()();
    i0.ɵɵelement(7, "span", 8);
    i0.ɵɵelementStart(8, "span", 9);
    i0.ɵɵtext(9);
    i0.ɵɵelementEnd()();
    i0.ɵɵconditionalCreate(10, PSCompareComponent_Conditional_2_Conditional_10_Template, 4, 0, "div", 10)(11, PSCompareComponent_Conditional_2_Conditional_11_Template, 19, 3);
} if (rf & 2) {
    const ctx_r1 = i0.ɵɵnextContext();
    i0.ɵɵadvance(4);
    i0.ɵɵtwoWayProperty("ngModel", ctx_r1.selectedSessionId);
    i0.ɵɵadvance();
    i0.ɵɵrepeater(ctx_r1.sessionOptions);
    i0.ɵɵadvance(4);
    i0.ɵɵtextInterpolate1("", ctx_r1.runs.length, " top runs \u00B7 ranked by score");
    i0.ɵɵadvance();
    i0.ɵɵconditional(ctx_r1.runs.length < 2 ? 10 : 11);
} }
/**
 * Compare Runs panel — a live side-by-side comparison of the top scored iterations (training runs)
 * within a selected experiment session. Fully live:
 *
 * - A session picker lists every session that has ≥2 scored iterations (only those are comparable).
 * - The top runs of the selected session are derived via {@link deriveCompareColumns} and rendered as
 *   side-by-side columns; the real metric rows (holdout score, compute cost) come from
 *   {@link buildCompareMetricRows}, with the best column per row highlighted.
 *
 * Empty/prompt state when nothing is comparable. 100% entity-agnostic.
 */
export class PSCompareComponent {
    engine;
    /** Sessions with ≥2 scored iterations — the comparable set. */
    sessionOptions = [];
    selectedSessionId = '';
    runs = [];
    metricRows = [];
    ngOnInit() {
        this.buildSessionOptions();
        this.selectedSessionId = this.sessionOptions[0]?.id ?? '';
        this.rebuild();
    }
    /** List sessions that have at least two scored iterations (the only ones worth comparing). */
    buildSessionOptions() {
        const sessions = this.engine?.Sessions ?? [];
        this.sessionOptions = sessions
            .map((s) => {
            const scoredCount = this.engine.IterationRowsForSession(s.ID).filter((it) => it.Score != null).length;
            return { id: s.ID, name: s.Name, scoredCount };
        })
            .filter((o) => o.scoredCount >= 2);
    }
    /** Derive the compare columns + metric rows for the selected session. */
    rebuild() {
        if (!this.selectedSessionId) {
            this.runs = [];
            this.metricRows = [];
            return;
        }
        const rows = this.engine.IterationRowsForSession(this.selectedSessionId);
        this.runs = deriveCompareColumns(rows, 3);
        this.metricRows = buildCompareMetricRows(this.runs);
    }
    /** CSS grid template — stub column + one fraction per run column. */
    get gridTemplate() {
        return `200px repeat(${this.runs.length}, 1fr)`;
    }
    /** A plain-language verdict naming the best run by holdout score. */
    get verdict() {
        const best = this.runs.find((r) => r.isBest);
        if (!best || best.holdoutAuc == null)
            return 'Pick the run that wins on the holdout score — the honest out-of-sample number.';
        return `${best.label} (${best.algorithm}) leads on the holdout score at ${best.holdoutAuc.toFixed(3)} — prefer the holdout number over training metrics when promoting.`;
    }
    static ɵfac = function PSCompareComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || PSCompareComponent)(); };
    static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: PSCompareComponent, selectors: [["ps-compare"]], inputs: { engine: "engine" }, decls: 3, vars: 1, consts: [["data-testid", "ps-compare-panel", 1, "ps-panel", "ps-compare"], ["data-testid", "ps-compare-empty", 1, "ps-empty"], [1, "ps-empty-ico"], [1, "fa-solid", "fa-chart-column"], [1, "cmp-toolbar"], [1, "ps-field", 2, "margin", "0", "min-width", "280px"], ["data-testid", "ps-compare-session", 1, "ps-input", 3, "ngModelChange", "ngModel"], [3, "value"], [1, "ps-spacer"], [1, "ps-small", "ps-muted"], [1, "ps-callout", "info"], [1, "fa-solid", "fa-circle-info"], [1, "ps-small"], ["data-testid", "ps-compare-layout-side", 1, "ps-card"], [1, "ps-card-head"], [1, "ps-muted", "ps-small"], [1, "ps-card-body", 2, "overflow-x", "auto"], [1, "cmp-grid"], [1, "stub"], [1, "colhead", 3, "border-top-color"], [1, "colhead"], [1, "rn"], [1, "ps-badge"], [1, "rowhdr"], [1, "h", "ps-muted", "ps-small"], [1, "cell", 3, "best"], [1, "cell"], [1, "v"], [1, "best-pill"]], template: function PSCompareComponent_Template(rf, ctx) { if (rf & 1) {
            i0.ɵɵelementStart(0, "div", 0);
            i0.ɵɵconditionalCreate(1, PSCompareComponent_Conditional_1_Template, 7, 0, "div", 1)(2, PSCompareComponent_Conditional_2_Template, 12, 3);
            i0.ɵɵelementEnd();
        } if (rf & 2) {
            i0.ɵɵadvance();
            i0.ɵɵconditional(ctx.sessionOptions.length === 0 ? 1 : 2);
        } }, dependencies: [CommonModule, FormsModule, i1.NgSelectOption, i1.ɵNgSelectMultipleOption, i1.SelectControlValueAccessor, i1.NgControlStatus, i1.NgModel], styles: ["/* ============================================================================\n   Predictive Studio \u2014 shared panel styles (design-token compliant)\n   Maps the mockup design system onto MemberJunction semantic --mj-* tokens.\n   Loaded by every PS panel component (styleUrls) under ViewEncapsulation.None,\n   so the class names are global within the PS dashboard subtree.\n   No hardcoded colors except the intentional categorical node/algorithm palette\n   (declared once as --ps-* custom props below) which must stay distinct across\n   light/dark to remain readable as diagram accents.\n   ============================================================================ */\n\n/* Categorical accents for DAG node types + algorithm chips. These are\n   data-visualization colors that must remain distinct regardless of theme\n   (allowed exception #3 in the design-token rules). */\n.ps-panel {\n  --ps-node-source: #6b7280;\n  --ps-node-feature: #2050c8;\n  --ps-node-embedding: #7b3ff0;\n  --ps-node-target: #1f9d57;\n  --ps-node-algorithm: #d98213;\n  /* budget-gauge categorical accents (reuse the node palette so light/dark stay distinct) */\n  --ps-gauge-cost: var(--ps-node-algorithm);\n  --ps-gauge-iterations: var(--ps-node-feature);\n}\n\n.ps-panel {\n  display: block;\n  height: 100%;\n}\n\n/* ---- generic layout helpers ---- */\n.ps-row { display: flex; gap: 16px; }\n.ps-col { display: flex; flex-direction: column; gap: 16px; }\n.ps-wrap { flex-wrap: wrap; }\n.ps-spacer { flex: 1; }\n.ps-muted { color: var(--mj-text-muted); }\n.ps-small { font-size: 12.5px; }\n.ps-mono { font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace; font-size: 12.5px; }\n.ps-section-title {\n  font-size: 12px; text-transform: uppercase; letter-spacing: .06em;\n  color: var(--mj-text-muted); margin: 4px 0 2px; font-weight: 700;\n}\n\n/* ---- cards ---- */\n.ps-card {\n  background: var(--mj-bg-surface);\n  border: 1px solid var(--mj-border-default);\n  border-radius: 10px;\n  box-shadow: var(--mj-shadow-sm);\n  overflow: hidden;\n}\n.ps-card-head {\n  display: flex; align-items: center; gap: 10px;\n  padding: 14px 16px; border-bottom: 1px solid var(--mj-border-subtle);\n}\n.ps-card-head h3 { font-size: 14.5px; margin: 0; font-weight: 650; color: var(--mj-text-primary); }\n.ps-card-body { padding: 16px; }\n\n/* ---- KPI tiles ---- */\n.ps-kpi {\n  background: var(--mj-bg-surface); border: 1px solid var(--mj-border-default);\n  border-radius: 10px; padding: 16px 18px; box-shadow: var(--mj-shadow-sm);\n}\n.ps-kpi .label { font-size: 12px; color: var(--mj-text-muted); font-weight: 600; }\n.ps-kpi .val { font-size: 26px; font-weight: 720; letter-spacing: -.02em; margin-top: 2px; color: var(--mj-text-primary); }\n\n/* ---- badges ---- */\n.ps-badge {\n  display: inline-flex; align-items: center; gap: 5px;\n  padding: 2px 9px; border-radius: 999px; font-size: 11.5px; font-weight: 650; line-height: 1.7;\n}\n.ps-badge.gray { background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary); }\n.ps-badge.blue { background: var(--mj-status-info-bg); color: var(--mj-status-info-text); }\n.ps-badge.green { background: var(--mj-status-success-bg); color: var(--mj-status-success-text); }\n.ps-badge.amber { background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text); }\n.ps-badge.red { background: var(--mj-status-error-bg); color: var(--mj-status-error-text); }\n.ps-dot { width: 7px; height: 7px; border-radius: 50%; display: inline-block; }\n\n/* recommendation-level chips (the ranking matrix payoff) */\n.ps-lvl {\n  display: inline-flex; align-items: center; justify-content: center;\n  min-width: 92px; padding: 4px 10px; border-radius: 7px;\n  font-weight: 650; font-size: 11.5px; color: var(--mj-text-inverse);\n}\n.ps-lvl-Primary { background: var(--mj-status-success); }\n.ps-lvl-Strong { background: var(--mj-status-info); }\n.ps-lvl-Viable { background: var(--mj-status-warning); }\n.ps-lvl-Weak { background: var(--mj-text-disabled); }\n.ps-lvl-NotRecommended { background: var(--mj-bg-surface-sunken); color: var(--mj-text-muted); }\n\n/* ---- tags ---- */\n.ps-tag {\n  display: inline-block; padding: 2px 8px; border-radius: 6px;\n  background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary);\n  font-size: 11.5px; font-weight: 600;\n}\n.ps-tag.muted { opacity: .6; }\n.ps-divider { height: 1px; background: var(--mj-border-subtle); margin: 8px 0; }\n\n/* ---- tables ---- */\n.ps-table { width: 100%; border-collapse: collapse; font-size: 13px; }\n.ps-table th {\n  text-align: left; font-size: 11.5px; text-transform: uppercase; letter-spacing: .04em;\n  color: var(--mj-text-muted); font-weight: 700; padding: 9px 12px;\n  border-bottom: 1px solid var(--mj-border-default);\n}\n.ps-table td { padding: 11px 12px; border-bottom: 1px solid var(--mj-border-subtle); color: var(--mj-text-primary); }\n.ps-table tr:hover td { background: var(--mj-bg-surface-hover); }\n.ps-table .num { text-align: right; font-variant-numeric: tabular-nums; }\n\n.ps-rank {\n  width: 22px; height: 22px; border-radius: 6px; background: var(--mj-bg-surface-sunken);\n  display: inline-grid; place-items: center; font-weight: 700; font-size: 11.5px; color: var(--mj-text-secondary);\n}\n.ps-rank.gold { background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text); }\n\n/* ---- progress bars ---- */\n.ps-bar { height: 8px; border-radius: 999px; background: var(--mj-bg-surface-sunken); overflow: hidden; }\n.ps-bar > span { display: block; height: 100%; border-radius: 999px; background: var(--mj-brand-primary); }\n.ps-bar.warn > span { background: var(--mj-status-warning); }\n.ps-bar.run > span { background: var(--mj-brand-primary); }\n\n.ps-fbar { display: grid; grid-template-columns: 150px 1fr 48px; align-items: center; gap: 10px; padding: 5px 0; }\n.ps-fbar .track { height: 14px; border-radius: 5px; background: var(--mj-bg-surface-sunken); overflow: hidden; }\n.ps-fbar .track > span { display: block; height: 100%; background: var(--mj-brand-primary); }\n.ps-fbar .track > span.warn { background: var(--mj-status-warning); }\n.ps-fbar .name { color: var(--mj-text-secondary); }\n\n/* gauge */\n.ps-gauge {\n  position: relative; width: 64px; height: 64px; border-radius: 50%; flex: 0 0 auto;\n  background: conic-gradient(var(--ps-gauge-color, var(--mj-brand-primary)) calc(var(--ps-p, 40) * 1%), var(--mj-bg-surface-sunken) 0);\n  display: grid; place-items: center;\n}\n.ps-gauge::after { content: ''; position: absolute; inset: 9px; background: var(--mj-bg-surface); border-radius: 50%; }\n.ps-gauge .g-val { position: relative; font-weight: 720; font-size: 14px; color: var(--mj-text-primary); }\n\n/* warning / info callouts */\n.ps-callout { display: flex; gap: 11px; padding: 12px 14px; border-radius: 10px; border: 1px solid; }\n.ps-callout.warn { background: var(--mj-status-warning-bg); border-color: var(--mj-status-warning-border); color: var(--mj-status-warning-text); }\n.ps-callout.info { background: var(--mj-status-info-bg); border-color: var(--mj-status-info-border); color: var(--mj-status-info-text); }\n.ps-callout.success { background: var(--mj-status-success-bg); border-color: var(--mj-status-success-border); color: var(--mj-status-success-text); }\n.ps-callout i { font-size: 16px; margin-top: 1px; }\n\n/* lifecycle stepper */\n.ps-stepper { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }\n.ps-step { display: flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; color: var(--mj-text-muted); }\n.ps-step .pip {\n  width: 22px; height: 22px; border-radius: 50%; border: 2px solid var(--mj-border-strong);\n  display: grid; place-items: center; font-size: 11px;\n}\n.ps-step.done { color: var(--mj-status-success-text); }\n.ps-step.done .pip { background: var(--mj-status-success); border-color: var(--mj-status-success); color: var(--mj-text-inverse); }\n.ps-step.curr { color: var(--mj-brand-primary); }\n.ps-step.curr .pip { border-color: var(--mj-brand-primary); color: var(--mj-brand-primary); }\n.ps-step .ln { width: 26px; height: 2px; background: var(--mj-border-strong); }\n\n/* ---- DAG flow canvas ---- */\n.ps-flow {\n  position: relative;\n  background:\n    linear-gradient(var(--mj-border-subtle) 1px, transparent 1px) 0 0 / 22px 22px,\n    linear-gradient(90deg, var(--mj-border-subtle) 1px, transparent 1px) 0 0 / 22px 22px,\n    var(--mj-bg-surface-card);\n  border: 1px solid var(--mj-border-default); border-radius: 10px;\n  min-height: 620px; overflow: hidden;\n}\n.ps-node {\n  position: absolute; width: 190px; background: var(--mj-bg-surface);\n  border: 1px solid var(--mj-border-strong); border-left-width: 3px; border-radius: 10px;\n  box-shadow: var(--mj-shadow-sm); cursor: pointer;\n}\n.ps-node .nh {\n  display: flex; align-items: center; gap: 8px; padding: 9px 11px;\n  border-bottom: 1px solid var(--mj-border-subtle); font-weight: 650; font-size: 12.5px; color: var(--mj-text-primary);\n}\n.ps-node .nh i.tile {\n  width: 24px; height: 24px; border-radius: 6px; display: grid; place-items: center;\n  color: var(--mj-text-inverse); font-size: 12px; flex: 0 0 auto;\n}\n.ps-node .nh .ps-tag { margin-left: auto; }\n.ps-node .nb { padding: 9px 11px; font-size: 12px; color: var(--mj-text-secondary); }\n.ps-node .nb-row { display: flex; justify-content: space-between; gap: 8px; padding: 2px 0; }\n.ps-node .nb-row .k { color: var(--mj-text-muted); }\n.ps-node.src { border-left-color: var(--ps-node-source); }\n.ps-node.src .nh i.tile { background: var(--ps-node-source); }\n.ps-node.feat { border-left-color: var(--ps-node-feature); }\n.ps-node.feat .nh i.tile { background: var(--ps-node-feature); }\n.ps-node.emb { border-left-color: var(--ps-node-embedding); }\n.ps-node.emb .nh i.tile { background: var(--ps-node-embedding); }\n.ps-node.target { border-left-color: var(--ps-node-target); }\n.ps-node.target .nh i.tile { background: var(--ps-node-target); }\n.ps-node.algo { border-left-color: var(--ps-node-algorithm); }\n.ps-node.algo .nh i.tile { background: var(--ps-node-algorithm); }\n.ps-node.output { border-left-color: var(--mj-status-success); }\n.ps-node.output .nh i.tile { background: var(--mj-status-success); }\n.ps-node.selected {\n  border-color: var(--mj-brand-primary);\n  box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 18%, transparent);\n}\n.ps-node .port {\n  position: absolute; width: 11px; height: 11px; border-radius: 50%;\n  background: var(--mj-bg-surface); border: 2px solid var(--mj-brand-primary);\n  top: 50%; transform: translateY(-50%);\n}\n.ps-node .port.in { left: -6px; }\n.ps-node .port.out { right: -6px; }\nsvg.ps-edges { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }\nsvg.ps-edges path { stroke: color-mix(in srgb, var(--mj-brand-primary) 45%, transparent); stroke-width: 2; fill: none; }\n\n/* palette chips */\n.ps-pchip {\n  display: inline-flex; align-items: center; gap: 7px; padding: 6px 11px; border-radius: 8px;\n  border: 1px dashed var(--mj-border-strong); background: var(--mj-bg-surface);\n  font-size: 12.5px; font-weight: 600; color: var(--mj-text-secondary); cursor: grab;\n}\n.ps-pchip i { font-size: 12px; color: var(--mj-text-inverse); width: 20px; height: 20px; border-radius: 5px; display: grid; place-items: center; }\n.ps-pchip.s i { background: var(--ps-node-source); }\n.ps-pchip.f i { background: var(--ps-node-feature); }\n.ps-pchip.e i { background: var(--ps-node-embedding); }\n.ps-pchip.t i { background: var(--ps-node-target); }\n.ps-pchip.a i { background: var(--ps-node-algorithm); }\n\n/* segmented control */\n.ps-seg { display: inline-flex; border: 1px solid var(--mj-border-default); border-radius: 8px; overflow: hidden; }\n.ps-seg button {\n  border: none; background: var(--mj-bg-surface); color: var(--mj-text-secondary);\n  padding: 6px 12px; font-size: 12.5px; font-weight: 600; cursor: pointer;\n  border-right: 1px solid var(--mj-border-default);\n}\n.ps-seg button:last-child { border-right: none; }\n.ps-seg button.on { background: var(--mj-brand-primary); color: var(--mj-text-inverse); }\n\n/* field control */\n.ps-field { margin-bottom: 14px; }\n.ps-field > label {\n  display: block; font-size: 11px; text-transform: uppercase; letter-spacing: .04em;\n  color: var(--mj-text-muted); font-weight: 700; margin-bottom: 6px;\n}\n.ps-input {\n  width: 100%; padding: 8px 10px; border: 1px solid var(--mj-border-default);\n  border-radius: 6px; font-size: 13px; background: var(--mj-bg-surface); color: var(--mj-text-primary);\n  box-sizing: border-box;\n}\n.ps-input:focus { outline: none; border-color: var(--mj-brand-primary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 12%, transparent); }\n\n/* loading container */\n.ps-loading { display: flex; align-items: center; justify-content: center; padding: 60px 0; }\n\n/* ---- empty / prompt states ---- */\n.ps-empty {\n  display: flex; flex-direction: column; align-items: center; justify-content: center;\n  text-align: center; gap: 10px; padding: 56px 24px; color: var(--mj-text-muted);\n}\n.ps-empty .ps-empty-ico {\n  width: 60px; height: 60px; border-radius: 16px; display: grid; place-items: center;\n  background: var(--mj-bg-surface-sunken); color: var(--mj-text-disabled); font-size: 24px;\n}\n.ps-empty h3 { margin: 4px 0 0; font-size: 16px; font-weight: 650; color: var(--mj-text-secondary); }\n.ps-empty p { margin: 0; max-width: 420px; font-size: 13px; line-height: 1.5; }\n\n/* ---- confirm modal ---- */\n.ps-modal-backdrop {\n  position: fixed; inset: 0; z-index: 1000;\n  background: var(--mj-bg-overlay);\n  display: flex; align-items: center; justify-content: center; padding: 24px;\n}\n.ps-modal {\n  width: 100%; max-width: 480px; background: var(--mj-bg-surface);\n  border: 1px solid var(--mj-border-default); border-radius: 14px;\n  box-shadow: var(--mj-shadow-lg, var(--mj-shadow-sm)); overflow: hidden;\n}\n.ps-modal-head {\n  display: flex; align-items: center; gap: 12px; padding: 18px 20px;\n  border-bottom: 1px solid var(--mj-border-subtle);\n}\n.ps-modal-head .ico {\n  width: 38px; height: 38px; border-radius: 10px; display: grid; place-items: center;\n  font-size: 16px; flex: 0 0 auto;\n  background: var(--mj-status-info-bg); color: var(--mj-status-info-text);\n}\n.ps-modal-head.warn .ico { background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text); }\n.ps-modal-head.danger .ico { background: var(--mj-status-error-bg); color: var(--mj-status-error-text); }\n.ps-modal-head h3 { margin: 0; font-size: 15.5px; font-weight: 650; color: var(--mj-text-primary); }\n.ps-modal-body { padding: 18px 20px; font-size: 13.5px; line-height: 1.55; color: var(--mj-text-secondary); }\n.ps-modal-body .ps-field { margin-top: 14px; margin-bottom: 0; }\n.ps-modal-foot {\n  display: flex; align-items: center; gap: 10px; padding: 14px 20px;\n  border-top: 1px solid var(--mj-border-subtle); background: var(--mj-bg-surface-card);\n}\n.ps-modal-foot .ps-spacer { flex: 1; }\n", ".ps-compare { display: flex; flex-direction: column; gap: 16px; }\n.ps-compare .cmp-toolbar { display: flex; align-items: center; gap: 12px; }\n\n/* side-by-side grid */\n.ps-compare .cmp-grid { display: grid; grid-template-columns: 200px repeat(3, 1fr); gap: 0; min-width: 720px; }\n.ps-compare .cmp-grid .stub { padding: 14px 12px; font-weight: 700; color: var(--mj-text-muted); font-size: 12px; text-transform: uppercase; letter-spacing: .04em; border-bottom: 1px solid var(--mj-border-default); }\n.ps-compare .colhead { padding: 12px; border-top: 3px solid var(--mj-brand-primary); border-bottom: 1px solid var(--mj-border-default); border-left: 1px solid var(--mj-border-subtle); }\n.ps-compare .colhead .rn { font-weight: 700; color: var(--mj-text-primary); }\n.ps-compare .rowhdr { padding: 11px 12px; border-bottom: 1px solid var(--mj-border-subtle); display: flex; flex-direction: column; }\n.ps-compare .rowhdr > span:first-child { color: var(--mj-text-primary); font-weight: 600; font-size: 13px; }\n.ps-compare .cell {\n  padding: 11px 12px; border-bottom: 1px solid var(--mj-border-subtle); border-left: 1px solid var(--mj-border-subtle);\n  display: flex; align-items: center; gap: 8px;\n}\n.ps-compare .cell .v { color: var(--mj-text-primary); font-weight: 600; font-variant-numeric: tabular-nums; }\n.ps-compare .cell.best { background: var(--mj-status-success-bg); }\n.ps-compare .cell.best .v { color: var(--mj-status-success-text); }\n.ps-compare .cell.warn .v { color: var(--mj-status-warning-text); }\n.ps-compare .best-pill { font-size: 9.5px; font-weight: 800; letter-spacing: .05em; color: var(--mj-status-success-text); background: color-mix(in srgb, var(--mj-status-success) 18%, transparent); padding: 1px 6px; border-radius: 999px; }\n\n/* overlay */\n.ps-compare .legend-row { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }\n.ps-compare .legend-row .li { display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px; color: var(--mj-text-secondary); }\n.ps-compare .sw { width: 11px; height: 11px; border-radius: 3px; display: inline-block; }\n.ps-compare .chart-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: start; }\n@media (max-width: 980px) { .ps-compare .chart-grid { grid-template-columns: 1fr; } }\n.ps-compare .chart-grid .span2 { grid-column: 1 / span 2; }\n@media (max-width: 980px) { .ps-compare .chart-grid .span2 { grid-column: auto; } }\n.ps-compare .chart { width: 100%; height: auto; }\n.ps-compare .chart .axis { stroke: var(--mj-border-strong); stroke-width: 1; }\n.ps-compare .chart .chance { stroke: var(--mj-border-strong); stroke-width: 1; stroke-dasharray: 4 4; }\n.ps-compare .chart .threshold { stroke: var(--mj-status-warning); stroke-width: 1.5; stroke-dasharray: 5 4; }\n.ps-compare .chart .axis-lbl { font-size: 10px; fill: var(--mj-text-muted); }\n.ps-compare .chart .warn-lbl { fill: var(--mj-status-warning-text); font-weight: 700; }\n.ps-compare .roc-legend { display: flex; gap: 14px; margin-top: 8px; }\n.ps-compare .roc-legend span { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--mj-text-secondary); font-variant-numeric: tabular-nums; }\n\n/* champion / challenger */\n.ps-compare .reco { align-items: center; }\n.ps-compare .vs-head { display: grid; grid-template-columns: 1fr 64px 1fr; gap: 0; align-items: stretch; }\n@media (max-width: 820px) { .ps-compare .vs-head { grid-template-columns: 1fr; } }\n.ps-compare .vs-card { border: 1px solid var(--mj-border-default); border-radius: 10px; padding: 16px; background: var(--mj-bg-surface); }\n.ps-compare .vs-card.champ { border-top: 4px solid var(--mj-status-success); }\n.ps-compare .vs-card.chall { border-top: 4px solid var(--ps-node-embedding); }\n.ps-compare .vs-card .role { display: inline-flex; align-items: center; gap: 7px; font-size: 12px; font-weight: 700; }\n.ps-compare .vs-card.champ .role { color: var(--mj-status-success-text); }\n.ps-compare .vs-card.chall .role { color: var(--ps-node-embedding); }\n.ps-compare .vs-card .title { font-size: 16px; font-weight: 700; color: var(--mj-text-primary); margin: 8px 0 2px; }\n.ps-compare .vs-stats { display: flex; gap: 18px; margin-top: 14px; }\n.ps-compare .vs-stats strong { font-size: 20px; color: var(--mj-text-primary); }\n.ps-compare .vs-stats .warn-txt { color: var(--mj-status-warning-text); }\n.ps-compare .vs-stats .err-txt { color: var(--mj-status-error-text); }\n.ps-compare .vs-mid { display: grid; place-items: center; font-weight: 800; color: var(--mj-text-muted); background: var(--mj-bg-surface-sunken); border-top: 1px solid var(--mj-border-default); border-bottom: 1px solid var(--mj-border-default); }\n@media (max-width: 820px) { .ps-compare .vs-mid { padding: 8px; } }\n\n.ps-compare .delta-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; }\n@media (max-width: 880px) { .ps-compare .delta-row { grid-template-columns: 1fr 1fr; } }\n.ps-compare .delta { border: 1px solid var(--mj-border-default); border-radius: 10px; padding: 14px; }\n.ps-compare .delta .lab { font-size: 12px; color: var(--mj-text-muted); font-weight: 600; }\n.ps-compare .delta .big { font-size: 20px; font-weight: 720; margin: 4px 0; display: flex; align-items: center; gap: 7px; }\n.ps-compare .delta.up .big { color: var(--mj-status-success-text); }\n.ps-compare .delta.down .big { color: var(--mj-status-error-text); }\n"], encapsulation: 2 });
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PSCompareComponent, [{
        type: Component,
        args: [{ standalone: true, selector: 'ps-compare', imports: [CommonModule, FormsModule], encapsulation: ViewEncapsulation.None, template: `
    <div class="ps-panel ps-compare" data-testid="ps-compare-panel">
      @if (sessionOptions.length === 0) {
        <div class="ps-empty" data-testid="ps-compare-empty">
          <span class="ps-empty-ico"><i class="fa-solid fa-chart-column"></i></span>
          <h3>Nothing to compare yet</h3>
          <p>Run an experiment with at least two scored iterations and you'll be able to line up their metrics side-by-side here to pick a winner.</p>
        </div>
      } @else {
        <!-- toolbar: session picker -->
        <div class="cmp-toolbar">
          <div class="ps-field" style="margin:0;min-width:280px">
            <label>Session to compare</label>
            <select class="ps-input" data-testid="ps-compare-session" [(ngModel)]="selectedSessionId" (ngModelChange)="rebuild()">
              @for (s of sessionOptions; track s.id) {
                <option [value]="s.id">{{ s.name }} · {{ s.scoredCount }} scored</option>
              }
            </select>
          </div>
          <span class="ps-spacer"></span>
          <span class="ps-small ps-muted">{{ runs.length }} top runs · ranked by score</span>
        </div>

        @if (runs.length < 2) {
          <div class="ps-callout info">
            <i class="fa-solid fa-circle-info"></i>
            <div class="ps-small">This session has fewer than two scored iterations — pick another session to compare.</div>
          </div>
        } @else {
          <div class="ps-card" data-testid="ps-compare-layout-side">
            <div class="ps-card-head"><h3>Side-by-side comparison</h3><span class="ps-muted ps-small">Best value in each row highlighted</span></div>
            <div class="ps-card-body" style="overflow-x:auto">
              <div class="cmp-grid" [style.grid-template-columns]="gridTemplate">
                <div class="stub">Run / Metric</div>
                @for (r of runs; track r.key) {
                  <div class="colhead" [style.border-top-color]="r.color">
                    <div class="rn">{{ r.label }}</div>
                    <div class="ps-muted ps-small">{{ r.algorithm }} · {{ r.descriptor }}</div>
                    <span class="ps-badge" [class]="r.isBest ? 'green' : 'gray'">{{ r.isBest ? 'Top scorer' : r.status }}</span>
                  </div>
                }
                @for (row of metricRows; track row.label) {
                  <div class="rowhdr"><span>{{ row.label }}</span><span class="h ps-muted ps-small">{{ row.qualifier }}</span></div>
                  @for (v of row.values; track $index) {
                    <div class="cell" [class.best]="$index === row.bestIndex">
                      <span class="v">{{ v }}</span>
                      @if ($index === row.bestIndex) { <span class="best-pill">BEST</span> }
                    </div>
                  }
                }
              </div>
            </div>
          </div>
          <div class="ps-callout info">
            <i class="fa-solid fa-circle-info"></i>
            <div class="ps-small">
              <strong>{{ verdict }}</strong>
            </div>
          </div>
        }
      }
    </div>
  `, styles: ["/* ============================================================================\n   Predictive Studio \u2014 shared panel styles (design-token compliant)\n   Maps the mockup design system onto MemberJunction semantic --mj-* tokens.\n   Loaded by every PS panel component (styleUrls) under ViewEncapsulation.None,\n   so the class names are global within the PS dashboard subtree.\n   No hardcoded colors except the intentional categorical node/algorithm palette\n   (declared once as --ps-* custom props below) which must stay distinct across\n   light/dark to remain readable as diagram accents.\n   ============================================================================ */\n\n/* Categorical accents for DAG node types + algorithm chips. These are\n   data-visualization colors that must remain distinct regardless of theme\n   (allowed exception #3 in the design-token rules). */\n.ps-panel {\n  --ps-node-source: #6b7280;\n  --ps-node-feature: #2050c8;\n  --ps-node-embedding: #7b3ff0;\n  --ps-node-target: #1f9d57;\n  --ps-node-algorithm: #d98213;\n  /* budget-gauge categorical accents (reuse the node palette so light/dark stay distinct) */\n  --ps-gauge-cost: var(--ps-node-algorithm);\n  --ps-gauge-iterations: var(--ps-node-feature);\n}\n\n.ps-panel {\n  display: block;\n  height: 100%;\n}\n\n/* ---- generic layout helpers ---- */\n.ps-row { display: flex; gap: 16px; }\n.ps-col { display: flex; flex-direction: column; gap: 16px; }\n.ps-wrap { flex-wrap: wrap; }\n.ps-spacer { flex: 1; }\n.ps-muted { color: var(--mj-text-muted); }\n.ps-small { font-size: 12.5px; }\n.ps-mono { font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace; font-size: 12.5px; }\n.ps-section-title {\n  font-size: 12px; text-transform: uppercase; letter-spacing: .06em;\n  color: var(--mj-text-muted); margin: 4px 0 2px; font-weight: 700;\n}\n\n/* ---- cards ---- */\n.ps-card {\n  background: var(--mj-bg-surface);\n  border: 1px solid var(--mj-border-default);\n  border-radius: 10px;\n  box-shadow: var(--mj-shadow-sm);\n  overflow: hidden;\n}\n.ps-card-head {\n  display: flex; align-items: center; gap: 10px;\n  padding: 14px 16px; border-bottom: 1px solid var(--mj-border-subtle);\n}\n.ps-card-head h3 { font-size: 14.5px; margin: 0; font-weight: 650; color: var(--mj-text-primary); }\n.ps-card-body { padding: 16px; }\n\n/* ---- KPI tiles ---- */\n.ps-kpi {\n  background: var(--mj-bg-surface); border: 1px solid var(--mj-border-default);\n  border-radius: 10px; padding: 16px 18px; box-shadow: var(--mj-shadow-sm);\n}\n.ps-kpi .label { font-size: 12px; color: var(--mj-text-muted); font-weight: 600; }\n.ps-kpi .val { font-size: 26px; font-weight: 720; letter-spacing: -.02em; margin-top: 2px; color: var(--mj-text-primary); }\n\n/* ---- badges ---- */\n.ps-badge {\n  display: inline-flex; align-items: center; gap: 5px;\n  padding: 2px 9px; border-radius: 999px; font-size: 11.5px; font-weight: 650; line-height: 1.7;\n}\n.ps-badge.gray { background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary); }\n.ps-badge.blue { background: var(--mj-status-info-bg); color: var(--mj-status-info-text); }\n.ps-badge.green { background: var(--mj-status-success-bg); color: var(--mj-status-success-text); }\n.ps-badge.amber { background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text); }\n.ps-badge.red { background: var(--mj-status-error-bg); color: var(--mj-status-error-text); }\n.ps-dot { width: 7px; height: 7px; border-radius: 50%; display: inline-block; }\n\n/* recommendation-level chips (the ranking matrix payoff) */\n.ps-lvl {\n  display: inline-flex; align-items: center; justify-content: center;\n  min-width: 92px; padding: 4px 10px; border-radius: 7px;\n  font-weight: 650; font-size: 11.5px; color: var(--mj-text-inverse);\n}\n.ps-lvl-Primary { background: var(--mj-status-success); }\n.ps-lvl-Strong { background: var(--mj-status-info); }\n.ps-lvl-Viable { background: var(--mj-status-warning); }\n.ps-lvl-Weak { background: var(--mj-text-disabled); }\n.ps-lvl-NotRecommended { background: var(--mj-bg-surface-sunken); color: var(--mj-text-muted); }\n\n/* ---- tags ---- */\n.ps-tag {\n  display: inline-block; padding: 2px 8px; border-radius: 6px;\n  background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary);\n  font-size: 11.5px; font-weight: 600;\n}\n.ps-tag.muted { opacity: .6; }\n.ps-divider { height: 1px; background: var(--mj-border-subtle); margin: 8px 0; }\n\n/* ---- tables ---- */\n.ps-table { width: 100%; border-collapse: collapse; font-size: 13px; }\n.ps-table th {\n  text-align: left; font-size: 11.5px; text-transform: uppercase; letter-spacing: .04em;\n  color: var(--mj-text-muted); font-weight: 700; padding: 9px 12px;\n  border-bottom: 1px solid var(--mj-border-default);\n}\n.ps-table td { padding: 11px 12px; border-bottom: 1px solid var(--mj-border-subtle); color: var(--mj-text-primary); }\n.ps-table tr:hover td { background: var(--mj-bg-surface-hover); }\n.ps-table .num { text-align: right; font-variant-numeric: tabular-nums; }\n\n.ps-rank {\n  width: 22px; height: 22px; border-radius: 6px; background: var(--mj-bg-surface-sunken);\n  display: inline-grid; place-items: center; font-weight: 700; font-size: 11.5px; color: var(--mj-text-secondary);\n}\n.ps-rank.gold { background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text); }\n\n/* ---- progress bars ---- */\n.ps-bar { height: 8px; border-radius: 999px; background: var(--mj-bg-surface-sunken); overflow: hidden; }\n.ps-bar > span { display: block; height: 100%; border-radius: 999px; background: var(--mj-brand-primary); }\n.ps-bar.warn > span { background: var(--mj-status-warning); }\n.ps-bar.run > span { background: var(--mj-brand-primary); }\n\n.ps-fbar { display: grid; grid-template-columns: 150px 1fr 48px; align-items: center; gap: 10px; padding: 5px 0; }\n.ps-fbar .track { height: 14px; border-radius: 5px; background: var(--mj-bg-surface-sunken); overflow: hidden; }\n.ps-fbar .track > span { display: block; height: 100%; background: var(--mj-brand-primary); }\n.ps-fbar .track > span.warn { background: var(--mj-status-warning); }\n.ps-fbar .name { color: var(--mj-text-secondary); }\n\n/* gauge */\n.ps-gauge {\n  position: relative; width: 64px; height: 64px; border-radius: 50%; flex: 0 0 auto;\n  background: conic-gradient(var(--ps-gauge-color, var(--mj-brand-primary)) calc(var(--ps-p, 40) * 1%), var(--mj-bg-surface-sunken) 0);\n  display: grid; place-items: center;\n}\n.ps-gauge::after { content: ''; position: absolute; inset: 9px; background: var(--mj-bg-surface); border-radius: 50%; }\n.ps-gauge .g-val { position: relative; font-weight: 720; font-size: 14px; color: var(--mj-text-primary); }\n\n/* warning / info callouts */\n.ps-callout { display: flex; gap: 11px; padding: 12px 14px; border-radius: 10px; border: 1px solid; }\n.ps-callout.warn { background: var(--mj-status-warning-bg); border-color: var(--mj-status-warning-border); color: var(--mj-status-warning-text); }\n.ps-callout.info { background: var(--mj-status-info-bg); border-color: var(--mj-status-info-border); color: var(--mj-status-info-text); }\n.ps-callout.success { background: var(--mj-status-success-bg); border-color: var(--mj-status-success-border); color: var(--mj-status-success-text); }\n.ps-callout i { font-size: 16px; margin-top: 1px; }\n\n/* lifecycle stepper */\n.ps-stepper { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }\n.ps-step { display: flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; color: var(--mj-text-muted); }\n.ps-step .pip {\n  width: 22px; height: 22px; border-radius: 50%; border: 2px solid var(--mj-border-strong);\n  display: grid; place-items: center; font-size: 11px;\n}\n.ps-step.done { color: var(--mj-status-success-text); }\n.ps-step.done .pip { background: var(--mj-status-success); border-color: var(--mj-status-success); color: var(--mj-text-inverse); }\n.ps-step.curr { color: var(--mj-brand-primary); }\n.ps-step.curr .pip { border-color: var(--mj-brand-primary); color: var(--mj-brand-primary); }\n.ps-step .ln { width: 26px; height: 2px; background: var(--mj-border-strong); }\n\n/* ---- DAG flow canvas ---- */\n.ps-flow {\n  position: relative;\n  background:\n    linear-gradient(var(--mj-border-subtle) 1px, transparent 1px) 0 0 / 22px 22px,\n    linear-gradient(90deg, var(--mj-border-subtle) 1px, transparent 1px) 0 0 / 22px 22px,\n    var(--mj-bg-surface-card);\n  border: 1px solid var(--mj-border-default); border-radius: 10px;\n  min-height: 620px; overflow: hidden;\n}\n.ps-node {\n  position: absolute; width: 190px; background: var(--mj-bg-surface);\n  border: 1px solid var(--mj-border-strong); border-left-width: 3px; border-radius: 10px;\n  box-shadow: var(--mj-shadow-sm); cursor: pointer;\n}\n.ps-node .nh {\n  display: flex; align-items: center; gap: 8px; padding: 9px 11px;\n  border-bottom: 1px solid var(--mj-border-subtle); font-weight: 650; font-size: 12.5px; color: var(--mj-text-primary);\n}\n.ps-node .nh i.tile {\n  width: 24px; height: 24px; border-radius: 6px; display: grid; place-items: center;\n  color: var(--mj-text-inverse); font-size: 12px; flex: 0 0 auto;\n}\n.ps-node .nh .ps-tag { margin-left: auto; }\n.ps-node .nb { padding: 9px 11px; font-size: 12px; color: var(--mj-text-secondary); }\n.ps-node .nb-row { display: flex; justify-content: space-between; gap: 8px; padding: 2px 0; }\n.ps-node .nb-row .k { color: var(--mj-text-muted); }\n.ps-node.src { border-left-color: var(--ps-node-source); }\n.ps-node.src .nh i.tile { background: var(--ps-node-source); }\n.ps-node.feat { border-left-color: var(--ps-node-feature); }\n.ps-node.feat .nh i.tile { background: var(--ps-node-feature); }\n.ps-node.emb { border-left-color: var(--ps-node-embedding); }\n.ps-node.emb .nh i.tile { background: var(--ps-node-embedding); }\n.ps-node.target { border-left-color: var(--ps-node-target); }\n.ps-node.target .nh i.tile { background: var(--ps-node-target); }\n.ps-node.algo { border-left-color: var(--ps-node-algorithm); }\n.ps-node.algo .nh i.tile { background: var(--ps-node-algorithm); }\n.ps-node.output { border-left-color: var(--mj-status-success); }\n.ps-node.output .nh i.tile { background: var(--mj-status-success); }\n.ps-node.selected {\n  border-color: var(--mj-brand-primary);\n  box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 18%, transparent);\n}\n.ps-node .port {\n  position: absolute; width: 11px; height: 11px; border-radius: 50%;\n  background: var(--mj-bg-surface); border: 2px solid var(--mj-brand-primary);\n  top: 50%; transform: translateY(-50%);\n}\n.ps-node .port.in { left: -6px; }\n.ps-node .port.out { right: -6px; }\nsvg.ps-edges { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }\nsvg.ps-edges path { stroke: color-mix(in srgb, var(--mj-brand-primary) 45%, transparent); stroke-width: 2; fill: none; }\n\n/* palette chips */\n.ps-pchip {\n  display: inline-flex; align-items: center; gap: 7px; padding: 6px 11px; border-radius: 8px;\n  border: 1px dashed var(--mj-border-strong); background: var(--mj-bg-surface);\n  font-size: 12.5px; font-weight: 600; color: var(--mj-text-secondary); cursor: grab;\n}\n.ps-pchip i { font-size: 12px; color: var(--mj-text-inverse); width: 20px; height: 20px; border-radius: 5px; display: grid; place-items: center; }\n.ps-pchip.s i { background: var(--ps-node-source); }\n.ps-pchip.f i { background: var(--ps-node-feature); }\n.ps-pchip.e i { background: var(--ps-node-embedding); }\n.ps-pchip.t i { background: var(--ps-node-target); }\n.ps-pchip.a i { background: var(--ps-node-algorithm); }\n\n/* segmented control */\n.ps-seg { display: inline-flex; border: 1px solid var(--mj-border-default); border-radius: 8px; overflow: hidden; }\n.ps-seg button {\n  border: none; background: var(--mj-bg-surface); color: var(--mj-text-secondary);\n  padding: 6px 12px; font-size: 12.5px; font-weight: 600; cursor: pointer;\n  border-right: 1px solid var(--mj-border-default);\n}\n.ps-seg button:last-child { border-right: none; }\n.ps-seg button.on { background: var(--mj-brand-primary); color: var(--mj-text-inverse); }\n\n/* field control */\n.ps-field { margin-bottom: 14px; }\n.ps-field > label {\n  display: block; font-size: 11px; text-transform: uppercase; letter-spacing: .04em;\n  color: var(--mj-text-muted); font-weight: 700; margin-bottom: 6px;\n}\n.ps-input {\n  width: 100%; padding: 8px 10px; border: 1px solid var(--mj-border-default);\n  border-radius: 6px; font-size: 13px; background: var(--mj-bg-surface); color: var(--mj-text-primary);\n  box-sizing: border-box;\n}\n.ps-input:focus { outline: none; border-color: var(--mj-brand-primary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 12%, transparent); }\n\n/* loading container */\n.ps-loading { display: flex; align-items: center; justify-content: center; padding: 60px 0; }\n\n/* ---- empty / prompt states ---- */\n.ps-empty {\n  display: flex; flex-direction: column; align-items: center; justify-content: center;\n  text-align: center; gap: 10px; padding: 56px 24px; color: var(--mj-text-muted);\n}\n.ps-empty .ps-empty-ico {\n  width: 60px; height: 60px; border-radius: 16px; display: grid; place-items: center;\n  background: var(--mj-bg-surface-sunken); color: var(--mj-text-disabled); font-size: 24px;\n}\n.ps-empty h3 { margin: 4px 0 0; font-size: 16px; font-weight: 650; color: var(--mj-text-secondary); }\n.ps-empty p { margin: 0; max-width: 420px; font-size: 13px; line-height: 1.5; }\n\n/* ---- confirm modal ---- */\n.ps-modal-backdrop {\n  position: fixed; inset: 0; z-index: 1000;\n  background: var(--mj-bg-overlay);\n  display: flex; align-items: center; justify-content: center; padding: 24px;\n}\n.ps-modal {\n  width: 100%; max-width: 480px; background: var(--mj-bg-surface);\n  border: 1px solid var(--mj-border-default); border-radius: 14px;\n  box-shadow: var(--mj-shadow-lg, var(--mj-shadow-sm)); overflow: hidden;\n}\n.ps-modal-head {\n  display: flex; align-items: center; gap: 12px; padding: 18px 20px;\n  border-bottom: 1px solid var(--mj-border-subtle);\n}\n.ps-modal-head .ico {\n  width: 38px; height: 38px; border-radius: 10px; display: grid; place-items: center;\n  font-size: 16px; flex: 0 0 auto;\n  background: var(--mj-status-info-bg); color: var(--mj-status-info-text);\n}\n.ps-modal-head.warn .ico { background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text); }\n.ps-modal-head.danger .ico { background: var(--mj-status-error-bg); color: var(--mj-status-error-text); }\n.ps-modal-head h3 { margin: 0; font-size: 15.5px; font-weight: 650; color: var(--mj-text-primary); }\n.ps-modal-body { padding: 18px 20px; font-size: 13.5px; line-height: 1.55; color: var(--mj-text-secondary); }\n.ps-modal-body .ps-field { margin-top: 14px; margin-bottom: 0; }\n.ps-modal-foot {\n  display: flex; align-items: center; gap: 10px; padding: 14px 20px;\n  border-top: 1px solid var(--mj-border-subtle); background: var(--mj-bg-surface-card);\n}\n.ps-modal-foot .ps-spacer { flex: 1; }\n", ".ps-compare { display: flex; flex-direction: column; gap: 16px; }\n.ps-compare .cmp-toolbar { display: flex; align-items: center; gap: 12px; }\n\n/* side-by-side grid */\n.ps-compare .cmp-grid { display: grid; grid-template-columns: 200px repeat(3, 1fr); gap: 0; min-width: 720px; }\n.ps-compare .cmp-grid .stub { padding: 14px 12px; font-weight: 700; color: var(--mj-text-muted); font-size: 12px; text-transform: uppercase; letter-spacing: .04em; border-bottom: 1px solid var(--mj-border-default); }\n.ps-compare .colhead { padding: 12px; border-top: 3px solid var(--mj-brand-primary); border-bottom: 1px solid var(--mj-border-default); border-left: 1px solid var(--mj-border-subtle); }\n.ps-compare .colhead .rn { font-weight: 700; color: var(--mj-text-primary); }\n.ps-compare .rowhdr { padding: 11px 12px; border-bottom: 1px solid var(--mj-border-subtle); display: flex; flex-direction: column; }\n.ps-compare .rowhdr > span:first-child { color: var(--mj-text-primary); font-weight: 600; font-size: 13px; }\n.ps-compare .cell {\n  padding: 11px 12px; border-bottom: 1px solid var(--mj-border-subtle); border-left: 1px solid var(--mj-border-subtle);\n  display: flex; align-items: center; gap: 8px;\n}\n.ps-compare .cell .v { color: var(--mj-text-primary); font-weight: 600; font-variant-numeric: tabular-nums; }\n.ps-compare .cell.best { background: var(--mj-status-success-bg); }\n.ps-compare .cell.best .v { color: var(--mj-status-success-text); }\n.ps-compare .cell.warn .v { color: var(--mj-status-warning-text); }\n.ps-compare .best-pill { font-size: 9.5px; font-weight: 800; letter-spacing: .05em; color: var(--mj-status-success-text); background: color-mix(in srgb, var(--mj-status-success) 18%, transparent); padding: 1px 6px; border-radius: 999px; }\n\n/* overlay */\n.ps-compare .legend-row { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }\n.ps-compare .legend-row .li { display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px; color: var(--mj-text-secondary); }\n.ps-compare .sw { width: 11px; height: 11px; border-radius: 3px; display: inline-block; }\n.ps-compare .chart-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: start; }\n@media (max-width: 980px) { .ps-compare .chart-grid { grid-template-columns: 1fr; } }\n.ps-compare .chart-grid .span2 { grid-column: 1 / span 2; }\n@media (max-width: 980px) { .ps-compare .chart-grid .span2 { grid-column: auto; } }\n.ps-compare .chart { width: 100%; height: auto; }\n.ps-compare .chart .axis { stroke: var(--mj-border-strong); stroke-width: 1; }\n.ps-compare .chart .chance { stroke: var(--mj-border-strong); stroke-width: 1; stroke-dasharray: 4 4; }\n.ps-compare .chart .threshold { stroke: var(--mj-status-warning); stroke-width: 1.5; stroke-dasharray: 5 4; }\n.ps-compare .chart .axis-lbl { font-size: 10px; fill: var(--mj-text-muted); }\n.ps-compare .chart .warn-lbl { fill: var(--mj-status-warning-text); font-weight: 700; }\n.ps-compare .roc-legend { display: flex; gap: 14px; margin-top: 8px; }\n.ps-compare .roc-legend span { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--mj-text-secondary); font-variant-numeric: tabular-nums; }\n\n/* champion / challenger */\n.ps-compare .reco { align-items: center; }\n.ps-compare .vs-head { display: grid; grid-template-columns: 1fr 64px 1fr; gap: 0; align-items: stretch; }\n@media (max-width: 820px) { .ps-compare .vs-head { grid-template-columns: 1fr; } }\n.ps-compare .vs-card { border: 1px solid var(--mj-border-default); border-radius: 10px; padding: 16px; background: var(--mj-bg-surface); }\n.ps-compare .vs-card.champ { border-top: 4px solid var(--mj-status-success); }\n.ps-compare .vs-card.chall { border-top: 4px solid var(--ps-node-embedding); }\n.ps-compare .vs-card .role { display: inline-flex; align-items: center; gap: 7px; font-size: 12px; font-weight: 700; }\n.ps-compare .vs-card.champ .role { color: var(--mj-status-success-text); }\n.ps-compare .vs-card.chall .role { color: var(--ps-node-embedding); }\n.ps-compare .vs-card .title { font-size: 16px; font-weight: 700; color: var(--mj-text-primary); margin: 8px 0 2px; }\n.ps-compare .vs-stats { display: flex; gap: 18px; margin-top: 14px; }\n.ps-compare .vs-stats strong { font-size: 20px; color: var(--mj-text-primary); }\n.ps-compare .vs-stats .warn-txt { color: var(--mj-status-warning-text); }\n.ps-compare .vs-stats .err-txt { color: var(--mj-status-error-text); }\n.ps-compare .vs-mid { display: grid; place-items: center; font-weight: 800; color: var(--mj-text-muted); background: var(--mj-bg-surface-sunken); border-top: 1px solid var(--mj-border-default); border-bottom: 1px solid var(--mj-border-default); }\n@media (max-width: 820px) { .ps-compare .vs-mid { padding: 8px; } }\n\n.ps-compare .delta-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; }\n@media (max-width: 880px) { .ps-compare .delta-row { grid-template-columns: 1fr 1fr; } }\n.ps-compare .delta { border: 1px solid var(--mj-border-default); border-radius: 10px; padding: 14px; }\n.ps-compare .delta .lab { font-size: 12px; color: var(--mj-text-muted); font-weight: 600; }\n.ps-compare .delta .big { font-size: 20px; font-weight: 720; margin: 4px 0; display: flex; align-items: center; gap: 7px; }\n.ps-compare .delta.up .big { color: var(--mj-status-success-text); }\n.ps-compare .delta.down .big { color: var(--mj-status-error-text); }\n"] }]
    }], null, { engine: [{
            type: Input
        }] }); })();
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(PSCompareComponent, { className: "PSCompareComponent", filePath: "src/PredictiveStudio/components/ps-compare.component.ts", lineNumber: 100 }); })();
//# sourceMappingURL=ps-compare.component.js.map