<!-- SOLIDABILITY-WORLD · part 57 -->
 0x222222 :
                  light.status === 'blinking' ? 0xffaa00 : 0xff2222;
    const bulbMat = new THREE.MeshStandardMaterial({
      color, emissive: color, emissiveIntensity: light.status === 'off' ? 0 : 1
    });
    const bulb = new THREE.Mesh(bulbGeo, bulbMat);
    bulb.position.set(light.position.x, light.position.y, light.position.z);
    scene.add(bulb);

    lights[light.roomKey] = { mesh: bulb, mat: bulbMat, status: light.status, phase: 0 };
  }

  function buildVertical(scene, layout) {
    // Staircase (simple steps)
    const stepMat = new THREE.MeshStandardMaterial({ color: 0x3a3a4a });
    for (let i = 0; i < 8; i++) {
      const step = new THREE.Mesh(new THREE.BoxGeometry(3, 0.5, 1), stepMat);
      step.position.set(
        layout.stairs.position.x,
        i * 1,
        layout.stairs.position.z - i * 1
      );
      scene.add(step);
    }
    // Landing platform at top of stairs (connects to floor 1)
    const landingGeo = new THREE.BoxGeometry(4, 0.5, 4);
    const landing = new THREE.Mesh(landingGeo, stepMat);
    landing.position.set(
      layout.stairs.position.x,
      layout.building.floorHeight - 0.25,
      layout.stairs.position.z - 9
    );
    landing.receiveShadow = true;
    scene.add(landing);
    addLabel(scene, "STAIRS", layout.stairs.position.x, 9, layout.stairs.position.z, 0x888899, 1);

    // Elevator (simple shaft)
    const shaftGeo = new THREE.BoxGeometry(3, 16, 3);
    const shaftMat = new THREE.MeshStandardMaterial({
      color: 0x2a3a4a, transparent: true, opacity: 0.4
    });
    const shaft = new THREE.Mesh(shaftGeo, shaftMat);
    shaft.position.set(layout.elevator.position.x, 8, layout.elevator.position.z);
    scene.add(shaft);
    addLabel(scene, "ELEVATOR", layout.elevator.position.x, 17, layout.elevator.position.z, 0x888899, 1);
  }

  // Labels: always face camera, render on top of geometry (never hidden behind walls)
  const labelMeshes = [];
  function addLabel(scene, text, x, y, z, color, size) {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    canvas.width = 512; canvas.height = 64;
    ctx.fillStyle = '#00000000';
    ctx.fillRect(0, 0, 512, 64);
    ctx.font = 'bold 30px monospace';
    // Dark outline for readability
    ctx.strokeStyle = '#000000';
    ctx.lineWidth = 4;
    ctx.textAlign = 'center';
    ctx.strokeText(text, 256, 42);
    ctx.fillStyle = '#' + color.toString(16).padStart(6, '0');
    ctx.fillText(text, 256, 42);

    const tex = new THREE.CanvasTexture(canvas);
    const mat = new THREE.MeshBasicMaterial({
      map: tex, transparent: true, depthTest: false
    });
    const mesh = new THREE.Mesh(new THREE.PlaneGeometry(size * 4, size), mat);
    mesh.position.set(x, y, z);
    mesh.renderOrder = 999; // always on top
    scene.add(mesh);
    labelMeshes.push(mesh);
  }

  // Billboarding: labels face camera every frame
  function updateLabels() {
    const camera = SWEngine.getCamera();
    if (!camera) return;
    labelMeshes.forEach(mesh => {
      mesh.quaternion.copy(camera.quaternion);
    });
  }

  function update(dt) {
    // Animate blinking lights
    Object.values(lights).forEach(light => {
      if (light.status === 'blinking') {
        light.phase += dt * 4;
        const on = Math.sin(light.phase) > 0;
        light.mat.emissiveIntensity = on ? 1.5 : 0.2;
      }
    });

    // Labels face camera
    updateLabels();

    // Proximity detection: show glass when near a room
    checkProximity();
  }

  function checkProximity() {
    const player = SWEngine.getPlayer();
    if (!player || !layout) return;

    let nearest = null, nearestDist = 8;
    layout.rooms.forEach(room => {
      const dx = player.position.x - room.position.x;
      const dz = player.position.z - room.position.z;
      const dy = Math.abs(player.position.y - room.position.y);
      const dist = Math.sqrt(dx * dx + dz * dz);
      if (dist < nearestDist && dy < 5) {
        nearest = room; nearestDist = dist;
      }
    });

    if (nearest && nearest.key !== selectedRoom) {
      selectedRoom = nearest.key;
      SWGlass.show(nearest);
    } else if (!nearest && selectedRoom) {
      selectedRoom = null;
      SWGlass.hide();
    }
  }

  function setupSelection() {
    // Tap/click to select buildings and walls — raycast from tap point
    const raycaster = new THREE.Raycaster();
    const tapPoint = new THREE.Vector2();
    let tapStart = 0;

    const container = document.getElementById('scene-container');

    container.addEventListener('touchstart', e => {
      tapStart = Date.now();
    }, { passive: true });

    container.addEventListener('touchend', e => {
      // Only treat as tap if short duration and minimal movement
      if (Date.now() - tapStart > 300) return;
      if (e.changedTouches.length !== 1) return;
      const touch = e.changedTouches[0];
      handleTap(touch.clientX, touch.clientY);
    }, { passive: true });

  