/* global THREE, feather */ class TimeMachine { constructor() { this.kappa = 1.273; this.now = Date.now(); this.targetYear = 1985; this.scene = new THREE.Scene(); this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }); this.torus = null; this.particles = null; this.clock = new THREE.Clock(); // TOPOLOGICAL MAP STATE this.timewaveCanvas = document.getElementById('timewave-canvas'); this.timewaveCtx = this.timewaveCanvas.getContext('2d'); this.eschatonDistance = 100; // % this.semanticQubits = ['concrete', 'fear', 'Giza pyramid', 'Mother', 'LOVE', 'JUNG', 'THE BROKEN GUITAR', 'Ω-HONK-DODECA', 'Canine-Olfactory-Timeline']; this.currentSemantic = 0; this.lithificationPressure = 0; this.concrescenceTriggered = false; // ENTANGLEMENT & GHOST CHAT this.isEntangled = false; this.memoryAnchors = JSON.parse(localStorage.getItem('chronoMemory') || '[]'); // NEW: Hat-Man Spectral API this.hatManAPI = new HatManDiracAPI(); // PHAROS INTEGRATION this.pharos = new PharosInterface(); this.pharos.init(); } init() { const container = document.getElementById('torus-container'); this.renderer.setSize(window.innerWidth, window.innerHeight); this.renderer.setPixelRatio(window.devicePixelRatio); container.appendChild(this.renderer.domElement); this.scene.background = null; // Lighting const ambient = new THREE.AmbientLight(0xffffff, 0.4); this.scene.add(ambient); const point = new THREE.PointLight(0x4f46e5, 1.2, 100); point.position.set(10, 15, 10); this.scene.add(point); // Torus const geometry = new THREE.TorusGeometry(10, 3.5, 16, 100); const material = new THREE.MeshStandardMaterial({ color: 0x6366f1, metalness: 0.7, roughness: 0.3, wireframe: true, }); this.torus = new THREE.Mesh(geometry, material); this.scene.add(this.torus); // Particle trails (past+future) const N = 1200; const vertices = new Float32Array(N * 3); for (let i = 0; i < N; i++) { const [x, y, z] = this.torusPosition(Math.random() * Math.PI * 2, Math.random() * Math.PI * 2, 11.5); vertices[i * 3] = x; vertices[i * 3 + 1] = y; vertices[i * 3 + 2] = z; } const geo = new THREE.BufferGeometry(); geo.setAttribute('position', new THREE.BufferAttribute(vertices, 3)); const mat = new THREE.PointsMaterial({ size: 0.12, color: 0xec4899, blending: THREE.AdditiveBlending, transparent: true, opacity: 0.7, }); this.particles = new THREE.Points(geo, mat); this.scene.add(this.particles); this.camera.position.set(0, 8, 30); this.camera.lookAt(0, 0, 0); this.animate(); this.bindUI(); this.loadAnchors(); this.initTimewaveGraph(); this.startTopologicalAcceleration(); this.initHatManEndpoint(); torusPosition(u, v, scale) { return [ scale * Math.cos(u) * (3 + Math.cos(v)), scale * Math.sin(v), scale * Math.sin(u) * (3 + Math.cos(v)), ]; } animate() { requestAnimationFrame(() => this.animate()); const t = this.clock.getElapsedTime(); const scrollSpeed = Math.abs(window.lastWheelDelta || 0); const k = Math.max(1.0, Math.min(2.0, 1.273 + scrollSpeed * 0.0005)); this.kappa = k; this.torus.rotation.x = t * 0.1 * this.kappa; this.torus.rotation.y = t * 0.15 * this.kappa; this.particles.rotation.x = t * 0.05; this.particles.rotation.z = t * 0.1; // TOPOLOGICAL SHEARING: hallway geometry failure if (this.eschatonDistance < 20) { this.torus.rotation.z = Math.sin(t * 10) * 0.1; this.particles.rotation.y = Math.sin(t * 15) * 0.2; } // Golden spiral anchors if (this.memoryAnchors.length) { this.memoryAnchors.forEach((m) => { const angle = ((parseInt(m.year) % 100) / 100) * 2 * Math.PI; const spiralU = angle * (1 + Math.sqrt(5)) / (2 * Math.PI); const [x, y, z] = this.torusPosition(spiralU, angle, 12.5); if (m.dot) { m.dot.position.set(x, y, z); m.dot.material.opacity = Math.max(0.3, Math.sin(t * 2 + m.year) * 0.5 + 0.5); } }); } this.renderer.render(this.scene, this.camera); this.updateTimewaveGraph(); this.updateSemanticQubit(); this.updateLithification(); this.checkConcrescence(); } bindUI() { const kappaSlider = document.getElementById('kappa-slider'); const kappaValue = document.getElementById('kappa-value'); const yearInput = document.getElementById('year-input'); const navBtn = document.getElementById('nav-year-btn'); const voiceBtn = document.getElementById('voice-btn'); const anchorBtn = document.getElementById('anchor-btn'); const memoryInput = document.getElementById('memory-input'); const paradoxModal = document.getElementById('paradox-modal'); const paradoxClose = document.getElementById('paradox-close'); const chatInput = document.getElementById('chat-input'); const chatSend = document.getElementById('chat-send'); const toggleEntangle = document.getElementById('toggle-entangle'); const chatBox = document.getElementById('entangled-messages'); const hatManBtn = document.getElementById('hat-man-btn'); window.lastWheelDelta = 0; window.addEventListener('wheel', (e) => { window.lastWheelDelta = e.deltaY; this.kappa = Math.max(1.0, Math.min(2.0, 1.273 + Math.abs(window.lastWheelDelta) * 0.0005)); kappaSlider.value = this.kappa.toFixed(3); kappaValue.textContent = this.kappa.toFixed(3); yearInput.value = Math.round(1970 + (parseInt(yearInput.value) - 1970) / (this.kappa / 1.273)); document.getElementById('year-label').textContent = yearInput.value; document.getElementById('status').textContent = `κ = ${this.kappa.toFixed(3)} • Scroll-Dilated`; // ACCELERATE ESCHATON this.eschatonDistance = Math.max(0, this.eschatonDistance - 0.5); document.getElementById('eschaton-value').textContent = this.eschatonDistance.toFixed(1) + '%'; document.getElementById('eschaton-fill').style.width = (100 - this.eschatonDistance) + '%'; if (this.eschatonDistance <= 0 && !this.concrescenceTriggered) { this.triggerConcrescence(); } if (this.kappa > 1.99) { document.getElementById('paradox-message').textContent = "Novelty Overflow: Too much scrolling. The universe is rebooting."; paradoxModal.classList.remove('hidden'); paradoxModal.classList.add('grid'); setTimeout(() => { this.kappa = 1.273; kappaSlider.value = 1.273; kappaValue.textContent = 1.273; yearInput.value = 1985; paradoxModal.classList.add('hidden'); paradoxModal.classList.remove('grid'); }, 2200); } this.updateEntropy(); }); kappaSlider.addEventListener('input', () => { this.kappa = parseFloat(kappaSlider.value); kappaValue.textContent = this.kappa.toFixed(3); this.updateEntropy(); }); navBtn.addEventListener('click', () => { const y = parseInt(yearInput.value); if (y === 1985) { this.showParadox('Error 418: Temporal Conflict. Your existence is now read-only.'); } else { this.transitionYear(y); } }); voiceBtn.addEventListener('click', () => { if (!('webkitSpeechRecognition' in window)) { alert('Voice requires Chrome.'); return; } const rec = new webkitSpeechRecognition(); rec.lang = 'en-US'; rec.interimResults = false; rec.maxAlternatives = 1; rec.start(); document.getElementById('voice-label').textContent = 'Listening…'; rec.onresult = (e) => { const transcript = e.results[0][0].transcript.trim(); const match = transcript.match(/\b\d{4}\b/); if (match) { this.transitionYear(parseInt(match[0])); } else if (/summer of love/i.test(transcript)) { this.transitionYear(1967); if (window.isSpotifyReady) { window.playSpotifyTrack('4kC4z6X9t0jQnwYIKKfO1F'); } } document.getElementById('voice-label').textContent = 'Done'; }; rec.onend = () => { document.getElementById('voice-label').textContent = 'Speak'; }; }); anchorBtn.addEventListener('click', () => { const text = memoryInput.value.trim(); if (!text) return; const m = { year: yearInput.value, text, id: Date.now() }; this.memoryAnchors.push(m); localStorage.setItem('chronoMemory', JSON.stringify(this.memoryAnchors)); this.placeAnchor(m); memoryInput.value = ''; }); paradoxClose.addEventListener('click', () => { paradoxModal.classList.add('hidden'); paradoxModal.classList.remove('grid'); }); chatSend.addEventListener('click', () => { if (!chatInput.value.trim()) return; this.sendGhostMessage(chatInput.value); chatInput.value = ''; }); toggleEntangle.addEventListener('click', () => { this.isEntangled = !this.isEntangled; toggleEntangle.classList.toggle('border-indigo-500', !this.isEntangled); toggleEntangle.classList.toggle('bg-indigo-600/20', !this.isEntangled); toggleEntangle.classList.toggle('border-green-400', this.isEntangled); toggleEntangle.classList.toggle('bg-green-500/20', this.isEntangled); toggleEntangle.textContent = this.isEntangled ? 'Disentangle' : 'Entangle'; if (this.isEntangled) { toggleEntangle.classList.add('pulse-entangle'); } else { toggleEntangle.classList.remove('pulse-entangle'); } if (this.isEntangled) { // Broadcast to other local tabs via storage event localStorage.setItem('entangled-msg', JSON.stringify({ type: 'entangle', id: Math.random() })); } }); window.addEventListener('storage', (e) => { if (e.key === 'entangled-msg') { const data = JSON.parse(e.newValue); if (data.type === 'chat') { this.receiveGhostMessage(data.msg); } } }); // Hat-Man API trigger hatManBtn.addEventListener('click', () => { this.hatManAPI.resolveHardProblem({ qualia: memoryInput.value || 'undefined fear vector', heartrate: 120 + Math.floor(Math.random() * 40) }); }); window.addEventListener('resize', () => { this.camera.aspect = window.innerWidth / window.innerHeight; this.camera.updateProjectionMatrix(); this.renderer.setSize(window.innerWidth, window.innerHeight); }); // Spotify API hook (mock) window.isSpotifyReady = true; window.playSpotifyTrack = (id) => { console.log('Playing Spotify Track:', id); }; } transitionYear(y) { document.getElementById('year-label').textContent = y; document.getElementById('year-input').value = y; const h3 = document.createElement('h3'); h3.className = 'fixed inset-0 flex items-center justify-center text-6xl font-black text-indigo-400 pointer-events-none z-40 chrono-enter'; h3.textContent = y; document.body.appendChild(h3); setTimeout(() => h3.remove(), 1000); this.updateEntropy(); } initHatManEndpoint() { // Hat-Man spectral endpoint UI const panel = document.createElement('section'); panel.id = 'hat-man-panel'; panel.className = 'absolute top-6 right-6 pointer-events-auto bg-gray-900/70 backdrop-blur border border-red-500/40 rounded-2xl p-4 max-w-xs hidden'; panel.innerHTML = `