/* eslint-disable @typescript-eslint/ban-ts-comment, @typescript-eslint/no-unused-vars, no-empty, no-useless-escape */
// @ts-nocheck
import {
  buildSpritePreviewDataUrl,
  fetchJsonOrThrow,
} from "../editorCore";
import {
  buildSpritesPayloadFromImagesPayload,
  buildTilesPayloadFromImagesPayload,
  mergeImagesPayloadWithSpritesPayload,
  mergeImagesPayloadWithTilesPayload,
  normalizeImageRecordForSave,
  normalizeTileRecordForSave,
} from "../contentTransforms/graphicsPayload";
import {
  buildSpriteCatalog,
  buildTileCatalogById,
  DEFAULT_MAP_BACKGROUND_COLOR,
  DEFAULT_TILE_COLOR,
} from "../components/worldshaperShared";
import type { WorldshaperStudioBootstrap } from "./bootstrap";
import {
  cacheStandaloneWorldshaperBootstrap,
  clearWorldshaperStudioBootstrap,
  createWorldshaperStudioToken,
  loadStandaloneWorldshaperBootstrap,
  registerWorldshaperStudioBootstrap,
} from "./bootstrap";
import { buildChunkKey, worldToChunkCoord, worldToLocalCoord } from "../worldChunking";
import {
  getCenteredWorldshaperStudioBounds,
  WORLDSHAPER_STUDIO_BOUNDS_STORAGE_KEY,
  openWorldshaperHeightViewerWindow,
  persistWorldshaperStudioBounds,
} from "./windowing";
import { createHistoryController } from "./historyController";
import { createHistoryStateStore } from "./historyStateStore";
import { createInteractionController } from "./interactionController";
import { createImportController } from "./importController";
import { createMapDocumentController } from "./mapDocumentController";
import { createMapDocumentStore } from "./mapDocumentStore";
import { createNpcController } from "./npcController";
import {
  createPanelFolderLayoutFolder,
  deletePanelFolderLayoutFolder,
  movePanelFolderLayoutNode,
  renamePanelFolderLayoutFolder,
  togglePanelFolderLayoutFolder,
} from "./panelFolders";
import { createEditorUiStore } from "./editorUiStore";
import { createChangelogSplashWindowController } from "./changelogSplashWindowController";
import { createEntityEditorWindowController } from "./entityEditorWindowController";
import { createEngineOverrideWindowController } from "./engineOverrideWindowController";
import {
  getEngineOverrideValue,
  normalizeEngineOverrideEntries,
} from "./engineOverrides";
import { createPersistenceController } from "./persistenceController";
import { createPopupSessionStore } from "./popupSessionStore";
import { createRenderController } from "./renderController";
import { createSidebarController } from "./sidebarController";
import { createStatusLogWindowController } from "./statusLogWindowController";
import { createTileArtEditorWindowController } from "./tileArtEditorWindowController";
import { createToolWindowController } from "./toolWindowController";
import { createWorldOverviewWindowController } from "./worldOverviewWindowController";
import { createDebouncedCallback } from "./debounce";
import {
  buildImageRecordFromSpriteRecord,
  buildImageRecordFromTileRecord,
  buildTileRecordFromImageRecord,
  getImageRecordFromPayload,
  normalizeGraphicRoles,
  normalizeImagesPayloadSnapshot,
} from "./graphicsDocumentHelpers";
import {
  DEFAULT_WORLDSHAPER_THEME_PRESET,
  applyWorldshaperThemePreset,
  getWorldshaperThemeLabel,
  getDefaultEditorSettings,
  normalizeEditorSettings,
  normalizeWorldshaperThemePreset,
  persistEditorSettings,
} from "./themePresets";
import { createAtTooltip } from "./tooltip";

function cloneValue(value) {
  if (typeof structuredClone === "function") {
    return structuredClone(value);
  }
  return value == null ? value : JSON.parse(JSON.stringify(value));
}

function createFilledRows(width, height, fillChar) {
  return Array.from({ length: Math.max(1, Number(height) || 1) }, () => String(fillChar || " ").repeat(Math.max(1, Number(width) || 1)));
}

function writeRowSegment(rows, y, x, segment) {
  if (!Array.isArray(rows) || !segment) {
    return;
  }
  const targetY = Math.floor(Number(y) || 0);
  if (targetY < 0 || targetY >= rows.length) {
    return;
  }
  const safeX = Math.max(0, Math.floor(Number(x) || 0));
  const sourceRow = String(rows[targetY] || "");
  const paddedRow = sourceRow.length >= safeX
    ? sourceRow
    : (sourceRow + " ".repeat(Math.max(0, safeX - sourceRow.length)));
  const before = paddedRow.slice(0, safeX);
  const afterStart = safeX + segment.length;
  const after = afterStart < paddedRow.length ? paddedRow.slice(afterStart) : "";
  rows[targetY] = before + segment + after;
}

function composeWorldRoomLayers(chunks, chunkWidth, chunkHeight, originChunkX, originChunkY, worldWidth, worldHeight) {
  const layerMap = new Map();
  (Array.isArray(chunks) ? chunks : []).forEach((chunk) => {
    const baseChunkX = Math.floor(Number(chunk?.chunkX) || 0);
    const baseChunkY = Math.floor(Number(chunk?.chunkY) || 0);
    const offsetX = (baseChunkX - originChunkX) * chunkWidth;
    const offsetY = (baseChunkY - originChunkY) * chunkHeight;
    const rawLayers = Array.isArray(chunk?.roomLayers) ? chunk.roomLayers : [];
    rawLayers.forEach((rawLayer) => {
      const layerNumber = Number(rawLayer?.layer) || 0;
      const fillChar = layerNumber === 0 ? "." : " ";
      if (!layerMap.has(layerNumber)) {
        layerMap.set(layerNumber, {
          layer: layerNumber,
          name: typeof rawLayer?.name === "string" && String(rawLayer.name).trim() ? String(rawLayer.name).trim() : undefined,
          rows: createFilledRows(worldWidth, worldHeight, fillChar),
          instanceIds: [],
        });
      }
      const targetLayer = layerMap.get(layerNumber);
      const sourceRows = Array.isArray(rawLayer?.rows) ? rawLayer.rows.map((row) => String(row || "")) : [];
      sourceRows.forEach((row, localY) => {
        const targetY = offsetY + localY;
        if (targetY < 0 || targetY >= targetLayer.rows.length) {
          return;
        }
        const maxWidth = Math.max(0, worldWidth - offsetX);
        writeRowSegment(targetLayer.rows, targetY, offsetX, row.slice(0, maxWidth));
      });
      const sourceInstanceIds = Array.isArray(rawLayer?.instanceIds)
        ? rawLayer.instanceIds.map((entry) => String(entry || "").trim()).filter(Boolean)
        : [];
      targetLayer.instanceIds = Array.from(new Set([...(targetLayer.instanceIds || []), ...sourceInstanceIds]));
    });
  });
  if (!layerMap.has(0)) {
    layerMap.set(0, {
      layer: 0,
      rows: createFilledRows(worldWidth, worldHeight, "."),
      instanceIds: [],
    });
  }
  return Array.from(layerMap.values()).sort((a, b) => (Number(a.layer) || 0) - (Number(b.layer) || 0));
}

function composeWorldHeightLayers(chunks, chunkWidth, chunkHeight, originChunkX, originChunkY) {
  const patches = [];
  (Array.isArray(chunks) ? chunks : []).forEach((chunk) => {
    const baseChunkX = Math.floor(Number(chunk?.chunkX) || 0);
    const baseChunkY = Math.floor(Number(chunk?.chunkY) || 0);
    const offsetX = (baseChunkX - originChunkX) * chunkWidth;
    const offsetY = (baseChunkY - originChunkY) * chunkHeight;
    const rawHeightLayers = Array.isArray(chunk?.heightLayers) ? chunk.heightLayers : [];
    rawHeightLayers.forEach((entry, index) => {
      const fallbackId = `height_${baseChunkX}_${baseChunkY}_${index + 1}`;
      patches.push({
        id: String(entry?.id || fallbackId).trim() || fallbackId,
        name: typeof entry?.name === "string" && String(entry.name).trim() ? String(entry.name).trim() : undefined,
        z: Math.max(1, Math.floor(Number(entry?.z) || 1)),
        x: offsetX + Math.max(0, Number(entry?.x) || 0),
        y: offsetY + Math.max(0, Number(entry?.y) || 0),
        rows: Array.isArray(entry?.rows) ? entry.rows.map((row) => String(row || "")) : [],
      });
    });
  });
  return patches.sort((a, b) => {
    if (a.z !== b.z) {
      return a.z - b.z;
    }
    return String(a.name || a.id).localeCompare(String(b.name || b.id));
  });
}

function buildWorldLayerMetadata(chunks) {
  const layerMap = new Map();
  (Array.isArray(chunks) ? chunks : []).forEach((chunk) => {
    const rawLayers = Array.isArray(chunk?.roomLayers) ? chunk.roomLayers : [];
    rawLayers.forEach((rawLayer) => {
      const layerNumber = Number(rawLayer?.layer) || 0;
      if (layerMap.has(layerNumber)) {
        return;
      }
      layerMap.set(layerNumber, {
        layer: layerNumber,
        name: typeof rawLayer?.name === "string" && String(rawLayer.name).trim() ? String(rawLayer.name).trim() : undefined,
        rows: [],
        instanceIds: Array.isArray(rawLayer?.instanceIds) ? rawLayer.instanceIds.map((entry) => String(entry || "").trim()).filter(Boolean) : [],
      });
    });
  });
  if (!layerMap.has(0)) {
    layerMap.set(0, {
      layer: 0,
      rows: [],
      instanceIds: [],
    });
  }
  if (!Array.from(layerMap.keys()).some((layerNumber) => layerNumber > 0)) {
    layerMap.set(1, {
      layer: 1,
      rows: [],
      instanceIds: [],
    });
  }
  return Array.from(layerMap.values()).sort((a, b) => (Number(a.layer) || 0) - (Number(b.layer) || 0));
}

function getContentRecords(payload, key) {
  const records = payload && Array.isArray(payload[key]) ? payload[key] : [];
  return records.filter((entry) => Boolean(entry) && typeof entry === "object" && !Array.isArray(entry));
}

function buildSpriteCatalogFromBootstrap(bootstrap) {
  const spriteRecords = getContentRecords(bootstrap?.contentByType?.sprites, "sprites");
  if (spriteRecords.length > 0) {
    return buildSpriteCatalog(spriteRecords, buildSpritePreviewDataUrl);
  }
  return cloneValue(bootstrap?.spriteCatalog) || {};
}

function buildTileCatalogByIdFromBootstrap(bootstrap) {
  const tileRecords = getContentRecords(bootstrap?.contentByType?.tiles, "tiles");
  if (tileRecords.length > 0) {
    return buildTileCatalogById(tileRecords, buildSpritePreviewDataUrl);
  }
  return cloneValue(bootstrap?.tileCatalogById) || {};
}

function buildNpcOverlaysFromWorldChunks(chunks, spriteCatalog, chunkWidth, chunkHeight, originChunkX, originChunkY) {
  return (Array.isArray(chunks) ? chunks : []).flatMap((chunk) => {
    const baseChunkX = Math.floor(Number(chunk?.chunkX) || 0);
    const baseChunkY = Math.floor(Number(chunk?.chunkY) || 0);
    const offsetX = (baseChunkX - originChunkX) * chunkWidth;
    const offsetY = (baseChunkY - originChunkY) * chunkHeight;
    const instances = Array.isArray(chunk?.instances) ? chunk.instances : [];
    return instances
      .filter((entry) => Boolean(entry) && typeof entry === "object" && !Array.isArray(entry))
      .map((entry) => {
        const record = entry.record && typeof entry.record === "object" && !Array.isArray(entry.record)
          ? cloneValue(entry.record)
          : {};
        const spriteId = String(record.spriteId || entry.spriteId || "").trim();
        const spriteEntry = spriteCatalog[spriteId] || null;
        const overlayX = offsetX + Math.max(0, Number(entry.x) || 0);
        const overlayY = offsetY + Math.max(0, Number(entry.y) || 0);
        record.position = {
          x: overlayX,
          y: overlayY,
        };
        return {
          id: String(entry.id || "").trim(),
          layer: Number(entry.layer) || 0,
          name: String(record.name || entry.id || "NPC"),
          spriteId,
          x: overlayX,
          y: overlayY,
          dataUrl: spriteEntry ? spriteEntry.dataUrl : null,
          spriteWidth: spriteEntry ? spriteEntry.spriteWidth : 28,
          spriteHeight: spriteEntry ? spriteEntry.spriteHeight : 28,
          opacity: spriteEntry ? spriteEntry.opacity : 1,
          record,
        };
      })
      .filter((entry) => entry.id);
  });
}

const MAX_WORLD_CHUNK_CACHE_ENTRIES = 256;
const MAX_DYNAMIC_WORLD_CHUNK_RADIUS = 4;
const TILE_SYMBOL_POOL = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!$%&()*+,-/:;<=>?@[]^_{|}~=";

