<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ScanFixAI — Ford Vehicle Diagnostic Tool</title>
<style>
/* ─── Reset & Base ─────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { font-size: 14px; scroll-behavior: smooth; }
body {
    font-family: 'Segoe UI', -apple-system, BlinkMacSystemFont, sans-serif;
    background: #0f0f23;
    color: #e0e0e0;
    min-height: 100vh;
    line-height: 1.5;
}
a { color: #00e676; text-decoration: none; }
a:hover { text-decoration: underline; }
button { cursor: pointer; font-family: inherit; }
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: #1a1a2e; }
::-webkit-scrollbar-thumb { background: #333; border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: #555; }

/* ─── Header ───────────────────────────────────────────────────────────── */
.header {
    background: linear-gradient(135deg, #0a0a1a 0%, #1a1a2e 100%);
    border-bottom: 2px solid #00e676;
    padding: 12px 24px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    position: sticky;
    top: 0;
    z-index: 100;
}
.header-left { display: flex; align-items: center; gap: 16px; }
.logo {
    font-size: 1.6rem;
    font-weight: 800;
    letter-spacing: -0.5px;
}
.logo span:first-child { color: #4fc3f7; }
.logo span:last-child { color: #00e676; }
.header-status {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.85rem;
    color: #888;
}
.status-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: #666;
    transition: background 0.3s;
}
.status-dot.connected { background: #00e676; box-shadow: 0 0 8px #00e67666; }
.status-dot.error { background: #ff5252; box-shadow: 0 0 8px #ff525266; }
.header-right { display: flex; align-items: center; gap: 12px; }

/* ─── Navigation ───────────────────────────────────────────────────────── */
.nav {
    background: #12122a;
    border-bottom: 1px solid #222;
    padding: 0 24px;
    display: flex;
    gap: 0;
    overflow-x: auto;
}
.nav-btn {
    background: none;
    border: none;
    color: #888;
    padding: 12px 20px;
    font-size: 0.9rem;
    font-weight: 500;
    border-bottom: 2px solid transparent;
    transition: all 0.2s;
    white-space: nowrap;
}
.nav-btn:hover { color: #ccc; background: #1a1a3a; }
.nav-btn.active { color: #00e676; border-bottom-color: #00e676; }

/* ─── Layout ───────────────────────────────────────────────────────────── */
.main { padding: 20px 24px; max-width: 1600px; margin: 0 auto; }
.section { display: none; }
.section.active { display: block; }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.grid-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 16px; }
@media (max-width: 900px) {
    .grid-2, .grid-3 { grid-template-columns: 1fr; }
}

/* ─── Cards ────────────────────────────────────────────────────────────── */
.card {
    background: #16162e;
    border: 1px solid #252545;
    border-radius: 10px;
    padding: 20px;
    margin-bottom: 16px;
    transition: border-color 0.2s;
}
.card:hover { border-color: #353565; }
.card-title {
    font-size: 1rem;
    font-weight: 600;
    color: #aaa;
    text-transform: uppercase;
    letter-spacing: 1px;
    margin-bottom: 16px;
    display: flex;
    align-items: center;
    gap: 8px;
}
.card-title .icon { font-size: 1.2rem; }

/* ─── Buttons ──────────────────────────────────────────────────────────── */
.btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 10px 20px;
    border: none;
    border-radius: 6px;
    font-size: 0.9rem;
    font-weight: 600;
    transition: all 0.2s;
}
.btn-primary { background: #00e676; color: #0a0a1a; }
.btn-primary:hover { background: #00c853; transform: translateY(-1px); }
.btn-primary:active { transform: translateY(0); }
.btn-danger { background: #ff5252; color: #fff; }
.btn-danger:hover { background: #ff1744; }
.btn-secondary { background: #252545; color: #ccc; }
.btn-secondary:hover { background: #303060; }
.btn-outline {
    background: transparent;
    color: #00e676;
    border: 1px solid #00e676;
}
.btn-outline:hover { background: #00e67615; }
.btn-sm { padding: 6px 14px; font-size: 0.8rem; }
.btn-lg { padding: 14px 28px; font-size: 1rem; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; transform: none; }
.btn-group { display: flex; gap: 8px; flex-wrap: wrap; }

/* ─── Inputs ───────────────────────────────────────────────────────────── */
.input, select {
    background: #1a1a35;
    border: 1px solid #333;
    border-radius: 6px;
    color: #e0e0e0;
    padding: 10px 14px;
    font-size: 0.9rem;
    font-family: inherit;
    outline: none;
    transition: border-color 0.2s;
}
.input:focus, select:focus { border-color: #00e676; }
.input-group { display: flex; gap: 8px; align-items: center; }
label {
    display: block;
    color: #888;
    font-size: 0.8rem;
    font-weight: 500;
    margin-bottom: 4px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

/* ─── Tags / Badges ────────────────────────────────────────────────────── */
.badge {
    display: inline-flex;
    align-items: center;
    padding: 3px 10px;
    border-radius: 20px;
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
.badge-green { background: #00e67622; color: #00e676; }
.badge-red { background: #ff525222; color: #ff5252; }
.badge-yellow { background: #ffc10722; color: #ffc107; }
.badge-blue { background: #4fc3f722; color: #4fc3f7; }
.badge-gray { background: #66666622; color: #999; }

.severity-critical { color: #ff5252; }
.severity-high { color: #ff9800; }
.severity-medium { color: #ffc107; }
.severity-low { color: #4fc3f7; }

/* ─── Tables ───────────────────────────────────────────────────────────── */
.table-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; }
th {
    text-align: left;
    padding: 10px 14px;
    font-size: 0.8rem;
    color: #888;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    border-bottom: 1px solid #252545;
    background: #12122a;
    position: sticky;
    top: 0;
}
td {
    padding: 10px 14px;
    border-bottom: 1px solid #1e1e3a;
    font-size: 0.9rem;
}
tr:hover { background: #1a1a3a; }

/* ─── Module List ──────────────────────────────────────────────────────── */
.module-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 14px;
    border-bottom: 1px solid #1e1e3a;
    transition: background 0.15s;
    cursor: pointer;
}
.module-item:hover { background: #1a1a3a; }
.module-item:last-child { border-bottom: none; }
.module-info { display: flex; align-items: center; gap: 10px; }
.module-status {
    width: 8px;
    height: 8px;
    border-radius: 50%;
}
.module-status.ok { background: #00e676; }
.module-status.warning { background: #ffc107; }
.module-status.error { background: #ff5252; }
.module-status.no_response { background: #555; }
.module-name { font-weight: 500; }
.module-addr { color: #666; font-family: 'Consolas', monospace; font-size: 0.85rem; }
.module-dtcs { font-size: 0.85rem; color: #888; }

/* ─── DTC Card ─────────────────────────────────────────────────────────── */
.dtc-item {
    background: #1a1a35;
    border: 1px solid #252545;
    border-radius: 8px;
    padding: 16px;
    margin-bottom: 10px;
    transition: border-color 0.2s;
}
.dtc-item:hover { border-color: #353565; }
.dtc-item.active-dtc { border-left: 3px solid #ff5252; }
.dtc-item.stored-dtc { border-left: 3px solid #ffc107; }
.dtc-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
}
.dtc-code {
    font-family: 'Consolas', monospace;
    font-size: 1.1rem;
    font-weight: 700;
    color: #4fc3f7;
}
.dtc-desc { font-weight: 500; margin-bottom: 6px; }
.dtc-module { color: #888; font-size: 0.85rem; }
.dtc-details { margin-top: 12px; padding-top: 12px; border-top: 1px solid #252545; }
.dtc-details summary {
    cursor: pointer;
    color: #00e676;
    font-size: 0.85rem;
    font-weight: 500;
    user-select: none;
}
.dtc-details summary:hover { text-decoration: underline; }
.dtc-cause-list, .dtc-fix-list {
    margin: 8px 0 8px 20px;
    font-size: 0.85rem;
    color: #bbb;
}
.dtc-cause-list li, .dtc-fix-list li { margin-bottom: 4px; }

/* ─── As-Built Hex Editor ──────────────────────────────────────────────── */
.hex-editor {
    font-family: 'Consolas', 'Courier New', monospace;
    font-size: 0.95rem;
    background: #0c0c1e;
    border: 1px solid #252545;
    border-radius: 8px;
    padding: 16px;
    overflow-x: auto;
}
.hex-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 4px 0;
    border-bottom: 1px solid #151530;
}
.hex-row:last-child { border-bottom: none; }
.hex-addr { color: #4fc3f7; min-width: 100px; font-weight: 600; }
.hex-bytes { display: flex; gap: 6px; flex-wrap: wrap; }
.hex-byte {
    background: #1a1a35;
    border: 1px solid #303060;
    border-radius: 3px;
    padding: 4px 6px;
    width: 32px;
    text-align: center;
    color: #00e676;
    font-size: 0.9rem;
    outline: none;
    transition: all 0.15s;
}
.hex-byte:focus { border-color: #00e676; background: #202050; }
.hex-byte.modified { color: #ff9800; border-color: #ff9800; background: #2a2000; }

/* ─── Analysis Panel ───────────────────────────────────────────────────── */
.analysis-box {
    background: #0c0c1e;
    border: 1px solid #252545;
    border-radius: 8px;
    padding: 20px;
    margin-bottom: 16px;
}
.analysis-summary {
    font-size: 1.05rem;
    line-height: 1.7;
    margin-bottom: 16px;
}
.urgency-banner {
    padding: 12px 16px;
    border-radius: 6px;
    font-weight: 600;
    margin-bottom: 16px;
}
.urgency-critical { background: #ff525220; border: 1px solid #ff5252; color: #ff5252; }
.urgency-high { background: #ff980020; border: 1px solid #ff9800; color: #ff9800; }
.urgency-medium { background: #ffc10720; border: 1px solid #ffc107; color: #ffc107; }
.urgency-low { background: #4fc3f720; border: 1px solid #4fc3f7; color: #4fc3f7; }
.urgency-none { background: #00e67620; border: 1px solid #00e676; color: #00e676; }
.fix-card {
    background: #16162e;
    border: 1px solid #252545;
    border-radius: 8px;
    padding: 16px;
    margin-bottom: 12px;
}
.fix-card h4 { color: #00e676; margin-bottom: 8px; }
.fix-meta {
    display: flex;
    gap: 16px;
    margin: 8px 0;
    flex-wrap: wrap;
}
.fix-meta span { font-size: 0.8rem; color: #888; }
.fix-meta span strong { color: #bbb; }
.fix-steps {
    margin: 10px 0 10px 20px;
    font-size: 0.9rem;
    color: #ccc;
}
.fix-steps li { margin-bottom: 6px; }

/* ─── History ──────────────────────────────────────────────────────────── */
.history-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    border-bottom: 1px solid #1e1e3a;
    cursor: pointer;
    transition: background 0.15s;
}
.history-item:hover { background: #1a1a3a; }
.history-date { color: #4fc3f7; font-weight: 500; }
.history-codes { color: #888; font-size: 0.85rem; display: flex; gap: 6px; flex-wrap: wrap; margin-top: 4px; }

/* ─── Connection Panel ─────────────────────────────────────────────────── */
.connect-panel {
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
}
.adapter-info {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 4px 16px;
    font-size: 0.9rem;
}
.adapter-info dt { color: #888; }
.adapter-info dd { color: #e0e0e0; font-weight: 500; }

/* ─── Vehicle Info Grid ────────────────────────────────────────────────── */
.vehicle-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 12px;
}
.vehicle-field {
    background: #1a1a35;
    border-radius: 6px;
    padding: 12px;
}
.vehicle-field .label { color: #888; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.5px; }
.vehicle-field .value { font-size: 1.1rem; font-weight: 600; color: #fff; margin-top: 2px; }

/* ─── Quick Actions ────────────────────────────────────────────────────── */
.quick-actions {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: 10px;
}
.action-btn {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 20px 16px;
    background: #1a1a35;
    border: 1px solid #252545;
    border-radius: 10px;
    color: #ccc;
    font-size: 0.85rem;
    font-weight: 500;
    transition: all 0.2s;
    text-align: center;
}
.action-btn:hover { border-color: #00e676; color: #00e676; transform: translateY(-2px); }
.action-btn:active { transform: translateY(0); }
.action-btn .action-icon { font-size: 2rem; }
.action-btn:disabled { opacity: 0.4; transform: none; }

/* ─── Stats Row ────────────────────────────────────────────────────────── */
.stats-row {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: 12px;
    margin-bottom: 20px;
}
.stat-card {
    background: #16162e;
    border: 1px solid #252545;
    border-radius: 10px;
    padding: 16px;
    text-align: center;
}
.stat-value { font-size: 2rem; font-weight: 700; color: #fff; }
.stat-label { font-size: 0.75rem; color: #888; text-transform: uppercase; letter-spacing: 0.5px; margin-top: 4px; }

/* ─── Loading / Spinner ────────────────────────────────────────────────── */
.spinner {
    display: inline-block;
    width: 18px;
    height: 18px;
    border: 2px solid #333;
    border-top-color: #00e676;
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.scanning-overlay {
    position: fixed;
    top: 0; left: 0; right: 0; bottom: 0;
    background: #0f0f23dd;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    z-index: 200;
    gap: 16px;
}
.scanning-overlay .big-spinner {
    width: 48px;
    height: 48px;
    border: 3px solid #333;
    border-top-color: #00e676;
    border-radius: 50%;
    animation: spin 1s linear infinite;
}
.scanning-overlay .scan-text { color: #ccc; font-size: 1.1rem; }
.hidden { display: none !important; }

/* ─── Toast ────────────────────────────────────────────────────────────── */
.toast-container {
    position: fixed;
    bottom: 24px;
    right: 24px;
    z-index: 300;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.toast {
    background: #1e1e3e;
    border: 1px solid #333;
    border-radius: 8px;
    padding: 12px 20px;
    color: #e0e0e0;
    font-size: 0.9rem;
    animation: slideIn 0.3s ease;
    max-width: 400px;
    box-shadow: 0 4px 20px #00000066;
}
.toast.success { border-left: 3px solid #00e676; }
.toast.error { border-left: 3px solid #ff5252; }
.toast.info { border-left: 3px solid #4fc3f7; }
@keyframes slideIn { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } }

/* ─── Live Data ────────────────────────────────────────────────────────── */
.ld-toolbar {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 16px;
}
.ld-toolbar .btn { min-width: 110px; }

.ld-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 12px;
    margin-bottom: 20px;
}
.ld-gauge {
    background: #16162e;
    border: 1px solid #252545;
    border-radius: 10px;
    padding: 14px;
    transition: border-color 0.3s;
    position: relative;
    overflow: hidden;
}
.ld-gauge.normal { border-left: 3px solid #00e676; }
.ld-gauge.warning { border-left: 3px solid #ffc107; }
.ld-gauge.danger { border-left: 3px solid #ff5252; }
.ld-gauge-name {
    font-size: 0.75rem;
    color: #888;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 4px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ld-gauge-value {
    font-size: 1.6rem;
    font-weight: 700;
    font-family: 'Consolas', 'Courier New', monospace;
    margin-bottom: 2px;
}
.ld-gauge-value.normal { color: #00e676; }
.ld-gauge-value.warning { color: #ffc107; }
.ld-gauge-value.danger { color: #ff5252; }
.ld-gauge-unit {
    font-size: 0.8rem;
    color: #666;
    margin-left: 4px;
    font-weight: 400;
    font-family: 'Segoe UI', sans-serif;
}
.ld-gauge-bar {
    height: 4px;
    background: #1a1a35;
    border-radius: 2px;
    margin-top: 8px;
    overflow: hidden;
    position: relative;
}
.ld-gauge-bar-fill {
    height: 100%;
    border-radius: 2px;
    transition: width 0.3s ease, background 0.3s;
}
.ld-gauge-bar-fill.normal { background: #00e676; }
.ld-gauge-bar-fill.warning { background: #ffc107; }
.ld-gauge-bar-fill.danger { background: #ff5252; }
.ld-gauge-range {
    display: flex;
    justify-content: space-between;
    font-size: 0.65rem;
    color: #555;
    margin-top: 2px;
}

/* PID Selector */
.ld-pid-selector {
    max-height: 400px;
    overflow-y: auto;
    border: 1px solid #252545;
    border-radius: 8px;
    padding: 12px;
    background: #0c0c1e;
}
.ld-pid-category {
    margin-bottom: 12px;
}
.ld-pid-category-title {
    font-size: 0.8rem;
    font-weight: 600;
    color: #4fc3f7;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 6px;
    padding-bottom: 4px;
    border-bottom: 1px solid #252545;
}
.ld-pid-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 8px;
    border-radius: 4px;
    cursor: pointer;
    font-size: 0.85rem;
    transition: background 0.15s;
}
.ld-pid-item:hover { background: #1a1a3a; }
.ld-pid-item input[type="checkbox"] { accent-color: #00e676; cursor: pointer; }
.ld-pid-item .pid-code { color: #666; font-family: 'Consolas', monospace; font-size: 0.75rem; min-width: 48px; }
.ld-pid-item .pid-name { color: #ccc; flex: 1; }
.ld-pid-item .pid-unit { color: #888; font-size: 0.75rem; min-width: 40px; text-align: right; }

/* Chart */
.ld-chart-container {
    background: #0c0c1e;
    border: 1px solid #252545;
    border-radius: 8px;
    padding: 16px;
    position: relative;
}
.ld-chart-canvas {
    width: 100%;
    height: 200px;
    display: block;
}
.ld-chart-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 10px;
    font-size: 0.8rem;
}
.ld-chart-legend-item {
    display: flex;
    align-items: center;
    gap: 4px;
    color: #bbb;
}
.ld-chart-legend-swatch {
    width: 12px;
    height: 12px;
    border-radius: 2px;
    display: inline-block;
}

/* Recording playback */
.ld-recordings-list {
    max-height: 300px;
    overflow-y: auto;
}
.ld-recording-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 14px;
    border-bottom: 1px solid #1e1e3a;
    transition: background 0.15s;
    cursor: pointer;
}
.ld-recording-item:hover { background: #1a1a3a; }
.ld-recording-meta { color: #888; font-size: 0.8rem; }

/* Anomaly toast style */
.toast.warning { border-left: 3px solid #ffc107; }
.toast.danger { border-left: 3px solid #ff5252; }

/* ─── Drive Mode ──────────────────────────────────────────────────────── */
.dm-state-banner {
    padding: 20px 24px;
    border-radius: 10px;
    text-align: center;
    font-size: 1.4rem;
    font-weight: 700;
    letter-spacing: 1px;
    text-transform: uppercase;
    margin-bottom: 16px;
    transition: all 0.5s;
    position: relative;
    overflow: hidden;
}
.dm-state-banner::before {
    content: '';
    position: absolute;
    top: 0; left: -100%;
    width: 200%; height: 100%;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,0.05), transparent);
    animation: dm-sweep 3s linear infinite;
}
@keyframes dm-sweep { to { transform: translateX(100%); } }
.dm-state-green { background: #00e67625; border: 2px solid #00e676; color: #00e676; }
.dm-state-yellow { background: #ffc10725; border: 2px solid #ffc107; color: #ffc107; }
.dm-state-blue { background: #4fc3f725; border: 2px solid #4fc3f7; color: #4fc3f7; }
.dm-state-red { background: #ff525225; border: 2px solid #ff5252; color: #ff5252; }
.dm-state-gray { background: #66666625; border: 2px solid #666; color: #999; }

.dm-test-progress {
    background: #0c0c1e;
    border: 1px solid #252545;
    border-radius: 8px;
    padding: 16px;
    margin-bottom: 16px;
}
.dm-test-name { font-size: 1.1rem; font-weight: 600; color: #4fc3f7; margin-bottom: 8px; }
.dm-test-desc { color: #888; font-size: 0.9rem; margin-bottom: 12px; }
.dm-progress-bar {
    height: 8px;
    background: #1a1a35;
    border-radius: 4px;
    overflow: hidden;
    margin-bottom: 6px;
}
.dm-progress-fill {
    height: 100%;
    background: linear-gradient(90deg, #4fc3f7, #00e676);
    border-radius: 4px;
    transition: width 0.5s;
}
.dm-progress-text { color: #888; font-size: 0.8rem; text-align: right; }

.dm-confirm-panel {
    display: flex;
    gap: 12px;
    justify-content: center;
    padding: 20px;
    margin-bottom: 16px;
}
.dm-confirm-btn {
    padding: 16px 32px;
    font-size: 1.1rem;
    font-weight: 700;
    border-radius: 10px;
    border: 2px solid;
    transition: all 0.2s;
}
.dm-confirm-btn.pullover {
    background: #ffc10720;
    border-color: #ffc107;
    color: #ffc107;
}
.dm-confirm-btn.pullover:hover { background: #ffc10740; transform: scale(1.02); }
.dm-confirm-btn.ready {
    background: #00e67620;
    border-color: #00e676;
    color: #00e676;
}
.dm-confirm-btn.ready:hover { background: #00e67640; transform: scale(1.02); }

.dm-voice-log {
    max-height: 250px;
    overflow-y: auto;
    border: 1px solid #252545;
    border-radius: 8px;
    padding: 12px;
    background: #0c0c1e;
}
.dm-voice-item {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 8px 0;
    border-bottom: 1px solid #151530;
    font-size: 0.9rem;
}
.dm-voice-item:last-child { border-bottom: none; }
.dm-voice-time { color: #555; font-size: 0.75rem; min-width: 60px; font-family: 'Consolas', monospace; }
.dm-voice-priority { font-size: 0.7rem; font-weight: 700; min-width: 65px; text-align: center; padding: 2px 6px; border-radius: 3px; }
.dm-voice-priority.INFO { background: #4fc3f720; color: #4fc3f7; }
.dm-voice-priority.WARNING { background: #ffc10720; color: #ffc107; }
.dm-voice-priority.CRITICAL { background: #ff525220; color: #ff5252; }
.dm-voice-text { color: #ccc; flex: 1; }

.dm-live-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: 10px;
}
.dm-live-item {
    background: #16162e;
    border: 1px solid #252545;
    border-radius: 8px;
    padding: 10px;
    text-align: center;
}
.dm-live-label { font-size: 0.7rem; color: #888; text-transform: uppercase; letter-spacing: 0.5px; }
.dm-live-value {
    font-size: 1.3rem;
    font-weight: 700;
    font-family: 'Consolas', monospace;
    color: #00e676;
}
.dm-live-unit { font-size: 0.75rem; color: #555; }

.dm-test-selector {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    gap: 10px;
    margin-bottom: 16px;
}
.dm-test-option {
    background: #1a1a35;
    border: 2px solid #252545;
    border-radius: 8px;
    padding: 14px;
    cursor: pointer;
    transition: all 0.2s;
}
.dm-test-option:hover { border-color: #4fc3f7; }
.dm-test-option.selected { border-color: #00e676; background: #00e67610; }
.dm-test-option input { accent-color: #00e676; margin-right: 8px; }
.dm-test-option .test-title { font-weight: 600; color: #e0e0e0; }
.dm-test-option .test-info { font-size: 0.8rem; color: #888; margin-top: 4px; }
.dm-test-option .test-duration { font-size: 0.75rem; color: #4fc3f7; margin-top: 4px; }

.dm-session-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    border-bottom: 1px solid #1e1e3a;
    cursor: pointer;
    transition: background 0.15s;
}
.dm-session-item:hover { background: #1a1a3a; }
.dm-session-meta { color: #888; font-size: 0.8rem; margin-top: 4px; }

@keyframes dm-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.5; }
}
.dm-pulse { animation: dm-pulse 1.5s ease-in-out infinite; }

/* ─── Print Styles ─────────────────────────────────────────────────────── */
@media print {
    body { background: #fff; color: #000; }
    .header, .nav, .btn, .action-btn, .toast-container { display: none; }
    .card { border: 1px solid #ccc; break-inside: avoid; }
    .dtc-item { border: 1px solid #ccc; }
    .section { display: block !important; }
    .hex-byte { border: 1px solid #999; color: #000; }
}

/* ─── Empty State ──────────────────────────────────────────────────────── */
.empty-state {
    text-align: center;
    padding: 60px 20px;
    color: #555;
}
.empty-state .empty-icon { font-size: 3rem; margin-bottom: 12px; }
.empty-state p { font-size: 1rem; }

/* ─── Knowledge Base ───────────────────────────────────────────────────── */
.kb-item {
    padding: 12px 0;
    border-bottom: 1px solid #1e1e3a;
}
.kb-item:last-child { border-bottom: none; }
.kb-code { font-family: 'Consolas', monospace; color: #4fc3f7; font-weight: 700; }
.kb-desc { color: #ccc; margin-left: 8px; }
</style>
</head>
<body>

<!-- ─── Header ──────────────────────────────────────────────────────────── -->
<div class="header">
    <div class="header-left">
        <div class="logo"><span>ScanFix</span><span>AI</span></div>
        <div class="header-status">
            <div class="status-dot" id="statusDot"></div>
            <span id="statusText">Disconnected</span>
        </div>
    </div>
    <div class="header-right">
        <span id="tierLabel" class="badge badge-yellow" style="cursor:pointer;" onclick="switchSection('license')">FREE</span>
        <span id="demoLabel" class="badge badge-yellow hidden">DEMO MODE</span>
        <span id="vinLabel" class="badge badge-blue hidden"></span>
        <button class="btn btn-sm btn-secondary" onclick="window.print()" title="Print scan report">Print</button>
    </div>
</div>

<!-- ─── Navigation ──────────────────────────────────────────────────────── -->
<div class="nav">
    <button class="nav-btn active" data-section="dashboard">Dashboard</button>
    <button class="nav-btn" data-section="modules">Modules</button>
    <button class="nav-btn" data-section="dtcs">Trouble Codes</button>
    <button class="nav-btn" data-section="livedata">Live Data</button>
    <button class="nav-btn" data-section="drivemode">Drive Mode</button>
    <button class="nav-btn" data-section="asbuilt">As-Built Data</button>
    <button class="nav-btn" data-section="analysis">AI Analysis</button>
    <button class="nav-btn" data-section="history">History</button>
    <button class="nav-btn" data-section="knowledge">Knowledge Base</button>
    <button class="nav-btn" data-section="license" style="color:#00e676;">License</button>
</div>

<!-- ─── Scanning Overlay ────────────────────────────────────────────────── -->
<div class="scanning-overlay hidden" id="scanOverlay">
    <div class="big-spinner"></div>
    <div class="scan-text" id="scanText">Scanning vehicle...</div>
</div>

<!-- ─── Toast Container ─────────────────────────────────────────────────── -->
<div class="toast-container" id="toastContainer"></div>

<!-- ─── Main Content ────────────────────────────────────────────────────── -->
<div class="main">

    <!-- ═══ Dashboard Section ═══ -->
    <div class="section active" id="sec-dashboard">
        <!-- Connection Card -->
        <div class="card">
            <div class="card-title"><span class="icon">&#x1F50C;</span> Connection</div>
            <div class="connect-panel">
                <div class="input-group">
                    <label for="portSelect" style="margin-bottom:0">Port</label>
                    <select id="portSelect" style="width:140px">
                        <option value="auto">Auto-Detect</option>
                        <option value="COM1">COM1</option>
                        <option value="COM2">COM2</option>
                        <option value="COM3">COM3</option>
                        <option value="COM4">COM4</option>
                        <option value="COM5">COM5</option>
                        <option value="COM6">COM6</option>
                        <option value="COM7">COM7</option>
                        <option value="COM8">COM8</option>
                        <option value="COM9">COM9</option>
                        <option value="COM10">COM10</option>
                    </select>
                </div>
                <button class="btn btn-primary btn-lg" id="connectBtn" onclick="toggleConnect()">Connect</button>
                <div class="adapter-info hidden" id="adapterInfo">
                    <dt>Adapter</dt><dd id="adapterType">—</dd>
                    <dt>Firmware</dt><dd id="adapterFirmware">—</dd>
                    <dt>Protocol</dt><dd id="adapterProtocol">—</dd>
                    <dt>Voltage</dt><dd id="adapterVoltage">—</dd>
                </div>
            </div>
        </div>

        <!-- Vehicle Info -->
        <div class="card hidden" id="vehicleCard">
            <div class="card-title"><span class="icon">&#x1F697;</span> Vehicle Information</div>
            <div class="vehicle-grid" id="vehicleGrid"></div>
        </div>

        <!-- Stats -->
        <div class="stats-row hidden" id="statsRow">
            <div class="stat-card">
                <div class="stat-value" id="statModules">0</div>
                <div class="stat-label">Modules</div>
            </div>
            <div class="stat-card">
                <div class="stat-value" id="statDtcs" style="color:#ff5252">0</div>
                <div class="stat-label">Trouble Codes</div>
            </div>
            <div class="stat-card">
                <div class="stat-value" id="statActive" style="color:#ff9800">0</div>
                <div class="stat-label">Active</div>
            </div>
            <div class="stat-card">
                <div class="stat-value" id="statStored" style="color:#ffc107">0</div>
                <div class="stat-label">Stored</div>
            </div>
        </div>

        <!-- Quick Actions -->
        <div class="card">
            <div class="card-title"><span class="icon">&#x26A1;</span> Quick Actions</div>
            <div class="quick-actions">
                <button class="action-btn" onclick="doScan('full')" id="btnScanAll" disabled>
                    <span class="action-icon">&#x1F50D;</span>
                    Full Scan
                </button>
                <button class="action-btn" onclick="readDtcs()" id="btnReadDtcs" disabled>
                    <span class="action-icon">&#x1F4CB;</span>
                    Read DTCs
                </button>
                <button class="action-btn" onclick="clearAllDtcs()" id="btnClearDtcs" disabled>
                    <span class="action-icon">&#x1F9F9;</span>
                    Clear All DTCs
                </button>
                <button class="action-btn" onclick="switchSection('asbuilt')" id="btnAsBuilt" disabled>
                    <span class="action-icon">&#x1F527;</span>
                    As-Built Data
                </button>
                <button class="action-btn" onclick="doAnalyze()" id="btnAnalyze" disabled>
                    <span class="action-icon">&#x1F9E0;</span>
                    AI Analysis
                </button>
                <button class="action-btn" onclick="readVin()" id="btnReadVin" disabled>
                    <span class="action-icon">&#x1F3F7;</span>
                    Read VIN
                </button>
            </div>
        </div>

        <!-- Quick DTC Summary (on dashboard) -->
        <div class="card hidden" id="dtcSummaryCard">
            <div class="card-title" style="justify-content:space-between">
                <span><span class="icon">&#x26A0;</span> Trouble Codes Found</span>
                <button class="btn btn-sm btn-outline" onclick="switchSection('dtcs')">View All</button>
            </div>
            <div id="dtcSummaryList"></div>
        </div>
    </div>

    <!-- ═══ Modules Section ═══ -->
    <div class="section" id="sec-modules">
        <div class="card">
            <div class="card-title"><span class="icon">&#x1F4E6;</span> Detected Modules</div>
            <div id="moduleList">
                <div class="empty-state">
                    <div class="empty-icon">&#x1F4E6;</div>
                    <p>No modules detected yet. Run a scan first.</p>
                </div>
            </div>
        </div>
    </div>

    <!-- ═══ DTCs Section ═══ -->
    <div class="section" id="sec-dtcs">
        <div class="card">
            <div class="card-title" style="justify-content:space-between">
                <span><span class="icon">&#x26A0;</span> Diagnostic Trouble Codes</span>
                <div class="btn-group">
                    <button class="btn btn-sm btn-danger" onclick="clearAllDtcs()">Clear All DTCs</button>
                    <button class="btn btn-sm btn-secondary" onclick="readDtcs()">Refresh</button>
                </div>
            </div>
            <div id="dtcFilterBar" class="hidden" style="margin-bottom:16px; display:flex; gap:8px; flex-wrap:wrap;">
                <button class="btn btn-sm btn-outline dtc-filter active" data-filter="all" onclick="filterDtcs('all')">All</button>
                <button class="btn btn-sm btn-outline dtc-filter" data-filter="active" onclick="filterDtcs('active')">Active</button>
                <button class="btn btn-sm btn-outline dtc-filter" data-filter="stored" onclick="filterDtcs('stored')">Stored</button>
            </div>
            <div id="dtcList">
                <div class="empty-state">
                    <div class="empty-icon">&#x2705;</div>
                    <p>No trouble codes found. Run a scan to check.</p>
                </div>
            </div>
        </div>
    </div>

    <!-- ═══ Live Data Section ═══ -->
    <div class="section" id="sec-livedata">
        <!-- Toolbar -->
        <div class="card">
            <div class="card-title" style="justify-content:space-between">
                <span><span class="icon">&#x1F4CA;</span> Live Data Monitor</span>
                <div class="btn-group">
                    <button class="btn btn-sm btn-secondary" onclick="toggleLdPidSelector()" id="ldPidToggle">Select PIDs</button>
                </div>
            </div>
            <div class="ld-toolbar">
                <button class="btn btn-primary" id="ldStartBtn" onclick="ldStart()" disabled>Start Monitoring</button>
                <button class="btn btn-danger" id="ldStopBtn" onclick="ldStop()" disabled>Stop</button>
                <div style="border-left:1px solid #333;height:28px;margin:0 4px"></div>
                <button class="btn btn-secondary" id="ldRecordBtn" onclick="ldToggleRecord()" disabled>Record</button>
                <button class="btn btn-secondary" id="ldPlaybackBtn" onclick="ldShowPlayback()">Playback</button>
                <div style="flex:1"></div>
                <span id="ldStatusBadge" class="badge badge-gray">Idle</span>
                <select id="ldIntervalSelect" style="width:110px" title="Poll interval">
                    <option value="100">100ms</option>
                    <option value="200" selected>200ms</option>
                    <option value="500">500ms</option>
                    <option value="1000">1 sec</option>
                    <option value="2000">2 sec</option>
                </select>
            </div>

            <!-- PID Selector (hidden by default) -->
            <div id="ldPidSelector" class="hidden" style="margin-bottom:16px">
                <div style="display:flex;gap:8px;margin-bottom:10px;align-items:center">
                    <input type="text" class="input" id="ldPidSearch" placeholder="Search PIDs..." style="flex:1" oninput="ldFilterPids()">
                    <button class="btn btn-sm btn-outline" onclick="ldSelectPreset('engine')">Engine</button>
                    <button class="btn btn-sm btn-outline" onclick="ldSelectPreset('fuel')">Fuel</button>
                    <button class="btn btn-sm btn-outline" onclick="ldSelectPreset('turbo')">Turbo</button>
                    <button class="btn btn-sm btn-outline" onclick="ldSelectPreset('trans')">Trans</button>
                    <button class="btn btn-sm btn-outline" onclick="ldSelectPreset('all')">All</button>
                    <button class="btn btn-sm btn-secondary" onclick="ldSelectPreset('none')">Clear</button>
                </div>
                <div class="ld-pid-selector" id="ldPidList">
                    <p style="color:#888">Loading PID definitions...</p>
                </div>
                <div style="margin-top:10px;display:flex;justify-content:space-between;align-items:center">
                    <span id="ldPidCount" style="color:#888;font-size:0.85rem">0 PIDs selected</span>
                    <button class="btn btn-sm btn-primary" onclick="toggleLdPidSelector()">Done</button>
                </div>
            </div>
        </div>

        <!-- Gauges -->
        <div class="ld-grid" id="ldGaugeGrid">
            <div class="empty-state" style="grid-column:1/-1">
                <div class="empty-icon">&#x1F4CA;</div>
                <p>Select PIDs and click "Start Monitoring" to view live data.</p>
            </div>
        </div>

        <!-- Chart -->
        <div class="card hidden" id="ldChartCard">
            <div class="card-title"><span class="icon">&#x1F4C8;</span> Value History (Last 60s)</div>
            <div class="ld-chart-container">
                <canvas class="ld-chart-canvas" id="ldChart"></canvas>
                <div class="ld-chart-legend" id="ldChartLegend"></div>
            </div>
        </div>

        <!-- Playback Panel (hidden by default) -->
        <div class="card hidden" id="ldPlaybackCard">
            <div class="card-title" style="justify-content:space-between">
                <span><span class="icon">&#x23EF;</span> Recordings</span>
                <button class="btn btn-sm btn-secondary" onclick="ldHidePlayback()">Close</button>
            </div>
            <div class="ld-recordings-list" id="ldRecordingsList">
                <p style="color:#888">Loading recordings...</p>
            </div>
        </div>
    </div>

    <!-- ═══ Drive Mode Section ═══ -->
    <div class="section" id="sec-drivemode">
        <!-- State Banner -->
        <div class="dm-state-banner dm-state-gray" id="dmStateBanner">
            READY — Select tests and start a diagnostic drive
        </div>

        <!-- Confirm Buttons (shown only when needed) -->
        <div class="dm-confirm-panel hidden" id="dmConfirmPanel">
            <button class="dm-confirm-btn pullover hidden" id="dmConfirmPullover" onclick="dmConfirmPullover()">
                I Have Pulled Over
            </button>
            <button class="dm-confirm-btn ready hidden" id="dmConfirmReady" onclick="dmConfirmReady()">
                Ready to Drive
            </button>
        </div>

        <!-- Controls Card -->
        <div class="card" id="dmControlsCard">
            <div class="card-title" style="justify-content:space-between">
                <span><span class="icon">&#x1F697;</span> Guided Diagnostic Drive</span>
                <div class="btn-group">
                    <button class="btn btn-sm btn-secondary" id="dmMuteBtn" onclick="dmToggleMute()">Mute Voice</button>
                </div>
            </div>

            <!-- Test Selector (shown when idle) -->
            <div id="dmTestSelector">
                <p style="color:#888;margin-bottom:12px">Select the diagnostic tests to run during your drive:</p>
                <div class="dm-test-selector" id="dmTestList">
                    <p style="color:#888">Loading tests...</p>
                </div>
                <div style="display:flex;gap:12px;align-items:center;margin-top:12px">
                    <button class="btn btn-primary btn-lg" id="dmStartBtn" onclick="dmStart()">
                        Start Drive Session
                    </button>
                    <button class="btn btn-danger btn-lg hidden" id="dmStopBtn" onclick="dmStop()">
                        Stop Session
                    </button>
                    <span id="dmDemoNote" class="badge badge-yellow" style="margin-left:8px">DEMO MODE</span>
                </div>
            </div>
        </div>

        <!-- Test Progress -->
        <div class="dm-test-progress hidden" id="dmTestProgress">
            <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px">
                <div class="dm-test-name" id="dmTestName">—</div>
                <span id="dmTestCounter" class="badge badge-blue">Test 0/0</span>
            </div>
            <div class="dm-test-desc" id="dmTestDesc">—</div>
            <div class="dm-progress-bar">
                <div class="dm-progress-fill" id="dmProgressFill" style="width:0%"></div>
            </div>
            <div class="dm-progress-text" id="dmProgressText">0%</div>
        </div>

        <!-- Live Values During Drive -->
        <div class="card hidden" id="dmLiveCard">
            <div class="card-title"><span class="icon">&#x1F4CA;</span> Live Monitoring</div>
            <div class="dm-live-grid" id="dmLiveGrid"></div>
        </div>

        <!-- Voice Prompt History -->
        <div class="card hidden" id="dmVoiceCard">
            <div class="card-title"><span class="icon">&#x1F50A;</span> Voice Alerts</div>
            <div class="dm-voice-log" id="dmVoiceLog">
                <p style="color:#555;text-align:center">No voice alerts yet</p>
            </div>
        </div>

        <!-- Session Summary (shown at end) -->
        <div class="card hidden" id="dmSummaryCard">
            <div class="card-title"><span class="icon">&#x1F4CB;</span> Session Summary</div>
            <div id="dmSummaryContent"></div>
        </div>

        <!-- Past Sessions -->
        <div class="card">
            <div class="card-title" style="justify-content:space-between">
                <span><span class="icon">&#x1F4C1;</span> Past Drive Sessions</span>
                <button class="btn btn-sm btn-secondary" onclick="dmLoadSessions()">Refresh</button>
            </div>
            <div id="dmSessionsList">
                <div class="empty-state" style="padding:20px">
                    <p>No past sessions. Start a diagnostic drive to create one.</p>
                </div>
            </div>
        </div>
    </div>

    <!-- ═══ As-Built Section ═══ -->
    <div class="section" id="sec-asbuilt">
        <div class="card">
            <div class="card-title"><span class="icon">&#x1F527;</span> As-Built Data</div>
            <div class="input-group" style="margin-bottom:16px">
                <label for="abModuleSelect" style="margin-bottom:0">Module</label>
                <select id="abModuleSelect" style="width:300px" onchange="loadAsBuilt()">
                    <option value="">— Select Module —</option>
                </select>
                <button class="btn btn-primary btn-sm" onclick="loadAsBuilt()">Read</button>
                <button class="btn btn-danger btn-sm" id="abWriteBtn" onclick="writeAsBuilt()" disabled>Write Changes</button>
            </div>
            <div id="asbuiltEditor">
                <div class="empty-state">
                    <div class="empty-icon">&#x1F527;</div>
                    <p>Select a module to read its as-built data.</p>
                </div>
            </div>
        </div>
    </div>

    <!-- ═══ Analysis Section ═══ -->
    <div class="section" id="sec-analysis">
        <div class="card">
            <div class="card-title" style="justify-content:space-between">
                <span><span class="icon">&#x1F9E0;</span> AI Diagnostic Analysis</span>
                <button class="btn btn-sm btn-primary" onclick="doAnalyze()">Run Analysis</button>
            </div>
            <div id="analysisContent">
                <div class="empty-state">
                    <div class="empty-icon">&#x1F9E0;</div>
                    <p>Run a scan first, then click "Run Analysis" for AI-powered diagnostics.</p>
                </div>
            </div>
        </div>
    </div>

    <!-- ═══ History Section ═══ -->
    <div class="section" id="sec-history">
        <div class="card">
            <div class="card-title"><span class="icon">&#x1F4C5;</span> Scan History</div>
            <div id="historyList">
                <div class="empty-state">
                    <div class="empty-icon">&#x1F4C5;</div>
                    <p>No scan history available. Connect and scan a vehicle to begin.</p>
                </div>
            </div>
        </div>
    </div>

    <!-- ═══ Knowledge Base Section ═══ -->
    <div class="section" id="sec-knowledge">
        <div class="card">
            <div class="card-title"><span class="icon">&#x1F4DA;</span> Knowledge Base</div>
            <div class="input-group" style="margin-bottom:16px">
                <input type="text" class="input" id="kbSearch" placeholder="Search DTCs, fixes, symptoms..." style="flex:1" oninput="searchKnowledge()">
            </div>
            <div id="knowledgeContent">
                <p style="color:#888">Loading knowledge base...</p>
            </div>
        </div>
    </div>

    <!-- ═══ License Section ═══ -->
    <div class="section" id="sec-license">
        <div class="card">
            <div class="card-title"><span class="icon">&#x1F511;</span> License</div>
            <div id="licenseContent">
                <div id="licFreePanel">
                    <div style="text-align:center; padding:20px 0;">
                        <div style="font-size:3rem; margin-bottom:8px;">&#x1F512;</div>
                        <h2 style="color:#fff; margin-bottom:8px;">You're on the Free Plan</h2>
                        <p style="color:#888; margin-bottom:24px;">Upgrade to Pro to unlock all features including code clearing, AI analysis, guided tests, as-built data, and drive mode.</p>
                        <div style="display:flex; gap:12px; justify-content:center; flex-wrap:wrap; margin-bottom:32px;">
                            <div style="background:#1a1a3a; border:1px solid #333; border-radius:8px; padding:16px 24px; min-width:140px;">
                                <div style="color:#4fc3f7; font-size:1.5rem; font-weight:800;">$9.99</div>
                                <div style="color:#888; font-size:0.8rem;">/month</div>
                            </div>
                            <div style="background:#1a1a3a; border:2px solid #00e676; border-radius:8px; padding:16px 24px; min-width:140px;">
                                <div style="color:#00e676; font-size:1.5rem; font-weight:800;">$39.99</div>
                                <div style="color:#888; font-size:0.8rem;">/year (save 67%)</div>
                            </div>
                            <div style="background:#1a1a3a; border:1px solid #333; border-radius:8px; padding:16px 24px; min-width:140px;">
                                <div style="color:#4fc3f7; font-size:1.5rem; font-weight:800;">$99.99</div>
                                <div style="color:#888; font-size:0.8rem;">lifetime</div>
                            </div>
                        </div>
                        <a href="https://scanfixai.com/pricing" target="_blank" class="btn btn-primary" style="padding:12px 32px; font-size:1rem;">Buy Pro License</a>
                    </div>
                    <hr style="border-color:#222; margin:24px 0;">
                    <h3 style="color:#fff; margin-bottom:12px;">Already have a license key?</h3>
                    <div class="input-group" style="gap:8px;">
                        <input type="text" class="input" id="licKeyInput" placeholder="SFAI-XXXX-XXXX-XXXX-XXXX" style="flex:1; text-transform:uppercase;">
                        <button class="btn btn-primary" onclick="activateLicense()">Activate</button>
                    </div>
                    <div style="margin-top:8px;">
                        <span style="color:#888; font-size:0.85rem;">Or activate with email: </span>
                        <input type="text" class="input" id="licEmailInput" placeholder="your@email.com" style="width:220px; margin-left:4px;">
                    </div>
                    <div id="licMessage" style="margin-top:12px; font-size:0.9rem;"></div>
                </div>
                <div id="licProPanel" style="display:none;">
                    <div style="text-align:center; padding:20px 0;">
                        <div style="font-size:3rem; margin-bottom:8px;">&#x2705;</div>
                        <h2 style="color:#00e676; margin-bottom:8px;">Pro License Active</h2>
                        <p style="color:#888;">All features unlocked.</p>
                        <div style="margin:20px 0; padding:16px; background:#1a1a3a; border-radius:8px; display:inline-block; text-align:left;">
                            <div style="margin-bottom:6px;"><span style="color:#888;">License:</span> <span id="licKeyDisplay" style="color:#fff; font-family:monospace;"></span></div>
                            <div style="margin-bottom:6px;"><span style="color:#888;">Email:</span> <span id="licEmailDisplay" style="color:#fff;"></span></div>
                            <div style="margin-bottom:6px;"><span style="color:#888;">Tier:</span> <span id="licTierDisplay" style="color:#00e676; font-weight:bold;"></span></div>
                            <div><span style="color:#888;">Expires:</span> <span id="licExpiresDisplay" style="color:#fff;"></span></div>
                        </div>
                        <br><br>
                        <button class="btn btn-sm" style="background:#ff5252; color:#fff;" onclick="deactivateLicense()">Deactivate This Device</button>
                    </div>
                </div>
            </div>
        </div>
    </div>

</div>

<!-- ─── Upgrade Modal ──────────────────────────────────────────────────── -->
<div id="upgradeModal" style="display:none; position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.8); z-index:1000; display:none; align-items:center; justify-content:center;">
    <div style="background:#12122a; border:2px solid #00e676; border-radius:16px; padding:32px; max-width:420px; text-align:center;">
        <div style="font-size:2.5rem; margin-bottom:12px;">&#x1F512;</div>
        <h2 style="color:#fff; margin-bottom:8px;" id="upgradeTitle">Pro Feature</h2>
        <p style="color:#888; margin-bottom:24px;" id="upgradeMessage">This feature requires ScanFixAI Pro.</p>
        <div style="display:flex; gap:12px; justify-content:center; flex-wrap:wrap; margin-bottom:20px;">
            <div style="background:#1a1a3a; border-radius:8px; padding:12px 20px;">
                <span style="color:#4fc3f7; font-weight:800;">$9.99/mo</span>
            </div>
            <div style="background:#1a1a3a; border:1px solid #00e676; border-radius:8px; padding:12px 20px;">
                <span style="color:#00e676; font-weight:800;">$39.99/yr</span>
            </div>
            <div style="background:#1a1a3a; border-radius:8px; padding:12px 20px;">
                <span style="color:#4fc3f7; font-weight:800;">$99.99 lifetime</span>
            </div>
        </div>
        <a href="https://scanfixai.com/pricing" target="_blank" class="btn btn-primary" style="padding:10px 28px; margin-right:8px;">Upgrade Now</a>
        <button class="btn btn-sm" style="background:#333; color:#aaa; padding:10px 20px;" onclick="closeUpgradeModal()">Maybe Later</button>
    </div>
</div>

<!-- ─── JavaScript ──────────────────────────────────────────────────────── -->
<script>
const API = '';
let state = {
    connected: false,
    demoMode: false,
    modules: [],
    dtcs: [],
    vehicle: null,
    analysis: null,
    asbuilt: {},
    asbuiltOriginal: {},
    currentFilter: 'all',
    license: { tier: 'free', features: {} },
};

// ─── API Helpers ─────────────────────────────────────────────────────────

async function api(method, path, body = null) {
    const opts = {
        method,
        headers: { 'Content-Type': 'application/json' },
    };
    if (body) opts.body = JSON.stringify(body);
    try {
        const res = await fetch(API + path, opts);
        const data = await res.json();
        if (!res.ok && data.error) {
            if (data.error === 'pro_required') {
                showUpgradeModal(data.feature ? data.feature.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase()) : 'Pro Feature', data.message || 'This feature requires ScanFixAI Pro.');
                return data;
            }
            toast(data.error, 'error');
        }
        return data;
    } catch (e) {
        toast('Connection failed: ' + e.message, 'error');
        return { error: e.message };
    }
}

// ─── Toast Notifications ─────────────────────────────────────────────────

function toast(message, type = 'info') {
    const container = document.getElementById('toastContainer');
    const el = document.createElement('div');
    el.className = `toast ${type}`;
    el.textContent = message;
    container.appendChild(el);
    setTimeout(() => {
        el.style.opacity = '0';
        el.style.transition = 'opacity 0.3s';
        setTimeout(() => el.remove(), 300);
    }, 4000);
}

// ─── Navigation ──────────────────────────────────────────────────────────

document.querySelectorAll('.nav-btn').forEach(btn => {
    btn.addEventListener('click', () => switchSection(btn.dataset.section));
});

function switchSection(name) {
    document.querySelectorAll('.nav-btn').forEach(b => b.classList.remove('active'));
    document.querySelectorAll('.section').forEach(s => s.classList.remove('active'));
    const navBtn = document.querySelector(`.nav-btn[data-section="${name}"]`);
    if (navBtn) navBtn.classList.add('active');
    const sec = document.getElementById(`sec-${name}`);
    if (sec) sec.classList.add('active');

    // Load content on tab switch
    if (name === 'knowledge') loadKnowledge();
    if (name === 'history' && state.vehicle) loadHistory();
    if (name === 'livedata') { ldLoadPids(); ldUpdateButtons(); }
    if (name === 'drivemode') { dmLoadTests(); dmLoadSessions(); }
}

// ─── Connection ──────────────────────────────────────────────────────────

async function toggleConnect() {
    if (state.connected) {
        await disconnect();
    } else {
        await connect();
    }
}

async function connect() {
    const port = document.getElementById('portSelect').value;
    const btn = document.getElementById('connectBtn');
    btn.disabled = true;
    btn.innerHTML = '<span class="spinner"></span> Connecting...';

    const data = await api('POST', '/api/connect', { port });

    if (data.success) {
        state.connected = true;
        state.demoMode = !!data.demo_mode;
        toast('Connected to adapter' + (state.demoMode ? ' (Demo Mode)' : ''), 'success');
        updateConnectionUI(data);
        enableActions(true);
    } else {
        toast('Failed to connect', 'error');
    }

    btn.disabled = false;
    btn.textContent = state.connected ? 'Disconnect' : 'Connect';
    if (state.connected) btn.classList.replace('btn-primary', 'btn-danger');
}

async function disconnect() {
    await api('POST', '/api/disconnect');
    state.connected = false;
    state.demoMode = false;
    state.modules = [];
    state.dtcs = [];
    state.vehicle = null;
    state.analysis = null;
    toast('Disconnected', 'info');
    updateConnectionUI(null);
    enableActions(false);
    clearDashboard();

    const btn = document.getElementById('connectBtn');
    btn.textContent = 'Connect';
    btn.classList.replace('btn-danger', 'btn-primary');
}

function updateConnectionUI(data) {
    const dot = document.getElementById('statusDot');
    const text = document.getElementById('statusText');
    const demo = document.getElementById('demoLabel');
    const info = document.getElementById('adapterInfo');

    if (state.connected) {
        dot.className = 'status-dot connected';
        text.textContent = `Connected (${data?.port || 'Unknown'})`;
        demo.classList.toggle('hidden', !state.demoMode);

        if (data?.adapter) {
            info.classList.remove('hidden');
            document.getElementById('adapterType').textContent = data.adapter.type || '—';
            document.getElementById('adapterFirmware').textContent = data.adapter.firmware || '—';
            document.getElementById('adapterProtocol').textContent = data.adapter.protocol || '—';
            document.getElementById('adapterVoltage').textContent = data.adapter.voltage || '—';
        }
    } else {
        dot.className = 'status-dot';
        text.textContent = 'Disconnected';
        demo.classList.add('hidden');
        info.classList.add('hidden');
        document.getElementById('vinLabel').classList.add('hidden');
    }
}

function enableActions(enabled) {
    ['btnScanAll', 'btnReadDtcs', 'btnClearDtcs', 'btnAsBuilt', 'btnAnalyze', 'btnReadVin'].forEach(id => {
        document.getElementById(id).disabled = !enabled;
    });
    // Live data start button depends on connection state
    const ldStart = document.getElementById('ldStartBtn');
    if (ldStart) ldStart.disabled = !enabled || ldState.monitoring;
}

function clearDashboard() {
    document.getElementById('vehicleCard').classList.add('hidden');
    document.getElementById('statsRow').classList.add('hidden');
    document.getElementById('dtcSummaryCard').classList.add('hidden');
    document.getElementById('vehicleGrid').innerHTML = '';
    document.getElementById('moduleList').innerHTML = '<div class="empty-state"><div class="empty-icon">&#x1F4E6;</div><p>No modules detected yet. Run a scan first.</p></div>';
    document.getElementById('dtcList').innerHTML = '<div class="empty-state"><div class="empty-icon">&#x2705;</div><p>No trouble codes found. Run a scan to check.</p></div>';
    document.getElementById('analysisContent').innerHTML = '<div class="empty-state"><div class="empty-icon">&#x1F9E0;</div><p>Run a scan first, then click "Run Analysis" for AI-powered diagnostics.</p></div>';
}

// ─── Scanning ────────────────────────────────────────────────────────────

async function doScan(type = 'full') {
    showOverlay('Scanning all modules...');
    const data = await api('POST', '/api/scan', { type });
    hideOverlay();

    if (data.success) {
        state.modules = data.modules || [];
        state.dtcs = data.dtcs || [];
        state.vehicle = data.vehicle || null;
        toast(`Scan complete: ${state.modules.length} modules, ${state.dtcs.length} DTCs`, 'success');
        updateDashboardAfterScan();
    }
}

async function readDtcs() {
    const data = await api('GET', '/api/dtcs');
    if (data.dtcs) {
        state.dtcs = data.dtcs;
        renderDtcs();
    }
}

async function readVin() {
    const data = await api('GET', '/api/vin');
    if (data.vin) {
        toast(`VIN: ${data.vin}`, 'success');
        document.getElementById('vinLabel').textContent = data.vin;
        document.getElementById('vinLabel').classList.remove('hidden');
    }
}

async function clearAllDtcs() {
    if (!isProFeature('clear_codes')) { showUpgradeModal('Clear Codes', 'Clearing diagnostic codes requires ScanFixAI Pro.'); return; }
    if (!confirm('Clear ALL diagnostic trouble codes?')) return;
    showOverlay('Clearing DTCs...');
    const data = await api('POST', '/api/dtcs/clear', { module: 'all' });
    hideOverlay();
    if (data.success) {
        state.dtcs = [];
        toast('All DTCs cleared', 'success');
        renderDtcs();
        updateStats();
    }
}

async function clearDtc(code) {
    const data = await api('POST', '/api/dtcs/clear', { code });
    if (data.success) {
        state.dtcs = state.dtcs.filter(d => d.code !== code);
        toast(`${code} cleared`, 'success');
        renderDtcs();
        updateStats();
    }
}

// ─── Dashboard Updates ───────────────────────────────────────────────────

function updateDashboardAfterScan() {
    // Vehicle info
    if (state.vehicle) {
        const grid = document.getElementById('vehicleGrid');
        const fields = [
            { label: 'VIN', value: state.vehicle.vin },
            { label: 'Year', value: state.vehicle.year },
            { label: 'Make', value: state.vehicle.make },
            { label: 'Model', value: state.vehicle.model },
            { label: 'Trim', value: state.vehicle.trim },
            { label: 'Engine', value: state.vehicle.engine },
            { label: 'Transmission', value: state.vehicle.transmission },
            { label: 'Drivetrain', value: state.vehicle.drivetrain },
        ];
        grid.innerHTML = fields.filter(f => f.value).map(f => `
            <div class="vehicle-field">
                <div class="label">${f.label}</div>
                <div class="value">${f.value}</div>
            </div>
        `).join('');
        document.getElementById('vehicleCard').classList.remove('hidden');

        document.getElementById('vinLabel').textContent = state.vehicle.vin || '';
        document.getElementById('vinLabel').classList.toggle('hidden', !state.vehicle.vin);
    }

    updateStats();
    renderModules();
    renderDtcs();
    renderDtcSummary();
    updateAsBuiltSelect();
}

function updateStats() {
    const activeCount = state.dtcs.filter(d => d.status === 'active').length;
    const storedCount = state.dtcs.filter(d => d.status === 'stored').length;

    document.getElementById('statModules').textContent = state.modules.length;
    document.getElementById('statDtcs').textContent = state.dtcs.length;
    document.getElementById('statActive').textContent = activeCount;
    document.getElementById('statStored').textContent = storedCount;

    document.getElementById('statsRow').classList.toggle('hidden', state.modules.length === 0);
}

// ─── Module Rendering ────────────────────────────────────────────────────

function renderModules() {
    const list = document.getElementById('moduleList');
    if (state.modules.length === 0) {
        list.innerHTML = '<div class="empty-state"><div class="empty-icon">&#x1F4E6;</div><p>No modules detected yet. Run a scan first.</p></div>';
        return;
    }

    list.innerHTML = state.modules.map(m => `
        <div class="module-item" onclick="viewModuleDtcs('${m.address}')">
            <div class="module-info">
                <div class="module-status ${m.status}"></div>
                <div>
                    <div class="module-name">${m.name}</div>
                    <div class="module-addr">0x${m.address}</div>
                </div>
            </div>
            <div class="module-dtcs">
                ${m.dtc_count > 0 ? `<span class="badge badge-red">${m.dtc_count} DTC${m.dtc_count > 1 ? 's' : ''}</span>` : '<span class="badge badge-green">OK</span>'}
            </div>
        </div>
    `).join('');
}

function viewModuleDtcs(addr) {
    switchSection('dtcs');
    // TODO: filter to specific module
}

// ─── DTC Rendering ───────────────────────────────────────────────────────

function renderDtcs() {
    const list = document.getElementById('dtcList');
    const filterBar = document.getElementById('dtcFilterBar');

    let dtcs = state.dtcs;
    if (state.currentFilter === 'active') dtcs = dtcs.filter(d => d.status === 'active');
    if (state.currentFilter === 'stored') dtcs = dtcs.filter(d => d.status === 'stored');

    if (state.dtcs.length === 0) {
        list.innerHTML = '<div class="empty-state"><div class="empty-icon">&#x2705;</div><p>No trouble codes found.</p></div>';
        filterBar.classList.add('hidden');
        return;
    }

    filterBar.classList.remove('hidden');
    filterBar.style.display = 'flex';

    list.innerHTML = dtcs.map(d => {
        const sevClass = d.severity ? `severity-${d.severity}` : '';
        const statusClass = d.status === 'active' ? 'active-dtc' : 'stored-dtc';
        const causes = (d.common_causes || []).map(c => `<li>${c}</li>`).join('');
        const fixes = (d.fix_steps || []).map(f => `<li>${f}</li>`).join('');
        const related = (d.related_dtcs || []).map(r => `<span class="badge badge-blue" style="font-size:0.7rem">${r}</span>`).join(' ');
        const notes = d.notes ? `<p style="margin-top:8px;color:#ffc107;font-size:0.85rem"><strong>Note:</strong> ${d.notes}</p>` : '';

        return `
        <div class="dtc-item ${statusClass}">
            <div class="dtc-header">
                <div>
                    <span class="dtc-code">${d.code}</span>
                    <span class="badge ${d.status === 'active' ? 'badge-red' : 'badge-yellow'}" style="margin-left:8px">${d.status}</span>
                    ${d.severity ? `<span class="badge badge-gray ${sevClass}" style="margin-left:4px">${d.severity}</span>` : ''}
                </div>
                <button class="btn btn-sm btn-danger" onclick="clearDtc('${d.code}')">Clear</button>
            </div>
            <div class="dtc-desc">${d.description}</div>
            <div class="dtc-module">${d.module} (0x${d.module_address || '???'})</div>
            ${causes || fixes ? `
            <details class="dtc-details">
                <summary>Diagnosis &amp; Fix Information</summary>
                ${causes ? `<h5 style="color:#ff9800;margin:8px 0 4px">Common Causes</h5><ul class="dtc-cause-list">${causes}</ul>` : ''}
                ${fixes ? `<h5 style="color:#00e676;margin:8px 0 4px">Fix Steps</h5><ol class="dtc-fix-list">${fixes}</ol>` : ''}
                ${related ? `<div style="margin-top:8px"><strong style="color:#888;font-size:0.8rem">Related:</strong> ${related}</div>` : ''}
                ${notes}
            </details>` : ''}
        </div>`;
    }).join('');
}

function filterDtcs(filter) {
    state.currentFilter = filter;
    document.querySelectorAll('.dtc-filter').forEach(b => b.classList.remove('active'));
    document.querySelector(`.dtc-filter[data-filter="${filter}"]`).classList.add('active');
    renderDtcs();
}

function renderDtcSummary() {
    const card = document.getElementById('dtcSummaryCard');
    const list = document.getElementById('dtcSummaryList');
    if (state.dtcs.length === 0) {
        card.classList.add('hidden');
        return;
    }
    card.classList.remove('hidden');
    list.innerHTML = state.dtcs.slice(0, 5).map(d => `
        <div style="display:flex;align-items:center;justify-content:space-between;padding:8px 0;border-bottom:1px solid #1e1e3a">
            <div>
                <span class="dtc-code" style="font-size:0.95rem">${d.code}</span>
                <span style="color:#bbb;margin-left:8px">${d.description}</span>
            </div>
            <span class="badge ${d.status === 'active' ? 'badge-red' : 'badge-yellow'}">${d.status}</span>
        </div>
    `).join('') + (state.dtcs.length > 5 ? `<p style="color:#888;padding:8px 0;text-align:center">+ ${state.dtcs.length - 5} more...</p>` : '');
}

// ─── As-Built Data ───────────────────────────────────────────────────────

function updateAsBuiltSelect() {
    const sel = document.getElementById('abModuleSelect');
    const current = sel.value;
    sel.innerHTML = '<option value="">-- Select Module --</option>';
    state.modules.forEach(m => {
        const opt = document.createElement('option');
        opt.value = m.address;
        opt.textContent = `${m.name} (0x${m.address})`;
        sel.appendChild(opt);
    });
    if (current) sel.value = current;
}

async function loadAsBuilt() {
    if (!isProFeature('asbuilt_rw')) { showUpgradeModal('As-Built Data', 'Reading and writing as-built data requires ScanFixAI Pro.'); return; }
    const addr = document.getElementById('abModuleSelect').value;
    if (!addr) return;

    const editor = document.getElementById('asbuiltEditor');
    editor.innerHTML = '<p style="color:#888"><span class="spinner"></span> Reading as-built data...</p>';

    const data = await api('GET', `/api/asbuilt/${addr}`);
    if (data.error) {
        editor.innerHTML = `<div class="empty-state"><p style="color:#ff5252">${data.error}</p></div>`;
        return;
    }

    const blocks = data.asbuilt?.blocks || {};
    state.asbuilt[addr] = JSON.parse(JSON.stringify(blocks));
    state.asbuiltOriginal[addr] = JSON.parse(JSON.stringify(blocks));

    renderHexEditor(addr, blocks);
    document.getElementById('abWriteBtn').disabled = false;
}

function renderHexEditor(moduleAddr, blocks) {
    const editor = document.getElementById('asbuiltEditor');
    if (Object.keys(blocks).length === 0) {
        editor.innerHTML = '<div class="empty-state"><p>No as-built data available for this module.</p></div>';
        return;
    }

    let html = '<div class="hex-editor">';
    for (const [blockAddr, hexStr] of Object.entries(blocks)) {
        const bytes = hexStr.trim().split(/\s+/);
        html += `<div class="hex-row">
            <span class="hex-addr">${blockAddr}</span>
            <div class="hex-bytes">
                ${bytes.map((b, i) => `<input class="hex-byte" maxlength="2" value="${b}" data-module="${moduleAddr}" data-block="${blockAddr}" data-index="${i}" data-orig="${b}" oninput="onHexEdit(this)">`).join('')}
            </div>
        </div>`;
    }
    html += '</div>';
    html += '<p style="margin-top:12px;color:#888;font-size:0.8rem">Edit hex values directly. Modified bytes will be highlighted. Click "Write Changes" to send to module.</p>';
    editor.innerHTML = html;
}

function onHexEdit(el) {
    el.value = el.value.toUpperCase().replace(/[^0-9A-F]/g, '');
    const isModified = el.value !== el.dataset.orig;
    el.classList.toggle('modified', isModified);

    // Update state
    const module = el.dataset.module;
    const block = el.dataset.block;
    const idx = parseInt(el.dataset.index);
    if (state.asbuilt[module] && state.asbuilt[module][block]) {
        const bytes = state.asbuilt[module][block].split(/\s+/);
        bytes[idx] = el.value || '00';
        state.asbuilt[module][block] = bytes.join(' ');
    }
}

async function writeAsBuilt() {
    if (!isProFeature('asbuilt_rw')) { showUpgradeModal('As-Built Data', 'Writing as-built data requires ScanFixAI Pro.'); return; }
    const addr = document.getElementById('abModuleSelect').value;
    if (!addr) return;

    // Find modified blocks
    const modified = {};
    const orig = state.asbuiltOriginal[addr] || {};
    const curr = state.asbuilt[addr] || {};

    for (const [block, val] of Object.entries(curr)) {
        if (val !== orig[block]) {
            modified[block] = val;
        }
    }

    if (Object.keys(modified).length === 0) {
        toast('No changes to write', 'info');
        return;
    }

    if (!confirm(`Write ${Object.keys(modified).length} modified block(s) to module 0x${addr}?\n\nModified blocks: ${Object.keys(modified).join(', ')}\n\nThis will modify the vehicle's module configuration.`)) return;

    showOverlay('Writing as-built data...');
    const data = await api('POST', `/api/asbuilt/${addr}`, { blocks: modified });
    hideOverlay();

    if (data.success) {
        toast('As-built data written successfully', 'success');
        state.asbuiltOriginal[addr] = JSON.parse(JSON.stringify(state.asbuilt[addr]));
        document.querySelectorAll('.hex-byte.modified').forEach(el => {
            el.classList.remove('modified');
            el.dataset.orig = el.value;
        });
    }
}

// ─── AI Analysis ─────────────────────────────────────────────────────────

async function doAnalyze() {
    if (!isProFeature('unlimited_ai')) {
        // Free tier gets 1/day — API handles the count, but show modal if features say no
        // Let the API decide and show modal on 403
    }
    if (state.dtcs.length === 0) {
        toast('No DTCs to analyze. Run a scan first.', 'info');
        return;
    }

    switchSection('analysis');
    const content = document.getElementById('analysisContent');
    content.innerHTML = '<div style="text-align:center;padding:40px"><span class="spinner" style="width:36px;height:36px;border-width:3px"></span><p style="margin-top:16px;color:#888">Analyzing diagnostic data...</p></div>';

    const data = await api('POST', '/api/analyze', {
        dtcs: state.dtcs,
        vehicle: state.vehicle,
    });

    if (data.analysis) {
        state.analysis = data.analysis;
        renderAnalysis(data.analysis);
    }
}

function renderAnalysis(a) {
    const content = document.getElementById('analysisContent');

    let html = '';

    // Urgency banner
    html += `<div class="urgency-banner urgency-${a.urgency || 'none'}">${a.urgency_text || 'Analysis complete.'}</div>`;

    // Summary
    html += `<div class="analysis-box">
        <div class="analysis-summary">${a.summary}</div>
        ${a.vehicle ? `<p style="color:#888">Vehicle: ${a.vehicle}</p>` : ''}
        <div style="display:flex;gap:16px;margin-top:12px">
            <span class="badge badge-red">${a.active_count || 0} Active</span>
            <span class="badge badge-yellow">${a.stored_count || 0} Stored</span>
            <span class="badge badge-blue">${(a.modules_affected || []).length} Modules</span>
        </div>
    </div>`;

    // Root causes
    if (a.root_causes && a.root_causes.length > 0) {
        html += '<h3 style="color:#ff9800;margin:20px 0 12px">Root Cause Analysis</h3>';
        a.root_causes.forEach(rc => {
            html += `<div class="analysis-box">
                <h4 style="color:#4fc3f7;margin-bottom:8px">${rc.title} <span class="badge badge-blue">${rc.confidence} match</span></h4>
                <p style="color:#ccc;line-height:1.6">${rc.description}</p>
                <div style="margin-top:8px">
                    <strong style="color:#888;font-size:0.8rem">Matched codes:</strong>
                    ${rc.matched_codes.map(c => `<span class="badge badge-red" style="margin-left:4px">${c}</span>`).join('')}
                </div>
            </div>`;
        });
    }

    // Recommendations
    if (a.recommendations && a.recommendations.length > 0) {
        html += '<h3 style="color:#00e676;margin:20px 0 12px">Recommended Fixes</h3>';
        a.recommendations.forEach((fix, i) => {
            html += `<div class="fix-card">
                <h4>${i + 1}. ${fix.title}</h4>
                <div class="fix-meta">
                    <span>Difficulty: <strong>${fix.difficulty}</strong></span>
                    <span>Time: <strong>${fix.estimated_time}</strong></span>
                </div>
                <ol class="fix-steps">
                    ${fix.steps.map(s => `<li>${s}</li>`).join('')}
                </ol>
                ${fix.parts_needed && fix.parts_needed.length > 0 ? `<p style="margin-top:8px;color:#888;font-size:0.85rem"><strong>Parts:</strong> ${fix.parts_needed.join(', ')}</p>` : ''}
                ${fix.tools_needed && fix.tools_needed.length > 0 ? `<p style="color:#888;font-size:0.85rem"><strong>Tools:</strong> ${fix.tools_needed.join(', ')}</p>` : ''}
            </div>`;
        });
    }

    html += `<p style="color:#555;font-size:0.8rem;margin-top:20px;text-align:right">Analysis generated: ${a.timestamp || new Date().toISOString()}</p>`;

    content.innerHTML = html;
}

// ─── History ─────────────────────────────────────────────────────────────

async function loadHistory() {
    if (!state.vehicle?.vin) return;

    const data = await api('GET', `/api/vehicle/${state.vehicle.vin}/history`);
    const list = document.getElementById('historyList');

    const history = data.history || [];
    if (history.length === 0) {
        list.innerHTML = '<div class="empty-state"><div class="empty-icon">&#x1F4C5;</div><p>No previous scans recorded for this vehicle.</p></div>';
        return;
    }

    list.innerHTML = history.map(h => {
        const date = new Date(h.timestamp).toLocaleString();
        return `
        <div class="history-item">
            <div>
                <div class="history-date">${date}</div>
                <div class="history-codes">
                    ${(h.codes || []).map(c => `<span class="badge badge-red" style="font-size:0.7rem">${c}</span>`).join('')}
                </div>
            </div>
            <div>
                <span class="badge badge-blue">${h.modules_scanned || 0} modules</span>
                <span class="badge ${h.dtc_count > 0 ? 'badge-red' : 'badge-green'}" style="margin-left:4px">${h.dtc_count || 0} DTCs</span>
            </div>
        </div>`;
    }).join('');
}

// ─── Knowledge Base ──────────────────────────────────────────────────────

let knowledgeData = null;

async function loadKnowledge() {
    if (knowledgeData) {
        renderKnowledge(knowledgeData);
        return;
    }

    const data = await api('GET', '/api/knowledge');
    knowledgeData = data;
    renderKnowledge(data);
}

function renderKnowledge(data) {
    const content = document.getElementById('knowledgeContent');
    const search = document.getElementById('kbSearch').value.toLowerCase();

    let dtcCodes = data.dtcs || [];
    let fixes = data.fixes || [];

    let html = `<p style="color:#888;margin-bottom:16px">${data.dtc_count || 0} DTCs and ${data.fix_count || 0} fix patterns in knowledge base.</p>`;

    // DTC list
    html += '<h3 style="color:#4fc3f7;margin:16px 0 8px">Known DTCs</h3>';
    const filteredDtcs = search ? dtcCodes.filter(c => c.toLowerCase().includes(search)) : dtcCodes;
    html += '<div style="display:flex;flex-wrap:wrap;gap:6px">';
    filteredDtcs.forEach(code => {
        html += `<span class="badge badge-blue" style="cursor:pointer;font-size:0.8rem" title="${code}">${code}</span>`;
    });
    html += '</div>';

    // Fix patterns
    html += '<h3 style="color:#00e676;margin:20px 0 8px">Fix Patterns</h3>';
    const filteredFixes = search
        ? fixes.filter(f => f.name.toLowerCase().includes(search) || f.trigger_dtcs.some(t => t.toLowerCase().includes(search)))
        : fixes;

    filteredFixes.forEach(f => {
        html += `<div class="kb-item">
            <div style="display:flex;justify-content:space-between;align-items:center">
                <strong style="color:#e0e0e0">${f.name}</strong>
                <div>${f.trigger_dtcs.map(t => `<span class="badge badge-red" style="font-size:0.7rem;margin-left:4px">${t}</span>`).join('')}</div>
            </div>
        </div>`;
    });

    content.innerHTML = html;
}

function searchKnowledge() {
    if (knowledgeData) renderKnowledge(knowledgeData);
}

// ─── Overlay ─────────────────────────────────────────────────────────────

function showOverlay(text) {
    document.getElementById('scanText').textContent = text;
    document.getElementById('scanOverlay').classList.remove('hidden');
}
function hideOverlay() {
    document.getElementById('scanOverlay').classList.add('hidden');
}

// ─── Auto Status Refresh ─────────────────────────────────────────────────

async function refreshStatus() {
    try {
        const data = await api('GET', '/api/status');
        if (data.connected !== undefined && data.connected !== state.connected) {
            state.connected = data.connected;
            updateConnectionUI(data);
            enableActions(data.connected);
        }
    } catch (e) {
        // Server might be down, ignore
    }
}

setInterval(refreshStatus, 5000);

// ─── Live Data ──────────────────────────────────────────────────────────

let ldState = {
    allPids: [],
    selectedPids: [],
    monitoring: false,
    recording: false,
    pollTimer: null,
    chartColors: [
        '#00e676','#4fc3f7','#ff9800','#ff5252','#ba68c8',
        '#ffc107','#26c6da','#ef5350','#66bb6a','#42a5f5',
        '#ab47bc','#ec407a','#7e57c2','#29b6f6','#9ccc65',
    ],
    previousAnomalies: {},
};

// Load all PIDs on first visit to livedata tab
async function ldLoadPids() {
    if (ldState.allPids.length > 0) return;
    const data = await api('GET', '/api/livedata/pids');
    if (data.pids) {
        ldState.allPids = data.pids;
        ldRenderPidSelector();
        // Default selection: common engine PIDs
        ldSelectPreset('engine');
    }
}

function ldRenderPidSelector(filter = '') {
    const container = document.getElementById('ldPidList');
    const categories = {};
    const filterLower = filter.toLowerCase();

    for (const p of ldState.allPids) {
        if (filterLower && !p.name.toLowerCase().includes(filterLower) &&
            !p.short_name.toLowerCase().includes(filterLower) &&
            !p.pid.toLowerCase().includes(filterLower) &&
            !p.category.toLowerCase().includes(filterLower)) {
            continue;
        }
        const cat = p.category || 'Other';
        if (!categories[cat]) categories[cat] = [];
        categories[cat].push(p);
    }

    let html = '';
    for (const [cat, pids] of Object.entries(categories)) {
        html += `<div class="ld-pid-category">
            <div class="ld-pid-category-title">${cat} (${pids.length})</div>`;
        for (const p of pids) {
            const checked = ldState.selectedPids.includes(p.pid) ? 'checked' : '';
            html += `<label class="ld-pid-item">
                <input type="checkbox" value="${p.pid}" ${checked} onchange="ldTogglePid(this)">
                <span class="pid-code">${p.pid}</span>
                <span class="pid-name">${p.short_name} — ${p.name}</span>
                <span class="pid-unit">${p.unit}</span>
            </label>`;
        }
        html += '</div>';
    }

    container.innerHTML = html || '<p style="color:#888">No PIDs match your search.</p>';
    ldUpdatePidCount();
}

function ldFilterPids() {
    const q = document.getElementById('ldPidSearch').value;
    ldRenderPidSelector(q);
}

function ldTogglePid(cb) {
    const pid = cb.value;
    if (cb.checked) {
        if (!ldState.selectedPids.includes(pid)) ldState.selectedPids.push(pid);
    } else {
        ldState.selectedPids = ldState.selectedPids.filter(p => p !== pid);
    }
    ldUpdatePidCount();
}

function ldUpdatePidCount() {
    document.getElementById('ldPidCount').textContent = `${ldState.selectedPids.length} PID${ldState.selectedPids.length !== 1 ? 's' : ''} selected`;
}

function ldSelectPreset(preset) {
    const presets = {
        engine: ['010C','010D','0105','010F','0110','0111','010B','0104','010E','015C','0142'],
        fuel: ['0106','0107','0108','0109','010A','012F','0114','0115','0124','0123'],
        turbo: ['22402A','22402B','22402C','22402D','010B','0110','0111','010C'],
        trans: ['224034','224035','224036','224037','224038','224039'],
        all: ldState.allPids.map(p => p.pid),
        none: [],
    };
    ldState.selectedPids = [...(presets[preset] || [])];
    ldRenderPidSelector(document.getElementById('ldPidSearch')?.value || '');
}

function toggleLdPidSelector() {
    const sel = document.getElementById('ldPidSelector');
    sel.classList.toggle('hidden');
    const btn = document.getElementById('ldPidToggle');
    btn.textContent = sel.classList.contains('hidden') ? 'Select PIDs' : 'Hide Selector';
}

async function ldStart() {
    if (ldState.selectedPids.length === 0) {
        toast('Select at least one PID to monitor', 'info');
        return;
    }

    const interval = parseInt(document.getElementById('ldIntervalSelect').value) || 200;
    const data = await api('POST', '/api/livedata/start', {
        pids: ldState.selectedPids,
        interval: interval,
    });

    if (data.success) {
        ldState.monitoring = true;
        ldUpdateButtons();
        ldStartPolling();
        toast(`Monitoring ${ldState.selectedPids.length} PIDs at ${interval}ms`, 'success');
    }
}

async function ldStop() {
    await api('POST', '/api/livedata/stop');
    ldState.monitoring = false;
    ldStopPolling();
    ldUpdateButtons();
    toast('Monitoring stopped', 'info');
}

function ldUpdateButtons() {
    document.getElementById('ldStartBtn').disabled = ldState.monitoring || !state.connected;
    document.getElementById('ldStopBtn').disabled = !ldState.monitoring;
    document.getElementById('ldRecordBtn').disabled = !ldState.monitoring;
    document.getElementById('ldRecordBtn').textContent = ldState.recording ? 'Stop Rec' : 'Record';
    document.getElementById('ldRecordBtn').className = ldState.recording ? 'btn btn-danger' : 'btn btn-secondary';

    const badge = document.getElementById('ldStatusBadge');
    if (ldState.monitoring) {
        if (ldState.recording) {
            badge.textContent = 'RECORDING';
            badge.className = 'badge badge-red';
        } else {
            badge.textContent = 'MONITORING';
            badge.className = 'badge badge-green';
        }
    } else {
        badge.textContent = 'Idle';
        badge.className = 'badge badge-gray';
    }
}

function ldStartPolling() {
    ldStopPolling();
    const interval = parseInt(document.getElementById('ldIntervalSelect').value) || 200;
    ldState.pollTimer = setInterval(ldPoll, Math.max(interval, 150));
}

function ldStopPolling() {
    if (ldState.pollTimer) {
        clearInterval(ldState.pollTimer);
        ldState.pollTimer = null;
    }
}

async function ldPoll() {
    const data = await api('GET', '/api/livedata/current');
    if (!data || data.error) return;

    ldRenderGauges(data.values || {});
    ldRenderChart(data.history || {});

    // Show anomaly toasts
    if (data.anomalies) {
        for (const a of data.anomalies) {
            const key = a.pid + '_' + a.severity;
            if (!ldState.previousAnomalies[key]) {
                toast(a.message, a.severity === 'danger' ? 'error' : 'info');
                ldState.previousAnomalies[key] = true;
                // Clear after 10 seconds so it can alert again
                setTimeout(() => { delete ldState.previousAnomalies[key]; }, 10000);
            }
        }
    }

    if (!data.monitoring && ldState.monitoring) {
        ldState.monitoring = false;
        ldStopPolling();
        ldUpdateButtons();
    }
}

function ldRenderGauges(values) {
    const grid = document.getElementById('ldGaugeGrid');
    const keys = Object.keys(values);
    if (keys.length === 0) return;

    // Sort: Engine first, then by PID key
    keys.sort((a, b) => {
        const ca = (values[a].category || '').toLowerCase();
        const cb = (values[b].category || '').toLowerCase();
        if (ca === cb) return a.localeCompare(b);
        if (ca === 'engine') return -1;
        if (cb === 'engine') return 1;
        return ca.localeCompare(cb);
    });

    let html = '';
    for (const pid of keys) {
        const v = values[pid];
        const range = v.max_val - v.min_val;
        const pct = range > 0 ? Math.max(0, Math.min(100,
            ((v.value - v.min_val) / range) * 100
        )) : 0;
        const dp = v.decimal_places !== undefined ? v.decimal_places : 1;
        const displayVal = Number(v.value).toFixed(dp);

        html += `<div class="ld-gauge ${v.status}">
            <div class="ld-gauge-name" title="${v.name}">${v.short_name}</div>
            <div class="ld-gauge-value ${v.status}">${displayVal}<span class="ld-gauge-unit">${v.unit}</span></div>
            <div class="ld-gauge-bar">
                <div class="ld-gauge-bar-fill ${v.status}" style="width:${pct}%"></div>
            </div>
            <div class="ld-gauge-range">
                <span>${v.min_val}</span>
                <span>${v.max_val}</span>
            </div>
        </div>`;
    }
    grid.innerHTML = html;

    // Show chart card
    document.getElementById('ldChartCard').classList.remove('hidden');
}

// ─── Canvas Chart ───────────────────────────────────────────────────────

function ldRenderChart(historyData) {
    const canvas = document.getElementById('ldChart');
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    const rect = canvas.parentElement.getBoundingClientRect();
    const dpr = window.devicePixelRatio || 1;
    canvas.width = rect.width * dpr;
    canvas.height = 200 * dpr;
    canvas.style.width = rect.width + 'px';
    canvas.style.height = '200px';
    ctx.scale(dpr, dpr);

    const W = rect.width;
    const H = 200;
    const PAD_L = 50, PAD_R = 10, PAD_T = 10, PAD_B = 25;
    const plotW = W - PAD_L - PAD_R;
    const plotH = H - PAD_T - PAD_B;

    // Clear
    ctx.clearRect(0, 0, W, H);
    ctx.fillStyle = '#0c0c1e';
    ctx.fillRect(0, 0, W, H);

    const pids = Object.keys(historyData).filter(k => historyData[k].length > 1);
    if (pids.length === 0) return;

    // Build legend
    const legendEl = document.getElementById('ldChartLegend');
    let legendHtml = '';

    // Draw each PID series
    const now = Date.now() / 1000;
    const timeWindow = 60; // seconds

    // Find a global time range
    const tMin = now - timeWindow;
    const tMax = now;

    // Draw grid
    ctx.strokeStyle = '#1e1e3a';
    ctx.lineWidth = 1;
    for (let i = 0; i <= 4; i++) {
        const y = PAD_T + (plotH * i / 4);
        ctx.beginPath(); ctx.moveTo(PAD_L, y); ctx.lineTo(W - PAD_R, y); ctx.stroke();
    }
    for (let i = 0; i <= 6; i++) {
        const x = PAD_L + (plotW * i / 6);
        ctx.beginPath(); ctx.moveTo(x, PAD_T); ctx.lineTo(x, H - PAD_B); ctx.stroke();
    }

    // Time labels
    ctx.fillStyle = '#555';
    ctx.font = '10px Consolas, monospace';
    ctx.textAlign = 'center';
    for (let i = 0; i <= 6; i++) {
        const t = -timeWindow + (timeWindow * i / 6);
        const x = PAD_L + (plotW * i / 6);
        ctx.fillText(t.toFixed(0) + 's', x, H - 5);
    }

    // Draw each series (normalize each to its own range)
    pids.forEach((pid, idx) => {
        const series = historyData[pid];
        if (!series || series.length < 2) return;
        const color = ldState.chartColors[idx % ldState.chartColors.length];

        // Find value range for this PID
        const vals = series.map(s => s.v);
        let vMin = Math.min(...vals);
        let vMax = Math.max(...vals);
        if (vMin === vMax) { vMin -= 1; vMax += 1; }
        const vRange = vMax - vMin;

        ctx.strokeStyle = color;
        ctx.lineWidth = 1.5;
        ctx.beginPath();
        let started = false;
        for (const pt of series) {
            const x = PAD_L + ((pt.t - tMin) / (tMax - tMin)) * plotW;
            const y = PAD_T + plotH - ((pt.v - vMin) / vRange) * plotH;
            if (!started) { ctx.moveTo(x, y); started = true; }
            else { ctx.lineTo(x, y); }
        }
        ctx.stroke();

        // Legend entry
        const pidInfo = ldState.allPids.find(p => p.pid === pid);
        const label = pidInfo ? pidInfo.short_name : pid;
        const lastVal = series[series.length - 1]?.v;
        const unit = pidInfo ? pidInfo.unit : '';
        legendHtml += `<div class="ld-chart-legend-item">
            <span class="ld-chart-legend-swatch" style="background:${color}"></span>
            ${label}: ${lastVal !== undefined ? lastVal.toFixed(1) : '?'} ${unit}
        </div>`;
    });

    legendEl.innerHTML = legendHtml;
}

// ─── Recording ──────────────────────────────────────────────────────────

async function ldToggleRecord() {
    if (ldState.recording) {
        const data = await api('POST', '/api/livedata/record/stop');
        if (data.success) {
            ldState.recording = false;
            toast('Recording saved', 'success');
        }
    } else {
        const data = await api('POST', '/api/livedata/record/start', {});
        if (data.success) {
            ldState.recording = true;
            toast('Recording started', 'success');
        }
    }
    ldUpdateButtons();
}

async function ldShowPlayback() {
    const card = document.getElementById('ldPlaybackCard');
    card.classList.remove('hidden');
    const list = document.getElementById('ldRecordingsList');
    list.innerHTML = '<p style="color:#888"><span class="spinner"></span> Loading...</p>';

    const data = await api('GET', '/api/livedata/recordings');
    const recordings = data.recordings || [];

    if (recordings.length === 0) {
        list.innerHTML = '<div class="empty-state" style="padding:20px"><p>No recordings yet. Start monitoring and click Record.</p></div>';
        return;
    }

    list.innerHTML = recordings.map(r => `
        <div class="ld-recording-item" onclick="ldPlayRecording('${r.id}')">
            <div>
                <div style="font-weight:500;color:#e0e0e0">${r.filename}</div>
                <div class="ld-recording-meta">
                    ${r.start_time ? new Date(r.start_time).toLocaleString() : 'Unknown'} &bull;
                    ${r.duration_seconds ? Math.round(r.duration_seconds) + 's' : '?'} &bull;
                    ${r.sample_count || 0} samples &bull;
                    ${(r.pids_recorded || []).length} PIDs
                </div>
            </div>
            <span class="badge badge-blue">Play</span>
        </div>
    `).join('');
}

function ldHidePlayback() {
    document.getElementById('ldPlaybackCard').classList.add('hidden');
}

async function ldPlayRecording(id) {
    toast('Loading recording...', 'info');
    const data = await api('GET', `/api/livedata/recording/${id}`);
    if (!data || data.error) {
        toast('Failed to load recording', 'error');
        return;
    }

    // Stop any active monitoring
    if (ldState.monitoring) await ldStop();

    const samples = data.data || [];
    if (samples.length === 0) {
        toast('Recording is empty', 'info');
        return;
    }

    toast(`Playing ${samples.length} samples...`, 'success');
    ldHidePlayback();

    // Group samples by timestamp (approx)
    let currentFrame = {};
    let lastTs = null;
    const grouped = [];

    for (const s of samples) {
        if (lastTs === null || Math.abs(s.timestamp - lastTs) < 0.05) {
            currentFrame[s.pid] = s;
            lastTs = s.timestamp;
        } else {
            grouped.push({...currentFrame});
            currentFrame = {};
            currentFrame[s.pid] = s;
            lastTs = s.timestamp;
        }
    }
    if (Object.keys(currentFrame).length > 0) grouped.push(currentFrame);

    // Playback at 200ms intervals
    let playIdx = 0;
    const playTimer = setInterval(() => {
        if (playIdx >= grouped.length) {
            clearInterval(playTimer);
            document.getElementById('ldStatusBadge').textContent = 'Idle';
            document.getElementById('ldStatusBadge').className = 'badge badge-gray';
            toast('Playback complete', 'info');
            return;
        }
        const frame = grouped[playIdx];
        ldRenderGauges(frame);
        document.getElementById('ldStatusBadge').textContent = `PLAYBACK ${playIdx+1}/${grouped.length}`;
        document.getElementById('ldStatusBadge').className = 'badge badge-blue';
        playIdx++;
    }, 200);
}

// ─── Drive Mode ─────────────────────────────────────────────────────────

let dmState = {
    active: false,
    pollTimer: null,
    selectedTests: ['GENERAL_HEALTH'],
    muted: false,
    availableTests: {},
    lastVoiceCount: 0,
};

function dmLoadTests() {
    // Load from status endpoint to get available tests
    api('GET', '/api/drivemode/status').then(data => {
        if (data.available_tests) {
            dmState.availableTests = data.available_tests;
            dmRenderTestSelector();
        }
        if (data.active) {
            dmState.active = true;
            dmStartPolling();
            dmUpdateUI(data);
        }
    });
}

function dmRenderTestSelector() {
    const container = document.getElementById('dmTestList');
    const tests = dmState.availableTests;
    if (!tests || Object.keys(tests).length === 0) {
        container.innerHTML = '<p style="color:#888">No tests available. Drive mode module not loaded.</p>';
        return;
    }

    let html = '';
    for (const [id, info] of Object.entries(tests)) {
        const checked = dmState.selectedTests.includes(id) ? 'checked' : '';
        const selected = dmState.selectedTests.includes(id) ? 'selected' : '';
        html += `<div class="dm-test-option ${selected}" onclick="dmToggleTest('${id}', this)">
            <label style="display:flex;align-items:flex-start;cursor:pointer">
                <input type="checkbox" value="${id}" ${checked} style="margin-top:3px"
                    onchange="dmToggleTest('${id}', this.closest('.dm-test-option'))" onclick="event.stopPropagation()">
                <div style="margin-left:8px">
                    <div class="test-title">${info.name}</div>
                    <div class="test-info">${info.description}</div>
                    <div class="test-duration">Duration: ${info.duration}s</div>
                </div>
            </label>
        </div>`;
    }
    container.innerHTML = html;
}

function dmToggleTest(testId, el) {
    const idx = dmState.selectedTests.indexOf(testId);
    if (idx >= 0) {
        dmState.selectedTests.splice(idx, 1);
    } else {
        dmState.selectedTests.push(testId);
    }
    // Update checkbox state
    const cb = el.querySelector('input[type="checkbox"]');
    if (cb) cb.checked = dmState.selectedTests.includes(testId);
    el.classList.toggle('selected', dmState.selectedTests.includes(testId));
}

async function dmStart() {
    if (!isProFeature('drive_mode')) { showUpgradeModal('Live Drive Mode', 'Guided drive mode with voice alerts requires ScanFixAI Pro.'); return; }
    if (dmState.selectedTests.length === 0) {
        toast('Select at least one test to run', 'info');
        return;
    }

    const data = await api('POST', '/api/drivemode/start', {
        tests: dmState.selectedTests,
        demo: !state.connected || state.demoMode,
    });

    if (data.success) {
        dmState.active = true;
        dmState.lastVoiceCount = 0;
        toast('Drive session started', 'success');
        dmStartPolling();
        document.getElementById('dmStartBtn').classList.add('hidden');
        document.getElementById('dmStopBtn').classList.remove('hidden');
        document.getElementById('dmTestSelector').querySelector('.dm-test-selector').classList.add('hidden');
        document.getElementById('dmVoiceCard').classList.remove('hidden');
        document.getElementById('dmLiveCard').classList.remove('hidden');
    } else {
        toast(data.error || 'Failed to start drive session', 'error');
    }
}

async function dmStop() {
    const data = await api('POST', '/api/drivemode/stop');
    if (data.success || data.error) {
        dmState.active = false;
        dmStopPolling();
        toast('Drive session stopped', 'info');
        document.getElementById('dmStartBtn').classList.remove('hidden');
        document.getElementById('dmStopBtn').classList.add('hidden');
        document.getElementById('dmTestSelector').querySelector('.dm-test-selector').classList.remove('hidden');
        // Refresh one more time to get final status
        dmPoll();
    }
}

async function dmConfirmPullover() {
    const data = await api('POST', '/api/drivemode/confirm', { type: 'pullover' });
    if (data.success) toast('Pullover confirmed', 'success');
}

async function dmConfirmReady() {
    const data = await api('POST', '/api/drivemode/confirm', { type: 'ready' });
    if (data.success) toast('Ready to drive confirmed', 'success');
}

async function dmToggleMute() {
    dmState.muted = !dmState.muted;
    await api('POST', '/api/drivemode/mute', { mute: dmState.muted });
    document.getElementById('dmMuteBtn').textContent = dmState.muted ? 'Unmute Voice' : 'Mute Voice';
    toast(dmState.muted ? 'Voice alerts muted' : 'Voice alerts unmuted', 'info');
}

function dmStartPolling() {
    dmStopPolling();
    dmState.pollTimer = setInterval(dmPoll, 1000);
    dmPoll(); // immediate first poll
}

function dmStopPolling() {
    if (dmState.pollTimer) {
        clearInterval(dmState.pollTimer);
        dmState.pollTimer = null;
    }
}

async function dmPoll() {
    const data = await api('GET', '/api/drivemode/status');
    if (!data || data.error) return;
    dmUpdateUI(data);
}

function dmUpdateUI(data) {
    // State banner
    const banner = document.getElementById('dmStateBanner');
    const colorMap = { green: 'dm-state-green', yellow: 'dm-state-yellow', blue: 'dm-state-blue', red: 'dm-state-red', gray: 'dm-state-gray' };
    banner.className = 'dm-state-banner ' + (colorMap[data.state_color] || 'dm-state-gray');
    if (data.state === 'PULLOVER_REQUESTED') {
        banner.innerHTML = '<span class="dm-pulse">PULL OVER SAFELY</span>';
    } else if (data.state === 'FIXING') {
        banner.innerHTML = '<span class="dm-pulse">APPLYING FIX — KEEP KEY ON</span>';
    } else {
        banner.textContent = data.state_label || data.state;
    }

    // Confirm buttons
    const confirmPanel = document.getElementById('dmConfirmPanel');
    const pulloverBtn = document.getElementById('dmConfirmPullover');
    const readyBtn = document.getElementById('dmConfirmReady');

    if (data.state === 'PULLOVER_REQUESTED') {
        confirmPanel.classList.remove('hidden');
        pulloverBtn.classList.remove('hidden');
        readyBtn.classList.add('hidden');
    } else if (data.state === 'FIX_APPLIED') {
        confirmPanel.classList.remove('hidden');
        pulloverBtn.classList.add('hidden');
        readyBtn.classList.remove('hidden');
    } else {
        confirmPanel.classList.add('hidden');
    }

    // Test progress
    const progressCard = document.getElementById('dmTestProgress');
    if (data.current_test && data.active) {
        progressCard.classList.remove('hidden');
        document.getElementById('dmTestName').textContent = data.current_test.name;
        document.getElementById('dmTestDesc').textContent = data.current_test.description;
        document.getElementById('dmProgressFill').style.width = data.current_test.progress + '%';
        document.getElementById('dmProgressText').textContent = data.current_test.progress + '% — ' +
            Math.round(data.current_test.elapsed) + 's / ' + data.current_test.duration + 's';
        document.getElementById('dmTestCounter').textContent =
            'Test ' + data.test_progress.current + '/' + data.test_progress.total;
    } else if (!data.active) {
        progressCard.classList.add('hidden');
    }

    // Live values
    const liveGrid = document.getElementById('dmLiveGrid');
    const liveCard = document.getElementById('dmLiveCard');
    if (data.current_values && Object.keys(data.current_values).length > 0) {
        liveCard.classList.remove('hidden');
        // Map PID codes to friendly names
        const pidNames = {
            '010C': {name: 'RPM', unit: 'rpm'},
            '010D': {name: 'Speed', unit: 'km/h'},
            '0105': {name: 'Coolant', unit: 'C'},
            '010F': {name: 'IAT', unit: 'C'},
            '0110': {name: 'MAF', unit: 'g/s'},
            '0111': {name: 'TPS', unit: '%'},
            '010B': {name: 'MAP', unit: 'kPa'},
            '0104': {name: 'Load', unit: '%'},
            '0106': {name: 'STFT B1', unit: '%'},
            '0108': {name: 'LTFT B1', unit: '%'},
            '0114': {name: 'O2 B1S1', unit: 'V'},
            '0142': {name: 'Battery', unit: 'V'},
            '015C': {name: 'Oil', unit: 'C'},
            '0146': {name: 'Ambient', unit: 'C'},
            '22402A': {name: 'Boost', unit: 'kPa'},
            '22402B': {name: 'Wastegate', unit: '%'},
            '224034': {name: 'Trans Temp', unit: 'C'},
            '224035': {name: 'Gear', unit: ''},
            '224039': {name: 'TCC Slip', unit: '%'},
        };

        let html = '';
        for (const [pid, val] of Object.entries(data.current_values)) {
            const info = pidNames[pid] || {name: pid, unit: ''};
            html += `<div class="dm-live-item">
                <div class="dm-live-label">${info.name}</div>
                <div class="dm-live-value">${val}<span class="dm-live-unit">${info.unit}</span></div>
            </div>`;
        }
        liveGrid.innerHTML = html;
    }

    // Voice log
    const voiceLog = document.getElementById('dmVoiceLog');
    const voiceCard = document.getElementById('dmVoiceCard');
    if (data.voice_history && data.voice_history.length > 0) {
        voiceCard.classList.remove('hidden');
        // Only update if new entries
        if (data.voice_history.length !== dmState.lastVoiceCount) {
            dmState.lastVoiceCount = data.voice_history.length;
            let html = '';
            // Reverse so newest is at top
            const reversed = [...data.voice_history].reverse();
            for (const v of reversed) {
                const t = new Date(v.timestamp * 1000);
                const timeStr = t.toLocaleTimeString([], {hour:'2-digit', minute:'2-digit', second:'2-digit'});
                html += `<div class="dm-voice-item">
                    <span class="dm-voice-time">${timeStr}</span>
                    <span class="dm-voice-priority ${v.priority}">${v.priority}</span>
                    <span class="dm-voice-text">${v.text}</span>
                </div>`;
            }
            voiceLog.innerHTML = html;
        }
    }

    // Session summary (when complete)
    const summaryCard = document.getElementById('dmSummaryCard');
    if (data.session && (data.state === 'COMPLETE' || data.state === 'ERROR') && !data.active) {
        summaryCard.classList.remove('hidden');
        const s = data.session;
        let html = `<div class="analysis-box">
            <p style="font-size:1.05rem;color:#e0e0e0;margin-bottom:12px">${s.summary || 'Session complete.'}</p>
            <div style="display:flex;gap:16px;flex-wrap:wrap">
                <span class="badge badge-blue">${(s.tests_run || []).length} Tests Run</span>
                <span class="badge badge-green">${(s.tests_passed || []).length} Passed</span>
                <span class="badge badge-red">${(s.tests_failed || []).length} Failed</span>
                <span class="badge badge-yellow">${(s.anomalies || []).length} Anomalies</span>
                <span class="badge badge-blue">${(s.fixes_applied || []).length} Fixes Applied</span>
            </div>
        </div>`;

        if (s.fixes_applied && s.fixes_applied.length > 0) {
            html += '<h4 style="color:#00e676;margin:16px 0 8px">Fixes Applied</h4>';
            for (const fix of s.fixes_applied) {
                const status = fix.success ? 'badge-green' : 'badge-red';
                const statusText = fix.success ? 'SUCCESS' : 'FAILED';
                html += `<div class="fix-card">
                    <div style="display:flex;justify-content:space-between;align-items:center">
                        <strong>${fix.fix_action?.description || fix.test}</strong>
                        <span class="badge ${status}">${statusText}</span>
                    </div>
                </div>`;
            }
        }

        if (s.anomalies && s.anomalies.length > 0) {
            html += '<h4 style="color:#ff9800;margin:16px 0 8px">Anomalies Detected</h4>';
            for (const a of s.anomalies) {
                html += `<div style="padding:8px 0;border-bottom:1px solid #1e1e3a;font-size:0.9rem">
                    <span style="color:#4fc3f7;font-family:monospace">${a.pid}</span>
                    <span style="color:#ccc;margin-left:8px">${a.description}</span>
                    <span style="color:#888;margin-left:8px">(value: ${a.value})</span>
                </div>`;
            }
        }

        document.getElementById('dmSummaryContent').innerHTML = html;

        // Reset controls
        dmState.active = false;
        dmStopPolling();
        document.getElementById('dmStartBtn').classList.remove('hidden');
        document.getElementById('dmStopBtn').classList.add('hidden');
        const testSelDiv = document.getElementById('dmTestSelector').querySelector('.dm-test-selector');
        if (testSelDiv) testSelDiv.classList.remove('hidden');
        dmLoadSessions();
    }
}

async function dmLoadSessions() {
    const data = await api('GET', '/api/drivemode/sessions');
    const container = document.getElementById('dmSessionsList');
    const sessions = data.sessions || [];

    if (sessions.length === 0) {
        container.innerHTML = '<div class="empty-state" style="padding:20px"><p>No past sessions.</p></div>';
        return;
    }

    let html = '';
    for (const s of sessions) {
        const date = s.start_time ? new Date(s.start_time).toLocaleString() : 'Unknown';
        const tests = (s.tests_run || []).join(', ') || 'None';
        const passCount = (s.tests_passed || []).length;
        const failCount = (s.tests_failed || []).length;
        const totalTests = (s.tests_run || []).length;
        html += `<div class="dm-session-item" onclick="dmViewSession('${s.session_id}')">
            <div>
                <div style="font-weight:500;color:#e0e0e0">${date}</div>
                <div class="dm-session-meta">
                    ${s.vin || 'Unknown VIN'} | Tests: ${tests}
                    ${s.demo_mode ? ' | <span class="badge badge-yellow" style="font-size:0.6rem">DEMO</span>' : ''}
                </div>
            </div>
            <div style="display:flex;gap:6px">
                <span class="badge badge-green">${passCount}/${totalTests}</span>
                ${failCount > 0 ? `<span class="badge badge-red">${failCount} fail</span>` : ''}
                ${s.fix_count > 0 ? `<span class="badge badge-blue">${s.fix_count} fix</span>` : ''}
            </div>
        </div>`;
    }
    container.innerHTML = html;
}

async function dmViewSession(sessionId) {
    const data = await api('GET', `/api/drivemode/session/${sessionId}`);
    if (!data || data.error) {
        toast('Failed to load session', 'error');
        return;
    }

    // Show in summary card
    const summaryCard = document.getElementById('dmSummaryCard');
    summaryCard.classList.remove('hidden');

    let html = `<div class="analysis-box">
        <p style="font-size:1.05rem;color:#e0e0e0;margin-bottom:12px">${data.summary || 'Session data.'}</p>
        <div style="display:flex;gap:12px;flex-wrap:wrap;margin-bottom:8px">
            <span style="color:#888">Start: ${data.start_time ? new Date(data.start_time).toLocaleString() : '?'}</span>
            <span style="color:#888">End: ${data.end_time ? new Date(data.end_time).toLocaleString() : '?'}</span>
            <span style="color:#888">VIN: ${data.vin || '?'}</span>
        </div>
        <div style="display:flex;gap:16px;flex-wrap:wrap">
            <span class="badge badge-blue">${(data.tests_run || []).length} Tests Run</span>
            <span class="badge badge-green">${(data.tests_passed || []).length} Passed</span>
            <span class="badge badge-red">${(data.tests_failed || []).length} Failed</span>
            <span class="badge badge-yellow">${(data.anomalies || []).length} Anomalies</span>
            <span class="badge badge-blue">${(data.fixes_applied || []).length} Fixes Applied</span>
            <span class="badge badge-gray">${data.pid_log_count || 0} PID Readings</span>
        </div>
    </div>`;

    if (data.voice_prompts && data.voice_prompts.length > 0) {
        html += '<h4 style="color:#4fc3f7;margin:16px 0 8px">Voice Prompts</h4><div class="dm-voice-log">';
        for (const v of data.voice_prompts) {
            const t = new Date(v.timestamp * 1000);
            const timeStr = t.toLocaleTimeString([], {hour:'2-digit', minute:'2-digit', second:'2-digit'});
            html += `<div class="dm-voice-item">
                <span class="dm-voice-time">${timeStr}</span>
                <span class="dm-voice-priority ${v.priority}">${v.priority}</span>
                <span class="dm-voice-text">${v.text}</span>
            </div>`;
        }
        html += '</div>';
    }

    if (data.fixes_applied && data.fixes_applied.length > 0) {
        html += '<h4 style="color:#00e676;margin:16px 0 8px">Fixes Applied</h4>';
        for (const fix of data.fixes_applied) {
            const status = fix.success ? 'badge-green' : 'badge-red';
            const statusText = fix.success ? 'SUCCESS' : 'FAILED';
            html += `<div class="fix-card">
                <div style="display:flex;justify-content:space-between;align-items:center">
                    <strong>${fix.fix_action?.description || fix.test}</strong>
                    <span class="badge ${status}">${statusText}</span>
                </div>
            </div>`;
        }
    }

    document.getElementById('dmSummaryContent').innerHTML = html;
    // Scroll to summary
    summaryCard.scrollIntoView({ behavior: 'smooth' });
}

// ─── License System ──────────────────────────────────────────────────────

async function loadLicenseStatus() {
    const data = await api('GET', '/api/license/status');
    if (data && !data.error) {
        state.license = data;
        updateLicenseUI(data);
    }
}

function updateLicenseUI(lic) {
    const tierLabel = document.getElementById('tierLabel');
    const freePanel = document.getElementById('licFreePanel');
    const proPanel = document.getElementById('licProPanel');

    if (lic.tier === 'pro' || lic.tier === 'pro_annual' || lic.tier === 'pro_lifetime') {
        tierLabel.textContent = 'PRO';
        tierLabel.className = 'badge badge-green';
        freePanel.style.display = 'none';
        proPanel.style.display = 'block';
        document.getElementById('licKeyDisplay').textContent = lic.license_key || '—';
        document.getElementById('licEmailDisplay').textContent = lic.email || '—';
        document.getElementById('licTierDisplay').textContent = lic.tier.toUpperCase();
        document.getElementById('licExpiresDisplay').textContent = lic.expires_at || 'Never (Lifetime)';
    } else {
        tierLabel.textContent = 'FREE';
        tierLabel.className = 'badge badge-yellow';
        freePanel.style.display = 'block';
        proPanel.style.display = 'none';
    }
}

function isProFeature(featureName) {
    return state.license.features && state.license.features[featureName] === true;
}

function showUpgradeModal(featureTitle, featureDesc) {
    document.getElementById('upgradeTitle').textContent = featureTitle || 'Pro Feature';
    document.getElementById('upgradeMessage').textContent = featureDesc || 'This feature requires ScanFixAI Pro.';
    const modal = document.getElementById('upgradeModal');
    modal.style.display = 'flex';
}

function closeUpgradeModal() {
    document.getElementById('upgradeModal').style.display = 'none';
}

async function activateLicense() {
    const key = document.getElementById('licKeyInput').value.trim();
    const email = document.getElementById('licEmailInput').value.trim();
    const msgEl = document.getElementById('licMessage');

    if (!key && !email) {
        msgEl.innerHTML = '<span style="color:#ff5252;">Enter a license key or email address.</span>';
        return;
    }

    msgEl.innerHTML = '<span style="color:#4fc3f7;">Activating...</span>';
    const data = await api('POST', '/api/license/activate', { license_key: key, email: email });

    if (data.success) {
        msgEl.innerHTML = '<span style="color:#00e676;">&#x2705; ' + data.message + '</span>';
        await loadLicenseStatus();
        toast('Pro license activated!', 'success');
    } else {
        msgEl.innerHTML = '<span style="color:#ff5252;">&#x274C; ' + (data.message || 'Activation failed.') + '</span>';
    }
}

async function deactivateLicense() {
    if (!confirm('Deactivate your Pro license on this device? You can re-activate later.')) return;
    const data = await api('POST', '/api/license/deactivate');
    toast(data.message || 'License deactivated.', 'info');
    await loadLicenseStatus();
}

// ─── Init ────────────────────────────────────────────────────────────────

// Load license status first, then check connection
loadLicenseStatus();
refreshStatus();
</script>

</body>
</html>
