/* Click-to-zoom lightbox for docs diagrams. Dependency-free.
 *
 * Sphinx renders graphviz SVG as <object>, which swallows clicks and
 * can't be lightboxed. We replace each with an <img> (crisp vector,
 * clickable), then a click opens a fullscreen overlay with
 * scroll-to-zoom + drag-to-pan so dense diagrams can be read in detail.
 * Esc / double-click / background-click closes. Degrades gracefully:
 * if JS is off, the inline image still renders. */
(function () {
  function ready(fn) {
    if (document.readyState !== "loading") fn();
    else document.addEventListener("DOMContentLoaded", fn);
  }

  ready(function () {
    // 1. graphviz <object> SVG -> clickable <img>
    document
      .querySelectorAll('.graphviz object[type="image/svg+xml"]')
      .forEach(function (obj) {
        var img = document.createElement("img");
        img.src = obj.getAttribute("data");
        img.className = "zoomable";
        img.alt = "diagram — click to zoom";
        obj.parentNode.replaceChild(img, obj);
      });

    // 2. overlay scaffold
    var ov = document.createElement("div");
    ov.id = "arb-zoom-overlay";
    var big = document.createElement("img");
    ov.appendChild(big);
    var hint = document.createElement("div");
    hint.id = "arb-zoom-hint";
    hint.textContent = "scroll = zoom · drag = pan · Esc / dbl-click = close";
    document.body.appendChild(ov);
    document.body.appendChild(hint);

    var scale = 1, tx = 0, ty = 0;
    var dragging = false, moved = false, sx = 0, sy = 0;

    function apply() {
      big.style.transform =
        "translate(" + tx + "px," + ty + "px) scale(" + scale + ")";
    }
    function open(src) {
      ov.classList.add("open");
      big.onload = function () {
        var s =
          Math.min(
            window.innerWidth / big.naturalWidth,
            window.innerHeight / big.naturalHeight
          ) * 0.95;
        scale = s > 0 ? s : 1;
        tx = (window.innerWidth - big.naturalWidth * scale) / 2;
        ty = (window.innerHeight - big.naturalHeight * scale) / 2;
        apply();
      };
      big.src = src;
    }
    function close() {
      ov.classList.remove("open");
      big.src = "";
    }

    document.body.addEventListener("click", function (e) {
      var t = e.target;
      if (t && t.classList && t.classList.contains("zoomable")) open(t.src);
    });

    ov.addEventListener(
      "wheel",
      function (e) {
        e.preventDefault();
        var f = e.deltaY < 0 ? 1.15 : 1 / 1.15;
        // zoom toward the cursor
        tx = e.clientX - (e.clientX - tx) * f;
        ty = e.clientY - (e.clientY - ty) * f;
        scale *= f;
        apply();
      },
      { passive: false }
    );

    ov.addEventListener("mousedown", function (e) {
      dragging = true;
      moved = false;
      sx = e.clientX - tx;
      sy = e.clientY - ty;
      ov.classList.add("grabbing");
    });
    window.addEventListener("mousemove", function (e) {
      if (!dragging) return;
      moved = true;
      tx = e.clientX - sx;
      ty = e.clientY - sy;
      apply();
    });
    window.addEventListener("mouseup", function () {
      dragging = false;
      ov.classList.remove("grabbing");
    });

    // background click (no drag) closes; dbl-click + Esc close
    ov.addEventListener("click", function (e) {
      if (e.target === ov && !moved) close();
    });
    ov.addEventListener("dblclick", close);
    document.addEventListener("keydown", function (e) {
      if (e.key === "Escape") close();
    });
  });
})();
