@memberjunction/ng-dashboards 5.46.0 → 5.48.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/DataExplorer/data-explorer-dashboard.component.d.ts +15 -4
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.js +45 -35
- package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
- package/dist/DataExplorer/models/explorer-state.interface.d.ts +7 -0
- package/dist/DataExplorer/models/explorer-state.interface.d.ts.map +1 -1
- package/dist/DataExplorer/models/explorer-state.interface.js.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.d.ts +4 -0
- package/dist/Lists/components/lists-browse-resource.component.d.ts.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.js +39 -30
- package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-my-lists-resource.component.d.ts.map +1 -1
- package/dist/Lists/components/lists-my-lists-resource.component.js +14 -12
- package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-operations-resource.component.d.ts.map +1 -1
- package/dist/Lists/components/lists-operations-resource.component.js +6 -1
- package/dist/Lists/components/lists-operations-resource.component.js.map +1 -1
- package/dist/Lists/services/list-set-operations.service.d.ts +11 -0
- package/dist/Lists/services/list-set-operations.service.d.ts.map +1 -1
- package/dist/Lists/services/list-set-operations.service.js +27 -2
- package/dist/Lists/services/list-set-operations.service.js.map +1 -1
- 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
|
@@ -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: [{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ps-home.component.js","sourceRoot":"","sources":["../../../src/PredictiveStudio/components/ps-home.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation, inject } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { MJButtonDirective } from '@memberjunction/ng-ui-components';\nimport { IMetadataProvider, UserInfo } from '@memberjunction/core';\nimport { PredictiveStudioEngine } from '../engine/predictive-studio.engine';\nimport { PSPanelKey } from '../predictive-studio.types';\nimport { PS_AGENT_STARTER_PROMPT } from './ps-agent-starter-prompt';\n\nexport { PS_AGENT_STARTER_PROMPT } from './ps-agent-starter-prompt';\nimport {\n PSActivityFeedItem,\n PSHomeKpis,\n PSModelEventSource,\n PSProcessRunRow,\n buildActivityFeed,\n computeHomeKpis,\n deriveModelEvents,\n} from '../predictive-studio.view-models';\n\n/**\n * Home panel — the action-forward landing: a hero \"Build a predictive model\" band with three entry\n * paths, a vertical recent-activity timeline, and a side rail of weekly KPIs. Fully live:\n *\n * - **KPIs** (published count, active experiments, best holdout AUC, scored-this-week) come from the\n * cached models/sessions + recent ML scoring runs loaded on demand, via {@link computeHomeKpis}.\n * - **Recent activity** merges recent ML scoring process runs and recent model promotions/archives\n * into one reverse-chronological feed via {@link buildActivityFeed}.\n *\n * Recent scoring runs are loaded once on init (cheap, capped) — `MJ: Process Runs` isn't bulk-cached\n * because it grows unbounded. 100% entity-agnostic.\n *\n * **\"Ask the agent\" entry path.** The hero CTA and the agent entry-path card emit {@link askAgent} with a\n * starter prompt string. The host resource (the Studio door's `PSStudioResourceComponent`) reveals the\n * docked Model Development Agent chat seeded with that prompt. The prompt is a deliberately entity-agnostic template\n * ({@link PS_AGENT_STARTER_PROMPT}) — it never names a specific entity/target, so Predictive Studio stays\n * 100% domain-neutral and the agent leads the user through choosing what to predict.\n */\n@Component({\n standalone: true,\n selector: 'ps-home',\n imports: [CommonModule, MJButtonDirective],\n encapsulation: ViewEncapsulation.None,\n styleUrls: ['../predictive-studio.shared.scss', './ps-home.component.scss'],\n template: `\n <div class=\"ps-panel ps-home\" data-testid=\"ps-home-panel\">\n <!-- Hero -->\n <div class=\"hero\" data-testid=\"ps-home-hero\">\n <h2>Build a predictive model</h2>\n <div class=\"sub\">\n Train a model on your own data, start from a proven template, or let the Model Dev Agent\n design the pipeline for you.\n </div>\n <div class=\"hero-stats\">\n <div class=\"s\"><div class=\"n\">{{ kpis.publishedCount }}</div><div class=\"l\">Published</div></div>\n <div class=\"s\"><div class=\"n\">{{ kpis.activeExperiments }}</div><div class=\"l\">Active Experiments</div></div>\n <div class=\"s\"><div class=\"n\">{{ kpis.bestHoldout }}</div><div class=\"l\">Best Holdout AUC</div></div>\n <div class=\"s\"><div class=\"n\">{{ kpis.scoredThisWeek }}</div><div class=\"l\">Scored this week</div></div>\n </div>\n <div class=\"hero-actions\">\n <button mjButton variant=\"secondary\" size=\"sm\" (click)=\"navigate.emit('pipelines')\">\n <i class=\"fa-solid fa-diagram-project\"></i> New Training Pipeline\n </button>\n <button class=\"hero-ghost\" (click)=\"onAskAgent()\">\n <i class=\"fa-solid fa-robot\"></i> Ask the Model Dev Agent\n </button>\n </div>\n </div>\n\n <!-- Entry paths -->\n <div class=\"paths\" data-testid=\"ps-home-paths\">\n <div class=\"path\" data-testid=\"ps-home-path-data\" (click)=\"navigate.emit('pipelines')\">\n <div class=\"ic\"><i class=\"fa-solid fa-table-cells-large\"></i></div>\n <h4>Start from data</h4>\n <p>Point Studio at any entity's records, pick the target you want to predict, and we'll profile features automatically.</p>\n <button mjButton variant=\"primary\" size=\"sm\"><i class=\"fa-solid fa-arrow-right-to-bracket\"></i> Choose dataset</button>\n </div>\n <div class=\"path\" data-testid=\"ps-home-path-template\" (click)=\"navigate.emit('catalog')\">\n <div class=\"ic green\"><i class=\"fa-solid fa-layer-group\"></i></div>\n <h4>Use a template</h4>\n <p>Browse the algorithm catalog with a use-case guide that ranks each algorithm for your scenario.</p>\n <button mjButton variant=\"secondary\" size=\"sm\"><i class=\"fa-solid fa-clone\"></i> Browse catalog</button>\n </div>\n <div class=\"path\" data-testid=\"ps-home-path-agent\" (click)=\"onAskAgent()\">\n <div class=\"ic purple\"><i class=\"fa-solid fa-robot\"></i></div>\n <h4>Ask the agent</h4>\n <p>Describe the goal in plain English. The agent proposes algorithms, features, and a budget.</p>\n <button mjButton variant=\"secondary\" size=\"sm\"><i class=\"fa-solid fa-comment-dots\"></i> Open agent</button>\n </div>\n </div>\n\n <!-- Lower: timeline + side rail -->\n <div class=\"lower\">\n <div class=\"ps-card\">\n <div class=\"ps-card-head\">\n <i class=\"fa-solid fa-clock-rotate-left\" style=\"color: var(--mj-brand-primary)\"></i>\n <h3>Recent Activity</h3>\n <span class=\"ps-spacer\"></span>\n </div>\n <div class=\"ps-card-body\">\n @if (activity.length > 0) {\n <div class=\"feed\">\n @for (item of activity; track item.title + item.when) {\n <div class=\"fitem\">\n <div class=\"ev\" [class]=\"item.kind\"><i [class]=\"item.icon\"></i></div>\n <div>\n <div class=\"ftitle\">{{ item.title }}</div>\n <div class=\"ps-muted ps-small\">{{ item.detail }}</div>\n <div class=\"when\">{{ item.when }}</div>\n </div>\n </div>\n }\n </div>\n } @else {\n <div class=\"ps-empty\" style=\"padding:32px 16px\">\n <span class=\"ps-empty-ico\"><i class=\"fa-solid fa-clock-rotate-left\"></i></span>\n <p>No activity yet. Promote a model or run a scoring batch and it'll show up here.</p>\n </div>\n }\n </div>\n </div>\n\n <div class=\"ps-col\">\n <div class=\"ps-card\">\n <div class=\"ps-card-head\">\n <i class=\"fa-solid fa-gauge-high\" style=\"color: var(--mj-brand-primary)\"></i>\n <h3>This Week</h3>\n </div>\n <div class=\"ps-card-body\">\n <div class=\"mini-kpi\"><div class=\"ps-muted ps-small\">Records scored</div><div class=\"v\">{{ kpis.scoredThisWeek }}</div></div>\n <div class=\"mini-kpi\"><div class=\"ps-muted ps-small\">Best holdout AUC</div><div class=\"v\">{{ kpis.bestHoldout }}</div></div>\n <div class=\"mini-kpi\"><div class=\"ps-muted ps-small\">Experiment runs</div><div class=\"v\">{{ kpis.experimentRuns }}</div></div>\n <div class=\"mini-kpi\"><div class=\"ps-muted ps-small\">Published models</div><div class=\"v\">{{ kpis.publishedCount }}</div></div>\n </div>\n </div>\n </div>\n </div>\n </div>\n `,\n})\nexport class PSHomeComponent implements OnInit {\n @Input() engine!: PredictiveStudioEngine;\n /** Provider to load recent scoring runs through (multi-provider correctness). */\n @Input() provider: IMetadataProvider | null = null;\n /** Acting user for the on-demand scoring-runs load. */\n @Input() currentUser: UserInfo | null = null;\n @Output() navigate = new EventEmitter<PSPanelKey>();\n /**\n * Emitted when the user clicks an \"Ask the agent\" entry path. The payload is the starter prompt to seed\n * the Model Development Agent chat with — the entity-agnostic {@link PS_AGENT_STARTER_PROMPT} by default.\n */\n @Output() askAgent = new EventEmitter<string>();\n\n private cdr = inject(ChangeDetectorRef);\n\n /** Entry-path handler — emits {@link askAgent} with the default entity-agnostic starter prompt. */\n public onAskAgent(): void {\n this.askAgent.emit(PS_AGENT_STARTER_PROMPT);\n }\n\n /** Derived KPI strip. Starts from the synchronously-available counts, refined once runs load. */\n public kpis: PSHomeKpis = { publishedCount: 0, activeExperiments: 0, bestHoldout: '—', scoredThisWeek: '0', experimentRuns: 0 };\n /** Recent-activity timeline. */\n public activity: PSActivityFeedItem[] = [];\n\n /** Cached recent scoring runs (loaded on demand). */\n private scoringRuns: PSProcessRunRow[] = [];\n\n async ngOnInit(): Promise<void> {\n // Render immediately from cached data, then refine with the on-demand scoring-run load.\n this.rebuild();\n await this.loadScoringRuns();\n this.rebuild();\n this.cdr.detectChanges();\n }\n\n /** Load the recent ML scoring runs once (cheap, capped) for the KPI + activity feed. */\n private async loadScoringRuns(): Promise<void> {\n if (!this.provider) return;\n try {\n this.scoringRuns = await this.engine.LoadRecentScoringRuns(this.provider, this.currentUser ?? undefined, {\n sinceDays: 7,\n maxRows: 50,\n });\n } catch {\n this.scoringRuns = [];\n }\n }\n\n /** Recompute the KPI strip + activity feed from the current cached data + scoring runs. */\n private rebuild(): void {\n const models = this.engine?.Models ?? [];\n const runningSessions = this.engine?.RunningSessions.length ?? 0;\n const experimentRuns = this.engine?.Iterations.length ?? 0;\n\n this.kpis = computeHomeKpis(models, runningSessions, this.scoringRuns, experimentRuns);\n\n const eventSources: PSModelEventSource[] = models.map((m) => ({\n Name: this.engine.ModelDisplayName(m),\n Algorithm: this.engine.AlgorithmName(m.AlgorithmID),\n Status: m.Status,\n Metrics: m.Metrics,\n HoldoutMetrics: m.HoldoutMetrics,\n UpdatedAt: m.__mj_UpdatedAt,\n }));\n this.activity = buildActivityFeed(this.scoringRuns, deriveModelEvents(eventSources), new Date(), 6);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ps-home.component.js","sourceRoot":"","sources":["../../../src/PredictiveStudio/components/ps-home.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation, inject } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { MJButtonDirective } from '@memberjunction/ng-ui-components';\nimport { IMetadataProvider, UserInfo } from '@memberjunction/core';\nimport { PredictiveStudioEngine } from '../engine/predictive-studio.engine';\nimport { PSPanelKey } from '../predictive-studio.types';\nimport { PS_AGENT_STARTER_PROMPT } from './ps-agent-starter-prompt';\n\nexport { PS_AGENT_STARTER_PROMPT } from './ps-agent-starter-prompt';\nimport {\n PSActivityFeedItem,\n PSHomeKpis,\n PSModelEventSource,\n PSProcessRunRow,\n buildActivityFeed,\n computeHomeKpis,\n deriveModelEvents,\n} from '../predictive-studio.view-models';\n\n/**\n * Home panel — the action-forward landing: a hero \"Build a predictive model\" band with three entry\n * paths, a vertical recent-activity timeline, and a side rail of weekly KPIs. Fully live:\n *\n * - **KPIs** (published count, active experiments, best holdout AUC, scored-this-week) come from the\n * cached models/sessions + recent ML scoring runs loaded on demand, via {@link computeHomeKpis}.\n * - **Recent activity** merges recent ML scoring process runs and recent model promotions/archives\n * into one reverse-chronological feed via {@link buildActivityFeed}.\n *\n * Recent scoring runs are loaded once on init (cheap, capped) — `MJ: Process Runs` isn't bulk-cached\n * because it grows unbounded. 100% entity-agnostic.\n *\n * **\"Ask the agent\" entry path.** The hero CTA and the agent entry-path card emit {@link askAgent} with a\n * starter prompt string. The host resource (the Studio door's `PSStudioResourceComponent`) reveals the\n * docked Model Development Agent chat seeded with that prompt. The prompt is a deliberately entity-agnostic template\n * ({@link PS_AGENT_STARTER_PROMPT}) — it never names a specific entity/target, so Predictive Studio stays\n * 100% domain-neutral and the agent leads the user through choosing what to predict.\n */\n@Component({\n standalone: true,\n selector: 'ps-home',\n imports: [CommonModule, MJButtonDirective],\n encapsulation: ViewEncapsulation.None,\n styleUrls: ['../predictive-studio.shared.css', './ps-home.component.css'],\n template: `\n <div class=\"ps-panel ps-home\" data-testid=\"ps-home-panel\">\n <!-- Hero -->\n <div class=\"hero\" data-testid=\"ps-home-hero\">\n <h2>Build a predictive model</h2>\n <div class=\"sub\">\n Train a model on your own data, start from a proven template, or let the Model Dev Agent\n design the pipeline for you.\n </div>\n <div class=\"hero-stats\">\n <div class=\"s\"><div class=\"n\">{{ kpis.publishedCount }}</div><div class=\"l\">Published</div></div>\n <div class=\"s\"><div class=\"n\">{{ kpis.activeExperiments }}</div><div class=\"l\">Active Experiments</div></div>\n <div class=\"s\"><div class=\"n\">{{ kpis.bestHoldout }}</div><div class=\"l\">Best Holdout AUC</div></div>\n <div class=\"s\"><div class=\"n\">{{ kpis.scoredThisWeek }}</div><div class=\"l\">Scored this week</div></div>\n </div>\n <div class=\"hero-actions\">\n <button mjButton variant=\"secondary\" size=\"sm\" (click)=\"navigate.emit('pipelines')\">\n <i class=\"fa-solid fa-diagram-project\"></i> New Training Pipeline\n </button>\n <button class=\"hero-ghost\" (click)=\"onAskAgent()\">\n <i class=\"fa-solid fa-robot\"></i> Ask the Model Dev Agent\n </button>\n </div>\n </div>\n\n <!-- Entry paths -->\n <div class=\"paths\" data-testid=\"ps-home-paths\">\n <div class=\"path\" data-testid=\"ps-home-path-data\" (click)=\"navigate.emit('pipelines')\">\n <div class=\"ic\"><i class=\"fa-solid fa-table-cells-large\"></i></div>\n <h4>Start from data</h4>\n <p>Point Studio at any entity's records, pick the target you want to predict, and we'll profile features automatically.</p>\n <button mjButton variant=\"primary\" size=\"sm\"><i class=\"fa-solid fa-arrow-right-to-bracket\"></i> Choose dataset</button>\n </div>\n <div class=\"path\" data-testid=\"ps-home-path-template\" (click)=\"navigate.emit('catalog')\">\n <div class=\"ic green\"><i class=\"fa-solid fa-layer-group\"></i></div>\n <h4>Use a template</h4>\n <p>Browse the algorithm catalog with a use-case guide that ranks each algorithm for your scenario.</p>\n <button mjButton variant=\"secondary\" size=\"sm\"><i class=\"fa-solid fa-clone\"></i> Browse catalog</button>\n </div>\n <div class=\"path\" data-testid=\"ps-home-path-agent\" (click)=\"onAskAgent()\">\n <div class=\"ic purple\"><i class=\"fa-solid fa-robot\"></i></div>\n <h4>Ask the agent</h4>\n <p>Describe the goal in plain English. The agent proposes algorithms, features, and a budget.</p>\n <button mjButton variant=\"secondary\" size=\"sm\"><i class=\"fa-solid fa-comment-dots\"></i> Open agent</button>\n </div>\n </div>\n\n <!-- Lower: timeline + side rail -->\n <div class=\"lower\">\n <div class=\"ps-card\">\n <div class=\"ps-card-head\">\n <i class=\"fa-solid fa-clock-rotate-left\" style=\"color: var(--mj-brand-primary)\"></i>\n <h3>Recent Activity</h3>\n <span class=\"ps-spacer\"></span>\n </div>\n <div class=\"ps-card-body\">\n @if (activity.length > 0) {\n <div class=\"feed\">\n @for (item of activity; track item.title + item.when) {\n <div class=\"fitem\">\n <div class=\"ev\" [class]=\"item.kind\"><i [class]=\"item.icon\"></i></div>\n <div>\n <div class=\"ftitle\">{{ item.title }}</div>\n <div class=\"ps-muted ps-small\">{{ item.detail }}</div>\n <div class=\"when\">{{ item.when }}</div>\n </div>\n </div>\n }\n </div>\n } @else {\n <div class=\"ps-empty\" style=\"padding:32px 16px\">\n <span class=\"ps-empty-ico\"><i class=\"fa-solid fa-clock-rotate-left\"></i></span>\n <p>No activity yet. Promote a model or run a scoring batch and it'll show up here.</p>\n </div>\n }\n </div>\n </div>\n\n <div class=\"ps-col\">\n <div class=\"ps-card\">\n <div class=\"ps-card-head\">\n <i class=\"fa-solid fa-gauge-high\" style=\"color: var(--mj-brand-primary)\"></i>\n <h3>This Week</h3>\n </div>\n <div class=\"ps-card-body\">\n <div class=\"mini-kpi\"><div class=\"ps-muted ps-small\">Records scored</div><div class=\"v\">{{ kpis.scoredThisWeek }}</div></div>\n <div class=\"mini-kpi\"><div class=\"ps-muted ps-small\">Best holdout AUC</div><div class=\"v\">{{ kpis.bestHoldout }}</div></div>\n <div class=\"mini-kpi\"><div class=\"ps-muted ps-small\">Experiment runs</div><div class=\"v\">{{ kpis.experimentRuns }}</div></div>\n <div class=\"mini-kpi\"><div class=\"ps-muted ps-small\">Published models</div><div class=\"v\">{{ kpis.publishedCount }}</div></div>\n </div>\n </div>\n </div>\n </div>\n </div>\n `,\n})\nexport class PSHomeComponent implements OnInit {\n @Input() engine!: PredictiveStudioEngine;\n /** Provider to load recent scoring runs through (multi-provider correctness). */\n @Input() provider: IMetadataProvider | null = null;\n /** Acting user for the on-demand scoring-runs load. */\n @Input() currentUser: UserInfo | null = null;\n @Output() navigate = new EventEmitter<PSPanelKey>();\n /**\n * Emitted when the user clicks an \"Ask the agent\" entry path. The payload is the starter prompt to seed\n * the Model Development Agent chat with — the entity-agnostic {@link PS_AGENT_STARTER_PROMPT} by default.\n */\n @Output() askAgent = new EventEmitter<string>();\n\n private cdr = inject(ChangeDetectorRef);\n\n /** Entry-path handler — emits {@link askAgent} with the default entity-agnostic starter prompt. */\n public onAskAgent(): void {\n this.askAgent.emit(PS_AGENT_STARTER_PROMPT);\n }\n\n /** Derived KPI strip. Starts from the synchronously-available counts, refined once runs load. */\n public kpis: PSHomeKpis = { publishedCount: 0, activeExperiments: 0, bestHoldout: '—', scoredThisWeek: '0', experimentRuns: 0 };\n /** Recent-activity timeline. */\n public activity: PSActivityFeedItem[] = [];\n\n /** Cached recent scoring runs (loaded on demand). */\n private scoringRuns: PSProcessRunRow[] = [];\n\n async ngOnInit(): Promise<void> {\n // Render immediately from cached data, then refine with the on-demand scoring-run load.\n this.rebuild();\n await this.loadScoringRuns();\n this.rebuild();\n this.cdr.detectChanges();\n }\n\n /** Load the recent ML scoring runs once (cheap, capped) for the KPI + activity feed. */\n private async loadScoringRuns(): Promise<void> {\n if (!this.provider) return;\n try {\n this.scoringRuns = await this.engine.LoadRecentScoringRuns(this.provider, this.currentUser ?? undefined, {\n sinceDays: 7,\n maxRows: 50,\n });\n } catch {\n this.scoringRuns = [];\n }\n }\n\n /** Recompute the KPI strip + activity feed from the current cached data + scoring runs. */\n private rebuild(): void {\n const models = this.engine?.Models ?? [];\n const runningSessions = this.engine?.RunningSessions.length ?? 0;\n const experimentRuns = this.engine?.Iterations.length ?? 0;\n\n this.kpis = computeHomeKpis(models, runningSessions, this.scoringRuns, experimentRuns);\n\n const eventSources: PSModelEventSource[] = models.map((m) => ({\n Name: this.engine.ModelDisplayName(m),\n Algorithm: this.engine.AlgorithmName(m.AlgorithmID),\n Status: m.Status,\n Metrics: m.Metrics,\n HoldoutMetrics: m.HoldoutMetrics,\n UpdatedAt: m.__mj_UpdatedAt,\n }));\n this.activity = buildActivityFeed(this.scoringRuns, deriveModelEvents(eventSources), new Date(), 6);\n }\n}\n"]}
|
|
@@ -448,7 +448,7 @@ export class PSOperateDialogComponent extends BaseAngularComponent {
|
|
|
448
448
|
i0.ɵɵproperty("disabled", ctx.busy);
|
|
449
449
|
i0.ɵɵadvance(2);
|
|
450
450
|
i0.ɵɵproperty("Visible", ctx.scheduleOpen)("JobTypeID", ctx.jobTypeId)("DefaultConfiguration", ctx.schedConfig)("HideJobType", true);
|
|
451
|
-
} }, dependencies: [CommonModule, MJButtonDirective, MJDialogComponent, SchedulingModule, i1.ScheduledJobDialogComponent], 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", "// \"Operate this model\" dialog \u2014 scope + output knobs, composed Remote Ops. Tokens only.\n\n.ps-operate {\n display: flex;\n flex-direction: column;\n gap: 18px;\n padding: 4px 2px;\n}\n\n.ps-operate .op-target {\n margin: 0;\n}\n\n.ps-operate .op-hint {\n margin-top: 6px;\n}\n\n.ps-operate .op-summary {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n color: var(--mj-text-secondary);\n}\n.ps-operate .op-summary i {\n color: var(--mj-brand-primary);\n}\n\n// smaller segmented control (value-kind toggle)\n.ps-operate .ps-seg.sm button {\n font-size: 12px;\n padding: 5px 10px;\n}\n\n.op-footer {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 14px 2px 2px;\n}\n"], encapsulation: 2 });
|
|
451
|
+
} }, dependencies: [CommonModule, MJButtonDirective, MJDialogComponent, SchedulingModule, i1.ScheduledJobDialogComponent], 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", "/* \"Operate this model\" dialog \u2014 scope + output knobs, composed Remote Ops. Tokens only. */\n\n.ps-operate {\n display: flex;\n flex-direction: column;\n gap: 18px;\n padding: 4px 2px;\n}\n\n.ps-operate .op-target {\n margin: 0;\n}\n\n.ps-operate .op-hint {\n margin-top: 6px;\n}\n\n.ps-operate .op-summary {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n color: var(--mj-text-secondary);\n}\n.ps-operate .op-summary i {\n color: var(--mj-brand-primary);\n}\n\n/* smaller segmented control (value-kind toggle) */\n.ps-operate .ps-seg.sm button {\n font-size: 12px;\n padding: 5px 10px;\n}\n\n.op-footer {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 14px 2px 2px;\n}\n"], encapsulation: 2 });
|
|
452
452
|
}
|
|
453
453
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PSOperateDialogComponent, [{
|
|
454
454
|
type: Component,
|
|
@@ -537,7 +537,7 @@ export class PSOperateDialogComponent extends BaseAngularComponent {
|
|
|
537
537
|
[HideJobType]="true"
|
|
538
538
|
(Close)="onScheduleClose($event)">
|
|
539
539
|
</mj-scheduled-job-dialog>
|
|
540
|
-
`, 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", "// \"Operate this model\" dialog \u2014 scope + output knobs, composed Remote Ops. Tokens only.\n\n.ps-operate {\n display: flex;\n flex-direction: column;\n gap: 18px;\n padding: 4px 2px;\n}\n\n.ps-operate .op-target {\n margin: 0;\n}\n\n.ps-operate .op-hint {\n margin-top: 6px;\n}\n\n.ps-operate .op-summary {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n color: var(--mj-text-secondary);\n}\n.ps-operate .op-summary i {\n color: var(--mj-brand-primary);\n}\n\n// smaller segmented control (value-kind toggle)\n.ps-operate .ps-seg.sm button {\n font-size: 12px;\n padding: 5px 10px;\n}\n\n.op-footer {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 14px 2px 2px;\n}\n"] }]
|
|
540
|
+
`, 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", "/* \"Operate this model\" dialog \u2014 scope + output knobs, composed Remote Ops. Tokens only. */\n\n.ps-operate {\n display: flex;\n flex-direction: column;\n gap: 18px;\n padding: 4px 2px;\n}\n\n.ps-operate .op-target {\n margin: 0;\n}\n\n.ps-operate .op-hint {\n margin-top: 6px;\n}\n\n.ps-operate .op-summary {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n color: var(--mj-text-secondary);\n}\n.ps-operate .op-summary i {\n color: var(--mj-brand-primary);\n}\n\n/* smaller segmented control (value-kind toggle) */\n.ps-operate .ps-seg.sm button {\n font-size: 12px;\n padding: 5px 10px;\n}\n\n.op-footer {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 14px 2px 2px;\n}\n"] }]
|
|
541
541
|
}], null, { modelId: [{
|
|
542
542
|
type: Input
|
|
543
543
|
}], modelLabel: [{
|