Instruction: Create an AUTARCH web template for the 'Forensics' 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: forensics.html
Sections: 10
Tabs: 3
Forms/API calls: 0
Has JavaScript: True

Output:
{% extends "base.html" %}
{% block title %}AUTARCH — Forensics Toolkit{% endblock %}
{% block content %}
<div class="page-header">
    <h1>Forensics Toolkit</h1>
    <p style="margin:0;font-size:0.85rem;color:var(--text-secondary)">
        File hashing, data carving, timeline analysis, and evidence chain of custody.
    </p>
</div>

<!-- Tab Bar -->
<div class="tab-bar">
    <button class="tab active" data-tab-group="forensics" data-tab="image" onclick="showTab('forensics','image')">Image</button>
    <button class="tab" data-tab-group="forensics" data-tab="carve" onclick="showTab('forensics','carve')">Carve</button>
    <button class="tab" data-tab-group="forensics" data-tab="timeline" onclick="showTab('forensics','timeline')">Timeline</button>
    <button class="tab" data-tab-group="forensics" data-tab="evidence" onclick="showTab('forensics','evidence')">Evidence</button>
</div>

<!-- ══ Image Tab ══ -->
<div class="tab-content active" data-tab-group="forensics" data-tab="image">

    <!-- Hash File -->
    <div class="section">
        <h2>Hash File</h2>
        <div class="form-row">
            <div class="form-group" style="flex:2">
                <label>File Path</label>
                <input type="text" id="for-hash-path" placeholder="/path/to/evidence/file.dd">
            </div>
        </div>
        <div class="tool-actions">
            <button id="btn-for-hash" class="btn btn-primary" onclick="forHashFile()">Compute Hashes</button>
        </div>
        <div id="for-hash-result" style="display:none">
            <table class="data-table" style="max-width:700px">
                <tbody>
                    <tr><td style="width:80px;font-weight:600">MD5</td><td id="for-hash-md5" style="font-family:monospace;font-size:0.85rem;word-break:break-all">—</td></tr>
                    <tr><td style="font-weight:600">SHA1</td><td id="for-hash-sha1" style="font-family:monospace;font-size:0.85rem;word-break:break-all">—</td></tr>
                    <tr><td style="font-weight:600">SHA256</td><td id="for-hash-sha256" style="font-family:monospace;font-size:0.85rem;word-break:break-all">—</td></tr>
                </tbody>
            </table>
        </div>
    </div>

    <!-- Verify Hash -->
    <div class="section">
        <h2>Verify Hash</h2>
        <div class="form-row">
            <div class="form-group" style="flex:2">
                <label>File Path</label>
                <input type="text" id="for-verify-path" placeholder="/path/to/evidence/file.dd">
            </div>
            <div class="form-group" style="flex:2">
                <label>Expected Hash (MD5, SHA1, or SHA256)</label>
                <input type="text" id="for-verify-hash" placeholder="e3b0c44298fc1c149afbf4c8996fb924...">
            </div>
        </div>
        <div class="tool-actions">
            <button id="btn-for-verify" class="btn btn-primary" onclick="forVerifyHash()">Verify</button>
        </div>
        <div id="for-verify-result" class="progress-text"></div>
    </div>

    <!-- Disk Image Creator -->
    <div class="section">
        <h2>Disk Image Creator</h2>
        <div class="form-row">
            <div class="form-group">
                <label>Source (device or file)</label>
                <input type="text" id="for-image-source" placeholder="/dev/sda1 or /path/to/source">
            </div>
            <div class="form-group">
                <label>Output File</label>
                <input type="text" id="for-image-output" placeholder="/path/to/output/image.dd">
            </div>
        </div>
        <div class="tool-actions">
            <button id="btn-for-image" class="btn btn-primary" onclick="forCreateImage()">Create Image</button>
        </div>
        <div id="for-image-status" class="progress-text"></div>
        <pre class="output-panel scrollable" id="for-image-output-log" style="max-height:200px;display:none"></pre>
    </div>
</div>

<!-- ══ Carve Tab ══ -->
<div class="tab-content" data-tab-group="forensics" data-tab="carve">

    <!-- Carve Form -->
    <div class="section">
        <h2>File Carving</h2>
        <div class="form-row">
            <div class="form-group" style="flex:2">
                <label>Source File</label>
                <input type="text" id="for-carve-source" placeholder="/path/to/disk/image.dd">
            </div>
        </div>
        <div class="form-row">
            <div class="form-group">
                <label>File Types</label>
                <div style="display:flex;gap:12px;flex-wrap:wrap;margin-top:4px">
                    <label style="font-size:0.85rem;cursor:pointer"><input type="checkbox" class="for-carve-type" value="jpg" checked> JPG</label>
                    <label style="font-size:0.85rem;cursor:pointer"><input type="checkbox" class="for-carve-type" value="png" checked> PNG</label>
                    <label style="font-size:0.85rem;cursor:pointer"><input type="checkbox" class="for-carve-type" value="pdf" checked> PDF</label>
                    <label style="font-size:0.85rem;cursor:pointer"><input type="checkbox" class="for-carve-type" value="doc"> DOC/DOCX</label>
                    <label style="font-size:0.85rem;cursor:pointer"><input type="checkbox" class="for-carve-type" value="zip"> ZIP</label>
                    <label style="font-size:0.85rem;cursor:pointer"><input type="checkbox" class="for-carve-type" value="sqlite"> SQLite</label>
                    <label style="font-size:0.85rem;cursor:pointer"><input type="checkbox" class="for-carve-type" value="exe"> EXE/PE</label>
                    <label style="font-size:0.85rem;cursor:pointer"><input type="checkbox" class="for-carve-type" value="elf"> ELF</label>
                </div>
            </div>
            <div class="form-group" style="max-width:160px">
                <label>Max Files</label>
                <input type="number" id="for-carve-max" value="100" min="1" max="10000">
            </div>
        </div>
        <div class="tool-actions">
            <button id="btn-for-carve" class="btn btn-primary" onclick="forCarve()">Carve</button>
        </div>
        <div id="for-carve-status" class="progress-text"></div>
    </div>

    <!-- Carved Files Table -->
    <div class="section">
        <h2>Carved Files</h2>
        <div class="tool-actions">
            <button class="btn btn-small" onclick="forExportCarved()">Export List</button>
            <button class="btn btn-small" onclick="forClearCarved()">Clear</button>
        </div>
        <table class="data-table">
            <thead>
                <tr>
                    <th>Name</th>
                    <th>Type</th>
                    <th>Offset</th>
                    <th>Size</th>
                    <th>MD5</th>
                </tr>
            </thead>
            <tbody id="for-carved-body">
                <tr><td colspan="5" class="empty-state">No carved files. Run file carving first.</td></tr>
            </tbody>
        </table>
    </div>
</div>

<!-- ══ Timeline Tab ══ -->
<div class="tab-content" data-tab-group="forensics" data-tab="timeline">

    <!-- Timeline Builder -->
    <div class="section">
        <h2>Timeline Builder</h2>
        <div class="form-row">
            <div class="form-group" style="flex:2">
                <label>Directory Path</label>
                <input type="text" id="for-timeline-path" placeholder="/path/to/evidence/directory">
            </div>
        </div>
        <div class="tool-actions">
            <button id="btn-for-timeline" class="btn btn-primary" onclick="forBuildTimeline()">Build Timeline</button>
        </div>
        <div id="for-timeline-status" class="progress-text"></div>
    </div>

    <!-- Events Table -->
    <div class="section">
        <h2>Events</h2>
        <div class="tool-actions">
            <button class="btn btn-small" onclick="forSortTimeline('timestamp')">Sort by Time</button>
            <button class="btn btn-small" onclick="forSortTimeline('type')">Sort by Type</button>
            <button class="btn btn-small" onclick="forSortTimeline('size')">Sort by Size</button>
            <button class="btn btn-small" onclick="forExportTimeline()">Export CSV</button>
        </div>
        <table class="data-table">
            <thead>
                <tr>
                    <th style="cursor:pointer" onclick="forSortTimeline('timestamp')">Timestamp</th>
                    <th style="cursor:pointer" onclick="forSortTimeline('type')">Type</th>
                    <th style="cursor:pointer" onclick="forSortTimeline('file')">File</th>
                    <th style="cursor:pointer" onclick="forSortTimeline('size')">Size</th>
                </tr>
            </thead>
            <tbody id="for-timeline-body">
                <tr><td colspan="4" class="empty-state">No timeline data. Build a timeline from a directory.</td></tr>
            </tbody>
        </table>
    </div>
</div>

<!-- ══ Evidence Tab ══ -->
<div class="tab-content" data-tab-group="forensics" data-tab="evidence">

    <!-- Evidence Files -->
    <div class="section">
        <h2>Evidence Files</h2>
        <div class="tool-actions">
            <button class="btn btn-small" onclick="forRefreshEvidence()">Refresh</button>
        </div>
        <div id="for-evidence-files">
            <p class="empty-state" style="padding:12px;font-size:0.85rem">No evidence files registered.</p>
        </div>
    </div>

    <!-- Carved Files List -->
    <div class="section">
        <h2>Carved Files</h2>
        <div id="for-evidence-carved">
            <p class="empty-state" style="padding:12px;font-size:0.85rem">No carved files. Use the Carve tab to extract files.</p>
        </div>
    </div>

    <!-- Chain of Custody -->
    <div class="section">
        <h2>Chain of Custody Log</h2>
        <div class="tool-actions">
            <button class="btn btn-small" onclick="forRefreshCustody()">Refresh</button>
            <button class="btn btn-small" onclick="forExportCustody()">Export</button>
        </div>
        <table class="data-table">
            <thead>
                <tr>
                    <th>Timestamp</th>
                    <th>Action</th>
                    <th>Target</th>
                    <th>Details</th>
                    <th>Hash</th>
                </tr>
            </thead>
            <tbody id="for-custody-body">
                <tr><td colspan="5" class="empty-state">No chain of custody entries.</td></tr>
            </tbody>
        </table>
    </div>
</div>

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

var forCarvedFiles = [];
var forTimelineEvents = [];
var forTimelineSortKey = 'timestamp';
var forTimelineSortAsc = true;

/* ── Image Tab ── */
function forHashFile() {
    var path = document.getElementById('for-hash-path').value.trim();
    if (!path) return;
    var btn = document.getElementById('btn-for-hash');
    setLoading(btn, true);
    postJSON('/forensics/hash', {path: path}).then(function(data) {
        setLoading(btn, false);
        if (data.error) {
            document.getElementById('for-hash-result').style.display = 'none';
            return;
        }
        document.getElementById('for-hash-result').style.display = '';
        document.getElementById('for-hash-md5').textContent = data.md5 || '—';
        document.getElementById('for-hash-sha1').textContent = data.sha1 || '—';
        document.getElementById('for-hash-sha256').textContent = data.sha256 || '—';
        forLogCustody('hash', path, 'Computed hashes', data.sha256 || '');
    }).catch(function() { setLoading(btn, false); });
}

