    const vscode = acquireVsCodeApi();
    let report = null;
    let activeTab = "fingerprints";
    let currentSource = "perfSchema";

    function loadFromPerfSchema() {
      const timeValEl = document.getElementById("perfSchemaTimeValue");
      const timeUnitEl = document.getElementById("perfSchemaTimeUnit");
      const limitEl = document.getElementById("perfSchemaLimit");
      const sortByEl = document.getElementById("perfSchemaSortBy");
      const minAvgEl = document.getElementById("pgMinAvgTimeMs");
      const dbEl = document.getElementById("pgStatDatabase");
      const workloadDbEl = document.getElementById("pgWorkloadDatabase");
      const timeValue = Number((timeValEl && timeValEl.value) || 1);
      const timeUnit = (timeUnitEl && timeUnitEl.value) || "days";
      const limit = Number((limitEl && limitEl.value) || 10000);
      const sortBy = (sortByEl && sortByEl.value) || "totalTime";
      const minAvgTimeMs = minAvgEl ? Number(minAvgEl.value || 0) : 0;
      const hostDatabase = dbEl ? String(dbEl.value || "").trim() : "";
      const filterDatabase = workloadDbEl ? String(workloadDbEl.value || "").trim() : "";
      vscode.postMessage({ command: "loadFromPerfSchema", timeValue, timeUnit, limit, sortBy, minAvgTimeMs, hostDatabase, filterDatabase });
    }
    function loadFromTable() {
      const timeValEl = document.getElementById("tableTimeValue");
      const timeUnitEl = document.getElementById("tableTimeUnit");
      const limitEl = document.getElementById("tableLimit");
      const sortByEl = document.getElementById("tableSortBy");
      const timeValue = Number((timeValEl && timeValEl.value) || 1);
      const timeUnit = (timeUnitEl && timeUnitEl.value) || "days";
      const limit = Number((limitEl && limitEl.value) || 10000);
      const sortBy = (sortByEl && sortByEl.value) || "totalTime";
      vscode.postMessage({ command: "loadFromTable", timeValue, timeUnit, limit, sortBy });
    }
    function enableSlowQueryLog() { vscode.postMessage({ command: "enableSlowQueryLog" }); }
    function formatSize(bytes) {
      if (!bytes || bytes < 0) return "";
      if (bytes < 1024) return bytes + " B";
      if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + " KB";
      return (bytes / (1024 * 1024)).toFixed(1) + " MB";
    }
    function loadFromDetectedPath() {
      const inputEl = document.getElementById("tailLinesInput");
      const tailLines = inputEl ? Math.min(100000, Math.max(1000, parseInt(inputEl.value, 10) || 10000)) : undefined;
      vscode.postMessage({ command: "loadFromDetectedPath", tailLines });
    }
    window.loadFromPerfSchema = loadFromPerfSchema;
    window.loadFromTable = loadFromTable;
    window.enableSlowQueryLog = enableSlowQueryLog;
    window.formatSize = formatSize;
    window.loadFromDetectedPath = loadFromDetectedPath;

    document.body.addEventListener("click", (e) => {
      const btn = e.target && e.target.closest ? e.target.closest("[data-action]") : null;
      if (btn && btn.disabled) return;
      if (btn) {
        const action = btn.getAttribute("data-action");
        if (action === "enableSlowQueryLog" || action === "loadFromDetectedPath") {
          e.preventDefault();
          e.stopPropagation();
        }
        const fn = action ? window[action] : null;
        if (typeof fn === "function") fn();
      }
    });

    let sortField = "impactScore";
    let sortDir = "desc";
    let usageSortField = "usagePct";
    let usageSortDir = "desc";
    let usageGridTab = "tables";
    let bubbleChartExpanded = true;
    let bubbleMetaByHash = {};
    let bubbleExecutionById = {};
    let bubbleColorByHash = {};

    function debugLog(message, data) { /* no-op: debug logging disabled */ }

    window.addEventListener("error", (e) => {
      debugLog("window.error", { message: e && e.message ? e.message : "", source: e && e.filename ? e.filename : "", line: e && typeof e.lineno !== "undefined" ? e.lineno : "", column: e && typeof e.colno !== "undefined" ? e.colno : "" });
    });
    window.addEventListener("unhandledrejection", (e) => {
      debugLog("unhandledrejection", { reason: String(e && e.reason ? e.reason : "") });
    });

    function loadFile() {
      vscode.postMessage({ command: "loadFile" });
    }
    function loadFilePath(path) {
      vscode.postMessage({ command: "loadFilePath", filePath: path });
    }
    function tryLoadFromPath() {
      const p = window._lastPathHintPath || "";
      if (p) loadFilePath(p);
    }
    // Ensure these handlers are accessible from inline HTML onclick="..." attributes.
    // In some webview contexts, function declarations may not bind to the expected global.
    window.loadFile = loadFile;
    window.loadFilePath = loadFilePath;
    window.tryLoadFromPath = tryLoadFromPath;

    function loadFromTable() {
      const timeValEl = document.getElementById("tableTimeValue");
      const timeUnitEl = document.getElementById("tableTimeUnit");
      const limitEl = document.getElementById("tableLimit");
      const sortByEl = document.getElementById("tableSortBy");
      const timeValue = Number((timeValEl && timeValEl.value) || 1);
      const timeUnit = (timeUnitEl && timeUnitEl.value) || "days";
      const limit = Number((limitEl && limitEl.value) || 10000);
      const sortBy = (sortByEl && sortByEl.value) || "totalTime";
      vscode.postMessage({ command: "loadFromTable", timeValue, timeUnit, limit, sortBy });
    }
    window.loadFromTable = loadFromTable;
    function enableSlowQueryLog() { vscode.postMessage({ command: "enableSlowQueryLog" }); }
    function loadFromDetectedPath() {
      const inputEl = document.getElementById("tailLinesInput");
      const tailLines = inputEl ? Math.min(100000, Math.max(1000, parseInt(inputEl.value, 10) || 10000)) : undefined;
      vscode.postMessage({ command: "loadFromDetectedPath", tailLines });
    }
    window.enableSlowQueryLog = enableSlowQueryLog;
    window.loadFromDetectedPath = loadFromDetectedPath;
    function analyzeQuery(hash) {
      const sample = (window._optimizerSamples || {})[hash];
      const database = (window._optimizerDatabases || {})[hash] || "";
      vscode.postMessage({ command: "analyzeQuery", queryHash: hash, sampleQuery: sample || "", database: database });
    }
    function analyzeQueryExplain(hash) {
      const sample = (window._optimizerSamples || {})[hash];
      const database = (window._optimizerDatabases || {})[hash] || "";
      vscode.postMessage({ command: "analyzeQueryExplain", queryHash: hash, sampleQuery: sample || "", database: database });
    }
    function analyzeQueryOptimize(hash) {
      const sample = (window._optimizerSamples || {})[hash];
      const database = (window._optimizerDatabases || {})[hash] || "";
      vscode.postMessage({ command: "analyzeQueryOptimize", queryHash: hash, sampleQuery: sample || "", database: database });
    }
    function copyFingerprintQuery(hash) {
      vscode.postMessage({ command: "copyFingerprintQuery", queryHash: hash });
    }
    function copyIndexRecommendationsForFingerprint(hash) {
      vscode.postMessage({ command: "copyIndexRecommendationsForFingerprint", queryHash: hash });
    }
    function copyRewriteTipsForFingerprint(hash) {
      vscode.postMessage({ command: "copyRewriteTipsForFingerprint", queryHash: hash });
    }
    window.analyzeQuery = analyzeQuery;
    window.analyzeQueryExplain = analyzeQueryExplain;
    window.analyzeQueryOptimize = analyzeQueryOptimize;
    window.copyFingerprintQuery = copyFingerprintQuery;
    function getTuneDatabaseFilterValue() {
      const el = document.getElementById("pgTuneDatabaseFilter");
      return el ? String(el.value || "").trim() : "";
    }
    function syncTuneDatabaseFilterToHost() {
      vscode.postMessage({ command: "setPgTuneDatabaseFilter", tuneDatabase: getTuneDatabaseFilterValue() });
    }
    function onPgTuneDatabaseFilterChange() {
      syncTuneDatabaseFilterToHost();
      applyFilter();
    }
    function populatePgTuneDatabaseFilter(report, selectedDb) {
      const wrap = document.getElementById("pgTuneDatabaseWrap");
      const select = document.getElementById("pgTuneDatabaseFilter");
      if (!wrap || !select) return;
      const isPg = document.body.classList.contains("pg-engine");
      if (!isPg || !report) {
        wrap.classList.add("hidden");
        return;
      }
      const seen = {};
      const names = [];
      (report.fingerprints || []).forEach(function(r) {
        const dbList = Array.isArray(r.databases) ? r.databases : [];
        dbList.forEach(function(d) {
          const name = String(d || "").trim();
          if (!name || seen[name]) return;
          if (/^(mysql|performance_schema|information_schema|sys)$/i.test(name)) return;
          seen[name] = true;
          names.push(name);
        });
      });
      names.sort(function(a, b) { return a.localeCompare(b); });
      if (names.length <= 1) {
        wrap.classList.add("hidden");
        select.value = "";
        syncTuneDatabaseFilterToHost();
        return;
      }
      wrap.classList.remove("hidden");
      const prev = String(select.value || "").trim();
      select.innerHTML = "";
      const allOpt = document.createElement("option");
      allOpt.value = "";
      allOpt.textContent = "All databases";
      select.appendChild(allOpt);
      names.forEach(function(name) {
        const opt = document.createElement("option");
        opt.value = name;
        opt.textContent = name;
        select.appendChild(opt);
      });
      const pick = String(selectedDb || "").trim();
      const next = pick && names.indexOf(pick) >= 0
        ? pick
        : (prev && names.indexOf(prev) >= 0 ? prev : "");
      select.value = next;
      syncTuneDatabaseFilterToHost();
    }
    window.onPgTuneDatabaseFilterChange = onPgTuneDatabaseFilterChange;
    function optimizeAllQueries() {
      vscode.postMessage({ command: "optimizeAllQueries", tuneDatabase: getTuneDatabaseFilterValue() });
    }
    function expertIndexesDDL() {
      vscode.postMessage({ command: "expertIndexesDDL", tuneDatabase: getTuneDatabaseFilterValue() });
    }
    function createIndexes() {
      vscode.postMessage({ command: "createIndexes", tuneDatabase: getTuneDatabaseFilterValue() });
    }
    function createIndexesValidate() {
      vscode.postMessage({ command: "createIndexesValidate", tuneDatabase: getTuneDatabaseFilterValue() });
    }
    window.optimizeAllQueries = optimizeAllQueries;
    window.expertIndexesDDL = expertIndexesDDL;
    window.createIndexes = createIndexes;
    window.createIndexesValidate = createIndexesValidate;
    window.toggleBubbleChart = toggleBubbleChart;

    function toggleCreateDropdown() {
      const dd = document.getElementById("createDropdown");
      const exp = document.getElementById("exportDropdown");
      if (exp) exp.classList.add("hidden");
      if (dd) dd.classList.toggle("hidden");
    }
    function closeCreateDropdown() { const dd = document.getElementById("createDropdown"); if (dd) dd.classList.add("hidden"); }
    function toggleExportDropdown() {
      const dd = document.getElementById("exportDropdown");
      const cr = document.getElementById("createDropdown");
      if (cr) cr.classList.add("hidden");
      if (dd) dd.classList.toggle("hidden");
    }
    function closeExportDropdown() { const dd = document.getElementById("exportDropdown"); if (dd) dd.classList.add("hidden"); }
    function exportIndexesScript() {
      vscode.postMessage({ command: "expertIndexesDDL", tuneDatabase: getTuneDatabaseFilterValue() });
    }
    function copyIndexesScript() {
      vscode.postMessage({ command: "exportIndexDDLCopy", tuneDatabase: getTuneDatabaseFilterValue() });
    }
    function cancelCurrentOperation() { vscode.postMessage({ command: "cancelOperation" }); }
    window.toggleCreateDropdown = toggleCreateDropdown;
    window.closeCreateDropdown = closeCreateDropdown;
    window.toggleExportDropdown = toggleExportDropdown;
    window.closeExportDropdown = closeExportDropdown;
    window.exportIndexesScript = exportIndexesScript;
    window.copyIndexesScript = copyIndexesScript;
    window.cancelCurrentOperation = cancelCurrentOperation;

    // ── Optimizer Settings (SQO + QO tabs) ──
    let optimizerSettings = null;
    function applyOptimizerSettingsToForm(settings) {
      if (!settings) return;
      const sqo = settings.sqo || {};
      const qo = settings.qo || {};
      const sqoSampling = document.getElementById("sqoSampling");
      const sqoScope = document.getElementById("sqoOptimizeScope");
      const sqoSkip = document.getElementById("sqoSkipHighIndexCount");
      const sqoMax = document.getElementById("sqoMaxIndexCount");
      const qoSampling = document.getElementById("qoSampling");
      if (sqoSampling) sqoSampling.checked = sqo.sampling !== false;
      if (sqoScope) sqoScope.value = sqo.optimizeScope || "all";
      if (sqoSkip) sqoSkip.checked = sqo.skipHighIndexCount === true;
      if (sqoMax && typeof sqo.maxIndexCount === "number") sqoMax.value = sqo.maxIndexCount;
      if (qoSampling) qoSampling.checked = qo.sampling !== false;
    }
    function switchOptimizerSettingsTab(tab) {
      const tabs = ["sqo", "qo"];
      tabs.forEach(function(t) {
        const tabBtn = document.getElementById("settingsTab-" + t);
        const pane = document.getElementById("settingsPane-" + t);
        if (tabBtn) tabBtn.classList.toggle("active", t === tab);
        if (pane) pane.classList.toggle("hidden", t !== tab);
      });
    }
    function openOptimizerSettings() {
      const overlay = document.getElementById("optimizerSettingsOverlay");
      if (!overlay) return;
      if (optimizerSettings) applyOptimizerSettingsToForm(optimizerSettings);
      vscode.postMessage({ command: "getOptimizerSettings" });
      switchOptimizerSettingsTab("sqo");
      overlay.classList.add("visible");
    }
    function closeOptimizerSettings() {
      const overlay = document.getElementById("optimizerSettingsOverlay");
      if (overlay) overlay.classList.remove("visible");
    }
    function saveOptimizerSettings() {
      const sqoSampling = document.getElementById("sqoSampling");
      const sqoScope = document.getElementById("sqoOptimizeScope");
      const sqoSkip = document.getElementById("sqoSkipHighIndexCount");
      const sqoMax = document.getElementById("sqoMaxIndexCount");
      const qoSampling = document.getElementById("qoSampling");
      const settings = {
        sqo: {
          sampling: sqoSampling ? sqoSampling.checked : true,
          optimizeScope: sqoScope ? sqoScope.value : "all",
          skipHighIndexCount: sqoSkip ? sqoSkip.checked : false,
          maxIndexCount: sqoMax ? Number(sqoMax.value || 7) : 7
        },
        qo: {
          sampling: qoSampling ? qoSampling.checked : true
        }
      };
      optimizerSettings = settings;
      vscode.postMessage({ command: "saveOptimizerSettings", settings: settings });
      closeOptimizerSettings();
    }
    window.openOptimizerSettings = openOptimizerSettings;
    window.closeOptimizerSettings = closeOptimizerSettings;
    window.switchOptimizerSettingsTab = switchOptimizerSettingsTab;
    window.saveOptimizerSettings = saveOptimizerSettings;

    function setActionButtonsBusy(busy) {
      ["btnOptimizeAll", "btnCreateIndexes", "btnExportIndexDDL"].forEach(function(id) {
        var btn = document.getElementById(id);
        if (btn) btn.disabled = !!busy;
      });
    }
    var operationStatusStartedAt = 0;
    var operationStatusLastMsg = null;
    var operationStatusTimer = null;
    function formatOperationElapsed(ms) {
      var total = Math.max(0, Math.floor(ms / 1000));
      var h = Math.floor(total / 3600);
      var m = Math.floor((total % 3600) / 60);
      var s = total % 60;
      if (h > 0) return h + "h " + String(m).padStart(2, "0") + "m " + String(s).padStart(2, "0") + "s";
      if (m > 0) return m + "m " + String(s).padStart(2, "0") + "s";
      return s + "s";
    }
    function escapeStatusHtml(value) {
      return String(value || "").replace(/[&<>"]/g, function(c) { return {"&":"&amp;","<":"&lt;",">":"&gt;","\"":"&quot;"}[c]; });
    }
    function buildEtaChip(startedAt, percent, className) {
      if (!startedAt || typeof percent !== "number" || percent <= 0 || percent >= 100) return "";
      var elapsedMs = Date.now() - startedAt;
      var totalMs = elapsedMs / (percent / 100);
      var remainingMs = Math.max(0, totalMs - elapsedMs);
      if (!isFinite(totalMs) || totalMs <= 0) return "";
      return '<span class="' + className + '">ETA <strong>' + formatOperationElapsed(remainingMs) + '</strong></span>' +
        '<span class="' + className + '">Est. Total <strong>' + formatOperationElapsed(totalMs) + '</strong></span>';
    }
    function renderOperationStatusDetails(msg) {
      var detailsEl = document.getElementById("operationStatusDetails");
      var sqlEl = document.getElementById("operationStatusSql");
      if (!detailsEl) return;
      var details = (msg && msg.details) || {};
      var chips = [];
      if (operationStatusStartedAt) {
        chips.push('<span class="operation-status-chip">Activity <strong>' + formatOperationElapsed(Date.now() - operationStatusStartedAt) + '</strong></span>');
      }
      var progressPct = typeof msg.percent === "number" ? Math.max(0, Math.min(100, msg.percent)) : null;
      var etaChip = buildEtaChip(operationStatusStartedAt, progressPct, "operation-status-chip");
      if (etaChip) chips.push(etaChip);
      if (details.threadId) chips.push('<span class="operation-status-chip">Thread <strong>' + String(details.threadId) + '</strong></span>');
      if (details.timeSeconds != null && !isNaN(Number(details.timeSeconds))) chips.push('<span class="operation-status-chip">DB State Time <strong>' + String(details.timeSeconds) + 's</strong></span>');
      if (details.state) chips.push('<span class="operation-status-chip">State <strong>' + escapeStatusHtml(details.state) + '</strong></span>');
      detailsEl.innerHTML = chips.join("");
      detailsEl.classList.toggle("hidden", chips.length === 0);
      if (sqlEl) {
        sqlEl.textContent = details.sql || "";
        sqlEl.style.display = details.sql ? "" : "none";
      }
    }
    function ensureOperationStatusTimer(active) {
      if (active && !operationStatusTimer) {
        operationStatusTimer = setInterval(function() {
          if (operationStatusLastMsg) renderOperationStatusDetails(operationStatusLastMsg);
        }, 1000);
      } else if (!active && operationStatusTimer) {
        clearInterval(operationStatusTimer);
        operationStatusTimer = null;
      }
    }
    function updateOperationStatus(msg) {
      var banner = document.getElementById("operationStatusBanner");
      if (!banner) return;
      var textEl = document.getElementById("operationStatusText");
      var badgeEl = document.getElementById("operationStatusBadge");
      var fillEl = document.getElementById("operationStatusFill");
      var pctEl = document.getElementById("operationStatusPct");
      var cancelBtn = document.getElementById("operationStatusCancel");
      var phase = msg.phase || "progress";
      var severity = msg.severity || "";
      var pct = typeof msg.percent === "number" ? Math.max(0, Math.min(100, Math.round(msg.percent))) : null;
      var isActive = phase === "start" || phase === "progress";
      if (phase === "start" || (isActive && !operationStatusStartedAt)) operationStatusStartedAt = Date.now();
      operationStatusLastMsg = msg;
      ensureOperationStatusTimer(isActive);
      banner.classList.remove("hidden", "success", "error", "ok", "warning", "blocked");
      banner.classList.toggle("active", phase === "start" || phase === "progress");
      if (phase === "complete") banner.classList.add("success");
      if (phase === "error") banner.classList.add("error");
      if ((phase === "start" || phase === "progress") && severity) banner.classList.add(severity);
      var details = msg.details || {};
      if (textEl) textEl.textContent = details.title || msg.message || "Working...";
      var badgeText = phase === "complete" ? "Complete" : phase === "error" ? "Stopped" : severity === "blocked" ? "Waiting / Locked" : severity === "warning" ? "Long Running" : "Running";
      if (badgeEl) badgeEl.textContent = badgeText;
      renderOperationStatusDetails(msg);
      if (fillEl && pct != null) fillEl.style.width = pct + "%";
      if (pctEl) pctEl.textContent = pct != null ? pct + "%" : "";
      if (cancelBtn) cancelBtn.classList.toggle("hidden", !(phase === "start" || phase === "progress"));
      setActionButtonsBusy(phase === "start" || phase === "progress");
      if (phase === "complete") {
        setTimeout(function() { banner.classList.add("hidden"); }, 6000);
      }
    }
    var createIndexesOperationStartedAt = 0;
    var createIndexesOperationLastMsg = null;
    var createIndexesOperationTimer = null;
    function renderCreateIndexesOperationDetails(root, msg) {
      var detailsEl = root.querySelector("#cip-operation-details");
      var sqlEl = root.querySelector("#cip-operation-sql");
      if (!detailsEl) return;
      var details = (msg && msg.details) || {};
      var chips = [];
      if (createIndexesOperationStartedAt) {
        chips.push('<span class="cip-operation-chip">Activity <strong>' + formatOperationElapsed(Date.now() - createIndexesOperationStartedAt) + '</strong></span>');
      }
      var progressPct = typeof msg.percent === "number" ? Math.max(0, Math.min(100, msg.percent)) : null;
      var etaChip = buildEtaChip(createIndexesOperationStartedAt, progressPct, "cip-operation-chip");
      if (etaChip) chips.push(etaChip);
      if (details.threadId) chips.push('<span class="cip-operation-chip">Thread <strong>' + String(details.threadId) + '</strong></span>');
      if (details.timeSeconds != null && !isNaN(Number(details.timeSeconds))) chips.push('<span class="cip-operation-chip">DB State Time <strong>' + String(details.timeSeconds) + 's</strong></span>');
      if (details.state) chips.push('<span class="cip-operation-chip">State <strong>' + escapeStatusHtml(details.state) + '</strong></span>');
      detailsEl.innerHTML = chips.join("");
      detailsEl.classList.toggle("hidden", chips.length === 0);
      if (sqlEl) {
        sqlEl.textContent = details.sql || "";
        sqlEl.style.display = details.sql ? "" : "none";
      }
    }
    function ensureCreateIndexesOperationTimer(active, root) {
      if (active && !createIndexesOperationTimer) {
        createIndexesOperationTimer = setInterval(function() {
          var overlay = document.getElementById("createIndexesOverlay");
          var liveRoot = overlay && overlay.classList.contains("active") ? overlay : document;
          if (createIndexesOperationLastMsg) renderCreateIndexesOperationDetails(liveRoot, createIndexesOperationLastMsg);
        }, 1000);
      } else if (!active && createIndexesOperationTimer) {
        clearInterval(createIndexesOperationTimer);
        createIndexesOperationTimer = null;
        if (root && createIndexesOperationLastMsg) renderCreateIndexesOperationDetails(root, createIndexesOperationLastMsg);
      }
    }
    function formatCreateIndexesProgressSummary(msg) {
      var stats = msg.stats || {};
      var done = typeof stats.done === "number" ? stats.done : null;
      var total = typeof stats.total === "number" ? stats.total : null;
      var ok = typeof stats.ok === "number" ? stats.ok : 0;
      var fail = typeof stats.fail === "number" ? stats.fail : 0;
      if (done == null || total == null) return null;
      var pct = typeof msg.percent === "number" ? msg.percent : (total > 0 ? Math.round((done / total) * 100) : 0);
      return "Progress: " + done + " / " + total + " · OK " + ok + " · Fail " + fail + " (" + pct + "%)";
    }
    function applyCreateIndexesRowUpdates(root, rowUpdates) {
      if (!root || !rowUpdates || !rowUpdates.length) return;
      rowUpdates.forEach(function(up) {
        var row = root.querySelector('.cip-grid-row[data-index="' + up.rowIndex + '"]');
        if (!row) return;
        var cell = row.querySelector(".cip-col-status span");
        if (!cell) return;
        var ok = up.status === "ok";
        cell.className = ok ? "cip-status-ok" : "cip-status-fail";
        cell.textContent = ok ? "OK" : "Fail";
      });
    }
    function updateCreateIndexesProgress(msg) {
      var overlay = document.getElementById("createIndexesOverlay");
      var root = overlay && overlay.classList.contains("active") ? overlay : document;
      var statusEl = root.querySelector("#cip-operation-status");
      var fillEl = root.querySelector("#cip-operation-fill");
      var textEl = root.querySelector("#cip-operation-text");
      var badgeEl = root.querySelector("#cip-operation-badge");
      var detailsEl = root.querySelector("#cip-operation-details");
      var sqlEl = root.querySelector("#cip-operation-sql");
      var pctEl = root.querySelector("#cip-operation-pct");
      var cancelBtn = root.querySelector("#cip-operation-cancel");
      var sumEl = root.querySelector("#cip-summary");
      if (!statusEl) return;
      var phase = msg.phase || "progress";
      var severity = msg.severity || "";
      var pct = typeof msg.percent === "number" ? Math.max(0, Math.min(100, Math.round(msg.percent))) : null;
      var isActive = phase === "start" || phase === "progress";
      if (phase === "start" || (isActive && !createIndexesOperationStartedAt)) createIndexesOperationStartedAt = Date.now();
      createIndexesOperationLastMsg = msg;
      ensureCreateIndexesOperationTimer(isActive, root);
      statusEl.classList.remove("hidden", "success", "error", "ok", "warning", "blocked");
      statusEl.classList.toggle("active", phase === "start" || phase === "progress");
      if (phase === "complete") statusEl.classList.add("success");
      if (phase === "error") statusEl.classList.add("error");
      if ((phase === "start" || phase === "progress") && severity) statusEl.classList.add(severity);
      var details = msg.details || {};
      if (textEl) textEl.textContent = details.title || msg.message || "Working...";
      var badgeText = phase === "complete" ? "Complete" : phase === "error" ? "Stopped" : severity === "blocked" ? "Waiting / Locked" : severity === "warning" ? "Long Running" : "Running";
      if (badgeEl) badgeEl.textContent = badgeText;
      renderCreateIndexesOperationDetails(root, msg);
      if (fillEl && pct != null) fillEl.style.width = pct + "%";
      if (pctEl) pctEl.textContent = pct != null ? pct + "%" : "";
      if (cancelBtn) cancelBtn.classList.toggle("hidden", !(phase === "start" || phase === "progress"));
      var progressText = formatCreateIndexesProgressSummary(msg);
      if (sumEl && progressText && (isActive || phase === "complete")) sumEl.textContent = progressText;
      applyCreateIndexesRowUpdates(root, msg.stats && msg.stats.rowUpdates);
      ["button", "input", "select"].forEach(function(sel) {
        root.querySelectorAll(sel).forEach(function(el) {
          if (el.id === "cip-operation-cancel") return;
          if (el.id === "cip-drop-unused-btn" || el.id === "cip-drop-all-btn") return;
          el.disabled = phase === "start" || phase === "progress";
        });
      });
    }

    function updateCreateIndexesSummary() {
      const el = document.getElementById("createIndexesOverlay");
      if (!el) return;
      const sumEl = el.querySelector("#cip-summary");
      const checked = el.querySelectorAll(".cip-checkbox:checked");
      const rows = el.querySelectorAll(".cip-grid-row");
      let totalSec = 0;
      checked.forEach(function(cb) {
        const row = cb.closest ? cb.closest(".cip-grid-row") : null;
        if (row) totalSec += parseFloat(row.getAttribute("data-duration-sec") || "0");
      });
      const durStr = totalSec > 3600 ? (totalSec/3600).toFixed(1) + " hrs" : totalSec > 60 ? (totalSec/60).toFixed(0) + " min" : totalSec > 0 ? totalSec.toFixed(0) + "s" : "—";
      if (sumEl) sumEl.textContent = checked.length + " of " + rows.length + " selected · Est. total: " + durStr;
    }
    function toggleAllCreateIndexes(checked) {
      const el = document.getElementById("createIndexesOverlay");
      if (!el) return;
      el.querySelectorAll(".cip-checkbox").forEach(function(cb) { cb.checked = checked; });
      updateCreateIndexesSummary();
    }
    function onIgnoreLowImpactChange(ignore) {
      const el = document.getElementById("createIndexesOverlay");
      if (!el) return;
      el.querySelectorAll(".cip-grid-row[data-impact-level='low'] .cip-checkbox").forEach(function(cb) { cb.checked = !ignore; });
      updateCreateIndexesSummary();
    }
    function preflightCreateIndexesOverlay() { vscode.postMessage({ command: "preflightIndexCheck" }); }
    function createIndexesOverlay(validate) {
      const el = document.getElementById("createIndexesOverlay");
      if (!el) return;
      let checked = Array.from(el.querySelectorAll(".cip-checkbox:checked")).map(function(cb) { return { idx: parseInt(cb.getAttribute("data-index"), 10), row: cb.closest(".cip-grid-row") }; }).filter(function(x) { return !isNaN(x.idx); });
      const ignoreLow = el.querySelector("#cip-ignore-low-impact") && el.querySelector("#cip-ignore-low-impact").checked;
      if (ignoreLow) checked = checked.filter(function(x) { return !x.row || x.row.getAttribute("data-impact-level") !== "low"; });
      checked = checked.map(function(x) { return x.idx; });
      if (checked.length === 0) return;
      const threadsEl = el.querySelector("#cip-threads");
      const threads = threadsEl ? parseInt(threadsEl.value || "1", 10) : 1;
      vscode.postMessage({ command: "createSelectedIndexes", indices: checked, validatePerformance: validate, threadCount: threads });
    }
    function closeCreateIndexesOverlay() {
      const el = document.getElementById("createIndexesOverlay");
      if (el) el.classList.remove("active");
      vscode.postMessage({ command: "closeCreateIndexesOverlay" });
    }
    function cancelCreateIndexesOperation() { vscode.postMessage({ command: "cancelCreateIndexesOperation" }); }
    function setCreateIndexesDropButtonsDisabled(disabled) {
      const el = document.getElementById("createIndexesOverlay");
      if (!el) return;
      const a = el.querySelector("#cip-drop-unused-btn");
      const b = el.querySelector("#cip-drop-all-btn");
      if (a) a.disabled = disabled;
      if (b) b.disabled = disabled;
    }
    let pendingCreateIndexesDropCommand = null;
    function closeCreateIndexesDropConfirm() {
      pendingCreateIndexesDropCommand = null;
      const modal = document.querySelector("#createIndexesOverlay #cip-drop-confirm");
      if (modal) modal.classList.remove("active");
    }
    function openCreateIndexesDropConfirm(command, title, message) {
      pendingCreateIndexesDropCommand = command;
      const modal = document.querySelector("#createIndexesOverlay #cip-drop-confirm");
      const titleEl = document.querySelector("#createIndexesOverlay #cip-drop-confirm-title");
      const messageEl = document.querySelector("#createIndexesOverlay #cip-drop-confirm-message");
      const okBtn = document.querySelector("#createIndexesOverlay #cip-drop-confirm-ok");
      if (!modal || !messageEl || !okBtn) return false;
      if (titleEl) titleEl.textContent = title;
      messageEl.textContent = message;
      okBtn.onclick = function() {
        const cmd = pendingCreateIndexesDropCommand;
        closeCreateIndexesDropConfirm();
        if (!cmd) return;
        setCreateIndexesDropButtonsDisabled(true);
        vscode.postMessage({ command: cmd, targets: window.__createIndexesDropTargets || [] });
      };
      modal.classList.add("active");
      okBtn.focus();
      return true;
    }
    function dropUnusedIndexes() {
      const root = document.querySelector("#createIndexesOverlay .cip-fullscreen");
      const message = (root && root.getAttribute("data-drop-unused-confirm")) || "Are you sure you want to Drop unused Recommended indexes?";
      if (!openCreateIndexesDropConfirm("dropUnusedIndexes", "Drop unused indexes", message)) {
        setCreateIndexesDropButtonsDisabled(true);
        vscode.postMessage({ command: "dropUnusedIndexes", targets: window.__createIndexesDropTargets || [] });
      }
    }
    function dropAllIndexes() {
      const root = document.querySelector("#createIndexesOverlay .cip-fullscreen");
      const message = (root && root.getAttribute("data-drop-all-confirm")) || "New indexes recommendation help to improve X performance. Are you sure to drop all recommended indexes?";
      if (!openCreateIndexesDropConfirm("dropAllIndexes", "Drop all recommended indexes", message)) {
        setCreateIndexesDropButtonsDisabled(true);
        vscode.postMessage({ command: "dropAllIndexes", targets: window.__createIndexesDropTargets || [] });
      }
    }
    function cancelDropIndexesOperation() { vscode.postMessage({ command: "cancelDropIndexesOperation" }); }
    (function initCreateIndexesTooltips() {
      var tipEl = null;
      function ensureTip() {
        if (!tipEl) {
          tipEl = document.createElement("div");
          tipEl.className = "cip-hover-tooltip";
          tipEl.style.display = "none";
          document.body.appendChild(tipEl);
        }
        return tipEl;
      }
      document.addEventListener("mousemove", function(event) {
        var target = event.target && event.target.closest ? event.target.closest("#createIndexesOverlay [data-tip]") : null;
        if (!target) {
          if (tipEl) tipEl.style.display = "none";
          return;
        }
        var text = target.getAttribute("data-tip");
        if (!text) return;
        var el = ensureTip();
        el.textContent = text;
        el.style.display = "block";
        var left = Math.min(event.clientX + 14, window.innerWidth - el.offsetWidth - 12);
        var top = Math.min(event.clientY + 14, window.innerHeight - el.offsetHeight - 12);
        el.style.left = Math.max(8, left) + "px";
        el.style.top = Math.max(8, top) + "px";
      });
      document.addEventListener("mouseleave", function() {
        if (tipEl) tipEl.style.display = "none";
      });
    })();
    window.updateCreateIndexesSummary = updateCreateIndexesSummary;
    window.toggleAllCreateIndexes = toggleAllCreateIndexes;
    window.onIgnoreLowImpactChange = onIgnoreLowImpactChange;
    window.preflightCreateIndexesOverlay = preflightCreateIndexesOverlay;
    window.createIndexesOverlay = createIndexesOverlay;
    window.closeCreateIndexesOverlay = closeCreateIndexesOverlay;
    window.cancelCreateIndexesOperation = cancelCreateIndexesOperation;
    window.dropUnusedIndexes = dropUnusedIndexes;
    window.dropAllIndexes = dropAllIndexes;
    window.closeCreateIndexesDropConfirm = closeCreateIndexesDropConfirm;
    window.cancelDropIndexesOperation = cancelDropIndexesOperation;
    window.setCreateIndexesDropButtonsDisabled = setCreateIndexesDropButtonsDisabled;

    document.addEventListener("click", (e) => {
      if (!e.target || !e.target.closest || (!e.target.closest(".dropdown-wrap") && !e.target.closest(".dropdown-menu"))) {
        closeCreateDropdown(); closeExportDropdown();
      }
    });

    // Event delegation for Actions column buttons (Explain, Optimize, Copy)
    // and Recommended Indexes column (Copy index DDL, Copy rewrite tips)
    const tableWrapEl = document.getElementById("tableWrap");
    if (tableWrapEl) {
      tableWrapEl.addEventListener("click", (e) => {
        const actionBtn = e.target && e.target.closest ? e.target.closest(".action-row-btn") : null;
        if (actionBtn) {
          const hash = actionBtn.getAttribute("data-query-hash");
          const action = actionBtn.getAttribute("data-action");
          if (!hash) return;
          if (action === "explain" && typeof window.analyzeQueryExplain === "function") {
            window.analyzeQueryExplain(hash);
          } else if (action === "optimize" && typeof window.analyzeQueryOptimize === "function") {
            window.analyzeQueryOptimize(hash);
          } else if (action === "copy" && typeof window.copyFingerprintQuery === "function") {
            window.copyFingerprintQuery(hash);
          }
          return;
        }
        const copyRecBtn = e.target && e.target.closest ? e.target.closest(".index-rec-copy-btn") : null;
        if (copyRecBtn) {
          const hash = copyRecBtn.getAttribute("data-query-hash");
          if (hash && typeof window.copyIndexRecommendationsForFingerprint === "function") {
            window.copyIndexRecommendationsForFingerprint(hash);
          }
          return;
        }
        const rewriteBtn = e.target && e.target.closest ? e.target.closest(".index-rec-rewrite-btn") : null;
        if (rewriteBtn) {
          const hash = rewriteBtn.getAttribute("data-query-hash");
          if (hash && typeof window.copyRewriteTipsForFingerprint === "function") {
            window.copyRewriteTipsForFingerprint(hash);
          }
        }
      });
    }

    function setSort(field) {
      if (sortField === field) {
        sortDir = sortDir === "asc" ? "desc" : "asc";
      } else {
        sortField = field;
        sortDir = "desc";
      }
      render();
    }

    function setUsageSort(field) {
      if (usageSortField === field) {
        usageSortDir = usageSortDir === "asc" ? "desc" : "asc";
      } else {
        usageSortField = field;
        usageSortDir = "desc";
      }
      render();
    }
    function usageSortTh(field, label) {
      const dir = usageSortField === field ? (usageSortDir === "asc" ? " ▲" : " ▼") : "";
      return `<th onclick="setUsageSort('${field}')" style="cursor:pointer;">${label}${dir}</th>`;
    }

    function setTab(tab) {
      activeTab = tab;
      ["fingerprints", "tables", "databases", "users"].forEach((name) => {
        const el = document.getElementById("tab-" + name);
        if (el) el.classList.toggle("active", name === tab);
      });
      if (tab === "fingerprints") {
        // Rank fingerprints by impact priority by default.
        sortField = "impactScore";
        sortDir = "desc";
      } else if (tab === "tables" || tab === "databases") {
        usageGridTab = tab;
      }
      render();
    }

    function setUsageGridTab(tab) {
      if (tab !== "tables" && tab !== "databases") return;
      usageGridTab = tab;
      render();
    }

    function toggleBubbleChart() {
      bubbleChartExpanded = !bubbleChartExpanded;
      render();
    }

    function applyFilter() {
      render();
    }

    function setHomeMode(isHome) {
      const filterWrap = document.getElementById("filterWrap");
      if (filterWrap) filterWrap.classList.toggle("hidden", isHome);
    }

    function fmtSec(v) {
      if (v >= 60) return (v / 60).toFixed(1) + "m";
      if (v >= 1) return v.toFixed(2) + "s";
      return (v * 1000).toFixed(1) + "ms";
    }
    // Normalize SQL (strip leading comments) before checking optimizable; handles MySQL /* */ and /*!50100 */ format
    function isOptimizableSql(sql) {
      let s = (sql || "").trim();
      // Strip MySQL version comment wrapper: /*!50100 SELECT ... */ -> SELECT ...
      s = s.replace(/^\/\*!\d*\s*/, "").replace(/\s*\*\/\s*$/, "").trim();
      // Strip pure block comments /* ... */ (not /*! which contains executable SQL)
      var blockCommentRe = /^\/\*(?!\!)[\s\S]*?\*\/\s*/;
      var lineCommentRe = /^--[^\n]*\n?\s*/;
      while (s) {
        var bc = s.match(blockCommentRe);
        var lc = s.match(lineCommentRe);
        if (bc) s = s.slice(bc[0].length).trim();
        else if (lc) s = s.slice(lc[0].length).trim();
        else break;
      }
      return s.length > 0 && /^(WITH|SELECT|UPDATE|DELETE)\b/i.test(s);
    }

    function stripSlowLogPrefixes(s) {
      var prev;
      do {
        prev = s;
        s = s.replace(/^use\s+[^;\r\n]+;\s*[\r\n]*/gi, "").trim();
        s = s.replace(/^SET\s+timestamp\s*=\s*\d+\s*;\s*[\r\n]*/gi, "").trim();
        s = s.replace(/^\/\*!\d*\s*/, "").replace(/\s*\*\/\s*$/, "").trim();
      } while (prev !== s);
      return s;
    }
    function getSampleForOptimize(r, report) {
      var s = (r.sampleQuery || r.queryTemplate || r.query_template || r.sample_query || r.query || "").trim();
      if (s) {
        s = stripSlowLogPrefixes(s);
        return s || "";
      }
      var ep = (report && report.entryPoints || []).find(function(p) { return p.queryHash === r.queryHash; });
      if (ep && ep.queryText) {
        s = stripSlowLogPrefixes(String(ep.queryText || "").trim());
        return s || "";
      }
      var byHash = report && report.sampleQueriesByHash;
      if (byHash && r.queryHash && byHash[r.queryHash]) {
        s = stripSlowLogPrefixes(String(byHash[r.queryHash] || "").trim());
        return s || "";
      }
      return "";
    }

    function stars(rating) {
      return "★".repeat(Math.max(1, Math.min(5, rating)));
    }
    function escTpl(s) {
      var x = String(s || "");
      return x.replace(/\\\\/g, "\\\\\\\\").replace(new RegExp(String.fromCharCode(96), "g"), "\\\\" + String.fromCharCode(96)).replace(/\$/g, "\\$");
    }

    function usageHeatStyle(usagePct, maxUsage) {
      const max = Math.max(1, Number(maxUsage) || 1);
      const t = Math.max(0, Math.min(1, (Number(usagePct) || 0) / max));
      const r = Math.round(30 + 210 * t);
      const g = Math.round(180 - 90 * t);
      const b = Math.round(70 - 50 * t);
      return `background: rgba(${r},${g},${Math.max(0, b)},${0.16 + t * 0.24}); border-color: rgba(${r},${g},${Math.max(0, b)},0.55);`;
    }

    function gradeColor(grade) {
      if (grade === "A") return "#ef4444";
      if (grade === "B") return "#f59e0b";
      if (grade === "C") return "#3b82f6";
      if (grade === "D" || grade === "E") return "#22c55e";
      return "#94a3b8";
    }

    const RANK_COLORS = {
      1: "#dc2626",
      2: "#ea580c",
      3: "#f97316",
      4: "#fb923c",
      5: "#fbbf24",
      6: "#facc15",
      7: "#a3e635",
      8: "#4ade80",
      9: "#34d399",
      10: "#2dd4bf"
    };

    function rankColor(rank) {
      return RANK_COLORS[rank] || "#94a3b8";
    }

    function hexToRgba(hex, alpha) {
      const h = String(hex || "").replace("#", "");
      const full = h.length === 3 ? (h[0] + h[0] + h[1] + h[1] + h[2] + h[2]) : h;
      const r = parseInt(full.substring(0, 2), 16);
      const g = parseInt(full.substring(2, 4), 16);
      const b = parseInt(full.substring(4, 6), 16);
      return "rgba(" + (Number.isFinite(r) ? r : 148) + "," + (Number.isFinite(g) ? g : 163) + "," + (Number.isFinite(b) ? b : 184) + "," + alpha + ")";
    }

    function rankCellStyle(rank) {
      if (rank <= 0) {
        return "background: rgba(148,163,184,.14); border-color: rgba(148,163,184,.35); color: var(--muted);";
      }
      const color = rankColor(rank);
      return "background: " + hexToRgba(color, 0.20) + "; border-color: " + hexToRgba(color, 0.55) + "; color: " + color + ";";
    }

    function lerp(a, b, t) {
      return Math.round(a + (b - a) * t);
    }

    function lerpHex(c1, c2, t) {
      const a = String(c1 || "#000000").replace("#", "");
      const b = String(c2 || "#000000").replace("#", "");
      const ar = parseInt(a.substring(0, 2), 16) || 0;
      const ag = parseInt(a.substring(2, 4), 16) || 0;
      const ab = parseInt(a.substring(4, 6), 16) || 0;
      const br = parseInt(b.substring(0, 2), 16) || 0;
      const bg = parseInt(b.substring(2, 4), 16) || 0;
      const bb = parseInt(b.substring(4, 6), 16) || 0;
      return "rgb(" + lerp(ar, br, t) + "," + lerp(ag, bg, t) + "," + lerp(ab, bb, t) + ")";
    }

    function pctImpactColor(pct) {
      const p = Math.max(0, Math.min(100, Number(pct) || 0));
      if (p > 10) {
        const t = (p - 10) / 90;
        return lerpHex("#f87171", "#dc2626", t);
      }
      if (p >= 5) {
        const t = (p - 5) / 5;
        return lerpHex("#fdba74", "#ea580c", t);
      }
      const t = p / 5;
      return lerpHex("#a3e635", "#facc15", t);
    }

    function renderBars(title, rows, valueFormatter, barField) {
      const top = rows.slice(0, 8);
      if (!top.length) return "";
      const field = barField || "usagePct";
      const maxVal = Math.max(0.0001, ...top.map((r) => Number(r[field]) || 0));
      return `<div class="panel">
        <div class="panel-title">${escTpl(title)}</div>
        <div class="bars">
          ${top.map((r) => {
            const val = Number(r[field]) || 0;
            const w = Math.max(2, Math.min(100, Math.round((val / maxVal) * 100)));
            return `<div class="bar-row">
              <div class="bar-label" title="${escTpl(r.name)}">${escTpl(r.name)}</div>
              <div class="bar-track"><div class="bar-fill" style="width:${w}%"></div></div>
              <div class="bar-val">${valueFormatter(r)}</div>
            </div>`;
          }).join("")}
        </div>
      </div>`;
    }

    function pieLabelText(name, pct) {
      const label = String(name || "");
      const short = label.length > 12 ? label.slice(0, 11) + "…" : label;
      return short + " " + (Number(pct) || 0).toFixed(1) + "%";
    }

    function renderPieChart(title, rows) {
      const top = rows.slice(0, 8);
      if (!top.length) return "";
      const total = Math.max(0.00001, top.reduce((sum, r) => sum + (Number(r.usagePct) || 0), 0));
      const cx = 120;
      const cy = 120;
      const radius = 88;
      const colors = ["#3b82f6", "#06b6d4", "#22c55e", "#a855f7", "#f59e0b", "#ef4444", "#14b8a6", "#8b5cf6"];

      let current = -Math.PI / 2;
      const slices = top.map((r, idx) => {
        const pct = (Number(r.usagePct) || 0) / total;
        const angle = pct * Math.PI * 2;
        const start = current;
        const end = current + angle;
        current = end;
        const x1 = cx + radius * Math.cos(start);
        const y1 = cy + radius * Math.sin(start);
        const x2 = cx + radius * Math.cos(end);
        const y2 = cy + radius * Math.sin(end);
        const largeArc = angle > Math.PI ? 1 : 0;
        return {
          idx,
          color: colors[idx % colors.length],
          path: `M ${cx} ${cy} L ${x1.toFixed(2)} ${y1.toFixed(2)} A ${radius} ${radius} 0 ${largeArc} 1 ${x2.toFixed(2)} ${y2.toFixed(2)} Z`,
          name: r.name,
          usagePct: Number(r.usagePct) || 0,
          mid: start + angle / 2,
          sharePct: pct * 100
        };
      });
      const labels = slices.filter((s) => s.sharePct >= 4 || s.idx < 5).map((s, i) => {
        const inside = s.sharePct >= 9;
        const labelRadius = inside ? 66 : 105;
        const x = cx + labelRadius * Math.cos(s.mid);
        const y = cy + labelRadius * Math.sin(s.mid);
        const anchor = inside ? "middle" : (Math.cos(s.mid) >= 0 ? "start" : "end");
        const text = pieLabelText(s.name, s.usagePct);
        return '<text x="' + x.toFixed(1) + '" y="' + (y + (i % 2 ? 5 : 0)).toFixed(1) + '" text-anchor="' + anchor + '" dominant-baseline="middle" class="chart-always-label" fill="#e5edf8">' + escTpl(text) + '</text>';
      }).join("");

      return `<div class="panel">
        <div class="panel-title">${escTpl(title)}</div>
        <div style="display:grid; grid-template-columns: 260px 1fr; gap:14px; align-items:center;">
          <svg viewBox="0 0 240 240" width="240" height="240" role="img" aria-label="Table usage pie chart">
            ${slices.map((s) => `<path d="${s.path}" fill="${s.color}" stroke="var(--bg)" stroke-width="1.5"><title>${escTpl(s.name)}: ${s.usagePct.toFixed(1)}%</title></path>`).join("")}
            <circle cx="${cx}" cy="${cy}" r="46" fill="var(--panel)"></circle>
            <text x="${cx}" y="${cy - 2}" text-anchor="middle" font-size="12" fill="var(--muted)">Top 8</text>
            <text x="${cx}" y="${cy + 16}" text-anchor="middle" font-size="13" fill="#60a5fa" font-weight="700">Usage</text>
            ${labels}
          </svg>
          <div>
            ${slices.map((s, i) => `<div style="display:grid; grid-template-columns: 16px 1fr auto; gap:8px; align-items:center; margin-bottom:6px; font-size:12px;">
              <span style="width:12px; height:12px; border-radius:3px; background:${s.color}; display:inline-block;"></span>
              <span class="bar-label" title="${escTpl(s.name)}">#${i + 1} ${escTpl(s.name)}</span>
              <span class="muted">${s.usagePct.toFixed(1)}%</span>
            </div>`).join("")}
          </div>
        </div>
      </div>`;
    }

    function renderSlowBubbleChart(entryPoints) {
      const points = Array.isArray(entryPoints) ? entryPoints.filter(p => p && p.timestampMs && p.queryTimeSec != null) : [];
      if (!points.length) return "";

      const width = 980;
      const height = 289;
      const svgHeight = 272;
      const padL = 64;
      const padR = 24;
      const padT = 20;
      const padB = 48;
      const plotW = width - padL - padR;
      const plotH = height - padT - padB;

      const minX = Math.min(...points.map(p => Number(p.timestampMs) || 0));
      const maxX = Math.max(...points.map(p => Number(p.timestampMs) || 0));
      const drawPoints = points;
      const maxY = Math.max(0.0001, ...points.map(p => Number(p.queryTimeSec) || 0));
      const minY = 0;
      const maxPoint = points.reduce((best, p) => {
        if (!best) return p;
        return (Number(p.queryTimeSec) || 0) > (Number(best.queryTimeSec) || 0) ? p : best;
      }, null);

      const xOf = (ts) => {
        const denom = Math.max(1, (maxX - minX));
        return padL + ((Number(ts) - minX) / denom) * plotW;
      };
      const yOf = (v) => {
        const t = (Math.max(0, Number(v) || 0) - minY) / Math.max(0.0001, (maxY - minY));
        return padT + (1 - t) * plotH;
      };

      const minR = 3.5;
      const maxR = 18;
      const rOf = (v) => {
        const t = Math.max(0, Math.min(1, (Number(v) || 0) / maxY));
        return minR + Math.sqrt(t) * (maxR - minR);
      };

      const formatTime = (ms) => {
        try {
          const d = new Date(ms);
          return d.toLocaleString();
        } catch {
          return String(ms);
        }
      };

      const yTicks = [0, 0.25, 0.5, 0.75, 1].map(t => {
        const v = maxY * t;
        return { y: yOf(v), v };
      });

      const xTicks = [0, 0.2, 0.4, 0.6, 0.8, 1].map(t => {
        const ms = minX + (maxX - minX) * t;
        return { x: xOf(ms), ms };
      });
      const formatAxisTime = (ms) => {
        const d = new Date(ms);
        const mm = String(d.getMonth() + 1).padStart(2, "0");
        const dd = String(d.getDate()).padStart(2, "0");
        const hh = String(d.getHours()).padStart(2, "0");
        const mi = String(d.getMinutes()).padStart(2, "0");
        const ss = String(d.getSeconds()).padStart(2, "0");
        return mm + "-" + dd + " " + hh + ":" + mi + ":" + ss;
      };

      const overlapCounts = {};
      const templateMaxPointByHash = {};
      drawPoints.forEach((p) => {
        const hash = p.queryHash || "";
        if (!hash) return;
        const existing = templateMaxPointByHash[hash];
        if (!existing || (Number(p.queryTimeSec) || 0) > (Number(existing.queryTimeSec) || 0)) {
          templateMaxPointByHash[hash] = p;
        }
      });
      const circles = drawPoints.map((p) => {
        const meta = bubbleMetaByHash[p.queryHash] || {};
        const color = bubbleColorByHash[p.queryHash] || "#94a3b8";
        const isTemplateMax = !!(templateMaxPointByHash[p.queryHash] && templateMaxPointByHash[p.queryHash].entryId === p.entryId);
        const stroke = isTemplateMax ? "#fbbf24" : "rgba(226,232,240,0.88)";
        const baseCx = xOf(p.timestampMs);
        const baseCy = yOf(p.queryTimeSec);
        const overlapKey = Math.round(baseCx) + ":" + Math.round(baseCy);
        const overlapIndex = overlapCounts[overlapKey] || 0;
        overlapCounts[overlapKey] = overlapIndex + 1;
        const jitterRadius = Math.min(10, overlapIndex * 1.8);
        const jitterAngle = overlapIndex * 0.9;
        const cx = baseCx + (overlapIndex > 0 ? Math.cos(jitterAngle) * jitterRadius : 0);
        const cy = baseCy + (overlapIndex > 0 ? Math.sin(jitterAngle) * jitterRadius : 0);
        const r = rOf(p.queryTimeSec) + (isTemplateMax ? 1.2 : 0);
        const title =
          "Time: " + formatTime(p.timestampMs) +
          "\\nResponse: " + fmtSec(p.queryTimeSec) +
          "\\nFingerprint: " + p.queryHash;
        return '<circle data-point-id="' + (p.entryId || '') + '" data-hash="' + (p.queryHash || '') + '" data-ts="' + (p.timestampMs || 0) + '" data-rt="' + (p.queryTimeSec || 0) + '" cx="' + cx.toFixed(1) + '" cy="' + cy.toFixed(1) + '" r="' + r.toFixed(1) +
          '" fill="' + color + '" stroke="' + stroke + '" stroke-width="' + (isTemplateMax ? "2.4" : "1.4") + '" fill-opacity="0.50" data-template-max="' + (isTemplateMax ? "1" : "0") + '">' +
          '<title>' + title.replace(/\"/g, '&quot;') + '</title></circle>';
      }).join("");
      const peakLabels = Object.keys(templateMaxPointByHash).slice(0, 8).map((hash, idx) => {
        const p = templateMaxPointByHash[hash];
        if (!p) return "";
        const x = xOf(p.timestampMs);
        const y = yOf(p.queryTimeSec);
        const meta = bubbleMetaByHash[hash] || {};
        const label = "#" + (idx + 1) + " " + fmtSec(p.queryTimeSec);
        const color = bubbleColorByHash[hash] || "#94a3b8";
        return '<g class="bubble-always-label"><rect x="' + (x + 8).toFixed(1) + '" y="' + (y - 20).toFixed(1) + '" width="' + Math.max(48, label.length * 7) + '" height="16" rx="8" fill="rgba(15,23,42,0.82)" stroke="' + color + '" stroke-opacity="0.75"></rect><text x="' + (x + 16).toFixed(1) + '" y="' + (y - 8).toFixed(1) + '" fill="#e5edf8" font-size="10" font-weight="700">' + escTpl(label) + '<title>' + escTpl(meta.queryTemplate || hash) + '</title></text></g>';
      }).join("");

      const chartHeader =
        '<div class="bubble-toolbar">' +
          '<div class="bubble-title">Response Time Bubble Chart</div>' +
          '<button class="bubble-toggle-btn" onclick="toggleBubbleChart()" title="' + (bubbleChartExpanded ? 'Minimize Chart' : 'Maximize Chart') + '">' + (bubbleChartExpanded ? '-' : '+') + '</button>' +
        '</div>';

      if (!bubbleChartExpanded) {
        return '<div class="panel slow-bubble-wrap" id="slowBubbleChartWrap">' +
          chartHeader +
        '</div>';
      }

      return '<div class="panel slow-bubble-wrap" id="slowBubbleChartWrap">' +
        chartHeader +
        '<div class="muted" style="margin-bottom:4px;">Range: ' + formatAxisTime(minX) + ' to ' + formatAxisTime(maxX) + '</div>' +
        '<svg viewBox="0 0 ' + width + ' ' + height + '" width="100%" height="' + svgHeight + '" role="img" aria-label="Slow query bubble chart">' +
        '<rect x="' + padL + '" y="' + padT + '" width="' + plotW + '" height="' + plotH + '" fill="transparent" stroke="var(--border)" />' +
        yTicks.map(t => '<line x1="' + padL + '" y1="' + t.y.toFixed(1) + '" x2="' + (padL + plotW) + '" y2="' + t.y.toFixed(1) + '" stroke="var(--border)" stroke-dasharray="3 3" />').join("") +
        xTicks.map(t => '<line x1="' + t.x.toFixed(1) + '" y1="' + padT + '" x2="' + t.x.toFixed(1) + '" y2="' + (padT + plotH) + '" stroke="var(--border)" stroke-opacity="0.22" />').join("") +
        circles +
        peakLabels +
        yTicks.map(t => '<text x="10" y="' + (t.y + 4).toFixed(1) + '" fill="var(--muted)" font-size="10">' + fmtSec(t.v) + '</text>').join("") +
        xTicks.map((t) => '<text x="' + t.x.toFixed(1) + '" y="' + (height - 14) + '" fill="var(--muted)" font-size="9" text-anchor="middle">' + formatAxisTime(t.ms) + '</text>').join("") +
        '<text x="' + padL + '" y="' + (height - 8) + '" fill="var(--muted)" font-size="10">Execution time -></text>' +
        '<text x="14" y="' + (padT - 6) + '" fill="var(--muted)" font-size="10">Response time (sec) ^</text>' +
        '</svg>' +
        '<div id="slowBubbleTooltip" class="slow-bubble-tooltip"></div>' +
        '</div>';
    }

    function wireBubbleTooltip() {
      const wrap = document.getElementById("slowBubbleChartWrap");
      if (!wrap) return;
      const tooltip = document.getElementById("slowBubbleTooltip");
      if (!tooltip) return;
      const esc = (v) => String(v || "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
      const circles = wrap.querySelectorAll("circle[data-hash]");

      circles.forEach((node) => {
        node.addEventListener("mousemove", (e) => {
          const pointId = node.getAttribute("data-point-id") || "";
          const hash = node.getAttribute("data-hash") || "";
          const ts = Number(node.getAttribute("data-ts") || 0);
          const rt = Number(node.getAttribute("data-rt") || 0);
          const isTemplateMax = node.getAttribute("data-template-max") === "1";
          const meta = bubbleMetaByHash[hash] || {};
          const executionMeta = bubbleExecutionById[pointId] || {};
          const query = String(executionMeta.queryText || meta.sampleQuery || meta.queryTemplate || hash || "").slice(0, 220);

          tooltip.innerHTML =
            '<div class="h">' + esc(meta.qualityTag || "QUERY") + ' • Grade ' + esc(meta.scoreGrade || "-") + '</div>' +
            '<div class="q">' + esc(query) + '</div>' +
            '<div class="g">' +
            '<span class="k">Response:</span><span class="v">' + esc(fmtSec(rt)) + '</span>' +
            '<span class="k">Avg:</span><span class="v">' + esc(fmtSec(Number(meta.avgTimeSec || 0))) + '</span>' +
            '<span class="k">Max:</span><span class="v">' + esc(fmtSec(Number(meta.maxTimeSec || 0))) + '</span>' +
            '<span class="k">Calls:</span><span class="v">' + esc((meta.callCount || 0).toLocaleString()) + '</span>' +
            '<span class="k">Impact:</span><span class="v">' + esc((meta.impactScore || 0).toFixed ? (meta.impactScore || 0).toFixed(1) : meta.impactScore) + '</span>' +
            '<span class="k">Time:</span><span class="v">' + esc(new Date(ts).toLocaleString()) + '</span>' +
            '<span class="k">Execution ID:</span><span class="v">' + esc(pointId || "-") + '</span>' +
            '<span class="k">Template Peak:</span><span class="v">' + (isTemplateMax ? "Yes" : "No") + '</span>' +
            '</div>';

          tooltip.style.display = "block";
          const x = (e.clientX || 0) + 12;
          const y = (e.clientY || 0) - 16;
          tooltip.style.left = x + "px";
          tooltip.style.top = y + "px";
        });

        node.addEventListener("mouseleave", () => {
          tooltip.style.display = "none";
        });
        node.addEventListener("dblclick", () => {
          const hash = node.getAttribute("data-hash") || "";
          focusTemplateRowByHash(hash);
        });
      });

    }

    function focusTemplateRowByHash(hash) {
      if (!hash) return;
      const tableWrap = document.getElementById("tableWrap");
      if (!tableWrap) return;
      const escapedHash = (window.CSS && CSS.escape) ? CSS.escape(hash) : hash.replace(/"/g, '\\"');
      const row = tableWrap.querySelector('tr[data-hash="' + escapedHash + '"]');
      if (!row) return;
      row.scrollIntoView({ behavior: "smooth", block: "center" });
      row.classList.add("row-focus");
      setTimeout(() => row.classList.remove("row-focus"), 1600);
    }

    function render() {
      if (!report) return;
      const text = (document.getElementById("filterText").value || "").trim().toLowerCase();
      const analyticsPanel = document.getElementById("analyticsPanel");
      const tableWrap = document.getElementById("tableWrap");

      if (activeTab === "fingerprints") {
        let rows = [...report.fingerprints];
        const tuneDb = getTuneDatabaseFilterValue();
        if (tuneDb) {
          rows = rows.filter((r) => {
            const dbList = Array.isArray(r.databases) ? r.databases : [];
            return dbList.some((d) => String(d || "").trim().toLowerCase() === tuneDb.toLowerCase());
          });
        }
        if (text) {
          rows = rows.filter((r) => {
            const db = (r.databases || []).join(" ").toLowerCase();
            const tb = (r.tables || []).join(" ").toLowerCase();
            return (
              (r.queryTemplate || "").toLowerCase().includes(text) ||
              (r.sampleQuery || "").toLowerCase().includes(text) ||
              db.includes(text) ||
              tb.includes(text)
            );
          });
        }

        rows.sort((a, b) => {
          const av = sortField === "database" ? (a.databases[0] || "") : sortField === "table" ? (a.tables[0] || "") : a[sortField];
          const bv = sortField === "database" ? (b.databases[0] || "") : sortField === "table" ? (b.tables[0] || "") : b[sortField];
          if (typeof av === "string") return sortDir === "asc" ? av.localeCompare(bv) : bv.localeCompare(av);
          return sortDir === "asc" ? (av - bv) : (bv - av);
        });

        // Impact rank among *visible* (filtered) rows only: 1 = highest impact (left/read as top priority).
        // Independent of current table sort so # and bubble colors always match impact priority.
        const impactRankByHash = {};
        const rowsByImpact = [...rows].sort((a, b) => {
          const bi = Number(b.impactScore) || 0;
          const ai = Number(a.impactScore) || 0;
          if (bi !== ai) return bi - ai;
          const bt = Number(b.totalTimeSec) || 0;
          const at = Number(a.totalTimeSec) || 0;
          if (bt !== at) return bt - at;
          return String(a.queryHash || "").localeCompare(String(b.queryHash || ""));
        });
        rowsByImpact.forEach((r, i) => {
          impactRankByHash[r.queryHash] = i + 1;
        });

        bubbleMetaByHash = {};
        bubbleExecutionById = {};
        bubbleColorByHash = {};
        (report.fingerprints || []).forEach((r) => {
          bubbleMetaByHash[r.queryHash] = r;
        });
        (report.entryPoints || []).forEach((p) => {
          bubbleExecutionById[p.entryId] = p;
        });
        rows.forEach((r) => {
          const rk = impactRankByHash[r.queryHash] || 999;
          bubbleColorByHash[r.queryHash] = rk <= 10 ? rankColor(rk) : "#94a3b8";
        });

        window._optimizerSamples = {};
        window._optimizerDatabases = {};
        rows.forEach((r) => {
          const sample = getSampleForOptimize(r, report);
          if (sample) {
            window._optimizerSamples[r.queryHash] = sample;
            const dbList = Array.isArray(r.databases) ? r.databases : (r.databases && typeof r.databases.forEach === "function" ? Array.from(r.databases) : []);
            const db = (dbList && dbList.find((d) => !/^(mysql|performance_schema|information_schema|sys)$/i.test(String(d || "")))) || (dbList && dbList[0]) || "";
            if (db) window._optimizerDatabases[r.queryHash] = db;
          }
        });

        const maxAvg = Math.max(0.0001, ...rows.map((r) => r.avgTimeSec || 0));
        const tableHtml = `<table>
          <thead>
            <tr>
              <th title="Impact rank among visible rows (1 = highest impact; fixed order, not sort order)">#</th>
              <th onclick="setSort('impactScore')" title="Higher = more impact; column next to rank for left-to-right priority read">Impact</th>
              <th onclick="setSort('rating')">QueryRating</th>
              <th onclick="setSort('queryTemplate')">Query Fingerprint</th>
              <th onclick="setSort('totalTimeSec')">ResponseTime</th>
              <th onclick="setSort('usagePct')">PCT(%)</th>
              <th onclick="setSort('callCount')">Calls</th>
              <th onclick="setSort('avgTimeSec')">AvgResponseTime</th>
              <th class="optimizer-col">Actions</th>
              <th onclick="setSort('maxTimeSec')">Max</th>
              <th onclick="setSort('database')">Database</th>
              <th onclick="setSort('table')">Table</th>
              <th onclick="setSort('queryScore')" title="Query Score Model: Score = 40% ResponseTime + 25% Usage(PCT) + 25% RowsExamined + 10% QueryScore. QueryScore follows optimizer pattern (rows examined vs rows sent ratio): avg_rows_examined / max(avg_rows_sent, 1)">QueryScore</th>
              <th onclick="setSort('avgRowsExamined')">RowsExamined</th>
              <th onclick="setSort('totalRowsSent')" title="Rows returned to client">RowsReturn</th>
              <th onclick="setSort('qualityTag')">Type</th>
              <th>Recommended Indexes</th>
            </tr>
          </thead>
          <tbody>
            ${rows.map((r, idx) => {
              const impactRank = impactRankByHash[r.queryHash] || idx + 1;
              const sparkPct = Math.max(2, Math.min(100, Math.round((r.avgTimeSec / maxAvg) * 100)));
              const pct = Math.max(0, Math.min(100, Number(r.usagePct) || 0));
              const pctColor = pctImpactColor(pct);
              const sampleForOptimize = getSampleForOptimize(r, report);
              const canOptimize = r.canOptimize === true;
              const optimizerWhy = canOptimize ? "" : String(r.optimizerWhy || (
                sampleForOptimize.length === 0 ? "No sample query (check CSV column: sql_text, query, statement, sql, query_text, query_stmt, sql_statement, or text)" :
                !isOptimizableSql(sampleForOptimize) ? "Query must start with SELECT, UPDATE, DELETE, or WITH (got: " + (sampleForOptimize.slice(0, 40) || "(empty)") + "...)" :
                "Not optimizable for this engine"
              ));
              const queryScoreTip = "Query Score Model: Score = 40% ResponseTime + 25% Usage(PCT) + 25% RowsExamined + 10% QueryScore. QueryScore follows optimizer pattern (rows examined vs rows sent ratio): avg_rows_examined / max(avg_rows_sent, 1)";
              const queryScoreValue = canOptimize ? Math.round(r.queryScore || 0) : "";
              const recs = r.recommendedIndexes || [];
              const hasRunOpt = !!report.hasRunOptimizeAll;
              let recsHtml;
              if (!hasRunOpt) {
                recsHtml = '<button type="button" class="index-recs-optimize-btn" onclick="event.stopPropagation(); optimizeAllQueries()" title="Analyze all queries and show recommended indexes">&#9889; Optimize All Queries</button>';
              } else if (recs.length === 0) {
                recsHtml = '<span class="index-recs-empty">No recommendations</span>';
              } else {
                const primaryCount = recs.filter(function(rec) { return !rec.isOptional; }).length;
                const optCount = recs.filter(function(rec) { return !!rec.isOptional; }).length;
                var summaryParts = [];
                if (primaryCount > 0) summaryParts.push(primaryCount + " idx");
                if (optCount > 0) summaryParts.push(optCount + " opt");
                const summary = summaryParts.length ? summaryParts.join(" \u2022 ") : recs.length + " idx";
                const ddlFull = recs.map((rec) => rec.createStatement || "").filter(Boolean).join("\n\n");
                const ddlTooltip = ddlFull.length > 400 ? ddlFull.slice(0, 300) + "... (click to copy all)" : ddlFull;
                const tipsParts = recs.map((rec) => {
                  var t = (rec.reason || "");
                  if (rec.warning) t += "\nWarning: " + rec.warning;
                  if (rec.estimatedImprovement) t += "\nImpact: " + rec.estimatedImprovement;
                  return t;
                });
                const tipsFull = tipsParts.join("\n---\n");
                const tipsTooltip = tipsFull.length > 400 ? tipsFull.slice(0, 350) + "..." : tipsFull;
                recsHtml = '<div class="index-rec-actions"><span class="index-rec-summary">' + summary.replace(/</g, "&lt;").replace(/>/g, "&gt;") + '</span>' +
                  '<button type="button" class="btn index-rec-copy-btn" data-query-hash="' + String(r.queryHash || "").replace(/"/g, "&quot;") + '" data-action="copyIndexRecs" title="Copy index DDL" aria-label="Copy DDL">&#128203;</button>' +
                  '<button type="button" class="btn index-rec-rewrite-btn" data-query-hash="' + String(r.queryHash || "").replace(/"/g, "&quot;") + '" data-action="copyRewriteTips" title="Copy rewrite tips" aria-label="Copy tips">&#128221;</button></div>';
              }
              const hashAttr = String(r.queryHash || "").replace(/"/g, "&quot;");
              let actionsHtml = "";
              if (canOptimize) {
                actionsHtml =
                  '<div class="action-buttons">' +
                  '<button type="button" class="btn action-row-btn" data-query-hash="' + hashAttr + '" data-action="explain" title="EXPLAIN Plan">&#128221;</button>' +
                  '<button type="button" class="btn action-row-btn" data-query-hash="' + hashAttr + '" data-action="optimize" title="Optimize Query">&#9889;</button>' +
                  '<button type="button" class="btn action-row-btn" data-query-hash="' + hashAttr + '" data-action="copy" title="Copy Query">&#128203;</button>' +
                  '</div>';
              } else if (optimizerWhy) {
                actionsHtml =
                  '<span class="optimizer-no-btn-hint" title="' + optimizerWhy.replace(/"/g, "&quot;") + '">—</span>';
              }
              return `<tr data-hash="${r.queryHash}">
                <td><span class="rank-cell" style="${rankCellStyle(impactRank)}">${impactRank}</span></td>
                <td>${(r.impactScore || 0).toFixed(1)}</td>
                <td><span class="star" title="${r.rating}/5">${stars(r.rating)}</span> <span class="score-chip grade-${r.scoreGrade}">${r.optimizationScore}/100</span></td>
                <td class="query query-fingerprint-col" title="${(r.sampleQuery || "").replace(/"/g, "&quot;")}">${r.queryTemplate}</td>
                <td>${fmtSec(r.totalTimeSec)}</td>
                <td>
                  <span class="pct-heat">
                    <span class="pct-heat-fill" style="width:${pct.toFixed(1)}%; background:${pctColor};"></span>
                    <span class="pct-heat-text">${r.usagePct.toFixed(1)}%</span>
                  </span>
                </td>
                <td>${r.callCount}</td>
                <td>${fmtSec(r.avgTimeSec)} <span class="spark"><span style="width:${sparkPct}%"></span></span></td>
                <td class="optimizer-col" title="${optimizerWhy ? optimizerWhy.replace(/"/g, "&quot;") : ""}">${actionsHtml}</td>
                <td>${fmtSec(r.maxTimeSec)}</td>
                <td>${(r.databases || []).join(", ") || "-"}</td>
                <td>${(r.tables || []).join(", ") || "-"}</td>
                <td title="${canOptimize ? queryScoreTip : ""}">${queryScoreValue}</td>
                <td>${Math.round(r.avgRowsExamined).toLocaleString()}</td>
                <td>${(r.totalRowsSent ?? 0).toLocaleString()}</td>
                <td><span class="tag tag-${r.qualityTag}">${r.qualityTag}</span></td>
                <td class="index-recs-col">${recsHtml}</td>
              </tr>`;
            }).join("")}
          </tbody>
        </table>`;
        analyticsPanel.innerHTML = renderSlowBubbleChart(report.entryPoints || []);
        tableWrap.innerHTML = tableHtml;
        wireBubbleTooltip();
        return;
      }

      const usageTables = report.usage && report.usage.tables ? report.usage.tables : [];
      const usageDatabases = report.usage && report.usage.databases ? report.usage.databases : [];
      const usageUsers = report.usage && report.usage.users ? report.usage.users : [];

      if (activeTab === "users") {
        let rows = [...usageUsers];
        if (text) {
          rows = rows.filter((r) =>
            r.name.toLowerCase().includes(text) || (r.sampleQuery || "").toLowerCase().includes(text)
          );
        }
        rows.sort((a, b) => {
          const av = a[usageSortField];
          const bv = b[usageSortField];
          if (typeof av === "string") return usageSortDir === "asc" ? av.localeCompare(bv) : bv.localeCompare(av);
          return usageSortDir === "asc" ? (av - bv) : (bv - av);
        });

        analyticsPanel.innerHTML =
          '<div class="dual-pies">' +
            renderBars("Top Users by Usage %", rows, (r) => r.usagePct.toFixed(1) + "%", "usagePct") +
            renderBars("Top Users by Total Time", rows, (r) => fmtSec(r.totalTimeSec), "totalTimeSec") +
          '</div>';
        const maxUsagePct = Math.max(1, ...rows.map((r) => Number(r.usagePct) || 0));
        tableWrap.innerHTML = `<table>
          <thead>
            <tr>
              <th onclick="setUsageSort('name')" style="cursor:pointer;">User</th>
              <th onclick="setUsageSort('count')" style="cursor:pointer;">Calls</th>
              ${usageSortTh('usagePct', 'PCT (%)')}
              ${usageSortTh('totalTimeSec', 'Response Time')}
              <th onclick="setUsageSort('avgTimeSec')" style="cursor:pointer;">Avg Time</th>
              <th onclick="setUsageSort('maxTimeSec')" style="cursor:pointer;">Max Time</th>
              <th onclick="setUsageSort('avgRowsExamined')" style="cursor:pointer;">Avg Rows Examined</th>
              <th>Sample Query</th>
            </tr>
          </thead>
          <tbody>
            ${rows.map((r) => `<tr>
              <td style="${usageHeatStyle(r.usagePct, maxUsagePct)}"><strong>${r.name}</strong></td>
              <td>${r.count}</td>
              <td><span class="usage-pill" style="${usageHeatStyle(r.usagePct, maxUsagePct)}">${r.usagePct.toFixed(1)}%</span></td>
              <td>${fmtSec(r.totalTimeSec)}</td>
              <td>${fmtSec(r.avgTimeSec)}</td>
              <td>${fmtSec(r.maxTimeSec)}</td>
              <td>${Math.round(r.avgRowsExamined).toLocaleString()}</td>
              <td class="query" title="${(r.sampleQuery || "").replace(/"/g, "&quot;")}">${r.sampleQuery || "-"}</td>
            </tr>`).join("")}
          </tbody>
        </table>`;
        return;
      }

      // Table/Database: show both pie charts together, and separate bottom grid tabs.
      analyticsPanel.innerHTML =
        '<div class="dual-pies">' +
          renderPieChart("Top Tables by Usage", usageTables) +
          renderPieChart("Top Databases by Usage", usageDatabases) +
        '</div>';

      const usageSource = usageGridTab === "databases" ? usageDatabases : usageTables;
      let rows = [...usageSource];
      if (text) {
        rows = rows.filter((r) =>
          r.name.toLowerCase().includes(text) || (r.sampleQuery || "").toLowerCase().includes(text)
        );
      }
      rows.sort((a, b) => {
        const av = a[usageSortField];
        const bv = b[usageSortField];
        if (typeof av === "string") return usageSortDir === "asc" ? av.localeCompare(bv) : bv.localeCompare(av);
        return usageSortDir === "asc" ? (av - bv) : (bv - av);
      });

      const maxUsagePct = Math.max(1, ...rows.map((r) => Number(r.usagePct) || 0));
      tableWrap.innerHTML =
        `<div class="tabs" style="margin:0 0 8px 0;">
          <button class="tab ${usageGridTab === "tables" ? "active" : ""}" onclick="setUsageGridTab('tables')">Table Grid</button>
          <button class="tab ${usageGridTab === "databases" ? "active" : ""}" onclick="setUsageGridTab('databases')">Database Grid</button>
        </div>` +
        `<table>
          <thead>
            <tr>
              <th onclick="setUsageSort('name')" style="cursor:pointer;">${usageGridTab === "databases" ? "Database" : "Table"}</th>
              <th onclick="setUsageSort('count')" style="cursor:pointer;">Calls</th>
              ${usageSortTh('usagePct', 'PCT (%)')}
              ${usageSortTh('totalTimeSec', 'Response Time')}
              <th onclick="setUsageSort('avgTimeSec')" style="cursor:pointer;">Avg Time</th>
              <th onclick="setUsageSort('maxTimeSec')" style="cursor:pointer;">Max Time</th>
              <th onclick="setUsageSort('avgRowsExamined')" style="cursor:pointer;">Avg Rows Examined</th>
              <th>Sample Query</th>
            </tr>
          </thead>
          <tbody>
            ${rows.map((r) => `<tr>
              <td style="${usageHeatStyle(r.usagePct, maxUsagePct)}"><strong>${r.name}</strong></td>
              <td>${r.count}</td>
              <td><span class="usage-pill" style="${usageHeatStyle(r.usagePct, maxUsagePct)}">${r.usagePct.toFixed(1)}%</span></td>
              <td>${fmtSec(r.totalTimeSec)}</td>
              <td>${fmtSec(r.avgTimeSec)}</td>
              <td>${fmtSec(r.maxTimeSec)}</td>
              <td>${Math.round(r.avgRowsExamined).toLocaleString()}</td>
              <td class="query" title="${(r.sampleQuery || "").replace(/"/g, "&quot;")}">${r.sampleQuery || "-"}</td>
            </tr>`).join("")}
          </tbody>
        </table>`;
    }

    window.addEventListener("message", (event) => {
      const msg = event.data;
      if (msg.command === "loading") {
        setHomeMode(true);
        document.getElementById("loadingBox").classList.remove("hidden");
        document.getElementById("emptyBox").classList.add("hidden");
        document.getElementById("reportBox").classList.add("hidden");
        document.getElementById("loadingMessage").textContent = msg.message || "Parsing log...";
      } else if (msg.command === "progress") {
        document.getElementById("progressFill").style.width = (msg.percent || 0) + "%";
      } else if (msg.command === "operationStatus") {
        updateOperationStatus(msg);
      } else if (msg.command === "createIndexesProgress") {
        updateCreateIndexesProgress(msg);
      } else if (msg.command === "slowLogTableAvailable") {
        const available = msg.available === true;
        const reason = msg.reason || "";
        const updateBtn = function(btn) {
          if (!btn) return;
          btn.disabled = !available;
          btn.title = available ? "Requires slow_query_log=ON and log_output=TABLE" : (reason || "Slow query log must be enabled with log_output=TABLE");
        };
        updateBtn(document.getElementById("btnAnalyzeSlowLogTable"));
        updateBtn(document.getElementById("btnLoadFromTable"));
      } else if (msg.command === "pgStatStatementsAvailable") {
        const available = msg.available === true;
        const reason = msg.reason || "";
        const statusEl = document.getElementById("pgStatExtensionStatus");
        if (statusEl) {
          statusEl.classList.remove("pg-ext-status--checking", "pg-ext-status--ok", "pg-ext-status--missing");
          if (available) {
            const hostDb = String(msg.hostDatabase || "").trim();
            statusEl.textContent = hostDb ? ("Ready (" + hostDb + ")") : "Extension active";
            statusEl.classList.add("pg-ext-status--ok");
            statusEl.title = hostDb
              ? ("pg_stat_statements is queryable via database \"" + hostDb + "\"" + (reason || ""))
              : "pg_stat_statements is installed and queryable on this server";
          } else {
            statusEl.textContent = "Not installed";
            statusEl.classList.add("pg-ext-status--missing");
            statusEl.title = reason || "Enable pg_stat_statements on PostgreSQL";
          }
        }
        const updatePgBtn = function(btn) {
          if (!btn) return;
          btn.disabled = !available;
          btn.title = available
            ? "Load aggregated query statistics from pg_stat_statements"
            : (reason || "Enable pg_stat_statements extension on PostgreSQL");
        };
        updatePgBtn(document.getElementById("btnLoadFromPerfSchema"));
        document.querySelectorAll('button[data-action="loadFromPerfSchema"]').forEach(updatePgBtn);
      } else if (msg.command === "pgStatStatementsDatabases") {
        const selectEl = document.getElementById("pgStatDatabase");
        const workloadEl = document.getElementById("pgWorkloadDatabase");
        const hintEl = document.getElementById("pgStatDbHint");
        if (!selectEl) return;
        const databases = Array.isArray(msg.databases) ? msg.databases : [];
        const workloadDatabases = Array.isArray(msg.workloadDatabases) ? msg.workloadDatabases : [];
        const selected = String(msg.selected || "").trim();
        const message = String(msg.message || "").trim();
        const prev = String(selectEl.value || "").trim();
        const prevWorkload = workloadEl ? String(workloadEl.value || "").trim() : "";
        selectEl.innerHTML = "";
        if (!databases.length) {
          const emptyOpt = document.createElement("option");
          emptyOpt.value = "";
          emptyOpt.textContent = "No extension databases";
          selectEl.appendChild(emptyOpt);
          selectEl.value = "";
          selectEl.disabled = true;
          if (workloadEl) {
            workloadEl.innerHTML = "";
            const wEmpty = document.createElement("option");
            wEmpty.value = "";
            wEmpty.textContent = "All databases";
            workloadEl.appendChild(wEmpty);
            workloadEl.disabled = true;
          }
          if (hintEl) {
            hintEl.textContent = message || "No databases have pg_stat_statements installed.";
            hintEl.classList.remove("hidden", "ok");
          }
        } else {
          databases.forEach(function(name) {
            const opt = document.createElement("option");
            opt.value = String(name || "");
            opt.textContent = String(name || "");
            selectEl.appendChild(opt);
          });
          const next = prev && databases.indexOf(prev) >= 0
            ? prev
            : (selected && databases.indexOf(selected) >= 0 ? selected : databases[0]);
          selectEl.value = next;
          selectEl.disabled = false;
          if (workloadEl) {
            workloadEl.innerHTML = "";
            const allOpt = document.createElement("option");
            allOpt.value = "";
            allOpt.textContent = "All databases";
            workloadEl.appendChild(allOpt);
            workloadDatabases.forEach(function(name) {
              const opt = document.createElement("option");
              opt.value = String(name || "");
              opt.textContent = String(name || "");
              workloadEl.appendChild(opt);
            });
            const wNext = prevWorkload && (prevWorkload === "" || workloadDatabases.indexOf(prevWorkload) >= 0)
              ? prevWorkload
              : "";
            workloadEl.value = wNext;
            workloadEl.disabled = false;
          }
          if (hintEl) {
            hintEl.textContent = "Stats are cluster-wide. Connect through any DB with the extension; default load shows all target databases.";
            hintEl.classList.add("ok");
            hintEl.classList.remove("hidden");
          }
        }
        const homeError = document.getElementById("homeError");
        if (homeError) {
          if (!databases.length && message) {
            homeError.textContent = message;
            homeError.classList.remove("hidden");
          } else if (homeError.textContent && homeError.textContent.indexOf("pg_stat_statements") >= 0) {
            homeError.textContent = "";
            homeError.classList.add("hidden");
          }
        }
      } else if (msg.command === "slowLogState") {
        const state = msg.state || "hidden";
        const fileSize = msg.fileSize || 0;
        const isPg = msg.engine === "postgresql";
        const FILE_SIZE_LIMIT = 100 * 1024 * 1024;
        const isLarge = fileSize >= FILE_SIZE_LIMIT;
        try {
        } catch (e) {}
        const homeWrap = document.getElementById("slowLogStateBtnHome");
        const tailLinesRow = document.getElementById("tailLinesRow");
        const updateBtn = function(btn) {
          if (!btn) return;
          btn.setAttribute("data-action", state === "disabled" ? "enableSlowQueryLog" : "loadFromDetectedPath");
          if (isPg) {
            btn.textContent = state === "disabled" ? "Enable PG Slow Logging" : "Load from PostgreSQL Server Log";
            btn.title = state === "disabled"
              ? "Enable log_min_duration_statement on PostgreSQL"
              : (msg.path ? "Click to load: " + msg.path : "Load PostgreSQL server log");
          } else {
            btn.textContent = state === "disabled" ? "Enable Slow Query Log" : "Load from MySQL Slow Query Log";
            btn.title = state === "loadReady" && msg.path ? "Click to load: " + msg.path : (state === "disabled" ? "Enable slow query logging on MySQL server" : "Load slow query log file");
          }
          btn.classList.remove("auto-detected", "auto-disabled");
          if (state === "loadReady") {
            btn.classList.add("auto-detected");
          } else if (state === "disabled") {
            btn.classList.add("auto-disabled");
          }
        };
        if (state === "hidden") {
          if (homeWrap) homeWrap.classList.add("hidden");
          if (tailLinesRow) tailLinesRow.classList.add("hidden");
          const statusEl = document.getElementById("autoDetectStatus");
          if (statusEl) statusEl.classList.add("hidden");
        } else if (state === "pathHint") {
          if (homeWrap) homeWrap.classList.remove("hidden");
          if (tailLinesRow) tailLinesRow.classList.add("hidden");
          window._lastPathHintPath = msg.path || "";
          const statusEl = document.getElementById("autoDetectStatus");
          if (statusEl) {
            statusEl.classList.remove("hidden");
            statusEl.classList.add("error");
            const pathPart = msg.path ? "Expected location (datadir + filename): " + msg.path + ". " : "";
            const tablePart = !isPg && msg.tableAvailable ? "Use 'Load from mysql.slow_log' (table format) or " : "";
            const uploadHint = isPg ? "upload a PostgreSQL log file manually." : "upload file manually.";
            statusEl.textContent = pathPart + tablePart + uploadHint;
            statusEl.title = msg.path || msg.error || "";
          }
          const pathHintBtn = homeWrap ? homeWrap.querySelector(".slow-log-state-btn") : null;
          if (pathHintBtn) {
            pathHintBtn.setAttribute("data-action", msg.path ? "tryLoadFromPath" : "loadFile");
            pathHintBtn.textContent = msg.path ? "Try Load from Path" : "Upload File";
            pathHintBtn.title = msg.path ? "Try loading from: " + msg.path : "Upload slow query log file";
          }
        } else {
          if (state === "loadReady" && isLarge) {
            if (homeWrap) homeWrap.classList.add("hidden");
            if (tailLinesRow) {
              tailLinesRow.classList.remove("hidden");
              const loadBtn = tailLinesRow.querySelector("[data-action=loadFromDetectedPath]");
              if (loadBtn) updateBtn(loadBtn);
            }
          } else {
            if (homeWrap) {
              homeWrap.classList.remove("hidden");
              updateBtn(homeWrap.querySelector(".slow-log-state-btn"));
            }
            if (tailLinesRow) tailLinesRow.classList.add("hidden");
          }
          const statusEl = document.getElementById("autoDetectStatus");
          if (statusEl && state === "loadReady" && msg.path) {
            const sizeStr = (typeof window.formatSize === "function" && msg.fileSize) ? " (" + window.formatSize(msg.fileSize) + ")" : "";
            statusEl.textContent = "Detected: " + msg.path + sizeStr;
            statusEl.classList.remove("hidden", "error");
            statusEl.title = msg.path;
          } else if (statusEl && state === "disabled") {
            statusEl.textContent = isPg ? "PostgreSQL slow logging is disabled (log_min_duration_statement)" : "Slow query log is disabled";
            statusEl.classList.remove("hidden");
            statusEl.classList.add("error");
          }
        }
      } else if (msg.command === "loaded") {
        if (!msg.report) return;
        setHomeMode(false);
        report = msg.report;
        document.getElementById("loadingBox").classList.add("hidden");
        document.getElementById("emptyBox").classList.add("hidden");
        document.getElementById("reportBox").classList.remove("hidden");
        var prevTiles = window._tilePrevValues || {};
        function updateTile(id, newVal, cardSelector) {
          var el = document.getElementById(id);
          if (!el) return;
          var card = cardSelector ? document.querySelector(cardSelector) : el.closest(".card");
          if (!card) return;
          var prev = prevTiles[id];
          var changed = prev !== undefined && String(prev) !== String(newVal);
          prevTiles[id] = newVal;
          el.textContent = newVal;
          if (changed && card) {
            card.classList.remove("tile-updated");
            card.offsetHeight;
            card.classList.add("tile-updated");
            clearTimeout(card._tileTimeout);
            card._tileTimeout = setTimeout(function() { card.classList.remove("tile-updated"); }, 60000);
          }
        }
        var tq = (report.totalQueries || 0).toLocaleString();
        var fp = (report.uniqueFingerprints || 0).toLocaleString();
        var tr = fmtSec(report.totalSlowTimeSec || 0);
        var as = Math.round(report.avgOptimizationScore || 0) + "/100";
        updateTile("sTotalQueries", tq);
        updateTile("sFingerprints", fp);
        updateTile("sTotalSlowTime", tr);
        updateTile("sAvgScore", as);
        const sIndexesEl = document.getElementById("sIndexes");
        const sIndexesCard = sIndexesEl ? sIndexesEl.closest(".card") : null;
        const sIndexesLabel = sIndexesCard ? sIndexesCard.querySelector(".k") : null;
        if (sIndexesEl) {
          const idxCount = (report.indexDetails || []).length || (report.totalRecommendedIndexes ?? 0);
          const critical = report.criticalFingerprints ?? 0;
          const hasOptimized = idxCount > 0;
          const optimizableCount = (report.fingerprints || []).filter(function(r) {
            return r.canOptimize === true;
          }).length;
          const idxVal = hasOptimized ? (critical > 0 ? idxCount + " • " + critical + " high priority" : String(idxCount)) : (optimizableCount > 0 ? optimizableCount + " optimizable" : "—");
          if (sIndexesLabel) sIndexesLabel.textContent = hasOptimized ? "Indexes" : "Indexes / Optimizable";
          var prevIdx = prevTiles["sIndexes"];
          var idxChanged = prevIdx !== undefined && String(prevIdx) !== String(idxVal);
          prevTiles["sIndexes"] = idxVal;
          sIndexesEl.textContent = idxVal;
          sIndexesEl.title = hasOptimized ? (critical > 0 ? idxCount + " recommended indexes, " + critical + " high priority" : "") : (optimizableCount > 0 ? optimizableCount + " queries can be optimized. Run Optimize All to get index recommendations." : "Run Optimize All to get index recommendations");
          var card = sIndexesEl.closest(".card");
          if (idxChanged && card) {
            card.classList.remove("tile-updated");
            card.offsetHeight;
            card.classList.add("tile-updated");
            clearTimeout(card._tileTimeout);
            card._tileTimeout = setTimeout(function() { card.classList.remove("tile-updated"); }, 60000);
          }
        }
        const sFullEl = document.getElementById("sFullScanImprovement");
        const sFullCard = sFullEl ? sFullEl.closest(".card") : null;
        const sFullLabel = sFullCard ? sFullCard.querySelector(".k") : null;
        if (sFullEl) {
          const fullScan = report.fullTableScanQueries ?? 0;
          const exp = report.expectedImprovement || "";
          const hasFullScanData = fullScan > 0 || exp.length > 0;
          const critical = report.criticalFingerprints ?? 0;
          const parts = [];
          if (fullScan > 0) parts.push(fullScan + " full scans");
          if (exp) parts.push(exp);
          const display = parts.join(" • ");
          const oneLine = display.length > 40 ? display.slice(0, 37) + "…" : display;
          var fullVal = hasFullScanData ? (display ? oneLine : "-") : (critical > 0 ? critical + " high impact" : "—");
          if (sFullLabel) sFullLabel.textContent = hasFullScanData ? "Full Table Scan / Improvement" : "Full Table Scan / High Impact";
          var prevFull = prevTiles["sFullScanImprovement"];
          var fullChanged = prevFull !== undefined && String(prevFull) !== String(fullVal);
          prevTiles["sFullScanImprovement"] = fullVal;
          sFullEl.textContent = fullVal;
          sFullEl.title = hasFullScanData ? (display || "") : (critical > 0 ? critical + " high impact queries. Run Optimize All to analyze full table scans." : "Run Optimize All to analyze full table scans");
          var card = sFullEl.closest(".card");
          if (fullChanged && card) {
            card.classList.remove("tile-updated");
            card.offsetHeight;
            card.classList.add("tile-updated");
            clearTimeout(card._tileTimeout);
            card._tileTimeout = setTimeout(function() { card.classList.remove("tile-updated"); }, 60000);
          }
        }
        window._tilePrevValues = prevTiles;
        const parseErrors = report.parseErrors || [];
        document.getElementById("parseErrors").textContent = parseErrors.length
          ? ("Parse warnings: " + parseErrors.length + " (showing up to 10)")
          : "";
        const btnOpt = document.getElementById("btnOptimizeAll");
        if (btnOpt) btnOpt.disabled = !(report.hasOptimizableQueries === true);
        const totalRecs = (report.totalRecommendedIndexes ?? 0);
        const createWrap = document.querySelector(".dropdown-wrap");
        const exportWrap = document.querySelectorAll(".dropdown-wrap")[1];
        const btnCreate = document.getElementById("btnCreateIndexes");
        const btnExport = document.getElementById("btnExportIndexDDL");
        if (btnCreate) btnCreate.disabled = totalRecs === 0;
        if (btnExport) btnExport.disabled = totalRecs === 0;
        if (createWrap) createWrap.style.opacity = totalRecs === 0 ? "0.5" : "1";
        if (exportWrap) exportWrap.style.opacity = totalRecs === 0 ? "0.5" : "1";
        setTab("fingerprints");
        const sortBy = msg.sortBy || "totalTime";
        const sortFieldMap = { totalTime: "totalTimeSec", avgTime: "avgTimeSec", callCount: "callCount" };
        if (sortFieldMap[sortBy]) {
          sortField = sortFieldMap[sortBy];
          sortDir = "desc";
        }
        var src = msg.source || "perfSchema";
        currentSource = src;
        populatePgTuneDatabaseFilter(report, msg.tuneDatabaseFilter || "");
        [document.getElementById("btnLoadFromPerfSchema"), document.getElementById("btnLoadFromTable"), document.getElementById("btnLoadFromFileTop")].forEach(function(btn) {
          if (!btn) return;
          var isActive = (src === "perfSchema" && btn.id === "btnLoadFromPerfSchema") || (src === "slowLogTable" && btn.id === "btnLoadFromTable") || (src === "file" && btn.id === "btnLoadFromFileTop");
          btn.classList.toggle("primary", isActive);
        });
        render();
      } else if (msg.command === "optimizeAllComplete") {
        if (msg.report) {
          report = msg.report;
          report.hasRunOptimizeAll = true;
          if (msg.indexRecommendationsByHash && report.fingerprints) {
            var recsByHash = msg.indexRecommendationsByHash;
            var totalRecs = 0;
            report.fingerprints = report.fingerprints.map(function(fp) {
              var recs = recsByHash[fp.queryHash] || fp.recommendedIndexes || [];
              totalRecs += recs.length;
              return Object.assign({}, fp, { recommendedIndexes: recs });
            });
            report.totalRecommendedIndexes = totalRecs;
          }
          var btnOpt = document.getElementById("btnOptimizeAll");
          if (btnOpt) btnOpt.disabled = !(report.hasOptimizableQueries === true);
          var totalIdx = (report.totalRecommendedIndexes ?? 0);
          var createWrap = document.querySelector(".dropdown-wrap");
          var exportWrap = document.querySelectorAll(".dropdown-wrap")[1];
          var btnCreate = document.getElementById("btnCreateIndexes");
          var btnExport = document.getElementById("btnExportIndexDDL");
          if (btnCreate) btnCreate.disabled = totalIdx === 0;
          if (btnExport) btnExport.disabled = totalIdx === 0;
          if (createWrap) createWrap.style.opacity = totalIdx === 0 ? "0.5" : "1";
          if (exportWrap) exportWrap.style.opacity = totalIdx === 0 ? "0.5" : "1";
          setTab("fingerprints");
          render();
        }
      } else if (msg.command === "error") {
        setHomeMode(true);
        document.getElementById("loadingBox").classList.add("hidden");
        document.getElementById("reportBox").classList.add("hidden");
        document.getElementById("emptyBox").classList.remove("hidden");
        const homeError = document.getElementById("homeError");
        if (homeError) {
          var errPrefix = msg.loadSource === "queryDigest" ? "" : "Failed to parse log: ";
          homeError.textContent = errPrefix + (msg.message || "Unknown error");
          homeError.classList.remove("hidden");
        }
      } else if (msg.command === "showToolModal") {
        const overlay = document.getElementById("toolModalOverlay");
        const msgEl = document.getElementById("toolModalMessage");
        const btnWrap = document.getElementById("toolModalButtons");
        const headerEl = document.getElementById("toolModalHeader");
        const box = document.getElementById("toolModalBox");
        if (overlay && msgEl && btnWrap) {
          if (headerEl) headerEl.classList.add("hidden");
          if (box) { box.classList.remove("diagnostic-modal"); box.style.maxWidth = ""; }
          msgEl.textContent = msg.message || "";
          msgEl.style.whiteSpace = "";
          msgEl.style.maxHeight = "";
          msgEl.style.overflowY = "";
          btnWrap.innerHTML = "";
          const actions = { "Copy Enable SQL": "copyEnableSql", "Copy SQL: Lower long_query_time": "copyLowerLongQueryTime", "Cancel": "cancel" };
          (msg.buttons || []).forEach(function(label) {
            const btn = document.createElement("button");
            btn.className = label === "Cancel" ? "btn btn-ghost" : "btn btn-primary";
            btn.textContent = label;
            btn.onclick = function(e) {
              e.stopPropagation();
              overlay.classList.remove("visible");
              if (actions[label] && actions[label] !== "cancel") {
                vscode.postMessage({ command: "modalAction", action: actions[label] });
              }
            };
            btnWrap.appendChild(btn);
          });
          overlay.onclick = function(e) {
            if (e.target === overlay) overlay.classList.remove("visible");
          };
          overlay.classList.add("visible");
        }
      } else if (msg.command === "showDiagnosticModal") {
        const overlay = document.getElementById("toolModalOverlay");
        const msgEl = document.getElementById("toolModalMessage");
        const btnWrap = document.getElementById("toolModalButtons");
        const headerEl = document.getElementById("toolModalHeader");
        const titleEl = document.getElementById("toolModalTitle");
        const box = document.getElementById("toolModalBox");
        const closeBtn = document.getElementById("toolModalClose");
        if (overlay && msgEl && btnWrap) {
          if (headerEl && titleEl) {
            titleEl.textContent = msg.title || "Diagnostic";
            headerEl.classList.remove("hidden");
          }
          if (box) { box.classList.add("diagnostic-modal"); box.style.maxWidth = "520px"; }
          msgEl.textContent = msg.message || "";
          msgEl.style.whiteSpace = "pre-wrap";
          msgEl.style.maxHeight = "70vh";
          msgEl.style.overflowY = "auto";
          btnWrap.innerHTML = "";
          const payload = msg.payload || {};
          var btnLabels = msg.buttons || ["OK"];
          btnLabels.forEach(function(label) {
            const btn = document.createElement("button");
            var isPrimary = label === "Enable Consumer" || (btnLabels.length === 1 && label === "OK");
            btn.className = isPrimary ? "btn btn-primary" : "btn btn-ghost";
            btn.textContent = label;
            btn.onclick = function(e) {
              e.stopPropagation();
              overlay.classList.remove("visible");
              if (label === "Enable Consumer") {
                vscode.postMessage({ command: "modalAction", action: "enableDigestConsumer", payload: payload });
              }
            };
            btnWrap.appendChild(btn);
          });
          if (closeBtn) {
            closeBtn.onclick = function(e) {
              e.stopPropagation();
              overlay.classList.remove("visible");
            };
          }
          overlay.onclick = function(e) {
            if (e.target === overlay) overlay.classList.remove("visible");
          };
          overlay.classList.add("visible");
        }
      } else if (msg.command === "showMessage") {
        const banner = document.getElementById("toolMessageBanner");
        if (banner) {
          banner.textContent = msg.message || "";
          banner.classList.remove("hidden");
          setTimeout(function() { banner.classList.add("hidden"); }, 8000);
        }
      } else if (msg.command === "renderCreateIndexesOverlay") {
        const el = document.getElementById("createIndexesOverlay");
        if (el) {
          el.innerHTML = msg.html || "";
          el.classList.add("active");
          el.scrollTop = 0;
          const first = el.firstElementChild;
          if (first) first.scrollTop = 0;
          if (typeof window.updateCreateIndexesSummary === "function") window.updateCreateIndexesSummary();
        }
      } else if (msg.command === "updateCreateIndexesOverlay") {
        const el = document.getElementById("createIndexesOverlay");
        if (el) {
          el.innerHTML = msg.html || "";
          el.classList.add("active");
          el.scrollTop = 0;
          const first = el.firstElementChild;
          if (first) first.scrollTop = 0;
          const scroller = el.querySelector(".cip-result-scroll,.cip-grid-wrap");
          if (scroller) scroller.scrollTop = 0;
          if (typeof window.updateCreateIndexesSummary === "function") window.updateCreateIndexesSummary();
        }
        window.__createIndexesDropTargets = msg.dropTargets || [];
      } else if (msg.command === "createIndexesDropStart") {
        if (typeof window.setCreateIndexesDropButtonsDisabled === "function") window.setCreateIndexesDropButtonsDisabled(true);
        const cancelBtn = document.querySelector("#createIndexesOverlay #cip-drop-cancel-btn");
        if (cancelBtn) cancelBtn.style.display = "";
        const statusEl = document.querySelector("#createIndexesOverlay #cip-drop-status");
        if (statusEl) { statusEl.textContent = "Dropping " + (msg.total || 0) + " index(es)..."; statusEl.className = "cip-drop-status active"; }
      } else if (msg.command === "createIndexesDropProgress") {
        const overlay = document.getElementById("createIndexesOverlay");
        if (overlay) {
          const rows = overlay.querySelectorAll("tr[data-table][data-index-name]");
          for (var i = 0; i < rows.length; i++) {
            if (rows[i].getAttribute("data-table") === msg.table && rows[i].getAttribute("data-index-name") === msg.indexName) {
              var statusCell = rows[i].querySelector(".cip-status-cell");
              var errorCell = rows[i].querySelector(".cip-error-cell");
              if (statusCell) statusCell.innerHTML = "<span class=\"cip-badge cip-status-" + (msg.status === "dropped" ? "dropped" : "drop-failed") + "\">" + (msg.status === "dropped" ? "dropped" : "drop failed") + "</span>";
              if (errorCell && msg.error) errorCell.textContent = msg.error;
              break;
            }
          }
          var statusEl = overlay.querySelector("#cip-drop-status");
          if (statusEl) {
            var detail = msg.message || ("Dropping " + (msg.done || 0) + "/" + (msg.total || 0) + " index(es)...");
            if (msg.details && msg.details.state) detail += "\nState: " + msg.details.state;
            if (msg.details && msg.details.threadId) detail += " | Thread: " + msg.details.threadId;
            statusEl.textContent = detail;
            statusEl.className = "cip-drop-status active" + (msg.severity === "blocked" ? " error" : msg.severity === "warning" ? " warn" : "");
          }
        }
      } else if (msg.command === "createIndexesDropComplete") {
        const statusEl = document.querySelector("#createIndexesOverlay #cip-drop-status");
        if (typeof window.setCreateIndexesDropButtonsDisabled === "function") window.setCreateIndexesDropButtonsDisabled(true);
        const cancelBtn = document.querySelector("#createIndexesOverlay #cip-drop-cancel-btn");
        if (cancelBtn) cancelBtn.style.display = "none";
        if (statusEl) {
          var details = Array.isArray(msg.details) && msg.details.length ? "\n\nDetails:\n- " + msg.details.join("\n- ") : "";
          var cls = (msg.failed || 0) > 0 ? ((msg.dropped || 0) > 0 ? " warn" : " error") : " success";
          statusEl.textContent = (msg.message || ("Dropped " + (msg.dropped || 0) + " of " + (msg.total || 0) + " index(es).")) + details;
          statusEl.className = "cip-drop-status active" + cls;
        }
      } else if (msg.command === "hideCreateIndexesOverlay") {
        const el = document.getElementById("createIndexesOverlay");
        if (el) el.classList.remove("active");
      } else if (msg.command === "optimizerSettings") {
        optimizerSettings = msg.settings || null;
        applyOptimizerSettingsToForm(optimizerSettings);
      }
    });
    try { vscode.postMessage({ command: "webviewReady" }); } catch (e) {}

    // Home-screen drag and drop upload.
    const dropZone = document.getElementById("dropZone");
    if (dropZone) {
      debugLog("Drop zone initialized", { id: "dropZone" });
      const prevent = (e) => { e.preventDefault(); e.stopPropagation(); };
      ["dragenter", "dragover", "dragleave", "drop"].forEach((name) => {
        window.addEventListener(name, prevent, false);
      });
      ["dragenter", "dragover"].forEach((name) => {
        dropZone.addEventListener(name, () => dropZone.classList.add("active"), false);
      });
      ["dragleave", "drop"].forEach((name) => {
        dropZone.addEventListener(name, () => dropZone.classList.remove("active"), false);
      });
      dropZone.addEventListener("drop", (e) => {
        debugLog("File dropped on drop zone");
        const files = e && e.dataTransfer ? e.dataTransfer.files : null;
        if (!files || files.length === 0) return;
        const f = files[0];
        const droppedPath = f.path || "";
        if (droppedPath) {
          loadFilePath(droppedPath);
        } else {
          loadFile();
        }
      });
      dropZone.addEventListener("click", () => {
        debugLog("Drop zone clicked");
        loadFile();
      });
    } else {
      debugLog("Drop zone not found", { id: "dropZone" });
    }