Instruction: Create an AUTARCH web template for the 'Loadtest' page. It should extend base.html, have a page header, and use AUTARCH's CSS variables and UI patterns (sections, tab bars, data tables, buttons).

Input:
Template: loadtest.html
Sections: 3
Tabs: 4
Forms/API calls: 6
Has JavaScript: True

Output:
{% extends "base.html" %}
{% block title %}Load Test - AUTARCH{% endblock %}

{% block content %}
<div class="page-header">
    <h1>Load Testing</h1>
</div>

<!-- Test Controls -->
<div class="section" id="controls-section">
    <h2>Test Configuration</h2>
    <div class="tab-bar">
        <button class="tab active" data-tab-group="lt-type" data-tab="http"      onclick="showTab('lt-type','http')">HTTP Flood</button>
        <button class="tab"        data-tab-group="lt-type" data-tab="slowloris"  onclick="showTab('lt-type','slowloris')">Slowloris</button>
        <button class="tab"        data-tab-group="lt-type" data-tab="tcp"        onclick="showTab('lt-type','tcp')">TCP Connect</button>
        <button class="tab"        data-tab-group="lt-type" data-tab="syn"        onclick="showTab('lt-type','syn')">SYN Flood</button>
        <button class="tab"        data-tab-group="lt-type" data-tab="udp"        onclick="showTab('lt-type','udp')">UDP Flood</button>
    </div>

    <!-- HTTP Flood -->
    <div class="tab-content active" data-tab-group="lt-type" data-tab="http">
        <div style="display:grid;grid-template-columns:1fr auto;gap:0.75rem;align-items:end;margin-top:0.75rem">
            <div class="form-group" style="margin-bottom:0">
                <label for="lt-target">Target URL</label>
                <input type="text" id="lt-target" placeholder="https://example.com/api/endpoint">
            </div>
            <div class="form-group" style="margin-bottom:0">
                <label for="lt-method">Method</label>
                <select id="lt-method" style="width:90px">
                    <option value="GET">GET</option>
                    <option value="POST">POST</option>
                    <option value="PUT">PUT</option>
                    <option value="DELETE">DELETE</option>
                    <option value="HEAD">HEAD</option>
                    <option value="PATCH">PATCH</option>
                </select>
            </div>
        </div>
        <div class="form-group" style="margin-top:0.5rem">
            <label for="lt-headers">Custom Headers (JSON)</label>
            <input type="text" id="lt-headers" placeholder='{"Authorization":"Bearer token","Content-Type":"application/json"}'>
        </div>
        <div class="form-group">
            <label for="lt-body">Request Body</label>
            <input type="text" id="lt-body" placeholder='{"key":"value"} or form data'>
        </div>
        <div style="display:flex;gap:0.75rem;flex-wrap:wrap">
            <label style="font-size:0.85rem;display:flex;align-items:center;gap:0.3rem;cursor:pointer">
                <input type="checkbox" id="lt-follow-redirects" checked> Follow redirects
            </label>
            <label style="font-size:0.85rem;display:flex;align-items:center;gap:0.3rem;cursor:pointer">
                <input type="checkbox" id="lt-verify-ssl"> Verify SSL
            </label>
            <label style="font-size:0.85rem;display:flex;align-items:center;gap:0.3rem;cursor:pointer">
                <input type="checkbox" id="lt-rotate-ua" checked> Rotate User-Agents
            </label>
        </div>
    </div>

    <!-- Slowloris -->
    <div class="tab-content" data-tab-group="lt-type" data-tab="slowloris">
        <div style="margin-top:0.75rem">
            <div class="form-group">
                <label for="lt-slowloris-target">Target URL or host:port</label>
                <input type="text" id="lt-slowloris-target" placeholder="https://example.com or 192.168.1.1:80">
            </div>
        </div>
        <p style="font-size:0.8rem;color:var(--text-muted)">Slowloris holds connections open with partial HTTP headers, exhausting the target's connection pool. Each worker manages ~50 sockets.</p>
    </div>

    <!-- TCP Connect -->
    <div class="tab-content" data-tab-group="lt-type" data-tab="tcp">
        <div style="display:grid;grid-template-columns:1fr auto;gap:0.75rem;align-items:end;margin-top:0.75rem">
            <div class="form-group" style="margin-bottom:0">
                <label for="lt-tcp-target">Target (host:port)</label>
                <input type="text" id="lt-tcp-target" placeholder="192.168.1.1:80">
            </div>
            <div class="form-group" style="margin-bottom:0">
                <label for="lt-tcp-payload">Payload (bytes)</label>
                <input type="number" id="lt-tcp-payload" value="0" style="width:90px" min="0" max="65535">
            </div>
        </div>
        <p style="font-size:0.8rem;color:var(--text-muted);margin-top:0.5rem">Rapid TCP connect/disconnect to exhaust server resources. Set payload &gt; 0 to send random data per connection.</p>
    </div>

    <!-- SYN Flood -->
    <div class="tab-content" data-tab-group="lt-type" data-tab="syn">
        <div style="display:grid;grid-template-columns:1fr auto;gap:0.75rem;align-items:end;margin-top:0.75rem">
            <div class="form-group" style="margin-bottom:0">
                <label for="lt-syn-target">Target (host:port)</label>
                <input type="text" id="lt-syn-target" placeholder="192.168.1.1:80">
            </div>
            <div class="form-group" style="margin-bottom:0">
                <label for="lt-syn-srcip">Source IP (optional)</label>
                <input type="text" id="lt-syn-srcip" placeholder="auto-detect" style="width:140px">
            </div>
        </div>
        <p style="font-size:0.8rem;color:var(--warning);margin-top:0.5rem">Requires administrator/root privileges for raw sockets. Falls back to TCP connect flood without admin.</p>
    </div>

    <!-- UDP Flood -->
    <div class="tab-content" data-tab-group="lt-type" data-tab="udp">
        <div style="display:grid;grid-template-columns:1fr auto;gap:0.75rem;align-items:end;margin-top:0.75rem">
            <div class="form-group" style="margin-bottom:0">
                <label for="lt-udp-target">Target (host:port)</label>
                <input type="text" id="lt-udp-target" placeholder="192.168.1.1:53">
            </div>
            <div class="form-group" style="margin-bottom:0">
                <label for="lt-udp-payload">Payload (bytes)</label>
                <input type="number" id="lt-udp-payload" value="1024" style="width:90px" min="1" max="65535">
            </div>
        </div>
        <p style="font-size:0.8rem;color:var(--text-muted);margin-top:0.5rem">Sends UDP packets at maximum rate. Effective against UDP services (DNS, NTP, etc.).</p>
    </div>

    <!-- Common settings -->
    <div style="margin-top:1rem;padding-top:0.75rem;border-top:1px solid var(--border)">
        <div style="display:grid;grid-template-columns:1fr 1fr 1fr 1fr;gap:0.75rem;align-items:end">
            <div class="form-group" style="margin-bottom:0">
                <label for="lt-workers">Workers</label>
                <input type="number" id="lt-workers" value="10" min="1" max="500">
            </div>
            <div class="form-group" style="margin-bottom:0">
                <label for="lt-duration">Duration (s)</label>
                <input type="number" id="lt-duration" value="30" min="0">
            </div>
            <div class="form-group" style="margin-bottom:0">
                <label for="lt-ramp">Ramp Pattern</label>
                <select id="lt-ramp">
                    <option value="constant">Constant</option>
                    <option value="linear">Linear Ramp</option>
                    <option value="step">Step</option>
                    <option value="spike">Spike</option>
                </select>
            </div>
            <div class="form-group" style="margin-bottom:0">
                <label for="lt-ramp-dur">Ramp Time (s)</label>
                <input type="number" id="lt-ramp-dur" value="0" min="0">
            </div>
        </div>
        <div style="display:grid;grid-template-columns:1fr 1fr 1fr 1fr;gap:0.75rem;align-items:end;margin-top:0.5rem">
            <div class="form-group" style="margin-bottom:0">
                <label for="lt-rate">Rate Limit (req/s)</label>
                <input type="number" id="lt-rate" value="0" min="0" placeholder="0 = unlimited">
            </div>
            <div class="form-group" style="margin-bottom:0">
                <label for="lt-timeout">Timeout (s)</label>
                <input type="number" id="lt-timeout" value="10" min="1">
            </div>
            <div class="form-group" style="margin-bottom:0">
                <label for="lt-max-req">Max Req/Worker</label>
                <input type="number" id="lt-max-req" value="0" min="0" placeholder="0 = unlimited">
            </div>
            <div></div>
        </div>
    </div>

    <!-- Launch controls -->
    <div class="tool-actions" style="margin-top:1rem">
        <button id="btn-start" class="btn btn-danger" onclick="startTest()">Start Test</button>
        <button id="btn-pause" class="btn btn-secondary" onclick="pauseTest()" style="display:none">Pause</button>
        <button id="btn-resume" class="btn btn-primary" onclick="resumeTest()" style="display:none">Resume</button>
        <button id="btn-stop" class="btn btn-secondary" onclick="stopTest()" style="display:none">Stop</button>
    </div>
</div>

<!-- Live Dashboard -->
<div class="section" id="dashboard-section" style="display:none">
    <h2>Live Metrics</h2>
    <div style="display:grid;grid-template-columns:repeat(4, 1fr);gap:0.75rem">
        <div class="card" style="text-align:center">
            <div style="font-size:1.8rem;font-weight:700;color:var(--accent)" id="m-rps">0</div>
            <div style="font-size:0.75rem;color:var(--text-muted)">Requests/sec</div>
        </div>
        <div class="card" style="text-align:center">
            <div style="font-size:1.8rem;font-weight:700" id="m-total">0</div>
            <div style="font-size:0.75rem;color:var(--text-muted)">Total Requests</div>
        </div>
        <div class="card" style="text-align:center">
            <div style="font-size:1.8rem;font-weight:700;color:var(--success)" id="m-success">0%</div>
            <div style="font-size:0.75rem;color:var(--text-muted)">Success Rate</div>
        </div>
        <div class="card" style="text-align:center">
            <div style="font-size:1.8rem;font-weight:700;color:var(--warning)" id="m-avg-latency">0ms</div>
            <div style="font-size:0.75rem;color:var(--text-muted)">Avg Latency</div>
        </div>
    </div>

    <!-- Detail metrics -->
    <div style="display:grid;grid-template-columns:1fr 1fr;gap:0.75rem;margin-top:0.75rem">
        <div class="card">
            <h3 style="margin:0 0 0.5rem 0;font-size:0.9rem">Performance</h3>
            <table style="width:100%;font-size:0.85rem">
                <tr><td style="color:var(--text-muted)">Workers</td><td id="m-workers" style="text-align:right">0</td></tr>
                <tr><td style="color:var(--text-muted)">Elapsed</td><td id="m-elapsed" style="text-align:right">0s</td></tr>
                <tr><td style="color:var(--text-muted)">Successful</td><td id="m-ok" style="text-align:right;color:var(--success)">0</td></tr>
                <tr><td style="color:var(--text-muted)">Failed</td><td id="m-fail" style="text-align:right;color:var(--error)">0</td></tr>
                <tr><td style="color:var(--text-muted)">Data Sent</td><td id="m-sent" style="text-align:right">0</td></tr>
                <tr><td style="color:var(--text-muted)">Data Recv</td><td id="m-recv" style="text-align:right">0</td></tr>
            </table>
        </div>
        <div class="card">
            <h3 style="margin:0 0 0.5rem 0;font-size:0.9rem">Latency Percentiles</h3>
            <table style="width:100%;font-size:0.85rem">
                <tr><td style="color:var(--text-muted)">Min</td><td id="m-p-min" style="text-align:right">0ms</td></tr>
                <tr><td style="color:var(--text-muted)">P50 (Median)</td><td id="m-p50" style="text-align:right">0ms</td></tr>
                <tr><td style="color:var(--text-muted)">P95</td><td id="m-p95" style="text-align:right">0ms</td></tr>
                <tr><td style="color:var(--text-muted)">P99</td><td id="m-p99" style="text-align:right">0ms</td></tr>
                <tr><td style="color:var(--text-muted)">Max</td><td id="m-p-max" style="text-align:right">0ms</td></tr>
                <tr><td style="color:var(--text-muted)">Error Rate</td><td id="m-err-rate" style="text-align:right">0%</td></tr>
            </table>
        </div>
    </div>

    <!-- RPS chart (ASCII-style bar chart) -->
    <div class="card" style="margin-top:0.75rem">
        <h3 style="margin:0 0 0.5rem 0;font-size:0.9rem">RPS Over Time</h3>
        <div id="rps-chart" style="height:80px;display:flex;align-items:flex-end;gap:1px;overflow:hidden"></div>
    </div>

    <!-- Status codes & errors -->
    <div style="display:grid;grid-template-columns:1fr 1fr;gap:0.75rem;margin-top:0.75rem">
        <div class="card">
            <h3 style="margin:0 0 0.5rem 0;font-size:0.9rem">Status Codes</h3>
            <div id="m-status-codes" style="font-size:0.85rem"><span style="color:var(--text-muted)">—</span></div>
        </div>
        <div class="card">
            <h3 style="margin:0 0 0.5rem 0;font-size:0.9rem">Top Errors</h3>
            <div id="m-errors" style="font-size:0.85rem"><span style="color:var(--text-muted)">—</span></div>
        </div>
    </div>
