<!-- SOLIDABILITY-WORLD · part 49 -->

      case 'untested': return 'off';
      case 'rough': return 'blinking';
      case 'defect': return 'solid';
      default: return 'off';
    }
  }

  // Stable identifier: derived from source identity, survives regeneration
  // Both Solid and ChatGPT reference stable_id, never coordinates
  function stableId(componentId) {
    const h = hashStr(componentId);
    return h.toString(16).padStart(8, '0');
  }

  return { generateLayout, complexityScore, verificationToLight, stableId };
})();


===== FILE: public/solidability-world/js/sw-map.js =====
// Solidability World — Full Map Loader
// Fetches the server-generated architectural map (authenticated, server-side analysis).
// Falls back to prototype data if the full map is unavailable.

const SWMap = (() => {
  let fullMap = null;
  let loading = false;
  let loadCallbacks = [];

  async function load() {
    if (fullMap) return fullMap;
    if (loading) {
      return new Promise(resolve => loadCallbacks.push(resolve));
    }
    loading = true;

    try {
      const resp = await fetch('/api/solidability-world/map', {
        credentials: 'same-origin',
        headers: { 'Accept': 'application/json' }
      });
      if (resp.ok) {
        fullMap = await resp.json();
        console.log(`Full map loaded: ${fullMap.total_files} files, ${fullMap.total_routes} routes`);
      } else {
        console.log('Full map not available, using prototype data');
      }
    } catch (e) {
      console.log('Map fetch failed, using prototype data:', e.message);
    }

    loading = false;
    loadCallbacks.forEach(cb => cb(fullMap));
    loadCallbacks = [];
    return fullMap;
  }

  function get() { return fullMap; }
  function hasFullMap() { return !!fullMap; }

  // Convert full map to layout using the universal geometry engine
  // (Deterministic, explainable, not Epistles-specific)
  function toLayout() {
    if (!fullMap) return null;
    // Use SWGeometry if available, else fall back to legacy
    if (typeof SWGeometry !== 'undefined') {
      const layout = SWGeometry.mapToWorld(fullMap);
      SWGeometry.applyHierarchy(layout, fullMap);
      return layout;
    }
    return legacyToLayout();
  }

  // Legacy layout (kept as fallback)
  function legacyToLayout() {
    if (!fullMap) return null;

    const layout = {
      building: { width: 400, depth: 400, floors: 1, floorHeight: 8 },
      rooms: [],      // files become "rooms" (buildings)
      districts: [],  // directories become districts
      lights: [],
      doors: [],
      stairs: { position: { x: 0, y: 0, z: -190 } },
      elevator: { position: { x: 6, y: 0, z: -190 } },
      hallways: [],
      fullMap: true,
    };

    // Sort directories by complexity (largest first, placed centrally)
    const dirs = Object.values(fullMap.directories)
      .sort((a, b) => b.complexity - a.complexity);

    // Grid layout for districts
    const cols = Math.ceil(Math.sqrt(dirs.length));
    const districtSpacing = 80;
    let dx = 0, dz = 0;

    dirs.forEach((dir, dirIdx) => {
      const gx = (dirIdx % cols) - (cols - 1) / 2;
      const gz = Math.floor(dirIdx / cols) - (Math.ceil(dirs.length / cols) - 1) / 2;
      const districtX = gx * districtSpacing;
      const districtZ = gz * districtSpacing;

      layout.districts.push({
        name: dir.path,
        position: { x: districtX, z: districtZ },
        fileCount: dir.file_count,
        complexity: dir.complexity,
      });

      // Files within district — arranged in sub-grid
      const files = dir.files.slice(0, 50); // cap at 50 per district for perf
      const fcols = Math.ceil(Math.sqrt(files.length));
      const fileSpacing = 12;

      files.forEach((file, fileIdx) => {
        const fx = (fileIdx % fcols) - (fcols - 1) / 2;
        const fz = Math.floor(fileIdx / fcols) - (Math.ceil(files.length / fcols) - 1) / 2;

        // Building size from complexity (not line count)
        const size = Math.max(4, Math.min(16, 4 + file.complexity * 0.15));
        const height = Math.max(3, Math.min(20, 3 + file.complexity * 0.2));

        const roomKey = 'file_' + file.path.replace(/[^a-zA-Z0-9]/g, '_');
        layout.rooms.push({
          key: roomKey,
          stable_id: 'epistles:file:' + file.path,
          component_id: 'epistles:file:' + file.path,
          label: file.name,
          filePath: file.path,
          floor: 0,
          district: dir.path,
          position: {
            x: districtX + fx * fileSpacing,
            y: 0,
            z: districtZ + fz * fileSpacing,
          },
          size: { width: size, depth: size, height: height },
          routes: file.routes.map(r => ({
            name: `${r.method} ${r.path}`,
            line: r.line,
            type: 'route',
          })),
          functions: file.functions,
          dependencies: file.dependencies,
          verification: { status: 'untested', note: 'Not yet verified' },
          complexity: file.c