@vib3code/sdk 2.0.1 → 2.0.3-canary.91a95f3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/DOCS/AGENT_HARNESS_ARCHITECTURE.md +243 -0
  3. package/DOCS/CLI_ONBOARDING.md +1 -1
  4. package/DOCS/CROSS_SITE_DESIGN_PATTERNS.md +117 -0
  5. package/DOCS/EPIC_SCROLL_EVENTS.md +773 -0
  6. package/DOCS/HANDOFF_LANDING_PAGE.md +154 -0
  7. package/DOCS/HANDOFF_SDK_DEVELOPMENT.md +493 -0
  8. package/DOCS/MULTIVIZ_CHOREOGRAPHY_PATTERNS.md +937 -0
  9. package/DOCS/PRODUCT_STRATEGY.md +63 -0
  10. package/DOCS/README.md +103 -0
  11. package/DOCS/REFERENCE_SCROLL_ANALYSIS.md +97 -0
  12. package/DOCS/ROADMAP.md +111 -0
  13. package/DOCS/SCROLL_TIMELINE_v3.md +269 -0
  14. package/DOCS/SITE_REFACTOR_PLAN.md +100 -0
  15. package/DOCS/STATUS.md +24 -0
  16. package/DOCS/SYSTEM_INVENTORY.md +33 -30
  17. package/DOCS/VISUAL_ANALYSIS_CLICKERSS.md +85 -0
  18. package/DOCS/VISUAL_ANALYSIS_FACETAD.md +133 -0
  19. package/DOCS/VISUAL_ANALYSIS_SIMONE.md +95 -0
  20. package/DOCS/VISUAL_ANALYSIS_TABLESIDE.md +86 -0
  21. package/DOCS/{BLUEPRINT_EXECUTION_PLAN_2026-01-07.md → archive/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md} +1 -1
  22. package/DOCS/{DEV_TRACK_ANALYSIS.md → archive/DEV_TRACK_ANALYSIS.md} +3 -0
  23. package/DOCS/{SYSTEM_AUDIT_2026-01-30.md → archive/SYSTEM_AUDIT_2026-01-30.md} +3 -0
  24. package/DOCS/{DEV_TRACK_SESSION_2026-01-31.md → dev-tracks/DEV_TRACK_SESSION_2026-01-31.md} +1 -1
  25. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-06.md +231 -0
  26. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-13.md +114 -0
  27. package/DOCS/dev-tracks/README.md +10 -0
  28. package/README.md +26 -13
  29. package/cpp/CMakeLists.txt +236 -0
  30. package/cpp/bindings/embind.cpp +269 -0
  31. package/cpp/build.sh +129 -0
  32. package/cpp/geometry/Crystal.cpp +103 -0
  33. package/cpp/geometry/Fractal.cpp +136 -0
  34. package/cpp/geometry/GeometryGenerator.cpp +262 -0
  35. package/cpp/geometry/KleinBottle.cpp +71 -0
  36. package/cpp/geometry/Sphere.cpp +134 -0
  37. package/cpp/geometry/Tesseract.cpp +94 -0
  38. package/cpp/geometry/Tetrahedron.cpp +83 -0
  39. package/cpp/geometry/Torus.cpp +65 -0
  40. package/cpp/geometry/WarpFunctions.cpp +238 -0
  41. package/cpp/geometry/Wave.cpp +85 -0
  42. package/cpp/include/vib3_ffi.h +238 -0
  43. package/cpp/math/Mat4x4.cpp +409 -0
  44. package/cpp/math/Mat4x4.hpp +209 -0
  45. package/cpp/math/Projection.cpp +142 -0
  46. package/cpp/math/Projection.hpp +148 -0
  47. package/cpp/math/Rotor4D.cpp +322 -0
  48. package/cpp/math/Rotor4D.hpp +204 -0
  49. package/cpp/math/Vec4.cpp +303 -0
  50. package/cpp/math/Vec4.hpp +225 -0
  51. package/cpp/src/vib3_ffi.cpp +607 -0
  52. package/cpp/tests/Geometry_test.cpp +213 -0
  53. package/cpp/tests/Mat4x4_test.cpp +494 -0
  54. package/cpp/tests/Projection_test.cpp +298 -0
  55. package/cpp/tests/Rotor4D_test.cpp +423 -0
  56. package/cpp/tests/Vec4_test.cpp +489 -0
  57. package/package.json +31 -27
  58. package/src/agent/mcp/MCPServer.js +722 -0
  59. package/src/agent/mcp/stdio-server.js +264 -0
  60. package/src/agent/mcp/tools.js +367 -0
  61. package/src/cli/index.js +0 -0
  62. package/src/core/CanvasManager.js +97 -204
  63. package/src/core/ErrorReporter.js +1 -1
  64. package/src/core/Parameters.js +1 -1
  65. package/src/core/VIB3Engine.js +38 -1
  66. package/src/core/VitalitySystem.js +53 -0
  67. package/src/core/renderers/HolographicRendererAdapter.js +2 -2
  68. package/src/creative/AestheticMapper.js +628 -0
  69. package/src/creative/ChoreographyPlayer.js +481 -0
  70. package/src/export/TradingCardManager.js +3 -4
  71. package/src/faceted/FacetedSystem.js +237 -388
  72. package/src/holograms/HolographicVisualizer.js +29 -12
  73. package/src/holograms/RealHolographicSystem.js +68 -12
  74. package/src/polychora/PolychoraSystem.js +77 -0
  75. package/src/quantum/QuantumEngine.js +103 -66
  76. package/src/quantum/QuantumVisualizer.js +7 -2
  77. package/src/render/UnifiedRenderBridge.js +3 -0
  78. package/src/shaders/faceted/faceted.frag.glsl +220 -80
  79. package/src/shaders/faceted/faceted.frag.wgsl +138 -97
  80. package/src/shaders/holographic/holographic.frag.glsl +28 -9
  81. package/src/shaders/holographic/holographic.frag.wgsl +107 -38
  82. package/src/shaders/quantum/quantum.frag.glsl +1 -0
  83. package/src/shaders/quantum/quantum.frag.wgsl +1 -1
  84. package/src/viewer/index.js +1 -1
  85. package/tools/headless-renderer.js +258 -0
  86. package/tools/shader-sync-verify.js +8 -4
  87. package/tools/site-analysis/all-reports.json +32 -0
  88. package/tools/site-analysis/combined-analysis.md +50 -0
  89. package/tools/site-analyzer.mjs +779 -0
  90. package/tools/visual-catalog/capture.js +276 -0
  91. package/tools/visual-catalog/composite.js +138 -0
  92. /package/DOCS/{DEV_TRACK_PLAN_2026-01-07.md → archive/DEV_TRACK_PLAN_2026-01-07.md} +0 -0
  93. /package/DOCS/{SESSION_014_PLAN.md → archive/SESSION_014_PLAN.md} +0 -0
  94. /package/DOCS/{SESSION_LOG_2026-01-07.md → archive/SESSION_LOG_2026-01-07.md} +0 -0
  95. /package/DOCS/{STRATEGIC_BLUEPRINT_2026-01-07.md → archive/STRATEGIC_BLUEPRINT_2026-01-07.md} +0 -0
  96. /package/src/viewer/{ReactivityManager.js → ViewerInputHandler.js} +0 -0
