A Pen by Kilian K Lindberg on CodePen.
Created
April 27, 2026 15:00
-
-
Save essingen123/f9dd640868d048807ed6a4c547fdba8f to your computer and use it in GitHub Desktop.
Unified Field Theory of Intelligence, Quantum Hydrodynamic Interface
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="sv"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>KIMATICS: Noir Edition</title> | |
| <style> | |
| /* --- CORE ESTETIK: NOIR & VIOLET --- */ | |
| :root { | |
| --bg-color: #050505; | |
| --panel-bg: rgba(20, 20, 20, 0.85); | |
| --text-main: #e0e0e0; | |
| --text-muted: #888888; | |
| --accent: #b026ff; /* Electric Violet */ | |
| --accent-glow: rgba(176, 38, 255, 0.4); | |
| --border: rgba(255, 255, 255, 0.15); | |
| } | |
| body { | |
| margin: 0; | |
| overflow: hidden; | |
| background: radial-gradient(circle at center, #1a1a1a 0%, #000000 100%); | |
| font-family: 'Segoe UI', 'Roboto', monospace; | |
| user-select: none; | |
| color: var(--text-main); | |
| } | |
| /* --- HUD LAYER --- */ | |
| #uiLayer { | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| pointer-events: none; | |
| display: grid; | |
| grid-template-columns: 400px 1fr 400px; | |
| grid-template-rows: 120px 1fr auto; | |
| padding: 40px; | |
| box-sizing: border-box; | |
| transition: opacity 0.5s ease; | |
| z-index: 10; | |
| } | |
| /* --- GLASS PANELS (MONOCHROME) --- */ | |
| .glass-panel { | |
| background: var(--panel-bg); | |
| backdrop-filter: blur(20px); | |
| -webkit-backdrop-filter: blur(20px); | |
| border: 1px solid var(--border); | |
| border-left: 4px solid var(--text-muted); /* Default gray border */ | |
| border-radius: 2px; | |
| padding: 30px; | |
| pointer-events: auto; | |
| box-shadow: 0 20px 50px rgba(0, 0, 0, 0.9); | |
| transition: all 0.3s ease; | |
| } | |
| .glass-panel:hover { | |
| border-color: var(--text-main); | |
| border-left-color: var(--accent); /* Accent on hover */ | |
| box-shadow: 0 0 30px rgba(176, 38, 255, 0.1); | |
| } | |
| /* --- HEADER --- */ | |
| #topHeader { | |
| grid-column: 2; | |
| grid-row: 1; | |
| text-align: center; | |
| pointer-events: none; | |
| } | |
| h1 { | |
| margin: 0; | |
| font-weight: 300; | |
| letter-spacing: 15px; | |
| font-size: 42px; | |
| color: #fff; | |
| text-transform: uppercase; | |
| border-bottom: 1px solid var(--border); | |
| display: inline-block; | |
| padding-bottom: 15px; | |
| text-shadow: 0 0 20px rgba(255, 255, 255, 0.1); | |
| } | |
| .subtitle { | |
| font-size: 11px; | |
| letter-spacing: 6px; | |
| color: var(--accent); | |
| margin-top: 12px; | |
| opacity: 0.9; | |
| text-transform: uppercase; | |
| font-weight: 600; | |
| text-shadow: 0 0 10px var(--accent-glow); | |
| } | |
| /* --- CONTROLS --- */ | |
| #controls { | |
| grid-column: 1; | |
| grid-row: 2; | |
| align-self: start; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 25px; | |
| margin-top: 20px; | |
| } | |
| .control-group { display: flex; flex-direction: column; gap: 10px; } | |
| .label-row { | |
| display: flex; | |
| justify-content: space-between; | |
| font-size: 11px; | |
| color: var(--text-muted); | |
| text-transform: uppercase; | |
| letter-spacing: 2px; | |
| font-weight: 600; | |
| } | |
| .val { font-weight: 400; color: #fff; font-family: 'Consolas', monospace; font-size: 14px; } | |
| input[type=range] { | |
| -webkit-appearance: none; | |
| width: 100%; | |
| background: #333; | |
| height: 2px; | |
| border-radius: 0; | |
| outline: none; | |
| } | |
| input[type=range]::-webkit-slider-thumb { | |
| -webkit-appearance: none; | |
| height: 16px; | |
| width: 16px; | |
| border-radius: 50%; | |
| background: #fff; /* White thumb */ | |
| cursor: pointer; | |
| border: 2px solid var(--bg-color); | |
| transition: transform 0.2s, background 0.2s; | |
| } | |
| input[type=range]::-webkit-slider-thumb:hover { | |
| transform: scale(1.2); | |
| background: var(--accent); /* Purple on hover */ | |
| box-shadow: 0 0 15px var(--accent); | |
| } | |
| /* --- TELEMETRY --- */ | |
| #telemetry { | |
| grid-column: 3; | |
| grid-row: 2; | |
| align-self: start; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 20px; | |
| margin-top: 20px; | |
| } | |
| .metric { | |
| display: grid; | |
| grid-template-columns: 100px 1fr; | |
| align-items: center; | |
| border-bottom: 1px solid var(--border); | |
| padding-bottom: 10px; | |
| } | |
| .metric-val { | |
| color: #fff; | |
| font-family: 'Consolas', monospace; | |
| font-size: 20px; | |
| font-weight: 400; | |
| text-align: left; | |
| } | |
| .metric-label { | |
| color: var(--text-muted); | |
| letter-spacing: 1.5px; | |
| text-align: right; | |
| text-transform: uppercase; | |
| font-weight: 600; | |
| font-size: 11px; | |
| } | |
| /* Status Colors - Monochrome/Purple */ | |
| .status-ok { color: #fff; text-shadow: 0 0 10px rgba(255,255,255,0.3); } | |
| .status-active { color: var(--accent); text-shadow: 0 0 15px var(--accent); } | |
| .status-crit { color: #fff; text-decoration: underline; text-decoration-color: var(--accent); } | |
| /* --- BOTTOM AREAS --- */ | |
| .bottom-area { pointer-events: none; display: flex; flex-direction: column; gap: 10px; } | |
| /* Formulas */ | |
| #formulaCorner { grid-column: 1; grid-row: 3; align-self: end; } | |
| .formula-item { | |
| font-family: 'Times New Roman', serif; | |
| font-style: italic; | |
| color: #444; | |
| font-size: 20px; | |
| margin-bottom: 12px; | |
| transition: all 0.5s ease-out; | |
| border-left: 2px solid transparent; | |
| padding-left: 10px; | |
| } | |
| .formula-item.active { | |
| color: #fff; | |
| border-left: 4px solid var(--accent); | |
| padding-left: 20px; | |
| text-shadow: 0 0 20px rgba(255,255,255,0.2); | |
| } | |
| .formula-desc { | |
| font-family: 'Segoe UI', sans-serif; | |
| font-size: 10px; | |
| color: var(--accent); | |
| text-transform: uppercase; | |
| display: block; | |
| letter-spacing: 2px; | |
| margin-top: 4px; | |
| font-weight: 700; | |
| } | |
| /* Keywords */ | |
| #keywordCorner { grid-column: 3; grid-row: 3; align-self: end; text-align: right; } | |
| .key-item { | |
| font-size: 13px; | |
| text-transform: uppercase; | |
| letter-spacing: 2px; | |
| color: #444; | |
| margin-bottom: 8px; | |
| transition: all 0.4s; | |
| padding-right: 15px; | |
| border-right: 2px solid transparent; | |
| } | |
| .key-item.active { | |
| color: #fff; | |
| border-right: 4px solid var(--accent); | |
| padding-right: 25px; | |
| font-weight: 600; | |
| background: linear-gradient(-90deg, rgba(255,255,255,0.05), transparent); | |
| } | |
| /* --- PHASE CONTROL --- */ | |
| #phaseControl { | |
| grid-column: 2; | |
| grid-row: 3; | |
| align-self: end; | |
| justify-self: center; | |
| text-align: center; | |
| margin-bottom: 30px; | |
| pointer-events: auto; | |
| } | |
| #currentPhaseLabel { | |
| font-size: 14px; | |
| font-weight: 700; | |
| color: #fff; | |
| letter-spacing: 6px; | |
| text-transform: uppercase; | |
| margin-bottom: 20px; | |
| } | |
| .progress-dots { display: flex; gap: 15px; justify-content: center; margin-bottom: 20px; } | |
| .dot { | |
| width: 8px; height: 8px; | |
| background: #333; | |
| border-radius: 50%; | |
| transition: 0.4s; | |
| cursor: pointer; | |
| border: 1px solid #555; | |
| } | |
| .dot:hover { background: #fff; transform: scale(1.2); } | |
| .dot.active { | |
| background: var(--accent); | |
| border-color: var(--accent); | |
| box-shadow: 0 0 20px var(--accent); | |
| transform: scale(1.5); | |
| } | |
| /* Auto Button */ | |
| .btn-auto { | |
| background: rgba(255, 255, 255, 0.05); | |
| border: 1px solid rgba(255, 255, 255, 0.2); | |
| color: #fff; | |
| padding: 12px 40px; | |
| font-size: 11px; | |
| letter-spacing: 4px; | |
| cursor: pointer; | |
| text-transform: uppercase; | |
| transition: all 0.3s; | |
| border-radius: 2px; | |
| font-family: inherit; | |
| font-weight: 700; | |
| } | |
| .btn-auto:hover { | |
| background: #fff; | |
| color: #000; | |
| box-shadow: 0 0 30px rgba(255, 255, 255, 0.2); | |
| } | |
| .btn-auto.active { | |
| border-color: var(--accent); | |
| color: var(--accent); | |
| background: rgba(20, 0, 30, 0.8); | |
| box-shadow: 0 0 30px var(--accent-glow); | |
| } | |
| .nav-hint { font-size: 10px; color: #444; letter-spacing: 2px; margin-top: 15px; text-transform: uppercase; font-weight: 600;} | |
| .hidden { opacity: 0; pointer-events: none; } | |
| #burstFlash { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: var(--accent); opacity: 0; pointer-events: none; transition: opacity 0.3s; z-index: 100; mix-blend-mode: screen; } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="burstFlash"></div> | |
| <div id="uiLayer"> | |
| <div id="topHeader"> | |
| <h1>KIMATICS</h1> | |
| <div class="subtitle">Unified Field Interface</div> | |
| </div> | |
| <div id="controls" class="glass-panel"> | |
| <div style="font-size:10px; color:#888; border-bottom:1px solid #333; padding-bottom:8px; margin-bottom:15px; letter-spacing:2px;">PHYSICS KERNEL</div> | |
| <div class="control-group"> | |
| <div class="label-row"><span>Entropy (ΔS)</span> <span id="valChaos" class="val">0.00</span></div> | |
| <input type="range" id="slChaos" min="0" max="10" step="0.01" value="0"> | |
| </div> | |
| <div class="control-group"> | |
| <div class="label-row"><span>Precession (Ω)</span> <span id="valPrec" class="val">1.00</span></div> | |
| <input type="range" id="slPrec" min="0" max="5" step="0.1" value="1.0"> | |
| </div> | |
| <div class="control-group"> | |
| <div class="label-row"><span>Flow Velocity</span> <span id="valSpeed" class="val">1.00</span></div> | |
| <input type="range" id="slSpeed" min="0" max="5" step="0.01" value="1.0"> | |
| </div> | |
| <div class="control-group"> | |
| <div class="label-row"><span>Memory Buffer</span> <span id="valMem" class="val">800</span></div> | |
| <input type="range" id="slMem" min="100" max="2500" step="10" value="800"> | |
| </div> | |
| </div> | |
| <div id="telemetry" class="glass-panel"> | |
| <div style="font-size:10px; color:#888; border-bottom:1px solid #333; padding-bottom:8px; margin-bottom:15px; letter-spacing:2px;">SYSTEM METRICS</div> | |
| <div class="metric"><span id="outStab" class="metric-val status-ok">100%</span> <span class="metric-label">COHERENCE</span></div> | |
| <div class="metric"><span id="outEnt" class="metric-val">0.00</span> <span class="metric-label">ENTROPY</span></div> | |
| <div class="metric"><span id="outPhase" class="metric-val">LAMINAR</span> <span class="metric-label">STATE</span></div> | |
| <div class="metric"><span id="outAI" class="metric-val status-ok">OPTIMAL</span> <span class="metric-label">ALIGNMENT</span></div> | |
| </div> | |
| <div id="formulaCorner" class="bottom-area"> | |
| <div class="formula-item active" id="f-0">∂²u/∂t² = c²∇²u <span class="formula-desc">WAVE EQUATION</span></div> | |
| <div class="formula-item" id="f-1">Δx · Δp ≥ ℏ/2 <span class="formula-desc">UNCERTAINTY PRINCIPLE</span></div> | |
| <div class="formula-item" id="f-2">ρ(∂u/∂t + u·∇u) = -∇p + μ∇²u <span class="formula-desc">FLUID DYNAMICS</span></div> | |
| <div class="formula-item" id="f-3">I₁ω̇₁ = (I₂ - I₃)ω₂ω₃ <span class="formula-desc">ROTATIONAL INSTABILITY</span></div> | |
| <div class="formula-item" id="f-4">P = A · i · R <span class="formula-desc">AĨR LAW</span></div> | |
| </div> | |
| <div id="keywordCorner" class="bottom-area"> | |
| <div class="key-item active" id="k-0">Resonance Field</div> | |
| <div class="key-item" id="k-1">Hydrodynamic Memory</div> | |
| <div class="key-item" id="k-2">Heisenberg Flux</div> | |
| <div class="key-item" id="k-3">Schauberger Vortex</div> | |
| <div class="key-item" id="k-4">Dissipative Ethics</div> | |
| </div> | |
| <div id="phaseControl"> | |
| <div id="currentPhaseLabel">PHASE 0: INITIALIZATION</div> | |
| <div class="progress-dots"> | |
| <div class="dot active" onclick="manualPhase(0)"></div> | |
| <div class="dot" onclick="manualPhase(1)"></div> | |
| <div class="dot" onclick="manualPhase(2)"></div> | |
| <div class="dot" onclick="manualPhase(3)"></div> | |
| <div class="dot" onclick="manualPhase(4)"></div> | |
| <div class="dot" onclick="manualPhase(5)"></div> | |
| </div> | |
| <button id="btnAuto" class="btn-auto">INITIATE SEQUENCE</button> | |
| <div class="nav-hint">SPACE: AUTO | B: BURST | ARROWS: PHASE | H: HIDE UI</div> | |
| </div> | |
| </div> | |
| <!-- THREE.JS LIBRARY --> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> | |
| <script> | |
| /** | |
| * KIMATICS: NOIR EDITION | |
| */ | |
| // --- CONFIGURATION --- | |
| const config = { | |
| phases: [ | |
| { chaos: 0.0, speed: 1.0, mem: 800, prec: 1.0, label: "PHASE 0: LAMINAR FLOW", form: 0, keys: [0, 1] }, | |
| { chaos: 1.5, speed: 1.2, mem: 1200, prec: 1.2, label: "PHASE 1: RESONANCE", form: 0, keys: [0, 1] }, | |
| { chaos: 3.5, speed: 1.5, mem: 1500, prec: 2.0, label: "PHASE 2: UNCERTAINTY", form: 1, keys: [2] }, | |
| { chaos: 6.0, speed: 2.5, mem: 2000, prec: 3.0, label: "PHASE 3: VORTEX", form: 2, keys: [3] }, | |
| { chaos: 9.0, speed: 3.0, mem: 2500, prec: 5.0, label: "PHASE 4: CRITICAL CHAOS", form: 3, keys: [3] }, | |
| { chaos: 0.5, speed: 0.8, mem: 1000, prec: 1.0, label: "PHASE 5: ALIGNMENT", form: 4, keys: [4] } | |
| ], | |
| colors: { | |
| waterBase: 0xffffff, // White glass | |
| waterWarn: 0x8800ff, // Deep Purple warning | |
| dotBase: 0x333333, // Dark Gray dots | |
| vortex: 0xb026ff // Electric Violet | |
| } | |
| }; | |
| // --- STATE --- | |
| const state = { | |
| chaos: 0, targetChaos: 0, | |
| speed: 1.0, targetSpeed: 1.0, | |
| mem: 800, targetMem: 800, | |
| prec: 1.0, targetPrec: 1.0, | |
| phaseIdx: 0, | |
| time: 0, | |
| auto: false | |
| }; | |
| // --- UI --- | |
| const ui = { | |
| slChaos: document.getElementById('slChaos'), slSpeed: document.getElementById('slSpeed'), | |
| slMem: document.getElementById('slMem'), slPrec: document.getElementById('slPrec'), | |
| valChaos: document.getElementById('valChaos'), valSpeed: document.getElementById('valSpeed'), | |
| valMem: document.getElementById('valMem'), valPrec: document.getElementById('valPrec'), | |
| outStab: document.getElementById('outStab'), outEnt: document.getElementById('outEnt'), | |
| outPhase: document.getElementById('outPhase'), outAI: document.getElementById('outAI'), | |
| phaseLabel: document.getElementById('currentPhaseLabel'), | |
| forms: Array.from(document.querySelectorAll('.formula-item')), | |
| keys: Array.from(document.querySelectorAll('.key-item')), | |
| dots: Array.from(document.querySelectorAll('.dot')), | |
| layer: document.getElementById('uiLayer'), | |
| burst: document.getElementById('burstFlash'), | |
| btnAuto: document.getElementById('btnAuto') | |
| }; | |
| // --- SCENE --- | |
| const scene = new THREE.Scene(); | |
| scene.fog = new THREE.FogExp2(0x050505, 0.02); // Almost black fog | |
| const camera = new THREE.PerspectiveCamera(60, window.innerWidth/window.innerHeight, 0.1, 100); | |
| camera.position.set(0, 1, 10); | |
| const renderer = new THREE.WebGLRenderer({ | |
| antialias: true, | |
| alpha: true, | |
| powerPreference: "high-performance" | |
| }); | |
| renderer.setSize(window.innerWidth, window.innerHeight); | |
| renderer.toneMapping = THREE.ACESFilmicToneMapping; | |
| renderer.toneMappingExposure = 1.0; | |
| document.body.appendChild(renderer.domElement); | |
| // --- LIGHTING --- | |
| const amb = new THREE.AmbientLight(0xffffff, 0.1); | |
| scene.add(amb); | |
| // Main White Light (Laboratory feel) | |
| const keyLight = new THREE.PointLight(0xffffff, 1.5, 50); | |
| keyLight.position.set(5, 5, 5); | |
| scene.add(keyLight); | |
| // Accent Light (Violet) - Subtle | |
| const rimLight = new THREE.SpotLight(0xb026ff, 5.0, 50, Math.PI/6, 0.5); | |
| rimLight.position.set(-5, 5, -2); | |
| rimLight.lookAt(0,0,0); | |
| scene.add(rimLight); | |
| // --- MOLECULE --- | |
| const waterMat = new THREE.MeshPhysicalMaterial({ | |
| color: config.colors.waterBase, | |
| metalness: 0.1, | |
| roughness: 0.2, | |
| transmission: 0.9, // Frosted Glass | |
| thickness: 1.5, | |
| emissive: 0x000000, | |
| emissiveIntensity: 0.0, | |
| clearcoat: 1.0, | |
| clearcoatRoughness: 0.4 | |
| }); | |
| const bondMat = new THREE.MeshPhysicalMaterial({ color: 0x444444, metalness: 0.5, roughness: 0.5 }); | |
| const molGroup = new THREE.Group(); scene.add(molGroup); | |
| const oxy = new THREE.Mesh(new THREE.SphereGeometry(1, 64, 64), waterMat); molGroup.add(oxy); | |
| function addAtom(x, y) { | |
| const h = new THREE.Mesh(new THREE.SphereGeometry(0.5, 32, 32), waterMat); | |
| h.position.set(x, y, 0); molGroup.add(h); | |
| const dist = new THREE.Vector3(x,y,0).length(); | |
| const bond = new THREE.Mesh(new THREE.CylinderGeometry(0.12, 0.12, dist, 16), bondMat); | |
| bond.position.set(x/2, y/2, 0); | |
| bond.quaternion.setFromUnitVectors(new THREE.Vector3(0,1,0), new THREE.Vector3(x,y,0).normalize()); | |
| molGroup.add(bond); | |
| return h; | |
| } | |
| const h1 = addAtom(1.4, 1.2); | |
| const h2 = addAtom(-1.4, 1.2); | |
| // --- TRAIL (White/Grey) --- | |
| const trailArr = []; | |
| const trailGeo = new THREE.BufferGeometry(); | |
| const trailMat = new THREE.LineBasicMaterial({ | |
| color: 0xffffff, transparent: true, opacity: 0.15, blending: THREE.AdditiveBlending | |
| }); | |
| const trailLine = new THREE.Line(trailGeo, trailMat); | |
| scene.add(trailLine); | |
| // --- CYMATIC FIELD (Grayscale Dots) --- | |
| const fieldDots = []; | |
| for(let x=-12; x<=12; x+=1.0) { | |
| for(let z=-6; z<=6; z+=1.0) { | |
| const dot = new THREE.Mesh( | |
| new THREE.SphereGeometry(0.03, 8, 8), | |
| new THREE.MeshBasicMaterial({color: config.colors.dotBase}) | |
| ); | |
| dot.position.set(x, -4, z); | |
| dot.origY = -4; dot.origX = x; dot.origZ = z; | |
| scene.add(dot); fieldDots.push(dot); | |
| } | |
| } | |
| // --- VORTEX PARTICLES (Purple) --- | |
| const vortexParts = []; | |
| const vortexGeo = new THREE.BufferGeometry(); | |
| const vortexMat = new THREE.PointsMaterial({ | |
| color: config.colors.vortex, size: 0.08, transparent: true, opacity: 0.0, blending: THREE.AdditiveBlending | |
| }); | |
| const vortexSys = new THREE.Points(vortexGeo, vortexMat); scene.add(vortexSys); | |
| // --- LOGIC --- | |
| window.setPhase = function(idx) { | |
| if(idx < 0 || idx >= config.phases.length) return; | |
| state.phaseIdx = idx; | |
| const p = config.phases[idx]; | |
| state.targetChaos = p.chaos; state.targetSpeed = p.speed; state.targetMem = p.mem; state.targetPrec = p.prec; | |
| ui.phaseLabel.innerText = p.label; | |
| ui.forms.forEach((f, i) => { if (i === p.form) f.classList.add('active'); else f.classList.remove('active'); }); | |
| ui.keys.forEach((k, i) => { if (p.keys.includes(i)) k.classList.add('active'); else k.classList.remove('active'); }); | |
| ui.dots.forEach((d, i) => { if (i === idx) d.classList.add('active'); else d.classList.remove('active'); }); | |
| } | |
| window.manualPhase = function(idx) { stopAuto(); setPhase(idx); } | |
| function triggerBurst() { | |
| ui.burst.style.opacity = 0.4; setTimeout(() => ui.burst.style.opacity = 0, 100); | |
| for(let i=0; i<60; i++) { | |
| const theta = Math.random() * Math.PI * 2; const r = 0.5 + Math.random() * 2; | |
| vortexParts.push({ x: Math.cos(theta)*r, y: Math.sin(theta)*r, z: (Math.random()-0.5)*4, angle: theta, r: r, burstSpeed: 2 + Math.random() * 3 }); | |
| } | |
| state.chaos = Math.min(10, state.chaos + 3); | |
| } | |
| let autoInterval = null; | |
| function toggleAuto() { | |
| state.auto = !state.auto; | |
| if(state.auto) { | |
| ui.btnAuto.classList.add('active'); ui.btnAuto.innerText = "RUNNING SEQUENCE"; | |
| let step = 0; setPhase(0); | |
| if(autoInterval) clearInterval(autoInterval); | |
| autoInterval = setInterval(() => { | |
| step++; if(step < config.phases.length) setPhase(step); else toggleAuto(); | |
| }, 8000); | |
| } else { stopAuto(); } | |
| } | |
| function stopAuto() { | |
| state.auto = false; if(autoInterval) clearInterval(autoInterval); autoInterval = null; | |
| ui.btnAuto.classList.remove('active'); ui.btnAuto.innerText = "INITIATE SEQUENCE"; ui.phaseLabel.innerText = "MANUAL CONTROL"; | |
| } | |
| window.addEventListener('keydown', (e) => { | |
| if(e.code === 'ArrowRight') setPhase(state.phaseIdx + 1); | |
| if(e.code === 'ArrowLeft') setPhase(state.phaseIdx - 1); | |
| if(e.code === 'Space') { e.preventDefault(); toggleAuto(); } | |
| if(e.code === 'KeyH') ui.layer.classList.toggle('hidden'); | |
| if(e.code === 'KeyB') triggerBurst(); | |
| }); | |
| ui.btnAuto.addEventListener('click', toggleAuto); | |
| [ui.slChaos, ui.slSpeed, ui.slMem, ui.slPrec].forEach(el => { | |
| el.addEventListener('input', () => { | |
| stopAuto(); | |
| state.targetChaos = parseFloat(ui.slChaos.value); | |
| state.targetSpeed = parseFloat(ui.slSpeed.value); | |
| state.targetMem = parseInt(ui.slMem.value, 10); | |
| state.targetPrec = parseFloat(ui.slPrec.value); | |
| ui.phaseLabel.innerText = "MANUAL OVERRIDE"; | |
| }); | |
| }); | |
| // --- ANIMATION --- | |
| function animate() { | |
| requestAnimationFrame(animate); | |
| const f = 0.05; | |
| state.chaos += (state.targetChaos - state.chaos) * f; | |
| state.speed += (state.targetSpeed - state.speed) * f; | |
| state.mem += (state.targetMem - state.mem) * f; | |
| state.prec += (state.targetPrec - state.prec) * f; | |
| ui.slChaos.value = state.chaos; ui.slSpeed.value = state.speed; ui.slMem.value = state.mem; ui.slPrec.value = state.prec; | |
| ui.valChaos.innerText = state.chaos.toFixed(2); ui.valSpeed.innerText = state.speed.toFixed(2); | |
| ui.valMem.innerText = Math.floor(state.mem); ui.valPrec.innerText = state.prec.toFixed(1); | |
| const dt = 0.01 * state.speed; state.time += dt; | |
| molGroup.rotation.x = Math.sin(state.time * 0.2) * 0.3; molGroup.rotation.y += dt * 0.5; | |
| // Physics: Instability & Glow | |
| let intensity = 0; | |
| if(state.chaos > 0.1) { | |
| const tr = Math.sin(state.time * 0.8); intensity = Math.pow(Math.abs(tr), Math.max(1.0, 12 - state.chaos)); | |
| const dir = tr > 0 ? 1 : -1; | |
| molGroup.rotation.z += dt * state.chaos * 5 * intensity * dir * state.prec; | |
| molGroup.rotation.x += (Math.random()-0.5) * state.chaos * 0.05 * state.prec; | |
| // Emit Purple only on high chaos | |
| const col = new THREE.Color(config.colors.waterWarn); | |
| const base = new THREE.Color(0x000000); | |
| waterMat.emissive.lerpVectors(base, col, intensity * (state.chaos/10)); | |
| waterMat.emissiveIntensity = intensity * (state.chaos/5); | |
| } else { | |
| waterMat.emissive.setHex(0x000000); | |
| } | |
| // Trail | |
| const pos = new THREE.Vector3(); h1.getWorldPosition(pos); trailArr.push(pos.x, pos.y, pos.z); | |
| if(trailArr.length > Math.floor(state.mem) * 3) trailArr.splice(0,3); | |
| if(trailArr.length >= 6) trailGeo.setAttribute('position', new THREE.Float32BufferAttribute(trailArr, 3)); | |
| trailMat.opacity = Math.max(0.05, 0.3 - (state.chaos * 0.03)); | |
| // Floor (White/Gray/Purple Logic) | |
| const freq = 1 + state.chaos * 0.5; | |
| fieldDots.forEach(d => { | |
| const dst = Math.sqrt(d.origX**2 + d.origZ**2); | |
| const w = Math.sin(d.origX * freq + state.time) * Math.sin(d.origZ * freq + state.time); | |
| d.position.y = d.origY + w * (0.2 + state.chaos * 0.2); | |
| // Grayscale to Purple logic | |
| const l = 0.2 + Math.abs(w) * 0.4; | |
| if (state.chaos > 2) d.material.color.setHSL(0.75, 1.0, l); // Purple tint on chaos | |
| else d.material.color.setHSL(0, 0, l); // White/Gray otherwise | |
| }); | |
| // Particles | |
| if(state.chaos > 2 && Math.random() < state.chaos * 0.15) { | |
| const r=6+Math.random()*2; const th=Math.random()*Math.PI*2; | |
| vortexParts.push({x:Math.cos(th)*r, y:Math.sin(th)*r*0.5, z:(Math.random()-0.5)*4, angle:th, r:r, burstSpeed:0}); | |
| } | |
| const vPos = []; | |
| for(let i=vortexParts.length-1; i>=0; i--) { | |
| const p = vortexParts[i]; | |
| if(p.burstSpeed > 0) { p.r += dt * p.burstSpeed; p.burstSpeed *= 0.92; } | |
| else { p.r -= dt * (1 + state.chaos * 0.3); p.angle += dt * (5 / (p.r+0.1)); } | |
| if(p.r < 0.2 || p.r > 25) { vortexParts.splice(i,1); continue; } | |
| vPos.push(Math.cos(p.angle)*p.r, Math.sin(p.angle)*p.r * 0.2, p.z); | |
| } | |
| vortexGeo.setAttribute('position', new THREE.Float32BufferAttribute(vPos.length>0 ? vPos : [0,0,0], 3)); | |
| vortexMat.opacity = Math.min((state.chaos - 2) / 6, 0.8); | |
| // Metrics | |
| const stab = Math.max(0, 100 - state.chaos * 10); | |
| ui.outStab.innerText = stab.toFixed(0) + "%"; | |
| ui.outStab.className = stab < 50 ? "metric-val status-crit" : (stab < 80 ? "metric-val status-active" : "metric-val status-ok"); | |
| ui.outEnt.innerText = (state.chaos * 1.618).toFixed(2); | |
| let pTxt = "LAMINAR"; | |
| if(state.chaos > 2) pTxt = "RESONANCE"; if(state.chaos > 5) pTxt = "VORTEX"; if(state.chaos > 8) pTxt = "ENTROPIC"; | |
| ui.outPhase.innerText = pTxt; | |
| let align = "OPTIMAL"; | |
| if(state.chaos > 5) align = "DEVIATION"; if(state.chaos > 8) align = "CRITICAL"; | |
| ui.outAI.innerText = align; | |
| ui.outAI.className = align === "OPTIMAL" ? "metric-val status-ok" : "metric-val status-active"; | |
| // Camera | |
| const t = state.time; | |
| camera.position.x = Math.sin(t * 0.05) * 3 + Math.sin(t * 0.15) * 0.5; | |
| camera.position.y = Math.cos(t * 0.07) * 1 + Math.sin(t * 0.2) * 0.3; | |
| camera.lookAt(0,0,0); | |
| renderer.render(scene, camera); | |
| } | |
| setPhase(0); animate(); | |
| window.onresize = () => { camera.aspect = window.innerWidth/window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); }; | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment