mirror of
https://github.com/myronblair/jarvis
synced 2026-06-30 17:50:23 -05:00
95d49f15cb
- stopListening() called in both toggleKiosk exit and _onFsChange so mic stops when leaving kiosk (was staying live indefinitely) - exitVoiceMode() now returns early if kiosk-mode active so the 30-min idle timer and face-detection loop cannot kill the always-on mic
479 lines
29 KiB
HTML
479 lines
29 KiB
HTML
<!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 <span id="tb-cpu">--</span>% CPU</div>
|
||
<div class="tb-stat">MEM <span id="tb-mem">--</span>%</div>
|
||
<div class="tb-stat">JARVIS VM <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="kioskBtn" class="btn-panels" onclick="toggleKiosk()" title="Full-screen kiosk mode">⛶ KIOSK</button>
|
||
<button id="agentBtn" class="btn-agent" onclick="openAgentModal()" title="Install JARVIS Agent on this machine"><div class="agent-dot"></div>AGENT</button>
|
||
|
||
<div id="themeBar" style="display:flex;gap:3px;align-items:center;margin-right:2px">
|
||
<button class="theme-btn active" id="theme-blue" data-theme="stark-blue" onclick="applyTheme('stark-blue')" title="Stark Blue" style="color:#00d4ff">●</button>
|
||
<button class="theme-btn" id="theme-red" data-theme="widow-red" onclick="applyTheme('widow-red')" title="Widow Red" style="color:#ff3366">●</button>
|
||
<button class="theme-btn" id="theme-green" data-theme="hulk-green" onclick="applyTheme('hulk-green')" title="Hulk Green" style="color:#39ff14">●</button>
|
||
</div>
|
||
<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">
|
||
<!-- 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>
|
||
<div class="panel" id="server-panel">
|
||
<div class="panel-title">JARVIS SERVER <span style="font-size:0.5rem;color:var(--text-dim)">10.48.200.211</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>
|
||
<!-- Web Host (DO Server) -->
|
||
<div style="font-family:var(--font-display);font-size:0.5rem;letter-spacing:2px;color:var(--text-dim);margin:10px 0 5px">WEB HOST <span id="do-host-status" style="color:var(--green)">●</span></div>
|
||
<div id="do-host-stats" style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:6px;font-family:var(--font-mono);font-size:0.62rem">
|
||
<div><div style="color:var(--text-dim);font-size:0.52rem">CPU</div><div id="do-cpu">--%</div></div>
|
||
<div><div style="color:var(--text-dim);font-size:0.52rem">RAM</div><div id="do-mem">--%</div></div>
|
||
<div><div style="color:var(--text-dim);font-size:0.52rem">DISK</div><div id="do-disk">--%</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">
|
||
|
||
<!-- Network Status -->
|
||
<div class="panel" id="network-status-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" id="tab-btn-agents" 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;display:flex;flex-direction:column">
|
||
<div style="display:flex;align-items:center;justify-content:flex-end;padding:2px 0 4px;gap:6px;flex-shrink:0">
|
||
<button id="agent-topo-btn" onclick="toggleAgentTopo()" style="font-family:var(--font-display);font-size:0.42rem;letter-spacing:1.5px;background:rgba(0,212,255,0.06);border:1px solid rgba(0,212,255,0.25);color:var(--cyan);padding:3px 10px;border-radius:2px;cursor:pointer">⬡ TOPOLOGY</button>
|
||
</div>
|
||
<div id="agents-list" style="flex:1;overflow-y:auto"><div class="loading-shimmer"></div></div>
|
||
<canvas id="agentTopoCanvas" style="display:none;flex:1;width:100%;min-height:260px"></canvas>
|
||
</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 & 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>
|
||
|
||
<!-- Voice Transcript Bar -->
|
||
<div id="quickNoteBar"><span style="color:var(--cyan);font-family:var(--font-mono);font-size:0.6rem;letter-spacing:2px;flex-shrink:0">✎ NOTE</span><input id="quickNoteInput" placeholder="Type a note and press Enter…" onkeydown="handleNoteKey(event)"><button onclick="closeQuickNote()" style="background:none;border:none;color:rgba(0,212,255,0.5);cursor:pointer;font-size:0.8rem">✕</button></div>
|
||
<div id="voiceTranscriptBar" style="position:fixed;bottom:44px;left:50%;transform:translateX(-50%);max-width:580px;width:88%;background:rgba(0,8,16,0.9);border:1px solid rgba(0,212,255,0.3);border-radius:3px;font-family:var(--font-mono);font-size:0.62rem;color:rgba(0,212,255,0.9);letter-spacing:1px;padding:5px 14px;text-align:center;z-index:900;opacity:0;transition:opacity 0.18s ease;pointer-events:none"></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>JARVIS VM</span> <span id="bb-do-status">CHECKING</span>
|
||
</div>
|
||
<div class="bb-item" id="bb-pve-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" id="bb-ha-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" id="bb-agents-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> · ONLINE <span id="nm-online-count">—</span> · 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 style="margin-left:auto;opacity:0.5">1-4 tabs · M mute · F5 refresh · Space→input</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')">✕ CLOSE</button>
|
||
<h3 id="agentModalTitle">● 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 data-cfasync="false" src="https://cdn.jsdelivr.net/npm/face-api.js@0.22.2/dist/face-api.min.js" crossorigin="anonymous"></script>
|
||
|
||
<script data-cfasync="false" src="assets/js/jarvis-effects.js?v=20260621k"></script>
|
||
<script data-cfasync="false" src="assets/js/jarvis-overlays.js?v=20260621k"></script>
|
||
<script data-cfasync="false" src="assets/js/jarvis-app.js?v=20260621k"></script>
|
||
<script data-cfasync="false" src="assets/js/panels/jarvis-arc.js?v=20260621k"></script>
|
||
<script data-cfasync="false" src="assets/js/panels/jarvis-agents.js?v=20260621k"></script>
|
||
<script data-cfasync="false" src="assets/js/panels/jarvis-assistant.js?v=20260621k"></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>
|