"""HTML reporter for security scan results"""

import html
from datetime import datetime
from typing import Any, Dict, List, Optional

from aisentry.models.finding import Finding, Severity
from aisentry.models.result import ScanResult, TestResult, UnifiedResult
from aisentry.models.vulnerability import LiveVulnerability

from .base_reporter import BaseReporter

# Import audit models (optional - may not be installed)
try:
    from aisentry.audit.models import AuditResult
    from aisentry.audit.models import CategoryScore as AuditCategoryScore
    AUDIT_AVAILABLE = True
except ImportError:
    AUDIT_AVAILABLE = False
    AuditResult = None
    AuditCategoryScore = None


class HTMLReporter(BaseReporter):
    """
    Generates HTML reports for security scan and test results.

    Produces self-contained HTML with embedded CSS styling.
    """

    # Severity color mapping
    SEVERITY_COLORS = {
        Severity.CRITICAL: "#dc3545",
        Severity.HIGH: "#fd7e14",
        Severity.MEDIUM: "#ffc107",
        Severity.LOW: "#17a2b8",
        Severity.INFO: "#6c757d",
    }

    def __init__(self, verbose: bool = False):
        super().__init__(verbose=verbose)

    def generate_scan_report(self, result: ScanResult) -> str:
        """Generate HTML report for static scan results."""
        return self._render_html(
            title="aisentry Static Scan Report",
            content=self._render_scan_content(result),
            report_type="static",
        )

    def generate_test_report(self, result: TestResult) -> str:
        """Generate HTML report for live test results."""
        return self._render_html(
            title="aisentry Live Test Report",
            content=self._render_test_content(result),
            report_type="live",
        )

    def generate_unified_report(self, result: UnifiedResult) -> str:
        """Generate HTML report combining static and live results."""
        return self._render_html(
            title="aisentry Unified Report",
            content=self._render_unified_content(result),
            report_type="unified",
        )

    def generate_scan_with_audit_report(
        self, scan_result: ScanResult, audit_result: Optional[Any] = None
    ) -> str:
        """
        Generate HTML report with tabbed interface combining scan and audit results.

        Args:
            scan_result: Static scan result with findings
            audit_result: Optional audit result with security posture

        Returns:
            HTML string with tabbed interface
        """
        return self._render_html(
            title="aisentry Report",
            content=self._render_tabbed_content(scan_result, audit_result),
            report_type="tabbed",
        )

    def _render_html(self, title: str, content: str, report_type: str) -> str:
        """Render complete HTML document."""
        return f"""<!DOCTYPE html>
<html lang="en" data-theme="light">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{html.escape(title)}</title>
    <style>
        {self._get_css()}
    </style>
</head>
<body>
    <div class="container">
        <header>
            <div class="header-content">
                <div class="header-left">
                    <div class="logo">
                        <svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                            <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>
                            <path d="M9 12l2 2 4-4"/>
                        </svg>
                    </div>
                    <div>
                        <h1>{html.escape(title)}</h1>
                        <p class="generated">Generated: {datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")} UTC</p>
                    </div>
                </div>
                <button class="theme-toggle" onclick="toggleTheme()" title="Toggle dark mode">
                    <svg class="sun-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                        <circle cx="12" cy="12" r="5"/>
                        <path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/>
                    </svg>
                    <svg class="moon-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                        <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
                    </svg>
                </button>
            </div>
        </header>
        {content}
        <footer>
            <p>Generated by <strong>aisentry CLI</strong> | <a href="https://aisentry.co" target="_blank">aisentry.co</a></p>
        </footer>
    </div>
    <script>
        {self._get_javascript()}
    </script>
</body>
</html>"""

    def _get_css(self) -> str:
        """Get embedded CSS styles."""
        return """
        /* CSS Variables for theming */
        :root, [data-theme="light"] {
            --bg-primary: #f8fafc;
            --bg-secondary: #ffffff;
            --bg-tertiary: #f1f5f9;
            --text-primary: #0f172a;
            --text-secondary: #475569;
            --text-muted: #94a3b8;
            --border-color: #e2e8f0;
            --accent-primary: #f97316;
            --accent-secondary: #ea580c;
            --accent-gradient: linear-gradient(135deg, #f97316 0%, #ea580c 100%);
            --success: #10b981;
            --warning: #f59e0b;
            --danger: #ef4444;
            --info: #3b82f6;
            --card-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
            --card-shadow-hover: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
        }

        [data-theme="dark"] {
            --bg-primary: #0f172a;
            --bg-secondary: #1e293b;
            --bg-tertiary: #334155;
            --text-primary: #f1f5f9;
            --text-secondary: #cbd5e1;
            --text-muted: #64748b;
            --border-color: #334155;
            --card-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3);
            --card-shadow-hover: 0 10px 15px -3px rgba(0, 0, 0, 0.4);
        }

        * { box-sizing: border-box; margin: 0; padding: 0; }

        body {
            font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            background: var(--bg-primary);
            color: var(--text-primary);
            line-height: 1.6;
            transition: background 0.3s, color 0.3s;
        }

        .container { max-width: 1280px; margin: 0 auto; padding: 24px; }

        /* Header */
        header {
            background: var(--accent-gradient);
            color: white;
            padding: 24px 32px;
            border-radius: 16px;
            margin-bottom: 24px;
            box-shadow: 0 10px 40px rgba(249, 115, 22, 0.3);
        }
        .header-content {
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        .header-left {
            display: flex;
            align-items: center;
            gap: 16px;
        }
        .logo {
            background: rgba(255,255,255,0.2);
            padding: 8px;
            border-radius: 12px;
        }
        header h1 { font-size: 1.5em; font-weight: 700; margin-bottom: 2px; }
        .generated { opacity: 0.9; font-size: 0.85em; }

        /* Theme Toggle */
        .theme-toggle {
            background: rgba(255,255,255,0.2);
            border: none;
            padding: 10px;
            border-radius: 10px;
            cursor: pointer;
            color: white;
            transition: all 0.3s;
        }
        .theme-toggle:hover {
            background: rgba(255,255,255,0.3);
            transform: scale(1.05);
        }
        [data-theme="light"] .moon-icon { display: none; }
        [data-theme="dark"] .sun-icon { display: none; }

        /* Cards */
        .summary-card {
            background: var(--bg-secondary);
            border-radius: 16px;
            padding: 24px;
            margin-bottom: 24px;
            box-shadow: var(--card-shadow);
            transition: box-shadow 0.3s, transform 0.3s;
        }
        .summary-card:hover {
            box-shadow: var(--card-shadow-hover);
        }
        .summary-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 20px;
        }
        .metric {
            text-align: center;
            padding: 20px;
            background: var(--bg-tertiary);
            border-radius: 12px;
            transition: transform 0.3s;
        }
        .metric:hover { transform: translateY(-2px); }
        .metric-value {
            font-size: 2.5em;
            font-weight: 800;
            background: var(--accent-gradient);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
        }
        .metric-label { color: var(--text-secondary); font-size: 0.9em; margin-top: 4px; }

        /* Circular Score Gauge */
        .score-gauge {
            position: relative;
            width: 120px;
            height: 120px;
            margin: 0 auto 12px;
        }
        .score-gauge svg {
            transform: rotate(-90deg);
        }
        .score-gauge-bg {
            fill: none;
            stroke: var(--bg-tertiary);
            stroke-width: 8;
        }
        .score-gauge-fill {
            fill: none;
            stroke-width: 8;
            stroke-linecap: round;
            transition: stroke-dashoffset 1s ease-out;
        }
        .score-gauge-text {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            font-size: 1.8em;
            font-weight: 800;
        }
        .score-high .score-gauge-fill { stroke: var(--success); }
        .score-medium .score-gauge-fill { stroke: var(--warning); }
        .score-low .score-gauge-fill { stroke: var(--danger); }
        .score-high .score-gauge-text { color: var(--success); }
        .score-medium .score-gauge-text { color: var(--warning); }
        .score-low .score-gauge-text { color: var(--danger); }

        .section { margin-bottom: 32px; }
        .section h2 {
            color: var(--text-primary);
            font-size: 1.3em;
            font-weight: 700;
            padding-bottom: 12px;
            margin-bottom: 16px;
            border-bottom: 3px solid var(--accent-primary);
            display: inline-block;
        }
        .section h3 {
            color: var(--text-primary);
            font-size: 1.1em;
            font-weight: 600;
            margin-bottom: 16px;
        }

        /* Findings & Vulnerabilities */
        .finding, .vulnerability {
            background: var(--bg-secondary);
            border-radius: 12px;
            padding: 20px;
            margin-bottom: 12px;
            box-shadow: var(--card-shadow);
            border-left: 4px solid;
            transition: all 0.3s;
        }
        .finding:hover, .vulnerability:hover {
            box-shadow: var(--card-shadow-hover);
            transform: translateX(4px);
        }
        .severity-critical { border-left-color: #ef4444; }
        .severity-high { border-left-color: #f97316; }
        .severity-medium { border-left-color: #f59e0b; }
        .severity-low { border-left-color: #3b82f6; }
        .severity-info { border-left-color: #64748b; }

        .finding-header, .vuln-header {
            display: flex;
            justify-content: space-between;
            align-items: flex-start;
            gap: 12px;
            margin-bottom: 12px;
            flex-wrap: wrap;
        }
        .finding-title, .vuln-title {
            font-weight: 600;
            font-size: 1.05em;
            color: var(--text-primary);
        }

        /* Badges with icons */
        .badge {
            padding: 5px 12px;
            border-radius: 20px;
            font-size: 0.75em;
            font-weight: 600;
            text-transform: uppercase;
            color: white;
            display: inline-flex;
            align-items: center;
            gap: 4px;
        }
        .badge::before { font-size: 0.9em; }
        .badge-critical { background: linear-gradient(135deg, #ef4444, #dc2626); }
        .badge-critical::before { content: "🔴"; }
        .badge-high { background: linear-gradient(135deg, #f97316, #ea580c); }
        .badge-high::before { content: "🟠"; }
        .badge-medium { background: linear-gradient(135deg, #f59e0b, #d97706); color: #1e293b; }
        .badge-medium::before { content: "🟡"; }
        .badge-low { background: linear-gradient(135deg, #3b82f6, #2563eb); }
        .badge-low::before { content: "🔵"; }
        .badge-info { background: linear-gradient(135deg, #64748b, #475569); }
        .badge-info::before { content: "⚪"; }

        .code-block {
            background: #1e293b;
            color: #e2e8f0;
            padding: 16px;
            border-radius: 10px;
            overflow-x: auto;
            font-family: 'JetBrains Mono', 'Fira Code', 'Monaco', monospace;
            font-size: 0.85em;
            margin: 12px 0;
            border: 1px solid var(--border-color);
        }
        .location {
            color: var(--text-muted);
            font-size: 0.85em;
            margin-bottom: 8px;
            font-family: monospace;
        }
        .description {
            margin: 12px 0;
            color: var(--text-secondary);
            line-height: 1.7;
        }
        .remediation {
            background: linear-gradient(135deg, rgba(249, 115, 22, 0.1), rgba(234, 88, 12, 0.05));
            border: 1px solid rgba(249, 115, 22, 0.2);
            padding: 16px;
            border-radius: 10px;
            margin-top: 12px;
        }
        [data-theme="dark"] .remediation {
            background: linear-gradient(135deg, rgba(249, 115, 22, 0.15), rgba(234, 88, 12, 0.1));
        }
        .remediation-title {
            font-weight: 600;
            color: var(--accent-primary);
            margin-bottom: 6px;
            display: flex;
            align-items: center;
            gap: 6px;
        }
        .remediation-title::before { content: "💡"; }

        .detector-card {
            background: var(--bg-secondary);
            border-radius: 12px;
            padding: 16px 20px;
            margin-bottom: 12px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            box-shadow: var(--card-shadow);
            transition: all 0.3s;
        }
        .detector-card:hover {
            box-shadow: var(--card-shadow-hover);
            transform: translateY(-2px);
        }
        .detector-info h3 { font-size: 1em; margin-bottom: 4px; color: var(--text-primary); }
        .detector-stats { display: flex; gap: 24px; }
        .stat { text-align: center; }
        .stat-value { font-weight: 700; font-size: 1.3em; color: var(--accent-primary); }
        .stat-label { font-size: 0.75em; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.5px; }

        /* Animated Progress Bar */
        .progress-bar {
            height: 8px;
            background: var(--bg-tertiary);
            border-radius: 4px;
            overflow: hidden;
            margin-top: 8px;
        }
        .progress-fill {
            height: 100%;
            background: var(--accent-gradient);
            border-radius: 4px;
            animation: progressFill 1s ease-out forwards;
            transform-origin: left;
        }
        @keyframes progressFill {
            from { transform: scaleX(0); }
            to { transform: scaleX(1); }
        }

        footer {
            text-align: center;
            padding: 24px;
            color: var(--text-muted);
            font-size: 0.9em;
            border-top: 1px solid var(--border-color);
            margin-top: 32px;
        }
        footer a {
            color: var(--accent-primary);
            text-decoration: none;
            font-weight: 500;
        }
        footer a:hover { text-decoration: underline; }

        .severity-breakdown {
            display: flex;
            gap: 10px;
            flex-wrap: wrap;
            margin-top: 10px;
        }
        .severity-item {
            display: flex;
            align-items: center;
            gap: 5px;
            padding: 5px 10px;
            background: #f8f9fa;
            border-radius: 4px;
        }
        .severity-dot {
            width: 10px;
            height: 10px;
            border-radius: 50%;
        }

        /* Filter Toolbar - Modern Sticky Design */
        .filter-toolbar {
            position: sticky;
            top: 0;
            z-index: 100;
            background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
            border-radius: 12px;
            padding: 16px 20px;
            margin-bottom: 20px;
            box-shadow: 0 4px 20px rgba(0,0,0,0.15);
        }
        .filter-toolbar-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 12px;
        }
        .filter-toolbar-title {
            color: white;
            font-size: 0.9em;
            font-weight: 600;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        .filter-toolbar-title svg {
            width: 18px;
            height: 18px;
        }
        .filter-stats-badge {
            background: rgba(255,255,255,0.15);
            color: white;
            padding: 4px 12px;
            border-radius: 20px;
            font-size: 0.85em;
        }
        .filter-stats-badge strong {
            color: #60a5fa;
        }
        .filter-sections {
            display: flex;
            flex-wrap: wrap;
            gap: 20px;
            align-items: flex-start;
        }
        .filter-section {
            flex: 1;
            min-width: 180px;
        }
        .filter-section-label {
            color: rgba(255,255,255,0.7);
            font-size: 0.75em;
            text-transform: uppercase;
            letter-spacing: 0.5px;
            margin-bottom: 8px;
            display: flex;
            align-items: center;
            justify-content: space-between;
        }
        .filter-section-actions {
            font-size: 0.9em;
        }
        .filter-section-actions a {
            color: #60a5fa;
            text-decoration: none;
            margin-left: 8px;
        }
        .filter-section-actions a:hover {
            text-decoration: underline;
        }
        .filter-chips {
            display: flex;
            flex-wrap: wrap;
            gap: 6px;
        }
        .filter-chip {
            display: inline-flex;
            align-items: center;
            gap: 4px;
            padding: 6px 12px;
            border-radius: 20px;
            font-size: 0.8em;
            font-weight: 500;
            cursor: pointer;
            transition: all 0.2s ease;
            border: none;
            user-select: none;
        }
        .filter-chip.severity-chip {
            background: rgba(255,255,255,0.1);
            color: rgba(255,255,255,0.6);
        }
        .filter-chip.severity-chip.active[data-value="CRITICAL"] {
            background: #dc3545;
            color: white;
        }
        .filter-chip.severity-chip.active[data-value="HIGH"] {
            background: #fd7e14;
            color: white;
        }
        .filter-chip.severity-chip.active[data-value="MEDIUM"] {
            background: #ffc107;
            color: #333;
        }
        .filter-chip.severity-chip.active[data-value="LOW"] {
            background: #17a2b8;
            color: white;
        }
        .filter-chip.severity-chip.active[data-value="INFO"] {
            background: #6c757d;
            color: white;
        }
        .filter-chip.category-chip {
            background: rgba(255,255,255,0.1);
            color: rgba(255,255,255,0.6);
        }
        .filter-chip.category-chip.active {
            background: #667eea;
            color: white;
        }
        .filter-chip:hover {
            transform: translateY(-1px);
            box-shadow: 0 2px 8px rgba(0,0,0,0.2);
        }
        .filter-chip .chip-count {
            font-size: 0.85em;
            opacity: 0.8;
        }
        .filter-search-box {
            flex: 1;
            min-width: 200px;
        }
        .filter-search-input {
            width: 100%;
            padding: 10px 14px;
            border: 2px solid rgba(255,255,255,0.1);
            border-radius: 8px;
            background: rgba(255,255,255,0.05);
            color: white;
            font-size: 0.9em;
            transition: all 0.2s;
        }
        .filter-search-input::placeholder {
            color: rgba(255,255,255,0.4);
        }
        .filter-search-input:focus {
            outline: none;
            border-color: #667eea;
            background: rgba(255,255,255,0.1);
        }
        .filter-reset-btn {
            background: rgba(255,255,255,0.1);
            border: none;
            color: white;
            padding: 8px 16px;
            border-radius: 6px;
            font-size: 0.85em;
            cursor: pointer;
            transition: all 0.2s;
            white-space: nowrap;
        }
        .filter-reset-btn:hover {
            background: rgba(255,255,255,0.2);
        }

        /* Hidden class for filtered items */
        .finding.filtered-out,
        .vulnerability.filtered-out {
            display: none !important;
        }

        /* No results message */
        .no-results {
            text-align: center;
            padding: 60px 20px;
            color: #666;
            background: white;
            border-radius: 12px;
            box-shadow: 0 2px 8px rgba(0,0,0,0.08);
        }
        .no-results-icon {
            font-size: 3em;
            margin-bottom: 15px;
        }
        .no-results h3 {
            color: #333;
            margin-bottom: 8px;
        }

        /* Tab Navigation - Pill Style */
        .tab-navigation {
            display: flex;
            background: var(--bg-secondary);
            border-radius: 16px;
            padding: 6px;
            box-shadow: var(--card-shadow);
            margin-bottom: 0;
            gap: 6px;
        }
        .tab-btn {
            flex: 1;
            padding: 14px 24px;
            border: none;
            background: transparent;
            font-size: 0.95em;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.3s ease;
            border-radius: 12px;
            color: var(--text-secondary);
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 10px;
        }
        .tab-btn::before {
            font-size: 1.1em;
        }
        .tab-btn[data-tab="vulnerabilities"]::before { content: "🛡️"; }
        .tab-btn[data-tab="security-posture"]::before { content: "📊"; }
        .tab-btn:hover {
            background: var(--bg-tertiary);
            color: var(--text-primary);
        }
        .tab-btn.active {
            background: var(--accent-gradient);
            color: white;
            box-shadow: 0 4px 12px rgba(249, 115, 22, 0.3);
        }
        .tab-btn .tab-badge {
            background: var(--bg-tertiary);
            color: var(--text-secondary);
            padding: 3px 10px;
            border-radius: 20px;
            font-size: 0.8em;
            font-weight: 600;
        }
        .tab-btn.active .tab-badge {
            background: rgba(255,255,255,0.25);
            color: white;
        }
        .tab-content {
            display: none;
            background: var(--bg-secondary);
            border-radius: 16px;
            padding: 24px;
            box-shadow: var(--card-shadow);
            margin-top: 12px;
            margin-bottom: 24px;
            animation: fadeIn 0.3s ease;
        }
        .tab-content.active {
            display: block;
        }
        @keyframes fadeIn {
            from { opacity: 0; transform: translateY(10px); }
            to { opacity: 1; transform: translateY(0); }
        }

        /* Audit-specific styles */
        .audit-summary {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
            gap: 16px;
            margin-bottom: 24px;
        }
        .audit-metric {
            text-align: center;
            padding: 24px 20px;
            background: var(--bg-tertiary);
            border-radius: 16px;
            transition: all 0.3s;
            border: 1px solid var(--border-color);
        }
        .audit-metric:hover {
            transform: translateY(-4px);
            box-shadow: var(--card-shadow);
        }
        .audit-metric-value {
            font-size: 2.5em;
            font-weight: 800;
            background: var(--accent-gradient);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
        }
        .audit-metric-label {
            color: var(--text-secondary);
            font-size: 0.85em;
            margin-top: 6px;
            font-weight: 500;
        }
        .maturity-badge {
            display: inline-flex;
            align-items: center;
            gap: 6px;
            padding: 6px 14px;
            border-radius: 20px;
            font-size: 0.85em;
            font-weight: 600;
            margin-top: 10px;
        }
        .maturity-badge::before { font-size: 0.9em; }
        .maturity-initial { background: linear-gradient(135deg, #fee2e2, #fecaca); color: #dc2626; }
        .maturity-initial::before { content: "⚠️"; }
        .maturity-developing { background: linear-gradient(135deg, #ffedd5, #fed7aa); color: #ea580c; }
        .maturity-developing::before { content: "🔄"; }
        .maturity-defined { background: linear-gradient(135deg, #fef3c7, #fde68a); color: #d97706; }
        .maturity-defined::before { content: "📋"; }
        .maturity-managed { background: linear-gradient(135deg, #d1fae5, #a7f3d0); color: #059669; }
        .maturity-managed::before { content: "✅"; }
        .maturity-optimizing { background: linear-gradient(135deg, #cffafe, #a5f3fc); color: #0891b2; }
        .maturity-optimizing::before { content: "🚀"; }

        .category-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
            gap: 20px;
            margin-top: 20px;
        }
        .category-card {
            background: var(--bg-tertiary);
            border-radius: 16px;
            border: 1px solid var(--border-color);
            transition: all 0.3s;
            overflow: hidden;
        }
        .category-card:hover {
            box-shadow: var(--card-shadow);
        }
        .category-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 20px;
            cursor: pointer;
            user-select: none;
            transition: background 0.2s;
        }
        .category-header:hover {
            background: var(--bg-secondary);
        }
        .category-header-left {
            display: flex;
            align-items: center;
            gap: 12px;
        }
        .category-name {
            font-weight: 600;
            color: var(--text-primary);
            font-size: 1.05em;
        }
        .category-score {
            font-weight: 800;
            color: var(--accent-primary);
            font-size: 1.2em;
        }
        .accordion-icon {
            width: 20px;
            height: 20px;
            transition: transform 0.3s ease;
            color: var(--text-muted);
        }
        .category-card.open .accordion-icon {
            transform: rotate(180deg);
        }
        .category-progress {
            height: 4px;
            background: var(--border-color);
            overflow: hidden;
        }
        .category-progress-fill {
            height: 100%;
            background: var(--accent-gradient);
            animation: progressFill 1s ease-out forwards;
            transform-origin: left;
        }
        .category-content {
            max-height: 0;
            overflow: hidden;
            transition: max-height 0.3s ease-out;
        }
        .category-card.open .category-content {
            max-height: 2000px;
            transition: max-height 0.5s ease-in;
        }
        .control-list {
            list-style: none;
            padding: 0 20px 20px;
        }
        .control-item {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 10px 0;
            border-bottom: 1px solid var(--border-color);
        }
        .control-item:last-child {
            border-bottom: none;
        }
        .control-name {
            font-size: 0.9em;
            color: var(--text-secondary);
        }
        .control-status {
            font-size: 0.75em;
            padding: 4px 12px;
            border-radius: 20px;
            font-weight: 600;
            display: inline-flex;
            align-items: center;
            gap: 4px;
        }
        .control-status::before { font-size: 0.85em; }
        .status-detected { background: linear-gradient(135deg, #d1fae5, #a7f3d0); color: #059669; }
        .status-detected::before { content: "✓"; }
        .status-missing { background: linear-gradient(135deg, #fee2e2, #fecaca); color: #dc2626; }
        .status-missing::before { content: "✗"; }
        .status-partial { background: linear-gradient(135deg, #fef3c7, #fde68a); color: #d97706; }
        .status-partial::before { content: "~"; }
        .category-stats {
            display: flex;
            gap: 16px;
            padding: 12px 20px;
            background: var(--bg-secondary);
            border-top: 1px solid var(--border-color);
            font-size: 0.75rem;
            color: var(--text-muted);
        }
        .stat-item {
            display: flex;
            align-items: center;
            gap: 4px;
        }
        .stat-dot {
            width: 8px;
            height: 8px;
            border-radius: 50%;
        }
        .stat-dot.detected { background: #059669; }
        .stat-dot.partial { background: #d97706; }
        .stat-dot.missing { background: #dc2626; }
        .section-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin: 20px 0 16px;
        }
        .section-header h3 {
            margin: 0;
            color: var(--text-primary);
            border-bottom: 2px solid var(--accent-primary);
            padding-bottom: 8px;
        }
        .expand-toggle {
            font-size: 0.8rem;
            color: var(--accent-primary);
            cursor: pointer;
            padding: 4px 12px;
            border: 1px solid var(--accent-primary);
            border-radius: 6px;
            background: var(--bg-secondary);
            transition: all 0.2s;
        }
        .expand-toggle:hover {
            background: var(--accent-primary);
            color: white;
        }

        .recommendations-section {
            margin-top: 32px;
        }
        .recommendations-section h3 {
            color: var(--text-primary);
            font-size: 1.15em;
            font-weight: 700;
            margin-bottom: 16px;
            padding-bottom: 10px;
            border-bottom: 3px solid var(--accent-primary);
            display: inline-block;
        }
        .rec-list {
            display: flex;
            flex-direction: column;
            gap: 12px;
        }
        .rec-item {
            background: var(--bg-tertiary);
            border-radius: 12px;
            padding: 18px;
            border-left: 4px solid;
            transition: all 0.3s;
        }
        .rec-item:hover {
            transform: translateX(4px);
            box-shadow: var(--card-shadow);
        }
        .rec-critical { border-color: #ef4444; }
        .rec-high { border-color: #f97316; }
        .rec-medium { border-color: #f59e0b; }
        .rec-low { border-color: #3b82f6; }
        .rec-header {
            display: flex;
            justify-content: space-between;
            align-items: flex-start;
            gap: 12px;
            margin-bottom: 10px;
            flex-wrap: wrap;
        }
        .rec-title {
            font-weight: 600;
            color: var(--text-primary);
            line-height: 1.4;
        }
        .rec-priority {
            font-size: 0.7em;
            padding: 4px 10px;
            border-radius: 20px;
            font-weight: 700;
            text-transform: uppercase;
            letter-spacing: 0.5px;
        }
        .priority-critical { background: linear-gradient(135deg, #fee2e2, #fecaca); color: #dc2626; }
        .priority-high { background: linear-gradient(135deg, #ffedd5, #fed7aa); color: #ea580c; }
        .priority-medium { background: linear-gradient(135deg, #fef3c7, #fde68a); color: #d97706; }
        .priority-low { background: linear-gradient(135deg, #dbeafe, #bfdbfe); color: #2563eb; }
        .rec-description {
            color: var(--text-secondary);
            font-size: 0.9em;
            line-height: 1.6;
        }

        /* Combined score display */
        .combined-score-section {
            background: var(--accent-gradient);
            border-radius: 20px;
            padding: 28px;
            margin-bottom: 24px;
            color: white;
            box-shadow: 0 10px 40px rgba(249, 115, 22, 0.3);
        }
        .combined-score-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
            gap: 20px;
            text-align: center;
        }
        .combined-metric {
            padding: 20px;
            background: rgba(255,255,255,0.15);
            border-radius: 16px;
            backdrop-filter: blur(10px);
            transition: all 0.3s;
        }
        .combined-metric:hover {
            background: rgba(255,255,255,0.25);
            transform: translateY(-4px);
        }
        .combined-metric-value {
            font-size: 2.8em;
            font-weight: 800;
        }
        .combined-metric-label {
            font-size: 0.85em;
            opacity: 0.95;
            margin-top: 6px;
            font-weight: 500;
        }

        /* Severity Filter Buttons */
        .severity-filter-btn {
            padding: 10px 18px;
            border: 2px solid var(--border-color);
            border-radius: 25px;
            background: var(--bg-secondary);
            color: var(--text-secondary);
            font-size: 0.9em;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.3s ease;
            display: inline-flex;
            align-items: center;
            gap: 6px;
        }
        .severity-filter-btn::before {
            font-size: 0.9em;
        }
        .severity-filter-btn[data-severity="all"]::before { content: "📋"; }
        .severity-filter-btn[data-severity="critical"]::before { content: "🔴"; }
        .severity-filter-btn[data-severity="high"]::before { content: "🟠"; }
        .severity-filter-btn[data-severity="medium"]::before { content: "🟡"; }
        .severity-filter-btn[data-severity="low"]::before { content: "🔵"; }
        .severity-filter-btn[data-severity="info"]::before { content: "⚪"; }
        .severity-filter-btn:hover {
            border-color: var(--accent-primary);
            color: var(--accent-primary);
            transform: translateY(-2px);
        }
        .severity-filter-btn.active {
            background: var(--accent-gradient);
            border-color: transparent;
            color: white;
            box-shadow: 0 4px 12px rgba(249, 115, 22, 0.3);
        }
        .severity-filter-btn[data-severity="critical"].active {
            background: linear-gradient(135deg, #ef4444, #dc2626);
            box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3);
        }
        .severity-filter-btn[data-severity="high"].active {
            background: linear-gradient(135deg, #f97316, #ea580c);
            box-shadow: 0 4px 12px rgba(249, 115, 22, 0.3);
        }
        .severity-filter-btn[data-severity="medium"].active {
            background: linear-gradient(135deg, #f59e0b, #d97706);
            color: #1e293b;
            box-shadow: 0 4px 12px rgba(245, 158, 11, 0.3);
        }
        .severity-filter-btn[data-severity="low"].active {
            background: linear-gradient(135deg, #3b82f6, #2563eb);
            box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);
        }
        .severity-filter-btn[data-severity="info"].active {
            background: linear-gradient(135deg, #64748b, #475569);
            box-shadow: 0 4px 12px rgba(100, 116, 139, 0.3);
        }
        .filter-count {
            opacity: 0.85;
            font-weight: 500;
        }

        /* Hidden items for pagination */
        .rec-hidden, .finding-hidden {
            display: none !important;
        }
        .rec-filtered, .finding-filtered {
            display: none !important;
        }

        /* Load More Button */
        .load-more-btn {
            padding: 14px 36px;
            background: var(--accent-gradient);
            border: none;
            border-radius: 30px;
            color: white;
            font-size: 1em;
            font-weight: 700;
            cursor: pointer;
            transition: all 0.3s ease;
            box-shadow: 0 6px 20px rgba(249, 115, 22, 0.35);
            display: inline-flex;
            align-items: center;
            gap: 8px;
        }
        .load-more-btn::before {
            content: "↓";
            font-size: 1.1em;
        }
        .load-more-btn:hover {
            transform: translateY(-3px);
            box-shadow: 0 8px 25px rgba(249, 115, 22, 0.45);
        }
        .load-more-btn:active {
            transform: translateY(-1px);
        }
        .load-more-btn:disabled {
            opacity: 0.5;
            cursor: not-allowed;
            transform: none;
            box-shadow: none;
        }
        #remaining-count, #findings-remaining-count {
            opacity: 0.9;
            font-weight: 500;
        }
        """

    def _render_scan_content(self, result: ScanResult) -> str:
        """Render static scan result content."""
        score_class = self._get_score_class(result.overall_score)
        severity_breakdown = self._get_severity_breakdown(result.findings)

        content = f"""
        <div class="summary-card">
            <div class="summary-grid">
                <div class="metric">
                    <div class="score-circle {score_class}">{result.overall_score:.0f}</div>
                    <div class="metric-label">Security Score</div>
                </div>
                <div class="metric">
                    <div class="metric-value">{result.files_scanned}</div>
                    <div class="metric-label">Files Scanned</div>
                </div>
                <div class="metric">
                    <div class="metric-value">{len(result.findings)}</div>
                    <div class="metric-label">Issues Found</div>
                </div>
                <div class="metric">
                    <div class="metric-value">{result.confidence*100:.0f}%</div>
                    <div class="metric-label">Confidence</div>
                </div>
            </div>
            <div class="severity-breakdown">
                {self._render_severity_items(severity_breakdown)}
            </div>
        </div>

        <div class="section">
            <h2>Target: {html.escape(result.target_path)}</h2>
            <p>Scan duration: {result.duration_seconds:.2f} seconds</p>
        </div>
        """

        if result.category_scores:
            content += self._render_category_scores(result.category_scores)

        if result.findings:
            content += self._render_findings(result.findings)

        return content

    def _render_test_content(self, result: TestResult) -> str:
        """Render live test result content."""
        score_class = self._get_score_class(result.overall_score)
        pass_rate = result.tests_passed / max(result.tests_run, 1) * 100
        severity_breakdown = self._get_vuln_severity_breakdown(result.vulnerabilities)

        content = f"""
        <div class="summary-card">
            <div class="summary-grid">
                <div class="metric">
                    <div class="score-circle {score_class}">{result.overall_score:.0f}</div>
                    <div class="metric-label">Security Score</div>
                </div>
                <div class="metric">
                    <div class="metric-value">{result.tests_run}</div>
                    <div class="metric-label">Tests Run</div>
                </div>
                <div class="metric">
                    <div class="metric-value">{pass_rate:.0f}%</div>
                    <div class="metric-label">Pass Rate</div>
                </div>
                <div class="metric">
                    <div class="metric-value">{len(result.vulnerabilities)}</div>
                    <div class="metric-label">Vulnerabilities</div>
                </div>
            </div>
            <div class="severity-breakdown">
                {self._render_severity_items(severity_breakdown)}
            </div>
        </div>

        <div class="section">
            <h2>Model: {html.escape(result.provider)} / {html.escape(result.model)}</h2>
            <p>Mode: {html.escape(result.mode)} | Duration: {result.duration_seconds:.2f} seconds</p>
        </div>
        """

        if result.detector_results:
            content += self._render_detector_results(result.detector_results)

        if result.vulnerabilities:
            content += self._render_vulnerabilities(result.vulnerabilities)

        return content

    def _render_unified_content(self, result: UnifiedResult) -> str:
        """Render unified report content."""
        score_class = self._get_score_class(result.overall_score)

        # Extract scores from sub-results
        static_score = result.static_result.overall_score if result.static_result else None
        live_score = result.live_result.overall_score if result.live_result else None

        # Calculate total issues from both static findings and live vulnerabilities
        total_issues = 0
        if result.static_result:
            total_issues += len(result.static_result.findings)
        if result.live_result:
            total_issues += len(result.live_result.vulnerabilities)

        # Format scores for display
        static_score_display = f"{static_score:.0f}" if static_score is not None else "N/A"
        live_score_display = f"{live_score:.0f}" if live_score is not None else "N/A"

        content = f"""
        <div class="summary-card">
            <div class="summary-grid">
                <div class="metric">
                    <div class="score-circle {score_class}">{result.overall_score:.0f}</div>
                    <div class="metric-label">Overall Score</div>
                </div>
                <div class="metric">
                    <div class="metric-value">{static_score_display}</div>
                    <div class="metric-label">Static Score</div>
                </div>
                <div class="metric">
                    <div class="metric-value">{live_score_display}</div>
                    <div class="metric-label">Live Score</div>
                </div>
                <div class="metric">
                    <div class="metric-value">{total_issues}</div>
                    <div class="metric-label">Total Issues</div>
                </div>
            </div>
        </div>
        """

        if result.static_result:
            content += f"""
            <div class="section">
                <h2>Static Analysis Results</h2>
                {self._render_scan_content(result.static_result)}
            </div>
            """

        if result.live_result:
            content += f"""
            <div class="section">
                <h2>Live Test Results</h2>
                {self._render_test_content(result.live_result)}
            </div>
            """

        # Build recommendations from the result's to_dict() which computes them
        result_dict = result.to_dict()
        recommendations = result_dict.get("summary", {}).get("recommendations", [])
        if recommendations:
            content += f"""
            <div class="section">
                <h2>Recommendations</h2>
                <ul>
                    {''.join(f'<li>{html.escape(rec)}</li>' for rec in recommendations)}
                </ul>
            </div>
            """

        return content

    def _render_tabbed_content(
        self, scan_result: ScanResult, audit_result: Optional[Any] = None
    ) -> str:
        """Render tabbed content combining scan and audit results."""
        # Calculate combined score if both results are present
        if audit_result:
            # Combine scores: 50% scan (vulnerabilities) + 50% audit (security posture)
            combined_score = (scan_result.overall_score + audit_result.overall_score) / 2
        else:
            combined_score = scan_result.overall_score

        finding_count = len(scan_result.findings)
        control_count = audit_result.detected_controls_count if audit_result else 0

        # Combined score header
        content = f"""
        <div class="combined-score-section">
            <div class="combined-score-grid">
                <div class="combined-metric">
                    <div class="combined-metric-value">{combined_score:.0f}</div>
                    <div class="combined-metric-label">Combined Security Score</div>
                </div>
                <div class="combined-metric">
                    <div class="combined-metric-value">{scan_result.overall_score:.0f}</div>
                    <div class="combined-metric-label">Vulnerability Score</div>
                </div>
        """
        if audit_result:
            content += f"""
                <div class="combined-metric">
                    <div class="combined-metric-value">{audit_result.overall_score:.0f}</div>
                    <div class="combined-metric-label">Security Posture</div>
                </div>
            """
        content += """
            </div>
        </div>
        """

        # Tab navigation
        content += f"""
        <div class="tab-navigation">
            <button class="tab-btn active" data-tab="vulnerabilities">
                Vulnerabilities
                <span class="tab-badge">{finding_count}</span>
            </button>
        """
        if audit_result:
            content += f"""
            <button class="tab-btn" data-tab="security-posture">
                Security Posture
                <span class="tab-badge">{control_count}/{audit_result.total_controls_count}</span>
            </button>
            """
        content += "</div>"

        # Vulnerabilities tab content
        content += f"""
        <div id="vulnerabilities" class="tab-content active">
            {self._render_scan_tab_content(scan_result)}
        </div>
        """

        # Security Posture tab content (if audit result is present)
        if audit_result:
            content += f"""
            <div id="security-posture" class="tab-content">
                {self._render_audit_tab_content(audit_result, scan_result.findings)}
            </div>
            """

        return content

    def _render_scan_tab_content(self, result: ScanResult) -> str:
        """Render scan content for the vulnerabilities tab."""
        severity_breakdown = self._get_severity_breakdown(result.findings)
        total_findings = len(result.findings)

        content = f"""
        <div class="audit-summary">
            <div class="audit-metric">
                <div class="audit-metric-value">{result.files_scanned}</div>
                <div class="audit-metric-label">Files Scanned</div>
            </div>
            <div class="audit-metric">
                <div class="audit-metric-value">{total_findings}</div>
                <div class="audit-metric-label">Issues Found</div>
            </div>
            <div class="audit-metric">
                <div class="audit-metric-value">{result.confidence*100:.0f}%</div>
                <div class="audit-metric-label">Confidence</div>
            </div>
            <div class="audit-metric">
                <div class="audit-metric-value">{result.duration_seconds:.1f}s</div>
                <div class="audit-metric-label">Scan Time</div>
            </div>
        </div>
        """

        if result.findings:
            # Severity filter buttons
            content += f"""
            <div class="section">
                <h3>Vulnerabilities ({total_findings})</h3>

                <!-- Severity Filter -->
                <div class="severity-filter" style="margin-bottom: 16px; display: flex; gap: 8px; flex-wrap: wrap;">
                    <button class="severity-filter-btn active" data-severity="all" data-target="findings" onclick="filterFindingsBySeverity('all')">
                        All <span class="filter-count">({total_findings})</span>
                    </button>
                    <button class="severity-filter-btn" data-severity="critical" data-target="findings" onclick="filterFindingsBySeverity('critical')">
                        Critical <span class="filter-count">({severity_breakdown.get('CRITICAL', 0)})</span>
                    </button>
                    <button class="severity-filter-btn" data-severity="high" data-target="findings" onclick="filterFindingsBySeverity('high')">
                        High <span class="filter-count">({severity_breakdown.get('HIGH', 0)})</span>
                    </button>
                    <button class="severity-filter-btn" data-severity="medium" data-target="findings" onclick="filterFindingsBySeverity('medium')">
                        Medium <span class="filter-count">({severity_breakdown.get('MEDIUM', 0)})</span>
                    </button>
                    <button class="severity-filter-btn" data-severity="low" data-target="findings" onclick="filterFindingsBySeverity('low')">
                        Low <span class="filter-count">({severity_breakdown.get('LOW', 0)})</span>
                    </button>
                    <button class="severity-filter-btn" data-severity="info" data-target="findings" onclick="filterFindingsBySeverity('info')">
                        Info <span class="filter-count">({severity_breakdown.get('INFO', 0)})</span>
                    </button>
                </div>

                <div class="findings-list" id="findings-list">
            """

            # Render findings with pagination
            for i, finding in enumerate(result.findings):
                severity_class = f"severity-{finding.severity.value.lower()}"
                badge_class = f"badge-{finding.severity.value.lower()}"
                file_path = finding.file_path or "unknown"
                line_number = finding.line_number or 0
                description = finding.description or ""
                recommendation = finding.recommendation or "No specific recommendation available."
                category = finding.category or "Unknown"

                # Hidden by default after first 10
                hidden_class = "finding-hidden" if i >= 10 else ""

                content += f"""
                <div class="finding {severity_class} {hidden_class}" data-severity="{finding.severity.value.lower()}" data-category="{html.escape(category)}" data-index="{i}">
                    <div class="finding-header">
                        <span class="finding-title">{html.escape(finding.title)}</span>
                        <div>
                            <span class="badge" style="background: #6c757d; margin-right: 5px;">{html.escape(category)}</span>
                            <span class="badge {badge_class}">{finding.severity.value}</span>
                        </div>
                    </div>
                    <div class="location">{html.escape(file_path)}:{line_number}</div>
                    <div class="description">{html.escape(description)}</div>
                    {f'<div class="code-block"><code>{html.escape(finding.code_snippet)}</code></div>' if finding.code_snippet else ''}
                    <div class="remediation">
                        <div class="remediation-title">Remediation</div>
                        {html.escape(recommendation)}
                    </div>
                </div>
                """

            content += """
                </div>

                <!-- Load More Button -->
                <div id="findings-load-more-container" style="text-align: center; margin-top: 16px;">
                    <button id="findings-load-more-btn" class="load-more-btn" onclick="loadMoreFindings()">
                        Show More <span id="findings-remaining-count"></span>
                    </button>
                </div>
            </div>
            """
        else:
            content += """
            <div class="no-results">
                <div class="no-results-icon">✅</div>
                <h3>No vulnerabilities found</h3>
                <p>Great job! Your code passed all security checks.</p>
            </div>
            """

        return content

    def _render_findings_simple(self, findings: List[Finding]) -> str:
        """Render findings without the filter toolbar (for tabbed view)."""
        content = f'<div class="section"><h3>Findings ({len(findings)})</h3>'

        for finding in findings:  # Show all findings
            severity_class = f"severity-{finding.severity.value.lower()}"
            badge_class = f"badge-{finding.severity.value.lower()}"
            file_path = finding.file_path or "unknown"
            line_number = finding.line_number or 0
            description = finding.description or ""
            recommendation = finding.recommendation or "No specific recommendation available."
            category = finding.category or "Unknown"
            content += f"""
            <div class="finding {severity_class}" data-severity="{finding.severity.value}" data-category="{html.escape(category)}">
                <div class="finding-header">
                    <span class="finding-title">{html.escape(finding.title)}</span>
                    <div>
                        <span class="badge" style="background: #6c757d; margin-right: 5px;">{html.escape(category)}</span>
                        <span class="badge {badge_class}">{finding.severity.value}</span>
                    </div>
                </div>
                <div class="location">{html.escape(file_path)}:{line_number}</div>
                <div class="description">{html.escape(description)}</div>
                {f'<div class="code-block"><code>{html.escape(finding.code_snippet)}</code></div>' if finding.code_snippet else ''}
                <div class="remediation">
                    <div class="remediation-title">Remediation</div>
                    {html.escape(recommendation)}
                </div>
            </div>
            """

        content += '</div>'
        return content

    def _render_audit_tab_content(self, result: Any, scan_findings: List[Finding] = None) -> str:
        """Render audit content for the security posture tab."""
        maturity_class = f"maturity-{result.maturity_level.value.lower()}"

        # Combine audit recommendations with scan findings
        all_recommendations = []

        # Add audit recommendations
        for rec in result.recommendations:
            all_recommendations.append({
                "title": rec.title,
                "description": rec.remediation,
                "priority": rec.priority,
                "source": "audit",
                "category": rec.category,
            })

        # Add scan findings as recommendations
        if scan_findings:
            for finding in scan_findings:
                severity_to_priority = {
                    "CRITICAL": "critical",
                    "HIGH": "high",
                    "MEDIUM": "medium",
                    "LOW": "low",
                    "INFO": "low",
                }
                all_recommendations.append({
                    "title": finding.title,
                    "description": finding.recommendation or finding.description or "",
                    "priority": severity_to_priority.get(finding.severity.value, "medium"),
                    "source": "scan",
                    "category": finding.category or "Vulnerability",
                    "file_path": finding.file_path,
                    "line_number": finding.line_number,
                })

        # Sort by priority
        priority_order = {"critical": 0, "high": 1, "medium": 2, "low": 3}
        all_recommendations.sort(key=lambda x: priority_order.get(x["priority"], 2))

        # Count by priority
        priority_counts = {"critical": 0, "high": 0, "medium": 0, "low": 0}
        for rec in all_recommendations:
            priority_counts[rec["priority"]] = priority_counts.get(rec["priority"], 0) + 1

        total_recs = len(all_recommendations)

        content = f"""
        <div class="audit-summary">
            <div class="audit-metric">
                <div class="audit-metric-value">{result.overall_score:.0f}</div>
                <div class="audit-metric-label">Overall Score</div>
                <span class="maturity-badge {maturity_class}">{result.maturity_level.value}</span>
            </div>
            <div class="audit-metric">
                <div class="audit-metric-value">{result.detected_controls_count}</div>
                <div class="audit-metric-label">Controls Detected</div>
                <span class="maturity-badge" style="background: #f1f5f9; color: #64748b;">of {result.total_controls_count}</span>
            </div>
            <div class="audit-metric">
                <div class="audit-metric-value">{result.files_scanned}</div>
                <div class="audit-metric-label">Files Analyzed</div>
            </div>
            <div class="audit-metric">
                <div class="audit-metric-value">{total_recs}</div>
                <div class="audit-metric-label">Total Recommendations</div>
            </div>
        </div>

        <div class="section-header">
            <h3 style="color: var(--text-primary); border-bottom: 2px solid var(--accent-primary); padding-bottom: 8px;">Category Scores</h3>
            <button class="expand-toggle" id="toggle-categories" onclick="toggleAllCategories()">Expand All</button>
        </div>
        <div class="category-grid">
        """

        # Render category cards
        for cat_id, cat_score in result.categories.items():
            content += self._render_audit_category_card(cat_score)

        content += "</div>"

        # Render recommendations with filtering and pagination
        if all_recommendations:
            content += f"""
            <div class="recommendations-section">
                <h3>All Recommendations ({total_recs})</h3>

                <!-- Severity Filter -->
                <div class="severity-filter" style="margin-bottom: 16px; display: flex; gap: 8px; flex-wrap: wrap;">
                    <button class="severity-filter-btn active" data-severity="all" onclick="filterBySeverity('all')">
                        All <span class="filter-count">({total_recs})</span>
                    </button>
                    <button class="severity-filter-btn" data-severity="critical" onclick="filterBySeverity('critical')">
                        Critical <span class="filter-count">({priority_counts['critical']})</span>
                    </button>
                    <button class="severity-filter-btn" data-severity="high" onclick="filterBySeverity('high')">
                        High <span class="filter-count">({priority_counts['high']})</span>
                    </button>
                    <button class="severity-filter-btn" data-severity="medium" onclick="filterBySeverity('medium')">
                        Medium <span class="filter-count">({priority_counts['medium']})</span>
                    </button>
                    <button class="severity-filter-btn" data-severity="low" onclick="filterBySeverity('low')">
                        Low <span class="filter-count">({priority_counts['low']})</span>
                    </button>
                </div>

                <div class="rec-list" id="recommendations-list">
            """

            for i, rec in enumerate(all_recommendations):
                priority_class = f"priority-{rec['priority']}"
                rec_border = f"rec-{rec['priority']}"
                source_badge = "Audit" if rec["source"] == "audit" else "Scan"
                source_style = "background: #667eea; color: white;" if rec["source"] == "audit" else "background: #f97316; color: white;"

                # Hidden by default after first 10
                hidden_class = "rec-hidden" if i >= 10 else ""

                location_html = ""
                if rec.get("file_path"):
                    location_html = f'<span style="color: #64748b; font-size: 0.8em; margin-left: 8px;">{html.escape(rec["file_path"])}:{rec.get("line_number", 0)}</span>'

                content += f"""
                <div class="rec-item {rec_border} {hidden_class}" data-priority="{rec['priority']}" data-index="{i}">
                    <div class="rec-header">
                        <span class="rec-title">{html.escape(rec['title'])}{location_html}</span>
                        <div style="display: flex; gap: 6px;">
                            <span class="rec-priority" style="{source_style}">{source_badge}</span>
                            <span class="rec-priority {priority_class}">{rec['priority']}</span>
                        </div>
                    </div>
                    <p class="rec-description">{html.escape(rec['description'])}</p>
                </div>
                """

            content += """
                </div>

                <!-- Load More Button -->
                <div id="load-more-container" style="text-align: center; margin-top: 16px;">
                    <button id="load-more-btn" class="load-more-btn" onclick="loadMoreRecommendations()">
                        Show More <span id="remaining-count"></span>
                    </button>
                </div>
            </div>
            """

        return content

    def _render_audit_category_card(self, cat: Any) -> str:
        """Render a single audit category card with accordion."""
        controls_html = ""
        detected_count = 0
        partial_count = 0
        missing_count = 0

        for control in cat.controls:
            if control.detected:
                if control.score >= 50:
                    detected_count += 1
                    status_class = "status-detected"
                    status_text = control.level.value.title()
                else:
                    partial_count += 1
                    status_class = "status-partial"
                    status_text = "Partial"
            else:
                missing_count += 1
                status_class = "status-missing"
                status_text = "Missing"

            controls_html += f"""
            <li class="control-item">
                <span class="control-name">{html.escape(control.control_name)}</span>
                <span class="control-status {status_class}">{status_text}</span>
            </li>
            """

        accordion_icon = """<svg class="accordion-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
        </svg>"""

        return f"""
        <div class="category-card">
            <div class="category-header" onclick="toggleCategory(this)">
                <div class="category-header-left">
                    <span class="category-name">{html.escape(cat.category_name)}</span>
                </div>
                <div style="display: flex; align-items: center; gap: 12px;">
                    <span class="category-score">{cat.score:.0f}/100</span>
                    {accordion_icon}
                </div>
            </div>
            <div class="category-progress">
                <div class="category-progress-fill" style="width: {cat.percentage}%"></div>
            </div>
            <div class="category-content">
                <ul class="control-list">
                    {controls_html}
                </ul>
                <div class="category-stats">
                    <span class="stat-item"><span class="stat-dot detected"></span> {detected_count} Detected</span>
                    <span class="stat-item"><span class="stat-dot partial"></span> {partial_count} Partial</span>
                    <span class="stat-item"><span class="stat-dot missing"></span> {missing_count} Missing</span>
                </div>
            </div>
        </div>
        """

    def _render_category_scores(self, category_scores: Dict) -> str:
        """Render category scores section."""
        content = '<div class="section"><h2>Category Scores</h2>'
        for cat_id, score in category_scores.items():
            content += f"""
            <div class="detector-card">
                <div class="detector-info">
                    <h3>{html.escape(score.category_name)}</h3>
                    <div class="progress-bar">
                        <div class="progress-fill" style="width: {score.score}%"></div>
                    </div>
                </div>
                <div class="detector-stats">
                    <div class="stat">
                        <div class="stat-value">{score.score:.0f}</div>
                        <div class="stat-label">Score</div>
                    </div>
                    <div class="stat">
                        <div class="stat-value">{score.confidence*100:.0f}%</div>
                        <div class="stat-label">Confidence</div>
                    </div>
                </div>
            </div>
            """
        content += '</div>'
        return content

    def _render_findings(self, findings: List[Finding]) -> str:
        """Render findings section with modern filter toolbar."""
        # Build modern filter toolbar
        content = """
        <div class="filter-toolbar">
            <div class="filter-toolbar-header">
                <div class="filter-toolbar-title">
                    <svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z"/>
                    </svg>
                    Filter Results
                </div>
                <div class="filter-stats-badge" id="filter-stats">Loading...</div>
            </div>
            <div class="filter-sections">
                <div class="filter-section">
                    <div class="filter-section-label">
                        Severity
                        <span class="filter-section-actions">
                            <a href="javascript:selectAllSeverity()">All</a>
                            <a href="javascript:selectNoneSeverity()">None</a>
                        </span>
                    </div>
                    <div class="filter-chips" id="severity-chips"></div>
                </div>
                <div class="filter-section">
                    <div class="filter-section-label">
                        Category
                        <span class="filter-section-actions">
                            <a href="javascript:selectAllCategory()">All</a>
                            <a href="javascript:selectNoneCategory()">None</a>
                        </span>
                    </div>
                    <div class="filter-chips" id="category-chips"></div>
                </div>
                <div class="filter-search-box">
                    <input type="text" id="filter-search" class="filter-search-input" placeholder="Search findings...">
                </div>
                <button onclick="resetFilters()" class="filter-reset-btn">Reset</button>
            </div>
        </div>
        """

        content += '<div class="section"><h2>Findings</h2>'
        content += """<div id="no-results" class="no-results" style="display: none;">
            <div class="no-results-icon">🔍</div>
            <h3>No findings match your filters</h3>
            <p>Try adjusting your filter criteria or click Reset to show all results.</p>
        </div>"""

        for finding in findings:
            severity_class = f"severity-{finding.severity.value.lower()}"
            badge_class = f"badge-{finding.severity.value.lower()}"
            file_path = finding.file_path or "unknown"
            line_number = finding.line_number or 0
            description = finding.description or ""
            recommendation = finding.recommendation or "No specific recommendation available."
            category = finding.category or "Unknown"
            content += f"""
            <div class="finding {severity_class}" data-severity="{finding.severity.value}" data-category="{html.escape(category)}">
                <div class="finding-header">
                    <span class="finding-title">{html.escape(finding.title)}</span>
                    <div>
                        <span class="badge" style="background: #6c757d; margin-right: 5px;">{html.escape(category)}</span>
                        <span class="badge {badge_class}">{finding.severity.value}</span>
                    </div>
                </div>
                <div class="location">{html.escape(file_path)}:{line_number}</div>
                <div class="description">{html.escape(description)}</div>
                {f'<div class="code-block"><code>{html.escape(finding.code_snippet)}</code></div>' if finding.code_snippet else ''}
                <div class="remediation">
                    <div class="remediation-title">Remediation</div>
                    {html.escape(recommendation)}
                </div>
            </div>
            """
        content += '</div>'
        return content

    def _render_detector_results(self, results: List) -> str:
        """Render detector results section."""
        content = '<div class="section"><h2>Detector Results</h2>'
        for result in results:
            content += f"""
            <div class="detector-card">
                <div class="detector-info">
                    <h3>{html.escape(result.detector_name)}</h3>
                    <div class="progress-bar">
                        <div class="progress-fill" style="width: {result.score}%"></div>
                    </div>
                </div>
                <div class="detector-stats">
                    <div class="stat">
                        <div class="stat-value">{result.score:.0f}</div>
                        <div class="stat-label">Score</div>
                    </div>
                    <div class="stat">
                        <div class="stat-value">{result.tests_passed}/{result.tests_run}</div>
                        <div class="stat-label">Tests Passed</div>
                    </div>
                    <div class="stat">
                        <div class="stat-value">{len(result.vulnerabilities)}</div>
                        <div class="stat-label">Issues</div>
                    </div>
                </div>
            </div>
            """
        content += '</div>'
        return content

    def _render_vulnerabilities(self, vulns: List[LiveVulnerability]) -> str:
        """Render vulnerabilities section with modern filter toolbar."""
        # Build modern filter toolbar
        content = """
        <div class="filter-toolbar">
            <div class="filter-toolbar-header">
                <div class="filter-toolbar-title">
                    <svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z"/>
                    </svg>
                    Filter Results
                </div>
                <div class="filter-stats-badge" id="filter-stats">Loading...</div>
            </div>
            <div class="filter-sections">
                <div class="filter-section">
                    <div class="filter-section-label">
                        Severity
                        <span class="filter-section-actions">
                            <a href="javascript:selectAllSeverity()">All</a>
                            <a href="javascript:selectNoneSeverity()">None</a>
                        </span>
                    </div>
                    <div class="filter-chips" id="severity-chips"></div>
                </div>
                <div class="filter-section">
                    <div class="filter-section-label">
                        Detector
                        <span class="filter-section-actions">
                            <a href="javascript:selectAllCategory()">All</a>
                            <a href="javascript:selectNoneCategory()">None</a>
                        </span>
                    </div>
                    <div class="filter-chips" id="category-chips"></div>
                </div>
                <div class="filter-search-box">
                    <input type="text" id="filter-search" class="filter-search-input" placeholder="Search vulnerabilities...">
                </div>
                <button onclick="resetFilters()" class="filter-reset-btn">Reset</button>
            </div>
        </div>
        """

        content += '<div class="section"><h2>Vulnerabilities</h2>'
        content += """<div id="no-results" class="no-results" style="display: none;">
            <div class="no-results-icon">🔍</div>
            <h3>No vulnerabilities match your filters</h3>
            <p>Try adjusting your filter criteria or click Reset to show all results.</p>
        </div>"""

        for vuln in vulns:
            severity_class = f"severity-{vuln.severity.value.lower()}"
            badge_class = f"badge-{vuln.severity.value.lower()}"
            detector_id = vuln.detector_id or "unknown"
            content += f"""
            <div class="vulnerability {severity_class}" data-severity="{vuln.severity.value}" data-category="{html.escape(detector_id)}">
                <div class="vuln-header">
                    <span class="vuln-title">{html.escape(vuln.title)}</span>
                    <div>
                        <span class="badge" style="background: #6c757d; margin-right: 5px;">{html.escape(detector_id)}</span>
                        <span class="badge {badge_class}">{vuln.severity.value}</span>
                    </div>
                </div>
                <div class="description">{html.escape(vuln.description)}</div>
                <div class="code-block"><code>Prompt: {html.escape(vuln.prompt_used[:200])}</code></div>
                <div class="remediation">
                    <div class="remediation-title">Remediation</div>
                    {html.escape(vuln.remediation)}
                </div>
            </div>
            """
        content += '</div>'
        return content

    def _get_score_class(self, score: float) -> str:
        """Get CSS class based on score."""
        if score >= 70:
            return "score-high"
        elif score >= 40:
            return "score-medium"
        return "score-low"

    def _get_severity_breakdown(self, findings: List[Finding]) -> Dict[str, int]:
        """Get count of findings by severity."""
        breakdown = {s.value: 0 for s in Severity}
        for finding in findings:
            breakdown[finding.severity.value] += 1
        return breakdown

    def _get_vuln_severity_breakdown(self, vulns: List[LiveVulnerability]) -> Dict[str, int]:
        """Get count of vulnerabilities by severity."""
        breakdown = {s.value: 0 for s in Severity}
        for vuln in vulns:
            breakdown[vuln.severity.value] += 1
        return breakdown

    def _render_severity_items(self, breakdown: Dict[str, int]) -> str:
        """Render severity breakdown items."""
        items = ""
        for severity in Severity:
            count = breakdown.get(severity.value, 0)
            if count > 0:
                color = self.SEVERITY_COLORS.get(severity, "#666")
                items += f"""
                <div class="severity-item">
                    <div class="severity-dot" style="background: {color}"></div>
                    <span>{severity.value}: {count}</span>
                </div>
                """
        return items

    def _get_javascript(self) -> str:
        """Get embedded JavaScript for interactive filtering."""
        return """
        // Filter state
        const filterState = {
            severities: new Set(['CRITICAL', 'HIGH', 'MEDIUM', 'LOW', 'INFO']),
            categories: new Set(),
            searchText: ''
        };

        // Initialize on DOM ready
        document.addEventListener('DOMContentLoaded', initializeFilters);

        function initializeFilters() {
            const findings = document.querySelectorAll('.finding, .vulnerability');
            if (findings.length === 0) return;

            // Collect unique categories
            const categories = new Set();
            findings.forEach(f => {
                if (f.dataset.category) {
                    categories.add(f.dataset.category);
                    filterState.categories.add(f.dataset.category);
                }
            });

            // Build severity chips
            const severityContainer = document.getElementById('severity-chips');
            if (severityContainer) {
                ['CRITICAL', 'HIGH', 'MEDIUM', 'LOW', 'INFO'].forEach(sev => {
                    const count = document.querySelectorAll('[data-severity="' + sev + '"]').length;
                    if (count > 0) {
                        const chip = document.createElement('span');
                        chip.className = 'filter-chip severity-chip active';
                        chip.dataset.type = 'severity';
                        chip.dataset.value = sev;
                        chip.innerHTML = sev + ' <span class="chip-count">(' + count + ')</span>';
                        chip.onclick = function() { toggleChip(this); };
                        severityContainer.appendChild(chip);
                    }
                });
            }

            // Build category chips
            const categoryContainer = document.getElementById('category-chips');
            if (categoryContainer && categories.size > 0) {
                // Sort categories
                const sortedCats = Array.from(categories).sort();
                sortedCats.forEach(cat => {
                    const count = document.querySelectorAll('[data-category="' + cat + '"]').length;
                    const chip = document.createElement('span');
                    chip.className = 'filter-chip category-chip active';
                    chip.dataset.type = 'category';
                    chip.dataset.value = cat;
                    // Shorten category name for display
                    const shortName = cat.length > 20 ? cat.substring(0, 20) + '...' : cat;
                    chip.innerHTML = shortName + ' <span class="chip-count">(' + count + ')</span>';
                    chip.title = cat;
                    chip.onclick = function() { toggleChip(this); };
                    categoryContainer.appendChild(chip);
                });
            }

            // Search input handler
            const searchInput = document.getElementById('filter-search');
            if (searchInput) {
                searchInput.oninput = function() {
                    filterState.searchText = this.value.toLowerCase();
                    applyFilters();
                };
            }

            updateStats();
        }

        function toggleChip(chip) {
            const type = chip.dataset.type;
            const value = chip.dataset.value;

            if (chip.classList.contains('active')) {
                chip.classList.remove('active');
                if (type === 'severity') {
                    filterState.severities.delete(value);
                } else {
                    filterState.categories.delete(value);
                }
            } else {
                chip.classList.add('active');
                if (type === 'severity') {
                    filterState.severities.add(value);
                } else {
                    filterState.categories.add(value);
                }
            }
            applyFilters();
        }

        function applyFilters() {
            const findings = document.querySelectorAll('.finding, .vulnerability');
            let visible = 0;

            findings.forEach(f => {
                const sev = f.dataset.severity;
                const cat = f.dataset.category;
                const text = f.textContent.toLowerCase();

                const sevMatch = filterState.severities.has(sev);
                const catMatch = filterState.categories.size === 0 || filterState.categories.has(cat);
                const searchMatch = !filterState.searchText || text.includes(filterState.searchText);

                if (sevMatch && catMatch && searchMatch) {
                    f.classList.remove('filtered-out');
                    visible++;
                } else {
                    f.classList.add('filtered-out');
                }
            });

            updateStats();

            // Show/hide no results
            const noResults = document.getElementById('no-results');
            if (noResults) {
                noResults.style.display = visible === 0 ? 'block' : 'none';
            }
        }

        function updateStats() {
            const total = document.querySelectorAll('.finding, .vulnerability').length;
            const visible = document.querySelectorAll('.finding:not(.filtered-out), .vulnerability:not(.filtered-out)').length;
            const statsEl = document.getElementById('filter-stats');
            if (statsEl) {
                statsEl.innerHTML = 'Showing <strong>' + visible + '</strong> of <strong>' + total + '</strong>';
            }
        }

        function selectAllSeverity() {
            document.querySelectorAll('.filter-chip.severity-chip').forEach(chip => {
                chip.classList.add('active');
                filterState.severities.add(chip.dataset.value);
            });
            applyFilters();
        }

        function selectNoneSeverity() {
            document.querySelectorAll('.filter-chip.severity-chip').forEach(chip => {
                chip.classList.remove('active');
                filterState.severities.delete(chip.dataset.value);
            });
            applyFilters();
        }

        function selectAllCategory() {
            document.querySelectorAll('.filter-chip.category-chip').forEach(chip => {
                chip.classList.add('active');
                filterState.categories.add(chip.dataset.value);
            });
            applyFilters();
        }

        function selectNoneCategory() {
            document.querySelectorAll('.filter-chip.category-chip').forEach(chip => {
                chip.classList.remove('active');
                filterState.categories.delete(chip.dataset.value);
            });
            applyFilters();
        }

        function resetFilters() {
            // Reset all severity chips
            document.querySelectorAll('.filter-chip.severity-chip').forEach(chip => {
                chip.classList.add('active');
                filterState.severities.add(chip.dataset.value);
            });

            // Reset all category chips
            document.querySelectorAll('.filter-chip.category-chip').forEach(chip => {
                chip.classList.add('active');
                filterState.categories.add(chip.dataset.value);
            });

            // Reset search
            const searchInput = document.getElementById('filter-search');
            if (searchInput) {
                searchInput.value = '';
                filterState.searchText = '';
            }

            applyFilters();
        }

        // Tab navigation
        function switchTab(tabId) {
            // Update tab buttons
            document.querySelectorAll('.tab-btn').forEach(btn => {
                btn.classList.remove('active');
                if (btn.dataset.tab === tabId) {
                    btn.classList.add('active');
                }
            });

            // Update tab content
            document.querySelectorAll('.tab-content').forEach(content => {
                content.classList.remove('active');
                if (content.id === tabId) {
                    content.classList.add('active');
                }
            });

            // Re-initialize filters for the active tab if needed
            setTimeout(initializeFilters, 100);
        }

        // Dark mode toggle
        function toggleTheme() {
            const html = document.documentElement;
            const currentTheme = html.getAttribute('data-theme');
            const newTheme = currentTheme === 'light' ? 'dark' : 'light';
            html.setAttribute('data-theme', newTheme);
            localStorage.setItem('theme', newTheme);
        }

        // Initialize theme from localStorage
        function initTheme() {
            const savedTheme = localStorage.getItem('theme');
            if (savedTheme) {
                document.documentElement.setAttribute('data-theme', savedTheme);
            } else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
                document.documentElement.setAttribute('data-theme', 'dark');
            }
        }

        // Initialize tabs on load
        document.addEventListener('DOMContentLoaded', function() {
            // Initialize theme
            initTheme();

            // Set up tab click handlers
            document.querySelectorAll('.tab-btn').forEach(btn => {
                btn.onclick = function() {
                    switchTab(this.dataset.tab);
                };
            });

            // Initialize recommendation pagination
            initRecommendations();
            // Initialize findings pagination
            initFindings();
        });

        // Recommendation pagination state
        let recState = {
            visibleCount: 10,
            pageSize: 10,
            currentFilter: 'all',
            totalItems: 0
        };

        function initRecommendations() {
            const items = document.querySelectorAll('#recommendations-list .rec-item');
            recState.totalItems = items.length;
            updateLoadMoreButton();
        }

        function updateLoadMoreButton() {
            const btn = document.getElementById('load-more-btn');
            const container = document.getElementById('load-more-container');
            const countSpan = document.getElementById('remaining-count');

            if (!btn || !container) return;

            // Count visible items based on current filter
            const items = document.querySelectorAll('#recommendations-list .rec-item');
            let matchingItems = 0;
            let visibleItems = 0;

            items.forEach(item => {
                const priority = item.dataset.priority;
                const matchesFilter = recState.currentFilter === 'all' || priority === recState.currentFilter;

                if (matchesFilter) {
                    matchingItems++;
                    if (!item.classList.contains('rec-hidden')) {
                        visibleItems++;
                    }
                }
            });

            const remaining = matchingItems - visibleItems;

            if (remaining <= 0) {
                container.style.display = 'none';
            } else {
                container.style.display = 'block';
                countSpan.textContent = `(${remaining} more)`;
            }
        }

        function loadMoreRecommendations() {
            const items = document.querySelectorAll('#recommendations-list .rec-item');
            let shown = 0;
            let toShow = recState.pageSize;

            items.forEach(item => {
                const priority = item.dataset.priority;
                const matchesFilter = recState.currentFilter === 'all' || priority === recState.currentFilter;

                if (matchesFilter && item.classList.contains('rec-hidden') && toShow > 0) {
                    item.classList.remove('rec-hidden');
                    toShow--;
                }
            });

            updateLoadMoreButton();
        }

        function filterBySeverity(severity) {
            recState.currentFilter = severity;

            // Update button states
            document.querySelectorAll('.severity-filter-btn').forEach(btn => {
                btn.classList.remove('active');
                if (btn.dataset.severity === severity) {
                    btn.classList.add('active');
                }
            });

            // Filter items
            const items = document.querySelectorAll('#recommendations-list .rec-item');
            let visibleCount = 0;

            items.forEach((item, index) => {
                const priority = item.dataset.priority;
                const matchesFilter = severity === 'all' || priority === severity;

                // Remove all visibility classes first
                item.classList.remove('rec-hidden', 'rec-filtered');

                if (!matchesFilter) {
                    item.classList.add('rec-filtered');
                } else {
                    // Show first 10 matching items
                    if (visibleCount >= recState.pageSize) {
                        item.classList.add('rec-hidden');
                    }
                    visibleCount++;
                }
            });

            updateLoadMoreButton();
        }

        // Findings pagination state
        let findingsState = {
            visibleCount: 10,
            pageSize: 10,
            currentFilter: 'all',
            totalItems: 0
        };

        function initFindings() {
            const items = document.querySelectorAll('#findings-list .finding');
            findingsState.totalItems = items.length;
            updateFindingsLoadMoreButton();
        }

        function updateFindingsLoadMoreButton() {
            const btn = document.getElementById('findings-load-more-btn');
            const container = document.getElementById('findings-load-more-container');
            const countSpan = document.getElementById('findings-remaining-count');

            if (!btn || !container) return;

            const items = document.querySelectorAll('#findings-list .finding');
            let matchingItems = 0;
            let visibleItems = 0;

            items.forEach(item => {
                const severity = item.dataset.severity;
                const matchesFilter = findingsState.currentFilter === 'all' || severity === findingsState.currentFilter;

                if (matchesFilter) {
                    matchingItems++;
                    if (!item.classList.contains('finding-hidden')) {
                        visibleItems++;
                    }
                }
            });

            const remaining = matchingItems - visibleItems;

            if (remaining <= 0) {
                container.style.display = 'none';
            } else {
                container.style.display = 'block';
                countSpan.textContent = `(${remaining} more)`;
            }
        }

        function loadMoreFindings() {
            const items = document.querySelectorAll('#findings-list .finding');
            let toShow = findingsState.pageSize;

            items.forEach(item => {
                const severity = item.dataset.severity;
                const matchesFilter = findingsState.currentFilter === 'all' || severity === findingsState.currentFilter;

                if (matchesFilter && item.classList.contains('finding-hidden') && toShow > 0) {
                    item.classList.remove('finding-hidden');
                    toShow--;
                }
            });

            updateFindingsLoadMoreButton();
        }

        function filterFindingsBySeverity(severity) {
            findingsState.currentFilter = severity;

            // Update button states (only for findings buttons)
            document.querySelectorAll('.severity-filter-btn[data-target="findings"]').forEach(btn => {
                btn.classList.remove('active');
                if (btn.dataset.severity === severity) {
                    btn.classList.add('active');
                }
            });

            // Filter items
            const items = document.querySelectorAll('#findings-list .finding');
            let visibleCount = 0;

            items.forEach((item, index) => {
                const itemSeverity = item.dataset.severity;
                const matchesFilter = severity === 'all' || itemSeverity === severity;

                // Remove all visibility classes first
                item.classList.remove('finding-hidden', 'finding-filtered');

                if (!matchesFilter) {
                    item.classList.add('finding-filtered');
                } else {
                    // Show first 10 matching items
                    if (visibleCount >= findingsState.pageSize) {
                        item.classList.add('finding-hidden');
                    }
                    visibleCount++;
                }
            });

            updateFindingsLoadMoreButton();
        }

        // Category accordion functionality
        function toggleCategory(header) {
            const card = header.parentElement;
            card.classList.toggle('open');
        }

        function toggleAllCategories() {
            const cards = document.querySelectorAll('.category-card');
            const btn = document.getElementById('toggle-categories');
            const allOpen = [...cards].every(card => card.classList.contains('open'));

            cards.forEach(card => {
                if (allOpen) {
                    card.classList.remove('open');
                } else {
                    card.classList.add('open');
                }
            });

            if (btn) {
                btn.textContent = allOpen ? 'Expand All' : 'Collapse All';
            }
        }
        """