</div>

<!-- Presets -->
<div class="section">
    <h2>Quick Presets</h2>
    <div style="display:grid;grid-template-columns:repeat(3, 1fr);gap:0.75rem">
        <button class="btn btn-small" onclick="applyPreset('gentle')">Gentle (5w / 10s)</button>
        <button class="btn btn-small" onclick="applyPreset('moderate')">Moderate (25w / 30s)</button>
        <button class="btn btn-small" onclick="applyPreset('heavy')">Heavy (100w / 60s)</button>
        <button class="btn btn-small" onclick="applyPreset('stress')">Stress (250w / 120s)</button>
        <button class="btn btn-small" onclick="applyPreset('ramp')">Linear Ramp (50w / 60s)</button>
        <button class="btn btn-small" onclick="applyPreset('spike')">Spike Test (100w / 30s)</button>
    </div>
</div>

<script>
let _ltEventSource = null;
let _ltPollTimer = null;

function _v(id) { const el = document.getElementById(id); return el ? el.value.trim() : ''; }

function _getActiveAttackType() {
    const tabs = document.querySelectorAll('[data-tab-group="lt-type"].tab-content');
    for (const t of tabs) {
        if (t.classList.contains('active')) return t.dataset.tab;
    }
    return 'http';
}

function _buildConfig() {
    const type = _getActiveAttackType();
    const config = {
        workers: parseInt(_v('lt-workers')) || 10,
        duration: parseInt(_v('lt-duration')) || 30,
        ramp_pattern: _v('lt-ramp') || 'constant',
        ramp_duration: parseInt(_v('lt-ramp-dur')) || 0,
        rate_limit: parseInt(_v('lt-rate')) || 0,
        timeout: parseInt(_v('lt-timeout')) || 10,
        requests_per_worker: parseInt(_v('lt-max-req')) || 0,
    };

    if (type === 'http') {
        config.attack_type = 'http_flood';
        config.target = _v('lt-target');
        config.method = _v('lt-method') || 'GET';
        config.body = _v('lt-body') || '';
        config.follow_redirects = document.getElementById('lt-follow-redirects').checked;
        config.verify_ssl = document.getElementById('lt-verify-ssl').checked;
        config.rotate_useragent = document.getElementById('lt-rotate-ua').checked;
        try { config.headers = JSON.parse(_v('lt-headers') || '{}'); } catch(e) { config.headers = {}; }
    } else if (type === 'slowloris') {
        config.attack_type = 'slowloris';
        config.target = _v('lt-slowloris-target');
    } else if (type === 'tcp') {
        config.attack_type = 'tcp_connect';
        config.target = _v('lt-tcp-target');
        config.payload_size = parseInt(_v('lt-tcp-payload')) || 0;
    } else if (type === 'syn') {
        config.attack_type = 'syn_flood';
        config.target = _v('lt-syn-target');
        config.source_ip = _v('lt-syn-srcip') || '';
    } else if (type === 'udp') {
        config.attack_type = 'udp_flood';
        config.target = _v('lt-udp-target');
        config.payload_size = parseInt(_v('lt-udp-payload')) || 1024;
    }

    return config;
}

function startTest() {
    const config = _buildConfig();
    if (!config.target) { alert('Enter a target'); return; }

    fetch('/loadtest/start', {
        method: 'POST', headers: {'Content-Type': 'application/json'},
        body: JSON.stringify(config)
    }).then(r => r.json()).then(d => {
        if (!d.ok) { alert(d.error || 'Failed to start'); return; }
        _showRunning();
        _startStream();
    }).catch(e => alert('Error: ' + e.message));
}

function stopTest() {
    fetch('/loadtest/stop', {method: 'POST'}).then(() => {
        _showStopped();
        _stopStream();
    });
}

function pauseTest() {
    fetch('/loadtest/pause', {method: 'POST'}).then(() => {
        document.getElementById('btn-pause').style.display = 'none';
        document.getElementById('btn-resume').style.display = '';
    });
}

function resumeTest() {
    fetch('/loadtest/resume', {method: 'POST'}).then(() => {
        document.getElementById('btn-resume').style.display = 'none';
        document.getElementById('btn-pause').style.display = '';
    });
}

function _showRunning() {
    document.getElementById('btn-start').style.display = 'none';
    document.getElementById('btn-pause').style.display = '';
    document.getElementById('btn-stop').style.display = '';
    document.getElementById('btn-resume').style.display = 'none';
    document.getElementById('dashboard-section').style.display = '';
}

function _showStopped() {
    document.getElementById('btn-start').style.display = '';
    document.getElementById('btn-pause').style.display = 'none';
    document.getElementById('btn-stop').style.display = 'none';
    document.getElementById('btn-resume').style.display = 'none';
}

function _startStream() {
    _stopStream();
    // Use polling as a reliable fallback (SSE can be flaky through proxies)
    _ltPollTimer = setInterval(function() {
        fetch('/loadtest/status').then(r => r.json()).then(d => {
            if (!d.running) {
                _showStopped();
                _stopStream();
            }
            if (d.metrics) _updateMetrics(d.metrics);
        }).catch(() => {});
    }, 1000);
}

function _stopStream() {
    if (_ltEventSource) { _ltEventSource.close(); _ltEventSource = null; }
    if (_ltPollTimer) { clearInterval(_ltPollTimer); _ltPollTimer = null; }
}

function _fmtBytes(b) {
    if (b < 1024) return b + ' B';
    if (b < 1048576) return (b / 1024).toFixed(1) + ' KB';
    if (b < 1073741824) return (b / 1048576).toFixed(1) + ' MB';
    return (b / 1073741824).toFixed(2) + ' GB';
}

function _updateMetrics(m) {
    document.getElementById('m-rps').textContent = m.rps.toFixed(1);
    document.getElementById('m-total').textContent = m.total_requests;
    document.getElementById('m-success').textContent = m.success_rate.toFixed(1) + '%';
    document.getElementById('m-avg-latency').textContent = m.avg_latency.toFixed(0) + 'ms';

    document.getElementById('m-workers').textContent = m.active_workers;
    document.getElementById('m-elapsed').textContent = m.elapsed.toFixed(0) + 's';
    document.getElementById('m-ok').textContent = m.successful;
    document.getElementById('m-fail').textContent = m.failed;
    document.getElementById('m-sent').textContent = _fmtBytes(m.bytes_sent);
    document.getElementById('m-recv').textContent = _fmtBytes(m.bytes_received);

    document.getElementById('m-p-min').textContent = m.min_latency.toFixed(1) + 'ms';
    document.getElementById('m-p50').textContent = m.p50_latency.toFixed(1) + 'ms';
    document.getElementById('m-p95').textContent = m.p95_latency.toFixed(1) + 'ms';
    document.getElementById('m-p99').textContent = m.p99_latency.toFixed(1) + 'ms';
    document.getElementById('m-p-max').textContent = m.max_latency.toFixed(1) + 'ms';
    document.getElementById('m-err-rate').textContent = m.error_rate.toFixed(1) + '%';

    // Status codes
    const codes = m.status_codes || {};
    const codeKeys = Object.keys(codes).sort();
    if (codeKeys.length) {
        document.getElementById('m-status-codes').innerHTML = codeKeys.map(c => {
            const color = c < 300 ? 'var(--success)' : c < 400 ? 'var(--warning)' : 'var(--error)';
            return '<span style="color:' + color + '">' + escapeHtml(c) + '</span>: ' + codes[c];
        }).join(' &nbsp; ');
    }

    // Errors
    const errs = m.top_errors || {};
    const errKeys = Object.keys(errs);
    if (errKeys.length) {
        document.getElementById('m-errors').innerHTML = errKeys.map(e =>
            '<div>' + errs[e] + '&times; <span style="color:var(--text-muted)">' + escapeHtml(e) + '</span></div>'
        ).join('');
    }

    // RPS chart
    const rpsHist = m.rps_history || [];
    if (rpsHist.length > 1) {
        const chart = document.getElementById('rps-chart');
        const maxRps = Math.max(...rpsHist, 1);
        chart.innerHTML = rpsHist.map(r => {
            const h = Math.max(2, (r / maxRps) * 70);
            return '<div style="flex:1;min-width:2px;background:var(--accent);height:' + h + 'px;border-radius:1px 1px 0 0" title="' + r + ' req/s"></div>';
        }).join('');
    }
}

function applyPreset(name) {
    const presets = {
        'gentle':   {workers: 5,   duration: 10,  ramp: 'constant', rampDur: 0},
        'moderate': {workers: 25,  duration: 30,  ramp: 'constant', rampDur: 0},
        'heavy':    {workers: 100, duration: 60,  ramp: 'constant', rampDur: 0},
        'stress':   {workers: 250, duration: 120, ramp: 'constant', rampDur: 0},
        'ramp':     {workers: 50,  duration: 60,  ramp: 'linear',   rampDur: 30},
        'spike':    {workers: 100, duration: 30,  ramp: 'spike',    rampDur: 10},
    };
    const p = presets[name];
    if (!p) return;
    document.getElementById('lt-workers').value = p.workers;
    document.getElementById('lt-duration').value = p.duration;
    document.getElementById('lt-ramp').value = p.ramp;
    document.getElementById('lt-ramp-dur').value = p.rampDur;
}

// On load: check if test is already running
document.addEventListener('DOMContentLoaded', function() {
    fetch('/loadtest/status').then(r => r.json()).then(d => {
        if (d.running) {
            _showRunning();
            _startStream();
            if (d.metrics) _updateMetrics(d.metrics);
        }
    }).catch(() => {});
});
</script>
{% endblock %}


