Spaces:
Running
Running
| <html lang="de"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>3-in-1 PRO | Signal Hunter | Ghost Detector | Audio Forensics</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"> | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&family=Inter:wght@300;400;600;800&display=swap'); | |
| :root { | |
| --bg: #050508; --panel: #0e0e12; --pri: #00ff9d; --acc: #ff0055; | |
| --txt: #e0e0e0; --border: #2a2a2a; --mono: 'JetBrains Mono', monospace; | |
| } | |
| * { margin:0; padding:0; box-sizing:border-box; } | |
| body { font-family:'Inter',sans-serif; background:var(--bg); color:var(--txt); overflow-x:hidden; min-height:100vh; } | |
| ::-webkit-scrollbar { width:4px; } ::-webkit-scrollbar-thumb { background:#333; border-radius:2px; } | |
| ::-webkit-scrollbar-thumb:hover { background:var(--pri); } | |
| .mode-btn { transition:all .25s ease; position:relative; overflow:hidden; } | |
| .mode-btn::after { content:''; position:absolute; bottom:0; left:50%; width:0; height:2px; background:var(--pri); transition:all .25s; transform:translateX(-50%); } | |
| .mode-btn.active::after { width:80%; } | |
| .mode-btn.active { background:rgba(0,255,157,.15)!important; border-color:var(--pri)!important; color:var(--pri)!important; box-shadow:0 0 20px rgba(0,255,157,.15); } | |
| @keyframes sweep { from{transform:rotate(0deg)} to{transform:rotate(360deg)} } | |
| @keyframes blip { 0%{transform:scale(0);opacity:1} 100%{transform:scale(3);opacity:0} } | |
| @keyframes pulse { 0%,100%{opacity:1} 50%{opacity:.5} } | |
| @keyframes float { 0%,100%{transform:translate(0,0)} 25%{transform:translate(10px,-10px)} 50%{transform:translate(-5px,15px)} 75%{transform:translate(-15px,-5px)} } | |
| @keyframes expand { 0%{transform:scale(.8);opacity:1} 100%{transform:scale(2);opacity:0} } | |
| @keyframes glow { 0%,100%{box-shadow:0 0 5px currentColor} 50%{box-shadow:0 0 20px currentColor,0 0 40px currentColor} } | |
| @keyframes dash { to{stroke-dashoffset:-1000} } | |
| .radar-sweep { position:absolute; top:50%; left:50%; width:50%; height:2px; | |
| background:linear-gradient(90deg,transparent,var(--pri),transparent); | |
| transform-origin:left center; animation:sweep 4s linear infinite; box-shadow:0 0 10px var(--pri); } | |
| .ghost-blip { position:absolute; width:20px; height:20px; border:2px solid #ff006e; | |
| border-radius:50%; animation:blip 2s ease-out infinite; box-shadow:0 0 20px #ff006e; } | |
| .emf-reading { font-family:var(--mono); text-shadow:0 0 10px currentColor; } | |
| .hotspot-ring { animation:expand 2s ease-out infinite; } | |
| .calibration-grid { | |
| background-image:linear-gradient(rgba(236,72,153,.2) 1px,transparent 1px), | |
| linear-gradient(90deg,rgba(236,72,153,.2) 1px,transparent 1px); background-size:50px 50px; } | |
| .filter-card { background:#151518; border:1px solid var(--border); border-radius:6px; | |
| padding:10px; margin-bottom:8px; transition:all .2s; } | |
| .filter-card.active { border-color:var(--pri); box-shadow:0 0 12px rgba(0,255,157,.08); } | |
| .filter-card:hover { border-color:#444; } | |
| input[type=range] { width:100%; height:3px; background:#000; -webkit-appearance:none; cursor:pointer; } | |
| input[type=range]::-webkit-slider-thumb { -webkit-appearance:none; width:12px; height:12px; | |
| background:#666; border-radius:50%; cursor:pointer; transition:background .2s; } | |
| .filter-card.active input[type=range]::-webkit-slider-thumb { background:var(--pri); box-shadow:0 0 6px var(--pri); } | |
| .toggle-sw { width:32px; height:16px; position:relative; cursor:pointer; flex-shrink:0; } | |
| .toggle-sw input { opacity:0; width:0; height:0; } | |
| .toggle-track { position:absolute; inset:0; background:#333; border-radius:8px; transition:.2s; } | |
| .toggle-knob { position:absolute; top:2px; left:2px; width:12px; height:12px; background:#888; | |
| border-radius:50%; transition:.2s; } | |
| .toggle-sw input:checked+.toggle-track { background:var(--pri); } | |
| .toggle-sw input:checked+.toggle-track .toggle-knob { transform:translateX(16px); background:#000; } | |
| .math-input { width:100%; background:#080808; border:1px solid #333; color:var(--pri); | |
| font-family:var(--mono); font-size:.7rem; padding:4px 6px; border-radius:3px; } | |
| .math-input:focus { border-color:var(--pri); outline:none; box-shadow:0 0 0 2px rgba(0,255,157,.15); } | |
| .toast { position:fixed; bottom:24px; right:24px; z-index:9999; padding:12px 20px; | |
| border-radius:10px; background:#1a1a2e; border:1px solid var(--pri); color:var(--txt); | |
| font-size:13px; box-shadow:0 8px 30px rgba(0,0,0,.5); transform:translateX(120%); | |
| transition:transform .4s cubic-bezier(.34,1.56,.64,1); display:flex; align-items:center; gap:10px; } | |
| .toast.show { transform:translateX(0); } | |
| .modal-bg { position:fixed; inset:0; background:rgba(0,0,0,.7); z-index:1000; | |
| display:none; place-items:center; backdrop-filter:blur(6px); } | |
| .modal-bg.open { display:grid; } | |
| .modal-box { background:#111; border:1px solid var(--pri); border-radius:12px; | |
| padding:24px; max-width:480px; width:90%; max-height:80vh; overflow-y:auto; } | |
| @media(max-width:768px) { | |
| .hide-mobile { display:none!important; } | |
| .mode-bar { flex-wrap:wrap; } | |
| } | |
| </style> | |
| </head> | |
| <body class="min-h-screen"> | |
| <!-- Toast --> | |
| <div class="toast" id="toast"><i class="fa-solid fa-circle-check" style="color:var(--pri)"></i><span id="toast-msg"></span></div> | |
| <!-- Calc Modal --> | |
| <div class="modal-bg" id="calcModal"> | |
| <div class="modal-box"> | |
| <div class="flex justify-between items-center mb-3"> | |
| <h3 class="text-sm font-bold" style="color:var(--pri)">SCIENTIFIC CALC</h3> | |
| <button onclick="document.getElementById('calcModal').classList.remove('open')" class="text-gray-500 hover:text-white text-lg">×</button> | |
| </div> | |
| <input type="text" id="calcDisplay" class="math-input text-base mb-3" style="height:40px"> | |
| <div class="grid grid-cols-5 gap-1" id="calcKeys"></div> | |
| <div class="flex gap-2 mt-3"> | |
| <button onclick="calcCheck()" class="flex-1 py-2 bg-gray-800 border border-gray-600 text-gray-300 rounded text-xs font-bold">() FIX</button> | |
| <button onclick="calcInsert()" class="flex-1 py-2 bg-green-500/20 border border-green-500/50 text-green-400 rounded text-xs font-bold">INSERT</button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Header --> | |
| <header class="fixed top-0 left-0 right-0 z-50 bg-black/90 backdrop-blur-md border-b border-green-500/30 px-4 py-2"> | |
| <div class="flex items-center justify-between max-w-[1920px] mx-auto"> | |
| <div class="flex items-center gap-3"> | |
| <div class="w-9 h-9 rounded-lg bg-gradient-to-br from-green-500 to-emerald-700 flex items-center justify-center shadow-lg shadow-green-500/20"> | |
| <i class="fa-solid fa-satellite-dish text-black text-sm"></i> | |
| </div> | |
| <div> | |
| <h1 class="text-sm font-bold text-green-400 tracking-wider">3-IN-1 PRO | SIGNAL HUNTER</h1> | |
| <p class="text-[9px] text-gray-500">Ghost | EMF | RF | Magnet | Audio | Fusion</p> | |
| </div> | |
| </div> | |
| <div class="flex items-center gap-3 text-xs font-mono"> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" | |
| class="text-[10px] text-gray-500 hover:text-green-400 transition uppercase tracking-wider">Built with anycoder</a> | |
| <span class="text-gray-600">|</span> | |
| <span class="text-gray-500">MODE:</span> | |
| <span id="currentMode" class="text-green-400 font-bold">SCOPE</span> | |
| <button onclick="toggleRunning()" id="btnToggle" | |
| class="px-3 py-1 bg-green-500/20 border border-green-500/50 text-green-400 rounded text-xs hover:bg-green-500/30 transition"> | |
| <i class="fa-solid fa-play"></i> <span class="hide-mobile">RUN</span> | |
| </button> | |
| </div> | |
| </div> | |
| </header> | |
| <!-- Mode Bar --> | |
| <div class="fixed top-[52px] left-0 right-0 z-40 bg-black/80 backdrop-blur border-b border-gray-800 px-3 py-2"> | |
| <div class="max-w-[1920px] mx-auto flex gap-2 overflow-x-auto mode-bar pb-1"> | |
| <button onclick="setMode('scope')" class="mode-btn active px-3 py-1.5 border border-gray-700 rounded-lg text-[11px] font-bold whitespace-nowrap" id="btn-scope"><i class="fa-solid fa-wave-square mr-1"></i>SCOPE</button> | |
| <button onclick="setMode('ghost')" class="mode-btn px-3 py-1.5 border border-gray-700 rounded-lg text-[11px] font-bold whitespace-nowrap text-purple-400" id="btn-ghost"><i class="fa-solid fa-ghost mr-1"></i>GHOST</button> | |
| <button onclick="setMode('emf')" class="mode-btn px-3 py-1.5 border border-gray-700 rounded-lg text-[11px] font-bold whitespace-nowrap text-yellow-400" id="btn-emf"><i class="fa-solid fa-bolt mr-1"></i>EMF</button> | |
| <button onclick="setMode('rf')" class="mode-btn px-3 py-1.5 border border-gray-700 rounded-lg text-[11px] font-bold whitespace-nowrap text-cyan-400" id="btn-rf"><i class="fa-solid fa-tower-broadcast mr-1"></i>RF</button> | |
| <button onclick="setMode('magnet')" class="mode-btn px-3 py-1.5 border border-gray-700 rounded-lg text-[11px] font-bold whitespace-nowrap text-red-400" id="btn-magnet"><i class="fa-solid fa-compass mr-1"></i>MAG</button> | |
| <button onclick="setMode('audio')" class="mode-btn px-3 py-1.5 border border-gray-700 rounded-lg text-[11px] font-bold whitespace-nowrap text-pink-400" id="btn-audio"><i class="fa-solid fa-music mr-1"></i>AUDIO</button> | |
| <button onclick="setMode('fx')" class="mode-btn px-3 py-1.5 border border-gray-700 rounded-lg text-[11px] font-bold whitespace-nowrap text-emerald-400" id="btn-fx"><i class="fa-solid fa-wand-magic-sparkles mr-1"></i>FX</button> | |
| <button onclick="setMode('fusion')" class="mode-btn px-3 py-1.5 border border-gray-700 rounded-lg text-[11px] font-bold whitespace-nowrap text-amber-400" id="btn-fusion"><i class="fa-solid fa-atom mr-1"></i>FUSION</button> | |
| </div> | |
| </div> | |
| <!-- Main --> | |
| <main class="pt-28 pb-4 px-2 max-w-[1920px] mx-auto"> | |
| <!-- SCOPE --> | |
| <div id="mode-scope" class="mode-content"> | |
| <div class="grid grid-cols-1 lg:grid-cols-3 gap-2"> | |
| <div class="lg:col-span-2 bg-gray-900/80 border border-green-500/30 rounded-lg overflow-hidden"> | |
| <div class="flex items-center justify-between px-3 py-2 bg-black/40 border-b border-green-500/20"> | |
| <h3 class="text-xs font-bold text-green-400">DUAL CHANNEL | 120MHz | 250MSa/s</h3> | |
| <div class="flex gap-1"> | |
| <button onclick="triggerMode='AUTO'" class="px-2 py-0.5 text-[10px] bg-green-500/20 text-green-400 rounded">AUTO</button> | |
| <button onclick="triggerMode='NORM'" class="px-2 py-0.5 text-[10px] bg-gray-800 text-gray-400 rounded">NORM</button> | |
| <button onclick="triggerMode='SINGLE'" class="px-2 py-0.5 text-[10px] bg-gray-800 text-gray-400 rounded">SINGLE</button> | |
| </div> | |
| </div> | |
| <div class="relative h-72 bg-black"><canvas id="scopeMain" class="w-full h-full"></canvas> | |
| <div class="absolute top-2 left-2 text-[10px] font-mono text-green-400/70">CH1: 2V/div | CH2: 1V/div | T: 500ns/div</div> | |
| </div> | |
| </div> | |
| <div class="space-y-2"> | |
| <div class="bg-gray-900/80 border border-cyan-500/30 rounded-lg overflow-hidden"> | |
| <div class="px-3 py-2 bg-black/40 border-b border-cyan-500/20"><h3 class="text-xs font-bold text-cyan-400">FFT SPECTRUM</h3></div> | |
| <canvas id="scopeFFT" class="w-full h-36 bg-black"></canvas> | |
| </div> | |
| <div class="bg-gray-900/80 border border-yellow-500/30 rounded-lg p-3"> | |
| <h3 class="text-xs font-bold text-yellow-400 mb-1">MULTIMETER</h3> | |
| <div class="text-2xl font-mono text-yellow-400" id="dmmDisplay">0.000 V DC</div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- GHOST --> | |
| <div id="mode-ghost" class="mode-content hidden"> | |
| <div class="grid grid-cols-1 lg:grid-cols-2 gap-2"> | |
| <div class="bg-gray-900/80 border border-purple-500/30 rounded-lg overflow-hidden"> | |
| <div class="px-3 py-2 bg-black/40 border-b border-purple-500/20 flex justify-between"> | |
| <h3 class="text-xs font-bold text-purple-400"><i class="fa-solid fa-ghost mr-1"></i>EMF SPIRIT DETECTOR</h3> | |
| <span class="text-[10px] text-purple-400 animate-pulse">SCANNING...</span> | |
| </div> | |
| <div class="relative h-80 bg-black flex items-center justify-center overflow-hidden" id="ghostRadar"> | |
| <div class="absolute w-56 h-56 border border-purple-500/30 rounded-full"></div> | |
| <div class="absolute w-40 h-40 border border-purple-500/20 rounded-full"></div> | |
| <div class="absolute w-24 h-24 border border-purple-500/10 rounded-full"></div> | |
| <div class="absolute w-3 h-3 bg-purple-500 rounded-full"></div> | |
| <div class="radar-sweep" style="--pri:#a855f7"></div> | |
| <div id="ghostBlips"></div> | |
| <div class="absolute top-3 left-3 emf-reading text-3xl text-purple-400" id="emfValue">0.00</div> | |
| <div class="absolute top-3 right-3 text-right"> | |
| <div class="text-[10px] text-gray-500">FIELD STRENGTH</div> | |
| <div class="text-xs text-purple-400" id="emfStatus">NORMAL</div> | |
| </div> | |
| </div> | |
| <div class="p-3 border-t border-purple-500/20"> | |
| <div class="flex justify-between text-[10px] mb-1"><span class="text-gray-500">SENSITIVITY</span><span class="text-purple-400" id="sensVal">HIGH</span></div> | |
| <input type="range" min="1" max="100" value="80" class="w-full h-1 bg-gray-700 rounded accent-purple-500" oninput="document.getElementById('sensVal').textContent=this.value>80?'HIGH':this.value>40?'MED':'LOW'"> | |
| </div> | |
| </div> | |
| <div class="bg-gray-900/80 border border-pink-500/30 rounded-lg overflow-hidden"> | |
| <div class="px-3 py-2 bg-black/40 border-b border-pink-500/20 flex justify-between"> | |
| <h3 class="text-xs font-bold text-pink-400"><i class="fa-solid fa-microphone mr-1"></i>EVP AUDIO ANALYZER</h3> | |
| <span class="text-[10px] text-pink-400">REC <i class="fa-solid fa-circle text-[8px]"></i></span> | |
| </div> | |
| <div class="relative h-56 bg-black"><canvas id="evpWave" class="w-full h-full"></canvas></div> | |
| <div class="p-3 space-y-2 border-t border-pink-500/20"> | |
| <div class="flex gap-2"> | |
| <button onclick="toast('EVP Recording started')" class="flex-1 py-2 bg-pink-500/20 border border-pink-500/50 text-pink-400 rounded text-xs">START RECORD</button> | |
| <button onclick="toast('FM Sweep: 88-108MHz')" class="flex-1 py-2 bg-gray-800 text-gray-400 rounded text-xs">FM SWEEP</button> | |
| </div> | |
| <div class="text-[10px] text-gray-500 font-mono" id="evpLog">> Waiting for anomalous signals...</div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- EMF --> | |
| <div id="mode-emf" class="mode-content hidden"> | |
| <div class="grid grid-cols-1 lg:grid-cols-3 gap-2"> | |
| <div class="lg:col-span-2 bg-gray-900/80 border border-yellow-500/30 rounded-lg overflow-hidden"> | |
| <div class="px-3 py-2 bg-black/40 border-b border-yellow-500/20"><h3 class="text-xs font-bold text-yellow-400"><i class="fa-solid fa-bolt mr-1"></i>ELEKTROMAGNETISCHE FELDKARTE</h3></div> | |
| <div class="relative h-80 bg-black"><canvas id="emfHeat" class="w-full h-full"></canvas> | |
| <div class="absolute bottom-3 right-3 bg-black/80 p-2 rounded text-[10px]"> | |
| <div class="flex items-center gap-2 mb-1"><div class="w-3 h-3 bg-blue-500 rounded"></div><span class="text-gray-400">0-0.1 uT</span></div> | |
| <div class="flex items-center gap-2 mb-1"><div class="w-3 h-3 bg-green-500 rounded"></div><span class="text-gray-400">0.1-1 uT</span></div> | |
| <div class="flex items-center gap-2 mb-1"><div class="w-3 h-3 bg-yellow-500 rounded"></div><span class="text-gray-400">1-10 uT</span></div> | |
| <div class="flex items-center gap-2"><div class="w-3 h-3 bg-red-500 rounded"></div><span class="text-gray-400">>10 uT</span></div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="space-y-2"> | |
| <div class="bg-gray-900/80 border border-yellow-500/30 rounded-lg p-4 text-center"> | |
| <h3 class="text-xs font-bold text-yellow-400 mb-3">MAGNETFELD STARKE</h3> | |
| <div class="text-4xl font-mono text-yellow-400" id="emfGauss">0.00</div> | |
| <div class="text-[10px] text-gray-500">uT (Mikrotesla)</div> | |
| </div> | |
| <div class="bg-gray-900/80 border border-yellow-500/30 rounded-lg p-3"> | |
| <h3 class="text-xs font-bold text-yellow-400 mb-2">FREQUENZ ANALYSE</h3> | |
| <canvas id="emfSpec" class="w-full h-28 bg-black rounded"></canvas> | |
| <div class="mt-2 text-[10px] text-gray-500">Dominant: <span class="text-yellow-400" id="emfFreq">50.0 Hz</span></div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- RF --> | |
| <div id="mode-rf" class="mode-content hidden"> | |
| <div class="grid grid-cols-1 lg:grid-cols-2 gap-2"> | |
| <div class="bg-gray-900/80 border border-cyan-500/30 rounded-lg overflow-hidden"> | |
| <div class="px-3 py-2 bg-black/40 border-b border-cyan-500/20"><h3 class="text-xs font-bold text-cyan-400"><i class="fa-solid fa-tower-broadcast mr-1"></i>RF WATERFALL | 100kHz-6GHz</h3></div> | |
| <div class="relative h-60 bg-black"><canvas id="rfCanvas" class="w-full h-full"></canvas> | |
| <div class="absolute top-0 left-0 right-0 h-5 flex items-center justify-around text-[8px] text-cyan-400/60 font-mono"> | |
| <span>100k</span><span>1M</span><span>10M</span><span>100M</span><span>1G</span><span>6G</span> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="bg-gray-900/80 border border-orange-500/30 rounded-lg overflow-hidden"> | |
| <div class="px-3 py-2 bg-black/40 border-b border-orange-500/20"><h3 class="text-xs font-bold text-orange-400"><i class="fa-solid fa-fire mr-1"></i>HOT SPOT FINDER</h3></div> | |
| <div class="relative h-60 bg-black"><canvas id="hotspotCanvas" class="w-full h-full"></canvas> | |
| <div class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 text-center"> | |
| <div class="w-16 h-16 border-2 border-orange-500/50 rounded-full flex items-center justify-center relative"> | |
| <div class="hotspot-ring absolute inset-0 border-2 border-orange-500 rounded-full"></div> | |
| <div><div class="text-lg font-bold text-orange-400" id="centerSig">-85</div><div class="text-[8px] text-gray-500">dBm</div></div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="p-2 border-t border-orange-500/20 grid grid-cols-4 gap-1 text-[9px]"> | |
| <div class="p-1 bg-gray-800 rounded text-center"><div class="text-cyan-400 font-bold">WiFi</div><div class="text-gray-400">-42dBm</div></div> | |
| <div class="p-1 bg-gray-800 rounded text-center"><div class="text-green-400 font-bold">LTE</div><div class="text-gray-400">-78dBm</div></div> | |
| <div class="p-1 bg-gray-800 rounded text-center"><div class="text-yellow-400 font-bold">GPS</div><div class="text-gray-400">-45dBm</div></div> | |
| <div class="p-1 bg-gray-800 rounded text-center"><div class="text-purple-400 font-bold">BT</div><div class="text-gray-400">-65dBm</div></div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- MAGNET --> | |
| <div id="mode-magnet" class="mode-content hidden"> | |
| <div class="grid grid-cols-1 lg:grid-cols-3 gap-2"> | |
| <div class="lg:col-span-2 bg-gray-900/80 border border-red-500/30 rounded-lg overflow-hidden"> | |
| <div class="px-3 py-2 bg-black/40 border-b border-red-500/20"><h3 class="text-xs font-bold text-red-400"><i class="fa-solid fa-compass mr-1"></i>3D MAGNETOMETER | XYZ</h3></div> | |
| <div class="relative h-72 bg-black"><canvas id="mag3d" class="w-full h-full"></canvas> | |
| <div class="absolute top-3 left-3 space-y-1 text-[10px] font-mono"> | |
| <div class="text-red-400">X: <span id="magX">12.4</span> uT</div> | |
| <div class="text-green-400">Y: <span id="magY">-8.2</span> uT</div> | |
| <div class="text-blue-400">Z: <span id="magZ">45.7</span> uT</div> | |
| <div class="text-white mt-2">Total: <span id="magTotal">47.8</span> uT</div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="space-y-2"> | |
| <div class="bg-gray-900/80 border border-red-500/30 rounded-lg p-3"> | |
| <h3 class="text-xs font-bold text-red-400 mb-2">FIELD HISTORY</h3> | |
| <canvas id="magHist" class="w-full h-28 bg-black rounded"></canvas> | |
| </div> | |
| <div class="bg-gray-900/80 border border-red-500/30 rounded-lg p-3"> | |
| <h3 class="text-xs font-bold text-red-400 mb-2">ANOMALY DETECTION</h3> | |
| <div class="space-y-2"> | |
| <div class="flex justify-between p-2 bg-gray-800 rounded text-[10px]"><span class="text-gray-400">Baseline</span><span class="text-red-400">48.2 uT</span></div> | |
| <div class="flex justify-between p-2 bg-gray-800 rounded text-[10px]"><span class="text-gray-400">Deviation</span><span class="text-yellow-400" id="magDev">+2.1 uT</span></div> | |
| <div class="flex justify-between p-2 bg-red-900/20 border border-red-500/30 rounded text-[10px]"><span class="text-red-400">Anomaly</span><span class="text-red-400" id="magAnom">DETECTED</span></div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- AUDIO --> | |
| <div id="mode-audio" class="mode-content hidden"> | |
| <div class="grid grid-cols-1 lg:grid-cols-2 gap-2"> | |
| <div class="bg-gray-900/80 border border-pink-500/30 rounded-lg overflow-hidden"> | |
| <div class="px-3 py-2 bg-black/40 border-b border-pink-500/20"><h3 class="text-xs font-bold text-pink-400"><i class="fa-solid fa-music mr-1"></i>SPEKTROGRAMM | 0-24kHz</h3></div> | |
| <div class="relative h-56 bg-black"><canvas id="audioSpec" class="w-full h-full"></canvas></div> | |
| </div> | |
| <div class="bg-gray-900/80 border border-pink-500/30 rounded-lg overflow-hidden"> | |
| <div class="px-3 py-2 bg-black/40 border-b border-pink-500/20"><h3 class="text-xs font-bold text-pink-400"><i class="fa-solid fa-fingerprint mr-1"></i>AUDIO FINGERPRINT</h3></div> | |
| <div class="p-4 space-y-3"> | |
| <div class="p-3 bg-gray-800 rounded"> | |
| <div class="flex justify-between items-center mb-2"><span class="text-[10px] text-gray-500">MATCH SCORE</span><span class="text-xl font-bold text-green-400" id="matchScore">87.3%</span></div> | |
| <div class="h-2 bg-gray-700 rounded overflow-hidden"><div class="h-full bg-gradient-to-r from-red-500 via-yellow-500 to-green-500 transition-all" id="matchBar" style="width:87.3%"></div></div> | |
| </div> | |
| <div class="flex gap-2"> | |
| <button onclick="toast('Recording...')" class="flex-1 py-2 bg-pink-500/20 border border-pink-500/50 text-pink-400 rounded text-xs"><i class="fa-solid fa-circle mr-1"></i>RECORD</button> | |
| <button onclick="toast('Reference loaded')" class="flex-1 py-2 bg-gray-800 text-gray-400 rounded text-xs">LOAD REF</button> | |
| <button onclick="toast('Comparing...')" class="flex-1 py-2 bg-gray-800 text-gray-400 rounded text-xs">COMPARE</button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- FX STUDIO --> | |
| <div id="mode-fx" class="mode-content hidden"> | |
| <div class="grid grid-cols-1 lg:grid-cols-4 gap-2"> | |
| <div class="lg:col-span-3 bg-gray-900/80 border border-emerald-500/30 rounded-lg overflow-hidden"> | |
| <div class="px-3 py-2 bg-black/40 border-b border-emerald-500/20 flex justify-between items-center"> | |
| <h3 class="text-xs font-bold text-emerald-400"><i class="fa-solid fa-wand-magic-sparkles mr-1"></i>VISION FX ENGINE</h3> | |
| <div class="flex gap-2"> | |
| <button onclick="randomizeFX()" class="px-2 py-1 text-[10px] bg-purple-500/20 border border-purple-500/50 text-purple-400 rounded hover:bg-purple-500/30 transition"><i class="fa-solid fa-shuffle mr-1"></i>RANDOM</button> | |
| <label class="px-2 py-1 text-[10px] bg-gray-800 border border-gray-600 text-gray-400 rounded cursor-pointer hover:border-emerald-500/50 transition"><i class="fa-solid fa-video mr-1"></i>LOAD<input type="file" id="fxFileInput" accept="video/*,image/*,audio/*" class="hidden"></label> | |
| <button onclick="exportSnapshot()" class="px-2 py-1 text-[10px] bg-emerald-500/20 border border-emerald-500/50 text-emerald-400 rounded hover:bg-emerald-500/30 transition"><i class="fa-solid fa-camera mr-1"></i>SNAP</button> | |
| <button onclick="exportGIF()" class="px-2 py-1 text-[10px] bg-pink-500/20 border border-pink-500/50 text-pink-400 rounded hover:bg-pink-500/30 transition"><i class="fa-solid fa-film mr-1"></i>GIF</button> | |
| </div> | |
| </div> | |
| <div class="relative bg-black" style="height:420px"><canvas id="fxCanvas" class="w-full h-full"></canvas></div> | |
| </div> | |
| <div class="space-y-2 max-h-[480px] overflow-y-auto"> | |
| <div class="bg-gray-900/80 border border-gray-700 rounded-lg p-2"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <span class="text-[10px] text-gray-500 font-bold">PRESETS</span> | |
| <button onclick="savePreset()" class="text-[10px] text-emerald-400 hover:text-white transition"><i class="fa-solid fa-save mr-1"></i>SAVE</button> | |
| </div> | |
| <div id="presetBar" class="flex flex-wrap gap-1"></div> | |
| </div> | |
| <div id="filterList"></div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- FUSION --> | |
| <div id="mode-fusion" class="mode-content hidden"> | |
| <div class="bg-gray-900/80 border border-amber-500/30 rounded-lg overflow-hidden"> | |
| <div class="px-3 py-2 bg-black/40 border-b border-amber-500/20 flex justify-between"> | |
| <h3 class="text-xs font-bold text-amber-400"><i class="fa-solid fa-atom mr-1"></i>KALIBRIERTE GESAMTÜBERSICHT | MULTI-SENSOR FUSION</h3> | |
| <div class="flex gap-2 text-[10px]"> | |
| <span class="px-2 py-0.5 bg-amber-500/20 text-amber-400 rounded">KALMAN FILTER</span> | |
| <span class="px-2 py-0.5 bg-gray-800 text-gray-400 rounded">SYNC: LOCKED</span> | |
| </div> | |
| </div> | |
| <div class="relative h-[420px] bg-black calibration-grid"><canvas id="fusionCanvas" class="w-full h-full"></canvas> | |
| <div class="absolute top-3 left-3 space-y-1 text-[10px] font-mono"> | |
| <div class="flex items-center gap-2"><div class="w-2 h-2 rounded-full bg-cyan-400"></div><span class="text-cyan-400">RF: 14 Signale</span></div> | |
| <div class="flex items-center gap-2"><div class="w-2 h-2 rounded-full bg-yellow-400"></div><span class="text-yellow-400">EMF: 3.2 uT</span></div> | |
| <div class="flex items-center gap-2"><div class="w-2 h-2 rounded-full bg-red-400"></div><span class="text-red-400">MAG: 47.8 uT</span></div> | |
| <div class="flex items-center gap-2"><div class="w-2 h-2 rounded-full bg-pink-400"></div><span class="text-pink-400">AUDIO: 58.7 dB</span></div> | |
| <div class="flex items-center gap-2"><div class="w-2 h-2 rounded-full bg-purple-400"></div><span class="text-purple-400">GHOST: 2 Anomalien</span></div> | |
| </div> | |
| <div class="absolute bottom-3 right-3 text-[10px] font-mono text-amber-400/60 text-right"> | |
| <div class="mb-1 font-bold">TRANSFORM MATRIX</div> | |
| <div>[0.998, -0.052, 0.000, 12.4]</div> | |
| <div>[0.052, 0.998, 0.000, -8.2]</div> | |
| <div>[0.000, 0.000, 1.000, 0.000]</div> | |
| <div class="mt-1 text-gray-500">Error: 0.03mm RMS</div> | |
| </div> | |
| </div> | |
| <div class="p-2 border-t border-amber-500/20 grid grid-cols-5 gap-2"> | |
| <button class="p-2 bg-cyan-500/20 border border-cyan-500/50 text-cyan-400 rounded text-xs hover:bg-cyan-500/30 transition"><i class="fa-solid fa-tower-broadcast mr-1"></i>RF</button> | |
| <button class="p-2 bg-yellow-500/20 border border-yellow-500/50 text-yellow-400 rounded text-xs hover:bg-yellow-500/30 transition"><i class="fa-solid fa-bolt mr-1"></i>EMF</button> | |
| <button class="p-2 bg-red-500/20 border border-red-500/50 text-red-400 rounded text-xs hover:bg-red-500/30 transition"><i class="fa-solid fa-compass mr-1"></i>MAG</button> | |
| <button class="p-2 bg-pink-500/20 border border-pink-500/50 text-pink-400 rounded text-xs hover:bg-pink-500/30 transition"><i class="fa-solid fa-music mr-1"></i>AUDIO</button> | |
| <button class="p-2 bg-purple-500/20 border border-purple-500/50 text-purple-400 rounded text-xs hover:bg-purple-500/30 transition"><i class="fa-solid fa-ghost mr-1"></i>GHOST</button> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| <script> | |
| // ========================================== | |
| // CORE STATE | |
| // ========================================== | |
| const S = { | |
| mode: 'scope', running: true, t: 0, dt: 0, lastFrame: 0, | |
| audio: { ctx: null, analyser: null, data: null, bass: 0, mid: 0, high: 0, luma: 0 }, | |
| fx: { mediaType: null, video: null, image: null, audioEl: null, width: 1280, height: 720 }, | |
| filters: [], presets: JSON.parse(localStorage.getItem('vfx_presets') || '[]'), | |
| history: JSON.parse(localStorage.getItem('vfx_history') || '{}'), | |
| calcTarget: null, triggerMode: 'AUTO' | |
| }; | |
| // ========================================== | |
| // UTILITY | |
| // ========================================== | |
| function toast(msg) { | |
| const el = document.getElementById('toast'); | |
| document.getElementById('toast-msg').textContent = msg; | |
| el.classList.add('show'); | |
| clearTimeout(el._tid); | |
| el._tid = setTimeout(() => el.classList.remove('show'), 2500); | |
| } | |
| function $(id) { return document.getElementById(id); } | |
| function fitCanvas(c) { | |
| const p = c.parentElement; | |
| if (!p) return; | |
| c.width = p.clientWidth; | |
| c.height = p.clientHeight; | |
| } | |
| // ========================================== | |
| // MODE SWITCHING | |
| // ========================================== | |
| function setMode(m) { | |
| S.mode = m; | |
| document.querySelectorAll('.mode-btn').forEach(b => b.classList.remove('active')); | |
| const btn = $('btn-' + m); | |
| if (btn) btn.classList.add('active'); | |
| document.querySelectorAll('.mode-content').forEach(el => el.classList.add('hidden')); | |
| const panel = $('mode-' + m); | |
| if (panel) panel.classList.remove('hidden'); | |
| $('currentMode').textContent = m.toUpperCase(); | |
| } | |
| function toggleRunning() { | |
| S.running = !S.running; | |
| const btn = $('btnToggle'); | |
| btn.innerHTML = S.running ? '<i class="fa-solid fa-pause"></i> <span class="hide-mobile">PAUSE</span>' : '<i class="fa-solid fa-play"></i> <span class="hide-mobile">RUN</span>'; | |
| } | |
| // ========================================== | |
| // AUDIO ENGINE | |
| // ========================================== | |
| function initAudio() { | |
| if (S.audio.ctx) return; | |
| try { | |
| S.audio.ctx = new (window.AudioContext || window.webkitAudioContext)(); | |
| S.audio.analyser = S.audio.ctx.createAnalyser(); | |
| S.audio.analyser.fftSize = 256; | |
| S.audio.data = new Uint8Array(S.audio.analyser.frequencyBinCount); | |
| } catch(e) { console.warn('Audio init failed:', e); } | |
| } | |
| function updateAudio() { | |
| if (!S.audio.analyser || !S.audio.data) return; | |
| S.audio.analyser.getByteFrequencyData(S.audio.data); | |
| const avg = (s, e) => { let sum = 0; for (let i = s; i < e; i++) sum += S.audio.data[i]; return (sum / (e - s)) / 255; }; | |
| S.audio.bass = avg(0, 10); | |
| S.audio.mid = avg(11, 60); | |
| S.audio.high = avg(61, 120); | |
| } | |
| // ========================================== |