@memberjunction/ng-dashboards 5.46.0 → 5.47.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/PredictiveStudio/at-risk.view-models.d.ts +33 -0
- package/dist/PredictiveStudio/at-risk.view-models.d.ts.map +1 -1
- package/dist/PredictiveStudio/at-risk.view-models.js +69 -2
- package/dist/PredictiveStudio/at-risk.view-models.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-catalog.component.js +2 -2
- package/dist/PredictiveStudio/components/ps-catalog.component.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-compare.component.js +2 -2
- package/dist/PredictiveStudio/components/ps-compare.component.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-confirm-modal.component.js +2 -2
- package/dist/PredictiveStudio/components/ps-confirm-modal.component.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-experiments.component.js +2 -2
- package/dist/PredictiveStudio/components/ps-experiments.component.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-home.component.js +2 -2
- package/dist/PredictiveStudio/components/ps-home.component.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-operate-dialog.component.js +2 -2
- package/dist/PredictiveStudio/components/ps-operate-dialog.component.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-pipelines.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/components/ps-pipelines.component.js +306 -297
- package/dist/PredictiveStudio/components/ps-pipelines.component.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-production.component.js +2 -2
- package/dist/PredictiveStudio/components/ps-production.component.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-registry.component.d.ts +1 -1
- package/dist/PredictiveStudio/components/ps-registry.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/components/ps-registry.component.js +15 -9
- package/dist/PredictiveStudio/components/ps-registry.component.js.map +1 -1
- package/dist/PredictiveStudio/predictive-studio-agent-context.d.ts +115 -0
- package/dist/PredictiveStudio/predictive-studio-agent-context.d.ts.map +1 -0
- package/dist/PredictiveStudio/predictive-studio-agent-context.js +119 -0
- package/dist/PredictiveStudio/predictive-studio-agent-context.js.map +1 -0
- package/dist/PredictiveStudio/predictive-studio-copilot.view-models.d.ts +36 -0
- package/dist/PredictiveStudio/predictive-studio-copilot.view-models.d.ts.map +1 -0
- package/dist/PredictiveStudio/predictive-studio-copilot.view-models.js +52 -0
- package/dist/PredictiveStudio/predictive-studio-copilot.view-models.js.map +1 -0
- package/dist/PredictiveStudio/resources/ps-models-resource.component.d.ts +9 -1
- package/dist/PredictiveStudio/resources/ps-models-resource.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/resources/ps-models-resource.component.js +133 -56
- package/dist/PredictiveStudio/resources/ps-models-resource.component.js.map +1 -1
- package/dist/PredictiveStudio/resources/ps-predictions-resource.component.d.ts +50 -1
- package/dist/PredictiveStudio/resources/ps-predictions-resource.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/resources/ps-predictions-resource.component.js +591 -165
- package/dist/PredictiveStudio/resources/ps-predictions-resource.component.js.map +1 -1
- package/dist/PredictiveStudio/resources/ps-resource-base.d.ts +17 -0
- package/dist/PredictiveStudio/resources/ps-resource-base.d.ts.map +1 -1
- package/dist/PredictiveStudio/resources/ps-resource-base.js +27 -1
- package/dist/PredictiveStudio/resources/ps-resource-base.js.map +1 -1
- package/dist/PredictiveStudio/resources/ps-studio-resource.component.d.ts +11 -1
- package/dist/PredictiveStudio/resources/ps-studio-resource.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/resources/ps-studio-resource.component.js +199 -99
- package/dist/PredictiveStudio/resources/ps-studio-resource.component.js.map +1 -1
- package/package.json +59 -59
|
@@ -627,7 +627,7 @@ export class PSExperimentsComponent {
|
|
|
627
627
|
i0.ɵɵconditional(!ctx.session ? 1 : 2);
|
|
628
628
|
i0.ɵɵadvance(2);
|
|
629
629
|
i0.ɵɵconditional(ctx.pendingAction ? 3 : -1);
|
|
630
|
-
} }, dependencies: [CommonModule, i1.NgTemplateOutlet, MJButtonDirective, PSConfirmModalComponent, i1.DecimalPipe], 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-experiments { display: flex; flex-direction: column; gap: 16px; }\n\n.ps-experiments .sess-head { display: flex; align-items: center; gap: 12px; }\n.ps-experiments .sess-head h2 { font-size: 18px; color: var(--mj-text-primary); display: flex; align-items: center; gap: 10px; }\n\n/* leaderboard strip */\n.ps-experiments .lead-strip { display: flex; gap: 10px; align-items: center; overflow-x: auto; }\n.ps-experiments .lead-lbl { padding-right: 14px; border-right: 1px solid var(--mj-border-default); flex: 0 0 auto; }\n.ps-experiments .lead-lbl .t { display: flex; align-items: center; gap: 7px; font-weight: 650; color: var(--mj-text-primary); }\n.ps-experiments .lp {\n display: flex; align-items: center; gap: 9px; flex: 0 0 auto; padding: 8px 12px;\n border: 1px solid var(--mj-border-default); border-radius: 9px; background: var(--mj-bg-surface);\n}\n.ps-experiments .lp.best { background: var(--mj-status-warning-bg); border-color: var(--mj-status-warning-border); }\n.ps-experiments .lp.pruned { opacity: .55; }\n.ps-experiments .algo-ic {\n width: 26px; height: 26px; border-radius: 7px; display: grid; place-items: center;\n color: var(--mj-text-inverse); font-size: 12px; flex: 0 0 auto;\n}\n.ps-experiments .lp .nm { font-size: 12.5px; font-weight: 600; color: var(--mj-text-primary); }\n.ps-experiments .lp .auc { font-weight: 740; font-variant-numeric: tabular-nums; color: var(--mj-text-primary); }\n.ps-experiments .lp .auc.win { color: var(--mj-status-success-text); }\n\n/* budget rail */\n.ps-experiments .budget-rail { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }\n@media (max-width: 880px) { .ps-experiments .budget-rail { grid-template-columns: 1fr; } }\n.ps-experiments .bud { display: flex; align-items: center; gap: 13px; }\n.ps-experiments .b-val { font-size: 15px; color: var(--mj-text-primary); margin-top: 2px; }\n\n/* kanban */\n.ps-experiments .kanban { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; align-items: start; }\n@media (max-width: 980px) { .ps-experiments .kanban { grid-template-columns: 1fr; } }\n.ps-experiments .kcol { background: var(--mj-bg-surface); border: 1px solid var(--mj-border-default); border-radius: 10px; overflow: hidden; }\n.ps-experiments .kcol-head {\n display: flex; align-items: center; gap: 9px; padding: 12px 14px; border-bottom: 1px solid var(--mj-border-subtle);\n font-weight: 650; color: var(--mj-text-primary);\n}\n.ps-experiments .kcol-head h3 { font-size: 13.5px; margin: 0; flex: 1; }\n.ps-experiments .kcol.run .kcol-head { border-top: 3px solid var(--mj-brand-primary); }\n.ps-experiments .kcol.done .kcol-head { border-top: 3px solid var(--mj-status-success); }\n.ps-experiments .kcol.prune .kcol-head { border-top: 3px solid var(--mj-text-disabled); }\n.ps-experiments .kcol.run .kcol-head i { color: var(--mj-brand-primary); }\n.ps-experiments .kcol.done .kcol-head i { color: var(--mj-status-success); }\n.ps-experiments .kcol.prune .kcol-head i { color: var(--mj-text-muted); }\n.ps-experiments .cnt {\n background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary);\n border-radius: 999px; padding: 1px 9px; font-size: 12px; font-weight: 700;\n}\n.ps-experiments .kbody { padding: 11px; display: flex; flex-direction: column; gap: 11px; }\n\n.ps-experiments .icard {\n border: 1px solid var(--mj-border-default); border-radius: 9px; padding: 11px;\n background: var(--mj-bg-surface-card); display: flex; flex-direction: column; gap: 9px;\n}\n.ps-experiments .icard.running { border-color: color-mix(in srgb, var(--mj-brand-primary) 40%, var(--mj-border-default)); }\n.ps-experiments .icard.best { border-left: 3px solid var(--mj-status-warning); }\n.ps-experiments .icard.pruned { opacity: .78; }\n.ps-experiments .ic-top { display: flex; align-items: center; gap: 9px; }\n.ps-experiments .ic-top .algo-ic { width: 30px; height: 30px; }\n.ps-experiments .ic-top .nm { font-weight: 600; color: var(--mj-text-primary); font-size: 13px; }\n.ps-experiments .feat-chips { display: flex; gap: 6px; flex-wrap: wrap; }\n.ps-experiments .ic-prog .meta { display: flex; justify-content: space-between; margin-top: 5px; }\n.ps-experiments .ic-score { display: flex; align-items: baseline; gap: 8px; }\n.ps-experiments .ic-score .v { font-size: 21px; font-weight: 720; color: var(--mj-text-primary); font-variant-numeric: tabular-nums; }\n.ps-experiments .ic-score .v.green { color: var(--mj-status-success-text); }\n.ps-experiments .rationale {\n display: flex; gap: 8px; padding-top: 8px; border-top: 1px solid var(--mj-border-subtle); color: var(--mj-text-secondary);\n}\n.ps-experiments .rationale i { color: var(--mj-brand-primary); margin-top: 2px; }\n"], encapsulation: 2 });
|
|
630
|
+
} }, dependencies: [CommonModule, i1.NgTemplateOutlet, MJButtonDirective, PSConfirmModalComponent, i1.DecimalPipe], 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: 8px;\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: 8px; padding: 16px 18px;\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: minmax(150px, 1.3fr) 2fr 56px; align-items: center; gap: 14px; padding: 8px 0; }\n.ps-fbar + .ps-fbar { border-top: 1px solid var(--mj-border-subtle); }\n.ps-fbar .track { height: 10px; border-radius: var(--mj-radius-full); background: var(--mj-bg-surface-sunken); overflow: hidden; }\n.ps-fbar .track > span { display: block; height: 100%; border-radius: var(--mj-radius-full); background: var(--mj-brand-primary); }\n.ps-fbar .track > span.warn { background: var(--mj-status-warning); }\n.ps-fbar .name { color: var(--mj-text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.ps-fbar > .ps-mono { text-align: right; color: var(--mj-text-secondary); font-variant-numeric: tabular-nums; }\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: 8px;\n 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-experiments { display: flex; flex-direction: column; gap: 16px; }\n\n.ps-experiments .sess-head { display: flex; align-items: center; gap: 12px; }\n.ps-experiments .sess-head h2 { font-size: 18px; color: var(--mj-text-primary); display: flex; align-items: center; gap: 10px; }\n\n/* leaderboard strip */\n.ps-experiments .lead-strip { display: flex; gap: 10px; align-items: center; overflow-x: auto; }\n.ps-experiments .lead-lbl { padding-right: 14px; border-right: 1px solid var(--mj-border-default); flex: 0 0 auto; }\n.ps-experiments .lead-lbl .t { display: flex; align-items: center; gap: 7px; font-weight: 650; color: var(--mj-text-primary); }\n.ps-experiments .lp {\n display: flex; align-items: center; gap: 9px; flex: 0 0 auto; padding: 8px 12px;\n border: 1px solid var(--mj-border-default); border-radius: 9px; background: var(--mj-bg-surface);\n}\n.ps-experiments .lp.best { background: var(--mj-status-warning-bg); border-color: var(--mj-status-warning-border); }\n.ps-experiments .lp.pruned { opacity: .55; }\n.ps-experiments .algo-ic {\n width: 26px; height: 26px; border-radius: 7px; display: grid; place-items: center;\n color: var(--mj-text-inverse); font-size: 12px; flex: 0 0 auto;\n}\n.ps-experiments .lp .nm { font-size: 12.5px; font-weight: 600; color: var(--mj-text-primary); }\n.ps-experiments .lp .auc { font-weight: 740; font-variant-numeric: tabular-nums; color: var(--mj-text-primary); }\n.ps-experiments .lp .auc.win { color: var(--mj-status-success-text); }\n\n/* budget rail */\n.ps-experiments .budget-rail { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }\n@media (max-width: 880px) { .ps-experiments .budget-rail { grid-template-columns: 1fr; } }\n.ps-experiments .bud { display: flex; align-items: center; gap: 13px; }\n.ps-experiments .b-val { font-size: 15px; color: var(--mj-text-primary); margin-top: 2px; }\n\n/* kanban */\n.ps-experiments .kanban { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; align-items: start; }\n@media (max-width: 980px) { .ps-experiments .kanban { grid-template-columns: 1fr; } }\n.ps-experiments .kcol { background: var(--mj-bg-surface); border: 1px solid var(--mj-border-default); border-radius: 10px; overflow: hidden; }\n.ps-experiments .kcol-head {\n display: flex; align-items: center; gap: 9px; padding: 12px 14px; border-bottom: 1px solid var(--mj-border-subtle);\n font-weight: 650; color: var(--mj-text-primary);\n}\n.ps-experiments .kcol-head h3 { font-size: 13.5px; margin: 0; flex: 1; }\n.ps-experiments .kcol.run .kcol-head { border-top: 3px solid var(--mj-brand-primary); }\n.ps-experiments .kcol.done .kcol-head { border-top: 3px solid var(--mj-status-success); }\n.ps-experiments .kcol.prune .kcol-head { border-top: 3px solid var(--mj-text-disabled); }\n.ps-experiments .kcol.run .kcol-head i { color: var(--mj-brand-primary); }\n.ps-experiments .kcol.done .kcol-head i { color: var(--mj-status-success); }\n.ps-experiments .kcol.prune .kcol-head i { color: var(--mj-text-muted); }\n.ps-experiments .cnt {\n background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary);\n border-radius: 999px; padding: 1px 9px; font-size: 12px; font-weight: 700;\n}\n.ps-experiments .kbody { padding: 11px; display: flex; flex-direction: column; gap: 11px; }\n\n.ps-experiments .icard {\n border: 1px solid var(--mj-border-default); border-radius: 9px; padding: 11px;\n background: var(--mj-bg-surface-card); display: flex; flex-direction: column; gap: 9px;\n}\n.ps-experiments .icard.running { border-color: color-mix(in srgb, var(--mj-brand-primary) 40%, var(--mj-border-default)); }\n.ps-experiments .icard.best { border-left: 3px solid var(--mj-status-warning); }\n.ps-experiments .icard.pruned { opacity: .78; }\n.ps-experiments .ic-top { display: flex; align-items: center; gap: 9px; }\n.ps-experiments .ic-top .algo-ic { width: 30px; height: 30px; }\n.ps-experiments .ic-top .nm { font-weight: 600; color: var(--mj-text-primary); font-size: 13px; }\n.ps-experiments .feat-chips { display: flex; gap: 6px; flex-wrap: wrap; }\n.ps-experiments .ic-prog .meta { display: flex; justify-content: space-between; margin-top: 5px; }\n.ps-experiments .ic-score { display: flex; align-items: baseline; gap: 8px; }\n.ps-experiments .ic-score .v { font-size: 21px; font-weight: 720; color: var(--mj-text-primary); font-variant-numeric: tabular-nums; }\n.ps-experiments .ic-score .v.green { color: var(--mj-status-success-text); }\n.ps-experiments .rationale {\n display: flex; gap: 8px; padding-top: 8px; border-top: 1px solid var(--mj-border-subtle); color: var(--mj-text-secondary);\n}\n.ps-experiments .rationale i { color: var(--mj-brand-primary); margin-top: 2px; }\n"], encapsulation: 2 });
|
|
631
631
|
}
|
|
632
632
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PSExperimentsComponent, [{
|
|
633
633
|
type: Component,
|
|
@@ -772,7 +772,7 @@ export class PSExperimentsComponent {
|
|
|
772
772
|
</ps-confirm-modal>
|
|
773
773
|
}
|
|
774
774
|
</div>
|
|
775
|
-
`, 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-experiments { display: flex; flex-direction: column; gap: 16px; }\n\n.ps-experiments .sess-head { display: flex; align-items: center; gap: 12px; }\n.ps-experiments .sess-head h2 { font-size: 18px; color: var(--mj-text-primary); display: flex; align-items: center; gap: 10px; }\n\n/* leaderboard strip */\n.ps-experiments .lead-strip { display: flex; gap: 10px; align-items: center; overflow-x: auto; }\n.ps-experiments .lead-lbl { padding-right: 14px; border-right: 1px solid var(--mj-border-default); flex: 0 0 auto; }\n.ps-experiments .lead-lbl .t { display: flex; align-items: center; gap: 7px; font-weight: 650; color: var(--mj-text-primary); }\n.ps-experiments .lp {\n display: flex; align-items: center; gap: 9px; flex: 0 0 auto; padding: 8px 12px;\n border: 1px solid var(--mj-border-default); border-radius: 9px; background: var(--mj-bg-surface);\n}\n.ps-experiments .lp.best { background: var(--mj-status-warning-bg); border-color: var(--mj-status-warning-border); }\n.ps-experiments .lp.pruned { opacity: .55; }\n.ps-experiments .algo-ic {\n width: 26px; height: 26px; border-radius: 7px; display: grid; place-items: center;\n color: var(--mj-text-inverse); font-size: 12px; flex: 0 0 auto;\n}\n.ps-experiments .lp .nm { font-size: 12.5px; font-weight: 600; color: var(--mj-text-primary); }\n.ps-experiments .lp .auc { font-weight: 740; font-variant-numeric: tabular-nums; color: var(--mj-text-primary); }\n.ps-experiments .lp .auc.win { color: var(--mj-status-success-text); }\n\n/* budget rail */\n.ps-experiments .budget-rail { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }\n@media (max-width: 880px) { .ps-experiments .budget-rail { grid-template-columns: 1fr; } }\n.ps-experiments .bud { display: flex; align-items: center; gap: 13px; }\n.ps-experiments .b-val { font-size: 15px; color: var(--mj-text-primary); margin-top: 2px; }\n\n/* kanban */\n.ps-experiments .kanban { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; align-items: start; }\n@media (max-width: 980px) { .ps-experiments .kanban { grid-template-columns: 1fr; } }\n.ps-experiments .kcol { background: var(--mj-bg-surface); border: 1px solid var(--mj-border-default); border-radius: 10px; overflow: hidden; }\n.ps-experiments .kcol-head {\n display: flex; align-items: center; gap: 9px; padding: 12px 14px; border-bottom: 1px solid var(--mj-border-subtle);\n font-weight: 650; color: var(--mj-text-primary);\n}\n.ps-experiments .kcol-head h3 { font-size: 13.5px; margin: 0; flex: 1; }\n.ps-experiments .kcol.run .kcol-head { border-top: 3px solid var(--mj-brand-primary); }\n.ps-experiments .kcol.done .kcol-head { border-top: 3px solid var(--mj-status-success); }\n.ps-experiments .kcol.prune .kcol-head { border-top: 3px solid var(--mj-text-disabled); }\n.ps-experiments .kcol.run .kcol-head i { color: var(--mj-brand-primary); }\n.ps-experiments .kcol.done .kcol-head i { color: var(--mj-status-success); }\n.ps-experiments .kcol.prune .kcol-head i { color: var(--mj-text-muted); }\n.ps-experiments .cnt {\n background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary);\n border-radius: 999px; padding: 1px 9px; font-size: 12px; font-weight: 700;\n}\n.ps-experiments .kbody { padding: 11px; display: flex; flex-direction: column; gap: 11px; }\n\n.ps-experiments .icard {\n border: 1px solid var(--mj-border-default); border-radius: 9px; padding: 11px;\n background: var(--mj-bg-surface-card); display: flex; flex-direction: column; gap: 9px;\n}\n.ps-experiments .icard.running { border-color: color-mix(in srgb, var(--mj-brand-primary) 40%, var(--mj-border-default)); }\n.ps-experiments .icard.best { border-left: 3px solid var(--mj-status-warning); }\n.ps-experiments .icard.pruned { opacity: .78; }\n.ps-experiments .ic-top { display: flex; align-items: center; gap: 9px; }\n.ps-experiments .ic-top .algo-ic { width: 30px; height: 30px; }\n.ps-experiments .ic-top .nm { font-weight: 600; color: var(--mj-text-primary); font-size: 13px; }\n.ps-experiments .feat-chips { display: flex; gap: 6px; flex-wrap: wrap; }\n.ps-experiments .ic-prog .meta { display: flex; justify-content: space-between; margin-top: 5px; }\n.ps-experiments .ic-score { display: flex; align-items: baseline; gap: 8px; }\n.ps-experiments .ic-score .v { font-size: 21px; font-weight: 720; color: var(--mj-text-primary); font-variant-numeric: tabular-nums; }\n.ps-experiments .ic-score .v.green { color: var(--mj-status-success-text); }\n.ps-experiments .rationale {\n display: flex; gap: 8px; padding-top: 8px; border-top: 1px solid var(--mj-border-subtle); color: var(--mj-text-secondary);\n}\n.ps-experiments .rationale i { color: var(--mj-brand-primary); margin-top: 2px; }\n"] }]
|
|
775
|
+
`, 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: 8px;\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: 8px; padding: 16px 18px;\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: minmax(150px, 1.3fr) 2fr 56px; align-items: center; gap: 14px; padding: 8px 0; }\n.ps-fbar + .ps-fbar { border-top: 1px solid var(--mj-border-subtle); }\n.ps-fbar .track { height: 10px; border-radius: var(--mj-radius-full); background: var(--mj-bg-surface-sunken); overflow: hidden; }\n.ps-fbar .track > span { display: block; height: 100%; border-radius: var(--mj-radius-full); background: var(--mj-brand-primary); }\n.ps-fbar .track > span.warn { background: var(--mj-status-warning); }\n.ps-fbar .name { color: var(--mj-text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.ps-fbar > .ps-mono { text-align: right; color: var(--mj-text-secondary); font-variant-numeric: tabular-nums; }\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: 8px;\n 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-experiments { display: flex; flex-direction: column; gap: 16px; }\n\n.ps-experiments .sess-head { display: flex; align-items: center; gap: 12px; }\n.ps-experiments .sess-head h2 { font-size: 18px; color: var(--mj-text-primary); display: flex; align-items: center; gap: 10px; }\n\n/* leaderboard strip */\n.ps-experiments .lead-strip { display: flex; gap: 10px; align-items: center; overflow-x: auto; }\n.ps-experiments .lead-lbl { padding-right: 14px; border-right: 1px solid var(--mj-border-default); flex: 0 0 auto; }\n.ps-experiments .lead-lbl .t { display: flex; align-items: center; gap: 7px; font-weight: 650; color: var(--mj-text-primary); }\n.ps-experiments .lp {\n display: flex; align-items: center; gap: 9px; flex: 0 0 auto; padding: 8px 12px;\n border: 1px solid var(--mj-border-default); border-radius: 9px; background: var(--mj-bg-surface);\n}\n.ps-experiments .lp.best { background: var(--mj-status-warning-bg); border-color: var(--mj-status-warning-border); }\n.ps-experiments .lp.pruned { opacity: .55; }\n.ps-experiments .algo-ic {\n width: 26px; height: 26px; border-radius: 7px; display: grid; place-items: center;\n color: var(--mj-text-inverse); font-size: 12px; flex: 0 0 auto;\n}\n.ps-experiments .lp .nm { font-size: 12.5px; font-weight: 600; color: var(--mj-text-primary); }\n.ps-experiments .lp .auc { font-weight: 740; font-variant-numeric: tabular-nums; color: var(--mj-text-primary); }\n.ps-experiments .lp .auc.win { color: var(--mj-status-success-text); }\n\n/* budget rail */\n.ps-experiments .budget-rail { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }\n@media (max-width: 880px) { .ps-experiments .budget-rail { grid-template-columns: 1fr; } }\n.ps-experiments .bud { display: flex; align-items: center; gap: 13px; }\n.ps-experiments .b-val { font-size: 15px; color: var(--mj-text-primary); margin-top: 2px; }\n\n/* kanban */\n.ps-experiments .kanban { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; align-items: start; }\n@media (max-width: 980px) { .ps-experiments .kanban { grid-template-columns: 1fr; } }\n.ps-experiments .kcol { background: var(--mj-bg-surface); border: 1px solid var(--mj-border-default); border-radius: 10px; overflow: hidden; }\n.ps-experiments .kcol-head {\n display: flex; align-items: center; gap: 9px; padding: 12px 14px; border-bottom: 1px solid var(--mj-border-subtle);\n font-weight: 650; color: var(--mj-text-primary);\n}\n.ps-experiments .kcol-head h3 { font-size: 13.5px; margin: 0; flex: 1; }\n.ps-experiments .kcol.run .kcol-head { border-top: 3px solid var(--mj-brand-primary); }\n.ps-experiments .kcol.done .kcol-head { border-top: 3px solid var(--mj-status-success); }\n.ps-experiments .kcol.prune .kcol-head { border-top: 3px solid var(--mj-text-disabled); }\n.ps-experiments .kcol.run .kcol-head i { color: var(--mj-brand-primary); }\n.ps-experiments .kcol.done .kcol-head i { color: var(--mj-status-success); }\n.ps-experiments .kcol.prune .kcol-head i { color: var(--mj-text-muted); }\n.ps-experiments .cnt {\n background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary);\n border-radius: 999px; padding: 1px 9px; font-size: 12px; font-weight: 700;\n}\n.ps-experiments .kbody { padding: 11px; display: flex; flex-direction: column; gap: 11px; }\n\n.ps-experiments .icard {\n border: 1px solid var(--mj-border-default); border-radius: 9px; padding: 11px;\n background: var(--mj-bg-surface-card); display: flex; flex-direction: column; gap: 9px;\n}\n.ps-experiments .icard.running { border-color: color-mix(in srgb, var(--mj-brand-primary) 40%, var(--mj-border-default)); }\n.ps-experiments .icard.best { border-left: 3px solid var(--mj-status-warning); }\n.ps-experiments .icard.pruned { opacity: .78; }\n.ps-experiments .ic-top { display: flex; align-items: center; gap: 9px; }\n.ps-experiments .ic-top .algo-ic { width: 30px; height: 30px; }\n.ps-experiments .ic-top .nm { font-weight: 600; color: var(--mj-text-primary); font-size: 13px; }\n.ps-experiments .feat-chips { display: flex; gap: 6px; flex-wrap: wrap; }\n.ps-experiments .ic-prog .meta { display: flex; justify-content: space-between; margin-top: 5px; }\n.ps-experiments .ic-score { display: flex; align-items: baseline; gap: 8px; }\n.ps-experiments .ic-score .v { font-size: 21px; font-weight: 720; color: var(--mj-text-primary); font-variant-numeric: tabular-nums; }\n.ps-experiments .ic-score .v.green { color: var(--mj-status-success-text); }\n.ps-experiments .rationale {\n display: flex; gap: 8px; padding-top: 8px; border-top: 1px solid var(--mj-border-subtle); color: var(--mj-text-secondary);\n}\n.ps-experiments .rationale i { color: var(--mj-brand-primary); margin-top: 2px; }\n"] }]
|
|
776
776
|
}], null, { engine: [{
|
|
777
777
|
type: Input
|
|
778
778
|
}], provider: [{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ps-experiments.component.js","sourceRoot":"","sources":["../../../src/PredictiveStudio/components/ps-experiments.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChangeDetectorRef, Component, Input, OnInit, ViewEncapsulation, inject } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { MJButtonDirective } from '@memberjunction/ng-ui-components';\nimport { MJNotificationService } from '@memberjunction/ng-notifications';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { IMetadataProvider, UserInfo } from '@memberjunction/core';\nimport {\n MJExperimentSessionEntity,\n PredictiveStudioControlExperimentSessionOperation,\n PredictiveStudioExperimentSessionAction,\n} from '@memberjunction/core-entities';\nimport { PredictiveStudioEngine } from '../engine/predictive-studio.engine';\nimport { PSIterationCard, PSLeaderboardEntry } from '../predictive-studio.types';\nimport {\n PSKanbanColumns,\n deriveLeaderboard,\n groupIterationsToKanban,\n} from '../predictive-studio.view-models';\nimport { PSConfirmModalComponent } from './ps-confirm-modal.component';\n\n/** A budget gauge derived from the session's budget JSON + actual iteration spend. */\ninterface BudgetGaugeVM {\n label: string;\n fillPct: number;\n centerText: string;\n value: string;\n cap: string;\n color: string;\n}\n\n/**\n * Experiments panel: a kanban of iteration cards in Running / Completed / Pruned columns, a leaderboard\n * strip ranked by score, and budget gauges — all live against `MJ: Experiment Sessions` + their\n * `MJ: Experiment Session Iterations`:\n *\n * - The **active session** is the first Running session, else the most-recently-created one.\n * - The **kanban** + **leaderboard** are derived from that session's iterations (grouped by status,\n * ranked by score) via the pure {@link groupIterationsToKanban} / {@link deriveLeaderboard} helpers.\n * - **Budget gauges** combine the session's budget JSON caps with actual iteration spend (compute\n * cost, iteration count).\n * - **Pause / Cancel** call the {@link PredictiveStudioControlExperimentSessionOperation} Remote Op\n * behind a confirmation; on success the engine refreshes.\n *\n * Empty state when there are no sessions. 100% entity-agnostic.\n */\n@Component({\n standalone: true,\n selector: 'ps-experiments',\n imports: [CommonModule, MJButtonDirective, PSConfirmModalComponent],\n encapsulation: ViewEncapsulation.None,\n styleUrls: ['../predictive-studio.shared.scss', './ps-experiments.component.scss'],\n template: `\n <div class=\"ps-panel ps-experiments\" data-testid=\"ps-experiments-panel\">\n @if (!session) {\n <div class=\"ps-empty\" data-testid=\"ps-experiments-empty\">\n <span class=\"ps-empty-ico\"><i class=\"fa-solid fa-flask\"></i></span>\n <h3>No experiment sessions yet</h3>\n <p>Launch an experiment to watch the Model Dev Agent search algorithms and feature sets in waves. Running and completed iterations will appear here with a live leaderboard.</p>\n </div>\n } @else {\n <!-- session header strip -->\n <div class=\"sess-head\">\n <div>\n <div class=\"ps-small ps-muted\">Experiment session</div>\n <h2>{{ session.Name }} <span class=\"ps-badge\" [class]=\"sessionBadgeClass\"><span class=\"ps-dot\" [style.background]=\"sessionDotColor\"></span> {{ session.Status }}</span></h2>\n </div>\n <span class=\"ps-spacer\"></span>\n <span class=\"ps-small ps-muted\">{{ iterationCountLabel }}</span>\n @if (canPause) {\n <button mjButton variant=\"secondary\" size=\"sm\" data-testid=\"ps-experiments-pause\" (click)=\"requestControl('pause')\"><i class=\"fa-solid fa-pause\"></i> Pause</button>\n }\n @if (canResume) {\n <button mjButton variant=\"secondary\" size=\"sm\" data-testid=\"ps-experiments-resume\" (click)=\"requestControl('resume')\"><i class=\"fa-solid fa-play\"></i> Resume</button>\n }\n @if (canCancel) {\n <button mjButton variant=\"danger\" size=\"sm\" data-testid=\"ps-experiments-cancel\" (click)=\"requestControl('cancel')\"><i class=\"fa-solid fa-stop\"></i> Cancel</button>\n }\n </div>\n\n <!-- Leaderboard strip -->\n <div class=\"ps-card\" data-testid=\"ps-experiments-leaderboard\">\n <div class=\"ps-card-body lead-strip\">\n <div class=\"lead-lbl\">\n <div class=\"t\"><i class=\"fa-solid fa-trophy\" style=\"color:var(--mj-status-warning)\"></i> Leaderboard</div>\n <div class=\"ps-small ps-muted\">{{ leaderboard.length }} scored · by metric</div>\n </div>\n @if (leaderboard.length === 0) {\n <span class=\"ps-small ps-muted\">No scored iterations yet.</span>\n }\n @for (lp of leaderboard; track lp.rank) {\n <div class=\"lp\" [class.best]=\"lp.best\" [class.pruned]=\"lp.pruned\">\n <span class=\"ps-rank\" [class.gold]=\"lp.best\">{{ lp.rank }}</span>\n <span class=\"algo-ic\" [style.background]=\"lp.algorithmColor\"><i [class]=\"lp.algorithmIcon\"></i></span>\n <div><div class=\"nm\">{{ lp.algorithm }}</div><div class=\"fs ps-muted ps-small\">{{ lp.features }}</div></div>\n <span class=\"auc\" [class.win]=\"lp.best\">{{ lp.auc | number: '1.3-3' }}</span>\n </div>\n }\n </div>\n </div>\n\n <!-- Budget rail -->\n @if (budget.length > 0) {\n <div class=\"ps-card\">\n <div class=\"ps-card-body budget-rail\">\n @for (b of budget; track b.label) {\n <div class=\"bud\">\n <div class=\"ps-gauge\" [style.--ps-p]=\"b.fillPct\" [style.--ps-gauge-color]=\"b.color\">\n <span class=\"g-val\">{{ b.centerText }}</span>\n </div>\n <div style=\"flex:1\">\n <div class=\"ps-section-title\">{{ b.label }}</div>\n <div class=\"b-val\"><strong>{{ b.value }}</strong> <span class=\"ps-muted ps-small\">/ {{ b.cap }}</span></div>\n <div class=\"ps-bar\" style=\"margin-top:6px;max-width:150px\"><span [style.width.%]=\"b.fillPct\" [style.background]=\"b.color\"></span></div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Kanban -->\n <div class=\"kanban\" data-testid=\"ps-experiments-kanban\">\n <div class=\"kcol run\" data-testid=\"ps-kanban-col-running\">\n <div class=\"kcol-head\"><i class=\"fa-solid fa-spinner\"></i><h3>Running</h3><span class=\"cnt\">{{ kanban.running.length }}</span></div>\n <div class=\"kbody\">\n @for (c of kanban.running; track c.iteration) {\n <ng-container [ngTemplateOutlet]=\"iterCard\" [ngTemplateOutletContext]=\"{ c: c }\"></ng-container>\n }\n @if (kanban.running.length === 0) { <span class=\"ps-small ps-muted\">No running iterations.</span> }\n </div>\n </div>\n <div class=\"kcol done\" data-testid=\"ps-kanban-col-completed\">\n <div class=\"kcol-head\"><i class=\"fa-solid fa-circle-check\"></i><h3>Completed</h3><span class=\"cnt\">{{ kanban.completed.length }}</span></div>\n <div class=\"kbody\">\n @for (c of kanban.completed; track c.iteration) {\n <ng-container [ngTemplateOutlet]=\"iterCard\" [ngTemplateOutletContext]=\"{ c: c }\"></ng-container>\n }\n @if (kanban.completed.length === 0) { <span class=\"ps-small ps-muted\">No completed iterations.</span> }\n </div>\n </div>\n <div class=\"kcol prune\" data-testid=\"ps-kanban-col-pruned\">\n <div class=\"kcol-head\"><i class=\"fa-solid fa-scissors\"></i><h3>Pruned</h3><span class=\"cnt\">{{ kanban.pruned.length }}</span></div>\n <div class=\"kbody\">\n @for (c of kanban.pruned; track c.iteration) {\n <ng-container [ngTemplateOutlet]=\"iterCard\" [ngTemplateOutletContext]=\"{ c: c }\"></ng-container>\n }\n @if (kanban.pruned.length === 0) { <span class=\"ps-small ps-muted\">Nothing pruned.</span> }\n </div>\n </div>\n </div>\n\n <ng-template #iterCard let-c=\"c\">\n <div class=\"icard\" [class.best]=\"c.status === 'Best'\" [class.running]=\"c.status === 'Running'\" [class.pruned]=\"c.status === 'Pruned'\">\n <div class=\"ic-top\">\n <span class=\"algo-ic\" [style.background]=\"c.algorithmColor\"><i [class]=\"c.algorithmIcon\"></i></span>\n <div><div class=\"nm\">{{ c.algorithm }}</div><div class=\"it ps-muted ps-small\">{{ c.iteration }}</div></div>\n <span class=\"ps-spacer\"></span>\n <span class=\"ps-badge\" [class]=\"statusBadgeClass(c.status)\">{{ statusLabel(c.status) }}</span>\n </div>\n <div class=\"feat-chips\">\n @for (f of c.features; track f) { <span class=\"ps-tag\">{{ f }}</span> }\n </div>\n @if (c.status === 'Running') {\n <div class=\"ic-prog\">\n <div class=\"ps-bar run\"><span [style.width.%]=\"c.progress\"></span></div>\n <div class=\"meta\"><span class=\"ps-muted ps-small\">{{ c.progressDetail }}</span></div>\n </div>\n } @else {\n <div class=\"ic-score\">\n <span class=\"v\" [class.green]=\"c.status === 'Best'\">{{ c.score | number: '1.3-3' }}</span>\n <span class=\"lbl ps-muted ps-small\">score · {{ c.scoreDelta }}</span>\n </div>\n }\n <div class=\"rationale\"><i class=\"fa-solid fa-robot\"></i><span class=\"ps-small\">{{ c.rationale }}</span></div>\n </div>\n </ng-template>\n }\n\n @if (pendingAction) {\n <ps-confirm-modal\n [title]=\"pendingTitle\"\n [icon]=\"pendingIcon\"\n [confirmIcon]=\"pendingIcon\"\n [confirmLabel]=\"pendingConfirmLabel\"\n [variant]=\"pendingAction === 'cancel' ? 'danger' : 'warn'\"\n [busy]=\"busy\"\n (confirmed)=\"confirmControl()\"\n (cancelled)=\"cancelControl()\">\n <div [innerHTML]=\"pendingMessage\"></div>\n </ps-confirm-modal>\n }\n </div>\n `,\n})\nexport class PSExperimentsComponent implements OnInit {\n @Input() engine!: PredictiveStudioEngine;\n /** Provider to route the control Remote Op + engine refresh through (multi-provider correctness). */\n @Input() provider: IMetadataProvider | null = null;\n /** Acting user for the engine refresh after a mutation. */\n @Input() currentUser: UserInfo | null = null;\n\n private cdr = inject(ChangeDetectorRef);\n private notifications = inject(MJNotificationService);\n\n /** The currently-displayed session ID (first Running, else most recent). */\n public sessionId = '';\n public kanban: PSKanbanColumns = { running: [], completed: [], pruned: [] };\n public leaderboard: PSLeaderboardEntry[] = [];\n public budget: BudgetGaugeVM[] = [];\n\n /** Pending control action awaiting confirmation (null when no modal is open). */\n public pendingAction: PredictiveStudioExperimentSessionAction | null = null;\n /** Remote Op in flight. */\n public busy = false;\n\n ngOnInit(): void {\n this.selectActiveSession();\n this.rebuild();\n }\n\n // ---- active session selection ----\n\n /** Pick the most relevant session to display: first Running, else the most-recently-created. */\n private selectActiveSession(): void {\n const sessions = this.engine?.Sessions ?? [];\n const running = sessions.find((s) => s.Status === 'Running');\n // Sessions are loaded OrderBy '__mj_CreatedAt DESC', so index 0 is the most recent.\n this.sessionId = (running ?? sessions[0])?.ID ?? '';\n }\n\n public get session(): MJExperimentSessionEntity | undefined {\n return this.engine?.Sessions.find((s) => UUIDsEqual(s.ID, this.sessionId));\n }\n\n public get iterationCountLabel(): string {\n const total = this.kanban.running.length + this.kanban.completed.length + this.kanban.pruned.length;\n return `${total} iteration${total === 1 ? '' : 's'}`;\n }\n\n // ---- derivations ----\n\n private rebuild(): void {\n if (!this.sessionId) {\n this.kanban = { running: [], completed: [], pruned: [] };\n this.leaderboard = [];\n this.budget = [];\n return;\n }\n const rows = this.engine.IterationRowsForSession(this.sessionId);\n this.kanban = groupIterationsToKanban(rows);\n this.leaderboard = deriveLeaderboard(rows);\n this.budget = this.buildBudget(rows);\n }\n\n /** Build the budget gauges from the session's budget JSON caps + actual iteration spend. */\n private buildBudget(rows: { ComputeCost: number | null }[]): BudgetGaugeVM[] {\n const session = this.session;\n if (!session) return [];\n const budgetJson = this.parseBudget(session.Budget);\n const gauges: BudgetGaugeVM[] = [];\n\n const spentCost = rows.reduce((sum, r) => sum + (r.ComputeCost ?? 0), 0);\n const maxCost = budgetJson.maxComputeCost;\n if (maxCost != null && maxCost > 0) {\n gauges.push(this.gauge('Compute cost', spentCost, maxCost, 'var(--ps-gauge-cost)', (v) => `$${v.toFixed(0)}`, `$${maxCost.toFixed(0)} cap`));\n }\n\n const iterations = rows.length;\n const maxIterations = budgetJson.maxIterations;\n if (maxIterations != null && maxIterations > 0) {\n gauges.push(this.gauge('Iterations', iterations, maxIterations, 'var(--ps-gauge-iterations)', (v) => `${v}`, `${maxIterations} trials`));\n }\n return gauges;\n }\n\n /** Construct a single gauge VM (fill clamped to 0..100). */\n private gauge(label: string, value: number, cap: number, color: string, fmt: (v: number) => string, capLabel: string): BudgetGaugeVM {\n const fillPct = Math.max(0, Math.min(100, Math.round((value / cap) * 100)));\n return { label, fillPct, centerText: `${fillPct}%`, value: fmt(value), cap: capLabel, color };\n }\n\n /** Tolerant parse of the session's budget JSON (accepts a few common key spellings). */\n private parseBudget(json: string | null): { maxComputeCost: number | null; maxIterations: number | null } {\n if (!json) return { maxComputeCost: null, maxIterations: null };\n try {\n const parsed = JSON.parse(json) as Record<string, unknown>;\n const num = (...keys: string[]): number | null => {\n for (const k of keys) {\n const v = parsed[k];\n if (typeof v === 'number' && Number.isFinite(v)) return v;\n }\n return null;\n };\n return {\n maxComputeCost: num('maxComputeCost', 'maxCost', 'computeBudget'),\n maxIterations: num('maxIterations', 'maxTrials', 'iterationBudget'),\n };\n } catch {\n return { maxComputeCost: null, maxIterations: null };\n }\n }\n\n // ---- session status chrome ----\n\n public get sessionBadgeClass(): string {\n switch (this.session?.Status) {\n case 'Running': return 'green';\n case 'Paused': return 'amber';\n case 'Cancelled': return 'red';\n case 'Completed': return 'blue';\n default: return 'gray';\n }\n }\n public get sessionDotColor(): string {\n switch (this.session?.Status) {\n case 'Running': return 'var(--mj-status-success)';\n case 'Paused': return 'var(--mj-status-warning)';\n case 'Cancelled': return 'var(--mj-status-error)';\n default: return 'var(--mj-text-muted)';\n }\n }\n\n public statusBadgeClass(status: PSIterationCard['status']): string {\n switch (status) {\n case 'Best': return 'green';\n case 'Completed': return 'gray';\n case 'AwaitingApproval': return 'amber';\n case 'Pruned': return 'red';\n case 'Running': return 'blue';\n }\n }\n\n public statusLabel(status: PSIterationCard['status']): string {\n switch (status) {\n case 'Best': return 'Best';\n case 'AwaitingApproval': return 'Awaiting approval';\n default: return status;\n }\n }\n\n // ---- control availability ----\n\n public get canPause(): boolean {\n return this.session?.Status === 'Running';\n }\n public get canResume(): boolean {\n return this.session?.Status === 'Paused';\n }\n public get canCancel(): boolean {\n const s = this.session?.Status;\n return s === 'Running' || s === 'Paused' || s === 'AwaitingApproval';\n }\n\n // ---- control flow (Remote Op) ----\n\n public requestControl(action: PredictiveStudioExperimentSessionAction): void {\n if (!this.session) return;\n this.pendingAction = action;\n }\n\n public cancelControl(): void {\n if (this.busy) return;\n this.pendingAction = null;\n }\n\n public get pendingTitle(): string {\n switch (this.pendingAction) {\n case 'pause': return 'Pause experiment';\n case 'resume': return 'Resume experiment';\n case 'cancel': return 'Cancel experiment';\n default: return '';\n }\n }\n public get pendingIcon(): string {\n switch (this.pendingAction) {\n case 'pause': return 'fa-solid fa-pause';\n case 'resume': return 'fa-solid fa-play';\n case 'cancel': return 'fa-solid fa-stop';\n default: return 'fa-solid fa-check';\n }\n }\n public get pendingConfirmLabel(): string {\n switch (this.pendingAction) {\n case 'pause': return 'Pause';\n case 'resume': return 'Resume';\n case 'cancel': return 'Cancel run';\n default: return 'Confirm';\n }\n }\n public get pendingMessage(): string {\n const name = escapeHtml(this.session?.Name ?? 'this session');\n switch (this.pendingAction) {\n case 'pause':\n return `Pause <strong>${name}</strong>? The orchestrator stops at the next wave checkpoint; in-flight iterations finish. You can resume later.`;\n case 'resume':\n return `Resume <strong>${name}</strong>? The orchestrator continues searching from where it paused.`;\n case 'cancel':\n return `Cancel <strong>${name}</strong>? This stops the search at the next checkpoint. Completed iterations and the leaderboard are kept, but the session cannot be resumed.`;\n default:\n return '';\n }\n }\n\n /** Run the control Remote Op, then refresh the engine + close on success. */\n public async confirmControl(): Promise<void> {\n if (!this.pendingAction || !this.session || this.busy) return;\n this.busy = true;\n const action = this.pendingAction;\n const sessionId = this.session.ID;\n const name = this.session.Name;\n try {\n const op = new PredictiveStudioControlExperimentSessionOperation();\n const result = await op.Execute(\n { sessionId, action },\n { provider: this.provider ?? undefined, user: this.currentUser ?? undefined },\n );\n if (result.Success) {\n this.notifications.CreateSimpleNotification(\n `${name} → ${result.Output?.status ?? action}`,\n 'success',\n 3500,\n );\n await this.refreshAfterMutation();\n this.pendingAction = null;\n } else {\n this.notifications.CreateSimpleNotification(\n result.ErrorMessage || `Could not ${action} ${name}.`,\n 'error',\n 5000,\n );\n }\n } catch (e) {\n this.notifications.CreateSimpleNotification(\n `${action} failed: ${e instanceof Error ? e.message : String(e)}`,\n 'error',\n 5000,\n );\n } finally {\n this.busy = false;\n this.cdr.detectChanges();\n }\n }\n\n /** Force-refresh the engine's cached sessions/iterations, then rebuild. */\n private async refreshAfterMutation(): Promise<void> {\n await this.engine.Config(true, this.currentUser ?? undefined, this.provider ?? undefined);\n this.selectActiveSession();\n this.rebuild();\n this.cdr.detectChanges();\n }\n}\n\n/** Minimal HTML-escape for interpolating session names into the modal's innerHTML message. */\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"');\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ps-experiments.component.js","sourceRoot":"","sources":["../../../src/PredictiveStudio/components/ps-experiments.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChangeDetectorRef, Component, Input, OnInit, ViewEncapsulation, inject } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { MJButtonDirective } from '@memberjunction/ng-ui-components';\nimport { MJNotificationService } from '@memberjunction/ng-notifications';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { IMetadataProvider, UserInfo } from '@memberjunction/core';\nimport {\n MJExperimentSessionEntity,\n PredictiveStudioControlExperimentSessionOperation,\n PredictiveStudioExperimentSessionAction,\n} from '@memberjunction/core-entities';\nimport { PredictiveStudioEngine } from '../engine/predictive-studio.engine';\nimport { PSIterationCard, PSLeaderboardEntry } from '../predictive-studio.types';\nimport {\n PSKanbanColumns,\n deriveLeaderboard,\n groupIterationsToKanban,\n} from '../predictive-studio.view-models';\nimport { PSConfirmModalComponent } from './ps-confirm-modal.component';\n\n/** A budget gauge derived from the session's budget JSON + actual iteration spend. */\ninterface BudgetGaugeVM {\n label: string;\n fillPct: number;\n centerText: string;\n value: string;\n cap: string;\n color: string;\n}\n\n/**\n * Experiments panel: a kanban of iteration cards in Running / Completed / Pruned columns, a leaderboard\n * strip ranked by score, and budget gauges — all live against `MJ: Experiment Sessions` + their\n * `MJ: Experiment Session Iterations`:\n *\n * - The **active session** is the first Running session, else the most-recently-created one.\n * - The **kanban** + **leaderboard** are derived from that session's iterations (grouped by status,\n * ranked by score) via the pure {@link groupIterationsToKanban} / {@link deriveLeaderboard} helpers.\n * - **Budget gauges** combine the session's budget JSON caps with actual iteration spend (compute\n * cost, iteration count).\n * - **Pause / Cancel** call the {@link PredictiveStudioControlExperimentSessionOperation} Remote Op\n * behind a confirmation; on success the engine refreshes.\n *\n * Empty state when there are no sessions. 100% entity-agnostic.\n */\n@Component({\n standalone: true,\n selector: 'ps-experiments',\n imports: [CommonModule, MJButtonDirective, PSConfirmModalComponent],\n encapsulation: ViewEncapsulation.None,\n styleUrls: ['../predictive-studio.shared.css', './ps-experiments.component.css'],\n template: `\n <div class=\"ps-panel ps-experiments\" data-testid=\"ps-experiments-panel\">\n @if (!session) {\n <div class=\"ps-empty\" data-testid=\"ps-experiments-empty\">\n <span class=\"ps-empty-ico\"><i class=\"fa-solid fa-flask\"></i></span>\n <h3>No experiment sessions yet</h3>\n <p>Launch an experiment to watch the Model Dev Agent search algorithms and feature sets in waves. Running and completed iterations will appear here with a live leaderboard.</p>\n </div>\n } @else {\n <!-- session header strip -->\n <div class=\"sess-head\">\n <div>\n <div class=\"ps-small ps-muted\">Experiment session</div>\n <h2>{{ session.Name }} <span class=\"ps-badge\" [class]=\"sessionBadgeClass\"><span class=\"ps-dot\" [style.background]=\"sessionDotColor\"></span> {{ session.Status }}</span></h2>\n </div>\n <span class=\"ps-spacer\"></span>\n <span class=\"ps-small ps-muted\">{{ iterationCountLabel }}</span>\n @if (canPause) {\n <button mjButton variant=\"secondary\" size=\"sm\" data-testid=\"ps-experiments-pause\" (click)=\"requestControl('pause')\"><i class=\"fa-solid fa-pause\"></i> Pause</button>\n }\n @if (canResume) {\n <button mjButton variant=\"secondary\" size=\"sm\" data-testid=\"ps-experiments-resume\" (click)=\"requestControl('resume')\"><i class=\"fa-solid fa-play\"></i> Resume</button>\n }\n @if (canCancel) {\n <button mjButton variant=\"danger\" size=\"sm\" data-testid=\"ps-experiments-cancel\" (click)=\"requestControl('cancel')\"><i class=\"fa-solid fa-stop\"></i> Cancel</button>\n }\n </div>\n\n <!-- Leaderboard strip -->\n <div class=\"ps-card\" data-testid=\"ps-experiments-leaderboard\">\n <div class=\"ps-card-body lead-strip\">\n <div class=\"lead-lbl\">\n <div class=\"t\"><i class=\"fa-solid fa-trophy\" style=\"color:var(--mj-status-warning)\"></i> Leaderboard</div>\n <div class=\"ps-small ps-muted\">{{ leaderboard.length }} scored · by metric</div>\n </div>\n @if (leaderboard.length === 0) {\n <span class=\"ps-small ps-muted\">No scored iterations yet.</span>\n }\n @for (lp of leaderboard; track lp.rank) {\n <div class=\"lp\" [class.best]=\"lp.best\" [class.pruned]=\"lp.pruned\">\n <span class=\"ps-rank\" [class.gold]=\"lp.best\">{{ lp.rank }}</span>\n <span class=\"algo-ic\" [style.background]=\"lp.algorithmColor\"><i [class]=\"lp.algorithmIcon\"></i></span>\n <div><div class=\"nm\">{{ lp.algorithm }}</div><div class=\"fs ps-muted ps-small\">{{ lp.features }}</div></div>\n <span class=\"auc\" [class.win]=\"lp.best\">{{ lp.auc | number: '1.3-3' }}</span>\n </div>\n }\n </div>\n </div>\n\n <!-- Budget rail -->\n @if (budget.length > 0) {\n <div class=\"ps-card\">\n <div class=\"ps-card-body budget-rail\">\n @for (b of budget; track b.label) {\n <div class=\"bud\">\n <div class=\"ps-gauge\" [style.--ps-p]=\"b.fillPct\" [style.--ps-gauge-color]=\"b.color\">\n <span class=\"g-val\">{{ b.centerText }}</span>\n </div>\n <div style=\"flex:1\">\n <div class=\"ps-section-title\">{{ b.label }}</div>\n <div class=\"b-val\"><strong>{{ b.value }}</strong> <span class=\"ps-muted ps-small\">/ {{ b.cap }}</span></div>\n <div class=\"ps-bar\" style=\"margin-top:6px;max-width:150px\"><span [style.width.%]=\"b.fillPct\" [style.background]=\"b.color\"></span></div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Kanban -->\n <div class=\"kanban\" data-testid=\"ps-experiments-kanban\">\n <div class=\"kcol run\" data-testid=\"ps-kanban-col-running\">\n <div class=\"kcol-head\"><i class=\"fa-solid fa-spinner\"></i><h3>Running</h3><span class=\"cnt\">{{ kanban.running.length }}</span></div>\n <div class=\"kbody\">\n @for (c of kanban.running; track c.iteration) {\n <ng-container [ngTemplateOutlet]=\"iterCard\" [ngTemplateOutletContext]=\"{ c: c }\"></ng-container>\n }\n @if (kanban.running.length === 0) { <span class=\"ps-small ps-muted\">No running iterations.</span> }\n </div>\n </div>\n <div class=\"kcol done\" data-testid=\"ps-kanban-col-completed\">\n <div class=\"kcol-head\"><i class=\"fa-solid fa-circle-check\"></i><h3>Completed</h3><span class=\"cnt\">{{ kanban.completed.length }}</span></div>\n <div class=\"kbody\">\n @for (c of kanban.completed; track c.iteration) {\n <ng-container [ngTemplateOutlet]=\"iterCard\" [ngTemplateOutletContext]=\"{ c: c }\"></ng-container>\n }\n @if (kanban.completed.length === 0) { <span class=\"ps-small ps-muted\">No completed iterations.</span> }\n </div>\n </div>\n <div class=\"kcol prune\" data-testid=\"ps-kanban-col-pruned\">\n <div class=\"kcol-head\"><i class=\"fa-solid fa-scissors\"></i><h3>Pruned</h3><span class=\"cnt\">{{ kanban.pruned.length }}</span></div>\n <div class=\"kbody\">\n @for (c of kanban.pruned; track c.iteration) {\n <ng-container [ngTemplateOutlet]=\"iterCard\" [ngTemplateOutletContext]=\"{ c: c }\"></ng-container>\n }\n @if (kanban.pruned.length === 0) { <span class=\"ps-small ps-muted\">Nothing pruned.</span> }\n </div>\n </div>\n </div>\n\n <ng-template #iterCard let-c=\"c\">\n <div class=\"icard\" [class.best]=\"c.status === 'Best'\" [class.running]=\"c.status === 'Running'\" [class.pruned]=\"c.status === 'Pruned'\">\n <div class=\"ic-top\">\n <span class=\"algo-ic\" [style.background]=\"c.algorithmColor\"><i [class]=\"c.algorithmIcon\"></i></span>\n <div><div class=\"nm\">{{ c.algorithm }}</div><div class=\"it ps-muted ps-small\">{{ c.iteration }}</div></div>\n <span class=\"ps-spacer\"></span>\n <span class=\"ps-badge\" [class]=\"statusBadgeClass(c.status)\">{{ statusLabel(c.status) }}</span>\n </div>\n <div class=\"feat-chips\">\n @for (f of c.features; track f) { <span class=\"ps-tag\">{{ f }}</span> }\n </div>\n @if (c.status === 'Running') {\n <div class=\"ic-prog\">\n <div class=\"ps-bar run\"><span [style.width.%]=\"c.progress\"></span></div>\n <div class=\"meta\"><span class=\"ps-muted ps-small\">{{ c.progressDetail }}</span></div>\n </div>\n } @else {\n <div class=\"ic-score\">\n <span class=\"v\" [class.green]=\"c.status === 'Best'\">{{ c.score | number: '1.3-3' }}</span>\n <span class=\"lbl ps-muted ps-small\">score · {{ c.scoreDelta }}</span>\n </div>\n }\n <div class=\"rationale\"><i class=\"fa-solid fa-robot\"></i><span class=\"ps-small\">{{ c.rationale }}</span></div>\n </div>\n </ng-template>\n }\n\n @if (pendingAction) {\n <ps-confirm-modal\n [title]=\"pendingTitle\"\n [icon]=\"pendingIcon\"\n [confirmIcon]=\"pendingIcon\"\n [confirmLabel]=\"pendingConfirmLabel\"\n [variant]=\"pendingAction === 'cancel' ? 'danger' : 'warn'\"\n [busy]=\"busy\"\n (confirmed)=\"confirmControl()\"\n (cancelled)=\"cancelControl()\">\n <div [innerHTML]=\"pendingMessage\"></div>\n </ps-confirm-modal>\n }\n </div>\n `,\n})\nexport class PSExperimentsComponent implements OnInit {\n @Input() engine!: PredictiveStudioEngine;\n /** Provider to route the control Remote Op + engine refresh through (multi-provider correctness). */\n @Input() provider: IMetadataProvider | null = null;\n /** Acting user for the engine refresh after a mutation. */\n @Input() currentUser: UserInfo | null = null;\n\n private cdr = inject(ChangeDetectorRef);\n private notifications = inject(MJNotificationService);\n\n /** The currently-displayed session ID (first Running, else most recent). */\n public sessionId = '';\n public kanban: PSKanbanColumns = { running: [], completed: [], pruned: [] };\n public leaderboard: PSLeaderboardEntry[] = [];\n public budget: BudgetGaugeVM[] = [];\n\n /** Pending control action awaiting confirmation (null when no modal is open). */\n public pendingAction: PredictiveStudioExperimentSessionAction | null = null;\n /** Remote Op in flight. */\n public busy = false;\n\n ngOnInit(): void {\n this.selectActiveSession();\n this.rebuild();\n }\n\n // ---- active session selection ----\n\n /** Pick the most relevant session to display: first Running, else the most-recently-created. */\n private selectActiveSession(): void {\n const sessions = this.engine?.Sessions ?? [];\n const running = sessions.find((s) => s.Status === 'Running');\n // Sessions are loaded OrderBy '__mj_CreatedAt DESC', so index 0 is the most recent.\n this.sessionId = (running ?? sessions[0])?.ID ?? '';\n }\n\n public get session(): MJExperimentSessionEntity | undefined {\n return this.engine?.Sessions.find((s) => UUIDsEqual(s.ID, this.sessionId));\n }\n\n public get iterationCountLabel(): string {\n const total = this.kanban.running.length + this.kanban.completed.length + this.kanban.pruned.length;\n return `${total} iteration${total === 1 ? '' : 's'}`;\n }\n\n // ---- derivations ----\n\n private rebuild(): void {\n if (!this.sessionId) {\n this.kanban = { running: [], completed: [], pruned: [] };\n this.leaderboard = [];\n this.budget = [];\n return;\n }\n const rows = this.engine.IterationRowsForSession(this.sessionId);\n this.kanban = groupIterationsToKanban(rows);\n this.leaderboard = deriveLeaderboard(rows);\n this.budget = this.buildBudget(rows);\n }\n\n /** Build the budget gauges from the session's budget JSON caps + actual iteration spend. */\n private buildBudget(rows: { ComputeCost: number | null }[]): BudgetGaugeVM[] {\n const session = this.session;\n if (!session) return [];\n const budgetJson = this.parseBudget(session.Budget);\n const gauges: BudgetGaugeVM[] = [];\n\n const spentCost = rows.reduce((sum, r) => sum + (r.ComputeCost ?? 0), 0);\n const maxCost = budgetJson.maxComputeCost;\n if (maxCost != null && maxCost > 0) {\n gauges.push(this.gauge('Compute cost', spentCost, maxCost, 'var(--ps-gauge-cost)', (v) => `$${v.toFixed(0)}`, `$${maxCost.toFixed(0)} cap`));\n }\n\n const iterations = rows.length;\n const maxIterations = budgetJson.maxIterations;\n if (maxIterations != null && maxIterations > 0) {\n gauges.push(this.gauge('Iterations', iterations, maxIterations, 'var(--ps-gauge-iterations)', (v) => `${v}`, `${maxIterations} trials`));\n }\n return gauges;\n }\n\n /** Construct a single gauge VM (fill clamped to 0..100). */\n private gauge(label: string, value: number, cap: number, color: string, fmt: (v: number) => string, capLabel: string): BudgetGaugeVM {\n const fillPct = Math.max(0, Math.min(100, Math.round((value / cap) * 100)));\n return { label, fillPct, centerText: `${fillPct}%`, value: fmt(value), cap: capLabel, color };\n }\n\n /** Tolerant parse of the session's budget JSON (accepts a few common key spellings). */\n private parseBudget(json: string | null): { maxComputeCost: number | null; maxIterations: number | null } {\n if (!json) return { maxComputeCost: null, maxIterations: null };\n try {\n const parsed = JSON.parse(json) as Record<string, unknown>;\n const num = (...keys: string[]): number | null => {\n for (const k of keys) {\n const v = parsed[k];\n if (typeof v === 'number' && Number.isFinite(v)) return v;\n }\n return null;\n };\n return {\n maxComputeCost: num('maxComputeCost', 'maxCost', 'computeBudget'),\n maxIterations: num('maxIterations', 'maxTrials', 'iterationBudget'),\n };\n } catch {\n return { maxComputeCost: null, maxIterations: null };\n }\n }\n\n // ---- session status chrome ----\n\n public get sessionBadgeClass(): string {\n switch (this.session?.Status) {\n case 'Running': return 'green';\n case 'Paused': return 'amber';\n case 'Cancelled': return 'red';\n case 'Completed': return 'blue';\n default: return 'gray';\n }\n }\n public get sessionDotColor(): string {\n switch (this.session?.Status) {\n case 'Running': return 'var(--mj-status-success)';\n case 'Paused': return 'var(--mj-status-warning)';\n case 'Cancelled': return 'var(--mj-status-error)';\n default: return 'var(--mj-text-muted)';\n }\n }\n\n public statusBadgeClass(status: PSIterationCard['status']): string {\n switch (status) {\n case 'Best': return 'green';\n case 'Completed': return 'gray';\n case 'AwaitingApproval': return 'amber';\n case 'Pruned': return 'red';\n case 'Running': return 'blue';\n }\n }\n\n public statusLabel(status: PSIterationCard['status']): string {\n switch (status) {\n case 'Best': return 'Best';\n case 'AwaitingApproval': return 'Awaiting approval';\n default: return status;\n }\n }\n\n // ---- control availability ----\n\n public get canPause(): boolean {\n return this.session?.Status === 'Running';\n }\n public get canResume(): boolean {\n return this.session?.Status === 'Paused';\n }\n public get canCancel(): boolean {\n const s = this.session?.Status;\n return s === 'Running' || s === 'Paused' || s === 'AwaitingApproval';\n }\n\n // ---- control flow (Remote Op) ----\n\n public requestControl(action: PredictiveStudioExperimentSessionAction): void {\n if (!this.session) return;\n this.pendingAction = action;\n }\n\n public cancelControl(): void {\n if (this.busy) return;\n this.pendingAction = null;\n }\n\n public get pendingTitle(): string {\n switch (this.pendingAction) {\n case 'pause': return 'Pause experiment';\n case 'resume': return 'Resume experiment';\n case 'cancel': return 'Cancel experiment';\n default: return '';\n }\n }\n public get pendingIcon(): string {\n switch (this.pendingAction) {\n case 'pause': return 'fa-solid fa-pause';\n case 'resume': return 'fa-solid fa-play';\n case 'cancel': return 'fa-solid fa-stop';\n default: return 'fa-solid fa-check';\n }\n }\n public get pendingConfirmLabel(): string {\n switch (this.pendingAction) {\n case 'pause': return 'Pause';\n case 'resume': return 'Resume';\n case 'cancel': return 'Cancel run';\n default: return 'Confirm';\n }\n }\n public get pendingMessage(): string {\n const name = escapeHtml(this.session?.Name ?? 'this session');\n switch (this.pendingAction) {\n case 'pause':\n return `Pause <strong>${name}</strong>? The orchestrator stops at the next wave checkpoint; in-flight iterations finish. You can resume later.`;\n case 'resume':\n return `Resume <strong>${name}</strong>? The orchestrator continues searching from where it paused.`;\n case 'cancel':\n return `Cancel <strong>${name}</strong>? This stops the search at the next checkpoint. Completed iterations and the leaderboard are kept, but the session cannot be resumed.`;\n default:\n return '';\n }\n }\n\n /** Run the control Remote Op, then refresh the engine + close on success. */\n public async confirmControl(): Promise<void> {\n if (!this.pendingAction || !this.session || this.busy) return;\n this.busy = true;\n const action = this.pendingAction;\n const sessionId = this.session.ID;\n const name = this.session.Name;\n try {\n const op = new PredictiveStudioControlExperimentSessionOperation();\n const result = await op.Execute(\n { sessionId, action },\n { provider: this.provider ?? undefined, user: this.currentUser ?? undefined },\n );\n if (result.Success) {\n this.notifications.CreateSimpleNotification(\n `${name} → ${result.Output?.status ?? action}`,\n 'success',\n 3500,\n );\n await this.refreshAfterMutation();\n this.pendingAction = null;\n } else {\n this.notifications.CreateSimpleNotification(\n result.ErrorMessage || `Could not ${action} ${name}.`,\n 'error',\n 5000,\n );\n }\n } catch (e) {\n this.notifications.CreateSimpleNotification(\n `${action} failed: ${e instanceof Error ? e.message : String(e)}`,\n 'error',\n 5000,\n );\n } finally {\n this.busy = false;\n this.cdr.detectChanges();\n }\n }\n\n /** Force-refresh the engine's cached sessions/iterations, then rebuild. */\n private async refreshAfterMutation(): Promise<void> {\n await this.engine.Config(true, this.currentUser ?? undefined, this.provider ?? undefined);\n this.selectActiveSession();\n this.rebuild();\n this.cdr.detectChanges();\n }\n}\n\n/** Minimal HTML-escape for interpolating session names into the modal's innerHTML message. */\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"');\n}\n"]}
|
|
@@ -272,7 +272,7 @@ export class PSHomeComponent {
|
|
|
272
272
|
i0.ɵɵtextInterpolate(ctx.kpis.experimentRuns);
|
|
273
273
|
i0.ɵɵadvance(5);
|
|
274
274
|
i0.ɵɵtextInterpolate(ctx.kpis.publishedCount);
|
|
275
|
-
} }, dependencies: [CommonModule, MJButtonDirective], 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-home { display: flex; flex-direction: column; gap: 18px; }\n\n/* Hero \u2014 intentional brand gradient band (categorical/branded surface).\n The gradient uses brand tokens; text on it uses --mj-text-inverse. */\n.ps-home .hero {\n position: relative; overflow: hidden; border-radius: 14px;\n background: linear-gradient(120deg,\n color-mix(in srgb, var(--mj-brand-primary) 78%, black) 0%,\n var(--mj-brand-primary) 55%,\n color-mix(in srgb, var(--mj-brand-primary) 60%, var(--ps-node-embedding)) 100%);\n color: var(--mj-text-inverse);\n padding: 26px 28px; box-shadow: var(--mj-shadow-lg);\n}\n.ps-home .hero::after {\n content: ''; position: absolute; right: -60px; top: -60px; width: 320px; height: 320px;\n border-radius: 50%; background: radial-gradient(circle, rgba(255, 255, 255, .14), transparent 70%);\n}\n.ps-home .hero h2 { font-size: 24px; letter-spacing: -.02em; color: var(--mj-text-inverse); }\n.ps-home .hero .sub { color: color-mix(in srgb, var(--mj-text-inverse) 80%, transparent); margin-top: 6px; max-width: 560px; font-size: 13.5px; }\n.ps-home .hero-stats { display: flex; gap: 26px; margin-top: 18px; position: relative; z-index: 1; }\n.ps-home .hero-stats .s .n { font-size: 22px; font-weight: 720; }\n.ps-home .hero-stats .s .l { font-size: 11.5px; color: color-mix(in srgb, var(--mj-text-inverse) 72%, transparent); text-transform: uppercase; letter-spacing: .05em; }\n.ps-home .hero-actions { margin-top: 20px; position: relative; z-index: 1; display: flex; gap: 10px; }\n.ps-home .hero-ghost {\n display: inline-flex; align-items: center; gap: 7px;\n background: rgba(255, 255, 255, .12); border: 1px solid rgba(255, 255, 255, .28);\n color: var(--mj-text-inverse); border-radius: 8px; padding: 6px 14px;\n font-weight: 600; font-size: 13px; cursor: pointer;\n}\n.ps-home .hero-ghost:hover { background: rgba(255, 255, 255, .2); }\n\n/* entry paths */\n.ps-home .paths { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }\n.ps-home .path {\n border: 1px solid var(--mj-border-default); border-radius: 10px;\n background: var(--mj-bg-surface); padding: 18px; cursor: pointer; transition: transform .08s, box-shadow .08s, border-color .08s;\n}\n.ps-home .path:hover { border-color: var(--mj-brand-primary); box-shadow: var(--mj-shadow-md); transform: translateY(-2px); }\n.ps-home .path .ic {\n width: 46px; height: 46px; border-radius: 12px; display: grid; place-items: center; font-size: 20px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface)); color: var(--mj-brand-primary);\n}\n.ps-home .path .ic.green { background: var(--mj-status-success-bg); color: var(--mj-status-success-text); }\n.ps-home .path .ic.purple { background: color-mix(in srgb, var(--ps-node-embedding) 14%, var(--mj-bg-surface)); color: var(--ps-node-embedding); }\n.ps-home .path h4 { margin-top: 12px; font-size: 15px; color: var(--mj-text-primary); }\n.ps-home .path p { color: var(--mj-text-secondary); font-size: 12.5px; margin: 6px 0 12px; }\n\n/* lower split */\n.ps-home .lower { display: grid; grid-template-columns: 1.5fr 1fr; gap: 16px; align-items: start; }\n@media (max-width: 980px) { .ps-home .lower, .ps-home .paths { grid-template-columns: 1fr; } }\n\n.ps-home .feed { position: relative; }\n.ps-home .fitem { display: grid; grid-template-columns: 34px 1fr; gap: 12px; padding: 12px 0; border-bottom: 1px solid var(--mj-border-subtle); }\n.ps-home .fitem:last-child { border-bottom: none; }\n.ps-home .ftitle { color: var(--mj-text-primary); }\n.ps-home .fitem .ev { width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center; font-size: 12px; color: var(--mj-text-inverse); }\n.ps-home .fitem .when { color: var(--mj-text-muted); font-size: 11.5px; margin-top: 2px; }\n.ps-home .ev.promote { background: var(--mj-status-success); }\n.ps-home .ev.run { background: var(--mj-brand-primary); }\n.ps-home .ev.warn { background: var(--mj-status-warning); }\n.ps-home .ev.archive { background: var(--mj-text-disabled); }\n\n.ps-home .mini-kpi { display: flex; align-items: center; justify-content: space-between; padding: 10px 0; border-bottom: 1px solid var(--mj-border-subtle); }\n.ps-home .mini-kpi:last-child { border-bottom: none; }\n.ps-home .mini-kpi .v { font-weight: 720; font-size: 18px; color: var(--mj-text-primary); }\n"], encapsulation: 2 });
|
|
275
|
+
} }, dependencies: [CommonModule, MJButtonDirective], 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: 8px;\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: 8px; padding: 16px 18px;\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: minmax(150px, 1.3fr) 2fr 56px; align-items: center; gap: 14px; padding: 8px 0; }\n.ps-fbar + .ps-fbar { border-top: 1px solid var(--mj-border-subtle); }\n.ps-fbar .track { height: 10px; border-radius: var(--mj-radius-full); background: var(--mj-bg-surface-sunken); overflow: hidden; }\n.ps-fbar .track > span { display: block; height: 100%; border-radius: var(--mj-radius-full); background: var(--mj-brand-primary); }\n.ps-fbar .track > span.warn { background: var(--mj-status-warning); }\n.ps-fbar .name { color: var(--mj-text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.ps-fbar > .ps-mono { text-align: right; color: var(--mj-text-secondary); font-variant-numeric: tabular-nums; }\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: 8px;\n 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-home { display: flex; flex-direction: column; gap: 18px; }\n\n/* Hero \u2014 flat surface card, styled exactly like every other .ps-card in the app\n (same background / border / radius tokens) so it adapts to light & dark mode. */\n.ps-home .hero {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 24px 28px;\n}\n.ps-home .hero h2 { margin: 0; font-size: 22px; font-weight: 700; letter-spacing: -.02em; color: var(--mj-text-primary); }\n.ps-home .hero .sub { color: var(--mj-text-secondary); margin-top: 6px; max-width: 680px; font-size: 13.5px; line-height: 1.5; }\n.ps-home .hero-stats { display: flex; gap: 26px; margin-top: 18px; }\n.ps-home .hero-stats .s .n { font-size: 22px; font-weight: 720; color: var(--mj-text-primary); }\n.ps-home .hero-stats .s .l { font-size: 11.5px; color: var(--mj-text-muted); text-transform: uppercase; letter-spacing: .05em; }\n.ps-home .hero-actions { margin-top: 18px; display: flex; gap: 10px; }\n.ps-home .hero-ghost {\n display: inline-flex; align-items: center; gap: 7px;\n background: transparent; border: 1px solid var(--mj-border-default);\n color: var(--mj-text-secondary); border-radius: 8px; padding: 6px 14px;\n font-weight: 600; font-size: 13px; cursor: pointer; transition: border-color .12s, color .12s;\n}\n.ps-home .hero-ghost:hover { border-color: var(--mj-brand-primary); color: var(--mj-brand-primary); }\n\n/* entry paths */\n.ps-home .paths { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }\n.ps-home .path {\n border: 1px solid var(--mj-border-default); border-radius: 10px;\n background: var(--mj-bg-surface); padding: 18px; cursor: pointer; transition: transform .08s, box-shadow .08s, border-color .08s;\n}\n.ps-home .path:hover { border-color: var(--mj-brand-primary); box-shadow: var(--mj-shadow-md); transform: translateY(-2px); }\n.ps-home .path .ic {\n width: 46px; height: 46px; border-radius: 12px; display: grid; place-items: center; font-size: 20px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface)); color: var(--mj-brand-primary);\n}\n.ps-home .path .ic.green { background: var(--mj-status-success-bg); color: var(--mj-status-success-text); }\n.ps-home .path .ic.purple { background: color-mix(in srgb, var(--ps-node-embedding) 14%, var(--mj-bg-surface)); color: var(--ps-node-embedding); }\n.ps-home .path h4 { margin-top: 12px; font-size: 15px; color: var(--mj-text-primary); }\n.ps-home .path p { color: var(--mj-text-secondary); font-size: 12.5px; margin: 6px 0 12px; }\n\n/* lower split */\n.ps-home .lower { display: grid; grid-template-columns: 1.5fr 1fr; gap: 16px; align-items: start; }\n@media (max-width: 980px) { .ps-home .lower, .ps-home .paths { grid-template-columns: 1fr; } }\n\n.ps-home .feed { position: relative; }\n.ps-home .fitem { display: grid; grid-template-columns: 34px 1fr; gap: 12px; padding: 12px 0; border-bottom: 1px solid var(--mj-border-subtle); }\n.ps-home .fitem:last-child { border-bottom: none; }\n.ps-home .ftitle { color: var(--mj-text-primary); }\n.ps-home .fitem .ev { width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center; font-size: 12px; color: var(--mj-text-inverse); }\n.ps-home .fitem .when { color: var(--mj-text-muted); font-size: 11.5px; margin-top: 2px; }\n.ps-home .ev.promote { background: var(--mj-status-success); }\n.ps-home .ev.run { background: var(--mj-brand-primary); }\n.ps-home .ev.warn { background: var(--mj-status-warning); }\n.ps-home .ev.archive { background: var(--mj-text-disabled); }\n\n.ps-home .mini-kpi { display: flex; align-items: center; justify-content: space-between; padding: 10px 0; border-bottom: 1px solid var(--mj-border-subtle); }\n.ps-home .mini-kpi:last-child { border-bottom: none; }\n.ps-home .mini-kpi .v { font-weight: 720; font-size: 18px; color: var(--mj-text-primary); }\n"], encapsulation: 2 });
|
|
276
276
|
}
|
|
277
277
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PSHomeComponent, [{
|
|
278
278
|
type: Component,
|
|
@@ -370,7 +370,7 @@ export class PSHomeComponent {
|
|
|
370
370
|
</div>
|
|
371
371
|
</div>
|
|
372
372
|
</div>
|
|
373
|
-
`, 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-home { display: flex; flex-direction: column; gap: 18px; }\n\n/* Hero \u2014 intentional brand gradient band (categorical/branded surface).\n The gradient uses brand tokens; text on it uses --mj-text-inverse. */\n.ps-home .hero {\n position: relative; overflow: hidden; border-radius: 14px;\n background: linear-gradient(120deg,\n color-mix(in srgb, var(--mj-brand-primary) 78%, black) 0%,\n var(--mj-brand-primary) 55%,\n color-mix(in srgb, var(--mj-brand-primary) 60%, var(--ps-node-embedding)) 100%);\n color: var(--mj-text-inverse);\n padding: 26px 28px; box-shadow: var(--mj-shadow-lg);\n}\n.ps-home .hero::after {\n content: ''; position: absolute; right: -60px; top: -60px; width: 320px; height: 320px;\n border-radius: 50%; background: radial-gradient(circle, rgba(255, 255, 255, .14), transparent 70%);\n}\n.ps-home .hero h2 { font-size: 24px; letter-spacing: -.02em; color: var(--mj-text-inverse); }\n.ps-home .hero .sub { color: color-mix(in srgb, var(--mj-text-inverse) 80%, transparent); margin-top: 6px; max-width: 560px; font-size: 13.5px; }\n.ps-home .hero-stats { display: flex; gap: 26px; margin-top: 18px; position: relative; z-index: 1; }\n.ps-home .hero-stats .s .n { font-size: 22px; font-weight: 720; }\n.ps-home .hero-stats .s .l { font-size: 11.5px; color: color-mix(in srgb, var(--mj-text-inverse) 72%, transparent); text-transform: uppercase; letter-spacing: .05em; }\n.ps-home .hero-actions { margin-top: 20px; position: relative; z-index: 1; display: flex; gap: 10px; }\n.ps-home .hero-ghost {\n display: inline-flex; align-items: center; gap: 7px;\n background: rgba(255, 255, 255, .12); border: 1px solid rgba(255, 255, 255, .28);\n color: var(--mj-text-inverse); border-radius: 8px; padding: 6px 14px;\n font-weight: 600; font-size: 13px; cursor: pointer;\n}\n.ps-home .hero-ghost:hover { background: rgba(255, 255, 255, .2); }\n\n/* entry paths */\n.ps-home .paths { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }\n.ps-home .path {\n border: 1px solid var(--mj-border-default); border-radius: 10px;\n background: var(--mj-bg-surface); padding: 18px; cursor: pointer; transition: transform .08s, box-shadow .08s, border-color .08s;\n}\n.ps-home .path:hover { border-color: var(--mj-brand-primary); box-shadow: var(--mj-shadow-md); transform: translateY(-2px); }\n.ps-home .path .ic {\n width: 46px; height: 46px; border-radius: 12px; display: grid; place-items: center; font-size: 20px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface)); color: var(--mj-brand-primary);\n}\n.ps-home .path .ic.green { background: var(--mj-status-success-bg); color: var(--mj-status-success-text); }\n.ps-home .path .ic.purple { background: color-mix(in srgb, var(--ps-node-embedding) 14%, var(--mj-bg-surface)); color: var(--ps-node-embedding); }\n.ps-home .path h4 { margin-top: 12px; font-size: 15px; color: var(--mj-text-primary); }\n.ps-home .path p { color: var(--mj-text-secondary); font-size: 12.5px; margin: 6px 0 12px; }\n\n/* lower split */\n.ps-home .lower { display: grid; grid-template-columns: 1.5fr 1fr; gap: 16px; align-items: start; }\n@media (max-width: 980px) { .ps-home .lower, .ps-home .paths { grid-template-columns: 1fr; } }\n\n.ps-home .feed { position: relative; }\n.ps-home .fitem { display: grid; grid-template-columns: 34px 1fr; gap: 12px; padding: 12px 0; border-bottom: 1px solid var(--mj-border-subtle); }\n.ps-home .fitem:last-child { border-bottom: none; }\n.ps-home .ftitle { color: var(--mj-text-primary); }\n.ps-home .fitem .ev { width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center; font-size: 12px; color: var(--mj-text-inverse); }\n.ps-home .fitem .when { color: var(--mj-text-muted); font-size: 11.5px; margin-top: 2px; }\n.ps-home .ev.promote { background: var(--mj-status-success); }\n.ps-home .ev.run { background: var(--mj-brand-primary); }\n.ps-home .ev.warn { background: var(--mj-status-warning); }\n.ps-home .ev.archive { background: var(--mj-text-disabled); }\n\n.ps-home .mini-kpi { display: flex; align-items: center; justify-content: space-between; padding: 10px 0; border-bottom: 1px solid var(--mj-border-subtle); }\n.ps-home .mini-kpi:last-child { border-bottom: none; }\n.ps-home .mini-kpi .v { font-weight: 720; font-size: 18px; color: var(--mj-text-primary); }\n"] }]
|
|
373
|
+
`, 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: 8px;\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: 8px; padding: 16px 18px;\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: minmax(150px, 1.3fr) 2fr 56px; align-items: center; gap: 14px; padding: 8px 0; }\n.ps-fbar + .ps-fbar { border-top: 1px solid var(--mj-border-subtle); }\n.ps-fbar .track { height: 10px; border-radius: var(--mj-radius-full); background: var(--mj-bg-surface-sunken); overflow: hidden; }\n.ps-fbar .track > span { display: block; height: 100%; border-radius: var(--mj-radius-full); background: var(--mj-brand-primary); }\n.ps-fbar .track > span.warn { background: var(--mj-status-warning); }\n.ps-fbar .name { color: var(--mj-text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.ps-fbar > .ps-mono { text-align: right; color: var(--mj-text-secondary); font-variant-numeric: tabular-nums; }\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: 8px;\n 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-home { display: flex; flex-direction: column; gap: 18px; }\n\n/* Hero \u2014 flat surface card, styled exactly like every other .ps-card in the app\n (same background / border / radius tokens) so it adapts to light & dark mode. */\n.ps-home .hero {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 24px 28px;\n}\n.ps-home .hero h2 { margin: 0; font-size: 22px; font-weight: 700; letter-spacing: -.02em; color: var(--mj-text-primary); }\n.ps-home .hero .sub { color: var(--mj-text-secondary); margin-top: 6px; max-width: 680px; font-size: 13.5px; line-height: 1.5; }\n.ps-home .hero-stats { display: flex; gap: 26px; margin-top: 18px; }\n.ps-home .hero-stats .s .n { font-size: 22px; font-weight: 720; color: var(--mj-text-primary); }\n.ps-home .hero-stats .s .l { font-size: 11.5px; color: var(--mj-text-muted); text-transform: uppercase; letter-spacing: .05em; }\n.ps-home .hero-actions { margin-top: 18px; display: flex; gap: 10px; }\n.ps-home .hero-ghost {\n display: inline-flex; align-items: center; gap: 7px;\n background: transparent; border: 1px solid var(--mj-border-default);\n color: var(--mj-text-secondary); border-radius: 8px; padding: 6px 14px;\n font-weight: 600; font-size: 13px; cursor: pointer; transition: border-color .12s, color .12s;\n}\n.ps-home .hero-ghost:hover { border-color: var(--mj-brand-primary); color: var(--mj-brand-primary); }\n\n/* entry paths */\n.ps-home .paths { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }\n.ps-home .path {\n border: 1px solid var(--mj-border-default); border-radius: 10px;\n background: var(--mj-bg-surface); padding: 18px; cursor: pointer; transition: transform .08s, box-shadow .08s, border-color .08s;\n}\n.ps-home .path:hover { border-color: var(--mj-brand-primary); box-shadow: var(--mj-shadow-md); transform: translateY(-2px); }\n.ps-home .path .ic {\n width: 46px; height: 46px; border-radius: 12px; display: grid; place-items: center; font-size: 20px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface)); color: var(--mj-brand-primary);\n}\n.ps-home .path .ic.green { background: var(--mj-status-success-bg); color: var(--mj-status-success-text); }\n.ps-home .path .ic.purple { background: color-mix(in srgb, var(--ps-node-embedding) 14%, var(--mj-bg-surface)); color: var(--ps-node-embedding); }\n.ps-home .path h4 { margin-top: 12px; font-size: 15px; color: var(--mj-text-primary); }\n.ps-home .path p { color: var(--mj-text-secondary); font-size: 12.5px; margin: 6px 0 12px; }\n\n/* lower split */\n.ps-home .lower { display: grid; grid-template-columns: 1.5fr 1fr; gap: 16px; align-items: start; }\n@media (max-width: 980px) { .ps-home .lower, .ps-home .paths { grid-template-columns: 1fr; } }\n\n.ps-home .feed { position: relative; }\n.ps-home .fitem { display: grid; grid-template-columns: 34px 1fr; gap: 12px; padding: 12px 0; border-bottom: 1px solid var(--mj-border-subtle); }\n.ps-home .fitem:last-child { border-bottom: none; }\n.ps-home .ftitle { color: var(--mj-text-primary); }\n.ps-home .fitem .ev { width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center; font-size: 12px; color: var(--mj-text-inverse); }\n.ps-home .fitem .when { color: var(--mj-text-muted); font-size: 11.5px; margin-top: 2px; }\n.ps-home .ev.promote { background: var(--mj-status-success); }\n.ps-home .ev.run { background: var(--mj-brand-primary); }\n.ps-home .ev.warn { background: var(--mj-status-warning); }\n.ps-home .ev.archive { background: var(--mj-text-disabled); }\n\n.ps-home .mini-kpi { display: flex; align-items: center; justify-content: space-between; padding: 10px 0; border-bottom: 1px solid var(--mj-border-subtle); }\n.ps-home .mini-kpi:last-child { border-bottom: none; }\n.ps-home .mini-kpi .v { font-weight: 720; font-size: 18px; color: var(--mj-text-primary); }\n"] }]
|
|
374
374
|
}], null, { engine: [{
|
|
375
375
|
type: Input
|
|
376
376
|
}], provider: [{
|