<!-- SOLIDABILITY-WORLD · part 37 -->
anged. Active. Being worked on.'],
      ['⬛ Ground', 'Stable. Untouched. Background.'],
      ['⚠️ Risk', 'Might break. Needs attention.'],
      ['🔀 Branch', 'A path code can take. A choice point.'],
      ['🔗 Connection', 'How pieces link together.'],
    ];

    let html = '<div class="glossary-panel"><h3>📖 Shared Language</h3>';
    html += '<p style="font-size:12px;color:#888;">Words we both use to talk about your website:</p>';
    terms.forEach(([term, def]) => {
      html += `<div class="glossary-term"><strong>${term}</strong><span>${def}</span></div>`;
    });
    html += '<button class="guide-btn" onclick="SWGuide.hideGlossary()">Close</button></div>';

    let panel = document.getElementById('glossary-panel');
    if (!panel) {
      panel = document.createElement('div');
      panel.id = 'glossary-panel';
      document.getElementById('app').appendChild(panel);
    }
    panel.innerHTML = html;
    panel.classList.add('visible');
  }

  function hideGlossary() {
    const panel = document.getElementById('glossary-panel');
    if (panel) panel.classList.remove('visible');
  }

  function isGuiding() { return guiding; }

  return {
    startTour, next, previous, stop, explain,
    humanDescription, humanName, isGuiding,
    showGlossary, hideGlossary,
  };
})();


===== FILE: public/solidability-world/js/sw-hyper.js =====
// Solidability World — Hyper Controller + AI DRIVE
// Extends the existing joystick with: LOOK, FOCUS, SCAN, NAVIGATE, RETURN, AI DRIVE.
// The joystick stays. This adds intelligence on top of movement.
// Principle: make the website understandable through movement.

const SWHyper = (() => {
  let mode = 'WALK'; // WALK | LOOK | AI_DRIVE
  let aiDriving = false;
  let navPath = []; // waypoints for navigation
  let navIndex = 0;
  let navigating = false;
  let lookYaw = 0, lookPitch = 0.3;
  let focusedRoom = null;
  let history = []; // return stack
  let scanPulse = null;
  let tourQueue = []; // guided tour rooms
  let tourIndex = 0;
  let touring = false;

  // Dynamic graph for full architectural map
  // Nodes: buildings + district centers. Edges: proximity-based (walkable).
  function buildFullMapGraph(layout) {
    const nodes = {};
    const edges = {};

    // Spawn at center
    nodes['spawn'] = { x: 0, y: 0, z: 0 };
    edges['spawn'] = [];

    // District centers as waypoints
    (layout.districts || []).forEach((d, idx) => {
      const key = 'district_' + idx;
      nodes[key] = { x: d.position.x, y: 0, z: d.position.z };
      edges[key] = [];
      // Connect to spawn and neighboring districts
      edges['spawn'].push(key);
      edges[key].push('spawn');
      if (idx > 0) {
        const prevKey = 'district_' + (idx - 1);
        edges[key].push(prevKey);
        edges[prevKey].push(key);
      }
    });

    // No districts (public world): open ground, so spawn links straight to every building.
    const noDistricts = !(layout.districts && layout.districts.length);
    // Buildings as nodes
    layout.rooms.filter(r => r.position).forEach(room => {
      if (noDistricts) { edges['spawn'].push(room.key); }
      const key = room.key;
      nodes[key] = { x: room.position.x, y: 0, z: room.position.z };
      edges[key] = noDistricts ? ['spawn'] : [];

      // Connect to nearest district center
      let nearestDist = null, nearestD = Infinity;
      (layout.districts || []).forEach((d, idx) => {
        const dist = Math.hypot(d.position.x - room.position.x, d.position.z - room.position.z);
        if (dist < nearestD) { nearestD = dist; nearestDist = 'district_' + idx; }
      });
      if (nearestDist) {
        edges[key].push(nearestDist);
        edges[nearestDist].push(key);
      }

      // Connect to nearby buildings (within 25 units = walkable)
      layout.rooms.forEach(other => {
        if (other.key === room.key || !other.position) return;
        const dist = Math.hypot(
          other.position.x - room.position.x,
          other.position.z - room.position.z
        );
        if (dist < 25 && dist > 0.1) {
          edges[key].push(other.key);
        }
      });
    });

    return { nodes, edges };
  }

  // Waypoint graph for pathfinding (respects walls, doors, stairs)
  function buildGraph() {
    const layout = SWWorld.getLayout();
    if (!layout) return null;

    // Full map AND the public world (no building/floors) use the dynamic graph.
    // 2026-10-09 fix: public layout has no `building` -> floorHeight crash.
    if (layout.fullMap || layout.public || !layout.building) {
      return buildFullMapGraph(layout);
    }

    const fh = layout.building.floorHeight;

    // Nodes: key -> {x, y, z}
    const nodes = {
      spawn: { x: 0, y: 0, z: -15 },
      hall_w: { x: -20, y: 0, z: -14 },
      hall_e: { x: 22, y: 0, z: -14 },
      auth_door: { x: -20, y: 0, z: -10 },
      forum_door: { x: 5, y: 0, z: -10 },
      stair_base: { x: 22, y: 0, z: -10 },
      stair_top: { x: 22, y: fh,