export function startWorldshaperStudio(bootstrap: WorldshaperStudioBootstrap, initialEditorSettings: unknown = getDefaultEditorSettings()): void {
    function normalizeMapBackgroundColor(value, fallback) {
      const f = fallback || DEFAULT_MAP_BACKGROUND_COLOR;
      const raw = String(value || "").trim();
      return /^#[0-9a-fA-F]{6}$/.test(raw) ? raw.toUpperCase() : f;
    }

    const baseTileSize = Math.max(8, Number(bootstrap.tileSize) || 32);
    const minZoomLevel = 0.5;
    const maxZoomLevel = 4;
    let zoomLevel = 1;
    let tileSize = baseTileSize;
    let currentMapId = String(bootstrap.mapId || "").trim();
    let currentBaseRows = Array.isArray(bootstrap.baseRows) ? bootstrap.baseRows.map((row) => String(row ?? "")) : [];
    const worldRuntimeState = {
      enabled: !!String(bootstrap.worldId || bootstrap.mapId || "").trim(),
      worldId: String(bootstrap.worldId || bootstrap.mapId || "").trim(),
      worldName: String(bootstrap.worldName || bootstrap.mapName || bootstrap.worldId || bootstrap.mapId || "World").trim() || "World",
      defaultBackgroundTileId: String(bootstrap.backgroundTileId || "").trim(),
      heightBlurStep: Math.max(0, Math.min(1, Number(bootstrap.heightBlurStep ?? bootstrap.heightDetailStep) || 0.1)),
      chunkWidth: Math.max(1, Number(bootstrap.worldChunkWidth) || 32),
      chunkHeight: Math.max(1, Number(bootstrap.worldChunkHeight) || 32),
      chunkRadius: Math.max(0, Math.floor(Number(bootstrap.worldChunkRadius) || 0)),
      originChunkX: Math.floor(Number(bootstrap.worldOriginChunkX) || 0),
      originChunkY: Math.floor(Number(bootstrap.worldOriginChunkY) || 0),
      tileOffsetX: Math.floor(Number(bootstrap.worldTileOffsetX) || 0),
      tileOffsetY: Math.floor(Number(bootstrap.worldTileOffsetY) || 0),
      spawnX: Math.floor(Number(bootstrap.worldSpawnX) || 0),
      spawnY: Math.floor(Number(bootstrap.worldSpawnY) || 0),
      centerChunkX: Math.floor(Number(bootstrap.worldOriginChunkX) || 0) + Math.max(0, Math.floor(Number(bootstrap.worldChunkRadius) || 0)),
      centerChunkY: Math.floor(Number(bootstrap.worldOriginChunkY) || 0) + Math.max(0, Math.floor(Number(bootstrap.worldChunkRadius) || 0)),
      sourceChunks: Array.isArray(bootstrap.sourceChunks)
        ? bootstrap.sourceChunks.map((entry) => ({
          chunkX: Math.floor(Number(entry?.chunkX) || 0),
          chunkY: Math.floor(Number(entry?.chunkY) || 0),
        }))
        : [],
      bookmarks: Array.isArray(bootstrap.worldBookmarks)
        ? bootstrap.worldBookmarks.map((entry, index) => ({
          id: String(entry?.id || `poi_${index + 1}`).trim() || `poi_${index + 1}`,
          label: String(entry?.label || entry?.id || `POI ${index + 1}`).trim() || `POI ${index + 1}`,
          x: Math.floor(Number(entry?.x) || 0),
          y: Math.floor(Number(entry?.y) || 0),
        }))
        : [],
      chunkCache: new Map(),
      dirtyChunkKeys: new Set(),
      pendingNeighborhoodFetches: new Map(),
      prefetchedNeighborhoodKeys: new Set(),
      pendingLoadKey: "",
      pendingLoadPromise: null,
      requestSerial: 0,
      documentDirty: false,
    };
    function isWorldModeActive() {
      return worldRuntimeState.enabled && !!worldRuntimeState.worldId;
    }
    const defaultTileColor = DEFAULT_TILE_COLOR;
    const tileColors = cloneValue(bootstrap.tileColors) || {};
    let graphicsVisualRevision = 0;
    function applyGraphicsVisualRevision(dataUrl, revision = graphicsVisualRevision) {
      const normalizedDataUrl = String(dataUrl || "").trim();
      if (!normalizedDataUrl) {
        return null;
      }
      const safeRevision = Math.max(0, Math.floor(Number(revision) || 0));
      const baseUrl = normalizedDataUrl.replace(/#gfxrev=\d+$/, "");
      return `${baseUrl}#gfxrev=${safeRevision}`;
    }
    function applyTileCatalogVisualRevision(catalog, revision = graphicsVisualRevision) {
      const nextCatalog = {};
      Object.entries(catalog || {}).forEach(([entryId, entry]) => {
        nextCatalog[entryId] = {
          ...(entry || {}),
          dataUrl: applyGraphicsVisualRevision(entry?.dataUrl, revision),
        };
      });
      return nextCatalog;
    }
    function applySpriteCatalogVisualRevision(catalog, revision = graphicsVisualRevision) {
      const nextCatalog = {};
      Object.entries(catalog || {}).forEach(([entryId, entry]) => {
        nextCatalog[entryId] = {
          ...(entry || {}),
          dataUrl: applyGraphicsVisualRevision(entry?.dataUrl, revision),
        };
      });
      return nextCatalog;
    }
    const tileCatalogById = applyTileCatalogVisualRevision(buildTileCatalogByIdFromBootstrap(bootstrap));
    function normalizeBackgroundTileId(value) {
      const normalizedId = String(value || "").trim();
      return normalizedId && tileCatalogById[normalizedId] ? normalizedId : "";
    }
    function normalizeWorldBookmarkEntry(entry, fallbackIndex) {
      const fallbackId = `poi_${Math.max(1, Number(fallbackIndex) || 1)}`;
      const fallbackLabel = `POI ${Math.max(1, Number(fallbackIndex) || 1)}`;
      return {
        id: String(entry?.id || fallbackId).trim() || fallbackId,
        label: String(entry?.label || entry?.id || fallbackLabel).trim() || fallbackLabel,
        x: Math.floor(Number(entry?.x) || 0),
        y: Math.floor(Number(entry?.y) || 0),
      };
    }
    function cloneWorldBookmarks(source) {
      return (Array.isArray(source) ? source : worldRuntimeState.bookmarks)
        .map((entry, index) => normalizeWorldBookmarkEntry(entry, index + 1));
    }
    function applyWorldBookmarkState(bookmarks) {
      worldRuntimeState.bookmarks = cloneWorldBookmarks(bookmarks);
      scope.refreshWorldOverviewWindow?.();
      return cloneWorldBookmarks();
    }
    function captureWorldBookmarkState() {
      return cloneWorldBookmarks();
    }
    function getWorldBookmarks() {
      return cloneWorldBookmarks();
    }
    function getInitialWorldViewTile() {
      const firstBookmark = cloneWorldBookmarks()[0] || null;
      if (firstBookmark) {
        return {
          worldTileX: Math.floor(Number(firstBookmark.x) || 0),
          worldTileY: Math.floor(Number(firstBookmark.y) || 0),
        };
      }
      return {
        worldTileX: worldRuntimeState.spawnX,
        worldTileY: worldRuntimeState.spawnY,
      };
    }
    function buildNextWorldBookmarkId() {
      const existingIds = new Set(cloneWorldBookmarks().map((entry) => String(entry.id || "").trim()).filter(Boolean));
      let nextIndex = existingIds.size + 1;
      let nextId = `poi_${nextIndex}`;
      while (existingIds.has(nextId)) {
        nextIndex += 1;
        nextId = `poi_${nextIndex}`;
      }
      return nextId;
    }
    function createWorldBookmark(worldTileX, worldTileY, label) {
      const nextEntry = normalizeWorldBookmarkEntry({
        id: buildNextWorldBookmarkId(),
        label,
        x: worldTileX,
        y: worldTileY,
      }, worldRuntimeState.bookmarks.length + 1);
      worldRuntimeState.bookmarks = [...cloneWorldBookmarks(), nextEntry];
      scope.refreshWorldOverviewWindow?.();
      return nextEntry;
    }
    function renameWorldBookmark(bookmarkId, nextLabel) {
      const normalizedId = String(bookmarkId || "").trim();
      if (!normalizedId) {
        return null;
      }
      const safeLabel = String(nextLabel || "").trim();
      let nextEntry = null;
      worldRuntimeState.bookmarks = cloneWorldBookmarks().map((entry) => {
        if (String(entry.id || "").trim() !== normalizedId) {
          return entry;
        }
        nextEntry = {
          ...entry,
          label: safeLabel || entry.label,
        };
        return nextEntry;
      });
      scope.refreshWorldOverviewWindow?.();
      return nextEntry;
    }
    function deleteWorldBookmark(bookmarkId) {
      const normalizedId = String(bookmarkId || "").trim();
      if (!normalizedId) {
        return null;
      }
      const existing = cloneWorldBookmarks();
      const nextEntry = existing.find((entry) => String(entry.id || "").trim() === normalizedId) || null;
      if (!nextEntry) {
        return null;
      }
      worldRuntimeState.bookmarks = existing.filter((entry) => String(entry.id || "").trim() !== normalizedId);
      scope.refreshWorldOverviewWindow?.();
      return nextEntry;
    }
    function buildMergedTileCatalog() {
      const merged = {};
      Object.entries(tileColors).forEach(([symbol, color]) => {
        merged[symbol] = {
          id: symbol,
          symbol,
          name: symbol === " " ? "Space" : symbol,
          color,
          dataUrl: null,
          width: 1,
          height: 1,
        };
      });
      Object.values(tileCatalogById || {}).forEach((entry) => {
        if (!entry || typeof entry !== "object") {
          return;
        }
        const symbol = String((entry && entry.symbol) || "").charAt(0);
        if (!symbol) {
          return;
        }
        const existing = merged[symbol] || {
          id: symbol,
          symbol,
          name: symbol === " " ? "Space" : symbol,
          color: defaultTileColor,
          dataUrl: null,
          width: 1,
          height: 1,
        };
        merged[symbol] = {
          ...existing,
          ...entry,
          symbol,
          color: String((entry && entry.color) || existing.color || defaultTileColor),
          rows: Array.isArray(entry?.rows) ? entry.rows.map((row) => String(row || "")) : existing.rows,
          pixelScale: Math.max(1, Number(entry?.pixelScale) || Number(existing.pixelScale) || 1),
        };
      });
      return merged;
    }
    const tileCatalog = buildMergedTileCatalog();
    const contentByType = cloneValue(bootstrap.contentByType) || {};
    const spriteCatalog = applySpriteCatalogVisualRevision(buildSpriteCatalogFromBootstrap(bootstrap));
    const defaultNpcTemplate = cloneValue(bootstrap.defaultNpcTemplate) || {};
    const apiBase = String(bootstrap.apiBase || "").replace(/\/+$/, "");
    function deriveHistoryStorageKey(mapIdValue) {
      return "worldshaper:world-history:v2:" + String(mapIdValue || "").trim();
    }
    const layerListEl = document.getElementById("layerList");
    const paintPaletteEl = document.getElementById("paintPalette");
    const instancePaletteEl = document.getElementById("instancePalette");
    const npcListEl = document.getElementById("npcList");
    const newNpcBtn = document.getElementById("newNpcBtn");
    const newTileFolderBtn = document.getElementById("newTileFolderBtn");
    const newTileBtn = document.getElementById("newTileBtn");
    const tileSearchModeBtn = document.getElementById("tileSearchModeBtn");
    const graphicsTilesBtn = document.getElementById("graphicsTilesBtn");
    const graphicsSpritesBtn = document.getElementById("graphicsSpritesBtn");
    const graphicsOtherBtn = document.getElementById("graphicsOtherBtn");
    const newTemplateFolderBtn = document.getElementById("newTemplateFolderBtn");
    const newPlacedFolderBtn = document.getElementById("newPlacedFolderBtn");
    const entitySearchModeBtn = document.getElementById("entitySearchModeBtn");
    const entitySearchModeHost = document.getElementById("entitySearchModeHost");
    const entityTypeFriendlyBtn = document.getElementById("entityTypeFriendlyBtn");
    const entityTypeHostileBtn = document.getElementById("entityTypeHostileBtn");
    const entityTypePropBtn = document.getElementById("entityTypePropBtn");
    const newMonsterFolderBtn = document.getElementById("newMonsterFolderBtn");
    const newTriggerFolderBtn = document.getElementById("newTriggerFolderBtn");
    const newPathFolderBtn = document.getElementById("newPathFolderBtn");
    const newTransitionFolderBtn = document.getElementById("newTransitionFolderBtn");
    const toggleTemplateSectionBtn = document.getElementById("toggleTemplateSectionBtn");
    const togglePlacedSectionBtn = document.getElementById("togglePlacedSectionBtn");
    const instanceTemplateSectionBody = document.getElementById("instanceTemplateSectionBody");
    const placedInstanceSectionBody = document.getElementById("placedInstanceSectionBody");
    const entityCatalogSection = document.getElementById("entityCatalogSection");
    const placedEntitiesSection = document.getElementById("placedEntitiesSection");
    const monsterListEl = document.getElementById("monsterList");
    const triggerListEl = document.getElementById("triggerList");
    const pathListEl = document.getElementById("pathList");
    const transitionListEl = document.getElementById("transitionList");
    const metaEl = document.getElementById("meta");
    const metaMainEl = document.getElementById("metaMain");
    const metaStatsEl = document.getElementById("metaStats");
    const historyListEl = document.getElementById("historyList");
    const historyPreviewEl = document.getElementById("historyPreview");
    const historyCurrentEl = document.getElementById("historyCurrent");
    const undoBtn = document.getElementById("undoBtn");
    const redoBtn = document.getElementById("redoBtn");
    const saveBtn = document.getElementById("saveBtn");
    const testHeightBtn = document.getElementById("testHeightBtn");
    const menuLayerSelectEl = document.getElementById("menuLayerSelect");
    const saveStatusEl = document.getElementById("saveStatus");
    const themePresetButtons = Array.from(document.querySelectorAll("[data-theme-preset]"));
    const informationTabBtn = document.getElementById("informationTabBtn");
    const layersTabBtn = document.getElementById("layersTabBtn");
    const tilesTabBtn = document.getElementById("tilesTabBtn");
    const instancesTabBtn = document.getElementById("instancesTabBtn");
    const triggersTabBtn = document.getElementById("triggersTabBtn");
    const pathsTabBtn = document.getElementById("pathsTabBtn");
    const transitionsTabBtn = document.getElementById("transitionsTabBtn");
    const historyTabBtn = document.getElementById("historyTabBtn");
    const newsTabBtn = document.getElementById("newsTabBtn");
    const editorBodyEl = document.getElementById("editorBody");
    const sidebarEl = document.getElementById("sidebar");
    const sidebarTabsEl = document.getElementById("sidebarTabs");
    const sidebarPanelsHostEl = document.getElementById("sidebarPanelsHost");
    const informationPanel = document.getElementById("informationPanel");
    const layersPanel = document.getElementById("layersPanel");
    const tilesPanel = document.getElementById("tilesPanel");
    const instancesPanel = document.getElementById("instancesPanel");
    const triggersPanel = document.getElementById("triggersPanel");
    const pathsPanel = document.getElementById("pathsPanel");
    const transitionsPanel = document.getElementById("transitionsPanel");
    const historyPanel = document.getElementById("historyPanel");
    const drawLayerSectionBody = document.getElementById("drawLayerSectionBody");
    const heightLayerSectionBody = document.getElementById("heightLayerSectionBody");
    const toggleDrawLayerSectionBtn = document.getElementById("toggleDrawLayerSectionBtn");
    const toggleHeightLayerSectionBtn = document.getElementById("toggleHeightLayerSectionBtn");
    const informationSettingsSectionBody = document.getElementById("informationSettingsSectionBody");
    const informationConfigurationSectionBody = document.getElementById("informationConfigurationSectionBody");
    const informationHotkeysSectionBody = document.getElementById("informationHotkeysSectionBody");
    const toggleInformationSettingsSectionBtn = document.getElementById("toggleInformationSettingsSectionBtn");
    const toggleInformationConfigurationSectionBtn = document.getElementById("toggleInformationConfigurationSectionBtn");
    const toggleInformationHotkeysSectionBtn = document.getElementById("toggleInformationHotkeysSectionBtn");
    const mapIdLockedEl = document.getElementById("mapIdLocked");
    const mapNameInputEl = document.getElementById("mapNameInput");
    const mapWidthInputEl = document.getElementById("mapWidthInput");
    const mapHeightInputEl = document.getElementById("mapHeightInput");
    const mapBackgroundColorInputEl = document.getElementById("mapBackgroundColorInput");
    const engineOverridesBtn = document.getElementById("engineOverridesBtn");
    const engineOverridesSummaryEl = document.getElementById("engineOverridesSummary");
    const backgroundModeBtn = document.getElementById("backgroundModeBtn");
    const backgroundModePreviewEl = document.getElementById("backgroundModePreview");
    const backgroundModeTitleEl = document.getElementById("backgroundModeTitle");
    const backgroundModeMetaEl = document.getElementById("backgroundModeMeta");
    const experimentalImportToggleBtn = document.getElementById("experimentalImportToggleBtn");
    const experimentalImportCheckEl = document.getElementById("experimentalImportCheck");
    const experimentalImportBodyEl = document.getElementById("experimentalImportBody");
    const importSpritesBtn = document.getElementById("importSpritesBtn");
    const importTilesBtn = document.getElementById("importTilesBtn");
    const importJsonBtn = document.getElementById("importJsonBtn");
    const importSpritesInputEl = document.getElementById("importSpritesInput");
    const importTilesInputEl = document.getElementById("importTilesInput");
    const importJsonModal = document.getElementById("importJsonModal");
    const importJsonTypeSelect = document.getElementById("importJsonTypeSelect");
    const importJsonTextarea = document.getElementById("importJsonTextarea");
    const importJsonConfirmBtn = document.getElementById("importJsonConfirmBtn");
    const importJsonCancelBtn = document.getElementById("importJsonCancelBtn");
    const mapWidthValueEl = document.getElementById("mapWidthValue");
    const mapHeightValueEl = document.getElementById("mapHeightValue");
    const mapWidthControlsEl = document.getElementById("mapWidthControls");
    const mapHeightControlsEl = document.getElementById("mapHeightControls");
    const confirmWidthBtn = document.getElementById("confirmWidthBtn");
    const cancelWidthBtn = document.getElementById("cancelWidthBtn");
    const confirmHeightBtn = document.getElementById("confirmHeightBtn");
    const cancelHeightBtn = document.getElementById("cancelHeightBtn");
    const restoreToolWindowsBtn = document.getElementById("restoreToolWindowsBtn");
    const resetWorkspaceLayoutBtn = document.getElementById("resetWorkspaceLayoutBtn");
    const addHeightLayerBtn = document.getElementById("addHeightLayerBtn");
    const heightLayerListEl = document.getElementById("heightLayerList");
    const stageEl = document.getElementById("stage");
    const canvasSelectToolBtn = document.getElementById("canvasSelectToolBtn");
    const toolWindowLayerEl = document.getElementById("toolWindowLayer");
    const viewport = document.getElementById("viewport");
    const viewportSpacer = document.getElementById("viewportSpacer");
    const pixiHost = document.getElementById("pixiHost");
    const canvas = document.getElementById("roomCanvas");
    const ctx = canvas.getContext("2d");

    const initialBackgroundColor = normalizeMapBackgroundColor(bootstrap.backgroundColor);
    const initialBackgroundTileId = normalizeBackgroundTileId(bootstrap.backgroundTileId);
    const initialHeightBlurStep = Math.max(0, Math.min(1, Number(bootstrap.heightBlurStep ?? bootstrap.heightDetailStep) || 0.1));
    const mapDocumentStore = createMapDocumentStore({
      mapId: currentMapId,
      mapName: bootstrap.mapName || bootstrap.mapId || "Untitled",
      width: bootstrap.width,
      height: bootstrap.height,
      backgroundColor: initialBackgroundColor,
      backgroundTileId: initialBackgroundTileId,
      heightBlurStep: initialHeightBlurStep,
      backgroundCellMode: initialBackgroundTileId ? "tile" : "inherit",
      mapInfoDraft: {
        width: Number(bootstrap.width) || 1,
        height: Number(bootstrap.height) || 1,
        backgroundColor: initialBackgroundColor,
        heightBlurStep: initialHeightBlurStep,
      },
      roomLayers: bootstrap.roomLayers,
      heightLayers: bootstrap.heightLayers,
      npcOverlays: bootstrap.npcOverlays,
      contentBundle: contentByType,
    });
    const mapDocument = mapDocumentStore.state;
    function cacheStandaloneMapBootstrap() {
      return cacheStandaloneWorldshaperBootstrap(buildCurrentBootstrapSnapshot(), window);
    }
    function syncDocumentTitle() {
      const titleName = String(mapDocument.mapName || currentMapId || "Untitled").trim() || "Untitled";
      document.title = "Worldshaper Studio - " + titleName;
    }
    function clampZoomLevel(value) {
      const normalized = Number(value);
      if (!Number.isFinite(normalized)) {
        return zoomLevel;
      }
      return Math.max(minZoomLevel, Math.min(maxZoomLevel, normalized));
    }
    function getZoomPercent() {
      return Math.round(clampZoomLevel(zoomLevel) * 100);
    }
    function getScaledSize(value, fallback) {
      const baseSize = Math.max(1, Number(fallback) || baseTileSize);
      const rawSize = Math.max(1, Number(value) || baseSize);
      return Math.max(1, Math.round(rawSize * (tileSize / baseTileSize)));
    }
    function syncCanvasDimensionsToTileSize() {
      const nextCanvasWidth = Math.max(1, Math.ceil(Number(viewport?.clientWidth) || 0));
      const nextCanvasHeight = Math.max(1, Math.ceil(Number(viewport?.clientHeight) || 0));
      if (canvas.width !== nextCanvasWidth || canvas.height !== nextCanvasHeight) {
        canvas.width = nextCanvasWidth;
        canvas.height = nextCanvasHeight;
      }
      canvas.style.width = nextCanvasWidth + "px";
      canvas.style.height = nextCanvasHeight + "px";
      if (pixiHost) {
        pixiHost.style.width = nextCanvasWidth + "px";
        pixiHost.style.height = nextCanvasHeight + "px";
      }
      const viewportLayer = canvas.parentElement;
      if (viewportLayer) {
        viewportLayer.style.width = nextCanvasWidth + "px";
        viewportLayer.style.height = nextCanvasHeight + "px";
      }
      if (viewportSpacer) {
        viewportSpacer.style.width = Math.max(nextCanvasWidth, mapDocument.width * tileSize) + "px";
        viewportSpacer.style.height = Math.max(nextCanvasHeight, mapDocument.height * tileSize) + "px";
      }
    }
    function applyZoomLevel(nextZoomLevel, anchorClientX, anchorClientY) {
      const clampedZoom = clampZoomLevel(nextZoomLevel);
      if (Math.abs(clampedZoom - zoomLevel) < 0.001) {
        return false;
      }
      const previousTileSize = tileSize;
      const viewportRect = viewport.getBoundingClientRect();
      const anchorOffsetX = Number.isFinite(anchorClientX)
        ? anchorClientX - viewportRect.left
        : viewport.clientWidth / 2;
      const anchorOffsetY = Number.isFinite(anchorClientY)
        ? anchorClientY - viewportRect.top
        : viewport.clientHeight / 2;
      const worldTileX = (viewport.scrollLeft + anchorOffsetX) / Math.max(1, previousTileSize);
      const worldTileY = (viewport.scrollTop + anchorOffsetY) / Math.max(1, previousTileSize);
      zoomLevel = clampedZoom;
      tileSize = Math.max(8, Math.round(baseTileSize * zoomLevel));
      syncCanvasDimensionsToTileSize();
      const nextScrollLeft = Math.round((worldTileX * tileSize) - anchorOffsetX);
      const nextScrollTop = Math.round((worldTileY * tileSize) - anchorOffsetY);
      const worldPixelWidth = Math.max(1, mapDocument.width * tileSize);
      const worldPixelHeight = Math.max(1, mapDocument.height * tileSize);
      const maxScrollLeft = Math.max(0, worldPixelWidth - viewport.clientWidth);
      const maxScrollTop = Math.max(0, worldPixelHeight - viewport.clientHeight);
      viewport.scrollLeft = Math.max(0, Math.min(maxScrollLeft, nextScrollLeft));
      viewport.scrollTop = Math.max(0, Math.min(maxScrollTop, nextScrollTop));
      if (isWorldModeActive()) {
        syncWorldNeighborhoodForViewport();
      }
      return true;
    }
    function startZoomPreview(durationMs) {
      popupSessionStore.state.zoomPreviewUntil = Date.now() + Math.max(16, Number(durationMs) || 120);
    }
    function isZoomPreviewActive() {
      return Date.now() < popupSessionStore.state.zoomPreviewUntil;
    }
    function startScrollPreview(durationMs) {
      popupSessionStore.state.scrollPreviewUntil = Date.now() + Math.max(16, Number(durationMs) || 90);
    }
    function isScrollPreviewActive() {
      return Date.now() < popupSessionStore.state.scrollPreviewUntil;
    }
    function centerViewportOnWorldPoint(worldX, worldY) {
      const targetX = Number(worldX);
      const targetY = Number(worldY);
      if (!Number.isFinite(targetX) || !Number.isFinite(targetY) || !viewport) {
        return false;
      }
      const worldPixelWidth = Math.max(1, mapDocument.width * tileSize);
      const worldPixelHeight = Math.max(1, mapDocument.height * tileSize);
      const maxScrollLeft = Math.max(0, worldPixelWidth - viewport.clientWidth);
      const maxScrollTop = Math.max(0, worldPixelHeight - viewport.clientHeight);
      viewport.scrollLeft = Math.max(0, Math.min(maxScrollLeft, Math.round(targetX - (viewport.clientWidth / 2))));
      viewport.scrollTop = Math.max(0, Math.min(maxScrollTop, Math.round(targetY - (viewport.clientHeight / 2))));
      return true;
    }
    function getViewportCenterWorldTile() {
      if (!viewport) {
        return { worldTileX: 0, worldTileY: 0 };
      }
      const localTileX = (Number(viewport.scrollLeft) + (Number(viewport.clientWidth) / 2)) / Math.max(1, tileSize);
      const localTileY = (Number(viewport.scrollTop) + (Number(viewport.clientHeight) / 2)) / Math.max(1, tileSize);
      return {
        worldTileX: worldRuntimeState.tileOffsetX + localTileX,
        worldTileY: worldRuntimeState.tileOffsetY + localTileY,
      };
    }
    function centerViewportOnWorldTile(worldTileX, worldTileY) {
      const localTileX = Number(worldTileX) - worldRuntimeState.tileOffsetX;
      const localTileY = Number(worldTileY) - worldRuntimeState.tileOffsetY;
      return centerViewportOnWorldPoint(
        localTileX * tileSize,
        localTileY * tileSize,
      );
    }

    function getVisibleWorldChunkPayloads() {
      if (!isWorldModeActive()) {
        return [];
      }
      return worldRuntimeState.sourceChunks
        .map((entry) => worldRuntimeState.chunkCache.get(buildChunkKey(entry.chunkX, entry.chunkY)) || null)
        .filter(Boolean);
    }

    function getWorldChunkCoordForLocalTile(localTileX, localTileY) {
      if (!isWorldModeActive()) {
        return null;
      }
      const safeLocalTileX = Math.floor(Number(localTileX) || 0);
      const safeLocalTileY = Math.floor(Number(localTileY) || 0);
      return {
        chunkX: worldToChunkCoord(worldRuntimeState.tileOffsetX + safeLocalTileX, worldRuntimeState.chunkWidth),
        chunkY: worldToChunkCoord(worldRuntimeState.tileOffsetY + safeLocalTileY, worldRuntimeState.chunkHeight),
      };
    }

    function getCachedWorldChunk(chunkX, chunkY) {
      if (!isWorldModeActive()) {
        return null;
      }
      return worldRuntimeState.chunkCache.get(buildChunkKey(chunkX, chunkY)) || null;
    }

    function getWorldChunkBackgroundTileId(chunkX, chunkY) {
      if (!isWorldModeActive()) {
        return normalizeBackgroundTileId(mapDocument.backgroundTileId);
      }
      const chunk = getCachedWorldChunk(chunkX, chunkY);
      const chunkBackgroundTileId = chunk && Object.prototype.hasOwnProperty.call(chunk, "backgroundTileId")
        ? String(chunk.backgroundTileId || "").trim()
        : "";
      return chunkBackgroundTileId || normalizeBackgroundTileId(mapDocument.backgroundTileId);
    }

    function getBackgroundTileIdForLocalTile(localTileX, localTileY) {
      if (!isWorldModeActive()) {
        return normalizeBackgroundTileId(mapDocument.backgroundTileId);
      }
      const chunkCoord = getWorldChunkCoordForLocalTile(localTileX, localTileY);
      if (!chunkCoord) {
        return normalizeBackgroundTileId(mapDocument.backgroundTileId);
      }
      return getWorldChunkBackgroundTileId(chunkCoord.chunkX, chunkCoord.chunkY);
    }

    function setWorldChunkBackgroundTileId(chunkX, chunkY, backgroundTileId) {
      if (!isWorldModeActive()) {
        return null;
      }
      const safeChunkX = Math.floor(Number(chunkX) || 0);
      const safeChunkY = Math.floor(Number(chunkY) || 0);
      const chunkKey = buildChunkKey(safeChunkX, safeChunkY);
      const normalizedBackgroundTileId = normalizeBackgroundTileId(backgroundTileId);
      const storedBackgroundTileId = normalizedBackgroundTileId === normalizeBackgroundTileId(mapDocument.backgroundTileId)
        ? ""
        : normalizedBackgroundTileId;
      const existingChunk = worldRuntimeState.chunkCache.get(chunkKey);
      const chunkValue = existingChunk
        ? cloneValue(existingChunk)
        : (rebuildWorldChunkPayloadFromDocument(safeChunkX, safeChunkY) || {
          worldId: String(worldRuntimeState.worldId || currentMapId || "").trim(),
          chunkX: safeChunkX,
          chunkY: safeChunkY,
          width: worldRuntimeState.chunkWidth,
          height: worldRuntimeState.chunkHeight,
          roomLayers: [],
          heightLayers: [],
          instances: [],
        });
      chunkValue.backgroundTileId = storedBackgroundTileId;
      touchWorldChunkCacheEntry(chunkKey, chunkValue);
      worldRuntimeState.dirtyChunkKeys.add(chunkKey);
      scope.invalidateWorldOverviewChunkSurfaces?.([chunkKey]);
      scope.refreshWorldOverviewWindow?.();
      return chunkValue;
    }

    function getPreferredWorldChunkCoord() {
      if (!isWorldModeActive()) {
        return null;
      }
      if (Number.isFinite(popupSessionStore.state.hoverTileX) && Number.isFinite(popupSessionStore.state.hoverTileY) && popupSessionStore.state.hoverTileX >= 0 && popupSessionStore.state.hoverTileY >= 0) {
        return getWorldChunkCoordForLocalTile(popupSessionStore.state.hoverTileX, popupSessionStore.state.hoverTileY);
      }
      const selectedTile = popupSessionStore.state.selectedTile && typeof popupSessionStore.state.selectedTile === "object"
        ? popupSessionStore.state.selectedTile
        : null;
      if (selectedTile && Number.isFinite(selectedTile.x) && Number.isFinite(selectedTile.y) && selectedTile.x >= 0 && selectedTile.y >= 0) {
        return getWorldChunkCoordForLocalTile(selectedTile.x, selectedTile.y);
      }
      return null;
    }

    function getSelectedWorldChunkCoord() {
      if (!isWorldModeActive() || popupSessionStore.state.canvasToolMode !== "select") {
        return null;
      }
      const selectedTile = popupSessionStore.state.selectedTile && typeof popupSessionStore.state.selectedTile === "object"
        ? popupSessionStore.state.selectedTile
        : null;
      if (selectedTile && Number.isFinite(selectedTile.x) && Number.isFinite(selectedTile.y) && selectedTile.x >= 0 && selectedTile.y >= 0) {
        return getWorldChunkCoordForLocalTile(selectedTile.x, selectedTile.y);
      }
      const selectedNpcId = String(popupSessionStore.state.selectedNpcId || "").trim();
      if (!selectedNpcId) {
        return null;
      }
      const npc = mapDocument.npcOverlays.find((entry) => String(entry?.id || "").trim() === selectedNpcId) || null;
      if (!npc) {
        return null;
      }
      const npcX = Math.floor(Number(npc.x));
      const npcY = Math.floor(Number(npc.y));
      if (!Number.isFinite(npcX) || !Number.isFinite(npcY) || npcX < 0 || npcY < 0) {
        return null;
      }
      return getWorldChunkCoordForLocalTile(npcX, npcY);
    }

    function captureWorldChunkBackgroundState() {
      if (!isWorldModeActive()) {
        return {};
      }
      const payload = {};
      Array.from(worldRuntimeState.chunkCache.entries())
        .sort((left, right) => String(left[0] || "").localeCompare(String(right[0] || "")))
        .forEach(([chunkKey, chunkValue]) => {
        payload[chunkKey] = chunkValue && Object.prototype.hasOwnProperty.call(chunkValue, "backgroundTileId")
          ? String(chunkValue.backgroundTileId || "").trim()
          : "";
        });
      return payload;
    }

    function applyWorldChunkBackgroundState(backgrounds) {
      if (!isWorldModeActive()) {
        return false;
      }
      const entries = backgrounds && typeof backgrounds === "object" && !Array.isArray(backgrounds)
        ? Object.entries(backgrounds)
        : [];
      let changed = false;
      entries.forEach(([chunkKey, backgroundTileId]) => {
        const existingChunk = worldRuntimeState.chunkCache.get(String(chunkKey || "").trim());
        if (!existingChunk) {
          return;
        }
        const nextBackgroundTileId = normalizeBackgroundTileId(backgroundTileId);
        if (String(existingChunk.backgroundTileId || "").trim() === nextBackgroundTileId) {
          return;
        }
        touchWorldChunkCacheEntry(String(chunkKey || "").trim(), {
          ...cloneValue(existingChunk),
          backgroundTileId: nextBackgroundTileId,
        });
        changed = true;
      });
      return changed;
    }

    function ensureWorldDocumentCurrent() {
      if (!isWorldModeActive() || worldRuntimeState.documentDirty !== true) {
        return false;
      }
      const visibleChunks = getVisibleWorldChunkPayloads();
      const composedWidth = ((worldRuntimeState.chunkRadius * 2) + 1) * worldRuntimeState.chunkWidth;
      const composedHeight = ((worldRuntimeState.chunkRadius * 2) + 1) * worldRuntimeState.chunkHeight;
      const roomLayers = composeWorldRoomLayers(
        visibleChunks,
        worldRuntimeState.chunkWidth,
        worldRuntimeState.chunkHeight,
        worldRuntimeState.originChunkX,
        worldRuntimeState.originChunkY,
        composedWidth,
        composedHeight,
      );
      const heightLayers = composeWorldHeightLayers(
        visibleChunks,
        worldRuntimeState.chunkWidth,
        worldRuntimeState.chunkHeight,
        worldRuntimeState.originChunkX,
        worldRuntimeState.originChunkY,
      );
      currentBaseRows = Array.isArray(roomLayers.find((layer) => Number(layer.layer) === 0)?.rows)
        ? roomLayers.find((layer) => Number(layer.layer) === 0).rows.map((row) => String(row || ""))
        : createFilledRows(composedWidth, composedHeight, ".");
      mapDocument.roomLayers = cloneLayers(roomLayers);
      mapDocument.heightLayers = cloneHeightLayers(heightLayers);
      popupSessionStore.syncLayerVisibility(mapDocument.roomLayers);
      ensureActiveHeightLayerSelection();
      worldRuntimeState.documentDirty = false;
      return true;
    }

    function touchWorldChunkCacheEntry(chunkKey, chunkValue) {
      const normalizedKey = String(chunkKey || "").trim();
      if (!normalizedKey) {
        return;
      }
      if (worldRuntimeState.chunkCache.has(normalizedKey)) {
        worldRuntimeState.chunkCache.delete(normalizedKey);
      }
      worldRuntimeState.chunkCache.set(normalizedKey, chunkValue);
    }

    function markWorldChunkDirty(chunkX, chunkY) {
      if (!isWorldModeActive()) {
        return false;
      }
      const chunkKey = buildChunkKey(chunkX, chunkY);
      if (!chunkKey) {
        return false;
      }
      worldRuntimeState.dirtyChunkKeys.add(chunkKey);
      return true;
    }

    function markWorldChunkDirtyByLocalTile(localTileX, localTileY) {
      if (!isWorldModeActive()) {
        return false;
      }
      const safeLocalTileX = Math.floor(Number(localTileX) || 0);
      const safeLocalTileY = Math.floor(Number(localTileY) || 0);
      const worldTileX = worldRuntimeState.tileOffsetX + safeLocalTileX;
      const worldTileY = worldRuntimeState.tileOffsetY + safeLocalTileY;
      return markWorldChunkDirty(
        worldToChunkCoord(worldTileX, worldRuntimeState.chunkWidth),
        worldToChunkCoord(worldTileY, worldRuntimeState.chunkHeight),
      );
    }

    function markWorldChunksDirtyByLocalBounds(bounds) {
      if (!isWorldModeActive() || !bounds || typeof bounds !== "object") {
        return [];
      }
      const minLocalX = Math.floor(Number(bounds.minX));
      const minLocalY = Math.floor(Number(bounds.minY));
      const maxLocalX = Math.floor(Number(bounds.maxX));
      const maxLocalY = Math.floor(Number(bounds.maxY));
      if (![minLocalX, minLocalY, maxLocalX, maxLocalY].every(Number.isFinite)) {
        return [];
      }
      const startChunkX = worldToChunkCoord(worldRuntimeState.tileOffsetX + Math.min(minLocalX, maxLocalX), worldRuntimeState.chunkWidth);
      const endChunkX = worldToChunkCoord(worldRuntimeState.tileOffsetX + Math.max(minLocalX, maxLocalX), worldRuntimeState.chunkWidth);
      const startChunkY = worldToChunkCoord(worldRuntimeState.tileOffsetY + Math.min(minLocalY, maxLocalY), worldRuntimeState.chunkHeight);
      const endChunkY = worldToChunkCoord(worldRuntimeState.tileOffsetY + Math.max(minLocalY, maxLocalY), worldRuntimeState.chunkHeight);
      const touchedKeys = [];
      for (let chunkY = startChunkY; chunkY <= endChunkY; chunkY += 1) {
        for (let chunkX = startChunkX; chunkX <= endChunkX; chunkX += 1) {
          const chunkKey = buildChunkKey(chunkX, chunkY);
          if (!chunkKey) {
            continue;
          }
          worldRuntimeState.dirtyChunkKeys.add(chunkKey);
          touchedKeys.push(chunkKey);
        }
      }
      return touchedKeys;
    }

    function markVisibleWorldChunksDirty() {
      if (!isWorldModeActive()) {
        return [];
      }
      return (Array.isArray(worldRuntimeState.sourceChunks) ? worldRuntimeState.sourceChunks : [])
        .map((entry) => {
          const chunkKey = buildChunkKey(entry?.chunkX, entry?.chunkY);
          if (chunkKey) {
            worldRuntimeState.dirtyChunkKeys.add(chunkKey);
          }
          return chunkKey;
        })
        .filter(Boolean);
    }

    function getDirtyWorldChunkKeys() {
      return Array.from(worldRuntimeState.dirtyChunkKeys.values());
    }

    function clearDirtyWorldChunks(chunkKeys) {
      const keys = Array.isArray(chunkKeys) ? chunkKeys : Array.from(worldRuntimeState.dirtyChunkKeys.values());
      keys.forEach((chunkKey) => {
        worldRuntimeState.dirtyChunkKeys.delete(String(chunkKey || "").trim());
      });
      return true;
    }

    function getDirtyWorldChunkPayloads() {
      return Array.from(worldRuntimeState.dirtyChunkKeys.values())
        .map((chunkKey) => worldRuntimeState.chunkCache.get(chunkKey) || null)
        .filter(Boolean)
        .map((entry) => cloneValue(entry));
    }

    function pruneWorldChunkCache() {
      if (worldRuntimeState.chunkCache.size <= MAX_WORLD_CHUNK_CACHE_ENTRIES) {
        return;
      }
      const preserveRadius = Math.max(0, worldRuntimeState.chunkRadius) + 2;
      const preservedKeys = new Set();
      for (let chunkY = worldRuntimeState.centerChunkY - preserveRadius; chunkY <= worldRuntimeState.centerChunkY + preserveRadius; chunkY += 1) {
        for (let chunkX = worldRuntimeState.centerChunkX - preserveRadius; chunkX <= worldRuntimeState.centerChunkX + preserveRadius; chunkX += 1) {
          preservedKeys.add(buildChunkKey(chunkX, chunkY));
        }
      }
      for (const sourceChunk of worldRuntimeState.sourceChunks) {
        preservedKeys.add(buildChunkKey(sourceChunk?.chunkX, sourceChunk?.chunkY));
      }
      for (const dirtyChunkKey of worldRuntimeState.dirtyChunkKeys) {
        preservedKeys.add(dirtyChunkKey);
      }
      for (const [chunkKey] of worldRuntimeState.chunkCache) {
        if (worldRuntimeState.chunkCache.size <= MAX_WORLD_CHUNK_CACHE_ENTRIES) {
          break;
        }
        if (preservedKeys.has(chunkKey)) {
          continue;
        }
        worldRuntimeState.chunkCache.delete(chunkKey);
      }
    }

    function getDesiredWorldChunkRadius() {
      if (!isWorldModeActive() || !viewport) {
        return Math.max(0, worldRuntimeState.chunkRadius);
      }
      const visibleTilesX = Math.max(1, (Number(viewport.clientWidth) || 0) / Math.max(1, tileSize));
      const visibleTilesY = Math.max(1, (Number(viewport.clientHeight) || 0) / Math.max(1, tileSize));
      const horizontalBufferTiles = Math.max(4, Math.ceil(worldRuntimeState.chunkWidth * 0.35));
      const verticalBufferTiles = Math.max(4, Math.ceil(worldRuntimeState.chunkHeight * 0.35));
      const horizontalRadius = Math.ceil(((visibleTilesX * 0.5) + horizontalBufferTiles) / Math.max(1, worldRuntimeState.chunkWidth));
      const verticalRadius = Math.ceil(((visibleTilesY * 0.5) + verticalBufferTiles) / Math.max(1, worldRuntimeState.chunkHeight));
      return Math.max(
        1,
        Math.min(
          MAX_DYNAMIC_WORLD_CHUNK_RADIUS,
          Math.max(horizontalRadius, verticalRadius),
        ),
      );
    }

    function sliceNormalizedRows(rows, startX, startY, width, height, fillChar) {
      return Array.from({ length: Math.max(1, Number(height) || 1) }, (_, rowOffset) => {
        const sourceRow = String((Array.isArray(rows) ? rows[startY + rowOffset] : "") || "");
        const paddedRow = sourceRow.length >= startX + width
          ? sourceRow
          : sourceRow + String(fillChar || " ").repeat(Math.max(0, (startX + width) - sourceRow.length));
        return paddedRow.slice(startX, startX + width);
      });
    }

    function buildChunkHeightLayersFromDocument(baseTileX, baseTileY, chunkWidth, chunkHeight) {
      return (Array.isArray(mapDocument.heightLayers) ? cloneHeightLayers(mapDocument.heightLayers) : [])
        .map((entry) => {
          const patchX = Math.max(0, Number(entry?.x) || 0);
          const patchY = Math.max(0, Number(entry?.y) || 0);
          const rows = Array.isArray(entry?.rows) ? entry.rows.map((row) => String(row || "")) : [];
          const patchWidth = rows.reduce((max, row) => Math.max(max, row.length), 0);
          const patchHeight = rows.length;
          const patchRight = patchX + patchWidth;
          const patchBottom = patchY + patchHeight;
          const chunkRight = baseTileX + chunkWidth;
          const chunkBottom = baseTileY + chunkHeight;
          const overlapLeft = Math.max(baseTileX, patchX);
          const overlapTop = Math.max(baseTileY, patchY);
          const overlapRight = Math.min(chunkRight, patchRight);
          const overlapBottom = Math.min(chunkBottom, patchBottom);
          if (overlapRight <= overlapLeft || overlapBottom <= overlapTop) {
            return null;
          }
          const localRows = [];
          for (let y = overlapTop; y < overlapBottom; y += 1) {
            const sourceRow = String(rows[y - patchY] || "");
            localRows.push(sourceRow.slice(overlapLeft - patchX, overlapRight - patchX).replace(/\s+$/g, ""));
          }
          return {
            id: String(entry?.id || "").trim(),
            name: typeof entry?.name === "string" && entry.name.trim() ? entry.name.trim() : undefined,
            z: Math.max(1, Number(entry?.z) || 1),
            x: overlapLeft - baseTileX,
            y: overlapTop - baseTileY,
            rows: localRows,
          };
        })
        .filter((entry) => entry && entry.id);
    }

    function buildChunkInstancesFromDocument(baseTileX, baseTileY, chunkWidth, chunkHeight) {
      const chunkInstances = cloneValue(mapDocument.npcOverlays)
        .filter((npc) => {
          const localX = Math.floor(Number(npc?.x));
          const localY = Math.floor(Number(npc?.y));
          return Number.isFinite(localX)
            && Number.isFinite(localY)
            && localX >= baseTileX
            && localX < baseTileX + chunkWidth
            && localY >= baseTileY
            && localY < baseTileY + chunkHeight;
        })
        .map((npc) => ({
          id: String(npc.id || "").trim(),
          templateId: String(npc?.record?.templateId || "").trim(),
          layer: Number(npc.layer) || 0,
          x: Math.floor(Number(npc.x) || 0) - baseTileX,
          y: Math.floor(Number(npc.y) || 0) - baseTileY,
          record: {
            ...cloneValue(npc.record || {}),
            id: String(npc.id || "").trim(),
            layer: Number(npc.layer) || 0,
            templateId: String(npc?.record?.templateId || "").trim(),
            name: String(npc.name || npc?.record?.name || ""),
            entityType: String(npc?.record?.entityType || npc?.entityType || "friendly"),
            faction: String(npc.faction || npc?.record?.faction || ""),
            spriteId: String(npc.spriteId || npc?.record?.spriteId || ""),
            dialogueId: String(npc.dialogueId || npc?.record?.dialogueId || ""),
            description: String(npc.description || npc?.record?.description || ""),
            tags: cloneValue(npc?.record?.tags) || [],
            enabled: typeof npc?.record?.enabled === "boolean" ? npc.record.enabled : true,
            position: {
              x: Math.floor(Number(npc.x) || 0) + worldRuntimeState.tileOffsetX,
              y: Math.floor(Number(npc.y) || 0) + worldRuntimeState.tileOffsetY,
            },
          },
        }))
        .filter((entry) => entry.id);
      const npcIdsByLayer = new Map();
      chunkInstances.forEach((entry) => {
        const layerNumber = Number(entry.layer) || 0;
        if (!npcIdsByLayer.has(layerNumber)) {
          npcIdsByLayer.set(layerNumber, []);
        }
        npcIdsByLayer.get(layerNumber).push(entry.id);
      });
      return {
        chunkInstances,
        npcIdsByLayer,
      };
    }

    function rebuildWorldChunkPayloadFromDocument(chunkX, chunkY) {
      if (!isWorldModeActive()) {
        return null;
      }
      const safeChunkX = Math.floor(Number(chunkX) || 0);
      const safeChunkY = Math.floor(Number(chunkY) || 0);
      const chunkWidth = Math.max(1, worldRuntimeState.chunkWidth);
      const chunkHeight = Math.max(1, worldRuntimeState.chunkHeight);
      const baseTileX = (safeChunkX - worldRuntimeState.originChunkX) * chunkWidth;
      const baseTileY = (safeChunkY - worldRuntimeState.originChunkY) * chunkHeight;
      const cachedChunk = worldRuntimeState.chunkCache.get(buildChunkKey(safeChunkX, safeChunkY)) || null;
      const chunkBackgroundTileId = cachedChunk && Object.prototype.hasOwnProperty.call(cachedChunk, "backgroundTileId")
        ? normalizeBackgroundTileId(cachedChunk.backgroundTileId)
        : "";
      const normalizedLayers = cloneLayers(mapDocument.roomLayers)
        .map((layer) => ({
          layer: Number(layer.layer) || 0,
          name: typeof layer.name === "string" && layer.name.trim() ? layer.name.trim() : undefined,
          rows: documentController.normalizeRows(layer.rows, (Number(layer.layer) || 0) === 0 ? "." : " "),
        }))
        .sort((left, right) => left.layer - right.layer);
      const { chunkInstances, npcIdsByLayer } = buildChunkInstancesFromDocument(baseTileX, baseTileY, chunkWidth, chunkHeight);
      const roomLayers = normalizedLayers.map((layer) => ({
        layer: layer.layer,
        name: layer.name,
        rows: sliceNormalizedRows(layer.rows, baseTileX, baseTileY, chunkWidth, chunkHeight, layer.layer === 0 ? "." : " "),
        instanceIds: npcIdsByLayer.get(layer.layer) || [],
      }));
      return {
        ...(cachedChunk && typeof cachedChunk === "object" && !Array.isArray(cachedChunk) ? cachedChunk : {}),
        worldId: String(worldRuntimeState.worldId || currentMapId || "").trim(),
        chunkX: safeChunkX,
        chunkY: safeChunkY,
        width: chunkWidth,
        height: chunkHeight,
        backgroundTileId: chunkBackgroundTileId,
        roomLayers,
        heightLayers: buildChunkHeightLayersFromDocument(baseTileX, baseTileY, chunkWidth, chunkHeight),
        instances: chunkInstances,
      };
    }

    function rebuildCachedWorldChunkFromDocument(chunkX, chunkY, options) {
      const config = options && typeof options === "object" ? options : {};
      const payload = rebuildWorldChunkPayloadFromDocument(chunkX, chunkY);
      if (!payload) {
        return null;
      }
      const chunkKey = buildChunkKey(payload.chunkX, payload.chunkY);
      touchWorldChunkCacheEntry(chunkKey, payload);
      if (config.markDirty !== false) {
        worldRuntimeState.dirtyChunkKeys.add(chunkKey);
      }
      return payload;
    }

    function rebuildVisibleWorldChunksFromDocument(targetChunkKeys) {
      if (!isWorldModeActive()) {
        return [];
      }
      const requestedKeys = new Set(
        (Array.isArray(targetChunkKeys) ? targetChunkKeys : [])
          .map((chunkKey) => String(chunkKey || "").trim())
          .filter(Boolean),
      );
      const nextPayloads = [];
      (Array.isArray(worldRuntimeState.sourceChunks) ? worldRuntimeState.sourceChunks : []).forEach((entry) => {
        const chunkKey = buildChunkKey(entry?.chunkX, entry?.chunkY);
        if (requestedKeys.size > 0 && !requestedKeys.has(chunkKey)) {
          return;
        }
        const payload = rebuildCachedWorldChunkFromDocument(entry?.chunkX, entry?.chunkY, { markDirty: true });
        if (payload) {
          nextPayloads.push(payload);
        }
      });
      pruneWorldChunkCache();
      scope.invalidateWorldOverviewChunkSurfaces?.(nextPayloads.map((entry) => buildChunkKey(entry?.chunkX, entry?.chunkY)));
      scope.refreshWorldOverviewWindow?.();
      return nextPayloads;
    }

    function rebuildWorldChunksForLocalBounds(bounds) {
      if (!isWorldModeActive() || !bounds || typeof bounds !== "object") {
        return [];
      }
      const touchedKeys = markWorldChunksDirtyByLocalBounds(bounds);
      const rebuiltPayloads = [];
      touchedKeys.forEach((chunkKey) => {
        const [chunkXPart, chunkYPart] = String(chunkKey || "").split(":");
        const payload = rebuildCachedWorldChunkFromDocument(Number(chunkXPart), Number(chunkYPart), { markDirty: true });
        if (payload) {
          rebuiltPayloads.push(payload);
        }
      });
      pruneWorldChunkCache();
      scope.invalidateWorldOverviewChunkSurfaces?.(rebuiltPayloads.map((entry) => buildChunkKey(entry?.chunkX, entry?.chunkY)));
      scope.refreshWorldOverviewWindow?.();
      return rebuiltPayloads;
    }

    function syncCachedWorldRoomLayerMetadata(options) {
      if (!isWorldModeActive()) {
        return false;
      }
      const config = options && typeof options === "object" ? options : {};
      const layerNumberMap = config.layerNumberMap && typeof config.layerNumberMap === "object"
        ? config.layerNumberMap
        : null;
      const fallbackLayerNumber = Number(config.fallbackLayerNumber) || 0;
      const removedLayerNumbers = new Set(
        (Array.isArray(config.removedLayerNumbers) ? config.removedLayerNumbers : [])
          .map((entry) => Number(entry) || 0),
      );
      const metadataByLayer = new Map(
        cloneLayers(mapDocument.roomLayers).map((layer) => [
          Number(layer.layer) || 0,
          {
            layer: Number(layer.layer) || 0,
            name: typeof layer.name === "string" && layer.name.trim() ? layer.name.trim() : undefined,
          },
        ]),
      );
      let changed = false;
      for (const [chunkKey, chunkValue] of worldRuntimeState.chunkCache.entries()) {
        if (!chunkValue || typeof chunkValue !== "object" || Array.isArray(chunkValue)) {
          continue;
        }
        const safeWidth = Math.max(1, Number(chunkValue.width) || worldRuntimeState.chunkWidth);
        const safeHeight = Math.max(1, Number(chunkValue.height) || worldRuntimeState.chunkHeight);
        const nextInstances = (Array.isArray(chunkValue.instances) ? chunkValue.instances : [])
          .map((entry) => {
            const previousLayer = Number(entry?.layer) || 0;
            const nextLayer = removedLayerNumbers.has(previousLayer)
              ? fallbackLayerNumber
              : (layerNumberMap ? (layerNumberMap[String(previousLayer)] ?? previousLayer) : previousLayer);
            return {
              ...cloneValue(entry),
              layer: nextLayer,
            };
          });
        const instanceIdsByLayer = new Map();
        nextInstances.forEach((entry) => {
          const layerNumber = Number(entry?.layer) || 0;
          if (!instanceIdsByLayer.has(layerNumber)) {
            instanceIdsByLayer.set(layerNumber, []);
          }
          instanceIdsByLayer.get(layerNumber).push(String(entry?.id || "").trim());
        });
        const nextRoomLayers = (Array.isArray(chunkValue.roomLayers) ? chunkValue.roomLayers : [])
          .map((entry) => {
            const previousLayer = Number(entry?.layer) || 0;
            if (removedLayerNumbers.has(previousLayer)) {
              return null;
            }
            const nextLayer = layerNumberMap
              ? (layerNumberMap[String(previousLayer)] ?? previousLayer)
              : previousLayer;
            const metadata = metadataByLayer.get(nextLayer) || { layer: nextLayer, name: undefined };
            const fillChar = nextLayer === 0 ? "." : " ";
            return {
              ...cloneValue(entry),
              layer: nextLayer,
              name: metadata.name,
              rows: Array.isArray(entry?.rows)
                ? entry.rows.map((row) => String(row || ""))
                : createFilledRows(safeWidth, safeHeight, fillChar),
              instanceIds: instanceIdsByLayer.get(nextLayer) || [],
            };
          })
          .filter(Boolean)
          .sort((left, right) => (Number(left?.layer) || 0) - (Number(right?.layer) || 0));
        const previousSignature = JSON.stringify({
          roomLayers: chunkValue.roomLayers || [],
          instances: chunkValue.instances || [],
        });
        const nextSignature = JSON.stringify({
          roomLayers: nextRoomLayers,
          instances: nextInstances,
        });
        if (previousSignature === nextSignature) {
          continue;
        }
        touchWorldChunkCacheEntry(chunkKey, {
          ...cloneValue(chunkValue),
          roomLayers: nextRoomLayers,
          instances: nextInstances,
        });
        worldRuntimeState.dirtyChunkKeys.add(chunkKey);
        changed = true;
      }
      if (changed) {
        scope.refreshWorldOverviewWindow?.();
      }
      return changed;
    }

    function syncWorldChunkCellFromLocalTile(layerNumber, localTileX, localTileY, storedChar) {
      if (!isWorldModeActive()) {
        return false;
      }
      const worldTileX = worldRuntimeState.tileOffsetX + Math.floor(Number(localTileX) || 0);
      const worldTileY = worldRuntimeState.tileOffsetY + Math.floor(Number(localTileY) || 0);
      const chunkX = worldToChunkCoord(worldTileX, worldRuntimeState.chunkWidth);
      const chunkY = worldToChunkCoord(worldTileY, worldRuntimeState.chunkHeight);
      const chunkKey = buildChunkKey(chunkX, chunkY);
      const cachedChunk = worldRuntimeState.chunkCache.get(chunkKey);
      if (!cachedChunk) {
        return false;
      }
      const localX = worldToLocalCoord(worldTileX, worldRuntimeState.chunkWidth);
      const localY = worldToLocalCoord(worldTileY, worldRuntimeState.chunkHeight);
      const safeLayerNumber = Number(layerNumber) || 0;
      const fillChar = safeLayerNumber === 0 ? "." : " ";
      let layerEntry = Array.isArray(cachedChunk.roomLayers)
        ? cachedChunk.roomLayers.find((layer) => Number(layer?.layer) === safeLayerNumber)
        : null;
      if (!layerEntry) {
        layerEntry = {
          layer: safeLayerNumber,
          rows: createFilledRows(cachedChunk.width || worldRuntimeState.chunkWidth, cachedChunk.height || worldRuntimeState.chunkHeight, fillChar),
          instanceIds: [],
        };
        if (!Array.isArray(cachedChunk.roomLayers)) {
          cachedChunk.roomLayers = [];
        }
        cachedChunk.roomLayers.push(layerEntry);
        cachedChunk.roomLayers.sort((left, right) => (Number(left?.layer) || 0) - (Number(right?.layer) || 0));
      }
      const targetRows = Array.isArray(layerEntry.rows)
        ? layerEntry.rows.map((row) => String(row || ""))
        : createFilledRows(cachedChunk.width || worldRuntimeState.chunkWidth, cachedChunk.height || worldRuntimeState.chunkHeight, fillChar);
      const safeWidth = Math.max(1, Number(cachedChunk.width) || worldRuntimeState.chunkWidth);
      while (targetRows.length <= localY) {
        targetRows.push(String(fillChar || " ").repeat(safeWidth));
      }
      const existingRow = String(targetRows[localY] || "").padEnd(safeWidth, fillChar).slice(0, safeWidth);
      targetRows[localY] = existingRow.slice(0, localX) + String(storedChar || fillChar).charAt(0) + existingRow.slice(localX + 1);
      layerEntry.rows = targetRows;
      touchWorldChunkCacheEntry(chunkKey, cachedChunk);
      worldRuntimeState.dirtyChunkKeys.add(chunkKey);
      scope.invalidateWorldOverviewChunkSurfaces?.([chunkKey]);
      scope.refreshWorldOverviewWindow?.();
      return true;
    }
    const popupSessionStore = createPopupSessionStore({
      activeLayer: 1,
      viewingAllLayers: false,
      visibleLayersById: {},
      activeSidebarTab: "layers",
      pan: { isPanning: false, startX: 0, startY: 0, scrollLeft: 0, scrollTop: 0 },
      draggingNpc: null,
      pointerCandidate: null,
      paintingStroke: null,
      dragDrawX: 0,
      dragDrawY: 0,
      isSaving: false,
      activeBrushTileId: "",
      activeGraphicsTab: "tiles",
      activeGraphicsRecordId: "",
      canvasToolMode: "paint",
      activeInstanceBrushId: "",
      activeEntityCategory: "friendly",
      hoverTileX: -1,
      hoverTileY: -1,
      selectedNpcId: mapDocument.npcOverlays[0] ? String(mapDocument.npcOverlays[0].id || "") : "",
      selectedTile: null,
      spritePickerOpenNpcId: "",
      hoveredNpcId: "",
      templateSectionCollapsed: false,
      placedSectionCollapsed: false,
      organizedListDrag: null,
      tileMutationBatchDepth: 0,
      hideTileGrid: false,
      showChunkBounds: false,
      zoomPreviewUntil: 0,
      scrollPreviewUntil: 0,
      hoverCanvasX: 0,
      hoverCanvasY: 0,
      editingTargetKind: "room",
      activeHeightLayerId: "",
    });
    popupSessionStore.restorePersistedLayout(window);
    const editorLogEntries = [];
    const EDITOR_LOG_LIMIT = 500;
    let statusLogWindowController = null;

    function formatEditorLogTimestamp(timestamp) {
      try {
        return new Date(timestamp).toLocaleString();
      } catch {
        return String(timestamp || "");
      }
    }

    function appendEditorLogEntry(level, message) {
      const normalizedMessage = String(message || "").trim();
      if (!normalizedMessage) {
        return null;
      }
      const timestamp = Date.now();
      const entry = {
        id: runtimeUniqueId(),
        timestamp,
        timestampLabel: formatEditorLogTimestamp(timestamp),
        level: String(level || "Information").trim() || "Information",
        message: normalizedMessage,
      };
      editorLogEntries.push(entry);
      while (editorLogEntries.length > EDITOR_LOG_LIMIT) {
        editorLogEntries.shift();
      }
      statusLogWindowController?.refresh?.();
      return entry;
    }

    function getEditorLogEntries() {
      return editorLogEntries.slice();
    }

    function clearEditorLogEntries() {
      editorLogEntries.splice(0, editorLogEntries.length);
      statusLogWindowController?.refresh?.();
    }

    window.addEventListener("error", (event) => {
      const message = String(event?.message || event?.error?.message || "Unknown runtime error");
      appendEditorLogEntry("Error", message);
    });
    window.addEventListener("unhandledrejection", (event) => {
      const reason = event?.reason;
      const message = typeof reason === "string"
        ? reason
        : String(reason?.message || reason || "Unhandled promise rejection");
      appendEditorLogEntry("Error", message);
    });
    let renderController = null;
    const documentController = createMapDocumentController({
      mapId: currentMapId,
      getMapId: () => currentMapId,
      mapDocument,
      popupSessionStore,
      baseRows: currentBaseRows,
      getBaseRows: () => currentBaseRows,
      baseTileSize,
      normalizeBackgroundTileId,
      normalizeMapBackgroundColor,
      onMapNameUpdated: syncDocumentTitle,
      invalidateTileSurface: () => {
        if (renderController && typeof renderController.invalidateTileSurface === "function") {
          renderController.invalidateTileSurface("document-controller");
        }
      },
    });
    let editorSettingsState = normalizeEditorSettings(initialEditorSettings);

    // ── AtTooltip: reusable anchored floating context menu ──────────────
    const atTooltip = createAtTooltip();

    const initialEditorUiState = bootstrap.editorUi;
    const editorUiStore = createEditorUiStore(initialEditorUiState);
    const historyState = createHistoryStateStore();
    let currentHistoryStorageKey = deriveHistoryStorageKey(currentMapId);
    const popupBoundsStorageKey = WORLDSHAPER_STUDIO_BOUNDS_STORAGE_KEY;

    function runtimeEscapeHtml(value) {
      return String(value || "")
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/\"/g, "&quot;")
        .replace(/'/g, "&#39;");
    }

    function getActiveThemePreset() {
      return normalizeWorldshaperThemePreset(editorSettingsState?.worldshaperStudio?.themePreset || DEFAULT_WORLDSHAPER_THEME_PRESET);
    }

    function getEditorEngineOverrides() {
      return normalizeEngineOverrideEntries(editorSettingsState?.worldshaperStudio?.engineOverrides);
    }

    function getEffectiveHeightBlurStep() {
      const overrideValue = getEngineOverrideValue(getEditorEngineOverrides(), "heightBlurStep", null);
      if (typeof overrideValue === "number" && Number.isFinite(overrideValue)) {
        return Math.max(0, Math.min(1, Number(overrideValue) || 0.1));
      }
      return Math.max(0, Math.min(1, Number(mapDocument.heightBlurStep ?? mapDocument.heightDetailStep) || 0.1));
    }

    function isRendererDebugEnabled() {
      const overrideValue = getEngineOverrideValue(getEditorEngineOverrides(), "rendererDebug", null);
      if (typeof overrideValue === "boolean") {
        return overrideValue;
      }
      return false;
    }

    function refreshEditorEngineOverridesUi() {
      scope.refreshEngineOverrideSummary?.();
      scope.refreshEngineOverrideWindow?.();
      renderController?.refreshRendererDebugState?.();
      drawNow();
    }

    async function saveEditorEngineOverrides(nextEntries) {
      const requestedEntries = normalizeEngineOverrideEntries(nextEntries);
      editorSettingsState = await persistEditorSettings(apiBase, {
        ...editorSettingsState,
        worldshaperStudio: {
          ...editorSettingsState.worldshaperStudio,
          engineOverrides: requestedEntries,
        },
      });
      const persistedEntries = getEditorEngineOverrides();
      const requestedSignature = JSON.stringify(requestedEntries);
      const persistedSignature = JSON.stringify(persistedEntries);
      if (requestedSignature !== persistedSignature) {
        throw new Error("Engine overrides were not persisted by the API. Restart the API server and try again.");
      }
      refreshEditorEngineOverridesUi();
      return persistedEntries;
    }

    function refreshThemePresetButtons() {
      const activePreset = getActiveThemePreset();
      themePresetButtons.forEach((button) => {
        const presetId = normalizeWorldshaperThemePreset(button.getAttribute("data-theme-preset") || "");
        button.classList.toggle("active", presetId === activePreset);
        button.setAttribute("aria-pressed", presetId === activePreset ? "true" : "false");
      });
    }

    async function saveThemePreset(nextPreset) {
      editorSettingsState = await persistEditorSettings(apiBase, {
        ...editorSettingsState,
        worldshaperStudio: {
          ...editorSettingsState.worldshaperStudio,
          themePreset: nextPreset,
        },
      });
      refreshThemePresetButtons();
    }

    function applyThemePreset(nextPreset, options) {
      const normalizedPreset = normalizeWorldshaperThemePreset(nextPreset);
      editorSettingsState = normalizeEditorSettings({
        ...editorSettingsState,
        worldshaperStudio: {
          ...editorSettingsState.worldshaperStudio,
          themePreset: normalizedPreset,
        },
      });
      applyWorldshaperThemePreset(normalizedPreset);
      refreshThemePresetButtons();
      if (!(options && options.silent)) {
        setStatus("Theme switched to " + getWorldshaperThemeLabel(normalizedPreset) + ".", false);
      }
      if (!(options && options.persist === false)) {
        void saveThemePreset(normalizedPreset).catch((error) => {
          setStatus(String(error), true);
        });
      }
      return normalizedPreset;
    }

    function cloneLayers(source) {
      return source.map((layer) => ({
        layer: Number(layer.layer) || 0,
        name: typeof layer.name === "string" && layer.name.trim() ? layer.name.trim() : undefined,
        rows: Array.isArray(layer.rows) ? layer.rows.map((row) => String(row || "")) : [],
        instanceIds: Array.isArray(layer.instanceIds) ? layer.instanceIds.map((id) => String(id || "").trim()).filter(Boolean) : [],
      }));
    }

    function cloneHeightLayers(source) {
      return documentController.cloneHeightLayers(source);
    }

    function getNeighborhoodCacheKey(centerChunkX, centerChunkY, radiusOverride) {
      const radius = Math.max(0, Math.floor(Number(radiusOverride) || worldRuntimeState.chunkRadius));
      return buildChunkKey(centerChunkX, centerChunkY) + ":r" + radius;
    }

    function buildNeighborhoodChunkCoords(centerChunkX, centerChunkY, radiusOverride) {
      const coords = [];
      const radius = Math.max(0, Math.floor(Number(radiusOverride) || worldRuntimeState.chunkRadius));
      for (let chunkY = centerChunkY - radius; chunkY <= centerChunkY + radius; chunkY += 1) {
        for (let chunkX = centerChunkX - radius; chunkX <= centerChunkX + radius; chunkX += 1) {
          coords.push({
            chunkX: Math.floor(Number(chunkX) || 0),
            chunkY: Math.floor(Number(chunkY) || 0),
          });
        }
      }
      return coords;
    }

    function cacheWorldChunks(chunks) {
      (Array.isArray(chunks) ? chunks : []).forEach((chunk) => {
        if (!chunk || typeof chunk !== "object" || Array.isArray(chunk)) {
          return;
        }
        const chunkX = Math.floor(Number(chunk?.chunkX) || 0);
        const chunkY = Math.floor(Number(chunk?.chunkY) || 0);
        const chunkKey = buildChunkKey(chunkX, chunkY);
        if (worldRuntimeState.dirtyChunkKeys.has(chunkKey) && worldRuntimeState.chunkCache.has(chunkKey)) {
          return;
        }
        touchWorldChunkCacheEntry(chunkKey, normalizeCachedWorldChunkPayload(chunk, chunkX, chunkY));
      });
      pruneWorldChunkCache();
    }

    function completeWorldNeighborhoodChunks(centerChunkX, centerChunkY, radiusOverride, sourceChunks) {
      const chunkMap = new Map();
      (Array.isArray(sourceChunks) ? sourceChunks : []).forEach((chunk) => {
        if (!chunk || typeof chunk !== "object" || Array.isArray(chunk)) {
          return;
        }
        const safeChunkX = Math.floor(Number(chunk?.chunkX) || 0);
        const safeChunkY = Math.floor(Number(chunk?.chunkY) || 0);
        chunkMap.set(
          buildChunkKey(safeChunkX, safeChunkY),
          normalizeCachedWorldChunkPayload(chunk, safeChunkX, safeChunkY),
        );
      });
      return buildNeighborhoodChunkCoords(centerChunkX, centerChunkY, radiusOverride)
        .map((coord) => {
          const chunkKey = buildChunkKey(coord.chunkX, coord.chunkY);
          const payload = chunkMap.get(chunkKey)
            || worldRuntimeState.chunkCache.get(chunkKey)
            || createEmptyWorldChunkPayload(coord.chunkX, coord.chunkY);
          return normalizeCachedWorldChunkPayload(payload, coord.chunkX, coord.chunkY);
        });
    }

    function syncCachedWorldHeightLayerMetadata() {
      if (!isWorldModeActive()) {
        return false;
      }
      const metadataById = new Map(
        (Array.isArray(mapDocument.heightLayers) ? mapDocument.heightLayers : [])
          .map((entry) => {
            const heightLayerId = String(entry?.id || "").trim();
            if (!heightLayerId) {
              return null;
            }
            return [heightLayerId, {
              id: heightLayerId,
              name: typeof entry?.name === "string" && entry.name.trim() ? entry.name.trim() : undefined,
              z: Math.max(1, Number(entry?.z) || 1),
            }];
          })
          .filter(Boolean),
      );
      const nextEntries = [];
      for (const [chunkKey, chunkValue] of worldRuntimeState.chunkCache.entries()) {
        if (!chunkValue || typeof chunkValue !== "object" || Array.isArray(chunkValue)) {
          continue;
        }
        const nextHeightLayers = (Array.isArray(chunkValue.heightLayers) ? chunkValue.heightLayers : [])
          .map((entry) => {
            const heightLayerId = String(entry?.id || "").trim();
            const metadata = metadataById.get(heightLayerId);
            if (!metadata) {
              return null;
            }
            return {
              ...cloneValue(entry),
              id: metadata.id,
              name: metadata.name,
              z: metadata.z,
            };
          })
          .filter(Boolean);
        nextEntries.push([chunkKey, {
          ...cloneValue(chunkValue),
          heightLayers: nextHeightLayers,
        }]);
      }
      nextEntries.forEach(([chunkKey, chunkValue]) => {
        const previousValue = worldRuntimeState.chunkCache.get(chunkKey);
        touchWorldChunkCacheEntry(chunkKey, chunkValue);
        if (JSON.stringify(previousValue?.heightLayers || []) !== JSON.stringify(chunkValue?.heightLayers || [])) {
          worldRuntimeState.dirtyChunkKeys.add(chunkKey);
        }
      });
      scope.refreshWorldOverviewWindow?.();
      return true;
    }

    function getCachedNeighborhoodChunks(centerChunkX, centerChunkY, radiusOverride) {
      const coords = buildNeighborhoodChunkCoords(centerChunkX, centerChunkY, radiusOverride);
      const chunks = [];
      for (const coord of coords) {
        const chunk = worldRuntimeState.chunkCache.get(buildChunkKey(coord.chunkX, coord.chunkY));
        if (!chunk) {
          return null;
        }
        touchWorldChunkCacheEntry(buildChunkKey(coord.chunkX, coord.chunkY), chunk);
        chunks.push(chunk);
      }
      return chunks;
    }

    async function requestWorldNeighborhood(centerChunkX, centerChunkY, options) {
      const config = options && typeof options === "object" ? options : {};
      const safeCenterChunkX = Math.floor(Number(centerChunkX) || 0);
      const safeCenterChunkY = Math.floor(Number(centerChunkY) || 0);
      const requestedRadius = Math.max(0, Math.floor(Number(config.radius) || worldRuntimeState.chunkRadius));
      const requestKey = getNeighborhoodCacheKey(safeCenterChunkX, safeCenterChunkY, requestedRadius);
      if (worldRuntimeState.pendingNeighborhoodFetches.has(requestKey)) {
        return worldRuntimeState.pendingNeighborhoodFetches.get(requestKey);
      }
      const requestUrl = new URL(`/api/world/${encodeURIComponent(worldRuntimeState.worldId)}/chunks`, apiBase || window.location.origin);
      requestUrl.searchParams.set("chunkX", String(safeCenterChunkX));
      requestUrl.searchParams.set("chunkY", String(safeCenterChunkY));
      requestUrl.searchParams.set("radius", String(requestedRadius));
      requestUrl.searchParams.set("createIfMissing", config.createIfMissing === true ? "1" : "0");
      const requestPromise = fetchJsonOrThrow(requestUrl.toString())
        .then((payload) => {
          const nextDefaultBackgroundTileId = String(payload?.world?.defaultBackgroundTileId || "").trim();
          if (nextDefaultBackgroundTileId) {
            worldRuntimeState.defaultBackgroundTileId = nextDefaultBackgroundTileId;
          }
          if (payload?.world) {
            worldRuntimeState.heightBlurStep = Math.max(0, Math.min(1, Number(payload.world.heightBlurStep ?? payload.world.heightDetailStep) || worldRuntimeState.heightBlurStep || 0.1));
          }
          const completedChunks = completeWorldNeighborhoodChunks(
            safeCenterChunkX,
            safeCenterChunkY,
            requestedRadius,
            payload?.chunks,
          );
          cacheWorldChunks(completedChunks);
          return {
            ...payload,
            chunks: completedChunks,
          };
        })
        .finally(() => {
          worldRuntimeState.pendingNeighborhoodFetches.delete(requestKey);
        });
      worldRuntimeState.pendingNeighborhoodFetches.set(requestKey, requestPromise);
      return requestPromise;
    }

    async function ensureWorldChunkCachedForEdit(chunkX, chunkY) {
      const safeChunkX = Math.floor(Number(chunkX) || 0);
      const safeChunkY = Math.floor(Number(chunkY) || 0);
      const existingChunk = getCachedWorldChunk(safeChunkX, safeChunkY);
      if (existingChunk) {
        return existingChunk;
      }
      await requestWorldNeighborhood(safeChunkX, safeChunkY, {
        createIfMissing: false,
        radius: 0,
      });
      const hydratedChunk = getCachedWorldChunk(safeChunkX, safeChunkY);
      if (hydratedChunk) {
        return hydratedChunk;
      }
      const emptyChunk = normalizeCachedWorldChunkPayload(
        createEmptyWorldChunkPayload(safeChunkX, safeChunkY),
        safeChunkX,
        safeChunkY,
      );
      touchWorldChunkCacheEntry(buildChunkKey(safeChunkX, safeChunkY), emptyChunk);
      return emptyChunk;
    }

    function normalizeWorldChunkRows(rows, width, height, fillChar) {
      const safeWidth = Math.max(1, Math.floor(Number(width) || 1));
      const safeHeight = Math.max(1, Math.floor(Number(height) || 1));
      return Array.from({ length: safeHeight }, (_entry, rowIndex) => {
        const sourceRow = String((Array.isArray(rows) ? rows[rowIndex] : "") || "");
        return sourceRow.length >= safeWidth
          ? sourceRow.slice(0, safeWidth)
          : (sourceRow + String(fillChar || " ").repeat(Math.max(0, safeWidth - sourceRow.length)));
      });
    }

    function cloneWorldChunkHeightLayers(source) {
      return (Array.isArray(source) ? source : [])
        .map((entry, index) => ({
          id: String(entry?.id || `height_patch_${index + 1}`).trim() || `height_patch_${index + 1}`,
          name: typeof entry?.name === "string" && entry.name.trim() ? entry.name.trim() : undefined,
          z: Math.max(1, Math.floor(Number(entry?.z) || 1)),
          x: Math.max(0, Math.floor(Number(entry?.x) || 0)),
          y: Math.max(0, Math.floor(Number(entry?.y) || 0)),
          rows: Array.isArray(entry?.rows) ? entry.rows.map((row) => String(row || "")) : [],
        }))
        .filter((entry) => entry.id);
    }

    function buildWorldChunkLayerInstanceIds(roomLayers, instances, width, height) {
      const safeWidth = Math.max(1, Math.floor(Number(width) || 1));
      const safeHeight = Math.max(1, Math.floor(Number(height) || 1));
      const nextLayers = new Map();
      (Array.isArray(roomLayers) ? roomLayers : []).forEach((layer) => {
        const layerNumber = Math.max(0, Math.floor(Number(layer?.layer) || 0));
        nextLayers.set(layerNumber, {
          layer: layerNumber,
          name: typeof layer?.name === "string" && layer.name.trim() ? layer.name.trim() : undefined,
          rows: normalizeWorldChunkRows(layer?.rows, safeWidth, safeHeight, layerNumber === 0 ? "." : " "),
          instanceIds: [],
        });
      });
      if (!nextLayers.has(0)) {
        nextLayers.set(0, {
          layer: 0,
          rows: normalizeWorldChunkRows([], safeWidth, safeHeight, "."),
          instanceIds: [],
        });
      }
      if (!Array.from(nextLayers.keys()).some((layerNumber) => layerNumber > 0)) {
        nextLayers.set(1, {
          layer: 1,
          rows: normalizeWorldChunkRows([], safeWidth, safeHeight, " "),
          instanceIds: [],
        });
      }
      (Array.isArray(instances) ? instances : []).forEach((entry) => {
        const layerNumber = Math.max(0, Math.floor(Number(entry?.layer) || 0));
        const instanceId = String(entry?.id || "").trim();
        if (!instanceId) {
          return;
        }
        if (!nextLayers.has(layerNumber)) {
          nextLayers.set(layerNumber, {
            layer: layerNumber,
            rows: normalizeWorldChunkRows([], safeWidth, safeHeight, layerNumber === 0 ? "." : " "),
            instanceIds: [],
          });
        }
        nextLayers.get(layerNumber).instanceIds.push(instanceId);
      });
      return Array.from(nextLayers.values())
        .map((entry) => ({
          ...entry,
          instanceIds: Array.from(new Set((Array.isArray(entry.instanceIds) ? entry.instanceIds : []).map((id) => String(id || "").trim()).filter(Boolean))),
        }))
        .sort((left, right) => (Number(left.layer) || 0) - (Number(right.layer) || 0));
    }

    function normalizeWorldChunkInstances(sourceInstances, chunkX, chunkY, width, height, options) {
      const config = options && typeof options === "object" ? options : {};
      const duplicateIds = config.duplicateIds === true;
      const safeChunkX = Math.floor(Number(chunkX) || 0);
      const safeChunkY = Math.floor(Number(chunkY) || 0);
      const safeWidth = Math.max(1, Math.floor(Number(width) || 1));
      const safeHeight = Math.max(1, Math.floor(Number(height) || 1));
      return (Array.isArray(sourceInstances) ? sourceInstances : [])
        .map((entry) => {
          const record = entry?.record && typeof entry.record === "object" && !Array.isArray(entry.record)
            ? cloneValue(entry.record)
            : {};
          const nextId = duplicateIds
            ? runtimeUniqueId()
            : (String(entry?.id || record?.id || runtimeUniqueId()).trim() || runtimeUniqueId());
          const nextLayer = Math.max(0, Math.floor(Number(entry?.layer ?? record?.layer) || 0));
          const nextX = Math.max(0, Math.min(safeWidth - 1, Math.floor(Number(entry?.x) || 0)));
          const nextY = Math.max(0, Math.min(safeHeight - 1, Math.floor(Number(entry?.y) || 0)));
          const nextTemplateId = String(entry?.templateId || record?.templateId || "").trim();
          record.id = nextId;
          record.layer = nextLayer;
          record.templateId = nextTemplateId;
          record.position = {
            x: (safeChunkX * safeWidth) + nextX,
            y: (safeChunkY * safeHeight) + nextY,
          };
          return {
            id: nextId,
            templateId: nextTemplateId,
            layer: nextLayer,
            x: nextX,
            y: nextY,
            record,
          };
        })
        .filter((entry) => entry.id);
    }

    function createEmptyWorldChunkPayload(chunkX, chunkY) {
      const safeChunkX = Math.floor(Number(chunkX) || 0);
      const safeChunkY = Math.floor(Number(chunkY) || 0);
      const chunkWidth = Math.max(1, Number(worldRuntimeState.chunkWidth) || 32);
      const chunkHeight = Math.max(1, Number(worldRuntimeState.chunkHeight) || 32);
      return {
        schemaVersion: 1,
        worldId: String(worldRuntimeState.worldId || currentMapId || "").trim(),
        chunkX: safeChunkX,
        chunkY: safeChunkY,
        width: chunkWidth,
        height: chunkHeight,
        backgroundTileId: "",
        roomLayers: [
          {
            layer: 0,
            rows: Array.from({ length: chunkHeight }, () => ".".repeat(chunkWidth)),
            instanceIds: [],
          },
          {
            layer: 1,
            rows: Array.from({ length: chunkHeight }, () => " ".repeat(chunkWidth)),
            instanceIds: [],
          },
        ],
        heightLayers: [],
        instances: [],
      };
    }

    function normalizeCachedWorldChunkPayload(chunkPayload, chunkX, chunkY, options) {
      const safeChunkX = Math.floor(Number(chunkX ?? chunkPayload?.chunkX) || 0);
      const safeChunkY = Math.floor(Number(chunkY ?? chunkPayload?.chunkY) || 0);
      const safeWidth = Math.max(1, Math.floor(Number(chunkPayload?.width) || Number(worldRuntimeState.chunkWidth) || 32));
      const safeHeight = Math.max(1, Math.floor(Number(chunkPayload?.height) || Number(worldRuntimeState.chunkHeight) || 32));
      const instances = normalizeWorldChunkInstances(chunkPayload?.instances, safeChunkX, safeChunkY, safeWidth, safeHeight, options);
      const roomLayers = buildWorldChunkLayerInstanceIds(chunkPayload?.roomLayers, instances, safeWidth, safeHeight);
      return {
        schemaVersion: Math.max(1, Math.floor(Number(chunkPayload?.schemaVersion) || 1)),
        worldId: String(chunkPayload?.worldId || worldRuntimeState.worldId || currentMapId || "").trim(),
        chunkX: safeChunkX,
        chunkY: safeChunkY,
        width: safeWidth,
        height: safeHeight,
        backgroundTileId: String(chunkPayload?.backgroundTileId || "").trim(),
        roomLayers,
        heightLayers: cloneWorldChunkHeightLayers(chunkPayload?.heightLayers),
        instances,
      };
    }

    function isChunkFillSymbol(ch, fillChar) {
      const symbol = String(ch || "").charAt(0);
      return !symbol || symbol === fillChar || symbol === "." || symbol === " ";
    }

    function isWorldChunkPayloadEmpty(chunkPayload) {
      const normalized = normalizeCachedWorldChunkPayload(chunkPayload, chunkPayload?.chunkX, chunkPayload?.chunkY);
      if (String(normalized?.backgroundTileId || "").trim()) {
        return false;
      }
      if (Array.isArray(normalized?.instances) && normalized.instances.length > 0) {
        return false;
      }
      if ((Array.isArray(normalized?.heightLayers) ? normalized.heightLayers : []).some((entry) => (
        Array.isArray(entry?.rows) && entry.rows.some((row) => /[^ .]/.test(String(row || "")))
      ))) {
        return false;
      }
      return !(Array.isArray(normalized?.roomLayers) ? normalized.roomLayers : []).some((layer) => {
        const fillChar = (Number(layer?.layer) || 0) === 0 ? "." : " ";
        return (Array.isArray(layer?.rows) ? layer.rows : []).some((row) => {
          const sourceRow = String(row || "");
          for (let index = 0; index < sourceRow.length; index += 1) {
            if (!isChunkFillSymbol(sourceRow.charAt(index), fillChar)) {
              return true;
            }
          }
          return false;
        });
      });
    }

    function transformChunkLocalCoord(localX, localY, width, height, operation) {
      const safeX = Math.floor(Number(localX) || 0);
      const safeY = Math.floor(Number(localY) || 0);
      const safeWidth = Math.max(1, Math.floor(Number(width) || 1));
      const safeHeight = Math.max(1, Math.floor(Number(height) || 1));
      switch (String(operation || "").trim()) {
        case "flipHorizontal":
          return { x: (safeWidth - 1) - safeX, y: safeY };
        case "flipVertical":
          return { x: safeX, y: (safeHeight - 1) - safeY };
        case "rotate180":
          return { x: (safeWidth - 1) - safeX, y: (safeHeight - 1) - safeY };
        case "rotate90cw":
          if (safeWidth !== safeHeight) {
            return null;
          }
          return { x: (safeWidth - 1) - safeY, y: safeX };
        case "rotate90ccw":
          if (safeWidth !== safeHeight) {
            return null;
          }
          return { x: safeY, y: (safeHeight - 1) - safeX };
        default:
          return { x: safeX, y: safeY };
      }
    }

    function transformChunkRows(rows, width, height, fillChar, operation) {
      const safeWidth = Math.max(1, Math.floor(Number(width) || 1));
      const safeHeight = Math.max(1, Math.floor(Number(height) || 1));
      const sourceRows = normalizeWorldChunkRows(rows, safeWidth, safeHeight, fillChar);
      const nextRows = Array.from({ length: safeHeight }, () => Array.from({ length: safeWidth }, () => String(fillChar || " ").charAt(0) || " "));
      for (let rowIndex = 0; rowIndex < safeHeight; rowIndex += 1) {
        const sourceRow = sourceRows[rowIndex];
        for (let columnIndex = 0; columnIndex < safeWidth; columnIndex += 1) {
          const char = String(sourceRow.charAt(columnIndex) || fillChar).charAt(0) || String(fillChar || " ").charAt(0) || " ";
          if (isChunkFillSymbol(char, fillChar)) {
            continue;
          }
          const nextCoord = transformChunkLocalCoord(columnIndex, rowIndex, safeWidth, safeHeight, operation);
          if (!nextCoord) {
            continue;
          }
          nextRows[nextCoord.y][nextCoord.x] = char;
        }
      }
      return nextRows.map((row) => row.join(""));
    }

    function transformChunkHeightPatch(patch, width, height, operation) {
      const safeWidth = Math.max(1, Math.floor(Number(width) || 1));
      const safeHeight = Math.max(1, Math.floor(Number(height) || 1));
      const sourceRows = Array.isArray(patch?.rows) ? patch.rows.map((row) => String(row || "")) : [];
      const patchWidth = sourceRows.reduce((max, row) => Math.max(max, row.length), 0);
      const patchHeight = sourceRows.length;
      const transformedCells = [];
      for (let localY = 0; localY < patchHeight; localY += 1) {
        const row = sourceRows[localY] || "";
        for (let localX = 0; localX < patchWidth; localX += 1) {
          const char = String(row.charAt(localX) || " ").charAt(0) || " ";
          if (char === " " || char === ".") {
            continue;
          }
          const worldX = Math.max(0, Math.floor(Number(patch?.x) || 0)) + localX;
          const worldY = Math.max(0, Math.floor(Number(patch?.y) || 0)) + localY;
          if (worldX < 0 || worldY < 0 || worldX >= safeWidth || worldY >= safeHeight) {
            continue;
          }
          const nextCoord = transformChunkLocalCoord(worldX, worldY, safeWidth, safeHeight, operation);
          if (!nextCoord) {
            continue;
          }
          transformedCells.push({
            x: nextCoord.x,
            y: nextCoord.y,
            char,
          });
        }
      }
      if (transformedCells.length <= 0) {
        return null;
      }
      const minX = transformedCells.reduce((min, entry) => Math.min(min, entry.x), transformedCells[0].x);
      const maxX = transformedCells.reduce((max, entry) => Math.max(max, entry.x), transformedCells[0].x);
      const minY = transformedCells.reduce((min, entry) => Math.min(min, entry.y), transformedCells[0].y);
      const maxY = transformedCells.reduce((max, entry) => Math.max(max, entry.y), transformedCells[0].y);
      const nextRows = Array.from({ length: (maxY - minY) + 1 }, () => Array.from({ length: (maxX - minX) + 1 }, () => " "));
      transformedCells.forEach((entry) => {
        nextRows[entry.y - minY][entry.x - minX] = entry.char;
      });
      return {
        id: String(patch?.id || "").trim(),
        name: typeof patch?.name === "string" && patch.name.trim() ? patch.name.trim() : undefined,
        z: Math.max(1, Math.floor(Number(patch?.z) || 1)),
        x: minX,
        y: minY,
        rows: nextRows.map((row) => row.join("").replace(/\s+$/g, "")),
      };
    }

    function transformWorldChunkPayload(chunkPayload, operation, options) {
      const config = options && typeof options === "object" ? options : {};
      const normalized = normalizeCachedWorldChunkPayload(chunkPayload, chunkPayload?.chunkX, chunkPayload?.chunkY, config);
      const safeWidth = Math.max(1, Math.floor(Number(normalized?.width) || 1));
      const safeHeight = Math.max(1, Math.floor(Number(normalized?.height) || 1));
      const normalizedOperation = String(operation || "").trim();
      if ((normalizedOperation === "rotate90cw" || normalizedOperation === "rotate90ccw") && safeWidth !== safeHeight) {
        throw new Error("Chunk rotation requires square chunks.");
      }
      const instances = normalizeWorldChunkInstances(
        (Array.isArray(normalized.instances) ? normalized.instances : []).map((entry) => {
          const nextCoord = transformChunkLocalCoord(entry.x, entry.y, safeWidth, safeHeight, normalizedOperation);
          return {
            ...cloneValue(entry),
            x: nextCoord?.x ?? entry.x,
            y: nextCoord?.y ?? entry.y,
          };
        }),
        normalized.chunkX,
        normalized.chunkY,
        safeWidth,
        safeHeight,
        config,
      );
      const roomLayers = buildWorldChunkLayerInstanceIds(
        (Array.isArray(normalized.roomLayers) ? normalized.roomLayers : []).map((layer) => ({
          ...cloneValue(layer),
          rows: transformChunkRows(layer?.rows, safeWidth, safeHeight, (Number(layer?.layer) || 0) === 0 ? "." : " ", normalizedOperation),
        })),
        instances,
        safeWidth,
        safeHeight,
      );
      const heightLayers = cloneWorldChunkHeightLayers(normalized.heightLayers)
        .map((entry) => transformChunkHeightPatch(entry, safeWidth, safeHeight, normalizedOperation))
        .filter(Boolean)
        .sort((left, right) => {
          if ((Number(left?.z) || 0) !== (Number(right?.z) || 0)) {
            return (Number(left?.z) || 0) - (Number(right?.z) || 0);
          }
          return String(left?.name || left?.id || "").localeCompare(String(right?.name || right?.id || ""));
        });
      return {
        ...normalized,
        roomLayers,
        heightLayers,
        instances,
      };
    }

    function commitWorldChunkPayloads(nextChunks, reason) {
      const entries = Array.isArray(nextChunks) ? nextChunks : [];
      if (entries.length <= 0) {
        return false;
      }
      const touchedChunkKeys = [];
      entries.forEach((entry) => {
        const normalized = normalizeCachedWorldChunkPayload(entry, entry?.chunkX, entry?.chunkY);
        const chunkKey = buildChunkKey(normalized.chunkX, normalized.chunkY);
        touchedChunkKeys.push(chunkKey);
        touchWorldChunkCacheEntry(chunkKey, normalized);
        worldRuntimeState.dirtyChunkKeys.add(chunkKey);
      });
      worldRuntimeState.documentDirty = true;
      ensureWorldDocumentCurrent();
      invalidateTileSurface(reason || "world-chunk-mutation");
      refreshInformationPanel();
      draw();
      scope.refreshToolbarState?.();
      scope.invalidateWorldOverviewChunkSurfaces?.(touchedChunkKeys);
      scope.refreshWorldOverviewWindow?.();
      return true;
    }

    async function moveWorldChunkContent(sourceChunkX, sourceChunkY, targetChunkX, targetChunkY) {
      if (!isWorldModeActive()) {
        return { ok: false, reason: "world-mode-inactive" };
      }
      const safeSourceChunkX = Math.floor(Number(sourceChunkX) || 0);
      const safeSourceChunkY = Math.floor(Number(sourceChunkY) || 0);
      const safeTargetChunkX = Math.floor(Number(targetChunkX) || 0);
      const safeTargetChunkY = Math.floor(Number(targetChunkY) || 0);
      if (safeSourceChunkX === safeTargetChunkX && safeSourceChunkY === safeTargetChunkY) {
        setStatus("Move cancelled: choose a different destination chunk.", true);
        return { ok: false, reason: "same-chunk" };
      }
      const sourceChunk = normalizeCachedWorldChunkPayload(
        cloneValue(await ensureWorldChunkCachedForEdit(safeSourceChunkX, safeSourceChunkY)) || createEmptyWorldChunkPayload(safeSourceChunkX, safeSourceChunkY),
        safeSourceChunkX,
        safeSourceChunkY,
      );
      if (isWorldChunkPayloadEmpty(sourceChunk)) {
        setStatus("Move failed: source chunk is empty.", true);
        return { ok: false, reason: "source-empty" };
      }
      const destinationChunk = normalizeCachedWorldChunkPayload(
        cloneValue(await ensureWorldChunkCachedForEdit(safeTargetChunkX, safeTargetChunkY)) || createEmptyWorldChunkPayload(safeTargetChunkX, safeTargetChunkY),
        safeTargetChunkX,
        safeTargetChunkY,
      );
      if (!isWorldChunkPayloadEmpty(destinationChunk)) {
        setStatus("Move failed: destination chunk is not empty.", true);
        return { ok: false, reason: "destination-occupied" };
      }
      const movedChunk = normalizeCachedWorldChunkPayload(sourceChunk, safeTargetChunkX, safeTargetChunkY);
      const clearedSource = createEmptyWorldChunkPayload(safeSourceChunkX, safeSourceChunkY);
      commitWorldChunkPayloads([movedChunk, clearedSource], "world-chunk-move");
      registerHistory(
        "Chunk moved",
        safeSourceChunkX + "," + safeSourceChunkY,
        safeTargetChunkX + "," + safeTargetChunkY,
        [
          "Source: " + safeSourceChunkX + "," + safeSourceChunkY,
          "Destination: " + safeTargetChunkX + "," + safeTargetChunkY,
        ],
      );
      setStatus("Moved chunk " + safeSourceChunkX + "," + safeSourceChunkY + " to " + safeTargetChunkX + "," + safeTargetChunkY + ".", false);
      return {
        ok: true,
        sourceChunkKey: buildChunkKey(safeSourceChunkX, safeSourceChunkY),
        targetChunkKey: buildChunkKey(safeTargetChunkX, safeTargetChunkY),
      };
    }

    async function duplicateWorldChunkContent(sourceChunkX, sourceChunkY, targetChunkX, targetChunkY) {
      if (!isWorldModeActive()) {
        return { ok: false, reason: "world-mode-inactive" };
      }
      const safeSourceChunkX = Math.floor(Number(sourceChunkX) || 0);
      const safeSourceChunkY = Math.floor(Number(sourceChunkY) || 0);
      const safeTargetChunkX = Math.floor(Number(targetChunkX) || 0);
      const safeTargetChunkY = Math.floor(Number(targetChunkY) || 0);
      if (safeSourceChunkX === safeTargetChunkX && safeSourceChunkY === safeTargetChunkY) {
        setStatus("Duplicate cancelled: choose a different destination chunk.", true);
        return { ok: false, reason: "same-chunk" };
      }
      const sourceChunk = normalizeCachedWorldChunkPayload(
        cloneValue(await ensureWorldChunkCachedForEdit(safeSourceChunkX, safeSourceChunkY)) || createEmptyWorldChunkPayload(safeSourceChunkX, safeSourceChunkY),
        safeSourceChunkX,
        safeSourceChunkY,
      );
      if (isWorldChunkPayloadEmpty(sourceChunk)) {
        setStatus("Duplicate failed: source chunk is empty.", true);
        return { ok: false, reason: "source-empty" };
      }
      const destinationChunk = normalizeCachedWorldChunkPayload(
        cloneValue(await ensureWorldChunkCachedForEdit(safeTargetChunkX, safeTargetChunkY)) || createEmptyWorldChunkPayload(safeTargetChunkX, safeTargetChunkY),
        safeTargetChunkX,
        safeTargetChunkY,
      );
      if (!isWorldChunkPayloadEmpty(destinationChunk)) {
        setStatus("Duplicate failed: destination chunk is not empty.", true);
        return { ok: false, reason: "destination-occupied" };
      }
      const duplicatedChunk = normalizeCachedWorldChunkPayload({
        ...cloneValue(sourceChunk),
        instances: [],
      }, safeTargetChunkX, safeTargetChunkY);
      commitWorldChunkPayloads([duplicatedChunk], "world-chunk-duplicate");
      registerHistory(
        "Chunk duplicated",
        safeSourceChunkX + "," + safeSourceChunkY,
        safeTargetChunkX + "," + safeTargetChunkY,
        [
          "Source: " + safeSourceChunkX + "," + safeSourceChunkY,
          "Destination: " + safeTargetChunkX + "," + safeTargetChunkY,
          "Placed entities copied: no",
        ],
      );
      setStatus("Duplicated chunk " + safeSourceChunkX + "," + safeSourceChunkY + " into " + safeTargetChunkX + "," + safeTargetChunkY + ".", false);
      return {
        ok: true,
        sourceChunkKey: buildChunkKey(safeSourceChunkX, safeSourceChunkY),
        targetChunkKey: buildChunkKey(safeTargetChunkX, safeTargetChunkY),
      };
    }

    async function transformWorldChunkAt(chunkX, chunkY, operation) {
      if (!isWorldModeActive()) {
        return { ok: false, reason: "world-mode-inactive" };
      }
      const safeChunkX = Math.floor(Number(chunkX) || 0);
      const safeChunkY = Math.floor(Number(chunkY) || 0);
      const normalizedOperation = String(operation || "").trim();
      const sourceChunk = normalizeCachedWorldChunkPayload(
        cloneValue(await ensureWorldChunkCachedForEdit(safeChunkX, safeChunkY)) || createEmptyWorldChunkPayload(safeChunkX, safeChunkY),
        safeChunkX,
        safeChunkY,
      );
      if (isWorldChunkPayloadEmpty(sourceChunk)) {
        setStatus("Transform failed: chunk is empty.", true);
        return { ok: false, reason: "source-empty" };
      }
      const transformedChunk = transformWorldChunkPayload(sourceChunk, normalizedOperation);
      commitWorldChunkPayloads([transformedChunk], "world-chunk-transform");
      registerHistory(
        "Chunk transformed",
        safeChunkX + "," + safeChunkY,
        normalizedOperation,
        [
          "Chunk: " + safeChunkX + "," + safeChunkY,
          "Operation: " + normalizedOperation,
        ],
      );
      setStatus("Transformed chunk " + safeChunkX + "," + safeChunkY + ".", false);
      return {
        ok: true,
        chunkKey: buildChunkKey(safeChunkX, safeChunkY),
      };
    }

    async function clearWorldChunkAt(chunkX, chunkY) {
      if (!isWorldModeActive()) {
        return { ok: false, reason: "world-mode-inactive" };
      }
      const safeChunkX = Math.floor(Number(chunkX) || 0);
      const safeChunkY = Math.floor(Number(chunkY) || 0);
      const existingChunk = normalizeCachedWorldChunkPayload(
        cloneValue(await ensureWorldChunkCachedForEdit(safeChunkX, safeChunkY)) || createEmptyWorldChunkPayload(safeChunkX, safeChunkY),
        safeChunkX,
        safeChunkY,
      );
      if (isWorldChunkPayloadEmpty(existingChunk)) {
        setStatus("Chunk " + safeChunkX + "," + safeChunkY + " is already empty.", false);
        return { ok: false, reason: "already-empty" };
      }
      commitWorldChunkPayloads([createEmptyWorldChunkPayload(safeChunkX, safeChunkY)], "world-chunk-clear");
      registerHistory(
        "Chunk cleared",
        safeChunkX + "," + safeChunkY,
        "empty",
        [
          "Chunk: " + safeChunkX + "," + safeChunkY,
        ],
      );
      setStatus("Cleared chunk " + safeChunkX + "," + safeChunkY + ".", false);
      return {
        ok: true,
        chunkKey: buildChunkKey(safeChunkX, safeChunkY),
      };
    }

    async function applyWorldChunkBackgroundTileAt(chunkX, chunkY, nextBackgroundTileId) {
      if (!isWorldModeActive()) {
        return false;
      }
      const safeChunkX = Math.floor(Number(chunkX) || 0);
      const safeChunkY = Math.floor(Number(chunkY) || 0);
      const chunkWidth = Math.max(1, Number(worldRuntimeState.chunkWidth) || 32);
      const chunkHeight = Math.max(1, Number(worldRuntimeState.chunkHeight) || 32);
      const worldBackgroundTileId = String(worldRuntimeState.defaultBackgroundTileId || mapDocument.backgroundTileId || "").trim();
      const normalizedBackgroundTileId = String(nextBackgroundTileId == null ? "" : normalizeBackgroundTileId(nextBackgroundTileId)).trim();
      const storedBackgroundTileId = normalizedBackgroundTileId && normalizedBackgroundTileId !== worldBackgroundTileId
        ? normalizedBackgroundTileId
        : "";
      const chunkKey = buildChunkKey(safeChunkX, safeChunkY);
      const existingChunk = cloneValue(await ensureWorldChunkCachedForEdit(safeChunkX, safeChunkY)) || {
        chunkX: safeChunkX,
        chunkY: safeChunkY,
        width: chunkWidth,
        height: chunkHeight,
        backgroundTileId: "",
        roomLayers: [],
        heightLayers: [],
        instances: [],
      };
      const baseLayerRows = Array.isArray(existingChunk?.roomLayers)
        ? ((existingChunk.roomLayers.find((entry) => Number(entry?.layer) === 0) || {}).rows || [])
        : [];
      const normalizedBaseRows = Array.from({ length: chunkHeight }, (_entry, rowIndex) => {
        const sourceRow = String(baseLayerRows[rowIndex] || "");
        return sourceRow.length >= chunkWidth
          ? sourceRow.slice(0, chunkWidth)
          : (sourceRow + ".".repeat(Math.max(0, chunkWidth - sourceRow.length)));
      });
      const hadExplicitBaseCells = normalizedBaseRows.some((row) => /[^.]/.test(String(row || "")));
      const currentStoredBackgroundTileId = String(existingChunk?.backgroundTileId || "").trim();
      if (currentStoredBackgroundTileId === storedBackgroundTileId && !hadExplicitBaseCells) {
        setStatus(
          storedBackgroundTileId
            ? ("Chunk " + safeChunkX + "," + safeChunkY + " already uses " + describeBrushTileId(storedBackgroundTileId) + ".")
            : ("Chunk " + safeChunkX + "," + safeChunkY + " already inherits the world background."),
          false,
        );
        return false;
      }
      const nextRoomLayers = Array.isArray(existingChunk?.roomLayers)
        ? cloneLayers(existingChunk.roomLayers)
        : [];
      let baseLayer = nextRoomLayers.find((entry) => Number(entry?.layer) === 0) || null;
      if (!baseLayer) {
        baseLayer = {
          layer: 0,
          rows: [],
          instanceIds: [],
        };
        nextRoomLayers.push(baseLayer);
      }
      baseLayer.rows = Array.from({ length: chunkHeight }, () => ".".repeat(chunkWidth));
      const nextChunk = {
        ...existingChunk,
        chunkX: safeChunkX,
        chunkY: safeChunkY,
        width: chunkWidth,
        height: chunkHeight,
        backgroundTileId: storedBackgroundTileId,
        roomLayers: nextRoomLayers,
      };
      touchWorldChunkCacheEntry(chunkKey, nextChunk);
      worldRuntimeState.dirtyChunkKeys.add(chunkKey);
      worldRuntimeState.documentDirty = true;
      ensureWorldDocumentCurrent();
      invalidateTileSurface("world-overview-chunk-fill");
      refreshInformationPanel();
      draw();
      scope.invalidateWorldOverviewChunkSurfaces?.([chunkKey]);
      scope.refreshWorldOverviewWindow?.();
      registerHistory(
        storedBackgroundTileId ? "Chunk background filled" : "Chunk background restored",
        safeChunkX + "," + safeChunkY,
        storedBackgroundTileId ? describeBrushTileId(storedBackgroundTileId) : "world background",
        [
          "Chunk: " + safeChunkX + "," + safeChunkY,
          "Target: " + (storedBackgroundTileId ? describeBrushTileId(storedBackgroundTileId) : "world background"),
          "Cleared explicit base cells: " + (hadExplicitBaseCells ? "yes" : "no"),
        ],
      );
      setStatus(
        storedBackgroundTileId
          ? ("Filled chunk " + safeChunkX + "," + safeChunkY + " with " + describeBrushTileId(storedBackgroundTileId) + ".")
          : ("Restored chunk " + safeChunkX + "," + safeChunkY + " to the world background."),
        false,
      );
      return true;
    }

    function applyWorldNeighborhoodFromChunks(centerChunkX, centerChunkY, chunks, preservedWorldCenter, sourceReason, radiusOverride) {
      const safeCenterChunkX = Math.floor(Number(centerChunkX) || 0);
      const safeCenterChunkY = Math.floor(Number(centerChunkY) || 0);
      const safeRadius = Math.max(0, Math.floor(Number(radiusOverride) || worldRuntimeState.chunkRadius));
      const originChunkX = safeCenterChunkX - safeRadius;
      const originChunkY = safeCenterChunkY - safeRadius;
      const composedWidth = ((safeRadius * 2) + 1) * worldRuntimeState.chunkWidth;
      const composedHeight = ((safeRadius * 2) + 1) * worldRuntimeState.chunkHeight;
      const previousTileOffsetX = Math.floor(Number(worldRuntimeState.tileOffsetX) || 0);
      const previousTileOffsetY = Math.floor(Number(worldRuntimeState.tileOffsetY) || 0);
      const previousHoverTileX = Math.floor(Number(popupSessionStore.state.hoverTileX) || -1);
      const previousHoverTileY = Math.floor(Number(popupSessionStore.state.hoverTileY) || -1);
      const previousSelectedTile = popupSessionStore.state.selectedTile
        ? {
          ...popupSessionStore.state.selectedTile,
          x: Math.floor(Number(popupSessionStore.state.selectedTile.x) || 0),
          y: Math.floor(Number(popupSessionStore.state.selectedTile.y) || 0),
        }
        : null;
      const roomLayers = composeWorldRoomLayers(
        chunks,
        worldRuntimeState.chunkWidth,
        worldRuntimeState.chunkHeight,
        originChunkX,
        originChunkY,
        composedWidth,
        composedHeight,
      );
      const heightLayers = composeWorldHeightLayers(
        chunks,
        worldRuntimeState.chunkWidth,
        worldRuntimeState.chunkHeight,
        originChunkX,
        originChunkY,
      );
      const npcOverlays = buildNpcOverlaysFromWorldChunks(
        chunks,
        spriteCatalog,
        worldRuntimeState.chunkWidth,
        worldRuntimeState.chunkHeight,
        originChunkX,
        originChunkY,
      );
      worldRuntimeState.chunkRadius = safeRadius;
      worldRuntimeState.centerChunkX = safeCenterChunkX;
      worldRuntimeState.centerChunkY = safeCenterChunkY;
      worldRuntimeState.originChunkX = originChunkX;
      worldRuntimeState.originChunkY = originChunkY;
      worldRuntimeState.tileOffsetX = originChunkX * worldRuntimeState.chunkWidth;
      worldRuntimeState.tileOffsetY = originChunkY * worldRuntimeState.chunkHeight;
      worldRuntimeState.sourceChunks = chunks.map((chunk) => ({
        chunkX: Math.floor(Number(chunk?.chunkX) || 0),
        chunkY: Math.floor(Number(chunk?.chunkY) || 0),
      }));

      mapDocument.width = Math.max(1, composedWidth);
      mapDocument.height = Math.max(1, composedHeight);
      mapDocumentStore.setMapName(worldRuntimeState.worldName, currentMapId);
      mapDocumentStore.setBackgroundTileId(
        worldRuntimeState.defaultBackgroundTileId || mapDocument.backgroundTileId,
        normalizeBackgroundTileId,
      );
      mapDocument.heightBlurStep = Math.max(0, Math.min(1, Number(worldRuntimeState.heightBlurStep) || mapDocument.heightBlurStep || mapDocument.heightDetailStep || 0.1));
      mapDocumentStore.setBackgroundCellMode(mapDocument.backgroundTileId ? "tile" : "inherit", ["tile", "hole", "inherit"]);
      mapDocument.mapInfoDraft = {
        width: mapDocument.width,
        height: mapDocument.height,
        name: String(mapDocument.mapName || currentMapId || ""),
        backgroundColor: normalizeMapBackgroundColor(mapDocument.backgroundColor),
        heightBlurStep: Math.max(0, Math.min(1, Number(mapDocument.heightBlurStep ?? mapDocument.heightDetailStep) || 0.1)),
      };
      currentBaseRows = Array.isArray(roomLayers.find((layer) => Number(layer.layer) === 0)?.rows)
        ? roomLayers.find((layer) => Number(layer.layer) === 0).rows.map((row) => String(row || ""))
        : createFilledRows(composedWidth, composedHeight, ".");
      mapDocument.roomLayers = cloneLayers(roomLayers);
      mapDocument.heightLayers = cloneHeightLayers(heightLayers);
      mapDocument.npcOverlays.length = 0;
      npcOverlays.forEach((npc) => mapDocument.npcOverlays.push(npc));
      const rebaseLocalTileToCurrentNeighborhood = (localTileX, localTileY) => {
        const safeLocalTileX = Math.floor(Number(localTileX));
        const safeLocalTileY = Math.floor(Number(localTileY));
        if (!Number.isFinite(safeLocalTileX) || !Number.isFinite(safeLocalTileY)) {
          return null;
        }
        const worldTileX = previousTileOffsetX + safeLocalTileX;
        const worldTileY = previousTileOffsetY + safeLocalTileY;
        const nextLocalTileX = worldTileX - worldRuntimeState.tileOffsetX;
        const nextLocalTileY = worldTileY - worldRuntimeState.tileOffsetY;
        if (
          nextLocalTileX < 0 || nextLocalTileX >= composedWidth
          || nextLocalTileY < 0 || nextLocalTileY >= composedHeight
        ) {
          return null;
        }
        return {
          x: nextLocalTileX,
          y: nextLocalTileY,
        };
      };
      const rebasedHoverTile = rebaseLocalTileToCurrentNeighborhood(previousHoverTileX, previousHoverTileY);
      popupSessionStore.state.hoverTileX = rebasedHoverTile ? rebasedHoverTile.x : -1;
      popupSessionStore.state.hoverTileY = rebasedHoverTile ? rebasedHoverTile.y : -1;
      if (previousSelectedTile) {
        const rebasedSelectedTile = rebaseLocalTileToCurrentNeighborhood(previousSelectedTile.x, previousSelectedTile.y);
        popupSessionStore.state.selectedTile = rebasedSelectedTile
          ? {
            ...previousSelectedTile,
            x: rebasedSelectedTile.x,
            y: rebasedSelectedTile.y,
          }
          : null;
      }
      popupSessionStore.syncLayerVisibility(mapDocument.roomLayers);
      syncCanvasDimensionsToTileSize();
      invalidateTileSurface(sourceReason || "world-neighborhood-apply");
      syncDocumentTitle();
      ensureActiveHeightLayerSelection();
      worldRuntimeState.documentDirty = false;
      centerViewportOnWorldTile(preservedWorldCenter.worldTileX, preservedWorldCenter.worldTileY);
      draw();
      return true;
    }

    function prefetchAdjacentWorldNeighborhoods(centerChunkX, centerChunkY) {
      if (!isWorldModeActive()) {
        return;
      }
      const prefetchRadius = Math.max(0, worldRuntimeState.chunkRadius);
      const viewportWidthTiles = (Number(viewport?.clientWidth) || 0) / Math.max(1, tileSize);
      const viewportHeightTiles = (Number(viewport?.clientHeight) || 0) / Math.max(1, tileSize);
      const horizontalThresholdTiles = Math.max(
        4,
        Math.floor(worldRuntimeState.chunkWidth * 0.45),
        Math.ceil(viewportWidthTiles * 0.35),
      );
      const verticalThresholdTiles = Math.max(
        4,
        Math.floor(worldRuntimeState.chunkHeight * 0.45),
        Math.ceil(viewportHeightTiles * 0.35),
      );
      const horizontalThresholdPixels = horizontalThresholdTiles * Math.max(1, tileSize);
      const verticalThresholdPixels = verticalThresholdTiles * Math.max(1, tileSize);
      const localWorldPixelWidth = Math.max(1, mapDocument.width * tileSize);
      const localWorldPixelHeight = Math.max(1, mapDocument.height * tileSize);
      const remainingRight = localWorldPixelWidth - ((Number(viewport?.scrollLeft) || 0) + (Number(viewport?.clientWidth) || 0));
      const remainingBottom = localWorldPixelHeight - ((Number(viewport?.scrollTop) || 0) + (Number(viewport?.clientHeight) || 0));
      const directions = [];
      if ((Number(viewport?.scrollLeft) || 0) <= horizontalThresholdPixels) {
        directions.push({ dx: -1, dy: 0 });
      } else if (remainingRight <= horizontalThresholdPixels) {
        directions.push({ dx: 1, dy: 0 });
      }
      if ((Number(viewport?.scrollTop) || 0) <= verticalThresholdPixels) {
        directions.push({ dx: 0, dy: -1 });
      } else if (remainingBottom <= verticalThresholdPixels) {
        directions.push({ dx: 0, dy: 1 });
      }
      directions.forEach(({ dx, dy }) => {
        const nextCenterChunkX = centerChunkX + dx;
        const nextCenterChunkY = centerChunkY + dy;
        const neighborhoodKey = getNeighborhoodCacheKey(nextCenterChunkX, nextCenterChunkY, prefetchRadius);
        if (getCachedNeighborhoodChunks(nextCenterChunkX, nextCenterChunkY, prefetchRadius)) {
          return;
        }
        if (worldRuntimeState.prefetchedNeighborhoodKeys.has(neighborhoodKey)) {
          return;
        }
        worldRuntimeState.prefetchedNeighborhoodKeys.add(neighborhoodKey);
        void requestWorldNeighborhood(nextCenterChunkX, nextCenterChunkY, { createIfMissing: false, radius: prefetchRadius })
          .catch(() => {})
          .finally(() => {
            worldRuntimeState.prefetchedNeighborhoodKeys.delete(neighborhoodKey);
          });
      });
    }

    async function loadWorldNeighborhoodAtChunk(centerChunkX, centerChunkY, options) {
      if (!isWorldModeActive()) {
        return false;
      }
      const config = options && typeof options === "object" ? options : {};
      const safeCenterChunkX = Math.floor(Number(centerChunkX) || 0);
      const safeCenterChunkY = Math.floor(Number(centerChunkY) || 0);
      const requestedRadius = Math.max(0, Math.floor(Number(config.radius) || worldRuntimeState.chunkRadius));
      const loadKey = getNeighborhoodCacheKey(safeCenterChunkX, safeCenterChunkY, requestedRadius);
      const forceReload = config.force === true;
      if (!forceReload && worldRuntimeState.pendingLoadKey === loadKey && worldRuntimeState.pendingLoadPromise) {
        return worldRuntimeState.pendingLoadPromise;
      }
      if (
        !forceReload
        && safeCenterChunkX === worldRuntimeState.centerChunkX
        && safeCenterChunkY === worldRuntimeState.centerChunkY
        && requestedRadius === worldRuntimeState.chunkRadius
      ) {
        return false;
      }
      const preservedWorldCenter = config.preserveWorldCenter
        ? {
          worldTileX: Number(config.preserveWorldCenter.worldTileX) || 0,
          worldTileY: Number(config.preserveWorldCenter.worldTileY) || 0,
        }
        : getViewportCenterWorldTile();
      const requestId = worldRuntimeState.requestSerial + 1;
      worldRuntimeState.requestSerial = requestId;
      worldRuntimeState.pendingLoadKey = loadKey;
      const loadPromise = Promise.resolve()
        .then(async () => {
          if (!forceReload) {
            const cachedChunks = getCachedNeighborhoodChunks(safeCenterChunkX, safeCenterChunkY, requestedRadius);
            if (cachedChunks) {
              return {
                chunks: cachedChunks,
                sourceReason: "world-neighborhood-cache",
              };
            }
          }
          const payload = await requestWorldNeighborhood(safeCenterChunkX, safeCenterChunkY, {
            createIfMissing: false,
            radius: requestedRadius,
          });
          return {
            chunks: Array.isArray(payload?.chunks) ? payload.chunks : [],
            sourceReason: "world-neighborhood-network",
          };
        })
        .then((result) => {
          if (requestId !== worldRuntimeState.requestSerial) {
            return false;
          }
          if (popupSessionStore.state.pan.isPanning) {
            return false;
          }
          const chunks = Array.isArray(result?.chunks) ? result.chunks : [];
          const applied = applyWorldNeighborhoodFromChunks(
            safeCenterChunkX,
            safeCenterChunkY,
            chunks,
            preservedWorldCenter,
            result?.sourceReason,
            requestedRadius,
          );
          prefetchAdjacentWorldNeighborhoods(safeCenterChunkX, safeCenterChunkY);
          return applied;
        })
        .catch((error) => {
          if (requestId === worldRuntimeState.requestSerial) {
            setStatus("World chunk load failed: " + String(error), true);
          }
          throw error;
        })
        .finally(() => {
          if (requestId === worldRuntimeState.requestSerial) {
            worldRuntimeState.pendingLoadKey = "";
            worldRuntimeState.pendingLoadPromise = null;
          }
        });
      worldRuntimeState.pendingLoadPromise = loadPromise;
      return loadPromise;
    }

    function syncWorldNeighborhoodForViewport() {
      if (!isWorldModeActive() || !viewport) {
        return false;
      }
      if (popupSessionStore.state.pan.isPanning || popupSessionStore.state.draggingNpc || popupSessionStore.state.paintingStroke) {
        return false;
      }
      const desiredRadius = getDesiredWorldChunkRadius();
      const { worldTileX, worldTileY } = getViewportCenterWorldTile();
      if (desiredRadius !== worldRuntimeState.chunkRadius) {
        void loadWorldNeighborhoodAtChunk(worldRuntimeState.centerChunkX, worldRuntimeState.centerChunkY, {
          radius: desiredRadius,
          preserveWorldCenter: { worldTileX, worldTileY },
        }).catch(() => {});
        return true;
      }
      const viewportWidthTiles = (Number(viewport.clientWidth) || 0) / Math.max(1, tileSize);
      const viewportHeightTiles = (Number(viewport.clientHeight) || 0) / Math.max(1, tileSize);
      const horizontalThresholdTiles = Math.max(
        4,
        Math.floor(worldRuntimeState.chunkWidth * 0.45),
        Math.ceil(viewportWidthTiles * 0.35),
      );
      const verticalThresholdTiles = Math.max(
        4,
        Math.floor(worldRuntimeState.chunkHeight * 0.45),
        Math.ceil(viewportHeightTiles * 0.35),
      );
      const horizontalThresholdPixels = horizontalThresholdTiles * Math.max(1, tileSize);
      const verticalThresholdPixels = verticalThresholdTiles * Math.max(1, tileSize);
      const localWorldPixelWidth = Math.max(1, mapDocument.width * tileSize);
      const localWorldPixelHeight = Math.max(1, mapDocument.height * tileSize);
      const remainingRight = localWorldPixelWidth - ((Number(viewport.scrollLeft) || 0) + (Number(viewport.clientWidth) || 0));
      const remainingBottom = localWorldPixelHeight - ((Number(viewport.scrollTop) || 0) + (Number(viewport.clientHeight) || 0));
      let nextChunkX = worldRuntimeState.centerChunkX;
      let nextChunkY = worldRuntimeState.centerChunkY;
      const canShiftHorizontally = localWorldPixelWidth > (Number(viewport.clientWidth) || 0) + horizontalThresholdPixels;
      const canShiftVertically = localWorldPixelHeight > (Number(viewport.clientHeight) || 0) + verticalThresholdPixels;
      if (canShiftHorizontally && (Number(viewport.scrollLeft) || 0) <= horizontalThresholdPixels) {
        nextChunkX -= 1;
      } else if (canShiftHorizontally && remainingRight <= horizontalThresholdPixels) {
        nextChunkX += 1;
      }
      if (canShiftVertically && (Number(viewport.scrollTop) || 0) <= verticalThresholdPixels) {
        nextChunkY -= 1;
      } else if (canShiftVertically && remainingBottom <= verticalThresholdPixels) {
        nextChunkY += 1;
      }
      if (nextChunkX === worldRuntimeState.centerChunkX && nextChunkY === worldRuntimeState.centerChunkY) {
        nextChunkX = worldToChunkCoord(worldTileX, worldRuntimeState.chunkWidth);
        nextChunkY = worldToChunkCoord(worldTileY, worldRuntimeState.chunkHeight);
      }
      if (nextChunkX === worldRuntimeState.centerChunkX && nextChunkY === worldRuntimeState.centerChunkY) {
        prefetchAdjacentWorldNeighborhoods(nextChunkX, nextChunkY);
        return false;
      }
      void loadWorldNeighborhoodAtChunk(nextChunkX, nextChunkY, {
        radius: desiredRadius,
        preserveWorldCenter: { worldTileX, worldTileY },
      }).catch(() => {});
      return true;
    }

    function buildCurrentBootstrapSnapshot(): WorldshaperStudioBootstrap {
      ensureWorldDocumentCurrent();
      const baseLayer = cloneLayers(mapDocument.roomLayers).find((layer) => Number(layer.layer) === 0) || null;
      const baseRows = Array.isArray(baseLayer?.rows)
        ? baseLayer.rows.map((row) => String(row || ""))
        : Array.from({ length: Math.max(1, Number(mapDocument.height) || 1) }, () => ".".repeat(Math.max(1, Number(mapDocument.width) || 1)));
      return {
        mapId: currentMapId,
        mapName: String(mapDocument.mapName || currentMapId || "Untitled"),
        width: Math.max(1, Number(mapDocument.width) || 1),
        height: Math.max(1, Number(mapDocument.height) || 1),
        tileSize: baseTileSize,
        backgroundTileId: normalizeBackgroundTileId(mapDocument.backgroundTileId),
        roomLayers: cloneLayers(mapDocument.roomLayers),
        heightLayers: cloneHeightLayers(mapDocument.heightLayers),
        tileColors: cloneValue(tileColors),
        baseRows,
        npcOverlays: cloneNpcOverlays(mapDocument.npcOverlays),
        contentByType: cloneValue(mapDocument.contentBundle),
        spriteCatalog: cloneValue(spriteCatalog),
        tileCatalogById: cloneValue(tileCatalogById),
        defaultNpcTemplate: cloneValue(defaultNpcTemplate),
        apiBase,
        backgroundColor: normalizeMapBackgroundColor(mapDocument.backgroundColor),
        heightBlurStep: Math.max(0, Math.min(1, Number(mapDocument.heightBlurStep ?? mapDocument.heightDetailStep) || 0.1)),
        editorUi: cloneEditorUiState(),
        sourceMode: "world",
        worldId: isWorldModeActive() ? worldRuntimeState.worldId : undefined,
        worldName: isWorldModeActive() ? worldRuntimeState.worldName : undefined,
        worldChunkWidth: isWorldModeActive() ? worldRuntimeState.chunkWidth : undefined,
        worldChunkHeight: isWorldModeActive() ? worldRuntimeState.chunkHeight : undefined,
        worldOriginChunkX: isWorldModeActive() ? worldRuntimeState.originChunkX : undefined,
        worldOriginChunkY: isWorldModeActive() ? worldRuntimeState.originChunkY : undefined,
        worldChunkRadius: isWorldModeActive() ? worldRuntimeState.chunkRadius : undefined,
        worldTileOffsetX: isWorldModeActive() ? worldRuntimeState.tileOffsetX : undefined,
        worldTileOffsetY: isWorldModeActive() ? worldRuntimeState.tileOffsetY : undefined,
        worldSpawnX: isWorldModeActive() ? worldRuntimeState.spawnX : undefined,
        worldSpawnY: isWorldModeActive() ? worldRuntimeState.spawnY : undefined,
        worldBookmarks: isWorldModeActive() ? cloneWorldBookmarks() : undefined,
        sourceChunks: isWorldModeActive() ? cloneValue(worldRuntimeState.sourceChunks) : undefined,
      };
    }

    function persistHistoryState() {
      return historyController.persistHistoryState();
    }

    function restoreHistoryState() {
      return historyController.restoreHistoryState();
    }

    function applyHistorySnapshot(snapshot) {
      return historyController.applyHistorySnapshot(snapshot);
    }

    function resetWindowPosition() {
      try {
        window.localStorage.removeItem(popupBoundsStorageKey);
      } catch (_err) {}
      const nextBounds = getCenteredWorldshaperStudioBounds(window);
      try {
        window.resizeTo(nextBounds.width, nextBounds.height);
        window.moveTo(nextBounds.left, nextBounds.top);
      } catch (_err) {}
      setStatus("Window position reset.", false);
    }
    function resetWorkspaceLayout() {
      popupSessionStore.clearPersistedLayout(window);
      resetWindowPosition();
      setStatus("Workspace layout reset.", false);
    }
    function runtimeUniqueId() {
      try {
        const bytes = new Uint8Array(5);
        crypto.getRandomValues(bytes);
        return 'inst_' + Array.from(bytes, function(b) { return b.toString(16).padStart(2, '0'); }).join('');
      } catch (_e) {
        return 'inst_' + Math.random().toString(16).slice(2, 12);
      }
    }

    function toFiniteNumber(value, fallback) {
      const nextValue = Number(value);
      return Number.isFinite(nextValue) ? nextValue : fallback;
    }

    function cloneEditorUiState(sourceState) {
      return editorUiStore.cloneState(sourceState);
    }

    function refreshStandaloneBootstrapCache() {
      try {
        cacheStandaloneMapBootstrap(currentMapId);
      } catch (_error) {}
    }

    function getPanelLayout(panelKey, itemIds) {
      return editorUiStore.getPanelLayout(panelKey, itemIds);
    }

    function setPanelLayout(panelKey, nextLayout, itemIds) {
      const nextState = editorUiStore.setPanelLayout(panelKey, nextLayout, itemIds);
      refreshStandaloneBootstrapCache();
      return nextState;
    }

    function updatePanelLayout(panelKey, itemIds, updater) {
      const nextState = editorUiStore.updatePanelLayout(panelKey, itemIds, updater);
      refreshStandaloneBootstrapCache();
      return nextState;
    }

    function takeNextAvailableTileSymbol() {
      const usedSymbols = new Set(
        Object.values(tileCatalogById)
          .map((entry) => String(entry?.symbol || "").charAt(0))
          .filter(Boolean),
      );
      for (const symbol of TILE_SYMBOL_POOL) {
        if (!usedSymbols.has(symbol)) {
          return symbol;
        }
      }
      return "";
    }

    function getImagesPayload() {
      return cloneValue(ensureDocumentContentPayload("images", { schemaVersion: 1, images: [] })) || { schemaVersion: 1, images: [] };
    }

    function buildDuplicateGraphicName(baseName, imagesPayload) {
      const normalizedBase = String(baseName || "Graphic").trim() || "Graphic";
      const existingNames = new Set(
        (Array.isArray(imagesPayload?.images) ? imagesPayload.images : [])
          .map((entry) => String(entry?.name || "").trim().toLowerCase())
          .filter(Boolean),
      );
      const firstCandidate = `${normalizedBase} Copy`;
      if (!existingNames.has(firstCandidate.toLowerCase())) {
        return firstCandidate;
      }
      let suffix = 2;
      while (suffix < 10000) {
        const nextCandidate = `${normalizedBase} Copy ${suffix}`;
        if (!existingNames.has(nextCandidate.toLowerCase())) {
          return nextCandidate;
        }
        suffix += 1;
      }
      return `${normalizedBase} Copy ${Date.now()}`;
    }

    async function persistImagesPayloadDirect(imagesPayload, options = {}) {
      const normalizedImagesPayload = normalizeImagesPayloadSnapshot(imagesPayload, cloneValue);
      await persistContentPayload("images", normalizedImagesPayload);
      applyContentPayloadToRuntime("images", normalizedImagesPayload, options);
      return normalizedImagesPayload;
    }

    async function persistGraphicsDerivedPayload(type, payload, options = {}) {
      const normalizedType = String(type || "").trim() === "sprites" ? "sprites" : "tiles";
      const nextImagesPayload = normalizedType === "sprites"
        ? mergeImagesPayloadWithSpritesPayload(getImagesPayload(), payload)
        : mergeImagesPayloadWithTilesPayload(getImagesPayload(), payload);
      return persistImagesPayloadDirect(nextImagesPayload, options);
    }

    async function reloadGraphicsContentFromApi(options = {}) {
      const requestUrl = `${apiBase}/api/content/images?ts=${Date.now()}`;
      const payload = await fetchJsonOrThrow(requestUrl);
      applyContentPayloadToRuntime("images", payload, options);
      return payload;
    }

    function syncRuntimeGraphicsFromImagesPayload(imagesPayload, options = {}) {
      const config = options && typeof options === "object" ? options : {};
      const normalizedImagesPayload = normalizeImagesPayloadSnapshot(imagesPayload, cloneValue);
      const nextTilesPayload = buildTilesPayloadFromImagesPayload(normalizedImagesPayload);
      const nextSpritesPayload = buildSpritesPayloadFromImagesPayload(normalizedImagesPayload);
      graphicsVisualRevision += 1;
      setDocumentContentPayload("images", cloneValue(normalizedImagesPayload) || { schemaVersion: 1, images: [] });
      setDocumentContentPayload("tiles", cloneValue(nextTilesPayload) || { schemaVersion: 1, tiles: [] });
      setDocumentContentPayload("sprites", cloneValue(nextSpritesPayload) || { schemaVersion: 1, sprites: [] });
      replaceObjectContents(
        tileCatalogById,
        applyTileCatalogVisualRevision(
          buildTileCatalogById(Array.isArray(nextTilesPayload?.tiles) ? nextTilesPayload.tiles : [], buildSpritePreviewDataUrl),
        ),
      );
      replaceObjectContents(
        spriteCatalog,
        applySpriteCatalogVisualRevision(
          buildSpriteCatalog(Array.isArray(nextSpritesPayload?.sprites) ? nextSpritesPayload.sprites : [], buildSpritePreviewDataUrl),
        ),
      );
      replaceObjectContents(tileCatalog, buildMergedTileCatalog());
      mapDocument.backgroundTileId = normalizeBackgroundTileId(mapDocument.backgroundTileId);
      const paintableTileIds = getPaintableTileIds();
      if (!paintableTileIds.includes(String(popupSessionStore.state.activeBrushTileId || "").trim())) {
        popupSessionStore.state.activeBrushTileId = "";
      }
      Object.keys(npcImages).forEach((npcId) => {
        delete npcImages[npcId];
      });
      mapDocument.npcOverlays.forEach((npc) => {
        syncNpcOverlayFromRecord(npc);
      });
      invalidateTileSurface("graphics-catalog-updated", { refreshTileImages: true });
      scope.invalidateWorldOverviewChunkSurfaces?.(null, { refreshTileVisuals: true });
      uiScope.refreshWorldOverviewWindow?.();
      if (!config.deferRefresh) {
        uiScope.renderNpcList();
        uiScope.renderInstancePalette();
        uiScope.renderPaintPalette();
      }
      return {
        images: mapDocument.contentBundle.images,
        tiles: nextTilesPayload,
        sprites: nextSpritesPayload,
      };
    }

    function buildSpriteLikeGraphicRecord(recordId, graphicRole) {
      return {
        id: String(recordId || "sprite_" + runtimeUniqueId().replace(/^inst_/, "")),
        name: "New " + (graphicRole === "other" ? "Graphic" : "Sprite"),
        width: 16,
        height: 16,
        pixelScale: 2,
        graphicRole: graphicRole === "other" ? "other" : "sprite",
        tags: [],
        rows: Array.from({ length: 16 }, () => ".".repeat(16)),
      };
    }

    async function createNewTile() {
      const nextSymbol = takeNextAvailableTileSymbol();
      if (!nextSymbol) {
        setStatus("No free tile symbols remain for new tiles.", true);
        return null;
      }
      const nextRecord = normalizeTileRecordForSave({
        id: "tile_" + runtimeUniqueId().replace(/^inst_/, ""),
        symbol: nextSymbol,
        name: "New Tile",
        description: "",
        width: 16,
        height: 16,
        pixelScale: 2,
        rows: Array.from({ length: 16 }, () => ".".repeat(16)),
      });
      const imagesPayload = getImagesPayload();
      const nextImages = Array.isArray(imagesPayload.images) ? imagesPayload.images.slice() : [];
      nextImages.push(buildImageRecordFromTileRecord(nextRecord, null, cloneValue));
      const nextPayload = {
        schemaVersion: typeof imagesPayload.schemaVersion === "number" ? imagesPayload.schemaVersion : 1,
        images: nextImages,
      };
      try {
        await persistImagesPayloadDirect(nextPayload);
        popupSessionStore.state.activeBrushTileId = String(nextRecord.id || "");
        popupSessionStore.state.activeGraphicsRecordId = String(nextRecord.id || "");
        popupSessionStore.state.activeGraphicsTab = "tiles";
        setSidebarTab("tiles");
        renderPaintPalette();
        draw();
        refreshStandaloneBootstrapCache();
        setStatus("Created " + describeBrushTileId(nextRecord.id) + ".", false);
        scope.openTileArtEditorWindow?.(nextRecord.id);
        return nextRecord;
      } catch (error) {
        setStatus(String(error || "Failed to create tile."), true);
        return null;
      }
    }

    async function createNewSpriteGraphic(graphicRole = "sprite") {
      const nextRecord = buildSpriteLikeGraphicRecord("sprite_" + runtimeUniqueId().replace(/^inst_/, ""), graphicRole);
      const imagesPayload = getImagesPayload();
      const nextImages = Array.isArray(imagesPayload.images) ? imagesPayload.images.slice() : [];
      nextImages.push(buildImageRecordFromSpriteRecord(nextRecord, graphicRole, null, cloneValue));
      const nextPayload = {
        schemaVersion: typeof imagesPayload.schemaVersion === "number" ? imagesPayload.schemaVersion : 1,
        images: nextImages,
      };
      try {
        await persistImagesPayloadDirect(nextPayload);
        popupSessionStore.state.activeGraphicsRecordId = String(nextRecord.id || "");
        popupSessionStore.state.activeGraphicsTab = graphicRole === "other" ? "other" : "sprites";
        setSidebarTab("tiles");
        renderPaintPalette();
        draw();
        refreshStandaloneBootstrapCache();
        setStatus("Created " + (nextRecord.name || nextRecord.id) + ".", false);
        scope.openTileArtEditorWindow?.(graphicRole === "other" ? "other" : "sprite", nextRecord.id);
        return nextRecord;
      } catch (error) {
        setStatus(String(error || "Failed to create graphic."), true);
        return null;
      }
    }

    async function duplicateGraphicRecord(recordType, graphicId) {
      const normalizedType = recordType === "other" ? "other" : (recordType === "sprite" ? "sprite" : "tile");
      const normalizedId = String(graphicId || "").trim();
      if (!normalizedId) {
        return null;
      }
      const imagesPayload = getImagesPayload();
      const sourceRecord = getImageRecordFromPayload(imagesPayload, normalizedId);
      if (!sourceRecord) {
        setStatus("Graphic not found.", true);
        return null;
      }
      let nextTileSymbol = String(sourceRecord.tileSymbol || "").trim().charAt(0);
      if (normalizedType === "tile") {
        nextTileSymbol = takeNextAvailableTileSymbol();
        if (!nextTileSymbol) {
          setStatus("No free tile symbols remain for duplicated tiles.", true);
          return null;
        }
      }
      const nextRecord = normalizeImageRecordForSave({
        ...cloneValue(sourceRecord),
        id: (normalizedType === "tile" ? "tile_" : "sprite_") + runtimeUniqueId().replace(/^inst_/, ""),
        name: buildDuplicateGraphicName(String(sourceRecord.name || normalizedId || "Graphic"), imagesPayload),
        tileSymbol: normalizedType === "tile" ? nextTileSymbol : String(sourceRecord.tileSymbol || "").trim().charAt(0),
        rows: Array.isArray(sourceRecord.rows) ? sourceRecord.rows.map((row) => String(row || "")) : [],
        frames: Array.isArray(sourceRecord.frames) ? cloneValue(sourceRecord.frames) : [],
        tags: Array.isArray(sourceRecord.tags) ? cloneValue(sourceRecord.tags) : [],
        roles: Array.isArray(sourceRecord.roles) ? cloneValue(sourceRecord.roles) : [],
      });
      const nextImages = Array.isArray(imagesPayload.images) ? imagesPayload.images.slice() : [];
      nextImages.push(nextRecord);
      const nextPayload = {
        schemaVersion: typeof imagesPayload.schemaVersion === "number" ? imagesPayload.schemaVersion : 1,
        images: nextImages,
      };
      try {
        await persistImagesPayloadDirect(nextPayload);
        popupSessionStore.state.activeGraphicsRecordId = String(nextRecord.id || "");
        popupSessionStore.state.activeGraphicsTab = normalizedType === "other" ? "other" : (normalizedType === "sprite" ? "sprites" : "tiles");
        if (normalizedType === "tile") {
          popupSessionStore.state.activeBrushTileId = String(nextRecord.id || "");
        }
        setSidebarTab("tiles");
        renderPaintPalette();
        draw();
        refreshStandaloneBootstrapCache();
        setStatus(
          "Duplicated "
            + (normalizedType === "tile" ? "tile" : (normalizedType === "sprite" ? "sprite" : "graphic"))
            + " as "
            + (nextRecord.name || nextRecord.id)
            + ".",
          false,
        );
        return nextRecord;
      } catch (error) {
        setStatus(String(error || "Failed to duplicate graphic."), true);
        return null;
      }
    }

    async function syncGraphicCounterpartFromRecord(recordType, record) {
      const normalizedType = recordType === "other" ? "other" : (recordType === "sprite" ? "sprite" : "tile");
      const normalizedId = String(record?.id || "").trim();
      if (!normalizedId) {
        return false;
      }
      if (normalizedType === "tile") {
        const imagesPayload = getImagesPayload();
        const nextImages = Array.isArray(imagesPayload.images) ? imagesPayload.images.slice() : [];
        const existingIndex = nextImages.findIndex((entry) => String(entry?.id || "").trim() === normalizedId);
        if (existingIndex < 0) {
          return false;
        }
        const existing = nextImages[existingIndex] || {};
        nextImages[existingIndex] = buildImageRecordFromTileRecord({
          ...cloneValue(record),
          symbol: String(record?.symbol || existing?.tileSymbol || "").charAt(0) || takeNextAvailableTileSymbol() || "T",
        }, existing, cloneValue);
        const nextPayload = {
          schemaVersion: typeof imagesPayload.schemaVersion === "number" ? imagesPayload.schemaVersion : 1,
          images: nextImages,
        };
        await persistImagesPayloadDirect(nextPayload);
        return true;
      }
      const imagesPayload = getImagesPayload();
      const nextImages = Array.isArray(imagesPayload.images) ? imagesPayload.images.slice() : [];
      const existingIndex = nextImages.findIndex((entry) => String(entry?.id || "").trim() === normalizedId);
      if (existingIndex < 0) {
        return false;
      }
      const existing = nextImages[existingIndex] || {};
      nextImages[existingIndex] = buildImageRecordFromSpriteRecord(record, normalizedType, existing, cloneValue);
      const nextPayload = {
        schemaVersion: typeof imagesPayload.schemaVersion === "number" ? imagesPayload.schemaVersion : 1,
        images: nextImages,
      };
      await persistImagesPayloadDirect(nextPayload);
      return true;
    }

    async function assignGraphicToCategory(sourceType, graphicId, targetCategory) {
      const normalizedId = String(graphicId || "").trim();
      const normalizedSourceType = sourceType === "sprite" || sourceType === "other" ? "sprite" : "tile";
      const normalizedTargetCategory = targetCategory === "other" ? "other" : (targetCategory === "sprites" ? "sprites" : "tiles");
      if (!normalizedId) {
        return false;
      }
      if (normalizedTargetCategory === "tiles") {
        const sourceRecord = getImageRecordFromPayload(getImagesPayload(), normalizedId);
        if (!sourceRecord) {
          setStatus("Graphic not found.", true);
          return false;
        }
        const imagesPayload = getImagesPayload();
        const nextImages = Array.isArray(imagesPayload.images) ? imagesPayload.images.slice() : [];
        const existingIndex = nextImages.findIndex((entry) => String(entry?.id || "").trim() === normalizedId);
        const existing = existingIndex >= 0 ? nextImages[existingIndex] : sourceRecord;
        const nextSymbol = String(existing?.tileSymbol || sourceRecord?.tileSymbol || "").charAt(0) || takeNextAvailableTileSymbol();
        if (!nextSymbol) {
          setStatus("No free tile symbols remain.", true);
          return false;
        }
        const nextRecord = buildImageRecordFromTileRecord({
          ...cloneValue(sourceRecord),
          symbol: nextSymbol,
        }, existing, cloneValue);
        if (existingIndex >= 0) {
          nextImages[existingIndex] = nextRecord;
        } else {
          nextImages.push(nextRecord);
        }
        const nextPayload = {
          schemaVersion: typeof imagesPayload.schemaVersion === "number" ? imagesPayload.schemaVersion : 1,
          images: nextImages,
        };
        await persistImagesPayloadDirect(nextPayload);
        setStatus("Assigned graphic to Tiles.", false);
        return true;
      }
      const sourceRecord = getImageRecordFromPayload(getImagesPayload(), normalizedId);
      if (!sourceRecord) {
        setStatus("Graphic not found.", true);
        return false;
      }
      const imagesPayload = getImagesPayload();
      const nextImages = Array.isArray(imagesPayload.images) ? imagesPayload.images.slice() : [];
      const existingIndex = nextImages.findIndex((entry) => String(entry?.id || "").trim() === normalizedId);
      const existing = existingIndex >= 0 ? nextImages[existingIndex] : sourceRecord;
      const nextRecord = buildImageRecordFromSpriteRecord(
        sourceRecord,
        normalizedTargetCategory === "other" ? "other" : "sprite",
        existing,
        cloneValue,
      );
      if (existingIndex >= 0) {
        nextImages[existingIndex] = nextRecord;
      } else {
        nextImages.push(nextRecord);
      }
      const nextPayload = {
        schemaVersion: typeof imagesPayload.schemaVersion === "number" ? imagesPayload.schemaVersion : 1,
        images: nextImages,
      };
      await persistImagesPayloadDirect(nextPayload);
      setStatus("Assigned graphic to " + (normalizedTargetCategory === "other" ? "Other" : "Sprites") + ".", false);
      return true;
    }

    function getRecordFromTilePayload(tileId) {
      const entry = getImageRecordFromPayload(getImagesPayload(), tileId);
      if (!entry || !normalizeGraphicRoles(entry.roles).includes("tile")) {
        return null;
      }
      return buildTileRecordFromImageRecord(entry, cloneValue);
    }

    function replaceTileSymbolInRows(rows, targetSymbol, replacementSymbol) {
      const normalizedTarget = String(targetSymbol || "").charAt(0);
      const normalizedReplacement = String(replacementSymbol || "").charAt(0) || " ";
      let changedCells = 0;
      const nextRows = (Array.isArray(rows) ? rows : []).map((row) => Array.from(String(row || "")).map((ch) => {
        if (!normalizedTarget || ch !== normalizedTarget) {
          return ch;
        }
        changedCells += 1;
        return normalizedReplacement;
      }).join(""));
      return {
        rows: nextRows,
        changedCells,
      };
    }

    function scrubTileReferencesFromRoomLayersLocal(sourceLayers, targetSymbol) {
      let changedCells = 0;
      const nextLayers = cloneLayers(sourceLayers).map((layer) => {
        const fillChar = (Number(layer.layer) || 0) === 0 ? "." : " ";
        const scrubbed = replaceTileSymbolInRows(layer.rows, targetSymbol, fillChar);
        changedCells += scrubbed.changedCells;
        return {
          ...layer,
          rows: scrubbed.rows,
        };
      });
      return {
        roomLayers: nextLayers,
        changedCells,
      };
    }

    function scrubTileReferencesFromHeightLayersLocal(sourceLayers, targetSymbol) {
      let changedCells = 0;
      const nextLayers = (Array.isArray(sourceLayers) ? sourceLayers : [])
        .map((entry) => {
          const scrubbed = replaceTileSymbolInRows(entry?.rows, targetSymbol, " ");
          changedCells += scrubbed.changedCells;
          return {
            ...entry,
            rows: scrubbed.rows,
          };
        })
        .filter((entry) => Array.isArray(entry?.rows) && entry.rows.some((row) => /[^ .]/.test(String(row || ""))));
      return {
        heightLayers: cloneHeightLayers(nextLayers),
        changedCells,
      };
    }

    function scrubTileReferencesFromCachedWorldChunks(targetTileId, targetSymbol) {
      let updatedChunks = 0;
      let changedRoomCells = 0;
      let changedHeightCells = 0;
      let clearedBackgrounds = 0;
      for (const [chunkKey, chunkValue] of worldRuntimeState.chunkCache.entries()) {
        if (!chunkValue || typeof chunkValue !== "object") {
          continue;
        }
        const scrubbedLayers = scrubTileReferencesFromRoomLayersLocal(chunkValue.roomLayers, targetSymbol);
        const scrubbedHeightLayers = scrubTileReferencesFromHeightLayersLocal(chunkValue.heightLayers, targetSymbol);
        const clearsBackground = String(chunkValue.backgroundTileId || "").trim() === targetTileId;
        const changed = scrubbedLayers.changedCells > 0 || scrubbedHeightLayers.changedCells > 0 || clearsBackground;
        if (!changed) {
          continue;
        }
        updatedChunks += 1;
        changedRoomCells += scrubbedLayers.changedCells;
        changedHeightCells += scrubbedHeightLayers.changedCells;
        if (clearsBackground) {
          clearedBackgrounds += 1;
        }
        touchWorldChunkCacheEntry(chunkKey, {
          ...cloneValue(chunkValue),
          backgroundTileId: clearsBackground ? "" : String(chunkValue.backgroundTileId || "").trim(),
          roomLayers: scrubbedLayers.roomLayers,
          heightLayers: scrubbedHeightLayers.heightLayers,
        });
      }
      return {
        updatedChunks,
        changedRoomCells,
        changedHeightCells,
        clearedBackgrounds,
      };
    }

    function scrubSpriteReferencesFromCachedWorldChunks(targetSpriteId) {
      const normalizedSpriteId = String(targetSpriteId || "").trim();
      let updatedChunks = 0;
      let scrubbedEntities = 0;
      for (const [chunkKey, chunkValue] of worldRuntimeState.chunkCache.entries()) {
        if (!chunkValue || typeof chunkValue !== "object") {
          continue;
        }
        let changedEntities = 0;
        const nextInstances = (Array.isArray(chunkValue.instances) ? chunkValue.instances : []).map((entry) => {
          if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
            return entry;
          }
          const nextEntry = cloneValue(entry) || {};
          const nextRecord = nextEntry.record && typeof nextEntry.record === "object" && !Array.isArray(nextEntry.record)
            ? { ...nextEntry.record }
            : {};
          const clearsSpriteId = String(nextRecord.spriteId || "").trim() === normalizedSpriteId;
          const clearsSpriteIdOverride = String(nextRecord.spriteIdOverride || "").trim() === normalizedSpriteId;
          const clearsTopLevelSpriteId = String(nextEntry.spriteId || "").trim() === normalizedSpriteId;
          if (clearsSpriteId) {
            nextRecord.spriteId = "";
          }
          if (clearsSpriteIdOverride) {
            nextRecord.spriteIdOverride = "";
          }
          if (clearsTopLevelSpriteId) {
            nextEntry.spriteId = "";
          }
          if (clearsSpriteId || clearsSpriteIdOverride || clearsTopLevelSpriteId) {
            changedEntities += 1;
          }
          nextEntry.record = nextRecord;
          return nextEntry;
        });
        if (changedEntities <= 0) {
          continue;
        }
        updatedChunks += 1;
        scrubbedEntities += changedEntities;
        touchWorldChunkCacheEntry(chunkKey, {
          ...cloneValue(chunkValue),
          instances: nextInstances,
        });
      }
      return {
        updatedChunks,
        scrubbedEntities,
      };
    }

    async function deleteTileEverywhere(tileId) {
      const normalizedTileId = String(tileId || "").trim();
      if (!normalizedTileId) {
        setStatus("Tile id missing. Cannot delete tile.", true);
        return false;
      }
      const tileEntry = getTileEntryById(normalizedTileId);
      const tileSymbol = String(tileEntry?.symbol || "").charAt(0);
      if (!tileSymbol || tileSymbol === "." || tileSymbol === " ") {
        setStatus("That tile cannot be deleted.", true);
        return false;
      }
      const tileLabel = describeBrushTileId(normalizedTileId);
      const confirmed = window.confirm(
        `Delete ${tileLabel}?\n\nThis will remove the tile from the tile catalog and scrub its saved references from world/map data.`,
      );
      if (!confirmed) {
        return false;
      }
      if (hasUnsavedChanges()) {
        const saved = await saveCurrentState();
        if (!saved) {
          setStatus("Save before delete failed. Tile delete cancelled.", true);
          return false;
        }
      }
      let response;
      try {
        response = await fetch(`${apiBase}/api/content/tiles/${encodeURIComponent(normalizedTileId)}/delete`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
        });
      } catch (error) {
        setStatus(String(error || "Tile delete failed."), true);
        return false;
      }
      if (!response.ok) {
        let errorMessage = "";
        try {
          const rawText = await response.text();
          if (rawText) {
            try {
              const parsed = JSON.parse(rawText);
              errorMessage = String(parsed?.error || rawText).trim();
            } catch (_parseError) {
              errorMessage = String(rawText || "").trim();
            }
          }
        } catch (_error) {}
        setStatus(`Tile delete failed (${response.status})${errorMessage ? `: ${errorMessage}` : ""}`, true);
        return false;
      }
      const payload = await response.json().catch(() => ({}));
      const scrubbedRoomLayers = scrubTileReferencesFromRoomLayersLocal(mapDocument.roomLayers, tileSymbol);
      const scrubbedHeightLayers = scrubTileReferencesFromHeightLayersLocal(mapDocument.heightLayers, tileSymbol);
      const mapBackgroundCleared = String(mapDocument.backgroundTileId || "").trim() === normalizedTileId;
      mapDocument.roomLayers = scrubbedRoomLayers.roomLayers;
      mapDocument.heightLayers = scrubbedHeightLayers.heightLayers;
      if (mapBackgroundCleared) {
        mapDocumentStore.setBackgroundTileId("", normalizeBackgroundTileId);
      }
      if (isWorldModeActive()) {
        if (String(worldRuntimeState.defaultBackgroundTileId || "").trim() === normalizedTileId) {
          worldRuntimeState.defaultBackgroundTileId = "";
        }
        const cachedChunkStats = scrubTileReferencesFromCachedWorldChunks(normalizedTileId, tileSymbol);
        void cachedChunkStats;
      }
      applyContentPayloadToRuntime("tiles", payload?.tiles || { schemaVersion: 1, tiles: [] }, { deferRefresh: true });
      renderPaintPalette();
      refreshInformationPanel();
      refreshToolbarState(true);
      refreshStandaloneBootstrapCache();
      scope.refreshWorldOverviewWindow?.();
      invalidateTileSurface("tile-deleted", { refreshTileImages: true });
      draw();
      const nextState = captureState();
      registerHistory("Tile deleted", tileLabel, "removed", [
        "Tile: " + tileLabel,
        "Removed from tile catalog and scrubbed from saved world/map data.",
      ], {
        nextState,
      });
      if (scope.historyEntries[scope.historyIndex]) {
        scope.lastSavedHistoryId = scope.historyEntries[scope.historyIndex].id;
        persistHistoryState();
      }
      refreshToolbarState(true);
      const stats = payload?.stats && typeof payload.stats === "object" ? payload.stats : {};
      const summary = [
        `Deleted ${tileLabel}.`,
        Number(stats.updatedChunks) > 0 ? (`Chunks scrubbed: ${Number(stats.updatedChunks) || 0}.`) : "",
        Number(stats.updatedMaps) > 0 ? (`Maps scrubbed: ${Number(stats.updatedMaps) || 0}.`) : "",
        Number(stats.updatedWorlds) > 0 ? (`Worlds updated: ${Number(stats.updatedWorlds) || 0}.`) : "",
      ].filter(Boolean).join(" ");
      setStatus(summary || (`Deleted ${tileLabel}.`), false);
      return true;
    }

    async function deleteSpriteEverywhere(spriteId) {
      const normalizedSpriteId = String(spriteId || "").trim();
      if (!normalizedSpriteId) {
        setStatus("Sprite id missing. Cannot delete sprite.", true);
        return false;
      }
      const spriteEntry = spriteCatalog[normalizedSpriteId] || null;
      const spriteLabel = String(spriteEntry?.name || normalizedSpriteId).trim() || normalizedSpriteId;
      const confirmed = window.confirm(
        `Delete ${spriteLabel}?\n\nThis will remove the sprite from graphics and scrub entity references from saved world data.`,
      );
      if (!confirmed) {
        return false;
      }
      if (hasUnsavedChanges()) {
        const saved = await saveCurrentState();
        if (!saved) {
          setStatus("Save before delete failed. Sprite delete cancelled.", true);
          return false;
        }
      }
      let response;
      try {
        response = await fetch(`${apiBase}/api/content/sprites/${encodeURIComponent(normalizedSpriteId)}/delete`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
        });
      } catch (error) {
        setStatus(String(error || "Sprite delete failed."), true);
        return false;
      }
      if (!response.ok) {
        let errorMessage = "";
        try {
          const rawText = await response.text();
          if (rawText) {
            try {
              const parsed = JSON.parse(rawText);
              errorMessage = String(parsed?.error || rawText).trim();
            } catch (_parseError) {
              errorMessage = String(rawText || "").trim();
            }
          }
        } catch (_error) {}
        setStatus(`Sprite delete failed (${response.status})${errorMessage ? `: ${errorMessage}` : ""}`, true);
        return false;
      }
      const payload = await response.json().catch(() => ({}));
      const templatePayload = ensureDocumentContentPayload("npc_templates", { schemaVersion: 1, npcTemplates: [] }) || { schemaVersion: 1, npcTemplates: [] };
      if (Array.isArray(templatePayload.npcTemplates)) {
        templatePayload.npcTemplates = templatePayload.npcTemplates.map((entry) => {
          if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
            return entry;
          }
          const nextEntry = { ...entry };
          if (String(nextEntry.spriteId || "").trim() === normalizedSpriteId) {
            nextEntry.spriteId = "";
          }
          if (String(nextEntry.spriteIdOverride || "").trim() === normalizedSpriteId) {
            nextEntry.spriteIdOverride = "";
          }
          return nextEntry;
        });
      }
      mapDocument.npcOverlays.forEach((npc) => {
        if (!npc || !npc.record || typeof npc.record !== "object" || Array.isArray(npc.record)) {
          return;
        }
        if (String(npc.record.spriteId || "").trim() === normalizedSpriteId) {
          npc.record.spriteId = "";
        }
        if (String(npc.record.spriteIdOverride || "").trim() === normalizedSpriteId) {
          npc.record.spriteIdOverride = "";
        }
        syncNpcOverlayFromRecord(npc);
      });
      if (isWorldModeActive()) {
        void scrubSpriteReferencesFromCachedWorldChunks(normalizedSpriteId);
      }
      applyContentPayloadToRuntime("images", payload?.images || { schemaVersion: 1, images: [] }, { deferRefresh: true });
      if (String(popupSessionStore.state.activeGraphicsRecordId || "").trim() === normalizedSpriteId) {
        popupSessionStore.state.activeGraphicsRecordId = "";
      }
      refreshStandaloneBootstrapCache();
      renderPaintPalette();
      renderNpcList();
      renderInstancePalette();
      draw();
      const nextState = captureState();
      registerHistory("Sprite deleted", spriteLabel, "removed", [
        "Sprite: " + spriteLabel,
        "Removed from graphics and scrubbed from saved entity references.",
      ], {
        nextState,
      });
      if (scope.historyEntries[scope.historyIndex]) {
        scope.lastSavedHistoryId = scope.historyEntries[scope.historyIndex].id;
        persistHistoryState();
      }
      const stats = payload?.stats && typeof payload.stats === "object" ? payload.stats : {};
      const summary = [
        `Deleted ${spriteLabel}.`,
        Number(stats.updatedChunks) > 0 ? (`Chunks updated: ${Number(stats.updatedChunks) || 0}.`) : "",
        Number(stats.scrubbedPlacedEntities) > 0 ? (`Placed entities scrubbed: ${Number(stats.scrubbedPlacedEntities) || 0}.`) : "",
        Number(stats.updatedNpcTemplateRecords) > 0 ? (`Templates scrubbed: ${Number(stats.updatedNpcTemplateRecords) || 0}.`) : "",
      ].filter(Boolean).join(" ");
      setStatus(summary || (`Deleted ${spriteLabel}.`), false);
      return true;
    }

    function createPanelFolder(panelKey, itemIds, panelLabel) {
      const currentLayout = getPanelLayout(panelKey, itemIds);
      const folderCount = Object.keys(currentLayout.folders || {}).length;
      const folderId = "folder_" + runtimeUniqueId().replace(/^inst_/, "");
      const folderName = "New Folder" + (folderCount > 0 ? " " + (folderCount + 1) : "");
      setPanelLayout(panelKey, createPanelFolderLayoutFolder(currentLayout, itemIds, folderId, folderName), itemIds);
      registerHistory(panelLabel + " folder created", "folders:" + folderCount, "folders:" + (folderCount + 1), [
        "Panel: " + panelLabel,
        "Folder: " + folderName,
      ]);
      setStatus("Created " + panelLabel.toLowerCase() + " folder " + folderName + ".", false);
      return folderId;
    }

    function togglePanelFolder(panelKey, itemIds, folderId, panelLabel) {
      const currentLayout = getPanelLayout(panelKey, itemIds);
      const folder = currentLayout.folders[String(folderId || "").trim()];
      if (!folder) {
        return false;
      }
      const nextCollapsed = !folder.collapsed;
      setPanelLayout(panelKey, togglePanelFolderLayoutFolder(currentLayout, itemIds, folderId), itemIds);
      registerHistory(panelLabel + " folder " + (nextCollapsed ? "collapsed" : "expanded"), nextCollapsed ? "open" : "closed", nextCollapsed ? "closed" : "open", [
        "Panel: " + panelLabel,
        "Folder: " + (folder.name || folder.id),
      ]);
      setStatus((nextCollapsed ? "Collapsed " : "Expanded ") + (folder.name || "folder") + ".", false);
      return true;
    }

    function renamePanelFolder(panelKey, itemIds, folderId, panelLabel) {
      const currentLayout = getPanelLayout(panelKey, itemIds);
      const folder = currentLayout.folders[String(folderId || "").trim()];
      if (!folder) {
        return false;
      }
      const nextName = String(window.prompt("Folder name", folder.name || "New Folder") || "").trim();
      if (!nextName || nextName === folder.name) {
        return false;
      }
      setPanelLayout(panelKey, renamePanelFolderLayoutFolder(currentLayout, itemIds, folderId, nextName), itemIds);
      registerHistory(panelLabel + " folder renamed", folder.name || folder.id, nextName, [
        "Panel: " + panelLabel,
        "Folder: " + (folder.name || folder.id) + " -> " + nextName,
      ]);
      setStatus("Renamed folder to " + nextName + ".", false);
      return true;
    }

    function deletePanelFolder(panelKey, itemIds, folderId, panelLabel) {
      const currentLayout = getPanelLayout(panelKey, itemIds);
      const folder = currentLayout.folders[String(folderId || "").trim()];
      if (!folder) {
        return false;
      }
      const itemCount = Array.isArray(folder.itemOrder) ? folder.itemOrder.length : 0;
      setPanelLayout(panelKey, deletePanelFolderLayoutFolder(currentLayout, itemIds, folderId), itemIds);
      registerHistory(panelLabel + " folder removed", folder.name || folder.id, "base panel", [
        "Panel: " + panelLabel,
        "Folder: " + (folder.name || folder.id),
        "Moved back to base panel: " + itemCount + " item" + (itemCount === 1 ? "" : "s"),
      ]);
      setStatus("Removed folder " + (folder.name || folder.id) + ".", false);
      return true;
    }

    function movePanelNode(panelKey, itemIds, panelLabel, dragging, dropTarget) {
      if (!dragging || !dropTarget) {
        return false;
      }
      const currentLayout = getPanelLayout(panelKey, itemIds);
      const nextLayout = movePanelFolderLayoutNode(currentLayout, itemIds, dragging, dropTarget);
      const beforeSignature = JSON.stringify(currentLayout);
      const afterSignature = JSON.stringify(nextLayout);
      if (beforeSignature === afterSignature) {
        return false;
      }
      setPanelLayout(panelKey, nextLayout, itemIds);
      registerHistory(panelLabel + " order changed", dragging.kind + ":" + dragging.id, dropTarget.kind + ":" + (dropTarget.id || "root"), [
        "Panel: " + panelLabel,
        "Moved " + dragging.kind + " " + dragging.id + ".",
      ]);
      setStatus("Updated " + panelLabel.toLowerCase() + " organization.", false);
      return true;
    }

    function cloneNpcPositions(source) {
      return source.map((npc) => ({
        id: String(npc.id || ""),
        name: String(npc.name || npc.id || "NPC"),
        x: toFiniteNumber(npc.x, 0),
        y: toFiniteNumber(npc.y, 0),
      }));
    }

    function toCellKey(layerNumber, tileX, tileY) {
      return String(Number(layerNumber) || 0) + ":" + String(Number(tileX) || 0) + ":" + String(Number(tileY) || 0);
    }

    function beginTileInstanceMutationBatch() {
      popupSessionStore.beginTileMutationBatch();
    }

    function endTileInstanceMutationBatch() {
      popupSessionStore.endTileMutationBatch();
    }

    function cloneNpcOverlays(source) {
      return source.map((src) => {
        const record = JSON.parse(JSON.stringify(src.record || {}));
        record.id = String(src.id || "");
        record.position = { x: toFiniteNumber(src.x, 0), y: toFiniteNumber(src.y, 0) };
        return {
          id: String(src.id || ""),
          layer: Number(src.layer ?? record.layer ?? 0) || 0,
          name: String(src.name || src.id || "NPC"),
          spriteId: String(src.spriteId || ""),
          isPlacementSlot: Boolean(src.isPlacementSlot),
          x: toFiniteNumber(src.x, 0),
          y: toFiniteNumber(src.y, 0),
          dataUrl: src.dataUrl || null,
          spriteWidth: Number(src.spriteWidth) || 28,
          spriteHeight: Number(src.spriteHeight) || 28,
          record,
        };
      });
    }

    function syncNpcOverlayFromRecord(npc) {
      const record = npc.record && typeof npc.record === "object" && !Array.isArray(npc.record) ? npc.record : {};
      const pos = record.position && typeof record.position === "object" && !Array.isArray(record.position)
        ? record.position
        : {};
      npc.id = String(record.id || npc.id || "");
      npc.layer = Number(record.layer ?? npc.layer ?? 0) || 0;
      npc.name = typeof record.name === "string"
        ? record.name
        : String(record.nameOverride || npc.name || npc.id || "NPC");
      npc.faction = String(record.faction || record.factionOverride || npc.faction || "");
      npc.spriteId = typeof record.spriteId === "string"
        ? record.spriteId
        : String(record.spriteIdOverride || npc.spriteId || "");
      npc.dialogueId = String(record.dialogueId || record.dialogueIdOverride || npc.dialogueId || "");
      npc.description = String(record.description || npc.description || "");
      npc.x = toFiniteNumber(pos.x ?? npc.x, 0);
      npc.y = toFiniteNumber(pos.y ?? npc.y, 0);
      const spriteEntry = spriteCatalog[npc.spriteId] || null;
      npc.dataUrl = spriteEntry ? spriteEntry.dataUrl : null;
      npc.spriteWidth = spriteEntry ? spriteEntry.spriteWidth : 28;
      npc.spriteHeight = spriteEntry ? spriteEntry.spriteHeight : 28;
    }

    function captureState() {
      return historyController.captureState();
    }

    function applyState(state) {
      return historyController.applyState(state);
    }

    function getStateSignature(state) {
      return historyController.getStateSignature(state);
    }

    function getVisibleNpcOverlays() {
      return npcController.getVisibleNpcOverlays();
    }

    function setStatus(message, isError, options) {
      return sidebarController.setStatus(message, isError, options);
    }

    function setSidebarTab(tab) {
      return sidebarController.setSidebarTab(tab);
    }

    function refreshInformationPanel() {
      return sidebarController.refreshInformationPanel();
    }

    function refreshBackgroundModeButton() {
      return sidebarController.refreshBackgroundModeButton();
    }

    function cycleBackgroundCellMode() {
      return sidebarController.cycleBackgroundCellMode();
    }

    function refreshInformationDraftState() {
      return sidebarController.refreshInformationDraftState();
    }

    function cancelDimensionEdit(field) {
      return sidebarController.cancelDimensionEdit(field);
    }

    function handleDimensionKeydown(field, event) {
      return sidebarController.handleDimensionKeydown(field, event);
    }

    function cancelInformationEdits() {
      return sidebarController.cancelInformationEdits();
    }

    function applyInformationEdits(options) {
      return sidebarController.applyInformationEdits(options);
    }

    function openTilePaletteContextMenu(tileId, tile, event, options) {
      return sidebarController.openTilePaletteContextMenu(tileId, tile, event, options);
    }

    function getNpcCatalogRecords() {
      return npcController.getNpcCatalogRecords();
    }

    function hasUnsavedChanges() {
      return sidebarController.hasUnsavedChanges();
    }

    function getDialogueCatalogRecords() {
      return npcController.getDialogueCatalogRecords();
    }

    function getFactionRecords() {
      return npcController.getFactionRecords();
    }

    function getSpriteCatalogRecords() {
      return npcController.getSpriteCatalogRecords();
    }

    function applyNpcEditorChange(npc, mutator, statusLabel) {
      return npcController.applyNpcEditorChange(npc, mutator, statusLabel);
    }

    function ensureNpcImageLoaded(npc) {
      return npcController.ensureNpcImageLoaded(npc);
    }

    function getCachedImage(cacheKey, dataUrl) {
      return npcController.getCachedImage(cacheKey, dataUrl);
    }

    function assignNpcToSlot(slotId, assignedTemplateId) {
      return npcController.assignNpcToSlot(slotId, assignedTemplateId);
    }

    function openPlacedEntityContextMenu(npc, event, options) {
      return npcController.openPlacedEntityContextMenu(npc, event, options);
    }

    function renderNpcList() {
      return npcController.renderNpcList();
    }

    function centerViewportOnNpc(npc) {
      return npcController.centerViewportOnNpc(npc);
    }

    function selectTile(tileX, tileY) {
      return interactionController.selectTile(tileX, tileY);
    }

    function selectNpc(npc) {
      return npcController.selectNpc(npc);
    }

    function removeNpcInstanceById(instanceId, sourceLabel) {
      return npcController.removeNpcInstanceById(instanceId, sourceLabel);
    }

    function findPlacedNpcByTemplateId(templateId) {
      return npcController.findPlacedNpcByTemplateId(templateId);
    }

    function getTileEntry(ch) {
      return tileCatalog[ch] || {
        id: ch,
        symbol: ch,
        name: ch === " " ? "Space" : ch,
        color: tileColors[ch] || defaultTileColor,
        dataUrl: null,
        width: 1,
        height: 1,
        pixelScale: 1,
        opacity: 1,
        rows: [],
        tags: [],
      };
    }

    function getPaintableTileIds() {
      const ids = Object.keys(tileCatalogById).filter((id) => id !== " ");
      if (ids.length > 0) {
        return ids;
      }
      return ["."];
    }

    function getTileEntryById(tileId) {
      const normalizedId = String(tileId || "").trim();
      return tileCatalogById[normalizedId] || tileCatalogById["."] || {
        id: normalizedId || ".",
        symbol: ".",
        name: "Empty",
        color: defaultTileColor,
        dataUrl: null,
        width: 1,
        height: 1,
        pixelScale: 1,
        opacity: 1,
        rows: [],
        tags: [],
      };
    }

    function getBackgroundTileEntry() {
      return mapDocument.backgroundTileId ? getTileEntryById(mapDocument.backgroundTileId) : null;
    }

    function getBackgroundTileSymbol() {
      const entry = getBackgroundTileEntry();
      return entry ? (String(entry.symbol || ".").charAt(0) || ".") : "";
    }

    function getBrushSymbol() {
      const entry = getTileEntryById(popupSessionStore.state.activeBrushTileId);
      const symbol = String(entry.symbol || ".").charAt(0);
      return symbol || ".";
    }

    function describeBrushTileId(tileId) {
      const entry = getTileEntryById(tileId);
      const symbol = String(entry.symbol || ".").charAt(0) || ".";
      const name = String(entry.name || "").trim();
      if (name && name !== symbol) {
        return tileId + " (" + symbol + " / " + name + ")";
      }
      return tileId + " (" + symbol + ")";
    }

    function describeTileSymbol(ch) {
      const tile = getTileEntry(ch);
      const symbolLabel = ch === " " ? "space" : ch;
      if (tile && tile.name && tile.name !== symbolLabel) {
        return symbolLabel + " (" + tile.name + ")";
      }
      return symbolLabel;
    }

    function formatCellCoord(cell) {
      return historyController.formatCellCoord(cell);
    }

    function getLayerByNumber(layerNumber) {
      return documentController.getLayerByNumber(layerNumber);
    }

    function getDefaultEditableLayerNumber() {
      return documentController.getDefaultEditableLayerNumber();
    }

    function getLayerDefaultName(layerNumber) {
      return documentController.getLayerDefaultName(layerNumber);
    }

    function getLayerDisplayName(layerOrNumber) {
      return documentController.getLayerDisplayName(layerOrNumber);
    }

    function isBackgroundLayer(layerNumber) {
      return documentController.isBackgroundLayer(layerNumber);
    }

    function cloneHeightLayers(source) {
      return documentController.cloneHeightLayers(source);
    }

    function getHeightLayerById(heightLayerId) {
      return documentController.getHeightLayerById(heightLayerId);
    }

    function getHeightLayerDisplayName(heightLayerOrId) {
      return documentController.getHeightLayerDisplayName(heightLayerOrId);
    }

    function formatHistoryLabel(entry) {
      return historyController.formatHistoryLabel(entry);
    }

    function renderHistoryPreview() {
      return historyController.renderHistoryPreview();
    }

    function renderHistoryList() {
      return historyController.renderHistoryList();
    }

    function refreshToolbarState(preserveCurrentStatus) {
      return historyController.refreshToolbarState(preserveCurrentStatus);
    }

    function registerHistory(label, before, after, details, options) {
      return historyController.registerHistory(label, before, after, details, options);
    }

    function undo() {
      return historyController.undo();
    }

    function redo() {
      return historyController.redo();
    }

    async function saveCurrentState() {
      return persistenceController.saveCurrentState();
    }

    function openHeightViewerWindow() {
      const token = createWorldshaperStudioToken();
      registerWorldshaperStudioBootstrap(token, buildCurrentBootstrapSnapshot(), window);
      const popup = openWorldshaperHeightViewerWindow(currentMapId, token, window);
      if (!popup) {
        setStatus("Worldshaper Height Viewer unavailable: viewer window was blocked.", true);
        return null;
      }
      window.setTimeout(() => {
        clearWorldshaperStudioBootstrap(token, window);
      }, 60_000);
      setStatus("Opened height viewer for " + currentMapId + ".", false);
      return popup;
    }

    const uiImageCache = {};
    const npcImages = {};

    function getCanvasPoint(event) {
      return renderController.getCanvasPoint(event);
    }

    function findTopNpcAtCanvas(canvasX, canvasY) {
      return renderController.findTopNpcAtCanvas(canvasX, canvasY);
    }

    function uiIconEl(slug, fallbackText, size) {
      return renderController.uiIconEl(slug, fallbackText, size);
    }

    function normalizeRows(rows, fillChar) {
      return documentController.normalizeRows(rows, fillChar);
    }

    function ensureBaseLayer() {
      return documentController.ensureBaseLayer();
    }

    function syncLayerVisibilityState() {
      popupSessionStore.syncLayerVisibility(mapDocument.roomLayers);
    }

    function setLayerVisibility(layerNumber, isVisible) {
      popupSessionStore.setLayerVisibility(layerNumber, isVisible, mapDocument.roomLayers);
    }

    function isLayerVisible(layerNumber) {
      return popupSessionStore.isLayerVisible(layerNumber, mapDocument.roomLayers);
    }

    function isLayerRendered(layerNumber) {
      const normalizedLayer = Number(layerNumber) || 0;
      if (!popupSessionStore.state.viewingAllLayers && normalizedLayer === (Number(popupSessionStore.state.activeLayer) || 0)) {
        return true;
      }
      return isLayerVisible(normalizedLayer);
    }

    function getEditableLayerNumber() {
      const currentLayer = Number(popupSessionStore.state.activeLayer) || 0;
      const hasCurrentLayer = mapDocument.roomLayers.some((layer) => (Number(layer.layer) || 0) === currentLayer);
      if (popupSessionStore.state.viewingAllLayers) {
        return hasCurrentLayer ? currentLayer : getDefaultEditableLayerNumber();
      }
      return hasCurrentLayer ? currentLayer : getDefaultEditableLayerNumber();
    }

    function ensureActiveHeightLayerSelection() {
      const currentId = String(popupSessionStore.state.activeHeightLayerId || "").trim();
      if (currentId && mapDocument.heightLayers.some((entry) => String(entry?.id || "").trim() === currentId)) {
        return currentId;
      }
      const firstId = String(mapDocument.heightLayers[0]?.id || "").trim();
      popupSessionStore.state.activeHeightLayerId = firstId;
      if (!firstId && popupSessionStore.state.editingTargetKind === "height") {
        popupSessionStore.state.editingTargetKind = "room";
      }
      return firstId;
    }

    function getActiveHeightLayer() {
      const activeId = ensureActiveHeightLayerSelection();
      return activeId ? getHeightLayerById(activeId) : null;
    }

    function isEditingHeightLayer() {
      return popupSessionStore.state.editingTargetKind === "height" && !!getActiveHeightLayer();
    }

    function setEditingTargetKind(nextKind, heightLayerId) {
      const normalizedKind = nextKind === "height" ? "height" : "room";
      if (normalizedKind === "height") {
        const requestedId = String(heightLayerId || popupSessionStore.state.activeHeightLayerId || "").trim();
        const resolvedEntry = requestedId ? getHeightLayerById(requestedId) : null;
        const fallbackEntry = resolvedEntry || mapDocument.heightLayers[0] || null;
        if (!fallbackEntry) {
          popupSessionStore.state.editingTargetKind = "room";
          popupSessionStore.state.activeHeightLayerId = "";
          return "room";
        }
        popupSessionStore.state.activeHeightLayerId = String(fallbackEntry.id || "").trim();
        popupSessionStore.state.editingTargetKind = "height";
        return "height";
      }
      popupSessionStore.state.editingTargetKind = "room";
      return "room";
    }

    function moveLayerToDepth(sourceLayerNumber, targetLayerNumber, position) {
      return documentController.moveLayerToDepth(sourceLayerNumber, targetLayerNumber, position);
    }

    function moveHeightLayerToDepth(sourceHeightLayerId, targetHeightLayerId, position) {
      return documentController.moveHeightLayerToDepth(sourceHeightLayerId, targetHeightLayerId, position);
    }

    function renderPaintPalette() {
      return sidebarController.renderPaintPalette();
    }

    function addHeightLayer() {
      return sidebarController.addHeightLayer();
    }

    function renderHeightLayerList() {
      return sidebarController.renderHeightLayerList();
    }

    function renderInstancePalette() {
      return sidebarController.renderInstancePalette();
    }

    function refreshEntityTypeTabs() {
      return sidebarController.refreshEntityTypeTabs();
    }

    function setActiveEntityCategory(nextType, options) {
      return sidebarController.setActiveEntityCategory(nextType, options);
    }

    function getTileIdForCell(layerNumber, tileX, tileY) {
      return sidebarController.getTileIdForCell(layerNumber, tileX, tileY);
    }

    function getRowFillChar(layerNumber) {
      return interactionController.getRowFillChar(layerNumber);
    }

    function setTileCharAt(layerNumber, tileX, tileY, ch, tileIdOverride) {
      return interactionController.setTileCharAt(layerNumber, tileX, tileY, ch, tileIdOverride);
    }

    function findOpenNpcSpawnTile() {
      return npcController.findOpenNpcSpawnTile();
    }

    function getNpcEntityType(npc) {
      return npcController.getNpcEntityType(npc);
    }

    function normalizeEntityType(value, fallback) {
      return npcController.normalizeEntityType(value, fallback);
    }

    function getEntityTypeLabel(value) {
      return npcController.getEntityTypeLabel(value);
    }

    function setNpcCatalogEntityType(templateId, nextType) {
      return npcController.setNpcCatalogEntityType(templateId, nextType);
    }

    function createNewNpc() {
      return npcController.createNewNpc();
    }

    function beginPaintStroke(tileX, tileY) {
      return interactionController.beginPaintStroke(tileX, tileY);
    }

    function paintStrokeAt(tileX, tileY) {
      return interactionController.paintStrokeAt(tileX, tileY);
    }

    function finalizePaintStroke() {
      return interactionController.finalizePaintStroke();
    }

    function draw() {
      return renderController.draw();
    }

    function drawNow() {
      return renderController.drawNow();
    }

    function invalidateTileSurface(reason, options) {
      return renderController.invalidateTileSurface(reason, options);
    }

    function patchTileSurfaceCell(tileX, tileY, reason) {
      return renderController.patchTileSurfaceCell(tileX, tileY, reason);
    }

    function renderLayerList() {
      return sidebarController.renderLayerList();
    }

    function refreshMenuLayerSelect() {
      return sidebarController.refreshMenuLayerSelect();
    }

    function handleMenuLayerSelectionChange() {
      return sidebarController.handleMenuLayerSelectionChange();
    }

    function renderTriggerList() {
      return sidebarController.renderTriggerList();
    }

    function renderMonsterList() {
      return sidebarController.renderMonsterList();
    }

    function renderPathList() {
      return sidebarController.renderPathList();
    }

    function renderTransitionList() {
      return sidebarController.renderTransitionList();
    }

    function toggleTemplateSection() {
      return sidebarController.toggleTemplateSection();
    }

    function togglePlacedSection() {
      return sidebarController.togglePlacedSection();
    }

    function toggleDrawLayerSection() {
      return sidebarController.toggleDrawLayerSection();
    }

    function toggleHeightLayerSection() {
      return sidebarController.toggleHeightLayerSection();
    }

    function refreshLayerSectionState() {
      return sidebarController.refreshLayerSectionState();
    }

    function refreshInstanceSectionState() {
      return sidebarController.refreshInstanceSectionState();
    }

    function collapseActiveSidebarTabSections() {
      return sidebarController.collapseActiveSidebarTabSections();
    }

    async function persistContentPayload(type, payload) {
      return persistenceController.persistContentPayload(type, payload);
    }

    function refreshImportControls() {
      return importController.refreshImportControls();
    }

    function toggleExperimentalImportPanel() {
      return importController.toggleExperimentalImportPanel();
    }

    function openImportDialog(type) {
      return importController.openImportDialog(type);
    }

    async function handleImportSelection(type) {
      return importController.handleImportSelection(type);
    }

    function openJsonImportModal() {
      return importController.openJsonImportModal();
    }

    function closeJsonImportModal() {
      return importController.closeJsonImportModal();
    }

    async function submitJsonImport() {
      return importController.submitJsonImport();
    }

    function applyMapInformationEditsToDocument(nextState) {
      return documentController.applyMapInformationEdits(nextState);
    }

    function ensureDocumentContentPayload(type, fallback) {
      return documentController.ensureContentPayload(type, fallback);
    }

    function setDocumentContentPayload(type, payload) {
      return documentController.setContentPayload(type, payload);
    }

    function replaceObjectContents(target, nextValue) {
      Object.keys(target || {}).forEach((key) => {
        delete target[key];
      });
      Object.assign(target, cloneValue(nextValue) || {});
      return target;
    }

    function applyContentPayloadToRuntime(type, payload, options) {
      const normalizedType = String(type || "").trim();
      const config = options && typeof options === "object" ? options : {};
      const isGraphicsPayload = normalizedType === "images" || normalizedType === "tiles" || normalizedType === "sprites";
      if (normalizedType === "images") {
        syncRuntimeGraphicsFromImagesPayload(payload, config);
      } else if (normalizedType === "tiles") {
        const nextImagesPayload = mergeImagesPayloadWithTilesPayload(getImagesPayload(), payload);
        syncRuntimeGraphicsFromImagesPayload(nextImagesPayload, config);
      } else if (normalizedType === "sprites") {
        const nextImagesPayload = mergeImagesPayloadWithSpritesPayload(getImagesPayload(), payload);
        syncRuntimeGraphicsFromImagesPayload(nextImagesPayload, config);
      } else {
        setDocumentContentPayload(normalizedType, cloneValue(payload) || {});
      }

      if (!config.deferRefresh) {
        if (isGraphicsPayload) {
          renderController.drawNow();
        } else {
          renderController.draw();
        }
      }

      return mapDocument.contentBundle[normalizedType];
    }

    function syncRuntimeCatalogs(nextBootstrap) {
      replaceObjectContents(tileCatalogById, applyTileCatalogVisualRevision(buildTileCatalogByIdFromBootstrap(nextBootstrap)));
      replaceObjectContents(spriteCatalog, applySpriteCatalogVisualRevision(buildSpriteCatalogFromBootstrap(nextBootstrap)));
      replaceObjectContents(defaultNpcTemplate, nextBootstrap.defaultNpcTemplate || {});
      replaceObjectContents(tileCatalog, buildMergedTileCatalog());
    }

    function resetSessionStateForLoadedMap() {
      popupSessionStore.state.activeLayer = 1;
      popupSessionStore.state.viewingAllLayers = false;
      popupSessionStore.state.visibleLayersById = {};
      popupSessionStore.state.pan.isPanning = false;
      popupSessionStore.state.pan.startX = 0;
      popupSessionStore.state.pan.startY = 0;
      popupSessionStore.state.pan.scrollLeft = 0;
      popupSessionStore.state.pan.scrollTop = 0;
      popupSessionStore.state.draggingNpc = null;
      popupSessionStore.state.pointerCandidate = null;
      popupSessionStore.state.paintingStroke = null;
      popupSessionStore.state.dragDrawX = 0;
      popupSessionStore.state.dragDrawY = 0;
      popupSessionStore.state.isSaving = false;
      popupSessionStore.state.activeInstanceBrushId = "";
      popupSessionStore.state.activeGraphicsTab = "tiles";
      popupSessionStore.state.activeGraphicsRecordId = "";
      popupSessionStore.state.hoverTileX = -1;
      popupSessionStore.state.hoverTileY = -1;
      popupSessionStore.state.selectedNpcId = mapDocument.npcOverlays[0] ? String(mapDocument.npcOverlays[0].id || "") : "";
      popupSessionStore.state.selectedTile = null;
      popupSessionStore.state.spritePickerOpenNpcId = "";
      popupSessionStore.state.hoveredNpcId = "";
      popupSessionStore.state.organizedListDrag = null;
      popupSessionStore.state.tileMutationBatchDepth = 0;
      popupSessionStore.state.zoomPreviewUntil = 0;
      popupSessionStore.state.scrollPreviewUntil = 0;
      popupSessionStore.state.hoverCanvasX = 0;
      popupSessionStore.state.hoverCanvasY = 0;
      popupSessionStore.state.editingTargetKind = "room";
      popupSessionStore.state.activeHeightLayerId = String(mapDocument.heightLayers[0]?.id || "").trim();
      mapDocument.heightBlurStep = Math.max(0, Math.min(1, Number(nextBootstrap.heightBlurStep ?? nextBootstrap.heightDetailStep) || 0.1));
      const paintableTileIds = getPaintableTileIds();
      if (!paintableTileIds.includes(String(popupSessionStore.state.activeBrushTileId || "").trim())) {
        popupSessionStore.state.activeBrushTileId = "";
      }
      popupSessionStore.syncLayerVisibility(mapDocument.roomLayers);
    }

    function initializeHistoryForCurrentMap() {
      scope.ensureBaseLayer();
      scope.historyEntries = [];
      scope.historyIndex = 0;
      scope.historySelectionIndex = 0;
      scope.nextHistoryId = 1;
      scope.lastSavedHistoryId = 1;
      const initialEntry = {
        id: scope.nextHistoryId,
        seq: scope.nextHistoryId,
        createdAt: Date.now(),
        label: "Initial state",
        before: "-",
        after: "-",
        details: ["Loaded initial map state."],
        state: scope.captureState(),
      };
      scope.historyEntries = [initialEntry];
      scope.historyIndex = 0;
      scope.historySelectionIndex = 0;
      scope.lastSavedHistoryId = initialEntry.id;
      scope.nextHistoryId = initialEntry.id + 1;

      const restoredHistory = scope.restoreHistoryState();
      if (!scope.applyHistorySnapshot(restoredHistory)) {
        scope.persistHistoryState();
      }
    }

    function refreshUiForLoadedMap() {
      scope.refreshInformationPanel();
      scope.refreshImportControls();
      scope.refreshInstanceSectionState();
      scope.renderPaintPalette();
      scope.renderInstancePalette();
      scope.renderLayerList();
      scope.renderNpcList();
      scope.renderMonsterList();
      scope.renderTriggerList();
      scope.renderPathList();
      scope.renderTransitionList();
      scope.setSidebarTab(scope.activeSidebarTab || "information");
      scope.refreshToolbarState();
      if (viewport) {
        viewport.scrollLeft = 0;
        viewport.scrollTop = 0;
      }
      scope.drawNow();
    }

    const scope = {
      mapId: currentMapId,
      tileCatalogById,
      tileCatalog,
      tileColors,
      contentBundle: mapDocument.contentBundle,
      spriteCatalog,
      defaultNpcTemplate,
      apiBase,
      npcOverlays: mapDocument.npcOverlays,
      atTooltip,
      pan: popupSessionStore.state.pan,
        uiImageCache,
        npcImages,
        historyStorageKey: currentHistoryStorageKey,
        popupBoundsStorageKey,
      layerListEl,
      paintPaletteEl,
      instancePaletteEl,
      npcListEl,
      newNpcBtn,
      newTileFolderBtn,
      newTileBtn,
      tileSearchModeBtn,
      graphicsTilesBtn,
      graphicsSpritesBtn,
      graphicsOtherBtn,
      newTemplateFolderBtn,
      newPlacedFolderBtn,
      entitySearchModeBtn,
      entitySearchModeHost,
      entityTypeFriendlyBtn,
      entityTypeHostileBtn,
      entityTypePropBtn,
      newMonsterFolderBtn,
      newTriggerFolderBtn,
      newPathFolderBtn,
      newTransitionFolderBtn,
      toggleTemplateSectionBtn,
      togglePlacedSectionBtn,
      instanceTemplateSectionBody,
      placedInstanceSectionBody,
      entityCatalogSection,
      placedEntitiesSection,
      monsterListEl,
      triggerListEl,
      pathListEl,
      transitionListEl,
      metaEl,
      metaMainEl,
      metaStatsEl,
      historyListEl,
      historyCurrentEl,
      historyPreviewEl,
      undoBtn,
      redoBtn,
      saveBtn,
      testHeightBtn,
      menuLayerSelectEl,
      saveStatusEl,
      themePresetButtons,
      informationTabBtn,
      layersTabBtn,
      tilesTabBtn,
      instancesTabBtn,
      triggersTabBtn,
      pathsTabBtn,
      transitionsTabBtn,
      historyTabBtn,
      newsTabBtn,
      editorBodyEl,
      sidebarEl,
      sidebarTabsEl,
      sidebarPanelsHostEl,
      informationPanel,
      layersPanel,
      tilesPanel,
      instancesPanel,
      triggersPanel,
      pathsPanel,
      transitionsPanel,
      historyPanel,
      drawLayerSectionBody,
      heightLayerSectionBody,
      toggleDrawLayerSectionBtn,
      toggleHeightLayerSectionBtn,
      informationSettingsSectionBody,
      informationConfigurationSectionBody,
      informationHotkeysSectionBody,
      toggleInformationSettingsSectionBtn,
      toggleInformationConfigurationSectionBtn,
      toggleInformationHotkeysSectionBtn,
      mapIdLockedEl,
      mapNameInputEl,
      mapWidthInputEl,
      mapHeightInputEl,
      mapBackgroundColorInputEl,
      engineOverridesBtn,
      engineOverridesSummaryEl,
      backgroundModeBtn,
      backgroundModePreviewEl,
      backgroundModeTitleEl,
      backgroundModeMetaEl,
      experimentalImportToggleBtn,
      experimentalImportCheckEl,
      experimentalImportBodyEl,
      importSpritesBtn,
      importTilesBtn,
      importJsonBtn,
      importSpritesInputEl,
      importTilesInputEl,
      importJsonModal,
      importJsonTypeSelect,
      importJsonTextarea,
      importJsonConfirmBtn,
      importJsonCancelBtn,
      mapWidthValueEl,
      mapHeightValueEl,
      mapWidthControlsEl,
      mapHeightControlsEl,
      confirmWidthBtn,
      cancelWidthBtn,
      confirmHeightBtn,
      cancelHeightBtn,
      restoreToolWindowsBtn,
      resetWorkspaceLayoutBtn,
      addHeightLayerBtn,
      heightLayerListEl,
      stageEl,
      canvasSelectToolBtn,
      toolWindowLayerEl,
      viewport,
      viewportSpacer,
      pixiHost,
      canvas,
      ctx,
      runtimeEscapeHtml,
      persistHistoryState,
      restoreHistoryState,
      applyHistorySnapshot,
      resetWindowPosition,
      resetWorkspaceLayout,
      persistPopupSessionLayout: () => popupSessionStore.persistPersistedLayoutDeferred(window),
      flushPersistedPopupSessionLayout: () => popupSessionStore.flushPersistedLayout(window),
      clearPersistedPopupSessionLayout: () => popupSessionStore.clearPersistedLayout(window),
      getPersistedToolWindowState: (key) => popupSessionStore.getToolWindowState(key),
      setPersistedToolWindowState: (key, value) => popupSessionStore.setToolWindowState(key, value),
      normalizeMapBackgroundColor,
      cloneLayers,
      cloneHeightLayers,
      cloneNpcOverlays,
      cloneEditorUiState,
      normalizeRows,
      toCellKey,
      getLayerByNumber,
      getLayerDefaultName,
      getLayerDisplayName,
      isBackgroundLayer,
      getHeightLayerById,
      getHeightLayerDisplayName,
      getActiveHeightLayer,
      isEditingHeightLayer,
      setEditingTargetKind,
      syncNpcOverlayFromRecord,
      ensureBaseLayer,
      syncLayerVisibilityState,
      setLayerVisibility,
      isLayerVisible,
      isLayerRendered,
      getEditableLayerNumber,
      moveLayerToDepth,
      moveHeightLayerToDepth,
      beginTileInstanceMutationBatch,
      endTileInstanceMutationBatch,
      runtimeUniqueId,
      uiIconEl,
      draw,
      drawNow,
      invalidateTileSurface,
      patchTileSurfaceCell,
      setStatus,
      setSidebarTab,
      refreshInformationPanel,
      refreshBackgroundModeButton,
      cycleBackgroundCellMode,
      resetWorkspaceLayout: null,
      restoreAllToolWindows: null,
      openTileArtEditorWindow: null,
      closeTileArtEditorWindow: null,
      openEntityEditorWindow: null,
      closeEntityEditorWindow: null,
      openWorldOverviewWindow: null,
      closeWorldOverviewWindow: null,
      refreshWorldOverviewWindow: null,
      openStatusLogWindow: null,
      closeStatusLogWindow: null,
      openTilePaletteContextMenu: null,
      openPlacedEntityContextMenu: null,
      addHeightLayer,
      renderPaintPalette,
      renderHeightLayerList,
      renderInstancePalette,
      refreshEntityTypeTabs,
      setActiveEntityCategory,
      renderLayerList,
      refreshMenuLayerSelect,
      handleMenuLayerSelectionChange,
      renderTriggerList,
      renderMonsterList,
      renderPathList,
      renderTransitionList,
      collapseActiveSidebarTabSections,
      toggleDrawLayerSection,
      toggleHeightLayerSection,
      toggleTemplateSection,
      togglePlacedSection,
      refreshLayerSectionState,
      refreshInstanceSectionState,
      renderNpcList,
      getPanelLayout,
      setPanelLayout,
      createPanelFolder,
      togglePanelFolder,
      renamePanelFolder,
      deletePanelFolder,
      movePanelNode,
      refreshInformationDraftState,
      getVisibleNpcOverlays,
      getNpcCatalogRecords,
      getDialogueCatalogRecords,
      getFactionRecords,
      getSpriteCatalogRecords,
      getNpcEntityType,
      normalizeEntityType,
      getEntityTypeLabel,
      hasUnsavedChanges,
      cacheStandaloneMapBootstrap,
      getCachedImage,
      assignNpcToSlot,
      setNpcCatalogEntityType,
      getTileIdForCell,
      getTileEntry,
      getBackgroundTileEntry,
      getBackgroundTileSymbol,
      getCanvasPoint,
      findTopNpcAtCanvas,
      centerViewportOnNpc,
      setTileCharAt,
      selectTile,
      selectNpc,
      removeNpcInstanceById,
      ensureNpcImageLoaded,
      findPlacedNpcByTemplateId,
      saveCurrentState,
      openHeightViewerWindow,
      persistContentPayload,
      undo,
      redo,
      cancelDimensionEdit,
      applyInformationEdits,
      handleDimensionKeydown,
      createNewNpc,
      deleteTileEverywhere,
      deleteSpriteEverywhere,
      createNewSpriteGraphic,
      duplicateGraphicRecord,
      assignGraphicToCategory,
      syncGraphicCounterpartFromRecord,
      appendEditorLogEntry,
      getEditorLogEntries,
      clearEditorLogEntries,
      getBrushSymbol,
      captureState,
      registerHistory,
      refreshToolbarState,
      refreshImportControls,
      toggleExperimentalImportPanel,
      openImportDialog,
      handleImportSelection,
      openJsonImportModal,
      closeJsonImportModal,
      submitJsonImport,
      applyMapInformationEditsToDocument,
      ensureDocumentContentPayload,
      setDocumentContentPayload,
      applyThemePreset,
      refreshThemePresetButtons,
      getPaintableTileIds,
      getTileEntryById,
      normalizeBackgroundTileId,
      backgroundCellModeOrder: ["tile", "hole", "inherit"],
      getRowFillChar,
      describeBrushTileId,
      describeTileSymbol,
      formatCellCoord,
      defaultTileColor,
      getScaledSize,
      getZoomPercent,
      applyZoomLevel,
      startZoomPreview,
      isZoomPreviewActive,
      startScrollPreview,
      isScrollPreviewActive,
      centerViewportOnWorldPoint,
      getViewportCenterWorldTile,
      centerViewportOnWorldTile,
      isWorldModeActive,
      ensureWorldDocumentCurrent,
      getVisibleWorldChunkPayloads,
      getWorldChunkCoordForLocalTile,
      getCachedWorldChunk,
      getWorldChunkBackgroundTileId,
      getBackgroundTileIdForLocalTile,
      setWorldChunkBackgroundTileId,
      getPreferredWorldChunkCoord,
      getSelectedWorldChunkCoord,
      captureWorldChunkBackgroundState,
      applyWorldChunkBackgroundState,
      captureWorldBookmarkState,
      applyWorldBookmarkState,
      getWorldBookmarks,
      createWorldBookmark,
      renameWorldBookmark,
      deleteWorldBookmark,
      applyWorldChunkBackgroundTileAt,
      moveWorldChunkContent,
      duplicateWorldChunkContent,
      transformWorldChunkAt,
      clearWorldChunkAt,
      getCachedWorldChunkPayloads: () => Array.from(worldRuntimeState.chunkCache.values()).map((entry) => cloneValue(entry)),
      getDirtyWorldChunkKeys,
      getDirtyWorldChunkPayloads,
      clearDirtyWorldChunks,
      markWorldChunkDirty,
      markWorldChunkDirtyByLocalTile,
      markWorldChunksDirtyByLocalBounds,
      markVisibleWorldChunksDirty,
      cacheWorldChunks,
      syncCachedWorldHeightLayerMetadata,
      syncCachedWorldRoomLayerMetadata,
      syncWorldChunkCellFromLocalTile,
      rebuildVisibleWorldChunksFromDocument,
      rebuildWorldChunksForLocalBounds,
      syncWorldNeighborhoodForViewport,
      loadWorldNeighborhoodAtChunk,
      syncViewportDimensions: syncCanvasDimensionsToTileSize,
    };
    Object.defineProperties(scope, {
      width: { get: () => mapDocument.width, set: (value) => { mapDocument.width = Math.max(1, Number(value) || 1); } },
      height: { get: () => mapDocument.height, set: (value) => { mapDocument.height = Math.max(1, Number(value) || 1); } },
      baseTileSize: { get: () => baseTileSize },
      tileSize: { get: () => tileSize, set: (value) => { tileSize = Math.max(8, Number(value) || baseTileSize); } },
      zoomLevel: { get: () => zoomLevel, set: (value) => { zoomLevel = clampZoomLevel(value); tileSize = Math.max(8, Math.round(baseTileSize * zoomLevel)); } },
      minZoomLevel: { get: () => minZoomLevel },
      maxZoomLevel: { get: () => maxZoomLevel },
      worldTileOffsetX: { get: () => worldRuntimeState.tileOffsetX },
      worldTileOffsetY: { get: () => worldRuntimeState.tileOffsetY },
      worldChunkWidth: { get: () => worldRuntimeState.chunkWidth },
      worldChunkHeight: { get: () => worldRuntimeState.chunkHeight },
      worldOriginChunkX: { get: () => worldRuntimeState.originChunkX },
      worldOriginChunkY: { get: () => worldRuntimeState.originChunkY },
      worldSpawnX: { get: () => worldRuntimeState.spawnX, set: (value) => { worldRuntimeState.spawnX = Math.floor(Number(value) || 0); } },
      worldSpawnY: { get: () => worldRuntimeState.spawnY, set: (value) => { worldRuntimeState.spawnY = Math.floor(Number(value) || 0); } },
      worldId: { get: () => worldRuntimeState.worldId, set: (value) => { worldRuntimeState.worldId = String(value || "").trim(); } },
      worldName: { get: () => worldRuntimeState.worldName, set: (value) => { worldRuntimeState.worldName = String(value || "").trim() || "World"; } },
      roomLayers: { get: () => mapDocument.roomLayers, set: (value) => { mapDocument.roomLayers = value; invalidateTileSurface("room-layers-replaced"); } },
      heightLayers: { get: () => mapDocument.heightLayers, set: (value) => { mapDocument.heightLayers = cloneHeightLayers(value); draw(); } },
      activeLayer: { get: () => popupSessionStore.state.activeLayer, set: (value) => { popupSessionStore.state.activeLayer = value; } },
      viewingAllLayers: { get: () => popupSessionStore.state.viewingAllLayers, set: (value) => { popupSessionStore.state.viewingAllLayers = value; } },
      activeSidebarTab: { get: () => popupSessionStore.state.activeSidebarTab, set: (value) => { popupSessionStore.state.activeSidebarTab = value; } },
      mapId: { get: () => currentMapId, set: (value) => { currentMapId = String(value || "").trim(); } },
      historyStorageKey: { get: () => currentHistoryStorageKey, set: (value) => { currentHistoryStorageKey = String(value || "").trim(); } },
      mapName: { get: () => mapDocument.mapName, set: (value) => { mapDocumentStore.setMapName(value, currentMapId); syncDocumentTitle(); } },
      backgroundColor: { get: () => mapDocument.backgroundColor, set: (value) => { mapDocument.backgroundColor = value; } },
      backgroundTileId: { get: () => mapDocument.backgroundTileId, set: (value) => { mapDocumentStore.setBackgroundTileId(value, normalizeBackgroundTileId); invalidateTileSurface("background-tile-changed"); } },
      heightBlurStep: {
        get: () => Math.max(0, Math.min(1, Number(mapDocument.heightBlurStep ?? mapDocument.heightDetailStep) || 0.1)),
        set: (value) => { mapDocument.heightBlurStep = Math.max(0, Math.min(1, Number(value) || 0.1)); },
      },
      backgroundCellMode: { get: () => mapDocument.backgroundCellMode, set: (value) => { mapDocumentStore.setBackgroundCellMode(value, ["tile", "hole", "inherit"]); } },
      mapInfoDraft: { get: () => mapDocument.mapInfoDraft, set: (value) => { mapDocument.mapInfoDraft = value; } },
      activeBrushTileId: { get: () => popupSessionStore.state.activeBrushTileId, set: (value) => { popupSessionStore.state.activeBrushTileId = value; } },
      activeGraphicsTab: { get: () => popupSessionStore.state.activeGraphicsTab, set: (value) => { popupSessionStore.state.activeGraphicsTab = String(value || "").trim() || "tiles"; } },
      activeGraphicsRecordId: { get: () => popupSessionStore.state.activeGraphicsRecordId, set: (value) => { popupSessionStore.state.activeGraphicsRecordId = String(value || "").trim(); } },
      canvasToolMode: {
        get: () => popupSessionStore.state.canvasToolMode === "select" ? "select" : "paint",
        set: (value) => { popupSessionStore.state.canvasToolMode = value === "select" ? "select" : "paint"; },
      },
      editingTargetKind: { get: () => popupSessionStore.state.editingTargetKind, set: (value) => { setEditingTargetKind(value, popupSessionStore.state.activeHeightLayerId); } },
      activeHeightLayerId: {
        get: () => popupSessionStore.state.activeHeightLayerId,
        set: (value) => {
          const normalized = String(value || "").trim();
          popupSessionStore.state.activeHeightLayerId = normalized;
          ensureActiveHeightLayerSelection();
        },
      },
      activeInstanceBrushId: { get: () => popupSessionStore.state.activeInstanceBrushId, set: (value) => { popupSessionStore.state.activeInstanceBrushId = value; } },
      activeEntityCategory: { get: () => popupSessionStore.state.activeEntityCategory, set: (value) => { popupSessionStore.state.activeEntityCategory = String(value || "").trim() || "friendly"; } },
      hoverTileX: { get: () => popupSessionStore.state.hoverTileX, set: (value) => { popupSessionStore.state.hoverTileX = value; } },
      hoverTileY: { get: () => popupSessionStore.state.hoverTileY, set: (value) => { popupSessionStore.state.hoverTileY = value; } },
      pointerCandidate: { get: () => popupSessionStore.state.pointerCandidate, set: (value) => { popupSessionStore.state.pointerCandidate = value; } },
      draggingNpc: { get: () => popupSessionStore.state.draggingNpc, set: (value) => { popupSessionStore.state.draggingNpc = value; } },
      dragDrawX: { get: () => popupSessionStore.state.dragDrawX, set: (value) => { popupSessionStore.state.dragDrawX = value; } },
      dragDrawY: { get: () => popupSessionStore.state.dragDrawY, set: (value) => { popupSessionStore.state.dragDrawY = value; } },
      paintingStroke: { get: () => popupSessionStore.state.paintingStroke, set: (value) => { popupSessionStore.state.paintingStroke = value; } },
      tileMutationBatchDepth: { get: () => popupSessionStore.state.tileMutationBatchDepth },
      selectedNpcId: { get: () => popupSessionStore.state.selectedNpcId, set: (value) => { popupSessionStore.state.selectedNpcId = value; } },
      selectedTile: { get: () => popupSessionStore.state.selectedTile, set: (value) => { popupSessionStore.state.selectedTile = value; } },
      hideTileGrid: {
        get: () => popupSessionStore.state.hideTileGrid,
        set: (value) => {
          const nextValue = value === true;
          if (popupSessionStore.state.hideTileGrid === nextValue) {
            return;
          }
          popupSessionStore.state.hideTileGrid = nextValue;
          draw();
        },
      },
      showChunkBounds: {
        get: () => popupSessionStore.state.showChunkBounds,
        set: (value) => {
          const nextValue = value === true;
          if (popupSessionStore.state.showChunkBounds === nextValue) {
            return;
          }
          popupSessionStore.state.showChunkBounds = nextValue;
          draw();
        },
      },
      zoomPreviewUntil: { get: () => popupSessionStore.state.zoomPreviewUntil, set: (value) => { popupSessionStore.state.zoomPreviewUntil = Math.max(0, Number(value) || 0); } },
      scrollPreviewUntil: { get: () => popupSessionStore.state.scrollPreviewUntil, set: (value) => { popupSessionStore.state.scrollPreviewUntil = Math.max(0, Number(value) || 0); } },
      spritePickerOpenNpcId: { get: () => popupSessionStore.state.spritePickerOpenNpcId, set: (value) => { popupSessionStore.state.spritePickerOpenNpcId = value; } },
      hoveredNpcId: { get: () => popupSessionStore.state.hoveredNpcId, set: (value) => { popupSessionStore.state.hoveredNpcId = value; } },
      hoverCanvasX: { get: () => popupSessionStore.state.hoverCanvasX, set: (value) => { popupSessionStore.state.hoverCanvasX = value; } },
      hoverCanvasY: { get: () => popupSessionStore.state.hoverCanvasY, set: (value) => { popupSessionStore.state.hoverCanvasY = value; } },
      templateSectionCollapsed: { get: () => popupSessionStore.state.templateSectionCollapsed, set: (value) => { popupSessionStore.state.templateSectionCollapsed = value === true; } },
      placedSectionCollapsed: { get: () => popupSessionStore.state.placedSectionCollapsed, set: (value) => { popupSessionStore.state.placedSectionCollapsed = value === true; } },
      drawLayerSectionCollapsed: { get: () => popupSessionStore.state.drawLayerSectionCollapsed, set: (value) => { popupSessionStore.state.drawLayerSectionCollapsed = value === true; } },
      heightLayerSectionCollapsed: { get: () => popupSessionStore.state.heightLayerSectionCollapsed, set: (value) => { popupSessionStore.state.heightLayerSectionCollapsed = value === true; } },
      organizedListDrag: { get: () => popupSessionStore.state.organizedListDrag, set: (value) => { popupSessionStore.state.organizedListDrag = value; } },
      editorUiState: { get: () => editorUiStore.getState(), set: (value) => { editorUiStore.setState(value); } },
      isSaving: { get: () => popupSessionStore.state.isSaving, set: (value) => { popupSessionStore.state.isSaving = value; } },
      historyEntries: { get: () => historyState.entries, set: (value) => { historyState.entries = value; } },
      historyIndex: { get: () => historyState.index, set: (value) => { historyState.index = value; } },
      historySelectionIndex: { get: () => historyState.selectionIndex, set: (value) => { historyState.selectionIndex = value; } },
      nextHistoryId: { get: () => historyState.nextId, set: (value) => { historyState.nextId = value; } },
      lastSavedHistoryId: { get: () => historyState.lastSavedId, set: (value) => { historyState.lastSavedId = value; } },
    });

    const documentScope = {
      mapId: currentMapId,
      tileCatalogById,
      tileCatalog,
      tileColors,
      contentBundle: mapDocument.contentBundle,
      spriteCatalog,
      defaultNpcTemplate,
      apiBase,
      npcOverlays: mapDocument.npcOverlays,
      cloneLayers,
      cloneHeightLayers,
      cloneNpcOverlays,
      cloneEditorUiState,
      normalizeMapBackgroundColor,
      normalizeBackgroundTileId,
      normalizeRows,
      getLayerByNumber,
      getLayerDefaultName,
      getLayerDisplayName,
      isBackgroundLayer,
      getHeightLayerById,
      getHeightLayerDisplayName,
      getActiveHeightLayer,
      isEditingHeightLayer,
      setEditingTargetKind,
      syncNpcOverlayFromRecord,
      ensureBaseLayer,
      syncLayerVisibilityState,
      setLayerVisibility,
      isLayerVisible,
      isLayerRendered,
      getEditableLayerNumber,
      moveLayerToDepth,
      moveHeightLayerToDepth,
      applyMapInformationEditsToDocument,
      ensureDocumentContentPayload,
      setDocumentContentPayload,
      applyContentPayloadToRuntime,
      getTileEntry,
      getBackgroundTileEntry,
      getBackgroundTileSymbol,
      getPaintableTileIds,
      getTileEntryById,
      getRowFillChar,
      getBrushSymbol,
      describeBrushTileId,
      describeTileSymbol,
      setTileCharAt,
      toCellKey,
      runtimeUniqueId,
      selectTile,
      selectNpc,
      findPlacedNpcByTemplateId,
      assignNpcToSlot,
      removeNpcInstanceById,
      createNewNpc,
      deleteTileEverywhere,
      deleteSpriteEverywhere,
      createNewSpriteGraphic,
      assignGraphicToCategory,
      syncGraphicCounterpartFromRecord,
      ensureNpcImageLoaded,
      findOpenNpcSpawnTile,
      getVisibleNpcOverlays,
      getNpcCatalogRecords,
      ensureWorldDocumentCurrent,
      cacheStandaloneMapBootstrap,
      saveCurrentState,
      persistContentPayload,
      backgroundCellModeOrder: ["tile", "hole", "inherit"],
    };
    Object.defineProperties(documentScope, {
      mapId: { get: () => scope.mapId, set: (value) => { scope.mapId = value; } },
      width: { get: () => scope.width, set: (value) => { scope.width = value; } },
      height: { get: () => scope.height, set: (value) => { scope.height = value; } },
      roomLayers: { get: () => scope.roomLayers, set: (value) => { scope.roomLayers = value; } },
      heightLayers: { get: () => scope.heightLayers, set: (value) => { scope.heightLayers = value; } },
      mapName: { get: () => scope.mapName, set: (value) => { scope.mapName = value; } },
      backgroundColor: { get: () => scope.backgroundColor, set: (value) => { scope.backgroundColor = value; } },
      backgroundTileId: { get: () => scope.backgroundTileId, set: (value) => { scope.backgroundTileId = value; } },
      heightBlurStep: { get: () => scope.heightBlurStep, set: (value) => { scope.heightBlurStep = value; } },
      backgroundCellMode: { get: () => scope.backgroundCellMode, set: (value) => { scope.backgroundCellMode = value; } },
      mapInfoDraft: { get: () => scope.mapInfoDraft, set: (value) => { scope.mapInfoDraft = value; } },
      editingTargetKind: { get: () => scope.editingTargetKind, set: (value) => { scope.editingTargetKind = value; } },
      activeHeightLayerId: { get: () => scope.activeHeightLayerId, set: (value) => { scope.activeHeightLayerId = value; } },
      baseTileSize: { get: () => scope.baseTileSize },
    });

    const renderScope = {
      pixiHost,
      canvas,
      ctx,
      viewport,
      viewportSpacer,
      getCanvasPoint,
      findTopNpcAtCanvas,
      uiIconEl,
      draw,
      drawNow,
      invalidateTileSurface,
      patchTileSurfaceCell,
      getCachedImage,
      getScaledSize,
      getZoomPercent,
      applyZoomLevel,
      startZoomPreview,
      isZoomPreviewActive,
      startScrollPreview,
      isScrollPreviewActive,
      centerViewportOnWorldPoint,
      centerViewportOnNpc,
      syncViewportDimensions: syncCanvasDimensionsToTileSize,
    };

    const historyScope = {
      historyStorageKey: currentHistoryStorageKey,
      persistHistoryState,
      restoreHistoryState,
      applyHistorySnapshot,
      captureState,
      registerHistory,
      refreshToolbarState,
      undo,
      redo,
      formatCellCoord,
      formatHistoryLabel,
      renderHistoryPreview,
      renderHistoryList,
    };
      Object.defineProperties(historyScope, {
        historyStorageKey: { get: () => currentHistoryStorageKey, set: (value) => { currentHistoryStorageKey = String(value || "").trim(); } },
        historyEntries: { get: () => scope.historyEntries, set: (value) => { scope.historyEntries = value; } },
        historyIndex: { get: () => scope.historyIndex, set: (value) => { scope.historyIndex = value; } },
        historySelectionIndex: { get: () => scope.historySelectionIndex, set: (value) => { scope.historySelectionIndex = value; } },
        nextHistoryId: { get: () => scope.nextHistoryId, set: (value) => { scope.nextHistoryId = value; } },
        lastSavedHistoryId: { get: () => scope.lastSavedHistoryId, set: (value) => { scope.lastSavedHistoryId = value; } },
        isSaving: { get: () => scope.isSaving, set: (value) => { scope.isSaving = value; } },
      });

    const uiScope = {
      layerListEl,
      paintPaletteEl,
      instancePaletteEl,
      npcListEl,
      newNpcBtn,
      newTileFolderBtn,
      newTileBtn,
      tileSearchModeBtn,
      graphicsTilesBtn,
      graphicsSpritesBtn,
      graphicsOtherBtn,
      newTemplateFolderBtn,
      newPlacedFolderBtn,
      entitySearchModeBtn,
      entitySearchModeHost,
      entityTypeFriendlyBtn,
      entityTypeHostileBtn,
      entityTypePropBtn,
      newMonsterFolderBtn,
      newTriggerFolderBtn,
      newPathFolderBtn,
      newTransitionFolderBtn,
      toggleTemplateSectionBtn,
      togglePlacedSectionBtn,
      instanceTemplateSectionBody,
      placedInstanceSectionBody,
      entityCatalogSection,
      placedEntitiesSection,
      monsterListEl,
      triggerListEl,
      pathListEl,
      transitionListEl,
      metaEl,
      metaMainEl,
      metaStatsEl,
      historyListEl,
      historyCurrentEl,
      historyPreviewEl,
      undoBtn,
      redoBtn,
      saveBtn,
      testHeightBtn,
      menuLayerSelectEl,
      saveStatusEl,
      themePresetButtons,
      informationTabBtn,
      layersTabBtn,
      tilesTabBtn,
      instancesTabBtn,
      triggersTabBtn,
      pathsTabBtn,
      transitionsTabBtn,
      historyTabBtn,
      newsTabBtn,
      editorBodyEl,
      sidebarEl,
      sidebarTabsEl,
      sidebarPanelsHostEl,
      informationPanel,
      layersPanel,
      tilesPanel,
      instancesPanel,
      triggersPanel,
      pathsPanel,
      transitionsPanel,
      historyPanel,
      drawLayerSectionBody,
      heightLayerSectionBody,
      toggleDrawLayerSectionBtn,
      toggleHeightLayerSectionBtn,
      mapIdLockedEl,
      mapNameInputEl,
      mapWidthInputEl,
      mapHeightInputEl,
      mapBackgroundColorInputEl,
      engineOverridesBtn,
      engineOverridesSummaryEl,
      backgroundModeBtn,
      backgroundModePreviewEl,
      backgroundModeTitleEl,
      backgroundModeMetaEl,
      experimentalImportToggleBtn,
      experimentalImportCheckEl,
      experimentalImportBodyEl,
      importSpritesBtn,
      importTilesBtn,
      importJsonBtn,
      importSpritesInputEl,
      importTilesInputEl,
      importJsonModal,
      importJsonTypeSelect,
      importJsonTextarea,
      importJsonConfirmBtn,
      importJsonCancelBtn,
      mapWidthValueEl,
      mapHeightValueEl,
      mapWidthControlsEl,
      mapHeightControlsEl,
      confirmWidthBtn,
      cancelWidthBtn,
      confirmHeightBtn,
      cancelHeightBtn,
      addHeightLayerBtn,
      heightLayerListEl,
      stageEl,
      canvasSelectToolBtn,
      toolWindowLayerEl,
      atTooltip,
      runtimeEscapeHtml,
      setStatus,
      setSidebarTab,
      refreshInformationPanel,
      refreshBackgroundModeButton,
      cycleBackgroundCellMode,
      addHeightLayer,
      renderPaintPalette,
      renderHeightLayerList,
      renderInstancePalette,
      refreshEntityTypeTabs,
      setActiveEntityCategory,
      renderLayerList,
      refreshMenuLayerSelect,
      handleMenuLayerSelectionChange,
      renderTriggerList,
      renderMonsterList,
      renderPathList,
      renderTransitionList,
      collapseActiveSidebarTabSections,
      toggleDrawLayerSection,
      toggleHeightLayerSection,
      toggleTemplateSection,
      togglePlacedSection,
      refreshLayerSectionState,
      refreshInstanceSectionState,
      renderNpcList,
      getPanelLayout,
      setPanelLayout,
      createPanelFolder,
      togglePanelFolder,
      renamePanelFolder,
      deletePanelFolder,
      movePanelNode,
      refreshInformationDraftState,
      refreshImportControls,
      openHeightViewerWindow,
      openEntityEditorWindow: null,
      closeEntityEditorWindow: null,
      toggleExperimentalImportPanel,
      openImportDialog,
      handleImportSelection,
      openJsonImportModal,
      closeJsonImportModal,
      submitJsonImport,
      applyThemePreset,
      refreshThemePresetButtons,
      getEditorEngineOverrides,
      saveEditorEngineOverrides,
      getEffectiveHeightBlurStep,
      isRendererDebugEnabled,
    };

    const sessionScope = {
      pan: popupSessionStore.state.pan,
      uiImageCache,
      npcImages,
      popupBoundsStorageKey,
      resetWindowPosition,
      resetWorkspaceLayout,
      beginTileInstanceMutationBatch,
      endTileInstanceMutationBatch,
      hasUnsavedChanges,
      getVisibleNpcOverlays,
      persistPopupSessionLayout: () => popupSessionStore.persistPersistedLayoutDeferred(window),
      flushPersistedPopupSessionLayout: () => popupSessionStore.flushPersistedLayout(window),
      clearPersistedPopupSessionLayout: () => popupSessionStore.clearPersistedLayout(window),
      getPersistedToolWindowState: (key) => popupSessionStore.getToolWindowState(key),
      setPersistedToolWindowState: (key, value) => popupSessionStore.setToolWindowState(key, value),
    };
    Object.defineProperties(sessionScope, {
      activeLayer: { get: () => scope.activeLayer, set: (value) => { scope.activeLayer = value; } },
      viewingAllLayers: { get: () => scope.viewingAllLayers, set: (value) => { scope.viewingAllLayers = value; } },
      activeSidebarTab: { get: () => scope.activeSidebarTab, set: (value) => { scope.activeSidebarTab = value; } },
      activeBrushTileId: { get: () => scope.activeBrushTileId, set: (value) => { scope.activeBrushTileId = value; } },
      canvasToolMode: { get: () => scope.canvasToolMode, set: (value) => { scope.canvasToolMode = value; } },
      editingTargetKind: { get: () => scope.editingTargetKind, set: (value) => { scope.editingTargetKind = value; } },
      activeHeightLayerId: { get: () => scope.activeHeightLayerId, set: (value) => { scope.activeHeightLayerId = value; } },
      activeInstanceBrushId: { get: () => scope.activeInstanceBrushId, set: (value) => { scope.activeInstanceBrushId = value; } },
      activeEntityCategory: { get: () => scope.activeEntityCategory, set: (value) => { scope.activeEntityCategory = value; } },
      hoverTileX: { get: () => scope.hoverTileX, set: (value) => { scope.hoverTileX = value; } },
      hoverTileY: { get: () => scope.hoverTileY, set: (value) => { scope.hoverTileY = value; } },
      pointerCandidate: { get: () => scope.pointerCandidate, set: (value) => { scope.pointerCandidate = value; } },
      draggingNpc: { get: () => scope.draggingNpc, set: (value) => { scope.draggingNpc = value; } },
      dragDrawX: { get: () => scope.dragDrawX, set: (value) => { scope.dragDrawX = value; } },
      dragDrawY: { get: () => scope.dragDrawY, set: (value) => { scope.dragDrawY = value; } },
      paintingStroke: { get: () => scope.paintingStroke, set: (value) => { scope.paintingStroke = value; } },
      tileMutationBatchDepth: { get: () => scope.tileMutationBatchDepth },
      selectedNpcId: { get: () => scope.selectedNpcId, set: (value) => { scope.selectedNpcId = value; } },
      selectedTile: { get: () => scope.selectedTile, set: (value) => { scope.selectedTile = value; } },
      hideTileGrid: { get: () => scope.hideTileGrid, set: (value) => { scope.hideTileGrid = value; } },
      showChunkBounds: { get: () => scope.showChunkBounds, set: (value) => { scope.showChunkBounds = value; } },
      zoomPreviewUntil: { get: () => scope.zoomPreviewUntil, set: (value) => { scope.zoomPreviewUntil = value; } },
      scrollPreviewUntil: { get: () => scope.scrollPreviewUntil, set: (value) => { scope.scrollPreviewUntil = value; } },
      spritePickerOpenNpcId: { get: () => scope.spritePickerOpenNpcId, set: (value) => { scope.spritePickerOpenNpcId = value; } },
      hoveredNpcId: { get: () => scope.hoveredNpcId, set: (value) => { scope.hoveredNpcId = value; } },
      hoverCanvasX: { get: () => scope.hoverCanvasX, set: (value) => { scope.hoverCanvasX = value; } },
      hoverCanvasY: { get: () => scope.hoverCanvasY, set: (value) => { scope.hoverCanvasY = value; } },
      templateSectionCollapsed: { get: () => scope.templateSectionCollapsed, set: (value) => { scope.templateSectionCollapsed = value; } },
      placedSectionCollapsed: { get: () => scope.placedSectionCollapsed, set: (value) => { scope.placedSectionCollapsed = value; } },
      drawLayerSectionCollapsed: { get: () => scope.drawLayerSectionCollapsed, set: (value) => { scope.drawLayerSectionCollapsed = value; } },
      heightLayerSectionCollapsed: { get: () => scope.heightLayerSectionCollapsed, set: (value) => { scope.heightLayerSectionCollapsed = value; } },
      organizedListDrag: { get: () => scope.organizedListDrag, set: (value) => { scope.organizedListDrag = value; } },
      editorUiState: { get: () => scope.editorUiState, set: (value) => { scope.editorUiState = value; } },
    });

    scope.documentScope = documentScope;
    scope.renderScope = renderScope;
    scope.historyScope = historyScope;
    scope.uiScope = uiScope;
    scope.sessionScope = sessionScope;
    const toolWindowController = createToolWindowController(scope);
    const tileArtEditorWindowController = createTileArtEditorWindowController(scope);
    const entityEditorWindowController = createEntityEditorWindowController(scope);
    const engineOverrideWindowController = createEngineOverrideWindowController(scope);
    const worldOverviewWindowController = createWorldOverviewWindowController(scope);
    const changelogSplashWindowController = createChangelogSplashWindowController(scope);
    statusLogWindowController = createStatusLogWindowController(scope);
    const syncToolPanels = () => toolWindowController.syncPanels();
    const handleSidebarTabButtonClick = (tab) => toolWindowController.handleTabButtonClick(tab);
    const restoreAllToolWindows = () => toolWindowController.restoreAllWindows();
    const openTileArtEditorWindow = (recordTypeOrId, maybeRecordId) => tileArtEditorWindowController.open(recordTypeOrId, maybeRecordId);
    const closeTileArtEditorWindow = () => tileArtEditorWindowController.close();
    const openEntityEditorWindow = (entityId) => entityEditorWindowController.open(entityId);
    const closeEntityEditorWindow = () => entityEditorWindowController.close();
    const openEngineOverrideWindow = () => engineOverrideWindowController.open();
    const closeEngineOverrideWindow = () => engineOverrideWindowController.close();
    const refreshEngineOverrideWindow = () => engineOverrideWindowController.refresh();
    const refreshEngineOverrideSummary = () => engineOverrideWindowController.updateSummary();
    const openWorldOverviewWindow = () => worldOverviewWindowController.open();
    const closeWorldOverviewWindow = () => worldOverviewWindowController.close();
    const refreshWorldOverviewWindow = () => worldOverviewWindowController.refresh();
    const invalidateWorldOverviewChunkSurfaces = (chunkKeys, options) => worldOverviewWindowController.invalidateChunkSurfaces?.(chunkKeys, options);
    const openStatusLogWindow = () => statusLogWindowController.open();
    const closeStatusLogWindow = () => statusLogWindowController.close();
    const openNewsWindow = (options = {}) => changelogSplashWindowController.open({ markSeen: false, ...options });
    const resetWorkspaceLayoutFlow = () => {
      resetWorkspaceLayout();
      toolWindowController.restoreAllWindows();
      setStatus("Workspace layout reset.", false);
    };
    scope.syncToolPanels = syncToolPanels;
    scope.handleSidebarTabButtonClick = handleSidebarTabButtonClick;
    scope.restoreAllToolWindows = restoreAllToolWindows;
    scope.resetWorkspaceLayout = resetWorkspaceLayoutFlow;
    scope.createNewTile = createNewTile;
    scope.createNewSpriteGraphic = createNewSpriteGraphic;
    scope.duplicateGraphicRecord = duplicateGraphicRecord;
    scope.openTileArtEditorWindow = openTileArtEditorWindow;
    scope.closeTileArtEditorWindow = closeTileArtEditorWindow;
    scope.openEntityEditorWindow = openEntityEditorWindow;
    scope.closeEntityEditorWindow = closeEntityEditorWindow;
    scope.openEngineOverrideWindow = openEngineOverrideWindow;
    scope.closeEngineOverrideWindow = closeEngineOverrideWindow;
    scope.refreshEngineOverrideWindow = refreshEngineOverrideWindow;
    scope.refreshEngineOverrideSummary = refreshEngineOverrideSummary;
    scope.openWorldOverviewWindow = openWorldOverviewWindow;
    scope.closeWorldOverviewWindow = closeWorldOverviewWindow;
    scope.refreshWorldOverviewWindow = refreshWorldOverviewWindow;
    scope.invalidateWorldOverviewChunkSurfaces = invalidateWorldOverviewChunkSurfaces;
    scope.openStatusLogWindow = openStatusLogWindow;
    scope.closeStatusLogWindow = closeStatusLogWindow;
    scope.openNewsWindow = openNewsWindow;
    scope.openTilePaletteContextMenu = openTilePaletteContextMenu;
    scope.openPlacedEntityContextMenu = openPlacedEntityContextMenu;
    scope.applyNpcEditorChange = applyNpcEditorChange;
    scope.getEditorEngineOverrides = getEditorEngineOverrides;
    scope.saveEditorEngineOverrides = saveEditorEngineOverrides;
    scope.getEffectiveHeightBlurStep = getEffectiveHeightBlurStep;
    scope.isRendererDebugEnabled = isRendererDebugEnabled;
    scope.reloadGraphicsContentFromApi = reloadGraphicsContentFromApi;
    uiScope.syncToolPanels = syncToolPanels;
    uiScope.handleSidebarTabButtonClick = handleSidebarTabButtonClick;
    uiScope.restoreAllToolWindows = restoreAllToolWindows;
    uiScope.resetWorkspaceLayout = resetWorkspaceLayoutFlow;
    uiScope.createNewTile = createNewTile;
    uiScope.createNewSpriteGraphic = createNewSpriteGraphic;
    uiScope.duplicateGraphicRecord = duplicateGraphicRecord;
    uiScope.openEntityEditorWindow = openEntityEditorWindow;
    uiScope.closeEntityEditorWindow = closeEntityEditorWindow;
    uiScope.openEngineOverrideWindow = openEngineOverrideWindow;
    uiScope.closeEngineOverrideWindow = closeEngineOverrideWindow;
    uiScope.refreshEngineOverrideWindow = refreshEngineOverrideWindow;
    uiScope.refreshEngineOverrideSummary = refreshEngineOverrideSummary;
    uiScope.openWorldOverviewWindow = openWorldOverviewWindow;
    uiScope.closeWorldOverviewWindow = closeWorldOverviewWindow;
    uiScope.refreshWorldOverviewWindow = refreshWorldOverviewWindow;
    uiScope.invalidateWorldOverviewChunkSurfaces = invalidateWorldOverviewChunkSurfaces;
    uiScope.openStatusLogWindow = openStatusLogWindow;
    uiScope.closeStatusLogWindow = closeStatusLogWindow;
    uiScope.openNewsWindow = openNewsWindow;
    uiScope.openTilePaletteContextMenu = openTilePaletteContextMenu;
    uiScope.openPlacedEntityContextMenu = openPlacedEntityContextMenu;
    uiScope.applyNpcEditorChange = applyNpcEditorChange;
    uiScope.getEditorEngineOverrides = getEditorEngineOverrides;
    uiScope.saveEditorEngineOverrides = saveEditorEngineOverrides;
    uiScope.getEffectiveHeightBlurStep = getEffectiveHeightBlurStep;
    uiScope.isRendererDebugEnabled = isRendererDebugEnabled;
    uiScope.reloadGraphicsContentFromApi = reloadGraphicsContentFromApi;

    syncDocumentTitle();
    const historyController = createHistoryController(scope);
    const npcController = createNpcController(scope);
    const sidebarController = createSidebarController(scope);
    renderController = createRenderController(scope);
    const persistenceController = createPersistenceController(scope);
    const importController = createImportController(scope);
    const interactionController = createInteractionController(scope);
    const persistPopupBounds = () => {
      persistWorldshaperStudioBounds(window);
    };
    const persistPopupBoundsDeferred = createDebouncedCallback(() => {
      persistPopupBounds();
    }, 160);
    syncCanvasDimensionsToTileSize();
    toolWindowController.initialize();
    tileArtEditorWindowController.initialize();
    entityEditorWindowController.initialize();
    engineOverrideWindowController.initialize();
    worldOverviewWindowController.initialize();
    changelogSplashWindowController.initialize();
    statusLogWindowController.initialize();
    renderController.initializeRenderAssets();
    interactionController.initializeEditorState();
    interactionController.bindDomEvents();
    interactionController.initializeUi();
    refreshEditorEngineOverridesUi();
    cacheStandaloneMapBootstrap(currentMapId);
    if (isWorldModeActive()) {
      window.requestAnimationFrame(() => {
        const initialWorldView = getInitialWorldViewTile();
        centerViewportOnWorldTile(initialWorldView.worldTileX, initialWorldView.worldTileY);
        prefetchAdjacentWorldNeighborhoods(worldRuntimeState.centerChunkX, worldRuntimeState.centerChunkY);
        syncWorldNeighborhoodForViewport();
        drawNow();
        setStatus("World mode loaded. Endless navigation is active.", false);
      });
    }
    window.requestAnimationFrame(() => {
      changelogSplashWindowController.maybeOpenForCurrentVersion();
    });
    window.addEventListener("resize", () => {
      persistPopupBoundsDeferred();
    });
    window.addEventListener("beforeunload", () => {
      popupSessionStore.flushPersistedLayout(window);
      persistPopupBounds();
    });
}

