<!-- SOLID CITY · part 79 -->
.x * scale, oy + L.y * scale, W, H); res(); } catch (e) { rej(e); } };
    img.onerror = function () { rej(new Error('layer image failed')); };
    img.src = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(svg);
  });
}
function blurRegion(ctx, g, scale, ox, oy) {
  var x = Math.round(ox + g.x * scale), y = Math.round(oy + g.y * scale), w = Math.round(g.w * scale), h = Math.round(g.h * scale); if (w < 2 || h < 2) return;
  var rad = g.blur * scale, f = Math.max(2, Math.min(24, rad / 2)), sw = Math.max(1, Math.round(w / f)), sh = Math.max(1, Math.round(h / f)), m = Math.ceil(rad);
  var t = document.createElement('canvas'); t.width = sw + 4; t.height = sh + 4; var tx = t.getContext('2d'); tx.imageSmoothingEnabled = true; tx.imageSmoothingQuality = 'high';
  tx.drawImage(ctx.canvas, x - m, y - m, w + 2 * m, h + 2 * m, 0, 0, sw + 4, sh + 4);                // downscale = box blur
  var t2 = document.createElement('canvas'); t2.width = Math.max(1, sw >> 1) + 2; t2.height = Math.max(1, sh >> 1) + 2; var t2x = t2.getContext('2d'); t2x.imageSmoothingQuality = 'high'; t2x.drawImage(t, 0, 0, t2.width, t2.height);
  ctx.save(); ctx.beginPath(); var r = g.r * scale; if (ctx.roundRect) ctx.roundRect(x, y, w, h, r); else ctx.rect(x, y, w, h); ctx.clip();
  ctx.imageSmoothingEnabled = true; ctx.imageSmoothingQuality = 'high'; ctx.drawImage(t2, x - m, y - m, w + 2 * m, h + 2 * m); ctx.restore();
}
/* top-level layers: visible children of the HUD and the #sc overlays, in paint order */
function layers(exclude) {
  var sc = document.getElementById('sc') || document.body, out = [], idx = 0;
  function z(el) { var v = parseInt(getComputedStyle(el).zIndex, 10); return isNaN(v) ? 0 : v; }
  [].forEach.call(sc.children, function (top) {
    if (top.tagName === 'CANVAS' || exclude(top) || !top.getClientRects().length) return;
    if (top.id === 'sc-hud') { var hz = z(top); [].forEach.call(top.children, function (el) { idx++; if (!exclude(el) && shown(el)) out.push({ el: el, k: [hz, z(el), idx] }); }); }
    else { idx++; if (shown(top)) out.push({ el: top, k: [z(top), 0, idx] }); }
  });
  [].forEach.call(document.body.children, function (el) { if (el !== sc && !exclude(el) && /^(DIV|SECTION|ASIDE|NAV|DIALOG)$/.test(el.tagName) && getComputedStyle(el).position !== 'static' && shown(el)) out.push({ el: el, k: [z(el), 0, ++idx] }); });
  out.sort(function (a, b) { return a.k[0] - b.k[0] || a.k[1] - b.k[1] || a.k[2] - b.k[2]; });
  return out.map(function (o) { return o.el; });
}
/* compose the visible HUD + panels over a world canvas. box: where the viewport maps into the output (contain-fit). */
function compose(ctx, W, H, opts) {
  opts = opts || {}; var vw = innerWidth, vh = innerHeight, s = Math.min(W / vw, H / vh), ox = (W - vw * s) / 2, oy = (H - vh * s) / 2;
  var exclude = opts.exclude || function () { return false; }, issues = [], drawn = 0, t0 = performance.now();
  var list = layers(exclude), jobs = list.map(function (el) {
    var pend = [], job = { issues: issues, glass: [], exclude: exclude,
      img: function (src, node) { if (!src) return; pend.push(toDataURL(src).then(function (d) { if (d) node.setAttribute('src', d); else { node.removeAttribute('src'); issues.push('an image'); } })); },
      bg: function (cs, node) { var bi = cs.backgroundImage; if (!bi || bi.indexOf('url(') < 0) return; var urls = []; bi.replace(/url\(["']?([^"')]+)["']?\)/g, function (m, u) { urls.push(u); });
        pend.push(Promise.all(urls.map(toDataURL)).then(function (ds) { var i = 0, v = bi.replace(/url\(["']?([^"')]+)["']?\)/g, function () { var d = ds[i++]; return d ? 'url("' + d + '")' : 'none'; }); node.setAttribute('style', (node.getAttribute('style') || '').replace(/background-image:[^;]*;/, 'background-image:' + v + ';')); })); } };
    var L = null; try { L = layerSvg(el, s, job); } catch (e) { issues.push((el.id || el.className || el.tagName) + ': ' + e.message); }
    return { el: el, L: L, job: job, pend: pend };
  });
  return jobs.reduce(function (p, j) {
    return p.then(function () {
      if (!j.L) return;
      return Promise.all(j.pend).then(function () {
        j.job.glass.forEach(function (g) { try { blurRegion(ctx, g, s, ox, oy); } catch (e) {} });
        var html = new XMLSerializer().serializeToString(j.L.clone);
        return fontsCss(html).then(function (fonts) { return drawSvg(ctx, j.L, s, ox, oy, fonts); }).then(function () { drawn++; })
          .catch(function (e) { issues.push((j.el.id || String(j.el.className).split(' ')[0] || j.el.tagName.toLowerCase()) + ' could not be drawn'); });
      });
    });
  }, Promise.resolve()).then(function () { return { layers: list.length, drawn: drawn, issues: issues, ms: Math.round(performance.now() - t0), scale: s, box: [ox, oy, vw * s, vh * s] }; });
}
window.CityDomShot = { compose: compose, layers: layers };
})();


===== FILE: public/city/capture-dom.js.bak-mq-20261011 =====
/* Solid City capture: WORLD + MENUS (2026-1