@memberjunction/ng-core-entity-forms 6.2.0 → 6.3.0-edge.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/README.md +5 -6
- package/dist/lib/custom/AIAgentCategories/ai-agent-category-header.panel.d.ts.map +1 -1
- package/dist/lib/custom/AIAgentCategories/ai-agent-category-header.panel.js +3 -3
- package/dist/lib/custom/AIAgentCategories/ai-agent-category-header.panel.js.map +1 -1
- package/dist/lib/custom/AIAgentSessions/ai-agent-session-form.component.d.ts +12 -0
- package/dist/lib/custom/AIAgentSessions/ai-agent-session-form.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgentSessions/ai-agent-session-form.component.js +293 -230
- package/dist/lib/custom/AIAgentSessions/ai-agent-session-form.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/add-action-dialog.component.js +2 -2
- package/dist/lib/custom/AIAgents/agent-prompt-advanced-settings-dialog.component.js +2 -2
- package/dist/lib/custom/AIAgents/ai-agent-form.component.d.ts +11 -0
- package/dist/lib/custom/AIAgents/ai-agent-form.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/ai-agent-form.component.js +862 -812
- package/dist/lib/custom/AIAgents/ai-agent-form.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/create-prompt-dialog.component.js +2 -2
- package/dist/lib/custom/AIAgents/create-sub-agent-dialog.component.js +2 -2
- package/dist/lib/custom/AIAgents/new-agent-dialog.component.js +2 -2
- package/dist/lib/custom/AIAgents/prompt-selector-dialog.component.js +2 -2
- package/dist/lib/custom/AIAgents/sub-agent-advanced-settings-dialog.component.js +2 -2
- package/dist/lib/custom/AIAgents/sub-agent-selector-dialog.component.js +2 -2
- package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.d.ts +12 -0
- package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.d.ts.map +1 -1
- package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.js +821 -763
- package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.js.map +1 -1
- package/dist/lib/custom/AIPromptRuns/chat-message-viewer.component.js +2 -2
- package/dist/lib/custom/AIPrompts/ai-prompt-form.component.d.ts +10 -0
- package/dist/lib/custom/AIPrompts/ai-prompt-form.component.d.ts.map +1 -1
- package/dist/lib/custom/AIPrompts/ai-prompt-form.component.js +700 -605
- package/dist/lib/custom/AIPrompts/ai-prompt-form.component.js.map +1 -1
- package/dist/lib/custom/Actions/action-execution-log-form.component.d.ts +10 -0
- package/dist/lib/custom/Actions/action-execution-log-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Actions/action-execution-log-form.component.js +223 -175
- package/dist/lib/custom/Actions/action-execution-log-form.component.js.map +1 -1
- package/dist/lib/custom/Actions/action-form.component.d.ts +10 -0
- package/dist/lib/custom/Actions/action-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Actions/action-form.component.js +502 -453
- package/dist/lib/custom/Actions/action-form.component.js.map +1 -1
- package/dist/lib/custom/Companies/company-header.panel.d.ts.map +1 -1
- package/dist/lib/custom/Companies/company-header.panel.js +3 -3
- package/dist/lib/custom/Companies/company-header.panel.js.map +1 -1
- package/dist/lib/custom/Conversations/conversation-header.panel.d.ts.map +1 -1
- package/dist/lib/custom/Conversations/conversation-header.panel.js +3 -3
- package/dist/lib/custom/Conversations/conversation-header.panel.js.map +1 -1
- package/dist/lib/custom/Employees/employee-header.panel.d.ts.map +1 -1
- package/dist/lib/custom/Employees/employee-header.panel.js +3 -3
- package/dist/lib/custom/Employees/employee-header.panel.js.map +1 -1
- package/dist/lib/custom/Entities/entity-form.component.d.ts +15 -0
- package/dist/lib/custom/Entities/entity-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Entities/entity-form.component.js +836 -801
- package/dist/lib/custom/Entities/entity-form.component.js.map +1 -1
- package/dist/lib/custom/EntityActions/entityaction.form.component.js +2 -2
- package/dist/lib/custom/Files/file-form.component.js +2 -2
- package/dist/lib/custom/Lists/list-form.component.d.ts +5 -0
- package/dist/lib/custom/Lists/list-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Lists/list-form.component.js +355 -338
- package/dist/lib/custom/Lists/list-form.component.js.map +1 -1
- package/dist/lib/custom/MLModels/ml-model-form.component.js +3 -3
- package/dist/lib/custom/MLModels/ml-model-form.component.js.map +1 -1
- package/dist/lib/custom/MLModels/ml-model-view-models.d.ts +17 -35
- package/dist/lib/custom/MLModels/ml-model-view-models.d.ts.map +1 -1
- package/dist/lib/custom/MLModels/ml-model-view-models.js +55 -54
- package/dist/lib/custom/MLModels/ml-model-view-models.js.map +1 -1
- package/dist/lib/custom/MLModels/ps-model-detail.component.d.ts +7 -99
- package/dist/lib/custom/MLModels/ps-model-detail.component.d.ts.map +1 -1
- package/dist/lib/custom/MLModels/ps-model-detail.component.js +124 -303
- package/dist/lib/custom/MLModels/ps-model-detail.component.js.map +1 -1
- package/dist/lib/custom/Queries/query-form.component.d.ts +9 -0
- package/dist/lib/custom/Queries/query-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Queries/query-form.component.js +493 -444
- package/dist/lib/custom/Queries/query-form.component.js.map +1 -1
- package/dist/lib/custom/Queries/query-run-dialog.component.js +2 -2
- package/dist/lib/custom/Templates/template-param-dialog.component.js +2 -2
- package/dist/lib/custom/Templates/templates-form.component.d.ts +9 -0
- package/dist/lib/custom/Templates/templates-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Templates/templates-form.component.js +118 -74
- package/dist/lib/custom/Templates/templates-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-form.component.d.ts +5 -0
- package/dist/lib/custom/Tests/test-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/test-form.component.js +471 -451
- package/dist/lib/custom/Tests/test-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-run-form.component.d.ts +5 -0
- package/dist/lib/custom/Tests/test-run-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/test-run-form.component.js +312 -289
- package/dist/lib/custom/Tests/test-run-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-suite-form.component.d.ts +5 -0
- package/dist/lib/custom/Tests/test-suite-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/test-suite-form.component.js +697 -677
- package/dist/lib/custom/Tests/test-suite-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-suite-run-form.component.d.ts +5 -0
- package/dist/lib/custom/Tests/test-suite-run-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/test-suite-run-form.component.js +453 -433
- package/dist/lib/custom/Tests/test-suite-run-form.component.js.map +1 -1
- package/dist/lib/custom/Users/user-header.panel.d.ts.map +1 -1
- package/dist/lib/custom/Users/user-header.panel.js +3 -3
- package/dist/lib/custom/Users/user-header.panel.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/agent-run-cost-split.d.ts +2 -2
- package/dist/lib/custom/ai-agent-run/agent-run-cost-split.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/agent-run-cost-split.js +30 -13
- package/dist/lib/custom/ai-agent-run/agent-run-cost-split.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run.component.d.ts +23 -0
- package/dist/lib/custom/ai-agent-run/ai-agent-run.component.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js +276 -216
- package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js.map +1 -1
- package/dist/lib/custom/custom-forms.module.d.ts +1 -1
- package/dist/lib/custom/custom-forms.module.d.ts.map +1 -1
- package/dist/lib/custom/custom-forms.module.js +7 -1
- package/dist/lib/custom/custom-forms.module.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIPromptRun/mjaipromptrun.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAIPromptRun/mjaipromptrun.form.component.js +32 -14
- package/dist/lib/generated/Entities/MJAIPromptRun/mjaipromptrun.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAction/mjaction.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAction/mjaction.form.component.js +119 -95
- package/dist/lib/generated/Entities/MJAction/mjaction.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJComment/mjcomment.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJComment/mjcomment.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJComment/mjcomment.form.component.js +124 -0
- package/dist/lib/generated/Entities/MJComment/mjcomment.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJCommentType/mjcommenttype.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJCommentType/mjcommenttype.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJCommentType/mjcommenttype.form.component.js +99 -0
- package/dist/lib/generated/Entities/MJCommentType/mjcommenttype.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJConversation/mjconversation.form.component.js +2 -2
- package/dist/lib/generated/Entities/MJConversation/mjconversation.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJConversationType/mjconversationtype.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJConversationType/mjconversationtype.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJConversationType/mjconversationtype.form.component.js +95 -0
- package/dist/lib/generated/Entities/MJConversationType/mjconversationtype.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJDocumentSequenceCounter/mjdocumentsequencecounter.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJDocumentSequenceCounter/mjdocumentsequencecounter.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJDocumentSequenceCounter/mjdocumentsequencecounter.form.component.js +60 -0
- package/dist/lib/generated/Entities/MJDocumentSequenceCounter/mjdocumentsequencecounter.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js +124 -106
- package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJEntityFieldValue/mjentityfieldvalue.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJEntityFieldValue/mjentityfieldvalue.form.component.js +12 -4
- package/dist/lib/generated/Entities/MJEntityFieldValue/mjentityfieldvalue.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJEntityOrganicKey/mjentityorganickey.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJEntityOrganicKey/mjentityorganickey.form.component.js +19 -11
- package/dist/lib/generated/Entities/MJEntityOrganicKey/mjentityorganickey.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJEntityUniqueKey/mjentityuniquekey.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJEntityUniqueKey/mjentityuniquekey.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJEntityUniqueKey/mjentityuniquekey.form.component.js +62 -0
- package/dist/lib/generated/Entities/MJEntityUniqueKey/mjentityuniquekey.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJFeatureValue/mjfeaturevalue.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJFeatureValue/mjfeaturevalue.form.component.js +26 -12
- package/dist/lib/generated/Entities/MJFeatureValue/mjfeaturevalue.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJFieldSuggestion/mjfieldsuggestion.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJFieldSuggestion/mjfieldsuggestion.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJFieldSuggestion/mjfieldsuggestion.form.component.js +140 -0
- package/dist/lib/generated/Entities/MJFieldSuggestion/mjfieldsuggestion.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJFile/mjfile.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJFile/mjfile.form.component.js +69 -15
- package/dist/lib/generated/Entities/MJFile/mjfile.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJFileStorageProvider/mjfilestorageprovider.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJFileStorageProvider/mjfilestorageprovider.form.component.js +31 -13
- package/dist/lib/generated/Entities/MJFileStorageProvider/mjfilestorageprovider.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJMLEvaluationProtocol/mjmlevaluationprotocol.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJMLEvaluationProtocol/mjmlevaluationprotocol.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJMLEvaluationProtocol/mjmlevaluationprotocol.form.component.js +205 -0
- package/dist/lib/generated/Entities/MJMLEvaluationProtocol/mjmlevaluationprotocol.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJMLModel/mjmlmodel.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJMLModel/mjmlmodel.form.component.js +24 -6
- package/dist/lib/generated/Entities/MJMLModel/mjmlmodel.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJMLPredictionUnit/mjmlpredictionunit.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJMLPredictionUnit/mjmlpredictionunit.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJMLPredictionUnit/mjmlpredictionunit.form.component.js +173 -0
- package/dist/lib/generated/Entities/MJMLPredictionUnit/mjmlpredictionunit.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJMLTrainingPipeline/mjmltrainingpipeline.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJMLTrainingPipeline/mjmltrainingpipeline.form.component.js +46 -24
- package/dist/lib/generated/Entities/MJMLTrainingPipeline/mjmltrainingpipeline.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJMLTrainingRun/mjmltrainingrun.form.component.js +22 -14
- package/dist/lib/generated/Entities/MJMLTrainingRun/mjmltrainingrun.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJMLTrainingSnapshot/mjmltrainingsnapshot.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJMLTrainingSnapshot/mjmltrainingsnapshot.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJMLTrainingSnapshot/mjmltrainingsnapshot.form.component.js +175 -0
- package/dist/lib/generated/Entities/MJMLTrainingSnapshot/mjmltrainingsnapshot.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJQueryField/mjqueryfield.form.component.js +8 -6
- package/dist/lib/generated/Entities/MJQueryField/mjqueryfield.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJRecordProcess/mjrecordprocess.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJRecordProcess/mjrecordprocess.form.component.js +44 -36
- package/dist/lib/generated/Entities/MJRecordProcess/mjrecordprocess.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJTask/mjtask.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJTask/mjtask.form.component.js +54 -32
- package/dist/lib/generated/Entities/MJTask/mjtask.form.component.js.map +1 -1
- package/dist/lib/generated/generated-forms.module.d.ts +452 -443
- package/dist/lib/generated/generated-forms.module.d.ts.map +1 -1
- package/dist/lib/generated/generated-forms.module.js +27 -0
- package/dist/lib/generated/generated-forms.module.js.map +1 -1
- package/dist/lib/panels/feature-values/feature-values.panel.js +1 -1
- package/dist/lib/panels/feature-values/feature-values.panel.js.map +1 -1
- package/dist/lib/panels/model-predictions/model-prediction.logic.d.ts +1 -1
- package/dist/lib/panels/model-predictions/model-prediction.logic.d.ts.map +1 -1
- package/dist/lib/panels/model-predictions/model-prediction.logic.js.map +1 -1
- package/dist/lib/shared/components/template-editor.component.js +2 -2
- package/dist/lib/shared/phone-hero.d.ts +17 -0
- package/dist/lib/shared/phone-hero.d.ts.map +1 -0
- package/dist/lib/shared/phone-hero.js +30 -0
- package/dist/lib/shared/phone-hero.js.map +1 -0
- package/dist/lib/shared/phone-sections-state.d.ts +28 -0
- package/dist/lib/shared/phone-sections-state.d.ts.map +1 -0
- package/dist/lib/shared/phone-sections-state.js +38 -0
- package/dist/lib/shared/phone-sections-state.js.map +1 -0
- package/package.json +50 -50
|
@@ -43,7 +43,7 @@ function MJTestSuiteFormComponentExtended_Conditional_21_Template(rf, ctx) { if
|
|
|
43
43
|
} }
|
|
44
44
|
function MJTestSuiteFormComponentExtended_Conditional_26_Template(rf, ctx) { if (rf & 1) {
|
|
45
45
|
i0.ɵɵelementStart(0, "span", 20);
|
|
46
|
-
i0.ɵɵelement(1, "i",
|
|
46
|
+
i0.ɵɵelement(1, "i", 34);
|
|
47
47
|
i0.ɵɵtext(2);
|
|
48
48
|
i0.ɵɵelementEnd();
|
|
49
49
|
} if (rf & 2) {
|
|
@@ -53,7 +53,7 @@ function MJTestSuiteFormComponentExtended_Conditional_26_Template(rf, ctx) { if
|
|
|
53
53
|
} }
|
|
54
54
|
function MJTestSuiteFormComponentExtended_Conditional_27_Template(rf, ctx) { if (rf & 1) {
|
|
55
55
|
i0.ɵɵelementStart(0, "span", 21);
|
|
56
|
-
i0.ɵɵelement(1, "i",
|
|
56
|
+
i0.ɵɵelement(1, "i", 58);
|
|
57
57
|
i0.ɵɵtext(2, " Unsaved ");
|
|
58
58
|
i0.ɵɵelementEnd();
|
|
59
59
|
} }
|
|
@@ -66,8 +66,8 @@ function MJTestSuiteFormComponentExtended_Conditional_39_Template(rf, ctx) { if
|
|
|
66
66
|
i0.ɵɵadvance(2);
|
|
67
67
|
i0.ɵɵtextInterpolate(ctx_r0.record.Description);
|
|
68
68
|
} }
|
|
69
|
-
function
|
|
70
|
-
i0.ɵɵelementStart(0, "span",
|
|
69
|
+
function MJTestSuiteFormComponentExtended_Conditional_49_Template(rf, ctx) { if (rf & 1) {
|
|
70
|
+
i0.ɵɵelementStart(0, "span", 35);
|
|
71
71
|
i0.ɵɵtext(1);
|
|
72
72
|
i0.ɵɵelementEnd();
|
|
73
73
|
} if (rf & 2) {
|
|
@@ -75,8 +75,8 @@ function MJTestSuiteFormComponentExtended_Conditional_48_Template(rf, ctx) { if
|
|
|
75
75
|
i0.ɵɵadvance();
|
|
76
76
|
i0.ɵɵtextInterpolate(ctx_r0.suiteTests.length);
|
|
77
77
|
} }
|
|
78
|
-
function
|
|
79
|
-
i0.ɵɵelementStart(0, "span",
|
|
78
|
+
function MJTestSuiteFormComponentExtended_Conditional_53_Template(rf, ctx) { if (rf & 1) {
|
|
79
|
+
i0.ɵɵelementStart(0, "span", 35);
|
|
80
80
|
i0.ɵɵtext(1);
|
|
81
81
|
i0.ɵɵelementEnd();
|
|
82
82
|
} if (rf & 2) {
|
|
@@ -84,8 +84,8 @@ function MJTestSuiteFormComponentExtended_Conditional_52_Template(rf, ctx) { if
|
|
|
84
84
|
i0.ɵɵadvance();
|
|
85
85
|
i0.ɵɵtextInterpolate(ctx_r0.suiteRuns.length);
|
|
86
86
|
} }
|
|
87
|
-
function
|
|
88
|
-
i0.ɵɵelementStart(0, "option",
|
|
87
|
+
function MJTestSuiteFormComponentExtended_Conditional_61_For_25_Template(rf, ctx) { if (rf & 1) {
|
|
88
|
+
i0.ɵɵelementStart(0, "option", 74);
|
|
89
89
|
i0.ɵɵtext(1);
|
|
90
90
|
i0.ɵɵelementEnd();
|
|
91
91
|
} if (rf & 2) {
|
|
@@ -94,8 +94,8 @@ function MJTestSuiteFormComponentExtended_Conditional_60_For_25_Template(rf, ctx
|
|
|
94
94
|
i0.ɵɵadvance();
|
|
95
95
|
i0.ɵɵtextInterpolate(opt_r3);
|
|
96
96
|
} }
|
|
97
|
-
function
|
|
98
|
-
i0.ɵɵelementStart(0, "option",
|
|
97
|
+
function MJTestSuiteFormComponentExtended_Conditional_61_For_33_Template(rf, ctx) { if (rf & 1) {
|
|
98
|
+
i0.ɵɵelementStart(0, "option", 74);
|
|
99
99
|
i0.ɵɵtext(1);
|
|
100
100
|
i0.ɵɵelementEnd();
|
|
101
101
|
} if (rf & 2) {
|
|
@@ -104,8 +104,8 @@ function MJTestSuiteFormComponentExtended_Conditional_60_For_33_Template(rf, ctx
|
|
|
104
104
|
i0.ɵɵadvance();
|
|
105
105
|
i0.ɵɵtextInterpolate(rubric_r4.name);
|
|
106
106
|
} }
|
|
107
|
-
function
|
|
108
|
-
i0.ɵɵelementStart(0, "option",
|
|
107
|
+
function MJTestSuiteFormComponentExtended_Conditional_61_For_41_Template(rf, ctx) { if (rf & 1) {
|
|
108
|
+
i0.ɵɵelementStart(0, "option", 74);
|
|
109
109
|
i0.ɵɵtext(1);
|
|
110
110
|
i0.ɵɵelementEnd();
|
|
111
111
|
} if (rf & 2) {
|
|
@@ -114,13 +114,13 @@ function MJTestSuiteFormComponentExtended_Conditional_60_For_41_Template(rf, ctx
|
|
|
114
114
|
i0.ɵɵadvance();
|
|
115
115
|
i0.ɵɵtextInterpolate(s_r5.Name);
|
|
116
116
|
} }
|
|
117
|
-
function
|
|
117
|
+
function MJTestSuiteFormComponentExtended_Conditional_61_For_47_Template(rf, ctx) { if (rf & 1) {
|
|
118
118
|
const _r7 = i0.ɵɵgetCurrentView();
|
|
119
|
-
i0.ɵɵelementStart(0, "span",
|
|
119
|
+
i0.ɵɵelementStart(0, "span", 81);
|
|
120
120
|
i0.ɵɵtext(1);
|
|
121
|
-
i0.ɵɵelementStart(2, "button",
|
|
122
|
-
i0.ɵɵlistener("click", function
|
|
123
|
-
i0.ɵɵelement(3, "i",
|
|
121
|
+
i0.ɵɵelementStart(2, "button", 93);
|
|
122
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_61_For_47_Template_button_click_2_listener($event) { const tag_r8 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r0 = i0.ɵɵnextContext(2); ctx_r0.removeTag(tag_r8); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
123
|
+
i0.ɵɵelement(3, "i", 94);
|
|
124
124
|
i0.ɵɵelementEnd()();
|
|
125
125
|
} if (rf & 2) {
|
|
126
126
|
const tag_r8 = ctx.$implicit;
|
|
@@ -129,100 +129,100 @@ function MJTestSuiteFormComponentExtended_Conditional_60_For_47_Template(rf, ctx
|
|
|
129
129
|
i0.ɵɵadvance();
|
|
130
130
|
i0.ɵɵattribute("aria-label", "Remove tag " + tag_r8);
|
|
131
131
|
} }
|
|
132
|
-
function
|
|
132
|
+
function MJTestSuiteFormComponentExtended_Conditional_61_Template(rf, ctx) { if (rf & 1) {
|
|
133
133
|
const _r2 = i0.ɵɵgetCurrentView();
|
|
134
|
-
i0.ɵɵelementStart(0, "div",
|
|
135
|
-
i0.ɵɵelement(4, "i",
|
|
134
|
+
i0.ɵɵelementStart(0, "div", 40)(1, "section", 59)(2, "header", 60)(3, "h3");
|
|
135
|
+
i0.ɵɵelement(4, "i", 61);
|
|
136
136
|
i0.ɵɵtext(5, " Details");
|
|
137
137
|
i0.ɵɵelementEnd();
|
|
138
|
-
i0.ɵɵelementStart(6, "p",
|
|
138
|
+
i0.ɵɵelementStart(6, "p", 62);
|
|
139
139
|
i0.ɵɵtext(7, "Edit any field \u2014 changes are saved with the bar at the bottom.");
|
|
140
140
|
i0.ɵɵelementEnd()();
|
|
141
|
-
i0.ɵɵelementStart(8, "div",
|
|
141
|
+
i0.ɵɵelementStart(8, "div", 63)(9, "div", 64)(10, "label", 65);
|
|
142
142
|
i0.ɵɵtext(11, "Name ");
|
|
143
|
-
i0.ɵɵelementStart(12, "span",
|
|
143
|
+
i0.ɵɵelementStart(12, "span", 66);
|
|
144
144
|
i0.ɵɵtext(13, "*");
|
|
145
145
|
i0.ɵɵelementEnd()();
|
|
146
|
-
i0.ɵɵelementStart(14, "input",
|
|
147
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
146
|
+
i0.ɵɵelementStart(14, "input", 67);
|
|
147
|
+
i0.ɵɵtwoWayListener("ngModelChange", function MJTestSuiteFormComponentExtended_Conditional_61_Template_input_ngModelChange_14_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r0.record.Name, $event) || (ctx_r0.record.Name = $event); return i0.ɵɵresetView($event); });
|
|
148
148
|
i0.ɵɵelementEnd()();
|
|
149
|
-
i0.ɵɵelementStart(15, "div",
|
|
149
|
+
i0.ɵɵelementStart(15, "div", 64)(16, "label", 68);
|
|
150
150
|
i0.ɵɵtext(17, "Description");
|
|
151
151
|
i0.ɵɵelementEnd();
|
|
152
|
-
i0.ɵɵelementStart(18, "textarea",
|
|
153
|
-
i0.ɵɵlistener("ngModelChange", function
|
|
152
|
+
i0.ɵɵelementStart(18, "textarea", 69);
|
|
153
|
+
i0.ɵɵlistener("ngModelChange", function MJTestSuiteFormComponentExtended_Conditional_61_Template_textarea_ngModelChange_18_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.record.Description = $event || null); });
|
|
154
154
|
i0.ɵɵelementEnd()();
|
|
155
|
-
i0.ɵɵelementStart(19, "div",
|
|
155
|
+
i0.ɵɵelementStart(19, "div", 70)(20, "label", 71);
|
|
156
156
|
i0.ɵɵtext(21, "Status");
|
|
157
157
|
i0.ɵɵelementEnd();
|
|
158
|
-
i0.ɵɵelementStart(22, "div",
|
|
159
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
160
|
-
i0.ɵɵrepeaterCreate(24,
|
|
158
|
+
i0.ɵɵelementStart(22, "div", 72)(23, "select", 73);
|
|
159
|
+
i0.ɵɵtwoWayListener("ngModelChange", function MJTestSuiteFormComponentExtended_Conditional_61_Template_select_ngModelChange_23_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r0.record.Status, $event) || (ctx_r0.record.Status = $event); return i0.ɵɵresetView($event); });
|
|
160
|
+
i0.ɵɵrepeaterCreate(24, MJTestSuiteFormComponentExtended_Conditional_61_For_25_Template, 2, 2, "option", 74, i0.ɵɵrepeaterTrackByIdentity);
|
|
161
161
|
i0.ɵɵelementEnd()()();
|
|
162
|
-
i0.ɵɵelementStart(26, "div",
|
|
162
|
+
i0.ɵɵelementStart(26, "div", 70)(27, "label", 75);
|
|
163
163
|
i0.ɵɵtext(28, "Rubric");
|
|
164
164
|
i0.ɵɵelementEnd();
|
|
165
|
-
i0.ɵɵelementStart(29, "select",
|
|
166
|
-
i0.ɵɵlistener("ngModelChange", function
|
|
167
|
-
i0.ɵɵelementStart(30, "option",
|
|
165
|
+
i0.ɵɵelementStart(29, "select", 76);
|
|
166
|
+
i0.ɵɵlistener("ngModelChange", function MJTestSuiteFormComponentExtended_Conditional_61_Template_select_ngModelChange_29_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.record.RubricID = $event || null); });
|
|
167
|
+
i0.ɵɵelementStart(30, "option", 74);
|
|
168
168
|
i0.ɵɵtext(31, "\u2014 None \u2014");
|
|
169
169
|
i0.ɵɵelementEnd();
|
|
170
|
-
i0.ɵɵrepeaterCreate(32,
|
|
170
|
+
i0.ɵɵrepeaterCreate(32, MJTestSuiteFormComponentExtended_Conditional_61_For_33_Template, 2, 2, "option", 74, _forTrack0);
|
|
171
171
|
i0.ɵɵelementEnd()();
|
|
172
|
-
i0.ɵɵelementStart(34, "div",
|
|
172
|
+
i0.ɵɵelementStart(34, "div", 70)(35, "label", 77);
|
|
173
173
|
i0.ɵɵtext(36, "Parent Suite");
|
|
174
174
|
i0.ɵɵelementEnd();
|
|
175
|
-
i0.ɵɵelementStart(37, "select",
|
|
176
|
-
i0.ɵɵlistener("ngModelChange", function
|
|
177
|
-
i0.ɵɵelementStart(38, "option",
|
|
175
|
+
i0.ɵɵelementStart(37, "select", 78);
|
|
176
|
+
i0.ɵɵlistener("ngModelChange", function MJTestSuiteFormComponentExtended_Conditional_61_Template_select_ngModelChange_37_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.record.ParentID = $event || null); });
|
|
177
|
+
i0.ɵɵelementStart(38, "option", 74);
|
|
178
178
|
i0.ɵɵtext(39, "\u2014 None (top-level) \u2014");
|
|
179
179
|
i0.ɵɵelementEnd();
|
|
180
|
-
i0.ɵɵrepeaterCreate(40,
|
|
180
|
+
i0.ɵɵrepeaterCreate(40, MJTestSuiteFormComponentExtended_Conditional_61_For_41_Template, 2, 2, "option", 74, _forTrack1);
|
|
181
181
|
i0.ɵɵelementEnd()();
|
|
182
|
-
i0.ɵɵelementStart(42, "div",
|
|
182
|
+
i0.ɵɵelementStart(42, "div", 64)(43, "label", 79);
|
|
183
183
|
i0.ɵɵtext(44, "Tags");
|
|
184
184
|
i0.ɵɵelementEnd();
|
|
185
|
-
i0.ɵɵelementStart(45, "div",
|
|
186
|
-
i0.ɵɵlistener("click", function
|
|
187
|
-
i0.ɵɵrepeaterCreate(46,
|
|
188
|
-
i0.ɵɵelementStart(48, "input",
|
|
189
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
190
|
-
i0.ɵɵlistener("keydown", function
|
|
185
|
+
i0.ɵɵelementStart(45, "div", 80);
|
|
186
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_61_Template_div_click_45_listener() { i0.ɵɵrestoreView(_r2); const tagInput_r6 = i0.ɵɵreference(49); return i0.ɵɵresetView(tagInput_r6.focus()); });
|
|
187
|
+
i0.ɵɵrepeaterCreate(46, MJTestSuiteFormComponentExtended_Conditional_61_For_47_Template, 4, 2, "span", 81, i0.ɵɵrepeaterTrackByIdentity);
|
|
188
|
+
i0.ɵɵelementStart(48, "input", 82, 0);
|
|
189
|
+
i0.ɵɵtwoWayListener("ngModelChange", function MJTestSuiteFormComponentExtended_Conditional_61_Template_input_ngModelChange_48_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r0.tagDraft, $event) || (ctx_r0.tagDraft = $event); return i0.ɵɵresetView($event); });
|
|
190
|
+
i0.ɵɵlistener("keydown", function MJTestSuiteFormComponentExtended_Conditional_61_Template_input_keydown_48_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onTagInputKeydown($event)); })("blur", function MJTestSuiteFormComponentExtended_Conditional_61_Template_input_blur_48_listener() { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.addTagFromDraft()); });
|
|
191
191
|
i0.ɵɵelementEnd()();
|
|
192
|
-
i0.ɵɵelementStart(50, "span",
|
|
192
|
+
i0.ɵɵelementStart(50, "span", 83);
|
|
193
193
|
i0.ɵɵtext(51, "Press Enter or comma to add a tag. Backspace on empty input removes the last tag.");
|
|
194
194
|
i0.ɵɵelementEnd()()()();
|
|
195
|
-
i0.ɵɵelementStart(52, "section",
|
|
196
|
-
i0.ɵɵelement(55, "i",
|
|
195
|
+
i0.ɵɵelementStart(52, "section", 59)(53, "header", 60)(54, "h3");
|
|
196
|
+
i0.ɵɵelement(55, "i", 84);
|
|
197
197
|
i0.ɵɵtext(56, " Execution Settings");
|
|
198
198
|
i0.ɵɵelementEnd()();
|
|
199
|
-
i0.ɵɵelementStart(57, "div",
|
|
199
|
+
i0.ɵɵelementStart(57, "div", 63)(58, "div", 70)(59, "label", 85);
|
|
200
200
|
i0.ɵɵtext(60, "Max Execution Time (ms)");
|
|
201
201
|
i0.ɵɵelementEnd();
|
|
202
|
-
i0.ɵɵelementStart(61, "input",
|
|
203
|
-
i0.ɵɵlistener("ngModelChange", function
|
|
202
|
+
i0.ɵɵelementStart(61, "input", 86);
|
|
203
|
+
i0.ɵɵlistener("ngModelChange", function MJTestSuiteFormComponentExtended_Conditional_61_Template_input_ngModelChange_61_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.record.MaxExecutionTimeMS = $event === "" || $event === null ? null : +$event); });
|
|
204
204
|
i0.ɵɵelementEnd();
|
|
205
|
-
i0.ɵɵelementStart(62, "span",
|
|
205
|
+
i0.ɵɵelementStart(62, "span", 83);
|
|
206
206
|
i0.ɵɵtext(63);
|
|
207
207
|
i0.ɵɵelementEnd()()()();
|
|
208
|
-
i0.ɵɵelementStart(64, "section",
|
|
208
|
+
i0.ɵɵelementStart(64, "section", 87)(65, "div", 88)(66, "div", 89)(67, "div", 90);
|
|
209
209
|
i0.ɵɵtext(68, "Created");
|
|
210
210
|
i0.ɵɵelementEnd();
|
|
211
|
-
i0.ɵɵelementStart(69, "div",
|
|
211
|
+
i0.ɵɵelementStart(69, "div", 91);
|
|
212
212
|
i0.ɵɵtext(70);
|
|
213
213
|
i0.ɵɵpipe(71, "date");
|
|
214
214
|
i0.ɵɵelementEnd()();
|
|
215
|
-
i0.ɵɵelementStart(72, "div",
|
|
215
|
+
i0.ɵɵelementStart(72, "div", 89)(73, "div", 90);
|
|
216
216
|
i0.ɵɵtext(74, "Last updated");
|
|
217
217
|
i0.ɵɵelementEnd();
|
|
218
|
-
i0.ɵɵelementStart(75, "div",
|
|
218
|
+
i0.ɵɵelementStart(75, "div", 91);
|
|
219
219
|
i0.ɵɵtext(76);
|
|
220
220
|
i0.ɵɵpipe(77, "date");
|
|
221
221
|
i0.ɵɵelementEnd()();
|
|
222
|
-
i0.ɵɵelementStart(78, "div",
|
|
222
|
+
i0.ɵɵelementStart(78, "div", 89)(79, "div", 90);
|
|
223
223
|
i0.ɵɵtext(80, "Suite ID");
|
|
224
224
|
i0.ɵɵelementEnd();
|
|
225
|
-
i0.ɵɵelementStart(81, "div",
|
|
225
|
+
i0.ɵɵelementStart(81, "div", 92);
|
|
226
226
|
i0.ɵɵtext(82);
|
|
227
227
|
i0.ɵɵelementEnd()()()()();
|
|
228
228
|
} if (rf & 2) {
|
|
@@ -263,8 +263,8 @@ function MJTestSuiteFormComponentExtended_Conditional_60_Template(rf, ctx) { if
|
|
|
263
263
|
i0.ɵɵadvance(6);
|
|
264
264
|
i0.ɵɵtextInterpolate(ctx_r0.record.ID);
|
|
265
265
|
} }
|
|
266
|
-
function
|
|
267
|
-
i0.ɵɵelementStart(0, "span",
|
|
266
|
+
function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
267
|
+
i0.ɵɵelementStart(0, "span", 97);
|
|
268
268
|
i0.ɵɵtext(1);
|
|
269
269
|
i0.ɵɵelementEnd();
|
|
270
270
|
} if (rf & 2) {
|
|
@@ -272,24 +272,24 @@ function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_5_Template(
|
|
|
272
272
|
i0.ɵɵadvance();
|
|
273
273
|
i0.ɵɵtextInterpolate(ctx_r0.suiteTests.length);
|
|
274
274
|
} }
|
|
275
|
-
function
|
|
276
|
-
i0.ɵɵelementStart(0, "div",
|
|
277
|
-
i0.ɵɵelement(1, "div",
|
|
278
|
-
i0.ɵɵelementStart(3, "div",
|
|
279
|
-
i0.ɵɵelement(4, "div",
|
|
275
|
+
function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_12_For_3_Template(rf, ctx) { if (rf & 1) {
|
|
276
|
+
i0.ɵɵelementStart(0, "div", 106);
|
|
277
|
+
i0.ɵɵelement(1, "div", 107)(2, "div", 108);
|
|
278
|
+
i0.ɵɵelementStart(3, "div", 109);
|
|
279
|
+
i0.ɵɵelement(4, "div", 110)(5, "div", 111);
|
|
280
280
|
i0.ɵɵelementEnd()();
|
|
281
281
|
} }
|
|
282
|
-
function
|
|
283
|
-
i0.ɵɵelementStart(0, "div",
|
|
284
|
-
i0.ɵɵrepeaterCreate(2,
|
|
282
|
+
function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
283
|
+
i0.ɵɵelementStart(0, "div", 102)(1, "div", 105);
|
|
284
|
+
i0.ɵɵrepeaterCreate(2, MJTestSuiteFormComponentExtended_Conditional_62_Conditional_12_For_3_Template, 6, 0, "div", 106, i0.ɵɵrepeaterTrackByIdentity);
|
|
285
285
|
i0.ɵɵelementEnd()();
|
|
286
286
|
} if (rf & 2) {
|
|
287
287
|
i0.ɵɵadvance(2);
|
|
288
288
|
i0.ɵɵrepeater(i0.ɵɵpureFunction0(0, _c1));
|
|
289
289
|
} }
|
|
290
|
-
function
|
|
290
|
+
function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_13_For_2_Conditional_11_Template(rf, ctx) { if (rf & 1) {
|
|
291
291
|
i0.ɵɵelementStart(0, "span");
|
|
292
|
-
i0.ɵɵelement(1, "i",
|
|
292
|
+
i0.ɵɵelement(1, "i", 122);
|
|
293
293
|
i0.ɵɵtext(2);
|
|
294
294
|
i0.ɵɵelementEnd();
|
|
295
295
|
} if (rf & 2) {
|
|
@@ -297,25 +297,25 @@ function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_13_For_2_Co
|
|
|
297
297
|
i0.ɵɵadvance(2);
|
|
298
298
|
i0.ɵɵtextInterpolate1(" ", test_r12.Status);
|
|
299
299
|
} }
|
|
300
|
-
function
|
|
301
|
-
i0.ɵɵelement(0, "i",
|
|
300
|
+
function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_13_For_2_Conditional_12_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
301
|
+
i0.ɵɵelement(0, "i", 126);
|
|
302
302
|
} }
|
|
303
|
-
function
|
|
303
|
+
function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_13_For_2_Conditional_12_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
304
304
|
i0.ɵɵtext(0, " Remove ");
|
|
305
305
|
} }
|
|
306
|
-
function
|
|
306
|
+
function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_13_For_2_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
307
307
|
const _r13 = i0.ɵɵgetCurrentView();
|
|
308
|
-
i0.ɵɵelementStart(0, "div",
|
|
309
|
-
i0.ɵɵlistener("click", function
|
|
310
|
-
i0.ɵɵelementStart(1, "span",
|
|
308
|
+
i0.ɵɵelementStart(0, "div", 123);
|
|
309
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_13_For_2_Conditional_12_Template_div_click_0_listener($event) { return $event.stopPropagation(); });
|
|
310
|
+
i0.ɵɵelementStart(1, "span", 124);
|
|
311
311
|
i0.ɵɵtext(2, "Remove from suite?");
|
|
312
312
|
i0.ɵɵelementEnd();
|
|
313
|
-
i0.ɵɵelementStart(3, "button",
|
|
314
|
-
i0.ɵɵlistener("click", function
|
|
315
|
-
i0.ɵɵconditionalCreate(4,
|
|
313
|
+
i0.ɵɵelementStart(3, "button", 125);
|
|
314
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_13_For_2_Conditional_12_Template_button_click_3_listener($event) { i0.ɵɵrestoreView(_r13); const test_r12 = i0.ɵɵnextContext().$implicit; const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.confirmRemoveTest(test_r12, $event)); });
|
|
315
|
+
i0.ɵɵconditionalCreate(4, MJTestSuiteFormComponentExtended_Conditional_62_Conditional_13_For_2_Conditional_12_Conditional_4_Template, 1, 0, "i", 126)(5, MJTestSuiteFormComponentExtended_Conditional_62_Conditional_13_For_2_Conditional_12_Conditional_5_Template, 1, 0);
|
|
316
316
|
i0.ɵɵelementEnd();
|
|
317
|
-
i0.ɵɵelementStart(6, "button",
|
|
318
|
-
i0.ɵɵlistener("click", function
|
|
317
|
+
i0.ɵɵelementStart(6, "button", 127);
|
|
318
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_13_For_2_Conditional_12_Template_button_click_6_listener($event) { i0.ɵɵrestoreView(_r13); const ctx_r0 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r0.cancelRemoveTest($event)); });
|
|
319
319
|
i0.ɵɵtext(7, " Cancel ");
|
|
320
320
|
i0.ɵɵelementEnd()();
|
|
321
321
|
} if (rf & 2) {
|
|
@@ -327,36 +327,36 @@ function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_13_For_2_Co
|
|
|
327
327
|
i0.ɵɵadvance(2);
|
|
328
328
|
i0.ɵɵproperty("disabled", ctx_r0.isRemovingTest);
|
|
329
329
|
} }
|
|
330
|
-
function
|
|
330
|
+
function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_13_For_2_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
331
331
|
const _r14 = i0.ɵɵgetCurrentView();
|
|
332
|
-
i0.ɵɵelementStart(0, "button",
|
|
333
|
-
i0.ɵɵlistener("click", function
|
|
334
|
-
i0.ɵɵelement(1, "i",
|
|
332
|
+
i0.ɵɵelementStart(0, "button", 128);
|
|
333
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_13_For_2_Conditional_13_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r14); const test_r12 = i0.ɵɵnextContext().$implicit; const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.requestRemoveTest(test_r12, $event)); });
|
|
334
|
+
i0.ɵɵelement(1, "i", 94);
|
|
335
335
|
i0.ɵɵelementEnd();
|
|
336
|
-
i0.ɵɵelementStart(2, "i",
|
|
337
|
-
i0.ɵɵlistener("click", function
|
|
336
|
+
i0.ɵɵelementStart(2, "i", 129);
|
|
337
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_13_For_2_Conditional_13_Template_i_click_2_listener() { i0.ɵɵrestoreView(_r14); const test_r12 = i0.ɵɵnextContext().$implicit; const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.openTest(test_r12.TestID)); });
|
|
338
338
|
i0.ɵɵelementEnd();
|
|
339
339
|
} }
|
|
340
|
-
function
|
|
340
|
+
function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_13_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
341
341
|
const _r11 = i0.ɵɵgetCurrentView();
|
|
342
|
-
i0.ɵɵelementStart(0, "div",
|
|
343
|
-
i0.ɵɵelement(2, "i",
|
|
342
|
+
i0.ɵɵelementStart(0, "div", 113)(1, "span", 114);
|
|
343
|
+
i0.ɵɵelement(2, "i", 115);
|
|
344
344
|
i0.ɵɵelementEnd();
|
|
345
|
-
i0.ɵɵelementStart(3, "div",
|
|
345
|
+
i0.ɵɵelementStart(3, "div", 116);
|
|
346
346
|
i0.ɵɵtext(4);
|
|
347
347
|
i0.ɵɵelementEnd();
|
|
348
|
-
i0.ɵɵelementStart(5, "div",
|
|
349
|
-
i0.ɵɵelement(6, "i",
|
|
348
|
+
i0.ɵɵelementStart(5, "div", 117);
|
|
349
|
+
i0.ɵɵelement(6, "i", 34);
|
|
350
350
|
i0.ɵɵelementEnd();
|
|
351
|
-
i0.ɵɵelementStart(7, "div",
|
|
352
|
-
i0.ɵɵlistener("click", function
|
|
353
|
-
i0.ɵɵelementStart(8, "div",
|
|
351
|
+
i0.ɵɵelementStart(7, "div", 118);
|
|
352
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_13_For_2_Template_div_click_7_listener() { const test_r12 = i0.ɵɵrestoreView(_r11).$implicit; const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.openTest(test_r12.TestID)); });
|
|
353
|
+
i0.ɵɵelementStart(8, "div", 119);
|
|
354
354
|
i0.ɵɵtext(9);
|
|
355
355
|
i0.ɵɵelementEnd();
|
|
356
|
-
i0.ɵɵelementStart(10, "div",
|
|
357
|
-
i0.ɵɵconditionalCreate(11,
|
|
356
|
+
i0.ɵɵelementStart(10, "div", 120);
|
|
357
|
+
i0.ɵɵconditionalCreate(11, MJTestSuiteFormComponentExtended_Conditional_62_Conditional_13_For_2_Conditional_11_Template, 3, 1, "span");
|
|
358
358
|
i0.ɵɵelementEnd()();
|
|
359
|
-
i0.ɵɵconditionalCreate(12,
|
|
359
|
+
i0.ɵɵconditionalCreate(12, MJTestSuiteFormComponentExtended_Conditional_62_Conditional_13_For_2_Conditional_12_Template, 8, 3, "div", 121)(13, MJTestSuiteFormComponentExtended_Conditional_62_Conditional_13_For_2_Conditional_13_Template, 3, 0);
|
|
360
360
|
i0.ɵɵelementEnd();
|
|
361
361
|
} if (rf & 2) {
|
|
362
362
|
const test_r12 = ctx.$implicit;
|
|
@@ -371,40 +371,40 @@ function MJTestSuiteFormComponentExtended_Conditional_61_Conditional_13_For_2_Te
|
|
|
371
371
|
i0.ɵɵadvance();
|
|
372
372
|
i0.ɵɵconditional(ctx_r0.confirmingRemoveSuiteTestId === test_r12.ID ? 12 : 13);
|
|
373
373
|
} }
|
|
374
|
-
function
|
|
374
|
+
function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
375
375
|
const _r10 = i0.ɵɵgetCurrentView();
|
|
376
|
-
i0.ɵɵelementStart(0, "div",
|
|
377
|
-
i0.ɵɵlistener("cdkDropListDropped", function
|
|
378
|
-
i0.ɵɵrepeaterCreate(1,
|
|
376
|
+
i0.ɵɵelementStart(0, "div", 112);
|
|
377
|
+
i0.ɵɵlistener("cdkDropListDropped", function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_13_Template_div_cdkDropListDropped_0_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.onTestDrop($event)); });
|
|
378
|
+
i0.ɵɵrepeaterCreate(1, MJTestSuiteFormComponentExtended_Conditional_62_Conditional_13_For_2_Template, 14, 5, "div", 113, _forTrack1);
|
|
379
379
|
i0.ɵɵelementEnd();
|
|
380
380
|
} if (rf & 2) {
|
|
381
381
|
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
382
382
|
i0.ɵɵadvance();
|
|
383
383
|
i0.ɵɵrepeater(ctx_r0.suiteTests);
|
|
384
384
|
} }
|
|
385
|
-
function
|
|
385
|
+
function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
386
386
|
const _r15 = i0.ɵɵgetCurrentView();
|
|
387
|
-
i0.ɵɵelementStart(0, "mj-empty-state",
|
|
388
|
-
i0.ɵɵlistener("Action", function
|
|
387
|
+
i0.ɵɵelementStart(0, "mj-empty-state", 130);
|
|
388
|
+
i0.ɵɵlistener("Action", function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_14_Template_mj_empty_state_Action_0_listener() { i0.ɵɵrestoreView(_r15); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.openAddTestsDialog()); });
|
|
389
389
|
i0.ɵɵelementEnd();
|
|
390
390
|
} }
|
|
391
|
-
function
|
|
391
|
+
function MJTestSuiteFormComponentExtended_Conditional_62_Template(rf, ctx) { if (rf & 1) {
|
|
392
392
|
const _r9 = i0.ɵɵgetCurrentView();
|
|
393
|
-
i0.ɵɵelementStart(0, "div",
|
|
393
|
+
i0.ɵɵelementStart(0, "div", 41)(1, "div", 95)(2, "div", 96)(3, "strong");
|
|
394
394
|
i0.ɵɵtext(4, "Suite tests");
|
|
395
395
|
i0.ɵɵelementEnd();
|
|
396
|
-
i0.ɵɵconditionalCreate(5,
|
|
397
|
-
i0.ɵɵelementStart(6, "span",
|
|
396
|
+
i0.ɵɵconditionalCreate(5, MJTestSuiteFormComponentExtended_Conditional_62_Conditional_5_Template, 2, 1, "span", 97);
|
|
397
|
+
i0.ɵɵelementStart(6, "span", 98);
|
|
398
398
|
i0.ɵɵtext(7, "Drag to reorder \u00B7 Hover a row to remove");
|
|
399
399
|
i0.ɵɵelementEnd()();
|
|
400
|
-
i0.ɵɵelementStart(8, "div",
|
|
401
|
-
i0.ɵɵlistener("click", function
|
|
402
|
-
i0.ɵɵelement(10, "i",
|
|
400
|
+
i0.ɵɵelementStart(8, "div", 99)(9, "button", 100);
|
|
401
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_62_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r9); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.openAddTestsDialog()); });
|
|
402
|
+
i0.ɵɵelement(10, "i", 101);
|
|
403
403
|
i0.ɵɵtext(11, " Add tests ");
|
|
404
404
|
i0.ɵɵelementEnd()()();
|
|
405
|
-
i0.ɵɵconditionalCreate(12,
|
|
406
|
-
i0.ɵɵconditionalCreate(13,
|
|
407
|
-
i0.ɵɵconditionalCreate(14,
|
|
405
|
+
i0.ɵɵconditionalCreate(12, MJTestSuiteFormComponentExtended_Conditional_62_Conditional_12_Template, 4, 1, "div", 102);
|
|
406
|
+
i0.ɵɵconditionalCreate(13, MJTestSuiteFormComponentExtended_Conditional_62_Conditional_13_Template, 3, 0, "div", 103);
|
|
407
|
+
i0.ɵɵconditionalCreate(14, MJTestSuiteFormComponentExtended_Conditional_62_Conditional_14_Template, 1, 0, "mj-empty-state", 104);
|
|
408
408
|
i0.ɵɵelementEnd();
|
|
409
409
|
} if (rf & 2) {
|
|
410
410
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
@@ -419,24 +419,24 @@ function MJTestSuiteFormComponentExtended_Conditional_61_Template(rf, ctx) { if
|
|
|
419
419
|
i0.ɵɵadvance();
|
|
420
420
|
i0.ɵɵconditional(ctx_r0.testsLoaded && !ctx_r0.loadingTests && ctx_r0.suiteTests.length === 0 ? 14 : -1);
|
|
421
421
|
} }
|
|
422
|
-
function
|
|
423
|
-
i0.ɵɵelementStart(0, "div",
|
|
424
|
-
i0.ɵɵelement(1, "div",
|
|
425
|
-
i0.ɵɵelementStart(2, "div",
|
|
426
|
-
i0.ɵɵelement(3, "div",
|
|
422
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_1_For_3_Template(rf, ctx) { if (rf & 1) {
|
|
423
|
+
i0.ɵɵelementStart(0, "div", 106);
|
|
424
|
+
i0.ɵɵelement(1, "div", 108);
|
|
425
|
+
i0.ɵɵelementStart(2, "div", 109);
|
|
426
|
+
i0.ɵɵelement(3, "div", 110)(4, "div", 111);
|
|
427
427
|
i0.ɵɵelementEnd()();
|
|
428
428
|
} }
|
|
429
|
-
function
|
|
430
|
-
i0.ɵɵelementStart(0, "div",
|
|
431
|
-
i0.ɵɵrepeaterCreate(2,
|
|
429
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
430
|
+
i0.ɵɵelementStart(0, "div", 102)(1, "div", 105);
|
|
431
|
+
i0.ɵɵrepeaterCreate(2, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_1_For_3_Template, 5, 0, "div", 106, i0.ɵɵrepeaterTrackByIdentity);
|
|
432
432
|
i0.ɵɵelementEnd()();
|
|
433
433
|
} if (rf & 2) {
|
|
434
434
|
i0.ɵɵadvance(2);
|
|
435
435
|
i0.ɵɵrepeater(i0.ɵɵpureFunction0(0, _c2));
|
|
436
436
|
} }
|
|
437
|
-
function
|
|
437
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
438
438
|
i0.ɵɵelementStart(0, "span");
|
|
439
|
-
i0.ɵɵelement(1, "i",
|
|
439
|
+
i0.ɵɵelement(1, "i", 149);
|
|
440
440
|
i0.ɵɵtext(2);
|
|
441
441
|
i0.ɵɵelementEnd();
|
|
442
442
|
} if (rf & 2) {
|
|
@@ -445,9 +445,9 @@ function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_2_For_2_Con
|
|
|
445
445
|
i0.ɵɵadvance(2);
|
|
446
446
|
i0.ɵɵtextInterpolate3(" ", run_r17.PassedTests, "/", run_r17.TotalTests, " (", ctx_r0.getPassRate(run_r17).toFixed(0), "%) ");
|
|
447
447
|
} }
|
|
448
|
-
function
|
|
449
|
-
i0.ɵɵelementStart(0, "span",
|
|
450
|
-
i0.ɵɵelement(1, "i",
|
|
448
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_15_Template(rf, ctx) { if (rf & 1) {
|
|
449
|
+
i0.ɵɵelementStart(0, "span", 150);
|
|
450
|
+
i0.ɵɵelement(1, "i", 136);
|
|
451
451
|
i0.ɵɵelementEnd();
|
|
452
452
|
} if (rf & 2) {
|
|
453
453
|
const run_r17 = i0.ɵɵnextContext().$implicit;
|
|
@@ -455,16 +455,16 @@ function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_2_For_2_Con
|
|
|
455
455
|
i0.ɵɵadvance();
|
|
456
456
|
i0.ɵɵclassProp("fa-circle-check", run_r17.Status === "Completed")("fa-circle-xmark", run_r17.Status === "Failed")("fa-spinner", run_r17.Status === "Running")("fa-clock", run_r17.Status === "Pending")("fa-ban", run_r17.Status === "Cancelled");
|
|
457
457
|
} }
|
|
458
|
-
function
|
|
459
|
-
i0.ɵɵelementStart(0, "span",
|
|
460
|
-
i0.ɵɵelement(1, "i",
|
|
461
|
-
i0.ɵɵelementStart(2, "span",
|
|
462
|
-
i0.ɵɵelement(3, "i",
|
|
458
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
459
|
+
i0.ɵɵelementStart(0, "span", 145);
|
|
460
|
+
i0.ɵɵelement(1, "i", 151);
|
|
461
|
+
i0.ɵɵelementStart(2, "span", 152);
|
|
462
|
+
i0.ɵɵelement(3, "i", 153);
|
|
463
463
|
i0.ɵɵelementEnd()();
|
|
464
464
|
} }
|
|
465
|
-
function
|
|
466
|
-
i0.ɵɵelementStart(0, "span",
|
|
467
|
-
i0.ɵɵelement(1, "i",
|
|
465
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
466
|
+
i0.ɵɵelementStart(0, "span", 154);
|
|
467
|
+
i0.ɵɵelement(1, "i", 155);
|
|
468
468
|
i0.ɵɵelementStart(2, "span");
|
|
469
469
|
i0.ɵɵtext(3);
|
|
470
470
|
i0.ɵɵelementEnd()();
|
|
@@ -475,8 +475,8 @@ function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_2_For_2_Con
|
|
|
475
475
|
i0.ɵɵadvance(3);
|
|
476
476
|
i0.ɵɵtextInterpolate1("", ctx_r0.getPassRate(run_r17).toFixed(0), "%");
|
|
477
477
|
} }
|
|
478
|
-
function
|
|
479
|
-
i0.ɵɵelementStart(0, "span",
|
|
478
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_18_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
479
|
+
i0.ɵɵelementStart(0, "span", 156);
|
|
480
480
|
i0.ɵɵtext(1);
|
|
481
481
|
i0.ɵɵelementEnd();
|
|
482
482
|
} if (rf & 2) {
|
|
@@ -484,9 +484,9 @@ function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_2_For_2_Con
|
|
|
484
484
|
i0.ɵɵadvance();
|
|
485
485
|
i0.ɵɵtextInterpolate(tag_r18);
|
|
486
486
|
} }
|
|
487
|
-
function
|
|
488
|
-
i0.ɵɵelementStart(0, "div",
|
|
489
|
-
i0.ɵɵrepeaterCreate(1,
|
|
487
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
488
|
+
i0.ɵɵelementStart(0, "div", 147);
|
|
489
|
+
i0.ɵɵrepeaterCreate(1, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_18_For_2_Template, 2, 1, "span", 156, i0.ɵɵrepeaterTrackByIdentity);
|
|
490
490
|
i0.ɵɵelementEnd();
|
|
491
491
|
} if (rf & 2) {
|
|
492
492
|
const run_r17 = i0.ɵɵnextContext().$implicit;
|
|
@@ -494,33 +494,33 @@ function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_2_For_2_Con
|
|
|
494
494
|
i0.ɵɵadvance();
|
|
495
495
|
i0.ɵɵrepeater(ctx_r0.getRunTags(run_r17));
|
|
496
496
|
} }
|
|
497
|
-
function
|
|
497
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
498
498
|
const _r16 = i0.ɵɵgetCurrentView();
|
|
499
|
-
i0.ɵɵelementStart(0, "div",
|
|
500
|
-
i0.ɵɵlistener("click", function
|
|
501
|
-
i0.ɵɵelementStart(1, "div",
|
|
502
|
-
i0.ɵɵelement(2, "i",
|
|
499
|
+
i0.ɵɵelementStart(0, "div", 134);
|
|
500
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_For_2_Template_div_click_0_listener() { const run_r17 = i0.ɵɵrestoreView(_r16).$implicit; const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.openSuiteRun(run_r17.ID)); });
|
|
501
|
+
i0.ɵɵelementStart(1, "div", 135);
|
|
502
|
+
i0.ɵɵelement(2, "i", 136);
|
|
503
503
|
i0.ɵɵelementEnd();
|
|
504
|
-
i0.ɵɵelementStart(3, "div",
|
|
504
|
+
i0.ɵɵelementStart(3, "div", 137)(4, "div", 138)(5, "span", 139);
|
|
505
505
|
i0.ɵɵtext(6);
|
|
506
506
|
i0.ɵɵelementEnd();
|
|
507
|
-
i0.ɵɵelementStart(7, "span",
|
|
507
|
+
i0.ɵɵelementStart(7, "span", 140);
|
|
508
508
|
i0.ɵɵtext(8);
|
|
509
509
|
i0.ɵɵelementEnd()();
|
|
510
|
-
i0.ɵɵelementStart(9, "div",
|
|
511
|
-
i0.ɵɵelement(11, "i",
|
|
510
|
+
i0.ɵɵelementStart(9, "div", 141)(10, "span");
|
|
511
|
+
i0.ɵɵelement(11, "i", 142);
|
|
512
512
|
i0.ɵɵtext(12);
|
|
513
513
|
i0.ɵɵelementEnd();
|
|
514
|
-
i0.ɵɵconditionalCreate(13,
|
|
514
|
+
i0.ɵɵconditionalCreate(13, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_13_Template, 3, 3, "span");
|
|
515
515
|
i0.ɵɵelementEnd();
|
|
516
|
-
i0.ɵɵelementStart(14, "div",
|
|
517
|
-
i0.ɵɵconditionalCreate(15,
|
|
518
|
-
i0.ɵɵconditionalCreate(16,
|
|
519
|
-
i0.ɵɵconditionalCreate(17,
|
|
516
|
+
i0.ɵɵelementStart(14, "div", 143);
|
|
517
|
+
i0.ɵɵconditionalCreate(15, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_15_Template, 2, 12, "span", 144);
|
|
518
|
+
i0.ɵɵconditionalCreate(16, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_16_Template, 4, 0, "span", 145);
|
|
519
|
+
i0.ɵɵconditionalCreate(17, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_17_Template, 4, 7, "span", 146);
|
|
520
520
|
i0.ɵɵelementEnd();
|
|
521
|
-
i0.ɵɵconditionalCreate(18,
|
|
521
|
+
i0.ɵɵconditionalCreate(18, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_For_2_Conditional_18_Template, 3, 0, "div", 147);
|
|
522
522
|
i0.ɵɵelementEnd();
|
|
523
|
-
i0.ɵɵelement(19, "i",
|
|
523
|
+
i0.ɵɵelement(19, "i", 148);
|
|
524
524
|
i0.ɵɵelementEnd();
|
|
525
525
|
} if (rf & 2) {
|
|
526
526
|
const run_r17 = ctx.$implicit;
|
|
@@ -548,26 +548,26 @@ function MJTestSuiteFormComponentExtended_Conditional_62_Conditional_2_For_2_Tem
|
|
|
548
548
|
i0.ɵɵadvance();
|
|
549
549
|
i0.ɵɵconditional(ctx_r0.getRunTags(run_r17).length > 0 ? 18 : -1);
|
|
550
550
|
} }
|
|
551
|
-
function
|
|
552
|
-
i0.ɵɵelementStart(0, "div",
|
|
553
|
-
i0.ɵɵrepeaterCreate(1,
|
|
551
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
552
|
+
i0.ɵɵelementStart(0, "div", 131);
|
|
553
|
+
i0.ɵɵrepeaterCreate(1, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_For_2_Template, 20, 22, "div", 133, i0.ɵɵrepeaterTrackByIdentity);
|
|
554
554
|
i0.ɵɵelementEnd();
|
|
555
555
|
} if (rf & 2) {
|
|
556
556
|
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
557
557
|
i0.ɵɵadvance();
|
|
558
558
|
i0.ɵɵrepeater(ctx_r0.suiteRuns);
|
|
559
559
|
} }
|
|
560
|
-
function
|
|
560
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
561
561
|
const _r19 = i0.ɵɵgetCurrentView();
|
|
562
|
-
i0.ɵɵelementStart(0, "mj-empty-state",
|
|
563
|
-
i0.ɵɵlistener("Action", function
|
|
562
|
+
i0.ɵɵelementStart(0, "mj-empty-state", 157);
|
|
563
|
+
i0.ɵɵlistener("Action", function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_3_Template_mj_empty_state_Action_0_listener() { i0.ɵɵrestoreView(_r19); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.runSuite()); });
|
|
564
564
|
i0.ɵɵelementEnd();
|
|
565
565
|
} }
|
|
566
|
-
function
|
|
567
|
-
i0.ɵɵelementStart(0, "div",
|
|
568
|
-
i0.ɵɵconditionalCreate(1,
|
|
569
|
-
i0.ɵɵconditionalCreate(2,
|
|
570
|
-
i0.ɵɵconditionalCreate(3,
|
|
566
|
+
function MJTestSuiteFormComponentExtended_Conditional_63_Template(rf, ctx) { if (rf & 1) {
|
|
567
|
+
i0.ɵɵelementStart(0, "div", 42);
|
|
568
|
+
i0.ɵɵconditionalCreate(1, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_1_Template, 4, 1, "div", 102);
|
|
569
|
+
i0.ɵɵconditionalCreate(2, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Template, 3, 0, "div", 131);
|
|
570
|
+
i0.ɵɵconditionalCreate(3, MJTestSuiteFormComponentExtended_Conditional_63_Conditional_3_Template, 1, 0, "mj-empty-state", 132);
|
|
571
571
|
i0.ɵɵelementEnd();
|
|
572
572
|
} if (rf & 2) {
|
|
573
573
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
@@ -578,12 +578,12 @@ function MJTestSuiteFormComponentExtended_Conditional_62_Template(rf, ctx) { if
|
|
|
578
578
|
i0.ɵɵadvance();
|
|
579
579
|
i0.ɵɵconditional(ctx_r0.runsLoaded && !ctx_r0.loadingRuns && ctx_r0.suiteRuns.length === 0 ? 3 : -1);
|
|
580
580
|
} }
|
|
581
|
-
function
|
|
582
|
-
i0.ɵɵelementStart(0, "div",
|
|
583
|
-
i0.ɵɵelement(1, "mj-loading",
|
|
581
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
582
|
+
i0.ɵɵelementStart(0, "div", 102);
|
|
583
|
+
i0.ɵɵelement(1, "mj-loading", 159);
|
|
584
584
|
i0.ɵɵelementEnd();
|
|
585
585
|
} }
|
|
586
|
-
function
|
|
586
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_ng_template_15_Conditional_2_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
587
587
|
i0.ɵɵelementStart(0, "span");
|
|
588
588
|
i0.ɵɵtext(1);
|
|
589
589
|
i0.ɵɵelementEnd();
|
|
@@ -592,10 +592,10 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_ng_templa
|
|
|
592
592
|
i0.ɵɵadvance();
|
|
593
593
|
i0.ɵɵtextInterpolate1(" \u00B7 ", ctx_r0.selectedTags.length, " tags");
|
|
594
594
|
} }
|
|
595
|
-
function
|
|
596
|
-
i0.ɵɵelementStart(0, "span",
|
|
595
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_ng_template_15_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
596
|
+
i0.ɵɵelementStart(0, "span", 170);
|
|
597
597
|
i0.ɵɵtext(1);
|
|
598
|
-
i0.ɵɵconditionalCreate(2,
|
|
598
|
+
i0.ɵɵconditionalCreate(2, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_ng_template_15_Conditional_2_Conditional_2_Template, 2, 1, "span");
|
|
599
599
|
i0.ɵɵelementEnd();
|
|
600
600
|
} if (rf & 2) {
|
|
601
601
|
const ctx_r0 = i0.ɵɵnextContext(4);
|
|
@@ -604,17 +604,17 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_ng_templa
|
|
|
604
604
|
i0.ɵɵadvance();
|
|
605
605
|
i0.ɵɵconditional(ctx_r0.selectedTags.length > 0 ? 2 : -1);
|
|
606
606
|
} }
|
|
607
|
-
function
|
|
608
|
-
i0.ɵɵelement(0, "i",
|
|
607
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_ng_template_15_Template(rf, ctx) { if (rf & 1) {
|
|
608
|
+
i0.ɵɵelement(0, "i", 169);
|
|
609
609
|
i0.ɵɵtext(1, " Filters ");
|
|
610
|
-
i0.ɵɵconditionalCreate(2,
|
|
610
|
+
i0.ɵɵconditionalCreate(2, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_ng_template_15_Conditional_2_Template, 3, 2, "span", 170);
|
|
611
611
|
} if (rf & 2) {
|
|
612
612
|
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
613
613
|
i0.ɵɵadvance(2);
|
|
614
614
|
i0.ɵɵconditional(ctx_r0.filtersCollapsed ? 2 : -1);
|
|
615
615
|
} }
|
|
616
|
-
function
|
|
617
|
-
i0.ɵɵelementStart(0, "span",
|
|
616
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_ng_template_16_Conditional_13_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
617
|
+
i0.ɵɵelementStart(0, "span", 175);
|
|
618
618
|
i0.ɵɵtext(1);
|
|
619
619
|
i0.ɵɵelementEnd();
|
|
620
620
|
} if (rf & 2) {
|
|
@@ -622,14 +622,14 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_ng_templa
|
|
|
622
622
|
i0.ɵɵadvance();
|
|
623
623
|
i0.ɵɵtextInterpolate1("(", ctx_r0.selectedTags.length, " selected)");
|
|
624
624
|
} }
|
|
625
|
-
function
|
|
626
|
-
i0.ɵɵelement(0, "i",
|
|
625
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_ng_template_16_Conditional_13_For_9_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
626
|
+
i0.ɵɵelement(0, "i", 180);
|
|
627
627
|
} }
|
|
628
|
-
function
|
|
628
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_ng_template_16_Conditional_13_For_9_Template(rf, ctx) { if (rf & 1) {
|
|
629
629
|
const _r23 = i0.ɵɵgetCurrentView();
|
|
630
|
-
i0.ɵɵelementStart(0, "button",
|
|
631
|
-
i0.ɵɵlistener("click", function
|
|
632
|
-
i0.ɵɵconditionalCreate(1,
|
|
630
|
+
i0.ɵɵelementStart(0, "button", 179);
|
|
631
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_ng_template_16_Conditional_13_For_9_Template_button_click_0_listener() { const tag_r24 = i0.ɵɵrestoreView(_r23).$implicit; const ctx_r0 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r0.toggleTagFilter(tag_r24)); });
|
|
632
|
+
i0.ɵɵconditionalCreate(1, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_ng_template_16_Conditional_13_For_9_Conditional_1_Template, 1, 0, "i", 180);
|
|
633
633
|
i0.ɵɵtext(2);
|
|
634
634
|
i0.ɵɵelementEnd();
|
|
635
635
|
} if (rf & 2) {
|
|
@@ -641,18 +641,18 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_ng_templa
|
|
|
641
641
|
i0.ɵɵadvance();
|
|
642
642
|
i0.ɵɵtextInterpolate1(" ", tag_r24, " ");
|
|
643
643
|
} }
|
|
644
|
-
function
|
|
644
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_ng_template_16_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
645
645
|
const _r22 = i0.ɵɵgetCurrentView();
|
|
646
|
-
i0.ɵɵelementStart(0, "div",
|
|
646
|
+
i0.ɵɵelementStart(0, "div", 172)(1, "label");
|
|
647
647
|
i0.ɵɵtext(2, "Filter by Tag ");
|
|
648
|
-
i0.ɵɵconditionalCreate(3,
|
|
648
|
+
i0.ɵɵconditionalCreate(3, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_ng_template_16_Conditional_13_Conditional_3_Template, 2, 1, "span", 175);
|
|
649
649
|
i0.ɵɵelementEnd();
|
|
650
|
-
i0.ɵɵelementStart(4, "div",
|
|
651
|
-
i0.ɵɵlistener("click", function
|
|
650
|
+
i0.ɵɵelementStart(4, "div", 176)(5, "button", 177);
|
|
651
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_ng_template_16_Conditional_13_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r22); const ctx_r0 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r0.toggleTagFilter(null)); });
|
|
652
652
|
i0.ɵɵelement(6, "i", 11);
|
|
653
653
|
i0.ɵɵtext(7, " All Tags ");
|
|
654
654
|
i0.ɵɵelementEnd();
|
|
655
|
-
i0.ɵɵrepeaterCreate(8,
|
|
655
|
+
i0.ɵɵrepeaterCreate(8, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_ng_template_16_Conditional_13_For_9_Template, 3, 4, "button", 178, i0.ɵɵrepeaterTrackByIdentity);
|
|
656
656
|
i0.ɵɵelementEnd()();
|
|
657
657
|
} if (rf & 2) {
|
|
658
658
|
const ctx_r0 = i0.ɵɵnextContext(4);
|
|
@@ -663,28 +663,28 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_ng_templa
|
|
|
663
663
|
i0.ɵɵadvance(3);
|
|
664
664
|
i0.ɵɵrepeater(ctx_r0.uniqueTags);
|
|
665
665
|
} }
|
|
666
|
-
function
|
|
666
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_ng_template_16_Template(rf, ctx) { if (rf & 1) {
|
|
667
667
|
const _r21 = i0.ɵɵgetCurrentView();
|
|
668
|
-
i0.ɵɵelementStart(0, "div",
|
|
668
|
+
i0.ɵɵelementStart(0, "div", 171)(1, "div", 172)(2, "label");
|
|
669
669
|
i0.ɵɵtext(3, "Time Range");
|
|
670
670
|
i0.ɵɵelementEnd();
|
|
671
|
-
i0.ɵɵelementStart(4, "div",
|
|
672
|
-
i0.ɵɵlistener("click", function
|
|
671
|
+
i0.ɵɵelementStart(4, "div", 173)(5, "button", 174);
|
|
672
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_ng_template_16_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r21); const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.setTimeRange("7d")); });
|
|
673
673
|
i0.ɵɵtext(6, "7 Days");
|
|
674
674
|
i0.ɵɵelementEnd();
|
|
675
|
-
i0.ɵɵelementStart(7, "button",
|
|
676
|
-
i0.ɵɵlistener("click", function
|
|
675
|
+
i0.ɵɵelementStart(7, "button", 174);
|
|
676
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_ng_template_16_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r21); const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.setTimeRange("30d")); });
|
|
677
677
|
i0.ɵɵtext(8, "30 Days");
|
|
678
678
|
i0.ɵɵelementEnd();
|
|
679
|
-
i0.ɵɵelementStart(9, "button",
|
|
680
|
-
i0.ɵɵlistener("click", function
|
|
679
|
+
i0.ɵɵelementStart(9, "button", 174);
|
|
680
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_ng_template_16_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r21); const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.setTimeRange("90d")); });
|
|
681
681
|
i0.ɵɵtext(10, "90 Days");
|
|
682
682
|
i0.ɵɵelementEnd();
|
|
683
|
-
i0.ɵɵelementStart(11, "button",
|
|
684
|
-
i0.ɵɵlistener("click", function
|
|
683
|
+
i0.ɵɵelementStart(11, "button", 174);
|
|
684
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_ng_template_16_Template_button_click_11_listener() { i0.ɵɵrestoreView(_r21); const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.setTimeRange("all")); });
|
|
685
685
|
i0.ɵɵtext(12, "All Time");
|
|
686
686
|
i0.ɵɵelementEnd()()();
|
|
687
|
-
i0.ɵɵconditionalCreate(13,
|
|
687
|
+
i0.ɵɵconditionalCreate(13, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_ng_template_16_Conditional_13_Template, 10, 3, "div", 172);
|
|
688
688
|
i0.ɵɵelementEnd();
|
|
689
689
|
} if (rf & 2) {
|
|
690
690
|
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
@@ -699,8 +699,8 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_ng_templa
|
|
|
699
699
|
i0.ɵɵadvance(2);
|
|
700
700
|
i0.ɵɵconditional(ctx_r0.uniqueTags.length > 0 ? 13 : -1);
|
|
701
701
|
} }
|
|
702
|
-
function
|
|
703
|
-
i0.ɵɵelementStart(0, "span",
|
|
702
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_17_For_60_For_21_Template(rf, ctx) { if (rf & 1) {
|
|
703
|
+
i0.ɵɵelementStart(0, "span", 204);
|
|
704
704
|
i0.ɵɵtext(1);
|
|
705
705
|
i0.ɵɵelementEnd();
|
|
706
706
|
} if (rf & 2) {
|
|
@@ -708,8 +708,8 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Condition
|
|
|
708
708
|
i0.ɵɵadvance();
|
|
709
709
|
i0.ɵɵtextInterpolate(tag_r27);
|
|
710
710
|
} }
|
|
711
|
-
function
|
|
712
|
-
i0.ɵɵelementStart(0, "span",
|
|
711
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_17_For_60_Conditional_22_Template(rf, ctx) { if (rf & 1) {
|
|
712
|
+
i0.ɵɵelementStart(0, "span", 205);
|
|
713
713
|
i0.ɵɵtext(1);
|
|
714
714
|
i0.ɵɵelementEnd();
|
|
715
715
|
} if (rf & 2) {
|
|
@@ -717,19 +717,19 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Condition
|
|
|
717
717
|
i0.ɵɵadvance();
|
|
718
718
|
i0.ɵɵtextInterpolate1("+", dp_r26.tags.length - 2);
|
|
719
719
|
} }
|
|
720
|
-
function
|
|
720
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_17_For_60_Template(rf, ctx) { if (rf & 1) {
|
|
721
721
|
const _r25 = i0.ɵɵgetCurrentView();
|
|
722
|
-
i0.ɵɵelementStart(0, "tr",
|
|
723
|
-
i0.ɵɵlistener("click", function
|
|
722
|
+
i0.ɵɵelementStart(0, "tr", 199);
|
|
723
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_17_For_60_Template_tr_click_0_listener() { const dp_r26 = i0.ɵɵrestoreView(_r25).$implicit; const ctx_r0 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r0.openSuiteRun(dp_r26.runId)); });
|
|
724
724
|
i0.ɵɵelementStart(1, "td");
|
|
725
725
|
i0.ɵɵtext(2);
|
|
726
726
|
i0.ɵɵpipe(3, "date");
|
|
727
727
|
i0.ɵɵelementEnd();
|
|
728
|
-
i0.ɵɵelementStart(4, "td")(5, "span",
|
|
728
|
+
i0.ɵɵelementStart(4, "td")(5, "span", 200);
|
|
729
729
|
i0.ɵɵtext(6);
|
|
730
730
|
i0.ɵɵelementEnd()();
|
|
731
|
-
i0.ɵɵelementStart(7, "td")(8, "div",
|
|
732
|
-
i0.ɵɵelement(9, "div",
|
|
731
|
+
i0.ɵɵelementStart(7, "td")(8, "div", 201);
|
|
732
|
+
i0.ɵɵelement(9, "div", 202);
|
|
733
733
|
i0.ɵɵelementStart(10, "span");
|
|
734
734
|
i0.ɵɵtext(11);
|
|
735
735
|
i0.ɵɵelementEnd()()();
|
|
@@ -742,9 +742,9 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Condition
|
|
|
742
742
|
i0.ɵɵelementStart(16, "td");
|
|
743
743
|
i0.ɵɵtext(17);
|
|
744
744
|
i0.ɵɵelementEnd();
|
|
745
|
-
i0.ɵɵelementStart(18, "td")(19, "div",
|
|
746
|
-
i0.ɵɵrepeaterCreate(20,
|
|
747
|
-
i0.ɵɵconditionalCreate(22,
|
|
745
|
+
i0.ɵɵelementStart(18, "td")(19, "div", 203);
|
|
746
|
+
i0.ɵɵrepeaterCreate(20, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_17_For_60_For_21_Template, 2, 1, "span", 204, i0.ɵɵrepeaterTrackByIdentity);
|
|
747
|
+
i0.ɵɵconditionalCreate(22, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_17_For_60_Conditional_22_Template, 2, 1, "span", 205);
|
|
748
748
|
i0.ɵɵelementEnd()()();
|
|
749
749
|
} if (rf & 2) {
|
|
750
750
|
const dp_r26 = ctx.$implicit;
|
|
@@ -771,55 +771,55 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Condition
|
|
|
771
771
|
i0.ɵɵadvance(2);
|
|
772
772
|
i0.ɵɵconditional(dp_r26.tags.length > 2 ? 22 : -1);
|
|
773
773
|
} }
|
|
774
|
-
function
|
|
775
|
-
i0.ɵɵelement(0, "mj-empty-state",
|
|
774
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_17_Conditional_61_Template(rf, ctx) { if (rf & 1) {
|
|
775
|
+
i0.ɵɵelement(0, "mj-empty-state", 198);
|
|
776
776
|
} }
|
|
777
|
-
function
|
|
778
|
-
i0.ɵɵelementStart(0, "div",
|
|
779
|
-
i0.ɵɵelement(3, "i",
|
|
777
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
778
|
+
i0.ɵɵelementStart(0, "div", 181)(1, "div", 182)(2, "div", 183);
|
|
779
|
+
i0.ɵɵelement(3, "i", 184);
|
|
780
780
|
i0.ɵɵelementEnd();
|
|
781
|
-
i0.ɵɵelementStart(4, "div",
|
|
781
|
+
i0.ɵɵelementStart(4, "div", 185)(5, "div", 186);
|
|
782
782
|
i0.ɵɵtext(6);
|
|
783
783
|
i0.ɵɵelementEnd();
|
|
784
|
-
i0.ɵɵelementStart(7, "div",
|
|
784
|
+
i0.ɵɵelementStart(7, "div", 187);
|
|
785
785
|
i0.ɵɵtext(8, "Total Runs");
|
|
786
786
|
i0.ɵɵelementEnd()()();
|
|
787
|
-
i0.ɵɵelementStart(9, "div",
|
|
788
|
-
i0.ɵɵelement(11, "i",
|
|
787
|
+
i0.ɵɵelementStart(9, "div", 182)(10, "div", 188);
|
|
788
|
+
i0.ɵɵelement(11, "i", 149);
|
|
789
789
|
i0.ɵɵelementEnd();
|
|
790
|
-
i0.ɵɵelementStart(12, "div",
|
|
790
|
+
i0.ɵɵelementStart(12, "div", 185)(13, "div", 186);
|
|
791
791
|
i0.ɵɵtext(14);
|
|
792
792
|
i0.ɵɵelementEnd();
|
|
793
|
-
i0.ɵɵelementStart(15, "div",
|
|
793
|
+
i0.ɵɵelementStart(15, "div", 187);
|
|
794
794
|
i0.ɵɵtext(16, "Avg Pass Rate");
|
|
795
795
|
i0.ɵɵelementEnd();
|
|
796
|
-
i0.ɵɵelementStart(17, "div",
|
|
796
|
+
i0.ɵɵelementStart(17, "div", 189);
|
|
797
797
|
i0.ɵɵelement(18, "i", 19);
|
|
798
798
|
i0.ɵɵtext(19);
|
|
799
799
|
i0.ɵɵelementEnd()()();
|
|
800
|
-
i0.ɵɵelementStart(20, "div",
|
|
801
|
-
i0.ɵɵelement(22, "i",
|
|
800
|
+
i0.ɵɵelementStart(20, "div", 182)(21, "div", 190);
|
|
801
|
+
i0.ɵɵelement(22, "i", 153);
|
|
802
802
|
i0.ɵɵelementEnd();
|
|
803
|
-
i0.ɵɵelementStart(23, "div",
|
|
803
|
+
i0.ɵɵelementStart(23, "div", 185)(24, "div", 186);
|
|
804
804
|
i0.ɵɵtext(25);
|
|
805
805
|
i0.ɵɵelementEnd();
|
|
806
|
-
i0.ɵɵelementStart(26, "div",
|
|
806
|
+
i0.ɵɵelementStart(26, "div", 187);
|
|
807
807
|
i0.ɵɵtext(27, "Avg Duration");
|
|
808
808
|
i0.ɵɵelementEnd()()();
|
|
809
|
-
i0.ɵɵelementStart(28, "div",
|
|
810
|
-
i0.ɵɵelement(30, "i",
|
|
809
|
+
i0.ɵɵelementStart(28, "div", 182)(29, "div", 191);
|
|
810
|
+
i0.ɵɵelement(30, "i", 192);
|
|
811
811
|
i0.ɵɵelementEnd();
|
|
812
|
-
i0.ɵɵelementStart(31, "div",
|
|
812
|
+
i0.ɵɵelementStart(31, "div", 185)(32, "div", 186);
|
|
813
813
|
i0.ɵɵtext(33);
|
|
814
814
|
i0.ɵɵelementEnd();
|
|
815
|
-
i0.ɵɵelementStart(34, "div",
|
|
815
|
+
i0.ɵɵelementStart(34, "div", 187);
|
|
816
816
|
i0.ɵɵtext(35, "Total Cost");
|
|
817
817
|
i0.ɵɵelementEnd()()()();
|
|
818
|
-
i0.ɵɵelementStart(36, "div",
|
|
819
|
-
i0.ɵɵelement(38, "i",
|
|
818
|
+
i0.ɵɵelementStart(36, "div", 193)(37, "h3");
|
|
819
|
+
i0.ɵɵelement(38, "i", 194);
|
|
820
820
|
i0.ɵɵtext(39, " Run History");
|
|
821
821
|
i0.ɵɵelementEnd();
|
|
822
|
-
i0.ɵɵelementStart(40, "div",
|
|
822
|
+
i0.ɵɵelementStart(40, "div", 195)(41, "table", 196)(42, "thead")(43, "tr")(44, "th");
|
|
823
823
|
i0.ɵɵtext(45, "Date");
|
|
824
824
|
i0.ɵɵelementEnd();
|
|
825
825
|
i0.ɵɵelementStart(46, "th");
|
|
@@ -841,9 +841,9 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Condition
|
|
|
841
841
|
i0.ɵɵtext(57, "Tags");
|
|
842
842
|
i0.ɵɵelementEnd()()();
|
|
843
843
|
i0.ɵɵelementStart(58, "tbody");
|
|
844
|
-
i0.ɵɵrepeaterCreate(59,
|
|
844
|
+
i0.ɵɵrepeaterCreate(59, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_17_For_60_Template, 23, 19, "tr", 197, i0.ɵɵrepeaterTrackByIdentity);
|
|
845
845
|
i0.ɵɵelementEnd()()();
|
|
846
|
-
i0.ɵɵconditionalCreate(61,
|
|
846
|
+
i0.ɵɵconditionalCreate(61, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_17_Conditional_61_Template, 1, 0, "mj-empty-state", 198);
|
|
847
847
|
i0.ɵɵelementEnd();
|
|
848
848
|
} if (rf & 2) {
|
|
849
849
|
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
@@ -866,20 +866,20 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Condition
|
|
|
866
866
|
i0.ɵɵadvance(2);
|
|
867
867
|
i0.ɵɵconditional(ctx_r0.getFilteredAnalyticsData().length === 0 ? 61 : -1);
|
|
868
868
|
} }
|
|
869
|
-
function
|
|
870
|
-
i0.ɵɵelementStart(0, "div",
|
|
871
|
-
i0.ɵɵelement(1, "mj-loading",
|
|
869
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
870
|
+
i0.ɵɵelementStart(0, "div", 102);
|
|
871
|
+
i0.ɵɵelement(1, "mj-loading", 208);
|
|
872
872
|
i0.ɵɵelementEnd();
|
|
873
873
|
} }
|
|
874
|
-
function
|
|
874
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
875
875
|
const _r29 = i0.ɵɵgetCurrentView();
|
|
876
|
-
i0.ɵɵelementStart(0, "button",
|
|
877
|
-
i0.ɵɵlistener("click", function
|
|
878
|
-
i0.ɵɵelement(1, "i",
|
|
876
|
+
i0.ɵɵelementStart(0, "button", 230);
|
|
877
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_Conditional_9_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r29); const ctx_r0 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r0.clearMatrixFilter()); });
|
|
878
|
+
i0.ɵɵelement(1, "i", 94);
|
|
879
879
|
i0.ɵɵelementEnd();
|
|
880
880
|
} }
|
|
881
|
-
function
|
|
882
|
-
i0.ɵɵelementStart(0, "span",
|
|
881
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_26_Conditional_3_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
882
|
+
i0.ɵɵelementStart(0, "span", 236);
|
|
883
883
|
i0.ɵɵtext(1);
|
|
884
884
|
i0.ɵɵelementEnd();
|
|
885
885
|
} if (rf & 2) {
|
|
@@ -887,8 +887,8 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Condition
|
|
|
887
887
|
i0.ɵɵadvance();
|
|
888
888
|
i0.ɵɵtextInterpolate(tag_r32);
|
|
889
889
|
} }
|
|
890
|
-
function
|
|
891
|
-
i0.ɵɵelementStart(0, "span",
|
|
890
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_26_Conditional_3_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
891
|
+
i0.ɵɵelementStart(0, "span", 237);
|
|
892
892
|
i0.ɵɵtext(1);
|
|
893
893
|
i0.ɵɵelementEnd();
|
|
894
894
|
} if (rf & 2) {
|
|
@@ -896,10 +896,10 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Condition
|
|
|
896
896
|
i0.ɵɵadvance();
|
|
897
897
|
i0.ɵɵtextInterpolate1("+", run_r31.tags.length - 2);
|
|
898
898
|
} }
|
|
899
|
-
function
|
|
900
|
-
i0.ɵɵelementStart(0, "div",
|
|
901
|
-
i0.ɵɵrepeaterCreate(1,
|
|
902
|
-
i0.ɵɵconditionalCreate(3,
|
|
899
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_26_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
900
|
+
i0.ɵɵelementStart(0, "div", 233);
|
|
901
|
+
i0.ɵɵrepeaterCreate(1, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_26_Conditional_3_For_2_Template, 2, 1, "span", 236, i0.ɵɵrepeaterTrackByIdentity);
|
|
902
|
+
i0.ɵɵconditionalCreate(3, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_26_Conditional_3_Conditional_3_Template, 2, 1, "span", 237);
|
|
903
903
|
i0.ɵɵelementEnd();
|
|
904
904
|
} if (rf & 2) {
|
|
905
905
|
const run_r31 = i0.ɵɵnextContext().$implicit;
|
|
@@ -908,17 +908,17 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Condition
|
|
|
908
908
|
i0.ɵɵadvance(2);
|
|
909
909
|
i0.ɵɵconditional(run_r31.tags.length > 2 ? 3 : -1);
|
|
910
910
|
} }
|
|
911
|
-
function
|
|
911
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_26_Template(rf, ctx) { if (rf & 1) {
|
|
912
912
|
const _r30 = i0.ɵɵgetCurrentView();
|
|
913
|
-
i0.ɵɵelementStart(0, "th",
|
|
913
|
+
i0.ɵɵelementStart(0, "th", 231);
|
|
914
914
|
i0.ɵɵpipe(1, "date");
|
|
915
|
-
i0.ɵɵlistener("click", function
|
|
916
|
-
i0.ɵɵelementStart(2, "div",
|
|
917
|
-
i0.ɵɵconditionalCreate(3,
|
|
918
|
-
i0.ɵɵelementStart(4, "div",
|
|
915
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_26_Template_th_click_0_listener() { const run_r31 = i0.ɵɵrestoreView(_r30).$implicit; const ctx_r0 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r0.openSuiteRun(run_r31.runId)); });
|
|
916
|
+
i0.ɵɵelementStart(2, "div", 232);
|
|
917
|
+
i0.ɵɵconditionalCreate(3, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_26_Conditional_3_Template, 4, 1, "div", 233);
|
|
918
|
+
i0.ɵɵelementStart(4, "div", 234);
|
|
919
919
|
i0.ɵɵtext(5);
|
|
920
920
|
i0.ɵɵelementEnd();
|
|
921
|
-
i0.ɵɵelementStart(6, "div",
|
|
921
|
+
i0.ɵɵelementStart(6, "div", 235);
|
|
922
922
|
i0.ɵɵtext(7);
|
|
923
923
|
i0.ɵɵelementEnd()()();
|
|
924
924
|
} if (rf & 2) {
|
|
@@ -934,9 +934,9 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Condition
|
|
|
934
934
|
i0.ɵɵadvance();
|
|
935
935
|
i0.ɵɵtextInterpolate1(" ", run_r31.passRate.toFixed(0), "% ");
|
|
936
936
|
} }
|
|
937
|
-
function
|
|
938
|
-
i0.ɵɵelementStart(0, "span",
|
|
939
|
-
i0.ɵɵelement(1, "i",
|
|
937
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_30_For_7_Conditional_1_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
938
|
+
i0.ɵɵelementStart(0, "span", 251);
|
|
939
|
+
i0.ɵɵelement(1, "i", 136);
|
|
940
940
|
i0.ɵɵelementEnd();
|
|
941
941
|
} if (rf & 2) {
|
|
942
942
|
const result_r37 = i0.ɵɵnextContext();
|
|
@@ -946,15 +946,15 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Condition
|
|
|
946
946
|
i0.ɵɵadvance();
|
|
947
947
|
i0.ɵɵclassProp("fa-check", result_r37.status === "Passed")("fa-times", result_r37.status === "Failed")("fa-exclamation", result_r37.status === "Error")("fa-hourglass-end", result_r37.status === "Timeout")("fa-forward", result_r37.status === "Skipped")("fa-spinner", result_r37.status === "Running")("fa-clock", result_r37.status === "Pending");
|
|
948
948
|
} }
|
|
949
|
-
function
|
|
950
|
-
i0.ɵɵelementStart(0, "span",
|
|
951
|
-
i0.ɵɵelement(1, "i",
|
|
949
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_30_For_7_Conditional_1_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
950
|
+
i0.ɵɵelementStart(0, "span", 247);
|
|
951
|
+
i0.ɵɵelement(1, "i", 252);
|
|
952
952
|
i0.ɵɵelementEnd();
|
|
953
953
|
} }
|
|
954
|
-
function
|
|
955
|
-
i0.ɵɵelementStart(0, "span",
|
|
956
|
-
i0.ɵɵelement(1, "i",
|
|
957
|
-
i0.ɵɵelementStart(2, "span",
|
|
954
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_30_For_7_Conditional_1_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
955
|
+
i0.ɵɵelementStart(0, "span", 253);
|
|
956
|
+
i0.ɵɵelement(1, "i", 151);
|
|
957
|
+
i0.ɵɵelementStart(2, "span", 254);
|
|
958
958
|
i0.ɵɵtext(3);
|
|
959
959
|
i0.ɵɵelementEnd()();
|
|
960
960
|
} if (rf & 2) {
|
|
@@ -965,10 +965,10 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Condition
|
|
|
965
965
|
i0.ɵɵadvance(3);
|
|
966
966
|
i0.ɵɵtextInterpolate(result_r37.humanRating);
|
|
967
967
|
} }
|
|
968
|
-
function
|
|
969
|
-
i0.ɵɵelementStart(0, "span",
|
|
970
|
-
i0.ɵɵelement(1, "i",
|
|
971
|
-
i0.ɵɵelementStart(2, "span",
|
|
968
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_30_For_7_Conditional_1_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
969
|
+
i0.ɵɵelementStart(0, "span", 255);
|
|
970
|
+
i0.ɵɵelement(1, "i", 155);
|
|
971
|
+
i0.ɵɵelementStart(2, "span", 256);
|
|
972
972
|
i0.ɵɵtext(3);
|
|
973
973
|
i0.ɵɵelementEnd()();
|
|
974
974
|
} if (rf & 2) {
|
|
@@ -978,18 +978,18 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Condition
|
|
|
978
978
|
i0.ɵɵadvance(3);
|
|
979
979
|
i0.ɵɵtextInterpolate((result_r37.score * 100).toFixed(0));
|
|
980
980
|
} }
|
|
981
|
-
function
|
|
982
|
-
i0.ɵɵelementStart(0, "span",
|
|
983
|
-
i0.ɵɵelement(1, "i",
|
|
981
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_30_For_7_Conditional_1_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
982
|
+
i0.ɵɵelementStart(0, "span", 250);
|
|
983
|
+
i0.ɵɵelement(1, "i", 155);
|
|
984
984
|
i0.ɵɵelementEnd();
|
|
985
985
|
} }
|
|
986
|
-
function
|
|
987
|
-
i0.ɵɵelementStart(0, "div",
|
|
988
|
-
i0.ɵɵconditionalCreate(1,
|
|
989
|
-
i0.ɵɵconditionalCreate(2,
|
|
990
|
-
i0.ɵɵconditionalCreate(3,
|
|
991
|
-
i0.ɵɵconditionalCreate(4,
|
|
992
|
-
i0.ɵɵconditionalCreate(5,
|
|
986
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_30_For_7_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
987
|
+
i0.ɵɵelementStart(0, "div", 244);
|
|
988
|
+
i0.ɵɵconditionalCreate(1, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_30_For_7_Conditional_1_Conditional_1_Template, 2, 18, "span", 246);
|
|
989
|
+
i0.ɵɵconditionalCreate(2, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_30_For_7_Conditional_1_Conditional_2_Template, 2, 0, "span", 247);
|
|
990
|
+
i0.ɵɵconditionalCreate(3, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_30_For_7_Conditional_1_Conditional_3_Template, 4, 10, "span", 248);
|
|
991
|
+
i0.ɵɵconditionalCreate(4, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_30_For_7_Conditional_1_Conditional_4_Template, 4, 10, "span", 249);
|
|
992
|
+
i0.ɵɵconditionalCreate(5, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_30_For_7_Conditional_1_Conditional_5_Template, 2, 0, "span", 250);
|
|
993
993
|
i0.ɵɵelementEnd();
|
|
994
994
|
} if (rf & 2) {
|
|
995
995
|
const result_r37 = ctx;
|
|
@@ -1005,17 +1005,17 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Condition
|
|
|
1005
1005
|
i0.ɵɵadvance();
|
|
1006
1006
|
i0.ɵɵconditional(ctx_r0.evalPreferences.showAuto && result_r37.score == null ? 5 : -1);
|
|
1007
1007
|
} }
|
|
1008
|
-
function
|
|
1009
|
-
i0.ɵɵelementStart(0, "span",
|
|
1010
|
-
i0.ɵɵelement(1, "i",
|
|
1008
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_30_For_7_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
1009
|
+
i0.ɵɵelementStart(0, "span", 245);
|
|
1010
|
+
i0.ɵɵelement(1, "i", 257);
|
|
1011
1011
|
i0.ɵɵelementEnd();
|
|
1012
1012
|
} }
|
|
1013
|
-
function
|
|
1013
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_30_For_7_Template(rf, ctx) { if (rf & 1) {
|
|
1014
1014
|
const _r35 = i0.ɵɵgetCurrentView();
|
|
1015
|
-
i0.ɵɵelementStart(0, "td",
|
|
1016
|
-
i0.ɵɵlistener("click", function
|
|
1017
|
-
i0.ɵɵconditionalCreate(1,
|
|
1018
|
-
i0.ɵɵconditionalCreate(2,
|
|
1015
|
+
i0.ɵɵelementStart(0, "td", 243);
|
|
1016
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_30_For_7_Template_td_click_0_listener($event) { const run_r36 = i0.ɵɵrestoreView(_r35).$implicit; const test_r34 = i0.ɵɵnextContext().$implicit; const ctx_r0 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r0.onMatrixCellClick(ctx_r0.getTestResultForRun(run_r36.runId, test_r34.testId), $event)); });
|
|
1017
|
+
i0.ɵɵconditionalCreate(1, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_30_For_7_Conditional_1_Template, 6, 5, "div", 244);
|
|
1018
|
+
i0.ɵɵconditionalCreate(2, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_30_For_7_Conditional_2_Template, 2, 0, "span", 245);
|
|
1019
1019
|
i0.ɵɵelementEnd();
|
|
1020
1020
|
} if (rf & 2) {
|
|
1021
1021
|
let tmp_27_0;
|
|
@@ -1030,18 +1030,18 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Condition
|
|
|
1030
1030
|
i0.ɵɵadvance();
|
|
1031
1031
|
i0.ɵɵconditional(!ctx_r0.getTestResultForRun(run_r36.runId, test_r34.testId) ? 2 : -1);
|
|
1032
1032
|
} }
|
|
1033
|
-
function
|
|
1033
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_30_Template(rf, ctx) { if (rf & 1) {
|
|
1034
1034
|
const _r33 = i0.ɵɵgetCurrentView();
|
|
1035
|
-
i0.ɵɵelementStart(0, "tr",
|
|
1036
|
-
i0.ɵɵlistener("click", function
|
|
1037
|
-
i0.ɵɵelementStart(1, "td",
|
|
1035
|
+
i0.ɵɵelementStart(0, "tr", 238);
|
|
1036
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_30_Template_tr_click_0_listener() { const test_r34 = i0.ɵɵrestoreView(_r33).$implicit; const ctx_r0 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r0.selectMatrixRow(test_r34.testId)); });
|
|
1037
|
+
i0.ɵɵelementStart(1, "td", 239);
|
|
1038
1038
|
i0.ɵɵtext(2);
|
|
1039
1039
|
i0.ɵɵelementEnd();
|
|
1040
|
-
i0.ɵɵelementStart(3, "td",
|
|
1040
|
+
i0.ɵɵelementStart(3, "td", 240)(4, "span", 241);
|
|
1041
1041
|
i0.ɵɵtext(5);
|
|
1042
1042
|
i0.ɵɵelementEnd()();
|
|
1043
|
-
i0.ɵɵrepeaterCreate(6,
|
|
1044
|
-
i0.ɵɵelement(8, "td",
|
|
1043
|
+
i0.ɵɵrepeaterCreate(6, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_30_For_7_Template, 3, 8, "td", 242, i0.ɵɵrepeaterTrackByIdentity);
|
|
1044
|
+
i0.ɵɵelement(8, "td", 229);
|
|
1045
1045
|
i0.ɵɵelementEnd();
|
|
1046
1046
|
} if (rf & 2) {
|
|
1047
1047
|
const test_r34 = ctx.$implicit;
|
|
@@ -1056,8 +1056,8 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Condition
|
|
|
1056
1056
|
i0.ɵɵadvance();
|
|
1057
1057
|
i0.ɵɵrepeater(ctx_r0.matrixData);
|
|
1058
1058
|
} }
|
|
1059
|
-
function
|
|
1060
|
-
i0.ɵɵelementStart(0, "span",
|
|
1059
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_38_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
1060
|
+
i0.ɵɵelementStart(0, "span", 259)(1, "span", 262);
|
|
1061
1061
|
i0.ɵɵtext(2);
|
|
1062
1062
|
i0.ɵɵelementEnd()();
|
|
1063
1063
|
} if (rf & 2) {
|
|
@@ -1066,8 +1066,8 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Condition
|
|
|
1066
1066
|
i0.ɵɵadvance(2);
|
|
1067
1067
|
i0.ɵɵtextInterpolate2("", ctx_r0.getRunPassedCount(run_r38), "/", ctx_r0.getRunTotalCount(run_r38));
|
|
1068
1068
|
} }
|
|
1069
|
-
function
|
|
1070
|
-
i0.ɵɵelementStart(0, "span",
|
|
1069
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_38_Conditional_3_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
1070
|
+
i0.ɵɵelementStart(0, "span", 263);
|
|
1071
1071
|
i0.ɵɵtext(1);
|
|
1072
1072
|
i0.ɵɵelementEnd();
|
|
1073
1073
|
} if (rf & 2) {
|
|
@@ -1077,10 +1077,10 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Condition
|
|
|
1077
1077
|
i0.ɵɵadvance();
|
|
1078
1078
|
i0.ɵɵtextInterpolate((tmp_16_0 = ctx_r0.getRunHumanAvg(run_r38)) == null ? null : tmp_16_0.toFixed(1));
|
|
1079
1079
|
} }
|
|
1080
|
-
function
|
|
1081
|
-
i0.ɵɵelementStart(0, "span",
|
|
1082
|
-
i0.ɵɵconditionalCreate(1,
|
|
1083
|
-
i0.ɵɵelementStart(2, "span",
|
|
1080
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_38_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
1081
|
+
i0.ɵɵelementStart(0, "span", 260);
|
|
1082
|
+
i0.ɵɵconditionalCreate(1, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_38_Conditional_3_Conditional_1_Template, 2, 1, "span", 263);
|
|
1083
|
+
i0.ɵɵelementStart(2, "span", 264);
|
|
1084
1084
|
i0.ɵɵtext(3);
|
|
1085
1085
|
i0.ɵɵelementEnd()();
|
|
1086
1086
|
} if (rf & 2) {
|
|
@@ -1091,8 +1091,8 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Condition
|
|
|
1091
1091
|
i0.ɵɵadvance(2);
|
|
1092
1092
|
i0.ɵɵtextInterpolate1("(", ctx_r0.getRunHumanCount(run_r38), ")");
|
|
1093
1093
|
} }
|
|
1094
|
-
function
|
|
1095
|
-
i0.ɵɵelementStart(0, "span",
|
|
1094
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_38_Conditional_4_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
1095
|
+
i0.ɵɵelementStart(0, "span", 263);
|
|
1096
1096
|
i0.ɵɵtext(1);
|
|
1097
1097
|
i0.ɵɵelementEnd();
|
|
1098
1098
|
} if (rf & 2) {
|
|
@@ -1101,10 +1101,10 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Condition
|
|
|
1101
1101
|
i0.ɵɵadvance();
|
|
1102
1102
|
i0.ɵɵtextInterpolate1("", (ctx_r0.getRunAutoAvg(run_r38) * 100).toFixed(0), "%");
|
|
1103
1103
|
} }
|
|
1104
|
-
function
|
|
1105
|
-
i0.ɵɵelementStart(0, "span",
|
|
1106
|
-
i0.ɵɵconditionalCreate(1,
|
|
1107
|
-
i0.ɵɵelementStart(2, "span",
|
|
1104
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_38_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
1105
|
+
i0.ɵɵelementStart(0, "span", 261);
|
|
1106
|
+
i0.ɵɵconditionalCreate(1, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_38_Conditional_4_Conditional_1_Template, 2, 1, "span", 263);
|
|
1107
|
+
i0.ɵɵelementStart(2, "span", 264);
|
|
1108
1108
|
i0.ɵɵtext(3);
|
|
1109
1109
|
i0.ɵɵelementEnd()();
|
|
1110
1110
|
} if (rf & 2) {
|
|
@@ -1115,11 +1115,11 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Condition
|
|
|
1115
1115
|
i0.ɵɵadvance(2);
|
|
1116
1116
|
i0.ɵɵtextInterpolate1("(", ctx_r0.getRunAutoCount(run_r38), ")");
|
|
1117
1117
|
} }
|
|
1118
|
-
function
|
|
1119
|
-
i0.ɵɵelementStart(0, "td",
|
|
1120
|
-
i0.ɵɵconditionalCreate(2,
|
|
1121
|
-
i0.ɵɵconditionalCreate(3,
|
|
1122
|
-
i0.ɵɵconditionalCreate(4,
|
|
1118
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_38_Template(rf, ctx) { if (rf & 1) {
|
|
1119
|
+
i0.ɵɵelementStart(0, "td", 228)(1, "div", 258);
|
|
1120
|
+
i0.ɵɵconditionalCreate(2, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_38_Conditional_2_Template, 3, 2, "span", 259);
|
|
1121
|
+
i0.ɵɵconditionalCreate(3, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_38_Conditional_3_Template, 4, 2, "span", 260);
|
|
1122
|
+
i0.ɵɵconditionalCreate(4, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_38_Conditional_4_Template, 4, 2, "span", 261);
|
|
1123
1123
|
i0.ɵɵelementEnd()();
|
|
1124
1124
|
} if (rf & 2) {
|
|
1125
1125
|
const ctx_r0 = i0.ɵɵnextContext(5);
|
|
@@ -1130,50 +1130,50 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Condition
|
|
|
1130
1130
|
i0.ɵɵadvance();
|
|
1131
1131
|
i0.ɵɵconditional(ctx_r0.evalPreferences.showAuto ? 4 : -1);
|
|
1132
1132
|
} }
|
|
1133
|
-
function
|
|
1133
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
1134
1134
|
const _r28 = i0.ɵɵgetCurrentView();
|
|
1135
|
-
i0.ɵɵelementStart(0, "div",
|
|
1136
|
-
i0.ɵɵelement(3, "i",
|
|
1135
|
+
i0.ɵɵelementStart(0, "div", 206)(1, "div", 209)(2, "h3");
|
|
1136
|
+
i0.ɵɵelement(3, "i", 164);
|
|
1137
1137
|
i0.ɵɵtext(4, " Test Results Matrix");
|
|
1138
1138
|
i0.ɵɵelementEnd();
|
|
1139
|
-
i0.ɵɵelementStart(5, "div",
|
|
1140
|
-
i0.ɵɵelement(7, "i",
|
|
1141
|
-
i0.ɵɵelementStart(8, "input",
|
|
1142
|
-
i0.ɵɵlistener("input", function
|
|
1139
|
+
i0.ɵɵelementStart(5, "div", 210)(6, "div", 211);
|
|
1140
|
+
i0.ɵɵelement(7, "i", 212);
|
|
1141
|
+
i0.ɵɵelementStart(8, "input", 213);
|
|
1142
|
+
i0.ɵɵlistener("input", function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_Template_input_input_8_listener($event) { i0.ɵɵrestoreView(_r28); const ctx_r0 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r0.onMatrixFilterInput($event)); });
|
|
1143
1143
|
i0.ɵɵelementEnd();
|
|
1144
|
-
i0.ɵɵconditionalCreate(9,
|
|
1144
|
+
i0.ɵɵconditionalCreate(9, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_Conditional_9_Template, 2, 0, "button", 214);
|
|
1145
1145
|
i0.ɵɵelementEnd();
|
|
1146
|
-
i0.ɵɵelementStart(10, "span",
|
|
1146
|
+
i0.ɵɵelementStart(10, "span", 215);
|
|
1147
1147
|
i0.ɵɵtext(11);
|
|
1148
1148
|
i0.ɵɵelementEnd();
|
|
1149
|
-
i0.ɵɵelementStart(12, "button",
|
|
1150
|
-
i0.ɵɵlistener("click", function
|
|
1151
|
-
i0.ɵɵelement(13, "i",
|
|
1149
|
+
i0.ɵɵelementStart(12, "button", 216);
|
|
1150
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_Template_button_click_12_listener() { i0.ɵɵrestoreView(_r28); const ctx_r0 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r0.exportMatrixToCSV()); });
|
|
1151
|
+
i0.ɵɵelement(13, "i", 217);
|
|
1152
1152
|
i0.ɵɵtext(14, " Export ");
|
|
1153
1153
|
i0.ɵɵelementEnd()()();
|
|
1154
|
-
i0.ɵɵelementStart(15, "div",
|
|
1155
|
-
i0.ɵɵlistener("click", function
|
|
1154
|
+
i0.ɵɵelementStart(15, "div", 218)(16, "table", 219)(17, "thead")(18, "tr")(19, "th", 220);
|
|
1155
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_Template_th_click_19_listener() { i0.ɵɵrestoreView(_r28); const ctx_r0 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r0.toggleMatrixSort("sequence")); });
|
|
1156
1156
|
i0.ɵɵtext(20, " # ");
|
|
1157
1157
|
i0.ɵɵelement(21, "i", 19);
|
|
1158
1158
|
i0.ɵɵelementEnd();
|
|
1159
|
-
i0.ɵɵelementStart(22, "th",
|
|
1160
|
-
i0.ɵɵlistener("click", function
|
|
1159
|
+
i0.ɵɵelementStart(22, "th", 221);
|
|
1160
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_Template_th_click_22_listener() { i0.ɵɵrestoreView(_r28); const ctx_r0 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r0.toggleMatrixSort("name")); });
|
|
1161
1161
|
i0.ɵɵtext(23, " Test ");
|
|
1162
1162
|
i0.ɵɵelement(24, "i", 19);
|
|
1163
1163
|
i0.ɵɵelementEnd();
|
|
1164
|
-
i0.ɵɵrepeaterCreate(25,
|
|
1165
|
-
i0.ɵɵelement(27, "th",
|
|
1164
|
+
i0.ɵɵrepeaterCreate(25, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_26_Template, 8, 12, "th", 222, i0.ɵɵrepeaterTrackByIdentity);
|
|
1165
|
+
i0.ɵɵelement(27, "th", 223);
|
|
1166
1166
|
i0.ɵɵelementEnd()();
|
|
1167
1167
|
i0.ɵɵelementStart(28, "tbody");
|
|
1168
|
-
i0.ɵɵrepeaterCreate(29,
|
|
1168
|
+
i0.ɵɵrepeaterCreate(29, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_30_Template, 9, 5, "tr", 224, i0.ɵɵrepeaterTrackByIdentity);
|
|
1169
1169
|
i0.ɵɵelementEnd();
|
|
1170
|
-
i0.ɵɵelementStart(31, "tfoot")(32, "tr",
|
|
1171
|
-
i0.ɵɵelement(33, "td",
|
|
1172
|
-
i0.ɵɵelementStart(34, "td",
|
|
1170
|
+
i0.ɵɵelementStart(31, "tfoot")(32, "tr", 225);
|
|
1171
|
+
i0.ɵɵelement(33, "td", 226);
|
|
1172
|
+
i0.ɵɵelementStart(34, "td", 227)(35, "strong");
|
|
1173
1173
|
i0.ɵɵtext(36, "Totals");
|
|
1174
1174
|
i0.ɵɵelementEnd()();
|
|
1175
|
-
i0.ɵɵrepeaterCreate(37,
|
|
1176
|
-
i0.ɵɵelement(39, "td",
|
|
1175
|
+
i0.ɵɵrepeaterCreate(37, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_For_38_Template, 5, 3, "td", 228, i0.ɵɵrepeaterTrackByIdentity);
|
|
1176
|
+
i0.ɵɵelement(39, "td", 229);
|
|
1177
1177
|
i0.ɵɵelementEnd()()()()();
|
|
1178
1178
|
} if (rf & 2) {
|
|
1179
1179
|
const ctx_r0 = i0.ɵɵnextContext(4);
|
|
@@ -1196,13 +1196,13 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Condition
|
|
|
1196
1196
|
i0.ɵɵadvance(8);
|
|
1197
1197
|
i0.ɵɵrepeater(ctx_r0.matrixData);
|
|
1198
1198
|
} }
|
|
1199
|
-
function
|
|
1200
|
-
i0.ɵɵelement(0, "mj-empty-state",
|
|
1199
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
1200
|
+
i0.ɵɵelement(0, "mj-empty-state", 207);
|
|
1201
1201
|
} }
|
|
1202
|
-
function
|
|
1203
|
-
i0.ɵɵconditionalCreate(0,
|
|
1204
|
-
i0.ɵɵconditionalCreate(1,
|
|
1205
|
-
i0.ɵɵconditionalCreate(2,
|
|
1202
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
1203
|
+
i0.ɵɵconditionalCreate(0, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_0_Template, 2, 0, "div", 102);
|
|
1204
|
+
i0.ɵɵconditionalCreate(1, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_1_Template, 40, 7, "div", 206);
|
|
1205
|
+
i0.ɵɵconditionalCreate(2, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Conditional_2_Template, 1, 0, "mj-empty-state", 207);
|
|
1206
1206
|
} if (rf & 2) {
|
|
1207
1207
|
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
1208
1208
|
i0.ɵɵconditional(ctx_r0.loadingMatrix ? 0 : -1);
|
|
@@ -1211,37 +1211,37 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Condition
|
|
|
1211
1211
|
i0.ɵɵadvance();
|
|
1212
1212
|
i0.ɵɵconditional(!ctx_r0.loadingMatrix && ctx_r0.matrixLoaded && ctx_r0.matrixData.length === 0 ? 2 : -1);
|
|
1213
1213
|
} }
|
|
1214
|
-
function
|
|
1215
|
-
i0.ɵɵelementStart(0, "div",
|
|
1216
|
-
i0.ɵɵelement(1, "mj-loading",
|
|
1214
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_19_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
1215
|
+
i0.ɵɵelementStart(0, "div", 102);
|
|
1216
|
+
i0.ɵɵelement(1, "mj-loading", 267);
|
|
1217
1217
|
i0.ɵɵelementEnd();
|
|
1218
1218
|
} }
|
|
1219
|
-
function
|
|
1220
|
-
i0.ɵɵelementStart(0, "div",
|
|
1221
|
-
i0.ɵɵelement(3, "i",
|
|
1219
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_19_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
1220
|
+
i0.ɵɵelementStart(0, "div", 265)(1, "div", 268)(2, "h3");
|
|
1221
|
+
i0.ɵɵelement(3, "i", 165);
|
|
1222
1222
|
i0.ɵɵtext(4, " Test Results Flow");
|
|
1223
1223
|
i0.ɵɵelementEnd();
|
|
1224
|
-
i0.ɵɵelementStart(5, "div",
|
|
1225
|
-
i0.ɵɵelement(7, "i",
|
|
1224
|
+
i0.ɵɵelementStart(5, "div", 269)(6, "span", 270);
|
|
1225
|
+
i0.ɵɵelement(7, "i", 180);
|
|
1226
1226
|
i0.ɵɵtext(8, " Passed");
|
|
1227
1227
|
i0.ɵɵelementEnd();
|
|
1228
|
-
i0.ɵɵelementStart(9, "span",
|
|
1229
|
-
i0.ɵɵelement(10, "i",
|
|
1228
|
+
i0.ɵɵelementStart(9, "span", 271);
|
|
1229
|
+
i0.ɵɵelement(10, "i", 94);
|
|
1230
1230
|
i0.ɵɵtext(11, " Failed");
|
|
1231
1231
|
i0.ɵɵelementEnd();
|
|
1232
|
-
i0.ɵɵelementStart(12, "span",
|
|
1233
|
-
i0.ɵɵelement(13, "i",
|
|
1232
|
+
i0.ɵɵelementStart(12, "span", 272);
|
|
1233
|
+
i0.ɵɵelement(13, "i", 273);
|
|
1234
1234
|
i0.ɵɵtext(14, " Error");
|
|
1235
1235
|
i0.ɵɵelementEnd();
|
|
1236
|
-
i0.ɵɵelementStart(15, "span",
|
|
1237
|
-
i0.ɵɵelement(16, "i",
|
|
1236
|
+
i0.ɵɵelementStart(15, "span", 274);
|
|
1237
|
+
i0.ɵɵelement(16, "i", 275);
|
|
1238
1238
|
i0.ɵɵtext(17, " Skipped");
|
|
1239
1239
|
i0.ɵɵelementEnd()()();
|
|
1240
|
-
i0.ɵɵelementStart(18, "div",
|
|
1241
|
-
i0.ɵɵelement(19, "div",
|
|
1240
|
+
i0.ɵɵelementStart(18, "div", 276);
|
|
1241
|
+
i0.ɵɵelement(19, "div", 277, 1);
|
|
1242
1242
|
i0.ɵɵelementEnd();
|
|
1243
|
-
i0.ɵɵelementStart(21, "div",
|
|
1244
|
-
i0.ɵɵelement(22, "i",
|
|
1243
|
+
i0.ɵɵelementStart(21, "div", 278);
|
|
1244
|
+
i0.ɵɵelement(22, "i", 122);
|
|
1245
1245
|
i0.ɵɵtext(23);
|
|
1246
1246
|
i0.ɵɵelementEnd()();
|
|
1247
1247
|
} if (rf & 2) {
|
|
@@ -1249,13 +1249,13 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Condition
|
|
|
1249
1249
|
i0.ɵɵadvance(23);
|
|
1250
1250
|
i0.ɵɵtextInterpolate1(" Interactive visualization showing test results across ", ctx_r0.matrixData.length, " runs. Hover over elements for details, click nodes to navigate. ");
|
|
1251
1251
|
} }
|
|
1252
|
-
function
|
|
1253
|
-
i0.ɵɵelement(0, "mj-empty-state",
|
|
1252
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_19_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
1253
|
+
i0.ɵɵelement(0, "mj-empty-state", 266);
|
|
1254
1254
|
} }
|
|
1255
|
-
function
|
|
1256
|
-
i0.ɵɵconditionalCreate(0,
|
|
1257
|
-
i0.ɵɵconditionalCreate(1,
|
|
1258
|
-
i0.ɵɵconditionalCreate(2,
|
|
1255
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_19_Template(rf, ctx) { if (rf & 1) {
|
|
1256
|
+
i0.ɵɵconditionalCreate(0, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_19_Conditional_0_Template, 2, 0, "div", 102);
|
|
1257
|
+
i0.ɵɵconditionalCreate(1, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_19_Conditional_1_Template, 24, 1, "div", 265);
|
|
1258
|
+
i0.ɵɵconditionalCreate(2, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_19_Conditional_2_Template, 1, 0, "mj-empty-state", 266);
|
|
1259
1259
|
} if (rf & 2) {
|
|
1260
1260
|
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
1261
1261
|
i0.ɵɵconditional(ctx_r0.loadingMatrix ? 0 : -1);
|
|
@@ -1264,33 +1264,33 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Condition
|
|
|
1264
1264
|
i0.ɵɵadvance();
|
|
1265
1265
|
i0.ɵɵconditional(!ctx_r0.loadingMatrix && ctx_r0.matrixLoaded && ctx_r0.matrixData.length === 0 ? 2 : -1);
|
|
1266
1266
|
} }
|
|
1267
|
-
function
|
|
1267
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
1268
1268
|
const _r20 = i0.ɵɵgetCurrentView();
|
|
1269
|
-
i0.ɵɵelementStart(0, "div",
|
|
1270
|
-
i0.ɵɵlistener("click", function
|
|
1271
|
-
i0.ɵɵelement(3, "i",
|
|
1269
|
+
i0.ɵɵelementStart(0, "div", 160)(1, "div", 161)(2, "button", 162);
|
|
1270
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Template_button_click_2_listener() { i0.ɵɵrestoreView(_r20); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.setAnalyticsView("summary")); });
|
|
1271
|
+
i0.ɵɵelement(3, "i", 163);
|
|
1272
1272
|
i0.ɵɵelementStart(4, "span");
|
|
1273
1273
|
i0.ɵɵtext(5, "Summary");
|
|
1274
1274
|
i0.ɵɵelementEnd()();
|
|
1275
|
-
i0.ɵɵelementStart(6, "button",
|
|
1276
|
-
i0.ɵɵlistener("click", function
|
|
1277
|
-
i0.ɵɵelement(7, "i",
|
|
1275
|
+
i0.ɵɵelementStart(6, "button", 162);
|
|
1276
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r20); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.setAnalyticsView("matrix")); });
|
|
1277
|
+
i0.ɵɵelement(7, "i", 164);
|
|
1278
1278
|
i0.ɵɵelementStart(8, "span");
|
|
1279
1279
|
i0.ɵɵtext(9, "Matrix");
|
|
1280
1280
|
i0.ɵɵelementEnd()();
|
|
1281
|
-
i0.ɵɵelementStart(10, "button",
|
|
1282
|
-
i0.ɵɵlistener("click", function
|
|
1283
|
-
i0.ɵɵelement(11, "i",
|
|
1281
|
+
i0.ɵɵelementStart(10, "button", 162);
|
|
1282
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Template_button_click_10_listener() { i0.ɵɵrestoreView(_r20); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.setAnalyticsView("chart")); });
|
|
1283
|
+
i0.ɵɵelement(11, "i", 165);
|
|
1284
1284
|
i0.ɵɵelementStart(12, "span");
|
|
1285
1285
|
i0.ɵɵtext(13, "Chart");
|
|
1286
1286
|
i0.ɵɵelementEnd()()()();
|
|
1287
|
-
i0.ɵɵelementStart(14, "mj-accordion-panel",
|
|
1288
|
-
i0.ɵɵlistener("ExpandedChange", function
|
|
1289
|
-
i0.ɵɵtemplate(15,
|
|
1287
|
+
i0.ɵɵelementStart(14, "mj-accordion-panel", 166);
|
|
1288
|
+
i0.ɵɵlistener("ExpandedChange", function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Template_mj_accordion_panel_ExpandedChange_14_listener($event) { i0.ɵɵrestoreView(_r20); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.onFiltersExpandedChange($event)); });
|
|
1289
|
+
i0.ɵɵtemplate(15, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_ng_template_15_Template, 3, 1, "ng-template", 167)(16, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_ng_template_16_Template, 14, 9, "ng-template", 168);
|
|
1290
1290
|
i0.ɵɵelementEnd();
|
|
1291
|
-
i0.ɵɵconditionalCreate(17,
|
|
1292
|
-
i0.ɵɵconditionalCreate(18,
|
|
1293
|
-
i0.ɵɵconditionalCreate(19,
|
|
1291
|
+
i0.ɵɵconditionalCreate(17, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_17_Template, 62, 15);
|
|
1292
|
+
i0.ɵɵconditionalCreate(18, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_18_Template, 3, 3);
|
|
1293
|
+
i0.ɵɵconditionalCreate(19, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Conditional_19_Template, 3, 3);
|
|
1294
1294
|
} if (rf & 2) {
|
|
1295
1295
|
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
1296
1296
|
i0.ɵɵadvance(2);
|
|
@@ -1308,17 +1308,17 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Conditional_2_Template(
|
|
|
1308
1308
|
i0.ɵɵadvance();
|
|
1309
1309
|
i0.ɵɵconditional(ctx_r0.analyticsView === "chart" ? 19 : -1);
|
|
1310
1310
|
} }
|
|
1311
|
-
function
|
|
1311
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
1312
1312
|
const _r39 = i0.ɵɵgetCurrentView();
|
|
1313
|
-
i0.ɵɵelementStart(0, "mj-empty-state",
|
|
1314
|
-
i0.ɵɵlistener("Action", function
|
|
1313
|
+
i0.ɵɵelementStart(0, "mj-empty-state", 279);
|
|
1314
|
+
i0.ɵɵlistener("Action", function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_3_Template_mj_empty_state_Action_0_listener() { i0.ɵɵrestoreView(_r39); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.runSuite()); });
|
|
1315
1315
|
i0.ɵɵelementEnd();
|
|
1316
1316
|
} }
|
|
1317
|
-
function
|
|
1318
|
-
i0.ɵɵelementStart(0, "div",
|
|
1319
|
-
i0.ɵɵconditionalCreate(1,
|
|
1320
|
-
i0.ɵɵconditionalCreate(2,
|
|
1321
|
-
i0.ɵɵconditionalCreate(3,
|
|
1317
|
+
function MJTestSuiteFormComponentExtended_Conditional_64_Template(rf, ctx) { if (rf & 1) {
|
|
1318
|
+
i0.ɵɵelementStart(0, "div", 43);
|
|
1319
|
+
i0.ɵɵconditionalCreate(1, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_1_Template, 2, 0, "div", 102);
|
|
1320
|
+
i0.ɵɵconditionalCreate(2, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_2_Template, 20, 11);
|
|
1321
|
+
i0.ɵɵconditionalCreate(3, MJTestSuiteFormComponentExtended_Conditional_64_Conditional_3_Template, 1, 0, "mj-empty-state", 158);
|
|
1322
1322
|
i0.ɵɵelementEnd();
|
|
1323
1323
|
} if (rf & 2) {
|
|
1324
1324
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
@@ -1329,8 +1329,8 @@ function MJTestSuiteFormComponentExtended_Conditional_63_Template(rf, ctx) { if
|
|
|
1329
1329
|
i0.ɵɵadvance();
|
|
1330
1330
|
i0.ɵɵconditional(!ctx_r0.loadingAnalytics && ctx_r0.analyticsLoaded && ctx_r0.analyticsData.length === 0 ? 3 : -1);
|
|
1331
1331
|
} }
|
|
1332
|
-
function
|
|
1333
|
-
i0.ɵɵelementStart(0, "span",
|
|
1332
|
+
function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_5_For_2_Conditional_8_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
1333
|
+
i0.ɵɵelementStart(0, "span", 296);
|
|
1334
1334
|
i0.ɵɵtext(1);
|
|
1335
1335
|
i0.ɵɵelementEnd();
|
|
1336
1336
|
} if (rf & 2) {
|
|
@@ -1338,9 +1338,9 @@ function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_5_For_2_Con
|
|
|
1338
1338
|
i0.ɵɵadvance();
|
|
1339
1339
|
i0.ɵɵtextInterpolate(tag_r42);
|
|
1340
1340
|
} }
|
|
1341
|
-
function
|
|
1342
|
-
i0.ɵɵelementStart(0, "div",
|
|
1343
|
-
i0.ɵɵrepeaterCreate(1,
|
|
1341
|
+
function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_5_For_2_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
1342
|
+
i0.ɵɵelementStart(0, "div", 295);
|
|
1343
|
+
i0.ɵɵrepeaterCreate(1, MJTestSuiteFormComponentExtended_Conditional_65_Conditional_5_For_2_Conditional_8_For_2_Template, 2, 1, "span", 296, i0.ɵɵrepeaterTrackByIdentity);
|
|
1344
1344
|
i0.ɵɵelementEnd();
|
|
1345
1345
|
} if (rf & 2) {
|
|
1346
1346
|
const run_r41 = i0.ɵɵnextContext().$implicit;
|
|
@@ -1348,19 +1348,19 @@ function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_5_For_2_Con
|
|
|
1348
1348
|
i0.ɵɵadvance();
|
|
1349
1349
|
i0.ɵɵrepeater(ctx_r0.getRunTags(run_r41).slice(0, 2));
|
|
1350
1350
|
} }
|
|
1351
|
-
function
|
|
1351
|
+
function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_5_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
1352
1352
|
const _r40 = i0.ɵɵgetCurrentView();
|
|
1353
|
-
i0.ɵɵelementStart(0, "div",
|
|
1354
|
-
i0.ɵɵlistener("click", function
|
|
1355
|
-
i0.ɵɵelement(1, "div",
|
|
1356
|
-
i0.ɵɵelementStart(2, "div",
|
|
1353
|
+
i0.ɵɵelementStart(0, "div", 290);
|
|
1354
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_5_For_2_Template_div_click_0_listener() { const run_r41 = i0.ɵɵrestoreView(_r40).$implicit; const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.selectCompareRunA(run_r41)); });
|
|
1355
|
+
i0.ɵɵelement(1, "div", 291);
|
|
1356
|
+
i0.ɵɵelementStart(2, "div", 292)(3, "div", 293);
|
|
1357
1357
|
i0.ɵɵtext(4);
|
|
1358
1358
|
i0.ɵɵpipe(5, "date");
|
|
1359
1359
|
i0.ɵɵelementEnd();
|
|
1360
|
-
i0.ɵɵelementStart(6, "div",
|
|
1360
|
+
i0.ɵɵelementStart(6, "div", 294);
|
|
1361
1361
|
i0.ɵɵtext(7);
|
|
1362
1362
|
i0.ɵɵelementEnd()();
|
|
1363
|
-
i0.ɵɵconditionalCreate(8,
|
|
1363
|
+
i0.ɵɵconditionalCreate(8, MJTestSuiteFormComponentExtended_Conditional_65_Conditional_5_For_2_Conditional_8_Template, 3, 0, "div", 295);
|
|
1364
1364
|
i0.ɵɵelementEnd();
|
|
1365
1365
|
} if (rf & 2) {
|
|
1366
1366
|
const run_r41 = ctx.$implicit;
|
|
@@ -1375,29 +1375,29 @@ function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_5_For_2_Tem
|
|
|
1375
1375
|
i0.ɵɵadvance();
|
|
1376
1376
|
i0.ɵɵconditional(ctx_r0.getRunTags(run_r41).length > 0 ? 8 : -1);
|
|
1377
1377
|
} }
|
|
1378
|
-
function
|
|
1379
|
-
i0.ɵɵelementStart(0, "div",
|
|
1380
|
-
i0.ɵɵrepeaterCreate(1,
|
|
1378
|
+
function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
1379
|
+
i0.ɵɵelementStart(0, "div", 282);
|
|
1380
|
+
i0.ɵɵrepeaterCreate(1, MJTestSuiteFormComponentExtended_Conditional_65_Conditional_5_For_2_Template, 9, 10, "div", 289, i0.ɵɵrepeaterTrackByIdentity);
|
|
1381
1381
|
i0.ɵɵelementEnd();
|
|
1382
1382
|
} if (rf & 2) {
|
|
1383
1383
|
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
1384
1384
|
i0.ɵɵadvance();
|
|
1385
1385
|
i0.ɵɵrepeater(ctx_r0.suiteRuns);
|
|
1386
1386
|
} }
|
|
1387
|
-
function
|
|
1387
|
+
function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
1388
1388
|
const _r43 = i0.ɵɵgetCurrentView();
|
|
1389
|
-
i0.ɵɵelementStart(0, "div",
|
|
1389
|
+
i0.ɵɵelementStart(0, "div", 283)(1, "div", 297)(2, "span", 298);
|
|
1390
1390
|
i0.ɵɵtext(3, "Selected:");
|
|
1391
1391
|
i0.ɵɵelementEnd();
|
|
1392
|
-
i0.ɵɵelementStart(4, "button",
|
|
1393
|
-
i0.ɵɵlistener("click", function
|
|
1392
|
+
i0.ɵɵelementStart(4, "button", 299);
|
|
1393
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_6_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r43); const ctx_r0 = i0.ɵɵnextContext(2); ctx_r0.compareRunA = null; return i0.ɵɵresetView(ctx_r0.compareResults = []); });
|
|
1394
1394
|
i0.ɵɵtext(5, "Clear");
|
|
1395
1395
|
i0.ɵɵelementEnd()();
|
|
1396
|
-
i0.ɵɵelementStart(6, "div",
|
|
1396
|
+
i0.ɵɵelementStart(6, "div", 300)(7, "span");
|
|
1397
1397
|
i0.ɵɵtext(8);
|
|
1398
1398
|
i0.ɵɵpipe(9, "date");
|
|
1399
1399
|
i0.ɵɵelementEnd();
|
|
1400
|
-
i0.ɵɵelementStart(10, "span",
|
|
1400
|
+
i0.ɵɵelementStart(10, "span", 301);
|
|
1401
1401
|
i0.ɵɵtext(11);
|
|
1402
1402
|
i0.ɵɵelementEnd()()();
|
|
1403
1403
|
} if (rf & 2) {
|
|
@@ -1407,8 +1407,8 @@ function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_6_Template(
|
|
|
1407
1407
|
i0.ɵɵadvance(3);
|
|
1408
1408
|
i0.ɵɵtextInterpolate1("", ctx_r0.getPassRate(ctx_r0.compareRunA).toFixed(1), "%");
|
|
1409
1409
|
} }
|
|
1410
|
-
function
|
|
1411
|
-
i0.ɵɵelementStart(0, "span",
|
|
1410
|
+
function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_12_For_2_Conditional_8_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
1411
|
+
i0.ɵɵelementStart(0, "span", 296);
|
|
1412
1412
|
i0.ɵɵtext(1);
|
|
1413
1413
|
i0.ɵɵelementEnd();
|
|
1414
1414
|
} if (rf & 2) {
|
|
@@ -1416,9 +1416,9 @@ function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_12_For_2_Co
|
|
|
1416
1416
|
i0.ɵɵadvance();
|
|
1417
1417
|
i0.ɵɵtextInterpolate(tag_r46);
|
|
1418
1418
|
} }
|
|
1419
|
-
function
|
|
1420
|
-
i0.ɵɵelementStart(0, "div",
|
|
1421
|
-
i0.ɵɵrepeaterCreate(1,
|
|
1419
|
+
function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_12_For_2_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
1420
|
+
i0.ɵɵelementStart(0, "div", 295);
|
|
1421
|
+
i0.ɵɵrepeaterCreate(1, MJTestSuiteFormComponentExtended_Conditional_65_Conditional_12_For_2_Conditional_8_For_2_Template, 2, 1, "span", 296, i0.ɵɵrepeaterTrackByIdentity);
|
|
1422
1422
|
i0.ɵɵelementEnd();
|
|
1423
1423
|
} if (rf & 2) {
|
|
1424
1424
|
const run_r45 = i0.ɵɵnextContext().$implicit;
|
|
@@ -1426,19 +1426,19 @@ function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_12_For_2_Co
|
|
|
1426
1426
|
i0.ɵɵadvance();
|
|
1427
1427
|
i0.ɵɵrepeater(ctx_r0.getRunTags(run_r45).slice(0, 2));
|
|
1428
1428
|
} }
|
|
1429
|
-
function
|
|
1429
|
+
function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_12_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
1430
1430
|
const _r44 = i0.ɵɵgetCurrentView();
|
|
1431
|
-
i0.ɵɵelementStart(0, "div",
|
|
1432
|
-
i0.ɵɵlistener("click", function
|
|
1433
|
-
i0.ɵɵelement(1, "div",
|
|
1434
|
-
i0.ɵɵelementStart(2, "div",
|
|
1431
|
+
i0.ɵɵelementStart(0, "div", 290);
|
|
1432
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_12_For_2_Template_div_click_0_listener() { const run_r45 = i0.ɵɵrestoreView(_r44).$implicit; const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(!ctx_r0.IsCompareRunA(run_r45) && ctx_r0.selectCompareRunB(run_r45)); });
|
|
1433
|
+
i0.ɵɵelement(1, "div", 291);
|
|
1434
|
+
i0.ɵɵelementStart(2, "div", 292)(3, "div", 293);
|
|
1435
1435
|
i0.ɵɵtext(4);
|
|
1436
1436
|
i0.ɵɵpipe(5, "date");
|
|
1437
1437
|
i0.ɵɵelementEnd();
|
|
1438
|
-
i0.ɵɵelementStart(6, "div",
|
|
1438
|
+
i0.ɵɵelementStart(6, "div", 294);
|
|
1439
1439
|
i0.ɵɵtext(7);
|
|
1440
1440
|
i0.ɵɵelementEnd()();
|
|
1441
|
-
i0.ɵɵconditionalCreate(8,
|
|
1441
|
+
i0.ɵɵconditionalCreate(8, MJTestSuiteFormComponentExtended_Conditional_65_Conditional_12_For_2_Conditional_8_Template, 3, 0, "div", 295);
|
|
1442
1442
|
i0.ɵɵelementEnd();
|
|
1443
1443
|
} if (rf & 2) {
|
|
1444
1444
|
const run_r45 = ctx.$implicit;
|
|
@@ -1453,29 +1453,29 @@ function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_12_For_2_Te
|
|
|
1453
1453
|
i0.ɵɵadvance();
|
|
1454
1454
|
i0.ɵɵconditional(ctx_r0.getRunTags(run_r45).length > 0 ? 8 : -1);
|
|
1455
1455
|
} }
|
|
1456
|
-
function
|
|
1457
|
-
i0.ɵɵelementStart(0, "div",
|
|
1458
|
-
i0.ɵɵrepeaterCreate(1,
|
|
1456
|
+
function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
1457
|
+
i0.ɵɵelementStart(0, "div", 282);
|
|
1458
|
+
i0.ɵɵrepeaterCreate(1, MJTestSuiteFormComponentExtended_Conditional_65_Conditional_12_For_2_Template, 9, 12, "div", 302, i0.ɵɵrepeaterTrackByIdentity);
|
|
1459
1459
|
i0.ɵɵelementEnd();
|
|
1460
1460
|
} if (rf & 2) {
|
|
1461
1461
|
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
1462
1462
|
i0.ɵɵadvance();
|
|
1463
1463
|
i0.ɵɵrepeater(ctx_r0.suiteRuns);
|
|
1464
1464
|
} }
|
|
1465
|
-
function
|
|
1465
|
+
function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
1466
1466
|
const _r47 = i0.ɵɵgetCurrentView();
|
|
1467
|
-
i0.ɵɵelementStart(0, "div",
|
|
1467
|
+
i0.ɵɵelementStart(0, "div", 283)(1, "div", 297)(2, "span", 298);
|
|
1468
1468
|
i0.ɵɵtext(3, "Selected:");
|
|
1469
1469
|
i0.ɵɵelementEnd();
|
|
1470
|
-
i0.ɵɵelementStart(4, "button",
|
|
1471
|
-
i0.ɵɵlistener("click", function
|
|
1470
|
+
i0.ɵɵelementStart(4, "button", 299);
|
|
1471
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_13_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r47); const ctx_r0 = i0.ɵɵnextContext(2); ctx_r0.compareRunB = null; return i0.ɵɵresetView(ctx_r0.compareResults = []); });
|
|
1472
1472
|
i0.ɵɵtext(5, "Clear");
|
|
1473
1473
|
i0.ɵɵelementEnd()();
|
|
1474
|
-
i0.ɵɵelementStart(6, "div",
|
|
1474
|
+
i0.ɵɵelementStart(6, "div", 300)(7, "span");
|
|
1475
1475
|
i0.ɵɵtext(8);
|
|
1476
1476
|
i0.ɵɵpipe(9, "date");
|
|
1477
1477
|
i0.ɵɵelementEnd();
|
|
1478
|
-
i0.ɵɵelementStart(10, "span",
|
|
1478
|
+
i0.ɵɵelementStart(10, "span", 301);
|
|
1479
1479
|
i0.ɵɵtext(11);
|
|
1480
1480
|
i0.ɵɵelementEnd()()();
|
|
1481
1481
|
} if (rf & 2) {
|
|
@@ -1485,8 +1485,8 @@ function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_13_Template
|
|
|
1485
1485
|
i0.ɵɵadvance(3);
|
|
1486
1486
|
i0.ɵɵtextInterpolate1("", ctx_r0.getPassRate(ctx_r0.compareRunB).toFixed(1), "%");
|
|
1487
1487
|
} }
|
|
1488
|
-
function
|
|
1489
|
-
i0.ɵɵelementStart(0, "span",
|
|
1488
|
+
function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_14_For_46_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
1489
|
+
i0.ɵɵelementStart(0, "span", 200);
|
|
1490
1490
|
i0.ɵɵtext(1);
|
|
1491
1491
|
i0.ɵɵelementEnd();
|
|
1492
1492
|
} if (rf & 2) {
|
|
@@ -1495,13 +1495,13 @@ function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_C
|
|
|
1495
1495
|
i0.ɵɵadvance();
|
|
1496
1496
|
i0.ɵɵtextInterpolate(result_r48.runA.status);
|
|
1497
1497
|
} }
|
|
1498
|
-
function
|
|
1499
|
-
i0.ɵɵelementStart(0, "span",
|
|
1498
|
+
function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_14_For_46_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
1499
|
+
i0.ɵɵelementStart(0, "span", 315);
|
|
1500
1500
|
i0.ɵɵtext(1, "N/A");
|
|
1501
1501
|
i0.ɵɵelementEnd();
|
|
1502
1502
|
} }
|
|
1503
|
-
function
|
|
1504
|
-
i0.ɵɵelementStart(0, "span",
|
|
1503
|
+
function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_14_For_46_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
1504
|
+
i0.ɵɵelementStart(0, "span", 200);
|
|
1505
1505
|
i0.ɵɵtext(1);
|
|
1506
1506
|
i0.ɵɵelementEnd();
|
|
1507
1507
|
} if (rf & 2) {
|
|
@@ -1510,13 +1510,13 @@ function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_C
|
|
|
1510
1510
|
i0.ɵɵadvance();
|
|
1511
1511
|
i0.ɵɵtextInterpolate(result_r48.runB.status);
|
|
1512
1512
|
} }
|
|
1513
|
-
function
|
|
1514
|
-
i0.ɵɵelementStart(0, "span",
|
|
1513
|
+
function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_14_For_46_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
1514
|
+
i0.ɵɵelementStart(0, "span", 315);
|
|
1515
1515
|
i0.ɵɵtext(1, "N/A");
|
|
1516
1516
|
i0.ɵɵelementEnd();
|
|
1517
1517
|
} }
|
|
1518
|
-
function
|
|
1519
|
-
i0.ɵɵelementStart(0, "span",
|
|
1518
|
+
function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_14_For_46_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
1519
|
+
i0.ɵɵelementStart(0, "span", 314);
|
|
1520
1520
|
i0.ɵɵtext(1);
|
|
1521
1521
|
i0.ɵɵelementEnd();
|
|
1522
1522
|
} if (rf & 2) {
|
|
@@ -1525,13 +1525,13 @@ function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_C
|
|
|
1525
1525
|
i0.ɵɵadvance();
|
|
1526
1526
|
i0.ɵɵtextInterpolate2(" ", result_r48.scoreDiff > 0 ? "+" : "", "", (result_r48.scoreDiff * 100).toFixed(1), "% ");
|
|
1527
1527
|
} }
|
|
1528
|
-
function
|
|
1529
|
-
i0.ɵɵelementStart(0, "span",
|
|
1528
|
+
function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_14_For_46_Conditional_11_Template(rf, ctx) { if (rf & 1) {
|
|
1529
|
+
i0.ɵɵelementStart(0, "span", 316);
|
|
1530
1530
|
i0.ɵɵtext(1, "-");
|
|
1531
1531
|
i0.ɵɵelementEnd();
|
|
1532
1532
|
} }
|
|
1533
|
-
function
|
|
1534
|
-
i0.ɵɵelementStart(0, "span",
|
|
1533
|
+
function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_14_For_46_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
1534
|
+
i0.ɵɵelementStart(0, "span", 314);
|
|
1535
1535
|
i0.ɵɵtext(1);
|
|
1536
1536
|
i0.ɵɵelementEnd();
|
|
1537
1537
|
} if (rf & 2) {
|
|
@@ -1540,52 +1540,52 @@ function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_C
|
|
|
1540
1540
|
i0.ɵɵadvance();
|
|
1541
1541
|
i0.ɵɵtextInterpolate2(" ", result_r48.durationDiff > 0 ? "+" : "", "", result_r48.durationDiff.toFixed(1), "s ");
|
|
1542
1542
|
} }
|
|
1543
|
-
function
|
|
1544
|
-
i0.ɵɵelementStart(0, "span",
|
|
1543
|
+
function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_14_For_46_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
1544
|
+
i0.ɵɵelementStart(0, "span", 316);
|
|
1545
1545
|
i0.ɵɵtext(1, "-");
|
|
1546
1546
|
i0.ɵɵelementEnd();
|
|
1547
1547
|
} }
|
|
1548
|
-
function
|
|
1549
|
-
i0.ɵɵelementStart(0, "span",
|
|
1550
|
-
i0.ɵɵelement(1, "i",
|
|
1548
|
+
function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_14_For_46_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
1549
|
+
i0.ɵɵelementStart(0, "span", 317);
|
|
1550
|
+
i0.ɵɵelement(1, "i", 320);
|
|
1551
1551
|
i0.ɵɵtext(2, " Fixed ");
|
|
1552
1552
|
i0.ɵɵelementEnd();
|
|
1553
1553
|
} }
|
|
1554
|
-
function
|
|
1555
|
-
i0.ɵɵelementStart(0, "span",
|
|
1556
|
-
i0.ɵɵelement(1, "i",
|
|
1554
|
+
function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_14_For_46_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
1555
|
+
i0.ɵɵelementStart(0, "span", 318);
|
|
1556
|
+
i0.ɵɵelement(1, "i", 321);
|
|
1557
1557
|
i0.ɵɵtext(2, " Broke ");
|
|
1558
1558
|
i0.ɵɵelementEnd();
|
|
1559
1559
|
} }
|
|
1560
|
-
function
|
|
1561
|
-
i0.ɵɵelementStart(0, "span",
|
|
1562
|
-
i0.ɵɵelement(1, "i",
|
|
1560
|
+
function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_14_For_46_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
1561
|
+
i0.ɵɵelementStart(0, "span", 319);
|
|
1562
|
+
i0.ɵɵelement(1, "i", 257);
|
|
1563
1563
|
i0.ɵɵelementEnd();
|
|
1564
1564
|
} }
|
|
1565
|
-
function
|
|
1566
|
-
i0.ɵɵelementStart(0, "tr",
|
|
1565
|
+
function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_14_For_46_Template(rf, ctx) { if (rf & 1) {
|
|
1566
|
+
i0.ɵɵelementStart(0, "tr", 314)(1, "td", 240);
|
|
1567
1567
|
i0.ɵɵtext(2);
|
|
1568
1568
|
i0.ɵɵelementEnd();
|
|
1569
1569
|
i0.ɵɵelementStart(3, "td");
|
|
1570
|
-
i0.ɵɵconditionalCreate(4,
|
|
1571
|
-
i0.ɵɵconditionalCreate(5,
|
|
1570
|
+
i0.ɵɵconditionalCreate(4, MJTestSuiteFormComponentExtended_Conditional_65_Conditional_14_For_46_Conditional_4_Template, 2, 2, "span", 200);
|
|
1571
|
+
i0.ɵɵconditionalCreate(5, MJTestSuiteFormComponentExtended_Conditional_65_Conditional_14_For_46_Conditional_5_Template, 2, 0, "span", 315);
|
|
1572
1572
|
i0.ɵɵelementEnd();
|
|
1573
1573
|
i0.ɵɵelementStart(6, "td");
|
|
1574
|
-
i0.ɵɵconditionalCreate(7,
|
|
1575
|
-
i0.ɵɵconditionalCreate(8,
|
|
1574
|
+
i0.ɵɵconditionalCreate(7, MJTestSuiteFormComponentExtended_Conditional_65_Conditional_14_For_46_Conditional_7_Template, 2, 2, "span", 200);
|
|
1575
|
+
i0.ɵɵconditionalCreate(8, MJTestSuiteFormComponentExtended_Conditional_65_Conditional_14_For_46_Conditional_8_Template, 2, 0, "span", 315);
|
|
1576
1576
|
i0.ɵɵelementEnd();
|
|
1577
1577
|
i0.ɵɵelementStart(9, "td");
|
|
1578
|
-
i0.ɵɵconditionalCreate(10,
|
|
1579
|
-
i0.ɵɵconditionalCreate(11,
|
|
1578
|
+
i0.ɵɵconditionalCreate(10, MJTestSuiteFormComponentExtended_Conditional_65_Conditional_14_For_46_Conditional_10_Template, 2, 6, "span", 314);
|
|
1579
|
+
i0.ɵɵconditionalCreate(11, MJTestSuiteFormComponentExtended_Conditional_65_Conditional_14_For_46_Conditional_11_Template, 2, 0, "span", 316);
|
|
1580
1580
|
i0.ɵɵelementEnd();
|
|
1581
1581
|
i0.ɵɵelementStart(12, "td");
|
|
1582
|
-
i0.ɵɵconditionalCreate(13,
|
|
1583
|
-
i0.ɵɵconditionalCreate(14,
|
|
1582
|
+
i0.ɵɵconditionalCreate(13, MJTestSuiteFormComponentExtended_Conditional_65_Conditional_14_For_46_Conditional_13_Template, 2, 6, "span", 314);
|
|
1583
|
+
i0.ɵɵconditionalCreate(14, MJTestSuiteFormComponentExtended_Conditional_65_Conditional_14_For_46_Conditional_14_Template, 2, 0, "span", 316);
|
|
1584
1584
|
i0.ɵɵelementEnd();
|
|
1585
1585
|
i0.ɵɵelementStart(15, "td");
|
|
1586
|
-
i0.ɵɵconditionalCreate(16,
|
|
1587
|
-
i0.ɵɵconditionalCreate(17,
|
|
1588
|
-
i0.ɵɵconditionalCreate(18,
|
|
1586
|
+
i0.ɵɵconditionalCreate(16, MJTestSuiteFormComponentExtended_Conditional_65_Conditional_14_For_46_Conditional_16_Template, 3, 0, "span", 317);
|
|
1587
|
+
i0.ɵɵconditionalCreate(17, MJTestSuiteFormComponentExtended_Conditional_65_Conditional_14_For_46_Conditional_17_Template, 3, 0, "span", 318);
|
|
1588
|
+
i0.ɵɵconditionalCreate(18, MJTestSuiteFormComponentExtended_Conditional_65_Conditional_14_For_46_Conditional_18_Template, 2, 0, "span", 319);
|
|
1589
1589
|
i0.ɵɵelementEnd()();
|
|
1590
1590
|
} if (rf & 2) {
|
|
1591
1591
|
const result_r48 = ctx.$implicit;
|
|
@@ -1615,38 +1615,38 @@ function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_For_46_T
|
|
|
1615
1615
|
i0.ɵɵadvance();
|
|
1616
1616
|
i0.ɵɵconditional(!result_r48.statusChanged ? 18 : -1);
|
|
1617
1617
|
} }
|
|
1618
|
-
function
|
|
1619
|
-
i0.ɵɵelementStart(0, "div",
|
|
1618
|
+
function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
1619
|
+
i0.ɵɵelementStart(0, "div", 286)(1, "div", 303)(2, "div", 304)(3, "div", 305);
|
|
1620
1620
|
i0.ɵɵtext(4, "Pass Rate Change");
|
|
1621
1621
|
i0.ɵɵelementEnd();
|
|
1622
|
-
i0.ɵɵelementStart(5, "div",
|
|
1622
|
+
i0.ɵɵelementStart(5, "div", 306);
|
|
1623
1623
|
i0.ɵɵelement(6, "i", 19);
|
|
1624
1624
|
i0.ɵɵtext(7);
|
|
1625
1625
|
i0.ɵɵelementEnd()();
|
|
1626
|
-
i0.ɵɵelementStart(8, "div",
|
|
1626
|
+
i0.ɵɵelementStart(8, "div", 304)(9, "div", 305);
|
|
1627
1627
|
i0.ɵɵtext(10, "Duration Change");
|
|
1628
1628
|
i0.ɵɵelementEnd();
|
|
1629
|
-
i0.ɵɵelementStart(11, "div",
|
|
1629
|
+
i0.ɵɵelementStart(11, "div", 306);
|
|
1630
1630
|
i0.ɵɵelement(12, "i", 19);
|
|
1631
1631
|
i0.ɵɵtext(13);
|
|
1632
1632
|
i0.ɵɵelementEnd()();
|
|
1633
|
-
i0.ɵɵelementStart(14, "div",
|
|
1633
|
+
i0.ɵɵelementStart(14, "div", 307)(15, "div", 305);
|
|
1634
1634
|
i0.ɵɵtext(16, "Improved");
|
|
1635
1635
|
i0.ɵɵelementEnd();
|
|
1636
|
-
i0.ɵɵelementStart(17, "div",
|
|
1636
|
+
i0.ɵɵelementStart(17, "div", 308);
|
|
1637
1637
|
i0.ɵɵtext(18);
|
|
1638
1638
|
i0.ɵɵelementEnd()();
|
|
1639
|
-
i0.ɵɵelementStart(19, "div",
|
|
1639
|
+
i0.ɵɵelementStart(19, "div", 309)(20, "div", 305);
|
|
1640
1640
|
i0.ɵɵtext(21, "Regressed");
|
|
1641
1641
|
i0.ɵɵelementEnd();
|
|
1642
|
-
i0.ɵɵelementStart(22, "div",
|
|
1642
|
+
i0.ɵɵelementStart(22, "div", 308);
|
|
1643
1643
|
i0.ɵɵtext(23);
|
|
1644
1644
|
i0.ɵɵelementEnd()()();
|
|
1645
|
-
i0.ɵɵelementStart(24, "div",
|
|
1646
|
-
i0.ɵɵelement(26, "i",
|
|
1645
|
+
i0.ɵɵelementStart(24, "div", 310)(25, "h3");
|
|
1646
|
+
i0.ɵɵelement(26, "i", 311);
|
|
1647
1647
|
i0.ɵɵtext(27, " Test-by-Test Comparison");
|
|
1648
1648
|
i0.ɵɵelementEnd();
|
|
1649
|
-
i0.ɵɵelementStart(28, "div",
|
|
1649
|
+
i0.ɵɵelementStart(28, "div", 312)(29, "table", 313)(30, "thead")(31, "tr")(32, "th");
|
|
1650
1650
|
i0.ɵɵtext(33, "Test");
|
|
1651
1651
|
i0.ɵɵelementEnd();
|
|
1652
1652
|
i0.ɵɵelementStart(34, "th");
|
|
@@ -1665,7 +1665,7 @@ function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_Template
|
|
|
1665
1665
|
i0.ɵɵtext(43, "Change");
|
|
1666
1666
|
i0.ɵɵelementEnd()()();
|
|
1667
1667
|
i0.ɵɵelementStart(44, "tbody");
|
|
1668
|
-
i0.ɵɵrepeaterCreate(45,
|
|
1668
|
+
i0.ɵɵrepeaterCreate(45, MJTestSuiteFormComponentExtended_Conditional_65_Conditional_14_For_46_Template, 19, 16, "tr", 314, i0.ɵɵrepeaterTrackByIdentity);
|
|
1669
1669
|
i0.ɵɵelementEnd()()()()();
|
|
1670
1670
|
} if (rf & 2) {
|
|
1671
1671
|
let tmp_4_0;
|
|
@@ -1689,40 +1689,40 @@ function MJTestSuiteFormComponentExtended_Conditional_64_Conditional_14_Template
|
|
|
1689
1689
|
i0.ɵɵadvance(22);
|
|
1690
1690
|
i0.ɵɵrepeater(ctx_r0.compareResults);
|
|
1691
1691
|
} }
|
|
1692
|
-
function
|
|
1693
|
-
i0.ɵɵelementStart(0, "div",
|
|
1694
|
-
i0.ɵɵelement(1, "mj-loading",
|
|
1692
|
+
function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_15_Template(rf, ctx) { if (rf & 1) {
|
|
1693
|
+
i0.ɵɵelementStart(0, "div", 102);
|
|
1694
|
+
i0.ɵɵelement(1, "mj-loading", 322);
|
|
1695
1695
|
i0.ɵɵelementEnd();
|
|
1696
1696
|
} }
|
|
1697
|
-
function
|
|
1698
|
-
i0.ɵɵelement(0, "mj-empty-state",
|
|
1697
|
+
function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
1698
|
+
i0.ɵɵelement(0, "mj-empty-state", 287);
|
|
1699
1699
|
} }
|
|
1700
|
-
function
|
|
1700
|
+
function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
1701
1701
|
const _r49 = i0.ɵɵgetCurrentView();
|
|
1702
|
-
i0.ɵɵelementStart(0, "mj-empty-state",
|
|
1703
|
-
i0.ɵɵlistener("Action", function
|
|
1702
|
+
i0.ɵɵelementStart(0, "mj-empty-state", 323);
|
|
1703
|
+
i0.ɵɵlistener("Action", function MJTestSuiteFormComponentExtended_Conditional_65_Conditional_17_Template_mj_empty_state_Action_0_listener() { i0.ɵɵrestoreView(_r49); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.runSuite()); });
|
|
1704
1704
|
i0.ɵɵelementEnd();
|
|
1705
1705
|
} }
|
|
1706
|
-
function
|
|
1707
|
-
i0.ɵɵelementStart(0, "div",
|
|
1706
|
+
function MJTestSuiteFormComponentExtended_Conditional_65_Template(rf, ctx) { if (rf & 1) {
|
|
1707
|
+
i0.ɵɵelementStart(0, "div", 44)(1, "div", 280)(2, "div", 281)(3, "h4");
|
|
1708
1708
|
i0.ɵɵtext(4, "Run A (Baseline)");
|
|
1709
1709
|
i0.ɵɵelementEnd();
|
|
1710
|
-
i0.ɵɵconditionalCreate(5,
|
|
1711
|
-
i0.ɵɵconditionalCreate(6,
|
|
1710
|
+
i0.ɵɵconditionalCreate(5, MJTestSuiteFormComponentExtended_Conditional_65_Conditional_5_Template, 3, 0, "div", 282);
|
|
1711
|
+
i0.ɵɵconditionalCreate(6, MJTestSuiteFormComponentExtended_Conditional_65_Conditional_6_Template, 12, 5, "div", 283);
|
|
1712
1712
|
i0.ɵɵelementEnd();
|
|
1713
|
-
i0.ɵɵelementStart(7, "div",
|
|
1714
|
-
i0.ɵɵelement(8, "i",
|
|
1713
|
+
i0.ɵɵelementStart(7, "div", 284);
|
|
1714
|
+
i0.ɵɵelement(8, "i", 285);
|
|
1715
1715
|
i0.ɵɵelementEnd();
|
|
1716
|
-
i0.ɵɵelementStart(9, "div",
|
|
1716
|
+
i0.ɵɵelementStart(9, "div", 281)(10, "h4");
|
|
1717
1717
|
i0.ɵɵtext(11, "Run B (Compare)");
|
|
1718
1718
|
i0.ɵɵelementEnd();
|
|
1719
|
-
i0.ɵɵconditionalCreate(12,
|
|
1720
|
-
i0.ɵɵconditionalCreate(13,
|
|
1719
|
+
i0.ɵɵconditionalCreate(12, MJTestSuiteFormComponentExtended_Conditional_65_Conditional_12_Template, 3, 0, "div", 282);
|
|
1720
|
+
i0.ɵɵconditionalCreate(13, MJTestSuiteFormComponentExtended_Conditional_65_Conditional_13_Template, 12, 5, "div", 283);
|
|
1721
1721
|
i0.ɵɵelementEnd()();
|
|
1722
|
-
i0.ɵɵconditionalCreate(14,
|
|
1723
|
-
i0.ɵɵconditionalCreate(15,
|
|
1724
|
-
i0.ɵɵconditionalCreate(16,
|
|
1725
|
-
i0.ɵɵconditionalCreate(17,
|
|
1722
|
+
i0.ɵɵconditionalCreate(14, MJTestSuiteFormComponentExtended_Conditional_65_Conditional_14_Template, 47, 23, "div", 286);
|
|
1723
|
+
i0.ɵɵconditionalCreate(15, MJTestSuiteFormComponentExtended_Conditional_65_Conditional_15_Template, 2, 0, "div", 102);
|
|
1724
|
+
i0.ɵɵconditionalCreate(16, MJTestSuiteFormComponentExtended_Conditional_65_Conditional_16_Template, 1, 0, "mj-empty-state", 287);
|
|
1725
|
+
i0.ɵɵconditionalCreate(17, MJTestSuiteFormComponentExtended_Conditional_65_Conditional_17_Template, 1, 0, "mj-empty-state", 288);
|
|
1726
1726
|
i0.ɵɵelementEnd();
|
|
1727
1727
|
} if (rf & 2) {
|
|
1728
1728
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
@@ -1743,46 +1743,46 @@ function MJTestSuiteFormComponentExtended_Conditional_64_Template(rf, ctx) { if
|
|
|
1743
1743
|
i0.ɵɵadvance();
|
|
1744
1744
|
i0.ɵɵconditional(ctx_r0.runsLoaded && ctx_r0.suiteRuns.length < 2 ? 17 : -1);
|
|
1745
1745
|
} }
|
|
1746
|
-
function
|
|
1746
|
+
function MJTestSuiteFormComponentExtended_Conditional_68_Template(rf, ctx) { if (rf & 1) {
|
|
1747
1747
|
const _r50 = i0.ɵɵgetCurrentView();
|
|
1748
|
-
i0.ɵɵelementStart(0, "div",
|
|
1749
|
-
i0.ɵɵelement(2, "i",
|
|
1748
|
+
i0.ɵɵelementStart(0, "div", 47)(1, "div", 324);
|
|
1749
|
+
i0.ɵɵelement(2, "i", 46);
|
|
1750
1750
|
i0.ɵɵtext(3, " Shortcuts ");
|
|
1751
|
-
i0.ɵɵelementStart(4, "button",
|
|
1752
|
-
i0.ɵɵlistener("click", function
|
|
1753
|
-
i0.ɵɵelement(5, "i",
|
|
1751
|
+
i0.ɵɵelementStart(4, "button", 325);
|
|
1752
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_68_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r50); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.toggleShortcuts()); });
|
|
1753
|
+
i0.ɵɵelement(5, "i", 94);
|
|
1754
1754
|
i0.ɵɵelementEnd()();
|
|
1755
|
-
i0.ɵɵelementStart(6, "div",
|
|
1755
|
+
i0.ɵɵelementStart(6, "div", 326)(7, "div", 327)(8, "span");
|
|
1756
1756
|
i0.ɵɵtext(9, "Save changes");
|
|
1757
1757
|
i0.ɵɵelementEnd();
|
|
1758
|
-
i0.ɵɵelementStart(10, "span",
|
|
1758
|
+
i0.ɵɵelementStart(10, "span", 328)(11, "kbd");
|
|
1759
1759
|
i0.ɵɵtext(12, "Cmd");
|
|
1760
1760
|
i0.ɵɵelementEnd();
|
|
1761
1761
|
i0.ɵɵelementStart(13, "kbd");
|
|
1762
1762
|
i0.ɵɵtext(14, "S");
|
|
1763
1763
|
i0.ɵɵelementEnd()()();
|
|
1764
|
-
i0.ɵɵelementStart(15, "div",
|
|
1764
|
+
i0.ɵɵelementStart(15, "div", 327)(16, "span");
|
|
1765
1765
|
i0.ɵɵtext(17, "Refresh");
|
|
1766
1766
|
i0.ɵɵelementEnd();
|
|
1767
|
-
i0.ɵɵelementStart(18, "span",
|
|
1767
|
+
i0.ɵɵelementStart(18, "span", 328)(19, "kbd");
|
|
1768
1768
|
i0.ɵɵtext(20, "Cmd");
|
|
1769
1769
|
i0.ɵɵelementEnd();
|
|
1770
1770
|
i0.ɵɵelementStart(21, "kbd");
|
|
1771
1771
|
i0.ɵɵtext(22, "R");
|
|
1772
1772
|
i0.ɵɵelementEnd()()();
|
|
1773
|
-
i0.ɵɵelementStart(23, "div",
|
|
1773
|
+
i0.ɵɵelementStart(23, "div", 327)(24, "span");
|
|
1774
1774
|
i0.ɵɵtext(25, "Run Suite");
|
|
1775
1775
|
i0.ɵɵelementEnd();
|
|
1776
|
-
i0.ɵɵelementStart(26, "span",
|
|
1776
|
+
i0.ɵɵelementStart(26, "span", 328)(27, "kbd");
|
|
1777
1777
|
i0.ɵɵtext(28, "Cmd");
|
|
1778
1778
|
i0.ɵɵelementEnd();
|
|
1779
1779
|
i0.ɵɵelementStart(29, "kbd");
|
|
1780
1780
|
i0.ɵɵtext(30, "Enter");
|
|
1781
1781
|
i0.ɵɵelementEnd()()();
|
|
1782
|
-
i0.ɵɵelementStart(31, "div",
|
|
1782
|
+
i0.ɵɵelementStart(31, "div", 327)(32, "span");
|
|
1783
1783
|
i0.ɵɵtext(33, "Switch Tabs");
|
|
1784
1784
|
i0.ɵɵelementEnd();
|
|
1785
|
-
i0.ɵɵelementStart(34, "span",
|
|
1785
|
+
i0.ɵɵelementStart(34, "span", 328)(35, "kbd");
|
|
1786
1786
|
i0.ɵɵtext(36, "1");
|
|
1787
1787
|
i0.ɵɵelementEnd();
|
|
1788
1788
|
i0.ɵɵtext(37, "-");
|
|
@@ -1790,12 +1790,12 @@ function MJTestSuiteFormComponentExtended_Conditional_67_Template(rf, ctx) { if
|
|
|
1790
1790
|
i0.ɵɵtext(39, "5");
|
|
1791
1791
|
i0.ɵɵelementEnd()()()()();
|
|
1792
1792
|
} }
|
|
1793
|
-
function
|
|
1793
|
+
function MJTestSuiteFormComponentExtended_Conditional_69_Template(rf, ctx) { if (rf & 1) {
|
|
1794
1794
|
const _r51 = i0.ɵɵgetCurrentView();
|
|
1795
|
-
i0.ɵɵelementStart(0, "mj-slide-panel",
|
|
1796
|
-
i0.ɵɵlistener("Closed", function
|
|
1797
|
-
i0.ɵɵelementStart(1, "app-test-run-dialog",
|
|
1798
|
-
i0.ɵɵlistener("PanelClose", function
|
|
1795
|
+
i0.ɵɵelementStart(0, "mj-slide-panel", 329);
|
|
1796
|
+
i0.ɵɵlistener("Closed", function MJTestSuiteFormComponentExtended_Conditional_69_Template_mj_slide_panel_Closed_0_listener() { i0.ɵɵrestoreView(_r51); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.OnPanelClosed()); });
|
|
1797
|
+
i0.ɵɵelementStart(1, "app-test-run-dialog", 330);
|
|
1798
|
+
i0.ɵɵlistener("PanelClose", function MJTestSuiteFormComponentExtended_Conditional_69_Template_app_test_run_dialog_PanelClose_1_listener() { i0.ɵɵrestoreView(_r51); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.OnPanelClosed()); });
|
|
1799
1799
|
i0.ɵɵelementEnd()();
|
|
1800
1800
|
} if (rf & 2) {
|
|
1801
1801
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
@@ -1803,14 +1803,14 @@ function MJTestSuiteFormComponentExtended_Conditional_68_Template(rf, ctx) { if
|
|
|
1803
1803
|
i0.ɵɵadvance();
|
|
1804
1804
|
i0.ɵɵproperty("PanelMode", true)("selectedTestId", (ctx_r0.testingDialogService.PanelOptions == null ? null : ctx_r0.testingDialogService.PanelOptions.testId) ?? null)("selectedSuiteId", (ctx_r0.testingDialogService.PanelOptions == null ? null : ctx_r0.testingDialogService.PanelOptions.suiteId) ?? null)("runMode", (ctx_r0.testingDialogService.PanelOptions == null ? null : ctx_r0.testingDialogService.PanelOptions.mode) ?? "suite");
|
|
1805
1805
|
} }
|
|
1806
|
-
function
|
|
1806
|
+
function MJTestSuiteFormComponentExtended_Conditional_70_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
1807
1807
|
const _r53 = i0.ɵɵgetCurrentView();
|
|
1808
|
-
i0.ɵɵelementStart(0, "button",
|
|
1809
|
-
i0.ɵɵlistener("click", function
|
|
1810
|
-
i0.ɵɵelement(1, "i",
|
|
1808
|
+
i0.ɵɵelementStart(0, "button", 351);
|
|
1809
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_70_Conditional_12_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r53); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.addTestsSearch = ""); });
|
|
1810
|
+
i0.ɵɵelement(1, "i", 94);
|
|
1811
1811
|
i0.ɵɵelementEnd();
|
|
1812
1812
|
} }
|
|
1813
|
-
function
|
|
1813
|
+
function MJTestSuiteFormComponentExtended_Conditional_70_Conditional_15_Template(rf, ctx) { if (rf & 1) {
|
|
1814
1814
|
i0.ɵɵelementStart(0, "strong");
|
|
1815
1815
|
i0.ɵɵtext(1);
|
|
1816
1816
|
i0.ɵɵelementEnd();
|
|
@@ -1820,37 +1820,37 @@ function MJTestSuiteFormComponentExtended_Conditional_69_Conditional_15_Template
|
|
|
1820
1820
|
i0.ɵɵadvance();
|
|
1821
1821
|
i0.ɵɵtextInterpolate(ctx_r0.selectedTestIdsToAdd.size);
|
|
1822
1822
|
} }
|
|
1823
|
-
function
|
|
1823
|
+
function MJTestSuiteFormComponentExtended_Conditional_70_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
1824
1824
|
i0.ɵɵtext(0);
|
|
1825
1825
|
} if (rf & 2) {
|
|
1826
1826
|
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
1827
1827
|
i0.ɵɵtextInterpolate2(" ", ctx_r0.filteredAvailableTests.length, " test", ctx_r0.filteredAvailableTests.length === 1 ? "" : "s", " available ");
|
|
1828
1828
|
} }
|
|
1829
|
-
function
|
|
1830
|
-
i0.ɵɵelementStart(0, "div",
|
|
1831
|
-
i0.ɵɵelement(1, "mj-loading",
|
|
1829
|
+
function MJTestSuiteFormComponentExtended_Conditional_70_Conditional_23_Template(rf, ctx) { if (rf & 1) {
|
|
1830
|
+
i0.ɵɵelementStart(0, "div", 346);
|
|
1831
|
+
i0.ɵɵelement(1, "mj-loading", 352);
|
|
1832
1832
|
i0.ɵɵelementEnd();
|
|
1833
1833
|
} }
|
|
1834
|
-
function
|
|
1835
|
-
i0.ɵɵelement(0, "mj-empty-state", 352);
|
|
1836
|
-
} }
|
|
1837
|
-
function MJTestSuiteFormComponentExtended_Conditional_69_Conditional_24_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
1834
|
+
function MJTestSuiteFormComponentExtended_Conditional_70_Conditional_24_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
1838
1835
|
i0.ɵɵelement(0, "mj-empty-state", 353);
|
|
1836
|
+
} }
|
|
1837
|
+
function MJTestSuiteFormComponentExtended_Conditional_70_Conditional_24_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
1838
|
+
i0.ɵɵelement(0, "mj-empty-state", 354);
|
|
1839
1839
|
} if (rf & 2) {
|
|
1840
1840
|
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
1841
1841
|
i0.ɵɵproperty("Message", ctx_r0.AddTestsNoMatchMessage);
|
|
1842
1842
|
} }
|
|
1843
|
-
function
|
|
1844
|
-
i0.ɵɵconditionalCreate(0,
|
|
1843
|
+
function MJTestSuiteFormComponentExtended_Conditional_70_Conditional_24_Template(rf, ctx) { if (rf & 1) {
|
|
1844
|
+
i0.ɵɵconditionalCreate(0, MJTestSuiteFormComponentExtended_Conditional_70_Conditional_24_Conditional_0_Template, 1, 0, "mj-empty-state", 353)(1, MJTestSuiteFormComponentExtended_Conditional_70_Conditional_24_Conditional_1_Template, 1, 1, "mj-empty-state", 354);
|
|
1845
1845
|
} if (rf & 2) {
|
|
1846
1846
|
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
1847
1847
|
i0.ɵɵconditional(ctx_r0.availableTests.length === 0 ? 0 : 1);
|
|
1848
1848
|
} }
|
|
1849
|
-
function
|
|
1850
|
-
i0.ɵɵelement(0, "i",
|
|
1849
|
+
function MJTestSuiteFormComponentExtended_Conditional_70_Conditional_25_For_2_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
1850
|
+
i0.ɵɵelement(0, "i", 180);
|
|
1851
1851
|
} }
|
|
1852
|
-
function
|
|
1853
|
-
i0.ɵɵelementStart(0, "div",
|
|
1852
|
+
function MJTestSuiteFormComponentExtended_Conditional_70_Conditional_25_For_2_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
1853
|
+
i0.ɵɵelementStart(0, "div", 360);
|
|
1854
1854
|
i0.ɵɵtext(1);
|
|
1855
1855
|
i0.ɵɵelementEnd();
|
|
1856
1856
|
} if (rf & 2) {
|
|
@@ -1858,8 +1858,8 @@ function MJTestSuiteFormComponentExtended_Conditional_69_Conditional_25_For_2_Co
|
|
|
1858
1858
|
i0.ɵɵadvance();
|
|
1859
1859
|
i0.ɵɵtextInterpolate(t_r55.Description);
|
|
1860
1860
|
} }
|
|
1861
|
-
function
|
|
1862
|
-
i0.ɵɵelementStart(0, "span",
|
|
1861
|
+
function MJTestSuiteFormComponentExtended_Conditional_70_Conditional_25_For_2_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
1862
|
+
i0.ɵɵelementStart(0, "span", 362);
|
|
1863
1863
|
i0.ɵɵtext(1);
|
|
1864
1864
|
i0.ɵɵelementEnd();
|
|
1865
1865
|
} if (rf & 2) {
|
|
@@ -1867,21 +1867,21 @@ function MJTestSuiteFormComponentExtended_Conditional_69_Conditional_25_For_2_Co
|
|
|
1867
1867
|
i0.ɵɵadvance();
|
|
1868
1868
|
i0.ɵɵtextInterpolate(t_r55.Type);
|
|
1869
1869
|
} }
|
|
1870
|
-
function
|
|
1870
|
+
function MJTestSuiteFormComponentExtended_Conditional_70_Conditional_25_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
1871
1871
|
const _r54 = i0.ɵɵgetCurrentView();
|
|
1872
|
-
i0.ɵɵelementStart(0, "li",
|
|
1873
|
-
i0.ɵɵlistener("click", function
|
|
1874
|
-
i0.ɵɵelementStart(1, "span",
|
|
1875
|
-
i0.ɵɵconditionalCreate(2,
|
|
1872
|
+
i0.ɵɵelementStart(0, "li", 356);
|
|
1873
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_70_Conditional_25_For_2_Template_li_click_0_listener() { const t_r55 = i0.ɵɵrestoreView(_r54).$implicit; const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.toggleAddSelection(t_r55.ID)); });
|
|
1874
|
+
i0.ɵɵelementStart(1, "span", 357);
|
|
1875
|
+
i0.ɵɵconditionalCreate(2, MJTestSuiteFormComponentExtended_Conditional_70_Conditional_25_For_2_Conditional_2_Template, 1, 0, "i", 180);
|
|
1876
1876
|
i0.ɵɵelementEnd();
|
|
1877
|
-
i0.ɵɵelementStart(3, "div",
|
|
1877
|
+
i0.ɵɵelementStart(3, "div", 358)(4, "div", 359);
|
|
1878
1878
|
i0.ɵɵtext(5);
|
|
1879
1879
|
i0.ɵɵelementEnd();
|
|
1880
|
-
i0.ɵɵconditionalCreate(6,
|
|
1880
|
+
i0.ɵɵconditionalCreate(6, MJTestSuiteFormComponentExtended_Conditional_70_Conditional_25_For_2_Conditional_6_Template, 2, 1, "div", 360);
|
|
1881
1881
|
i0.ɵɵelementEnd();
|
|
1882
|
-
i0.ɵɵelementStart(7, "div",
|
|
1883
|
-
i0.ɵɵconditionalCreate(8,
|
|
1884
|
-
i0.ɵɵelementStart(9, "span",
|
|
1882
|
+
i0.ɵɵelementStart(7, "div", 361);
|
|
1883
|
+
i0.ɵɵconditionalCreate(8, MJTestSuiteFormComponentExtended_Conditional_70_Conditional_25_For_2_Conditional_8_Template, 2, 1, "span", 362);
|
|
1884
|
+
i0.ɵɵelementStart(9, "span", 363);
|
|
1885
1885
|
i0.ɵɵtext(10);
|
|
1886
1886
|
i0.ɵɵelementEnd()()();
|
|
1887
1887
|
} if (rf & 2) {
|
|
@@ -1902,81 +1902,81 @@ function MJTestSuiteFormComponentExtended_Conditional_69_Conditional_25_For_2_Te
|
|
|
1902
1902
|
i0.ɵɵadvance();
|
|
1903
1903
|
i0.ɵɵtextInterpolate(t_r55.Status);
|
|
1904
1904
|
} }
|
|
1905
|
-
function
|
|
1906
|
-
i0.ɵɵelementStart(0, "ul",
|
|
1907
|
-
i0.ɵɵrepeaterCreate(1,
|
|
1905
|
+
function MJTestSuiteFormComponentExtended_Conditional_70_Conditional_25_Template(rf, ctx) { if (rf & 1) {
|
|
1906
|
+
i0.ɵɵelementStart(0, "ul", 347);
|
|
1907
|
+
i0.ɵɵrepeaterCreate(1, MJTestSuiteFormComponentExtended_Conditional_70_Conditional_25_For_2_Template, 11, 9, "li", 355, _forTrack1);
|
|
1908
1908
|
i0.ɵɵelementEnd();
|
|
1909
1909
|
} if (rf & 2) {
|
|
1910
1910
|
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
1911
1911
|
i0.ɵɵadvance();
|
|
1912
1912
|
i0.ɵɵrepeater(ctx_r0.filteredAvailableTests);
|
|
1913
1913
|
} }
|
|
1914
|
-
function
|
|
1915
|
-
i0.ɵɵelement(0, "i",
|
|
1914
|
+
function MJTestSuiteFormComponentExtended_Conditional_70_Conditional_28_Template(rf, ctx) { if (rf & 1) {
|
|
1915
|
+
i0.ɵɵelement(0, "i", 126);
|
|
1916
1916
|
i0.ɵɵtext(1, " Adding\u2026 ");
|
|
1917
1917
|
} }
|
|
1918
|
-
function
|
|
1918
|
+
function MJTestSuiteFormComponentExtended_Conditional_70_Conditional_29_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
1919
1919
|
i0.ɵɵtext(0, " Add tests ");
|
|
1920
1920
|
} }
|
|
1921
|
-
function
|
|
1921
|
+
function MJTestSuiteFormComponentExtended_Conditional_70_Conditional_29_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
1922
1922
|
i0.ɵɵtext(0, " Add 1 test ");
|
|
1923
1923
|
} }
|
|
1924
|
-
function
|
|
1924
|
+
function MJTestSuiteFormComponentExtended_Conditional_70_Conditional_29_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
1925
1925
|
i0.ɵɵtext(0);
|
|
1926
1926
|
} if (rf & 2) {
|
|
1927
1927
|
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
1928
1928
|
i0.ɵɵtextInterpolate1(" Add ", ctx_r0.selectedTestIdsToAdd.size, " tests ");
|
|
1929
1929
|
} }
|
|
1930
|
-
function
|
|
1931
|
-
i0.ɵɵelement(0, "i",
|
|
1932
|
-
i0.ɵɵconditionalCreate(1,
|
|
1930
|
+
function MJTestSuiteFormComponentExtended_Conditional_70_Conditional_29_Template(rf, ctx) { if (rf & 1) {
|
|
1931
|
+
i0.ɵɵelement(0, "i", 180);
|
|
1932
|
+
i0.ɵɵconditionalCreate(1, MJTestSuiteFormComponentExtended_Conditional_70_Conditional_29_Conditional_1_Template, 1, 0)(2, MJTestSuiteFormComponentExtended_Conditional_70_Conditional_29_Conditional_2_Template, 1, 0)(3, MJTestSuiteFormComponentExtended_Conditional_70_Conditional_29_Conditional_3_Template, 1, 1);
|
|
1933
1933
|
} if (rf & 2) {
|
|
1934
1934
|
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
1935
1935
|
i0.ɵɵadvance();
|
|
1936
1936
|
i0.ɵɵconditional(ctx_r0.selectedTestIdsToAdd.size === 0 ? 1 : ctx_r0.selectedTestIdsToAdd.size === 1 ? 2 : 3);
|
|
1937
1937
|
} }
|
|
1938
|
-
function
|
|
1938
|
+
function MJTestSuiteFormComponentExtended_Conditional_70_Template(rf, ctx) { if (rf & 1) {
|
|
1939
1939
|
const _r52 = i0.ɵɵgetCurrentView();
|
|
1940
|
-
i0.ɵɵelementStart(0, "div",
|
|
1941
|
-
i0.ɵɵlistener("click", function
|
|
1940
|
+
i0.ɵɵelementStart(0, "div", 331);
|
|
1941
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_70_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r52); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.closeAddTestsDialog()); });
|
|
1942
1942
|
i0.ɵɵelementEnd();
|
|
1943
|
-
i0.ɵɵelementStart(1, "div",
|
|
1944
|
-
i0.ɵɵlistener("click", function
|
|
1945
|
-
i0.ɵɵelementStart(2, "div",
|
|
1946
|
-
i0.ɵɵelement(4, "i",
|
|
1943
|
+
i0.ɵɵelementStart(1, "div", 332);
|
|
1944
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_70_Template_div_click_1_listener($event) { return $event.stopPropagation(); });
|
|
1945
|
+
i0.ɵɵelementStart(2, "div", 333)(3, "h2", 334);
|
|
1946
|
+
i0.ɵɵelement(4, "i", 335);
|
|
1947
1947
|
i0.ɵɵtext(5, " Add tests to suite ");
|
|
1948
1948
|
i0.ɵɵelementEnd();
|
|
1949
|
-
i0.ɵɵelementStart(6, "button",
|
|
1950
|
-
i0.ɵɵlistener("click", function
|
|
1951
|
-
i0.ɵɵelement(7, "i",
|
|
1949
|
+
i0.ɵɵelementStart(6, "button", 336);
|
|
1950
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_70_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r52); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.closeAddTestsDialog()); });
|
|
1951
|
+
i0.ɵɵelement(7, "i", 94);
|
|
1952
1952
|
i0.ɵɵelementEnd()();
|
|
1953
|
-
i0.ɵɵelementStart(8, "div",
|
|
1954
|
-
i0.ɵɵelement(9, "i",
|
|
1955
|
-
i0.ɵɵelementStart(10, "input",
|
|
1956
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
1953
|
+
i0.ɵɵelementStart(8, "div", 337);
|
|
1954
|
+
i0.ɵɵelement(9, "i", 338);
|
|
1955
|
+
i0.ɵɵelementStart(10, "input", 339, 2);
|
|
1956
|
+
i0.ɵɵtwoWayListener("ngModelChange", function MJTestSuiteFormComponentExtended_Conditional_70_Template_input_ngModelChange_10_listener($event) { i0.ɵɵrestoreView(_r52); const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r0.addTestsSearch, $event) || (ctx_r0.addTestsSearch = $event); return i0.ɵɵresetView($event); });
|
|
1957
1957
|
i0.ɵɵelementEnd();
|
|
1958
|
-
i0.ɵɵconditionalCreate(12,
|
|
1958
|
+
i0.ɵɵconditionalCreate(12, MJTestSuiteFormComponentExtended_Conditional_70_Conditional_12_Template, 2, 0, "button", 340);
|
|
1959
1959
|
i0.ɵɵelementEnd();
|
|
1960
|
-
i0.ɵɵelementStart(13, "div",
|
|
1961
|
-
i0.ɵɵconditionalCreate(15,
|
|
1960
|
+
i0.ɵɵelementStart(13, "div", 341)(14, "span", 342);
|
|
1961
|
+
i0.ɵɵconditionalCreate(15, MJTestSuiteFormComponentExtended_Conditional_70_Conditional_15_Template, 3, 1)(16, MJTestSuiteFormComponentExtended_Conditional_70_Conditional_16_Template, 1, 2);
|
|
1962
1962
|
i0.ɵɵelementEnd();
|
|
1963
|
-
i0.ɵɵelementStart(17, "div",
|
|
1964
|
-
i0.ɵɵlistener("click", function
|
|
1963
|
+
i0.ɵɵelementStart(17, "div", 343)(18, "button", 344);
|
|
1964
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_70_Template_button_click_18_listener() { i0.ɵɵrestoreView(_r52); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.selectAllFiltered()); });
|
|
1965
1965
|
i0.ɵɵtext(19, " Select all ");
|
|
1966
1966
|
i0.ɵɵelementEnd();
|
|
1967
|
-
i0.ɵɵelementStart(20, "button",
|
|
1968
|
-
i0.ɵɵlistener("click", function
|
|
1967
|
+
i0.ɵɵelementStart(20, "button", 344);
|
|
1968
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_70_Template_button_click_20_listener() { i0.ɵɵrestoreView(_r52); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.clearAddSelection()); });
|
|
1969
1969
|
i0.ɵɵtext(21, " Clear ");
|
|
1970
1970
|
i0.ɵɵelementEnd()()();
|
|
1971
|
-
i0.ɵɵelementStart(22, "div",
|
|
1972
|
-
i0.ɵɵconditionalCreate(23,
|
|
1971
|
+
i0.ɵɵelementStart(22, "div", 345);
|
|
1972
|
+
i0.ɵɵconditionalCreate(23, MJTestSuiteFormComponentExtended_Conditional_70_Conditional_23_Template, 2, 0, "div", 346)(24, MJTestSuiteFormComponentExtended_Conditional_70_Conditional_24_Template, 2, 1)(25, MJTestSuiteFormComponentExtended_Conditional_70_Conditional_25_Template, 3, 0, "ul", 347);
|
|
1973
1973
|
i0.ɵɵelementEnd();
|
|
1974
|
-
i0.ɵɵelementStart(26, "div",
|
|
1975
|
-
i0.ɵɵlistener("click", function
|
|
1976
|
-
i0.ɵɵconditionalCreate(28,
|
|
1974
|
+
i0.ɵɵelementStart(26, "div", 348)(27, "button", 349);
|
|
1975
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_70_Template_button_click_27_listener() { i0.ɵɵrestoreView(_r52); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.confirmAddTests()); });
|
|
1976
|
+
i0.ɵɵconditionalCreate(28, MJTestSuiteFormComponentExtended_Conditional_70_Conditional_28_Template, 2, 0)(29, MJTestSuiteFormComponentExtended_Conditional_70_Conditional_29_Template, 4, 1);
|
|
1977
1977
|
i0.ɵɵelementEnd();
|
|
1978
|
-
i0.ɵɵelementStart(30, "button",
|
|
1979
|
-
i0.ɵɵlistener("click", function
|
|
1978
|
+
i0.ɵɵelementStart(30, "button", 350);
|
|
1979
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Conditional_70_Template_button_click_30_listener() { i0.ɵɵrestoreView(_r52); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.closeAddTestsDialog()); });
|
|
1980
1980
|
i0.ɵɵtext(31, " Cancel ");
|
|
1981
1981
|
i0.ɵɵelementEnd()()();
|
|
1982
1982
|
} if (rf & 2) {
|
|
@@ -2002,26 +2002,26 @@ function MJTestSuiteFormComponentExtended_Conditional_69_Template(rf, ctx) { if
|
|
|
2002
2002
|
i0.ɵɵadvance(2);
|
|
2003
2003
|
i0.ɵɵproperty("disabled", ctx_r0.isAddingTests);
|
|
2004
2004
|
} }
|
|
2005
|
-
function
|
|
2005
|
+
function MJTestSuiteFormComponentExtended_Conditional_79_Template(rf, ctx) { if (rf & 1) {
|
|
2006
2006
|
i0.ɵɵtext(0);
|
|
2007
2007
|
} if (rf & 2) {
|
|
2008
2008
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
2009
2009
|
i0.ɵɵtextInterpolate1(" ", ctx_r0.dirtyFieldNames[0], " edited ");
|
|
2010
2010
|
} }
|
|
2011
|
-
function
|
|
2011
|
+
function MJTestSuiteFormComponentExtended_Conditional_80_Template(rf, ctx) { if (rf & 1) {
|
|
2012
2012
|
i0.ɵɵtext(0);
|
|
2013
2013
|
} if (rf & 2) {
|
|
2014
2014
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
2015
2015
|
i0.ɵɵtextInterpolate1(" ", ctx_r0.dirtyFieldNames.length, " fields edited ");
|
|
2016
2016
|
} }
|
|
2017
|
-
function
|
|
2018
|
-
i0.ɵɵelement(0, "i",
|
|
2017
|
+
function MJTestSuiteFormComponentExtended_Conditional_83_Template(rf, ctx) { if (rf & 1) {
|
|
2018
|
+
i0.ɵɵelement(0, "i", 126);
|
|
2019
2019
|
i0.ɵɵtext(1, " Saving\u2026 ");
|
|
2020
2020
|
} }
|
|
2021
|
-
function
|
|
2022
|
-
i0.ɵɵelement(0, "i",
|
|
2021
|
+
function MJTestSuiteFormComponentExtended_Conditional_84_Template(rf, ctx) { if (rf & 1) {
|
|
2022
|
+
i0.ɵɵelement(0, "i", 180);
|
|
2023
2023
|
i0.ɵɵtext(1, " Save changes ");
|
|
2024
|
-
i0.ɵɵelementStart(2, "span",
|
|
2024
|
+
i0.ɵɵelementStart(2, "span", 364)(3, "kbd");
|
|
2025
2025
|
i0.ɵɵtext(4, "\u2318");
|
|
2026
2026
|
i0.ɵɵelementEnd();
|
|
2027
2027
|
i0.ɵɵelementStart(5, "kbd");
|
|
@@ -2578,6 +2578,21 @@ let MJTestSuiteFormComponentExtended = class MJTestSuiteFormComponentExtended ex
|
|
|
2578
2578
|
const tag = el.tagName;
|
|
2579
2579
|
return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || el.isContentEditable;
|
|
2580
2580
|
}
|
|
2581
|
+
/** The tab strip as `mj-section-picker` items: strip order, a count once that tab's data has loaded. */
|
|
2582
|
+
get SectionPickerItems() {
|
|
2583
|
+
return [
|
|
2584
|
+
{ Key: 'overview', Title: 'Overview', Icon: 'fas fa-th-large' },
|
|
2585
|
+
{ Key: 'tests', Title: 'Tests', Icon: 'fas fa-flask', Count: this.TestsLoaded ? this.SuiteTests.length : null },
|
|
2586
|
+
{ Key: 'runs', Title: 'Runs', Icon: 'fas fa-history', Count: this.RunsLoaded ? this.SuiteRuns.length : null },
|
|
2587
|
+
{ Key: 'analytics', Title: 'Analytics', Icon: 'fas fa-chart-line' },
|
|
2588
|
+
{ Key: 'compare', Title: 'Compare', Icon: 'fas fa-balance-scale' },
|
|
2589
|
+
];
|
|
2590
|
+
}
|
|
2591
|
+
/** A pick from the phone section sheet; goes through ChangeTab so lazy loads fire. An unknown key is ignored. */
|
|
2592
|
+
OnSectionPicked(key) {
|
|
2593
|
+
if (this.SectionPickerItems.some((i) => i.Key === key))
|
|
2594
|
+
this.ChangeTab(key);
|
|
2595
|
+
}
|
|
2581
2596
|
ChangeTab(tab) {
|
|
2582
2597
|
this.ActiveTab = tab;
|
|
2583
2598
|
if (tab === 'tests' && !this.TestsLoaded)
|
|
@@ -4836,7 +4851,7 @@ let MJTestSuiteFormComponentExtended = class MJTestSuiteFormComponentExtended ex
|
|
|
4836
4851
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.ChartContainer = _t.first);
|
|
4837
4852
|
} }, hostBindings: function MJTestSuiteFormComponentExtended_HostBindings(rf, ctx) { if (rf & 1) {
|
|
4838
4853
|
i0.ɵɵlistener("keydown", function MJTestSuiteFormComponentExtended_keydown_HostBindingHandler($event) { return ctx.handleKeyboardShortcut($event); }, i0.ɵɵresolveDocument)("beforeunload", function MJTestSuiteFormComponentExtended_beforeunload_HostBindingHandler($event) { return ctx.handleBeforeUnload($event); }, i0.ɵɵresolveWindow);
|
|
4839
|
-
} }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 87, vars: 51, consts: [["tagInput", ""], ["chartContainer", ""], ["pickerSearch", ""], [1, "test-suite-form"], [1, "suite-header"], ["aria-label", "Breadcrumb", 1, "breadcrumb"], ["href", "javascript:void(0)", 3, "click"], [1, "fas", "fa-vial"], [1, "breadcrumb-text"], [1, "current"], [1, "fas", "fa-chevron-right", "separator"], [1, "fas", "fa-layer-group"], [1, "header-content"], [1, "header-left"], [1, "suite-icon"], [1, "suite-info"], ["title", "You have unsaved changes", "aria-label", "Unsaved changes", 1, "dirty-indicator"], [1, "suite-meta"], [1, "status-badge", 3, "ngClass"], [1, "fas", 3, "ngClass"], [1, "test-count"], ["title", "You have unsaved changes", 1, "unsaved-pill"], [1, "header-actions"], ["mjButton", "", "title", "Export to CSV", 3, "click"], [1, "fas", "fa-file-excel"], ["mjButton", "", "variant", "primary", 3, "click"], [1, "fas", "fa-play"], ["mjButton", "", 3, "click", "disabled"], [1, "suite-description"], [1, "tabs-container"], ["role", "tablist", 1, "tabs"], ["role", "tab", 1, "tab", 3, "click"], [1, "fas", "fa-th-large"], [1, "fas", "fa-flask"], [1, "tab-badge"], [1, "fas", "fa-history"], [1, "fas", "fa-chart-line"], [1, "fas", "fa-balance-scale"], [1, "tab-content"], [1, "overview-tab"], [1, "tests-tab"], [1, "runs-tab"], [1, "analytics-tab"], [1, "compare-tab"], [1, "shortcuts-toggle", 3, "click", "title"], [1, "fas", "fa-keyboard"], [1, "keyboard-shortcuts"], ["Mode", "slide", 3, "Title", "Resizable"], ["role", "region", "aria-label", "Unsaved changes", 1, "save-bar"], [1, "save-bar-message"], ["aria-hidden", "true", 1, "save-bar-dot"], [1, "save-bar-text"], [1, "save-bar-fields"], [1, "save-bar-actions"], ["type", "button", "title", "Save changes (\u2318S)", 1, "save-bar-btn", "save-bar-btn--primary", 3, "click", "disabled"], ["type", "button", "title", "Discard changes", 1, "save-bar-btn", "save-bar-btn--ghost", 3, "click", "disabled"], [1, "fas", "fa-undo"], [1, "fas", "fa-circle"], [1, "edit-section"], [1, "edit-section-header"], [1, "fas", "fa-pen-to-square"], [1, "edit-section-sub"], [1, "edit-grid"], [1, "edit-field", "edit-field--full"], ["for", "suite-name"], [1, "required"], ["id", "suite-name", "type", "text", "placeholder", "e.g., Core Agent Test Suite", 1, "config-input", 3, "ngModelChange", "ngModel"], ["for", "suite-description"], ["id", "suite-description", "rows", "3", "placeholder", "What does this suite cover?", 1, "config-input", "config-textarea", 3, "ngModelChange", "ngModel"], [1, "edit-field"], ["for", "suite-status"], [1, "select-wrapper"], ["id", "suite-status", 1, "config-input", 3, "ngModelChange", "ngModel"], [3, "ngValue"], ["for", "suite-rubric"], ["id", "suite-rubric", 1, "config-input", 3, "ngModelChange", "ngModel"], ["for", "suite-parent"], ["id", "suite-parent", 1, "config-input", 3, "ngModelChange", "ngModel"], ["for", "suite-tags"], [1, "tag-editor", 3, "click"], [1, "tag-chip-editable"], ["id", "suite-tags", "type", "text", 1, "tag-input-inline", 3, "ngModelChange", "keydown", "blur", "placeholder", "ngModel"], [1, "config-hint"], [1, "fas", "fa-cogs"], ["for", "suite-timeout"], ["id", "suite-timeout", "type", "number", "placeholder", "Default: 300000 (5 min)", 1, "config-input", 3, "ngModelChange", "ngModel"], [1, "meta-section"], [1, "meta-grid"], [1, "meta-item"], [1, "meta-label"], [1, "meta-value"], [1, "meta-value", "meta-mono"], ["type", "button", 1, "tag-remove", 3, "click"], [1, "fas", "fa-times"], [1, "tests-actionbar"], [1, "tests-actionbar-text"], [1, "tests-actionbar-count"], [1, "tests-actionbar-hint"], [1, "tests-actionbar-actions"], ["mjButton", "", "variant", "primary", 3, "click", "disabled"], [1, "fas", "fa-plus"], [1, "loading-state"], ["cdkDropList", "", 1, "tests-list"], ["Icon", "fa-solid fa-flask", "Title", "No Tests in Suite", "Message", "Add tests to this suite to start running them together.", "ActionText", "Add tests", "ActionIcon", "fa-solid fa-plus"], [1, "skeleton-list"], [1, "skeleton-card"], [1, "skeleton-sequence"], [1, "skeleton-icon"], [1, "skeleton-content"], [1, "skeleton-line", "wide"], [1, "skeleton-line", "narrow"], ["cdkDropList", "", 1, "tests-list", 3, "cdkDropListDropped"], ["cdkDrag", "", 1, "test-item", 3, "cdkDragDisabled"], ["cdkDragHandle", "", "title", "Drag to reorder", "aria-label", "Drag to reorder", 1, "test-drag-handle"], [1, "fas", "fa-grip-vertical"], [1, "test-sequence"], [1, "test-icon"], [1, "test-content", 3, "click"], [1, "test-name"], [1, "test-status"], [1, "test-remove-confirm"], [1, "fas", "fa-info-circle"], [1, "test-remove-confirm", 3, "click"], [1, "test-remove-confirm-text"], ["type", "button", 1, "test-remove-confirm-btn", "test-remove-confirm-btn--danger", 3, "click", "disabled"], [1, "fas", "fa-spinner", "fa-spin"], ["type", "button", 1, "test-remove-confirm-btn", "test-remove-confirm-btn--ghost", 3, "click", "disabled"], ["type", "button", "title", "Remove from suite", "aria-label", "Remove from suite", 1, "test-remove-btn", 3, "click"], [1, "fas", "fa-chevron-right", "test-chevron", 3, "click"], ["Icon", "fa-solid fa-flask", "Title", "No Tests in Suite", "Message", "Add tests to this suite to start running them together.", "ActionText", "Add tests", "ActionIcon", "fa-solid fa-plus", 3, "Action"], [1, "runs-list"], ["Icon", "fa-solid fa-circle-play", "Title", "No Suite Runs Yet", "Message", "Run this suite to see execution history and results here.", "ActionText", "Run Suite Now", "ActionIcon", "fa-solid fa-play"], [1, "run-item"], [1, "run-item", 3, "click"], [1, "run-icon"], [1, "fas"], [1, "run-content"], [1, "run-header"], [1, "run-id"], [1, "run-status"], [1, "run-meta"], [1, "fas", "fa-calendar"], [1, "run-eval-metrics"], [1, "eval-metric", "status", 3, "class"], ["title", "Human evaluation", 1, "eval-metric", "human"], ["title", "Auto score (pass rate)", 1, "eval-metric", "auto", 3, "high", "medium", "low"], [1, "run-tags"], [1, "fas", "fa-chevron-right"], [1, "fas", "fa-check-circle"], [1, "eval-metric", "status"], [1, "fas", "fa-user"], [1, "eval-pending"], [1, "fas", "fa-clock"], ["title", "Auto score (pass rate)", 1, "eval-metric", "auto"], [1, "fas", "fa-robot"], [1, "tag-chip"], ["Icon", "fa-solid fa-circle-play", "Title", "No Suite Runs Yet", "Message", "Run this suite to see execution history and results here.", "ActionText", "Run Suite Now", "ActionIcon", "fa-solid fa-play", 3, "Action"], ["Icon", "fa-solid fa-chart-line", "Title", "No Analytics Data", "Message", "Run this suite to start collecting analytics data.", "ActionText", "Run Suite Now", "ActionIcon", "fa-solid fa-play"], ["text", "Loading analytics data..."], [1, "analytics-subnav"], [1, "subnav-tabs"], [1, "subnav-tab", 3, "click"], [1, "fas", "fa-chart-bar"], [1, "fas", "fa-th"], [1, "fas", "fa-project-diagram"], ["Size", "sm", 3, "ExpandedChange", "FlushBody", "Expanded"], ["mjAccordionTitle", ""], ["mjAccordionBody", ""], [1, "fas", "fa-filter", 2, "color", "var(--test-primary)"], [1, "mj-accordion-badge", "mj-accordion-badge--right", "mj-accordion-badge--muted"], [1, "filters-content"], [1, "filter-group"], [1, "filter-buttons"], [1, "filter-btn", 3, "click"], [1, "filter-hint"], [1, "filter-buttons", "tag-filters"], [1, "filter-btn", "tag-btn", "all-tags-btn", 3, "click"], [1, "filter-btn", "tag-btn", 3, "active"], [1, "filter-btn", "tag-btn", 3, "click"], [1, "fas", "fa-check"], [1, "analytics-kpis"], [1, "kpi-card"], [1, "kpi-icon"], [1, "fas", "fa-play-circle"], [1, "kpi-content"], [1, "kpi-value"], [1, "kpi-label"], [1, "kpi-icon", "success"], [1, "kpi-trend", 3, "ngClass"], [1, "kpi-icon", "info"], [1, "kpi-icon", "warning"], [1, "fas", "fa-dollar-sign"], [1, "analytics-table-section"], [1, "fas", "fa-table"], [1, "analytics-table-wrapper"], [1, "analytics-table"], [1, "clickable-row"], ["Variant", "no-results", "Size", "compact", "Title", "No runs match the current filters."], [1, "clickable-row", 3, "click"], [1, "status-chip", 3, "ngClass"], [1, "pass-rate-cell"], [1, "pass-rate-bar", 3, "ngClass"], [1, "tag-cell"], [1, "tag-chip-table"], [1, "tag-more"], [1, "matrix-section"], ["Variant", "no-results", "Icon", "fa-solid fa-table-cells", "Title", "No Matrix Data", "Message", "No suite runs match the current filters."], ["text", "Loading test matrix..."], [1, "matrix-header"], [1, "matrix-header-right"], [1, "matrix-filter-input"], [1, "fas", "fa-search"], ["type", "text", "placeholder", "Filter tests...", 1, "filter-input", 3, "input", "value"], ["title", "Clear filter", 1, "clear-filter-btn"], [1, "matrix-run-count"], ["mjButton", "", "title", "Export matrix to CSV", 3, "click", "disabled"], [1, "fas", "fa-download"], [1, "matrix-scroll-container"], [1, "test-matrix"], ["title", "Sort by sequence", 1, "seq-header", 3, "click"], ["title", "Sort by name", 1, "test-name-header", 3, "click"], [1, "run-header", 3, "title"], [1, "spacer-header"], [3, "row-selected"], [1, "totals-row"], [1, "seq-cell", "totals-label"], [1, "test-name-cell", "totals-label"], [1, "result-cell", "totals-cell"], [1, "spacer-cell"], ["title", "Clear filter", 1, "clear-filter-btn", 3, "click"], [1, "run-header", 3, "click", "title"], [1, "run-header-content"], [1, "run-tags-header"], [1, "run-date"], [1, "run-pass-rate", 3, "ngClass"], [1, "tag-chip-header"], [1, "tag-more-header"], [3, "click"], [1, "seq-cell"], [1, "test-name-cell"], [1, "test-name", 3, "title"], [1, "result-cell", 3, "ngClass", "clickable", "cell-not-run", "title"], [1, "result-cell", 3, "click", "ngClass", "title"], [1, "cell-eval-stack"], [1, "cell-not-run-indicator"], [1, "cell-status", 3, "ngClass", "cell-skipped-status", "title"], ["title", "Human Review: No rating submitted yet", 1, "cell-human", "no-feedback"], [1, "cell-human", "has-feedback", 3, "rating-low", "rating-medium", "rating-good", "rating-excellent", "title"], [1, "cell-auto", "has-score", 3, "score-low", "score-medium", "score-good", "score-excellent", "title"], ["title", "Auto Score: No automated score available", 1, "cell-auto", "no-score"], [1, "cell-status", 3, "ngClass", "title"], [1, "fas", "fa-user-slash"], [1, "cell-human", "has-feedback", 3, "title"], [1, "rating-value"], [1, "cell-auto", "has-score", 3, "title"], [1, "score-value"], [1, "fas", "fa-minus"], [1, "cell-eval-stack", "totals-stack"], [1, "totals-status"], [1, "totals-human"], [1, "totals-auto"], [1, "pass-count"], [1, "avg-label"], [1, "count-label"], [1, "chart-section"], ["Variant", "no-results", "Icon", "fa-solid fa-diagram-project", "Title", "No Chart Data", "Message", "No suite runs match the current filters."], ["text", "Loading chart data..."], [1, "chart-header"], [1, "chart-legend"], [1, "legend-item", "chart-passed"], [1, "legend-item", "chart-failed"], [1, "legend-item", "chart-error"], [1, "fas", "fa-exclamation"], [1, "legend-item", "chart-skipped"], [1, "fas", "fa-forward"], [1, "chart-container"], [1, "d3-chart"], [1, "chart-info"], ["Icon", "fa-solid fa-chart-line", "Title", "No Analytics Data", "Message", "Run this suite to start collecting analytics data.", "ActionText", "Run Suite Now", "ActionIcon", "fa-solid fa-play", 3, "Action"], [1, "compare-selection"], [1, "compare-run-selector"], [1, "run-selector-list"], [1, "selected-run-preview"], [1, "compare-vs"], [1, "fas", "fa-exchange-alt"], [1, "compare-results"], ["Icon", "fa-solid fa-scale-balanced", "Title", "Select Two Runs to Compare", "Message", "Choose a baseline run (A) and a comparison run (B) from the lists above to see a detailed side-by-side comparison."], ["Icon", "fa-solid fa-scale-balanced", "Title", "Not Enough Runs to Compare", "Message", "You need at least 2 suite runs to use the comparison feature.", "ActionText", "Run Suite Now", "ActionIcon", "fa-solid fa-play"], [1, "run-selector-item", 3, "selected"], [1, "run-selector-item", 3, "click"], [1, "selector-status"], [1, "selector-content"], [1, "selector-date"], [1, "selector-rate"], [1, "selector-tags"], [1, "tag-mini"], [1, "preview-header"], [1, "preview-label"], [1, "clear-btn", 3, "click"], [1, "preview-details"], [1, "preview-rate"], [1, "run-selector-item", 3, "selected", "disabled"], [1, "compare-summary"], [1, "compare-summary-card"], [1, "summary-label"], [1, "summary-value", 3, "ngClass"], [1, "compare-summary-card", "improved"], [1, "summary-value"], [1, "compare-summary-card", "regressed"], [1, "compare-table-section"], [1, "fas", "fa-list"], [1, "compare-table-wrapper"], [1, "compare-table"], [3, "ngClass"], [1, "status-chip", "status-missing"], [1, "muted"], [1, "change-indicator", "improved"], [1, "change-indicator", "regressed"], [1, "change-indicator", "unchanged"], [1, "fas", "fa-arrow-up"], [1, "fas", "fa-arrow-down"], ["text", "Loading comparison data..."], ["Icon", "fa-solid fa-scale-balanced", "Title", "Not Enough Runs to Compare", "Message", "You need at least 2 suite runs to use the comparison feature.", "ActionText", "Run Suite Now", "ActionIcon", "fa-solid fa-play", 3, "Action"], [1, "shortcuts-header"], ["title", "Hide shortcuts", 1, "shortcuts-close", 3, "click"], [1, "shortcut-list"], [1, "shortcut-item"], [1, "shortcut-keys"], ["Mode", "slide", 3, "Closed", "Title", "Resizable"], [3, "PanelClose", "PanelMode", "selectedTestId", "selectedSuiteId", "runMode"], [1, "picker-backdrop", 3, "click"], ["role", "dialog", "aria-modal", "true", "aria-labelledby", "add-tests-dialog-title", 1, "picker-dialog", 3, "click"], [1, "picker-header"], ["id", "add-tests-dialog-title", 1, "picker-title"], [1, "fas", "fa-plus-circle"], ["type", "button", "aria-label", "Close", 1, "picker-close", 3, "click", "disabled"], [1, "picker-search"], [1, "fas", "fa-search", "picker-search-icon"], ["type", "text", "placeholder", "Search tests by name, description, or type...", "autofocus", "", 1, "picker-search-input", 3, "ngModelChange", "ngModel"], ["type", "button", "aria-label", "Clear search", 1, "picker-search-clear"], [1, "picker-toolbar"], [1, "picker-toolbar-status"], [1, "picker-toolbar-actions"], ["type", "button", 1, "picker-link-btn", 3, "click", "disabled"], [1, "picker-body"], [1, "picker-loading"], [1, "picker-list"], [1, "picker-footer"], ["type", "button", 1, "picker-btn", "picker-btn--primary", 3, "click", "disabled"], ["type", "button", 1, "picker-btn", "picker-btn--ghost", 3, "click", "disabled"], ["type", "button", "aria-label", "Clear search", 1, "picker-search-clear", 3, "click"], ["text", "Loading tests..."], ["Variant", "success", "Size", "compact", "Title", "Everything's already in the suite", "Message", "This suite contains every available test. Create a new test first to add more."], ["Variant", "no-results", "Size", "compact", "Title", "No matches", 3, "Message"], ["role", "checkbox", "tabindex", "0", 1, "picker-row", 3, "picker-row--selected"], ["role", "checkbox", "tabindex", "0", 1, "picker-row", 3, "click"], [1, "picker-check"], [1, "picker-row-main"], [1, "picker-row-name"], [1, "picker-row-desc"], [1, "picker-row-meta"], [1, "picker-row-pill"], [1, "picker-row-pill", "picker-row-pill--status"], [1, "save-bar-kbd"]], template: function MJTestSuiteFormComponentExtended_Template(rf, ctx) { if (rf & 1) {
|
|
4854
|
+
} }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 88, vars: 53, consts: [["tagInput", ""], ["chartContainer", ""], ["pickerSearch", ""], [1, "test-suite-form"], [1, "suite-header"], ["aria-label", "Breadcrumb", 1, "breadcrumb"], ["href", "javascript:void(0)", 3, "click"], [1, "fas", "fa-vial"], [1, "breadcrumb-text"], [1, "current"], [1, "fas", "fa-chevron-right", "separator"], [1, "fas", "fa-layer-group"], [1, "header-content"], [1, "header-left"], [1, "suite-icon"], [1, "suite-info"], ["title", "You have unsaved changes", "aria-label", "Unsaved changes", 1, "dirty-indicator"], [1, "suite-meta"], [1, "status-badge", 3, "ngClass"], [1, "fas", 3, "ngClass"], [1, "test-count"], ["title", "You have unsaved changes", 1, "unsaved-pill"], [1, "header-actions"], ["mjButton", "", "title", "Export to CSV", 3, "click"], [1, "fas", "fa-file-excel"], ["mjButton", "", "variant", "primary", 3, "click"], [1, "fas", "fa-play"], ["mjButton", "", 3, "click", "disabled"], [1, "suite-description"], [1, "tabs-container"], [1, "phone-section-picker", 3, "ActiveKeyChange", "Items", "ActiveKey"], ["role", "tablist", 1, "tabs"], ["role", "tab", 1, "tab", 3, "click"], [1, "fas", "fa-th-large"], [1, "fas", "fa-flask"], [1, "tab-badge"], [1, "fas", "fa-history"], [1, "fas", "fa-chart-line"], [1, "fas", "fa-balance-scale"], [1, "tab-content"], [1, "overview-tab"], [1, "tests-tab"], [1, "runs-tab"], [1, "analytics-tab"], [1, "compare-tab"], [1, "shortcuts-toggle", 3, "click", "title"], [1, "fas", "fa-keyboard"], [1, "keyboard-shortcuts"], ["Mode", "slide", 3, "Title", "Resizable"], ["role", "region", "aria-label", "Unsaved changes", 1, "save-bar"], [1, "save-bar-message"], ["aria-hidden", "true", 1, "save-bar-dot"], [1, "save-bar-text"], [1, "save-bar-fields"], [1, "save-bar-actions"], ["type", "button", "title", "Save changes (\u2318S)", 1, "save-bar-btn", "save-bar-btn--primary", 3, "click", "disabled"], ["type", "button", "title", "Discard changes", 1, "save-bar-btn", "save-bar-btn--ghost", 3, "click", "disabled"], [1, "fas", "fa-undo"], [1, "fas", "fa-circle"], [1, "edit-section"], [1, "edit-section-header"], [1, "fas", "fa-pen-to-square"], [1, "edit-section-sub"], [1, "edit-grid"], [1, "edit-field", "edit-field--full"], ["for", "suite-name"], [1, "required"], ["id", "suite-name", "type", "text", "placeholder", "e.g., Core Agent Test Suite", 1, "config-input", 3, "ngModelChange", "ngModel"], ["for", "suite-description"], ["id", "suite-description", "rows", "3", "placeholder", "What does this suite cover?", 1, "config-input", "config-textarea", 3, "ngModelChange", "ngModel"], [1, "edit-field"], ["for", "suite-status"], [1, "select-wrapper"], ["id", "suite-status", 1, "config-input", 3, "ngModelChange", "ngModel"], [3, "ngValue"], ["for", "suite-rubric"], ["id", "suite-rubric", 1, "config-input", 3, "ngModelChange", "ngModel"], ["for", "suite-parent"], ["id", "suite-parent", 1, "config-input", 3, "ngModelChange", "ngModel"], ["for", "suite-tags"], [1, "tag-editor", 3, "click"], [1, "tag-chip-editable"], ["id", "suite-tags", "type", "text", 1, "tag-input-inline", 3, "ngModelChange", "keydown", "blur", "placeholder", "ngModel"], [1, "config-hint"], [1, "fas", "fa-cogs"], ["for", "suite-timeout"], ["id", "suite-timeout", "type", "number", "placeholder", "Default: 300000 (5 min)", 1, "config-input", 3, "ngModelChange", "ngModel"], [1, "meta-section"], [1, "meta-grid"], [1, "meta-item"], [1, "meta-label"], [1, "meta-value"], [1, "meta-value", "meta-mono"], ["type", "button", 1, "tag-remove", 3, "click"], [1, "fas", "fa-times"], [1, "tests-actionbar"], [1, "tests-actionbar-text"], [1, "tests-actionbar-count"], [1, "tests-actionbar-hint"], [1, "tests-actionbar-actions"], ["mjButton", "", "variant", "primary", 3, "click", "disabled"], [1, "fas", "fa-plus"], [1, "loading-state"], ["cdkDropList", "", 1, "tests-list"], ["Icon", "fa-solid fa-flask", "Title", "No Tests in Suite", "Message", "Add tests to this suite to start running them together.", "ActionText", "Add tests", "ActionIcon", "fa-solid fa-plus"], [1, "skeleton-list"], [1, "skeleton-card"], [1, "skeleton-sequence"], [1, "skeleton-icon"], [1, "skeleton-content"], [1, "skeleton-line", "wide"], [1, "skeleton-line", "narrow"], ["cdkDropList", "", 1, "tests-list", 3, "cdkDropListDropped"], ["cdkDrag", "", 1, "test-item", 3, "cdkDragDisabled"], ["cdkDragHandle", "", "title", "Drag to reorder", "aria-label", "Drag to reorder", 1, "test-drag-handle"], [1, "fas", "fa-grip-vertical"], [1, "test-sequence"], [1, "test-icon"], [1, "test-content", 3, "click"], [1, "test-name"], [1, "test-status"], [1, "test-remove-confirm"], [1, "fas", "fa-info-circle"], [1, "test-remove-confirm", 3, "click"], [1, "test-remove-confirm-text"], ["type", "button", 1, "test-remove-confirm-btn", "test-remove-confirm-btn--danger", 3, "click", "disabled"], [1, "fas", "fa-spinner", "fa-spin"], ["type", "button", 1, "test-remove-confirm-btn", "test-remove-confirm-btn--ghost", 3, "click", "disabled"], ["type", "button", "title", "Remove from suite", "aria-label", "Remove from suite", 1, "test-remove-btn", 3, "click"], [1, "fas", "fa-chevron-right", "test-chevron", 3, "click"], ["Icon", "fa-solid fa-flask", "Title", "No Tests in Suite", "Message", "Add tests to this suite to start running them together.", "ActionText", "Add tests", "ActionIcon", "fa-solid fa-plus", 3, "Action"], [1, "runs-list"], ["Icon", "fa-solid fa-circle-play", "Title", "No Suite Runs Yet", "Message", "Run this suite to see execution history and results here.", "ActionText", "Run Suite Now", "ActionIcon", "fa-solid fa-play"], [1, "run-item"], [1, "run-item", 3, "click"], [1, "run-icon"], [1, "fas"], [1, "run-content"], [1, "run-header"], [1, "run-id"], [1, "run-status"], [1, "run-meta"], [1, "fas", "fa-calendar"], [1, "run-eval-metrics"], [1, "eval-metric", "status", 3, "class"], ["title", "Human evaluation", 1, "eval-metric", "human"], ["title", "Auto score (pass rate)", 1, "eval-metric", "auto", 3, "high", "medium", "low"], [1, "run-tags"], [1, "fas", "fa-chevron-right"], [1, "fas", "fa-check-circle"], [1, "eval-metric", "status"], [1, "fas", "fa-user"], [1, "eval-pending"], [1, "fas", "fa-clock"], ["title", "Auto score (pass rate)", 1, "eval-metric", "auto"], [1, "fas", "fa-robot"], [1, "tag-chip"], ["Icon", "fa-solid fa-circle-play", "Title", "No Suite Runs Yet", "Message", "Run this suite to see execution history and results here.", "ActionText", "Run Suite Now", "ActionIcon", "fa-solid fa-play", 3, "Action"], ["Icon", "fa-solid fa-chart-line", "Title", "No Analytics Data", "Message", "Run this suite to start collecting analytics data.", "ActionText", "Run Suite Now", "ActionIcon", "fa-solid fa-play"], ["text", "Loading analytics data..."], [1, "analytics-subnav"], [1, "subnav-tabs"], [1, "subnav-tab", 3, "click"], [1, "fas", "fa-chart-bar"], [1, "fas", "fa-th"], [1, "fas", "fa-project-diagram"], ["Size", "sm", 3, "ExpandedChange", "FlushBody", "Expanded"], ["mjAccordionTitle", ""], ["mjAccordionBody", ""], [1, "fas", "fa-filter", 2, "color", "var(--test-primary)"], [1, "mj-accordion-badge", "mj-accordion-badge--right", "mj-accordion-badge--muted"], [1, "filters-content"], [1, "filter-group"], [1, "filter-buttons"], [1, "filter-btn", 3, "click"], [1, "filter-hint"], [1, "filter-buttons", "tag-filters"], [1, "filter-btn", "tag-btn", "all-tags-btn", 3, "click"], [1, "filter-btn", "tag-btn", 3, "active"], [1, "filter-btn", "tag-btn", 3, "click"], [1, "fas", "fa-check"], [1, "analytics-kpis"], [1, "kpi-card"], [1, "kpi-icon"], [1, "fas", "fa-play-circle"], [1, "kpi-content"], [1, "kpi-value"], [1, "kpi-label"], [1, "kpi-icon", "success"], [1, "kpi-trend", 3, "ngClass"], [1, "kpi-icon", "info"], [1, "kpi-icon", "warning"], [1, "fas", "fa-dollar-sign"], [1, "analytics-table-section"], [1, "fas", "fa-table"], [1, "analytics-table-wrapper"], [1, "analytics-table"], [1, "clickable-row"], ["Variant", "no-results", "Size", "compact", "Title", "No runs match the current filters."], [1, "clickable-row", 3, "click"], [1, "status-chip", 3, "ngClass"], [1, "pass-rate-cell"], [1, "pass-rate-bar", 3, "ngClass"], [1, "tag-cell"], [1, "tag-chip-table"], [1, "tag-more"], [1, "matrix-section"], ["Variant", "no-results", "Icon", "fa-solid fa-table-cells", "Title", "No Matrix Data", "Message", "No suite runs match the current filters."], ["text", "Loading test matrix..."], [1, "matrix-header"], [1, "matrix-header-right"], [1, "matrix-filter-input"], [1, "fas", "fa-search"], ["type", "text", "placeholder", "Filter tests...", 1, "filter-input", 3, "input", "value"], ["title", "Clear filter", 1, "clear-filter-btn"], [1, "matrix-run-count"], ["mjButton", "", "title", "Export matrix to CSV", 3, "click", "disabled"], [1, "fas", "fa-download"], [1, "matrix-scroll-container"], [1, "test-matrix"], ["title", "Sort by sequence", 1, "seq-header", 3, "click"], ["title", "Sort by name", 1, "test-name-header", 3, "click"], [1, "run-header", 3, "title"], [1, "spacer-header"], [3, "row-selected"], [1, "totals-row"], [1, "seq-cell", "totals-label"], [1, "test-name-cell", "totals-label"], [1, "result-cell", "totals-cell"], [1, "spacer-cell"], ["title", "Clear filter", 1, "clear-filter-btn", 3, "click"], [1, "run-header", 3, "click", "title"], [1, "run-header-content"], [1, "run-tags-header"], [1, "run-date"], [1, "run-pass-rate", 3, "ngClass"], [1, "tag-chip-header"], [1, "tag-more-header"], [3, "click"], [1, "seq-cell"], [1, "test-name-cell"], [1, "test-name", 3, "title"], [1, "result-cell", 3, "ngClass", "clickable", "cell-not-run", "title"], [1, "result-cell", 3, "click", "ngClass", "title"], [1, "cell-eval-stack"], [1, "cell-not-run-indicator"], [1, "cell-status", 3, "ngClass", "cell-skipped-status", "title"], ["title", "Human Review: No rating submitted yet", 1, "cell-human", "no-feedback"], [1, "cell-human", "has-feedback", 3, "rating-low", "rating-medium", "rating-good", "rating-excellent", "title"], [1, "cell-auto", "has-score", 3, "score-low", "score-medium", "score-good", "score-excellent", "title"], ["title", "Auto Score: No automated score available", 1, "cell-auto", "no-score"], [1, "cell-status", 3, "ngClass", "title"], [1, "fas", "fa-user-slash"], [1, "cell-human", "has-feedback", 3, "title"], [1, "rating-value"], [1, "cell-auto", "has-score", 3, "title"], [1, "score-value"], [1, "fas", "fa-minus"], [1, "cell-eval-stack", "totals-stack"], [1, "totals-status"], [1, "totals-human"], [1, "totals-auto"], [1, "pass-count"], [1, "avg-label"], [1, "count-label"], [1, "chart-section"], ["Variant", "no-results", "Icon", "fa-solid fa-diagram-project", "Title", "No Chart Data", "Message", "No suite runs match the current filters."], ["text", "Loading chart data..."], [1, "chart-header"], [1, "chart-legend"], [1, "legend-item", "chart-passed"], [1, "legend-item", "chart-failed"], [1, "legend-item", "chart-error"], [1, "fas", "fa-exclamation"], [1, "legend-item", "chart-skipped"], [1, "fas", "fa-forward"], [1, "chart-container"], [1, "d3-chart"], [1, "chart-info"], ["Icon", "fa-solid fa-chart-line", "Title", "No Analytics Data", "Message", "Run this suite to start collecting analytics data.", "ActionText", "Run Suite Now", "ActionIcon", "fa-solid fa-play", 3, "Action"], [1, "compare-selection"], [1, "compare-run-selector"], [1, "run-selector-list"], [1, "selected-run-preview"], [1, "compare-vs"], [1, "fas", "fa-exchange-alt"], [1, "compare-results"], ["Icon", "fa-solid fa-scale-balanced", "Title", "Select Two Runs to Compare", "Message", "Choose a baseline run (A) and a comparison run (B) from the lists above to see a detailed side-by-side comparison."], ["Icon", "fa-solid fa-scale-balanced", "Title", "Not Enough Runs to Compare", "Message", "You need at least 2 suite runs to use the comparison feature.", "ActionText", "Run Suite Now", "ActionIcon", "fa-solid fa-play"], [1, "run-selector-item", 3, "selected"], [1, "run-selector-item", 3, "click"], [1, "selector-status"], [1, "selector-content"], [1, "selector-date"], [1, "selector-rate"], [1, "selector-tags"], [1, "tag-mini"], [1, "preview-header"], [1, "preview-label"], [1, "clear-btn", 3, "click"], [1, "preview-details"], [1, "preview-rate"], [1, "run-selector-item", 3, "selected", "disabled"], [1, "compare-summary"], [1, "compare-summary-card"], [1, "summary-label"], [1, "summary-value", 3, "ngClass"], [1, "compare-summary-card", "improved"], [1, "summary-value"], [1, "compare-summary-card", "regressed"], [1, "compare-table-section"], [1, "fas", "fa-list"], [1, "compare-table-wrapper"], [1, "compare-table"], [3, "ngClass"], [1, "status-chip", "status-missing"], [1, "muted"], [1, "change-indicator", "improved"], [1, "change-indicator", "regressed"], [1, "change-indicator", "unchanged"], [1, "fas", "fa-arrow-up"], [1, "fas", "fa-arrow-down"], ["text", "Loading comparison data..."], ["Icon", "fa-solid fa-scale-balanced", "Title", "Not Enough Runs to Compare", "Message", "You need at least 2 suite runs to use the comparison feature.", "ActionText", "Run Suite Now", "ActionIcon", "fa-solid fa-play", 3, "Action"], [1, "shortcuts-header"], ["title", "Hide shortcuts", 1, "shortcuts-close", 3, "click"], [1, "shortcut-list"], [1, "shortcut-item"], [1, "shortcut-keys"], ["Mode", "slide", 3, "Closed", "Title", "Resizable"], [3, "PanelClose", "PanelMode", "selectedTestId", "selectedSuiteId", "runMode"], [1, "picker-backdrop", 3, "click"], ["role", "dialog", "aria-modal", "true", "aria-labelledby", "add-tests-dialog-title", 1, "picker-dialog", 3, "click"], [1, "picker-header"], ["id", "add-tests-dialog-title", 1, "picker-title"], [1, "fas", "fa-plus-circle"], ["type", "button", "aria-label", "Close", 1, "picker-close", 3, "click", "disabled"], [1, "picker-search"], [1, "fas", "fa-search", "picker-search-icon"], ["type", "text", "placeholder", "Search tests by name, description, or type...", "autofocus", "", 1, "picker-search-input", 3, "ngModelChange", "ngModel"], ["type", "button", "aria-label", "Clear search", 1, "picker-search-clear"], [1, "picker-toolbar"], [1, "picker-toolbar-status"], [1, "picker-toolbar-actions"], ["type", "button", 1, "picker-link-btn", 3, "click", "disabled"], [1, "picker-body"], [1, "picker-loading"], [1, "picker-list"], [1, "picker-footer"], ["type", "button", 1, "picker-btn", "picker-btn--primary", 3, "click", "disabled"], ["type", "button", 1, "picker-btn", "picker-btn--ghost", 3, "click", "disabled"], ["type", "button", "aria-label", "Clear search", 1, "picker-search-clear", 3, "click"], ["text", "Loading tests..."], ["Variant", "success", "Size", "compact", "Title", "Everything's already in the suite", "Message", "This suite contains every available test. Create a new test first to add more."], ["Variant", "no-results", "Size", "compact", "Title", "No matches", 3, "Message"], ["role", "checkbox", "tabindex", "0", 1, "picker-row", 3, "picker-row--selected"], ["role", "checkbox", "tabindex", "0", 1, "picker-row", 3, "click"], [1, "picker-check"], [1, "picker-row-main"], [1, "picker-row-name"], [1, "picker-row-desc"], [1, "picker-row-meta"], [1, "picker-row-pill"], [1, "picker-row-pill", "picker-row-pill--status"], [1, "save-bar-kbd"]], template: function MJTestSuiteFormComponentExtended_Template(rf, ctx) { if (rf & 1) {
|
|
4840
4855
|
i0.ɵɵelementStart(0, "div", 3)(1, "div", 4)(2, "nav", 5)(3, "ol")(4, "li")(5, "a", 6);
|
|
4841
4856
|
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Template_a_click_5_listener() { return ctx.navigateToTestingDashboard(); });
|
|
4842
4857
|
i0.ɵɵelement(6, "i", 7);
|
|
@@ -4881,64 +4896,67 @@ let MJTestSuiteFormComponentExtended = class MJTestSuiteFormComponentExtended ex
|
|
|
4881
4896
|
i0.ɵɵelementEnd()()();
|
|
4882
4897
|
i0.ɵɵconditionalCreate(39, MJTestSuiteFormComponentExtended_Conditional_39_Template, 3, 1, "div", 28);
|
|
4883
4898
|
i0.ɵɵelementEnd();
|
|
4884
|
-
i0.ɵɵelementStart(40, "div", 29)(41, "
|
|
4885
|
-
i0.ɵɵlistener("
|
|
4886
|
-
i0.ɵɵ
|
|
4887
|
-
i0.ɵɵ
|
|
4899
|
+
i0.ɵɵelementStart(40, "div", 29)(41, "mj-section-picker", 30);
|
|
4900
|
+
i0.ɵɵlistener("ActiveKeyChange", function MJTestSuiteFormComponentExtended_Template_mj_section_picker_ActiveKeyChange_41_listener($event) { return ctx.OnSectionPicked($event); });
|
|
4901
|
+
i0.ɵɵelementEnd();
|
|
4902
|
+
i0.ɵɵelementStart(42, "div", 31)(43, "button", 32);
|
|
4903
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Template_button_click_43_listener() { return ctx.changeTab("overview"); });
|
|
4904
|
+
i0.ɵɵelement(44, "i", 33);
|
|
4905
|
+
i0.ɵɵtext(45, " Overview ");
|
|
4888
4906
|
i0.ɵɵelementEnd();
|
|
4889
|
-
i0.ɵɵelementStart(
|
|
4890
|
-
i0.ɵɵlistener("click", function
|
|
4891
|
-
i0.ɵɵelement(
|
|
4892
|
-
i0.ɵɵtext(
|
|
4893
|
-
i0.ɵɵconditionalCreate(
|
|
4907
|
+
i0.ɵɵelementStart(46, "button", 32);
|
|
4908
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Template_button_click_46_listener() { return ctx.changeTab("tests"); });
|
|
4909
|
+
i0.ɵɵelement(47, "i", 34);
|
|
4910
|
+
i0.ɵɵtext(48, " Tests ");
|
|
4911
|
+
i0.ɵɵconditionalCreate(49, MJTestSuiteFormComponentExtended_Conditional_49_Template, 2, 1, "span", 35);
|
|
4894
4912
|
i0.ɵɵelementEnd();
|
|
4895
|
-
i0.ɵɵelementStart(
|
|
4896
|
-
i0.ɵɵlistener("click", function
|
|
4897
|
-
i0.ɵɵelement(
|
|
4898
|
-
i0.ɵɵtext(
|
|
4899
|
-
i0.ɵɵconditionalCreate(
|
|
4913
|
+
i0.ɵɵelementStart(50, "button", 32);
|
|
4914
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Template_button_click_50_listener() { return ctx.changeTab("runs"); });
|
|
4915
|
+
i0.ɵɵelement(51, "i", 36);
|
|
4916
|
+
i0.ɵɵtext(52, " Runs ");
|
|
4917
|
+
i0.ɵɵconditionalCreate(53, MJTestSuiteFormComponentExtended_Conditional_53_Template, 2, 1, "span", 35);
|
|
4900
4918
|
i0.ɵɵelementEnd();
|
|
4901
|
-
i0.ɵɵelementStart(
|
|
4902
|
-
i0.ɵɵlistener("click", function
|
|
4903
|
-
i0.ɵɵelement(
|
|
4904
|
-
i0.ɵɵtext(
|
|
4919
|
+
i0.ɵɵelementStart(54, "button", 32);
|
|
4920
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Template_button_click_54_listener() { return ctx.changeTab("analytics"); });
|
|
4921
|
+
i0.ɵɵelement(55, "i", 37);
|
|
4922
|
+
i0.ɵɵtext(56, " Analytics ");
|
|
4905
4923
|
i0.ɵɵelementEnd();
|
|
4906
|
-
i0.ɵɵelementStart(
|
|
4907
|
-
i0.ɵɵlistener("click", function
|
|
4908
|
-
i0.ɵɵelement(
|
|
4909
|
-
i0.ɵɵtext(
|
|
4924
|
+
i0.ɵɵelementStart(57, "button", 32);
|
|
4925
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Template_button_click_57_listener() { return ctx.changeTab("compare"); });
|
|
4926
|
+
i0.ɵɵelement(58, "i", 38);
|
|
4927
|
+
i0.ɵɵtext(59, " Compare ");
|
|
4910
4928
|
i0.ɵɵelementEnd()()();
|
|
4911
|
-
i0.ɵɵelementStart(
|
|
4912
|
-
i0.ɵɵconditionalCreate(
|
|
4913
|
-
i0.ɵɵconditionalCreate(
|
|
4914
|
-
i0.ɵɵconditionalCreate(62, MJTestSuiteFormComponentExtended_Conditional_62_Template, 4, 3, "div", 41);
|
|
4929
|
+
i0.ɵɵelementStart(60, "div", 39);
|
|
4930
|
+
i0.ɵɵconditionalCreate(61, MJTestSuiteFormComponentExtended_Conditional_61_Template, 83, 20, "div", 40);
|
|
4931
|
+
i0.ɵɵconditionalCreate(62, MJTestSuiteFormComponentExtended_Conditional_62_Template, 15, 5, "div", 41);
|
|
4915
4932
|
i0.ɵɵconditionalCreate(63, MJTestSuiteFormComponentExtended_Conditional_63_Template, 4, 3, "div", 42);
|
|
4916
|
-
i0.ɵɵconditionalCreate(64, MJTestSuiteFormComponentExtended_Conditional_64_Template,
|
|
4933
|
+
i0.ɵɵconditionalCreate(64, MJTestSuiteFormComponentExtended_Conditional_64_Template, 4, 3, "div", 43);
|
|
4934
|
+
i0.ɵɵconditionalCreate(65, MJTestSuiteFormComponentExtended_Conditional_65_Template, 18, 8, "div", 44);
|
|
4917
4935
|
i0.ɵɵelementEnd();
|
|
4918
|
-
i0.ɵɵelementStart(
|
|
4919
|
-
i0.ɵɵlistener("click", function
|
|
4920
|
-
i0.ɵɵelement(
|
|
4936
|
+
i0.ɵɵelementStart(66, "button", 45);
|
|
4937
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Template_button_click_66_listener() { return ctx.toggleShortcuts(); });
|
|
4938
|
+
i0.ɵɵelement(67, "i", 46);
|
|
4921
4939
|
i0.ɵɵelementEnd();
|
|
4922
|
-
i0.ɵɵconditionalCreate(
|
|
4923
|
-
i0.ɵɵconditionalCreate(
|
|
4924
|
-
i0.ɵɵconditionalCreate(
|
|
4925
|
-
i0.ɵɵelementStart(
|
|
4926
|
-
i0.ɵɵtext(
|
|
4940
|
+
i0.ɵɵconditionalCreate(68, MJTestSuiteFormComponentExtended_Conditional_68_Template, 40, 0, "div", 47);
|
|
4941
|
+
i0.ɵɵconditionalCreate(69, MJTestSuiteFormComponentExtended_Conditional_69_Template, 2, 6, "mj-slide-panel", 48);
|
|
4942
|
+
i0.ɵɵconditionalCreate(70, MJTestSuiteFormComponentExtended_Conditional_70_Template, 32, 10);
|
|
4943
|
+
i0.ɵɵelementStart(71, "div", 49)(72, "div", 50)(73, "span", 51);
|
|
4944
|
+
i0.ɵɵtext(74, "\u25CF");
|
|
4927
4945
|
i0.ɵɵelementEnd();
|
|
4928
|
-
i0.ɵɵelementStart(
|
|
4929
|
-
i0.ɵɵtext(
|
|
4946
|
+
i0.ɵɵelementStart(75, "span", 52)(76, "strong");
|
|
4947
|
+
i0.ɵɵtext(77, "Unsaved changes");
|
|
4930
4948
|
i0.ɵɵelementEnd();
|
|
4931
|
-
i0.ɵɵelementStart(
|
|
4932
|
-
i0.ɵɵconditionalCreate(
|
|
4949
|
+
i0.ɵɵelementStart(78, "span", 53);
|
|
4950
|
+
i0.ɵɵconditionalCreate(79, MJTestSuiteFormComponentExtended_Conditional_79_Template, 1, 1)(80, MJTestSuiteFormComponentExtended_Conditional_80_Template, 1, 1);
|
|
4933
4951
|
i0.ɵɵelementEnd()()();
|
|
4934
|
-
i0.ɵɵelementStart(
|
|
4935
|
-
i0.ɵɵlistener("click", function
|
|
4936
|
-
i0.ɵɵconditionalCreate(
|
|
4952
|
+
i0.ɵɵelementStart(81, "div", 54)(82, "button", 55);
|
|
4953
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Template_button_click_82_listener() { return ctx.saveChanges(); });
|
|
4954
|
+
i0.ɵɵconditionalCreate(83, MJTestSuiteFormComponentExtended_Conditional_83_Template, 2, 0)(84, MJTestSuiteFormComponentExtended_Conditional_84_Template, 7, 0);
|
|
4937
4955
|
i0.ɵɵelementEnd();
|
|
4938
|
-
i0.ɵɵelementStart(
|
|
4939
|
-
i0.ɵɵlistener("click", function
|
|
4940
|
-
i0.ɵɵelement(
|
|
4941
|
-
i0.ɵɵtext(
|
|
4956
|
+
i0.ɵɵelementStart(85, "button", 56);
|
|
4957
|
+
i0.ɵɵlistener("click", function MJTestSuiteFormComponentExtended_Template_button_click_85_listener() { return ctx.discardChanges(); });
|
|
4958
|
+
i0.ɵɵelement(86, "i", 57);
|
|
4959
|
+
i0.ɵɵtext(87, " Discard ");
|
|
4942
4960
|
i0.ɵɵelementEnd()()()();
|
|
4943
4961
|
} if (rf & 2) {
|
|
4944
4962
|
i0.ɵɵadvance(13);
|
|
@@ -4967,19 +4985,21 @@ let MJTestSuiteFormComponentExtended = class MJTestSuiteFormComponentExtended ex
|
|
|
4967
4985
|
i0.ɵɵtextInterpolate1(" ", ctx.isRefreshing ? "Refreshing..." : "Refresh", " ");
|
|
4968
4986
|
i0.ɵɵadvance();
|
|
4969
4987
|
i0.ɵɵconditional(ctx.record.Description ? 39 : -1);
|
|
4970
|
-
i0.ɵɵadvance(
|
|
4988
|
+
i0.ɵɵadvance(2);
|
|
4989
|
+
i0.ɵɵproperty("Items", ctx.SectionPickerItems)("ActiveKey", ctx.ActiveTab);
|
|
4990
|
+
i0.ɵɵadvance(2);
|
|
4971
4991
|
i0.ɵɵclassProp("active", ctx.activeTab === "overview");
|
|
4972
4992
|
i0.ɵɵattribute("aria-selected", ctx.activeTab === "overview");
|
|
4973
4993
|
i0.ɵɵadvance(3);
|
|
4974
4994
|
i0.ɵɵclassProp("active", ctx.activeTab === "tests");
|
|
4975
4995
|
i0.ɵɵattribute("aria-selected", ctx.activeTab === "tests");
|
|
4976
4996
|
i0.ɵɵadvance(3);
|
|
4977
|
-
i0.ɵɵconditional(ctx.testsLoaded ?
|
|
4997
|
+
i0.ɵɵconditional(ctx.testsLoaded ? 49 : -1);
|
|
4978
4998
|
i0.ɵɵadvance();
|
|
4979
4999
|
i0.ɵɵclassProp("active", ctx.activeTab === "runs");
|
|
4980
5000
|
i0.ɵɵattribute("aria-selected", ctx.activeTab === "runs");
|
|
4981
5001
|
i0.ɵɵadvance(3);
|
|
4982
|
-
i0.ɵɵconditional(ctx.runsLoaded ?
|
|
5002
|
+
i0.ɵɵconditional(ctx.runsLoaded ? 53 : -1);
|
|
4983
5003
|
i0.ɵɵadvance();
|
|
4984
5004
|
i0.ɵɵclassProp("active", ctx.activeTab === "analytics");
|
|
4985
5005
|
i0.ɵɵattribute("aria-selected", ctx.activeTab === "analytics");
|
|
@@ -4989,37 +5009,37 @@ let MJTestSuiteFormComponentExtended = class MJTestSuiteFormComponentExtended ex
|
|
|
4989
5009
|
i0.ɵɵadvance(3);
|
|
4990
5010
|
i0.ɵɵclassProp("has-savebar", ctx.isDirty);
|
|
4991
5011
|
i0.ɵɵadvance();
|
|
4992
|
-
i0.ɵɵconditional(ctx.activeTab === "overview" ?
|
|
5012
|
+
i0.ɵɵconditional(ctx.activeTab === "overview" ? 61 : -1);
|
|
4993
5013
|
i0.ɵɵadvance();
|
|
4994
|
-
i0.ɵɵconditional(ctx.activeTab === "tests" ?
|
|
5014
|
+
i0.ɵɵconditional(ctx.activeTab === "tests" ? 62 : -1);
|
|
4995
5015
|
i0.ɵɵadvance();
|
|
4996
|
-
i0.ɵɵconditional(ctx.activeTab === "runs" ?
|
|
5016
|
+
i0.ɵɵconditional(ctx.activeTab === "runs" ? 63 : -1);
|
|
4997
5017
|
i0.ɵɵadvance();
|
|
4998
|
-
i0.ɵɵconditional(ctx.activeTab === "analytics" ?
|
|
5018
|
+
i0.ɵɵconditional(ctx.activeTab === "analytics" ? 64 : -1);
|
|
4999
5019
|
i0.ɵɵadvance();
|
|
5000
|
-
i0.ɵɵconditional(ctx.activeTab === "compare" ?
|
|
5020
|
+
i0.ɵɵconditional(ctx.activeTab === "compare" ? 65 : -1);
|
|
5001
5021
|
i0.ɵɵadvance();
|
|
5002
5022
|
i0.ɵɵproperty("title", ctx.showShortcuts ? "Hide keyboard shortcuts" : "Show keyboard shortcuts");
|
|
5003
5023
|
i0.ɵɵadvance(2);
|
|
5004
|
-
i0.ɵɵconditional(ctx.showShortcuts ?
|
|
5024
|
+
i0.ɵɵconditional(ctx.showShortcuts ? 68 : -1);
|
|
5005
5025
|
i0.ɵɵadvance();
|
|
5006
|
-
i0.ɵɵconditional(ctx.testingDialogService.IsPanelOpen ?
|
|
5026
|
+
i0.ɵɵconditional(ctx.testingDialogService.IsPanelOpen ? 69 : -1);
|
|
5007
5027
|
i0.ɵɵadvance();
|
|
5008
|
-
i0.ɵɵconditional(ctx.showAddTestsDialog ?
|
|
5028
|
+
i0.ɵɵconditional(ctx.showAddTestsDialog ? 70 : -1);
|
|
5009
5029
|
i0.ɵɵadvance();
|
|
5010
5030
|
i0.ɵɵclassProp("save-bar--visible", ctx.isDirty);
|
|
5011
5031
|
i0.ɵɵattribute("aria-hidden", !ctx.isDirty);
|
|
5012
5032
|
i0.ɵɵadvance(8);
|
|
5013
|
-
i0.ɵɵconditional(ctx.dirtyFieldNames.length === 1 ?
|
|
5033
|
+
i0.ɵɵconditional(ctx.dirtyFieldNames.length === 1 ? 79 : ctx.dirtyFieldNames.length > 1 ? 80 : -1);
|
|
5014
5034
|
i0.ɵɵadvance(3);
|
|
5015
5035
|
i0.ɵɵproperty("disabled", ctx.isSaving || !ctx.isDirty);
|
|
5016
5036
|
i0.ɵɵattribute("tabindex", ctx.isDirty ? 0 : -1);
|
|
5017
5037
|
i0.ɵɵadvance();
|
|
5018
|
-
i0.ɵɵconditional(ctx.isSaving ?
|
|
5038
|
+
i0.ɵɵconditional(ctx.isSaving ? 83 : 84);
|
|
5019
5039
|
i0.ɵɵadvance(2);
|
|
5020
5040
|
i0.ɵɵproperty("disabled", ctx.isSaving || !ctx.isDirty);
|
|
5021
5041
|
i0.ɵɵattribute("tabindex", ctx.isDirty ? 0 : -1);
|
|
5022
|
-
} }, dependencies: [i1.NgClass, i2.NgSelectOption, i2.ɵNgSelectMultipleOption, i2.DefaultValueAccessor, i2.NumberValueAccessor, i2.SelectControlValueAccessor, i2.NgControlStatus, i2.NgModel, i3.CdkDropList, i3.CdkDrag, i3.CdkDragHandle, i4.MJEmptyStateComponent, i4.MJButtonDirective, i4.MJAccordionPanelComponent, i4.MJAccordionTitleDirective, i4.MJAccordionBodyDirective, i5.TestRunDialogComponent, i5.EvaluationModeToggleComponent, i6.LoadingComponent, i4.MjSlidePanelComponent, i1.DatePipe], styles: ["\n\n\n\n\n[_nghost-%COMP%] {\n --test-primary: var(--mj-brand-primary);\n --test-primary-light: var(--mj-brand-primary);\n --test-success: var(--mj-status-success);\n --test-error: var(--mj-status-error);\n --test-warning: var(--mj-status-warning);\n --test-disabled: var(--mj-text-muted);\n --test-bg: var(--mj-bg-surface-card);\n --test-surface: var(--mj-bg-surface);\n --test-border: var(--mj-border-default);\n --test-text: var(--mj-text-primary);\n --test-text-secondary: var(--mj-text-secondary);\n --test-text-muted: var(--mj-text-disabled);\n --test-radius-sm: 6px;\n --test-radius-md: 10px;\n --test-radius-lg: 16px;\n --test-shadow-sm: var(--mj-shadow-sm);\n --test-shadow-md: var(--mj-shadow-md);\n --test-shadow-lg: var(--mj-shadow-lg);\n --test-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n display: block;\n height: 100%;\n}\n\n.test-suite-form[_ngcontent-%COMP%] {\n position: relative;\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--test-bg);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n}\n\n\n.breadcrumb[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n}\n\n.breadcrumb[_ngcontent-%COMP%] ol[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n list-style: none;\n margin: 0;\n padding: 0;\n font-size: 13px;\n}\n\n.breadcrumb[_ngcontent-%COMP%] li[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.breadcrumb[_ngcontent-%COMP%] a[_ngcontent-%COMP%] {\n color: var(--test-primary);\n text-decoration: none;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 8px;\n border-radius: 6px;\n transition: background 0.15s;\n}\n\n.breadcrumb[_ngcontent-%COMP%] a[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n text-decoration: none;\n}\n\n.breadcrumb[_ngcontent-%COMP%] .separator[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--test-text-muted);\n margin: 0 4px;\n}\n\n.breadcrumb[_ngcontent-%COMP%] .current[_ngcontent-%COMP%] {\n color: var(--test-text-secondary);\n font-weight: 500;\n}\n\n.breadcrumb-text[_ngcontent-%COMP%] {\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n\n.suite-header[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-bottom: 1px solid var(--test-border);\n padding: 20px;\n}\n\n.header-content[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 16px;\n gap: 16px;\n}\n\n.header-left[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n flex: 1;\n min-width: 0;\n}\n\n.suite-icon[_ngcontent-%COMP%] {\n width: 56px;\n height: 56px;\n border-radius: var(--test-radius-md);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-inverse);\n font-size: 24px;\n flex-shrink: 0;\n box-shadow: var(--test-shadow-md);\n transition: var(--test-transition);\n}\n\n.suite-icon[_ngcontent-%COMP%]:hover { transform: scale(1.05); }\n\n.suite-info[_ngcontent-%COMP%] { flex: 1; min-width: 0; }\n\n.suite-info[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: clamp(18px, 4vw, 24px);\n font-weight: 700;\n color: var(--test-text);\n word-wrap: break-word;\n}\n\n.suite-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.status-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 14px;\n border-radius: 20px;\n color: var(--mj-text-inverse);\n font-size: 12px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-badge.status-active[_ngcontent-%COMP%] { background: var(--test-success); }\n.status-badge.status-disabled[_ngcontent-%COMP%] { background: var(--test-disabled); }\n.status-badge.status-pending[_ngcontent-%COMP%] { background: var(--test-warning); }\n\n.status-badge-inline[_ngcontent-%COMP%] {\n display: inline-flex;\n padding: 2px 10px;\n border-radius: 10px;\n color: var(--mj-text-inverse);\n font-size: 11px;\n font-weight: 600;\n}\n\n.status-badge-inline.status-active[_ngcontent-%COMP%] { background: var(--test-success); }\n.status-badge-inline.status-disabled[_ngcontent-%COMP%] { background: var(--test-disabled); }\n.status-badge-inline.status-pending[_ngcontent-%COMP%] { background: var(--test-warning); }\n\n.test-count[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-size: 14px;\n color: var(--test-text-secondary);\n padding: 4px 10px;\n background: var(--test-bg);\n border-radius: var(--test-radius-sm);\n}\n\n.header-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n flex-shrink: 0;\n}\n\n.suite-description[_ngcontent-%COMP%] {\n padding: 16px;\n background: var(--mj-bg-surface-card);\n border-radius: var(--test-radius-md);\n border: 1px solid var(--test-border);\n}\n\n.suite-description[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n color: var(--test-text-secondary);\n line-height: 1.6;\n font-size: 14px;\n}\n\n\n.tabs-container[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-bottom: 1px solid var(--test-border);\n position: sticky;\n top: 0;\n z-index: 10;\n}\n\n.tabs[_ngcontent-%COMP%] {\n display: flex;\n padding: 0 20px;\n overflow-x: auto;\n scrollbar-width: none;\n}\n\n.tabs[_ngcontent-%COMP%]::-webkit-scrollbar { display: none; }\n\n.tab[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 14px 18px;\n border: none;\n background: transparent;\n border-bottom: 3px solid transparent;\n color: var(--test-text-secondary);\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: var(--test-transition);\n white-space: nowrap;\n}\n\n.tab[_ngcontent-%COMP%]:hover {\n color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.tab.active[_ngcontent-%COMP%] {\n color: var(--test-primary);\n border-bottom-color: var(--test-primary);\n font-weight: 600;\n}\n\n.tab-badge[_ngcontent-%COMP%] {\n background: var(--test-border);\n color: var(--test-text-secondary);\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.tab.active[_ngcontent-%COMP%] .tab-badge[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n color: var(--test-primary);\n}\n\n.tab-shortcut[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--test-text-muted);\n background: var(--test-bg);\n padding: 2px 6px;\n border-radius: 4px;\n font-weight: 600;\n}\n\n\n.tab-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n}\n\n\n.overview-tab[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 20px;\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-out;\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from { opacity: 0; transform: translateY(10px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n.info-section[_ngcontent-%COMP%], .config-section[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.info-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%], .config-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 20px 0;\n font-size: 18px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.info-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%], .config-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.info-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 16px;\n}\n\n.info-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.info-label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.info-value[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--test-text);\n font-weight: 500;\n}\n\n.config-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 20px;\n}\n\n.config-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.config-item[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.config-input[_ngcontent-%COMP%] {\n padding: 10px 14px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n font-size: 14px;\n transition: var(--test-transition);\n}\n\n.config-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--test-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.config-hint[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--test-text-muted);\n}\n\n\n.tests-tab[_ngcontent-%COMP%], .runs-tab[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-out;\n}\n\n.loading-state[_ngcontent-%COMP%] { padding: 0; }\n\n.skeleton-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.skeleton-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 16px;\n background: var(--test-surface);\n border-radius: var(--test-radius-md);\n border: 1px solid var(--test-border);\n}\n\n.skeleton-sequence[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n background: linear-gradient(90deg, var(--mj-border-default) 25%, var(--mj-bg-surface-sunken) 50%, var(--mj-border-default) 75%);\n background-size: 200% 100%;\n animation: _ngcontent-%COMP%_shimmer 1.5s infinite;\n}\n\n.skeleton-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n border-radius: var(--test-radius-md);\n background: linear-gradient(90deg, var(--mj-border-default) 25%, var(--mj-bg-surface-sunken) 50%, var(--mj-border-default) 75%);\n background-size: 200% 100%;\n animation: _ngcontent-%COMP%_shimmer 1.5s infinite;\n}\n\n.skeleton-content[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.skeleton-line[_ngcontent-%COMP%] {\n height: 14px;\n border-radius: 4px;\n background: linear-gradient(90deg, var(--mj-border-default) 25%, var(--mj-bg-surface-sunken) 50%, var(--mj-border-default) 75%);\n background-size: 200% 100%;\n animation: _ngcontent-%COMP%_shimmer 1.5s infinite;\n}\n\n.skeleton-line.wide[_ngcontent-%COMP%] { width: 70%; }\n.skeleton-line.narrow[_ngcontent-%COMP%] { width: 40%; }\n\n@keyframes _ngcontent-%COMP%_shimmer {\n 0% { background-position: 200% 0; }\n 100% { background-position: -200% 0; }\n}\n\n.tests-list[_ngcontent-%COMP%], .runs-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.test-item[_ngcontent-%COMP%], .run-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 16px;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.test-item[_ngcontent-%COMP%]:hover, .run-item[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n border-color: var(--test-primary-light);\n transform: translateX(4px);\n}\n\n.test-sequence[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--test-bg);\n border-radius: 50%;\n font-size: 14px;\n font-weight: 700;\n color: var(--test-text-secondary);\n flex-shrink: 0;\n}\n\n.test-icon[_ngcontent-%COMP%], .run-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: var(--test-radius-md);\n color: var(--mj-text-inverse);\n font-size: 18px;\n flex-shrink: 0;\n box-shadow: var(--test-shadow-sm);\n}\n\n.test-icon[_ngcontent-%COMP%] {\n background: var(--test-primary);\n}\n\n.test-content[_ngcontent-%COMP%], .run-content[_ngcontent-%COMP%] { flex: 1; min-width: 0; }\n\n.test-name[_ngcontent-%COMP%], .run-header[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n margin-bottom: 4px;\n}\n\n.run-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.run-id[_ngcontent-%COMP%] { font-weight: 600; }\n\n.run-status[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n}\n\n.test-status[_ngcontent-%COMP%], .run-meta[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n font-size: 12px;\n color: var(--test-text-secondary);\n}\n\n.test-status[_ngcontent-%COMP%] span[_ngcontent-%COMP%], .run-meta[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n\n.test-item[_ngcontent-%COMP%] > i[_ngcontent-%COMP%], .run-item[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] {\n color: var(--test-text-muted);\n font-size: 14px;\n transition: var(--test-transition);\n}\n\n.test-item[_ngcontent-%COMP%]:hover > i[_ngcontent-%COMP%], .run-item[_ngcontent-%COMP%]:hover > i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n transform: translateX(2px);\n}\n\n\n\n.shortcuts-toggle[_ngcontent-%COMP%] {\n position: fixed;\n bottom: 20px;\n right: 20px;\n width: 36px;\n height: 36px;\n border-radius: 50%;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n box-shadow: var(--test-shadow-md);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--test-text-secondary);\n font-size: 14px;\n z-index: 99;\n transition: var(--test-transition);\n opacity: 0.7;\n}\n\n.shortcuts-toggle[_ngcontent-%COMP%]:hover {\n opacity: 1;\n transform: scale(1.1);\n color: var(--test-primary);\n border-color: var(--test-primary);\n}\n\n.keyboard-shortcuts[_ngcontent-%COMP%] {\n position: fixed;\n bottom: 20px;\n right: 20px;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n padding: 12px 16px;\n box-shadow: var(--test-shadow-lg);\n font-size: 12px;\n z-index: 100;\n max-width: 260px;\n}\n\n.shortcuts-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-bottom: 10px;\n padding-bottom: 8px;\n border-bottom: 1px solid var(--test-border);\n font-weight: 600;\n color: var(--test-text);\n}\n\n.shortcuts-close[_ngcontent-%COMP%] {\n margin-left: auto;\n background: none;\n border: none;\n cursor: pointer;\n color: var(--test-text-muted);\n font-size: 12px;\n padding: 2px 4px;\n border-radius: 4px;\n transition: var(--test-transition);\n}\n\n.shortcuts-close[_ngcontent-%COMP%]:hover {\n color: var(--test-text);\n background: var(--test-border);\n}\n\n.shortcut-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.shortcut-item[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n color: var(--test-text-secondary);\n}\n\n.shortcut-keys[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n}\n\n.shortcut-keys[_ngcontent-%COMP%] kbd[_ngcontent-%COMP%] {\n background: var(--test-bg);\n border: 1px solid var(--test-border);\n border-radius: 4px;\n padding: 2px 6px;\n font-size: 11px;\n color: var(--test-text);\n}\n\n\n@media (max-width: 1024px) {\n .keyboard-shortcuts[_ngcontent-%COMP%], .shortcuts-toggle[_ngcontent-%COMP%] { display: none; }\n}\n\n@media (max-width: 768px) {\n .suite-header[_ngcontent-%COMP%] { padding: 16px; }\n\n .header-content[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 16px;\n }\n\n .header-actions[_ngcontent-%COMP%] {\n width: 100%;\n justify-content: stretch;\n }\n\n .header-actions[_ngcontent-%COMP%] button[_ngcontent-%COMP%] { flex: 1; }\n\n .tab-shortcut[_ngcontent-%COMP%] { display: none; }\n\n .info-grid[_ngcontent-%COMP%] { grid-template-columns: 1fr; }\n\n .test-item[_ngcontent-%COMP%], .run-item[_ngcontent-%COMP%] { padding: 14px; }\n}\n\n@media (max-width: 480px) {\n .suite-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n font-size: 18px;\n }\n\n .suite-info[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] { font-size: 16px; }\n\n .tab-badge[_ngcontent-%COMP%] { display: none; }\n\n .test-sequence[_ngcontent-%COMP%] { display: none; }\n}\n\n@media (hover: none) and (pointer: coarse) {\n .test-item[_ngcontent-%COMP%]:active, .run-item[_ngcontent-%COMP%]:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n transform: scale(0.98);\n }\n\n .tab[_ngcontent-%COMP%] { min-height: 48px; }\n .test-item[_ngcontent-%COMP%], .run-item[_ngcontent-%COMP%] { min-height: 64px; }\n}\n\n@media (prefers-reduced-motion: reduce) {\n *[_ngcontent-%COMP%], *[_ngcontent-%COMP%]::before, *[_ngcontent-%COMP%]::after {\n animation-duration: 0.01ms !important;\n transition-duration: 0.01ms !important;\n }\n}\n\n@media print {\n .header-actions[_ngcontent-%COMP%], .tabs-container[_ngcontent-%COMP%], .keyboard-shortcuts[_ngcontent-%COMP%] {\n display: none !important;\n }\n}\n\n\n\n\n.run-tags[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin-top: 8px;\n}\n\n.tag-chip[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 3px 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-brand-primary-hover);\n}\n\n.tag-mini[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 4px;\n font-size: 10px;\n font-weight: 500;\n color: var(--mj-text-muted);\n}\n\n.tag-more[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-text-disabled);\n font-weight: 500;\n}\n\n\n.run-eval-metrics[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 8px;\n}\n\n.eval-metric[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 3px 8px;\n border-radius: 6px;\n font-size: 11px;\n font-weight: 500;\n}\n\n.eval-metric.status[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.eval-metric.status.status-completed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.eval-metric.status.status-failed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.eval-metric.status.status-running[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.eval-metric.status.status-pending[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.eval-metric.human[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n border: 1px solid var(--mj-status-warning);\n color: var(--mj-status-warning);\n}\n\n.eval-metric.human[_ngcontent-%COMP%] .eval-pending[_ngcontent-%COMP%] {\n font-size: 9px;\n color: var(--mj-status-warning);\n}\n\n.eval-metric.auto[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n color: var(--mj-brand-primary-hover);\n}\n\n.eval-metric.auto.high[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-success) 30%, transparent);\n color: var(--mj-status-success);\n}\n\n.eval-metric.auto.medium[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 30%, transparent);\n color: var(--mj-status-warning);\n}\n\n.eval-metric.auto.low[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 30%, transparent);\n color: var(--mj-status-error);\n}\n\n.tag-cell[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-wrap: wrap;\n}\n\n.tag-chip-table[_ngcontent-%COMP%] {\n display: inline-block;\n padding: 3px 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n color: var(--mj-brand-primary-hover);\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n white-space: nowrap;\n max-width: 80px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n\n\n\n.analytics-tab[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-out;\n}\n\n\n\n\n\n\n\n\n\n\n.filters-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 16px;\n padding: 12px 16px 16px 16px;\n border-top: 1px solid var(--test-border);\n}\n\n.filter-group[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.filter-group[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.filter-buttons[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.filter-btn[_ngcontent-%COMP%] {\n padding: 8px 16px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n background: var(--test-surface);\n color: var(--test-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.filter-btn[_ngcontent-%COMP%]:hover {\n border-color: var(--test-primary);\n color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.filter-btn.active[_ngcontent-%COMP%] {\n background: var(--test-primary);\n border-color: var(--test-primary);\n color: var(--mj-text-inverse);\n}\n\n.filter-btn.tag-btn[_ngcontent-%COMP%] {\n padding: 6px 12px;\n font-size: 12px;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n}\n\n.filter-btn.tag-btn[_ngcontent-%COMP%] i.fa-check[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n.filter-btn.tag-btn.all-tags-btn[_ngcontent-%COMP%] {\n font-weight: 600;\n}\n\n.filter-btn.tag-btn.all-tags-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n}\n\n.filter-hint[_ngcontent-%COMP%] {\n font-weight: 400;\n font-size: 10px;\n color: var(--test-primary);\n text-transform: none;\n letter-spacing: normal;\n}\n\n.tag-filters[_ngcontent-%COMP%] {\n max-height: 120px;\n overflow-y: auto;\n}\n\n\n.analytics-kpis[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.kpi-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 20px;\n box-shadow: var(--test-shadow-sm);\n transition: var(--test-transition);\n}\n\n.kpi-card[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: var(--test-shadow-md);\n}\n\n.kpi-icon[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-radius: var(--test-radius-md);\n color: var(--test-primary);\n font-size: 20px;\n}\n\n.kpi-icon.success[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.kpi-icon.info[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.kpi-icon.warning[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--test-warning);\n}\n\n.kpi-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.kpi-value[_ngcontent-%COMP%] {\n font-size: 24px;\n font-weight: 700;\n color: var(--test-text);\n line-height: 1.2;\n}\n\n.kpi-label[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-secondary);\n margin-top: 2px;\n}\n\n.kpi-trend[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 12px;\n font-weight: 600;\n margin-top: 4px;\n padding: 2px 8px;\n border-radius: 10px;\n background: var(--mj-bg-surface-sunken);\n color: var(--test-text-secondary);\n}\n\n.kpi-trend.trend-up[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.kpi-trend.trend-down[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n\n.analytics-table-section[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.analytics-table-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 16px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.analytics-table-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.analytics-table-wrapper[_ngcontent-%COMP%] {\n overflow-x: auto;\n margin: 0 -24px;\n padding: 0 24px;\n}\n\n.analytics-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.analytics-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n text-align: left;\n padding: 12px 16px;\n background: var(--mj-bg-surface-card);\n border-bottom: 2px solid var(--test-border);\n font-weight: 600;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n font-size: 11px;\n letter-spacing: 0.5px;\n white-space: nowrap;\n}\n\n.analytics-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 14px 16px;\n border-bottom: 1px solid var(--test-border);\n color: var(--test-text);\n}\n\n.analytics-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.clickable-row[_ngcontent-%COMP%] {\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.analytics-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.clickable-row[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.status-chip[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 4px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-chip.status-completed[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--test-success); }\n.status-chip.status-passed[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--test-success); }\n.status-chip.status-failed[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface)); color: var(--test-error); }\n.status-chip.status-error[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--test-warning); }\n.status-chip.status-running[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--test-primary); }\n.status-chip.status-pending[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n.status-chip.status-cancelled[_ngcontent-%COMP%] { background: var(--mj-bg-surface-sunken); color: var(--test-disabled); }\n.status-chip.status-missing[_ngcontent-%COMP%] { background: var(--mj-bg-surface-sunken); color: var(--test-text-muted); }\n.status-chip.status-timeout[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--test-warning); }\n.status-chip.status-skipped[_ngcontent-%COMP%] { background: var(--mj-bg-surface-sunken); color: var(--test-disabled); }\n\n.pass-rate-cell[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 100px;\n}\n\n.pass-rate-bar[_ngcontent-%COMP%] {\n height: 6px;\n border-radius: 3px;\n background: var(--test-success);\n transition: width 0.3s ease;\n max-width: 60px;\n}\n\n.pass-rate-bar.medium[_ngcontent-%COMP%] { background: var(--test-warning); }\n.pass-rate-bar.low[_ngcontent-%COMP%] { background: var(--test-error); }\n\n\n.analytics-subnav[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 8px;\n margin-bottom: 20px;\n box-shadow: var(--test-shadow-sm);\n display: inline-flex;\n}\n\n.subnav-tabs[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n background: var(--test-bg);\n border-radius: var(--test-radius-md);\n padding: 4px;\n}\n\n.subnav-tab[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n border: none;\n border-radius: var(--test-radius-sm);\n background: transparent;\n color: var(--test-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.subnav-tab[_ngcontent-%COMP%]:hover {\n color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.subnav-tab.active[_ngcontent-%COMP%] {\n background: var(--test-surface);\n color: var(--test-primary);\n box-shadow: var(--test-shadow-sm);\n}\n\n.subnav-tab[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n\n.matrix-section[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 16px;\n box-shadow: var(--test-shadow-sm);\n display: flex;\n flex-direction: column;\n max-height: calc(100vh - 280px);\n min-height: 300px;\n}\n\n.matrix-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 12px;\n margin-bottom: 12px;\n padding-bottom: 12px;\n border-bottom: 1px solid var(--test-border);\n flex-shrink: 0;\n}\n\n.matrix-header-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.matrix-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 0;\n font-size: 15px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.matrix-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.matrix-run-count[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-muted);\n font-weight: 500;\n}\n\n\n.matrix-filter-input[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--test-border);\n border-radius: 6px;\n padding: 4px 10px;\n min-width: 180px;\n}\n\n.matrix-filter-input[_ngcontent-%COMP%] i.fa-search[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled);\n font-size: 12px;\n}\n\n.matrix-filter-input[_ngcontent-%COMP%] .filter-input[_ngcontent-%COMP%] {\n border: none;\n background: transparent;\n outline: none;\n font-size: 12px;\n color: var(--test-text);\n width: 100%;\n}\n\n.matrix-filter-input[_ngcontent-%COMP%] .filter-input[_ngcontent-%COMP%]::placeholder {\n color: var(--mj-text-disabled);\n}\n\n.clear-filter-btn[_ngcontent-%COMP%] {\n border: none;\n background: none;\n padding: 2px 4px;\n cursor: pointer;\n color: var(--mj-text-disabled);\n font-size: 10px;\n border-radius: 3px;\n transition: all 0.15s ease;\n}\n\n.clear-filter-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-border-default);\n color: var(--mj-text-muted);\n}\n\n\n.matrix-scroll-container[_ngcontent-%COMP%] {\n flex: 1;\n overflow: auto;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n}\n\n.test-matrix[_ngcontent-%COMP%] {\n display: table;\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.test-matrix[_ngcontent-%COMP%] thead[_ngcontent-%COMP%] {\n display: table-header-group;\n}\n\n.test-matrix[_ngcontent-%COMP%] thead[_ngcontent-%COMP%] tr[_ngcontent-%COMP%] {\n display: table-row;\n}\n\n.test-matrix[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] {\n display: table-row-group;\n}\n\n.test-matrix[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%] {\n display: table-row;\n cursor: pointer;\n transition: background-color 0.15s ease;\n}\n\n.test-matrix[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.test-matrix[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.row-selected[_ngcontent-%COMP%] {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent) !important;\n}\n\n.test-matrix[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.row-selected[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n border-top: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n border-bottom: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.test-matrix[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.row-selected[_ngcontent-%COMP%] .seq-cell[_ngcontent-%COMP%], \n.test-matrix[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.row-selected[_ngcontent-%COMP%] .test-name-cell[_ngcontent-%COMP%] {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent) !important;\n}\n\n.test-matrix[_ngcontent-%COMP%] tfoot[_ngcontent-%COMP%] {\n display: table-footer-group;\n}\n\n.test-matrix[_ngcontent-%COMP%] th[_ngcontent-%COMP%], \n.test-matrix[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n display: table-cell;\n border: 1px solid var(--test-border);\n padding: 8px 12px;\n text-align: center;\n vertical-align: middle;\n}\n\n.test-matrix[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n background: var(--test-bg);\n font-weight: 600;\n font-size: 11px;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n position: sticky;\n top: 0;\n z-index: 10;\n border-bottom: 3px solid var(--mj-text-secondary) !important;\n}\n\n\n.test-matrix[_ngcontent-%COMP%] .seq-header[_ngcontent-%COMP%], \n.test-matrix[_ngcontent-%COMP%] .seq-cell[_ngcontent-%COMP%] {\n width: 36px;\n min-width: 36px;\n max-width: 36px;\n text-align: center;\n position: sticky;\n left: 0;\n font-size: 11px;\n color: var(--mj-text-muted);\n border-right: 1px solid var(--test-border);\n padding: 6px 4px !important;\n}\n\n\n.test-matrix[_ngcontent-%COMP%] .seq-header[_ngcontent-%COMP%] {\n cursor: pointer;\n font-weight: 600;\n background: var(--test-bg);\n z-index: 12; \n top: 0;\n}\n\n\n.test-matrix[_ngcontent-%COMP%] .seq-cell[_ngcontent-%COMP%] {\n background: var(--test-surface);\n z-index: 2;\n}\n\n.test-matrix[_ngcontent-%COMP%] .seq-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 9px;\n margin-left: 2px;\n opacity: 0.6;\n}\n\n.test-matrix[_ngcontent-%COMP%] .seq-header[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.test-matrix[_ngcontent-%COMP%] .test-name-header[_ngcontent-%COMP%] {\n text-align: left;\n min-width: 150px;\n max-width: 500px;\n width: auto;\n position: sticky;\n left: 36px;\n background: var(--test-bg);\n z-index: 11;\n border-right: 2px solid var(--test-border);\n cursor: pointer;\n}\n\n.test-matrix[_ngcontent-%COMP%] .test-name-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 9px;\n margin-left: 4px;\n opacity: 0.6;\n}\n\n.test-matrix[_ngcontent-%COMP%] .test-name-header[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.test-matrix[_ngcontent-%COMP%] .run-header[_ngcontent-%COMP%] {\n min-width: 120px;\n width: 120px;\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n\n.test-matrix[_ngcontent-%COMP%] .spacer-header[_ngcontent-%COMP%], \n.test-matrix[_ngcontent-%COMP%] .spacer-cell[_ngcontent-%COMP%] {\n width: 100%;\n min-width: 20px;\n background: var(--test-bg);\n border: none;\n}\n\n.test-matrix[_ngcontent-%COMP%] .spacer-cell[_ngcontent-%COMP%] {\n background: var(--test-surface);\n}\n\n.test-matrix[_ngcontent-%COMP%] .run-header[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.run-header-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n}\n\n.run-date[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.run-pass-rate[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 700;\n padding: 2px 8px;\n border-radius: 10px;\n}\n\n.run-pass-rate.high[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.run-pass-rate.medium[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--test-warning);\n}\n\n.run-pass-rate.low[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n.run-tags[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n}\n\n.tag-tiny[_ngcontent-%COMP%] {\n font-size: 9px;\n padding: 2px 6px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--test-primary);\n border-radius: 8px;\n white-space: nowrap;\n max-width: 60px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n\n.run-tags-header[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 3px;\n justify-content: center;\n margin-bottom: 4px;\n}\n\n.tag-chip-header[_ngcontent-%COMP%] {\n display: inline-block;\n padding: 3px 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n color: var(--mj-brand-primary-hover);\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n white-space: nowrap;\n max-width: 70px;\n overflow: hidden;\n text-overflow: ellipsis;\n text-transform: none;\n letter-spacing: normal;\n}\n\n.tag-more-header[_ngcontent-%COMP%] {\n font-size: 9px;\n color: var(--test-text-secondary);\n padding: 2px 4px;\n}\n\n.test-matrix[_ngcontent-%COMP%] .test-name-cell[_ngcontent-%COMP%] {\n text-align: left;\n min-width: 150px;\n max-width: 500px;\n width: auto;\n position: sticky;\n left: 36px;\n background: var(--test-surface);\n z-index: 2;\n border-right: 2px solid var(--test-border);\n padding: 6px 10px !important;\n}\n\n.test-name[_ngcontent-%COMP%] {\n display: block;\n white-space: nowrap;\n font-weight: 500;\n color: var(--test-text);\n font-size: 12px;\n}\n\n.result-cell[_ngcontent-%COMP%] {\n position: relative;\n min-width: 120px;\n width: 120px;\n transition: var(--test-transition);\n}\n\n.result-cell.clickable[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.result-cell.clickable[_ngcontent-%COMP%]:hover {\n transform: scale(1.1);\n box-shadow: var(--mj-shadow-md);\n z-index: 5;\n}\n\n.result-cell[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n\n.result-cell.cell-passed[_ngcontent-%COMP%], \n.result-cell.cell-failed[_ngcontent-%COMP%], \n.result-cell.cell-error[_ngcontent-%COMP%], \n.result-cell.cell-timeout[_ngcontent-%COMP%], \n.result-cell.cell-running[_ngcontent-%COMP%], \n.result-cell.cell-pending[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n color: var(--test-text);\n}\n\n\n.result-cell.cell-skipped[_ngcontent-%COMP%] {\n background: repeating-linear-gradient(\n 45deg,\n var(--mj-bg-surface-card),\n var(--mj-bg-surface-card) 4px,\n var(--mj-border-default) 4px,\n var(--mj-border-default) 8px\n );\n color: var(--test-disabled);\n}\n\n.result-cell.cell-none[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n color: var(--test-text-muted);\n}\n\n.cell-score[_ngcontent-%COMP%] {\n display: block;\n font-size: 10px;\n font-weight: 600;\n margin-top: 2px;\n}\n\n\n.cell-eval-stack[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n flex-wrap: nowrap;\n}\n\n.result-cell.multi-eval[_ngcontent-%COMP%] {\n min-width: 120px;\n width: auto;\n}\n\n\n.cell-status.status-timeout[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 11px;\n}\n\n.cell-status.status-passed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-status.status-failed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-status.status-error[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status.status-skipped[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.cell-status.status-running[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.cell-status.status-pending[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.cell-human[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 50%;\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n font-size: 10px;\n}\n\n.cell-auto[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 10px;\n font-weight: 600;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.cell-auto.high[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-auto.medium[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-auto.low[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-none-indicator[_ngcontent-%COMP%] {\n color: var(--test-text-muted);\n opacity: 0.5;\n}\n\n.matrix-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: var(--test-text-muted);\n padding: 12px;\n background: var(--test-bg);\n border-radius: var(--test-radius-sm);\n}\n\n.matrix-info[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n\n\n\n.chart-section[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.chart-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 16px;\n margin-bottom: 20px;\n padding-bottom: 16px;\n border-bottom: 1px solid var(--test-border);\n}\n\n.chart-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.chart-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.chart-legend[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.chart-legend[_ngcontent-%COMP%] .legend-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n font-weight: 500;\n padding: 4px 10px;\n border-radius: 12px;\n}\n\n.chart-legend[_ngcontent-%COMP%] .legend-item.chart-passed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.chart-legend[_ngcontent-%COMP%] .legend-item.chart-failed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n.chart-legend[_ngcontent-%COMP%] .legend-item.chart-error[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--test-warning);\n}\n\n.chart-legend[_ngcontent-%COMP%] .legend-item.chart-skipped[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--test-disabled);\n}\n\n.chart-container[_ngcontent-%COMP%] {\n min-height: 500px;\n position: relative;\n overflow: hidden;\n background: var(--mj-bg-surface-card);\n border-radius: var(--test-radius-md);\n border: 1px solid var(--test-border);\n}\n\n.d3-chart[_ngcontent-%COMP%] {\n width: 100%;\n height: 500px;\n}\n\n.d3-chart[_ngcontent-%COMP%] svg[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n}\n\n\n.d3-chart[_ngcontent-%COMP%] .node[_ngcontent-%COMP%] {\n cursor: pointer;\n transition: transform 0.2s ease;\n}\n\n.d3-chart[_ngcontent-%COMP%] .node[_ngcontent-%COMP%]:hover {\n transform: scale(1.05);\n}\n\n.d3-chart[_ngcontent-%COMP%] .node-label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 500;\n fill: var(--test-text);\n pointer-events: none;\n}\n\n.d3-chart[_ngcontent-%COMP%] .link[_ngcontent-%COMP%] {\n fill: none;\n stroke-opacity: 0.4;\n transition: stroke-opacity 0.2s ease;\n}\n\n.d3-chart[_ngcontent-%COMP%] .link[_ngcontent-%COMP%]:hover {\n stroke-opacity: 0.8;\n}\n\n.d3-chart[_ngcontent-%COMP%] .tooltip[_ngcontent-%COMP%] {\n position: absolute;\n padding: 10px 14px;\n background: var(--mj-bg-overlay);\n color: var(--mj-text-inverse);\n border-radius: 8px;\n font-size: 12px;\n pointer-events: none;\n z-index: 100;\n box-shadow: var(--mj-shadow-lg);\n max-width: 250px;\n}\n\n.d3-chart[_ngcontent-%COMP%] .tooltip-title[_ngcontent-%COMP%] {\n font-weight: 600;\n margin-bottom: 4px;\n}\n\n.d3-chart[_ngcontent-%COMP%] .tooltip-value[_ngcontent-%COMP%] {\n opacity: 0.8;\n}\n\n.chart-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: var(--test-text-muted);\n padding: 12px;\n background: var(--test-bg);\n border-radius: var(--test-radius-sm);\n margin-top: 16px;\n}\n\n.chart-info[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n\n\n\n.compare-tab[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-out;\n}\n\n.compare-selection[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr auto 1fr;\n gap: 24px;\n align-items: flex-start;\n margin-bottom: 24px;\n}\n\n.compare-run-selector[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 20px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.compare-run-selector[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 16px 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.run-selector-list[_ngcontent-%COMP%] {\n max-height: 200px;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-bottom: 12px;\n}\n\n.run-selector-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.run-selector-item[_ngcontent-%COMP%]:hover {\n border-color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.run-selector-item.selected[_ngcontent-%COMP%] {\n border-color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n}\n\n.run-selector-item.disabled[_ngcontent-%COMP%] {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.selector-status[_ngcontent-%COMP%] {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.selector-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.selector-date[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 500;\n color: var(--test-text);\n}\n\n.selector-rate[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--test-text-secondary);\n}\n\n.selector-tags[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n flex-wrap: wrap;\n}\n\n.selected-run-preview[_ngcontent-%COMP%] {\n padding: 12px;\n background: var(--mj-bg-surface-card);\n border-radius: var(--test-radius-sm);\n border: 1px solid var(--test-border);\n}\n\n.preview-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.preview-label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n color: var(--test-text-muted);\n}\n\n.clear-btn[_ngcontent-%COMP%] {\n padding: 4px 8px;\n border: none;\n background: transparent;\n color: var(--test-error);\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n}\n\n.clear-btn[_ngcontent-%COMP%]:hover { text-decoration: underline; }\n\n.preview-details[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n font-size: 12px;\n color: var(--test-text);\n}\n\n.preview-rate[_ngcontent-%COMP%] {\n font-weight: 600;\n color: var(--test-success);\n}\n\n.compare-vs[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n background: var(--test-bg);\n border-radius: 50%;\n color: var(--test-text-muted);\n font-size: 16px;\n align-self: center;\n margin-top: 60px;\n}\n\n\n.compare-results[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-out;\n}\n\n.compare-summary[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.compare-summary-card[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 20px;\n box-shadow: var(--test-shadow-sm);\n text-align: center;\n}\n\n.compare-summary-card[_ngcontent-%COMP%] .summary-label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n color: var(--test-text-muted);\n margin-bottom: 8px;\n}\n\n.compare-summary-card[_ngcontent-%COMP%] .summary-value[_ngcontent-%COMP%] {\n font-size: 24px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n}\n\n.compare-summary-card[_ngcontent-%COMP%] .summary-value.positive[_ngcontent-%COMP%] { color: var(--test-success); }\n.compare-summary-card[_ngcontent-%COMP%] .summary-value.negative[_ngcontent-%COMP%] { color: var(--test-error); }\n\n.compare-summary-card.improved[_ngcontent-%COMP%] {\n border-left: 4px solid var(--test-success);\n}\n\n.compare-summary-card.improved[_ngcontent-%COMP%] .summary-value[_ngcontent-%COMP%] { color: var(--test-success); }\n\n.compare-summary-card.regressed[_ngcontent-%COMP%] {\n border-left: 4px solid var(--test-error);\n}\n\n.compare-summary-card.regressed[_ngcontent-%COMP%] .summary-value[_ngcontent-%COMP%] { color: var(--test-error); }\n\n\n.compare-table-section[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.compare-table-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 16px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.compare-table-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.compare-table-wrapper[_ngcontent-%COMP%] {\n overflow-x: auto;\n}\n\n.compare-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.compare-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n text-align: left;\n padding: 12px 16px;\n background: var(--mj-bg-surface-card);\n border-bottom: 2px solid var(--test-border);\n font-weight: 600;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n font-size: 11px;\n letter-spacing: 0.5px;\n white-space: nowrap;\n}\n\n.compare-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 14px 16px;\n border-bottom: 1px solid var(--test-border);\n color: var(--test-text);\n}\n\n.compare-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.improved[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 5%, transparent);\n}\n\n.compare-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.regressed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 5%, transparent);\n}\n\n.test-name-cell[_ngcontent-%COMP%] {\n font-weight: 500;\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.positive[_ngcontent-%COMP%] { color: var(--test-success); }\n.negative[_ngcontent-%COMP%] { color: var(--test-error); }\n.muted[_ngcontent-%COMP%] { color: var(--test-text-muted); }\n\n.change-indicator[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.change-indicator.improved[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.change-indicator.regressed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n.change-indicator.unchanged[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--test-text-muted);\n}\n\n\n\n\n@media (max-width: 1024px) {\n .compare-selection[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n gap: 16px;\n }\n\n .compare-vs[_ngcontent-%COMP%] {\n margin: 0;\n align-self: center;\n justify-self: center;\n }\n\n .analytics-kpis[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n}\n\n@media (max-width: 768px) {\n .filter-buttons[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .filter-btn[_ngcontent-%COMP%] {\n width: 100%;\n text-align: center;\n }\n\n .analytics-kpis[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .kpi-card[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .kpi-value[_ngcontent-%COMP%] {\n font-size: 20px;\n }\n\n .compare-summary[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .analytics-table-wrapper[_ngcontent-%COMP%], \n .compare-table-wrapper[_ngcontent-%COMP%] {\n margin: 0 -20px;\n padding: 0 20px;\n }\n\n .run-selector-list[_ngcontent-%COMP%] {\n max-height: 150px;\n }\n}\n\n@media (max-width: 480px) {\n .compare-summary[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .compare-summary-card[_ngcontent-%COMP%] .summary-value[_ngcontent-%COMP%] {\n font-size: 20px;\n }\n\n .analytics-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%], \n .analytics-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%], \n .compare-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%], \n .compare-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 10px 12px;\n font-size: 12px;\n }\n}\n\n\n\n\n\n\n.cell-human[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 3px;\n min-width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 10px;\n}\n\n.cell-human.no-feedback[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n}\n\n.cell-human.no-feedback[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n}\n\n.cell-human.has-feedback[_ngcontent-%COMP%] {\n padding: 0 6px;\n border-radius: 12px;\n min-width: 36px;\n}\n\n.cell-human.has-feedback[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 9px;\n}\n\n.cell-human.has-feedback[_ngcontent-%COMP%] .rating-value[_ngcontent-%COMP%] {\n font-weight: 700;\n font-size: 11px;\n}\n\n\n.cell-human.rating-low[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-human.rating-medium[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-human.rating-good[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-human.rating-excellent[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n\n.cell-auto[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 3px;\n min-width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 10px;\n}\n\n.cell-auto.no-score[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n}\n\n.cell-auto.no-score[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n}\n\n.cell-auto.has-score[_ngcontent-%COMP%] {\n padding: 0 6px;\n border-radius: 12px;\n min-width: 36px;\n}\n\n.cell-auto.has-score[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 9px;\n}\n\n.cell-auto.has-score[_ngcontent-%COMP%] .score-value[_ngcontent-%COMP%] {\n font-weight: 700;\n font-size: 10px;\n}\n\n\n.cell-auto.score-low[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-auto.score-medium[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-auto.score-good[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-auto.score-excellent[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n\n.cell-status[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 11px;\n}\n\n.cell-status.status-passed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-status.status-failed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-status.status-error[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status.status-timeout[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status.status-skipped[_ngcontent-%COMP%], \n.cell-status.status-pending[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.cell-status.status-running[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n\n.result-cell.cell-not-run[_ngcontent-%COMP%] {\n background: repeating-linear-gradient(\n 45deg,\n var(--mj-bg-surface-card),\n var(--mj-bg-surface-card) 4px,\n var(--mj-border-default) 4px,\n var(--mj-border-default) 8px\n );\n color: var(--mj-text-disabled);\n}\n\n.result-cell.cell-not-run[_ngcontent-%COMP%] .cell-eval-stack[_ngcontent-%COMP%] {\n opacity: 0.6;\n}\n\n.cell-not-run-indicator[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n color: var(--mj-text-disabled);\n font-size: 11px;\n}\n\n\n\n\n.test-matrix[_ngcontent-%COMP%] tfoot[_ngcontent-%COMP%] {\n position: sticky;\n bottom: 0;\n z-index: 2;\n}\n\n.totals-row[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n border-top: 2px solid var(--test-border);\n}\n\n.totals-row[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 10px 12px;\n font-weight: 600;\n}\n\n.totals-row[_ngcontent-%COMP%] .totals-label[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n font-size: 12px;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.totals-row[_ngcontent-%COMP%] .totals-cell[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n}\n\n.totals-stack[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n}\n\n.totals-status[_ngcontent-%COMP%], \n.totals-human[_ngcontent-%COMP%], \n.totals-auto[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n padding: 2px 8px;\n border-radius: 10px;\n white-space: nowrap;\n}\n\n.totals-status[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.totals-status[_ngcontent-%COMP%] .pass-count[_ngcontent-%COMP%] {\n font-weight: 700;\n}\n\n.totals-human[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.totals-human[_ngcontent-%COMP%] .avg-label[_ngcontent-%COMP%] {\n font-weight: 700;\n}\n\n.totals-human[_ngcontent-%COMP%] .count-label[_ngcontent-%COMP%] {\n font-size: 10px;\n opacity: 0.8;\n}\n\n.totals-auto[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.totals-auto[_ngcontent-%COMP%] .avg-label[_ngcontent-%COMP%] {\n font-weight: 700;\n}\n\n.totals-auto[_ngcontent-%COMP%] .count-label[_ngcontent-%COMP%] {\n font-size: 10px;\n opacity: 0.8;\n}\n\n\n\n\n\n.edit-section[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.edit-section-header[_ngcontent-%COMP%] {\n margin: 0 0 18px 0;\n}\n\n.edit-section-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 4px 0;\n font-size: 18px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.edit-section-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.edit-section-sub[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 12px;\n color: var(--test-text-muted);\n}\n\n.edit-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 18px;\n}\n\n@media (max-width: 720px) {\n .edit-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n}\n\n.edit-field[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n min-width: 0;\n}\n\n.edit-field--full[_ngcontent-%COMP%] {\n grid-column: 1 / -1;\n}\n\n.edit-field[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.edit-field[_ngcontent-%COMP%] .required[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n margin-left: 2px;\n}\n\n.config-textarea[_ngcontent-%COMP%] {\n resize: vertical;\n min-height: 72px;\n font-family: inherit;\n line-height: 1.5;\n}\n\n.select-wrapper[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.select-wrapper[_ngcontent-%COMP%] select.config-input[_ngcontent-%COMP%] {\n padding-right: 36px;\n appearance: none;\n background-color: var(--test-surface);\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%2364748b' d='M1.41 0L6 4.59 10.59 0 12 1.41l-6 6-6-6z'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 14px center;\n background-size: 10px 7px;\n}\n\n\n.tag-editor[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n padding: 8px 10px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n background: var(--test-surface);\n transition: var(--test-transition);\n cursor: text;\n min-height: 42px;\n align-items: center;\n}\n\n.tag-editor[_ngcontent-%COMP%]:focus-within {\n border-color: var(--test-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.tag-chip-editable[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 3px 4px 3px 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n border-radius: 999px;\n font-size: 12px;\n font-weight: 600;\n line-height: 1;\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n}\n\n.tag-chip-editable[_ngcontent-%COMP%] .tag-remove[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n border: none;\n background: transparent;\n color: var(--mj-brand-primary);\n cursor: pointer;\n font-size: 10px;\n transition: background 0.15s;\n}\n\n.tag-chip-editable[_ngcontent-%COMP%] .tag-remove[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n color: var(--mj-brand-primary-hover);\n}\n\n.tag-input-inline[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 140px;\n border: none;\n background: transparent;\n outline: none;\n font-size: 13px;\n color: var(--test-text);\n padding: 4px 2px;\n}\n\n.tag-input-inline[_ngcontent-%COMP%]::placeholder {\n color: var(--test-text-muted);\n}\n\n\n.meta-section[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--test-radius-md);\n padding: 14px 18px;\n border: 1px solid var(--test-border);\n}\n\n.meta-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 14px;\n}\n\n.meta-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.meta-label[_ngcontent-%COMP%] {\n font-size: 10px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.meta-value[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-secondary);\n font-weight: 500;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.meta-mono[_ngcontent-%COMP%] {\n font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;\n font-size: 11px;\n}\n\n\n.dirty-indicator[_ngcontent-%COMP%] {\n display: inline-block;\n margin-left: 8px;\n font-size: 14px;\n color: var(--mj-status-warning);\n line-height: 1;\n animation: _ngcontent-%COMP%_pulseDot 1.8s ease-in-out infinite;\n vertical-align: middle;\n}\n\n@keyframes _ngcontent-%COMP%_pulseDot {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.5; transform: scale(0.85); }\n}\n\n.unsaved-pill[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning-text, var(--mj-status-warning));\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 30%, transparent);\n border-radius: 999px;\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.4px;\n}\n\n.unsaved-pill[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 6px;\n animation: _ngcontent-%COMP%_pulseDot 1.8s ease-in-out infinite;\n}\n\n\n\n.tab-content.has-savebar[_ngcontent-%COMP%] {\n padding-bottom: 84px;\n}\n\n\n\n\n\n.save-bar[_ngcontent-%COMP%] {\n position: absolute;\n left: 16px;\n right: 96px; \n bottom: 16px;\n z-index: 50;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n padding: 12px 16px 12px 20px;\n background: var(--mj-bg-surface-elevated, var(--test-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 25%, var(--test-border));\n border-radius: 14px;\n box-shadow: 0 12px 32px color-mix(in srgb, var(--mj-status-warning) 10%, rgba(0, 0, 0, 0.18));\n backdrop-filter: blur(8px);\n \n\n\n opacity: 0;\n transform: translateY(calc(100% + 32px));\n pointer-events: none;\n transition:\n transform 420ms cubic-bezier(0.16, 1, 0.3, 1),\n opacity 260ms cubic-bezier(0.16, 1, 0.3, 1);\n will-change: transform, opacity;\n}\n\n.save-bar--visible[_ngcontent-%COMP%] {\n opacity: 1;\n transform: translateY(0);\n pointer-events: auto;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .save-bar[_ngcontent-%COMP%] {\n transition: opacity 180ms ease-out;\n transform: none;\n }\n .save-bar--visible[_ngcontent-%COMP%] {\n transform: none;\n }\n}\n\n.save-bar-message[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n min-width: 0;\n}\n\n.save-bar-dot[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n font-size: 12px;\n line-height: 1;\n animation: _ngcontent-%COMP%_pulseDot 1.8s ease-in-out infinite;\n}\n\n.save-bar-text[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.save-bar-text[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--test-text);\n font-weight: 700;\n}\n\n.save-bar-fields[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-muted);\n}\n\n.save-bar-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-shrink: 0;\n}\n\n.save-bar-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 9px 16px;\n font-size: 13px;\n font-weight: 600;\n border-radius: 8px;\n border: 1px solid transparent;\n cursor: pointer;\n transition: var(--test-transition);\n font-family: inherit;\n}\n\n.save-bar-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.save-bar-btn--primary[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse, white);\n border-color: var(--mj-brand-primary);\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-brand-primary) 35%, transparent);\n}\n\n.save-bar-btn--primary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover, var(--mj-brand-primary));\n transform: translateY(-1px);\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-brand-primary) 45%, transparent);\n}\n\n.save-bar-btn--primary[_ngcontent-%COMP%]:active:not(:disabled) {\n transform: translateY(0);\n}\n\n.save-bar-btn--ghost[_ngcontent-%COMP%] {\n background: transparent;\n color: var(--test-text-secondary);\n border-color: var(--test-border);\n}\n\n.save-bar-btn--ghost[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n border-color: var(--test-text-muted);\n}\n\n.save-bar-kbd[_ngcontent-%COMP%] {\n display: inline-flex;\n gap: 3px;\n margin-left: 6px;\n opacity: 0.85;\n}\n\n.save-bar-kbd[_ngcontent-%COMP%] kbd[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 4px;\n font-size: 10px;\n font-weight: 600;\n font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;\n background: color-mix(in srgb, white 18%, transparent);\n border: 1px solid color-mix(in srgb, white 35%, transparent);\n border-radius: 4px;\n color: inherit;\n}\n\n@media (max-width: 640px) {\n .save-bar[_ngcontent-%COMP%] {\n left: 8px;\n right: 8px;\n bottom: 88px; \n flex-direction: column;\n align-items: stretch;\n padding: 12px;\n }\n .save-bar-actions[_ngcontent-%COMP%] {\n justify-content: space-between;\n }\n .save-bar-kbd[_ngcontent-%COMP%] {\n display: none;\n }\n}\n\n\n\n\n\n.tests-actionbar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding: 12px 16px;\n margin-bottom: 16px;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n}\n\n.tests-actionbar-text[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n flex-wrap: wrap;\n min-width: 0;\n}\n\n.tests-actionbar-text[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--test-text);\n font-weight: 700;\n}\n\n.tests-actionbar-count[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 22px;\n height: 22px;\n padding: 0 8px;\n border-radius: 999px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n font-size: 12px;\n font-weight: 700;\n}\n\n.tests-actionbar-hint[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-muted);\n}\n\n.tests-actionbar-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n flex-shrink: 0;\n}\n\n\n.tests-list[cdk-drop-list][_ngcontent-%COMP%] .test-item[_ngcontent-%COMP%]:hover, \n.tests-list[_ngcontent-%COMP%] .test-item.cdk-drag[_ngcontent-%COMP%]:hover {\n transform: none;\n}\n\n\n.test-item.cdk-drag[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.test-item[_ngcontent-%COMP%] .test-content[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n\n.test-drag-handle[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 28px;\n border-radius: 4px;\n color: var(--test-text-muted);\n cursor: grab;\n flex-shrink: 0;\n transition: background 0.15s, color 0.15s;\n user-select: none;\n}\n\n.test-drag-handle[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n color: var(--test-primary);\n}\n\n.test-drag-handle[_ngcontent-%COMP%]:active, \n.cdk-drag-preview[_ngcontent-%COMP%] .test-drag-handle[_ngcontent-%COMP%] {\n cursor: grabbing;\n}\n\n\n.test-remove-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border-radius: 50%;\n border: none;\n background: transparent;\n color: var(--test-text-muted);\n cursor: pointer;\n flex-shrink: 0;\n opacity: 0;\n transition: opacity 0.15s, background 0.15s, color 0.15s;\n}\n\n.test-item[_ngcontent-%COMP%]:hover .test-remove-btn[_ngcontent-%COMP%], \n.test-remove-btn[_ngcontent-%COMP%]:focus-visible {\n opacity: 1;\n}\n\n.test-remove-btn[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-status-error) 12%, transparent);\n color: var(--mj-status-error);\n}\n\n.test-chevron[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n\n.test-remove-confirm[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 4px 8px 4px 12px;\n border-radius: 999px;\n background: color-mix(in srgb, var(--mj-status-error) 8%, var(--test-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 30%, transparent);\n flex-shrink: 0;\n}\n\n.test-remove-confirm-text[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-status-error-text, var(--mj-status-error));\n}\n\n.test-remove-confirm-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 4px 10px;\n border-radius: 6px;\n border: 1px solid transparent;\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n font-family: inherit;\n transition: var(--test-transition);\n}\n\n.test-remove-confirm-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.test-remove-confirm-btn--danger[_ngcontent-%COMP%] {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse, white);\n}\n\n.test-remove-confirm-btn--danger[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-status-error) 88%, black);\n}\n\n.test-remove-confirm-btn--ghost[_ngcontent-%COMP%] {\n background: transparent;\n color: var(--test-text-secondary);\n border-color: var(--test-border);\n}\n\n.test-remove-confirm-btn--ghost[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n}\n\n\n.cdk-drag-preview[_ngcontent-%COMP%] {\n box-shadow: 0 12px 32px rgba(0, 0, 0, 0.25);\n border-radius: var(--test-radius-md);\n background: var(--test-surface);\n opacity: 0.95;\n}\n\n.cdk-drag-placeholder[_ngcontent-%COMP%] {\n opacity: 0;\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n border: 2px dashed var(--test-primary);\n border-radius: var(--test-radius-md);\n}\n\n.cdk-drag-placeholder[_ngcontent-%COMP%] *[_ngcontent-%COMP%] {\n visibility: hidden;\n}\n\n.cdk-drag-animating[_ngcontent-%COMP%] {\n transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);\n}\n\n.tests-list.cdk-drop-list-dragging[_ngcontent-%COMP%] .test-item[_ngcontent-%COMP%]:not(.cdk-drag-placeholder) {\n transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);\n}\n\n\n\n\n\n.picker-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.45);\n z-index: 200;\n animation: _ngcontent-%COMP%_pickerFadeIn 180ms ease-out;\n backdrop-filter: blur(2px);\n}\n\n@keyframes _ngcontent-%COMP%_pickerFadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.picker-dialog[_ngcontent-%COMP%] {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: min(720px, calc(100vw - 32px));\n max-height: min(80vh, 720px);\n z-index: 201;\n display: flex;\n flex-direction: column;\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n box-shadow: 0 24px 64px rgba(0, 0, 0, 0.28);\n animation: _ngcontent-%COMP%_pickerSlideUp 220ms cubic-bezier(0.16, 1, 0.3, 1);\n overflow: hidden;\n}\n\n@keyframes _ngcontent-%COMP%_pickerSlideUp {\n from {\n opacity: 0;\n transform: translate(-50%, calc(-50% + 16px));\n }\n to {\n opacity: 1;\n transform: translate(-50%, -50%);\n }\n}\n\n.picker-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 18px 20px;\n border-bottom: 1px solid var(--test-border);\n}\n\n.picker-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 16px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.picker-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.picker-close[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border-radius: 8px;\n border: none;\n background: transparent;\n color: var(--test-text-muted);\n cursor: pointer;\n font-size: 14px;\n transition: background 0.15s, color 0.15s;\n}\n\n.picker-close[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n}\n\n.picker-close[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.picker-search[_ngcontent-%COMP%] {\n position: relative;\n padding: 14px 20px 0 20px;\n}\n\n.picker-search-icon[_ngcontent-%COMP%] {\n position: absolute;\n top: 50%;\n left: 32px;\n transform: translateY(-30%);\n color: var(--test-text-muted);\n font-size: 13px;\n pointer-events: none;\n}\n\n.picker-search-input[_ngcontent-%COMP%] {\n width: 100%;\n padding: 10px 36px 10px 36px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n background: var(--test-surface);\n font-size: 14px;\n color: var(--test-text);\n font-family: inherit;\n transition: var(--test-transition);\n}\n\n.picker-search-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--test-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.picker-search-clear[_ngcontent-%COMP%] {\n position: absolute;\n top: 50%;\n right: 32px;\n transform: translateY(-30%);\n width: 22px;\n height: 22px;\n border-radius: 50%;\n border: none;\n background: transparent;\n color: var(--test-text-muted);\n cursor: pointer;\n font-size: 11px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.picker-search-clear[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n}\n\n.picker-toolbar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 20px;\n border-bottom: 1px solid var(--test-border);\n}\n\n.picker-toolbar-status[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-secondary);\n}\n\n.picker-toolbar-status[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary-hover);\n font-weight: 700;\n}\n\n.picker-toolbar-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 14px;\n}\n\n.picker-link-btn[_ngcontent-%COMP%] {\n border: none;\n background: transparent;\n color: var(--test-primary);\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n padding: 0;\n font-family: inherit;\n}\n\n.picker-link-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n text-decoration: underline;\n}\n\n.picker-link-btn[_ngcontent-%COMP%]:disabled {\n color: var(--test-text-muted);\n cursor: not-allowed;\n}\n\n.picker-body[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 8px 12px;\n min-height: 200px;\n}\n\n.picker-loading[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px;\n}\n\n.picker-list[_ngcontent-%COMP%] {\n list-style: none;\n padding: 0;\n margin: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.picker-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n border-radius: 8px;\n cursor: pointer;\n transition: background 0.12s, border-color 0.12s;\n border: 1px solid transparent;\n}\n\n.picker-row[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n}\n\n.picker-row[_ngcontent-%COMP%]:focus-visible {\n outline: none;\n border-color: var(--test-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.picker-row--selected[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--test-surface));\n border-color: color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.picker-row--selected[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--test-surface));\n}\n\n.picker-check[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n border-radius: 5px;\n border: 1.5px solid var(--test-border);\n background: var(--test-surface);\n color: var(--mj-text-inverse, white);\n font-size: 11px;\n flex-shrink: 0;\n transition: background 0.12s, border-color 0.12s;\n}\n\n.picker-row--selected[_ngcontent-%COMP%] .picker-check[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.picker-row-main[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.picker-row-name[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: var(--test-text);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.picker-row-desc[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n margin-top: 2px;\n}\n\n.picker-row-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-shrink: 0;\n}\n\n.picker-row-pill[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 2px 8px;\n border-radius: 999px;\n font-size: 10px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n background: var(--mj-bg-surface-sunken, var(--test-bg));\n color: var(--test-text-secondary);\n border: 1px solid var(--test-border);\n}\n\n.picker-row-pill--status[data-status=\"active\"][_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 12%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n border-color: color-mix(in srgb, var(--mj-status-success) 30%, transparent);\n}\n\n.picker-row-pill--status[data-status=\"disabled\"][_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken, var(--test-bg));\n color: var(--test-text-muted);\n}\n\n.picker-row-pill--status[data-status=\"pending\"][_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 12%, var(--mj-bg-surface));\n color: var(--mj-status-warning-text, var(--mj-status-warning));\n border-color: color-mix(in srgb, var(--mj-status-warning) 30%, transparent);\n}\n\n.picker-footer[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n padding: 14px 20px;\n border-top: 1px solid var(--test-border);\n background: var(--mj-bg-surface-sunken, var(--test-bg));\n}\n\n.picker-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 9px 16px;\n font-size: 13px;\n font-weight: 600;\n border-radius: 8px;\n border: 1px solid transparent;\n cursor: pointer;\n font-family: inherit;\n transition: var(--test-transition);\n}\n\n.picker-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.picker-btn--primary[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse, white);\n border-color: var(--mj-brand-primary);\n}\n\n.picker-btn--primary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover, var(--mj-brand-primary));\n}\n\n.picker-btn--ghost[_ngcontent-%COMP%] {\n background: transparent;\n color: var(--test-text-secondary);\n border-color: var(--test-border);\n}\n\n.picker-btn--ghost[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n}\n\n@media (max-width: 640px) {\n .picker-dialog[_ngcontent-%COMP%] {\n width: calc(100vw - 16px);\n max-height: calc(100vh - 32px);\n }\n .tests-actionbar[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: stretch;\n }\n .tests-actionbar-actions[_ngcontent-%COMP%] {\n justify-content: flex-end;\n }\n .test-remove-btn[_ngcontent-%COMP%] {\n opacity: 1; \n }\n}"], changeDetection: 0 }); }
|
|
5042
|
+
} }, dependencies: [i1.NgClass, i2.NgSelectOption, i2.ɵNgSelectMultipleOption, i2.DefaultValueAccessor, i2.NumberValueAccessor, i2.SelectControlValueAccessor, i2.NgControlStatus, i2.NgModel, i3.CdkDropList, i3.CdkDrag, i3.CdkDragHandle, i4.MJEmptyStateComponent, i4.MJSectionPickerComponent, i4.MJButtonDirective, i4.MJAccordionPanelComponent, i4.MJAccordionTitleDirective, i4.MJAccordionBodyDirective, i5.TestRunDialogComponent, i5.EvaluationModeToggleComponent, i6.LoadingComponent, i4.MjSlidePanelComponent, i1.DatePipe], styles: ["\n\n\n\n\n[_nghost-%COMP%] {\n --test-primary: var(--mj-brand-primary);\n --test-primary-light: var(--mj-brand-primary);\n --test-success: var(--mj-status-success);\n --test-error: var(--mj-status-error);\n --test-warning: var(--mj-status-warning);\n --test-disabled: var(--mj-text-muted);\n --test-bg: var(--mj-bg-surface-card);\n --test-surface: var(--mj-bg-surface);\n --test-border: var(--mj-border-default);\n --test-text: var(--mj-text-primary);\n --test-text-secondary: var(--mj-text-secondary);\n --test-text-muted: var(--mj-text-disabled);\n --test-radius-sm: 6px;\n --test-radius-md: 10px;\n --test-radius-lg: 16px;\n --test-shadow-sm: var(--mj-shadow-sm);\n --test-shadow-md: var(--mj-shadow-md);\n --test-shadow-lg: var(--mj-shadow-lg);\n --test-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n display: block;\n height: 100%;\n}\n\n.test-suite-form[_ngcontent-%COMP%] {\n position: relative;\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--test-bg);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n}\n\n\n.breadcrumb[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n}\n\n.breadcrumb[_ngcontent-%COMP%] ol[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n list-style: none;\n margin: 0;\n padding: 0;\n font-size: 13px;\n}\n\n.breadcrumb[_ngcontent-%COMP%] li[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.breadcrumb[_ngcontent-%COMP%] a[_ngcontent-%COMP%] {\n color: var(--test-primary);\n text-decoration: none;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 8px;\n border-radius: 6px;\n transition: background 0.15s;\n}\n\n.breadcrumb[_ngcontent-%COMP%] a[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n text-decoration: none;\n}\n\n.breadcrumb[_ngcontent-%COMP%] .separator[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--test-text-muted);\n margin: 0 4px;\n}\n\n.breadcrumb[_ngcontent-%COMP%] .current[_ngcontent-%COMP%] {\n color: var(--test-text-secondary);\n font-weight: 500;\n}\n\n.breadcrumb-text[_ngcontent-%COMP%] {\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n\n.suite-header[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-bottom: 1px solid var(--test-border);\n padding: 20px;\n}\n\n.header-content[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 16px;\n gap: 16px;\n}\n\n.header-left[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n flex: 1;\n min-width: 0;\n}\n\n.suite-icon[_ngcontent-%COMP%] {\n width: 56px;\n height: 56px;\n border-radius: var(--test-radius-md);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-inverse);\n font-size: 24px;\n flex-shrink: 0;\n box-shadow: var(--test-shadow-md);\n transition: var(--test-transition);\n}\n\n.suite-icon[_ngcontent-%COMP%]:hover { transform: scale(1.05); }\n\n.suite-info[_ngcontent-%COMP%] { flex: 1; min-width: 0; }\n\n.suite-info[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: clamp(18px, 4vw, 24px);\n font-weight: 700;\n color: var(--test-text);\n word-wrap: break-word;\n}\n\n.suite-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.status-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 14px;\n border-radius: 20px;\n color: var(--mj-text-inverse);\n font-size: 12px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-badge.status-active[_ngcontent-%COMP%] { background: var(--test-success); }\n.status-badge.status-disabled[_ngcontent-%COMP%] { background: var(--test-disabled); }\n.status-badge.status-pending[_ngcontent-%COMP%] { background: var(--test-warning); }\n\n.status-badge-inline[_ngcontent-%COMP%] {\n display: inline-flex;\n padding: 2px 10px;\n border-radius: 10px;\n color: var(--mj-text-inverse);\n font-size: 11px;\n font-weight: 600;\n}\n\n.status-badge-inline.status-active[_ngcontent-%COMP%] { background: var(--test-success); }\n.status-badge-inline.status-disabled[_ngcontent-%COMP%] { background: var(--test-disabled); }\n.status-badge-inline.status-pending[_ngcontent-%COMP%] { background: var(--test-warning); }\n\n.test-count[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-size: 14px;\n color: var(--test-text-secondary);\n padding: 4px 10px;\n background: var(--test-bg);\n border-radius: var(--test-radius-sm);\n}\n\n.header-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n flex-shrink: 0;\n}\n\n.suite-description[_ngcontent-%COMP%] {\n padding: 16px;\n background: var(--mj-bg-surface-card);\n border-radius: var(--test-radius-md);\n border: 1px solid var(--test-border);\n}\n\n.suite-description[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n color: var(--test-text-secondary);\n line-height: 1.6;\n font-size: 14px;\n}\n\n\n.tabs-container[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-bottom: 1px solid var(--test-border);\n position: sticky;\n top: 0;\n z-index: 10;\n}\n\n\n.phone-section-picker[_ngcontent-%COMP%] {\n display: none;\n}\n\n.tabs[_ngcontent-%COMP%] {\n display: flex;\n padding: 0 20px;\n overflow-x: auto;\n scrollbar-width: none;\n}\n\n.tabs[_ngcontent-%COMP%]::-webkit-scrollbar { display: none; }\n\n.tab[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 14px 18px;\n border: none;\n background: transparent;\n border-bottom: 3px solid transparent;\n color: var(--test-text-secondary);\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: var(--test-transition);\n white-space: nowrap;\n}\n\n.tab[_ngcontent-%COMP%]:hover {\n color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.tab.active[_ngcontent-%COMP%] {\n color: var(--test-primary);\n border-bottom-color: var(--test-primary);\n font-weight: 600;\n}\n\n.tab-badge[_ngcontent-%COMP%] {\n background: var(--test-border);\n color: var(--test-text-secondary);\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.tab.active[_ngcontent-%COMP%] .tab-badge[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n color: var(--test-primary);\n}\n\n.tab-shortcut[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--test-text-muted);\n background: var(--test-bg);\n padding: 2px 6px;\n border-radius: 4px;\n font-weight: 600;\n}\n\n\n.tab-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n}\n\n\n.overview-tab[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 20px;\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-out;\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from { opacity: 0; transform: translateY(10px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n.info-section[_ngcontent-%COMP%], .config-section[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.info-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%], .config-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 20px 0;\n font-size: 18px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.info-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%], .config-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.info-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 16px;\n}\n\n.info-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.info-label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.info-value[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--test-text);\n font-weight: 500;\n}\n\n.config-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 20px;\n}\n\n.config-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.config-item[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.config-input[_ngcontent-%COMP%] {\n padding: 10px 14px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n font-size: 14px;\n transition: var(--test-transition);\n}\n\n.config-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--test-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.config-hint[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--test-text-muted);\n}\n\n\n.tests-tab[_ngcontent-%COMP%], .runs-tab[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-out;\n}\n\n.loading-state[_ngcontent-%COMP%] { padding: 0; }\n\n.skeleton-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.skeleton-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 16px;\n background: var(--test-surface);\n border-radius: var(--test-radius-md);\n border: 1px solid var(--test-border);\n}\n\n.skeleton-sequence[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n background: linear-gradient(90deg, var(--mj-border-default) 25%, var(--mj-bg-surface-sunken) 50%, var(--mj-border-default) 75%);\n background-size: 200% 100%;\n animation: _ngcontent-%COMP%_shimmer 1.5s infinite;\n}\n\n.skeleton-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n border-radius: var(--test-radius-md);\n background: linear-gradient(90deg, var(--mj-border-default) 25%, var(--mj-bg-surface-sunken) 50%, var(--mj-border-default) 75%);\n background-size: 200% 100%;\n animation: _ngcontent-%COMP%_shimmer 1.5s infinite;\n}\n\n.skeleton-content[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.skeleton-line[_ngcontent-%COMP%] {\n height: 14px;\n border-radius: 4px;\n background: linear-gradient(90deg, var(--mj-border-default) 25%, var(--mj-bg-surface-sunken) 50%, var(--mj-border-default) 75%);\n background-size: 200% 100%;\n animation: _ngcontent-%COMP%_shimmer 1.5s infinite;\n}\n\n.skeleton-line.wide[_ngcontent-%COMP%] { width: 70%; }\n.skeleton-line.narrow[_ngcontent-%COMP%] { width: 40%; }\n\n@keyframes _ngcontent-%COMP%_shimmer {\n 0% { background-position: 200% 0; }\n 100% { background-position: -200% 0; }\n}\n\n.tests-list[_ngcontent-%COMP%], .runs-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.test-item[_ngcontent-%COMP%], .run-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 16px;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.test-item[_ngcontent-%COMP%]:hover, .run-item[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n border-color: var(--test-primary-light);\n transform: translateX(4px);\n}\n\n.test-sequence[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--test-bg);\n border-radius: 50%;\n font-size: 14px;\n font-weight: 700;\n color: var(--test-text-secondary);\n flex-shrink: 0;\n}\n\n.test-icon[_ngcontent-%COMP%], .run-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: var(--test-radius-md);\n color: var(--mj-text-inverse);\n font-size: 18px;\n flex-shrink: 0;\n box-shadow: var(--test-shadow-sm);\n}\n\n.test-icon[_ngcontent-%COMP%] {\n background: var(--test-primary);\n}\n\n.test-content[_ngcontent-%COMP%], .run-content[_ngcontent-%COMP%] { flex: 1; min-width: 0; }\n\n.test-name[_ngcontent-%COMP%], .run-header[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n margin-bottom: 4px;\n}\n\n.run-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.run-id[_ngcontent-%COMP%] { font-weight: 600; }\n\n.run-status[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n}\n\n.test-status[_ngcontent-%COMP%], .run-meta[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n font-size: 12px;\n color: var(--test-text-secondary);\n}\n\n.test-status[_ngcontent-%COMP%] span[_ngcontent-%COMP%], .run-meta[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n\n.test-item[_ngcontent-%COMP%] > i[_ngcontent-%COMP%], .run-item[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] {\n color: var(--test-text-muted);\n font-size: 14px;\n transition: var(--test-transition);\n}\n\n.test-item[_ngcontent-%COMP%]:hover > i[_ngcontent-%COMP%], .run-item[_ngcontent-%COMP%]:hover > i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n transform: translateX(2px);\n}\n\n\n\n.shortcuts-toggle[_ngcontent-%COMP%] {\n position: fixed;\n bottom: 20px;\n right: 20px;\n width: 36px;\n height: 36px;\n border-radius: 50%;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n box-shadow: var(--test-shadow-md);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--test-text-secondary);\n font-size: 14px;\n z-index: 99;\n transition: var(--test-transition);\n opacity: 0.7;\n}\n\n.shortcuts-toggle[_ngcontent-%COMP%]:hover {\n opacity: 1;\n transform: scale(1.1);\n color: var(--test-primary);\n border-color: var(--test-primary);\n}\n\n.keyboard-shortcuts[_ngcontent-%COMP%] {\n position: fixed;\n bottom: 20px;\n right: 20px;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n padding: 12px 16px;\n box-shadow: var(--test-shadow-lg);\n font-size: 12px;\n z-index: 100;\n max-width: 260px;\n}\n\n.shortcuts-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-bottom: 10px;\n padding-bottom: 8px;\n border-bottom: 1px solid var(--test-border);\n font-weight: 600;\n color: var(--test-text);\n}\n\n.shortcuts-close[_ngcontent-%COMP%] {\n margin-left: auto;\n background: none;\n border: none;\n cursor: pointer;\n color: var(--test-text-muted);\n font-size: 12px;\n padding: 2px 4px;\n border-radius: 4px;\n transition: var(--test-transition);\n}\n\n.shortcuts-close[_ngcontent-%COMP%]:hover {\n color: var(--test-text);\n background: var(--test-border);\n}\n\n.shortcut-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.shortcut-item[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n color: var(--test-text-secondary);\n}\n\n.shortcut-keys[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n}\n\n.shortcut-keys[_ngcontent-%COMP%] kbd[_ngcontent-%COMP%] {\n background: var(--test-bg);\n border: 1px solid var(--test-border);\n border-radius: 4px;\n padding: 2px 6px;\n font-size: 11px;\n color: var(--test-text);\n}\n\n\n@media (max-width: 1024px) {\n .keyboard-shortcuts[_ngcontent-%COMP%], .shortcuts-toggle[_ngcontent-%COMP%] { display: none; }\n}\n\n@media (max-width: 768px) {\n \n .tabs[_ngcontent-%COMP%] {\n display: none;\n }\n\n .phone-section-picker[_ngcontent-%COMP%] {\n display: block;\n padding: 4px 8px;\n }\n\n .suite-header[_ngcontent-%COMP%] { padding: 16px; }\n\n .header-content[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 16px;\n }\n\n .header-actions[_ngcontent-%COMP%] {\n width: 100%;\n justify-content: stretch;\n }\n\n .header-actions[_ngcontent-%COMP%] button[_ngcontent-%COMP%] { flex: 1; }\n\n .tab-shortcut[_ngcontent-%COMP%] { display: none; }\n\n .info-grid[_ngcontent-%COMP%] { grid-template-columns: 1fr; }\n\n .test-item[_ngcontent-%COMP%], .run-item[_ngcontent-%COMP%] { padding: 14px; }\n}\n\n@media (max-width: 480px) {\n .suite-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n font-size: 18px;\n }\n\n .suite-info[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] { font-size: 16px; }\n\n .tab-badge[_ngcontent-%COMP%] { display: none; }\n\n .test-sequence[_ngcontent-%COMP%] { display: none; }\n}\n\n@media (hover: none) and (pointer: coarse) {\n .test-item[_ngcontent-%COMP%]:active, .run-item[_ngcontent-%COMP%]:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n transform: scale(0.98);\n }\n\n .tab[_ngcontent-%COMP%] { min-height: 48px; }\n .test-item[_ngcontent-%COMP%], .run-item[_ngcontent-%COMP%] { min-height: 64px; }\n}\n\n@media (prefers-reduced-motion: reduce) {\n *[_ngcontent-%COMP%], *[_ngcontent-%COMP%]::before, *[_ngcontent-%COMP%]::after {\n animation-duration: 0.01ms !important;\n transition-duration: 0.01ms !important;\n }\n}\n\n@media print {\n .header-actions[_ngcontent-%COMP%], .tabs-container[_ngcontent-%COMP%], .keyboard-shortcuts[_ngcontent-%COMP%] {\n display: none !important;\n }\n}\n\n\n\n\n.run-tags[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin-top: 8px;\n}\n\n.tag-chip[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 3px 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-brand-primary-hover);\n}\n\n.tag-mini[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 4px;\n font-size: 10px;\n font-weight: 500;\n color: var(--mj-text-muted);\n}\n\n.tag-more[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-text-disabled);\n font-weight: 500;\n}\n\n\n.run-eval-metrics[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 8px;\n}\n\n.eval-metric[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 3px 8px;\n border-radius: 6px;\n font-size: 11px;\n font-weight: 500;\n}\n\n.eval-metric.status[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.eval-metric.status.status-completed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.eval-metric.status.status-failed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.eval-metric.status.status-running[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.eval-metric.status.status-pending[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.eval-metric.human[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n border: 1px solid var(--mj-status-warning);\n color: var(--mj-status-warning);\n}\n\n.eval-metric.human[_ngcontent-%COMP%] .eval-pending[_ngcontent-%COMP%] {\n font-size: 9px;\n color: var(--mj-status-warning);\n}\n\n.eval-metric.auto[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n color: var(--mj-brand-primary-hover);\n}\n\n.eval-metric.auto.high[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-success) 30%, transparent);\n color: var(--mj-status-success);\n}\n\n.eval-metric.auto.medium[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 30%, transparent);\n color: var(--mj-status-warning);\n}\n\n.eval-metric.auto.low[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 30%, transparent);\n color: var(--mj-status-error);\n}\n\n.tag-cell[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-wrap: wrap;\n}\n\n.tag-chip-table[_ngcontent-%COMP%] {\n display: inline-block;\n padding: 3px 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n color: var(--mj-brand-primary-hover);\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n white-space: nowrap;\n max-width: 80px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n\n\n\n.analytics-tab[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-out;\n}\n\n\n\n\n\n\n\n\n\n\n.filters-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 16px;\n padding: 12px 16px 16px 16px;\n border-top: 1px solid var(--test-border);\n}\n\n.filter-group[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.filter-group[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.filter-buttons[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.filter-btn[_ngcontent-%COMP%] {\n padding: 8px 16px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n background: var(--test-surface);\n color: var(--test-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.filter-btn[_ngcontent-%COMP%]:hover {\n border-color: var(--test-primary);\n color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.filter-btn.active[_ngcontent-%COMP%] {\n background: var(--test-primary);\n border-color: var(--test-primary);\n color: var(--mj-text-inverse);\n}\n\n.filter-btn.tag-btn[_ngcontent-%COMP%] {\n padding: 6px 12px;\n font-size: 12px;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n}\n\n.filter-btn.tag-btn[_ngcontent-%COMP%] i.fa-check[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n.filter-btn.tag-btn.all-tags-btn[_ngcontent-%COMP%] {\n font-weight: 600;\n}\n\n.filter-btn.tag-btn.all-tags-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n}\n\n.filter-hint[_ngcontent-%COMP%] {\n font-weight: 400;\n font-size: 10px;\n color: var(--test-primary);\n text-transform: none;\n letter-spacing: normal;\n}\n\n.tag-filters[_ngcontent-%COMP%] {\n max-height: 120px;\n overflow-y: auto;\n}\n\n\n.analytics-kpis[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.kpi-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 20px;\n box-shadow: var(--test-shadow-sm);\n transition: var(--test-transition);\n}\n\n.kpi-card[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: var(--test-shadow-md);\n}\n\n.kpi-icon[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-radius: var(--test-radius-md);\n color: var(--test-primary);\n font-size: 20px;\n}\n\n.kpi-icon.success[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.kpi-icon.info[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.kpi-icon.warning[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--test-warning);\n}\n\n.kpi-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.kpi-value[_ngcontent-%COMP%] {\n font-size: 24px;\n font-weight: 700;\n color: var(--test-text);\n line-height: 1.2;\n}\n\n.kpi-label[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-secondary);\n margin-top: 2px;\n}\n\n.kpi-trend[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 12px;\n font-weight: 600;\n margin-top: 4px;\n padding: 2px 8px;\n border-radius: 10px;\n background: var(--mj-bg-surface-sunken);\n color: var(--test-text-secondary);\n}\n\n.kpi-trend.trend-up[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.kpi-trend.trend-down[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n\n.analytics-table-section[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.analytics-table-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 16px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.analytics-table-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.analytics-table-wrapper[_ngcontent-%COMP%] {\n overflow-x: auto;\n margin: 0 -24px;\n padding: 0 24px;\n}\n\n.analytics-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.analytics-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n text-align: left;\n padding: 12px 16px;\n background: var(--mj-bg-surface-card);\n border-bottom: 2px solid var(--test-border);\n font-weight: 600;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n font-size: 11px;\n letter-spacing: 0.5px;\n white-space: nowrap;\n}\n\n.analytics-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 14px 16px;\n border-bottom: 1px solid var(--test-border);\n color: var(--test-text);\n}\n\n.analytics-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.clickable-row[_ngcontent-%COMP%] {\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.analytics-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.clickable-row[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.status-chip[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 4px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-chip.status-completed[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--test-success); }\n.status-chip.status-passed[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--test-success); }\n.status-chip.status-failed[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface)); color: var(--test-error); }\n.status-chip.status-error[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--test-warning); }\n.status-chip.status-running[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--test-primary); }\n.status-chip.status-pending[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n.status-chip.status-cancelled[_ngcontent-%COMP%] { background: var(--mj-bg-surface-sunken); color: var(--test-disabled); }\n.status-chip.status-missing[_ngcontent-%COMP%] { background: var(--mj-bg-surface-sunken); color: var(--test-text-muted); }\n.status-chip.status-timeout[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--test-warning); }\n.status-chip.status-skipped[_ngcontent-%COMP%] { background: var(--mj-bg-surface-sunken); color: var(--test-disabled); }\n\n.pass-rate-cell[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 100px;\n}\n\n.pass-rate-bar[_ngcontent-%COMP%] {\n height: 6px;\n border-radius: 3px;\n background: var(--test-success);\n transition: width 0.3s ease;\n max-width: 60px;\n}\n\n.pass-rate-bar.medium[_ngcontent-%COMP%] { background: var(--test-warning); }\n.pass-rate-bar.low[_ngcontent-%COMP%] { background: var(--test-error); }\n\n\n.analytics-subnav[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 8px;\n margin-bottom: 20px;\n box-shadow: var(--test-shadow-sm);\n display: inline-flex;\n}\n\n.subnav-tabs[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n background: var(--test-bg);\n border-radius: var(--test-radius-md);\n padding: 4px;\n}\n\n.subnav-tab[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n border: none;\n border-radius: var(--test-radius-sm);\n background: transparent;\n color: var(--test-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.subnav-tab[_ngcontent-%COMP%]:hover {\n color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.subnav-tab.active[_ngcontent-%COMP%] {\n background: var(--test-surface);\n color: var(--test-primary);\n box-shadow: var(--test-shadow-sm);\n}\n\n.subnav-tab[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n\n.matrix-section[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 16px;\n box-shadow: var(--test-shadow-sm);\n display: flex;\n flex-direction: column;\n max-height: calc(100vh - 280px);\n min-height: 300px;\n}\n\n.matrix-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 12px;\n margin-bottom: 12px;\n padding-bottom: 12px;\n border-bottom: 1px solid var(--test-border);\n flex-shrink: 0;\n}\n\n.matrix-header-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.matrix-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 0;\n font-size: 15px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.matrix-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.matrix-run-count[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-muted);\n font-weight: 500;\n}\n\n\n.matrix-filter-input[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--test-border);\n border-radius: 6px;\n padding: 4px 10px;\n min-width: 180px;\n}\n\n.matrix-filter-input[_ngcontent-%COMP%] i.fa-search[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled);\n font-size: 12px;\n}\n\n.matrix-filter-input[_ngcontent-%COMP%] .filter-input[_ngcontent-%COMP%] {\n border: none;\n background: transparent;\n outline: none;\n font-size: 12px;\n color: var(--test-text);\n width: 100%;\n}\n\n.matrix-filter-input[_ngcontent-%COMP%] .filter-input[_ngcontent-%COMP%]::placeholder {\n color: var(--mj-text-disabled);\n}\n\n.clear-filter-btn[_ngcontent-%COMP%] {\n border: none;\n background: none;\n padding: 2px 4px;\n cursor: pointer;\n color: var(--mj-text-disabled);\n font-size: 10px;\n border-radius: 3px;\n transition: all 0.15s ease;\n}\n\n.clear-filter-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-border-default);\n color: var(--mj-text-muted);\n}\n\n\n.matrix-scroll-container[_ngcontent-%COMP%] {\n flex: 1;\n overflow: auto;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n}\n\n.test-matrix[_ngcontent-%COMP%] {\n display: table;\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.test-matrix[_ngcontent-%COMP%] thead[_ngcontent-%COMP%] {\n display: table-header-group;\n}\n\n.test-matrix[_ngcontent-%COMP%] thead[_ngcontent-%COMP%] tr[_ngcontent-%COMP%] {\n display: table-row;\n}\n\n.test-matrix[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] {\n display: table-row-group;\n}\n\n.test-matrix[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%] {\n display: table-row;\n cursor: pointer;\n transition: background-color 0.15s ease;\n}\n\n.test-matrix[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.test-matrix[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.row-selected[_ngcontent-%COMP%] {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent) !important;\n}\n\n.test-matrix[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.row-selected[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n border-top: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n border-bottom: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.test-matrix[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.row-selected[_ngcontent-%COMP%] .seq-cell[_ngcontent-%COMP%], \n.test-matrix[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.row-selected[_ngcontent-%COMP%] .test-name-cell[_ngcontent-%COMP%] {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent) !important;\n}\n\n.test-matrix[_ngcontent-%COMP%] tfoot[_ngcontent-%COMP%] {\n display: table-footer-group;\n}\n\n.test-matrix[_ngcontent-%COMP%] th[_ngcontent-%COMP%], \n.test-matrix[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n display: table-cell;\n border: 1px solid var(--test-border);\n padding: 8px 12px;\n text-align: center;\n vertical-align: middle;\n}\n\n.test-matrix[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n background: var(--test-bg);\n font-weight: 600;\n font-size: 11px;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n position: sticky;\n top: 0;\n z-index: 10;\n border-bottom: 3px solid var(--mj-text-secondary) !important;\n}\n\n\n.test-matrix[_ngcontent-%COMP%] .seq-header[_ngcontent-%COMP%], \n.test-matrix[_ngcontent-%COMP%] .seq-cell[_ngcontent-%COMP%] {\n width: 36px;\n min-width: 36px;\n max-width: 36px;\n text-align: center;\n position: sticky;\n left: 0;\n font-size: 11px;\n color: var(--mj-text-muted);\n border-right: 1px solid var(--test-border);\n padding: 6px 4px !important;\n}\n\n\n.test-matrix[_ngcontent-%COMP%] .seq-header[_ngcontent-%COMP%] {\n cursor: pointer;\n font-weight: 600;\n background: var(--test-bg);\n z-index: 12; \n top: 0;\n}\n\n\n.test-matrix[_ngcontent-%COMP%] .seq-cell[_ngcontent-%COMP%] {\n background: var(--test-surface);\n z-index: 2;\n}\n\n.test-matrix[_ngcontent-%COMP%] .seq-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 9px;\n margin-left: 2px;\n opacity: 0.6;\n}\n\n.test-matrix[_ngcontent-%COMP%] .seq-header[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.test-matrix[_ngcontent-%COMP%] .test-name-header[_ngcontent-%COMP%] {\n text-align: left;\n min-width: 150px;\n max-width: 500px;\n width: auto;\n position: sticky;\n left: 36px;\n background: var(--test-bg);\n z-index: 11;\n border-right: 2px solid var(--test-border);\n cursor: pointer;\n}\n\n.test-matrix[_ngcontent-%COMP%] .test-name-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 9px;\n margin-left: 4px;\n opacity: 0.6;\n}\n\n.test-matrix[_ngcontent-%COMP%] .test-name-header[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.test-matrix[_ngcontent-%COMP%] .run-header[_ngcontent-%COMP%] {\n min-width: 120px;\n width: 120px;\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n\n.test-matrix[_ngcontent-%COMP%] .spacer-header[_ngcontent-%COMP%], \n.test-matrix[_ngcontent-%COMP%] .spacer-cell[_ngcontent-%COMP%] {\n width: 100%;\n min-width: 20px;\n background: var(--test-bg);\n border: none;\n}\n\n.test-matrix[_ngcontent-%COMP%] .spacer-cell[_ngcontent-%COMP%] {\n background: var(--test-surface);\n}\n\n.test-matrix[_ngcontent-%COMP%] .run-header[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.run-header-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n}\n\n.run-date[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.run-pass-rate[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 700;\n padding: 2px 8px;\n border-radius: 10px;\n}\n\n.run-pass-rate.high[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.run-pass-rate.medium[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--test-warning);\n}\n\n.run-pass-rate.low[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n.run-tags[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n}\n\n.tag-tiny[_ngcontent-%COMP%] {\n font-size: 9px;\n padding: 2px 6px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--test-primary);\n border-radius: 8px;\n white-space: nowrap;\n max-width: 60px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n\n.run-tags-header[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 3px;\n justify-content: center;\n margin-bottom: 4px;\n}\n\n.tag-chip-header[_ngcontent-%COMP%] {\n display: inline-block;\n padding: 3px 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n color: var(--mj-brand-primary-hover);\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n white-space: nowrap;\n max-width: 70px;\n overflow: hidden;\n text-overflow: ellipsis;\n text-transform: none;\n letter-spacing: normal;\n}\n\n.tag-more-header[_ngcontent-%COMP%] {\n font-size: 9px;\n color: var(--test-text-secondary);\n padding: 2px 4px;\n}\n\n.test-matrix[_ngcontent-%COMP%] .test-name-cell[_ngcontent-%COMP%] {\n text-align: left;\n min-width: 150px;\n max-width: 500px;\n width: auto;\n position: sticky;\n left: 36px;\n background: var(--test-surface);\n z-index: 2;\n border-right: 2px solid var(--test-border);\n padding: 6px 10px !important;\n}\n\n.test-name[_ngcontent-%COMP%] {\n display: block;\n white-space: nowrap;\n font-weight: 500;\n color: var(--test-text);\n font-size: 12px;\n}\n\n.result-cell[_ngcontent-%COMP%] {\n position: relative;\n min-width: 120px;\n width: 120px;\n transition: var(--test-transition);\n}\n\n.result-cell.clickable[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.result-cell.clickable[_ngcontent-%COMP%]:hover {\n transform: scale(1.1);\n box-shadow: var(--mj-shadow-md);\n z-index: 5;\n}\n\n.result-cell[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n\n.result-cell.cell-passed[_ngcontent-%COMP%], \n.result-cell.cell-failed[_ngcontent-%COMP%], \n.result-cell.cell-error[_ngcontent-%COMP%], \n.result-cell.cell-timeout[_ngcontent-%COMP%], \n.result-cell.cell-running[_ngcontent-%COMP%], \n.result-cell.cell-pending[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n color: var(--test-text);\n}\n\n\n.result-cell.cell-skipped[_ngcontent-%COMP%] {\n background: repeating-linear-gradient(\n 45deg,\n var(--mj-bg-surface-card),\n var(--mj-bg-surface-card) 4px,\n var(--mj-border-default) 4px,\n var(--mj-border-default) 8px\n );\n color: var(--test-disabled);\n}\n\n.result-cell.cell-none[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n color: var(--test-text-muted);\n}\n\n.cell-score[_ngcontent-%COMP%] {\n display: block;\n font-size: 10px;\n font-weight: 600;\n margin-top: 2px;\n}\n\n\n.cell-eval-stack[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n flex-wrap: nowrap;\n}\n\n.result-cell.multi-eval[_ngcontent-%COMP%] {\n min-width: 120px;\n width: auto;\n}\n\n\n.cell-status.status-timeout[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 11px;\n}\n\n.cell-status.status-passed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-status.status-failed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-status.status-error[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status.status-skipped[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.cell-status.status-running[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.cell-status.status-pending[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.cell-human[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 50%;\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n font-size: 10px;\n}\n\n.cell-auto[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 10px;\n font-weight: 600;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.cell-auto.high[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-auto.medium[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-auto.low[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-none-indicator[_ngcontent-%COMP%] {\n color: var(--test-text-muted);\n opacity: 0.5;\n}\n\n.matrix-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: var(--test-text-muted);\n padding: 12px;\n background: var(--test-bg);\n border-radius: var(--test-radius-sm);\n}\n\n.matrix-info[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n\n\n\n.chart-section[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.chart-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 16px;\n margin-bottom: 20px;\n padding-bottom: 16px;\n border-bottom: 1px solid var(--test-border);\n}\n\n.chart-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.chart-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.chart-legend[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.chart-legend[_ngcontent-%COMP%] .legend-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n font-weight: 500;\n padding: 4px 10px;\n border-radius: 12px;\n}\n\n.chart-legend[_ngcontent-%COMP%] .legend-item.chart-passed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.chart-legend[_ngcontent-%COMP%] .legend-item.chart-failed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n.chart-legend[_ngcontent-%COMP%] .legend-item.chart-error[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--test-warning);\n}\n\n.chart-legend[_ngcontent-%COMP%] .legend-item.chart-skipped[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--test-disabled);\n}\n\n.chart-container[_ngcontent-%COMP%] {\n min-height: 500px;\n position: relative;\n overflow: hidden;\n background: var(--mj-bg-surface-card);\n border-radius: var(--test-radius-md);\n border: 1px solid var(--test-border);\n}\n\n.d3-chart[_ngcontent-%COMP%] {\n width: 100%;\n height: 500px;\n}\n\n.d3-chart[_ngcontent-%COMP%] svg[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n}\n\n\n.d3-chart[_ngcontent-%COMP%] .node[_ngcontent-%COMP%] {\n cursor: pointer;\n transition: transform 0.2s ease;\n}\n\n.d3-chart[_ngcontent-%COMP%] .node[_ngcontent-%COMP%]:hover {\n transform: scale(1.05);\n}\n\n.d3-chart[_ngcontent-%COMP%] .node-label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 500;\n fill: var(--test-text);\n pointer-events: none;\n}\n\n.d3-chart[_ngcontent-%COMP%] .link[_ngcontent-%COMP%] {\n fill: none;\n stroke-opacity: 0.4;\n transition: stroke-opacity 0.2s ease;\n}\n\n.d3-chart[_ngcontent-%COMP%] .link[_ngcontent-%COMP%]:hover {\n stroke-opacity: 0.8;\n}\n\n.d3-chart[_ngcontent-%COMP%] .tooltip[_ngcontent-%COMP%] {\n position: absolute;\n padding: 10px 14px;\n background: var(--mj-bg-overlay);\n color: var(--mj-text-inverse);\n border-radius: 8px;\n font-size: 12px;\n pointer-events: none;\n z-index: 100;\n box-shadow: var(--mj-shadow-lg);\n max-width: 250px;\n}\n\n.d3-chart[_ngcontent-%COMP%] .tooltip-title[_ngcontent-%COMP%] {\n font-weight: 600;\n margin-bottom: 4px;\n}\n\n.d3-chart[_ngcontent-%COMP%] .tooltip-value[_ngcontent-%COMP%] {\n opacity: 0.8;\n}\n\n.chart-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: var(--test-text-muted);\n padding: 12px;\n background: var(--test-bg);\n border-radius: var(--test-radius-sm);\n margin-top: 16px;\n}\n\n.chart-info[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n\n\n\n.compare-tab[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-out;\n}\n\n.compare-selection[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr auto 1fr;\n gap: 24px;\n align-items: flex-start;\n margin-bottom: 24px;\n}\n\n.compare-run-selector[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 20px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.compare-run-selector[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 16px 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.run-selector-list[_ngcontent-%COMP%] {\n max-height: 200px;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-bottom: 12px;\n}\n\n.run-selector-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.run-selector-item[_ngcontent-%COMP%]:hover {\n border-color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.run-selector-item.selected[_ngcontent-%COMP%] {\n border-color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n}\n\n.run-selector-item.disabled[_ngcontent-%COMP%] {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.selector-status[_ngcontent-%COMP%] {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.selector-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.selector-date[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 500;\n color: var(--test-text);\n}\n\n.selector-rate[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--test-text-secondary);\n}\n\n.selector-tags[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n flex-wrap: wrap;\n}\n\n.selected-run-preview[_ngcontent-%COMP%] {\n padding: 12px;\n background: var(--mj-bg-surface-card);\n border-radius: var(--test-radius-sm);\n border: 1px solid var(--test-border);\n}\n\n.preview-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.preview-label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n color: var(--test-text-muted);\n}\n\n.clear-btn[_ngcontent-%COMP%] {\n padding: 4px 8px;\n border: none;\n background: transparent;\n color: var(--test-error);\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n}\n\n.clear-btn[_ngcontent-%COMP%]:hover { text-decoration: underline; }\n\n.preview-details[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n font-size: 12px;\n color: var(--test-text);\n}\n\n.preview-rate[_ngcontent-%COMP%] {\n font-weight: 600;\n color: var(--test-success);\n}\n\n.compare-vs[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n background: var(--test-bg);\n border-radius: 50%;\n color: var(--test-text-muted);\n font-size: 16px;\n align-self: center;\n margin-top: 60px;\n}\n\n\n.compare-results[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-out;\n}\n\n.compare-summary[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.compare-summary-card[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 20px;\n box-shadow: var(--test-shadow-sm);\n text-align: center;\n}\n\n.compare-summary-card[_ngcontent-%COMP%] .summary-label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n color: var(--test-text-muted);\n margin-bottom: 8px;\n}\n\n.compare-summary-card[_ngcontent-%COMP%] .summary-value[_ngcontent-%COMP%] {\n font-size: 24px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n}\n\n.compare-summary-card[_ngcontent-%COMP%] .summary-value.positive[_ngcontent-%COMP%] { color: var(--test-success); }\n.compare-summary-card[_ngcontent-%COMP%] .summary-value.negative[_ngcontent-%COMP%] { color: var(--test-error); }\n\n.compare-summary-card.improved[_ngcontent-%COMP%] {\n border-left: 4px solid var(--test-success);\n}\n\n.compare-summary-card.improved[_ngcontent-%COMP%] .summary-value[_ngcontent-%COMP%] { color: var(--test-success); }\n\n.compare-summary-card.regressed[_ngcontent-%COMP%] {\n border-left: 4px solid var(--test-error);\n}\n\n.compare-summary-card.regressed[_ngcontent-%COMP%] .summary-value[_ngcontent-%COMP%] { color: var(--test-error); }\n\n\n.compare-table-section[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.compare-table-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 16px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.compare-table-section[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.compare-table-wrapper[_ngcontent-%COMP%] {\n overflow-x: auto;\n}\n\n.compare-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.compare-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n text-align: left;\n padding: 12px 16px;\n background: var(--mj-bg-surface-card);\n border-bottom: 2px solid var(--test-border);\n font-weight: 600;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n font-size: 11px;\n letter-spacing: 0.5px;\n white-space: nowrap;\n}\n\n.compare-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 14px 16px;\n border-bottom: 1px solid var(--test-border);\n color: var(--test-text);\n}\n\n.compare-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.improved[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 5%, transparent);\n}\n\n.compare-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.regressed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 5%, transparent);\n}\n\n.test-name-cell[_ngcontent-%COMP%] {\n font-weight: 500;\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.positive[_ngcontent-%COMP%] { color: var(--test-success); }\n.negative[_ngcontent-%COMP%] { color: var(--test-error); }\n.muted[_ngcontent-%COMP%] { color: var(--test-text-muted); }\n\n.change-indicator[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.change-indicator.improved[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.change-indicator.regressed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n.change-indicator.unchanged[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--test-text-muted);\n}\n\n\n\n\n@media (max-width: 1024px) {\n .compare-selection[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n gap: 16px;\n }\n\n .compare-vs[_ngcontent-%COMP%] {\n margin: 0;\n align-self: center;\n justify-self: center;\n }\n\n .analytics-kpis[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n}\n\n@media (max-width: 768px) {\n .filter-buttons[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .filter-btn[_ngcontent-%COMP%] {\n width: 100%;\n text-align: center;\n }\n\n .analytics-kpis[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .kpi-card[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .kpi-value[_ngcontent-%COMP%] {\n font-size: 20px;\n }\n\n .compare-summary[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .analytics-table-wrapper[_ngcontent-%COMP%], \n .compare-table-wrapper[_ngcontent-%COMP%] {\n margin: 0 -20px;\n padding: 0 20px;\n }\n\n .run-selector-list[_ngcontent-%COMP%] {\n max-height: 150px;\n }\n}\n\n@media (max-width: 480px) {\n .compare-summary[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .compare-summary-card[_ngcontent-%COMP%] .summary-value[_ngcontent-%COMP%] {\n font-size: 20px;\n }\n\n .analytics-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%], \n .analytics-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%], \n .compare-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%], \n .compare-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 10px 12px;\n font-size: 12px;\n }\n}\n\n\n\n\n\n\n.cell-human[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 3px;\n min-width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 10px;\n}\n\n.cell-human.no-feedback[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n}\n\n.cell-human.no-feedback[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n}\n\n.cell-human.has-feedback[_ngcontent-%COMP%] {\n padding: 0 6px;\n border-radius: 12px;\n min-width: 36px;\n}\n\n.cell-human.has-feedback[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 9px;\n}\n\n.cell-human.has-feedback[_ngcontent-%COMP%] .rating-value[_ngcontent-%COMP%] {\n font-weight: 700;\n font-size: 11px;\n}\n\n\n.cell-human.rating-low[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-human.rating-medium[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-human.rating-good[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-human.rating-excellent[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n\n.cell-auto[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 3px;\n min-width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 10px;\n}\n\n.cell-auto.no-score[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n}\n\n.cell-auto.no-score[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n}\n\n.cell-auto.has-score[_ngcontent-%COMP%] {\n padding: 0 6px;\n border-radius: 12px;\n min-width: 36px;\n}\n\n.cell-auto.has-score[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 9px;\n}\n\n.cell-auto.has-score[_ngcontent-%COMP%] .score-value[_ngcontent-%COMP%] {\n font-weight: 700;\n font-size: 10px;\n}\n\n\n.cell-auto.score-low[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-auto.score-medium[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-auto.score-good[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-auto.score-excellent[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n\n.cell-status[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 11px;\n}\n\n.cell-status.status-passed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-status.status-failed[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-status.status-error[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status.status-timeout[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status.status-skipped[_ngcontent-%COMP%], \n.cell-status.status-pending[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.cell-status.status-running[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n\n.result-cell.cell-not-run[_ngcontent-%COMP%] {\n background: repeating-linear-gradient(\n 45deg,\n var(--mj-bg-surface-card),\n var(--mj-bg-surface-card) 4px,\n var(--mj-border-default) 4px,\n var(--mj-border-default) 8px\n );\n color: var(--mj-text-disabled);\n}\n\n.result-cell.cell-not-run[_ngcontent-%COMP%] .cell-eval-stack[_ngcontent-%COMP%] {\n opacity: 0.6;\n}\n\n.cell-not-run-indicator[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n color: var(--mj-text-disabled);\n font-size: 11px;\n}\n\n\n\n\n.test-matrix[_ngcontent-%COMP%] tfoot[_ngcontent-%COMP%] {\n position: sticky;\n bottom: 0;\n z-index: 2;\n}\n\n.totals-row[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n border-top: 2px solid var(--test-border);\n}\n\n.totals-row[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 10px 12px;\n font-weight: 600;\n}\n\n.totals-row[_ngcontent-%COMP%] .totals-label[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n font-size: 12px;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.totals-row[_ngcontent-%COMP%] .totals-cell[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n}\n\n.totals-stack[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n}\n\n.totals-status[_ngcontent-%COMP%], \n.totals-human[_ngcontent-%COMP%], \n.totals-auto[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n padding: 2px 8px;\n border-radius: 10px;\n white-space: nowrap;\n}\n\n.totals-status[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.totals-status[_ngcontent-%COMP%] .pass-count[_ngcontent-%COMP%] {\n font-weight: 700;\n}\n\n.totals-human[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.totals-human[_ngcontent-%COMP%] .avg-label[_ngcontent-%COMP%] {\n font-weight: 700;\n}\n\n.totals-human[_ngcontent-%COMP%] .count-label[_ngcontent-%COMP%] {\n font-size: 10px;\n opacity: 0.8;\n}\n\n.totals-auto[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.totals-auto[_ngcontent-%COMP%] .avg-label[_ngcontent-%COMP%] {\n font-weight: 700;\n}\n\n.totals-auto[_ngcontent-%COMP%] .count-label[_ngcontent-%COMP%] {\n font-size: 10px;\n opacity: 0.8;\n}\n\n\n\n\n\n.edit-section[_ngcontent-%COMP%] {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.edit-section-header[_ngcontent-%COMP%] {\n margin: 0 0 18px 0;\n}\n\n.edit-section-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 4px 0;\n font-size: 18px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.edit-section-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.edit-section-sub[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 12px;\n color: var(--test-text-muted);\n}\n\n.edit-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 18px;\n}\n\n@media (max-width: 720px) {\n .edit-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n}\n\n.edit-field[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n min-width: 0;\n}\n\n.edit-field--full[_ngcontent-%COMP%] {\n grid-column: 1 / -1;\n}\n\n.edit-field[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.edit-field[_ngcontent-%COMP%] .required[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n margin-left: 2px;\n}\n\n.config-textarea[_ngcontent-%COMP%] {\n resize: vertical;\n min-height: 72px;\n font-family: inherit;\n line-height: 1.5;\n}\n\n.select-wrapper[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.select-wrapper[_ngcontent-%COMP%] select.config-input[_ngcontent-%COMP%] {\n padding-right: 36px;\n appearance: none;\n background-color: var(--test-surface);\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%2364748b' d='M1.41 0L6 4.59 10.59 0 12 1.41l-6 6-6-6z'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 14px center;\n background-size: 10px 7px;\n}\n\n\n.tag-editor[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n padding: 8px 10px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n background: var(--test-surface);\n transition: var(--test-transition);\n cursor: text;\n min-height: 42px;\n align-items: center;\n}\n\n.tag-editor[_ngcontent-%COMP%]:focus-within {\n border-color: var(--test-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.tag-chip-editable[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 3px 4px 3px 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n border-radius: 999px;\n font-size: 12px;\n font-weight: 600;\n line-height: 1;\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n}\n\n.tag-chip-editable[_ngcontent-%COMP%] .tag-remove[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n border: none;\n background: transparent;\n color: var(--mj-brand-primary);\n cursor: pointer;\n font-size: 10px;\n transition: background 0.15s;\n}\n\n.tag-chip-editable[_ngcontent-%COMP%] .tag-remove[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n color: var(--mj-brand-primary-hover);\n}\n\n.tag-input-inline[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 140px;\n border: none;\n background: transparent;\n outline: none;\n font-size: 13px;\n color: var(--test-text);\n padding: 4px 2px;\n}\n\n.tag-input-inline[_ngcontent-%COMP%]::placeholder {\n color: var(--test-text-muted);\n}\n\n\n.meta-section[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--test-radius-md);\n padding: 14px 18px;\n border: 1px solid var(--test-border);\n}\n\n.meta-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 14px;\n}\n\n.meta-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.meta-label[_ngcontent-%COMP%] {\n font-size: 10px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.meta-value[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-secondary);\n font-weight: 500;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.meta-mono[_ngcontent-%COMP%] {\n font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;\n font-size: 11px;\n}\n\n\n.dirty-indicator[_ngcontent-%COMP%] {\n display: inline-block;\n margin-left: 8px;\n font-size: 14px;\n color: var(--mj-status-warning);\n line-height: 1;\n animation: _ngcontent-%COMP%_pulseDot 1.8s ease-in-out infinite;\n vertical-align: middle;\n}\n\n@keyframes _ngcontent-%COMP%_pulseDot {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.5; transform: scale(0.85); }\n}\n\n.unsaved-pill[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning-text, var(--mj-status-warning));\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 30%, transparent);\n border-radius: 999px;\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.4px;\n}\n\n.unsaved-pill[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 6px;\n animation: _ngcontent-%COMP%_pulseDot 1.8s ease-in-out infinite;\n}\n\n\n\n.tab-content.has-savebar[_ngcontent-%COMP%] {\n padding-bottom: 84px;\n}\n\n\n\n\n\n.save-bar[_ngcontent-%COMP%] {\n position: absolute;\n left: 16px;\n right: 96px; \n bottom: 16px;\n z-index: 50;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n padding: 12px 16px 12px 20px;\n background: var(--mj-bg-surface-elevated, var(--test-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 25%, var(--test-border));\n border-radius: 14px;\n box-shadow: 0 12px 32px color-mix(in srgb, var(--mj-status-warning) 10%, rgba(0, 0, 0, 0.18));\n backdrop-filter: blur(8px);\n \n\n\n opacity: 0;\n transform: translateY(calc(100% + 32px));\n pointer-events: none;\n transition:\n transform 420ms cubic-bezier(0.16, 1, 0.3, 1),\n opacity 260ms cubic-bezier(0.16, 1, 0.3, 1);\n will-change: transform, opacity;\n}\n\n.save-bar--visible[_ngcontent-%COMP%] {\n opacity: 1;\n transform: translateY(0);\n pointer-events: auto;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .save-bar[_ngcontent-%COMP%] {\n transition: opacity 180ms ease-out;\n transform: none;\n }\n .save-bar--visible[_ngcontent-%COMP%] {\n transform: none;\n }\n}\n\n.save-bar-message[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n min-width: 0;\n}\n\n.save-bar-dot[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n font-size: 12px;\n line-height: 1;\n animation: _ngcontent-%COMP%_pulseDot 1.8s ease-in-out infinite;\n}\n\n.save-bar-text[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.save-bar-text[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--test-text);\n font-weight: 700;\n}\n\n.save-bar-fields[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-muted);\n}\n\n.save-bar-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-shrink: 0;\n}\n\n.save-bar-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 9px 16px;\n font-size: 13px;\n font-weight: 600;\n border-radius: 8px;\n border: 1px solid transparent;\n cursor: pointer;\n transition: var(--test-transition);\n font-family: inherit;\n}\n\n.save-bar-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.save-bar-btn--primary[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse, white);\n border-color: var(--mj-brand-primary);\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-brand-primary) 35%, transparent);\n}\n\n.save-bar-btn--primary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover, var(--mj-brand-primary));\n transform: translateY(-1px);\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-brand-primary) 45%, transparent);\n}\n\n.save-bar-btn--primary[_ngcontent-%COMP%]:active:not(:disabled) {\n transform: translateY(0);\n}\n\n.save-bar-btn--ghost[_ngcontent-%COMP%] {\n background: transparent;\n color: var(--test-text-secondary);\n border-color: var(--test-border);\n}\n\n.save-bar-btn--ghost[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n border-color: var(--test-text-muted);\n}\n\n.save-bar-kbd[_ngcontent-%COMP%] {\n display: inline-flex;\n gap: 3px;\n margin-left: 6px;\n opacity: 0.85;\n}\n\n.save-bar-kbd[_ngcontent-%COMP%] kbd[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 4px;\n font-size: 10px;\n font-weight: 600;\n font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;\n background: color-mix(in srgb, white 18%, transparent);\n border: 1px solid color-mix(in srgb, white 35%, transparent);\n border-radius: 4px;\n color: inherit;\n}\n\n@media (max-width: 640px) {\n .save-bar[_ngcontent-%COMP%] {\n left: 8px;\n right: 8px;\n bottom: 88px; \n flex-direction: column;\n align-items: stretch;\n padding: 12px;\n }\n .save-bar-actions[_ngcontent-%COMP%] {\n justify-content: space-between;\n }\n .save-bar-kbd[_ngcontent-%COMP%] {\n display: none;\n }\n}\n\n\n\n\n\n.tests-actionbar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding: 12px 16px;\n margin-bottom: 16px;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n}\n\n.tests-actionbar-text[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n flex-wrap: wrap;\n min-width: 0;\n}\n\n.tests-actionbar-text[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--test-text);\n font-weight: 700;\n}\n\n.tests-actionbar-count[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 22px;\n height: 22px;\n padding: 0 8px;\n border-radius: 999px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n font-size: 12px;\n font-weight: 700;\n}\n\n.tests-actionbar-hint[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-muted);\n}\n\n.tests-actionbar-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n flex-shrink: 0;\n}\n\n\n.tests-list[cdk-drop-list][_ngcontent-%COMP%] .test-item[_ngcontent-%COMP%]:hover, \n.tests-list[_ngcontent-%COMP%] .test-item.cdk-drag[_ngcontent-%COMP%]:hover {\n transform: none;\n}\n\n\n.test-item.cdk-drag[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.test-item[_ngcontent-%COMP%] .test-content[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n\n.test-drag-handle[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 28px;\n border-radius: 4px;\n color: var(--test-text-muted);\n cursor: grab;\n flex-shrink: 0;\n transition: background 0.15s, color 0.15s;\n user-select: none;\n}\n\n.test-drag-handle[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n color: var(--test-primary);\n}\n\n.test-drag-handle[_ngcontent-%COMP%]:active, \n.cdk-drag-preview[_ngcontent-%COMP%] .test-drag-handle[_ngcontent-%COMP%] {\n cursor: grabbing;\n}\n\n\n.test-remove-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border-radius: 50%;\n border: none;\n background: transparent;\n color: var(--test-text-muted);\n cursor: pointer;\n flex-shrink: 0;\n opacity: 0;\n transition: opacity 0.15s, background 0.15s, color 0.15s;\n}\n\n.test-item[_ngcontent-%COMP%]:hover .test-remove-btn[_ngcontent-%COMP%], \n.test-remove-btn[_ngcontent-%COMP%]:focus-visible {\n opacity: 1;\n}\n\n.test-remove-btn[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-status-error) 12%, transparent);\n color: var(--mj-status-error);\n}\n\n.test-chevron[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n\n.test-remove-confirm[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 4px 8px 4px 12px;\n border-radius: 999px;\n background: color-mix(in srgb, var(--mj-status-error) 8%, var(--test-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 30%, transparent);\n flex-shrink: 0;\n}\n\n.test-remove-confirm-text[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-status-error-text, var(--mj-status-error));\n}\n\n.test-remove-confirm-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 4px 10px;\n border-radius: 6px;\n border: 1px solid transparent;\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n font-family: inherit;\n transition: var(--test-transition);\n}\n\n.test-remove-confirm-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.test-remove-confirm-btn--danger[_ngcontent-%COMP%] {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse, white);\n}\n\n.test-remove-confirm-btn--danger[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-status-error) 88%, black);\n}\n\n.test-remove-confirm-btn--ghost[_ngcontent-%COMP%] {\n background: transparent;\n color: var(--test-text-secondary);\n border-color: var(--test-border);\n}\n\n.test-remove-confirm-btn--ghost[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n}\n\n\n.cdk-drag-preview[_ngcontent-%COMP%] {\n box-shadow: 0 12px 32px rgba(0, 0, 0, 0.25);\n border-radius: var(--test-radius-md);\n background: var(--test-surface);\n opacity: 0.95;\n}\n\n.cdk-drag-placeholder[_ngcontent-%COMP%] {\n opacity: 0;\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n border: 2px dashed var(--test-primary);\n border-radius: var(--test-radius-md);\n}\n\n.cdk-drag-placeholder[_ngcontent-%COMP%] *[_ngcontent-%COMP%] {\n visibility: hidden;\n}\n\n.cdk-drag-animating[_ngcontent-%COMP%] {\n transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);\n}\n\n.tests-list.cdk-drop-list-dragging[_ngcontent-%COMP%] .test-item[_ngcontent-%COMP%]:not(.cdk-drag-placeholder) {\n transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);\n}\n\n\n\n\n\n.picker-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.45);\n z-index: 200;\n animation: _ngcontent-%COMP%_pickerFadeIn 180ms ease-out;\n backdrop-filter: blur(2px);\n}\n\n@keyframes _ngcontent-%COMP%_pickerFadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.picker-dialog[_ngcontent-%COMP%] {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: min(720px, calc(100vw - 32px));\n max-height: min(80vh, 720px);\n z-index: 201;\n display: flex;\n flex-direction: column;\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n box-shadow: 0 24px 64px rgba(0, 0, 0, 0.28);\n animation: _ngcontent-%COMP%_pickerSlideUp 220ms cubic-bezier(0.16, 1, 0.3, 1);\n overflow: hidden;\n}\n\n@keyframes _ngcontent-%COMP%_pickerSlideUp {\n from {\n opacity: 0;\n transform: translate(-50%, calc(-50% + 16px));\n }\n to {\n opacity: 1;\n transform: translate(-50%, -50%);\n }\n}\n\n.picker-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 18px 20px;\n border-bottom: 1px solid var(--test-border);\n}\n\n.picker-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 16px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.picker-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--test-primary);\n}\n\n.picker-close[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border-radius: 8px;\n border: none;\n background: transparent;\n color: var(--test-text-muted);\n cursor: pointer;\n font-size: 14px;\n transition: background 0.15s, color 0.15s;\n}\n\n.picker-close[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n}\n\n.picker-close[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.picker-search[_ngcontent-%COMP%] {\n position: relative;\n padding: 14px 20px 0 20px;\n}\n\n.picker-search-icon[_ngcontent-%COMP%] {\n position: absolute;\n top: 50%;\n left: 32px;\n transform: translateY(-30%);\n color: var(--test-text-muted);\n font-size: 13px;\n pointer-events: none;\n}\n\n.picker-search-input[_ngcontent-%COMP%] {\n width: 100%;\n padding: 10px 36px 10px 36px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n background: var(--test-surface);\n font-size: 14px;\n color: var(--test-text);\n font-family: inherit;\n transition: var(--test-transition);\n}\n\n.picker-search-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--test-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.picker-search-clear[_ngcontent-%COMP%] {\n position: absolute;\n top: 50%;\n right: 32px;\n transform: translateY(-30%);\n width: 22px;\n height: 22px;\n border-radius: 50%;\n border: none;\n background: transparent;\n color: var(--test-text-muted);\n cursor: pointer;\n font-size: 11px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.picker-search-clear[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n}\n\n.picker-toolbar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 20px;\n border-bottom: 1px solid var(--test-border);\n}\n\n.picker-toolbar-status[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-secondary);\n}\n\n.picker-toolbar-status[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary-hover);\n font-weight: 700;\n}\n\n.picker-toolbar-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 14px;\n}\n\n.picker-link-btn[_ngcontent-%COMP%] {\n border: none;\n background: transparent;\n color: var(--test-primary);\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n padding: 0;\n font-family: inherit;\n}\n\n.picker-link-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n text-decoration: underline;\n}\n\n.picker-link-btn[_ngcontent-%COMP%]:disabled {\n color: var(--test-text-muted);\n cursor: not-allowed;\n}\n\n.picker-body[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 8px 12px;\n min-height: 200px;\n}\n\n.picker-loading[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px;\n}\n\n.picker-list[_ngcontent-%COMP%] {\n list-style: none;\n padding: 0;\n margin: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.picker-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n border-radius: 8px;\n cursor: pointer;\n transition: background 0.12s, border-color 0.12s;\n border: 1px solid transparent;\n}\n\n.picker-row[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n}\n\n.picker-row[_ngcontent-%COMP%]:focus-visible {\n outline: none;\n border-color: var(--test-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.picker-row--selected[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--test-surface));\n border-color: color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.picker-row--selected[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--test-surface));\n}\n\n.picker-check[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n border-radius: 5px;\n border: 1.5px solid var(--test-border);\n background: var(--test-surface);\n color: var(--mj-text-inverse, white);\n font-size: 11px;\n flex-shrink: 0;\n transition: background 0.12s, border-color 0.12s;\n}\n\n.picker-row--selected[_ngcontent-%COMP%] .picker-check[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.picker-row-main[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.picker-row-name[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: var(--test-text);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.picker-row-desc[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--test-text-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n margin-top: 2px;\n}\n\n.picker-row-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-shrink: 0;\n}\n\n.picker-row-pill[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 2px 8px;\n border-radius: 999px;\n font-size: 10px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n background: var(--mj-bg-surface-sunken, var(--test-bg));\n color: var(--test-text-secondary);\n border: 1px solid var(--test-border);\n}\n\n.picker-row-pill--status[data-status=\"active\"][_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 12%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n border-color: color-mix(in srgb, var(--mj-status-success) 30%, transparent);\n}\n\n.picker-row-pill--status[data-status=\"disabled\"][_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken, var(--test-bg));\n color: var(--test-text-muted);\n}\n\n.picker-row-pill--status[data-status=\"pending\"][_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 12%, var(--mj-bg-surface));\n color: var(--mj-status-warning-text, var(--mj-status-warning));\n border-color: color-mix(in srgb, var(--mj-status-warning) 30%, transparent);\n}\n\n.picker-footer[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n padding: 14px 20px;\n border-top: 1px solid var(--test-border);\n background: var(--mj-bg-surface-sunken, var(--test-bg));\n}\n\n.picker-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 9px 16px;\n font-size: 13px;\n font-weight: 600;\n border-radius: 8px;\n border: 1px solid transparent;\n cursor: pointer;\n font-family: inherit;\n transition: var(--test-transition);\n}\n\n.picker-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.picker-btn--primary[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse, white);\n border-color: var(--mj-brand-primary);\n}\n\n.picker-btn--primary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover, var(--mj-brand-primary));\n}\n\n.picker-btn--ghost[_ngcontent-%COMP%] {\n background: transparent;\n color: var(--test-text-secondary);\n border-color: var(--test-border);\n}\n\n.picker-btn--ghost[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n}\n\n@media (max-width: 640px) {\n .picker-dialog[_ngcontent-%COMP%] {\n width: calc(100vw - 16px);\n max-height: calc(100vh - 32px);\n }\n .tests-actionbar[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: stretch;\n }\n .tests-actionbar-actions[_ngcontent-%COMP%] {\n justify-content: flex-end;\n }\n .test-remove-btn[_ngcontent-%COMP%] {\n opacity: 1; \n }\n}\n\n\n\n\n@media (max-width: 768px) {\n .header-actions[_ngcontent-%COMP%] {\n flex-wrap: wrap;\n }\n\n .header-actions[_ngcontent-%COMP%] app-evaluation-mode-toggle[_ngcontent-%COMP%] {\n flex-basis: 100%;\n }\n\n .breadcrumb[_ngcontent-%COMP%] ol[_ngcontent-%COMP%] {\n flex-wrap: wrap;\n }\n\n .breadcrumb[_ngcontent-%COMP%] li[_ngcontent-%COMP%] {\n min-width: 0;\n }\n}"], changeDetection: 0 }); }
|
|
5023
5043
|
};
|
|
5024
5044
|
MJTestSuiteFormComponentExtended = __decorate([
|
|
5025
5045
|
RegisterClass(BaseFormComponent, 'MJ: Test Suites')
|
|
@@ -5027,7 +5047,7 @@ MJTestSuiteFormComponentExtended = __decorate([
|
|
|
5027
5047
|
export { MJTestSuiteFormComponentExtended };
|
|
5028
5048
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MJTestSuiteFormComponentExtended, [{
|
|
5029
5049
|
type: Component,
|
|
5030
|
-
args: [{ standalone: false, selector: 'mj-test-suite-form', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"test-suite-form\">\n <!-- Header Section -->\n <div class=\"suite-header\">\n <!-- Breadcrumb Navigation -->\n <nav class=\"breadcrumb\" aria-label=\"Breadcrumb\">\n <ol>\n <li>\n <a href=\"javascript:void(0)\" (click)=\"navigateToTestingDashboard()\">\n <i class=\"fas fa-vial\"></i>\n <span class=\"breadcrumb-text\">Testing</span>\n </a>\n </li>\n <li class=\"current\">\n <i class=\"fas fa-chevron-right separator\"></i>\n <i class=\"fas fa-layer-group\"></i>\n <span>{{ record.Name }}</span>\n </li>\n </ol>\n </nav>\n\n <div class=\"header-content\">\n <div class=\"header-left\">\n <div class=\"suite-icon\" [style.background-color]=\"getStatusColor()\">\n <i class=\"fas fa-layer-group\"></i>\n </div>\n <div class=\"suite-info\">\n <h1>\n {{ record.Name }}\n @if (isDirty) {\n <span class=\"dirty-indicator\" title=\"You have unsaved changes\" aria-label=\"Unsaved changes\">\u25CF</span>\n }\n </h1>\n <div class=\"suite-meta\">\n <span class=\"status-badge\" [ngClass]=\"getStatusClass()\">\n <i class=\"fas\" [ngClass]=\"record.Status === 'Active' ? 'fa-circle-check' : 'fa-circle-pause'\"></i>\n {{ record.Status }}\n </span>\n @if (testsLoaded) {\n <span class=\"test-count\">\n <i class=\"fas fa-flask\"></i>\n {{ suiteTests.length }} tests\n </span>\n }\n @if (isDirty) {\n <span class=\"unsaved-pill\" title=\"You have unsaved changes\">\n <i class=\"fas fa-circle\"></i> Unsaved\n </span>\n }\n </div>\n </div>\n </div>\n <div class=\"header-actions\">\n <app-evaluation-mode-toggle></app-evaluation-mode-toggle>\n <button mjButton (click)=\"exportToExcel()\" title=\"Export to CSV\">\n <i class=\"fas fa-file-excel\"></i> Export\n </button>\n <button mjButton (click)=\"runSuite()\" variant=\"primary\">\n <i class=\"fas fa-play\"></i> Run Suite\n </button>\n <button mjButton (click)=\"refresh()\" [disabled]=\"isRefreshing\">\n <i class=\"fas\" [ngClass]=\"isRefreshing ? 'fa-sync fa-spin' : 'fa-sync'\"></i>\n {{ isRefreshing ? 'Refreshing...' : 'Refresh' }}\n </button>\n </div>\n </div>\n @if (record.Description) {\n <div class=\"suite-description\">\n <p>{{ record.Description }}</p>\n </div>\n }\n </div>\n\n <!-- Tabs -->\n <div class=\"tabs-container\">\n <div class=\"tabs\" role=\"tablist\">\n <button class=\"tab\"\n [class.active]=\"activeTab === 'overview'\"\n (click)=\"changeTab('overview')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'overview'\">\n <i class=\"fas fa-th-large\"></i> Overview\n </button>\n <button class=\"tab\"\n [class.active]=\"activeTab === 'tests'\"\n (click)=\"changeTab('tests')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'tests'\">\n <i class=\"fas fa-flask\"></i> Tests\n @if (testsLoaded) {\n <span class=\"tab-badge\">{{ suiteTests.length }}</span>\n }\n </button>\n <button class=\"tab\"\n [class.active]=\"activeTab === 'runs'\"\n (click)=\"changeTab('runs')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'runs'\">\n <i class=\"fas fa-history\"></i> Runs\n @if (runsLoaded) {\n <span class=\"tab-badge\">{{ suiteRuns.length }}</span>\n }\n </button>\n <button class=\"tab\"\n [class.active]=\"activeTab === 'analytics'\"\n (click)=\"changeTab('analytics')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'analytics'\">\n <i class=\"fas fa-chart-line\"></i> Analytics\n </button>\n <button class=\"tab\"\n [class.active]=\"activeTab === 'compare'\"\n (click)=\"changeTab('compare')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'compare'\">\n <i class=\"fas fa-balance-scale\"></i> Compare\n </button>\n </div>\n </div>\n\n <!-- Tab Content -->\n <div class=\"tab-content\" [class.has-savebar]=\"isDirty\">\n <!-- Overview Tab -->\n @if (activeTab === 'overview') {\n <div class=\"overview-tab\">\n <!-- Editable Details -->\n <section class=\"edit-section\">\n <header class=\"edit-section-header\">\n <h3><i class=\"fas fa-pen-to-square\"></i> Details</h3>\n <p class=\"edit-section-sub\">Edit any field \u2014 changes are saved with the bar at the bottom.</p>\n </header>\n <div class=\"edit-grid\">\n <div class=\"edit-field edit-field--full\">\n <label for=\"suite-name\">Name <span class=\"required\">*</span></label>\n <input\n id=\"suite-name\"\n type=\"text\"\n class=\"config-input\"\n placeholder=\"e.g., Core Agent Test Suite\"\n [(ngModel)]=\"record.Name\"\n />\n </div>\n\n <div class=\"edit-field edit-field--full\">\n <label for=\"suite-description\">Description</label>\n <textarea\n id=\"suite-description\"\n class=\"config-input config-textarea\"\n rows=\"3\"\n placeholder=\"What does this suite cover?\"\n [ngModel]=\"record.Description\"\n (ngModelChange)=\"record.Description = $event || null\"\n ></textarea>\n </div>\n\n <div class=\"edit-field\">\n <label for=\"suite-status\">Status</label>\n <div class=\"select-wrapper\">\n <select\n id=\"suite-status\"\n class=\"config-input\"\n [(ngModel)]=\"record.Status\"\n >\n @for (opt of statusOptions; track opt) {\n <option [ngValue]=\"opt\">{{ opt }}</option>\n }\n </select>\n </div>\n </div>\n\n <div class=\"edit-field\">\n <label for=\"suite-rubric\">Rubric</label>\n <select\n id=\"suite-rubric\"\n class=\"config-input\"\n [ngModel]=\"record.RubricID\"\n (ngModelChange)=\"record.RubricID = $event || null\"\n >\n <option [ngValue]=\"null\">\u2014 None \u2014</option>\n @for (rubric of RubricOptions; track rubric.id) {\n <option [ngValue]=\"rubric.id\">{{ rubric.name }}</option>\n }\n </select>\n </div>\n\n <div class=\"edit-field\">\n <label for=\"suite-parent\">Parent Suite</label>\n <select\n id=\"suite-parent\"\n class=\"config-input\"\n [ngModel]=\"record.ParentID\"\n (ngModelChange)=\"record.ParentID = $event || null\"\n >\n <option [ngValue]=\"null\">\u2014 None (top-level) \u2014</option>\n @for (s of parentSuiteOptions; track s.ID) {\n <option [ngValue]=\"s.ID\">{{ s.Name }}</option>\n }\n </select>\n </div>\n\n <div class=\"edit-field edit-field--full\">\n <label for=\"suite-tags\">Tags</label>\n <div class=\"tag-editor\" (click)=\"tagInput.focus()\">\n @for (tag of tags; track tag) {\n <span class=\"tag-chip-editable\">\n {{ tag }}\n <button type=\"button\" class=\"tag-remove\" (click)=\"removeTag(tag); $event.stopPropagation()\" [attr.aria-label]=\"'Remove tag ' + tag\">\n <i class=\"fas fa-times\"></i>\n </button>\n </span>\n }\n <input\n #tagInput\n id=\"suite-tags\"\n type=\"text\"\n class=\"tag-input-inline\"\n [placeholder]=\"tags.length === 0 ? 'Add tags, press Enter or comma...' : ''\"\n [(ngModel)]=\"tagDraft\"\n (keydown)=\"onTagInputKeydown($event)\"\n (blur)=\"addTagFromDraft()\"\n />\n </div>\n <span class=\"config-hint\">Press Enter or comma to add a tag. Backspace on empty input removes the last tag.</span>\n </div>\n </div>\n </section>\n\n <!-- Execution Settings -->\n <section class=\"edit-section\">\n <header class=\"edit-section-header\">\n <h3><i class=\"fas fa-cogs\"></i> Execution Settings</h3>\n </header>\n <div class=\"edit-grid\">\n <div class=\"edit-field\">\n <label for=\"suite-timeout\">Max Execution Time (ms)</label>\n <input\n id=\"suite-timeout\"\n type=\"number\"\n class=\"config-input\"\n placeholder=\"Default: 300000 (5 min)\"\n [ngModel]=\"record.MaxExecutionTimeMS\"\n (ngModelChange)=\"record.MaxExecutionTimeMS = $event === '' || $event === null ? null : +$event\"\n />\n <span class=\"config-hint\">Default timeout for tests in this suite. Currently: {{ formatTimeout(record.MaxExecutionTimeMS) }}</span>\n </div>\n </div>\n </section>\n\n <!-- Metadata (read-only) -->\n <section class=\"meta-section\">\n <div class=\"meta-grid\">\n <div class=\"meta-item\">\n <div class=\"meta-label\">Created</div>\n <div class=\"meta-value\">{{ record.__mj_CreatedAt | date:'medium' }}</div>\n </div>\n <div class=\"meta-item\">\n <div class=\"meta-label\">Last updated</div>\n <div class=\"meta-value\">{{ record.__mj_UpdatedAt | date:'medium' }}</div>\n </div>\n <div class=\"meta-item\">\n <div class=\"meta-label\">Suite ID</div>\n <div class=\"meta-value meta-mono\">{{ record.ID }}</div>\n </div>\n </div>\n </section>\n </div>\n }\n\n <!-- Tests Tab -->\n @if (activeTab === 'tests') {\n <div class=\"tests-tab\">\n <!-- Header: action bar -->\n <div class=\"tests-actionbar\">\n <div class=\"tests-actionbar-text\">\n <strong>Suite tests</strong>\n @if (testsLoaded) {\n <span class=\"tests-actionbar-count\">{{ suiteTests.length }}</span>\n }\n <span class=\"tests-actionbar-hint\">Drag to reorder \u00B7 Hover a row to remove</span>\n </div>\n <div class=\"tests-actionbar-actions\">\n <button mjButton variant=\"primary\" (click)=\"openAddTestsDialog()\" [disabled]=\"isReorderingTests\">\n <i class=\"fas fa-plus\"></i> Add tests\n </button>\n </div>\n </div>\n\n <!-- Loading State -->\n @if (loadingTests) {\n <div class=\"loading-state\">\n <div class=\"skeleton-list\">\n @for (i of [1,2,3,4,5]; track i) {\n <div class=\"skeleton-card\">\n <div class=\"skeleton-sequence\"></div>\n <div class=\"skeleton-icon\"></div>\n <div class=\"skeleton-content\">\n <div class=\"skeleton-line wide\"></div>\n <div class=\"skeleton-line narrow\"></div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n <!-- Tests List -->\n @if (!loadingTests && suiteTests.length > 0) {\n <div class=\"tests-list\" cdkDropList (cdkDropListDropped)=\"onTestDrop($event)\">\n @for (test of suiteTests; track test.ID) {\n <div class=\"test-item\" cdkDrag [cdkDragDisabled]=\"isReorderingTests || isRemovingTest\">\n <span class=\"test-drag-handle\" cdkDragHandle title=\"Drag to reorder\" aria-label=\"Drag to reorder\">\n <i class=\"fas fa-grip-vertical\"></i>\n </span>\n <div class=\"test-sequence\">{{ test.Sequence }}</div>\n <div class=\"test-icon\"><i class=\"fas fa-flask\"></i></div>\n <div class=\"test-content\" (click)=\"openTest(test.TestID)\">\n <div class=\"test-name\">{{ test.Test }}</div>\n <div class=\"test-status\">\n @if (test.Status) {\n <span><i class=\"fas fa-info-circle\"></i> {{ test.Status }}</span>\n }\n </div>\n </div>\n <!-- Inline remove confirm OR hover-reveal X -->\n @if (confirmingRemoveSuiteTestId === test.ID) {\n <div class=\"test-remove-confirm\" (click)=\"$event.stopPropagation()\">\n <span class=\"test-remove-confirm-text\">Remove from suite?</span>\n <button\n type=\"button\"\n class=\"test-remove-confirm-btn test-remove-confirm-btn--danger\"\n (click)=\"confirmRemoveTest(test, $event)\"\n [disabled]=\"isRemovingTest\"\n >\n @if (isRemovingTest) {\n <i class=\"fas fa-spinner fa-spin\"></i>\n } @else {\n Remove\n }\n </button>\n <button\n type=\"button\"\n class=\"test-remove-confirm-btn test-remove-confirm-btn--ghost\"\n (click)=\"cancelRemoveTest($event)\"\n [disabled]=\"isRemovingTest\"\n >\n Cancel\n </button>\n </div>\n } @else {\n <button\n type=\"button\"\n class=\"test-remove-btn\"\n title=\"Remove from suite\"\n aria-label=\"Remove from suite\"\n (click)=\"requestRemoveTest(test, $event)\"\n >\n <i class=\"fas fa-times\"></i>\n </button>\n <i class=\"fas fa-chevron-right test-chevron\" (click)=\"openTest(test.TestID)\"></i>\n }\n </div>\n }\n </div>\n }\n <!-- Empty State -->\n @if (testsLoaded && !loadingTests && suiteTests.length === 0) {\n <mj-empty-state\n Icon=\"fa-solid fa-flask\"\n Title=\"No Tests in Suite\"\n Message=\"Add tests to this suite to start running them together.\"\n ActionText=\"Add tests\"\n ActionIcon=\"fa-solid fa-plus\"\n (Action)=\"openAddTestsDialog()\" />\n }\n </div>\n }\n\n <!-- Runs Tab -->\n @if (activeTab === 'runs') {\n <div class=\"runs-tab\">\n <!-- Loading State -->\n @if (loadingRuns) {\n <div class=\"loading-state\">\n <div class=\"skeleton-list\">\n @for (i of [1,2,3]; track i) {\n <div class=\"skeleton-card\">\n <div class=\"skeleton-icon\"></div>\n <div class=\"skeleton-content\">\n <div class=\"skeleton-line wide\"></div>\n <div class=\"skeleton-line narrow\"></div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n <!-- Runs List -->\n @if (!loadingRuns && suiteRuns.length > 0) {\n <div class=\"runs-list\">\n @for (run of suiteRuns; track run) {\n <div class=\"run-item\" (click)=\"openSuiteRun(run.ID)\">\n <div class=\"run-icon\" [style.background-color]=\"getRunStatusColor(run.Status)\">\n <i class=\"fas\"\n [class.fa-check]=\"run.Status === 'Completed'\"\n [class.fa-times]=\"run.Status === 'Failed'\"\n [class.fa-spinner]=\"run.Status === 'Running'\"\n [class.fa-clock]=\"run.Status === 'Pending'\"\n [class.fa-ban]=\"run.Status === 'Cancelled'\"></i>\n </div>\n <div class=\"run-content\">\n <div class=\"run-header\">\n <span class=\"run-id\">Run #{{ run.ID.substring(0, 8) }}</span>\n <span class=\"run-status\" [style.color]=\"getRunStatusColor(run.Status)\">{{ run.Status }}</span>\n </div>\n <div class=\"run-meta\">\n <span><i class=\"fas fa-calendar\"></i> {{ getRelativeTime(run.StartedAt) }}</span>\n @if (run.TotalTests) {\n <span>\n <i class=\"fas fa-check-circle\"></i> {{ run.PassedTests }}/{{ run.TotalTests }}\n ({{ getPassRate(run).toFixed(0) }}%)\n </span>\n }\n </div>\n <!-- Evaluation metrics row -->\n <div class=\"run-eval-metrics\">\n <!-- Status badge -->\n @if (evalPreferences.showExecution) {\n <span class=\"eval-metric status\" [class]=\"'status-' + run.Status.toLowerCase()\">\n <i class=\"fas\"\n [class.fa-circle-check]=\"run.Status === 'Completed'\"\n [class.fa-circle-xmark]=\"run.Status === 'Failed'\"\n [class.fa-spinner]=\"run.Status === 'Running'\"\n [class.fa-clock]=\"run.Status === 'Pending'\"\n [class.fa-ban]=\"run.Status === 'Cancelled'\"></i>\n </span>\n }\n <!-- Human score (placeholder - need avg from suite run) -->\n @if (evalPreferences.showHuman) {\n <span class=\"eval-metric human\" title=\"Human evaluation\">\n <i class=\"fas fa-user\"></i>\n <span class=\"eval-pending\"><i class=\"fas fa-clock\"></i></span>\n </span>\n }\n <!-- Auto score (pass rate as proxy) -->\n @if (evalPreferences.showAuto && run.TotalTests) {\n <span class=\"eval-metric auto\"\n [class.high]=\"getPassRate(run) >= 80\"\n [class.medium]=\"getPassRate(run) >= 50 && getPassRate(run) < 80\"\n [class.low]=\"getPassRate(run) < 50\"\n title=\"Auto score (pass rate)\">\n <i class=\"fas fa-robot\"></i>\n <span>{{ getPassRate(run).toFixed(0) }}%</span>\n </span>\n }\n </div>\n <!-- Tags display -->\n @if (getRunTags(run).length > 0) {\n <div class=\"run-tags\">\n @for (tag of getRunTags(run); track tag) {\n <span class=\"tag-chip\">{{ tag }}</span>\n }\n </div>\n }\n </div>\n <i class=\"fas fa-chevron-right\"></i>\n </div>\n }\n </div>\n }\n <!-- Empty State -->\n @if (runsLoaded && !loadingRuns && suiteRuns.length === 0) {\n <mj-empty-state\n Icon=\"fa-solid fa-circle-play\"\n Title=\"No Suite Runs Yet\"\n Message=\"Run this suite to see execution history and results here.\"\n ActionText=\"Run Suite Now\"\n ActionIcon=\"fa-solid fa-play\"\n (Action)=\"runSuite()\" />\n }\n </div>\n }\n\n <!-- Analytics Tab -->\n @if (activeTab === 'analytics') {\n <div class=\"analytics-tab\">\n <!-- Loading State -->\n @if (loadingAnalytics) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading analytics data...\"></mj-loading>\n </div>\n }\n @if (!loadingAnalytics && analyticsLoaded) {\n <!-- View Toggle Sub-nav -->\n <div class=\"analytics-subnav\">\n <div class=\"subnav-tabs\">\n <button class=\"subnav-tab\"\n [class.active]=\"analyticsView === 'summary'\"\n (click)=\"setAnalyticsView('summary')\">\n <i class=\"fas fa-chart-bar\"></i>\n <span>Summary</span>\n </button>\n <button class=\"subnav-tab\"\n [class.active]=\"analyticsView === 'matrix'\"\n (click)=\"setAnalyticsView('matrix')\">\n <i class=\"fas fa-th\"></i>\n <span>Matrix</span>\n </button>\n <button class=\"subnav-tab\"\n [class.active]=\"analyticsView === 'chart'\"\n (click)=\"setAnalyticsView('chart')\">\n <i class=\"fas fa-project-diagram\"></i>\n <span>Chart</span>\n </button>\n </div>\n </div>\n <!-- Collapsible Filters (shared by both views) -->\n <mj-accordion-panel Size=\"sm\" [FlushBody]=\"true\"\n [Expanded]=\"!filtersCollapsed\" (ExpandedChange)=\"onFiltersExpandedChange($event)\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-filter\" style=\"color: var(--test-primary);\"></i>\n Filters\n @if (filtersCollapsed) {\n <span class=\"mj-accordion-badge mj-accordion-badge--right mj-accordion-badge--muted\">\n {{ analyticsTimeRange === 'all' ? 'All Time' : analyticsTimeRange }}\n @if (selectedTags.length > 0) {\n <span> \u00B7 {{ selectedTags.length }} tags</span>\n }\n </span>\n }\n </ng-template>\n <ng-template mjAccordionBody>\n <div class=\"filters-content\">\n <div class=\"filter-group\">\n <label>Time Range</label>\n <div class=\"filter-buttons\">\n <button class=\"filter-btn\" [class.active]=\"analyticsTimeRange === '7d'\" (click)=\"setTimeRange('7d')\">7 Days</button>\n <button class=\"filter-btn\" [class.active]=\"analyticsTimeRange === '30d'\" (click)=\"setTimeRange('30d')\">30 Days</button>\n <button class=\"filter-btn\" [class.active]=\"analyticsTimeRange === '90d'\" (click)=\"setTimeRange('90d')\">90 Days</button>\n <button class=\"filter-btn\" [class.active]=\"analyticsTimeRange === 'all'\" (click)=\"setTimeRange('all')\">All Time</button>\n </div>\n </div>\n @if (uniqueTags.length > 0) {\n <div class=\"filter-group\">\n <label>Filter by Tag @if (selectedTags.length > 0) {\n <span class=\"filter-hint\">({{ selectedTags.length }} selected)</span>\n }</label>\n <div class=\"filter-buttons tag-filters\">\n <button class=\"filter-btn tag-btn all-tags-btn\"\n [class.active]=\"selectedTags.length === 0\"\n (click)=\"toggleTagFilter(null)\">\n <i class=\"fas fa-layer-group\"></i> All Tags\n </button>\n @for (tag of uniqueTags; track tag) {\n <button class=\"filter-btn tag-btn\"\n [class.active]=\"isTagSelected(tag)\"\n (click)=\"toggleTagFilter(tag)\">\n @if (isTagSelected(tag)) {\n <i class=\"fas fa-check\"></i>\n }\n {{ tag }}\n </button>\n }\n </div>\n </div>\n }\n </div>\n </ng-template>\n </mj-accordion-panel>\n <!-- Summary View -->\n @if (analyticsView === 'summary') {\n <!-- KPI Cards -->\n <div class=\"analytics-kpis\">\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\"><i class=\"fas fa-play-circle\"></i></div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ getTotalRuns() }}</div>\n <div class=\"kpi-label\">Total Runs</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon success\"><i class=\"fas fa-check-circle\"></i></div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ getAveragePassRate().toFixed(1) }}%</div>\n <div class=\"kpi-label\">Avg Pass Rate</div>\n <div class=\"kpi-trend\" [ngClass]=\"{'trend-up': getPassRateTrend().direction === 'up', 'trend-down': getPassRateTrend().direction === 'down'}\">\n <i class=\"fas\" [ngClass]=\"{'fa-arrow-up': getPassRateTrend().direction === 'up', 'fa-arrow-down': getPassRateTrend().direction === 'down', 'fa-minus': getPassRateTrend().direction === 'stable'}\"></i>\n {{ getPassRateTrend().value.toFixed(1) }}%\n </div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon info\"><i class=\"fas fa-clock\"></i></div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ formatDuration(getAverageDuration()) }}</div>\n <div class=\"kpi-label\">Avg Duration</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon warning\"><i class=\"fas fa-dollar-sign\"></i></div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ formatCost(getTotalCost()) }}</div>\n <div class=\"kpi-label\">Total Cost</div>\n </div>\n </div>\n </div>\n <!-- Runs Table -->\n <div class=\"analytics-table-section\">\n <h3><i class=\"fas fa-table\"></i> Run History</h3>\n <div class=\"analytics-table-wrapper\">\n <table class=\"analytics-table\">\n <thead>\n <tr>\n <th>Date</th>\n <th>Status</th>\n <th>Pass Rate</th>\n <th>Tests</th>\n <th>Duration</th>\n <th>Cost</th>\n <th>Tags</th>\n </tr>\n </thead>\n <tbody>\n @for (dp of getFilteredAnalyticsData(); track dp) {\n <tr (click)=\"openSuiteRun(dp.runId)\" class=\"clickable-row\">\n <td>{{ dp.date | date:'short' }}</td>\n <td>\n <span class=\"status-chip\" [ngClass]=\"'status-' + dp.status.toLowerCase()\">{{ dp.status }}</span>\n </td>\n <td>\n <div class=\"pass-rate-cell\">\n <div class=\"pass-rate-bar\" [style.width.%]=\"dp.passRate\" [ngClass]=\"{'high': dp.passRate >= 80, 'medium': dp.passRate >= 50 && dp.passRate < 80, 'low': dp.passRate < 50}\"></div>\n <span>{{ dp.passRate.toFixed(0) }}%</span>\n </div>\n </td>\n <td>{{ dp.passedTests }}/{{ dp.totalTests }}</td>\n <td>{{ formatDuration(dp.duration) }}</td>\n <td>{{ formatCost(dp.cost) }}</td>\n <td>\n <div class=\"tag-cell\">\n @for (tag of dp.tags.slice(0, 2); track tag) {\n <span class=\"tag-chip-table\">{{ tag }}</span>\n }\n @if (dp.tags.length > 2) {\n <span class=\"tag-more\">+{{ dp.tags.length - 2 }}</span>\n }\n </div>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n @if (getFilteredAnalyticsData().length === 0) {\n <mj-empty-state\n Variant=\"no-results\"\n Size=\"compact\"\n Title=\"No runs match the current filters.\" />\n }\n </div>\n }\n <!-- Matrix View -->\n @if (analyticsView === 'matrix') {\n <!-- Loading Matrix -->\n @if (loadingMatrix) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading test matrix...\"></mj-loading>\n </div>\n }\n <!-- Matrix Content -->\n @if (!loadingMatrix && matrixLoaded && matrixData.length > 0) {\n <div class=\"matrix-section\">\n <div class=\"matrix-header\">\n <h3><i class=\"fas fa-th\"></i> Test Results Matrix</h3>\n <div class=\"matrix-header-right\">\n <div class=\"matrix-filter-input\">\n <i class=\"fas fa-search\"></i>\n <input type=\"text\"\n placeholder=\"Filter tests...\"\n [value]=\"matrixTestFilter\"\n (input)=\"onMatrixFilterInput($event)\"\n class=\"filter-input\">\n @if (matrixTestFilter) {\n <button class=\"clear-filter-btn\" (click)=\"clearMatrixFilter()\" title=\"Clear filter\">\n <i class=\"fas fa-times\"></i>\n </button>\n }\n </div>\n <span class=\"matrix-run-count\">{{ matrixData.length }} runs \u00B7 {{ getUniqueTestsFromMatrix().length }} tests</span>\n <button mjButton (click)=\"exportMatrixToCSV()\" [disabled]=\"matrixData.length === 0\" title=\"Export matrix to CSV\">\n <i class=\"fas fa-download\"></i> Export\n </button>\n </div>\n </div>\n <div class=\"matrix-scroll-container\">\n <table class=\"test-matrix\">\n <thead>\n <tr>\n <th class=\"seq-header\" (click)=\"toggleMatrixSort('sequence')\" title=\"Sort by sequence\">\n #\n <i class=\"fas\" [ngClass]=\"matrixSortBy === 'sequence' ? (matrixSortAsc ? 'fa-sort-up' : 'fa-sort-down') : 'fa-sort'\"></i>\n </th>\n <th class=\"test-name-header\" (click)=\"toggleMatrixSort('name')\" title=\"Sort by name\">\n Test\n <i class=\"fas\" [ngClass]=\"matrixSortBy === 'name' ? (matrixSortAsc ? 'fa-sort-up' : 'fa-sort-down') : 'fa-sort'\"></i>\n </th>\n @for (run of matrixData; track run) {\n <th class=\"run-header\" (click)=\"openSuiteRun(run.runId)\" [title]=\"'Click to view suite run - ' + (run.date | date:'medium')\">\n <div class=\"run-header-content\">\n @if (run.tags.length > 0) {\n <div class=\"run-tags-header\">\n @for (tag of run.tags.slice(0, 2); track tag) {\n <span class=\"tag-chip-header\">{{ tag }}</span>\n }\n @if (run.tags.length > 2) {\n <span class=\"tag-more-header\">+{{ run.tags.length - 2 }}</span>\n }\n </div>\n }\n <div class=\"run-date\">{{ getRelativeTime(run.date) }}</div>\n <div class=\"run-pass-rate\" [ngClass]=\"{'high': run.passRate >= 80, 'medium': run.passRate >= 50 && run.passRate < 80, 'low': run.passRate < 50}\">\n {{ run.passRate.toFixed(0) }}%\n </div>\n </div>\n </th>\n }\n <th class=\"spacer-header\"></th>\n </tr>\n </thead>\n <tbody>\n @for (test of getUniqueTestsFromMatrix(); track test) {\n <tr\n [class.row-selected]=\"selectedMatrixTestId === test.testId\"\n (click)=\"selectMatrixRow(test.testId)\">\n <td class=\"seq-cell\">{{ test.sequence }}</td>\n <td class=\"test-name-cell\">\n <span class=\"test-name\" [title]=\"test.testName\">{{ test.testName }}</span>\n </td>\n @for (run of matrixData; track run) {\n <td class=\"result-cell\"\n [ngClass]=\"getMatrixCellClass(getTestResultForRun(run.runId, test.testId))\"\n [class.clickable]=\"getTestResultForRun(run.runId, test.testId)\"\n [class.cell-not-run]=\"!getTestResultForRun(run.runId, test.testId)\"\n [title]=\"getTestResultForRun(run.runId, test.testId)?.status + ' - Click to view test run' || 'Not Run'\"\n (click)=\"onMatrixCellClick(getTestResultForRun(run.runId, test.testId), $event)\">\n @if (getTestResultForRun(run.runId, test.testId); as result) {\n <div class=\"cell-eval-stack\">\n <!-- Status indicator -->\n @if (evalPreferences.showExecution) {\n <span class=\"cell-status\"\n [ngClass]=\"'status-' + result.status.toLowerCase()\"\n [class.cell-skipped-status]=\"result.status === 'Skipped' || result.status === 'Pending'\"\n [title]=\"getStatusTooltip(result.status)\">\n <i class=\"fas\"\n [class.fa-check]=\"result.status === 'Passed'\"\n [class.fa-times]=\"result.status === 'Failed'\"\n [class.fa-exclamation]=\"result.status === 'Error'\"\n [class.fa-hourglass-end]=\"result.status === 'Timeout'\"\n [class.fa-forward]=\"result.status === 'Skipped'\"\n [class.fa-spinner]=\"result.status === 'Running'\"\n [class.fa-clock]=\"result.status === 'Pending'\"></i>\n </span>\n }\n <!-- Human score - slashed icon if no feedback, colored by rating if has feedback -->\n @if (evalPreferences.showHuman && !result.humanRating) {\n <span class=\"cell-human no-feedback\"\n title=\"Human Review: No rating submitted yet\">\n <i class=\"fas fa-user-slash\"></i>\n </span>\n }\n @if (evalPreferences.showHuman && result.humanRating) {\n <span class=\"cell-human has-feedback\"\n [class.rating-low]=\"result.humanRating <= 4\"\n [class.rating-medium]=\"result.humanRating >= 5 && result.humanRating <= 6\"\n [class.rating-good]=\"result.humanRating >= 7 && result.humanRating <= 8\"\n [class.rating-excellent]=\"result.humanRating >= 9\"\n [title]=\"getHumanTooltip(result.humanRating, result.humanComments)\">\n <i class=\"fas fa-user\"></i>\n <span class=\"rating-value\">{{ result.humanRating }}</span>\n </span>\n }\n <!-- Auto score - colored by percentage -->\n @if (evalPreferences.showAuto && result.score != null) {\n <span class=\"cell-auto has-score\"\n [class.score-low]=\"result.score < 0.5\"\n [class.score-medium]=\"result.score >= 0.5 && result.score < 0.7\"\n [class.score-good]=\"result.score >= 0.7 && result.score < 0.85\"\n [class.score-excellent]=\"result.score >= 0.85\"\n [title]=\"'Auto Score: ' + (result.score * 100).toFixed(0) + '% automated evaluation'\">\n <i class=\"fas fa-robot\"></i>\n <span class=\"score-value\">{{ (result.score * 100).toFixed(0) }}</span>\n </span>\n }\n @if (evalPreferences.showAuto && result.score == null) {\n <span class=\"cell-auto no-score\"\n title=\"Auto Score: No automated score available\">\n <i class=\"fas fa-robot\"></i>\n </span>\n }\n </div>\n }\n @if (!getTestResultForRun(run.runId, test.testId)) {\n <span class=\"cell-not-run-indicator\">\n <i class=\"fas fa-minus\"></i>\n </span>\n }\n </td>\n }\n <td class=\"spacer-cell\"></td>\n </tr>\n }\n </tbody>\n <!-- Footer row with totals -->\n <tfoot>\n <tr class=\"totals-row\">\n <td class=\"seq-cell totals-label\"></td>\n <td class=\"test-name-cell totals-label\">\n <strong>Totals</strong>\n </td>\n @for (run of matrixData; track run) {\n <td class=\"result-cell totals-cell\">\n <div class=\"cell-eval-stack totals-stack\">\n <!-- Status totals -->\n @if (evalPreferences.showExecution) {\n <span class=\"totals-status\">\n <span class=\"pass-count\">{{ getRunPassedCount(run) }}/{{ getRunTotalCount(run) }}</span>\n </span>\n }\n <!-- Human totals -->\n @if (evalPreferences.showHuman) {\n <span class=\"totals-human\">\n @if (getRunHumanAvg(run) != null) {\n <span class=\"avg-label\">{{ getRunHumanAvg(run)?.toFixed(1) }}</span>\n }\n <span class=\"count-label\">({{ getRunHumanCount(run) }})</span>\n </span>\n }\n <!-- Auto totals -->\n @if (evalPreferences.showAuto) {\n <span class=\"totals-auto\">\n @if (getRunAutoAvg(run) != null) {\n <span class=\"avg-label\">{{ (getRunAutoAvg(run)! * 100).toFixed(0) }}%</span>\n }\n <span class=\"count-label\">({{ getRunAutoCount(run) }})</span>\n </span>\n }\n </div>\n </td>\n }\n <td class=\"spacer-cell\"></td>\n </tr>\n </tfoot>\n </table>\n </div>\n </div>\n }\n <!-- Empty Matrix State -->\n @if (!loadingMatrix && matrixLoaded && matrixData.length === 0) {\n <mj-empty-state\n Variant=\"no-results\"\n Icon=\"fa-solid fa-table-cells\"\n Title=\"No Matrix Data\"\n Message=\"No suite runs match the current filters.\" />\n }\n }\n <!-- Chart View -->\n @if (analyticsView === 'chart') {\n <!-- Loading Chart -->\n @if (loadingMatrix) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading chart data...\"></mj-loading>\n </div>\n }\n <!-- Chart Content -->\n @if (!loadingMatrix && matrixLoaded && matrixData.length > 0) {\n <div class=\"chart-section\">\n <div class=\"chart-header\">\n <h3><i class=\"fas fa-project-diagram\"></i> Test Results Flow</h3>\n <div class=\"chart-legend\">\n <span class=\"legend-item chart-passed\"><i class=\"fas fa-check\"></i> Passed</span>\n <span class=\"legend-item chart-failed\"><i class=\"fas fa-times\"></i> Failed</span>\n <span class=\"legend-item chart-error\"><i class=\"fas fa-exclamation\"></i> Error</span>\n <span class=\"legend-item chart-skipped\"><i class=\"fas fa-forward\"></i> Skipped</span>\n </div>\n </div>\n <div class=\"chart-container\">\n <div #chartContainer class=\"d3-chart\"></div>\n </div>\n <div class=\"chart-info\">\n <i class=\"fas fa-info-circle\"></i>\n Interactive visualization showing test results across {{ matrixData.length }} runs.\n Hover over elements for details, click nodes to navigate.\n </div>\n </div>\n }\n <!-- Empty Chart State -->\n @if (!loadingMatrix && matrixLoaded && matrixData.length === 0) {\n <mj-empty-state\n Variant=\"no-results\"\n Icon=\"fa-solid fa-diagram-project\"\n Title=\"No Chart Data\"\n Message=\"No suite runs match the current filters.\" />\n }\n }\n }\n <!-- Empty State -->\n @if (!loadingAnalytics && analyticsLoaded && analyticsData.length === 0) {\n <mj-empty-state\n Icon=\"fa-solid fa-chart-line\"\n Title=\"No Analytics Data\"\n Message=\"Run this suite to start collecting analytics data.\"\n ActionText=\"Run Suite Now\"\n ActionIcon=\"fa-solid fa-play\"\n (Action)=\"runSuite()\" />\n }\n </div>\n }\n\n <!-- Compare Tab -->\n @if (activeTab === 'compare') {\n <div class=\"compare-tab\">\n <!-- Run Selection -->\n <div class=\"compare-selection\">\n <div class=\"compare-run-selector\">\n <h4>Run A (Baseline)</h4>\n @if (!loadingRuns && suiteRuns.length > 0) {\n <div class=\"run-selector-list\">\n @for (run of suiteRuns; track run) {\n <div class=\"run-selector-item\"\n [class.selected]=\"IsCompareRunA(run)\"\n (click)=\"selectCompareRunA(run)\">\n <div class=\"selector-status\" [style.background-color]=\"getRunStatusColor(run.Status)\"></div>\n <div class=\"selector-content\">\n <div class=\"selector-date\">{{ run.StartedAt | date:'short' }}</div>\n <div class=\"selector-rate\">{{ getPassRate(run).toFixed(0) }}% pass</div>\n </div>\n @if (getRunTags(run).length > 0) {\n <div class=\"selector-tags\">\n @for (tag of getRunTags(run).slice(0, 2); track tag) {\n <span class=\"tag-mini\">{{ tag }}</span>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n @if (compareRunA) {\n <div class=\"selected-run-preview\">\n <div class=\"preview-header\">\n <span class=\"preview-label\">Selected:</span>\n <button class=\"clear-btn\" (click)=\"compareRunA = null; compareResults = []\">Clear</button>\n </div>\n <div class=\"preview-details\">\n <span>{{ compareRunA.StartedAt | date:'medium' }}</span>\n <span class=\"preview-rate\">{{ getPassRate(compareRunA).toFixed(1) }}%</span>\n </div>\n </div>\n }\n </div>\n <div class=\"compare-vs\"><i class=\"fas fa-exchange-alt\"></i></div>\n <div class=\"compare-run-selector\">\n <h4>Run B (Compare)</h4>\n @if (!loadingRuns && suiteRuns.length > 0) {\n <div class=\"run-selector-list\">\n @for (run of suiteRuns; track run) {\n <div class=\"run-selector-item\"\n [class.selected]=\"IsCompareRunB(run)\"\n [class.disabled]=\"IsCompareRunA(run)\"\n (click)=\"!IsCompareRunA(run) && selectCompareRunB(run)\">\n <div class=\"selector-status\" [style.background-color]=\"getRunStatusColor(run.Status)\"></div>\n <div class=\"selector-content\">\n <div class=\"selector-date\">{{ run.StartedAt | date:'short' }}</div>\n <div class=\"selector-rate\">{{ getPassRate(run).toFixed(0) }}% pass</div>\n </div>\n @if (getRunTags(run).length > 0) {\n <div class=\"selector-tags\">\n @for (tag of getRunTags(run).slice(0, 2); track tag) {\n <span class=\"tag-mini\">{{ tag }}</span>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n @if (compareRunB) {\n <div class=\"selected-run-preview\">\n <div class=\"preview-header\">\n <span class=\"preview-label\">Selected:</span>\n <button class=\"clear-btn\" (click)=\"compareRunB = null; compareResults = []\">Clear</button>\n </div>\n <div class=\"preview-details\">\n <span>{{ compareRunB.StartedAt | date:'medium' }}</span>\n <span class=\"preview-rate\">{{ getPassRate(compareRunB).toFixed(1) }}%</span>\n </div>\n </div>\n }\n </div>\n </div>\n <!-- Comparison Results -->\n @if (compareRunA && compareRunB && !loadingCompare) {\n <div class=\"compare-results\">\n <!-- Summary Cards -->\n <div class=\"compare-summary\">\n <div class=\"compare-summary-card\">\n <div class=\"summary-label\">Pass Rate Change</div>\n <div class=\"summary-value\" [ngClass]=\"{'positive': getComparePassRateDiff()! > 0, 'negative': getComparePassRateDiff()! < 0}\">\n <i class=\"fas\" [ngClass]=\"{'fa-arrow-up': getComparePassRateDiff()! > 0, 'fa-arrow-down': getComparePassRateDiff()! < 0, 'fa-minus': getComparePassRateDiff() === 0}\"></i>\n {{ getComparePassRateDiff()! > 0 ? '+' : '' }}{{ getComparePassRateDiff()?.toFixed(1) }}%\n </div>\n </div>\n <div class=\"compare-summary-card\">\n <div class=\"summary-label\">Duration Change</div>\n <div class=\"summary-value\" [ngClass]=\"{'positive': getCompareDurationDiff()! < 0, 'negative': getCompareDurationDiff()! > 0}\">\n <i class=\"fas\" [ngClass]=\"{'fa-arrow-down': getCompareDurationDiff()! < 0, 'fa-arrow-up': getCompareDurationDiff()! > 0, 'fa-minus': getCompareDurationDiff() === 0}\"></i>\n {{ formatDuration(getAbsCompareDurationDiff()) }}\n </div>\n </div>\n <div class=\"compare-summary-card improved\">\n <div class=\"summary-label\">Improved</div>\n <div class=\"summary-value\">{{ getCompareImprovedCount() }}</div>\n </div>\n <div class=\"compare-summary-card regressed\">\n <div class=\"summary-label\">Regressed</div>\n <div class=\"summary-value\">{{ getCompareRegressedCount() }}</div>\n </div>\n </div>\n <!-- Detailed Comparison Table -->\n <div class=\"compare-table-section\">\n <h3><i class=\"fas fa-list\"></i> Test-by-Test Comparison</h3>\n <div class=\"compare-table-wrapper\">\n <table class=\"compare-table\">\n <thead>\n <tr>\n <th>Test</th>\n <th>Run A Status</th>\n <th>Run B Status</th>\n <th>Score Diff</th>\n <th>Duration Diff</th>\n <th>Change</th>\n </tr>\n </thead>\n <tbody>\n @for (result of compareResults; track result) {\n <tr [ngClass]=\"{'improved': result.runA && result.runB && result.runA.status !== 'Passed' && result.runB.status === 'Passed', 'regressed': result.runA && result.runB && result.runA.status === 'Passed' && result.runB.status !== 'Passed'}\">\n <td class=\"test-name-cell\">{{ result.testName }}</td>\n <td>\n @if (result.runA) {\n <span class=\"status-chip\" [ngClass]=\"'status-' + result.runA.status.toLowerCase()\">{{ result.runA.status }}</span>\n }\n @if (!result.runA) {\n <span class=\"status-chip status-missing\">N/A</span>\n }\n </td>\n <td>\n @if (result.runB) {\n <span class=\"status-chip\" [ngClass]=\"'status-' + result.runB.status.toLowerCase()\">{{ result.runB.status }}</span>\n }\n @if (!result.runB) {\n <span class=\"status-chip status-missing\">N/A</span>\n }\n </td>\n <td>\n @if (result.scoreDiff != null) {\n <span [ngClass]=\"{'positive': result.scoreDiff > 0, 'negative': result.scoreDiff < 0}\">\n {{ result.scoreDiff > 0 ? '+' : '' }}{{ (result.scoreDiff * 100).toFixed(1) }}%\n </span>\n }\n @if (result.scoreDiff == null) {\n <span class=\"muted\">-</span>\n }\n </td>\n <td>\n @if (result.durationDiff != null) {\n <span [ngClass]=\"{'positive': result.durationDiff < 0, 'negative': result.durationDiff > 0}\">\n {{ result.durationDiff > 0 ? '+' : '' }}{{ result.durationDiff.toFixed(1) }}s\n </span>\n }\n @if (result.durationDiff == null) {\n <span class=\"muted\">-</span>\n }\n </td>\n <td>\n @if (result.runA && result.runB && result.runA.status !== 'Passed' && result.runB.status === 'Passed') {\n <span class=\"change-indicator improved\">\n <i class=\"fas fa-arrow-up\"></i> Fixed\n </span>\n }\n @if (result.runA && result.runB && result.runA.status === 'Passed' && result.runB.status !== 'Passed') {\n <span class=\"change-indicator regressed\">\n <i class=\"fas fa-arrow-down\"></i> Broke\n </span>\n }\n @if (!result.statusChanged) {\n <span class=\"change-indicator unchanged\">\n <i class=\"fas fa-minus\"></i>\n </span>\n }\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </div>\n </div>\n }\n <!-- Loading State for Compare -->\n @if (loadingCompare) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading comparison data...\"></mj-loading>\n </div>\n }\n <!-- Empty State -->\n @if (!compareRunA || !compareRunB) {\n <mj-empty-state\n Icon=\"fa-solid fa-scale-balanced\"\n Title=\"Select Two Runs to Compare\"\n Message=\"Choose a baseline run (A) and a comparison run (B) from the lists above to see a detailed side-by-side comparison.\" />\n }\n <!-- No Runs State -->\n @if (runsLoaded && suiteRuns.length < 2) {\n <mj-empty-state\n Icon=\"fa-solid fa-scale-balanced\"\n Title=\"Not Enough Runs to Compare\"\n Message=\"You need at least 2 suite runs to use the comparison feature.\"\n ActionText=\"Run Suite Now\"\n ActionIcon=\"fa-solid fa-play\"\n (Action)=\"runSuite()\" />\n }\n </div>\n }\n </div>\n\n <!-- Keyboard Shortcuts Toggle Button -->\n <button class=\"shortcuts-toggle\" (click)=\"toggleShortcuts()\" [title]=\"showShortcuts ? 'Hide keyboard shortcuts' : 'Show keyboard shortcuts'\">\n <i class=\"fas fa-keyboard\"></i>\n </button>\n\n <!-- Keyboard Shortcuts Hint (Desktop Only) -->\n @if (showShortcuts) {\n <div class=\"keyboard-shortcuts\">\n <div class=\"shortcuts-header\">\n <i class=\"fas fa-keyboard\"></i>\n Shortcuts\n <button class=\"shortcuts-close\" (click)=\"toggleShortcuts()\" title=\"Hide shortcuts\">\n <i class=\"fas fa-times\"></i>\n </button>\n </div>\n <div class=\"shortcut-list\">\n <div class=\"shortcut-item\">\n <span>Save changes</span>\n <span class=\"shortcut-keys\"><kbd>Cmd</kbd><kbd>S</kbd></span>\n </div>\n <div class=\"shortcut-item\">\n <span>Refresh</span>\n <span class=\"shortcut-keys\"><kbd>Cmd</kbd><kbd>R</kbd></span>\n </div>\n <div class=\"shortcut-item\">\n <span>Run Suite</span>\n <span class=\"shortcut-keys\"><kbd>Cmd</kbd><kbd>Enter</kbd></span>\n </div>\n <div class=\"shortcut-item\">\n <span>Switch Tabs</span>\n <span class=\"shortcut-keys\"><kbd>1</kbd>-<kbd>5</kbd></span>\n </div>\n </div>\n </div>\n }\n\n <!-- Slide Panel for Suite Execution -->\n @if (testingDialogService.IsPanelOpen) {\n <mj-slide-panel\n Mode=\"slide\"\n [Title]=\"testingDialogService.PanelOptions?.suiteId ? 'Suite Execution' : 'Run Suite'\"\n [Resizable]=\"true\"\n (Closed)=\"OnPanelClosed()\">\n <app-test-run-dialog\n [PanelMode]=\"true\"\n [selectedTestId]=\"testingDialogService.PanelOptions?.testId ?? null\"\n [selectedSuiteId]=\"testingDialogService.PanelOptions?.suiteId ?? null\"\n [runMode]=\"testingDialogService.PanelOptions?.mode ?? 'suite'\"\n (PanelClose)=\"OnPanelClosed()\">\n </app-test-run-dialog>\n </mj-slide-panel>\n }\n\n <!-- Add Tests Picker Dialog -->\n @if (showAddTestsDialog) {\n <div class=\"picker-backdrop\" (click)=\"closeAddTestsDialog()\"></div>\n <div class=\"picker-dialog\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"add-tests-dialog-title\" (click)=\"$event.stopPropagation()\">\n <div class=\"picker-header\">\n <h2 id=\"add-tests-dialog-title\" class=\"picker-title\">\n <i class=\"fas fa-plus-circle\"></i> Add tests to suite\n </h2>\n <button type=\"button\" class=\"picker-close\" (click)=\"closeAddTestsDialog()\" [disabled]=\"isAddingTests\" aria-label=\"Close\">\n <i class=\"fas fa-times\"></i>\n </button>\n </div>\n\n <div class=\"picker-search\">\n <i class=\"fas fa-search picker-search-icon\"></i>\n <input\n #pickerSearch\n type=\"text\"\n class=\"picker-search-input\"\n placeholder=\"Search tests by name, description, or type...\"\n [(ngModel)]=\"addTestsSearch\"\n autofocus\n />\n @if (addTestsSearch) {\n <button type=\"button\" class=\"picker-search-clear\" (click)=\"addTestsSearch = ''\" aria-label=\"Clear search\">\n <i class=\"fas fa-times\"></i>\n </button>\n }\n </div>\n\n <div class=\"picker-toolbar\">\n <span class=\"picker-toolbar-status\">\n @if (selectedTestIdsToAdd.size > 0) {\n <strong>{{ selectedTestIdsToAdd.size }}</strong> selected\n } @else if (!loadingAvailableTests) {\n {{ filteredAvailableTests.length }} test{{ filteredAvailableTests.length === 1 ? '' : 's' }} available\n }\n </span>\n <div class=\"picker-toolbar-actions\">\n <button type=\"button\" class=\"picker-link-btn\" (click)=\"selectAllFiltered()\" [disabled]=\"loadingAvailableTests || filteredAvailableTests.length === 0\">\n Select all\n </button>\n <button type=\"button\" class=\"picker-link-btn\" (click)=\"clearAddSelection()\" [disabled]=\"selectedTestIdsToAdd.size === 0\">\n Clear\n </button>\n </div>\n </div>\n\n <div class=\"picker-body\">\n @if (loadingAvailableTests) {\n <div class=\"picker-loading\">\n <mj-loading text=\"Loading tests...\"></mj-loading>\n </div>\n } @else if (filteredAvailableTests.length === 0) {\n @if (availableTests.length === 0) {\n <mj-empty-state\n Variant=\"success\"\n Size=\"compact\"\n Title=\"Everything's already in the suite\"\n Message=\"This suite contains every available test. Create a new test first to add more.\" />\n } @else {\n <mj-empty-state\n Variant=\"no-results\"\n Size=\"compact\"\n Title=\"No matches\"\n [Message]=\"AddTestsNoMatchMessage\" />\n }\n } @else {\n <ul class=\"picker-list\">\n @for (t of filteredAvailableTests; track t.ID) {\n <li\n class=\"picker-row\"\n [class.picker-row--selected]=\"isAddSelected(t.ID)\"\n (click)=\"toggleAddSelection(t.ID)\"\n role=\"checkbox\"\n [attr.aria-checked]=\"isAddSelected(t.ID)\"\n tabindex=\"0\"\n >\n <span class=\"picker-check\">\n @if (isAddSelected(t.ID)) {\n <i class=\"fas fa-check\"></i>\n }\n </span>\n <div class=\"picker-row-main\">\n <div class=\"picker-row-name\">{{ t.Name }}</div>\n @if (t.Description) {\n <div class=\"picker-row-desc\">{{ t.Description }}</div>\n }\n </div>\n <div class=\"picker-row-meta\">\n @if (t.Type) {\n <span class=\"picker-row-pill\">{{ t.Type }}</span>\n }\n <span class=\"picker-row-pill picker-row-pill--status\" [attr.data-status]=\"t.Status?.toLowerCase()\">{{ t.Status }}</span>\n </div>\n </li>\n }\n </ul>\n }\n </div>\n\n <div class=\"picker-footer\">\n <button\n type=\"button\"\n class=\"picker-btn picker-btn--primary\"\n (click)=\"confirmAddTests()\"\n [disabled]=\"selectedTestIdsToAdd.size === 0 || isAddingTests\"\n >\n @if (isAddingTests) {\n <i class=\"fas fa-spinner fa-spin\"></i> Adding\u2026\n } @else {\n <i class=\"fas fa-check\"></i>\n @if (selectedTestIdsToAdd.size === 0) {\n Add tests\n } @else if (selectedTestIdsToAdd.size === 1) {\n Add 1 test\n } @else {\n Add {{ selectedTestIdsToAdd.size }} tests\n }\n }\n </button>\n <button\n type=\"button\"\n class=\"picker-btn picker-btn--ghost\"\n (click)=\"closeAddTestsDialog()\"\n [disabled]=\"isAddingTests\"\n >\n Cancel\n </button>\n </div>\n </div>\n }\n\n <!-- Sticky Save Bar \u2014 always in the DOM so CSS transitions can fire reliably.\n Visibility is controlled by the .save-bar--visible class, driven by isDirty. -->\n <div\n class=\"save-bar\"\n [class.save-bar--visible]=\"isDirty\"\n [attr.aria-hidden]=\"!isDirty\"\n role=\"region\"\n aria-label=\"Unsaved changes\"\n >\n <div class=\"save-bar-message\">\n <span class=\"save-bar-dot\" aria-hidden=\"true\">\u25CF</span>\n <span class=\"save-bar-text\">\n <strong>Unsaved changes</strong>\n <span class=\"save-bar-fields\">\n @if (dirtyFieldNames.length === 1) {\n {{ dirtyFieldNames[0] }} edited\n } @else if (dirtyFieldNames.length > 1) {\n {{ dirtyFieldNames.length }} fields edited\n }\n </span>\n </span>\n </div>\n <div class=\"save-bar-actions\">\n <button\n type=\"button\"\n class=\"save-bar-btn save-bar-btn--primary\"\n (click)=\"saveChanges()\"\n [disabled]=\"isSaving || !isDirty\"\n [attr.tabindex]=\"isDirty ? 0 : -1\"\n title=\"Save changes (\u2318S)\"\n >\n @if (isSaving) {\n <i class=\"fas fa-spinner fa-spin\"></i> Saving\u2026\n } @else {\n <i class=\"fas fa-check\"></i> Save changes\n <span class=\"save-bar-kbd\"><kbd>\u2318</kbd><kbd>S</kbd></span>\n }\n </button>\n <button\n type=\"button\"\n class=\"save-bar-btn save-bar-btn--ghost\"\n (click)=\"discardChanges()\"\n [disabled]=\"isSaving || !isDirty\"\n [attr.tabindex]=\"isDirty ? 0 : -1\"\n title=\"Discard changes\"\n >\n <i class=\"fas fa-undo\"></i> Discard\n </button>\n </div>\n </div>\n</div>\n", styles: ["/* ===========================\n Test Suite Form - World-Class UX\n =========================== */\n\n/* CSS Custom Properties for Theming - using :host for Angular encapsulation */\n:host {\n --test-primary: var(--mj-brand-primary);\n --test-primary-light: var(--mj-brand-primary);\n --test-success: var(--mj-status-success);\n --test-error: var(--mj-status-error);\n --test-warning: var(--mj-status-warning);\n --test-disabled: var(--mj-text-muted);\n --test-bg: var(--mj-bg-surface-card);\n --test-surface: var(--mj-bg-surface);\n --test-border: var(--mj-border-default);\n --test-text: var(--mj-text-primary);\n --test-text-secondary: var(--mj-text-secondary);\n --test-text-muted: var(--mj-text-disabled);\n --test-radius-sm: 6px;\n --test-radius-md: 10px;\n --test-radius-lg: 16px;\n --test-shadow-sm: var(--mj-shadow-sm);\n --test-shadow-md: var(--mj-shadow-md);\n --test-shadow-lg: var(--mj-shadow-lg);\n --test-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n display: block;\n height: 100%;\n}\n\n.test-suite-form {\n position: relative;\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--test-bg);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n}\n\n/* Breadcrumb */\n.breadcrumb {\n margin-bottom: 16px;\n}\n\n.breadcrumb ol {\n display: flex;\n align-items: center;\n gap: 4px;\n list-style: none;\n margin: 0;\n padding: 0;\n font-size: 13px;\n}\n\n.breadcrumb li {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.breadcrumb a {\n color: var(--test-primary);\n text-decoration: none;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 8px;\n border-radius: 6px;\n transition: background 0.15s;\n}\n\n.breadcrumb a:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n text-decoration: none;\n}\n\n.breadcrumb .separator {\n font-size: 10px;\n color: var(--test-text-muted);\n margin: 0 4px;\n}\n\n.breadcrumb .current {\n color: var(--test-text-secondary);\n font-weight: 500;\n}\n\n.breadcrumb-text {\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* Header */\n.suite-header {\n background: var(--test-surface);\n border-bottom: 1px solid var(--test-border);\n padding: 20px;\n}\n\n.header-content {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 16px;\n gap: 16px;\n}\n\n.header-left {\n display: flex;\n gap: 16px;\n flex: 1;\n min-width: 0;\n}\n\n.suite-icon {\n width: 56px;\n height: 56px;\n border-radius: var(--test-radius-md);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-inverse);\n font-size: 24px;\n flex-shrink: 0;\n box-shadow: var(--test-shadow-md);\n transition: var(--test-transition);\n}\n\n.suite-icon:hover { transform: scale(1.05); }\n\n.suite-info { flex: 1; min-width: 0; }\n\n.suite-info h1 {\n margin: 0 0 8px 0;\n font-size: clamp(18px, 4vw, 24px);\n font-weight: 700;\n color: var(--test-text);\n word-wrap: break-word;\n}\n\n.suite-meta {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.status-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 14px;\n border-radius: 20px;\n color: var(--mj-text-inverse);\n font-size: 12px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-badge.status-active { background: var(--test-success); }\n.status-badge.status-disabled { background: var(--test-disabled); }\n.status-badge.status-pending { background: var(--test-warning); }\n\n.status-badge-inline {\n display: inline-flex;\n padding: 2px 10px;\n border-radius: 10px;\n color: var(--mj-text-inverse);\n font-size: 11px;\n font-weight: 600;\n}\n\n.status-badge-inline.status-active { background: var(--test-success); }\n.status-badge-inline.status-disabled { background: var(--test-disabled); }\n.status-badge-inline.status-pending { background: var(--test-warning); }\n\n.test-count {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-size: 14px;\n color: var(--test-text-secondary);\n padding: 4px 10px;\n background: var(--test-bg);\n border-radius: var(--test-radius-sm);\n}\n\n.header-actions {\n display: flex;\n gap: 8px;\n flex-shrink: 0;\n}\n\n.suite-description {\n padding: 16px;\n background: var(--mj-bg-surface-card);\n border-radius: var(--test-radius-md);\n border: 1px solid var(--test-border);\n}\n\n.suite-description p {\n margin: 0;\n color: var(--test-text-secondary);\n line-height: 1.6;\n font-size: 14px;\n}\n\n/* Tabs */\n.tabs-container {\n background: var(--test-surface);\n border-bottom: 1px solid var(--test-border);\n position: sticky;\n top: 0;\n z-index: 10;\n}\n\n.tabs {\n display: flex;\n padding: 0 20px;\n overflow-x: auto;\n scrollbar-width: none;\n}\n\n.tabs::-webkit-scrollbar { display: none; }\n\n.tab {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 14px 18px;\n border: none;\n background: transparent;\n border-bottom: 3px solid transparent;\n color: var(--test-text-secondary);\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: var(--test-transition);\n white-space: nowrap;\n}\n\n.tab:hover {\n color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.tab.active {\n color: var(--test-primary);\n border-bottom-color: var(--test-primary);\n font-weight: 600;\n}\n\n.tab-badge {\n background: var(--test-border);\n color: var(--test-text-secondary);\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.tab.active .tab-badge {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n color: var(--test-primary);\n}\n\n.tab-shortcut {\n font-size: 10px;\n color: var(--test-text-muted);\n background: var(--test-bg);\n padding: 2px 6px;\n border-radius: 4px;\n font-weight: 600;\n}\n\n/* Tab Content */\n.tab-content {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n}\n\n/* Overview Tab */\n.overview-tab {\n display: flex;\n flex-direction: column;\n gap: 20px;\n animation: fadeIn 0.3s ease-out;\n}\n\n@keyframes fadeIn {\n from { opacity: 0; transform: translateY(10px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n.info-section, .config-section {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.info-section h3, .config-section h3 {\n margin: 0 0 20px 0;\n font-size: 18px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.info-section h3 i, .config-section h3 i {\n color: var(--test-primary);\n}\n\n.info-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 16px;\n}\n\n.info-item {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.info-label {\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.info-value {\n font-size: 14px;\n color: var(--test-text);\n font-weight: 500;\n}\n\n.config-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 20px;\n}\n\n.config-item {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.config-item label {\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.config-input {\n padding: 10px 14px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n font-size: 14px;\n transition: var(--test-transition);\n}\n\n.config-input:focus {\n outline: none;\n border-color: var(--test-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.config-hint {\n font-size: 11px;\n color: var(--test-text-muted);\n}\n\n/* Tests Tab */\n.tests-tab, .runs-tab {\n animation: fadeIn 0.3s ease-out;\n}\n\n.loading-state { padding: 0; }\n\n.skeleton-list {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.skeleton-card {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 16px;\n background: var(--test-surface);\n border-radius: var(--test-radius-md);\n border: 1px solid var(--test-border);\n}\n\n.skeleton-sequence {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n background: linear-gradient(90deg, var(--mj-border-default) 25%, var(--mj-bg-surface-sunken) 50%, var(--mj-border-default) 75%);\n background-size: 200% 100%;\n animation: shimmer 1.5s infinite;\n}\n\n.skeleton-icon {\n width: 40px;\n height: 40px;\n border-radius: var(--test-radius-md);\n background: linear-gradient(90deg, var(--mj-border-default) 25%, var(--mj-bg-surface-sunken) 50%, var(--mj-border-default) 75%);\n background-size: 200% 100%;\n animation: shimmer 1.5s infinite;\n}\n\n.skeleton-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.skeleton-line {\n height: 14px;\n border-radius: 4px;\n background: linear-gradient(90deg, var(--mj-border-default) 25%, var(--mj-bg-surface-sunken) 50%, var(--mj-border-default) 75%);\n background-size: 200% 100%;\n animation: shimmer 1.5s infinite;\n}\n\n.skeleton-line.wide { width: 70%; }\n.skeleton-line.narrow { width: 40%; }\n\n@keyframes shimmer {\n 0% { background-position: 200% 0; }\n 100% { background-position: -200% 0; }\n}\n\n.tests-list, .runs-list {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.test-item, .run-item {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 16px;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.test-item:hover, .run-item:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n border-color: var(--test-primary-light);\n transform: translateX(4px);\n}\n\n.test-sequence {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--test-bg);\n border-radius: 50%;\n font-size: 14px;\n font-weight: 700;\n color: var(--test-text-secondary);\n flex-shrink: 0;\n}\n\n.test-icon, .run-icon {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: var(--test-radius-md);\n color: var(--mj-text-inverse);\n font-size: 18px;\n flex-shrink: 0;\n box-shadow: var(--test-shadow-sm);\n}\n\n.test-icon {\n background: var(--test-primary);\n}\n\n.test-content, .run-content { flex: 1; min-width: 0; }\n\n.test-name, .run-header {\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n margin-bottom: 4px;\n}\n\n.run-header {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.run-id { font-weight: 600; }\n\n.run-status {\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n}\n\n.test-status, .run-meta {\n display: flex;\n gap: 12px;\n font-size: 12px;\n color: var(--test-text-secondary);\n}\n\n.test-status span, .run-meta span {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n\n.test-item > i, .run-item > i {\n color: var(--test-text-muted);\n font-size: 14px;\n transition: var(--test-transition);\n}\n\n.test-item:hover > i, .run-item:hover > i {\n color: var(--test-primary);\n transform: translateX(2px);\n}\n\n/* Keyboard Shortcuts */\n/* Keyboard shortcuts toggle button - visible when shortcuts are hidden */\n.shortcuts-toggle {\n position: fixed;\n bottom: 20px;\n right: 20px;\n width: 36px;\n height: 36px;\n border-radius: 50%;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n box-shadow: var(--test-shadow-md);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--test-text-secondary);\n font-size: 14px;\n z-index: 99;\n transition: var(--test-transition);\n opacity: 0.7;\n}\n\n.shortcuts-toggle:hover {\n opacity: 1;\n transform: scale(1.1);\n color: var(--test-primary);\n border-color: var(--test-primary);\n}\n\n.keyboard-shortcuts {\n position: fixed;\n bottom: 20px;\n right: 20px;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n padding: 12px 16px;\n box-shadow: var(--test-shadow-lg);\n font-size: 12px;\n z-index: 100;\n max-width: 260px;\n}\n\n.shortcuts-header {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-bottom: 10px;\n padding-bottom: 8px;\n border-bottom: 1px solid var(--test-border);\n font-weight: 600;\n color: var(--test-text);\n}\n\n.shortcuts-close {\n margin-left: auto;\n background: none;\n border: none;\n cursor: pointer;\n color: var(--test-text-muted);\n font-size: 12px;\n padding: 2px 4px;\n border-radius: 4px;\n transition: var(--test-transition);\n}\n\n.shortcuts-close:hover {\n color: var(--test-text);\n background: var(--test-border);\n}\n\n.shortcut-list {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.shortcut-item {\n display: flex;\n justify-content: space-between;\n align-items: center;\n color: var(--test-text-secondary);\n}\n\n.shortcut-keys {\n display: flex;\n gap: 4px;\n}\n\n.shortcut-keys kbd {\n background: var(--test-bg);\n border: 1px solid var(--test-border);\n border-radius: 4px;\n padding: 2px 6px;\n font-size: 11px;\n color: var(--test-text);\n}\n\n/* Responsive */\n@media (max-width: 1024px) {\n .keyboard-shortcuts, .shortcuts-toggle { display: none; }\n}\n\n@media (max-width: 768px) {\n .suite-header { padding: 16px; }\n\n .header-content {\n flex-direction: column;\n gap: 16px;\n }\n\n .header-actions {\n width: 100%;\n justify-content: stretch;\n }\n\n .header-actions button { flex: 1; }\n\n .tab-shortcut { display: none; }\n\n .info-grid { grid-template-columns: 1fr; }\n\n .test-item, .run-item { padding: 14px; }\n}\n\n@media (max-width: 480px) {\n .suite-icon {\n width: 40px;\n height: 40px;\n font-size: 18px;\n }\n\n .suite-info h1 { font-size: 16px; }\n\n .tab-badge { display: none; }\n\n .test-sequence { display: none; }\n}\n\n@media (hover: none) and (pointer: coarse) {\n .test-item:active, .run-item:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n transform: scale(0.98);\n }\n\n .tab { min-height: 48px; }\n .test-item, .run-item { min-height: 64px; }\n}\n\n@media (prefers-reduced-motion: reduce) {\n *, *::before, *::after {\n animation-duration: 0.01ms !important;\n transition-duration: 0.01ms !important;\n }\n}\n\n@media print {\n .header-actions, .tabs-container, .keyboard-shortcuts {\n display: none !important;\n }\n}\n\n/* ===========================\n Tags UI\n =========================== */\n.run-tags {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin-top: 8px;\n}\n\n.tag-chip {\n display: inline-flex;\n align-items: center;\n padding: 3px 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-brand-primary-hover);\n}\n\n.tag-mini {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 4px;\n font-size: 10px;\n font-weight: 500;\n color: var(--mj-text-muted);\n}\n\n.tag-more {\n font-size: 10px;\n color: var(--mj-text-disabled);\n font-weight: 500;\n}\n\n/* Evaluation metrics row for Runs list */\n.run-eval-metrics {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 8px;\n}\n\n.eval-metric {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 3px 8px;\n border-radius: 6px;\n font-size: 11px;\n font-weight: 500;\n}\n\n.eval-metric.status {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.eval-metric.status.status-completed {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.eval-metric.status.status-failed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.eval-metric.status.status-running {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.eval-metric.status.status-pending {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.eval-metric.human {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n border: 1px solid var(--mj-status-warning);\n color: var(--mj-status-warning);\n}\n\n.eval-metric.human .eval-pending {\n font-size: 9px;\n color: var(--mj-status-warning);\n}\n\n.eval-metric.auto {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n color: var(--mj-brand-primary-hover);\n}\n\n.eval-metric.auto.high {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-success) 30%, transparent);\n color: var(--mj-status-success);\n}\n\n.eval-metric.auto.medium {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 30%, transparent);\n color: var(--mj-status-warning);\n}\n\n.eval-metric.auto.low {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 30%, transparent);\n color: var(--mj-status-error);\n}\n\n.tag-cell {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-wrap: wrap;\n}\n\n.tag-chip-table {\n display: inline-block;\n padding: 3px 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n color: var(--mj-brand-primary-hover);\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n white-space: nowrap;\n max-width: 80px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* ===========================\n Analytics Tab\n =========================== */\n.analytics-tab {\n animation: fadeIn 0.3s ease-out;\n}\n\n/* Collapsible filters */\n/* Filters disclosure migrated to <mj-accordion-panel>. The bespoke\n .analytics-filters wrapper card chrome, the .filters-header bar (+ hover),\n and the .filters-header > i chevron are now owned by the accordion and were\n removed. The title-slot layout (.filters-title flex row) and font are now\n provided by the accordion title + Size=\"sm\"; the collapsed summary uses the\n shared .mj-accordion-badge (--muted --right). Only the body content\n (.filters-content) styling is kept below. */\n\n.filters-content {\n display: flex;\n flex-direction: column;\n gap: 16px;\n padding: 12px 16px 16px 16px;\n border-top: 1px solid var(--test-border);\n}\n\n.filter-group {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.filter-group label {\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.filter-buttons {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.filter-btn {\n padding: 8px 16px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n background: var(--test-surface);\n color: var(--test-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.filter-btn:hover {\n border-color: var(--test-primary);\n color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.filter-btn.active {\n background: var(--test-primary);\n border-color: var(--test-primary);\n color: var(--mj-text-inverse);\n}\n\n.filter-btn.tag-btn {\n padding: 6px 12px;\n font-size: 12px;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n}\n\n.filter-btn.tag-btn i.fa-check {\n font-size: 10px;\n}\n\n.filter-btn.tag-btn.all-tags-btn {\n font-weight: 600;\n}\n\n.filter-btn.tag-btn.all-tags-btn i {\n font-size: 11px;\n}\n\n.filter-hint {\n font-weight: 400;\n font-size: 10px;\n color: var(--test-primary);\n text-transform: none;\n letter-spacing: normal;\n}\n\n.tag-filters {\n max-height: 120px;\n overflow-y: auto;\n}\n\n/* KPI Cards */\n.analytics-kpis {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.kpi-card {\n display: flex;\n align-items: center;\n gap: 16px;\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 20px;\n box-shadow: var(--test-shadow-sm);\n transition: var(--test-transition);\n}\n\n.kpi-card:hover {\n transform: translateY(-2px);\n box-shadow: var(--test-shadow-md);\n}\n\n.kpi-icon {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-radius: var(--test-radius-md);\n color: var(--test-primary);\n font-size: 20px;\n}\n\n.kpi-icon.success {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.kpi-icon.info {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.kpi-icon.warning {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--test-warning);\n}\n\n.kpi-content {\n flex: 1;\n min-width: 0;\n}\n\n.kpi-value {\n font-size: 24px;\n font-weight: 700;\n color: var(--test-text);\n line-height: 1.2;\n}\n\n.kpi-label {\n font-size: 12px;\n color: var(--test-text-secondary);\n margin-top: 2px;\n}\n\n.kpi-trend {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 12px;\n font-weight: 600;\n margin-top: 4px;\n padding: 2px 8px;\n border-radius: 10px;\n background: var(--mj-bg-surface-sunken);\n color: var(--test-text-secondary);\n}\n\n.kpi-trend.trend-up {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.kpi-trend.trend-down {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n/* Analytics Table */\n.analytics-table-section {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.analytics-table-section h3 {\n margin: 0 0 16px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.analytics-table-section h3 i {\n color: var(--test-primary);\n}\n\n.analytics-table-wrapper {\n overflow-x: auto;\n margin: 0 -24px;\n padding: 0 24px;\n}\n\n.analytics-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.analytics-table th {\n text-align: left;\n padding: 12px 16px;\n background: var(--mj-bg-surface-card);\n border-bottom: 2px solid var(--test-border);\n font-weight: 600;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n font-size: 11px;\n letter-spacing: 0.5px;\n white-space: nowrap;\n}\n\n.analytics-table td {\n padding: 14px 16px;\n border-bottom: 1px solid var(--test-border);\n color: var(--test-text);\n}\n\n.analytics-table tbody tr.clickable-row {\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.analytics-table tbody tr.clickable-row:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.status-chip {\n display: inline-flex;\n align-items: center;\n padding: 4px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-chip.status-completed { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--test-success); }\n.status-chip.status-passed { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--test-success); }\n.status-chip.status-failed { background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface)); color: var(--test-error); }\n.status-chip.status-error { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--test-warning); }\n.status-chip.status-running { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--test-primary); }\n.status-chip.status-pending { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n.status-chip.status-cancelled { background: var(--mj-bg-surface-sunken); color: var(--test-disabled); }\n.status-chip.status-missing { background: var(--mj-bg-surface-sunken); color: var(--test-text-muted); }\n.status-chip.status-timeout { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--test-warning); }\n.status-chip.status-skipped { background: var(--mj-bg-surface-sunken); color: var(--test-disabled); }\n\n.pass-rate-cell {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 100px;\n}\n\n.pass-rate-bar {\n height: 6px;\n border-radius: 3px;\n background: var(--test-success);\n transition: width 0.3s ease;\n max-width: 60px;\n}\n\n.pass-rate-bar.medium { background: var(--test-warning); }\n.pass-rate-bar.low { background: var(--test-error); }\n\n/* Analytics Sub-navigation */\n.analytics-subnav {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 8px;\n margin-bottom: 20px;\n box-shadow: var(--test-shadow-sm);\n display: inline-flex;\n}\n\n.subnav-tabs {\n display: flex;\n gap: 4px;\n background: var(--test-bg);\n border-radius: var(--test-radius-md);\n padding: 4px;\n}\n\n.subnav-tab {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n border: none;\n border-radius: var(--test-radius-sm);\n background: transparent;\n color: var(--test-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.subnav-tab:hover {\n color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.subnav-tab.active {\n background: var(--test-surface);\n color: var(--test-primary);\n box-shadow: var(--test-shadow-sm);\n}\n\n.subnav-tab i {\n font-size: 14px;\n}\n\n/* Matrix View */\n.matrix-section {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 16px;\n box-shadow: var(--test-shadow-sm);\n display: flex;\n flex-direction: column;\n max-height: calc(100vh - 280px);\n min-height: 300px;\n}\n\n.matrix-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 12px;\n margin-bottom: 12px;\n padding-bottom: 12px;\n border-bottom: 1px solid var(--test-border);\n flex-shrink: 0;\n}\n\n.matrix-header-right {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.matrix-header h3 {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 0;\n font-size: 15px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.matrix-header h3 i {\n color: var(--test-primary);\n}\n\n.matrix-run-count {\n font-size: 12px;\n color: var(--test-text-muted);\n font-weight: 500;\n}\n\n/* Matrix filter input */\n.matrix-filter-input {\n display: flex;\n align-items: center;\n gap: 8px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--test-border);\n border-radius: 6px;\n padding: 4px 10px;\n min-width: 180px;\n}\n\n.matrix-filter-input i.fa-search {\n color: var(--mj-text-disabled);\n font-size: 12px;\n}\n\n.matrix-filter-input .filter-input {\n border: none;\n background: transparent;\n outline: none;\n font-size: 12px;\n color: var(--test-text);\n width: 100%;\n}\n\n.matrix-filter-input .filter-input::placeholder {\n color: var(--mj-text-disabled);\n}\n\n.clear-filter-btn {\n border: none;\n background: none;\n padding: 2px 4px;\n cursor: pointer;\n color: var(--mj-text-disabled);\n font-size: 10px;\n border-radius: 3px;\n transition: all 0.15s ease;\n}\n\n.clear-filter-btn:hover {\n background: var(--mj-border-default);\n color: var(--mj-text-muted);\n}\n\n/* Scrollable matrix container with fixed height */\n.matrix-scroll-container {\n flex: 1;\n overflow: auto;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n}\n\n.test-matrix {\n display: table;\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.test-matrix thead {\n display: table-header-group;\n}\n\n.test-matrix thead tr {\n display: table-row;\n}\n\n.test-matrix tbody {\n display: table-row-group;\n}\n\n.test-matrix tbody tr {\n display: table-row;\n cursor: pointer;\n transition: background-color 0.15s ease;\n}\n\n.test-matrix tbody tr:hover {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.test-matrix tbody tr.row-selected {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent) !important;\n}\n\n.test-matrix tbody tr.row-selected td {\n border-top: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n border-bottom: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.test-matrix tbody tr.row-selected .seq-cell,\n.test-matrix tbody tr.row-selected .test-name-cell {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent) !important;\n}\n\n.test-matrix tfoot {\n display: table-footer-group;\n}\n\n.test-matrix th,\n.test-matrix td {\n display: table-cell;\n border: 1px solid var(--test-border);\n padding: 8px 12px;\n text-align: center;\n vertical-align: middle;\n}\n\n.test-matrix th {\n background: var(--test-bg);\n font-weight: 600;\n font-size: 11px;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n position: sticky;\n top: 0;\n z-index: 10;\n border-bottom: 3px solid var(--mj-text-secondary) !important;\n}\n\n/* Sequence column - shared styles */\n.test-matrix .seq-header,\n.test-matrix .seq-cell {\n width: 36px;\n min-width: 36px;\n max-width: 36px;\n text-align: center;\n position: sticky;\n left: 0;\n font-size: 11px;\n color: var(--mj-text-muted);\n border-right: 1px solid var(--test-border);\n padding: 6px 4px !important;\n}\n\n/* Seq header - sticky top AND left, highest z-index */\n.test-matrix .seq-header {\n cursor: pointer;\n font-weight: 600;\n background: var(--test-bg);\n z-index: 12; /* Higher than other headers */\n top: 0;\n}\n\n/* Seq body cells - sticky left only, lower z-index */\n.test-matrix .seq-cell {\n background: var(--test-surface);\n z-index: 2;\n}\n\n.test-matrix .seq-header i {\n font-size: 9px;\n margin-left: 2px;\n opacity: 0.6;\n}\n\n.test-matrix .seq-header:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.test-matrix .test-name-header {\n text-align: left;\n min-width: 150px;\n max-width: 500px;\n width: auto;\n position: sticky;\n left: 36px;\n background: var(--test-bg);\n z-index: 11;\n border-right: 2px solid var(--test-border);\n cursor: pointer;\n}\n\n.test-matrix .test-name-header i {\n font-size: 9px;\n margin-left: 4px;\n opacity: 0.6;\n}\n\n.test-matrix .test-name-header:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.test-matrix .run-header {\n min-width: 120px;\n width: 120px;\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n/* Spacer column absorbs extra width */\n.test-matrix .spacer-header,\n.test-matrix .spacer-cell {\n width: 100%;\n min-width: 20px;\n background: var(--test-bg);\n border: none;\n}\n\n.test-matrix .spacer-cell {\n background: var(--test-surface);\n}\n\n.test-matrix .run-header:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.run-header-content {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n}\n\n.run-date {\n font-size: 12px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.run-pass-rate {\n font-size: 11px;\n font-weight: 700;\n padding: 2px 8px;\n border-radius: 10px;\n}\n\n.run-pass-rate.high {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.run-pass-rate.medium {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--test-warning);\n}\n\n.run-pass-rate.low {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n.run-tags {\n display: flex;\n gap: 4px;\n}\n\n.tag-tiny {\n font-size: 9px;\n padding: 2px 6px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--test-primary);\n border-radius: 8px;\n white-space: nowrap;\n max-width: 60px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* Matrix column header tags - emphasized */\n.run-tags-header {\n display: flex;\n flex-wrap: wrap;\n gap: 3px;\n justify-content: center;\n margin-bottom: 4px;\n}\n\n.tag-chip-header {\n display: inline-block;\n padding: 3px 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n color: var(--mj-brand-primary-hover);\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n white-space: nowrap;\n max-width: 70px;\n overflow: hidden;\n text-overflow: ellipsis;\n text-transform: none;\n letter-spacing: normal;\n}\n\n.tag-more-header {\n font-size: 9px;\n color: var(--test-text-secondary);\n padding: 2px 4px;\n}\n\n.test-matrix .test-name-cell {\n text-align: left;\n min-width: 150px;\n max-width: 500px;\n width: auto;\n position: sticky;\n left: 36px;\n background: var(--test-surface);\n z-index: 2;\n border-right: 2px solid var(--test-border);\n padding: 6px 10px !important;\n}\n\n.test-name {\n display: block;\n white-space: nowrap;\n font-weight: 500;\n color: var(--test-text);\n font-size: 12px;\n}\n\n.result-cell {\n position: relative;\n min-width: 120px;\n width: 120px;\n transition: var(--test-transition);\n}\n\n.result-cell.clickable {\n cursor: pointer;\n}\n\n.result-cell.clickable:hover {\n transform: scale(1.1);\n box-shadow: var(--mj-shadow-md);\n z-index: 5;\n}\n\n.result-cell i {\n font-size: 14px;\n}\n\n/* Completed cells have neutral white background - pills tell the story */\n.result-cell.cell-passed,\n.result-cell.cell-failed,\n.result-cell.cell-error,\n.result-cell.cell-timeout,\n.result-cell.cell-running,\n.result-cell.cell-pending {\n background: var(--mj-bg-surface);\n color: var(--test-text);\n}\n\n/* Skipped/not-run cells get hatched background */\n.result-cell.cell-skipped {\n background: repeating-linear-gradient(\n 45deg,\n var(--mj-bg-surface-card),\n var(--mj-bg-surface-card) 4px,\n var(--mj-border-default) 4px,\n var(--mj-border-default) 8px\n );\n color: var(--test-disabled);\n}\n\n.result-cell.cell-none {\n background: var(--mj-bg-surface-card);\n color: var(--test-text-muted);\n}\n\n.cell-score {\n display: block;\n font-size: 10px;\n font-weight: 600;\n margin-top: 2px;\n}\n\n/* Matrix cell evaluation stack - shows multiple eval types horizontally */\n.cell-eval-stack {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n flex-wrap: nowrap;\n}\n\n.result-cell.multi-eval {\n min-width: 120px;\n width: auto;\n}\n\n/* Add timeout status icon */\n.cell-status.status-timeout {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 11px;\n}\n\n.cell-status.status-passed {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-status.status-failed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-status.status-error {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status.status-skipped {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.cell-status.status-running {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.cell-status.status-pending {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.cell-human {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 50%;\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n font-size: 10px;\n}\n\n.cell-auto {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 10px;\n font-weight: 600;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.cell-auto.high {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-auto.medium {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-auto.low {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-none-indicator {\n color: var(--test-text-muted);\n opacity: 0.5;\n}\n\n.matrix-info {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: var(--test-text-muted);\n padding: 12px;\n background: var(--test-bg);\n border-radius: var(--test-radius-sm);\n}\n\n.matrix-info i {\n color: var(--test-primary);\n}\n\n/* ===========================\n Chart View\n =========================== */\n.chart-section {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.chart-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 16px;\n margin-bottom: 20px;\n padding-bottom: 16px;\n border-bottom: 1px solid var(--test-border);\n}\n\n.chart-header h3 {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.chart-header h3 i {\n color: var(--test-primary);\n}\n\n.chart-legend {\n display: flex;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.chart-legend .legend-item {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n font-weight: 500;\n padding: 4px 10px;\n border-radius: 12px;\n}\n\n.chart-legend .legend-item.chart-passed {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.chart-legend .legend-item.chart-failed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n.chart-legend .legend-item.chart-error {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--test-warning);\n}\n\n.chart-legend .legend-item.chart-skipped {\n background: var(--mj-bg-surface-sunken);\n color: var(--test-disabled);\n}\n\n.chart-container {\n min-height: 500px;\n position: relative;\n overflow: hidden;\n background: var(--mj-bg-surface-card);\n border-radius: var(--test-radius-md);\n border: 1px solid var(--test-border);\n}\n\n.d3-chart {\n width: 100%;\n height: 500px;\n}\n\n.d3-chart svg {\n width: 100%;\n height: 100%;\n}\n\n/* D3 Chart Node Styles */\n.d3-chart .node {\n cursor: pointer;\n transition: transform 0.2s ease;\n}\n\n.d3-chart .node:hover {\n transform: scale(1.05);\n}\n\n.d3-chart .node-label {\n font-size: 11px;\n font-weight: 500;\n fill: var(--test-text);\n pointer-events: none;\n}\n\n.d3-chart .link {\n fill: none;\n stroke-opacity: 0.4;\n transition: stroke-opacity 0.2s ease;\n}\n\n.d3-chart .link:hover {\n stroke-opacity: 0.8;\n}\n\n.d3-chart .tooltip {\n position: absolute;\n padding: 10px 14px;\n background: var(--mj-bg-overlay);\n color: var(--mj-text-inverse);\n border-radius: 8px;\n font-size: 12px;\n pointer-events: none;\n z-index: 100;\n box-shadow: var(--mj-shadow-lg);\n max-width: 250px;\n}\n\n.d3-chart .tooltip-title {\n font-weight: 600;\n margin-bottom: 4px;\n}\n\n.d3-chart .tooltip-value {\n opacity: 0.8;\n}\n\n.chart-info {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: var(--test-text-muted);\n padding: 12px;\n background: var(--test-bg);\n border-radius: var(--test-radius-sm);\n margin-top: 16px;\n}\n\n.chart-info i {\n color: var(--test-primary);\n}\n\n/* ===========================\n Compare Tab\n =========================== */\n.compare-tab {\n animation: fadeIn 0.3s ease-out;\n}\n\n.compare-selection {\n display: grid;\n grid-template-columns: 1fr auto 1fr;\n gap: 24px;\n align-items: flex-start;\n margin-bottom: 24px;\n}\n\n.compare-run-selector {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 20px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.compare-run-selector h4 {\n margin: 0 0 16px 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.run-selector-list {\n max-height: 200px;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-bottom: 12px;\n}\n\n.run-selector-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.run-selector-item:hover {\n border-color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.run-selector-item.selected {\n border-color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n}\n\n.run-selector-item.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.selector-status {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.selector-content {\n flex: 1;\n min-width: 0;\n}\n\n.selector-date {\n font-size: 12px;\n font-weight: 500;\n color: var(--test-text);\n}\n\n.selector-rate {\n font-size: 11px;\n color: var(--test-text-secondary);\n}\n\n.selector-tags {\n display: flex;\n gap: 4px;\n flex-wrap: wrap;\n}\n\n.selected-run-preview {\n padding: 12px;\n background: var(--mj-bg-surface-card);\n border-radius: var(--test-radius-sm);\n border: 1px solid var(--test-border);\n}\n\n.preview-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.preview-label {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n color: var(--test-text-muted);\n}\n\n.clear-btn {\n padding: 4px 8px;\n border: none;\n background: transparent;\n color: var(--test-error);\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n}\n\n.clear-btn:hover { text-decoration: underline; }\n\n.preview-details {\n display: flex;\n justify-content: space-between;\n font-size: 12px;\n color: var(--test-text);\n}\n\n.preview-rate {\n font-weight: 600;\n color: var(--test-success);\n}\n\n.compare-vs {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n background: var(--test-bg);\n border-radius: 50%;\n color: var(--test-text-muted);\n font-size: 16px;\n align-self: center;\n margin-top: 60px;\n}\n\n/* Compare Results */\n.compare-results {\n animation: fadeIn 0.3s ease-out;\n}\n\n.compare-summary {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.compare-summary-card {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 20px;\n box-shadow: var(--test-shadow-sm);\n text-align: center;\n}\n\n.compare-summary-card .summary-label {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n color: var(--test-text-muted);\n margin-bottom: 8px;\n}\n\n.compare-summary-card .summary-value {\n font-size: 24px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n}\n\n.compare-summary-card .summary-value.positive { color: var(--test-success); }\n.compare-summary-card .summary-value.negative { color: var(--test-error); }\n\n.compare-summary-card.improved {\n border-left: 4px solid var(--test-success);\n}\n\n.compare-summary-card.improved .summary-value { color: var(--test-success); }\n\n.compare-summary-card.regressed {\n border-left: 4px solid var(--test-error);\n}\n\n.compare-summary-card.regressed .summary-value { color: var(--test-error); }\n\n/* Compare Table */\n.compare-table-section {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.compare-table-section h3 {\n margin: 0 0 16px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.compare-table-section h3 i {\n color: var(--test-primary);\n}\n\n.compare-table-wrapper {\n overflow-x: auto;\n}\n\n.compare-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.compare-table th {\n text-align: left;\n padding: 12px 16px;\n background: var(--mj-bg-surface-card);\n border-bottom: 2px solid var(--test-border);\n font-weight: 600;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n font-size: 11px;\n letter-spacing: 0.5px;\n white-space: nowrap;\n}\n\n.compare-table td {\n padding: 14px 16px;\n border-bottom: 1px solid var(--test-border);\n color: var(--test-text);\n}\n\n.compare-table tbody tr.improved {\n background: color-mix(in srgb, var(--mj-status-success) 5%, transparent);\n}\n\n.compare-table tbody tr.regressed {\n background: color-mix(in srgb, var(--mj-status-error) 5%, transparent);\n}\n\n.test-name-cell {\n font-weight: 500;\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.positive { color: var(--test-success); }\n.negative { color: var(--test-error); }\n.muted { color: var(--test-text-muted); }\n\n.change-indicator {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.change-indicator.improved {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.change-indicator.regressed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n.change-indicator.unchanged {\n background: var(--mj-bg-surface-sunken);\n color: var(--test-text-muted);\n}\n\n/* ===========================\n Responsive Analytics/Compare\n =========================== */\n@media (max-width: 1024px) {\n .compare-selection {\n grid-template-columns: 1fr;\n gap: 16px;\n }\n\n .compare-vs {\n margin: 0;\n align-self: center;\n justify-self: center;\n }\n\n .analytics-kpis {\n grid-template-columns: repeat(2, 1fr);\n }\n}\n\n@media (max-width: 768px) {\n .filter-buttons {\n flex-direction: column;\n }\n\n .filter-btn {\n width: 100%;\n text-align: center;\n }\n\n .analytics-kpis {\n grid-template-columns: 1fr;\n }\n\n .kpi-card {\n padding: 16px;\n }\n\n .kpi-value {\n font-size: 20px;\n }\n\n .compare-summary {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .analytics-table-wrapper,\n .compare-table-wrapper {\n margin: 0 -20px;\n padding: 0 20px;\n }\n\n .run-selector-list {\n max-height: 150px;\n }\n}\n\n@media (max-width: 480px) {\n .compare-summary {\n grid-template-columns: 1fr;\n }\n\n .compare-summary-card .summary-value {\n font-size: 20px;\n }\n\n .analytics-table th,\n .analytics-table td,\n .compare-table th,\n .compare-table td {\n padding: 10px 12px;\n font-size: 12px;\n }\n}\n\n/* ===========================\n Matrix Evaluation Indicators\n =========================== */\n\n/* Human Feedback Indicators */\n.cell-human {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 3px;\n min-width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 10px;\n}\n\n.cell-human.no-feedback {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n}\n\n.cell-human.no-feedback i {\n font-size: 11px;\n}\n\n.cell-human.has-feedback {\n padding: 0 6px;\n border-radius: 12px;\n min-width: 36px;\n}\n\n.cell-human.has-feedback i {\n font-size: 9px;\n}\n\n.cell-human.has-feedback .rating-value {\n font-weight: 700;\n font-size: 11px;\n}\n\n/* Human rating color coding: red \u22644, yellow 5-6, light-green 7-8, green 9-10 */\n.cell-human.rating-low {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-human.rating-medium {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-human.rating-good {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-human.rating-excellent {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n/* Auto Score Indicators */\n.cell-auto {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 3px;\n min-width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 10px;\n}\n\n.cell-auto.no-score {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n}\n\n.cell-auto.no-score i {\n font-size: 11px;\n}\n\n.cell-auto.has-score {\n padding: 0 6px;\n border-radius: 12px;\n min-width: 36px;\n}\n\n.cell-auto.has-score i {\n font-size: 9px;\n}\n\n.cell-auto.has-score .score-value {\n font-weight: 700;\n font-size: 10px;\n}\n\n/* Auto score color coding (0-100%): red <50, yellow 50-69, light-green 70-84, green 85+ */\n.cell-auto.score-low {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-auto.score-medium {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-auto.score-good {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-auto.score-excellent {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n/* Status indicators in matrix cells */\n.cell-status {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 11px;\n}\n\n.cell-status.status-passed {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-status.status-failed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-status.status-error {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status.status-timeout {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status.status-skipped,\n.cell-status.status-pending {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.cell-status.status-running {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n/* Not-run / Skipped cells with hatch pattern */\n.result-cell.cell-not-run {\n background: repeating-linear-gradient(\n 45deg,\n var(--mj-bg-surface-card),\n var(--mj-bg-surface-card) 4px,\n var(--mj-border-default) 4px,\n var(--mj-border-default) 8px\n );\n color: var(--mj-text-disabled);\n}\n\n.result-cell.cell-not-run .cell-eval-stack {\n opacity: 0.6;\n}\n\n.cell-not-run-indicator {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n color: var(--mj-text-disabled);\n font-size: 11px;\n}\n\n/* ===========================\n Matrix Totals Footer Row\n =========================== */\n.test-matrix tfoot {\n position: sticky;\n bottom: 0;\n z-index: 2;\n}\n\n.totals-row {\n background: var(--mj-bg-surface-sunken);\n border-top: 2px solid var(--test-border);\n}\n\n.totals-row td {\n padding: 10px 12px;\n font-weight: 600;\n}\n\n.totals-row .totals-label {\n background: var(--mj-bg-surface-sunken);\n font-size: 12px;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.totals-row .totals-cell {\n background: var(--mj-bg-surface-sunken);\n}\n\n.totals-stack {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n}\n\n.totals-status,\n.totals-human,\n.totals-auto {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n padding: 2px 8px;\n border-radius: 10px;\n white-space: nowrap;\n}\n\n.totals-status {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.totals-status .pass-count {\n font-weight: 700;\n}\n\n.totals-human {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.totals-human .avg-label {\n font-weight: 700;\n}\n\n.totals-human .count-label {\n font-size: 10px;\n opacity: 0.8;\n}\n\n.totals-auto {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.totals-auto .avg-label {\n font-weight: 700;\n}\n\n.totals-auto .count-label {\n font-size: 10px;\n opacity: 0.8;\n}\n\n/* ===========================\n Editable Overview Form\n =========================== */\n\n.edit-section {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.edit-section-header {\n margin: 0 0 18px 0;\n}\n\n.edit-section-header h3 {\n margin: 0 0 4px 0;\n font-size: 18px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.edit-section-header h3 i {\n color: var(--test-primary);\n}\n\n.edit-section-sub {\n margin: 0;\n font-size: 12px;\n color: var(--test-text-muted);\n}\n\n.edit-grid {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 18px;\n}\n\n@media (max-width: 720px) {\n .edit-grid {\n grid-template-columns: 1fr;\n }\n}\n\n.edit-field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n min-width: 0;\n}\n\n.edit-field--full {\n grid-column: 1 / -1;\n}\n\n.edit-field label {\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.edit-field .required {\n color: var(--mj-status-error);\n margin-left: 2px;\n}\n\n.config-textarea {\n resize: vertical;\n min-height: 72px;\n font-family: inherit;\n line-height: 1.5;\n}\n\n.select-wrapper {\n position: relative;\n}\n\n.select-wrapper select.config-input {\n padding-right: 36px;\n appearance: none;\n background-color: var(--test-surface);\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%2364748b' d='M1.41 0L6 4.59 10.59 0 12 1.41l-6 6-6-6z'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 14px center;\n background-size: 10px 7px;\n}\n\n/* Tag editor (chips + inline input) */\n.tag-editor {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n padding: 8px 10px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n background: var(--test-surface);\n transition: var(--test-transition);\n cursor: text;\n min-height: 42px;\n align-items: center;\n}\n\n.tag-editor:focus-within {\n border-color: var(--test-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.tag-chip-editable {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 3px 4px 3px 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n border-radius: 999px;\n font-size: 12px;\n font-weight: 600;\n line-height: 1;\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n}\n\n.tag-chip-editable .tag-remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n border: none;\n background: transparent;\n color: var(--mj-brand-primary);\n cursor: pointer;\n font-size: 10px;\n transition: background 0.15s;\n}\n\n.tag-chip-editable .tag-remove:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n color: var(--mj-brand-primary-hover);\n}\n\n.tag-input-inline {\n flex: 1;\n min-width: 140px;\n border: none;\n background: transparent;\n outline: none;\n font-size: 13px;\n color: var(--test-text);\n padding: 4px 2px;\n}\n\n.tag-input-inline::placeholder {\n color: var(--test-text-muted);\n}\n\n/* Read-only metadata section */\n.meta-section {\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--test-radius-md);\n padding: 14px 18px;\n border: 1px solid var(--test-border);\n}\n\n.meta-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 14px;\n}\n\n.meta-item {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.meta-label {\n font-size: 10px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.meta-value {\n font-size: 12px;\n color: var(--test-text-secondary);\n font-weight: 500;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.meta-mono {\n font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;\n font-size: 11px;\n}\n\n/* Dirty indicator next to the title */\n.dirty-indicator {\n display: inline-block;\n margin-left: 8px;\n font-size: 14px;\n color: var(--mj-status-warning);\n line-height: 1;\n animation: pulseDot 1.8s ease-in-out infinite;\n vertical-align: middle;\n}\n\n@keyframes pulseDot {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.5; transform: scale(0.85); }\n}\n\n.unsaved-pill {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning-text, var(--mj-status-warning));\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 30%, transparent);\n border-radius: 999px;\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.4px;\n}\n\n.unsaved-pill i {\n font-size: 6px;\n animation: pulseDot 1.8s ease-in-out infinite;\n}\n\n/* Pad the bottom of the tab content when the save bar is visible\n so the bar doesn't cover the last form field. */\n.tab-content.has-savebar {\n padding-bottom: 84px;\n}\n\n/* ===========================\n Sticky Save Bar\n =========================== */\n\n.save-bar {\n position: absolute;\n left: 16px;\n right: 96px; /* leaves room for the bottom-right chat launcher */\n bottom: 16px;\n z-index: 50;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n padding: 12px 16px 12px 20px;\n background: var(--mj-bg-surface-elevated, var(--test-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 25%, var(--test-border));\n border-radius: 14px;\n box-shadow: 0 12px 32px color-mix(in srgb, var(--mj-status-warning) 10%, rgba(0, 0, 0, 0.18));\n backdrop-filter: blur(8px);\n /* Hidden / off-screen state by default. The .save-bar--visible class\n animates it up into view. Using `transition` (not `animation`)\n guarantees the change runs every time isDirty toggles. */\n opacity: 0;\n transform: translateY(calc(100% + 32px));\n pointer-events: none;\n transition:\n transform 420ms cubic-bezier(0.16, 1, 0.3, 1),\n opacity 260ms cubic-bezier(0.16, 1, 0.3, 1);\n will-change: transform, opacity;\n}\n\n.save-bar--visible {\n opacity: 1;\n transform: translateY(0);\n pointer-events: auto;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .save-bar {\n transition: opacity 180ms ease-out;\n transform: none;\n }\n .save-bar--visible {\n transform: none;\n }\n}\n\n.save-bar-message {\n display: flex;\n align-items: center;\n gap: 12px;\n min-width: 0;\n}\n\n.save-bar-dot {\n color: var(--mj-status-warning);\n font-size: 12px;\n line-height: 1;\n animation: pulseDot 1.8s ease-in-out infinite;\n}\n\n.save-bar-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.save-bar-text strong {\n font-size: 14px;\n color: var(--test-text);\n font-weight: 700;\n}\n\n.save-bar-fields {\n font-size: 12px;\n color: var(--test-text-muted);\n}\n\n.save-bar-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-shrink: 0;\n}\n\n.save-bar-btn {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 9px 16px;\n font-size: 13px;\n font-weight: 600;\n border-radius: 8px;\n border: 1px solid transparent;\n cursor: pointer;\n transition: var(--test-transition);\n font-family: inherit;\n}\n\n.save-bar-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.save-bar-btn--primary {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse, white);\n border-color: var(--mj-brand-primary);\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-brand-primary) 35%, transparent);\n}\n\n.save-bar-btn--primary:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover, var(--mj-brand-primary));\n transform: translateY(-1px);\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-brand-primary) 45%, transparent);\n}\n\n.save-bar-btn--primary:active:not(:disabled) {\n transform: translateY(0);\n}\n\n.save-bar-btn--ghost {\n background: transparent;\n color: var(--test-text-secondary);\n border-color: var(--test-border);\n}\n\n.save-bar-btn--ghost:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n border-color: var(--test-text-muted);\n}\n\n.save-bar-kbd {\n display: inline-flex;\n gap: 3px;\n margin-left: 6px;\n opacity: 0.85;\n}\n\n.save-bar-kbd kbd {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 4px;\n font-size: 10px;\n font-weight: 600;\n font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;\n background: color-mix(in srgb, white 18%, transparent);\n border: 1px solid color-mix(in srgb, white 35%, transparent);\n border-radius: 4px;\n color: inherit;\n}\n\n@media (max-width: 640px) {\n .save-bar {\n left: 8px;\n right: 8px;\n bottom: 88px; /* push above the chat launcher on small screens */\n flex-direction: column;\n align-items: stretch;\n padding: 12px;\n }\n .save-bar-actions {\n justify-content: space-between;\n }\n .save-bar-kbd {\n display: none;\n }\n}\n\n/* ===========================\n Tests Tab \u2014 Action Bar + Drag/Remove\n =========================== */\n\n.tests-actionbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding: 12px 16px;\n margin-bottom: 16px;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n}\n\n.tests-actionbar-text {\n display: flex;\n align-items: center;\n gap: 10px;\n flex-wrap: wrap;\n min-width: 0;\n}\n\n.tests-actionbar-text strong {\n font-size: 14px;\n color: var(--test-text);\n font-weight: 700;\n}\n\n.tests-actionbar-count {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 22px;\n height: 22px;\n padding: 0 8px;\n border-radius: 999px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n font-size: 12px;\n font-weight: 700;\n}\n\n.tests-actionbar-hint {\n font-size: 12px;\n color: var(--test-text-muted);\n}\n\n.tests-actionbar-actions {\n display: flex;\n gap: 8px;\n flex-shrink: 0;\n}\n\n/* Override the default test-item hover translate so drag transforms don't fight it. */\n.tests-list[cdk-drop-list] .test-item:hover,\n.tests-list .test-item.cdk-drag:hover {\n transform: none;\n}\n\n/* The whole row is draggable. .test-content keeps the click-to-open behavior. */\n.test-item.cdk-drag {\n position: relative;\n}\n\n.test-item .test-content {\n cursor: pointer;\n}\n\n/* Drag handle */\n.test-drag-handle {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 28px;\n border-radius: 4px;\n color: var(--test-text-muted);\n cursor: grab;\n flex-shrink: 0;\n transition: background 0.15s, color 0.15s;\n user-select: none;\n}\n\n.test-drag-handle:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n color: var(--test-primary);\n}\n\n.test-drag-handle:active,\n.cdk-drag-preview .test-drag-handle {\n cursor: grabbing;\n}\n\n/* Remove (X) button \u2014 hover-revealed */\n.test-remove-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border-radius: 50%;\n border: none;\n background: transparent;\n color: var(--test-text-muted);\n cursor: pointer;\n flex-shrink: 0;\n opacity: 0;\n transition: opacity 0.15s, background 0.15s, color 0.15s;\n}\n\n.test-item:hover .test-remove-btn,\n.test-remove-btn:focus-visible {\n opacity: 1;\n}\n\n.test-remove-btn:hover {\n background: color-mix(in srgb, var(--mj-status-error) 12%, transparent);\n color: var(--mj-status-error);\n}\n\n.test-chevron {\n cursor: pointer;\n}\n\n/* Inline remove-confirm */\n.test-remove-confirm {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 4px 8px 4px 12px;\n border-radius: 999px;\n background: color-mix(in srgb, var(--mj-status-error) 8%, var(--test-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 30%, transparent);\n flex-shrink: 0;\n}\n\n.test-remove-confirm-text {\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-status-error-text, var(--mj-status-error));\n}\n\n.test-remove-confirm-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 4px 10px;\n border-radius: 6px;\n border: 1px solid transparent;\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n font-family: inherit;\n transition: var(--test-transition);\n}\n\n.test-remove-confirm-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.test-remove-confirm-btn--danger {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse, white);\n}\n\n.test-remove-confirm-btn--danger:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-status-error) 88%, black);\n}\n\n.test-remove-confirm-btn--ghost {\n background: transparent;\n color: var(--test-text-secondary);\n border-color: var(--test-border);\n}\n\n.test-remove-confirm-btn--ghost:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n}\n\n/* CDK drag-drop visuals */\n.cdk-drag-preview {\n box-shadow: 0 12px 32px rgba(0, 0, 0, 0.25);\n border-radius: var(--test-radius-md);\n background: var(--test-surface);\n opacity: 0.95;\n}\n\n.cdk-drag-placeholder {\n opacity: 0;\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n border: 2px dashed var(--test-primary);\n border-radius: var(--test-radius-md);\n}\n\n.cdk-drag-placeholder * {\n visibility: hidden;\n}\n\n.cdk-drag-animating {\n transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);\n}\n\n.tests-list.cdk-drop-list-dragging .test-item:not(.cdk-drag-placeholder) {\n transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);\n}\n\n/* ===========================\n Add Tests Picker Dialog\n =========================== */\n\n.picker-backdrop {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.45);\n z-index: 200;\n animation: pickerFadeIn 180ms ease-out;\n backdrop-filter: blur(2px);\n}\n\n@keyframes pickerFadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.picker-dialog {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: min(720px, calc(100vw - 32px));\n max-height: min(80vh, 720px);\n z-index: 201;\n display: flex;\n flex-direction: column;\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n box-shadow: 0 24px 64px rgba(0, 0, 0, 0.28);\n animation: pickerSlideUp 220ms cubic-bezier(0.16, 1, 0.3, 1);\n overflow: hidden;\n}\n\n@keyframes pickerSlideUp {\n from {\n opacity: 0;\n transform: translate(-50%, calc(-50% + 16px));\n }\n to {\n opacity: 1;\n transform: translate(-50%, -50%);\n }\n}\n\n.picker-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 18px 20px;\n border-bottom: 1px solid var(--test-border);\n}\n\n.picker-title {\n margin: 0;\n font-size: 16px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.picker-title i {\n color: var(--test-primary);\n}\n\n.picker-close {\n width: 32px;\n height: 32px;\n border-radius: 8px;\n border: none;\n background: transparent;\n color: var(--test-text-muted);\n cursor: pointer;\n font-size: 14px;\n transition: background 0.15s, color 0.15s;\n}\n\n.picker-close:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n}\n\n.picker-close:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.picker-search {\n position: relative;\n padding: 14px 20px 0 20px;\n}\n\n.picker-search-icon {\n position: absolute;\n top: 50%;\n left: 32px;\n transform: translateY(-30%);\n color: var(--test-text-muted);\n font-size: 13px;\n pointer-events: none;\n}\n\n.picker-search-input {\n width: 100%;\n padding: 10px 36px 10px 36px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n background: var(--test-surface);\n font-size: 14px;\n color: var(--test-text);\n font-family: inherit;\n transition: var(--test-transition);\n}\n\n.picker-search-input:focus {\n outline: none;\n border-color: var(--test-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.picker-search-clear {\n position: absolute;\n top: 50%;\n right: 32px;\n transform: translateY(-30%);\n width: 22px;\n height: 22px;\n border-radius: 50%;\n border: none;\n background: transparent;\n color: var(--test-text-muted);\n cursor: pointer;\n font-size: 11px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.picker-search-clear:hover {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n}\n\n.picker-toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 20px;\n border-bottom: 1px solid var(--test-border);\n}\n\n.picker-toolbar-status {\n font-size: 12px;\n color: var(--test-text-secondary);\n}\n\n.picker-toolbar-status strong {\n color: var(--mj-brand-primary-hover);\n font-weight: 700;\n}\n\n.picker-toolbar-actions {\n display: flex;\n gap: 14px;\n}\n\n.picker-link-btn {\n border: none;\n background: transparent;\n color: var(--test-primary);\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n padding: 0;\n font-family: inherit;\n}\n\n.picker-link-btn:hover:not(:disabled) {\n text-decoration: underline;\n}\n\n.picker-link-btn:disabled {\n color: var(--test-text-muted);\n cursor: not-allowed;\n}\n\n.picker-body {\n flex: 1;\n overflow-y: auto;\n padding: 8px 12px;\n min-height: 200px;\n}\n\n.picker-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px;\n}\n\n.picker-list {\n list-style: none;\n padding: 0;\n margin: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.picker-row {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n border-radius: 8px;\n cursor: pointer;\n transition: background 0.12s, border-color 0.12s;\n border: 1px solid transparent;\n}\n\n.picker-row:hover {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n}\n\n.picker-row:focus-visible {\n outline: none;\n border-color: var(--test-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.picker-row--selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--test-surface));\n border-color: color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.picker-row--selected:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--test-surface));\n}\n\n.picker-check {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n border-radius: 5px;\n border: 1.5px solid var(--test-border);\n background: var(--test-surface);\n color: var(--mj-text-inverse, white);\n font-size: 11px;\n flex-shrink: 0;\n transition: background 0.12s, border-color 0.12s;\n}\n\n.picker-row--selected .picker-check {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.picker-row-main {\n flex: 1;\n min-width: 0;\n}\n\n.picker-row-name {\n font-size: 13px;\n font-weight: 600;\n color: var(--test-text);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.picker-row-desc {\n font-size: 12px;\n color: var(--test-text-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n margin-top: 2px;\n}\n\n.picker-row-meta {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-shrink: 0;\n}\n\n.picker-row-pill {\n display: inline-flex;\n align-items: center;\n padding: 2px 8px;\n border-radius: 999px;\n font-size: 10px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n background: var(--mj-bg-surface-sunken, var(--test-bg));\n color: var(--test-text-secondary);\n border: 1px solid var(--test-border);\n}\n\n.picker-row-pill--status[data-status=\"active\"] {\n background: color-mix(in srgb, var(--mj-status-success) 12%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n border-color: color-mix(in srgb, var(--mj-status-success) 30%, transparent);\n}\n\n.picker-row-pill--status[data-status=\"disabled\"] {\n background: var(--mj-bg-surface-sunken, var(--test-bg));\n color: var(--test-text-muted);\n}\n\n.picker-row-pill--status[data-status=\"pending\"] {\n background: color-mix(in srgb, var(--mj-status-warning) 12%, var(--mj-bg-surface));\n color: var(--mj-status-warning-text, var(--mj-status-warning));\n border-color: color-mix(in srgb, var(--mj-status-warning) 30%, transparent);\n}\n\n.picker-footer {\n display: flex;\n gap: 8px;\n padding: 14px 20px;\n border-top: 1px solid var(--test-border);\n background: var(--mj-bg-surface-sunken, var(--test-bg));\n}\n\n.picker-btn {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 9px 16px;\n font-size: 13px;\n font-weight: 600;\n border-radius: 8px;\n border: 1px solid transparent;\n cursor: pointer;\n font-family: inherit;\n transition: var(--test-transition);\n}\n\n.picker-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.picker-btn--primary {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse, white);\n border-color: var(--mj-brand-primary);\n}\n\n.picker-btn--primary:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover, var(--mj-brand-primary));\n}\n\n.picker-btn--ghost {\n background: transparent;\n color: var(--test-text-secondary);\n border-color: var(--test-border);\n}\n\n.picker-btn--ghost:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n}\n\n@media (max-width: 640px) {\n .picker-dialog {\n width: calc(100vw - 16px);\n max-height: calc(100vh - 32px);\n }\n .tests-actionbar {\n flex-direction: column;\n align-items: stretch;\n }\n .tests-actionbar-actions {\n justify-content: flex-end;\n }\n .test-remove-btn {\n opacity: 1; /* always visible on touch */\n }\n}\n\n"] }]
|
|
5050
|
+
args: [{ standalone: false, selector: 'mj-test-suite-form', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"test-suite-form\">\n <!-- Header Section -->\n <div class=\"suite-header\">\n <!-- Breadcrumb Navigation -->\n <nav class=\"breadcrumb\" aria-label=\"Breadcrumb\">\n <ol>\n <li>\n <a href=\"javascript:void(0)\" (click)=\"navigateToTestingDashboard()\">\n <i class=\"fas fa-vial\"></i>\n <span class=\"breadcrumb-text\">Testing</span>\n </a>\n </li>\n <li class=\"current\">\n <i class=\"fas fa-chevron-right separator\"></i>\n <i class=\"fas fa-layer-group\"></i>\n <span>{{ record.Name }}</span>\n </li>\n </ol>\n </nav>\n\n <div class=\"header-content\">\n <div class=\"header-left\">\n <div class=\"suite-icon\" [style.background-color]=\"getStatusColor()\">\n <i class=\"fas fa-layer-group\"></i>\n </div>\n <div class=\"suite-info\">\n <h1>\n {{ record.Name }}\n @if (isDirty) {\n <span class=\"dirty-indicator\" title=\"You have unsaved changes\" aria-label=\"Unsaved changes\">\u25CF</span>\n }\n </h1>\n <div class=\"suite-meta\">\n <span class=\"status-badge\" [ngClass]=\"getStatusClass()\">\n <i class=\"fas\" [ngClass]=\"record.Status === 'Active' ? 'fa-circle-check' : 'fa-circle-pause'\"></i>\n {{ record.Status }}\n </span>\n @if (testsLoaded) {\n <span class=\"test-count\">\n <i class=\"fas fa-flask\"></i>\n {{ suiteTests.length }} tests\n </span>\n }\n @if (isDirty) {\n <span class=\"unsaved-pill\" title=\"You have unsaved changes\">\n <i class=\"fas fa-circle\"></i> Unsaved\n </span>\n }\n </div>\n </div>\n </div>\n <div class=\"header-actions\">\n <app-evaluation-mode-toggle></app-evaluation-mode-toggle>\n <button mjButton (click)=\"exportToExcel()\" title=\"Export to CSV\">\n <i class=\"fas fa-file-excel\"></i> Export\n </button>\n <button mjButton (click)=\"runSuite()\" variant=\"primary\">\n <i class=\"fas fa-play\"></i> Run Suite\n </button>\n <button mjButton (click)=\"refresh()\" [disabled]=\"isRefreshing\">\n <i class=\"fas\" [ngClass]=\"isRefreshing ? 'fa-sync fa-spin' : 'fa-sync'\"></i>\n {{ isRefreshing ? 'Refreshing...' : 'Refresh' }}\n </button>\n </div>\n </div>\n @if (record.Description) {\n <div class=\"suite-description\">\n <p>{{ record.Description }}</p>\n </div>\n }\n </div>\n\n <!-- Tabs -->\n <div class=\"tabs-container\">\n <!-- Phone: the strip becomes one button that opens the Sections sheet -->\n <mj-section-picker class=\"phone-section-picker\"\n [Items]=\"SectionPickerItems\"\n [ActiveKey]=\"ActiveTab\"\n (ActiveKeyChange)=\"OnSectionPicked($event)\"></mj-section-picker>\n <div class=\"tabs\" role=\"tablist\">\n <button class=\"tab\"\n [class.active]=\"activeTab === 'overview'\"\n (click)=\"changeTab('overview')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'overview'\">\n <i class=\"fas fa-th-large\"></i> Overview\n </button>\n <button class=\"tab\"\n [class.active]=\"activeTab === 'tests'\"\n (click)=\"changeTab('tests')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'tests'\">\n <i class=\"fas fa-flask\"></i> Tests\n @if (testsLoaded) {\n <span class=\"tab-badge\">{{ suiteTests.length }}</span>\n }\n </button>\n <button class=\"tab\"\n [class.active]=\"activeTab === 'runs'\"\n (click)=\"changeTab('runs')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'runs'\">\n <i class=\"fas fa-history\"></i> Runs\n @if (runsLoaded) {\n <span class=\"tab-badge\">{{ suiteRuns.length }}</span>\n }\n </button>\n <button class=\"tab\"\n [class.active]=\"activeTab === 'analytics'\"\n (click)=\"changeTab('analytics')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'analytics'\">\n <i class=\"fas fa-chart-line\"></i> Analytics\n </button>\n <button class=\"tab\"\n [class.active]=\"activeTab === 'compare'\"\n (click)=\"changeTab('compare')\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'compare'\">\n <i class=\"fas fa-balance-scale\"></i> Compare\n </button>\n </div>\n </div>\n\n <!-- Tab Content -->\n <div class=\"tab-content\" [class.has-savebar]=\"isDirty\">\n <!-- Overview Tab -->\n @if (activeTab === 'overview') {\n <div class=\"overview-tab\">\n <!-- Editable Details -->\n <section class=\"edit-section\">\n <header class=\"edit-section-header\">\n <h3><i class=\"fas fa-pen-to-square\"></i> Details</h3>\n <p class=\"edit-section-sub\">Edit any field \u2014 changes are saved with the bar at the bottom.</p>\n </header>\n <div class=\"edit-grid\">\n <div class=\"edit-field edit-field--full\">\n <label for=\"suite-name\">Name <span class=\"required\">*</span></label>\n <input\n id=\"suite-name\"\n type=\"text\"\n class=\"config-input\"\n placeholder=\"e.g., Core Agent Test Suite\"\n [(ngModel)]=\"record.Name\"\n />\n </div>\n\n <div class=\"edit-field edit-field--full\">\n <label for=\"suite-description\">Description</label>\n <textarea\n id=\"suite-description\"\n class=\"config-input config-textarea\"\n rows=\"3\"\n placeholder=\"What does this suite cover?\"\n [ngModel]=\"record.Description\"\n (ngModelChange)=\"record.Description = $event || null\"\n ></textarea>\n </div>\n\n <div class=\"edit-field\">\n <label for=\"suite-status\">Status</label>\n <div class=\"select-wrapper\">\n <select\n id=\"suite-status\"\n class=\"config-input\"\n [(ngModel)]=\"record.Status\"\n >\n @for (opt of statusOptions; track opt) {\n <option [ngValue]=\"opt\">{{ opt }}</option>\n }\n </select>\n </div>\n </div>\n\n <div class=\"edit-field\">\n <label for=\"suite-rubric\">Rubric</label>\n <select\n id=\"suite-rubric\"\n class=\"config-input\"\n [ngModel]=\"record.RubricID\"\n (ngModelChange)=\"record.RubricID = $event || null\"\n >\n <option [ngValue]=\"null\">\u2014 None \u2014</option>\n @for (rubric of RubricOptions; track rubric.id) {\n <option [ngValue]=\"rubric.id\">{{ rubric.name }}</option>\n }\n </select>\n </div>\n\n <div class=\"edit-field\">\n <label for=\"suite-parent\">Parent Suite</label>\n <select\n id=\"suite-parent\"\n class=\"config-input\"\n [ngModel]=\"record.ParentID\"\n (ngModelChange)=\"record.ParentID = $event || null\"\n >\n <option [ngValue]=\"null\">\u2014 None (top-level) \u2014</option>\n @for (s of parentSuiteOptions; track s.ID) {\n <option [ngValue]=\"s.ID\">{{ s.Name }}</option>\n }\n </select>\n </div>\n\n <div class=\"edit-field edit-field--full\">\n <label for=\"suite-tags\">Tags</label>\n <div class=\"tag-editor\" (click)=\"tagInput.focus()\">\n @for (tag of tags; track tag) {\n <span class=\"tag-chip-editable\">\n {{ tag }}\n <button type=\"button\" class=\"tag-remove\" (click)=\"removeTag(tag); $event.stopPropagation()\" [attr.aria-label]=\"'Remove tag ' + tag\">\n <i class=\"fas fa-times\"></i>\n </button>\n </span>\n }\n <input\n #tagInput\n id=\"suite-tags\"\n type=\"text\"\n class=\"tag-input-inline\"\n [placeholder]=\"tags.length === 0 ? 'Add tags, press Enter or comma...' : ''\"\n [(ngModel)]=\"tagDraft\"\n (keydown)=\"onTagInputKeydown($event)\"\n (blur)=\"addTagFromDraft()\"\n />\n </div>\n <span class=\"config-hint\">Press Enter or comma to add a tag. Backspace on empty input removes the last tag.</span>\n </div>\n </div>\n </section>\n\n <!-- Execution Settings -->\n <section class=\"edit-section\">\n <header class=\"edit-section-header\">\n <h3><i class=\"fas fa-cogs\"></i> Execution Settings</h3>\n </header>\n <div class=\"edit-grid\">\n <div class=\"edit-field\">\n <label for=\"suite-timeout\">Max Execution Time (ms)</label>\n <input\n id=\"suite-timeout\"\n type=\"number\"\n class=\"config-input\"\n placeholder=\"Default: 300000 (5 min)\"\n [ngModel]=\"record.MaxExecutionTimeMS\"\n (ngModelChange)=\"record.MaxExecutionTimeMS = $event === '' || $event === null ? null : +$event\"\n />\n <span class=\"config-hint\">Default timeout for tests in this suite. Currently: {{ formatTimeout(record.MaxExecutionTimeMS) }}</span>\n </div>\n </div>\n </section>\n\n <!-- Metadata (read-only) -->\n <section class=\"meta-section\">\n <div class=\"meta-grid\">\n <div class=\"meta-item\">\n <div class=\"meta-label\">Created</div>\n <div class=\"meta-value\">{{ record.__mj_CreatedAt | date:'medium' }}</div>\n </div>\n <div class=\"meta-item\">\n <div class=\"meta-label\">Last updated</div>\n <div class=\"meta-value\">{{ record.__mj_UpdatedAt | date:'medium' }}</div>\n </div>\n <div class=\"meta-item\">\n <div class=\"meta-label\">Suite ID</div>\n <div class=\"meta-value meta-mono\">{{ record.ID }}</div>\n </div>\n </div>\n </section>\n </div>\n }\n\n <!-- Tests Tab -->\n @if (activeTab === 'tests') {\n <div class=\"tests-tab\">\n <!-- Header: action bar -->\n <div class=\"tests-actionbar\">\n <div class=\"tests-actionbar-text\">\n <strong>Suite tests</strong>\n @if (testsLoaded) {\n <span class=\"tests-actionbar-count\">{{ suiteTests.length }}</span>\n }\n <span class=\"tests-actionbar-hint\">Drag to reorder \u00B7 Hover a row to remove</span>\n </div>\n <div class=\"tests-actionbar-actions\">\n <button mjButton variant=\"primary\" (click)=\"openAddTestsDialog()\" [disabled]=\"isReorderingTests\">\n <i class=\"fas fa-plus\"></i> Add tests\n </button>\n </div>\n </div>\n\n <!-- Loading State -->\n @if (loadingTests) {\n <div class=\"loading-state\">\n <div class=\"skeleton-list\">\n @for (i of [1,2,3,4,5]; track i) {\n <div class=\"skeleton-card\">\n <div class=\"skeleton-sequence\"></div>\n <div class=\"skeleton-icon\"></div>\n <div class=\"skeleton-content\">\n <div class=\"skeleton-line wide\"></div>\n <div class=\"skeleton-line narrow\"></div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n <!-- Tests List -->\n @if (!loadingTests && suiteTests.length > 0) {\n <div class=\"tests-list\" cdkDropList (cdkDropListDropped)=\"onTestDrop($event)\">\n @for (test of suiteTests; track test.ID) {\n <div class=\"test-item\" cdkDrag [cdkDragDisabled]=\"isReorderingTests || isRemovingTest\">\n <span class=\"test-drag-handle\" cdkDragHandle title=\"Drag to reorder\" aria-label=\"Drag to reorder\">\n <i class=\"fas fa-grip-vertical\"></i>\n </span>\n <div class=\"test-sequence\">{{ test.Sequence }}</div>\n <div class=\"test-icon\"><i class=\"fas fa-flask\"></i></div>\n <div class=\"test-content\" (click)=\"openTest(test.TestID)\">\n <div class=\"test-name\">{{ test.Test }}</div>\n <div class=\"test-status\">\n @if (test.Status) {\n <span><i class=\"fas fa-info-circle\"></i> {{ test.Status }}</span>\n }\n </div>\n </div>\n <!-- Inline remove confirm OR hover-reveal X -->\n @if (confirmingRemoveSuiteTestId === test.ID) {\n <div class=\"test-remove-confirm\" (click)=\"$event.stopPropagation()\">\n <span class=\"test-remove-confirm-text\">Remove from suite?</span>\n <button\n type=\"button\"\n class=\"test-remove-confirm-btn test-remove-confirm-btn--danger\"\n (click)=\"confirmRemoveTest(test, $event)\"\n [disabled]=\"isRemovingTest\"\n >\n @if (isRemovingTest) {\n <i class=\"fas fa-spinner fa-spin\"></i>\n } @else {\n Remove\n }\n </button>\n <button\n type=\"button\"\n class=\"test-remove-confirm-btn test-remove-confirm-btn--ghost\"\n (click)=\"cancelRemoveTest($event)\"\n [disabled]=\"isRemovingTest\"\n >\n Cancel\n </button>\n </div>\n } @else {\n <button\n type=\"button\"\n class=\"test-remove-btn\"\n title=\"Remove from suite\"\n aria-label=\"Remove from suite\"\n (click)=\"requestRemoveTest(test, $event)\"\n >\n <i class=\"fas fa-times\"></i>\n </button>\n <i class=\"fas fa-chevron-right test-chevron\" (click)=\"openTest(test.TestID)\"></i>\n }\n </div>\n }\n </div>\n }\n <!-- Empty State -->\n @if (testsLoaded && !loadingTests && suiteTests.length === 0) {\n <mj-empty-state\n Icon=\"fa-solid fa-flask\"\n Title=\"No Tests in Suite\"\n Message=\"Add tests to this suite to start running them together.\"\n ActionText=\"Add tests\"\n ActionIcon=\"fa-solid fa-plus\"\n (Action)=\"openAddTestsDialog()\" />\n }\n </div>\n }\n\n <!-- Runs Tab -->\n @if (activeTab === 'runs') {\n <div class=\"runs-tab\">\n <!-- Loading State -->\n @if (loadingRuns) {\n <div class=\"loading-state\">\n <div class=\"skeleton-list\">\n @for (i of [1,2,3]; track i) {\n <div class=\"skeleton-card\">\n <div class=\"skeleton-icon\"></div>\n <div class=\"skeleton-content\">\n <div class=\"skeleton-line wide\"></div>\n <div class=\"skeleton-line narrow\"></div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n <!-- Runs List -->\n @if (!loadingRuns && suiteRuns.length > 0) {\n <div class=\"runs-list\">\n @for (run of suiteRuns; track run) {\n <div class=\"run-item\" (click)=\"openSuiteRun(run.ID)\">\n <div class=\"run-icon\" [style.background-color]=\"getRunStatusColor(run.Status)\">\n <i class=\"fas\"\n [class.fa-check]=\"run.Status === 'Completed'\"\n [class.fa-times]=\"run.Status === 'Failed'\"\n [class.fa-spinner]=\"run.Status === 'Running'\"\n [class.fa-clock]=\"run.Status === 'Pending'\"\n [class.fa-ban]=\"run.Status === 'Cancelled'\"></i>\n </div>\n <div class=\"run-content\">\n <div class=\"run-header\">\n <span class=\"run-id\">Run #{{ run.ID.substring(0, 8) }}</span>\n <span class=\"run-status\" [style.color]=\"getRunStatusColor(run.Status)\">{{ run.Status }}</span>\n </div>\n <div class=\"run-meta\">\n <span><i class=\"fas fa-calendar\"></i> {{ getRelativeTime(run.StartedAt) }}</span>\n @if (run.TotalTests) {\n <span>\n <i class=\"fas fa-check-circle\"></i> {{ run.PassedTests }}/{{ run.TotalTests }}\n ({{ getPassRate(run).toFixed(0) }}%)\n </span>\n }\n </div>\n <!-- Evaluation metrics row -->\n <div class=\"run-eval-metrics\">\n <!-- Status badge -->\n @if (evalPreferences.showExecution) {\n <span class=\"eval-metric status\" [class]=\"'status-' + run.Status.toLowerCase()\">\n <i class=\"fas\"\n [class.fa-circle-check]=\"run.Status === 'Completed'\"\n [class.fa-circle-xmark]=\"run.Status === 'Failed'\"\n [class.fa-spinner]=\"run.Status === 'Running'\"\n [class.fa-clock]=\"run.Status === 'Pending'\"\n [class.fa-ban]=\"run.Status === 'Cancelled'\"></i>\n </span>\n }\n <!-- Human score (placeholder - need avg from suite run) -->\n @if (evalPreferences.showHuman) {\n <span class=\"eval-metric human\" title=\"Human evaluation\">\n <i class=\"fas fa-user\"></i>\n <span class=\"eval-pending\"><i class=\"fas fa-clock\"></i></span>\n </span>\n }\n <!-- Auto score (pass rate as proxy) -->\n @if (evalPreferences.showAuto && run.TotalTests) {\n <span class=\"eval-metric auto\"\n [class.high]=\"getPassRate(run) >= 80\"\n [class.medium]=\"getPassRate(run) >= 50 && getPassRate(run) < 80\"\n [class.low]=\"getPassRate(run) < 50\"\n title=\"Auto score (pass rate)\">\n <i class=\"fas fa-robot\"></i>\n <span>{{ getPassRate(run).toFixed(0) }}%</span>\n </span>\n }\n </div>\n <!-- Tags display -->\n @if (getRunTags(run).length > 0) {\n <div class=\"run-tags\">\n @for (tag of getRunTags(run); track tag) {\n <span class=\"tag-chip\">{{ tag }}</span>\n }\n </div>\n }\n </div>\n <i class=\"fas fa-chevron-right\"></i>\n </div>\n }\n </div>\n }\n <!-- Empty State -->\n @if (runsLoaded && !loadingRuns && suiteRuns.length === 0) {\n <mj-empty-state\n Icon=\"fa-solid fa-circle-play\"\n Title=\"No Suite Runs Yet\"\n Message=\"Run this suite to see execution history and results here.\"\n ActionText=\"Run Suite Now\"\n ActionIcon=\"fa-solid fa-play\"\n (Action)=\"runSuite()\" />\n }\n </div>\n }\n\n <!-- Analytics Tab -->\n @if (activeTab === 'analytics') {\n <div class=\"analytics-tab\">\n <!-- Loading State -->\n @if (loadingAnalytics) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading analytics data...\"></mj-loading>\n </div>\n }\n @if (!loadingAnalytics && analyticsLoaded) {\n <!-- View Toggle Sub-nav -->\n <div class=\"analytics-subnav\">\n <div class=\"subnav-tabs\">\n <button class=\"subnav-tab\"\n [class.active]=\"analyticsView === 'summary'\"\n (click)=\"setAnalyticsView('summary')\">\n <i class=\"fas fa-chart-bar\"></i>\n <span>Summary</span>\n </button>\n <button class=\"subnav-tab\"\n [class.active]=\"analyticsView === 'matrix'\"\n (click)=\"setAnalyticsView('matrix')\">\n <i class=\"fas fa-th\"></i>\n <span>Matrix</span>\n </button>\n <button class=\"subnav-tab\"\n [class.active]=\"analyticsView === 'chart'\"\n (click)=\"setAnalyticsView('chart')\">\n <i class=\"fas fa-project-diagram\"></i>\n <span>Chart</span>\n </button>\n </div>\n </div>\n <!-- Collapsible Filters (shared by both views) -->\n <mj-accordion-panel Size=\"sm\" [FlushBody]=\"true\"\n [Expanded]=\"!filtersCollapsed\" (ExpandedChange)=\"onFiltersExpandedChange($event)\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-filter\" style=\"color: var(--test-primary);\"></i>\n Filters\n @if (filtersCollapsed) {\n <span class=\"mj-accordion-badge mj-accordion-badge--right mj-accordion-badge--muted\">\n {{ analyticsTimeRange === 'all' ? 'All Time' : analyticsTimeRange }}\n @if (selectedTags.length > 0) {\n <span> \u00B7 {{ selectedTags.length }} tags</span>\n }\n </span>\n }\n </ng-template>\n <ng-template mjAccordionBody>\n <div class=\"filters-content\">\n <div class=\"filter-group\">\n <label>Time Range</label>\n <div class=\"filter-buttons\">\n <button class=\"filter-btn\" [class.active]=\"analyticsTimeRange === '7d'\" (click)=\"setTimeRange('7d')\">7 Days</button>\n <button class=\"filter-btn\" [class.active]=\"analyticsTimeRange === '30d'\" (click)=\"setTimeRange('30d')\">30 Days</button>\n <button class=\"filter-btn\" [class.active]=\"analyticsTimeRange === '90d'\" (click)=\"setTimeRange('90d')\">90 Days</button>\n <button class=\"filter-btn\" [class.active]=\"analyticsTimeRange === 'all'\" (click)=\"setTimeRange('all')\">All Time</button>\n </div>\n </div>\n @if (uniqueTags.length > 0) {\n <div class=\"filter-group\">\n <label>Filter by Tag @if (selectedTags.length > 0) {\n <span class=\"filter-hint\">({{ selectedTags.length }} selected)</span>\n }</label>\n <div class=\"filter-buttons tag-filters\">\n <button class=\"filter-btn tag-btn all-tags-btn\"\n [class.active]=\"selectedTags.length === 0\"\n (click)=\"toggleTagFilter(null)\">\n <i class=\"fas fa-layer-group\"></i> All Tags\n </button>\n @for (tag of uniqueTags; track tag) {\n <button class=\"filter-btn tag-btn\"\n [class.active]=\"isTagSelected(tag)\"\n (click)=\"toggleTagFilter(tag)\">\n @if (isTagSelected(tag)) {\n <i class=\"fas fa-check\"></i>\n }\n {{ tag }}\n </button>\n }\n </div>\n </div>\n }\n </div>\n </ng-template>\n </mj-accordion-panel>\n <!-- Summary View -->\n @if (analyticsView === 'summary') {\n <!-- KPI Cards -->\n <div class=\"analytics-kpis\">\n <div class=\"kpi-card\">\n <div class=\"kpi-icon\"><i class=\"fas fa-play-circle\"></i></div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ getTotalRuns() }}</div>\n <div class=\"kpi-label\">Total Runs</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon success\"><i class=\"fas fa-check-circle\"></i></div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ getAveragePassRate().toFixed(1) }}%</div>\n <div class=\"kpi-label\">Avg Pass Rate</div>\n <div class=\"kpi-trend\" [ngClass]=\"{'trend-up': getPassRateTrend().direction === 'up', 'trend-down': getPassRateTrend().direction === 'down'}\">\n <i class=\"fas\" [ngClass]=\"{'fa-arrow-up': getPassRateTrend().direction === 'up', 'fa-arrow-down': getPassRateTrend().direction === 'down', 'fa-minus': getPassRateTrend().direction === 'stable'}\"></i>\n {{ getPassRateTrend().value.toFixed(1) }}%\n </div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon info\"><i class=\"fas fa-clock\"></i></div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ formatDuration(getAverageDuration()) }}</div>\n <div class=\"kpi-label\">Avg Duration</div>\n </div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-icon warning\"><i class=\"fas fa-dollar-sign\"></i></div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ formatCost(getTotalCost()) }}</div>\n <div class=\"kpi-label\">Total Cost</div>\n </div>\n </div>\n </div>\n <!-- Runs Table -->\n <div class=\"analytics-table-section\">\n <h3><i class=\"fas fa-table\"></i> Run History</h3>\n <div class=\"analytics-table-wrapper\">\n <table class=\"analytics-table\">\n <thead>\n <tr>\n <th>Date</th>\n <th>Status</th>\n <th>Pass Rate</th>\n <th>Tests</th>\n <th>Duration</th>\n <th>Cost</th>\n <th>Tags</th>\n </tr>\n </thead>\n <tbody>\n @for (dp of getFilteredAnalyticsData(); track dp) {\n <tr (click)=\"openSuiteRun(dp.runId)\" class=\"clickable-row\">\n <td>{{ dp.date | date:'short' }}</td>\n <td>\n <span class=\"status-chip\" [ngClass]=\"'status-' + dp.status.toLowerCase()\">{{ dp.status }}</span>\n </td>\n <td>\n <div class=\"pass-rate-cell\">\n <div class=\"pass-rate-bar\" [style.width.%]=\"dp.passRate\" [ngClass]=\"{'high': dp.passRate >= 80, 'medium': dp.passRate >= 50 && dp.passRate < 80, 'low': dp.passRate < 50}\"></div>\n <span>{{ dp.passRate.toFixed(0) }}%</span>\n </div>\n </td>\n <td>{{ dp.passedTests }}/{{ dp.totalTests }}</td>\n <td>{{ formatDuration(dp.duration) }}</td>\n <td>{{ formatCost(dp.cost) }}</td>\n <td>\n <div class=\"tag-cell\">\n @for (tag of dp.tags.slice(0, 2); track tag) {\n <span class=\"tag-chip-table\">{{ tag }}</span>\n }\n @if (dp.tags.length > 2) {\n <span class=\"tag-more\">+{{ dp.tags.length - 2 }}</span>\n }\n </div>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n @if (getFilteredAnalyticsData().length === 0) {\n <mj-empty-state\n Variant=\"no-results\"\n Size=\"compact\"\n Title=\"No runs match the current filters.\" />\n }\n </div>\n }\n <!-- Matrix View -->\n @if (analyticsView === 'matrix') {\n <!-- Loading Matrix -->\n @if (loadingMatrix) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading test matrix...\"></mj-loading>\n </div>\n }\n <!-- Matrix Content -->\n @if (!loadingMatrix && matrixLoaded && matrixData.length > 0) {\n <div class=\"matrix-section\">\n <div class=\"matrix-header\">\n <h3><i class=\"fas fa-th\"></i> Test Results Matrix</h3>\n <div class=\"matrix-header-right\">\n <div class=\"matrix-filter-input\">\n <i class=\"fas fa-search\"></i>\n <input type=\"text\"\n placeholder=\"Filter tests...\"\n [value]=\"matrixTestFilter\"\n (input)=\"onMatrixFilterInput($event)\"\n class=\"filter-input\">\n @if (matrixTestFilter) {\n <button class=\"clear-filter-btn\" (click)=\"clearMatrixFilter()\" title=\"Clear filter\">\n <i class=\"fas fa-times\"></i>\n </button>\n }\n </div>\n <span class=\"matrix-run-count\">{{ matrixData.length }} runs \u00B7 {{ getUniqueTestsFromMatrix().length }} tests</span>\n <button mjButton (click)=\"exportMatrixToCSV()\" [disabled]=\"matrixData.length === 0\" title=\"Export matrix to CSV\">\n <i class=\"fas fa-download\"></i> Export\n </button>\n </div>\n </div>\n <div class=\"matrix-scroll-container\">\n <table class=\"test-matrix\">\n <thead>\n <tr>\n <th class=\"seq-header\" (click)=\"toggleMatrixSort('sequence')\" title=\"Sort by sequence\">\n #\n <i class=\"fas\" [ngClass]=\"matrixSortBy === 'sequence' ? (matrixSortAsc ? 'fa-sort-up' : 'fa-sort-down') : 'fa-sort'\"></i>\n </th>\n <th class=\"test-name-header\" (click)=\"toggleMatrixSort('name')\" title=\"Sort by name\">\n Test\n <i class=\"fas\" [ngClass]=\"matrixSortBy === 'name' ? (matrixSortAsc ? 'fa-sort-up' : 'fa-sort-down') : 'fa-sort'\"></i>\n </th>\n @for (run of matrixData; track run) {\n <th class=\"run-header\" (click)=\"openSuiteRun(run.runId)\" [title]=\"'Click to view suite run - ' + (run.date | date:'medium')\">\n <div class=\"run-header-content\">\n @if (run.tags.length > 0) {\n <div class=\"run-tags-header\">\n @for (tag of run.tags.slice(0, 2); track tag) {\n <span class=\"tag-chip-header\">{{ tag }}</span>\n }\n @if (run.tags.length > 2) {\n <span class=\"tag-more-header\">+{{ run.tags.length - 2 }}</span>\n }\n </div>\n }\n <div class=\"run-date\">{{ getRelativeTime(run.date) }}</div>\n <div class=\"run-pass-rate\" [ngClass]=\"{'high': run.passRate >= 80, 'medium': run.passRate >= 50 && run.passRate < 80, 'low': run.passRate < 50}\">\n {{ run.passRate.toFixed(0) }}%\n </div>\n </div>\n </th>\n }\n <th class=\"spacer-header\"></th>\n </tr>\n </thead>\n <tbody>\n @for (test of getUniqueTestsFromMatrix(); track test) {\n <tr\n [class.row-selected]=\"selectedMatrixTestId === test.testId\"\n (click)=\"selectMatrixRow(test.testId)\">\n <td class=\"seq-cell\">{{ test.sequence }}</td>\n <td class=\"test-name-cell\">\n <span class=\"test-name\" [title]=\"test.testName\">{{ test.testName }}</span>\n </td>\n @for (run of matrixData; track run) {\n <td class=\"result-cell\"\n [ngClass]=\"getMatrixCellClass(getTestResultForRun(run.runId, test.testId))\"\n [class.clickable]=\"getTestResultForRun(run.runId, test.testId)\"\n [class.cell-not-run]=\"!getTestResultForRun(run.runId, test.testId)\"\n [title]=\"getTestResultForRun(run.runId, test.testId)?.status + ' - Click to view test run' || 'Not Run'\"\n (click)=\"onMatrixCellClick(getTestResultForRun(run.runId, test.testId), $event)\">\n @if (getTestResultForRun(run.runId, test.testId); as result) {\n <div class=\"cell-eval-stack\">\n <!-- Status indicator -->\n @if (evalPreferences.showExecution) {\n <span class=\"cell-status\"\n [ngClass]=\"'status-' + result.status.toLowerCase()\"\n [class.cell-skipped-status]=\"result.status === 'Skipped' || result.status === 'Pending'\"\n [title]=\"getStatusTooltip(result.status)\">\n <i class=\"fas\"\n [class.fa-check]=\"result.status === 'Passed'\"\n [class.fa-times]=\"result.status === 'Failed'\"\n [class.fa-exclamation]=\"result.status === 'Error'\"\n [class.fa-hourglass-end]=\"result.status === 'Timeout'\"\n [class.fa-forward]=\"result.status === 'Skipped'\"\n [class.fa-spinner]=\"result.status === 'Running'\"\n [class.fa-clock]=\"result.status === 'Pending'\"></i>\n </span>\n }\n <!-- Human score - slashed icon if no feedback, colored by rating if has feedback -->\n @if (evalPreferences.showHuman && !result.humanRating) {\n <span class=\"cell-human no-feedback\"\n title=\"Human Review: No rating submitted yet\">\n <i class=\"fas fa-user-slash\"></i>\n </span>\n }\n @if (evalPreferences.showHuman && result.humanRating) {\n <span class=\"cell-human has-feedback\"\n [class.rating-low]=\"result.humanRating <= 4\"\n [class.rating-medium]=\"result.humanRating >= 5 && result.humanRating <= 6\"\n [class.rating-good]=\"result.humanRating >= 7 && result.humanRating <= 8\"\n [class.rating-excellent]=\"result.humanRating >= 9\"\n [title]=\"getHumanTooltip(result.humanRating, result.humanComments)\">\n <i class=\"fas fa-user\"></i>\n <span class=\"rating-value\">{{ result.humanRating }}</span>\n </span>\n }\n <!-- Auto score - colored by percentage -->\n @if (evalPreferences.showAuto && result.score != null) {\n <span class=\"cell-auto has-score\"\n [class.score-low]=\"result.score < 0.5\"\n [class.score-medium]=\"result.score >= 0.5 && result.score < 0.7\"\n [class.score-good]=\"result.score >= 0.7 && result.score < 0.85\"\n [class.score-excellent]=\"result.score >= 0.85\"\n [title]=\"'Auto Score: ' + (result.score * 100).toFixed(0) + '% automated evaluation'\">\n <i class=\"fas fa-robot\"></i>\n <span class=\"score-value\">{{ (result.score * 100).toFixed(0) }}</span>\n </span>\n }\n @if (evalPreferences.showAuto && result.score == null) {\n <span class=\"cell-auto no-score\"\n title=\"Auto Score: No automated score available\">\n <i class=\"fas fa-robot\"></i>\n </span>\n }\n </div>\n }\n @if (!getTestResultForRun(run.runId, test.testId)) {\n <span class=\"cell-not-run-indicator\">\n <i class=\"fas fa-minus\"></i>\n </span>\n }\n </td>\n }\n <td class=\"spacer-cell\"></td>\n </tr>\n }\n </tbody>\n <!-- Footer row with totals -->\n <tfoot>\n <tr class=\"totals-row\">\n <td class=\"seq-cell totals-label\"></td>\n <td class=\"test-name-cell totals-label\">\n <strong>Totals</strong>\n </td>\n @for (run of matrixData; track run) {\n <td class=\"result-cell totals-cell\">\n <div class=\"cell-eval-stack totals-stack\">\n <!-- Status totals -->\n @if (evalPreferences.showExecution) {\n <span class=\"totals-status\">\n <span class=\"pass-count\">{{ getRunPassedCount(run) }}/{{ getRunTotalCount(run) }}</span>\n </span>\n }\n <!-- Human totals -->\n @if (evalPreferences.showHuman) {\n <span class=\"totals-human\">\n @if (getRunHumanAvg(run) != null) {\n <span class=\"avg-label\">{{ getRunHumanAvg(run)?.toFixed(1) }}</span>\n }\n <span class=\"count-label\">({{ getRunHumanCount(run) }})</span>\n </span>\n }\n <!-- Auto totals -->\n @if (evalPreferences.showAuto) {\n <span class=\"totals-auto\">\n @if (getRunAutoAvg(run) != null) {\n <span class=\"avg-label\">{{ (getRunAutoAvg(run)! * 100).toFixed(0) }}%</span>\n }\n <span class=\"count-label\">({{ getRunAutoCount(run) }})</span>\n </span>\n }\n </div>\n </td>\n }\n <td class=\"spacer-cell\"></td>\n </tr>\n </tfoot>\n </table>\n </div>\n </div>\n }\n <!-- Empty Matrix State -->\n @if (!loadingMatrix && matrixLoaded && matrixData.length === 0) {\n <mj-empty-state\n Variant=\"no-results\"\n Icon=\"fa-solid fa-table-cells\"\n Title=\"No Matrix Data\"\n Message=\"No suite runs match the current filters.\" />\n }\n }\n <!-- Chart View -->\n @if (analyticsView === 'chart') {\n <!-- Loading Chart -->\n @if (loadingMatrix) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading chart data...\"></mj-loading>\n </div>\n }\n <!-- Chart Content -->\n @if (!loadingMatrix && matrixLoaded && matrixData.length > 0) {\n <div class=\"chart-section\">\n <div class=\"chart-header\">\n <h3><i class=\"fas fa-project-diagram\"></i> Test Results Flow</h3>\n <div class=\"chart-legend\">\n <span class=\"legend-item chart-passed\"><i class=\"fas fa-check\"></i> Passed</span>\n <span class=\"legend-item chart-failed\"><i class=\"fas fa-times\"></i> Failed</span>\n <span class=\"legend-item chart-error\"><i class=\"fas fa-exclamation\"></i> Error</span>\n <span class=\"legend-item chart-skipped\"><i class=\"fas fa-forward\"></i> Skipped</span>\n </div>\n </div>\n <div class=\"chart-container\">\n <div #chartContainer class=\"d3-chart\"></div>\n </div>\n <div class=\"chart-info\">\n <i class=\"fas fa-info-circle\"></i>\n Interactive visualization showing test results across {{ matrixData.length }} runs.\n Hover over elements for details, click nodes to navigate.\n </div>\n </div>\n }\n <!-- Empty Chart State -->\n @if (!loadingMatrix && matrixLoaded && matrixData.length === 0) {\n <mj-empty-state\n Variant=\"no-results\"\n Icon=\"fa-solid fa-diagram-project\"\n Title=\"No Chart Data\"\n Message=\"No suite runs match the current filters.\" />\n }\n }\n }\n <!-- Empty State -->\n @if (!loadingAnalytics && analyticsLoaded && analyticsData.length === 0) {\n <mj-empty-state\n Icon=\"fa-solid fa-chart-line\"\n Title=\"No Analytics Data\"\n Message=\"Run this suite to start collecting analytics data.\"\n ActionText=\"Run Suite Now\"\n ActionIcon=\"fa-solid fa-play\"\n (Action)=\"runSuite()\" />\n }\n </div>\n }\n\n <!-- Compare Tab -->\n @if (activeTab === 'compare') {\n <div class=\"compare-tab\">\n <!-- Run Selection -->\n <div class=\"compare-selection\">\n <div class=\"compare-run-selector\">\n <h4>Run A (Baseline)</h4>\n @if (!loadingRuns && suiteRuns.length > 0) {\n <div class=\"run-selector-list\">\n @for (run of suiteRuns; track run) {\n <div class=\"run-selector-item\"\n [class.selected]=\"IsCompareRunA(run)\"\n (click)=\"selectCompareRunA(run)\">\n <div class=\"selector-status\" [style.background-color]=\"getRunStatusColor(run.Status)\"></div>\n <div class=\"selector-content\">\n <div class=\"selector-date\">{{ run.StartedAt | date:'short' }}</div>\n <div class=\"selector-rate\">{{ getPassRate(run).toFixed(0) }}% pass</div>\n </div>\n @if (getRunTags(run).length > 0) {\n <div class=\"selector-tags\">\n @for (tag of getRunTags(run).slice(0, 2); track tag) {\n <span class=\"tag-mini\">{{ tag }}</span>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n @if (compareRunA) {\n <div class=\"selected-run-preview\">\n <div class=\"preview-header\">\n <span class=\"preview-label\">Selected:</span>\n <button class=\"clear-btn\" (click)=\"compareRunA = null; compareResults = []\">Clear</button>\n </div>\n <div class=\"preview-details\">\n <span>{{ compareRunA.StartedAt | date:'medium' }}</span>\n <span class=\"preview-rate\">{{ getPassRate(compareRunA).toFixed(1) }}%</span>\n </div>\n </div>\n }\n </div>\n <div class=\"compare-vs\"><i class=\"fas fa-exchange-alt\"></i></div>\n <div class=\"compare-run-selector\">\n <h4>Run B (Compare)</h4>\n @if (!loadingRuns && suiteRuns.length > 0) {\n <div class=\"run-selector-list\">\n @for (run of suiteRuns; track run) {\n <div class=\"run-selector-item\"\n [class.selected]=\"IsCompareRunB(run)\"\n [class.disabled]=\"IsCompareRunA(run)\"\n (click)=\"!IsCompareRunA(run) && selectCompareRunB(run)\">\n <div class=\"selector-status\" [style.background-color]=\"getRunStatusColor(run.Status)\"></div>\n <div class=\"selector-content\">\n <div class=\"selector-date\">{{ run.StartedAt | date:'short' }}</div>\n <div class=\"selector-rate\">{{ getPassRate(run).toFixed(0) }}% pass</div>\n </div>\n @if (getRunTags(run).length > 0) {\n <div class=\"selector-tags\">\n @for (tag of getRunTags(run).slice(0, 2); track tag) {\n <span class=\"tag-mini\">{{ tag }}</span>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n @if (compareRunB) {\n <div class=\"selected-run-preview\">\n <div class=\"preview-header\">\n <span class=\"preview-label\">Selected:</span>\n <button class=\"clear-btn\" (click)=\"compareRunB = null; compareResults = []\">Clear</button>\n </div>\n <div class=\"preview-details\">\n <span>{{ compareRunB.StartedAt | date:'medium' }}</span>\n <span class=\"preview-rate\">{{ getPassRate(compareRunB).toFixed(1) }}%</span>\n </div>\n </div>\n }\n </div>\n </div>\n <!-- Comparison Results -->\n @if (compareRunA && compareRunB && !loadingCompare) {\n <div class=\"compare-results\">\n <!-- Summary Cards -->\n <div class=\"compare-summary\">\n <div class=\"compare-summary-card\">\n <div class=\"summary-label\">Pass Rate Change</div>\n <div class=\"summary-value\" [ngClass]=\"{'positive': getComparePassRateDiff()! > 0, 'negative': getComparePassRateDiff()! < 0}\">\n <i class=\"fas\" [ngClass]=\"{'fa-arrow-up': getComparePassRateDiff()! > 0, 'fa-arrow-down': getComparePassRateDiff()! < 0, 'fa-minus': getComparePassRateDiff() === 0}\"></i>\n {{ getComparePassRateDiff()! > 0 ? '+' : '' }}{{ getComparePassRateDiff()?.toFixed(1) }}%\n </div>\n </div>\n <div class=\"compare-summary-card\">\n <div class=\"summary-label\">Duration Change</div>\n <div class=\"summary-value\" [ngClass]=\"{'positive': getCompareDurationDiff()! < 0, 'negative': getCompareDurationDiff()! > 0}\">\n <i class=\"fas\" [ngClass]=\"{'fa-arrow-down': getCompareDurationDiff()! < 0, 'fa-arrow-up': getCompareDurationDiff()! > 0, 'fa-minus': getCompareDurationDiff() === 0}\"></i>\n {{ formatDuration(getAbsCompareDurationDiff()) }}\n </div>\n </div>\n <div class=\"compare-summary-card improved\">\n <div class=\"summary-label\">Improved</div>\n <div class=\"summary-value\">{{ getCompareImprovedCount() }}</div>\n </div>\n <div class=\"compare-summary-card regressed\">\n <div class=\"summary-label\">Regressed</div>\n <div class=\"summary-value\">{{ getCompareRegressedCount() }}</div>\n </div>\n </div>\n <!-- Detailed Comparison Table -->\n <div class=\"compare-table-section\">\n <h3><i class=\"fas fa-list\"></i> Test-by-Test Comparison</h3>\n <div class=\"compare-table-wrapper\">\n <table class=\"compare-table\">\n <thead>\n <tr>\n <th>Test</th>\n <th>Run A Status</th>\n <th>Run B Status</th>\n <th>Score Diff</th>\n <th>Duration Diff</th>\n <th>Change</th>\n </tr>\n </thead>\n <tbody>\n @for (result of compareResults; track result) {\n <tr [ngClass]=\"{'improved': result.runA && result.runB && result.runA.status !== 'Passed' && result.runB.status === 'Passed', 'regressed': result.runA && result.runB && result.runA.status === 'Passed' && result.runB.status !== 'Passed'}\">\n <td class=\"test-name-cell\">{{ result.testName }}</td>\n <td>\n @if (result.runA) {\n <span class=\"status-chip\" [ngClass]=\"'status-' + result.runA.status.toLowerCase()\">{{ result.runA.status }}</span>\n }\n @if (!result.runA) {\n <span class=\"status-chip status-missing\">N/A</span>\n }\n </td>\n <td>\n @if (result.runB) {\n <span class=\"status-chip\" [ngClass]=\"'status-' + result.runB.status.toLowerCase()\">{{ result.runB.status }}</span>\n }\n @if (!result.runB) {\n <span class=\"status-chip status-missing\">N/A</span>\n }\n </td>\n <td>\n @if (result.scoreDiff != null) {\n <span [ngClass]=\"{'positive': result.scoreDiff > 0, 'negative': result.scoreDiff < 0}\">\n {{ result.scoreDiff > 0 ? '+' : '' }}{{ (result.scoreDiff * 100).toFixed(1) }}%\n </span>\n }\n @if (result.scoreDiff == null) {\n <span class=\"muted\">-</span>\n }\n </td>\n <td>\n @if (result.durationDiff != null) {\n <span [ngClass]=\"{'positive': result.durationDiff < 0, 'negative': result.durationDiff > 0}\">\n {{ result.durationDiff > 0 ? '+' : '' }}{{ result.durationDiff.toFixed(1) }}s\n </span>\n }\n @if (result.durationDiff == null) {\n <span class=\"muted\">-</span>\n }\n </td>\n <td>\n @if (result.runA && result.runB && result.runA.status !== 'Passed' && result.runB.status === 'Passed') {\n <span class=\"change-indicator improved\">\n <i class=\"fas fa-arrow-up\"></i> Fixed\n </span>\n }\n @if (result.runA && result.runB && result.runA.status === 'Passed' && result.runB.status !== 'Passed') {\n <span class=\"change-indicator regressed\">\n <i class=\"fas fa-arrow-down\"></i> Broke\n </span>\n }\n @if (!result.statusChanged) {\n <span class=\"change-indicator unchanged\">\n <i class=\"fas fa-minus\"></i>\n </span>\n }\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </div>\n </div>\n }\n <!-- Loading State for Compare -->\n @if (loadingCompare) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading comparison data...\"></mj-loading>\n </div>\n }\n <!-- Empty State -->\n @if (!compareRunA || !compareRunB) {\n <mj-empty-state\n Icon=\"fa-solid fa-scale-balanced\"\n Title=\"Select Two Runs to Compare\"\n Message=\"Choose a baseline run (A) and a comparison run (B) from the lists above to see a detailed side-by-side comparison.\" />\n }\n <!-- No Runs State -->\n @if (runsLoaded && suiteRuns.length < 2) {\n <mj-empty-state\n Icon=\"fa-solid fa-scale-balanced\"\n Title=\"Not Enough Runs to Compare\"\n Message=\"You need at least 2 suite runs to use the comparison feature.\"\n ActionText=\"Run Suite Now\"\n ActionIcon=\"fa-solid fa-play\"\n (Action)=\"runSuite()\" />\n }\n </div>\n }\n </div>\n\n <!-- Keyboard Shortcuts Toggle Button -->\n <button class=\"shortcuts-toggle\" (click)=\"toggleShortcuts()\" [title]=\"showShortcuts ? 'Hide keyboard shortcuts' : 'Show keyboard shortcuts'\">\n <i class=\"fas fa-keyboard\"></i>\n </button>\n\n <!-- Keyboard Shortcuts Hint (Desktop Only) -->\n @if (showShortcuts) {\n <div class=\"keyboard-shortcuts\">\n <div class=\"shortcuts-header\">\n <i class=\"fas fa-keyboard\"></i>\n Shortcuts\n <button class=\"shortcuts-close\" (click)=\"toggleShortcuts()\" title=\"Hide shortcuts\">\n <i class=\"fas fa-times\"></i>\n </button>\n </div>\n <div class=\"shortcut-list\">\n <div class=\"shortcut-item\">\n <span>Save changes</span>\n <span class=\"shortcut-keys\"><kbd>Cmd</kbd><kbd>S</kbd></span>\n </div>\n <div class=\"shortcut-item\">\n <span>Refresh</span>\n <span class=\"shortcut-keys\"><kbd>Cmd</kbd><kbd>R</kbd></span>\n </div>\n <div class=\"shortcut-item\">\n <span>Run Suite</span>\n <span class=\"shortcut-keys\"><kbd>Cmd</kbd><kbd>Enter</kbd></span>\n </div>\n <div class=\"shortcut-item\">\n <span>Switch Tabs</span>\n <span class=\"shortcut-keys\"><kbd>1</kbd>-<kbd>5</kbd></span>\n </div>\n </div>\n </div>\n }\n\n <!-- Slide Panel for Suite Execution -->\n @if (testingDialogService.IsPanelOpen) {\n <mj-slide-panel\n Mode=\"slide\"\n [Title]=\"testingDialogService.PanelOptions?.suiteId ? 'Suite Execution' : 'Run Suite'\"\n [Resizable]=\"true\"\n (Closed)=\"OnPanelClosed()\">\n <app-test-run-dialog\n [PanelMode]=\"true\"\n [selectedTestId]=\"testingDialogService.PanelOptions?.testId ?? null\"\n [selectedSuiteId]=\"testingDialogService.PanelOptions?.suiteId ?? null\"\n [runMode]=\"testingDialogService.PanelOptions?.mode ?? 'suite'\"\n (PanelClose)=\"OnPanelClosed()\">\n </app-test-run-dialog>\n </mj-slide-panel>\n }\n\n <!-- Add Tests Picker Dialog -->\n @if (showAddTestsDialog) {\n <div class=\"picker-backdrop\" (click)=\"closeAddTestsDialog()\"></div>\n <div class=\"picker-dialog\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"add-tests-dialog-title\" (click)=\"$event.stopPropagation()\">\n <div class=\"picker-header\">\n <h2 id=\"add-tests-dialog-title\" class=\"picker-title\">\n <i class=\"fas fa-plus-circle\"></i> Add tests to suite\n </h2>\n <button type=\"button\" class=\"picker-close\" (click)=\"closeAddTestsDialog()\" [disabled]=\"isAddingTests\" aria-label=\"Close\">\n <i class=\"fas fa-times\"></i>\n </button>\n </div>\n\n <div class=\"picker-search\">\n <i class=\"fas fa-search picker-search-icon\"></i>\n <input\n #pickerSearch\n type=\"text\"\n class=\"picker-search-input\"\n placeholder=\"Search tests by name, description, or type...\"\n [(ngModel)]=\"addTestsSearch\"\n autofocus\n />\n @if (addTestsSearch) {\n <button type=\"button\" class=\"picker-search-clear\" (click)=\"addTestsSearch = ''\" aria-label=\"Clear search\">\n <i class=\"fas fa-times\"></i>\n </button>\n }\n </div>\n\n <div class=\"picker-toolbar\">\n <span class=\"picker-toolbar-status\">\n @if (selectedTestIdsToAdd.size > 0) {\n <strong>{{ selectedTestIdsToAdd.size }}</strong> selected\n } @else if (!loadingAvailableTests) {\n {{ filteredAvailableTests.length }} test{{ filteredAvailableTests.length === 1 ? '' : 's' }} available\n }\n </span>\n <div class=\"picker-toolbar-actions\">\n <button type=\"button\" class=\"picker-link-btn\" (click)=\"selectAllFiltered()\" [disabled]=\"loadingAvailableTests || filteredAvailableTests.length === 0\">\n Select all\n </button>\n <button type=\"button\" class=\"picker-link-btn\" (click)=\"clearAddSelection()\" [disabled]=\"selectedTestIdsToAdd.size === 0\">\n Clear\n </button>\n </div>\n </div>\n\n <div class=\"picker-body\">\n @if (loadingAvailableTests) {\n <div class=\"picker-loading\">\n <mj-loading text=\"Loading tests...\"></mj-loading>\n </div>\n } @else if (filteredAvailableTests.length === 0) {\n @if (availableTests.length === 0) {\n <mj-empty-state\n Variant=\"success\"\n Size=\"compact\"\n Title=\"Everything's already in the suite\"\n Message=\"This suite contains every available test. Create a new test first to add more.\" />\n } @else {\n <mj-empty-state\n Variant=\"no-results\"\n Size=\"compact\"\n Title=\"No matches\"\n [Message]=\"AddTestsNoMatchMessage\" />\n }\n } @else {\n <ul class=\"picker-list\">\n @for (t of filteredAvailableTests; track t.ID) {\n <li\n class=\"picker-row\"\n [class.picker-row--selected]=\"isAddSelected(t.ID)\"\n (click)=\"toggleAddSelection(t.ID)\"\n role=\"checkbox\"\n [attr.aria-checked]=\"isAddSelected(t.ID)\"\n tabindex=\"0\"\n >\n <span class=\"picker-check\">\n @if (isAddSelected(t.ID)) {\n <i class=\"fas fa-check\"></i>\n }\n </span>\n <div class=\"picker-row-main\">\n <div class=\"picker-row-name\">{{ t.Name }}</div>\n @if (t.Description) {\n <div class=\"picker-row-desc\">{{ t.Description }}</div>\n }\n </div>\n <div class=\"picker-row-meta\">\n @if (t.Type) {\n <span class=\"picker-row-pill\">{{ t.Type }}</span>\n }\n <span class=\"picker-row-pill picker-row-pill--status\" [attr.data-status]=\"t.Status?.toLowerCase()\">{{ t.Status }}</span>\n </div>\n </li>\n }\n </ul>\n }\n </div>\n\n <div class=\"picker-footer\">\n <button\n type=\"button\"\n class=\"picker-btn picker-btn--primary\"\n (click)=\"confirmAddTests()\"\n [disabled]=\"selectedTestIdsToAdd.size === 0 || isAddingTests\"\n >\n @if (isAddingTests) {\n <i class=\"fas fa-spinner fa-spin\"></i> Adding\u2026\n } @else {\n <i class=\"fas fa-check\"></i>\n @if (selectedTestIdsToAdd.size === 0) {\n Add tests\n } @else if (selectedTestIdsToAdd.size === 1) {\n Add 1 test\n } @else {\n Add {{ selectedTestIdsToAdd.size }} tests\n }\n }\n </button>\n <button\n type=\"button\"\n class=\"picker-btn picker-btn--ghost\"\n (click)=\"closeAddTestsDialog()\"\n [disabled]=\"isAddingTests\"\n >\n Cancel\n </button>\n </div>\n </div>\n }\n\n <!-- Sticky Save Bar \u2014 always in the DOM so CSS transitions can fire reliably.\n Visibility is controlled by the .save-bar--visible class, driven by isDirty. -->\n <div\n class=\"save-bar\"\n [class.save-bar--visible]=\"isDirty\"\n [attr.aria-hidden]=\"!isDirty\"\n role=\"region\"\n aria-label=\"Unsaved changes\"\n >\n <div class=\"save-bar-message\">\n <span class=\"save-bar-dot\" aria-hidden=\"true\">\u25CF</span>\n <span class=\"save-bar-text\">\n <strong>Unsaved changes</strong>\n <span class=\"save-bar-fields\">\n @if (dirtyFieldNames.length === 1) {\n {{ dirtyFieldNames[0] }} edited\n } @else if (dirtyFieldNames.length > 1) {\n {{ dirtyFieldNames.length }} fields edited\n }\n </span>\n </span>\n </div>\n <div class=\"save-bar-actions\">\n <button\n type=\"button\"\n class=\"save-bar-btn save-bar-btn--primary\"\n (click)=\"saveChanges()\"\n [disabled]=\"isSaving || !isDirty\"\n [attr.tabindex]=\"isDirty ? 0 : -1\"\n title=\"Save changes (\u2318S)\"\n >\n @if (isSaving) {\n <i class=\"fas fa-spinner fa-spin\"></i> Saving\u2026\n } @else {\n <i class=\"fas fa-check\"></i> Save changes\n <span class=\"save-bar-kbd\"><kbd>\u2318</kbd><kbd>S</kbd></span>\n }\n </button>\n <button\n type=\"button\"\n class=\"save-bar-btn save-bar-btn--ghost\"\n (click)=\"discardChanges()\"\n [disabled]=\"isSaving || !isDirty\"\n [attr.tabindex]=\"isDirty ? 0 : -1\"\n title=\"Discard changes\"\n >\n <i class=\"fas fa-undo\"></i> Discard\n </button>\n </div>\n </div>\n</div>\n", styles: ["/* ===========================\n Test Suite Form - World-Class UX\n =========================== */\n\n/* CSS Custom Properties for Theming - using :host for Angular encapsulation */\n:host {\n --test-primary: var(--mj-brand-primary);\n --test-primary-light: var(--mj-brand-primary);\n --test-success: var(--mj-status-success);\n --test-error: var(--mj-status-error);\n --test-warning: var(--mj-status-warning);\n --test-disabled: var(--mj-text-muted);\n --test-bg: var(--mj-bg-surface-card);\n --test-surface: var(--mj-bg-surface);\n --test-border: var(--mj-border-default);\n --test-text: var(--mj-text-primary);\n --test-text-secondary: var(--mj-text-secondary);\n --test-text-muted: var(--mj-text-disabled);\n --test-radius-sm: 6px;\n --test-radius-md: 10px;\n --test-radius-lg: 16px;\n --test-shadow-sm: var(--mj-shadow-sm);\n --test-shadow-md: var(--mj-shadow-md);\n --test-shadow-lg: var(--mj-shadow-lg);\n --test-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n display: block;\n height: 100%;\n}\n\n.test-suite-form {\n position: relative;\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--test-bg);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n}\n\n/* Breadcrumb */\n.breadcrumb {\n margin-bottom: 16px;\n}\n\n.breadcrumb ol {\n display: flex;\n align-items: center;\n gap: 4px;\n list-style: none;\n margin: 0;\n padding: 0;\n font-size: 13px;\n}\n\n.breadcrumb li {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.breadcrumb a {\n color: var(--test-primary);\n text-decoration: none;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 8px;\n border-radius: 6px;\n transition: background 0.15s;\n}\n\n.breadcrumb a:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n text-decoration: none;\n}\n\n.breadcrumb .separator {\n font-size: 10px;\n color: var(--test-text-muted);\n margin: 0 4px;\n}\n\n.breadcrumb .current {\n color: var(--test-text-secondary);\n font-weight: 500;\n}\n\n.breadcrumb-text {\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* Header */\n.suite-header {\n background: var(--test-surface);\n border-bottom: 1px solid var(--test-border);\n padding: 20px;\n}\n\n.header-content {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 16px;\n gap: 16px;\n}\n\n.header-left {\n display: flex;\n gap: 16px;\n flex: 1;\n min-width: 0;\n}\n\n.suite-icon {\n width: 56px;\n height: 56px;\n border-radius: var(--test-radius-md);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-inverse);\n font-size: 24px;\n flex-shrink: 0;\n box-shadow: var(--test-shadow-md);\n transition: var(--test-transition);\n}\n\n.suite-icon:hover { transform: scale(1.05); }\n\n.suite-info { flex: 1; min-width: 0; }\n\n.suite-info h1 {\n margin: 0 0 8px 0;\n font-size: clamp(18px, 4vw, 24px);\n font-weight: 700;\n color: var(--test-text);\n word-wrap: break-word;\n}\n\n.suite-meta {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.status-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 14px;\n border-radius: 20px;\n color: var(--mj-text-inverse);\n font-size: 12px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-badge.status-active { background: var(--test-success); }\n.status-badge.status-disabled { background: var(--test-disabled); }\n.status-badge.status-pending { background: var(--test-warning); }\n\n.status-badge-inline {\n display: inline-flex;\n padding: 2px 10px;\n border-radius: 10px;\n color: var(--mj-text-inverse);\n font-size: 11px;\n font-weight: 600;\n}\n\n.status-badge-inline.status-active { background: var(--test-success); }\n.status-badge-inline.status-disabled { background: var(--test-disabled); }\n.status-badge-inline.status-pending { background: var(--test-warning); }\n\n.test-count {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-size: 14px;\n color: var(--test-text-secondary);\n padding: 4px 10px;\n background: var(--test-bg);\n border-radius: var(--test-radius-sm);\n}\n\n.header-actions {\n display: flex;\n gap: 8px;\n flex-shrink: 0;\n}\n\n.suite-description {\n padding: 16px;\n background: var(--mj-bg-surface-card);\n border-radius: var(--test-radius-md);\n border: 1px solid var(--test-border);\n}\n\n.suite-description p {\n margin: 0;\n color: var(--test-text-secondary);\n line-height: 1.6;\n font-size: 14px;\n}\n\n/* Tabs */\n.tabs-container {\n background: var(--test-surface);\n border-bottom: 1px solid var(--test-border);\n position: sticky;\n top: 0;\n z-index: 10;\n}\n\n/* Phone section picker: hidden until the 768px rule swaps it in for the strip */\n.phone-section-picker {\n display: none;\n}\n\n.tabs {\n display: flex;\n padding: 0 20px;\n overflow-x: auto;\n scrollbar-width: none;\n}\n\n.tabs::-webkit-scrollbar { display: none; }\n\n.tab {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 14px 18px;\n border: none;\n background: transparent;\n border-bottom: 3px solid transparent;\n color: var(--test-text-secondary);\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: var(--test-transition);\n white-space: nowrap;\n}\n\n.tab:hover {\n color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.tab.active {\n color: var(--test-primary);\n border-bottom-color: var(--test-primary);\n font-weight: 600;\n}\n\n.tab-badge {\n background: var(--test-border);\n color: var(--test-text-secondary);\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.tab.active .tab-badge {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n color: var(--test-primary);\n}\n\n.tab-shortcut {\n font-size: 10px;\n color: var(--test-text-muted);\n background: var(--test-bg);\n padding: 2px 6px;\n border-radius: 4px;\n font-weight: 600;\n}\n\n/* Tab Content */\n.tab-content {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n}\n\n/* Overview Tab */\n.overview-tab {\n display: flex;\n flex-direction: column;\n gap: 20px;\n animation: fadeIn 0.3s ease-out;\n}\n\n@keyframes fadeIn {\n from { opacity: 0; transform: translateY(10px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n.info-section, .config-section {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.info-section h3, .config-section h3 {\n margin: 0 0 20px 0;\n font-size: 18px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.info-section h3 i, .config-section h3 i {\n color: var(--test-primary);\n}\n\n.info-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 16px;\n}\n\n.info-item {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.info-label {\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.info-value {\n font-size: 14px;\n color: var(--test-text);\n font-weight: 500;\n}\n\n.config-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 20px;\n}\n\n.config-item {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.config-item label {\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.config-input {\n padding: 10px 14px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n font-size: 14px;\n transition: var(--test-transition);\n}\n\n.config-input:focus {\n outline: none;\n border-color: var(--test-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.config-hint {\n font-size: 11px;\n color: var(--test-text-muted);\n}\n\n/* Tests Tab */\n.tests-tab, .runs-tab {\n animation: fadeIn 0.3s ease-out;\n}\n\n.loading-state { padding: 0; }\n\n.skeleton-list {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.skeleton-card {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 16px;\n background: var(--test-surface);\n border-radius: var(--test-radius-md);\n border: 1px solid var(--test-border);\n}\n\n.skeleton-sequence {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n background: linear-gradient(90deg, var(--mj-border-default) 25%, var(--mj-bg-surface-sunken) 50%, var(--mj-border-default) 75%);\n background-size: 200% 100%;\n animation: shimmer 1.5s infinite;\n}\n\n.skeleton-icon {\n width: 40px;\n height: 40px;\n border-radius: var(--test-radius-md);\n background: linear-gradient(90deg, var(--mj-border-default) 25%, var(--mj-bg-surface-sunken) 50%, var(--mj-border-default) 75%);\n background-size: 200% 100%;\n animation: shimmer 1.5s infinite;\n}\n\n.skeleton-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.skeleton-line {\n height: 14px;\n border-radius: 4px;\n background: linear-gradient(90deg, var(--mj-border-default) 25%, var(--mj-bg-surface-sunken) 50%, var(--mj-border-default) 75%);\n background-size: 200% 100%;\n animation: shimmer 1.5s infinite;\n}\n\n.skeleton-line.wide { width: 70%; }\n.skeleton-line.narrow { width: 40%; }\n\n@keyframes shimmer {\n 0% { background-position: 200% 0; }\n 100% { background-position: -200% 0; }\n}\n\n.tests-list, .runs-list {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.test-item, .run-item {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 16px;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.test-item:hover, .run-item:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n border-color: var(--test-primary-light);\n transform: translateX(4px);\n}\n\n.test-sequence {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--test-bg);\n border-radius: 50%;\n font-size: 14px;\n font-weight: 700;\n color: var(--test-text-secondary);\n flex-shrink: 0;\n}\n\n.test-icon, .run-icon {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: var(--test-radius-md);\n color: var(--mj-text-inverse);\n font-size: 18px;\n flex-shrink: 0;\n box-shadow: var(--test-shadow-sm);\n}\n\n.test-icon {\n background: var(--test-primary);\n}\n\n.test-content, .run-content { flex: 1; min-width: 0; }\n\n.test-name, .run-header {\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n margin-bottom: 4px;\n}\n\n.run-header {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.run-id { font-weight: 600; }\n\n.run-status {\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n}\n\n.test-status, .run-meta {\n display: flex;\n gap: 12px;\n font-size: 12px;\n color: var(--test-text-secondary);\n}\n\n.test-status span, .run-meta span {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n\n.test-item > i, .run-item > i {\n color: var(--test-text-muted);\n font-size: 14px;\n transition: var(--test-transition);\n}\n\n.test-item:hover > i, .run-item:hover > i {\n color: var(--test-primary);\n transform: translateX(2px);\n}\n\n/* Keyboard Shortcuts */\n/* Keyboard shortcuts toggle button - visible when shortcuts are hidden */\n.shortcuts-toggle {\n position: fixed;\n bottom: 20px;\n right: 20px;\n width: 36px;\n height: 36px;\n border-radius: 50%;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n box-shadow: var(--test-shadow-md);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--test-text-secondary);\n font-size: 14px;\n z-index: 99;\n transition: var(--test-transition);\n opacity: 0.7;\n}\n\n.shortcuts-toggle:hover {\n opacity: 1;\n transform: scale(1.1);\n color: var(--test-primary);\n border-color: var(--test-primary);\n}\n\n.keyboard-shortcuts {\n position: fixed;\n bottom: 20px;\n right: 20px;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n padding: 12px 16px;\n box-shadow: var(--test-shadow-lg);\n font-size: 12px;\n z-index: 100;\n max-width: 260px;\n}\n\n.shortcuts-header {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-bottom: 10px;\n padding-bottom: 8px;\n border-bottom: 1px solid var(--test-border);\n font-weight: 600;\n color: var(--test-text);\n}\n\n.shortcuts-close {\n margin-left: auto;\n background: none;\n border: none;\n cursor: pointer;\n color: var(--test-text-muted);\n font-size: 12px;\n padding: 2px 4px;\n border-radius: 4px;\n transition: var(--test-transition);\n}\n\n.shortcuts-close:hover {\n color: var(--test-text);\n background: var(--test-border);\n}\n\n.shortcut-list {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.shortcut-item {\n display: flex;\n justify-content: space-between;\n align-items: center;\n color: var(--test-text-secondary);\n}\n\n.shortcut-keys {\n display: flex;\n gap: 4px;\n}\n\n.shortcut-keys kbd {\n background: var(--test-bg);\n border: 1px solid var(--test-border);\n border-radius: 4px;\n padding: 2px 6px;\n font-size: 11px;\n color: var(--test-text);\n}\n\n/* Responsive */\n@media (max-width: 1024px) {\n .keyboard-shortcuts, .shortcuts-toggle { display: none; }\n}\n\n@media (max-width: 768px) {\n /* The tab strip becomes one section-picker button (same pattern as the standard record form). */\n .tabs {\n display: none;\n }\n\n .phone-section-picker {\n display: block;\n padding: 4px 8px;\n }\n\n .suite-header { padding: 16px; }\n\n .header-content {\n flex-direction: column;\n gap: 16px;\n }\n\n .header-actions {\n width: 100%;\n justify-content: stretch;\n }\n\n .header-actions button { flex: 1; }\n\n .tab-shortcut { display: none; }\n\n .info-grid { grid-template-columns: 1fr; }\n\n .test-item, .run-item { padding: 14px; }\n}\n\n@media (max-width: 480px) {\n .suite-icon {\n width: 40px;\n height: 40px;\n font-size: 18px;\n }\n\n .suite-info h1 { font-size: 16px; }\n\n .tab-badge { display: none; }\n\n .test-sequence { display: none; }\n}\n\n@media (hover: none) and (pointer: coarse) {\n .test-item:active, .run-item:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n transform: scale(0.98);\n }\n\n .tab { min-height: 48px; }\n .test-item, .run-item { min-height: 64px; }\n}\n\n@media (prefers-reduced-motion: reduce) {\n *, *::before, *::after {\n animation-duration: 0.01ms !important;\n transition-duration: 0.01ms !important;\n }\n}\n\n@media print {\n .header-actions, .tabs-container, .keyboard-shortcuts {\n display: none !important;\n }\n}\n\n/* ===========================\n Tags UI\n =========================== */\n.run-tags {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin-top: 8px;\n}\n\n.tag-chip {\n display: inline-flex;\n align-items: center;\n padding: 3px 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n border-radius: 12px;\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-brand-primary-hover);\n}\n\n.tag-mini {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 4px;\n font-size: 10px;\n font-weight: 500;\n color: var(--mj-text-muted);\n}\n\n.tag-more {\n font-size: 10px;\n color: var(--mj-text-disabled);\n font-weight: 500;\n}\n\n/* Evaluation metrics row for Runs list */\n.run-eval-metrics {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 8px;\n}\n\n.eval-metric {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 3px 8px;\n border-radius: 6px;\n font-size: 11px;\n font-weight: 500;\n}\n\n.eval-metric.status {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.eval-metric.status.status-completed {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.eval-metric.status.status-failed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.eval-metric.status.status-running {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.eval-metric.status.status-pending {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.eval-metric.human {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n border: 1px solid var(--mj-status-warning);\n color: var(--mj-status-warning);\n}\n\n.eval-metric.human .eval-pending {\n font-size: 9px;\n color: var(--mj-status-warning);\n}\n\n.eval-metric.auto {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n color: var(--mj-brand-primary-hover);\n}\n\n.eval-metric.auto.high {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-success) 30%, transparent);\n color: var(--mj-status-success);\n}\n\n.eval-metric.auto.medium {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 30%, transparent);\n color: var(--mj-status-warning);\n}\n\n.eval-metric.auto.low {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 30%, transparent);\n color: var(--mj-status-error);\n}\n\n.tag-cell {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-wrap: wrap;\n}\n\n.tag-chip-table {\n display: inline-block;\n padding: 3px 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n color: var(--mj-brand-primary-hover);\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n white-space: nowrap;\n max-width: 80px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* ===========================\n Analytics Tab\n =========================== */\n.analytics-tab {\n animation: fadeIn 0.3s ease-out;\n}\n\n/* Collapsible filters */\n/* Filters disclosure migrated to <mj-accordion-panel>. The bespoke\n .analytics-filters wrapper card chrome, the .filters-header bar (+ hover),\n and the .filters-header > i chevron are now owned by the accordion and were\n removed. The title-slot layout (.filters-title flex row) and font are now\n provided by the accordion title + Size=\"sm\"; the collapsed summary uses the\n shared .mj-accordion-badge (--muted --right). Only the body content\n (.filters-content) styling is kept below. */\n\n.filters-content {\n display: flex;\n flex-direction: column;\n gap: 16px;\n padding: 12px 16px 16px 16px;\n border-top: 1px solid var(--test-border);\n}\n\n.filter-group {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.filter-group label {\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.filter-buttons {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.filter-btn {\n padding: 8px 16px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n background: var(--test-surface);\n color: var(--test-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.filter-btn:hover {\n border-color: var(--test-primary);\n color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.filter-btn.active {\n background: var(--test-primary);\n border-color: var(--test-primary);\n color: var(--mj-text-inverse);\n}\n\n.filter-btn.tag-btn {\n padding: 6px 12px;\n font-size: 12px;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n}\n\n.filter-btn.tag-btn i.fa-check {\n font-size: 10px;\n}\n\n.filter-btn.tag-btn.all-tags-btn {\n font-weight: 600;\n}\n\n.filter-btn.tag-btn.all-tags-btn i {\n font-size: 11px;\n}\n\n.filter-hint {\n font-weight: 400;\n font-size: 10px;\n color: var(--test-primary);\n text-transform: none;\n letter-spacing: normal;\n}\n\n.tag-filters {\n max-height: 120px;\n overflow-y: auto;\n}\n\n/* KPI Cards */\n.analytics-kpis {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.kpi-card {\n display: flex;\n align-items: center;\n gap: 16px;\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 20px;\n box-shadow: var(--test-shadow-sm);\n transition: var(--test-transition);\n}\n\n.kpi-card:hover {\n transform: translateY(-2px);\n box-shadow: var(--test-shadow-md);\n}\n\n.kpi-icon {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-radius: var(--test-radius-md);\n color: var(--test-primary);\n font-size: 20px;\n}\n\n.kpi-icon.success {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.kpi-icon.info {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.kpi-icon.warning {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--test-warning);\n}\n\n.kpi-content {\n flex: 1;\n min-width: 0;\n}\n\n.kpi-value {\n font-size: 24px;\n font-weight: 700;\n color: var(--test-text);\n line-height: 1.2;\n}\n\n.kpi-label {\n font-size: 12px;\n color: var(--test-text-secondary);\n margin-top: 2px;\n}\n\n.kpi-trend {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 12px;\n font-weight: 600;\n margin-top: 4px;\n padding: 2px 8px;\n border-radius: 10px;\n background: var(--mj-bg-surface-sunken);\n color: var(--test-text-secondary);\n}\n\n.kpi-trend.trend-up {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.kpi-trend.trend-down {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n/* Analytics Table */\n.analytics-table-section {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.analytics-table-section h3 {\n margin: 0 0 16px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.analytics-table-section h3 i {\n color: var(--test-primary);\n}\n\n.analytics-table-wrapper {\n overflow-x: auto;\n margin: 0 -24px;\n padding: 0 24px;\n}\n\n.analytics-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.analytics-table th {\n text-align: left;\n padding: 12px 16px;\n background: var(--mj-bg-surface-card);\n border-bottom: 2px solid var(--test-border);\n font-weight: 600;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n font-size: 11px;\n letter-spacing: 0.5px;\n white-space: nowrap;\n}\n\n.analytics-table td {\n padding: 14px 16px;\n border-bottom: 1px solid var(--test-border);\n color: var(--test-text);\n}\n\n.analytics-table tbody tr.clickable-row {\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.analytics-table tbody tr.clickable-row:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.status-chip {\n display: inline-flex;\n align-items: center;\n padding: 4px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-chip.status-completed { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--test-success); }\n.status-chip.status-passed { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--test-success); }\n.status-chip.status-failed { background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface)); color: var(--test-error); }\n.status-chip.status-error { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--test-warning); }\n.status-chip.status-running { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--test-primary); }\n.status-chip.status-pending { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n.status-chip.status-cancelled { background: var(--mj-bg-surface-sunken); color: var(--test-disabled); }\n.status-chip.status-missing { background: var(--mj-bg-surface-sunken); color: var(--test-text-muted); }\n.status-chip.status-timeout { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--test-warning); }\n.status-chip.status-skipped { background: var(--mj-bg-surface-sunken); color: var(--test-disabled); }\n\n.pass-rate-cell {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 100px;\n}\n\n.pass-rate-bar {\n height: 6px;\n border-radius: 3px;\n background: var(--test-success);\n transition: width 0.3s ease;\n max-width: 60px;\n}\n\n.pass-rate-bar.medium { background: var(--test-warning); }\n.pass-rate-bar.low { background: var(--test-error); }\n\n/* Analytics Sub-navigation */\n.analytics-subnav {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 8px;\n margin-bottom: 20px;\n box-shadow: var(--test-shadow-sm);\n display: inline-flex;\n}\n\n.subnav-tabs {\n display: flex;\n gap: 4px;\n background: var(--test-bg);\n border-radius: var(--test-radius-md);\n padding: 4px;\n}\n\n.subnav-tab {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n border: none;\n border-radius: var(--test-radius-sm);\n background: transparent;\n color: var(--test-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.subnav-tab:hover {\n color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.subnav-tab.active {\n background: var(--test-surface);\n color: var(--test-primary);\n box-shadow: var(--test-shadow-sm);\n}\n\n.subnav-tab i {\n font-size: 14px;\n}\n\n/* Matrix View */\n.matrix-section {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 16px;\n box-shadow: var(--test-shadow-sm);\n display: flex;\n flex-direction: column;\n max-height: calc(100vh - 280px);\n min-height: 300px;\n}\n\n.matrix-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 12px;\n margin-bottom: 12px;\n padding-bottom: 12px;\n border-bottom: 1px solid var(--test-border);\n flex-shrink: 0;\n}\n\n.matrix-header-right {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.matrix-header h3 {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 0;\n font-size: 15px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.matrix-header h3 i {\n color: var(--test-primary);\n}\n\n.matrix-run-count {\n font-size: 12px;\n color: var(--test-text-muted);\n font-weight: 500;\n}\n\n/* Matrix filter input */\n.matrix-filter-input {\n display: flex;\n align-items: center;\n gap: 8px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--test-border);\n border-radius: 6px;\n padding: 4px 10px;\n min-width: 180px;\n}\n\n.matrix-filter-input i.fa-search {\n color: var(--mj-text-disabled);\n font-size: 12px;\n}\n\n.matrix-filter-input .filter-input {\n border: none;\n background: transparent;\n outline: none;\n font-size: 12px;\n color: var(--test-text);\n width: 100%;\n}\n\n.matrix-filter-input .filter-input::placeholder {\n color: var(--mj-text-disabled);\n}\n\n.clear-filter-btn {\n border: none;\n background: none;\n padding: 2px 4px;\n cursor: pointer;\n color: var(--mj-text-disabled);\n font-size: 10px;\n border-radius: 3px;\n transition: all 0.15s ease;\n}\n\n.clear-filter-btn:hover {\n background: var(--mj-border-default);\n color: var(--mj-text-muted);\n}\n\n/* Scrollable matrix container with fixed height */\n.matrix-scroll-container {\n flex: 1;\n overflow: auto;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n}\n\n.test-matrix {\n display: table;\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.test-matrix thead {\n display: table-header-group;\n}\n\n.test-matrix thead tr {\n display: table-row;\n}\n\n.test-matrix tbody {\n display: table-row-group;\n}\n\n.test-matrix tbody tr {\n display: table-row;\n cursor: pointer;\n transition: background-color 0.15s ease;\n}\n\n.test-matrix tbody tr:hover {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.test-matrix tbody tr.row-selected {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent) !important;\n}\n\n.test-matrix tbody tr.row-selected td {\n border-top: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n border-bottom: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.test-matrix tbody tr.row-selected .seq-cell,\n.test-matrix tbody tr.row-selected .test-name-cell {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent) !important;\n}\n\n.test-matrix tfoot {\n display: table-footer-group;\n}\n\n.test-matrix th,\n.test-matrix td {\n display: table-cell;\n border: 1px solid var(--test-border);\n padding: 8px 12px;\n text-align: center;\n vertical-align: middle;\n}\n\n.test-matrix th {\n background: var(--test-bg);\n font-weight: 600;\n font-size: 11px;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n position: sticky;\n top: 0;\n z-index: 10;\n border-bottom: 3px solid var(--mj-text-secondary) !important;\n}\n\n/* Sequence column - shared styles */\n.test-matrix .seq-header,\n.test-matrix .seq-cell {\n width: 36px;\n min-width: 36px;\n max-width: 36px;\n text-align: center;\n position: sticky;\n left: 0;\n font-size: 11px;\n color: var(--mj-text-muted);\n border-right: 1px solid var(--test-border);\n padding: 6px 4px !important;\n}\n\n/* Seq header - sticky top AND left, highest z-index */\n.test-matrix .seq-header {\n cursor: pointer;\n font-weight: 600;\n background: var(--test-bg);\n z-index: 12; /* Higher than other headers */\n top: 0;\n}\n\n/* Seq body cells - sticky left only, lower z-index */\n.test-matrix .seq-cell {\n background: var(--test-surface);\n z-index: 2;\n}\n\n.test-matrix .seq-header i {\n font-size: 9px;\n margin-left: 2px;\n opacity: 0.6;\n}\n\n.test-matrix .seq-header:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.test-matrix .test-name-header {\n text-align: left;\n min-width: 150px;\n max-width: 500px;\n width: auto;\n position: sticky;\n left: 36px;\n background: var(--test-bg);\n z-index: 11;\n border-right: 2px solid var(--test-border);\n cursor: pointer;\n}\n\n.test-matrix .test-name-header i {\n font-size: 9px;\n margin-left: 4px;\n opacity: 0.6;\n}\n\n.test-matrix .test-name-header:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.test-matrix .run-header {\n min-width: 120px;\n width: 120px;\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n/* Spacer column absorbs extra width */\n.test-matrix .spacer-header,\n.test-matrix .spacer-cell {\n width: 100%;\n min-width: 20px;\n background: var(--test-bg);\n border: none;\n}\n\n.test-matrix .spacer-cell {\n background: var(--test-surface);\n}\n\n.test-matrix .run-header:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.run-header-content {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n}\n\n.run-date {\n font-size: 12px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.run-pass-rate {\n font-size: 11px;\n font-weight: 700;\n padding: 2px 8px;\n border-radius: 10px;\n}\n\n.run-pass-rate.high {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.run-pass-rate.medium {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--test-warning);\n}\n\n.run-pass-rate.low {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n.run-tags {\n display: flex;\n gap: 4px;\n}\n\n.tag-tiny {\n font-size: 9px;\n padding: 2px 6px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--test-primary);\n border-radius: 8px;\n white-space: nowrap;\n max-width: 60px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* Matrix column header tags - emphasized */\n.run-tags-header {\n display: flex;\n flex-wrap: wrap;\n gap: 3px;\n justify-content: center;\n margin-bottom: 4px;\n}\n\n.tag-chip-header {\n display: inline-block;\n padding: 3px 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n color: var(--mj-brand-primary-hover);\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n white-space: nowrap;\n max-width: 70px;\n overflow: hidden;\n text-overflow: ellipsis;\n text-transform: none;\n letter-spacing: normal;\n}\n\n.tag-more-header {\n font-size: 9px;\n color: var(--test-text-secondary);\n padding: 2px 4px;\n}\n\n.test-matrix .test-name-cell {\n text-align: left;\n min-width: 150px;\n max-width: 500px;\n width: auto;\n position: sticky;\n left: 36px;\n background: var(--test-surface);\n z-index: 2;\n border-right: 2px solid var(--test-border);\n padding: 6px 10px !important;\n}\n\n.test-name {\n display: block;\n white-space: nowrap;\n font-weight: 500;\n color: var(--test-text);\n font-size: 12px;\n}\n\n.result-cell {\n position: relative;\n min-width: 120px;\n width: 120px;\n transition: var(--test-transition);\n}\n\n.result-cell.clickable {\n cursor: pointer;\n}\n\n.result-cell.clickable:hover {\n transform: scale(1.1);\n box-shadow: var(--mj-shadow-md);\n z-index: 5;\n}\n\n.result-cell i {\n font-size: 14px;\n}\n\n/* Completed cells have neutral white background - pills tell the story */\n.result-cell.cell-passed,\n.result-cell.cell-failed,\n.result-cell.cell-error,\n.result-cell.cell-timeout,\n.result-cell.cell-running,\n.result-cell.cell-pending {\n background: var(--mj-bg-surface);\n color: var(--test-text);\n}\n\n/* Skipped/not-run cells get hatched background */\n.result-cell.cell-skipped {\n background: repeating-linear-gradient(\n 45deg,\n var(--mj-bg-surface-card),\n var(--mj-bg-surface-card) 4px,\n var(--mj-border-default) 4px,\n var(--mj-border-default) 8px\n );\n color: var(--test-disabled);\n}\n\n.result-cell.cell-none {\n background: var(--mj-bg-surface-card);\n color: var(--test-text-muted);\n}\n\n.cell-score {\n display: block;\n font-size: 10px;\n font-weight: 600;\n margin-top: 2px;\n}\n\n/* Matrix cell evaluation stack - shows multiple eval types horizontally */\n.cell-eval-stack {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n flex-wrap: nowrap;\n}\n\n.result-cell.multi-eval {\n min-width: 120px;\n width: auto;\n}\n\n/* Add timeout status icon */\n.cell-status.status-timeout {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 11px;\n}\n\n.cell-status.status-passed {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-status.status-failed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-status.status-error {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status.status-skipped {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.cell-status.status-running {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.cell-status.status-pending {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.cell-human {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 50%;\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n font-size: 10px;\n}\n\n.cell-auto {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 10px;\n font-weight: 600;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.cell-auto.high {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-auto.medium {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-auto.low {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-none-indicator {\n color: var(--test-text-muted);\n opacity: 0.5;\n}\n\n.matrix-info {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: var(--test-text-muted);\n padding: 12px;\n background: var(--test-bg);\n border-radius: var(--test-radius-sm);\n}\n\n.matrix-info i {\n color: var(--test-primary);\n}\n\n/* ===========================\n Chart View\n =========================== */\n.chart-section {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.chart-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 16px;\n margin-bottom: 20px;\n padding-bottom: 16px;\n border-bottom: 1px solid var(--test-border);\n}\n\n.chart-header h3 {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--test-text);\n}\n\n.chart-header h3 i {\n color: var(--test-primary);\n}\n\n.chart-legend {\n display: flex;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.chart-legend .legend-item {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n font-weight: 500;\n padding: 4px 10px;\n border-radius: 12px;\n}\n\n.chart-legend .legend-item.chart-passed {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.chart-legend .legend-item.chart-failed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n.chart-legend .legend-item.chart-error {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--test-warning);\n}\n\n.chart-legend .legend-item.chart-skipped {\n background: var(--mj-bg-surface-sunken);\n color: var(--test-disabled);\n}\n\n.chart-container {\n min-height: 500px;\n position: relative;\n overflow: hidden;\n background: var(--mj-bg-surface-card);\n border-radius: var(--test-radius-md);\n border: 1px solid var(--test-border);\n}\n\n.d3-chart {\n width: 100%;\n height: 500px;\n}\n\n.d3-chart svg {\n width: 100%;\n height: 100%;\n}\n\n/* D3 Chart Node Styles */\n.d3-chart .node {\n cursor: pointer;\n transition: transform 0.2s ease;\n}\n\n.d3-chart .node:hover {\n transform: scale(1.05);\n}\n\n.d3-chart .node-label {\n font-size: 11px;\n font-weight: 500;\n fill: var(--test-text);\n pointer-events: none;\n}\n\n.d3-chart .link {\n fill: none;\n stroke-opacity: 0.4;\n transition: stroke-opacity 0.2s ease;\n}\n\n.d3-chart .link:hover {\n stroke-opacity: 0.8;\n}\n\n.d3-chart .tooltip {\n position: absolute;\n padding: 10px 14px;\n background: var(--mj-bg-overlay);\n color: var(--mj-text-inverse);\n border-radius: 8px;\n font-size: 12px;\n pointer-events: none;\n z-index: 100;\n box-shadow: var(--mj-shadow-lg);\n max-width: 250px;\n}\n\n.d3-chart .tooltip-title {\n font-weight: 600;\n margin-bottom: 4px;\n}\n\n.d3-chart .tooltip-value {\n opacity: 0.8;\n}\n\n.chart-info {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: var(--test-text-muted);\n padding: 12px;\n background: var(--test-bg);\n border-radius: var(--test-radius-sm);\n margin-top: 16px;\n}\n\n.chart-info i {\n color: var(--test-primary);\n}\n\n/* ===========================\n Compare Tab\n =========================== */\n.compare-tab {\n animation: fadeIn 0.3s ease-out;\n}\n\n.compare-selection {\n display: grid;\n grid-template-columns: 1fr auto 1fr;\n gap: 24px;\n align-items: flex-start;\n margin-bottom: 24px;\n}\n\n.compare-run-selector {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 20px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.compare-run-selector h4 {\n margin: 0 0 16px 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.run-selector-list {\n max-height: 200px;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-bottom: 12px;\n}\n\n.run-selector-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n cursor: pointer;\n transition: var(--test-transition);\n}\n\n.run-selector-item:hover {\n border-color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n}\n\n.run-selector-item.selected {\n border-color: var(--test-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n}\n\n.run-selector-item.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.selector-status {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.selector-content {\n flex: 1;\n min-width: 0;\n}\n\n.selector-date {\n font-size: 12px;\n font-weight: 500;\n color: var(--test-text);\n}\n\n.selector-rate {\n font-size: 11px;\n color: var(--test-text-secondary);\n}\n\n.selector-tags {\n display: flex;\n gap: 4px;\n flex-wrap: wrap;\n}\n\n.selected-run-preview {\n padding: 12px;\n background: var(--mj-bg-surface-card);\n border-radius: var(--test-radius-sm);\n border: 1px solid var(--test-border);\n}\n\n.preview-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.preview-label {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n color: var(--test-text-muted);\n}\n\n.clear-btn {\n padding: 4px 8px;\n border: none;\n background: transparent;\n color: var(--test-error);\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n}\n\n.clear-btn:hover { text-decoration: underline; }\n\n.preview-details {\n display: flex;\n justify-content: space-between;\n font-size: 12px;\n color: var(--test-text);\n}\n\n.preview-rate {\n font-weight: 600;\n color: var(--test-success);\n}\n\n.compare-vs {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n background: var(--test-bg);\n border-radius: 50%;\n color: var(--test-text-muted);\n font-size: 16px;\n align-self: center;\n margin-top: 60px;\n}\n\n/* Compare Results */\n.compare-results {\n animation: fadeIn 0.3s ease-out;\n}\n\n.compare-summary {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.compare-summary-card {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 20px;\n box-shadow: var(--test-shadow-sm);\n text-align: center;\n}\n\n.compare-summary-card .summary-label {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n color: var(--test-text-muted);\n margin-bottom: 8px;\n}\n\n.compare-summary-card .summary-value {\n font-size: 24px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n}\n\n.compare-summary-card .summary-value.positive { color: var(--test-success); }\n.compare-summary-card .summary-value.negative { color: var(--test-error); }\n\n.compare-summary-card.improved {\n border-left: 4px solid var(--test-success);\n}\n\n.compare-summary-card.improved .summary-value { color: var(--test-success); }\n\n.compare-summary-card.regressed {\n border-left: 4px solid var(--test-error);\n}\n\n.compare-summary-card.regressed .summary-value { color: var(--test-error); }\n\n/* Compare Table */\n.compare-table-section {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.compare-table-section h3 {\n margin: 0 0 16px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.compare-table-section h3 i {\n color: var(--test-primary);\n}\n\n.compare-table-wrapper {\n overflow-x: auto;\n}\n\n.compare-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.compare-table th {\n text-align: left;\n padding: 12px 16px;\n background: var(--mj-bg-surface-card);\n border-bottom: 2px solid var(--test-border);\n font-weight: 600;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n font-size: 11px;\n letter-spacing: 0.5px;\n white-space: nowrap;\n}\n\n.compare-table td {\n padding: 14px 16px;\n border-bottom: 1px solid var(--test-border);\n color: var(--test-text);\n}\n\n.compare-table tbody tr.improved {\n background: color-mix(in srgb, var(--mj-status-success) 5%, transparent);\n}\n\n.compare-table tbody tr.regressed {\n background: color-mix(in srgb, var(--mj-status-error) 5%, transparent);\n}\n\n.test-name-cell {\n font-weight: 500;\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.positive { color: var(--test-success); }\n.negative { color: var(--test-error); }\n.muted { color: var(--test-text-muted); }\n\n.change-indicator {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.change-indicator.improved {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--test-success);\n}\n\n.change-indicator.regressed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--test-error);\n}\n\n.change-indicator.unchanged {\n background: var(--mj-bg-surface-sunken);\n color: var(--test-text-muted);\n}\n\n/* ===========================\n Responsive Analytics/Compare\n =========================== */\n@media (max-width: 1024px) {\n .compare-selection {\n grid-template-columns: 1fr;\n gap: 16px;\n }\n\n .compare-vs {\n margin: 0;\n align-self: center;\n justify-self: center;\n }\n\n .analytics-kpis {\n grid-template-columns: repeat(2, 1fr);\n }\n}\n\n@media (max-width: 768px) {\n .filter-buttons {\n flex-direction: column;\n }\n\n .filter-btn {\n width: 100%;\n text-align: center;\n }\n\n .analytics-kpis {\n grid-template-columns: 1fr;\n }\n\n .kpi-card {\n padding: 16px;\n }\n\n .kpi-value {\n font-size: 20px;\n }\n\n .compare-summary {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .analytics-table-wrapper,\n .compare-table-wrapper {\n margin: 0 -20px;\n padding: 0 20px;\n }\n\n .run-selector-list {\n max-height: 150px;\n }\n}\n\n@media (max-width: 480px) {\n .compare-summary {\n grid-template-columns: 1fr;\n }\n\n .compare-summary-card .summary-value {\n font-size: 20px;\n }\n\n .analytics-table th,\n .analytics-table td,\n .compare-table th,\n .compare-table td {\n padding: 10px 12px;\n font-size: 12px;\n }\n}\n\n/* ===========================\n Matrix Evaluation Indicators\n =========================== */\n\n/* Human Feedback Indicators */\n.cell-human {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 3px;\n min-width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 10px;\n}\n\n.cell-human.no-feedback {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n}\n\n.cell-human.no-feedback i {\n font-size: 11px;\n}\n\n.cell-human.has-feedback {\n padding: 0 6px;\n border-radius: 12px;\n min-width: 36px;\n}\n\n.cell-human.has-feedback i {\n font-size: 9px;\n}\n\n.cell-human.has-feedback .rating-value {\n font-weight: 700;\n font-size: 11px;\n}\n\n/* Human rating color coding: red \u22644, yellow 5-6, light-green 7-8, green 9-10 */\n.cell-human.rating-low {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-human.rating-medium {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-human.rating-good {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-human.rating-excellent {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n/* Auto Score Indicators */\n.cell-auto {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 3px;\n min-width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 10px;\n}\n\n.cell-auto.no-score {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n}\n\n.cell-auto.no-score i {\n font-size: 11px;\n}\n\n.cell-auto.has-score {\n padding: 0 6px;\n border-radius: 12px;\n min-width: 36px;\n}\n\n.cell-auto.has-score i {\n font-size: 9px;\n}\n\n.cell-auto.has-score .score-value {\n font-weight: 700;\n font-size: 10px;\n}\n\n/* Auto score color coding (0-100%): red <50, yellow 50-69, light-green 70-84, green 85+ */\n.cell-auto.score-low {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-auto.score-medium {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-auto.score-good {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-auto.score-excellent {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n/* Status indicators in matrix cells */\n.cell-status {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 50%;\n font-size: 11px;\n}\n\n.cell-status.status-passed {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.cell-status.status-failed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.cell-status.status-error {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status.status-timeout {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.cell-status.status-skipped,\n.cell-status.status-pending {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.cell-status.status-running {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n/* Not-run / Skipped cells with hatch pattern */\n.result-cell.cell-not-run {\n background: repeating-linear-gradient(\n 45deg,\n var(--mj-bg-surface-card),\n var(--mj-bg-surface-card) 4px,\n var(--mj-border-default) 4px,\n var(--mj-border-default) 8px\n );\n color: var(--mj-text-disabled);\n}\n\n.result-cell.cell-not-run .cell-eval-stack {\n opacity: 0.6;\n}\n\n.cell-not-run-indicator {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n color: var(--mj-text-disabled);\n font-size: 11px;\n}\n\n/* ===========================\n Matrix Totals Footer Row\n =========================== */\n.test-matrix tfoot {\n position: sticky;\n bottom: 0;\n z-index: 2;\n}\n\n.totals-row {\n background: var(--mj-bg-surface-sunken);\n border-top: 2px solid var(--test-border);\n}\n\n.totals-row td {\n padding: 10px 12px;\n font-weight: 600;\n}\n\n.totals-row .totals-label {\n background: var(--mj-bg-surface-sunken);\n font-size: 12px;\n color: var(--test-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.totals-row .totals-cell {\n background: var(--mj-bg-surface-sunken);\n}\n\n.totals-stack {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n}\n\n.totals-status,\n.totals-human,\n.totals-auto {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n padding: 2px 8px;\n border-radius: 10px;\n white-space: nowrap;\n}\n\n.totals-status {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.totals-status .pass-count {\n font-weight: 700;\n}\n\n.totals-human {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.totals-human .avg-label {\n font-weight: 700;\n}\n\n.totals-human .count-label {\n font-size: 10px;\n opacity: 0.8;\n}\n\n.totals-auto {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.totals-auto .avg-label {\n font-weight: 700;\n}\n\n.totals-auto .count-label {\n font-size: 10px;\n opacity: 0.8;\n}\n\n/* ===========================\n Editable Overview Form\n =========================== */\n\n.edit-section {\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n padding: 24px;\n box-shadow: var(--test-shadow-sm);\n}\n\n.edit-section-header {\n margin: 0 0 18px 0;\n}\n\n.edit-section-header h3 {\n margin: 0 0 4px 0;\n font-size: 18px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.edit-section-header h3 i {\n color: var(--test-primary);\n}\n\n.edit-section-sub {\n margin: 0;\n font-size: 12px;\n color: var(--test-text-muted);\n}\n\n.edit-grid {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 18px;\n}\n\n@media (max-width: 720px) {\n .edit-grid {\n grid-template-columns: 1fr;\n }\n}\n\n.edit-field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n min-width: 0;\n}\n\n.edit-field--full {\n grid-column: 1 / -1;\n}\n\n.edit-field label {\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.edit-field .required {\n color: var(--mj-status-error);\n margin-left: 2px;\n}\n\n.config-textarea {\n resize: vertical;\n min-height: 72px;\n font-family: inherit;\n line-height: 1.5;\n}\n\n.select-wrapper {\n position: relative;\n}\n\n.select-wrapper select.config-input {\n padding-right: 36px;\n appearance: none;\n background-color: var(--test-surface);\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%2364748b' d='M1.41 0L6 4.59 10.59 0 12 1.41l-6 6-6-6z'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 14px center;\n background-size: 10px 7px;\n}\n\n/* Tag editor (chips + inline input) */\n.tag-editor {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n padding: 8px 10px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n background: var(--test-surface);\n transition: var(--test-transition);\n cursor: text;\n min-height: 42px;\n align-items: center;\n}\n\n.tag-editor:focus-within {\n border-color: var(--test-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.tag-chip-editable {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 3px 4px 3px 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n border-radius: 999px;\n font-size: 12px;\n font-weight: 600;\n line-height: 1;\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n}\n\n.tag-chip-editable .tag-remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n border: none;\n background: transparent;\n color: var(--mj-brand-primary);\n cursor: pointer;\n font-size: 10px;\n transition: background 0.15s;\n}\n\n.tag-chip-editable .tag-remove:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n color: var(--mj-brand-primary-hover);\n}\n\n.tag-input-inline {\n flex: 1;\n min-width: 140px;\n border: none;\n background: transparent;\n outline: none;\n font-size: 13px;\n color: var(--test-text);\n padding: 4px 2px;\n}\n\n.tag-input-inline::placeholder {\n color: var(--test-text-muted);\n}\n\n/* Read-only metadata section */\n.meta-section {\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--test-radius-md);\n padding: 14px 18px;\n border: 1px solid var(--test-border);\n}\n\n.meta-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 14px;\n}\n\n.meta-item {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.meta-label {\n font-size: 10px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--test-text-muted);\n}\n\n.meta-value {\n font-size: 12px;\n color: var(--test-text-secondary);\n font-weight: 500;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.meta-mono {\n font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;\n font-size: 11px;\n}\n\n/* Dirty indicator next to the title */\n.dirty-indicator {\n display: inline-block;\n margin-left: 8px;\n font-size: 14px;\n color: var(--mj-status-warning);\n line-height: 1;\n animation: pulseDot 1.8s ease-in-out infinite;\n vertical-align: middle;\n}\n\n@keyframes pulseDot {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.5; transform: scale(0.85); }\n}\n\n.unsaved-pill {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning-text, var(--mj-status-warning));\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 30%, transparent);\n border-radius: 999px;\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.4px;\n}\n\n.unsaved-pill i {\n font-size: 6px;\n animation: pulseDot 1.8s ease-in-out infinite;\n}\n\n/* Pad the bottom of the tab content when the save bar is visible\n so the bar doesn't cover the last form field. */\n.tab-content.has-savebar {\n padding-bottom: 84px;\n}\n\n/* ===========================\n Sticky Save Bar\n =========================== */\n\n.save-bar {\n position: absolute;\n left: 16px;\n right: 96px; /* leaves room for the bottom-right chat launcher */\n bottom: 16px;\n z-index: 50;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n padding: 12px 16px 12px 20px;\n background: var(--mj-bg-surface-elevated, var(--test-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 25%, var(--test-border));\n border-radius: 14px;\n box-shadow: 0 12px 32px color-mix(in srgb, var(--mj-status-warning) 10%, rgba(0, 0, 0, 0.18));\n backdrop-filter: blur(8px);\n /* Hidden / off-screen state by default. The .save-bar--visible class\n animates it up into view. Using `transition` (not `animation`)\n guarantees the change runs every time isDirty toggles. */\n opacity: 0;\n transform: translateY(calc(100% + 32px));\n pointer-events: none;\n transition:\n transform 420ms cubic-bezier(0.16, 1, 0.3, 1),\n opacity 260ms cubic-bezier(0.16, 1, 0.3, 1);\n will-change: transform, opacity;\n}\n\n.save-bar--visible {\n opacity: 1;\n transform: translateY(0);\n pointer-events: auto;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .save-bar {\n transition: opacity 180ms ease-out;\n transform: none;\n }\n .save-bar--visible {\n transform: none;\n }\n}\n\n.save-bar-message {\n display: flex;\n align-items: center;\n gap: 12px;\n min-width: 0;\n}\n\n.save-bar-dot {\n color: var(--mj-status-warning);\n font-size: 12px;\n line-height: 1;\n animation: pulseDot 1.8s ease-in-out infinite;\n}\n\n.save-bar-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.save-bar-text strong {\n font-size: 14px;\n color: var(--test-text);\n font-weight: 700;\n}\n\n.save-bar-fields {\n font-size: 12px;\n color: var(--test-text-muted);\n}\n\n.save-bar-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-shrink: 0;\n}\n\n.save-bar-btn {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 9px 16px;\n font-size: 13px;\n font-weight: 600;\n border-radius: 8px;\n border: 1px solid transparent;\n cursor: pointer;\n transition: var(--test-transition);\n font-family: inherit;\n}\n\n.save-bar-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.save-bar-btn--primary {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse, white);\n border-color: var(--mj-brand-primary);\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-brand-primary) 35%, transparent);\n}\n\n.save-bar-btn--primary:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover, var(--mj-brand-primary));\n transform: translateY(-1px);\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-brand-primary) 45%, transparent);\n}\n\n.save-bar-btn--primary:active:not(:disabled) {\n transform: translateY(0);\n}\n\n.save-bar-btn--ghost {\n background: transparent;\n color: var(--test-text-secondary);\n border-color: var(--test-border);\n}\n\n.save-bar-btn--ghost:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n border-color: var(--test-text-muted);\n}\n\n.save-bar-kbd {\n display: inline-flex;\n gap: 3px;\n margin-left: 6px;\n opacity: 0.85;\n}\n\n.save-bar-kbd kbd {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 4px;\n font-size: 10px;\n font-weight: 600;\n font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;\n background: color-mix(in srgb, white 18%, transparent);\n border: 1px solid color-mix(in srgb, white 35%, transparent);\n border-radius: 4px;\n color: inherit;\n}\n\n@media (max-width: 640px) {\n .save-bar {\n left: 8px;\n right: 8px;\n bottom: 88px; /* push above the chat launcher on small screens */\n flex-direction: column;\n align-items: stretch;\n padding: 12px;\n }\n .save-bar-actions {\n justify-content: space-between;\n }\n .save-bar-kbd {\n display: none;\n }\n}\n\n/* ===========================\n Tests Tab \u2014 Action Bar + Drag/Remove\n =========================== */\n\n.tests-actionbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding: 12px 16px;\n margin-bottom: 16px;\n background: var(--test-surface);\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-md);\n}\n\n.tests-actionbar-text {\n display: flex;\n align-items: center;\n gap: 10px;\n flex-wrap: wrap;\n min-width: 0;\n}\n\n.tests-actionbar-text strong {\n font-size: 14px;\n color: var(--test-text);\n font-weight: 700;\n}\n\n.tests-actionbar-count {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 22px;\n height: 22px;\n padding: 0 8px;\n border-radius: 999px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n font-size: 12px;\n font-weight: 700;\n}\n\n.tests-actionbar-hint {\n font-size: 12px;\n color: var(--test-text-muted);\n}\n\n.tests-actionbar-actions {\n display: flex;\n gap: 8px;\n flex-shrink: 0;\n}\n\n/* Override the default test-item hover translate so drag transforms don't fight it. */\n.tests-list[cdk-drop-list] .test-item:hover,\n.tests-list .test-item.cdk-drag:hover {\n transform: none;\n}\n\n/* The whole row is draggable. .test-content keeps the click-to-open behavior. */\n.test-item.cdk-drag {\n position: relative;\n}\n\n.test-item .test-content {\n cursor: pointer;\n}\n\n/* Drag handle */\n.test-drag-handle {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 28px;\n border-radius: 4px;\n color: var(--test-text-muted);\n cursor: grab;\n flex-shrink: 0;\n transition: background 0.15s, color 0.15s;\n user-select: none;\n}\n\n.test-drag-handle:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n color: var(--test-primary);\n}\n\n.test-drag-handle:active,\n.cdk-drag-preview .test-drag-handle {\n cursor: grabbing;\n}\n\n/* Remove (X) button \u2014 hover-revealed */\n.test-remove-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border-radius: 50%;\n border: none;\n background: transparent;\n color: var(--test-text-muted);\n cursor: pointer;\n flex-shrink: 0;\n opacity: 0;\n transition: opacity 0.15s, background 0.15s, color 0.15s;\n}\n\n.test-item:hover .test-remove-btn,\n.test-remove-btn:focus-visible {\n opacity: 1;\n}\n\n.test-remove-btn:hover {\n background: color-mix(in srgb, var(--mj-status-error) 12%, transparent);\n color: var(--mj-status-error);\n}\n\n.test-chevron {\n cursor: pointer;\n}\n\n/* Inline remove-confirm */\n.test-remove-confirm {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 4px 8px 4px 12px;\n border-radius: 999px;\n background: color-mix(in srgb, var(--mj-status-error) 8%, var(--test-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 30%, transparent);\n flex-shrink: 0;\n}\n\n.test-remove-confirm-text {\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-status-error-text, var(--mj-status-error));\n}\n\n.test-remove-confirm-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 4px 10px;\n border-radius: 6px;\n border: 1px solid transparent;\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n font-family: inherit;\n transition: var(--test-transition);\n}\n\n.test-remove-confirm-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.test-remove-confirm-btn--danger {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse, white);\n}\n\n.test-remove-confirm-btn--danger:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-status-error) 88%, black);\n}\n\n.test-remove-confirm-btn--ghost {\n background: transparent;\n color: var(--test-text-secondary);\n border-color: var(--test-border);\n}\n\n.test-remove-confirm-btn--ghost:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n}\n\n/* CDK drag-drop visuals */\n.cdk-drag-preview {\n box-shadow: 0 12px 32px rgba(0, 0, 0, 0.25);\n border-radius: var(--test-radius-md);\n background: var(--test-surface);\n opacity: 0.95;\n}\n\n.cdk-drag-placeholder {\n opacity: 0;\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n border: 2px dashed var(--test-primary);\n border-radius: var(--test-radius-md);\n}\n\n.cdk-drag-placeholder * {\n visibility: hidden;\n}\n\n.cdk-drag-animating {\n transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);\n}\n\n.tests-list.cdk-drop-list-dragging .test-item:not(.cdk-drag-placeholder) {\n transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);\n}\n\n/* ===========================\n Add Tests Picker Dialog\n =========================== */\n\n.picker-backdrop {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.45);\n z-index: 200;\n animation: pickerFadeIn 180ms ease-out;\n backdrop-filter: blur(2px);\n}\n\n@keyframes pickerFadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.picker-dialog {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: min(720px, calc(100vw - 32px));\n max-height: min(80vh, 720px);\n z-index: 201;\n display: flex;\n flex-direction: column;\n background: var(--test-surface);\n border-radius: var(--test-radius-lg);\n box-shadow: 0 24px 64px rgba(0, 0, 0, 0.28);\n animation: pickerSlideUp 220ms cubic-bezier(0.16, 1, 0.3, 1);\n overflow: hidden;\n}\n\n@keyframes pickerSlideUp {\n from {\n opacity: 0;\n transform: translate(-50%, calc(-50% + 16px));\n }\n to {\n opacity: 1;\n transform: translate(-50%, -50%);\n }\n}\n\n.picker-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 18px 20px;\n border-bottom: 1px solid var(--test-border);\n}\n\n.picker-title {\n margin: 0;\n font-size: 16px;\n font-weight: 700;\n color: var(--test-text);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.picker-title i {\n color: var(--test-primary);\n}\n\n.picker-close {\n width: 32px;\n height: 32px;\n border-radius: 8px;\n border: none;\n background: transparent;\n color: var(--test-text-muted);\n cursor: pointer;\n font-size: 14px;\n transition: background 0.15s, color 0.15s;\n}\n\n.picker-close:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n}\n\n.picker-close:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.picker-search {\n position: relative;\n padding: 14px 20px 0 20px;\n}\n\n.picker-search-icon {\n position: absolute;\n top: 50%;\n left: 32px;\n transform: translateY(-30%);\n color: var(--test-text-muted);\n font-size: 13px;\n pointer-events: none;\n}\n\n.picker-search-input {\n width: 100%;\n padding: 10px 36px 10px 36px;\n border: 1px solid var(--test-border);\n border-radius: var(--test-radius-sm);\n background: var(--test-surface);\n font-size: 14px;\n color: var(--test-text);\n font-family: inherit;\n transition: var(--test-transition);\n}\n\n.picker-search-input:focus {\n outline: none;\n border-color: var(--test-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.picker-search-clear {\n position: absolute;\n top: 50%;\n right: 32px;\n transform: translateY(-30%);\n width: 22px;\n height: 22px;\n border-radius: 50%;\n border: none;\n background: transparent;\n color: var(--test-text-muted);\n cursor: pointer;\n font-size: 11px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.picker-search-clear:hover {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n}\n\n.picker-toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 20px;\n border-bottom: 1px solid var(--test-border);\n}\n\n.picker-toolbar-status {\n font-size: 12px;\n color: var(--test-text-secondary);\n}\n\n.picker-toolbar-status strong {\n color: var(--mj-brand-primary-hover);\n font-weight: 700;\n}\n\n.picker-toolbar-actions {\n display: flex;\n gap: 14px;\n}\n\n.picker-link-btn {\n border: none;\n background: transparent;\n color: var(--test-primary);\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n padding: 0;\n font-family: inherit;\n}\n\n.picker-link-btn:hover:not(:disabled) {\n text-decoration: underline;\n}\n\n.picker-link-btn:disabled {\n color: var(--test-text-muted);\n cursor: not-allowed;\n}\n\n.picker-body {\n flex: 1;\n overflow-y: auto;\n padding: 8px 12px;\n min-height: 200px;\n}\n\n.picker-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px;\n}\n\n.picker-list {\n list-style: none;\n padding: 0;\n margin: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.picker-row {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n border-radius: 8px;\n cursor: pointer;\n transition: background 0.12s, border-color 0.12s;\n border: 1px solid transparent;\n}\n\n.picker-row:hover {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n}\n\n.picker-row:focus-visible {\n outline: none;\n border-color: var(--test-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.picker-row--selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--test-surface));\n border-color: color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.picker-row--selected:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--test-surface));\n}\n\n.picker-check {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n border-radius: 5px;\n border: 1.5px solid var(--test-border);\n background: var(--test-surface);\n color: var(--mj-text-inverse, white);\n font-size: 11px;\n flex-shrink: 0;\n transition: background 0.12s, border-color 0.12s;\n}\n\n.picker-row--selected .picker-check {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.picker-row-main {\n flex: 1;\n min-width: 0;\n}\n\n.picker-row-name {\n font-size: 13px;\n font-weight: 600;\n color: var(--test-text);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.picker-row-desc {\n font-size: 12px;\n color: var(--test-text-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n margin-top: 2px;\n}\n\n.picker-row-meta {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-shrink: 0;\n}\n\n.picker-row-pill {\n display: inline-flex;\n align-items: center;\n padding: 2px 8px;\n border-radius: 999px;\n font-size: 10px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n background: var(--mj-bg-surface-sunken, var(--test-bg));\n color: var(--test-text-secondary);\n border: 1px solid var(--test-border);\n}\n\n.picker-row-pill--status[data-status=\"active\"] {\n background: color-mix(in srgb, var(--mj-status-success) 12%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n border-color: color-mix(in srgb, var(--mj-status-success) 30%, transparent);\n}\n\n.picker-row-pill--status[data-status=\"disabled\"] {\n background: var(--mj-bg-surface-sunken, var(--test-bg));\n color: var(--test-text-muted);\n}\n\n.picker-row-pill--status[data-status=\"pending\"] {\n background: color-mix(in srgb, var(--mj-status-warning) 12%, var(--mj-bg-surface));\n color: var(--mj-status-warning-text, var(--mj-status-warning));\n border-color: color-mix(in srgb, var(--mj-status-warning) 30%, transparent);\n}\n\n.picker-footer {\n display: flex;\n gap: 8px;\n padding: 14px 20px;\n border-top: 1px solid var(--test-border);\n background: var(--mj-bg-surface-sunken, var(--test-bg));\n}\n\n.picker-btn {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 9px 16px;\n font-size: 13px;\n font-weight: 600;\n border-radius: 8px;\n border: 1px solid transparent;\n cursor: pointer;\n font-family: inherit;\n transition: var(--test-transition);\n}\n\n.picker-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.picker-btn--primary {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse, white);\n border-color: var(--mj-brand-primary);\n}\n\n.picker-btn--primary:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover, var(--mj-brand-primary));\n}\n\n.picker-btn--ghost {\n background: transparent;\n color: var(--test-text-secondary);\n border-color: var(--test-border);\n}\n\n.picker-btn--ghost:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover, var(--mj-bg-surface-card));\n color: var(--test-text);\n}\n\n@media (max-width: 640px) {\n .picker-dialog {\n width: calc(100vw - 16px);\n max-height: calc(100vh - 32px);\n }\n .tests-actionbar {\n flex-direction: column;\n align-items: stretch;\n }\n .tests-actionbar-actions {\n justify-content: flex-end;\n }\n .test-remove-btn {\n opacity: 1; /* always visible on touch */\n }\n}\n\n/* Phone (375px): the action row wraps instead of running past the edge, the SHOW\n toggle takes its own line, and the breadcrumb wraps. (The tab strip is\n hidden on phones; the section picker replaces it.) */\n@media (max-width: 768px) {\n .header-actions {\n flex-wrap: wrap;\n }\n\n .header-actions app-evaluation-mode-toggle {\n flex-basis: 100%;\n }\n\n .breadcrumb ol {\n flex-wrap: wrap;\n }\n\n .breadcrumb li {\n min-width: 0;\n }\n}\n"] }]
|
|
5031
5051
|
}], null, { ChartContainer: [{
|
|
5032
5052
|
type: ViewChild,
|
|
5033
5053
|
args: ['chartContainer']
|