<!-- SOLIDIVISM · part 43 -->
===================================
   SOLIDIVISM FOUNDATION v1.0
   The most impressive kind — clean, solid, unbreakable.
   Claimed by The King, October 8, 2026.
   
   Principles:
   1. Everything visible IS solid. Everything solid IS visible.
   2. No separation between render and collision — one system.
   3. Built to be seen. Built to hold.
   ============================================================ */

const Solidivism = (function() {
  'use strict';

  let scene, camera, renderer, player;
  let colliders = [];
  let buildings = [];
  let labelMeshes = [];

  // ── INIT: The foundation ──
  function init(containerId) {
    const container = document.getElementById(containerId);
    
    // Scene: dark tactical void
    scene = new THREE.Scene();
    scene.background = new THREE.Color(0x0a0a0e);
    
    // Camera: cinematic third-person
    camera = new THREE.PerspectiveCamera(
      60, window.innerWidth / window.innerHeight, 0.1, 500
    );
    camera.position.set(0, 12, 83); // Behind avatar at new spawn
    
    // Renderer: maximum quality
    renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(container.clientWidth, container.clientHeight);
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
    container.appendChild(renderer.domElement);
    
    // Lights: dramatic tactical lighting
    const ambient = new THREE.AmbientLight(0xffffff, 0.4);
    scene.add(ambient);
    
    const keyLight = new THREE.DirectionalLight(0xff3333, 1.2);
    keyLight.position.set(30, 50, 30);
    scene.add(keyLight);
    
    const fillLight = new THREE.DirectionalLight(0x3388ff, 0.5);
    fillLight.position.set(-30, 20, -30);
    scene.add(fillLight);
    
    const rimLight = new THREE.PointLight(0xff0000, 1.2, 150);
    rimLight.position.set(0, 10, 0);
    scene.add(rimLight);
    
    // Ground: tactical grid
    createGround();
    
    // Player: the avatar
    createPlayer();
    
    // Start the loop
    animate();
    
    // Handle resize
    window.addEventListener('resize', onResize);
  }

  // ── GROUND: Futuristic motherboard floor (seamless 4-side loop) ──
  function createMotherboardTexture() {
    const S = 512;
    const c = document.createElement('canvas');
    c.width = S; c.height = S;
    const x = c.getContext('2d');
    
    // PCB base: deep black-green
    x.fillStyle = '#0a0f0a';
    x.fillRect(0, 0, S, S);
    
    // Subtle PCB texture noise
    x.fillStyle = '#0d130d';
    for (let i = 0; i < 200; i++) {
      const px = Math.floor(Math.random() * S);
      const py = Math.floor(Math.random() * S);
      x.fillRect(px, py, 2, 2);
    }
    
    // Circuit traces: red copper lines (keep away from edges for seamless loop)
    const M = 24; // margin — nothing crosses the edge
    x.strokeStyle = '#CC0000';
    x.lineWidth = 3;
    
    // Horizontal traces
    const hLines = [80, 150, 230, 320, 410, 470];
    hLines.forEach(y => {
      x.beginPath();
      x.moveTo(M, y);
      // Zigzag like real motherboard traces
      let cx = M;
      while (cx < S - M - 40) {
        const seg = 40 + Math.random() * 60;
        x.lineTo(cx + seg, y);
        if (Math.random() > 0.5 && cx + seg < S - M - 40) {
          const dy = (Math.random() > 0.5 ? 1 : -1) * 30;
          x.lineTo(cx + seg, y + dy);
          x.lineTo(cx + seg + 30, y + dy);
          x.lineTo(cx + seg + 30, y);
          cx += seg + 30;
        } else {
          cx += seg;
        }
      }
      x.lineTo(S - M, y);
      x.stroke();
    });
    
    // Vertical traces
    const vLines = [70, 140, 250, 340, 430];
    vLines.forEach(px => {
      x.beginPath();
      x.moveTo(px, M);
      let cy = M;
      while (cy < S - M - 40) {
        const seg = 40 + Math.random() * 60;
        x.lineTo(px, cy + seg);
        cy += seg;
      }
      x.lineTo(px, S - M);
      x.stroke();
    });
    
    // Vias: connection points (red dots with dark centers)
    x.fillStyle = '#FF0000';
    for (let i = 0; i < 40; i++) {
      const px = M + Math.random() * (S - 2 * M);
      const py = M + Math.random() * (S - 2 * M);
      x.beginPath(); x.arc(px, py, 6, 0, 7); x.fill();
      x.fillStyle = '#0a0f0a';
      x.beginPath(); x.arc(px, py, 3, 0, 7); x.fill();
      x.fillStyle = '#FF0000';
    }
    
    // Chip pads: rectangles (like CPU sockets)
    x.strokeStyle = '#FF3333';
    x.lineWidth = 2;
    const chips = [[100, 100, 80, 60], [300, 250, 100, 80], [150, 380, 70, 50], [380, 120, 60, 60]];
    chips.forEach(([cx, cy, w, h]) => {
      x.strokeRect(cx - w/2, cy - h/2, w, h);
      // Inner pins
      x.fillStyle = '#FF0000';
      for (let px = cx - w/2 + 8; px < cx + w/2 - 4; px += 12) {
        x.fillRect(px, cy - h/2 - 4, 6, 4);
        x.fillRect(px, cy + h/2, 6, 4);
      }
    });
    
    // Glowing red edge frame (seamless — same on all sides)
    x.strokeStyle = '#FF0000';
    x.lineWidth = 4;
    x.strokeRect(2, 2, S-4, S-4);
    x.strokeStyl