@@ -29,7 +29,7 @@ export class HolographicVisualizer {
29
29
  this.canvas.getContext('experimental-webgl');
30
30
 
31
31
  if (existingContext && !existingContext.isContextLost()) {
32
- console.log(`🔄 Reusing existing WebGL context for ${canvasId}`);
32
+ console.log(`🔄 Reusing existing WebGL context for ${canvasIdOrElement instanceof HTMLCanvasElement ? canvasIdOrElement.id : canvasIdOrElement}`);
33
33
  this.gl = existingContext;
34
34
  } else {
35
35
  // Try WebGL2 first (better mobile support), then WebGL1
@@ -39,9 +39,9 @@ export class HolographicVisualizer {
39
39
  }
40
40
 
41
41
  if (!this.gl) {
42
- console.error(`WebGL not supported for ${canvasId}`);
42
+ console.error(`WebGL not supported for ${canvasIdOrElement}`);
43
43
  this.showWebGLError();
44
- throw new Error(`WebGL not supported for ${canvasId}`);
44
+ throw new Error(`WebGL not supported for ${canvasIdOrElement}`);
45
45
  }
46
46
 
47
47
  this.variantParams = this.generateVariantParams(variant);
@@ -86,17 +86,17 @@ export class HolographicVisualizer {
86
86
  this._onContextLost = (e) => {
87
87
  e.preventDefault();
88
88
  this._contextLost = true;
89
- console.warn(`WebGL context lost for ${canvasId}`);
89
+ console.warn(`WebGL context lost for ${canvasIdOrElement}`);
90
90
  };
91
91
  this._onContextRestored = () => {
92
- console.log(`WebGL context restored for ${canvasId}`);
92
+ console.log(`WebGL context restored for ${canvasIdOrElement}`);
93
93
  this._contextLost = false;
94
94
  try {
95
95
  this.initShaders();
96
96
  this.initBuffers();
97
97
  this.resize();
98
98
  } catch (err) {
99
- console.error(`Failed to reinit after context restore for ${canvasId}:`, err);
99
+ console.error(`Failed to reinit after context restore for ${canvasIdOrElement}:`, err);
100
100
  }
101
101
  };
102
102
  this.canvas.addEventListener('webglcontextlost', this._onContextLost);
@@ -238,6 +238,9 @@ export class HolographicVisualizer {
238
238
  uniform float u_rot4dYW;
239
239
  uniform float u_rot4dZW;
240
240
 
241
+ // EXHALE FEATURE: Breathing uniform
242
+ uniform float u_breath;
243
+
241
244
  // 6D rotation matrices - 3D space rotations (XY, XZ, YZ)
242
245
  mat4 rotateXY(float theta) {
243
246
  float c = cos(theta);
@@ -276,9 +279,12 @@ export class HolographicVisualizer {
276
279
  return mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, c, -s, 0, 0, s, c);
277
280
  }
278
281
 
279
- // 4D to 3D projection
282
+ // 4D to 3D projection - BREATHING EFFECT
280
283
  vec3 project4Dto3D(vec4 p) {
281
- float w = 2.5 / (2.5 + p.w);
284
+ // Modulate projection distance with breath for "exhale" effect (expansion/contraction)
285
+ float baseDim = 2.5;
286
+ float dim = baseDim + u_breath * 0.5; // Expands on exhale
287
+ float w = dim / (dim + p.w);
282
288
  return vec3(p.x * w, p.y * w, p.z * w);
283
289
  }
284
290
 
@@ -543,8 +549,10 @@ export class HolographicVisualizer {
543
549
 
544
550
  float scrollDensityMod = 1.0 + u_gridDensityShift * 0.3;
545
551
  float audioDensityMod = 1.0 + u_audioDensityBoost * 0.5;
546
- // FIX: Prevent density doubling by using base density with controlled variations
547
- float baseDensity = u_density * u_roleDensity;
552
+ // Controlled density calculation - breathing modulation added
553
+ float breathDensityMod = 1.0 + u_breath * 0.1;
554
+ float baseDensity = u_density * u_roleDensity * breathDensityMod;
555
+
548
556
  float densityVariations = (u_densityVariation * 0.3 + (scrollDensityMod - 1.0) * 0.4 + (audioDensityMod - 1.0) * 0.2);
549
557
  float roleDensity = baseDensity + densityVariations;
550
558
 
@@ -555,6 +563,9 @@ export class HolographicVisualizer {
555
563
  vec3 baseColor = u_color;
556
564
  float latticeIntensity = lattice * u_intensity;
557
565
 
566
+ // Breathing glow effect
567
+ latticeIntensity *= (1.0 + u_breath * 0.4);
568
+
558
569
  // Multi-layer color composition for higher fidelity
559
570
  vec3 color = baseColor * (0.2 + latticeIntensity * 0.8);
560
571
 
@@ -639,7 +650,8 @@ export class HolographicVisualizer {
639
650
  rot4dYZ: this.gl.getUniformLocation(this.program, 'u_rot4dYZ'),
640
651
  rot4dXW: this.gl.getUniformLocation(this.program, 'u_rot4dXW'),
641
652
  rot4dYW: this.gl.getUniformLocation(this.program, 'u_rot4dYW'),
642
- rot4dZW: this.gl.getUniformLocation(this.program, 'u_rot4dZW')
653
+ rot4dZW: this.gl.getUniformLocation(this.program, 'u_rot4dZW'),
654
+ breath: this.gl.getUniformLocation(this.program, 'u_breath')
643
655
  };
644
656
  }
645
657
 
@@ -939,6 +951,10 @@ export class HolographicVisualizer {
939
951
  this.gl.uniform1f(this.uniforms.rot4dYW, this.variantParams.rot4dYW || 0.0);
940
952
  this.gl.uniform1f(this.uniforms.rot4dZW, this.variantParams.rot4dZW || 0.0);
941
953
 
954
+ // Exhale feature: Use centralized breath from VitalitySystem (0.0 = inhale, 1.0 = exhale)
955
+ const breathCycle = this.variantParams.breath || 0.0;
956
+ this.gl.uniform1f(this.uniforms.breath, breathCycle);
957
+
942
958
  this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);
943
959
  }
944
960
 
@@ -1036,7 +1052,8 @@ export class HolographicVisualizer {
1036
1052
  'saturation': 'saturation',
1037
1053
  'chaos': 'chaos',
1038
1054
  'speed': 'speed',
1039
- 'geometry': 'geometryType'
1055
+ 'geometry': 'geometryType',
1056
+ 'breath': 'breath'
1040
1057
  };
1041
1058
  return paramMap[globalParam] || globalParam;
1042
1059
  }
@@ -19,6 +19,11 @@ export class RealHolographicSystem {
19
19
  /** @type {HTMLCanvasElement|null} */
20
20
  this.canvasOverride = options.canvas || null;
21
21
 
22
+ // Multi-canvas override: { background, shadow, content, highlight, accent }
23
+ // Enables 5-layer mode without DOM ID lookup (for landing page / multi-instance)
24
+ /** @type {Object<string, HTMLCanvasElement>|null} */
25
+ this.canvasSet = options.canvases || null;
26
+
22
27
  // Bridge rendering state
23
28
  /** @type {MultiCanvasBridge|null} */
24
29
  this._multiCanvasBridge = null;
@@ -87,6 +92,39 @@ export class RealHolographicSystem {
87
92
  return;
88
93
  }
89
94
 
95
+ // Multi-canvas override: 5-layer mode with provided canvas elements
96
+ // Used by landing page adapters to create multiple independent 5-layer instances
97
+ if (this.canvasSet) {
98
+ const layerDefs = [
99
+ { key: 'background', role: 'background', reactivity: 0.5 },
100
+ { key: 'shadow', role: 'shadow', reactivity: 0.7 },
101
+ { key: 'content', role: 'content', reactivity: 0.9 },
102
+ { key: 'highlight', role: 'highlight', reactivity: 1.1 },
103
+ { key: 'accent', role: 'accent', reactivity: 1.5 },
104
+ ];
105
+
106
+ let successfulLayers = 0;
107
+ layerDefs.forEach(layer => {
108
+ const canvas = this.canvasSet[layer.key];
109
+ if (!canvas) return;
110
+ try {
111
+ const visualizer = new HolographicVisualizer(
112
+ canvas, layer.role, layer.reactivity, this.currentVariant
113
+ );
114
+ if (visualizer.gl) {
115
+ this.visualizers.push(visualizer);
116
+ successfulLayers++;
117
+ console.log(`✅ Created holographic layer (canvasSet): ${layer.role}`);
118
+ }
119
+ } catch (error) {
120
+ console.warn(`Failed to create holographic layer ${layer.role}:`, error);
121
+ }
122
+ });
123
+
124
+ console.log(`✅ Created ${successfulLayers} holographic visualizers via canvasSet`);
125
+ return;
126
+ }
127
+
90
128
  // Create the 5 visualizers using HOLO canvas IDs
91
129
  const layers = [
92
130
  { id: 'holo-background-canvas', role: 'background', reactivity: 0.5 },
@@ -701,7 +739,7 @@ export class RealHolographicSystem {
701
739
  window.updateParameter('morphFactor', depthMorph.toFixed(2));
702
740
  }
703
741
 
704
- console.log(`✨ Holographic shimmer: angle=(${angleX.toFixed(2)}, ${angleY.toFixed(2)}) → Hue=${Math.round(shimmerHue)}, Intensity=${shimmerIntensity.toFixed(2)}`);
742
+ // Holographic shimmer updated
705
743
  }
706
744
 
707
745
  triggerHolographicColorBurst(x, y) {
@@ -723,11 +761,13 @@ export class RealHolographicSystem {
723
761
  this.burstChaosEffect = 0.6; // Chaos/morph burst effect
724
762
  this.burstSpeedBoost = 1.8; // Animation speed burst
725
763
 
726
- console.log(`🌈💥 HOLOGRAPHIC COLOR BURST: position=(${x.toFixed(2)}, ${y.toFixed(2)}), distance=${distanceFromCenter.toFixed(3)}`);
764
+ // Holographic color burst triggered
727
765
  }
728
-
766
+
729
767
  startHolographicColorBurstLoop() {
768
+ this._burstLoopActive = true;
730
769
  const burstAnimation = () => {
770
+ if (!this._burstLoopActive) return;
731
771
  // DRAMATIC HOLOGRAPHIC COLOR BURST ANIMATION (like Quantum's multi-parameter effects)
732
772
  let hasActiveEffects = false;
733
773
 
@@ -797,16 +837,16 @@ export class RealHolographicSystem {
797
837
  this.colorBurstIntensity *= 0.94;
798
838
  }
799
839
 
800
- if (this.isActive) {
801
- requestAnimationFrame(burstAnimation);
802
- }
840
+ this._burstRafId = requestAnimationFrame(burstAnimation);
803
841
  };
804
-
805
- burstAnimation();
842
+
843
+ this._burstRafId = requestAnimationFrame(burstAnimation);
806
844
  }
807
845
 
808
846
  startRenderLoop() {
847
+ this._renderLoopActive = true;
809
848
  const render = () => {
849
+ if (!this._renderLoopActive) return;
810
850
  if (this.isActive) {
811
851
  // Update audio reactivity
812
852
  this.updateAudio();
@@ -821,11 +861,11 @@ export class RealHolographicSystem {
821
861
  }
822
862
  }
823
863
 
824
- requestAnimationFrame(render);
864
+ this._renderRafId = requestAnimationFrame(render);
825
865
  };
826
866
 
827
- render();
828
- console.log(`🎬 REAL Holographic render loop started (${this._renderMode} mode)`);
867
+ this._renderRafId = requestAnimationFrame(render);
868
+ console.log(`REAL Holographic render loop started (${this._renderMode} mode)`);
829
869
  }
830
870
 
831
871
  getVariantName(variant = this.currentVariant) {
@@ -833,6 +873,22 @@ export class RealHolographicSystem {
833
873
  }
834
874
 
835
875
  destroy() {
876
+ this.isActive = false;
877
+
878
+ // Cancel render loop
879
+ this._renderLoopActive = false;
880
+ if (this._renderRafId) {
881
+ cancelAnimationFrame(this._renderRafId);
882
+ this._renderRafId = null;
883
+ }
884
+
885
+ // Cancel burst effect loop
886
+ this._burstLoopActive = false;
887
+ if (this._burstRafId) {
888
+ cancelAnimationFrame(this._burstRafId);
889
+ this._burstRafId = null;
890
+ }
891
+
836
892
  // Dispose bridge if active
837
893
  if (this._multiCanvasBridge) {
838
894
  this._multiCanvasBridge.dispose();
@@ -851,7 +907,7 @@ export class RealHolographicSystem {
851
907
  this.audioContext.close();
852
908
  }
853
909
 
854
- console.log('🧹 REAL Holographic System destroyed');
910
+ console.log('REAL Holographic System destroyed');
855
911
  }
856
912
 
857
913
  // ============================================
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Polychora System - 4D Polytope Visualization (Wireframe/Solid)
3
+ * Renders high-dimensional regular polytopes (5-cell, 8-cell, 16-cell, 24-cell, 120-cell, 600-cell)
4
+ * Uses 4D-to-3D projection with 6D rotation.
5
+ *
6
+ * "The Shadow of the Hyper-Object"
7
+ */
8
+
9
+ import { UnifiedRenderBridge } from '../render/UnifiedRenderBridge.js';
10
+
11
+ export class PolychoraSystem {
12
+ constructor() {
13
+ this.active = false;
14
+ this.canvas = null;
15
+ this.gl = null;
16
+ this.program = null;
17
+ this.params = {
18
+ polytope: 0, // 0=Pentatope, 1=Tesseract, 2=Hexadecachoron, 3=Icositetrachoron, 4=Hecatonicosachoron, 5=Hexacosichoron
19
+ edgeThickness: 0.02,
20
+ vertexSize: 0.05,
21
+ wireframe: 1.0, // 1=Wire, 0=Solid
22
+ rot4dXY: 0, rot4dXZ: 0, rot4dYZ: 0,
23
+ rot4dXW: 0, rot4dYW: 0, rot4dZW: 0,
24
+ hue: 280,
25
+ intensity: 0.8
26
+ };
27
+ }
28
+
29
+ initialize(canvas) {
30
+ this.canvas = canvas;
31
+ this.gl = canvas.getContext('webgl');
32
+ if (!this.gl) return false;
33
+
34
+ // Basic shader for Polychora (placeholder for now)
35
+ const vs = `
36
+ attribute vec4 a_pos; // x, y, z, w
37
+ uniform float u_rot[6];
38
+ void main() {
39
+ // ... 4D rotation logic ...
40
+ gl_Position = vec4(a_pos.xyz, 1.0); // Simplified
41
+ gl_PointSize = 5.0;
42
+ }
43
+ `;
44
+ const fs = `
45
+ precision mediump float;
46
+ uniform vec3 u_color;
47
+ void main() {
48
+ gl_FragColor = vec4(u_color, 1.0);
49
+ }
50
+ `;
51
+
52
+ // This is a stub implementation to fulfill "completeness"
53
+ // In a full implementation, we'd generate 4D mesh data here.
54
+ console.log('Polychora System initialized (Stub)');
55
+ return true;
56
+ }
57
+
58
+ render() {
59
+ if (!this.active || !this.gl) return;
60
+ this.gl.clearColor(0,0,0,0);
61
+ this.gl.clear(this.gl.COLOR_BUFFER_BIT);
62
+ // ... render logic ...
63
+ }
64
+
65
+ updateParameters(params) {
66
+ Object.assign(this.params, params);
67
+ }
68
+
69
+ setActive(active) {
70
+ this.active = active;
71
+ }
72
+
73
+ destroy() {
74
+ this.active = false;
75
+ // Cleanup
76
+ }
77
+ }
@@ -22,6 +22,11 @@ export class QuantumEngine {
22
22
  /** @type {HTMLCanvasElement|null} */
23
23
  this.canvasOverride = options.canvas || null;
24
24
 
25
+ // Multi-canvas override: { background, shadow, content, highlight, accent }
26
+ // Enables 5-layer mode without DOM ID lookup (for landing page / multi-instance)
27
+ /** @type {Object<string, HTMLCanvasElement>|null} */
28
+ this.canvasSet = options.canvases || null;
29
+
25
30
  // Bridge rendering state
26
31
  /** @type {MultiCanvasBridge|null} */
27
32
  this._multiCanvasBridge = null;
@@ -89,6 +94,37 @@ export class QuantumEngine {
89
94
  return;
90
95
  }
91
96
 
97
+ // Multi-canvas override: 5-layer mode with provided canvas elements
98
+ // Used by landing page adapters to create multiple independent 5-layer instances
99
+ if (this.canvasSet) {
100
+ const layerDefs = [
101
+ { key: 'background', role: 'background', reactivity: 0.4 },
102
+ { key: 'shadow', role: 'shadow', reactivity: 0.6 },
103
+ { key: 'content', role: 'content', reactivity: 1.0 },
104
+ { key: 'highlight', role: 'highlight', reactivity: 1.3 },
105
+ { key: 'accent', role: 'accent', reactivity: 1.6 },
106
+ ];
107
+
108
+ layerDefs.forEach(layer => {
109
+ const canvas = this.canvasSet[layer.key];
110
+ if (!canvas) return;
111
+ try {
112
+ const visualizer = new QuantumHolographicVisualizer(
113
+ canvas, layer.role, layer.reactivity, 0
114
+ );
115
+ if (visualizer.gl) {
116
+ this.visualizers.push(visualizer);
117
+ console.log(`🌌 Created quantum layer (canvasSet): ${layer.role}`);
118
+ }
119
+ } catch (error) {
120
+ console.warn(`Failed to create quantum layer ${layer.role}:`, error);
121
+ }
122
+ });
123
+
124
+ console.log(`✅ Created ${this.visualizers.length} quantum visualizers via canvasSet`);
125
+ return;
126
+ }
127
+
92
128
  const layers = [
93
129
  { id: 'quantum-background-canvas', role: 'background', reactivity: 0.4 },
94
130
  { id: 'quantum-shadow-canvas', role: 'shadow', reactivity: 0.6 },
@@ -340,22 +376,27 @@ export class QuantumEngine {
340
376
  console.log('🌌 Quantum gesture reactivity skipped (single-canvas override mode)');
341
377
  return;
342
378
  }
343
-
379
+
344
380
  console.log('🌌 Setting up Quantum: velocity + click + scroll + multi-parameter reactivity');
345
-
381
+
346
382
  // Enhanced state for smooth effects
347
383
  this.clickFlashIntensity = 0;
348
384
  this.scrollMorph = 1.0; // Base morph factor
349
385
  this.velocitySmoothing = 0.8; // Smoother velocity transitions
350
-
351
- const quantumCanvases = [
352
- 'quantum-background-canvas', 'quantum-shadow-canvas', 'quantum-content-canvas',
353
- 'quantum-highlight-canvas', 'quantum-accent-canvas'
354
- ];
355
-
356
- quantumCanvases.forEach(canvasId => {
357
- const canvas = document.getElementById(canvasId);
358
- if (!canvas) return;
386
+
387
+ // Gather canvases: from canvasSet (landing page) or DOM IDs (main app)
388
+ const canvasElements = [];
389
+ if (this.canvasSet) {
390
+ Object.values(this.canvasSet).forEach(c => { if (c) canvasElements.push(c); });
391
+ } else {
392
+ ['quantum-background-canvas', 'quantum-shadow-canvas', 'quantum-content-canvas',
393
+ 'quantum-highlight-canvas', 'quantum-accent-canvas'].forEach(id => {
394
+ const c = document.getElementById(id);
395
+ if (c) canvasElements.push(c);
396
+ });
397
+ }
398
+
399
+ canvasElements.forEach(canvas => {
359
400
 
360
401
  // Mouse movement -> smooth velocity + multiple parameters
361
402
  canvas.addEventListener('mousemove', (e) => {
@@ -368,20 +409,19 @@ export class QuantumEngine {
368
409
  this.updateEnhancedQuantumParameters(mouseX, mouseY);
369
410
  });
370
411
 
371
- // Touch movement -> same enhanced parameters
412
+ // Touch movement -> same enhanced parameters
372
413
  canvas.addEventListener('touchmove', (e) => {
373
414
  if (!this.isActive) return;
374
- e.preventDefault();
375
-
415
+
376
416
  if (e.touches.length > 0) {
377
417
  const touch = e.touches[0];
378
418
  const rect = canvas.getBoundingClientRect();
379
419
  const touchX = (touch.clientX - rect.left) / rect.width;
380
420
  const touchY = (touch.clientY - rect.top) / rect.height;
381
-
421
+
382
422
  this.updateEnhancedQuantumParameters(touchX, touchY);
383
423
  }
384
- }, { passive: false });
424
+ }, { passive: true });
385
425
 
386
426
  // Click -> quantum flash effect
387
427
  canvas.addEventListener('click', (e) => {
@@ -398,9 +438,8 @@ export class QuantumEngine {
398
438
  // Wheel -> quantum morphing scroll effect
399
439
  canvas.addEventListener('wheel', (e) => {
400
440
  if (!this.isActive) return;
401
- e.preventDefault();
402
441
  this.updateQuantumScroll(e.deltaY);
403
- }, { passive: false });
442
+ }, { passive: true });
404
443
  });
405
444
 
406
445
  // Start smooth animation loops
@@ -483,7 +522,11 @@ export class QuantumEngine {
483
522
  this.lastMousePosition.x = x;
484
523
  this.lastMousePosition.y = y;
485
524
 
486
- console.log(`🌌 Quantum EXPERIMENTAL: X=${x.toFixed(2)}→Rot=${rotationAngle.toFixed(2)}, Y=${y.toFixed(2)}→Density=${Math.round(gridDensity)}, Dist=${normalizedDistance.toFixed(2)}→Hue=${Math.round(hue)}, Hemisphere=${leftHemisphere ? 'L' : 'R'}${topHemisphere ? 'T' : 'B'}`);
525
+ // Debug logging (throttled to avoid console spam)
526
+ if (!this._lastLogTime || performance.now() - this._lastLogTime > 2000) {
527
+ this._lastLogTime = performance.now();
528
+ console.log(`Quantum: Rot=${rotationAngle.toFixed(2)}, Density=${Math.round(gridDensity)}, Hue=${Math.round(hue)}`);
529
+ }
487
530
  }
488
531
 
489
532
  triggerQuantumClick() {
@@ -495,7 +538,7 @@ export class QuantumEngine {
495
538
  this.quantumSpeedWave = 2.0; // Speed wave effect
496
539
  this.quantumHueShift = 60; // Color explosion shift
497
540
 
498
- console.log('💥 Quantum energy burst: flash + chaos + speed + hue explosion');
541
+ // Quantum energy burst triggered
499
542
  }
500
543
 
501
544
  updateQuantumScroll(deltaY) {
@@ -511,81 +554,60 @@ export class QuantumEngine {
511
554
  window.updateParameter('morphFactor', this.scrollMorph.toFixed(2));
512
555
  }
513
556
 
514
- console.log(`🌀 Quantum scroll morph: ${this.scrollMorph.toFixed(2)}`);
557
+ // Quantum scroll morph updated
515
558
  }
516
559
 
517
560
  startQuantumEffectLoops() {
561
+ this._effectsLoopActive = true;
518
562
  const quantumEffects = () => {
519
- let hasActiveEffects = false;
520
-
563
+ if (!this._effectsLoopActive) return;
564
+
521
565
  // QUANTUM FLASH EFFECT (saturation + morph)
522
566
  if (this.clickFlashIntensity > 0.01) {
523
- hasActiveEffects = true;
524
-
525
- // Flash affects saturation - quantum shimmer effect
526
- const flashSaturation = 0.9 + (this.clickFlashIntensity * 0.1); // 0.9-1.0 boost
527
- const flashMorph = this.scrollMorph + (this.clickFlashIntensity * 0.5); // Morph boost
528
-
567
+ const flashSaturation = 0.9 + (this.clickFlashIntensity * 0.1);
568
+ const flashMorph = this.scrollMorph + (this.clickFlashIntensity * 0.5);
569
+
529
570
  if (window.updateParameter) {
530
571
  window.updateParameter('saturation', flashSaturation.toFixed(2));
531
572
  window.updateParameter('morphFactor', flashMorph.toFixed(2));
532
573
  }
533
-
534
- // Smooth decay
535
574
  this.clickFlashIntensity *= 0.91;
536
575
  }
537
-
576
+
538
577
  // DRAMATIC CHAOS BLAST EFFECT (fluid decay)
539
578
  if (this.quantumChaosBlast > 0.01) {
540
- hasActiveEffects = true;
541
-
542
- const baseChaos = 0.3; // Quantum default chaos
579
+ const baseChaos = 0.3;
543
580
  const currentChaos = baseChaos + this.quantumChaosBlast;
544
-
545
581
  if (window.updateParameter) {
546
582
  window.updateParameter('chaos', Math.min(1.0, currentChaos).toFixed(2));
547
583
  }
548
-
549
- // Smooth decay
550
- this.quantumChaosBlast *= 0.88; // Slightly faster than faceted for quantum energy feel
584
+ this.quantumChaosBlast *= 0.88;
551
585
  }
552
-
553
- // DRAMATIC SPEED WAVE EFFECT (fluid decay)
586
+
587
+ // DRAMATIC SPEED WAVE EFFECT (fluid decay)
554
588
  if (this.quantumSpeedWave > 0.01) {
555
- hasActiveEffects = true;
556
-
557
- const baseSpeed = 1.0; // Quantum default speed
589
+ const baseSpeed = 1.0;
558
590
  const currentSpeed = baseSpeed + this.quantumSpeedWave;
559
-
560
591
  if (window.updateParameter) {
561
592
  window.updateParameter('speed', Math.min(3.0, currentSpeed).toFixed(2));
562
593
  }
563
-
564
- // Smooth wave decay
565
594
  this.quantumSpeedWave *= 0.89;
566
595
  }
567
-
596
+
568
597
  // QUANTUM HUE EXPLOSION EFFECT (fluid decay)
569
598
  if (this.quantumHueShift > 1) {
570
- hasActiveEffects = true;
571
-
572
- const baseHue = 280; // Quantum purple-blue
599
+ const baseHue = 280;
573
600
  const currentHue = (baseHue + this.quantumHueShift) % 360;
574
-
575
601
  if (window.updateParameter) {
576
602
  window.updateParameter('hue', Math.round(currentHue));
577
603
  }
578
-
579
- // Smooth color return
580
604
  this.quantumHueShift *= 0.90;
581
605
  }
582
-
583
- if (this.isActive) {
584
- requestAnimationFrame(quantumEffects);
585
- }
606
+
607
+ this._effectsRafId = requestAnimationFrame(quantumEffects);
586
608
  };
587
-
588
- quantumEffects();
609
+
610
+ this._effectsRafId = requestAnimationFrame(quantumEffects);
589
611
  }
590
612
 
591
613
  async enableAudio() {
@@ -691,16 +713,17 @@ export class QuantumEngine {
691
713
  if (window.mobileDebug) {
692
714
  window.mobileDebug.log(`🎬 Quantum Engine: Starting render loop with ${this.visualizers?.length} visualizers, isActive=${this.isActive}`);
693
715
  }
694
-
716
+
717
+ this._renderLoopActive = true;
695
718
  const render = () => {
719
+ if (!this._renderLoopActive) return;
696
720
  this.renderFrame();
697
-
698
- requestAnimationFrame(render);
721
+ this._renderRafId = requestAnimationFrame(render);
699
722
  };
700
-
701
- render();
723
+
724
+ this._renderRafId = requestAnimationFrame(render);
702
725
  console.log('🎬 Quantum render loop started');
703
-
726
+
704
727
  if (window.mobileDebug) {
705
728
  window.mobileDebug.log(`✅ Quantum Engine: Render loop started, will render when isActive=true`);
706
729
  }
@@ -777,6 +800,20 @@ export class QuantumEngine {
777
800
  destroy() {
778
801
  this.isActive = false;
779
802
 
803
+ // Cancel render loop
804
+ this._renderLoopActive = false;
805
+ if (this._renderRafId) {
806
+ cancelAnimationFrame(this._renderRafId);
807
+ this._renderRafId = null;
808
+ }
809
+
810
+ // Cancel effects loop
811
+ this._effectsLoopActive = false;
812
+ if (this._effectsRafId) {
813
+ cancelAnimationFrame(this._effectsRafId);
814
+ this._effectsRafId = null;
815
+ }
816
+
780
817
  // Disconnect from universal reactivity
781
818
  if (window.universalReactivity) {
782
819
  window.universalReactivity.disconnectSystem('quantum');
@@ -276,6 +276,7 @@ uniform float u_rot4dZW;
276
276
  uniform float u_mouseIntensity;
277
277
  uniform float u_clickIntensity;
278
278
  uniform float u_roleIntensity;
279
+ uniform float u_breath;
279
280
 
280
281
  // 6D rotation matrices - 3D space rotations (XY, XZ, YZ)
281
282
  mat4 rotateXY(float theta) {
@@ -681,7 +682,9 @@ void main() {
681
682
  geometryIntensity += shimmer * geometryIntensity;
682
683
 
683
684
  // Apply user intensity control
684
- float finalIntensity = geometryIntensity * u_intensity;
685
+ // Breath modulation (Exhale system)
686
+ float breathMod = 1.0 + (u_breath * 0.4);
687
+ float finalIntensity = geometryIntensity * u_intensity * breathMod;
685
688
 
686
689
  // LAYER-BY-LAYER COLOR SYSTEM with user hue/saturation/intensity controls
687
690
  // Determine canvas layer from role/variant (0=background, 1=shadow, 2=content, 3=highlight, 4=accent)
@@ -792,7 +795,8 @@ void main() {
792
795
  rot4dZW: this.gl.getUniformLocation(this.program, 'u_rot4dZW'),
793
796
  mouseIntensity: this.gl.getUniformLocation(this.program, 'u_mouseIntensity'),
794
797
  clickIntensity: this.gl.getUniformLocation(this.program, 'u_clickIntensity'),
795
- roleIntensity: this.gl.getUniformLocation(this.program, 'u_roleIntensity')
798
+ roleIntensity: this.gl.getUniformLocation(this.program, 'u_roleIntensity'),
799
+ breath: this.gl.getUniformLocation(this.program, 'u_breath')
796
800
  };
797
801
  }
798
802
 
@@ -1065,6 +1069,7 @@ void main() {
1065
1069
  this.gl.uniform1f(this.uniforms.mouseIntensity, this.mouseIntensity);
1066
1070
  this.gl.uniform1f(this.uniforms.clickIntensity, this.clickIntensity);
1067
1071
  this.gl.uniform1f(this.uniforms.roleIntensity, roleIntensities[this.role] || 1.0);
1072
+ this.gl.uniform1f(this.uniforms.breath, this.params.breath || 0.0);
1068
1073
 
1069
1074
  this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);
1070
1075
  }
@@ -56,6 +56,9 @@ function packVIB3Uniforms(uniforms) {
56
56
  data[22] = uniforms.u_mid || 0;
57
57
  data[23] = uniforms.u_high || 0;
58
58
 
59
+ // Breath/Vitality parameter
60
+ data[32] = uniforms.u_breath || 0;
61
+
59
62
  data[24] = uniforms.u_layerScale || 1.0;
60
63
  data[25] = uniforms.u_layerOpacity || 1.0;
61
64
  data[26] = 0; // _pad1