var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { BaseDashboard } from '@memberjunction/ng-shared';
import { RegisterClass } from '@memberjunction/global';
import { Subject, firstValueFrom } from 'rxjs';
import { debounceTime, takeUntil } from 'rxjs/operators';
import { buildTestingAgentContext, isValidTestingTab, isValidTestingStatusFilter, isValidTestingTimeRange, TESTING_TABS, TESTING_STATUS_FILTERS, TESTING_TIME_RANGES, } from './testing-agent-context';
import { validateStringParam } from '../shared/agent-tool-validation';
import { TestEngineBase } from '@memberjunction/testing-engine-base';
import * as i0 from "@angular/core";
import * as i1 from "@memberjunction/ng-testing";
import * as i2 from "./services/testing-instrumentation.service";
import * as i3 from "@memberjunction/ng-ui-components";
import * as i4 from "@memberjunction/ng-shared-generic";
import * as i5 from "./components/testing-dashboard-tab.component";
import * as i6 from "./components/testing-runs.component";
import * as i7 from "./components/testing-analytics.component";
import * as i8 from "./components/testing-review.component";
function TestingDashboardComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelement(0, "mj-stat-badge", 2);
} if (rf & 2) {
    const ctx_r0 = i0.ɵɵnextContext();
    i0.ɵɵproperty("Count", ctx_r0.ActiveRuns.length);
} }
function TestingDashboardComponent_Conditional_9_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 7);
    i0.ɵɵelement(1, "mj-loading", 9);
    i0.ɵɵelementEnd();
} }
function TestingDashboardComponent_Conditional_10_Conditional_0_Template(rf, ctx) { if (rf & 1) {
    const _r2 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "div", 10);
    i0.ɵɵelement(1, "i", 13);
    i0.ɵɵelementStart(2, "span", 14);
    i0.ɵɵtext(3);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(4, "span", 15);
    i0.ɵɵtext(5);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(6, "button", 16);
    i0.ɵɵlistener("click", function TestingDashboardComponent_Conditional_10_Conditional_0_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.OnViewActiveRun(ctx_r0.ActiveRuns[0])); });
    i0.ɵɵtext(7, "View");
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const ctx_r0 = i0.ɵɵnextContext(2);
    i0.ɵɵadvance(3);
    i0.ɵɵtextInterpolate2("", ctx_r0.ActiveRuns.length, " test", ctx_r0.ActiveRuns.length === 1 ? "" : "s", " running");
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate2("", ctx_r0.ActiveRuns[0].TestName, " \u2014 ", ctx_r0.ActiveRuns[0].Progress, "%");
} }
function TestingDashboardComponent_Conditional_10_Conditional_2_Template(rf, ctx) { if (rf & 1) {
    const _r3 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "app-testing-dashboard-tab", 17);
    i0.ɵɵlistener("stateChange", function TestingDashboardComponent_Conditional_10_Conditional_2_Template_app_testing_dashboard_tab_stateChange_0_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.onDashboardStateChange($event)); });
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const ctx_r0 = i0.ɵɵnextContext(2);
    i0.ɵɵproperty("initialState", ctx_r0.dashboardState)("HideToolbar", true);
} }
function TestingDashboardComponent_Conditional_10_Conditional_3_Template(rf, ctx) { if (rf & 1) {
    const _r4 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "app-testing-runs", 17);
    i0.ɵɵlistener("stateChange", function TestingDashboardComponent_Conditional_10_Conditional_3_Template_app_testing_runs_stateChange_0_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.onRunsStateChange($event)); });
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const ctx_r0 = i0.ɵɵnextContext(2);
    i0.ɵɵproperty("initialState", ctx_r0.runsState)("HideToolbar", true);
} }
function TestingDashboardComponent_Conditional_10_Conditional_4_Template(rf, ctx) { if (rf & 1) {
    const _r5 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "app-testing-analytics", 17);
    i0.ɵɵlistener("stateChange", function TestingDashboardComponent_Conditional_10_Conditional_4_Template_app_testing_analytics_stateChange_0_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.onAnalyticsStateChange($event)); });
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const ctx_r0 = i0.ɵɵnextContext(2);
    i0.ɵɵproperty("initialState", ctx_r0.analyticsState)("HideToolbar", true);
} }
function TestingDashboardComponent_Conditional_10_Conditional_5_Template(rf, ctx) { if (rf & 1) {
    const _r6 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "app-testing-review", 17);
    i0.ɵɵlistener("stateChange", function TestingDashboardComponent_Conditional_10_Conditional_5_Template_app_testing_review_stateChange_0_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.onReviewStateChange($event)); });
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const ctx_r0 = i0.ɵɵnextContext(2);
    i0.ɵɵproperty("initialState", ctx_r0.reviewState)("HideToolbar", true);
} }
function TestingDashboardComponent_Conditional_10_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵconditionalCreate(0, TestingDashboardComponent_Conditional_10_Conditional_0_Template, 8, 4, "div", 10);
    i0.ɵɵelementStart(1, "div", 11);
    i0.ɵɵconditionalCreate(2, TestingDashboardComponent_Conditional_10_Conditional_2_Template, 1, 2, "app-testing-dashboard-tab", 12);
    i0.ɵɵconditionalCreate(3, TestingDashboardComponent_Conditional_10_Conditional_3_Template, 1, 2, "app-testing-runs", 12);
    i0.ɵɵconditionalCreate(4, TestingDashboardComponent_Conditional_10_Conditional_4_Template, 1, 2, "app-testing-analytics", 12);
    i0.ɵɵconditionalCreate(5, TestingDashboardComponent_Conditional_10_Conditional_5_Template, 1, 2, "app-testing-review", 12);
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const ctx_r0 = i0.ɵɵnextContext();
    i0.ɵɵconditional(ctx_r0.ActiveRuns.length > 0 ? 0 : -1);
    i0.ɵɵadvance(2);
    i0.ɵɵconditional(ctx_r0.activeTab === "dashboard" && ctx_r0.hasVisited("dashboard") ? 2 : -1);
    i0.ɵɵadvance();
    i0.ɵɵconditional(ctx_r0.activeTab === "runs" && ctx_r0.hasVisited("runs") ? 3 : -1);
    i0.ɵɵadvance();
    i0.ɵɵconditional(ctx_r0.activeTab === "analytics" && ctx_r0.hasVisited("analytics") ? 4 : -1);
    i0.ɵɵadvance();
    i0.ɵɵconditional(ctx_r0.activeTab === "review" && ctx_r0.hasVisited("review") ? 5 : -1);
} }
function TestingDashboardComponent_Conditional_11_Template(rf, ctx) { if (rf & 1) {
    const _r7 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "mj-slide-panel", 18);
    i0.ɵɵlistener("Closed", function TestingDashboardComponent_Conditional_11_Template_mj_slide_panel_Closed_0_listener() { i0.ɵɵrestoreView(_r7); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.OnPanelClosed()); });
    i0.ɵɵelementStart(1, "app-test-run-dialog", 19);
    i0.ɵɵlistener("PanelClose", function TestingDashboardComponent_Conditional_11_Template_app_test_run_dialog_PanelClose_1_listener() { i0.ɵɵrestoreView(_r7); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.OnPanelClosed()); });
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const ctx_r0 = i0.ɵɵnextContext();
    i0.ɵɵproperty("Title", (ctx_r0.testingDialogService.PanelOptions == null ? null : ctx_r0.testingDialogService.PanelOptions.testId) ? "Test Execution" : "Run Test")("Resizable", true);
    i0.ɵɵadvance();
    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) ?? "test");
} }
let TestingDashboardComponent = class TestingDashboardComponent extends BaseDashboard {
    cdr;
    testingDialogService;
    executionService;
    instrumentationService;
    isLoading = false;
    activeTab = 'dashboard';
    selectedIndex = 0;
    // Active test runs from execution service
    ActiveRuns = [];
    // Latest run-instrumentation KPIs, used to build agent context. Null until the
    // first kpis$ emission arrives.
    latestKPIs = null;
    // The tab the agent tool-set was last registered for. Mode-scoping guard: the
    // tool surface differs per tab, so we only re-register on a tab transition
    // (mirrors the Data Explorer's `lastRegisteredToolMode`).
    lastRegisteredToolMode = null;
    // Component states
    dashboardState = null;
    runsState = null;
    analyticsState = null;
    reviewState = null;
    // Track visited tabs for lazy loading
    visitedTabs = new Set();
    // Navigation items
    navigationItems = ['dashboard', 'runs', 'analytics', 'review'];
    navigationConfig = [
        { text: 'Dashboard', icon: 'fa-solid fa-gauge-high', selected: false },
        { text: 'Runs', icon: 'fa-solid fa-play-circle', selected: false },
        { text: 'Analytics', icon: 'fa-solid fa-chart-bar', selected: false },
        { text: 'Review', icon: 'fa-solid fa-clipboard-check', selected: false }
    ];
    get Tabs() {
        return [
            { key: 'dashboard', label: 'Dashboard', icon: 'fa-solid fa-gauge-high' },
            {
                key: 'runs',
                label: 'Runs',
                icon: 'fa-solid fa-play-circle',
                badge: this.ActiveRuns.length > 0 ? this.ActiveRuns.length : null,
                badgeVariant: this.ActiveRuns.length > 0 ? 'warning' : 'default'
            },
            { key: 'analytics', label: 'Analytics', icon: 'fa-solid fa-chart-bar' },
            { key: 'review', label: 'Review', icon: 'fa-solid fa-clipboard-check' }
        ];
    }
    stateChangeSubject = new Subject();
    destroy$ = new Subject();
    constructor(cdr, testingDialogService, executionService, instrumentationService) {
        super();
        this.cdr = cdr;
        this.testingDialogService = testingDialogService;
        this.executionService = executionService;
        this.instrumentationService = instrumentationService;
        this.setupStateManagement();
        this.updateNavigationSelection();
    }
    async GetResourceDisplayName(data) {
        return 'Testing';
    }
    ngAfterViewInit() {
        this.visitedTabs.add(this.activeTab);
        this.updateNavigationSelection();
        this.emitStateChange();
        this.executionService.ActiveRuns$.pipe(takeUntil(this.destroy$)).subscribe(runs => {
            this.ActiveRuns = runs;
            this.emitAgentContext();
            this.cdr.markForCheck();
        });
        // Keep agent context in sync with the run-instrumentation KPIs (pass rate,
        // failures, cost, pending review, etc.).
        this.instrumentationService.kpis$.pipe(takeUntil(this.destroy$)).subscribe(kpis => {
            this.latestKPIs = kpis;
            this.emitAgentContext();
        });
        this.emitAgentContext();
        this.syncAgentToolsForMode();
        this.testingDialogService.PanelStateChanged$.pipe(takeUntil(this.destroy$)).subscribe((isOpen) => {
            console.log('[TestingDashboard] PanelStateChanged$:', isOpen, 'IsPanelOpen:', this.testingDialogService.IsPanelOpen);
            this.cdr.detectChanges();
        });
        this.cdr.detectChanges();
    }
    ngOnDestroy() {
        super.ngOnDestroy();
        this.destroy$.next();
        this.destroy$.complete();
        this.stateChangeSubject.complete();
    }
    onTabChange(tabId) {
        this.activeTab = tabId;
        const index = this.navigationItems.indexOf(tabId);
        this.selectedIndex = index >= 0 ? index : 0;
        this.updateNavigationSelection();
        this.visitedTabs.add(tabId);
        this.emitStateChange();
        this.emitAgentContext();
        this.syncAgentToolsForMode();
        this.cdr.markForCheck();
    }
    hasVisited(tabId) {
        return this.visitedTabs.has(tabId);
    }
    setupStateManagement() {
        this.stateChangeSubject.pipe(debounceTime(50), takeUntil(this.destroy$)).subscribe(state => {
            this.UserStateChanged.emit(state);
        });
    }
    emitStateChange() {
        const state = {
            activeTab: this.activeTab,
            dashboardState: (this.dashboardState || {}),
            runsState: (this.runsState || {}),
            analyticsState: (this.analyticsState || {}),
            reviewState: (this.reviewState || {})
        };
        this.stateChangeSubject.next(state);
    }
    onDashboardStateChange(state) {
        this.dashboardState = state;
        this.emitStateChange();
        this.emitAgentContext();
    }
    onRunsStateChange(state) {
        this.runsState = state;
        this.emitStateChange();
        this.emitAgentContext();
    }
    onAnalyticsStateChange(state) {
        this.analyticsState = state;
        this.emitStateChange();
        this.emitAgentContext();
    }
    onReviewStateChange(state) {
        this.reviewState = state;
        this.emitStateChange();
        this.emitAgentContext();
    }
    loadUserState(state) {
        if (state.activeTab) {
            this.activeTab = state.activeTab;
            const index = this.navigationItems.indexOf(state.activeTab);
            this.selectedIndex = index >= 0 ? index : 0;
            this.visitedTabs.add(state.activeTab);
            this.updateNavigationSelection();
        }
        if (state.dashboardState)
            this.dashboardState = state.dashboardState;
        if (state.runsState)
            this.runsState = state.runsState;
        if (state.analyticsState)
            this.analyticsState = state.analyticsState;
        if (state.reviewState)
            this.reviewState = state.reviewState;
        this.cdr.markForCheck();
    }
    initDashboard() {
        try {
            this.isLoading = true;
            this.instrumentationService.Provider = this.ProviderToUse;
        }
        catch (error) {
            console.error('Error initializing Testing dashboard:', error);
            this.Error.emit(new Error('Failed to initialize Testing dashboard. Please try again.'));
        }
        finally {
            this.isLoading = false;
        }
    }
    loadData() {
        if (this.Config?.userState) {
            setTimeout(() => {
                if (this.Config?.userState) {
                    this.loadUserState(this.Config.userState);
                }
            }, 0);
        }
        this.NotifyLoadComplete();
    }
    getCurrentTabLabel() {
        const tabIndex = this.navigationItems.indexOf(this.activeTab);
        return tabIndex >= 0 ? this.navigationConfig[tabIndex].text : 'Testing Dashboard';
    }
    OnPanelClosed() {
        this.testingDialogService.ClosePanel();
        this.cdr.markForCheck();
    }
    OnViewActiveRun(run) {
        this.testingDialogService.OpenTestPanel(run.TestId);
        this.cdr.markForCheck();
    }
    OnViewRunningTestFromTab(testId) {
        this.testingDialogService.OpenTestPanel(testId);
        this.cdr.detectChanges();
    }
    updateNavigationSelection() {
        this.navigationConfig.forEach((item, index) => {
            item.selected = this.navigationItems[index] === this.activeTab;
        });
    }
    // ================================================================
    // AI Agent context + client tools
    // ================================================================
    /**
     * Report the current Testing surface state to the AI agent (async chat agent
     * + realtime co-agent). Re-emitted on tab switch, active-run changes, child
     * state changes, and on every kpis$ refresh. Always publishes the KPI slice;
     * additionally publishes the detailed slice for the ACTIVE tab (selected run
     * id+NAME, visible run names, analytics breakdowns, review queue depth, etc.)
     * via the pure {@link buildTestingAgentContext} helper.
     */
    emitAgentContext() {
        const k = this.latestKPIs;
        const tab = isValidTestingTab(this.activeTab) ? this.activeTab : 'dashboard';
        this.navigationService.SetAgentContext(this, buildTestingAgentContext({
            ActiveTab: tab,
            ActiveRunCount: this.ActiveRuns.length,
            TotalTestsRun: k?.totalTestRuns ?? 0,
            PassedCount: this.computePassedCount(k),
            PassRate: k?.passRateThisMonth ?? 0,
            FailureCount: k?.failedTests ?? 0,
            SkippedCount: k?.skippedTests ?? 0,
            ActiveTestCount: this.computeActiveTestCount(k),
            AverageRunDuration: k?.averageDuration ?? 0,
            TotalTestCost: k?.totalCostThisMonth ?? 0,
            PendingReviewCount: k?.testsPendingReview ?? 0,
            PassRateTrend: k?.passRateTrend ?? 0,
            ActiveRunNames: this.ActiveRuns.map(r => r.TestName),
            Runs: tab === 'runs' ? this.buildRunsSurfaceState() : undefined,
            Analytics: tab === 'analytics' ? this.buildAnalyticsSurfaceState() : undefined,
            Review: tab === 'review' ? this.buildReviewSurfaceState() : undefined,
        }));
    }
    /** Derive the passing-run count from the KPI snapshot (total − failed − skipped, floored at 0). */
    computePassedCount(k) {
        if (!k)
            return 0;
        return Math.max(0, k.totalTestRuns - k.failedTests - k.skippedTests);
    }
    /** Active-test-catalog count: prefer the KPI value, fall back to the engine cache. */
    computeActiveTestCount(k) {
        if (k && k.totalTestsActive > 0) {
            return k.totalTestsActive;
        }
        try {
            return TestEngineBase.Instance.Tests.filter(t => t.Status === 'Active').length;
        }
        catch {
            return k?.totalTestsActive ?? 0;
        }
    }
    /** Read the Runs-surface slice from the child component's reported state. */
    buildRunsSurfaceState() {
        const s = this.runsState ?? {};
        const status = s['status'];
        const timeRange = s['timeRange'];
        return {
            StatusFilter: isValidTestingStatusFilter(status) ? status : 'all',
            TimeRange: isValidTestingTimeRange(timeRange) ? timeRange : 'month',
            SearchText: typeof s['searchText'] === 'string' ? s['searchText'] : '',
            VisibleRunCount: typeof s['visibleRunCount'] === 'number' ? s['visibleRunCount'] : 0,
            VisibleRunNames: this.toStringArray(s['visibleRunNames']),
            SelectedRunId: typeof s['selectedRunId'] === 'string' ? s['selectedRunId'] : null,
            SelectedRunName: typeof s['selectedRunName'] === 'string' ? s['selectedRunName'] : null,
            DetailPanelOpen: s['detailPanelOpen'] === true,
        };
    }
    /** Read the Analytics-surface slice from the child component's reported state. */
    buildAnalyticsSurfaceState() {
        const s = this.analyticsState ?? {};
        return {
            SelectedDays: typeof s['selectedDays'] === 'number' ? s['selectedDays'] : 30,
            TopFailingTests: this.toStringArray(s['topFailingTests']),
            SlowestTests: this.toStringArray(s['slowestTests']),
            MostExpensiveTests: this.toStringArray(s['mostExpensiveTests']),
            VersionCount: typeof s['versionCount'] === 'number' ? s['versionCount'] : 0,
        };
    }
    /** Read the Review-surface slice from the child component's reported state. */
    buildReviewSurfaceState() {
        const s = this.reviewState ?? {};
        const view = s['viewMode'];
        return {
            View: (view === 'queue' || view === 'history') ? view : 'queue',
            PendingCount: typeof s['pendingCount'] === 'number' ? s['pendingCount'] : (this.latestKPIs?.testsPendingReview ?? 0),
            ReviewedCount: typeof s['reviewedCount'] === 'number' ? s['reviewedCount'] : 0,
            AverageHumanRating: typeof s['averageHumanRating'] === 'number' ? s['averageHumanRating'] : 0,
            AgreementRate: typeof s['agreementRate'] === 'number' ? s['agreementRate'] : 0,
            HistorySearchText: typeof s['historySearchText'] === 'string' ? s['historySearchText'] : '',
        };
    }
    /** Coerce an unknown value into a string[] (tolerant of non-array / mixed input). */
    toStringArray(value) {
        if (!Array.isArray(value))
            return [];
        return value.filter((v) => typeof v === 'string');
    }
    // ----------------------------------------------------------------
    // Mode-scoped client tools
    // ----------------------------------------------------------------
    /**
     * Register the agent tool-set appropriate for the active tab.
     *
     * MODE-SCOPING (mirrors the Data Explorer's `syncAgentToolsForMode`): the tool
     * surface differs per tab — at Analytics the agent gets the analytics window
     * tool but not run-selection; on Runs it gets run filter/search/select/open;
     * on Review it gets the queue view + feedback tools. `SetAgentClientTools`
     * replaces the registered set wholesale, so we only re-register on a tab
     * transition (guarded by {@link lastRegisteredToolMode}).
     *
     * 🔒 SAFETY BOUNDARY: every tab exposes ONLY navigation, filter, refresh,
     * read-only, run-SELECTION (open the detail panel / open the run's record —
     * both read-only navigation), and the bounded human-feedback write. Test-
     * EXECUTING operations (StartNewTest / RerunTest) are intentionally NEVER
     * exposed on ANY tab — running a test has real side effects (cost, execution,
     * state changes) and must remain a deliberate user action from the UI.
     * SelectTestRun and SubmitTestFeedback are safe: the former is read-only
     * navigation, the latter a bounded evaluation write on an existing run. Do not
     * add execute/run tools without an explicit user-confirmation design.
     */
    syncAgentToolsForMode() {
        const tab = isValidTestingTab(this.activeTab) ? this.activeTab : 'dashboard';
        if (this.lastRegisteredToolMode === tab) {
            return;
        }
        this.lastRegisteredToolMode = tab;
        this.navigationService.SetAgentClientTools(this, this.buildToolsForMode(tab));
    }
    /** Compose the tool list for a given tab: common tools + per-tab tools. */
    buildToolsForMode(tab) {
        const tools = [...this.buildCommonTools()];
        switch (tab) {
            case 'runs':
                tools.push(...this.buildRunsTools());
                break;
            case 'analytics':
                tools.push(...this.buildAnalyticsTools());
                break;
            case 'review':
                tools.push(...this.buildReviewTools());
                break;
            case 'dashboard':
            default:
                // Dashboard (overview) tab: common navigation/refresh/read-only tools only.
                break;
        }
        return tools;
    }
    /** Tools available on EVERY tab: tab switch, refresh, time-range, read-only lookup. */
    buildCommonTools() {
        return [
            {
                Name: 'SwitchTestingTab',
                Description: `Switch the Testing dashboard to a specific tab. One of: ${TESTING_TABS.join(', ')}.`,
                ParameterSchema: { type: 'object', properties: { tab: { type: 'string', enum: [...TESTING_TABS] } }, required: ['tab'] },
                Handler: async (params) => {
                    const tab = params['tab'];
                    if (!isValidTestingTab(tab)) {
                        return { Success: false, ErrorMessage: `Invalid tab. Expected one of: ${TESTING_TABS.join(', ')}.` };
                    }
                    this.onTabChange(tab);
                    return { Success: true };
                },
            },
            {
                Name: 'RefreshTestingData',
                Description: 'Refresh all Testing dashboard data (KPIs, runs, analytics) from the server.',
                ParameterSchema: { type: 'object', properties: {} },
                Handler: async () => {
                    this.instrumentationService.refresh();
                    return { Success: true };
                },
            },
            {
                Name: 'FilterTestsByTimeRange',
                Description: `Set the active time range for all Testing data (KPIs, runs, analytics, review). One of: ${TESTING_TIME_RANGES.join(', ')}.`,
                ParameterSchema: { type: 'object', properties: { range: { type: 'string', enum: [...TESTING_TIME_RANGES] } }, required: ['range'] },
                Handler: async (params) => {
                    const range = params['range'];
                    if (!isValidTestingTimeRange(range)) {
                        return { Success: false, ErrorMessage: `Invalid range. Expected one of: ${TESTING_TIME_RANGES.join(', ')}.` };
                    }
                    this.instrumentationService.setDateRangeByName(range);
                    return { Success: true };
                },
            },
            {
                Name: 'GetTestRunDetails',
                Description: 'Get read-only details for a single test run by its ID (name, status, score, cost, duration, human feedback).',
                ParameterSchema: { type: 'object', properties: { runId: { type: 'string' } }, required: ['runId'] },
                Handler: async (params) => {
                    const validated = validateStringParam(params['runId'], 'runId');
                    if (!validated.ok) {
                        return validated.result;
                    }
                    return this.getTestRunDetails(validated.value);
                },
            },
        ];
    }
    /** Runs-tab tools: status filter, search, select-run, open-run (all read-only nav). */
    buildRunsTools() {
        return [
            {
                Name: 'FilterTestsByStatus',
                Description: `Filter the test runs list by execution status. One of: ${TESTING_STATUS_FILTERS.join(', ')}.`,
                ParameterSchema: { type: 'object', properties: { status: { type: 'string', enum: [...TESTING_STATUS_FILTERS] } }, required: ['status'] },
                Handler: async (params) => {
                    const status = params['status'];
                    if (!isValidTestingStatusFilter(status)) {
                        return { Success: false, ErrorMessage: `Invalid status. Expected one of: ${TESTING_STATUS_FILTERS.join(', ')}.` };
                    }
                    this.onTabChange('runs');
                    this.instrumentationService.setRunsFilterIntent({ status: status });
                    return { Success: true };
                },
            },
            {
                Name: 'SearchTests',
                Description: 'Search/filter the test runs list by test name (substring match). Pass an empty string to clear.',
                ParameterSchema: { type: 'object', properties: { query: { type: 'string' } }, required: ['query'] },
                Handler: async (params) => {
                    const validated = validateStringParam(params['query'], 'query');
                    if (!validated.ok) {
                        return validated.result;
                    }
                    this.onTabChange('runs');
                    this.instrumentationService.setRunsFilterIntent({ searchText: validated.value });
                    return { Success: true };
                },
            },
            {
                Name: 'SelectTestRun',
                // 🔒 SAFE: read-only navigation. Selecting opens the run's detail panel;
                // `open: true` additionally opens the run's record in the entity
                // workspace. Neither executes or re-runs a test.
                Description: 'Select a test run by its ID to open its detail panel in the Runs view. Set open=true to also open the run record in the entity workspace. Read-only navigation only.',
                ParameterSchema: {
                    type: 'object',
                    properties: {
                        runId: { type: 'string' },
                        open: { type: 'boolean' },
                    },
                    required: ['runId'],
                },
                Handler: async (params) => {
                    return this.selectTestRun(params);
                },
            },
        ];
    }
    /** Analytics-tab tools: read-only window narrowing (delegates to the shared time-range). */
    buildAnalyticsTools() {
        return [
            {
                Name: 'SetAnalyticsTimeRange',
                Description: `Set the analytics trailing window. One of: ${TESTING_TIME_RANGES.join(', ')}. Updates the trend, pass-rate, and breakdown charts.`,
                ParameterSchema: { type: 'object', properties: { range: { type: 'string', enum: [...TESTING_TIME_RANGES] } }, required: ['range'] },
                Handler: async (params) => {
                    const range = params['range'];
                    if (!isValidTestingTimeRange(range)) {
                        return { Success: false, ErrorMessage: `Invalid range. Expected one of: ${TESTING_TIME_RANGES.join(', ')}.` };
                    }
                    this.onTabChange('analytics');
                    this.instrumentationService.setDateRangeByName(range);
                    return { Success: true };
                },
            },
        ];
    }
    /** Review-tab tools: the bounded human-feedback write + select-run for review. */
    buildReviewTools() {
        return [
            {
                Name: 'SubmitTestFeedback',
                // 🔒 SAFE: bounded write that is part of the normal evaluation flow —
                // records a human rating/correctness on an existing test run. Not a
                // test-execution side effect.
                Description: 'Submit human evaluation feedback for an existing test run: a 1-10 rating, whether the result is correct, and optional comments.',
                ParameterSchema: {
                    type: 'object',
                    properties: {
                        runId: { type: 'string' },
                        rating: { type: 'number', minimum: 1, maximum: 10 },
                        isCorrect: { type: 'boolean' },
                        comments: { type: 'string' },
                    },
                    required: ['runId', 'rating', 'isCorrect'],
                },
                Handler: async (params) => {
                    return this.submitTestFeedback(params);
                },
            },
            {
                Name: 'SelectTestRun',
                // 🔒 SAFE: read-only navigation (opens the run on the Runs surface so the
                // user can review/feedback it there).
                Description: 'Open a test run by its ID for review (switches to the Runs view and opens its detail panel). Set open=true to also open the run record. Read-only navigation only.',
                ParameterSchema: {
                    type: 'object',
                    properties: {
                        runId: { type: 'string' },
                        open: { type: 'boolean' },
                    },
                    required: ['runId'],
                },
                Handler: async (params) => {
                    return this.selectTestRun(params);
                },
            },
        ];
    }
    /**
     * Validate a run-selection request and publish it as a {@link RunSelectionIntent}
     * for the Runs surface to act on. Switches to the Runs tab so the detail panel
     * is visible. Read-only navigation — no test execution.
     */
    async selectTestRun(params) {
        const validated = validateStringParam(params['runId'], 'runId');
        if (!validated.ok) {
            return validated.result;
        }
        const runId = validated.value.trim();
        if (!runId) {
            return { Success: false, ErrorMessage: 'runId must be a non-empty string.' };
        }
        // Confirm the run exists in the current date range before navigating.
        const lookup = await this.getTestRunDetails(runId);
        if (!lookup.Success) {
            return { Success: false, ErrorMessage: lookup.ErrorMessage };
        }
        const open = params['open'] === true;
        this.onTabChange('runs');
        this.instrumentationService.setRunSelectionIntent(runId, open);
        return { Success: true };
    }
    /** Read-only lookup of a single test run from the current run-instrumentation cache. */
    async getTestRunDetails(runId) {
        const runs = await firstValueFrom(this.instrumentationService.testRunsWithFeedback$);
        const run = runs.find(r => r.id === runId);
        if (!run) {
            return { Success: false, ErrorMessage: `No test run found with ID "${runId}" in the current date range.` };
        }
        return {
            Success: true,
            Data: {
                ID: run.id,
                TestName: run.testName,
                Status: run.status,
                Score: run.score,
                Cost: run.cost,
                Duration: run.duration,
                RunDateTime: run.runDateTime,
                HasHumanFeedback: run.hasHumanFeedback,
                HumanRating: run.humanRating,
                HumanIsCorrect: run.humanIsCorrect,
                HumanComments: run.humanComments,
            },
        };
    }
    /** Validate and submit human feedback for an existing test run. */
    async submitTestFeedback(params) {
        const runIdValidated = validateStringParam(params['runId'], 'runId');
        if (!runIdValidated.ok) {
            return runIdValidated.result;
        }
        const rawRating = params['rating'];
        const rating = typeof rawRating === 'number' ? rawRating : Number(rawRating);
        if (!Number.isFinite(rating) || rating < 1 || rating > 10) {
            return { Success: false, ErrorMessage: 'rating must be a number between 1 and 10.' };
        }
        const isCorrect = params['isCorrect'];
        if (typeof isCorrect !== 'boolean') {
            return { Success: false, ErrorMessage: 'isCorrect must be a boolean.' };
        }
        const rawComments = params['comments'];
        const comments = typeof rawComments === 'string' ? rawComments : '';
        const ok = await this.instrumentationService.submitFeedback(runIdValidated.value, rating, isCorrect, comments);
        return ok
            ? { Success: true }
            : { Success: false, ErrorMessage: 'Failed to submit feedback for the specified test run.' };
    }
    static ɵfac = function TestingDashboardComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || TestingDashboardComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i1.TestingDialogService), i0.ɵɵdirectiveInject(i1.TestingExecutionService), i0.ɵɵdirectiveInject(i2.TestingInstrumentationService)); };
    static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: TestingDashboardComponent, selectors: [["mj-testing-dashboard"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 12, vars: 7, consts: [["Title", "Testing", "Icon", "fa-solid fa-vial-circle-check", "Subtitle", "Evaluate AI agents, workflows, and system components"], ["meta", ""], ["Icon", "fa-solid fa-spinner fa-spin", "Label", "running", "Variant", "running", 3, "Count"], ["actions", ""], ["toolbar", ""], [3, "TabChange", "Tabs", "ActiveKey"], [3, "Flex"], [1, "loading-container"], ["Mode", "slide", 3, "Title", "Resizable"], ["text", "Loading Testing Dashboard...", "size", "large"], [1, "active-runs-banner"], [1, "dashboard-content"], [3, "initialState", "HideToolbar"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "active-runs-count"], [1, "active-runs-detail"], [1, "active-runs-view-btn", 3, "click"], [3, "stateChange", "initialState", "HideToolbar"], ["Mode", "slide", 3, "Closed", "Title", "Resizable"], [3, "PanelClose", "PanelMode", "selectedTestId", "selectedSuiteId", "runMode"]], template: function TestingDashboardComponent_Template(rf, ctx) { if (rf & 1) {
            i0.ɵɵelementStart(0, "mj-page-layout")(1, "mj-page-header", 0)(2, "div", 1);
            i0.ɵɵconditionalCreate(3, TestingDashboardComponent_Conditional_3_Template, 1, 1, "mj-stat-badge", 2);
            i0.ɵɵelementEnd();
            i0.ɵɵelementStart(4, "div", 3);
            i0.ɵɵelement(5, "app-evaluation-mode-toggle");
            i0.ɵɵelementEnd();
            i0.ɵɵelementStart(6, "div", 4)(7, "mj-tab-nav", 5);
            i0.ɵɵlistener("TabChange", function TestingDashboardComponent_Template_mj_tab_nav_TabChange_7_listener($event) { return ctx.onTabChange($event); });
            i0.ɵɵelementEnd()()();
            i0.ɵɵelementStart(8, "mj-page-body", 6);
            i0.ɵɵconditionalCreate(9, TestingDashboardComponent_Conditional_9_Template, 2, 0, "div", 7);
            i0.ɵɵconditionalCreate(10, TestingDashboardComponent_Conditional_10_Template, 6, 5);
            i0.ɵɵelementEnd();
            i0.ɵɵconditionalCreate(11, TestingDashboardComponent_Conditional_11_Template, 2, 6, "mj-slide-panel", 8);
            i0.ɵɵelementEnd();
        } if (rf & 2) {
            i0.ɵɵadvance(3);
            i0.ɵɵconditional(ctx.ActiveRuns.length > 0 ? 3 : -1);
            i0.ɵɵadvance(4);
            i0.ɵɵproperty("Tabs", ctx.Tabs)("ActiveKey", ctx.activeTab);
            i0.ɵɵadvance();
            i0.ɵɵproperty("Flex", true);
            i0.ɵɵadvance();
            i0.ɵɵconditional(ctx.isLoading ? 9 : -1);
            i0.ɵɵadvance();
            i0.ɵɵconditional(!ctx.isLoading ? 10 : -1);
            i0.ɵɵadvance();
            i0.ɵɵconditional(ctx.testingDialogService.IsPanelOpen ? 11 : -1);
        } }, dependencies: [i3.MJPageHeaderComponent, i3.MJPageLayoutComponent, i3.MJPageBodyComponent, i3.MJTabNavComponent, i3.MJStatBadgeComponent, i1.TestRunDialogComponent, i1.EvaluationModeToggleComponent, i3.MjSlidePanelComponent, i4.LoadingComponent, i5.TestingDashboardTabComponent, i6.TestingRunsComponent, i7.TestingAnalyticsComponent, i8.TestingReviewComponent], styles: ["\n\n\n\n\n\n\n\n.loading-container[_ngcontent-%COMP%] {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  height: 100%;\n  background: var(--mj-bg-surface);\n  backdrop-filter: blur(8px);\n}\n\n.loading-content[_ngcontent-%COMP%] {\n  text-align: center;\n}\n\n.loading-spinner[_ngcontent-%COMP%] {\n  display: inline-block;\n  position: relative;\n  width: 80px;\n  height: 80px;\n}\n\n.spinner-ring[_ngcontent-%COMP%] {\n  box-sizing: border-box;\n  display: block;\n  position: absolute;\n  width: 64px;\n  height: 64px;\n  margin: 8px;\n  border: 8px solid var(--mj-brand-primary);\n  border-radius: 50%;\n  animation: _ngcontent-%COMP%_spinner-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;\n  border-color: var(--mj-brand-primary) transparent transparent transparent;\n}\n\n.spinner-ring[_ngcontent-%COMP%]:nth-child(1) {\n  animation-delay: -0.45s;\n}\n\n.spinner-ring[_ngcontent-%COMP%]:nth-child(2) {\n  animation-delay: -0.3s;\n}\n\n.spinner-ring[_ngcontent-%COMP%]:nth-child(3) {\n  animation-delay: -0.15s;\n}\n\n@keyframes _ngcontent-%COMP%_spinner-ring {\n  0% {\n    transform: rotate(0deg);\n  }\n  100% {\n    transform: rotate(360deg);\n  }\n}\n\n.loading-text[_ngcontent-%COMP%] {\n  margin-top: 20px;\n  font-size: 16px;\n  color: var(--mj-text-muted);\n  font-weight: 500;\n}\n\n.dashboard-content[_ngcontent-%COMP%] {\n  flex: 1;\n  min-height: 0;\n  overflow: hidden;\n}\n\n\n\n.active-runs-banner[_ngcontent-%COMP%] {\n  display: flex;\n  align-items: center;\n  gap: 12px;\n  padding: 10px 20px;\n  background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n  border-bottom: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, var(--mj-border-default));\n  font-size: 13px;\n  color: var(--mj-text-primary);\n}\n\n.active-runs-banner[_ngcontent-%COMP%]   i[_ngcontent-%COMP%] {\n  color: var(--mj-brand-primary);\n}\n\n.active-runs-count[_ngcontent-%COMP%] {\n  font-weight: 600;\n}\n\n.active-runs-detail[_ngcontent-%COMP%] {\n  color: var(--mj-text-secondary);\n  flex: 1;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.active-runs-view-btn[_ngcontent-%COMP%] {\n  padding: 4px 14px;\n  border: 1px solid var(--mj-brand-primary);\n  border-radius: 6px;\n  background: transparent;\n  color: var(--mj-brand-primary);\n  font-size: 12px;\n  font-weight: 600;\n  cursor: pointer;\n  white-space: nowrap;\n  transition: background 0.2s;\n}\n\n.active-runs-view-btn[_ngcontent-%COMP%]:hover {\n  background: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n}\n\n\n\n@media (max-width: 768px) {\n  .testing-dashboard-nav[_ngcontent-%COMP%] {\n    padding: 0 8px;\n    overflow-x: auto;\n  }\n\n  .nav-item[_ngcontent-%COMP%] {\n    padding: 12px 16px;\n    gap: 8px;\n  }\n\n  .nav-item[_ngcontent-%COMP%]   span[_ngcontent-%COMP%] {\n    font-size: 11px;\n  }\n\n  .nav-item[_ngcontent-%COMP%]   i[_ngcontent-%COMP%] {\n    font-size: 18px;\n  }\n\n  .active-runs-banner[_ngcontent-%COMP%] {\n    flex-wrap: wrap;\n    padding: 8px 12px;\n    gap: 6px;\n  }\n\n  .active-runs-detail[_ngcontent-%COMP%] {\n    width: 100%;\n    order: 3;\n  }\n}\n\n@media (max-width: 480px) {\n  .nav-item[_ngcontent-%COMP%]   span[_ngcontent-%COMP%] {\n    display: none;\n  }\n\n  .nav-item[_ngcontent-%COMP%] {\n    padding: 12px 14px;\n  }\n}"], changeDetection: 0 });
};
TestingDashboardComponent = __decorate([
    RegisterClass(BaseDashboard, 'TestingDashboard')
], TestingDashboardComponent);
export { TestingDashboardComponent };
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TestingDashboardComponent, [{
        type: Component,
        args: [{ standalone: false, selector: 'mj-testing-dashboard', changeDetection: ChangeDetectionStrategy.OnPush, template: "<mj-page-layout>\n  <mj-page-header\n    Title=\"Testing\"\n    Icon=\"fa-solid fa-vial-circle-check\"\n    Subtitle=\"Evaluate AI agents, workflows, and system components\">\n    <div meta>\n      @if (ActiveRuns.length > 0) {\n        <mj-stat-badge\n          Icon=\"fa-solid fa-spinner fa-spin\"\n          [Count]=\"ActiveRuns.length\"\n          Label=\"running\"\n          Variant=\"running\">\n        </mj-stat-badge>\n      }\n    </div>\n    <div actions>\n      <app-evaluation-mode-toggle></app-evaluation-mode-toggle>\n    </div>\n    <div toolbar>\n      <mj-tab-nav\n        [Tabs]=\"Tabs\"\n        [ActiveKey]=\"activeTab\"\n        (TabChange)=\"onTabChange($any($event))\">\n      </mj-tab-nav>\n    </div>\n  </mj-page-header>\n\n  <mj-page-body [Flex]=\"true\">\n  @if (isLoading) {\n    <div class=\"loading-container\">\n      <mj-loading text=\"Loading Testing Dashboard...\" size=\"large\"></mj-loading>\n    </div>\n  }\n\n  @if (!isLoading) {\n    <!-- Active Runs Banner (in-body so it doesn't crowd the page-header) -->\n    @if (ActiveRuns.length > 0) {\n      <div class=\"active-runs-banner\">\n        <i class=\"fa-solid fa-spinner fa-spin\"></i>\n        <span class=\"active-runs-count\">{{ ActiveRuns.length }} test{{ ActiveRuns.length === 1 ? '' : 's' }} running</span>\n        <span class=\"active-runs-detail\">{{ ActiveRuns[0].TestName }} &mdash; {{ ActiveRuns[0].Progress }}%</span>\n        <button class=\"active-runs-view-btn\" (click)=\"OnViewActiveRun(ActiveRuns[0])\">View</button>\n      </div>\n    }\n\n    <div class=\"dashboard-content\">\n      @if (activeTab === 'dashboard' && hasVisited('dashboard')) {\n        <app-testing-dashboard-tab\n          [initialState]=\"dashboardState\"\n          [HideToolbar]=\"true\"\n          (stateChange)=\"onDashboardStateChange($event)\"\n        ></app-testing-dashboard-tab>\n      }\n\n      @if (activeTab === 'runs' && hasVisited('runs')) {\n        <app-testing-runs\n          [initialState]=\"runsState\"\n          [HideToolbar]=\"true\"\n          (stateChange)=\"onRunsStateChange($event)\"\n        ></app-testing-runs>\n      }\n\n      @if (activeTab === 'analytics' && hasVisited('analytics')) {\n        <app-testing-analytics\n          [initialState]=\"analyticsState\"\n          [HideToolbar]=\"true\"\n          (stateChange)=\"onAnalyticsStateChange($event)\"\n        ></app-testing-analytics>\n      }\n\n      @if (activeTab === 'review' && hasVisited('review')) {\n        <app-testing-review\n          [initialState]=\"reviewState\"\n          [HideToolbar]=\"true\"\n          (stateChange)=\"onReviewStateChange($event)\"\n        ></app-testing-review>\n      }\n    </div>\n  }\n  </mj-page-body>\n\n  <!-- Slide Panel for Test Execution -->\n  @if (testingDialogService.IsPanelOpen) {\n    <mj-slide-panel\n      Mode=\"slide\"\n      [Title]=\"testingDialogService.PanelOptions?.testId ? 'Test Execution' : 'Run Test'\"\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 ?? 'test'\"\n        (PanelClose)=\"OnPanelClosed()\">\n      </app-test-run-dialog>\n    </mj-slide-panel>\n  }\n</mj-page-layout>\n", styles: ["/* ============================================\n   Testing Dashboard - Premium Design System\n   Based on AI Dashboard patterns\n   ============================================ */\n\n/* Loading State */\n.loading-container {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  height: 100%;\n  background: var(--mj-bg-surface);\n  backdrop-filter: blur(8px);\n}\n\n.loading-content {\n  text-align: center;\n}\n\n.loading-spinner {\n  display: inline-block;\n  position: relative;\n  width: 80px;\n  height: 80px;\n}\n\n.spinner-ring {\n  box-sizing: border-box;\n  display: block;\n  position: absolute;\n  width: 64px;\n  height: 64px;\n  margin: 8px;\n  border: 8px solid var(--mj-brand-primary);\n  border-radius: 50%;\n  animation: spinner-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;\n  border-color: var(--mj-brand-primary) transparent transparent transparent;\n}\n\n.spinner-ring:nth-child(1) {\n  animation-delay: -0.45s;\n}\n\n.spinner-ring:nth-child(2) {\n  animation-delay: -0.3s;\n}\n\n.spinner-ring:nth-child(3) {\n  animation-delay: -0.15s;\n}\n\n@keyframes spinner-ring {\n  0% {\n    transform: rotate(0deg);\n  }\n  100% {\n    transform: rotate(360deg);\n  }\n}\n\n.loading-text {\n  margin-top: 20px;\n  font-size: 16px;\n  color: var(--mj-text-muted);\n  font-weight: 500;\n}\n\n.dashboard-content {\n  flex: 1;\n  min-height: 0;\n  overflow: hidden;\n}\n\n/* Active Runs Banner */\n.active-runs-banner {\n  display: flex;\n  align-items: center;\n  gap: 12px;\n  padding: 10px 20px;\n  background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n  border-bottom: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, var(--mj-border-default));\n  font-size: 13px;\n  color: var(--mj-text-primary);\n}\n\n.active-runs-banner i {\n  color: var(--mj-brand-primary);\n}\n\n.active-runs-count {\n  font-weight: 600;\n}\n\n.active-runs-detail {\n  color: var(--mj-text-secondary);\n  flex: 1;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.active-runs-view-btn {\n  padding: 4px 14px;\n  border: 1px solid var(--mj-brand-primary);\n  border-radius: 6px;\n  background: transparent;\n  color: var(--mj-brand-primary);\n  font-size: 12px;\n  font-weight: 600;\n  cursor: pointer;\n  white-space: nowrap;\n  transition: background 0.2s;\n}\n\n.active-runs-view-btn:hover {\n  background: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n}\n\n/* Responsive */\n@media (max-width: 768px) {\n  .testing-dashboard-nav {\n    padding: 0 8px;\n    overflow-x: auto;\n  }\n\n  .nav-item {\n    padding: 12px 16px;\n    gap: 8px;\n  }\n\n  .nav-item span {\n    font-size: 11px;\n  }\n\n  .nav-item i {\n    font-size: 18px;\n  }\n\n  .active-runs-banner {\n    flex-wrap: wrap;\n    padding: 8px 12px;\n    gap: 6px;\n  }\n\n  .active-runs-detail {\n    width: 100%;\n    order: 3;\n  }\n}\n\n@media (max-width: 480px) {\n  .nav-item span {\n    display: none;\n  }\n\n  .nav-item {\n    padding: 12px 14px;\n  }\n}\n"] }]
    }], () => [{ type: i0.ChangeDetectorRef }, { type: i1.TestingDialogService }, { type: i1.TestingExecutionService }, { type: i2.TestingInstrumentationService }], null); })();
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TestingDashboardComponent, { className: "TestingDashboardComponent", filePath: "src/Testing/testing-dashboard.component.ts", lineNumber: 57 }); })();
//# sourceMappingURL=testing-dashboard.component.js.map