Files
jarvis/public_html/index.html
T
myron b2aa3280e1 Add morning briefing, command palette, and boot animations
#11 Smart Morning Briefing: auto-speaks once per day before noon — fetches
tasks, appointments, active alerts, and weather, composes a ~2-sentence TTS
summary. Stored in localStorage (jarvis_brief_YYYY-MM-DD) to fire only once.

#12 Quick Command Palette (Ctrl+K): frosted-glass overlay with 20 pre-loaded
commands across 6 groups (Network/Agents/Planner/Media/Smart Home/System).
Fuzzy filter as you type, arrow-key navigation, Enter to fire. Matches are
highlighted. Backdrop click or Escape to close.

#13 Live Boot Animation: stat bars and numbers now count from 0 on first render
via tickTo() change. Arc Reactor rings spin in with staggered delays (0.08s
per ring) on login using boot-spin CSS class + @keyframes arcBootSpin.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 03:00:16 +00:00

455 lines
25 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1"/>
<title>JARVIS — Integrated Defense and Logistics System</title>
<link rel="preconnect" href="https://fonts.googleapis.com"/>
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;600;700;900&family=Rajdhani:wght@300;400;500;600&family=Share+Tech+Mono&display=swap" rel="stylesheet"/>
<link rel="stylesheet" href="assets/css/jarvis.css"/>
</head>
<body>
<canvas id="particleCanvas"></canvas>
<canvas id="dataStreamCanvas"></canvas>
<canvas id="hudCornersCanvas"></canvas>
<div id="alertOverlay"></div>
<div id="vignetteOverlay"></div>
<div id="faceScanOverlay">
<div class="fso-ring"></div>
<div class="fso-tr"></div>
<div class="fso-bl"></div>
<div class="fso-dot"></div>
<div class="fso-label">TRACKING</div>
</div>
<div class="scanlines"></div>
<div class="scanline-sweep"></div>
<!-- ── LOGIN ────────────────────────────────────────────────────────── -->
<div id="loginScreen">
<div class="login-reactor">
<div class="ring r1"></div><div class="ring r2"></div>
<div class="ring r3"></div><div class="ring r4"></div>
<div class="core"></div>
<div class="hud-ticks"></div>
</div>
<h1>JARVIS</h1>
<p>Just A Rather Very Intelligent System</p>
<form class="login-form" id="loginForm">
<input type="text" id="loginUser" placeholder="IDENTIFICATION" autocomplete="username" value="myron"/>
<input type="password" id="loginPass" placeholder="ACCESS CODE" autocomplete="current-password"/>
<button type="submit">INITIALIZE SYSTEM</button>
<div id="loginError"></div>
</form>
</div>
<!-- ── MAIN APP ──────────────────────────────────────────────────────── -->
<div id="app">
<!-- Top Bar -->
<div id="topBar">
<div class="tb-logo">
<div class="tb-reactor"><div class="tbr-ring tbr-r1"></div><div class="tbr-ring tbr-r2"></div><div class="tbr-core"></div><canvas id="audioRingCanvas" width="60" height="60"></canvas></div>
<span class="tb-logo-text" data-text="JARVIS SYSTEM">JARVIS SYSTEM</span>
</div>
<div class="tb-center">
<div class="tb-stat">LOCAL&nbsp;<span id="tb-cpu">--</span>% CPU</div>
<div class="tb-stat">MEM&nbsp;<span id="tb-mem">--</span>%</div>
<div class="tb-stat">DO SERVER&nbsp;<span id="tb-do" class="text-dim">--</span></div>
<div class="tb-stat"><span id="tb-alerts" class="text-green">NO ALERTS</span></div>
<div class="tb-stat" id="tb-planner" style="display:none"><span id="tb-planner-text" class="text-yellow"></span></div>
</div>
<div class="tb-right">
<div>
<div id="clock">--:--:--</div>
<div id="date-display">LOADING...</div>
</div>
<div class="status-dot"></div>
<button id="cameraBtn" class="btn-camera" onclick="toggleCamera()" title="Auto-mic when face detected (hands-free)">◉ CAMERA</button>
<button id="panelToggleBtn" class="btn-panels" onclick="togglePanels()" title="Toggle side panels (or say 'focus mode')">◧ PANELS</button>
<button id="agentBtn" class="btn-agent" onclick="openAgentModal()" title="Install JARVIS Agent on this machine"><div class="agent-dot"></div>AGENT</button>
<button id="btn-swap-panels" onclick="swapPanels()" title="Swap side panels">⇄ SWAP</button>
<button class="btn-logout" onclick="logout()">LOGOUT</button>
</div>
</div>
<!-- Main Layout -->
<div id="mainLayout">
<!-- LEFT: System Stats -->
<div id="leftPanel">
<div class="panel">
<div class="panel-title">JARVIS SERVER <span style="font-size:0.5rem;color:var(--text-dim)">165.22.1.228</span><div class="indicator"></div></div>
<!-- Metric bars + sparklines -->
<div class="metric-row">
<div class="metric-label">CPU <span id="cpu-val">--%</span></div>
<div class="metric-bar"><div class="metric-bar-fill" id="cpu-bar" style="width:0%"></div></div>
<div class="sparkline-wrap"><canvas id="spark-cpu"></canvas></div>
</div>
<div class="metric-row">
<div class="metric-label">MEMORY <span id="mem-val">--%</span></div>
<div class="metric-bar"><div class="metric-bar-fill" id="mem-bar" style="width:0%"></div></div>
<div class="sparkline-wrap"><canvas id="spark-mem"></canvas></div>
</div>
<div class="metric-row">
<div class="metric-label">DISK <span id="disk-val">--%</span></div>
<div class="metric-bar"><div class="metric-bar-fill" id="disk-bar" style="width:0%"></div></div>
<div class="sparkline-wrap"><canvas id="spark-disk"></canvas></div>
</div>
<div class="val-row"><div class="lbl">UPTIME</div><div class="val" id="uptime-val">--</div></div>
<div class="val-row"><div class="lbl">LOAD</div><div class="val" id="load-val">--</div></div>
<div class="val-row"><div class="lbl">HOST</div><div class="val" id="host-val">--</div></div>
<!-- Services -->
<div style="font-family:var(--font-display);font-size:0.5rem;letter-spacing:2px;color:var(--text-dim);margin:10px 0 5px">SERVICES</div>
<div id="services-list">
<div class="loading-shimmer" style="margin-bottom:4px"></div>
</div>
<!-- Site health -->
<div style="font-family:var(--font-display);font-size:0.5rem;letter-spacing:2px;color:var(--text-dim);margin:10px 0 5px">WEBSITES</div>
<div id="sites-list">
<div class="loading-shimmer" style="margin-bottom:4px"></div>
</div>
<!-- Top processes -->
<div style="font-family:var(--font-display);font-size:0.5rem;letter-spacing:2px;color:var(--text-dim);margin:10px 0 5px">PROCESSES</div>
<div id="procs-list">
<div class="loading-shimmer" style="margin-bottom:4px"></div>
</div>
</div>
</div>
<!-- CENTER: Arc Reactor + Chat -->
<div id="centerPanel">
<div id="arcReactor">
<div class="arc-ring r1"></div><div class="arc-ring r2"></div>
<div class="arc-ring r3"></div><div class="arc-ring r4"></div>
<div class="arc-ring r5"></div><div class="arc-ring r6"></div>
<div class="arc-ring r7"></div>
<div class="arc-core"></div>
<div class="hud-ticks"></div>
</div>
<div id="chatArea">
<div id="chatLog">
<div class="msg system">◈ JARVIS ONLINE — AWAITING INSTRUCTIONS ◈</div>
</div>
<div id="waveform">
<div class="wave-bar" style="--d:0.4s"></div>
<div class="wave-bar" style="--d:0.5s"></div>
<div class="wave-bar" style="--d:0.35s"></div>
<div class="wave-bar" style="--d:0.6s"></div>
<div class="wave-bar" style="--d:0.45s"></div>
<div class="wave-bar" style="--d:0.55s"></div>
<div class="wave-bar" style="--d:0.4s"></div>
<div class="wave-bar" style="--d:0.5s"></div>
<div class="wave-bar" style="--d:0.38s"></div>
<div class="wave-bar" style="--d:0.52s"></div>
</div>
<div id="contextChip">
<span id="contextType">CONTEXT</span>
<span id="contextLabel"></span>
<button id="contextClear" onclick="clearContext()" title="Clear context">×</button>
</div>
<div id="inputArea">
<button id="micBtn" onclick="toggleVoice()" title="Voice Command">
<span id="micIcon">🎤</span>
</button>
<input type="text" id="textInput" placeholder="Enter command or speak to JARVIS..."
autocomplete="off" onkeydown="if(event.key==='Enter')sendMessage()"/>
<button id="sendBtn" onclick="sendMessage()">TRANSMIT</button>
<button id="searchBtn" onclick="openSearchModal()" title="Search chat history" style="background:transparent;border:1px solid var(--panel-border);color:var(--text-dim);font-size:1rem;padding:0 10px;cursor:pointer;transition:all 0.2s;min-height:36px" onmouseover="this.style.color='var(--cyan)';this.style.borderColor='var(--cyan)'" onmouseout="this.style.color='var(--text-dim)';this.style.borderColor='var(--panel-border)'">🔍</button>
</div>
</div>
</div>
<!-- RIGHT: Network + VMs + HA -->
<div id="rightPanel">
<!-- Weather Widget -->
<div class="panel" style="flex:0 0 auto">
<div class="panel-title">WEATHER <span id="weather-loc" style="font-size:0.55rem;color:var(--text-dim)">FORT WORTH, TX</span></div>
<div style="display:flex;align-items:flex-start;gap:12px;margin-bottom:8px">
<div style="flex:1">
<div style="display:flex;align-items:baseline;gap:8px">
<span style="font-size:1.8rem;font-family:var(--font-display);color:var(--cyan);line-height:1" id="weather-temp">--</span>
<span style="font-size:0.75rem;color:var(--text-dim)">°F</span>
</div>
<div style="font-size:0.7rem;color:var(--text-primary);margin-top:2px;font-family:var(--font-display);letter-spacing:1px" id="weather-desc">LOADING...</div>
<div style="font-size:0.58rem;color:var(--text-dim);margin-top:3px" id="weather-details"></div>
</div>
<div style="text-align:right;flex-shrink:0">
<div style="font-size:0.52rem;color:var(--text-dim);letter-spacing:1px">FEELS LIKE</div>
<div style="font-size:1rem;font-family:var(--font-display);color:var(--cyan)" id="weather-feels">--°F</div>
<div style="font-size:0.52rem;color:var(--text-dim);margin-top:4px;letter-spacing:1px">HUMIDITY</div>
<div style="font-size:0.75rem;font-family:var(--font-display);color:var(--text-primary)" id="weather-humidity">--%</div>
</div>
</div>
<div id="weather-forecast" style="display:grid;grid-template-columns:repeat(4,1fr);gap:4px"></div>
</div>
<!-- Network Status -->
<div class="panel" style="flex:0 1 auto;max-height:35%;display:flex;flex-direction:column;min-height:100px">
<div class="panel-title">NETWORK STATUS <div class="indicator"></div><span id="net-agent-count" style="font-size:0.6rem;color:var(--cyan);margin-left:auto"></span><button onclick="addNetworkDevice()" title="Add device" style="background:none;border:none;color:var(--cyan);cursor:pointer;font-size:1rem;padding:0 4px;margin-left:4px;line-height:1">+</button></div>
<canvas id="topoCanvas" height="100"></canvas>
<div id="network-list" style="overflow-y:auto;flex:1;padding-right:2px">
<div class="loading-shimmer" style="margin-bottom:6px"></div>
<div class="loading-shimmer" style="margin-bottom:6px"></div>
<div class="loading-shimmer"></div>
</div>
<button onclick="scanNetwork()" style="margin-top:8px;flex-shrink:0;width:100%;background:rgba(0,212,255,0.06);border:1px solid var(--panel-border);border-radius:4px;padding:4px;color:var(--cyan);font-family:var(--font-display);font-size:0.55rem;letter-spacing:2px;cursor:pointer" id="scanBtn">RUN NETWORK SCAN</button>
</div>
<!-- Tab Panel -->
<div class="panel" style="flex:1;overflow:hidden;display:flex;flex-direction:column">
<!-- Clearance Alert Banner -->
<div id="clearance-banner">
<span>◈ CLEARANCE REQUIRED —</span>
<span class="clr-count" id="clr-banner-count">0</span>
<span>PENDING AUTHORIZATION</span>
<span class="clr-view" onclick="switchTab('clearance')">VIEW →</span>
</div>
<div class="tab-bar">
<div class="tab active" onclick="switchTab('ha')">HOME</div>
<div class="tab" onclick="switchTab('alerts')">ALERTS</div>
<div class="tab" onclick="switchTab('news')">NEWS</div>
<div class="tab" onclick="switchTab('agents')">AGENTS</div>
<div class="tab" onclick="switchTab('sites')">SITES</div>
<div class="tab" id="tab-btn-intel" onclick="switchTab('intel')">INTEL</div>
<div class="tab" id="tab-btn-comms" onclick="switchTab('comms')">COMMS</div>
<div class="tab" id="tab-btn-guardian" onclick="switchTab('guardian')">GUARDIAN</div>
<div class="tab" id="tab-btn-missions" onclick="switchTab('missions')">MISSIONS</div>
<div class="tab" id="tab-btn-directives" onclick="switchTab('directives')">DIRECTIVES</div>
<div class="tab" id="tab-btn-clearance" onclick="switchTab('clearance')">CLEARANCE <span id="clr-tab-badge" style="display:none;background:#ff2244;color:#fff;border-radius:3px;padding:0 4px;font-size:0.5rem;margin-left:2px"></span></div>
</div>
<div id="tab-vms" class="tab-pane" style="overflow-y:auto;flex:1">
<div id="vm-list"><div class="loading-shimmer"></div></div>
</div>
<div id="tab-ha" class="tab-pane active" style="overflow-y:auto;flex:1">
<div id="ha-list"><div class="loading-shimmer"></div></div>
</div>
<div id="tab-alerts" class="tab-pane" style="overflow-y:auto;flex:1">
<div id="alerts-list"><div class="loading-shimmer"></div></div>
</div>
<div id="tab-news" class="tab-pane" style="overflow-y:auto;flex:1">
<div style="display:flex;align-items:center;justify-content:flex-end;margin-bottom:4px">
<button onclick="toggleNewsFilter()" title="Filter news sources" style="background:none;border:none;color:var(--text-dim);cursor:pointer;font-size:0.85rem;padding:2px 4px;transition:color 0.2s" onmouseover="this.style.color='var(--cyan)'" onmouseout="this.style.color='var(--text-dim)'"></button>
</div>
<div id="news-filter-panel" style="display:none;margin-bottom:8px;padding:8px;background:rgba(0,212,255,0.04);border:1px solid var(--panel-border);border-radius:4px">
<div style="font-family:var(--font-display);font-size:0.52rem;letter-spacing:2px;color:var(--cyan);margin-bottom:6px">SHOW CATEGORIES</div>
<div id="news-filter-checkboxes" style="display:flex;flex-direction:column;gap:4px"></div>
</div>
<div id="news-list"><div class="loading-shimmer"></div></div>
</div>
<div id="tab-agents" class="tab-pane" style="overflow-y:auto;flex:1">
<div id="agents-list"><div class="loading-shimmer"></div></div>
</div>
<div id="tab-intel" class="tab-pane" style="overflow-y:auto;flex:1;padding:4px 0">
<div id="intel-list"><div class="loading-shimmer"></div></div>
</div>
<div id="tab-comms" class="tab-pane" style="overflow-y:auto;flex:1;padding:4px 0">
<div id="comms-list"><div class="loading-shimmer"></div></div>
<div class="comms-section-label" style="margin:12px 4px 6px">◈ OUTBOX — SENT &amp; QUEUED</div>
<div id="comms-outbox"><div class="loading-shimmer"></div></div>
</div>
<div id="tab-guardian" class="tab-pane" style="overflow-y:auto;flex:1;padding:4px 0">
<div id="guardian-list"><div class="loading-shimmer"></div></div>
</div>
<div id="tab-missions" class="tab-pane" style="overflow-y:auto;flex:1;padding:4px 0">
<div id="missions-hud"><div class="loading-shimmer"></div></div>
</div>
<div id="tab-directives" class="tab-pane" style="overflow-y:auto;flex:1;padding:4px 0">
<div id="directives-hud"><div class="loading-shimmer"></div></div>
</div>
<div id="tab-clearance" class="tab-pane" style="overflow-y:auto;flex:1;padding:4px 0">
<div id="clearance-hud"><div class="loading-shimmer"></div></div>
</div>
</div>
</div>
</div>
<!-- Bottom Bar -->
<div id="bottomBar">
<div class="bb-item">
<div class="bb-dot online"></div>
<span>JARVIS CORE</span> ONLINE
</div>
<div class="bb-item">
<div class="bb-dot" id="bb-do-dot"></div>
<span>DO SERVER</span> <span id="bb-do-status">CHECKING</span>
</div>
<div class="bb-item">
<div class="bb-dot" id="bb-pve-dot"></div>
<span>PROXMOX</span> <span id="bb-pve-status">CHECKING</span>
</div>
<div class="bb-item">
<div class="bb-dot" id="bb-ha-dot"></div>
<span>HOME ASSISTANT</span> <span id="bb-ha-status">CHECKING</span>
</div>
<div class="bb-item">
<div class="bb-dot" id="bb-agent-dot"></div>
<span>AGENTS</span> <span id="bb-agent-status">--</span>
</div>
<div class="bb-item">
<div class="bb-dot" id="bb-arc-dot"></div>
<span>ARC REACTOR</span> <span id="bb-arc-status">OFFLINE</span>
</div>
<div class="bb-item" id="bb-guardian-item" style="cursor:pointer" onclick="switchGuardianTab()">
<div class="bb-dot" id="bb-guardian-dot" style="background:var(--text-dim)"></div>
<span>GUARDIAN</span> <span id="bb-guardian-status" style="color:var(--text-dim)">INIT</span>
<span id="bb-guardian-badge" style="display:none;background:var(--red);color:#fff;font-size:0.45rem;padding:1px 4px;border-radius:2px;font-family:var(--font-mono);letter-spacing:0">0</span>
</div>
<div class="bb-item" style="cursor:pointer" onclick="switchTab('clearance')" id="bb-memory-item">
<div class="bb-dot" id="bb-memory-dot" style="background:rgba(0,212,255,0.3)"></div>
<span>MEMORY</span> <span id="bb-memory-count" style="color:var(--text-dim)">--</span>
</div>
<div id="ekgWrap" style="margin-left:auto"><canvas id="ekgCanvas"></canvas></div>
<div style="font-size:0.65rem;flex-shrink:0">
JARVIS v2.0 · SECURITY LEVEL ALPHA · UPDATED <span id="last-refresh">--:--:--</span>
</div>
</div>
</div>
<!-- NETWORK MAP OVERLAY -->
<div id="netMapOverlay">
<div id="nmHeader">
<div id="nmTitle"><div class="nm-pulse"></div>◈ NETWORK TOPOLOGY — LIVE</div>
<div id="nmStats">NODES <span id="nm-node-count"></span> &nbsp;·&nbsp; ONLINE <span id="nm-online-count"></span> &nbsp;·&nbsp; AGENTS <span id="nm-agent-count"></span></div>
<div style="display:flex;align-items:center;gap:12px">
<span style="font-family:var(--font-mono);font-size:0.52rem;color:var(--text-dim);letter-spacing:1px">SAY "CLOSE MAP"</span>
<button id="nmClose" onclick="closeNetMap()">✕ CLOSE</button>
</div>
</div>
<canvas id="nmCanvas"></canvas>
<div id="nmLegend">
<span><span class="nm-leg-dot" style="background:#00ff88;box-shadow:0 0 4px #00ff88"></span>PROXMOX</span>
<span><span class="nm-leg-dot" style="background:#ffd700;box-shadow:0 0 4px #ffd700"></span>SERVICES</span>
<span><span class="nm-leg-dot" style="background:#00beff;box-shadow:0 0 4px #00beff"></span>AGENTS</span>
<span><span class="nm-leg-dot" style="background:rgba(0,160,200,0.9)"></span>DEVICES</span>
<span><span class="nm-leg-dot" style="background:rgba(0,110,170,0.9)"></span>NETWORK</span>
<span><span class="nm-leg-dot" style="background:#ff2244;box-shadow:0 0 4px #ff2244"></span>OFFLINE</span>
<span style="margin-left:auto;opacity:0.4;font-size:0.5rem">CYAN = DATA IN · ORANGE = CMD OUT</span>
</div>
<div id="nmNodeInfo"><div class="ni-title" id="ni-name"></div><div class="ni-row" id="ni-ip"></div><div class="ni-row" id="ni-status"></div><div class="ni-row" id="ni-type"></div></div>
</div>
<!-- COMMAND PALETTE -->
<div id="cmdPalette">
<div id="cmdPaletteBox">
<input id="cmdPaletteInput" type="text" placeholder="TYPE A COMMAND..." autocomplete="off" spellcheck="false"/>
<div id="cmdPaletteList"></div>
<div id="cmdPaletteFooter">
<span>↑↓ navigate</span><span>↵ execute</span><span>ESC close</span><span>CTRL+K toggle</span>
</div>
</div>
</div>
<!-- SLEEP OVERLAY -->
<div id="sleepOverlay">
<div class="sleep-reactor">
<div class="sleep-ring sr1"></div>
<div class="sleep-ring sr2"></div>
<div class="sleep-ring sr3"></div>
<div class="sleep-core"></div>
</div>
<div class="sleep-label">JARVIS — STANDBY</div>
<div class="sleep-sub">SAY "WAKE UP JARVIS" TO RESUME</div>
</div>
<div id="sitesModal" style="position:fixed;inset:0;background:rgba(0,0,0,0.92);z-index:9999;display:none;align-items:flex-start;justify-content:center;padding:24px;overflow-y:auto">
<div style="background:var(--panel-bg);border:1px solid var(--panel-border);width:100%;max-width:960px;font-family:var(--font-mono)">
<div style="display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--panel-border)">
<div style="color:var(--cyan);font-size:0.75rem;letter-spacing:4px">◈ SITES MANAGER — EMAIL SETTINGS</div>
<button onclick="closeSitesModal()" style="background:transparent;border:1px solid var(--panel-border);color:var(--text-dim);cursor:pointer;font-family:var(--font-mono);font-size:0.6rem;padding:4px 12px;letter-spacing:2px">✕ CLOSE</button>
</div>
<div style="padding:20px 24px">
<!-- Global API Key -->
<div style="background:rgba(0,212,255,0.04);border:1px solid rgba(0,212,255,0.2);padding:16px;margin-bottom:20px">
<div style="color:var(--cyan);font-size:0.62rem;letter-spacing:3px;margin-bottom:10px">▸ CYBERMAIL API KEY — PUSH TO ALL SITES</div>
<div style="display:flex;gap:10px;align-items:center">
<input id="global-api-key" type="password"
style="flex:1;background:#0a0f1a;border:1px solid rgba(0,212,255,0.25);color:var(--text);font-family:var(--font-mono);font-size:0.7rem;padding:8px 12px;outline:none"
placeholder="sk_live_...">
<button onclick="pushApiKey()"
style="background:rgba(0,212,255,0.12);border:1px solid var(--cyan);color:var(--cyan);font-family:var(--font-mono);font-size:0.6rem;letter-spacing:2px;padding:8px 18px;cursor:pointer;white-space:nowrap">
PUSH TO ALL
</button>
</div>
<div id="push-status" style="font-size:0.6rem;color:var(--text-dim);margin-top:6px;min-height:16px"></div>
</div>
<!-- Site Cards Grid -->
<div id="sites-grid" style="display:grid;grid-template-columns:1fr 1fr;gap:14px">
<div style="grid-column:1/-1;color:var(--text-dim);font-size:0.65rem">LOADING...</div>
</div>
</div>
</div>
</div>
<div id="agentModal">
<div class="agent-modal-box">
<button class="agent-modal-close" onclick="document.getElementById('agentModal').classList.remove('open')">&#x2715; CLOSE</button>
<h3 id="agentModalTitle">&#9679; JARVIS AGENT</h3>
<div id="agentModalContent"></div>
</div>
</div>
<!-- Hidden camera feed for face detection -->
<video id="faceVideo" autoplay muted playsinline
style="position:fixed;top:-9999px;left:-9999px;width:320px;height:240px"></video>
<script src="https://cdn.jsdelivr.net/npm/face-api.js@0.22.2/dist/face-api.min.js" crossorigin="anonymous"></script>
<script src="assets/js/jarvis-effects.js"></script>
<script src="assets/js/jarvis-overlays.js"></script>
<script src="assets/js/jarvis-app.js"></script>
<script src="assets/js/jarvis-protocols.js"></script>
<!-- VISION LIGHTBOX -->
<div id="vision-lightbox">
<div id="vision-lb-header">
<span id="vision-lb-title">◈ VISION PROTOCOL</span>
<button id="vision-lb-close" onclick="closeVisionLightbox()">✕ CLOSE</button>
</div>
<div id="vision-lb-spinner">● SCANNING...</div>
<img id="vision-lb-img" alt="Agent Screenshot" style="display:none">
<pre id="vision-lb-analysis"></pre>
</div>
<!-- CHAT HISTORY SEARCH MODAL -->
<div id="searchModal" style="display:none;position:fixed;inset:0;z-index:200;background:rgba(0,0,0,0.7);backdrop-filter:blur(4px);align-items:center;justify-content:center">
<div style="background:#000d1f;border:1px solid var(--panel-border);border-radius:6px;padding:20px;width:min(620px,94vw);max-height:80vh;display:flex;flex-direction:column;gap:12px">
<div style="display:flex;align-items:center;justify-content:space-between">
<div style="font-family:var(--font-display);font-size:0.75rem;letter-spacing:3px;color:var(--cyan)">◈ CHAT HISTORY SEARCH</div>
<button onclick="closeSearchModal()" style="background:none;border:none;color:var(--text-dim);cursor:pointer;font-size:1rem"></button>
</div>
<div style="display:flex;gap:8px">
<input id="searchInput" type="text" placeholder="Search conversations…"
style="flex:1;background:rgba(0,212,255,0.05);border:1px solid var(--panel-border);color:var(--text-primary);font-family:var(--font-mono);font-size:0.75rem;padding:8px 12px;outline:none"
onkeydown="if(event.key==='Enter')runSearch()" autocomplete="off"/>
<button onclick="runSearch()" style="background:rgba(0,212,255,0.1);border:1px solid rgba(0,212,255,0.3);color:var(--cyan);font-family:var(--font-display);font-size:0.6rem;letter-spacing:2px;padding:8px 16px;cursor:pointer">SEARCH</button>
</div>
<div id="searchResults" style="overflow-y:auto;flex:1;display:flex;flex-direction:column;gap:6px;min-height:60px">
<div style="color:var(--text-dim);font-size:0.65rem;text-align:center;padding:20px">Type to search your JARVIS conversations</div>
</div>
</div>
</div>
<nav id="mobileNav">
<button class="mob-nav-btn active" id="mob-btn-left" onclick="mobSwitch('left')">
<span class="mob-icon">📊</span>STATS
</button>
<button class="mob-nav-btn" id="mob-btn-center" onclick="mobSwitch('center')">
<span class="mob-icon">💬</span>CHAT
</button>
<button class="mob-nav-btn" id="mob-btn-right" onclick="mobSwitch('right')">
<span class="mob-icon">🛰</span>INFO
</button>
</nav>
</body>
</html>