function forVerifyHash() {
    var path = document.getElementById('for-verify-path').value.trim();
    var expected = document.getElementById('for-verify-hash').value.trim();
    if (!path || !expected) return;
    var btn = document.getElementById('btn-for-verify');
    setLoading(btn, true);
    postJSON('/forensics/verify', {path: path, expected: expected}).then(function(data) {
        setLoading(btn, false);
        var el = document.getElementById('for-verify-result');
        if (data.error) {
            el.textContent = 'Error: ' + data.error;
            el.style.color = 'var(--danger)';
            return;
        }
        if (data.match) {
            el.textContent = 'MATCH — Hash verified (' + (data.algorithm || 'unknown') + ')';
            el.style.color = 'var(--success,#4ade80)';
        } else {
            el.textContent = 'MISMATCH — Expected: ' + expected + ', Got: ' + (data.actual || '?');
            el.style.color = 'var(--danger)';
        }
        forLogCustody('verify', path, data.match ? 'Hash verified' : 'Hash mismatch', expected);
    }).catch(function() { setLoading(btn, false); });
}

function forCreateImage() {
    var source = document.getElementById('for-image-source').value.trim();
    var output = document.getElementById('for-image-output').value.trim();
    if (!source || !output) return;
    var btn = document.getElementById('btn-for-image');
    var log = document.getElementById('for-image-output-log');
    setLoading(btn, true);
    log.style.display = 'block';
    log.textContent = '';
    document.getElementById('for-image-status').textContent = 'Creating disk image...';
    postJSON('/forensics/create-image', {source: source, output: output}).then(function(data) {
        setLoading(btn, false);
        if (data.error) {
            document.getElementById('for-image-status').textContent = 'Error: ' + data.error;
            log.textContent = data.error;
            return;
        }
        document.getElementById('for-image-status').textContent = 'Image created successfully';
        var lines = [];
        if (data.size) lines.push('Size: ' + data.size);
        if (data.hash) lines.push('SHA256: ' + data.hash);
        if (data.duration) lines.push('Duration: ' + data.duration + 's');
        log.textContent = lines.join('\n') || 'Done.';
        forLogCustody('image', output, 'Disk image created from ' + source, data.hash || '');
    }).catch(function() { setLoading(btn, false); });
}

/* ── Carve Tab ── */
function forGetCarveTypes() {
    var checked = [];
    document.querySelectorAll('.for-carve-type:checked').forEach(function(cb) {
        checked.push(cb.value);
    });
    return checked;
}

function forCarve() {
    var source = document.getElementById('for-carve-source').value.trim();
    if (!source) return;
    var types = forGetCarveTypes();
    if (!types.length) { document.getElementById('for-carve-status').textContent = 'Select at least one file type'; return; }
    var maxFiles = parseInt(document.getElementById('for-carve-max').value) || 100;
    var btn = document.getElementById('btn-for-carve');
    setLoading(btn, true);
    document.getElementById('for-carve-status').textContent = 'Carving files from image...';
    postJSON('/forensics/carve', {source: source, types: types, max_files: maxFiles}).then(function(data) {
        setLoading(btn, false);
        if (data.error) {
            document.getElementById('for-carve-status').textContent = 'Error: ' + data.error;
            return;
        }
        forCarvedFiles = data.files || [];
        document.getElementById('for-carve-status').textContent = 'Carved ' + forCarvedFiles.length + ' file(s)';
        forRenderCarved();
        forLogCustody('carve', source, 'Carved ' + forCarvedFiles.length + ' files (' + types.join(',') + ')', '');
    }).catch(function() { setLoading(btn, false); });
}

function forRenderCarved() {
    var tbody = document.getElementById('for-carved-body');
    if (!forCarvedFiles.length) {
        tbody.innerHTML = '<tr><td colspan="5" class="empty-state">No carved files.</td></tr>';
        return;
    }
    var html = '';
    forCarvedFiles.forEach(function(f) {
        html += '<tr>'
            + '<td>' + esc(f.name || '—') + '</td>'
            + '<td>' + esc(f.type || '—') + '</td>'
            + '<td style="font-family:monospace;font-size:0.8rem">' + esc(f.offset != null ? '0x' + f.offset.toString(16) : '—') + '</td>'
            + '<td>' + esc(forFormatSize(f.size)) + '</td>'
            + '<td style="font-family:monospace;font-size:0.8rem">' + esc(f.md5 || '—') + '</td>'
            + '</tr>';
    });
    tbody.innerHTML = html;
}

function forFormatSize(bytes) {
    if (bytes == null) return '—';
    if (bytes < 1024) return bytes + ' B';
    if (bytes < 1048576) return (bytes / 1024).toFixed(1) + ' KB';
    if (bytes < 1073741824) return (bytes / 1048576).toFixed(1) + ' MB';
    return (bytes / 1073741824).toFixed(2) + ' GB';
}

function forExportCarved() {
    var blob = new Blob([JSON.stringify(forCarvedFiles, null, 2)], {type: 'application/json'});
    var a = document.createElement('a');
    a.href = URL.createObjectURL(blob);
    a.download = 'carved_files.json';
    a.click();
}

function forClearCarved() {
    forCarvedFiles = [];
    forRenderCarved();
}

/* ── Timeline Tab ── */
function forBuildTimeline() {
    var path = document.getElementById('for-timeline-path').value.trim();
    if (!path) return;
    var btn = document.getElementById('btn-for-timeline');
    setLoading(btn, true);
    document.getElementById('for-timeline-status').textContent = 'Building timeline...';
    postJSON('/forensics/timeline', {path: path}).then(function(data) {
        setLoading(btn, false);
        if (data.error) {
            document.getElementById('for-timeline-status').textContent = 'Error: ' + data.error;
            return;
        }
        forTimelineEvents = data.events || [];
        document.getElementById('for-timeline-status').textContent = 'Timeline built — ' + forTimelineEvents.length + ' event(s)';
        forRenderTimeline();
        forLogCustody('timeline', path, 'Built timeline with ' + forTimelineEvents.length + ' events', '');
    }).catch(function() { setLoading(btn, false); });
}

function forSortTimeline(key) {
    if (forTimelineSortKey === key) {
        forTimelineSortAsc = !forTimelineSortAsc;
    } else {
        forTimelineSortKey = key;
        forTimelineSortAsc = true;
    }
    forTimelineEvents.sort(function(a, b) {
        var va = a[key] || '', vb = b[key] || '';
        if (key === 'size') { va = Number(va) || 0; vb = Number(vb) || 0; }
        else { va = String(va).toLowerCase(); vb = String(vb).toLowerCase(); }
        if (va < vb) return forTimelineSortAsc ? -1 : 1;
        if (va > vb) return forTimelineSortAsc ? 1 : -1;
        return 0;
    });
    forRenderTimeline();
}

function forRenderTimeline() {
    var tbody = document.getElementById('for-timeline-body');
    if (!forTimelineEvents.length) {
        tbody.innerHTML = '<tr><td colspan="4" class="empty-state">No timeline data.</td></tr>';
        return;
    }
    var html = '';
    forTimelineEvents.forEach(function(e) {
        var typeCls = '';
        var t = (e.type || '').toLowerCase();
        if (t === 'created') typeCls = 'color:var(--success,#4ade80)';
        else if (t === 'modified') typeCls = 'color:var(--warning,#f59e0b)';
        else if (t === 'deleted') typeCls = 'color:var(--danger)';
        else if (t === 'accessed') typeCls = 'color:var(--accent)';
        html += '<tr>'
            + '<td style="font-family:monospace;font-size:0.8rem;white-space:nowrap">' + esc(e.timestamp || '—') + '</td>'
            + '<td><span style="' + typeCls + '">' + esc(e.type || '—') + '</span></td>'
            + '<td style="max-width:350px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">' + esc(e.file || '—') + '</td>'
            + '<td>' + esc(forFormatSize(e.size)) + '</td>'
            + '</tr>';
    });
    tbody.innerHTML = html;
}

