// static/physics.js // Pure pulse-engine math. No DOM. app.js drives the DOM from these numbers. // Everything here is a function of the live VADUGWI mood — animation READS the // soul; it never invents motion the soul didn't justify. 'use strict'; (function (global) { function springStep(state, target, dt, k, c) { const x = state.pos, v = state.vel; const a = -k * (x - target) - c * v; const nv = v + a * dt; const nx = x + nv * dt; return { pos: nx, vel: nv }; } function breath(phase, mood) { const a = mood[1] ?? 128; const depth = 0.012 + (a / 255) * 0.05; return 1 + Math.sin(phase) * depth; } function breathRate(mood) { const a = mood[1] ?? 128; return 0.6 + (a / 255) * 3.2; } function behaviorFor(mood) { const a = mood[1] ?? 128, u = mood[3] ?? 0; if (a < 70 && u < 60) return 'sleep'; if (a >= 195) return 'excited'; if (a >= 150) return 'roam'; if (a < 120) return 'calm'; return 'idle'; } function sway(phase, mood) { const a = mood[1] ?? 128, i = mood[6] ?? 128; const amp = 1.5 + (a / 255) * 5.0; const bias = (i - 128) / 128 * 2.0; return Math.sin(phase * 0.6) * amp + bias; } global.ClankerPhysics = { springStep, breath, breathRate, behaviorFor, sway }; })(window);