Instruction: Create an AUTARCH web template for the 'Log Correlator' page. It should extend base.html, have a page header, and use AUTARCH's CSS variables and UI patterns (sections, tab bars, data tables, buttons).

Input:
Template: log_correlator.html
Sections: 12
Tabs: 3
Forms/API calls: 0
Has JavaScript: True

Output:
{% extends "base.html" %}
{% block title %}AUTARCH — Log Correlator{% endblock %}

{% block content %}
<div class="page-header">
    <h1>Log Correlator</h1>
    <p style="margin:0;font-size:0.85rem;color:var(--text-secondary)">
        Ingest, correlate, and alert on security events from multiple log sources.
    </p>
</div>

<!-- Tab Bar -->
<div class="tab-bar">
    <button class="tab active" data-tab-group="logs" data-tab="ingest" onclick="showTab('logs','ingest')">Ingest</button>
    <button class="tab" data-tab-group="logs" data-tab="alerts" onclick="showTab('logs','alerts')">Alerts</button>
    <button class="tab" data-tab-group="logs" data-tab="rules" onclick="showTab('logs','rules')">Rules</button>
    <button class="tab" data-tab-group="logs" data-tab="stats" onclick="showTab('logs','stats')">Stats</button>
</div>

<!-- ==================== INGEST TAB ==================== -->
<div class="tab-content active" data-tab-group="logs" data-tab="ingest">

<div class="section">
    <h2>Ingest from File</h2>
    <div class="input-row">
        <input type="text" id="log-ingest-path" placeholder="Log file path (e.g. /var/log/auth.log)">
        <button id="btn-ingest-file" class="btn btn-primary" onclick="logIngestFile()">Ingest File</button>
    </div>
    <pre class="output-panel" id="log-ingest-file-output" style="min-height:0"></pre>
</div>

<div class="section">
    <h2>Paste Log Data</h2>
    <div class="form-group">
        <label>Paste raw log entries</label>
        <textarea id="log-ingest-paste" rows="6" style="width:100%;background:var(--bg-input);border:1px solid var(--border);border-radius:var(--radius);color:var(--text-primary);padding:10px;font-family:monospace;font-size:0.85rem;resize:vertical" placeholder="Paste log lines here..."></textarea>
    </div>
    <div class="tool-actions">
        <button id="btn-ingest-paste" class="btn btn-primary" onclick="logIngestPaste()">Ingest Pasted Data</button>
    </div>
    <pre class="output-panel" id="log-ingest-paste-output" style="min-height:0"></pre>
</div>

<div class="section">
    <h2>Sources</h2>
    <div class="tool-actions" style="margin-bottom:12px">
        <button class="btn btn-small" onclick="logLoadSources()">Refresh</button>
    </div>
    <table class="data-table">
        <thead><tr><th>Source</th><th>Type</th><th>Entries</th><th>Last Ingested</th></tr></thead>
        <tbody id="log-sources-table">
            <tr><td colspan="4" class="empty-state">No log sources ingested yet.</td></tr>
        </tbody>
    </table>
</div>

<div class="section">
    <h2>Search Logs</h2>
    <div class="input-row">
        <input type="text" id="log-search-query" placeholder="Search pattern (regex supported)" onkeydown="if(event.key==='Enter')logSearch()">
        <button id="btn-log-search" class="btn btn-primary" onclick="logSearch()">Search</button>
    </div>
    <span id="log-search-count" style="font-size:0.8rem;color:var(--text-muted)"></span>
    <table class="data-table" style="margin-top:8px">
        <thead><tr><th>Timestamp</th><th>Source</th><th>Log Entry</th></tr></thead>
        <tbody id="log-search-results">
            <tr><td colspan="3" class="empty-state">Enter a query and click Search.</td></tr>
        </tbody>
    </table>
</div>

<div class="section">
    <div class="tool-actions">
        <button class="btn btn-danger btn-small" onclick="logClearAll()">Clear All Logs</button>
    </div>
</div>

</div>

<!-- ==================== ALERTS TAB ==================== -->
<div class="tab-content" data-tab-group="logs" data-tab="alerts">

<div class="section">
    <h2>Security Alerts</h2>
    <div style="display:flex;gap:8px;align-items:center;margin-bottom:12px;flex-wrap:wrap">
        <span style="font-size:0.85rem;color:var(--text-secondary)">Severity:</span>
        <button class="btn btn-small log-sev-btn active" data-severity="all" onclick="logFilterAlerts('all',this)">All</button>
        <button class="btn btn-small log-sev-btn" data-severity="critical" onclick="logFilterAlerts('critical',this)" style="border-color:var(--danger);color:var(--danger)">Critical</button>
        <button class="btn btn-small log-sev-btn" data-severity="high" onclick="logFilterAlerts('high',this)" style="border-color:#f97316;color:#f97316">High</button>
        <button class="btn btn-small log-sev-btn" data-severity="medium" onclick="logFilterAlerts('medium',this)" style="border-color:var(--warning);color:var(--warning)">Medium</button>
        <button class="btn btn-small log-sev-btn" data-severity="low" onclick="logFilterAlerts('low',this)" style="border-color:var(--accent);color:var(--accent)">Low</button>
        <button class="btn btn-small" style="margin-left:auto" onclick="logRefreshAlerts()">Refresh</button>
    </div>
    <table class="data-table">
        <thead><tr><th>Timestamp</th><th>Rule</th><th>Severity</th><th>Source</th><th>Log Entry</th></tr></thead>
        <tbody id="log-alerts-table">
            <tr><td colspan="5" class="empty-state">No alerts triggered yet.</td></tr>
        </tbody>
    </table>
    <div class="tool-actions" style="margin-top:12px">
        <button class="btn btn-danger btn-small" onclick="logClearAlerts()">Clear Alerts</button>
    </div>
</div>

</div>

<!-- ==================== RULES TAB ==================== -->
<div class="tab-content" data-tab-group="logs" data-tab="rules">

<div class="section">
    <h2>Detection Rules</h2>
    <div class="tool-actions" style="margin-bottom:12px">
        <button class="btn btn-small" onclick="logLoadRules()">Refresh</button>
    </div>
    <table class="data-table">
        <thead><tr><th>ID</th><th>Name</th><th>Pattern</th><th>Severity</th><th>Type</th><th>Action</th></tr></thead>
        <tbody id="log-rules-table">
            <tr><td colspan="6" class="empty-state">No rules loaded.</td></tr>
        </tbody>
    </table>
</div>

<div class="section">
    <h2>Add Custom Rule</h2>
    <div class="form-row" style="margin-bottom:8px">
        <div class="form-group">
            <label>Rule ID</label>
            <input type="text" id="log-rule-id" placeholder="e.g. CUSTOM-001">
        </div>
        <div class="form-group">
            <label>Name</label>
            <input type="text" id="log-rule-name" placeholder="e.g. SSH Root Login">
        </div>
    </div>
    <div class="form-row" style="margin-bottom:8px">
        <div class="form-group" style="flex:2">
            <label>Pattern (regex)</label>
            <input type="text" id="log-rule-pattern" placeholder="e.g. Failed password for root">
        </div>
        <div class="form-group">
            <label>Severity</label>
            <select id="log-rule-severity">
                <option value="low">Low</option>
                <option value="medium" selected>Medium</option>
                <option value="high">High</option>
                <option value="critical">Critical</option>
            </select>
        </div>
    </div>
    <div class="form-row" style="margin-bottom:12px">
        <div class="form-group">
            <label>Threshold (count)</label>
            <input type="number" id="log-rule-threshold" value="1" min="1" max="10000">
        </div>
        <div class="form-group">
            <label>Window (seconds)</label>
            <input type="number" id="log-rule-window" value="300" min="1" max="86400">
        </div>
    </div>
    <div class="tool-actions">
        <button id="btn-add-rule" class="btn btn-primary" onclick="logAddRule()">Add Rule</button>
    </div>
    <pre class="output-panel" id="log-rule-output" style="min-height:0"></pre>
</div>

</div>

<!-- ==================== STATS TAB ==================== -->
<div class="tab-content" data-tab-group="logs" data-tab="stats">

<div class="section">
    <h2>Overview</h2>
    <div class="stats-grid">
        <div class="stat-card">
            <div class="stat-label">Total Logs</div>
            <div class="stat-value" id="log-stat-total">--</div>
        </div>
        <div class="stat-card">
            <div class="stat-label">Total Alerts</div>
            <div class="stat-value" id="log-stat-alerts">--</div>
        </div>
        <div class="stat-card">
            <div class="stat-label">Sources</div>
            <div class="stat-value" id="log-stat-sources">--</div>
        </div>
        <div class="stat-card">
            <div class="stat-label">Active Rules</div>
            <div class="stat-value" id="log-stat-rules">--</div>
        </div>
    </div>
    <div class="tool-actions" style="margin-bottom:12px">
        <button class="btn btn-small" onclick="logLoadStats()">Refresh Stats</button>
    </div>
</div>

<div class="section">
    <h2>Alerts by Severity</h2>
    <table class="data-table" style="max-width:400px">
        <tbody id="log-stats-severity">
            <tr><td>Critical</td><td id="log-sev-critical">--</td></tr>
            <tr><td>High</td><td id="log-sev-high">--</td></tr>
            <tr><td>Medium</td><td id="log-sev-medium">--</td></tr>
            <tr><td>Low</td><td id="log-sev-low">--</td></tr>
        </tbody>
    </table>
</div>

<div class="section">
    <h2>Top Triggered Rules</h2>
    <table class="data-table">
        <thead><tr><th>Rule</th><th>Count</th><th>Last Triggered</th></tr></thead>
        <tbody id="log-stats-top-rules">
            <tr><td colspan="3" class="empty-state">No data yet.</td></tr>
        </tbody>
    </table>
</div>

<div class="section">
    <h2>Timeline (Hourly Alert Counts)</h2>
    <div id="log-stats-timeline" style="background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);padding:16px;min-height:120px">
        <div id="log-timeline-bars" style="display:flex;align-items:flex-end;gap:2px;height:100px"></div>
        <div id="log-timeline-labels" style="display:flex;gap:2px;font-size:0.65rem;color:var(--text-muted);margin-top:4px"></div>
        <p id="log-timeline-empty" class="empty-state" style="margin:0;padding:24px 0">No timeline data yet. Ingest logs and trigger rules to populate.</p>
    </div>
</div>

</div>