function forExportTimeline() {
    if (!forTimelineEvents.length) return;
    var csv = 'Timestamp,Type,File,Size\n';
    forTimelineEvents.forEach(function(e) {
        csv += '"' + (e.timestamp || '') + '","' + (e.type || '') + '","' + (e.file || '').replace(/"/g, '""') + '",' + (e.size || 0) + '\n';
    });
    var blob = new Blob([csv], {type: 'text/csv'});
    var a = document.createElement('a');
    a.href = URL.createObjectURL(blob);
    a.download = 'forensic_timeline.csv';
    a.click();
}

/* ── Evidence Tab ── */
var forCustodyLog = [];

function forRefreshEvidence() {
    fetchJSON('/forensics/evidence').then(function(data) {
        var container = document.getElementById('for-evidence-files');
        var files = data.files || [];
        if (!files.length) {
            container.innerHTML = '<p class="empty-state" style="padding:12px;font-size:0.85rem">No evidence files registered.</p>';
        } else {
            var html = '<table class="data-table"><thead><tr><th>File</th><th>Size</th><th>Hash</th><th>Added</th></tr></thead><tbody>';
            files.forEach(function(f) {
                html += '<tr>'
                    + '<td>' + esc(f.name || '—') + '</td>'
                    + '<td>' + esc(forFormatSize(f.size)) + '</td>'
                    + '<td style="font-family:monospace;font-size:0.8rem;max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">' + esc(f.hash || '—') + '</td>'
                    + '<td style="font-size:0.8rem">' + esc(f.added || '—') + '</td>'
                    + '</tr>';
            });
            html += '</tbody></table>';
            container.innerHTML = html;
        }

        /* Also update carved files in evidence view */
        var carvedContainer = document.getElementById('for-evidence-carved');
        var carved = data.carved || forCarvedFiles;
        if (!carved.length) {
            carvedContainer.innerHTML = '<p class="empty-state" style="padding:12px;font-size:0.85rem">No carved files.</p>';
        } else {
            var chtml = '<table class="data-table"><thead><tr><th>Name</th><th>Type</th><th>Size</th><th>MD5</th></tr></thead><tbody>';
            carved.forEach(function(f) {
                chtml += '<tr>'
                    + '<td>' + esc(f.name || '—') + '</td>'
                    + '<td>' + esc(f.type || '—') + '</td>'
                    + '<td>' + esc(forFormatSize(f.size)) + '</td>'
                    + '<td style="font-family:monospace;font-size:0.8rem">' + esc(f.md5 || '—') + '</td>'
                    + '</tr>';
            });
            chtml += '</tbody></table>';
            carvedContainer.innerHTML = chtml;
        }
    }).catch(function() {});

    forRefreshCustody();
}

function forLogCustody(action, target, details, hash) {
    var entry = {
        timestamp: new Date().toISOString().replace('T', ' ').substring(0, 19),
        action: action,
        target: target,
        details: details,
        hash: hash
    };
    forCustodyLog.push(entry);
    postJSON('/forensics/custody/log', entry).catch(function() {});
    forRenderCustody();
}

function forRefreshCustody() {
    fetchJSON('/forensics/custody').then(function(data) {
        if (data.entries && data.entries.length) {
            forCustodyLog = data.entries;
        }
        forRenderCustody();
    }).catch(function() { forRenderCustody(); });
}

function forRenderCustody() {
    var tbody = document.getElementById('for-custody-body');
    if (!forCustodyLog.length) {
        tbody.innerHTML = '<tr><td colspan="5" class="empty-state">No chain of custody entries.</td></tr>';
        return;
    }
    var html = '';
    forCustodyLog.forEach(function(e) {
        html += '<tr>'
            + '<td style="font-size:0.8rem;white-space:nowrap">' + esc(e.timestamp || '—') + '</td>'
            + '<td><span class="badge" style="background:rgba(99,102,241,0.15);color:var(--accent)">' + esc(e.action || '—') + '</span></td>'
            + '<td style="max-width:250px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">' + esc(e.target || '—') + '</td>'
            + '<td style="font-size:0.85rem">' + esc(e.details || '—') + '</td>'
            + '<td style="font-family:monospace;font-size:0.75rem;max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">' + esc(e.hash || '—') + '</td>'
            + '</tr>';
    });
    tbody.innerHTML = html;
}

function forExportCustody() {
    var blob = new Blob([JSON.stringify(forCustodyLog, null, 2)], {type: 'application/json'});
    var a = document.createElement('a');
    a.href = URL.createObjectURL(blob);
    a.download = 'chain_of_custody.json';
    a.click();
}

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


Instruction: Create an AUTARCH web template for the 'Hack Hijack' 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: hack_hijack.html
Sections: 0
Tabs: 3
Forms/API calls: 8
Has JavaScript: True

Output:
{% extends "base.html" %}
{% block title %}Hack Hijack — AUTARCH{% endblock %}
{% block content %}
<div class="page-header">
    <h1>Hack Hijack</h1>
    <p class="text-muted">Scan for existing compromises and take over backdoors</p>
</div>

<div class="tabs">
    <button class="tab active" onclick="switchTab('scan')">Scan Target</button>
    <button class="tab" onclick="switchTab('results')">Results</button>
    <button class="tab" onclick="switchTab('sessions')">Sessions <span id="session-count" class="badge" style="display:none">0</span></button>
    <button class="tab" onclick="switchTab('history')">History</button>
</div>

<!-- Scan Tab -->
<div id="tab-scan" class="tab-content active">
    <div style="display:grid;grid-template-columns:360px 1fr;gap:1.5rem;align-items:start">
        <!-- Config panel -->
        <div class="card">
            <h3>Target Scan</h3>
            <div class="form-group">
                <label>Target IP Address</label>
                <input type="text" id="hh-target" class="form-control" placeholder="192.168.1.100">
            </div>
            <div class="form-group">
                <label>Scan Type</label>
                <select id="hh-scan-type" class="form-control" onchange="toggleCustomPorts()">
                    <option value="quick">Quick — Backdoor signature ports only (~30 ports)</option>
                    <option value="full">Full — All suspicious ports (~70 ports)</option>
                    <option value="nmap">Nmap Deep — Service version + OS detection (requires nmap)</option>
                    <option value="custom">Custom — Specify ports</option>
                </select>
            </div>
            <div class="form-group" id="custom-ports-group" style="display:none">
                <label>Custom Ports (comma-separated)</label>
                <input type="text" id="hh-custom-ports" class="form-control" placeholder="22,80,443,445,4444,8080">
            </div>
            <div style="display:flex;gap:0.5rem">
                <button id="hh-scan-btn" class="btn btn-primary" onclick="startScan()" style="flex:1">Scan for Compromises</button>
                <button id="hh-cancel-btn" class="btn" style="display:none;background:var(--danger);color:#fff" onclick="cancelScan()">Cancel</button>
            </div>

            <!-- Progress bar -->
            <div id="hh-progress-wrap" style="display:none;margin-top:1rem">
                <div style="display:flex;justify-content:space-between;font-size:0.8rem;margin-bottom:4px">
                    <span id="hh-prog-label">Scanning…</span>
                    <span id="hh-prog-pct">0%</span>
                </div>
                <div style="background:var(--border);border-radius:4px;height:6px;overflow:hidden">
                    <div id="hh-prog-bar" style="height:100%;background:var(--accent);transition:width 0.3s;width:0"></div>
                </div>
            </div>
        </div>

        <!-- Live output -->
        <div class="card" style="display:flex;flex-direction:column">
            <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:0.5rem">
                <h3 style="margin:0">Live Output</h3>
                <button class="btn btn-sm" onclick="clearOutput()">Clear</button>
            </div>
            <pre id="hh-output" style="background:#0d0d14;color:#c9d1d9;font-family:monospace;font-size:0.78rem;
                padding:12px;border-radius:var(--radius);height:340px;overflow-y:auto;
                white-space:pre-wrap;word-break:break-all;margin:0;border:1px solid var(--border)">Ready. Enter target and click Scan.</pre>

            <!-- Live found ports mini-table -->
            <div id="hh-live-ports" style="margin-top:0.75rem;display:none">
                <h4 style="font-size:0.8rem;color:var(--text-secondary);margin-bottom:6px">Live Discovered Ports</h4>
                <table class="data-table" style="font-size:0.78rem">
                    <thead><tr><th>Port</th><th>Service</th><th>Banner</th></tr></thead>
                    <tbody id="hh-live-ports-body"></tbody>
                </table>
            </div>
        </div>
    </div>

    <div class="card" style="margin-top:1.5rem">
        <h3>What This Scans For</h3>
        <div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:1rem;font-size:0.85rem">
            <div><strong style="color:var(--danger)">EternalBlue</strong><br>DoublePulsar SMB implant, MS17-010 vulnerability</div>
            <div><strong style="color:#f59e0b">RAT / C2</strong><br>Meterpreter, Cobalt Strike, njRAT, DarkComet, Quasar, AsyncRAT, Gh0st, Poison Ivy</div>
            <div><strong style="color:#6366f1">Shell Backdoors</strong><br>Netcat listeners, bind shells, telnet backdoors, rogue SSH</div>
            <div><strong style="color:#22c55e">Web Shells</strong><br>PHP/ASP/JSP shells on HTTP services</div>
            <div><strong style="color:#8b5cf6">Proxies</strong><br>SOCKS, HTTP proxies, tunnels used as pivot points</div>
            <div><strong style="color:#06b6d4">Miners</strong><br>Cryptocurrency mining stratum connections</div>
        </div>
    </div>
</div>

<!-- Results Tab -->
<div id="tab-results" class="tab-content" style="display:none">
    <div id="hh-no-results" class="card" style="text-align:center;color:var(--text-muted)">
        No scan results yet. Run a scan from the Scan tab.
    </div>
    <div id="hh-results" style="display:none">
        <div class="card">
            <div style="display:flex;justify-content:space-between;align-items:center">
                <h3>Scan: <span id="res-target" style="color:var(--accent)"></span></h3>
                <span id="res-time" style="font-size:0.8rem;color:var(--text-muted)"></span>
            </div>
            <div style="display:flex;gap:2rem;margin:1rem 0;font-size:0.85rem">
                <div><strong id="res-ports-count">0</strong> open ports</div>
                <div><strong id="res-backdoors-count" style="color:var(--danger)">0</strong> backdoor indicators</div>
                <div>Duration: <strong id="res-duration">0</strong>s</div>
                <div id="res-os" style="display:none">OS: <strong id="res-os-text"></strong></div>
            </div>
        </div>

        <!-- Backdoors -->
        <div id="hh-backdoors-section" class="card" style="margin-top:1rem;display:none">
            <h3 style="color:var(--danger)">Backdoor Indicators</h3>
            <table class="data-table" style="margin-top:0.5rem">
                <thead><tr>
                    <th>Confidence</th><th>Signature</th><th>Port</th>
                    <th>Category</th><th>Details</th><th>Action</th>
                </tr></thead>
                <tbody id="hh-backdoors-body"></tbody>
            </table>
        </div>

        <!-- SMB Info -->
        <div id="hh-smb-section" class="card" style="margin-top:1rem;display:none">
            <h3>SMB / EternalBlue</h3>
            <div id="hh-smb-info" style="font-size:0.85rem"></div>
        </div>

        <!-- Open Ports -->
        <div class="card" style="margin-top:1rem">
            <h3>Open Ports</h3>
            <table class="data-table" style="margin-top:0.5rem">
                <thead><tr>
                    <th>Port</th><th>Protocol</th><th>Service</th><th>Banner</th>
                </tr></thead>
                <tbody id="hh-ports-body"></tbody>
            </table>
        </div>
    </div>
</div>

<!-- Sessions Tab -->
<div id="tab-sessions" class="tab-content" style="display:none">
    <div id="hh-no-sessions" class="card" style="text-align:center;color:var(--text-muted)">
        No active sessions. Take over a detected backdoor to start a session.
    </div>
    <div id="hh-sessions-list"></div>

    <!-- Shell terminal -->
    <div id="hh-shell" class="card" style="margin-top:1rem;display:none">
        <div style="display:flex;justify-content:space-between;align-items:center">
            <h3>Shell: <span id="shell-target" style="color:var(--accent)"></span></h3>
            <button class="btn btn-sm" style="background:var(--danger);color:#fff" onclick="closeCurrentSession()">Disconnect</button>
        </div>
        <div id="shell-output" style="background:#0a0a0a;color:#0f0;font-family:monospace;font-size:0.8rem;
            padding:1rem;border-radius:var(--radius);height:400px;overflow-y:auto;white-space:pre-wrap;margin:0.5rem 0"></div>
        <div style="display:flex;gap:0.5rem;margin-top:0.5rem">
            <input type="text" id="shell-input" class="form-control" placeholder="Enter command..."
                   onkeypress="if(event.key==='Enter')shellExec()" style="font-family:monospace">
            <button class="btn btn-primary" onclick="shellExec()">Run</button>
        </div>
    </div>
</div>

<!-- History Tab -->
<div id="tab-history" class="tab-content" style="display:none">
    <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:1rem">
        <h3>Scan History</h3>
        <button class="btn btn-sm" style="background:var(--danger);color:#fff" onclick="clearHistory()">Clear All</button>
    </div>
    <div id="hh-history-list"></div>
</div>

<style>
.badge{display:inline-block;background:var(--danger);color:#fff;border-radius:10px;padding:0 6px;font-size:0.7rem;margin-left:4px;vertical-align:top}
.conf-high{color:var(--danger);font-weight:700}
.conf-medium{color:#f59e0b;font-weight:600}
.conf-low{color:var(--text-muted)}
.cat-eternalblue{color:var(--danger)}
.cat-rat{color:#f59e0b}
.cat-shell{color:#6366f1}
.cat-webshell{color:#22c55e}
.cat-proxy{color:#8b5cf6}
.cat-miner{color:#06b6d4}
.cat-generic{color:var(--text-secondary)}
/* output line colors */
#hh-output .ln-status{color:#7dd3fc}
#hh-output .ln-open{color:#4ade80;font-weight:700}
#hh-output .ln-warn{color:#fbbf24}
#hh-output .ln-error{color:#f87171}
#hh-output .ln-done{color:#a78bfa;font-weight:700}
#hh-output .ln-prog{color:#6b7280}
</style>

<script>
let currentScanResult = null;
let currentSessionId = null;
let activeStream = null;
let currentJobId = null;

function switchTab(name){
    document.querySelectorAll('.tab').forEach((t,i)=>t.classList.toggle('active',
        ['scan','results','sessions','history'][i]===name));
    document.querySelectorAll('.tab-content').forEach(c=>c.style.display='none');
    document.getElementById('tab-'+name).style.display='block';
    if(name==='sessions') loadSessions();
    if(name==='history') loadHistory();
}

function toggleCustomPorts(){
    document.getElementById('custom-ports-group').style.display=
        document.getElementById('hh-scan-type').value==='custom'?'':'none';
}

function appendOutput(text, cls){
    const out = document.getElementById('hh-output');
    const line = document.createElement('span');
    if(cls) line.className = cls;
    line.textContent = text + '\n';
    out.appendChild(line);
    out.scrollTop = out.scrollHeight;
}

function clearOutput(){
    document.getElementById('hh-output').textContent = '';
}

function startScan(){
    const target = document.getElementById('hh-target').value.trim();
    if(!target){ alert('Enter a target IP'); return; }
    const scanType = document.getElementById('hh-scan-type').value;
    let customPorts = [];
    if(scanType === 'custom'){
        customPorts = document.getElementById('hh-custom-ports').value
            .split(',').map(p=>parseInt(p.trim())).filter(p=>p>0&&p<65536);
        if(!customPorts.length){ alert('Enter valid ports'); return; }
    }

    // Reset UI
    clearOutput();
    document.getElementById('hh-live-ports').style.display = 'none';
    document.getElementById('hh-live-ports-body').innerHTML = '';
    document.getElementById('hh-scan-btn').disabled = true;
    document.getElementById('hh-cancel-btn').style.display = '';
    document.getElementById('hh-progress-wrap').style.display = '';
    document.getElementById('hh-prog-bar').style.width = '0';
    document.getElementById('hh-prog-pct').textContent = '0%';
    document.getElementById('hh-prog-label').textContent = 'Starting…';
    appendOutput(`[*] Starting ${scanType} scan on ${target}…`, 'ln-status');

    fetch('/hack-hijack/scan', {method:'POST', headers:{'Content-Type':'application/json'},
        body: JSON.stringify({target, scan_type: scanType, custom_ports: customPorts})})
    .then(r=>r.json()).then(d=>{
        if(!d.ok){ scanDone(false, d.error); return; }
        currentJobId = d.job_id;
        openStream(d.job_id);
    }).catch(e=>scanDone(false, e.message));
}

function openStream(jobId){
    if(activeStream){ activeStream.close(); activeStream = null; }
    const es = new EventSource('/hack-hijack/scan/' + jobId + '/stream');
    activeStream = es;

    es.onmessage = function(e){
        try{ handleEvent(JSON.parse(e.data)); } catch(ex){}
    };
    es.onerror = function(){
        es.close(); activeStream = null;
        appendOutput('[!] Stream connection lost', 'ln-error');
        scanDone(false, 'Stream disconnected');
    };
}

function handleEvent(ev){
    switch(ev.type){
        case 'progress': {
            const pct = ev.pct || 0;
            document.getElementById('hh-prog-bar').style.width = pct + '%';
            document.getElementById('hh-prog-pct').textContent = pct + '%';
            if(ev.msg) document.getElementById('hh-prog-label').textContent = ev.msg;
            if(ev.msg) appendOutput('[~] ' + ev.msg, 'ln-prog');
            break;
        }
        case 'status':
            appendOutput('[*] ' + ev.msg, 'ln-status');
            document.getElementById('hh-prog-label').textContent = ev.msg;
            break;
        case 'port_found': {
            const svc = ev.service ? ` (${ev.service})` : '';
            const banner = ev.banner ? `  "${ev.banner.slice(0,60)}"` : '';
            appendOutput(`[+] OPEN  ${ev.port}/tcp${svc}${banner}`, 'ln-open');
            addLivePort(ev.port, ev.service, ev.banner);
            break;
        }
        case 'error':
            appendOutput('[!] ' + ev.msg, 'ln-error');
            break;
        case 'done':
            if(activeStream){ activeStream.close(); activeStream = null; }
            document.getElementById('hh-prog-bar').style.width = '100%';
            document.getElementById('hh-prog-pct').textContent = '100%';
            if(ev.ok){
                appendOutput('[✓] Scan complete — fetching results…', 'ln-done');
                fetchResult(currentJobId);
            } else {
                appendOutput('[!] Scan failed', 'ln-error');
                scanDone(false, 'Scan failed');
            }
            break;
    }
}

function addLivePort(port, service, banner){
    const tbody = document.getElementById('hh-live-ports-body');
    document.getElementById('hh-live-ports').style.display = '';
    const tr = document.createElement('tr');
    tr.innerHTML = `<td>${port}</td><td>${esc(service||'—')}</td>
        <td style="font-family:monospace;font-size:0.72rem;max-width:300px;overflow:hidden;text-overflow:ellipsis">${esc((banner||'').slice(0,80))}</td>`;
    tbody.appendChild(tr);
}

function fetchResult(jobId){
    fetch('/hack-hijack/scan/' + jobId)
    .then(r=>r.json()).then(d=>{
        if(!d.done){ setTimeout(()=>fetchResult(jobId), 500); return; }
        if(!d.ok){ scanDone(false, d.error); return; }
        currentScanResult = d.result;
        appendOutput(`[✓] Done — ${d.result.open_ports.length} ports, ${d.result.backdoors.length} backdoor indicators`, 'ln-done');
        scanDone(true);
        renderResults(d.result);
        switchTab('results');
    }).catch(e=>scanDone(false, e.message));
}

function scanDone(ok, errMsg){
    document.getElementById('hh-scan-btn').disabled = false;
    document.getElementById('hh-cancel-btn').style.display = 'none';
    document.getElementById('hh-progress-wrap').style.display = 'none';
    if(!ok && errMsg) appendOutput('[!] Error: ' + errMsg, 'ln-error');
    currentJobId = null;
}

function cancelScan(){
    if(activeStream){ activeStream.close(); activeStream = null; }
    appendOutput('[x] Scan cancelled by user', 'ln-warn');
    scanDone(false);
}

function renderResults(r){
    document.getElementById('hh-no-results').style.display='none';
    document.getElementById('hh-results').style.display='';
    document.getElementById('res-target').textContent=r.target;
    document.getElementById('res-time').textContent=(r.scan_time||'').replace('T',' ').slice(0,19)+' UTC';
    document.getElementById('res-ports-count').textContent=(r.open_ports||[]).length;
    document.getElementById('res-backdoors-count').textContent=(r.backdoors||[]).length;
    document.getElementById('res-duration').textContent=r.duration;
    if(r.os_guess){
        document.getElementById('res-os').style.display='';
        document.getElementById('res-os-text').textContent=r.os_guess;
    }

    // Ports table
    const pb=document.getElementById('hh-ports-body');
    pb.innerHTML='';
    (r.open_ports||[]).forEach(p=>{
        const tr=document.createElement('tr');
        tr.innerHTML=`<td>${p.port}</td><td>${p.protocol}</td><td>${p.service||'—'}</td>
            <td style="font-family:monospace;font-size:0.75rem;max-width:400px;overflow:hidden;text-overflow:ellipsis">${esc(p.banner||'')}</td>`;
        pb.appendChild(tr);
    });

    // Backdoors
    const bs=document.getElementById('hh-backdoors-section');
    const bb=document.getElementById('hh-backdoors-body');
    if((r.backdoors||[]).length){
        bs.style.display='';
        bb.innerHTML='';
        r.backdoors.forEach((b,i)=>{
            const tr=document.createElement('tr');
            tr.innerHTML=`<td class="conf-${b.confidence}">${b.confidence.toUpperCase()}</td>
                <td>${esc(b.signature)}</td><td>${b.port}</td>
                <td><span class="cat-${b.category}">${b.category}</span></td>
                <td style="font-size:0.8rem">${esc(b.details)}</td>
                <td><button class="btn btn-sm btn-primary" onclick="tryTakeover(${i})">Takeover</button></td>`;
            bb.appendChild(tr);
        });
    } else {
        bs.style.display='none';
    }

    // SMB
    const ss=document.getElementById('hh-smb-section');
    if(r.smb_info&&(r.smb_info.vulnerable||r.smb_info.os)){
        ss.style.display='';
        let html='';
        if(r.smb_info.vulnerable) html+='<p style="color:var(--danger);font-weight:700">MS17-010 (EternalBlue) VULNERABLE</p>';
        if(r.smb_info.os) html+=`<p>OS: ${esc(r.smb_info.os)}</p>`;
        if(r.smb_info.signing) html+=`<p>SMB Signing: ${esc(r.smb_info.signing)}</p>`;
        document.getElementById('hh-smb-info').innerHTML=html;
    } else {
        ss.style.display='none';
    }
}

function tryTakeover(idx){
    if(!currentScanResult) return;
    const bd=currentScanResult.backdoors[idx];
    const host=currentScanResult.target;
    fetch('/hack-hijack/takeover',{method:'POST',headers:{'Content-Type':'application/json'},
        body:JSON.stringify({host,backdoor:{port:bd.port,takeover_method:bd.takeover_method}})})
    .then(r=>r.json()).then(d=>{
        if(d.session_id){
            currentSessionId=d.session_id;
            switchTab('sessions');
            openShell(d.session_id,host+':'+bd.port,d.initial_output||d.message||'');
        } else {
            alert(d.message||d.error||'Takeover result received');
            if(d.msf_command){
                navigator.clipboard.writeText(d.msf_command).then(()=>{
                    alert('MSF command copied to clipboard');
                }).catch(()=>{});
            }
        }
    }).catch(e=>alert('Error: '+e.message));
}

function loadSessions(){
    fetch('/hack-hijack/sessions').then(r=>r.json()).then(d=>{
        const list=document.getElementById('hh-sessions-list');
        const badge=document.getElementById('session-count');
        const sessions=d.sessions||[];
        if(!sessions.length){
            document.getElementById('hh-no-sessions').style.display='';
            list.innerHTML='';
            badge.style.display='none';
            return;
        }
        document.getElementById('hh-no-sessions').style.display='none';
        badge.style.display='';badge.textContent=sessions.length;
        list.innerHTML=sessions.map(s=>`<div class="card" style="margin-bottom:0.5rem;cursor:pointer"
            onclick="openShell('${esc(s.session_id)}','${esc(s.host)}:${s.port}','')">
            <div style="display:flex;justify-content:space-between;align-items:center">
                <div><strong>${esc(s.type)}</strong> &rarr; ${esc(s.host)}:${s.port}</div>
                <div style="font-size:0.75rem;color:var(--text-muted)">${(s.connected_at||'').slice(0,19)}</div>
            </div></div>`).join('');
    });
}

function openShell(sessionId,label,initial){
    currentSessionId=sessionId;
    document.getElementById('hh-shell').style.display='';
    document.getElementById('shell-target').textContent=label;
    const out=document.getElementById('shell-output');
    out.textContent=initial||'Connected. Type commands below.\n';
    document.getElementById('shell-input').focus();
}

function shellExec(){
    if(!currentSessionId) return;
    const input=document.getElementById('shell-input');
    const cmd=input.value.trim();
    if(!cmd) return;
    input.value='';
    const out=document.getElementById('shell-output');
    out.textContent+='$ '+cmd+'\n';
    fetch('/hack-hijack/sessions/'+currentSessionId+'/exec',{
        method:'POST',headers:{'Content-Type':'application/json'},
        body:JSON.stringify({command:cmd})})
    .then(r=>r.json()).then(d=>{
        if(d.ok) out.textContent+=(d.output||'')+'\n';
        else out.textContent+='[error] '+(d.error||'failed')+'\n';
        out.scrollTop=out.scrollHeight;
    }).catch(e=>{out.textContent+='[error] '+e.message+'\n'});
}

function closeCurrentSession(){
    if(!currentSessionId) return;
    fetch('/hack-hijack/sessions/'+currentSessionId,{method:'DELETE'})
    .then(r=>r.json()).then(()=>{
        document.getElementById('hh-shell').style.display='none';
        currentSessionId=null;
        loadSessions();
    });
}

function loadHistory(){
    fetch('/hack-hijack/history').then(r=>r.json()).then(d=>{
        const list=document.getElementById('hh-history-list');
        const scans=d.scans||[];
        if(!scans.length){list.innerHTML='<div class="card" style="text-align:center;color:var(--text-muted)">No scan history</div>';return}
        list.innerHTML=scans.map(s=>{
            const highCount=(s.backdoors||[]).filter(b=>b.confidence==='high').length;
            const medCount=(s.backdoors||[]).filter(b=>b.confidence==='medium').length;
            return `<div class="card" style="margin-bottom:0.5rem;cursor:pointer" onclick='loadHistoryScan(${JSON.stringify(s).replace(/'/g,"&#39;")})'>
                <div style="display:flex;justify-content:space-between;align-items:center">
                    <div><strong>${esc(s.target)}</strong>
                        — ${(s.open_ports||[]).length} ports,
                        ${(s.backdoors||[]).length} indicators
                        ${highCount?'<span class="conf-high">('+highCount+' HIGH)</span>':''}
                        ${medCount?'<span class="conf-medium">('+medCount+' MED)</span>':''}
                    </div>
                    <div style="font-size:0.75rem;color:var(--text-muted)">${(s.scan_time||'').slice(0,19)} — ${s.duration}s</div>
                </div></div>`;
        }).join('');
    });
}

function loadHistoryScan(scan){
    currentScanResult=scan;
    renderResults(scan);
    switchTab('results');
}

function clearHistory(){
    if(!confirm('Clear all scan history?')) return;
    fetch('/hack-hijack/history',{method:'DELETE'}).then(r=>r.json()).then(()=>loadHistory());
}

function esc(s){return s?String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;'):''}
</script>
{% endblock %}


Instruction: Create an AUTARCH web template for the 'Hardware' 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: hardware.html
Sections: 15
Tabs: 2
Forms/API calls: 0
Has JavaScript: True

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

{% block extra_head %}{% endblock %}

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

<!-- ── Connection Mode Toggle ── -->
<div class="hw-mode-bar">
    <span class="hw-mode-label">Connection Mode:</span>
    <div class="hw-mode-toggle">
        <button id="hw-mode-server" class="hw-mode-btn active" onclick="hwSetMode('server')">
            Server
            <span class="hw-mode-desc">Device on AUTARCH host</span>
        </button>
        <button id="hw-mode-direct" class="hw-mode-btn" onclick="hwSetMode('direct')">
            Direct (WebUSB)
            <span class="hw-mode-desc">Device on this PC</span>
        </button>
    </div>
    <div id="hw-mode-warning" class="hw-mode-warning" style="display:none"></div>
</div>

<!-- Status Cards (server mode) -->
<div id="hw-status-server" class="stats-grid" style="grid-template-columns:repeat(auto-fit,minmax(140px,1fr))">
    <div class="stat-card">
        <div class="stat-label">ADB</div>
        <div class="stat-value small">
            <span class="status-dot {{ 'active' if status.adb else 'inactive' }}"></span>
            {{ 'Available' if status.adb else 'Not found' }}
        </div>
    </div>
    <div class="stat-card">
        <div class="stat-label">Fastboot</div>
        <div class="stat-value small">
            <span class="status-dot {{ 'active' if status.fastboot else 'inactive' }}"></span>
            {{ 'Available' if status.fastboot else 'Not found' }}
        </div>
    </div>
    <div class="stat-card">
        <div class="stat-label">Serial</div>
        <div class="stat-value small">
            <span class="status-dot {{ 'active' if status.serial else 'warning' }}"></span>
            {{ 'Available' if status.serial else 'Not installed' }}
        </div>
    </div>
    <div class="stat-card">
        <div class="stat-label">ESPTool</div>
        <div class="stat-value small">
            <span class="status-dot {{ 'active' if status.esptool else 'warning' }}"></span>
            {{ 'Available' if status.esptool else 'Not installed' }}
        </div>
    </div>
</div>

<!-- Status Cards (direct mode) -->
<div id="hw-status-direct" class="stats-grid" style="grid-template-columns:repeat(auto-fit,minmax(140px,1fr)); display:none">
    <div class="stat-card">
        <div class="stat-label">WebUSB</div>
        <div class="stat-value small">
            <span id="hw-cap-webusb" class="status-dot inactive"></span>
            <span id="hw-cap-webusb-text">Checking...</span>
        </div>
    </div>
    <div class="stat-card">
        <div class="stat-label">Web Serial</div>
        <div class="stat-value small">
            <span id="hw-cap-webserial" class="status-dot inactive"></span>
            <span id="hw-cap-webserial-text">Checking...</span>
        </div>
    </div>
    <div class="stat-card">
        <div class="stat-label">ADB Device</div>
        <div class="stat-value small">
            <span id="hw-direct-adb-status" class="status-dot inactive"></span>
            <span id="hw-direct-adb-text">Not connected</span>
        </div>
    </div>
    <div class="stat-card">
        <div class="stat-label">Fastboot Device</div>
        <div class="stat-value small">
            <span id="hw-direct-fb-status" class="status-dot inactive"></span>
            <span id="hw-direct-fb-text">Not connected</span>
        </div>
    </div>
</div>

<!-- Main Tabs -->
<div class="tab-bar">
    <button class="tab active" data-tab-group="hw-main" data-tab="android" onclick="showTab('hw-main','android')">Android (ADB/Fastboot)</button>
    <button class="tab" data-tab-group="hw-main" data-tab="esp32" onclick="showTab('hw-main','esp32')">ESP32 (Serial)</button>
    <button class="tab" data-tab-group="hw-main" data-tab="factory" onclick="showTab('hw-main','factory')">Factory Flash</button>
</div>

<!-- ══ Android Tab ══ -->
<div class="tab-content active" data-tab-group="hw-main" data-tab="android">

    <!-- Archon Server Bootstrap -->
    <div id="hw-archon-section" class="section">
        <h2>Archon Server Bootstrap</h2>
        <p class="text-muted">Start the ArchonServer privileged process on a USB-connected Android device running the Archon companion app.</p>
        <div class="tool-actions" style="margin-bottom:12px">
            <button class="btn btn-primary" onclick="hwArchonBootstrap()">Bootstrap ArchonServer</button>
            <button class="btn btn-small" onclick="hwArchonStatus()">Check Status</button>
            <button class="btn btn-stop btn-small" onclick="hwArchonStop()">Stop Server</button>
        </div>
        <div id="hw-archon-output" class="output-panel scrollable" style="max-height:300px;overflow-y:auto;white-space:pre-wrap;word-wrap:break-word"></div>
    </div>

    <!-- Direct-mode ADB connect -->
    <div id="hw-direct-adb-connect" class="section" style="display:none">
        <h2>ADB Connection</h2>
        <p class="text-muted">Connect to an Android device via USB. The device must have USB Debugging enabled.</p>
        <div class="tool-actions">
            <button class="btn btn-primary" onclick="hwDirectAdbConnect()">Connect ADB Device</button>
            <button class="btn btn-danger btn-small" id="hw-direct-adb-disconnect-btn" onclick="hwDirectAdbDisconnect()" style="display:none">Disconnect</button>
        </div>
        <div id="hw-direct-adb-msg" class="progress-text"></div>
    </div>

    <!-- ADB Devices (server mode: list from server, direct mode: show connected) -->
    <div id="hw-adb-section" class="section">
        <h2>ADB Devices</h2>
        <div class="tool-actions" id="hw-adb-refresh-bar">
            <button class="btn btn-primary btn-small" onclick="hwRefreshAdbDevices()">Refresh</button>
        </div>
        <div id="hw-adb-devices"></div>
    </div>

    <!-- Device Actions (shown when device selected) -->
    <div id="hw-device-actions" style="display:none">

        <!-- Device Info -->
        <div class="section">
            <h2>Device Info <span id="hw-selected-serial" style="color:var(--accent);font-size:0.85rem"></span></h2>
            <div id="hw-device-info" class="device-info-grid"></div>
        </div>

        <!-- Shell -->
        <div class="section">
            <h2>ADB Shell</h2>
            <div class="input-row">
                <input type="text" id="hw-shell-cmd" placeholder="Enter command (e.g., ls /sdcard, getprop ro.product.model)" onkeydown="if(event.key==='Enter')hwShell()">
                <button class="btn btn-primary" onclick="hwShell()">Run</button>
            </div>
            <div id="hw-shell-output" class="output-panel scrollable" style="max-height:300px"></div>
        </div>

        <!-- Reboot / Sideload / File Transfer -->
        <div class="section">
            <h2>Device Actions</h2>
            <div class="tool-actions" style="margin-bottom:16px">
                <button class="btn btn-warning btn-small" onclick="hwReboot('system')">Reboot System</button>
                <button class="btn btn-warning btn-small" onclick="hwReboot('recovery')">Reboot Recovery</button>
                <button class="btn btn-warning btn-small" onclick="hwReboot('bootloader')">Reboot Bootloader</button>
            </div>

            <h3>Sideload / Install</h3>
            <!-- Server mode: text path input -->
            <div id="hw-sideload-server" class="input-row">
                <input type="text" id="hw-sideload-path" placeholder="Path to APK or ZIP file">
                <button class="btn btn-primary" onclick="hwSideload()">Sideload</button>
            </div>
            <!-- Direct mode: file picker -->
            <div id="hw-sideload-direct" class="input-row" style="display:none">
                <input type="file" id="hw-sideload-file" accept=".apk,.zip">
                <button class="btn btn-primary" onclick="hwSideloadDirect()">Install APK</button>
            </div>
            <div id="hw-sideload-progress" style="display:none">
                <div class="hw-progress">
                    <div class="hw-progress-fill" id="hw-sideload-fill" style="width:0%">
                        <span class="hw-progress-text" id="hw-sideload-pct">0%</span>
                    </div>
                </div>
                <div class="progress-text" id="hw-sideload-msg"></div>
            </div>

            <h3 style="margin-top:16px">File Transfer</h3>
            <!-- Server mode: text paths -->
            <div id="hw-transfer-server">
                <div class="form-row" style="margin-bottom:8px">
                    <div class="form-group">
                        <label>Local Path</label>
                        <input type="text" id="hw-push-local" placeholder="/path/to/local/file">
                    </div>
                    <div class="form-group">
                        <label>Remote Path</label>
                        <input type="text" id="hw-push-remote" placeholder="/sdcard/Download/">
                    </div>
                </div>
                <div class="tool-actions">
                    <button class="btn btn-small" onclick="hwPush()">Push to Device</button>
                    <button class="btn btn-small" onclick="hwPull()">Pull from Device</button>
                </div>
            </div>
            <!-- Direct mode: file picker + remote path -->
            <div id="hw-transfer-direct" style="display:none">
                <div class="form-row" style="margin-bottom:8px">
                    <div class="form-group">
                        <label>File to Push</label>
                        <input type="file" id="hw-push-file">
                    </div>
                    <div class="form-group">
                        <label>Remote Path</label>
                        <input type="text" id="hw-push-remote-direct" placeholder="/sdcard/Download/">
                    </div>
                </div>
                <div class="tool-actions">
                    <button class="btn btn-small" onclick="hwPushDirect()">Push to Device</button>
                    <button class="btn btn-small" onclick="hwPullDirect()">Pull from Device</button>
                </div>
            </div>
            <div class="progress-text" id="hw-transfer-msg"></div>

            <h3 style="margin-top:16px">Logcat</h3>
            <div class="input-row">
                <input type="number" id="hw-logcat-lines" value="50" min="10" max="1000" style="max-width:100px">
                <button class="btn btn-small" onclick="hwLogcat()">Get Logcat</button>
            </div>
            <div id="hw-logcat-output" class="output-panel scrollable" style="max-height:250px;display:none"></div>
        </div>
    </div>

    <!-- Direct-mode Fastboot connect -->
    <div id="hw-direct-fb-connect" class="section" style="display:none">
        <h2>Fastboot Connection</h2>
        <p class="text-muted">Connect to a device in bootloader/fastboot mode via USB.</p>
        <div class="tool-actions">
            <button class="btn btn-primary" onclick="hwDirectFbConnect()">Connect Fastboot Device</button>
            <button class="btn btn-danger btn-small" id="hw-direct-fb-disconnect-btn" onclick="hwDirectFbDisconnect()" style="display:none">Disconnect</button>
        </div>
        <div id="hw-direct-fb-msg" class="progress-text"></div>
    </div>

    <!-- Fastboot Devices (server mode) -->
    <div id="hw-fastboot-section" class="section">
        <h2>Fastboot Devices</h2>
        <div class="tool-actions" id="hw-fb-refresh-bar">
            <button class="btn btn-primary btn-small" onclick="hwRefreshFastbootDevices()">Refresh</button>
        </div>
        <div id="hw-fastboot-devices"></div>
    </div>

    <!-- Fastboot Actions (shown when fastboot device selected) -->
    <div id="hw-fastboot-actions" style="display:none">
        <div class="section">
            <h2>Fastboot Info <span id="hw-fb-selected" style="color:var(--accent);font-size:0.85rem"></span></h2>
            <div id="hw-fastboot-info" class="device-info-grid"></div>

            <h3 style="margin-top:16px">Flash Partition</h3>
            <div class="form-row" style="margin-bottom:8px">
                <div class="form-group">
                    <label>Partition</label>
                    <select id="hw-fb-partition">
                        <option value="boot">boot</option>
                        <option value="recovery">recovery</option>
                        <option value="system">system</option>
                        <option value="vendor">vendor</option>
                        <option value="vbmeta">vbmeta</option>
                        <option value="dtbo">dtbo</option>
                        <option value="vendor_boot">vendor_boot</option>
                        <option value="init_boot">init_boot</option>
                        <option value="radio">radio</option>
                        <option value="bootloader">bootloader</option>
                    </select>
                </div>
                <div class="form-group" id="hw-fb-firmware-server">
                    <label>Firmware Image</label>
                    <input type="text" id="hw-fb-firmware" placeholder="Path to firmware image file">
                </div>
                <div class="form-group" id="hw-fb-firmware-direct" style="display:none">
                    <label>Firmware Image</label>
                    <input type="file" id="hw-fb-firmware-file" accept=".img,.bin,.mbn">
                </div>
            </div>
            <div class="tool-actions">
                <button class="btn btn-primary" onclick="hwFastbootFlash()">Flash</button>
            </div>
            <div id="hw-fb-flash-progress" style="display:none">
                <div class="hw-progress">
                    <div class="hw-progress-fill" id="hw-fb-flash-fill" style="width:0%">
                        <span class="hw-progress-text" id="hw-fb-flash-pct">0%</span>
                    </div>
                </div>
                <div class="progress-text" id="hw-fb-flash-msg"></div>
            </div>

            <h3 style="margin-top:16px">Fastboot Actions</h3>
            <div class="tool-actions">
                <button class="btn btn-warning btn-small" onclick="hwFastbootReboot('system')">Reboot System</button>
                <button class="btn btn-warning btn-small" onclick="hwFastbootReboot('bootloader')">Reboot Bootloader</button>
                <button class="btn btn-warning btn-small" onclick="hwFastbootReboot('recovery')">Reboot Recovery</button>
                <button class="btn btn-danger btn-small" onclick="hwFastbootUnlock()">OEM Unlock</button>
            </div>
            <div id="hw-fb-confirm" style="display:none" class="confirm-dialog">
                <p>WARNING: OEM Unlock will erase all data on the device. This cannot be undone. Continue?</p>
                <div class="tool-actions">
                    <button class="btn btn-danger btn-small" onclick="hwFastbootUnlockConfirm()">Yes, Unlock</button>
                    <button class="btn btn-small" onclick="document.getElementById('hw-fb-confirm').style.display='none'">Cancel</button>
                </div>
            </div>
            <div class="progress-text" id="hw-fb-msg"></div>
        </div>
    </div>
</div>

<!-- ══ ESP32 Tab ══ -->
<div class="tab-content" data-tab-group="hw-main" data-tab="esp32">

    <!-- Direct-mode serial connect -->
    <div id="hw-direct-esp-connect" class="section" style="display:none">
        <h2>Serial Connection</h2>
        <p class="text-muted">Connect to an ESP32/ESP8266 device via USB serial. Select the device from the browser's serial port picker.</p>
        <div class="tool-actions">
            <button class="btn btn-primary" onclick="hwDirectEspConnect()">Select Serial Port</button>
            <button class="btn btn-danger btn-small" id="hw-direct-esp-disconnect-btn" onclick="hwDirectEspDisconnect()" style="display:none">Disconnect</button>
        </div>
        <div id="hw-direct-esp-msg" class="progress-text"></div>
    </div>

    <!-- Serial Ports (server mode) -->
    <div id="hw-serial-section">
        <div class="section">
            <h2>Serial Ports</h2>
            <div class="tool-actions">
                <button class="btn btn-primary btn-small" onclick="hwRefreshSerialPorts()">Refresh</button>
            </div>
            <div id="hw-serial-ports"></div>
        </div>

        <!-- Chip Detection -->
        <div class="section">
            <h2>Chip Detection</h2>
            <div class="form-row" style="margin-bottom:8px">
                <div class="form-group">
                    <label>Port</label>
                    <select id="hw-detect-port"><option value="">Select port...</option></select>
                </div>
                <div class="form-group">
                    <label>Baud Rate</label>
                    <select id="hw-detect-baud">
                        <option value="115200" selected>115200</option>
                        <option value="9600">9600</option>
                        <option value="57600">57600</option>
                        <option value="230400">230400</option>
                        <option value="460800">460800</option>
                        <option value="921600">921600</option>
                    </select>
                </div>
            </div>
            <div class="tool-actions">
                <button class="btn btn-primary" onclick="hwDetectChip()">Detect Chip</button>
            </div>
            <div id="hw-detect-result" class="progress-text"></div>
        </div>
    </div>

    <!-- ESP32 Flash -->
    <div class="section">
        <h2>Flash Firmware</h2>
        <!-- Server mode: port select + text path -->
        <div id="hw-esp-flash-server">
            <div class="form-row" style="margin-bottom:8px">
                <div class="form-group">
                    <label>Port</label>
                    <select id="hw-flash-port"><option value="">Select port...</option></select>
                </div>
                <div class="form-group">
                    <label>Baud Rate</label>
                    <select id="hw-flash-baud">
                        <option value="460800" selected>460800</option>
                        <option value="115200">115200</option>
                        <option value="230400">230400</option>
                        <option value="921600">921600</option>
                    </select>
                </div>
                <div class="form-group">
                    <label>Firmware File</label>
                    <input type="text" id="hw-flash-firmware" placeholder="Path to firmware binary">
                </div>
            </div>
        </div>
        <!-- Direct mode: file picker + address -->
        <div id="hw-esp-flash-direct" style="display:none">
            <div class="form-row" style="margin-bottom:8px">
                <div class="form-group">
                    <label>Baud Rate</label>
                    <select id="hw-flash-baud-direct">
                        <option value="460800" selected>460800</option>
                        <option value="115200">115200</option>
                        <option value="230400">230400</option>
                        <option value="921600">921600</option>
                    </select>
                </div>
                <div class="form-group">
                    <label>Firmware File</label>
                    <input type="file" id="hw-flash-firmware-file" accept=".bin,.elf">
                </div>
                <div class="form-group">
                    <label>Flash Address (hex)</label>
                    <input type="text" id="hw-flash-address" value="0x0" placeholder="0x0">
                </div>
            </div>
        </div>
        <div class="tool-actions">
            <button class="btn btn-primary" onclick="hwFlashEsp()">Flash</button>
        </div>
        <div id="hw-esp-flash-progress" style="display:none">
            <div class="hw-progress">
                <div class="hw-progress-fill" id="hw-esp-flash-fill" style="width:0%">
                    <span class="hw-progress-text" id="hw-esp-flash-pct">0%</span>
                </div>
            </div>
            <div class="progress-text" id="hw-esp-flash-msg"></div>
        </div>
    </div>

    <!-- Serial Monitor -->
    <div class="section">
        <h2>Serial Monitor</h2>
        <!-- Server mode: port selector -->
        <div id="hw-monitor-server">
            <div class="form-row" style="margin-bottom:8px">
                <div class="form-group">
                    <label>Port</label>
                    <select id="hw-monitor-port"><option value="">Select port...</option></select>
                </div>
                <div class="form-group">
                    <label>Baud Rate</label>
                    <select id="hw-monitor-baud">
                        <option value="115200" selected>115200</option>
                        <option value="9600">9600</option>
                        <option value="57600">57600</option>
                        <option value="230400">230400</option>
                        <option value="460800">460800</option>
                        <option value="921600">921600</option>
                    </select>
                </div>
            </div>
        </div>
        <!-- Direct mode: baud only (port already selected) -->
        <div id="hw-monitor-direct" style="display:none">
            <div class="form-row" style="margin-bottom:8px">
                <div class="form-group">
                    <label>Baud Rate</label>
                    <select id="hw-monitor-baud-direct">
                        <option value="115200" selected>115200</option>
                        <option value="9600">9600</option>
                        <option value="57600">57600</option>
                        <option value="230400">230400</option>
                        <option value="460800">460800</option>
                        <option value="921600">921600</option>
                    </select>
                </div>
            </div>
        </div>
        <div class="tool-actions">
            <button id="hw-monitor-start-btn" class="btn btn-primary btn-small" onclick="hwMonitorStart()">Start Monitor</button>
            <button id="hw-monitor-stop-btn" class="btn btn-stop btn-small" onclick="hwMonitorStop()" style="display:none">Stop</button>
            <button class="btn btn-small" onclick="hwMonitorClear()">Clear</button>
        </div>
        <div id="hw-monitor-output" class="serial-monitor"></div>
        <div class="serial-input-row">
            <input type="text" id="hw-monitor-input" placeholder="Send data..." onkeydown="if(event.key==='Enter')hwMonitorSend()">
            <button class="btn btn-small" onclick="hwMonitorSend()">Send</button>
        </div>
    </div>
</div>

<!-- ══ Factory Flash Tab (Direct mode only) ══ -->
<div class="tab-content" data-tab-group="hw-main" data-tab="factory">
    <div class="section">
        <h2>Factory Image Flash</h2>
        <p class="text-muted">Flash a complete factory image to an Android device. Inspired by PixelFlasher. Requires Direct mode with a device in fastboot.</p>

        <div id="hw-factory-requires-direct" style="display:none">
            <div class="hw-mode-warning">This feature requires Direct mode. Switch to Direct mode and connect a fastboot device first.</div>
        </div>

        <div id="hw-factory-controls">
            <!-- Step 1: Select factory image -->
            <div class="form-row" style="margin-bottom:16px">
                <div class="form-group" style="flex:2">
                    <label>Factory Image ZIP</label>
                    <input type="file" id="hw-factory-zip" accept=".zip" onchange="hwFactoryZipSelected(this)">
                </div>
            </div>

            <!-- Step 2: Flash plan (populated after ZIP selected) -->
            <div id="hw-factory-plan" style="display:none">
                <h3>Flash Plan</h3>
                <div id="hw-factory-device-check" class="progress-text"></div>
                <div id="hw-factory-plan-details"></div>

                <!-- Options -->
                <div class="form-row" style="margin:16px 0">
                    <label class="hw-checkbox"><input type="checkbox" id="hw-factory-skip-userdata" checked> Skip userdata (preserve data)</label>
                    <label class="hw-checkbox"><input type="checkbox" id="hw-factory-disable-vbmeta"> Disable vbmeta verification</label>
                </div>

                <!-- Step 3: Flash -->
                <div class="tool-actions">
                    <button class="btn btn-primary" onclick="hwFactoryFlash()">Flash Factory Image</button>
                </div>
            </div>

            <!-- Progress -->
            <div id="hw-factory-progress" style="display:none">
                <div class="hw-progress">
                    <div class="hw-progress-fill" id="hw-factory-fill" style="width:0%">
                        <span class="hw-progress-text" id="hw-factory-pct">0%</span>
                    </div>
                </div>
                <div class="progress-text" id="hw-factory-msg"></div>
                <div id="hw-factory-log" class="output-panel scrollable" style="max-height:200px;margin-top:8px"></div>
            </div>
        </div>
    </div>
</div>

<script>
document.addEventListener('DOMContentLoaded', function() {
    // Initialize mode from localStorage
    var savedMode = localStorage.getItem('hw_connection_mode') || 'server';
    hwSetMode(savedMode);

    // Server mode: auto-refresh
    if (savedMode === 'server') {
        hwRefreshAdbDevices();
        hwRefreshFastbootDevices();
        hwRefreshSerialPorts();
    }
});
</script>
{% endblock %}


Instruction: Create an AUTARCH web template for the 'Hash Detection' 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: hash_detection.html
Sections: 6
Tabs: 5
Forms/API calls: 0
Has JavaScript: True

Output:
{% extends "base.html" %}
{% block title %}Hash Toolkit - AUTARCH{% endblock %}

{% block content %}
<div class="page-header" style="display:flex;align-items:center;gap:1rem;flex-wrap:wrap">
    <div>
        <h1>Hash Toolkit</h1>
        <p style="margin:0;font-size:0.85rem;color:var(--text-secondary)">
            Identify unknown hashes, compute file/text digests, and look up threat intelligence.
        </p>
    </div>
    <a href="{{ url_for('analyze.index') }}" class="btn btn-sm" style="margin-left:auto">&larr; Analyze</a>
</div>

<!-- Tab Bar -->
<div class="tab-bar">
    <button class="tab active" data-tab-group="hashtool" data-tab="identify" onclick="showTab('hashtool','identify')">Identify</button>
    <button class="tab" data-tab-group="hashtool" data-tab="filehash" onclick="showTab('hashtool','filehash')">File Hash</button>
    <button class="tab" data-tab-group="hashtool" data-tab="texthash" onclick="showTab('hashtool','texthash')">Text Hash</button>
    <button class="tab" data-tab-group="hashtool" data-tab="mutate" onclick="showTab('hashtool','mutate')">Mutate</button>
    <button class="tab" data-tab-group="hashtool" data-tab="generate" onclick="showTab('hashtool','generate')">Generate</button>
    <button class="tab" data-tab-group="hashtool" data-tab="reference" onclick="showTab('hashtool','reference')">Reference</button>
</div>

<!-- ══ Identify Tab ══ -->
<div class="tab-content active" data-tab-group="hashtool" data-tab="identify">
<div class="section">
    <h2>Hash Algorithm Detection</h2>
    <p style="font-size:0.8rem;color:var(--text-muted);margin-bottom:8px">
        Paste an unknown hash to identify possible algorithms (supports 40+ hash types).
    </p>
    <div class="input-row">
        <input type="text" id="ht-identify-input" placeholder="Paste hash string here..." style="font-family:monospace">
        <button id="btn-ht-identify" class="btn btn-primary" onclick="htIdentify()">Identify</button>
    </div>
    <pre class="output-panel scrollable" id="ht-identify-output"></pre>
    <div id="ht-threat-links" style="margin-top:8px;display:none">
        <h3 style="font-size:0.85rem;color:var(--text-secondary);margin-bottom:6px">Threat Intelligence Lookups</h3>
        <div id="ht-links-container" style="display:flex;flex-wrap:wrap;gap:6px"></div>
    </div>
</div>
</div>

<!-- ══ File Hash Tab ══ -->
<div class="tab-content" data-tab-group="hashtool" data-tab="filehash">
<div class="section">
    <h2>File Hashing</h2>
    <p style="font-size:0.8rem;color:var(--text-muted);margin-bottom:8px">
        Compute CRC32, MD5, SHA1, SHA256, and SHA512 digests for any file.
    </p>
    <div class="input-row">
        <input type="text" id="ht-file-path" placeholder="File path (e.g., /usr/bin/ls)">
        <button id="btn-ht-file" class="btn btn-primary" onclick="htHashFile()">Hash File</button>
    </div>
    <pre class="output-panel scrollable" id="ht-file-output"></pre>
</div>
</div>

<!-- ══ Text Hash Tab ══ -->
<div class="tab-content" data-tab-group="hashtool" data-tab="texthash">
<div class="section">
    <h2>Text / String Hashing</h2>
    <div class="form-group" style="margin-bottom:0.75rem">
        <textarea id="ht-text-input" rows="4" placeholder="Enter text to hash..." style="width:100%;font-family:monospace"></textarea>
    </div>
    <div class="input-row">
        <select id="ht-text-algo">
            <option value="md5">MD5</option>
            <option value="sha1">SHA-1</option>
            <option value="sha224">SHA-224</option>
            <option value="sha256" selected>SHA-256</option>
            <option value="sha384">SHA-384</option>
            <option value="sha512">SHA-512</option>
            <option value="sha3-256">SHA3-256</option>
            <option value="sha3-512">SHA3-512</option>
            <option value="blake2b">BLAKE2b</option>
            <option value="blake2s">BLAKE2s</option>
            <option value="crc32">CRC32</option>
            <option value="all">ALL algorithms</option>
        </select>
        <button id="btn-ht-text" class="btn btn-primary" onclick="htHashText()">Hash</button>
    </div>
    <pre class="output-panel scrollable" id="ht-text-output"></pre>
</div>
</div>

<!-- ══ Mutate Tab ══ -->
<div class="tab-content" data-tab-group="hashtool" data-tab="mutate">
<div class="section">
    <h2>Change File Hash</h2>
    <p style="font-size:0.8rem;color:var(--text-muted);margin-bottom:8px">
        Append bytes to a copy of a file to change its hash. Original file is not modified.
    </p>
    <div class="input-row">
        <input type="text" id="ht-mutate-path" placeholder="File path to mutate">
        <select id="ht-mutate-method" style="max-width:140px">
            <option value="random">Random bytes</option>
            <option value="null">Null bytes</option>
            <option value="space">Spaces</option>
            <option value="newline">Newlines</option>
        </select>
        <input type="number" id="ht-mutate-bytes" value="4" min="1" max="1024" style="max-width:80px" title="Bytes to append">
        <button id="btn-ht-mutate" class="btn btn-primary" onclick="htMutate()">Mutate</button>
    </div>
    <pre class="output-panel scrollable" id="ht-mutate-output"></pre>
</div>
</div>

<!-- ══ Generate Tab ══ -->
<div class="tab-content" data-tab-group="hashtool" data-tab="generate">
<div class="section">
    <h2>Create Dummy Hash Files</h2>
    <p style="font-size:0.8rem;color:var(--text-muted);margin-bottom:8px">
        Generate test files with known content for hash verification and testing.
    </p>
    <div class="input-row">
        <input type="text" id="ht-gen-dir" placeholder="Output directory (e.g., /tmp)" value="/tmp">
        <input type="text" id="ht-gen-name" placeholder="Filename" value="hashtest.bin" style="max-width:180px">
    </div>
    <div class="input-row" style="margin-top:6px">
        <select id="ht-gen-type">
            <option value="random">Random data</option>
            <option value="zeros">All zeros (0x00)</option>
            <option value="ones">All ones (0xFF)</option>
            <option value="pattern">Repeating pattern (ABCDEF...)</option>
            <option value="text">Custom text (repeated)</option>
        </select>
        <input type="number" id="ht-gen-size" value="1024" min="1" max="10485760" style="max-width:120px" title="Size in bytes">
        <button id="btn-ht-gen" class="btn btn-primary" onclick="htGenerate()">Generate</button>
    </div>
    <div id="ht-gen-custom-row" class="input-row" style="margin-top:6px;display:none">
        <input type="text" id="ht-gen-custom" placeholder="Custom text to repeat...">
    </div>
    <pre class="output-panel scrollable" id="ht-gen-output"></pre>
</div>
</div>

<!-- ══ Reference Tab ══ -->
<div class="tab-content" data-tab-group="hashtool" data-tab="reference">
<div class="section">
    <h2>Hash Type Reference</h2>
    <p style="font-size:0.8rem;color:var(--text-muted);margin-bottom:8px">
        Common hash types, output lengths, and hashcat mode numbers.
    </p>
    <div id="ht-reference-table" style="overflow-x:auto"></div>
</div>
</div>

<script>
/* ── Hash Toolkit ─────────────────────────────────────────────────── */

function htIdentify() {
    var hash = document.getElementById('ht-identify-input').value.trim();
    if (!hash) return;
    var btn = document.getElementById('btn-ht-identify');
    setLoading(btn, true);
    postJSON('/analyze/hash-detection/identify', {hash: hash}).then(function(data) {
        setLoading(btn, false);
        if (data.error) { renderOutput('ht-identify-output', 'Error: ' + data.error); return; }

        var lines = [];
        lines.push('Input:  ' + data.hash);
        lines.push('Length: ' + data.length + ' characters');
        lines.push('');

        if (data.matches && data.matches.length) {
            lines.push('Possible Algorithms (' + data.matches.length + ' match' + (data.matches.length > 1 ? 'es' : '') + '):');
            lines.push('');
            data.matches.forEach(function(m, i) {
                var hc = m.hashcat !== null ? '  [hashcat: ' + m.hashcat + ']' : '';
                lines.push('  ' + (i + 1) + '. ' + m.name + hc);
                lines.push('     ' + m.description);
            });
        } else {
            lines.push(data.message || 'No matching hash algorithms found.');
        }
        renderOutput('ht-identify-output', lines.join('\n'));

        // Show threat intel links for hex hashes of typical lengths
        var linksDiv = document.getElementById('ht-threat-links');
        var container = document.getElementById('ht-links-container');
        var hexLens = [32, 40, 64, 128];
        if (/^[a-fA-F0-9]+$/.test(hash) && hexLens.indexOf(hash.length) !== -1) {
            container.innerHTML = '';
            htGetThreatLinks(hash).forEach(function(link) {
                var a = document.createElement('a');
                a.href = link.url;
                a.target = '_blank';
                a.rel = 'noopener';
                a.className = 'btn btn-sm';
                a.textContent = link.name;
                a.style.fontSize = '0.8rem';
                container.appendChild(a);
            });
            linksDiv.style.display = '';
        } else {
            linksDiv.style.display = 'none';
        }
    }).catch(function() { setLoading(btn, false); });
}

function htGetThreatLinks(hash) {
    return [
        {name: 'VirusTotal',      url: 'https://www.virustotal.com/gui/file/' + hash},
        {name: 'Hybrid Analysis', url: 'https://www.hybrid-analysis.com/search?query=' + hash},
        {name: 'MalwareBazaar',   url: 'https://bazaar.abuse.ch/browse.php?search=' + hash},
        {name: 'AlienVault OTX',  url: 'https://otx.alienvault.com/indicator/file/' + hash},
        {name: 'Shodan',          url: 'https://www.shodan.io/search?query=' + hash},
    ];
}

function htHashFile() {
    var filepath = document.getElementById('ht-file-path').value.trim();
    if (!filepath) return;
    var btn = document.getElementById('btn-ht-file');
    setLoading(btn, true);
    postJSON('/analyze/hash-detection/file', {filepath: filepath}).then(function(data) {
        setLoading(btn, false);
        if (data.error) { renderOutput('ht-file-output', 'Error: ' + data.error); return; }
        var lines = [];
        lines.push('File:   ' + data.path);
        lines.push('Size:   ' + data.size + ' bytes');
        lines.push('');
        lines.push('Digests:');
        if (data.hashes) {
            lines.push('  CRC32:  ' + (data.hashes.crc32 || ''));
            lines.push('  MD5:    ' + (data.hashes.md5 || ''));
            lines.push('  SHA1:   ' + (data.hashes.sha1 || ''));
            lines.push('  SHA256: ' + (data.hashes.sha256 || ''));
            lines.push('  SHA512: ' + (data.hashes.sha512 || ''));
        }
        renderOutput('ht-file-output', lines.join('\n'));
    }).catch(function() { setLoading(btn, false); });
}

function htHashText() {
    var text = document.getElementById('ht-text-input').value;
    if (!text) return;
    var algo = document.getElementById('ht-text-algo').value;
    var btn = document.getElementById('btn-ht-text');
    setLoading(btn, true);
    postJSON('/analyze/hash-detection/text', {text: text, algorithm: algo}).then(function(data) {
        setLoading(btn, false);
        if (data.error) { renderOutput('ht-text-output', 'Error: ' + data.error); return; }
        var lines = [];
        lines.push('Input length: ' + data.text_length + ' characters');
        lines.push('');
        if (data.algorithm === 'all' && data.hashes) {
            lines.push('All Digests:');
            Object.keys(data.hashes).sort().forEach(function(name) {
                var pad = '          '.slice(0, 10 - name.length);
                lines.push('  ' + name + ':' + pad + data.hashes[name]);
            });
        } else {
            lines.push('Algorithm: ' + data.algorithm.toUpperCase());
            lines.push('Hash:      ' + data.hash);
        }
        renderOutput('ht-text-output', lines.join('\n'));
    }).catch(function() { setLoading(btn, false); });
}

function htMutate() {
    var filepath = document.getElementById('ht-mutate-path').value.trim();
    if (!filepath) return;
    var method = document.getElementById('ht-mutate-method').value;
    var numBytes = document.getElementById('ht-mutate-bytes').value || '4';
    var btn = document.getElementById('btn-ht-mutate');
    setLoading(btn, true);
    postJSON('/analyze/hash-detection/mutate', {filepath: filepath, method: method, num_bytes: numBytes}).then(function(data) {
        setLoading(btn, false);
        if (data.error) { renderOutput('ht-mutate-output', 'Error: ' + data.error); return; }
        var lines = [];
        lines.push('Original: ' + data.original_path + ' (' + data.original_size + ' bytes)');
        lines.push('Mutated:  ' + data.mutated_path + ' (' + data.mutated_size + ' bytes)');
        lines.push('Method:   ' + data.method + ' (' + data.bytes_appended + ' bytes appended)');
        lines.push('');
        lines.push('Before:');
        lines.push('  MD5:    ' + data.original_hashes.md5);
        lines.push('  SHA256: ' + data.original_hashes.sha256);
        lines.push('');
        lines.push('After:');
        lines.push('  MD5:    ' + data.new_hashes.md5);
        lines.push('  SHA256: ' + data.new_hashes.sha256);
        renderOutput('ht-mutate-output', lines.join('\n'));
    }).catch(function() { setLoading(btn, false); });
}

function htGenerate() {
    var dir = document.getElementById('ht-gen-dir').value.trim();
    var name = document.getElementById('ht-gen-name').value.trim();
    var type = document.getElementById('ht-gen-type').value;
    var size = document.getElementById('ht-gen-size').value || '1024';
    var custom = document.getElementById('ht-gen-custom').value;
    if (!dir || !name) return;
    var btn = document.getElementById('btn-ht-gen');
    setLoading(btn, true);
    postJSON('/analyze/hash-detection/generate', {
        output_dir: dir, filename: name, content_type: type, size: size, custom_text: custom
    }).then(function(data) {
        setLoading(btn, false);
        if (data.error) { renderOutput('ht-gen-output', 'Error: ' + data.error); return; }
        var lines = [];
        lines.push('Created: ' + data.path);
        lines.push('Size:    ' + data.size + ' bytes');
        lines.push('Content: ' + data.content_type);
        lines.push('');
        lines.push('Digests:');
        if (data.hashes) {
            lines.push('  CRC32:  ' + (data.hashes.crc32 || ''));
            lines.push('  MD5:    ' + (data.hashes.md5 || ''));
            lines.push('  SHA1:   ' + (data.hashes.sha1 || ''));
            lines.push('  SHA256: ' + (data.hashes.sha256 || ''));
            lines.push('  SHA512: ' + (data.hashes.sha512 || ''));
        }
        renderOutput('ht-gen-output', lines.join('\n'));
    }).catch(function() { setLoading(btn, false); });
}

/* Show/hide custom text input when content type changes */
document.getElementById('ht-gen-type').addEventListener('change', function() {
    document.getElementById('ht-gen-custom-row').style.display = this.value === 'text' ? '' : 'none';
});

/* Build static reference table */
(function() {
    var el = document.getElementById('ht-reference-table');
    if (!el) return;
    var ref = [
        ['CRC32',         '8',   'Hex',        '11500'],
        ['MD4',           '32',  'Hex',        '900'],
        ['MD5',           '32',  'Hex',        '0'],
        ['NTLM',          '32',  'Hex',        '1000'],
        ['LM',            '32',  'Hex',        '3000'],
        ['MySQL323',      '16',  'Hex',        '200'],
        ['MySQL41',       '41',  '*Hex',       '300'],
        ['RIPEMD-160',    '40',  'Hex',        '6000'],
        ['SHA-1',         '40',  'Hex',        '100'],
        ['Tiger-192',     '48',  'Hex',        '10000'],
        ['SHA-224',       '56',  'Hex',        '--'],
        ['SHA-256',       '64',  'Hex',        '1400'],
        ['SHA-384',       '96',  'Hex',        '10800'],
        ['SHA-512',       '128', 'Hex',        '1700'],
        ['SHA3-256',      '64',  'Hex',        '17400'],
        ['SHA3-512',      '128', 'Hex',        '17600'],
        ['BLAKE2b',       '128', 'Hex',        '600'],
        ['BLAKE2s',       '64',  'Hex',        '--'],
        ['Whirlpool',     '128', 'Hex',        '6100'],
        ['bcrypt',        '60',  '$2a$...',    '3200'],
        ['MD5 crypt',     '34',  '$1$...',     '500'],
        ['SHA-256 crypt', '63',  '$5$...',     '7400'],
        ['SHA-512 crypt', '98',  '$6$...',     '1800'],
        ['Argon2',        'var', '$argon2...', '--'],
        ['PBKDF2',        'var', '$pbkdf2...', '10900'],
        ['WordPress',     '34',  '$P$...',     '400'],
        ['Drupal7',       '55',  '$S$...',     '7900'],
    ];
    var html = '<table style="width:100%;font-size:0.82rem;border-collapse:collapse">';
    html += '<thead><tr style="border-bottom:2px solid var(--border);text-align:left">';
    html += '<th style="padding:6px 10px">Algorithm</th>';
    html += '<th style="padding:6px 10px">Length</th>';
    html += '<th style="padding:6px 10px">Format</th>';
    html += '<th style="padding:6px 10px">Hashcat Mode</th></tr></thead><tbody>';
    ref.forEach(function(r) {
        html += '<tr style="border-bottom:1px solid var(--border)">';
        r.forEach(function(c) { html += '<td style="padding:5px 10px;font-family:monospace">' + c + '</td>'; });
        html += '</tr>';
    });
    html += '</tbody></table>';
    el.innerHTML = html;
})();
</script>
{% endblock %}