(() => {
  function mountOverlayManagement(root, { signal } = {}) {
  const lifecycleSignal = signal || new AbortController().signal;
  let obsStatusTimer = null;
  let editorCleanup = () => {};
  async function jsonRequest(url, options = {}) {
    const response = await fetch(url, {
      credentials: "same-origin",
      headers: { "Content-Type": "application/json", ...(options.headers || {}) },
      ...options
    });
    const payload = await response.json().catch(() => ({ ok: false, error: "Lumi returned an unexpected reply." }));
    if (!response.ok) throw new Error(payload.error || "The request did not work.");
    return payload;
  }

  document.querySelectorAll("[data-copy-value]").forEach((button) => {
    button.addEventListener("click", async () => {
      try {
        await navigator.clipboard.writeText(button.dataset.copyValue || "");
        const original = button.textContent;
        button.textContent = "Copied";
        setTimeout(() => { button.textContent = original; }, 1400);
      } catch {
        button.closest(".overlay-url-row")?.querySelector("input")?.select();
      }
    });
  });

  function wireModal(modalSelector, openSelector, closeSelector) {
    const modal = document.querySelector(modalSelector);
    if (!modal) return;
    const open = () => {
      modal.classList.add("is-open");
      modal.setAttribute("aria-hidden", "false");
      modal.querySelector("input")?.focus();
    };
    const close = () => {
      modal.classList.remove("is-open");
      modal.setAttribute("aria-hidden", "true");
    };
    document.querySelectorAll(openSelector).forEach((button) => button.addEventListener("click", open));
    modal.querySelectorAll(closeSelector).forEach((button) => button.addEventListener("click", close));
    modal.addEventListener("click", (event) => { if (event.target === modal) close(); });
    document.addEventListener("keydown", (event) => { if (event.key === "Escape") close(); }, { signal: lifecycleSignal });
  }

  wireModal("[data-overlay-create-modal]", "[data-overlay-create-open]", "[data-overlay-create-close]");
  wireModal("[data-scene-create-modal]", "[data-scene-create-open]", "[data-scene-create-close]");

  const supportedHexColor = /^#(?:[0-9a-f]{3}|[0-9a-f]{4}|[0-9a-f]{6}|[0-9a-f]{8})$/i;
  const pickerValue = (value) => {
    if (!supportedHexColor.test(value)) return null;
    const digits = value.slice(1);
    return digits.length <= 4
      ? `#${digits.slice(0, 3).split("").map((digit) => digit + digit).join("")}`
      : `#${digits.slice(0, 6)}`;
  };
  const alphaValue = (value) => {
    if (!supportedHexColor.test(value)) return "";
    const digits = value.slice(1);
    if (digits.length === 4) return digits[3] + digits[3];
    if (digits.length === 8) return digits.slice(6);
    return "";
  };

  document.querySelectorAll("[data-color-field]").forEach((field) => {
    const textInput = field.querySelector("[data-color-text]");
    const picker = field.querySelector("[data-color-picker]");
    if (!textInput || !picker) return;
    textInput.addEventListener("input", () => {
      const nextPickerValue = pickerValue(textInput.value.trim());
      if (nextPickerValue) picker.value = nextPickerValue;
    });
    picker.addEventListener("input", () => {
      textInput.value = `${picker.value}${alphaValue(textInput.value.trim())}`;
      textInput.dispatchEvent(new Event("input", { bubbles: true }));
    });
  });

  document.querySelectorAll("[data-reorder-form]").forEach((form) => {
    const list = form.querySelector("[data-reorder-list]");
    const value = form.querySelector("[data-reorder-value]");
    if (!list || !value) return;
    const sync = () => {
      value.value = JSON.stringify(Array.from(list.querySelectorAll("[data-reorder-id]")).map((item) => item.dataset.reorderId));
    };
    list.addEventListener("click", (event) => {
      const item = event.target.closest("[data-reorder-id]");
      if (!item) return;
      const next = item.nextElementSibling;
      if (next) next.after(item);
      else list.prepend(item);
      sync();
    });
    form.addEventListener("submit", sync);
    sync();
  });

  function syncModuleFields(form) {
    const select = form.querySelector("[data-module-type-select]");
    if (!select) return;
    form.querySelectorAll("[data-module-fields]").forEach((group) => {
      const visible = group.dataset.moduleFields === select.value;
      group.hidden = !visible;
      group.querySelectorAll("input, select, textarea, button").forEach((field) => { field.disabled = !visible; });
    });
  }

  document.querySelectorAll("[data-module-editor]").forEach((form) => {
    const select = form.querySelector("[data-module-type-select]");
    select?.addEventListener("change", () => syncModuleFields(form));
    syncModuleFields(form);
  });

  const editorRoot = document.querySelector("[data-overlay-editor]");
  const editorData = document.querySelector("[data-overlay-editor-state]");
  const renderer = window.LumiOverlayRenderer;
  let editorApi = null;

  if (editorRoot && editorData && renderer) {
    const state = JSON.parse(editorData.textContent || "{}");
    const savedModules = new Map(state.scenes.flatMap((scene) => scene.modules).map((module) => [module.id, JSON.parse(JSON.stringify(module))]));
    const canvas = editorRoot.querySelector("[data-overlay-canvas]");
    const layer = editorRoot.querySelector("[data-overlay-canvas-layer]");
    const sceneSelect = editorRoot.querySelector("[data-editor-scene]");
    const snapToggle = editorRoot.querySelector("[data-editor-snap]");
    const snapHint = editorRoot.querySelector("[data-snap-hint]");
    const nameReadout = editorRoot.querySelector("[data-selected-name]");
    const positionReadout = editorRoot.querySelector("[data-selected-position]");
    const saveState = editorRoot.querySelector("[data-editor-save-state]");
    const sourceList = editorRoot.querySelector("[data-canvas-source-list]");
    const guideX = editorRoot.querySelector("[data-guide-x]");
    const guideY = editorRoot.querySelector("[data-guide-y]");
    const workspace = editorRoot.closest(".overlay-workspace");
    const previewStage = editorRoot.querySelector("[data-preview-stage]");
    const previewFrame = editorRoot.querySelector("[data-preview-frame]");
    const drawerToggle = document.querySelector("[data-preview-drawer-toggle]");
    const drawerClose = editorRoot.querySelector("[data-preview-drawer-close]");
    const popoutButton = editorRoot.querySelector("[data-preview-popout]");
    const widePreview = window.matchMedia("(min-width: 1180px)");
    const anchorFactors = {
      "top-left": [0, 0], "top-center": [0.5, 0], "top-right": [1, 0],
      "center-left": [0, 0.5], center: [0.5, 0.5], "center-right": [1, 0.5],
      "bottom-left": [0, 1], "bottom-center": [0.5, 1], "bottom-right": [1, 1]
    };
    let selectedId = null;
    let drag = null;
    let elements = new Map();
    const previewRequests = new Map();
    let previewChannel = null;

    const currentScene = () => state.scenes.find((scene) => scene.id === sceneSelect.value) || state.scenes[0];
    const selectedModule = () => currentScene()?.modules.find((module) => module.id === selectedId) || null;
    const round = (number) => Math.round(number * 100) / 100;
    const clamp = (number, min, max) => Math.min(max, Math.max(min, number));

    function previewState() {
      return {
        overlayId: state.overlayId,
        canvas: state.canvas,
        activeSceneId: state.activeSceneId,
        previewSceneId: sceneSelect.value,
        scenes: state.scenes
      };
    }

    function broadcastPreview() {
      previewChannel?.postMessage({ type: "state", state: previewState() });
    }

    function sizeWorkspace() {
      if (!widePreview.matches) {
        workspace?.style.removeProperty("--overlay-workspace-height");
        return;
      }
      const styles = getComputedStyle(editorRoot);
      const stickyTop = Number.parseFloat(styles.top) || 0;
      const currentTop = Math.max(stickyTop, workspace?.getBoundingClientRect().top || editorRoot.getBoundingClientRect().top);
      const bottomSpace = Math.max(8, stickyTop);
      workspace?.style.setProperty("--overlay-workspace-height", `${Math.max(180, Math.floor(window.innerHeight - currentTop - bottomSpace))}px`);
    }

    function fitPreview() {
      if (!previewStage || !previewFrame) return;
      sizeWorkspace();
      const sourceWidth = Math.max(1, Number(state.canvas?.width) || 1920);
      const sourceHeight = Math.max(1, Number(state.canvas?.height) || 1080);
      const availableWidth = Math.max(1, previewStage.clientWidth);
      const panelMaxHeight = Number.parseFloat(getComputedStyle(editorRoot).maxHeight) || window.innerHeight;
      const nonCanvasHeight = Math.max(0, editorRoot.scrollHeight - previewStage.offsetHeight);
      const availableHeight = Math.max(72, panelMaxHeight - nonCanvasHeight);
      const scale = Math.min(availableWidth / sourceWidth, availableHeight / sourceHeight);
      const frameWidth = Math.max(1, sourceWidth * scale);
      const frameHeight = Math.max(1, sourceHeight * scale);
      previewFrame.style.width = `${frameWidth}px`;
      previewFrame.style.height = `${frameHeight}px`;
      previewStage.style.height = `${frameHeight}px`;
      previewFrame.style.setProperty("--overlay-aspect", `${sourceWidth} / ${sourceHeight}`);
    }

    function scaleRenderedCanvas() {
      fitPreview();
      const stageElement = layer.querySelector(":scope > .lumi-overlay-stage");
      if (!stageElement) return;
      const layout = renderer.stageLayout(layer, state.canvas);
      stageElement.style.width = `${layout.width}px`;
      stageElement.style.height = `${layout.height}px`;
      stageElement.style.transform = `scale(${layout.scaleX}, ${layout.scaleY})`;
      const editorScale = Math.max(0.01, Math.min(layout.scaleX, layout.scaleY));
      const handleSize = window.matchMedia("(max-width: 700px)").matches ? 14 : 10;
      stageElement.style.setProperty("--lumi-editor-handle-size", `${handleSize / editorScale}px`);
      stageElement.style.setProperty("--lumi-editor-outline-size", `${2 / editorScale}px`);
      stageElement.style.setProperty("--lumi-editor-label-font-size", `${11.2 / editorScale}px`);
      stageElement.style.setProperty("--lumi-editor-label-max-width", `${192 / editorScale}px`);
      stageElement.style.setProperty("--lumi-editor-label-padding-y", `${3.2 / editorScale}px`);
      stageElement.style.setProperty("--lumi-editor-label-padding-x", `${6.4 / editorScale}px`);
      stageElement.style.setProperty("--lumi-editor-label-radius", `${4 / editorScale}px`);
    }

    function setDrawerOpen(open, { restoreFocus = false } = {}) {
      if (widePreview.matches) {
        editorRoot.classList.remove("is-open");
        editorRoot.inert = false;
        editorRoot.removeAttribute("aria-hidden");
        drawerToggle?.setAttribute("aria-expanded", "true");
        return;
      }
      editorRoot.classList.toggle("is-open", open);
      editorRoot.inert = !open;
      editorRoot.setAttribute("aria-hidden", open ? "false" : "true");
      drawerToggle?.setAttribute("aria-expanded", open ? "true" : "false");
      if (open) requestAnimationFrame(() => {
        renderCanvas();
        sceneSelect.focus({ preventScroll: true });
      });
      if (!open && restoreFocus) drawerToggle?.focus({ preventScroll: true });
    }

    drawerToggle?.addEventListener("click", () => setDrawerOpen(!editorRoot.classList.contains("is-open")), { signal: lifecycleSignal });
    drawerClose?.addEventListener("click", () => setDrawerOpen(false, { restoreFocus: true }), { signal: lifecycleSignal });
    document.addEventListener("keydown", (event) => {
      if (event.key === "Escape" && !widePreview.matches && editorRoot.classList.contains("is-open")) setDrawerOpen(false, { restoreFocus: true });
    }, { signal: lifecycleSignal });
    widePreview.addEventListener("change", () => {
      setDrawerOpen(false);
      requestAnimationFrame(renderCanvas);
    }, { signal: lifecycleSignal });
    setDrawerOpen(false);

    if ("BroadcastChannel" in window) {
      previewChannel = new BroadcastChannel(`lumi-overlay-preview:${state.overlayId}`);
      previewChannel.addEventListener("message", (event) => {
        if (event.data?.type === "request-state") {
          broadcastPreview();
          return;
        }
        if (event.data?.type !== "transform" || !event.data.moduleId || !event.data.config) return;
        const module = moduleForId(event.data.moduleId);
        if (!module) return;
        if (event.data.sceneId && state.scenes.some((scene) => scene.id === event.data.sceneId)) sceneSelect.value = event.data.sceneId;
        Object.assign(module.config, event.data.config);
        const saved = savedModules.get(module.id);
        if (saved) Object.assign(saved.config, event.data.config);
        selectedId = module.id;
        syncForm(module);
        renderCanvas();
        saveState.textContent = "Saved from pop-out";
        setTimeout(() => { if (saveState.textContent === "Saved from pop-out") saveState.textContent = "Ready"; }, 1600);
      });
    }

    popoutButton?.addEventListener("click", () => {
      const url = editorRoot.dataset.previewPopoutUrl;
      if (!url) return;
      const popup = window.open(url, `lumi-overlay-preview-${state.overlayId}`, "popup=yes,width=960,height=600,resizable=yes,scrollbars=no");
      if (!popup) {
        const original = popoutButton.textContent;
        popoutButton.textContent = "Allow pop-ups to preview";
        setTimeout(() => { popoutButton.textContent = original; }, 2400);
        return;
      }
      setTimeout(broadcastPreview, 250);
    }, { signal: lifecycleSignal });

    function edges(config) {
      const [ax, ay] = anchorFactors[config.anchor] || anchorFactors["top-left"];
      const width = Number(config.width || 0);
      const height = Number(config.height || 0);
      const left = Number(config.x || 0) - ax * width;
      const top = Number(config.y || 0) - ay * height;
      return { left, top, right: left + width, bottom: top + height, width, height, ax, ay };
    }

    function configFromEdges(box, anchor) {
      const [ax, ay] = anchorFactors[anchor] || anchorFactors["top-left"];
      const width = clamp(box.right - box.left, 0.5, 100);
      const height = clamp(box.bottom - box.top, 0.5, 100);
      return {
        x: clamp(box.left + ax * width, 0, 100),
        y: clamp(box.top + ay * height, 0, 100),
        width,
        height
      };
    }

    function updateReadout() {
      const module = selectedModule();
      if (!module) {
        nameReadout.textContent = "No source selected";
        positionReadout.textContent = "";
        return;
      }
      const config = module.config;
      nameReadout.textContent = module.name;
      positionReadout.textContent = `X ${round(config.x)}% · Y ${round(config.y)}% · ${round(config.width)} × ${round(config.height)}%`;
    }

    function syncForm(module) {
      const form = document.querySelector(`[data-module-editor][data-module-id="${CSS.escape(module.id)}"]`);
      if (!form) return;
      for (const [name, key] of [["x", "x"], ["y", "y"], ["width", "width"], ["height", "height"], ["anchor", "anchor"]]) {
        const field = form.elements[name];
        if (field) field.value = module.config[key];
      }
    }

    function formBody(form) {
      const body = {};
      for (const [key, value] of new FormData(form).entries()) body[key] = value;
      return body;
    }

    function setPreviewStatus(form, message, stateName = "") {
      const status = form.querySelector("[data-source-preview-status]");
      if (status) status.textContent = message;
      form.closest("[data-module-card]")?.classList.toggle("is-dirty", stateName === "dirty");
      if (stateName === "dirty") saveState.textContent = "Unsaved preview";
    }

    function moduleForId(moduleId) {
      return state.scenes.flatMap((scene) => scene.modules).find((module) => module.id === moduleId) || null;
    }

    function previewForm(form) {
      const moduleId = form.dataset.moduleId;
      const module = moduleForId(moduleId);
      if (!module) return;
      clearTimeout(previewRequests.get(moduleId)?.timer);
      previewRequests.get(moduleId)?.controller?.abort();
      setPreviewStatus(form, "Previewing unsaved changes…", "dirty");
      const controller = new AbortController();
      const timer = setTimeout(async () => {
        try {
          const payload = await jsonRequest(`/api/admin/overlays/${state.overlayId}/modules/${moduleId}/preview`, {
            method: "POST",
            body: JSON.stringify(formBody(form)),
            signal: controller.signal
          });
          Object.assign(module, payload.module);
          selectedId = moduleId;
          renderCanvas();
          setPreviewStatus(form, "Live preview · not saved", "dirty");
        } catch (error) {
          if (error.name !== "AbortError") setPreviewStatus(form, `Preview problem: ${error.message}`, "dirty");
        }
      }, 280);
      previewRequests.set(moduleId, { controller, timer });
    }

    document.querySelectorAll("[data-module-editor][data-module-id]").forEach((form) => {
      const update = () => previewForm(form);
      form.addEventListener("input", update);
      form.addEventListener("change", update);
      form.addEventListener("submit", () => {
        setPreviewStatus(form, "Saving…");
        saveState.textContent = "Saving…";
      });
      form.addEventListener("lumi:form-saved", (event) => {
        const canonical = event.detail?.data?.result;
        const module = moduleForId(form.dataset.moduleId);
        if (!canonical || !module) return;
        Object.assign(module, canonical);
        savedModules.set(module.id, JSON.parse(JSON.stringify(module)));
        selectedId = module.id;
        renderCanvas();
        setPreviewStatus(form, "Saved");
        saveState.textContent = "Saved";
      });
      form.querySelector("[data-source-revert]")?.addEventListener("click", () => {
        const saved = savedModules.get(form.dataset.moduleId);
        const module = moduleForId(form.dataset.moduleId);
        if (!saved || !module) return;
        previewRequests.get(module.id)?.controller?.abort();
        clearTimeout(previewRequests.get(module.id)?.timer);
        form.reset();
        syncModuleFields(form);
        Object.assign(module, JSON.parse(JSON.stringify(saved)));
        selectedId = module.id;
        renderCanvas();
        setPreviewStatus(form, "Saved settings restored");
        saveState.textContent = "Ready";
      });
    });

    function selectSource(moduleId, { openSettings = false, focusCanvas = true } = {}) {
      selectedId = moduleId;
      layer.querySelectorAll(".lumi-overlay-module").forEach((element) => element.classList.toggle("is-selected", element.dataset.moduleId === moduleId));
      sourceList.querySelectorAll("[data-canvas-select]").forEach((button) => button.classList.toggle("is-selected", button.dataset.canvasSelect === moduleId));
      updateReadout();
      if (openSettings) {
        const card = document.querySelector(`[data-module-card="${CSS.escape(moduleId)}"]`);
        if (card) card.open = true;
      }
      if (focusCanvas) canvas.focus({ preventScroll: true });
    }

    function renderCanvas() {
      const scene = currentScene();
      fitPreview();
      elements = renderer.render(layer, { enabled: true, canvas: state.canvas, scene }, { editor: true, canvas: state.canvas });
      sourceList.replaceChildren();
      for (const module of scene?.modules || []) {
        const button = document.createElement("button");
        button.type = "button";
        button.className = "button subtle";
        button.dataset.canvasSelect = module.id;
        button.textContent = `${module.name}${module.enabled ? "" : " (hidden)"}`;
        button.disabled = !module.enabled;
        button.addEventListener("click", () => selectSource(module.id, { openSettings: true }));
        sourceList.appendChild(button);
      }
      if (!elements.has(selectedId)) selectedId = elements.keys().next().value || null;
      if (selectedId) selectSource(selectedId, { focusCanvas: false });
      else updateReadout();
      broadcastPreview();
    }

    function showGuide(axis, value) {
      const guide = axis === "x" ? guideX : guideY;
      guide.style[axis === "x" ? "left" : "top"] = `${value}%`;
      guide.classList.add("is-visible");
    }

    function clearGuides() {
      guideX.classList.remove("is-visible");
      guideY.classList.remove("is-visible");
    }

    function snapTargets(moduleId, axis) {
      const result = [0, 50, 100];
      for (const module of currentScene()?.modules || []) {
        if (module.id === moduleId || !module.enabled) continue;
        const box = edges(module.config);
        result.push(axis === "x" ? box.left : box.top, axis === "x" ? (box.left + box.right) / 2 : (box.top + box.bottom) / 2, axis === "x" ? box.right : box.bottom);
      }
      return result;
    }

    function snapAdjustment(points, targets, threshold) {
      let best = null;
      for (const point of points) for (const target of targets) {
        const difference = target - point;
        if (Math.abs(difference) <= threshold && (!best || Math.abs(difference) < Math.abs(best.difference))) best = { difference, target };
      }
      return best;
    }

    function snappingActive(event) {
      return Boolean(snapToggle.checked) !== Boolean(event.ctrlKey || event.metaKey);
    }

    function applyDrag(event) {
      if (!drag) return;
      const module = selectedModule();
      if (!module) return;
      const dx = ((event.clientX - drag.startX) / drag.rect.width) * 100;
      const dy = ((event.clientY - drag.startY) / drag.rect.height) * 100;
      const startBox = edges(drag.config);
      let box = { ...startBox };
      if (drag.handle) {
        if (drag.handle.includes("w")) box.left += dx;
        if (drag.handle.includes("e")) box.right += dx;
        if (drag.handle.includes("n")) box.top += dy;
        if (drag.handle.includes("s")) box.bottom += dy;
        if (box.right - box.left < 0.5) box.right = box.left + 0.5;
        if (box.bottom - box.top < 0.5) box.bottom = box.top + 0.5;
      } else {
        box.left += dx; box.right += dx; box.top += dy; box.bottom += dy;
      }
      clearGuides();
      if (snappingActive(event)) {
        const thresholdX = (7 / drag.rect.width) * 100;
        const thresholdY = (7 / drag.rect.height) * 100;
        const xPoints = drag.handle
          ? [drag.handle.includes("w") ? box.left : drag.handle.includes("e") ? box.right : (box.left + box.right) / 2]
          : [box.left, (box.left + box.right) / 2, box.right];
        const yPoints = drag.handle
          ? [drag.handle.includes("n") ? box.top : drag.handle.includes("s") ? box.bottom : (box.top + box.bottom) / 2]
          : [box.top, (box.top + box.bottom) / 2, box.bottom];
        const snapX = snapAdjustment(xPoints, snapTargets(module.id, "x"), thresholdX);
        const snapY = snapAdjustment(yPoints, snapTargets(module.id, "y"), thresholdY);
        if (snapX) {
          if (drag.handle?.includes("w")) box.left += snapX.difference;
          else if (drag.handle?.includes("e")) box.right += snapX.difference;
          else { box.left += snapX.difference; box.right += snapX.difference; }
          showGuide("x", snapX.target);
        }
        if (snapY) {
          if (drag.handle?.includes("n")) box.top += snapY.difference;
          else if (drag.handle?.includes("s")) box.bottom += snapY.difference;
          else { box.top += snapY.difference; box.bottom += snapY.difference; }
          showGuide("y", snapY.target);
        }
      }
      Object.assign(module.config, configFromEdges(box, module.config.anchor || "top-left"));
      renderer.applyBox(elements.get(module.id), module.config);
      syncForm(module);
      updateReadout();
    }

    async function saveTransform(module) {
      if (!module) return;
      saveState.textContent = "Saving…";
      try {
        const payload = await jsonRequest(`/api/admin/overlays/${state.overlayId}/modules/${module.id}/transform`, {
          method: "POST",
          body: JSON.stringify({
            x: module.config.x, y: module.config.y,
            width: module.config.width, height: module.config.height,
            anchor: module.config.anchor || "top-left"
          })
        });
        Object.assign(module.config, payload.module.config);
        syncForm(module);
        saveState.textContent = "Saved";
        setTimeout(() => { saveState.textContent = "Ready"; }, 1300);
      } catch (error) {
        saveState.textContent = "Save failed";
        saveState.title = error.message;
      }
    }

    layer.addEventListener("pointerdown", (event) => {
      const element = event.target.closest(".lumi-overlay-module");
      if (!element) return;
      event.preventDefault();
      selectSource(element.dataset.moduleId);
      const module = selectedModule();
      drag = {
        startX: event.clientX,
        startY: event.clientY,
        rect: canvas.getBoundingClientRect(),
        config: { ...module.config },
        handle: event.target.closest("[data-resize-handle]")?.dataset.resizeHandle || null
      };
    });
    window.addEventListener("pointermove", applyDrag, { signal: lifecycleSignal });
    window.addEventListener("pointerup", () => {
      if (!drag) return;
      drag = null;
      clearGuides();
      saveTransform(selectedModule());
    }, { signal: lifecycleSignal });

    canvas.addEventListener("keydown", (event) => {
      if (!selectedModule() || !["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown"].includes(event.key)) return;
      event.preventDefault();
      const amount = event.shiftKey ? 1 : 0.1;
      const module = selectedModule();
      if (event.key === "ArrowLeft") module.config.x = clamp(Number(module.config.x) - amount, 0, 100);
      if (event.key === "ArrowRight") module.config.x = clamp(Number(module.config.x) + amount, 0, 100);
      if (event.key === "ArrowUp") module.config.y = clamp(Number(module.config.y) - amount, 0, 100);
      if (event.key === "ArrowDown") module.config.y = clamp(Number(module.config.y) + amount, 0, 100);
      renderer.applyBox(elements.get(module.id), module.config);
      syncForm(module);
      updateReadout();
      clearTimeout(canvas._saveTimer);
      canvas._saveTimer = setTimeout(() => saveTransform(module), 300);
    });

    function transformSelected(changes) {
      const module = selectedModule();
      if (!module) return;
      Object.assign(module.config, changes);
      renderer.applyBox(elements.get(module.id), module.config);
      syncForm(module);
      updateReadout();
      saveTransform(module);
    }

    editorRoot.querySelector("[data-editor-center]")?.addEventListener("click", () => transformSelected({ x: 50, y: 50, anchor: "center" }));
    editorRoot.querySelector("[data-editor-fit]")?.addEventListener("click", () => transformSelected({ x: 0, y: 0, width: 100, height: 100, anchor: "top-left" }));
    editorRoot.querySelector("[data-editor-reset]")?.addEventListener("click", () => transformSelected({ x: 0, y: 0, width: 50, height: 25, anchor: "top-left" }));
    editorRoot.querySelectorAll("[data-preview-background]").forEach((button) => button.addEventListener("click", () => {
      const background = button.dataset.previewBackground;
      previewFrame?.classList.toggle("preview-bg-dark", background === "dark");
      previewFrame?.classList.toggle("preview-bg-light", background === "light");
      button.parentElement?.querySelectorAll("[data-preview-background]").forEach((item) => item.setAttribute("aria-pressed", item === button ? "true" : "false"));
    }));
    editorRoot.querySelector("[data-preview-grid]")?.addEventListener("click", (event) => {
      const active = !previewFrame?.classList.contains("show-grid");
      previewFrame?.classList.toggle("show-grid", active);
      event.currentTarget.setAttribute("aria-pressed", active ? "true" : "false");
    });
    snapToggle.addEventListener("change", () => { snapHint.textContent = snapToggle.checked ? "off" : "on"; });
    sceneSelect.addEventListener("change", () => { selectedId = null; renderCanvas(); });
    let previewLayoutFrame = null;
    const schedulePreviewLayout = () => {
      if (previewLayoutFrame) return;
      previewLayoutFrame = requestAnimationFrame(() => {
        previewLayoutFrame = null;
        scaleRenderedCanvas();
      });
    };
    window.addEventListener("resize", schedulePreviewLayout, { signal: lifecycleSignal });
    window.addEventListener("scroll", schedulePreviewLayout, { signal: lifecycleSignal, passive: true });
    editorRoot.querySelector(".overlay-preview-details")?.addEventListener("toggle", schedulePreviewLayout, { signal: lifecycleSignal });

    document.querySelectorAll("[data-edit-scene]").forEach((button) => button.addEventListener("click", () => {
      sceneSelect.value = button.dataset.editScene;
      selectedId = null;
      renderCanvas();
    }));
    document.querySelectorAll("[data-select-source]").forEach((button) => button.addEventListener("click", () => {
      const scene = state.scenes.find((item) => item.modules.some((module) => module.id === button.dataset.selectSource));
      if (scene) sceneSelect.value = scene.id;
      selectedId = button.dataset.selectSource;
      renderCanvas();
    }));

    editorApi = {
      reconcile(nextState) {
        if (!nextState?.scenes) return;
        const selectedScene = sceneSelect.value;
        state.canvas = nextState.canvas || state.canvas;
        state.activeSceneId = nextState.activeSceneId || state.activeSceneId;
        state.scenes = nextState.scenes;
        sceneSelect.replaceChildren(...state.scenes.map((scene) => {
          const option = document.createElement("option");
          option.value = scene.id;
          option.textContent = scene.name;
          return option;
        }));
        sceneSelect.value = state.scenes.some((scene) => scene.id === selectedScene) ? selectedScene : state.activeSceneId || state.scenes[0]?.id || "";
        const frame = editorRoot.querySelector("[data-preview-frame]");
        if (frame && state.canvas?.width && state.canvas?.height) frame.style.setProperty("--overlay-aspect", `${state.canvas.width} / ${state.canvas.height}`);
        renderCanvas();
      },
      reload(moduleId) {
        const frame = renderer.findSourceContent(layer, moduleId, ".lumi-overlay-frame");
        if (frame) {
          const replacement = frame.cloneNode(false);
          replacement.src = frame.dataset.originalUrl || frame.src;
          frame.replaceWith(replacement);
          return;
        }
        renderer.restartMediaElement(renderer.findSourceContent(layer, moduleId, "video, audio"));
      }
    };
    editorCleanup = () => {
      if (previewLayoutFrame) cancelAnimationFrame(previewLayoutFrame);
      previewChannel?.close();
    };
    renderCanvas();
  }

  document.querySelectorAll("[data-refresh-source]").forEach((button) => button.addEventListener("click", async () => {
    const original = button.textContent;
    button.disabled = true;
    button.textContent = "Refreshing…";
    try {
      editorApi?.reload(button.dataset.refreshSource);
      const overlayId = document.querySelector("[data-overlay-editor-state]")
        ? JSON.parse(document.querySelector("[data-overlay-editor-state]").textContent || "{}").overlayId
        : null;
      await jsonRequest(`/api/admin/overlays/${overlayId}/modules/${button.dataset.refreshSource}/refresh`, { method: "POST", body: "{}" });
      button.textContent = "Refreshed";
    } catch (error) {
      button.textContent = "Refresh failed";
      button.title = error.message;
    } finally {
      setTimeout(() => { button.disabled = false; button.textContent = original; }, 1600);
    }
  }));

  document.querySelectorAll("[data-check-source]").forEach((button) => button.addEventListener("click", async () => {
    const output = document.querySelector(`[data-source-health="${CSS.escape(button.dataset.checkSource)}"]`);
    const stateData = document.querySelector("[data-overlay-editor-state]");
    const overlayId = stateData ? JSON.parse(stateData.textContent || "{}").overlayId : null;
    button.disabled = true;
    if (output) output.textContent = "Checking the website…";
    try {
      const result = await jsonRequest(`/api/admin/overlays/${overlayId}/modules/${button.dataset.checkSource}/health`);
      if (output) output.textContent = result.skipped ? result.reason : result.healthy ? `Website replied normally${result.status ? ` (HTTP ${result.status})` : ""}.` : result.reason;
    } catch (error) {
      if (output) output.textContent = error.message;
    } finally {
      button.disabled = false;
    }
  }));

  document.querySelectorAll("[data-event-hook-form]").forEach((form) => {
    const eventType = form.querySelector("[data-event-type]");
    const action = form.querySelector("[data-event-action]");
    const source = form.querySelector("[data-event-source]");
    const duration = form.querySelector("[data-event-duration]");
    const tier = form.querySelector("[data-event-tier]");
    const sourceHelp = form.querySelector("[data-event-source-help]");
    const submit = form.querySelector('button[type="submit"]');
    const sync = () => {
      const selectedAction = action?.selectedOptions?.[0];
      const accepted = new Set(String(selectedAction?.dataset.renderTypes || "").split(",").filter(Boolean));
      let available = 0;
      source?.querySelectorAll("option").forEach((option) => {
        const compatible = accepted.has(option.dataset.renderType);
        option.hidden = !compatible;
        option.disabled = !compatible;
        if (compatible) available += 1;
      });
      if (source?.selectedOptions?.[0]?.disabled) source.value = source.querySelector("option:not(:disabled)")?.value || "";
      if (duration) duration.hidden = action?.value !== "show_temporary";
      const supportsTier = eventType?.selectedOptions?.[0]?.dataset.supportsTier === "true";
      if (tier) tier.hidden = !supportsTier;
      if (submit) submit.disabled = available === 0;
      if (sourceHelp) sourceHelp.textContent = available ? "" : `Add an ${Array.from(accepted).join(" or ")} source before creating this alert.`;
    };
    eventType?.addEventListener("change", sync);
    action?.addEventListener("change", sync);
    sync();
  });

  const connector = document.querySelector("[data-obs-connector]");
  if (!connector) return editorCleanup;
  const overlayId = connector.dataset.overlayId;
  const settingsForm = connector.querySelector("[data-obs-settings-form]");
  const sceneForm = connector.querySelector("[data-obs-scene-form]");
  const statusState = connector.querySelector("[data-obs-state]");
  const current = connector.querySelector("[data-obs-current]");
  const error = connector.querySelector("[data-obs-error]");
  const sceneSelect = connector.querySelector("[data-obs-scenes]");
  const providerSelect = connector.querySelector("[data-obs-provider]");
  const permission = connector.querySelector("[data-obs-permission]");
  const transition = connector.querySelector("[data-obs-transition]");
  const canvasSize = connector.querySelector("[data-obs-canvas]");
  const profile = connector.querySelector("[data-obs-profile]");
  const collection = connector.querySelector("[data-obs-collection]");
  const sourceStatus = connector.querySelector("[data-obs-source]");
  const outputs = connector.querySelector("[data-obs-outputs]");
  const importResult = connector.querySelector("[data-obs-import-result]");

  function syncProviderFields() {
    const browserBridge = providerSelect?.value === "obs_browser_bridge";
    connector.querySelectorAll("[data-obs-websocket-field]").forEach((field) => {
      field.hidden = browserBridge;
      field.querySelectorAll("input, select").forEach((input) => { input.disabled = browserBridge; });
    });
    const help = connector.querySelector("[data-obs-browser-help]");
    if (help) help.hidden = !browserBridge;
  }

  function renderStatus(payload) {
    if (statusState) statusState.textContent = payload.state || (payload.ok ? "connected" : "error");
    if (current) current.textContent = payload.current_scene || "Unknown";
    if (error) error.textContent = payload.error || "None";
    if (permission) permission.textContent = payload.control_level_label || "Not reported";
    if (transition) transition.textContent = payload.current_transition || "Unknown";
    if (canvasSize) canvasSize.textContent = payload.canvas_width && payload.canvas_height ? `${payload.canvas_width} × ${payload.canvas_height}` : "Unknown";
    if (profile) profile.textContent = payload.profiles_supported === false ? "Not exposed by Browser Bridge" : (payload.current_profile || "Unknown");
    if (collection) collection.textContent = payload.scene_collections_supported === false ? "Not exposed by Browser Bridge" : (payload.current_scene_collection || "Unknown");
    if (sourceStatus) sourceStatus.textContent = payload.source_active === true ? "Active" : payload.source_visible === true ? "Visible" : payload.source_active === false ? "Inactive" : "Unknown";
    if (outputs) {
      const activeOutputs = [];
      if (payload.outputs?.streaming) activeOutputs.push("Streaming");
      if (payload.outputs?.recording) activeOutputs.push(payload.outputs.recording_paused ? "Recording paused" : "Recording");
      if (payload.outputs?.replay_buffer) activeOutputs.push("Replay buffer");
      if (payload.outputs?.virtual_camera) activeOutputs.push("Virtual camera");
      outputs.textContent = activeOutputs.join(", ") || "Idle or unavailable";
    }
    if (sceneSelect && Array.isArray(payload.scenes)) {
      const selected = sceneSelect.value;
      sceneSelect.replaceChildren(new Option("Choose an OBS scene", ""));
      payload.scenes.forEach((name) => sceneSelect.add(new Option(name, name)));
      if (payload.scenes.includes(selected)) sceneSelect.value = selected;
    }
  }

  providerSelect?.addEventListener("change", syncProviderFields);
  syncProviderFields();

  const refreshObsStatus = async () => {
    try { renderStatus(await jsonRequest(`/api/admin/overlays/${overlayId}/obs/status`)); }
    catch (requestError) { renderStatus({ state: "error", error: requestError.message }); }
  };
  connector.querySelector("[data-obs-refresh]")?.addEventListener("click", refreshObsStatus);
  settingsForm?.addEventListener("lumi:form-saved", (event) => {
    if (event.detail?.data?.status) renderStatus(event.detail.data.status);
  });
  obsStatusTimer = window.setInterval(refreshObsStatus, 5000);
  connector.querySelector("[data-obs-test]")?.addEventListener("click", async () => {
    const data = new FormData(settingsForm);
    renderStatus({ state: "testing", error: null });
    try {
      renderStatus(await jsonRequest(`/api/admin/overlays/${overlayId}/obs/test`, { method: "POST", body: JSON.stringify({ provider: data.get("provider"), endpoint: data.get("endpoint"), password: data.get("password") }) }));
    } catch (requestError) { renderStatus({ state: "error", error: requestError.message }); }
  });
  connector.querySelector("[data-obs-import]")?.addEventListener("click", async (event) => {
    const button = event.currentTarget;
    button.disabled = true;
    if (importResult) importResult.textContent = "Applying the detected OBS setup…";
    try {
      const result = await jsonRequest(`/api/admin/overlays/${overlayId}/obs/import`, { method: "POST", body: "{}" });
      editorApi?.reconcile(result.editor);
      renderStatus(result.status || await jsonRequest(`/api/admin/overlays/${overlayId}/obs/status`));
      if (importResult) importResult.textContent = `${result.message}${result.canvas_updated ? " Canvas size and preview updated." : " Preview updated."}`;
      button.disabled = false;
    } catch (requestError) {
      if (importResult) importResult.textContent = requestError.message;
      button.disabled = false;
    }
  });
  sceneForm?.addEventListener("submit", async (event) => {
    event.preventDefault();
    const sceneName = new FormData(sceneForm).get("scene_name");
    if (!sceneName) return;
    try { renderStatus(await jsonRequest(`/api/admin/overlays/${overlayId}/obs/scene`, { method: "POST", body: JSON.stringify({ scene_name: sceneName }) })); }
    catch (requestError) { renderStatus({ state: "error", error: requestError.message }); }
  });
  return () => {
    if (obsStatusTimer) window.clearInterval(obsStatusTimer);
    editorCleanup();
  };
  }

  if (window.LumiPage) {
    window.LumiPage.register("overlay-management", { mount: mountOverlayManagement });
  } else {
    document.addEventListener("DOMContentLoaded", () => mountOverlayManagement(document), { once: true });
  }
})();