<script>
function esc(s) { return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;'); }

var _currentSevFilter = 'all';

/* ── Ingest ── */
function logIngestFile() {
    var path = document.getElementById('log-ingest-path').value.trim();
    if (!path) return;
    var btn = document.getElementById('btn-ingest-file');
    setLoading(btn, true);
    postJSON('/logs/ingest/file', {path: path}).then(function(data) {
        setLoading(btn, false);
        renderOutput('log-ingest-file-output', data.message || data.error || 'Done');
        if (data.success) logLoadSources();
    }).catch(function() { setLoading(btn, false); });
}

function logIngestPaste() {
    var text = document.getElementById('log-ingest-paste').value.trim();
    if (!text) return;
    var btn = document.getElementById('btn-ingest-paste');
    setLoading(btn, true);
    postJSON('/logs/ingest/paste', {data: text}).then(function(data) {
        setLoading(btn, false);
        renderOutput('log-ingest-paste-output', data.message || data.error || 'Done');
        if (data.success) logLoadSources();
    }).catch(function() { setLoading(btn, false); });
}

function logLoadSources() {
    fetchJSON('/logs/sources').then(function(data) {
        var tb = document.getElementById('log-sources-table');
        var sources = data.sources || [];
        if (!sources.length) {
            tb.innerHTML = '<tr><td colspan="4" class="empty-state">No log sources ingested yet.</td></tr>';
            return;
        }
        var html = '';
        sources.forEach(function(s) {
            html += '<tr><td>' + esc(s.name) + '</td><td>' + esc(s.type) + '</td>'
                + '<td>' + (s.entries || 0) + '</td><td>' + esc(s.last_ingested || '--') + '</td></tr>';
        });
        tb.innerHTML = html;
    });
}

function logSearch() {
    var query = document.getElementById('log-search-query').value.trim();
    if (!query) return;
    var btn = document.getElementById('btn-log-search');
    setLoading(btn, true);
    postJSON('/logs/search', {query: query}).then(function(data) {
        setLoading(btn, false);
        var results = data.results || [];
        document.getElementById('log-search-count').textContent = results.length + ' results';
        var tb = document.getElementById('log-search-results');
        if (!results.length) {
            tb.innerHTML = '<tr><td colspan="3" class="empty-state">No matches found.</td></tr>';
            return;
        }
        var html = '';
        results.forEach(function(r) {
            html += '<tr><td style="white-space:nowrap;font-size:0.8rem">' + esc(r.timestamp || '--') + '</td>'
                + '<td>' + esc(r.source || '--') + '</td>'
                + '<td style="font-family:monospace;font-size:0.8rem">' + esc(r.entry) + '</td></tr>';
        });
        tb.innerHTML = html;
    }).catch(function() { setLoading(btn, false); });
}

function logClearAll() {
    if (!confirm('Clear all ingested logs? This cannot be undone.')) return;
    postJSON('/logs/clear', {}).then(function(data) {
        if (data.success) {
            logLoadSources();
            document.getElementById('log-search-results').innerHTML = '<tr><td colspan="3" class="empty-state">No matches found.</td></tr>';
            document.getElementById('log-search-count').textContent = '';
        }
    });
}

/* ── Alerts ── */
function logRefreshAlerts() {
    logFilterAlerts(_currentSevFilter);
}

function logFilterAlerts(severity, btnEl) {
    _currentSevFilter = severity;
    document.querySelectorAll('.log-sev-btn').forEach(function(b) {
        b.classList.toggle('active', b.dataset.severity === severity);
    });
    fetchJSON('/logs/alerts?severity=' + severity).then(function(data) {
        var tb = document.getElementById('log-alerts-table');
        var alerts = data.alerts || [];
        if (!alerts.length) {
            tb.innerHTML = '<tr><td colspan="5" class="empty-state">No alerts' + (severity !== 'all' ? ' with severity "' + severity + '"' : '') + '.</td></tr>';
            return;
        }
        var html = '';
        alerts.forEach(function(a) {
            var sev = (a.severity || 'low').toLowerCase();
            var badgeClass = sev === 'critical' ? 'badge-fail'
                           : sev === 'high' ? 'badge-high'
                           : sev === 'medium' ? 'badge-medium' : 'badge-low';
            html += '<tr><td style="white-space:nowrap;font-size:0.8rem">' + esc(a.timestamp || '--') + '</td>'
                + '<td>' + esc(a.rule || '--') + '</td>'
                + '<td><span class="badge ' + badgeClass + '">' + esc(a.severity) + '</span></td>'
                + '<td>' + esc(a.source || '--') + '</td>'
                + '<td style="font-family:monospace;font-size:0.8rem;max-width:300px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">' + esc(a.entry || '') + '</td></tr>';
        });
        tb.innerHTML = html;
    });
}

function logClearAlerts() {
    if (!confirm('Clear all alerts?')) return;
    postJSON('/logs/alerts/clear', {}).then(function(data) {
        if (data.success) logRefreshAlerts();
    });
}

/* ── Rules ── */
function logLoadRules() {
    fetchJSON('/logs/rules').then(function(data) {
        var tb = document.getElementById('log-rules-table');
        var rules = data.rules || [];
        if (!rules.length) {
            tb.innerHTML = '<tr><td colspan="6" class="empty-state">No rules loaded.</td></tr>';
            return;
        }
        var html = '';
        rules.forEach(function(r) {
            var sev = (r.severity || 'low').toLowerCase();
            var badgeClass = sev === 'critical' ? 'badge-fail'
                           : sev === 'high' ? 'badge-high'
                           : sev === 'medium' ? 'badge-medium' : 'badge-low';
            var typeBadge = r.builtin ? '<span class="badge badge-info">Built-in</span>' : '<span class="badge badge-medium">Custom</span>';
            var deleteBtn = r.builtin ? '' : '<button class="btn btn-danger btn-small" onclick="logDeleteRule(\'' + esc(r.id) + '\')">Delete</button>';
            html += '<tr><td style="font-family:monospace;font-size:0.85rem">' + esc(r.id) + '</td>'
                + '<td>' + esc(r.name) + '</td>'
                + '<td style="font-family:monospace;font-size:0.8rem">' + esc(r.pattern) + '</td>'
                + '<td><span class="badge ' + badgeClass + '">' + esc(r.severity) + '</span></td>'
                + '<td>' + typeBadge + '</td>'
                + '<td>' + deleteBtn + '</td></tr>';
        });
        tb.innerHTML = html;
    });
}

function logAddRule() {
    var rule = {
        id: document.getElementById('log-rule-id').value.trim(),
        name: document.getElementById('log-rule-name').value.trim(),
        pattern: document.getElementById('log-rule-pattern').value.trim(),
        severity: document.getElementById('log-rule-severity').value,
        threshold: parseInt(document.getElementById('log-rule-threshold').value) || 1,
        window: parseInt(document.getElementById('log-rule-window').value) || 300
    };
    if (!rule.id || !rule.name || !rule.pattern) {
        renderOutput('log-rule-output', 'Rule ID, Name, and Pattern are required.');
        return;
    }
    var btn = document.getElementById('btn-add-rule');
    setLoading(btn, true);
    postJSON('/logs/rules/add', rule).then(function(data) {
        setLoading(btn, false);
        renderOutput('log-rule-output', data.message || data.error || 'Done');
        if (data.success) {
            logLoadRules();
            document.getElementById('log-rule-id').value = '';
            document.getElementById('log-rule-name').value = '';
            document.getElementById('log-rule-pattern').value = '';
        }
    }).catch(function() { setLoading(btn, false); });
}

function logDeleteRule(id) {
    if (!confirm('Delete rule "' + id + '"?')) return;
    postJSON('/logs/rules/delete', {id: id}).then(function(data) {
        if (data.success) logLoadRules();
    });
}

/* ── Stats ── */
function logLoadStats() {
    fetchJSON('/logs/stats').then(function(data) {
        document.getElementById('log-stat-total').textContent = data.total_logs || 0;
        document.getElementById('log-stat-alerts').textContent = data.total_alerts || 0;
        document.getElementById('log-stat-sources').textContent = data.total_sources || 0;
        document.getElementById('log-stat-rules').textContent = data.total_rules || 0;

        var bySev = data.alerts_by_severity || {};
        document.getElementById('log-sev-critical').textContent = bySev.critical || 0;
        document.getElementById('log-sev-high').textContent = bySev.high || 0;
        document.getElementById('log-sev-medium').textContent = bySev.medium || 0;
        document.getElementById('log-sev-low').textContent = bySev.low || 0;

        var topRules = data.top_rules || [];
        var trTb = document.getElementById('log-stats-top-rules');
        if (!topRules.length) {
            trTb.innerHTML = '<tr><td colspan="3" class="empty-state">No data yet.</td></tr>';
        } else {
            var html = '';
            topRules.forEach(function(r) {
                html += '<tr><td>' + esc(r.name) + '</td><td>' + r.count + '</td><td>' + esc(r.last_triggered || '--') + '</td></tr>';
            });
            trTb.innerHTML = html;
        }

        /* Timeline bars */
        var timeline = data.timeline || [];
        var emptyMsg = document.getElementById('log-timeline-empty');
        var barsEl = document.getElementById('log-timeline-bars');
        var labelsEl = document.getElementById('log-timeline-labels');
        if (!timeline.length) {
            emptyMsg.style.display = 'block';
            barsEl.innerHTML = '';
            labelsEl.innerHTML = '';
        } else {
            emptyMsg.style.display = 'none';
            var maxVal = Math.max.apply(null, timeline.map(function(t) { return t.count; })) || 1;
            var barsHtml = '';
            var labelsHtml = '';
            timeline.forEach(function(t) {
                var pct = Math.max(2, Math.round((t.count / maxVal) * 100));
                var color = t.count > maxVal * 0.7 ? 'var(--danger)' : t.count > maxVal * 0.4 ? 'var(--warning)' : 'var(--accent)';
                barsHtml += '<div style="flex:1;height:' + pct + '%;background:' + color + ';border-radius:2px 2px 0 0;min-width:4px" title="' + esc(t.hour) + ': ' + t.count + ' alerts"></div>';
                labelsHtml += '<div style="flex:1;text-align:center;min-width:4px">' + esc(t.hour || '') + '</div>';
            });
            barsEl.innerHTML = barsHtml;
            labelsEl.innerHTML = labelsHtml;
        }
    });
}

/* ── Init ── */
document.addEventListener('DOMContentLoaded', function() {
    logLoadSources();
    logLoadRules();
    logRefreshAlerts();
    logLoadStats();
});
</script>
{% endblock %}


Instruction: Create an AUTARCH web template for the 'Malware Sandbox' page. It should extend base.html, have a page header, and use AUTARCH's CSS variables and UI patterns (sections, tab bars, data tables, buttons).

Input:
Template: malware_sandbox.html
Sections: 8
Tabs: 2
Forms/API calls: 1
Has JavaScript: True

Output:
{% extends "base.html" %}
{% block title %}AUTARCH — Malware Sandbox{% endblock %}

{% block content %}
<div class="page-header">
    <h1>Malware Sandbox</h1>
    <p style="margin:0;font-size:0.85rem;color:var(--text-secondary)">
        Submit, analyze, and report on suspicious files using static and dynamic analysis.
    </p>
</div>

<!-- Tab Bar -->
<div class="tab-bar">
    <button class="tab active" data-tab-group="sandbox" data-tab="submit" onclick="showTab('sandbox','submit')">Submit</button>
    <button class="tab" data-tab-group="sandbox" data-tab="analyze" onclick="showTab('sandbox','analyze')">Analyze</button>
    <button class="tab" data-tab-group="sandbox" data-tab="reports" onclick="showTab('sandbox','reports')">Reports</button>
</div>

<!-- ==================== SUBMIT TAB ==================== -->
<div class="tab-content active" data-tab-group="sandbox" data-tab="submit">

<div class="section">
    <h2>Submit Sample</h2>
    <p style="font-size:0.8rem;color:var(--text-muted);margin-bottom:12px">
        Upload a file or specify a path on the server to submit for analysis.
    </p>

    <div class="form-row" style="margin-bottom:12px">
        <div class="form-group">
            <label>Upload File</label>
            <input type="file" id="sandbox-upload-file">
        </div>
    </div>
    <div style="font-size:0.8rem;color:var(--text-muted);text-align:center;margin-bottom:12px">-- OR --</div>
    <div class="form-row" style="margin-bottom:12px">
        <div class="form-group">
            <label>Server File Path</label>
            <input type="text" id="sandbox-file-path" placeholder="/path/to/suspicious/file">
        </div>
    </div>
    <div class="tool-actions" style="margin-bottom:12px">
        <button id="btn-sandbox-submit" class="btn btn-primary" onclick="sandboxSubmit()">Submit Sample</button>
    </div>
    <pre class="output-panel" id="sandbox-submit-output" style="min-height:0"></pre>
</div>

<div class="section">
    <h2>Submitted Samples</h2>
    <div class="tool-actions" style="margin-bottom:12px">
        <button class="btn btn-small" onclick="sandboxLoadSamples()">Refresh</button>
    </div>
    <table class="data-table">
        <thead><tr><th>Name</th><th>Size</th><th>SHA256</th><th>Submitted</th><th>Status</th></tr></thead>
        <tbody id="sandbox-samples-table">
            <tr><td colspan="5" class="empty-state">No samples submitted yet.</td></tr>
        </tbody>
    </table>
</div>

</div>

<!-- ==================== ANALYZE TAB ==================== -->
<div class="tab-content" data-tab-group="sandbox" data-tab="analyze">

<div class="section">
    <h2>Select Sample</h2>
    <div class="input-row">
        <select id="sandbox-sample-select" style="flex:2">
            <option value="">-- Select a sample --</option>
        </select>
        <button class="btn btn-small" onclick="sandboxRefreshSelect()">Refresh List</button>
    </div>
</div>

<div class="section">
    <h2>Static Analysis</h2>
    <p style="font-size:0.8rem;color:var(--text-muted);margin-bottom:8px">
        Inspect file headers, strings, imports, and calculate risk score without execution.
    </p>
    <div class="tool-actions" style="margin-bottom:12px">
        <button id="btn-static" class="btn btn-primary" onclick="sandboxStatic()">Run Static Analysis</button>
    </div>

    <!-- Risk Score Gauge -->
    <div id="sandbox-static-results" style="display:none">
        <div style="display:flex;gap:24px;align-items:flex-start;flex-wrap:wrap;margin-bottom:16px">
            <div class="score-display">
                <div class="score-value" id="sandbox-risk-score">--</div>
                <div class="score-label">Risk Score</div>
            </div>
            <div style="flex:1;min-width:250px">
                <table class="data-table" style="font-size:0.85rem">
                    <tbody>
                        <tr><td>File Type</td><td id="sandbox-file-type">--</td></tr>
                        <tr><td>File Size</td><td id="sandbox-file-size">--</td></tr>
                        <tr><td>MD5</td><td id="sandbox-md5" style="font-family:monospace;font-size:0.8rem">--</td></tr>
                        <tr><td>SHA256</td><td id="sandbox-sha256" style="font-family:monospace;font-size:0.8rem;word-break:break-all">--</td></tr>
                    </tbody>
                </table>
            </div>
        </div>

        <h3>Indicators by Category</h3>
        <div id="sandbox-indicators" style="margin-bottom:16px"></div>

        <h3>Interesting Strings</h3>
        <pre class="output-panel scrollable" id="sandbox-strings" style="max-height:200px"></pre>
    </div>
</div>

<div class="section">
    <h2>Dynamic Analysis</h2>
    <p style="font-size:0.8rem;color:var(--text-muted);margin-bottom:8px">
        Execute sample in an isolated Docker container and monitor behavior.
    </p>
    <div class="tool-actions" style="margin-bottom:12px">
        <button id="btn-dynamic" class="btn btn-danger" onclick="sandboxDynamic()">Run Dynamic Analysis</button>
        <span id="sandbox-dynamic-status" style="font-size:0.8rem;color:var(--text-muted);margin-left:12px"></span>
    </div>

    <div id="sandbox-dynamic-results" style="display:none">
        <h3>Syscalls</h3>
        <pre class="output-panel scrollable" id="sandbox-syscalls" style="max-height:200px"></pre>

        <h3 style="margin-top:12px">Files Accessed</h3>
        <pre class="output-panel scrollable" id="sandbox-files" style="max-height:200px"></pre>

        <h3 style="margin-top:12px">Network Calls</h3>
        <pre class="output-panel scrollable" id="sandbox-network" style="max-height:200px"></pre>
    </div>
</div>

</div>

<!-- ==================== REPORTS TAB ==================== -->
<div class="tab-content" data-tab-group="sandbox" data-tab="reports">

<div class="section">
    <h2>Analysis Reports</h2>
    <div class="tool-actions" style="margin-bottom:12px">
        <button class="btn btn-small" onclick="sandboxLoadReports()">Refresh</button>
    </div>
    <table class="data-table">
        <thead><tr><th>Sample</th><th>Risk Level</th><th>Date</th><th>Action</th></tr></thead>
        <tbody id="sandbox-reports-table">
            <tr><td colspan="4" class="empty-state">No reports generated yet.</td></tr>
        </tbody>
    </table>
</div>

<div class="section">
    <h2>Generate Report</h2>
    <div class="input-row">
        <select id="sandbox-report-sample" style="flex:2">
            <option value="">-- Select a sample --</option>
        </select>
        <button id="btn-gen-report" class="btn btn-primary" onclick="sandboxGenReport()">Generate Report</button>
    </div>
</div>

<div class="section" id="sandbox-report-viewer" style="display:none">
    <h2>Report</h2>
    <div id="sandbox-report-content"></div>
</div>

</div>

<script>
function esc(s) { return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;'); }

var _dynamicPoll = null;

/* ── Submit ── */
function sandboxSubmit() {
    var btn = document.getElementById('btn-sandbox-submit');
    var fileInput = document.getElementById('sandbox-upload-file');
    var pathInput = document.getElementById('sandbox-file-path').value.trim();

    if (fileInput.files.length > 0) {
        setLoading(btn, true);
        var fd = new FormData();
        fd.append('file', fileInput.files[0]);
        fetch('/sandbox/submit', {method: 'POST', body: fd}).then(function(r) { return r.json(); }).then(function(data) {
            setLoading(btn, false);
            renderOutput('sandbox-submit-output', data.message || data.error || 'Submitted');
            if (data.success) { sandboxLoadSamples(); sandboxRefreshSelect(); }
        }).catch(function() { setLoading(btn, false); renderOutput('sandbox-submit-output', 'Upload failed'); });
    } else if (pathInput) {
        setLoading(btn, true);
        postJSON('/sandbox/submit', {path: pathInput}).then(function(data) {
            setLoading(btn, false);
            renderOutput('sandbox-submit-output', data.message || data.error || 'Submitted');
            if (data.success) { sandboxLoadSamples(); sandboxRefreshSelect(); }
        }).catch(function() { setLoading(btn, false); });
    } else {
        renderOutput('sandbox-submit-output', 'Select a file or enter a path.');
    }
}

function sandboxLoadSamples() {
    fetchJSON('/sandbox/samples').then(function(data) {
        var tb = document.getElementById('sandbox-samples-table');
        var samples = data.samples || [];
        if (!samples.length) {
            tb.innerHTML = '<tr><td colspan="5" class="empty-state">No samples submitted yet.</td></tr>';
            return;
        }
        var html = '';
        samples.forEach(function(s) {
            var statusBadge = s.status === 'analyzed' ? '<span class="badge badge-pass">Analyzed</span>'
                            : s.status === 'pending'  ? '<span class="badge badge-medium">Pending</span>'
                            : '<span class="badge badge-info">' + esc(s.status) + '</span>';
            html += '<tr><td>' + esc(s.name) + '</td><td>' + esc(s.size) + '</td>'
                + '<td style="font-family:monospace;font-size:0.75rem;word-break:break-all">' + esc(s.sha256 || '--') + '</td>'
                + '<td>' + esc(s.date) + '</td><td>' + statusBadge + '</td></tr>';
        });
        tb.innerHTML = html;
    });
}

function sandboxRefreshSelect() {
    fetchJSON('/sandbox/samples').then(function(data) {
        var samples = data.samples || [];
        var opts = '<option value="">-- Select a sample --</option>';
        samples.forEach(function(s) {
            opts += '<option value="' + esc(s.id || s.sha256) + '">' + esc(s.name) + ' (' + esc(s.size) + ')</option>';
        });
        document.getElementById('sandbox-sample-select').innerHTML = opts;
        document.getElementById('sandbox-report-sample').innerHTML = opts;
    });
}

/* ── Static Analysis ── */
function sandboxStatic() {
    var sampleId = document.getElementById('sandbox-sample-select').value;
    if (!sampleId) { alert('Select a sample first.'); return; }
    var btn = document.getElementById('btn-static');
    setLoading(btn, true);
    document.getElementById('sandbox-static-results').style.display = 'none';

    postJSON('/sandbox/analyze/static', {sample_id: sampleId}).then(function(data) {
        setLoading(btn, false);
        if (data.error) { alert('Error: ' + data.error); return; }
        document.getElementById('sandbox-static-results').style.display = 'block';

        var score = data.risk_score || 0;
        var scoreEl = document.getElementById('sandbox-risk-score');
        scoreEl.textContent = score + '/100';
        scoreEl.style.color = score >= 70 ? 'var(--danger)' : score >= 40 ? 'var(--warning)' : 'var(--success)';

        document.getElementById('sandbox-file-type').textContent = data.file_type || '--';
        document.getElementById('sandbox-file-size').textContent = data.file_size || '--';
        document.getElementById('sandbox-md5').textContent = data.md5 || '--';
        document.getElementById('sandbox-sha256').textContent = data.sha256 || '--';

        var indHtml = '';
        var indicators = data.indicators || {};
        Object.keys(indicators).forEach(function(cat) {
            indHtml += '<div style="margin-bottom:8px"><strong style="color:var(--text-secondary);font-size:0.85rem">' + esc(cat) + '</strong><ul style="margin:4px 0 0 16px;font-size:0.85rem">';
            (indicators[cat] || []).forEach(function(item) {
                indHtml += '<li>' + esc(item) + '</li>';
            });
            indHtml += '</ul></div>';
        });
        document.getElementById('sandbox-indicators').innerHTML = indHtml || '<span class="empty-state">No indicators found.</span>';

        var strings = (data.strings || []).join('\n');
        renderOutput('sandbox-strings', strings || 'No interesting strings found.');
    }).catch(function() { setLoading(btn, false); });
}

/* ── Dynamic Analysis ── */
function sandboxDynamic() {
    var sampleId = document.getElementById('sandbox-sample-select').value;
    if (!sampleId) { alert('Select a sample first.'); return; }
    var btn = document.getElementById('btn-dynamic');
    setLoading(btn, true);
    document.getElementById('sandbox-dynamic-status').textContent = 'Submitting for dynamic analysis...';
    document.getElementById('sandbox-dynamic-results').style.display = 'none';

    postJSON('/sandbox/analyze/dynamic', {sample_id: sampleId}).then(function(data) {
        if (data.error) {
            setLoading(btn, false);
            document.getElementById('sandbox-dynamic-status').textContent = 'Error: ' + data.error;
            return;
        }
        if (data.job_id) {
            document.getElementById('sandbox-dynamic-status').textContent = 'Running in Docker sandbox...';
            sandboxPollDynamic(data.job_id);
        } else {
            setLoading(btn, false);
            sandboxRenderDynamic(data);
        }
    }).catch(function() {
        setLoading(btn, false);
        document.getElementById('sandbox-dynamic-status').textContent = 'Request failed';
    });
}

function sandboxPollDynamic(jobId) {
    if (_dynamicPoll) clearInterval(_dynamicPoll);
    _dynamicPoll = setInterval(function() {
        fetchJSON('/sandbox/analyze/dynamic/status/' + jobId).then(function(data) {
            if (data.status === 'running') {
                document.getElementById('sandbox-dynamic-status').textContent = 'Running... (' + (data.elapsed || '0') + 's)';
            } else {
                clearInterval(_dynamicPoll);
                _dynamicPoll = null;
                setLoading(document.getElementById('btn-dynamic'), false);
                if (data.status === 'complete') {
                    document.getElementById('sandbox-dynamic-status').textContent = 'Analysis complete';
                    sandboxRenderDynamic(data);
                } else {
                    document.getElementById('sandbox-dynamic-status').textContent = 'Failed: ' + (data.error || 'unknown');
                }
            }
        }).catch(function() {
            clearInterval(_dynamicPoll);
            _dynamicPoll = null;
            setLoading(document.getElementById('btn-dynamic'), false);
            document.getElementById('sandbox-dynamic-status').textContent = 'Poll error';
        });
    }, 3000);
}

function sandboxRenderDynamic(data) {
    document.getElementById('sandbox-dynamic-results').style.display = 'block';
    renderOutput('sandbox-syscalls', (data.syscalls || []).join('\n') || 'No syscalls captured.');
    renderOutput('sandbox-files', (data.files_accessed || []).join('\n') || 'No file access recorded.');
    renderOutput('sandbox-network', (data.network_calls || []).join('\n') || 'No network activity recorded.');
}

/* ── Reports ── */
function sandboxLoadReports() {
    fetchJSON('/sandbox/reports').then(function(data) {
        var tb = document.getElementById('sandbox-reports-table');
        var reports = data.reports || [];
        if (!reports.length) {
            tb.innerHTML = '<tr><td colspan="4" class="empty-state">No reports generated yet.</td></tr>';
            return;
        }
        var html = '';
        reports.forEach(function(r) {
            var lvl = (r.risk_level || 'unknown').toLowerCase();
            var badgeClass = lvl === 'critical' || lvl === 'high' ? 'badge-fail'
                           : lvl === 'medium' ? 'badge-medium'
                           : lvl === 'low' ? 'badge-low' : 'badge-info';
            html += '<tr><td>' + esc(r.sample_name) + '</td>'
                + '<td><span class="badge ' + badgeClass + '">' + esc(r.risk_level) + '</span></td>'
                + '<td>' + esc(r.date) + '</td>'
                + '<td><button class="btn btn-small" onclick="sandboxViewReport(\'' + esc(r.id) + '\')">View</button></td></tr>';
        });
        tb.innerHTML = html;
    });
}

function sandboxGenReport() {
    var sampleId = document.getElementById('sandbox-report-sample').value;
    if (!sampleId) { alert('Select a sample first.'); return; }
    var btn = document.getElementById('btn-gen-report');
    setLoading(btn, true);
    postJSON('/sandbox/reports/generate', {sample_id: sampleId}).then(function(data) {
        setLoading(btn, false);
        if (data.error) { alert('Error: ' + data.error); return; }
        sandboxLoadReports();
        if (data.report_id) sandboxViewReport(data.report_id);
    }).catch(function() { setLoading(btn, false); });
}

function sandboxViewReport(reportId) {
    fetchJSON('/sandbox/reports/' + reportId).then(function(data) {
        if (data.error) { alert('Error: ' + data.error); return; }
        document.getElementById('sandbox-report-viewer').style.display = 'block';
        var html = '<div style="background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);padding:16px">';

        var lvl = (data.risk_level || 'unknown').toLowerCase();
        var badgeClass = lvl === 'critical' || lvl === 'high' ? 'badge-fail'
                       : lvl === 'medium' ? 'badge-medium'
                       : lvl === 'low' ? 'badge-low' : 'badge-info';
        html += '<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px">'
            + '<strong>' + esc(data.sample_name || 'Unknown') + '</strong>'
            + '<span class="badge ' + badgeClass + '">' + esc(data.risk_level || 'N/A') + '</span></div>';

        html += '<table class="data-table" style="font-size:0.85rem;margin-bottom:12px"><tbody>';
        html += '<tr><td>Risk Score</td><td>' + (data.risk_score || '--') + '/100</td></tr>';
        html += '<tr><td>File Type</td><td>' + esc(data.file_type || '--') + '</td></tr>';
        html += '<tr><td>SHA256</td><td style="font-family:monospace;font-size:0.8rem;word-break:break-all">' + esc(data.sha256 || '--') + '</td></tr>';
        html += '<tr><td>Date</td><td>' + esc(data.date || '--') + '</td></tr>';
        html += '</tbody></table>';

        if (data.summary) {
            html += '<h4 style="margin-bottom:6px;font-size:0.85rem;color:var(--text-secondary)">Summary</h4>';
            html += '<p style="font-size:0.85rem;margin-bottom:12px">' + esc(data.summary) + '</p>';
        }

        html += '</div>';
        document.getElementById('sandbox-report-content').innerHTML = html;
    });
}

/* ── Init ── */
document.addEventListener('DOMContentLoaded', function() {
    sandboxLoadSamples();
    sandboxRefreshSelect();
    sandboxLoadReports();
});
</script>
{% endblock %}


Instruction: Create an AUTARCH web template for the 'Manual' page. It should extend base.html, have a page header, and use AUTARCH's CSS variables and UI patterns (sections, tab bars, data tables, buttons).

Input:
Template: manual.html
Sections: 0
Tabs: 0
Forms/API calls: 0
Has JavaScript: False

Output:
{% extends "base.html" %}
{% block title %}User Manual — AUTARCH{% endblock %}

{% block extra_head %}
<style>
    .manual-content {
        max-width: 900px;
        line-height: 1.7;
        font-size: 15px;
    }
    .manual-content h1 { color: #00ff41; font-size: 28px; margin: 30px 0 15px; border-bottom: 1px solid #333; padding-bottom: 8px; }
    .manual-content h2 { color: #00ff41; font-size: 22px; margin: 28px 0 12px; border-bottom: 1px solid #222; padding-bottom: 6px; }
    .manual-content h3 { color: #00cc33; font-size: 18px; margin: 22px 0 10px; }
    .manual-content h4 { color: #00aa22; font-size: 16px; margin: 18px 0 8px; }
    .manual-content p { margin: 8px 0; color: #ccc; }
    .manual-content code {
        background: #1a1a2e;
        color: #00ff41;
        padding: 2px 6px;
        border-radius: 3px;
        font-family: 'Courier New', monospace;
        font-size: 14px;
    }
    .manual-content pre {
        background: #0a0a1a;
        border: 1px solid #333;
        border-radius: 6px;
        padding: 14px;
        overflow-x: auto;
        margin: 12px 0;
    }
    .manual-content pre code {
        background: transparent;
        padding: 0;
        font-size: 13px;
    }
    .manual-content table {
        width: 100%;
        border-collapse: collapse;
        margin: 12px 0;
    }
    .manual-content th {
        background: #1a1a2e;
        color: #00ff41;
        text-align: left;
        padding: 8px 12px;
        border: 1px solid #333;
        font-size: 13px;
    }
    .manual-content td {
        padding: 8px 12px;
        border: 1px solid #222;
        color: #ccc;
        font-size: 13px;
    }
    .manual-content tr:nth-child(even) { background: #111122; }
    .manual-content ul, .manual-content ol { margin: 8px 0; padding-left: 24px; color: #ccc; }
    .manual-content li { margin: 4px 0; }
    .manual-content strong { color: #fff; }
    .manual-content em { color: #aaa; }
    .manual-content hr { border: none; border-top: 1px solid #333; margin: 24px 0; }
    .manual-content a { color: #00cc99; text-decoration: none; }
    .manual-content a:hover { text-decoration: underline; }
    .manual-content blockquote {
        border-left: 3px solid #00ff41;
        margin: 12px 0;
        padding: 8px 16px;
        background: #111122;
        color: #aaa;
    }
</style>
{% endblock %}

{% block content %}
<div class="manual-content">
    {{ manual_html }}
</div>
{% endblock %}


Instruction: Create an AUTARCH web template for the 'Mcp Settings' page. It should extend base.html, have a page header, and use AUTARCH's CSS variables and UI patterns (sections, tab bars, data tables, buttons).

Input:
Template: mcp_settings.html
Sections: 1
Tabs: 0
Forms/API calls: 6
Has JavaScript: True

Output:
{% extends "base.html" %}
{% block title %}MCP Server - AUTARCH{% endblock %}

{% block content %}
<div class="page-header" style="display:flex;align-items:center;gap:1rem;flex-wrap:wrap">
    <h1>MCP Server</h1>
    <a href="{{ url_for('settings.index') }}" class="btn btn-sm" style="margin-left:auto">&larr; Back to Settings</a>
</div>

<div class="section">
    <h2>Model Context Protocol</h2>
    <p style="font-size:0.82rem;color:var(--text-secondary);margin-bottom:1rem">
        The <a href="https://modelcontextprotocol.io/docs/getting-started/intro" target="_blank" rel="noopener">Model Context Protocol (MCP)</a>
        lets AI assistants like Claude Desktop, Claude Code, and other MCP-compatible clients use AUTARCH's security tools directly.
        When connected, Claude can run nmap scans, look up IPs, capture packets, manage devices, and more &mdash; all through natural conversation.
    </p>

    <!-- ── Section 1: Server Control ── -->
    <div style="border:1px solid var(--border);background:var(--bg-card);border-radius:var(--radius);padding:0.85rem 1rem;margin-bottom:1.25rem">
        <h3 style="font-size:0.95rem;margin-bottom:0.5rem">Server Control</h3>
        <div style="display:flex;align-items:center;gap:0.75rem;flex-wrap:wrap;margin-bottom:0.75rem">
            <button class="btn btn-primary btn-sm" onclick="mcpStart()" id="btn-mcp-start">Start MCP Server</button>
            <button class="btn btn-sm" onclick="mcpStop()" id="btn-mcp-stop">Stop</button>
            <div id="mcp-status-dot" style="width:10px;height:10px;border-radius:50%;background:var(--text-muted);flex-shrink:0"></div>
            <span id="mcp-status-text" style="font-size:0.82rem;color:var(--text-secondary)">Checking...</span>
        </div>
        <div style="display:flex;align-items:center;gap:1.5rem;flex-wrap:wrap;font-size:0.82rem;margin-bottom:0.5rem">
            <label style="display:flex;align-items:center;gap:0.4rem;cursor:pointer">
                <input type="checkbox" id="mcp-auto-start" {{ 'checked' if mcp.auto_start == 'true' }}>
                Auto-start on launch
            </label>
            <span style="color:var(--text-muted)">Transport: <strong id="mcp-transport-display">{{ mcp.transport }}</strong></span>
        </div>
        <p style="font-size:0.75rem;color:var(--text-muted);margin:0">
            SSE endpoint: <code>http://{{ request.host.split(':')[0] }}:{{ mcp.port }}/sse</code>
        </p>
    </div>

    <!-- ── Section 2: Transport & Network ── -->
    <div style="border:1px solid var(--border);background:var(--bg-card);border-radius:var(--radius);padding:0.85rem 1rem;margin-bottom:1.25rem">
        <h3 style="font-size:0.95rem;margin-bottom:0.5rem">Transport &amp; Network Settings</h3>
        <div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:0.75rem;font-size:0.82rem">
            <div>
                <label style="display:block;color:var(--text-secondary);margin-bottom:0.25rem">Transport</label>
                <select id="mcp-transport" style="width:100%;padding:0.35rem 0.5rem;border-radius:var(--radius);border:1px solid var(--border);background:var(--bg-main);color:inherit;font-size:0.82rem">
                    <option value="sse" {{ 'selected' if mcp.transport == 'sse' }}>SSE (HTTP)</option>
                    <option value="stdio" {{ 'selected' if mcp.transport == 'stdio' }}>stdio (CLI only)</option>
                </select>
            </div>
            <div>
                <label style="display:block;color:var(--text-secondary);margin-bottom:0.25rem">Host</label>
                <input type="text" id="mcp-host" value="{{ mcp.host }}" placeholder="0.0.0.0"
                       style="width:100%;padding:0.35rem 0.5rem;border-radius:var(--radius);border:1px solid var(--border);background:var(--bg-main);color:inherit;font-size:0.82rem;box-sizing:border-box">
            </div>
            <div>
                <label style="display:block;color:var(--text-secondary);margin-bottom:0.25rem">Port</label>
                <input type="number" id="mcp-port" value="{{ mcp.port }}" placeholder="8081"
                       style="width:100%;padding:0.35rem 0.5rem;border-radius:var(--radius);border:1px solid var(--border);background:var(--bg-main);color:inherit;font-size:0.82rem;box-sizing:border-box">
            </div>
            <div>
                <label style="display:block;color:var(--text-secondary);margin-bottom:0.25rem">CORS Origins</label>
                <input type="text" id="mcp-cors-origins" value="{{ mcp.cors_origins }}" placeholder="*"
                       style="width:100%;padding:0.35rem 0.5rem;border-radius:var(--radius);border:1px solid var(--border);background:var(--bg-main);color:inherit;font-size:0.82rem;box-sizing:border-box">
            </div>
        </div>
    </div>

    <!-- ── Section 3: Security ── -->
    <div style="border:1px solid var(--border);background:var(--bg-card);border-radius:var(--radius);padding:0.85rem 1rem;margin-bottom:1.25rem">
        <h3 style="font-size:0.95rem;margin-bottom:0.5rem">Security</h3>
        <div style="display:flex;flex-direction:column;gap:0.75rem;font-size:0.82rem">
            <label style="display:flex;align-items:center;gap:0.4rem;cursor:pointer">
                <input type="checkbox" id="mcp-auth-enabled" {{ 'checked' if mcp.auth_enabled == 'true' }}>
                Enable authentication
            </label>
            <div>
                <label style="display:block;color:var(--text-secondary);margin-bottom:0.25rem">Auth Token</label>
                <div style="display:flex;align-items:center;gap:0.5rem;flex-wrap:wrap">
                    <input type="password" id="mcp-auth-token" value="{{ mcp.auth_token }}" readonly
                           style="flex:1;min-width:200px;padding:0.35rem 0.5rem;border-radius:var(--radius);border:1px solid var(--border);background:var(--bg-main);color:inherit;font-size:0.82rem;font-family:monospace">
                    <button class="btn btn-sm" onclick="mcpToggleToken()" id="btn-toggle-token" style="font-size:0.75rem">Show</button>
                    <button class="btn btn-sm" onclick="mcpGenerateToken()" style="font-size:0.75rem">Generate New Token</button>
                </div>
            </div>
            <div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:0.75rem">
                <div>
                    <label style="display:block;color:var(--text-secondary);margin-bottom:0.25rem">Rate Limit</label>
                    <input type="text" id="mcp-rate-limit" value="{{ mcp.rate_limit }}" placeholder="100/hour"
                           style="width:100%;padding:0.35rem 0.5rem;border-radius:var(--radius);border:1px solid var(--border);background:var(--bg-main);color:inherit;font-size:0.82rem;box-sizing:border-box">
                </div>
            </div>
            <label style="display:flex;align-items:center;gap:0.4rem;cursor:pointer">
                <input type="checkbox" id="mcp-mask-errors" {{ 'checked' if mcp.mask_errors == 'true' }}>
                Mask error details in responses
            </label>
            <div style="border-top:1px solid var(--border);padding-top:0.75rem;margin-top:0.25rem">
                <label style="display:flex;align-items:center;gap:0.4rem;cursor:pointer;margin-bottom:0.5rem">
                    <input type="checkbox" id="mcp-ssl-enabled" {{ 'checked' if mcp.ssl_enabled == 'true' }}>
                    Enable SSL / TLS
                </label>
                <div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:0.75rem">
                    <div>
                        <label style="display:block;color:var(--text-secondary);margin-bottom:0.25rem">SSL Certificate Path</label>
                        <input type="text" id="mcp-ssl-cert" value="{{ mcp.ssl_cert }}" placeholder="/path/to/cert.pem"
                               style="width:100%;padding:0.35rem 0.5rem;border-radius:var(--radius);border:1px solid var(--border);background:var(--bg-main);color:inherit;font-size:0.82rem;box-sizing:border-box">
                    </div>
                    <div>
                        <label style="display:block;color:var(--text-secondary);margin-bottom:0.25rem">SSL Key Path</label>
                        <input type="text" id="mcp-ssl-key" value="{{ mcp.ssl_key }}" placeholder="/path/to/key.pem"
                               style="width:100%;padding:0.35rem 0.5rem;border-radius:var(--radius);border:1px solid var(--border);background:var(--bg-main);color:inherit;font-size:0.82rem;box-sizing:border-box">
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- ── Section 4: Tool Management ── -->
    <div style="border:1px solid var(--border);background:var(--bg-card);border-radius:var(--radius);padding:0.85rem 1rem;margin-bottom:1.25rem">
        <h3 style="font-size:0.95rem;margin-bottom:0.5rem">Tool Management</h3>
        <p style="font-size:0.78rem;color:var(--text-secondary);margin-bottom:0.75rem">
            Enable or disable individual MCP tools. Disabled tools will not be exposed to connected clients.
        </p>
        <div id="mcp-tools-grid" style="display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:0.5rem;font-size:0.82rem">
        </div>
    </div>

    <!-- ── Section 5: Tool Timeouts ── -->
    <div style="border:1px solid var(--border);background:var(--bg-card);border-radius:var(--radius);padding:0.85rem 1rem;margin-bottom:1.25rem">
        <h3 style="font-size:0.95rem;margin-bottom:0.5rem">Tool Timeouts</h3>
        <div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:0.75rem;font-size:0.82rem">
            <div>
                <label style="display:block;color:var(--text-secondary);margin-bottom:0.25rem">nmap timeout (s)</label>
                <input type="number" id="mcp-nmap-timeout" value="{{ mcp.nmap_timeout }}" placeholder="120"
                       style="width:100%;padding:0.35rem 0.5rem;border-radius:var(--radius);border:1px solid var(--border);background:var(--bg-main);color:inherit;font-size:0.82rem;box-sizing:border-box">
            </div>
            <div>
                <label style="display:block;color:var(--text-secondary);margin-bottom:0.25rem">tcpdump timeout (s)</label>
                <input type="number" id="mcp-tcpdump-timeout" value="{{ mcp.tcpdump_timeout }}" placeholder="30"
                       style="width:100%;padding:0.35rem 0.5rem;border-radius:var(--radius);border:1px solid var(--border);background:var(--bg-main);color:inherit;font-size:0.82rem;box-sizing:border-box">
            </div>
            <div>
                <label style="display:block;color:var(--text-secondary);margin-bottom:0.25rem">whois timeout (s)</label>
                <input type="number" id="mcp-whois-timeout" value="{{ mcp.whois_timeout }}" placeholder="15"
                       style="width:100%;padding:0.35rem 0.5rem;border-radius:var(--radius);border:1px solid var(--border);background:var(--bg-main);color:inherit;font-size:0.82rem;box-sizing:border-box">
            </div>
            <div>
                <label style="display:block;color:var(--text-secondary);margin-bottom:0.25rem">DNS timeout (s)</label>
                <input type="number" id="mcp-dns-timeout" value="{{ mcp.dns_timeout }}" placeholder="10"
                       style="width:100%;padding:0.35rem 0.5rem;border-radius:var(--radius);border:1px solid var(--border);background:var(--bg-main);color:inherit;font-size:0.82rem;box-sizing:border-box">
            </div>
            <div>
                <label style="display:block;color:var(--text-secondary);margin-bottom:0.25rem">GeoIP timeout (s)</label>
                <input type="number" id="mcp-geoip-timeout" value="{{ mcp.geoip_timeout }}" placeholder="10"
                       style="width:100%;padding:0.35rem 0.5rem;border-radius:var(--radius);border:1px solid var(--border);background:var(--bg-main);color:inherit;font-size:0.82rem;box-sizing:border-box">
            </div>
            <div>
                <label style="display:block;color:var(--text-secondary);margin-bottom:0.25rem">GeoIP Endpoint URL</label>
                <input type="text" id="mcp-geoip-endpoint" value="{{ mcp.geoip_endpoint }}" placeholder="http://ip-api.com/json/"
                       style="width:100%;padding:0.35rem 0.5rem;border-radius:var(--radius);border:1px solid var(--border);background:var(--bg-main);color:inherit;font-size:0.82rem;box-sizing:border-box">
            </div>
        </div>
    </div>

    <!-- ── Section 6: Advanced ── -->
    <div style="border:1px solid var(--border);background:var(--bg-card);border-radius:var(--radius);padding:0.85rem 1rem;margin-bottom:1.25rem">
        <h3 style="font-size:0.95rem;margin-bottom:0.5rem">Advanced</h3>
        <div style="display:flex;flex-direction:column;gap:0.75rem;font-size:0.82rem">
            <div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:0.75rem">
                <div>
                    <label style="display:block;color:var(--text-secondary);margin-bottom:0.25rem">Log Level</label>
                    <select id="mcp-log-level" style="width:100%;padding:0.35rem 0.5rem;border-radius:var(--radius);border:1px solid var(--border);background:var(--bg-main);color:inherit;font-size:0.82rem">
                        <option value="DEBUG" {{ 'selected' if mcp.log_level == 'DEBUG' }}>DEBUG</option>
                        <option value="INFO" {{ 'selected' if mcp.log_level == 'INFO' }}>INFO</option>
                        <option value="WARNING" {{ 'selected' if mcp.log_level == 'WARNING' }}>WARNING</option>
                        <option value="ERROR" {{ 'selected' if mcp.log_level == 'ERROR' }}>ERROR</option>
                    </select>
                </div>
                <div>
                    <label style="display:block;color:var(--text-secondary);margin-bottom:0.25rem">Request Timeout (s)</label>
                    <input type="number" id="mcp-request-timeout" value="{{ mcp.request_timeout }}" placeholder="30"
                           style="width:100%;padding:0.35rem 0.5rem;border-radius:var(--radius);border:1px solid var(--border);background:var(--bg-main);color:inherit;font-size:0.82rem;box-sizing:border-box">
                </div>
                <div>
                    <label style="display:block;color:var(--text-secondary);margin-bottom:0.25rem">Max Message Size (bytes)</label>
                    <input type="number" id="mcp-max-message-size" value="{{ mcp.max_message_size }}" placeholder="1048576"
                           style="width:100%;padding:0.35rem 0.5rem;border-radius:var(--radius);border:1px solid var(--border);background:var(--bg-main);color:inherit;font-size:0.82rem;box-sizing:border-box">
                </div>
            </div>
            <div>
                <label style="display:block;color:var(--text-secondary);margin-bottom:0.25rem">Server Instructions</label>
                <textarea id="mcp-instructions" rows="4" placeholder="Instructions sent to MCP clients describing this server's capabilities..."
                          style="width:100%;padding:0.5rem;border-radius:var(--radius);border:1px solid var(--border);background:var(--bg-main);color:inherit;font-size:0.82rem;font-family:inherit;resize:vertical;box-sizing:border-box">{{ mcp.instructions }}</textarea>
            </div>
        </div>
    </div>

    <!-- ── Section 7: Integration ── -->
    <div style="border:1px solid var(--border);background:var(--bg-card);border-radius:var(--radius);padding:0.85rem 1rem;margin-bottom:1.25rem">
        <h3 style="font-size:0.95rem;margin-bottom:0.5rem">Integration</h3>
        <p style="font-size:0.82rem;color:var(--text-secondary);margin-bottom:0.5rem">
            <strong>Claude Desktop / Claude Code config:</strong> Add this to your
            <code>claude_desktop_config.json</code> or <code>.claude/settings.json</code>:
        </p>
        <div style="position:relative;margin-bottom:1rem">
            <pre id="mcp-config-block" style="background:var(--bg-main);border:1px solid var(--border);border-radius:var(--radius);
                 padding:0.75rem;font-size:0.78rem;overflow-x:auto;margin:0">Loading...</pre>
            <button class="btn btn-sm" onclick="mcpCopyConfig()" id="btn-mcp-copy"
                    style="position:absolute;top:0.4rem;right:0.4rem;font-size:0.7rem">Copy</button>
        </div>
        <p style="font-size:0.82rem;color:var(--text-secondary);margin-bottom:0.5rem"><strong>CLI Commands:</strong></p>
        <pre style="background:var(--bg-main);border:1px solid var(--border);border-radius:var(--radius);
             padding:0.75rem;font-size:0.78rem;overflow-x:auto;margin:0"><span style="color:var(--text-muted)"># stdio mode (Claude Desktop / Claude Code)</span>
python autarch.py --mcp stdio

<span style="color:var(--text-muted)"># SSE mode (remote / web clients)</span>
python autarch.py --mcp sse --mcp-port {{ mcp.port }}</pre>
    </div>

    <!-- ── Save Button ── -->
    <div style="position:sticky;bottom:0;padding:0.75rem 0;background:var(--bg-main);border-top:1px solid var(--border);display:flex;align-items:center;gap:1rem;z-index:10">
        <button class="btn btn-primary" onclick="mcpSave()" id="btn-mcp-save" style="font-size:0.9rem;padding:0.5rem 1.5rem">
            Save MCP Settings
        </button>
        <span id="mcp-save-status" style="font-size:0.82rem;color:var(--text-muted)"></span>
    </div>
</div>

<script>
// ── Tool definitions ─────────────────────────────────────────────────────────
var MCP_TOOLS = [
    {name: 'nmap_scan',        desc: 'Run an nmap network scan'},
    {name: 'geoip_lookup',     desc: 'GeoIP information for an IP'},
    {name: 'dns_lookup',       desc: 'DNS record queries'},
    {name: 'whois_lookup',     desc: 'WHOIS lookup for domain/IP'},
    {name: 'packet_capture',   desc: 'Capture network packets'},
    {name: 'wireguard_status', desc: 'WireGuard VPN status'},
    {name: 'upnp_status',      desc: 'UPnP port mapping status'},
    {name: 'system_info',      desc: 'System information'},
    {name: 'llm_chat',         desc: 'Chat with configured LLM'},
    {name: 'android_devices',  desc: 'List Android devices via ADB'},
    {name: 'config_get',       desc: 'Read AUTARCH configuration'}
];

var disabledToolsRaw = {{ mcp.disabled_tools | tojson }};

function escapeHtml(s) {
    var d = document.createElement('div');
    d.textContent = s;
    return d.innerHTML;
}

function buildToolGrid() {
    var disabled = (disabledToolsRaw || '').split(',').map(function(s) { return s.trim(); }).filter(Boolean);
    var grid = document.getElementById('mcp-tools-grid');
    grid.innerHTML = '';
    for (var i = 0; i < MCP_TOOLS.length; i++) {
        var t = MCP_TOOLS[i];
        var isEnabled = disabled.indexOf(t.name) === -1;
        var el = document.createElement('label');
        el.style.cssText = 'display:flex;align-items:flex-start;gap:0.5rem;padding:0.5rem 0.6rem;border-radius:4px;border:1px solid var(--border);background:var(--bg-main);cursor:pointer';
        el.innerHTML = '<input type="checkbox" class="mcp-tool-cb" data-tool="' + t.name + '" ' + (isEnabled ? 'checked' : '') + ' style="margin-top:0.15rem">'
            + '<div><strong style="color:var(--accent)">' + escapeHtml(t.name) + '</strong>'
            + '<div style="font-size:0.72rem;color:var(--text-muted);margin-top:0.1rem">' + escapeHtml(t.desc) + '</div></div>';
        grid.appendChild(el);
    }
}

// ── Server Controls ──────────────────────────────────────────────────────────
function mcpStart() {
    var btn = document.getElementById('btn-mcp-start');
    btn.disabled = true; btn.textContent = 'Starting...';
    fetch('/settings/mcp/start', {method: 'POST'})
        .then(function(r) { return r.json(); })
        .then(function(d) {
            btn.disabled = false; btn.textContent = 'Start MCP Server';
            mcpRefreshStatus();
        })
        .catch(function(e) { btn.disabled = false; btn.textContent = 'Start MCP Server'; alert(e.message); });
}

function mcpStop() {
    var btn = document.getElementById('btn-mcp-stop');
    btn.disabled = true; btn.textContent = 'Stopping...';
    fetch('/settings/mcp/stop', {method: 'POST'})
        .then(function(r) { return r.json(); })
        .then(function(d) {
            btn.disabled = false; btn.textContent = 'Stop';
            mcpRefreshStatus();
        })
        .catch(function(e) { btn.disabled = false; btn.textContent = 'Stop'; });
}

function mcpRefreshStatus() {
    fetch('/settings/mcp/status', {method: 'POST'})
        .then(function(r) { return r.json(); })
        .then(function(d) {
            var dot = document.getElementById('mcp-status-dot');
            var text = document.getElementById('mcp-status-text');
            if (d.ok && d.status && d.status.running) {
                dot.style.background = 'var(--success, #34c759)';
                text.innerHTML = '&#x2713; Running (PID ' + d.status.pid + ')';
            } else {
                dot.style.background = 'var(--text-muted)';
                text.textContent = 'Stopped';
            }
        })
        .catch(function() {
            document.getElementById('mcp-status-dot').style.background = 'var(--text-muted)';
            document.getElementById('mcp-status-text').textContent = 'Error checking status';
        });
}

// ── Save ─────────────────────────────────────────────────────────────────────
function mcpSave() {
    var btn = document.getElementById('btn-mcp-save');
    var status = document.getElementById('mcp-save-status');
    btn.disabled = true; btn.textContent = 'Saving...';
    status.textContent = '';

    // Collect disabled tools
    var disabledTools = [];
    var cbs = document.querySelectorAll('.mcp-tool-cb');
    for (var i = 0; i < cbs.length; i++) {
        if (!cbs[i].checked) disabledTools.push(cbs[i].getAttribute('data-tool'));
    }

    var payload = {
        enabled:          true,
        auto_start:       document.getElementById('mcp-auto-start').checked,
        transport:        document.getElementById('mcp-transport').value,
        host:             document.getElementById('mcp-host').value,
        port:             document.getElementById('mcp-port').value,
        cors_origins:     document.getElementById('mcp-cors-origins').value,
        auth_enabled:     document.getElementById('mcp-auth-enabled').checked,
        auth_token:       document.getElementById('mcp-auth-token').value,
        rate_limit:       document.getElementById('mcp-rate-limit').value,
        mask_errors:      document.getElementById('mcp-mask-errors').checked,
        ssl_enabled:      document.getElementById('mcp-ssl-enabled').checked,
        ssl_cert:         document.getElementById('mcp-ssl-cert').value,
        ssl_key:          document.getElementById('mcp-ssl-key').value,
        log_level:        document.getElementById('mcp-log-level').value,
        instructions:     document.getElementById('mcp-instructions').value,
        request_timeout:  document.getElementById('mcp-request-timeout').value,
        max_message_size: document.getElementById('mcp-max-message-size').value,
        disabled_tools:   disabledTools.join(','),
        nmap_timeout:     document.getElementById('mcp-nmap-timeout').value,
        tcpdump_timeout:  document.getElementById('mcp-tcpdump-timeout').value,
        whois_timeout:    document.getElementById('mcp-whois-timeout').value,
        dns_timeout:      document.getElementById('mcp-dns-timeout').value,
        geoip_timeout:    document.getElementById('mcp-geoip-timeout').value,
        geoip_endpoint:   document.getElementById('mcp-geoip-endpoint').value
    };

    fetch('/settings/mcp/save', {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify(payload)
    })
    .then(function(r) { return r.json(); })
    .then(function(d) {
        btn.disabled = false; btn.textContent = 'Save MCP Settings';
        if (d.ok) {
            status.style.color = 'var(--success, #34c759)';
            status.textContent = 'Settings saved successfully.';
        } else {
            status.style.color = 'var(--danger, #ff3b30)';
            status.textContent = 'Error: ' + (d.error || 'Unknown error');
        }
        setTimeout(function() { status.textContent = ''; }, 4000);
    })
    .catch(function(e) {
        btn.disabled = false; btn.textContent = 'Save MCP Settings';
        status.style.color = 'var(--danger, #ff3b30)';
        status.textContent = 'Error: ' + e.message;
    });
}

// ── Token helpers ────────────────────────────────────────────────────────────
function mcpGenerateToken() {
    fetch('/settings/mcp/generate-token', {method: 'POST'})
        .then(function(r) { return r.json(); })
        .then(function(d) {
            if (d.ok && d.token) {
                var input = document.getElementById('mcp-auth-token');
                input.value = d.token;
                input.type = 'text';
                document.getElementById('btn-toggle-token').textContent = 'Hide';
            }
        })
        .catch(function(e) { alert('Failed to generate token: ' + e.message); });
}

function mcpToggleToken() {
    var input = document.getElementById('mcp-auth-token');
    var btn = document.getElementById('btn-toggle-token');
    if (input.type === 'password') {
        input.type = 'text';
        btn.textContent = 'Hide';
    } else {
        input.type = 'password';
        btn.textContent = 'Show';
    }
}

// ── Config copy ──────────────────────────────────────────────────────────────
function mcpCopyConfig() {
    var block = document.getElementById('mcp-config-block');
    navigator.clipboard.writeText(block.textContent).then(function() {
        var btn = document.getElementById('btn-mcp-copy');
        btn.textContent = 'Copied!';
        setTimeout(function() { btn.textContent = 'Copy'; }, 2000);
    });
}

// ── Page load ────────────────────────────────────────────────────────────────
document.addEventListener('DOMContentLoaded', function() {
    buildToolGrid();
    mcpRefreshStatus();
    // Fetch config snippet
    fetch('/settings/mcp/config', {method: 'POST'})
        .then(function(r) { return r.json(); })
        .then(function(d) {
            if (d.ok) document.getElementById('mcp-config-block').textContent = d.config;
        });
});
</script>
{% endblock %}