<!-- SOLIDABILITY-WORLD · part 29 -->
nst hasTest = room.has_test;
    const sizeKB = room.size_bytes ? (room.size_bytes / 1024).toFixed(1) : '?';

    html += '<div class="file-meta" style="margin-top:12px;">';
    html += '<h4 style="color:#aaa;margin:0 0 8px 0;">📊 File Data</h4>';
    html += `<p style="font-size:12px;color:#999;line-height:1.8;">`;
    html += `Size: ${sizeKB} KB · Lines: ${room.lines || '?'}<br>`;
    if (ageDays >= 0) {
      const ageStr = ageDays < 1 ? 'today' : ageDays < 30 ? `${Math.round(ageDays)}d ago` : `${Math.round(ageDays/30)}mo ago`;
      html += `Modified: ${ageStr}<br>`;
    }
    html += `Tests: ${hasTest ? '<span class="good">✓ found</span>' : '<span class="warn">✗ none found</span>'}`;
    // Risk signal: complex + untested + recently changed = high risk
    const riskCx = room.complexity || 0;
    if (riskCx > 500 && !hasTest) {
      html += `<br><span class="risk">⚠️ High risk: complex (${riskCx}) + untested</span>`;
    }
    html += `</p></div>`;

    // Code quality notes (AI best-practice perspective)
    html += '<div class="code-quality" style="margin-top:12px;"><h4 style="color:#aaa;margin:0 0 8px 0;">Code Health</h4>';
    const cx = room.complexity || 0;
    const fixes = [];

    if (cx > 1000) {
      html += `<p><span class="risk">⚠️ High complexity (${cx})</span></p>`;
      fixes.push({
        title: 'Split by responsibility',
        steps: [
          '1. List the route groups (admin, forum, auth, etc.)',
          '2. Create lib/api/{group}.js for each group',
          '3. Move routes + their helpers into each module',
          '4. Export a router from each, mount in server.js',
          '5. Verify: all routes still respond, no 404s',
        ],
      });
    } else if (cx > 200) {
      html += `<p><span class="warn">⚡ Moderate complexity (${cx})</span></p>`;
      fixes.push({
        title: 'Extract helpers',
        steps: [
          '1. Identify repeated logic blocks',
          '2. Move to named functions at top of file',
          '3. Reduce nesting: early returns instead of deep if/else',
        ],
      });
    } else {
      html += `<p><span class="good">✓ Healthy complexity (${cx})</span></p>`;
    }

    if (deps.length > 15) {
      html += `<p><span class="warn">⚡ ${deps.length} dependencies — high coupling</span></p>`;
      fixes.push({
        title: 'Reduce coupling',
        steps: [
          '1. List all ' + deps.length + ' imports',
          '2. Group by purpose (db, views, utils, etc.)',
          '3. Create facade modules that re-export related imports',
          '4. File imports 3-5 facades instead of ' + deps.length + ' individuals',
        ],
      });
    }

    const routeCount = routes.length;
    if (routeCount > 50) {
      html += `<p><span class="risk">⚠️ ${routeCount} routes in one file</span></p>`;
      fixes.push({
        title: 'Thin route handlers',
        steps: [
          '1. Each route handler should be <20 lines',
          '2. Move business logic to lib/services/{domain}.js',
          '3. Routes become: validate input → call service → send response',
          '4. Test: each service function independently',
        ],
      });
    }

    if (!hasTest && cx > 200) {
      fixes.push({
        title: 'Add test coverage',
        steps: [
          '1. Create test file mirroring source structure',
          '2. Test happy path first (does it work at all?)',
          '3. Test error paths (what if input is bad?)',
          '4. Test edge cases (empty, null, oversized)',
          '5. Target: 80% of branches covered',
        ],
      });
    }

    // Render fix guides
    if (fixes.length > 0) {
      html += '<div class="fix-guides" style="margin-top:12px;">';
      html += '<h4 style="color:#00ffcc;margin:0 0 8px 0;">🔧 How to Fix</h4>';
      fixes.forEach((fix, idx) => {
        html += `<div class="fix-guide" style="margin-bottom:12px;background:rgba(0,255,204,0.05);border-radius:8px;padding:10px;">`;
        html += `<p style="color:#00ffcc;font-weight:bold;margin:0 0 6px 0;font-size:13px;">${fix.title}</p>`;
        html += fix.steps.map(s =>
          `<p style="font-size:12px;color:#bbb;margin:3px 0;line-height:1.5;">${escapeHtml(s)}</p>`
        ).join('');
        html += `</div>`;
      });
      html += '</div>';
    }

    // Outdated patterns: modernization candidates (NOT defects)
    // Per GPT-6: classify honestly — old syntax isn't broken without evidence
    const patterns = room.outdated_patterns || [];
    if (patterns.length > 0) {
      // Group by category
      const byCat = {};
      patterns.forEach(p => {
        const cat = p.category || 'stylistic';
        if (!byCat[cat]) byCat[cat] = [];
        byCat[cat].push(p);
      });

      html += '<div class="modernize-section" style="margin-top:12px;">';
      html += '<h4 style="color:#ffaa44;margin:0 0 8px 0;">🔄 Modernization Candidates</h4>';
      html += '<p style="font-size:11px;color:#666;margin-bottom: