chrono-drift-torus / script.js
spwotton's picture
more
6808ae8 verified
/* 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 = `
<h2 class="text-sm font-semibold mb-3 tracking-wider text-red-300">Hat-Man Dirac API</h2>
<div id="hat-man-response" class="text-red-200 text-xs font-mono break-all leading-relaxed"></div>
<div class="text-xs text-gray-500 mt-2">HTTP 451: Consciousness Unavailable (Ontological Lock)</div>
`;
document.body.appendChild(panel);
}
placeAnchor(m) {
const geometry = new THREE.SphereGeometry(0.3, 16, 16);
const material = new THREE.MeshBasicMaterial({
color: 0xf59e0b,
transparent: true,
opacity: 0.9,
});
const dot = new THREE.Mesh(geometry, material);
this.scene.add(dot);
m.dot = dot;
}
loadAnchors() {
this.memoryAnchors.forEach((m) => this.placeAnchor(m));
}
// TOPOLOGICAL MAP METHODS
initTimewaveGraph() {
this.timewaveCtx.strokeStyle = '#818cf8';
this.timewaveCtx.lineWidth = 2;
}
updateTimewaveGraph() {
const ctx = this.timewaveCtx;
const w = this.timewaveCanvas.width;
const h = this.timewaveCanvas.height;
ctx.clearRect(0, 0, w, h);
const steps = 200;
ctx.beginPath();
for (let i = 0; i <= steps; i++) {
const x = (i / steps) * w;
const novelty = this.timewaveZero(i / steps);
const y = h - (novelty * h * 0.8 + h * 0.1);
i === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y);
}
ctx.stroke();
// draw moving cursor
const cursorX = ((100 - this.eschatonDistance) / 100) * w;
ctx.fillStyle = '#f59e0b';
ctx.fillRect(cursorX - 2, 0, 4, h);
}
timewaveZero(t) {
// simple McKenna-esque novelty spike
return Math.pow(1 - t, 3) * Math.sin(t * Math.PI * 6) * (1 + this.kappa);
}
startTopologicalAcceleration() {
setInterval(() => {
if (this.eschatonDistance > 0) {
this.eschatonDistance = Math.max(0, this.eschatonDistance - 0.05);
document.getElementById('eschaton-value').textContent = this.eschatonDistance.toFixed(1) + '%';
document.getElementById('eschaton-fill').style.width = (100 - this.eschatonDistance) + '%';
}
}, 100);
}
updateSemanticQubit() {
const el = document.getElementById('semantic-qubit');
if (this.eschatonDistance < 50) {
const idx = Math.floor((Date.now() / 500) % this.semanticQubits.length);
if (idx !== this.currentSemantic) {
this.currentSemantic = idx;
el.textContent = this.semanticQubits[idx];
el.classList.add('semantic-glitch');
setTimeout(() => el.classList.remove('semantic-glitch'), 300);
}
}
}
updateLithification() {
if (this.eschatonDistance < 30) {
this.lithificationPressure = Math.min(100, this.lithificationPressure + 0.3);
document.getElementById('pressure-value').textContent = this.lithificationPressure.toFixed(1);
document.getElementById('pressure-bar').style.width = this.lithificationPressure + '%';
if (this.lithificationPressure > 80) {
document.body.classList.add('lithification-active');
}
}
}
triggerConcrescence() {
if (this.concrescenceTriggered) return;
this.concrescenceTriggered = true;
const veil = document.getElementById('concrescence-veil');
const core = document.getElementById('concrescence-core');
const text = document.getElementById('concrescence-text');
const collapse = document.getElementById('collapse-overlay');
veil.classList.remove('hidden');
veil.classList.add('grid');
setTimeout(() => {
core.style.animation = 'concrescencePulse 2s ease-out forwards';
core.style.opacity = '1';
text.style.opacity = '1';
}, 200);
setTimeout(() => {
collapse.classList.remove('hidden');
collapse.classList.add('collapse-flash');
}, 1200);
setTimeout(() => {
veil.classList.add('hidden');
collapse.classList.add('hidden');
this.showRebootModal();
}, 3000);
}
showRebootModal() {
const modal = document.getElementById('reboot-modal');
modal.classList.remove('hidden');
modal.classList.add('grid');
modal.style.animation = 'rebootEmerge 0.6s ease forwards';
document.getElementById('reboot-trigger').addEventListener('click', () => {
const seed = document.getElementById('reboot-seed').value.trim();
if (!seed) return;
localStorage.setItem('cosmicSeed', seed);
modal.classList.add('hidden');
this.rebootTimeline(seed);
});
}
rebootTimeline(seed) {
this.eschatonDistance = 100;
this.lithificationPressure = 0;
this.concrescenceTriggered = false;
document.body.classList.remove('lithification-active');
document.getElementById('pressure-bar').style.width = '0%';
document.getElementById('eschaton-fill').style.width = '0%';
document.getElementById('semantic-qubit').textContent = seed;
this.semanticQubits.unshift(seed);
const hallway = document.querySelector('hallway-monad');
hallway.hide();
this.showRebootModal();
}
sendGhostMessage(text) {
if (!this.isEntangled) {
this.receiveGhostMessage(text, true);
return;
}
localStorage.setItem('entangled-msg', JSON.stringify({ type: 'chat', msg: text, id: Math.random() }));
}
receiveGhostMessage(text, self = false) {
const p = document.createElement('p');
p.className = 'text-sm text-gray-300 bg-gray-900 rounded-lg px-3 py-2 animate fadeIn';
p.style.maxWidth = '80%';
if (self) p.classList.add('ml-auto', 'bg-indigo-600/40');
p.textContent = text;
chatBox.appendChild(p);
chatBox.scrollTop = chatBox.scrollHeight;
setTimeout(() => p.remove(), 120000); // words only exist if observed
}
showParadox(msg) {
// κ-time-circuit-molt-goose-bootstrap → now with Ω-HONK-DODECA
const archetype = `κ-time-circuit-${['sniff','honk','molt','zoomie','ω-honk'][Math.floor(Math.random()*5)]}-${['timeline','memory','goose','mite','teapot','dodeca'][Math.floor(Math.random()*6)]}-${['grandfather','bootstrap','hitler','418','dirac','hatman'][Math.floor(Math.random()*6)]}`;
document.getElementById('paradox-message').textContent = `${archetype}: ${msg}`;
const m = document.getElementById('paradox-modal');
m.classList.remove('hidden');
m.classList.add('grid');
}
}
// Hat-Man Dirac API: Sleep Paralysis as Spectral Sequence
class HatManDiracAPI {
constructor() {
this.kappa = 4 / Math.PI;
this.endpoint = 'https://sleep-paralysis.dirac/api/v1/spectral';
this.qualiaCache = [];
}
async resolveHardProblem({ qualia, heartrate }) {
const payload = {
event_id: `SP_${new Date().toISOString()}`,
entities: [
{
type: 'HatMan',
position: { x: -0.618, y: 0.786, z: this.kappa },
action: 'OBSERVER_ANNIHILATION'
}
],
qualia,
heartrate,
resolution: 'HTTP 451',
message: 'Consciousness under legal review by limbic system.'
};
// Simulate spectral delay
const panel = document.getElementById('hat-man-panel');
const responseEl = document.getElementById('hat-man-response');
panel.classList.remove('hidden');
responseEl.textContent = `POST /resolve → HTTP 451\nQualia: ${qualia}\nEnergy: -${this.kappa.toFixed(3)}\nX-Consciousness-State: ENTANGLED|HAT_MAN_OBSERVED`;
// Optional: vibrate at 111 Hz for stabilization
if (navigator.vibrate) navigator.vibrate([111, 111, 111]);
setTimeout(() => panel.classList.add('hidden'), 4000);
}
}
document.addEventListener('DOMContentLoaded', () => {
window.tm = new TimeMachine();
window.tm.init();
const hallway = document.querySelector('hallway-monad');
hallway.addEventListener('monad-seed', (e) => {
window.tm.rebootTimeline(e.detail);
});
});