(function () {
  "use strict";

  const $ = (id) => document.getElementById(id);

  const state = {
    initialized: false,
    loading: false,
    dirty: false,
    selectedId: "",
    grids: [],
    mySkins: [],
    registryPath: "",
    bridgeStatus: null,
    nameCleanupStatus: null,
    aiVehicleSpecSupport: {},
    cacheStatus: null,
    contentPackageStatus: null,
    bridgeGuideShownThisSession: false,
  };

  function escapeHtml(value) {
    return String(value ?? "")
      .replace(/&/g, "&amp;")
      .replace(/</g, "&lt;")
      .replace(/>/g, "&gt;")
      .replace(/"/g, "&quot;")
      .replace(/'/g, "&#039;");
  }

  function showModal(type, title, message, details = "") {
    if (typeof window.showStatusModal === "function") {
      window.showStatusModal({
        type,
        title,
        subtitle: type === "error" ? "Action failed" : "Custom Grids",
        message,
        details,
      });
      return;
    }
    console[type === "error" ? "error" : "log"](`${title}: ${message}`);
  }

  function icon(name) {
    const icons = {
      up: '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 5v14"/><path d="m6 11 6-6 6 6"/></svg>',
      down: '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 19V5"/><path d="m18 13-6 6-6-6"/></svg>',
      trash: '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 7h16"/><path d="M10 11v6"/><path d="M14 11v6"/><path d="M6 7l1 14h10l1-14"/><path d="M9 7V4h6v3"/></svg>',
      save: '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><path d="M17 21v-8H7v8"/><path d="M7 3v5h8"/></svg>',
      plus: '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 5v14"/><path d="M5 12h14"/></svg>',
      power: '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3v8"/><path d="M7.1 6.8a7 7 0 1 0 9.8 0"/></svg>',
      plug: '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 22v-5"/><path d="M9 8V3"/><path d="M15 8V3"/><path d="M6 8h12v4a6 6 0 0 1-12 0V8Z"/></svg>',
      unplug: '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 22v-5"/><path d="M8 3v4"/><path d="M16 3v4"/><path d="M6 8h12v4a6 6 0 0 1-6 6"/><path d="m4 4 16 16"/></svg>',
    };
    return icons[name] ? `<span class="button-icon">${icons[name]}</span>` : "";
  }

  function setStatus(text, dirty = state.dirty) {
    const node = $("customGridStatus");
    if (!node) return;
    node.textContent = dirty ? `${text} / Unsaved` : text;
  }

  function selectedGrid() {
    return state.grids.find((grid) => grid.id === state.selectedId) || state.grids[0] || null;
  }

  function bridgeActiveGridId() {
    return String(state.bridgeStatus?.activeGridId || "").trim();
  }

  function isBridgeActiveGrid(grid) {
    const activeId = bridgeActiveGridId();
    return !!(grid?.id && activeId && String(grid.id) === activeId);
  }

  function parseIsoTime(value) {
    const time = Date.parse(String(value || ""));
    return Number.isFinite(time) ? time : 0;
  }

  function bridgeGridNeedsUpdate(grid) {
    if (!isBridgeActiveGrid(grid)) return false;
    const localUpdatedAt = parseIsoTime(grid?.updatedAt);
    const exportedAt = parseIsoTime(state.bridgeStatus?.activeGridExportedAt);
    return !!(localUpdatedAt && exportedAt && localUpdatedAt > exportedAt);
  }

  function isDebugMode() {
    return document.documentElement.classList.contains("is-debug-mode");
  }

  function bridgeGridActionState(grid) {
    if (!state.bridgeStatus?.installed) {
      return {
        label: "Activate Grid in Game",
        modalLabel: "Activate Grid",
        primary: true,
        pulse: true,
        disabled: false,
        statusLabel: "Ready to activate",
        statusClass: "partial",
        statusText: "Activate prepares the required AC EVO files automatically.",
      };
    }
    const active = isBridgeActiveGrid(grid);
    const needsUpdate = bridgeGridNeedsUpdate(grid);
    if (active && needsUpdate) {
      return {
        label: "Update Grid in Game",
        modalLabel: "Update Grid",
        primary: true,
        pulse: true,
        disabled: false,
        statusLabel: "Update available",
        statusClass: "partial",
        statusText: "Local changes are newer than the active game grid.",
      };
    }
    if (active) {
      return {
        label: "Deactivate Grid in Game",
        modalLabel: "Deactivate Grid",
        primary: false,
        pulse: false,
        disabled: false,
        statusLabel: "Active in game",
        statusClass: "complete",
        statusText: "Loaded by the in-game LiveryLab button.",
      };
    }
    return {
      label: "Activate Grid in Game",
      modalLabel: "Activate Grid",
      primary: true,
      pulse: true,
      disabled: false,
      statusLabel: "Not active in AC EVO",
      statusClass: "missing",
      statusText: "Only one custom grid can be active per game start.",
    };
  }

  function bridgeActiveGridBadgeHtml(grid) {
    if (!isBridgeActiveGrid(grid)) return "";
    return `<span class="status complete custom-grid-active-pill">Active in game</span>`;
  }

  function placeholderSrc() {
    return "./assets/placeholder.png";
  }

  function gridPreviewPath(grid) {
    return String(grid?.previewPngPath || "").trim();
  }

  function gridPreviewMarkHtml(grid = {}, options = {}) {
    const previewPath = gridPreviewPath(grid);
    const classes = ["custom-grid-mark"];
    if (options.large) classes.push("is-large");
    if (previewPath) classes.push("has-preview");
    if (!previewPath) {
      return `<div class="${classes.join(" ")}"><span>GRID</span></div>`;
    }
    return `
      <div class="${classes.join(" ")}">
        <img alt="" src="${placeholderSrc()}" data-custom-grid-preview-path="${escapeHtml(previewPath)}" />
      </div>
    `;
  }

  async function loadGridPreviewImages(root = document) {
    if (!window.pywebview?.api?.load_image_preview) return;
    const nodes = Array.from(root.querySelectorAll("[data-custom-grid-preview-path], [data-custom-grid-entry-thumb-path]"));
    for (const image of nodes) {
      const attr = image.hasAttribute("data-custom-grid-entry-thumb-path")
        ? "data-custom-grid-entry-thumb-path"
        : "data-custom-grid-preview-path";
      const path = image.getAttribute(attr) || "";
      if (!path) continue;
      try {
        const result = await window.pywebview.api.load_image_preview(path, "custom-grid-preview");
        const src = result?.ok ? (result.data?.data_url || result.data?.dataUrl || "") : "";
        if (src && image.getAttribute(attr) === path) image.src = src;
      } catch (_error) {
        // Keep the generic placeholder when preview loading fails.
      }
    }
  }

  function normalizeEntryFromSkin(skin) {
    const displayName = String(skin.display_name || skin.displayName || skin.skin_id || skin.skinId || "Skin").trim();
    const numberplateVariant = skin.numberplate_variant && typeof skin.numberplate_variant === "object" ? skin.numberplate_variant : {};
    const numberplateBake = skin.numberplate_bake && typeof skin.numberplate_bake === "object" ? skin.numberplate_bake : {};
    const carNumber = String(
      skin.start_number || skin.startNumber || numberplateVariant.start_number || numberplateVariant.startNumber || numberplateBake.start_number || numberplateBake.startNumber || "",
    ).replace(/\D/g, "").slice(0, 3);
    return {
      id: `entry_${Date.now().toString(36)}_${Math.random().toString(16).slice(2, 8)}`,
      skinKey: String(skin.key || "").trim(),
      carModel: String(skin.car_model || skin.carModel || "").trim(),
      carContentPath: String(skin.car_content_path || skin.carContentPath || "").trim(),
      skinId: String(skin.skin_id || skin.skinId || "").trim(),
      displayName,
      driverName: displayName,
      team: "",
      carNumber,
      aiVehicleSpec: "standard",
      thumbnailPngDiskPath: String(skin.thumbnail_png_disk_path || skin.thumbnailPngDiskPath || "").trim(),
      notes: "",
    };
  }

  function aiVehicleSpecValue(entry) {
    const value = String(entry?.aiVehicleSpec || entry?.ai_vehicle_spec || "standard").trim().toLowerCase().replace(/[-\s]+/g, "_");
    return value === "endurance" || value === "endurance_spec" || value === "ll_endurance" ? "endurance" : "standard";
  }

  function aiVehicleSpecLabel(entry) {
    return aiVehicleSpecUiValue(entry) === "endurance" ? "Endurance" : "Standard";
  }

  function normalizeGameRel(value) {
    return String(value || "").trim().replace(/\//g, "\\").toLowerCase();
  }

  function carContentPathForEntry(entry) {
    const skin = findSkinForEntry(entry);
    return String(
      skin?.car_content_path
      || skin?.carContentPath
      || entry?.carContentPath
      || entry?.car_content_path
      || "",
    ).trim();
  }

  function aiVehicleSpecSupported(entry, spec) {
    const value = String(spec || "standard").trim().toLowerCase();
    if (value !== "endurance") return true;
    const key = normalizeGameRel(carContentPathForEntry(entry));
    if (!key) return false;
    return Boolean(state.aiVehicleSpecSupport?.[key]?.supported);
  }

  function aiVehicleSpecUiValue(entry) {
    const value = aiVehicleSpecValue(entry);
    return aiVehicleSpecSupported(entry, value) ? value : "standard";
  }

  function entryLabel(entry, index = 0) {
    return String(entry?.displayName || entry?.skinId || entry?.skinKey || `Entry ${index + 1}`).trim();
  }

  function entrySkinKey(entry) {
    return String(entry?.skinKey || "").trim().toLowerCase();
  }

  function entryModelSkinKey(entry) {
    return [
      String(entry?.carModel || "").trim().toLowerCase(),
      String(entry?.skinId || "").trim().toLowerCase(),
    ].join(":");
  }

  function findSkinForEntry(entry) {
    const skinKey = entrySkinKey(entry);
    if (skinKey) {
      const byKey = state.mySkins.find((skin) => String(skin.key || "").trim().toLowerCase() === skinKey);
      if (byKey) return byKey;
    }
    const carModel = String(entry?.carModel || "").trim().toLowerCase();
    const skinId = String(entry?.skinId || "").trim().toLowerCase();
    if (!carModel || !skinId) return null;
    return state.mySkins.find((skin) => (
      String(skin.car_model || skin.carModel || "").trim().toLowerCase() === carModel
      && String(skin.skin_id || skin.skinId || "").trim().toLowerCase() === skinId
    )) || null;
  }

  function startNumberFromSkin(skin) {
    if (!skin) return "";
    const numberplateVariant = skin.numberplate_variant && typeof skin.numberplate_variant === "object" ? skin.numberplate_variant : {};
    const numberplateBake = skin.numberplate_bake && typeof skin.numberplate_bake === "object" ? skin.numberplate_bake : {};
    return String(
      skin.start_number || skin.startNumber || numberplateVariant.start_number || numberplateVariant.startNumber || numberplateBake.start_number || numberplateBake.startNumber || "",
    ).replace(/\D/g, "").slice(0, 3);
  }

  function entryCarNumber(entry) {
    const explicit = String(entry?.carNumber || entry?.car_number || "").replace(/\D/g, "").slice(0, 3);
    return explicit || startNumberFromSkin(findSkinForEntry(entry));
  }

  function skinFileValue(skin, key) {
    const files = skin?.files && typeof skin.files === "object" ? skin.files : {};
    return String(files[key] || skin?.[key] || "").trim();
  }

  function preflightGrid(grid, options = {}) {
    const forExport = Boolean(options.forExport);
    const entries = Array.isArray(grid?.entries) ? grid.entries : [];
    const blockers = [];
    const warnings = [];
    const notes = [];
    const seenSkins = new Map();
    const seenDrivers = new Map();

    if (!entries.length && forExport) {
      blockers.push("Add at least one livery before exporting this grid.");
    }

    if (forExport && state.contentPackageStatus?.activeExists) {
      blockers.push("content.kspkg is active. Disable or rename it before exporting to the loose AC EVO UI bridge.");
    }

    const enduranceCount = entries.filter((entry) => aiVehicleSpecValue(entry) === "endurance").length;
    if (forExport && enduranceCount) {
      notes.push(`${enduranceCount} grid entr${enduranceCount === 1 ? "y uses" : "ies use"} Endurance AI spec. LiveryLab will create temporary AC EVO mechanical presets and clean unused specs when another grid is activated or the bridge is removed.`);
    }

    entries.forEach((entry, index) => {
      const label = entryLabel(entry, index);
      const carModel = String(entry?.carModel || "").trim();
      const skinId = String(entry?.skinId || "").trim();
      const driverName = String(entry?.driverName || "").trim();
      const key = entrySkinKey(entry) || entryModelSkinKey(entry);

      if (!carModel || !skinId) {
        blockers.push(`${label}: missing car model or skin id.`);
      }

      if (!driverName) {
        blockers.push(`${label}: missing driver name.`);
      } else {
        const driverKey = driverName.toLowerCase();
        if (seenDrivers.has(driverKey)) {
          warnings.push(`${label}: driver name is also used by ${seenDrivers.get(driverKey)}.`);
        } else {
          seenDrivers.set(driverKey, label);
        }
      }

      if (key && seenSkins.has(key)) {
        warnings.push(`${label}: livery is already in this grid as ${seenSkins.get(key)}.`);
      } else if (key) {
        seenSkins.set(key, label);
      }

      const skin = findSkinForEntry(entry);
      if (!skin) {
        blockers.push(`${label}: livery is no longer registered in My Liveries.`);
        return;
      }

      if (skin.active === false) {
        const message = `${label}: livery is not active in game.`;
        if (forExport) blockers.push(message);
        else warnings.push(message);
      }

      if (!skinFileValue(skin, "visual_preset")) {
        const message = `${label}: missing visual preset reference.`;
        if (forExport) blockers.push(message);
        else warnings.push(message);
      }

      if (!skinFileValue(skin, "carfinalstate")) {
        const message = `${label}: missing car final state reference.`;
        if (forExport) blockers.push(message);
        else warnings.push(message);
      }
    });

    return { blockers, warnings, notes };
  }

  function preflightDetails(preflight) {
    const lines = [];
    if (preflight.blockers.length) {
      lines.push("Required fixes:");
      preflight.blockers.forEach((item) => lines.push(`- ${item}`));
    }
    if (preflight.warnings.length) {
      if (lines.length) lines.push("");
      lines.push("Warnings:");
      preflight.warnings.forEach((item) => lines.push(`- ${item}`));
    }
    if (preflight.notes?.length) {
      if (lines.length) lines.push("");
      lines.push("Notes:");
      preflight.notes.forEach((item) => lines.push(`- ${item}`));
    }
    return lines.join("\n");
  }

  async function confirmPreflight(context, preflight, confirmLabel) {
    if (preflight.blockers.length) {
      const message = [
        `${preflight.blockers.length} issue${preflight.blockers.length === 1 ? "" : "s"} must be fixed first.`,
        "",
        "Required fixes:",
        ...preflight.blockers.map((item) => `- ${item}`),
      ].join("\n");
      showModal("error", context, message);
      return false;
    }
    const hasWarnings = Boolean(preflight.warnings.length);
    const hasNotes = Boolean(preflight.notes?.length);
    if (!hasWarnings && !hasNotes) return { proceed: true, confirmed: false };
    if (typeof window.showConfirmModal !== "function") {
      showModal(hasWarnings ? "error" : "info", context, hasWarnings ? `${preflight.warnings.length} warning${preflight.warnings.length === 1 ? "" : "s"} found.` : "Review these notes before continuing.", preflightDetails(preflight));
      return false;
    }
    const confirmed = await window.showConfirmModal({
      type: hasWarnings ? "warning" : "info",
      title: hasWarnings ? context : "Grid export notes",
      message: hasWarnings ? `${preflight.warnings.length} warning${preflight.warnings.length === 1 ? "" : "s"} found.` : "Review these notes before continuing.",
      details: preflightDetails(preflight),
      confirmLabel,
      loadingLabel: "Continuing...",
    });
    return confirmed ? { proceed: true, confirmed: true } : false;
  }

  async function apiCall(name, payload = undefined) {
    if (!window.pywebview?.api?.[name]) {
      throw new Error(`API not available: ${name}`);
    }
    const result = payload === undefined
      ? await window.pywebview.api[name]()
      : await window.pywebview.api[name](payload);
    if (!result?.ok) {
      throw new Error(result?.message || `API call failed: ${name}`);
    }
    return result;
  }

  async function loadMySkins() {
    try {
      const root = $("rootPath")?.value?.trim() || "";
      const result = await window.pywebview.api.get_my_skins(root, false);
      state.mySkins = result?.ok && Array.isArray(result.data?.skins) ? result.data.skins : [];
      await loadAiVehicleSpecSupport(false);
    } catch (_error) {
      state.mySkins = [];
      state.aiVehicleSpecSupport = {};
    }
  }

  async function loadAiVehicleSpecSupport(renderAfter = true) {
    const carContentPaths = [...new Set(state.mySkins.map((skin) => String(skin.car_content_path || skin.carContentPath || "").trim()).filter(Boolean))];
    if (!carContentPaths.length) {
      state.aiVehicleSpecSupport = {};
      if (renderAfter) renderDetail();
      return state.aiVehicleSpecSupport;
    }
    try {
      const result = await apiCall("get_ai_vehicle_spec_support", { root: gameRoot(), carContentPaths });
      state.aiVehicleSpecSupport = result.data?.items || {};
    } catch (_error) {
      state.aiVehicleSpecSupport = {};
    }
    if (renderAfter) renderDetail();
    return state.aiVehicleSpecSupport;
  }

  async function load() {
    if (state.loading) return;
    state.loading = true;
    setStatus("Loading...");
    render();
    try {
      await Promise.all([
        apiCall("list_custom_grids"),
        loadMySkins(),
        loadBridgeStatus(false),
        loadNameCleanupStatus(false),
        loadContentPackageStatus(false),
        loadGridCacheStatus(false),
      ]).then(([gridResult]) => {
        state.grids = Array.isArray(gridResult.data?.items) ? gridResult.data.items : [];
        state.registryPath = String(gridResult.data?.path || "");
      });
      if (!state.grids.some((grid) => grid.id === state.selectedId)) {
        state.selectedId = state.grids[0]?.id || "";
      }
      state.dirty = false;
      render();
      setStatus(state.grids.length ? "Ready" : "Empty");
      showBridgeGuideModalWhenNeeded();
    } catch (error) {
      showModal("error", "Custom Grids", error?.message || String(error));
      setStatus("Error");
    } finally {
      state.loading = false;
      render();
    }
  }

  function isBridgeGuideDismissed() {
    return Boolean(window.LiveryLabUiNotices?.isCustomGridBridgeGuideDismissed?.());
  }

  function showBridgeGuideModalWhenNeeded() {
    const modal = $("customGridBridgeGuideModal");
    if (!modal || state.bridgeGuideShownThisSession || isBridgeGuideDismissed()) return;
    const checkbox = $("customGridBridgeGuideDoNotShow");
    if (checkbox) checkbox.checked = false;
    state.bridgeGuideShownThisSession = true;
    modal.hidden = false;
  }

  async function closeBridgeGuideModal() {
    const modal = $("customGridBridgeGuideModal");
    if (!modal) return;
    if ($("customGridBridgeGuideDoNotShow")?.checked) {
      await window.LiveryLabUiNotices?.setCustomGridBridgeGuideDismissed?.();
    }
    modal.hidden = true;
  }

  async function createGrid() {
    try {
      const result = await apiCall("create_custom_grid", { name: "New Grid" });
      state.grids = Array.isArray(result.data?.items) ? result.data.items : state.grids;
      state.selectedId = result.data?.item?.id || state.grids[state.grids.length - 1]?.id || "";
      state.dirty = false;
      render();
      setStatus("Created");
    } catch (error) {
      showModal("error", "Create Custom Grid", error?.message || String(error));
    }
  }

  function markDirty() {
    state.dirty = true;
    setStatus("Editing", true);
    const save = $("saveCustomGrid");
    if (save) save.classList.add("primary");
  }

  function updateSelectedFromForm() {
    const grid = selectedGrid();
    if (!grid) return null;
    grid.name = $("customGridName")?.value?.trim() || "New Grid";
    grid.description = $("customGridDescription")?.value?.trim() || "";
    grid.entries = Array.from(document.querySelectorAll("[data-custom-grid-entry]")).map((row, index) => {
      const id = row.dataset.entryId || "";
      const current = (grid.entries || []).find((entry) => entry.id === id) || {};
      const driverNameInput = row.querySelector("[data-entry-field='driverName']");
      const aiSpecInput = row.querySelector("[data-entry-field='aiVehicleSpec']");
      return {
        ...current,
        id: current.id || id || `entry_${index + 1}`,
        driverName: driverNameInput ? driverNameInput.value.trim() : (current.driverName || current.displayName || current.skinId || "Driver"),
        aiVehicleSpec: aiSpecInput && !aiSpecInput.disabled ? aiSpecInput.value : "standard",
        team: row.querySelector("[data-entry-field='team']")?.value?.trim() || "",
        carNumber: entryCarNumber(current),
      };
    });
    return grid;
  }

  async function saveSelected() {
    const grid = updateSelectedFromForm();
    if (!grid) return;
    const canContinue = await confirmPreflight("Save Custom Grid", preflightGrid(grid), "Save Anyway");
    if (!canContinue) return;
    try {
      const result = await apiCall("save_custom_grid", grid);
      const saved = result.data?.item || grid;
      const items = Array.isArray(result.data?.items) ? result.data.items : state.grids.map((item) => item.id === saved.id ? saved : item);
      state.grids = items;
      state.selectedId = saved.id;
      state.dirty = false;
      render();
      setStatus("Saved");
      showModal("success", "Custom Grid Saved", `${saved.name || saved.id} was saved locally.`, result.message || "");
    } catch (error) {
      showModal("error", "Save Custom Grid", error?.message || String(error));
    }
  }

  async function duplicateSelected() {
    const grid = selectedGrid();
    if (!grid) return;
    try {
      const result = await apiCall("duplicate_custom_grid", { id: grid.id });
      state.grids = Array.isArray(result.data?.items) ? result.data.items : state.grids;
      state.selectedId = result.data?.item?.id || state.selectedId;
      state.dirty = false;
      render();
      setStatus("Duplicated");
    } catch (error) {
      showModal("error", "Duplicate Custom Grid", error?.message || String(error));
    }
  }

  async function deleteSelected() {
    const grid = selectedGrid();
    if (!grid) return;
    let confirmed = true;
    if (typeof window.showConfirmModal === "function") {
      confirmed = await window.showConfirmModal({
        type: "danger",
        title: "Delete custom grid",
        message: `Delete "${grid.name || grid.id}" from the local grid library?`,
        details: "This only removes the local JSON entry. No AC EVO game files are changed.",
        confirmLabel: "Delete",
        loadingLabel: "Deleting...",
      });
    }
    if (!confirmed) return;
    try {
      const result = await apiCall("delete_custom_grid", { id: grid.id });
      state.grids = Array.isArray(result.data?.items) ? result.data.items : state.grids.filter((item) => item.id !== grid.id);
      state.selectedId = state.grids[0]?.id || "";
      state.dirty = false;
      render();
      setStatus("Deleted");
    } catch (error) {
      showModal("error", "Delete Custom Grid", error?.message || String(error));
    }
  }

  async function chooseGridPreviewPng() {
    const grid = updateSelectedFromForm();
    if (!grid?.id) return;
    if (!window.pywebview?.api?.choose_path) {
      showModal("error", "Grid Preview", "File picker is not available in this build.");
      return;
    }
    const picked = await window.pywebview.api.choose_path("file", ["PNG (*.png)", "All files (*.*)"], "");
    if (!picked?.ok || !picked.data?.path) return;
    const button = $("chooseCustomGridPreviewPng");
    const previousText = button?.textContent || "";
    if (button) {
      button.disabled = true;
      button.textContent = "Saving...";
    }
    try {
      const result = await apiCall("save_custom_grid_preview_image", { id: grid.id, previewPng: picked.data.path });
      const item = result.data?.item || {};
      const current = selectedGrid();
      if (current?.id === grid.id) {
        current.previewPng = item.previewPng || current.previewPng || "";
        current.previewPngPath = item.previewPngPath || current.previewPngPath || "";
      }
      state.grids = state.grids.map((row) => {
        if (row.id !== grid.id) return row;
        return {
          ...row,
          previewPng: item.previewPng || row.previewPng || "",
          previewPngPath: item.previewPngPath || row.previewPngPath || "",
        };
      });
      render();
      setStatus(state.dirty ? "Preview saved" : "Preview saved", state.dirty);
    } catch (error) {
      showModal("error", "Save Grid Preview", error?.message || String(error));
    } finally {
      if (button) {
        button.disabled = false;
        button.textContent = previousText || "Choose PNG";
      }
    }
  }

  async function packageExportRoot() {
    if (!window.pywebview?.api?.get_custom_grid_package_export_root) return "";
    const result = await window.pywebview.api.get_custom_grid_package_export_root(gameRoot());
    return result?.ok && result.data?.path ? result.data.path : "";
  }

  async function choosePackageFolder(initialDir = "") {
    if (!window.pywebview?.api?.choose_path) return "";
    const picked = await window.pywebview.api.choose_path("folder", ["All files (*.*)"], "", initialDir || "");
    return picked?.ok && picked.data?.path ? picked.data.path : "";
  }

  async function choosePackageZip(initialDir = "") {
    if (!window.pywebview?.api?.choose_path) return "";
    const picked = await window.pywebview.api.choose_path("file", ["Custom Grid Package (*.zip)", "ZIP (*.zip)", "All files (*.*)"], "", initialDir || "");
    return picked?.ok && picked.data?.path ? picked.data.path : "";
  }

  async function exportSelectedPackage() {
    const grid = selectedGrid();
    if (!grid?.id) {
      showModal("error", "Export Custom Grid", "Select a custom grid before exporting.");
      return;
    }
    if (state.dirty) {
      showModal("error", "Export Custom Grid", "Save pending grid changes before exporting.");
      return;
    }
    if (!window.pywebview?.api?.export_custom_grid_package) {
      showModal("error", "Export Custom Grid", "Custom grid package export is not available.");
      return;
    }
    const outDir = await choosePackageFolder(await packageExportRoot());
    if (!outDir) return;
    const button = $("exportCustomGridPreset");
    const previousText = button?.textContent || "";
    if (button) {
      button.disabled = true;
      button.textContent = "Exporting...";
    }
    try {
      const result = await apiCall("export_custom_grid_package", { id: grid.id, outDir, root: gameRoot() });
      const packagePath = result.data?.packagePath || result.data?.packageRoot || "";
      if (typeof window.showStatusModal === "function") {
        window.showStatusModal({
          type: "success",
          title: "Custom grid exported",
          subtitle: grid.name || grid.id || "Package ready",
          message: "The custom grid package was exported successfully.",
          details: result.message || `Package: ${packagePath || "-"}`,
          openFolderPath: packagePath,
        });
      }
      setStatus("Exported", false);
    } catch (error) {
      showModal("error", "Export Custom Grid", error?.message || String(error));
    } finally {
      if (button) {
        button.disabled = false;
        button.textContent = previousText || "Export Grid";
      }
      syncPackageButtons();
    }
  }

  async function importPackage() {
    if (!window.pywebview?.api?.inspect_custom_grid_package || !window.pywebview?.api?.import_custom_grid_package) {
      showModal("error", "Import Custom Grid", "Custom grid package import is not available.");
      return;
    }
    const packageDir = await choosePackageZip(await packageExportRoot());
    if (!packageDir) return;
    try {
      const inspected = await apiCall("inspect_custom_grid_package", packageDir);
      const grid = inspected.data?.grid || {};
      const manifest = grid.manifest || {};
      const missingCount = Number(inspected.data?.missingCount || 0);
      if (missingCount) {
        showModal(
          "error",
          "Custom grid package",
          `Package is incomplete: ${missingCount} missing entr${missingCount === 1 ? "y" : "ies"}.`,
          (inspected.data?.missing || []).map((item) => `- ${item.kind || "file"}: ${item.path || "-"} ${item.reason ? `(${item.reason})` : ""}`).join("\n"),
        );
        return;
      }
      let proceed = true;
      if (typeof window.showConfirmModal === "function") {
        proceed = await window.showConfirmModal({
          type: "info",
          title: "Import custom grid package",
          message: "Import this custom grid into your local library?",
          details: [
            `Grid: ${manifest.name || grid.name || grid.id || "-"}`,
            `ZIP: ${packageDir}`,
            `Entries: ${inspected.data?.entryCount || 0}`,
            "",
            "If the same grid id already exists, the imported grid receives a new id.",
          ].join("\n"),
          confirmLabel: "Import Grid",
          cancelLabel: "Cancel",
        });
      }
      if (!proceed) return;
      const result = await apiCall("import_custom_grid_package", { packageDir, conflictMode: "rename" });
      state.grids = Array.isArray(result.data?.items) ? result.data.items : state.grids;
      state.selectedId = result.data?.gridId || result.data?.grid?.id || state.selectedId;
      state.dirty = false;
      render();
      setStatus("Imported");
    } catch (error) {
      showModal("error", "Import Custom Grid", error?.message || String(error));
    }
  }

  function gameRoot() {
    return $("rootPath")?.value?.trim() || "";
  }

  async function loadBridgeStatus(renderAfter = true) {
    try {
      const result = await apiCall("get_custom_grid_bridge_status", { root: gameRoot() });
      state.bridgeStatus = result.data || null;
      if (renderAfter) {
        renderBridgeTools();
        renderList();
        renderDetail();
      }
      return state.bridgeStatus;
    } catch (_error) {
      state.bridgeStatus = null;
      if (renderAfter) {
        renderBridgeTools();
        renderList();
        renderDetail();
      }
      return null;
    }
  }

  async function loadGridCacheStatus(renderAfter = true) {
    try {
      const result = await apiCall("get_ace_grid_cache_status");
      state.cacheStatus = result.data || null;
      if (renderAfter) renderDetail();
      return state.cacheStatus;
    } catch (_error) {
      state.cacheStatus = null;
      if (renderAfter) renderDetail();
      return null;
    }
  }

  async function loadNameCleanupStatus(renderAfter = true) {
    try {
      const result = await apiCall("get_ai_name_marker_cleanup_status", { root: gameRoot() });
      state.nameCleanupStatus = result.data || null;
      if (renderAfter) renderDetail();
      return state.nameCleanupStatus;
    } catch (_error) {
      state.nameCleanupStatus = null;
      if (renderAfter) renderDetail();
      return null;
    }
  }

  async function loadContentPackageStatus(renderAfter = true) {
    try {
      const root = gameRoot();
      if (!root) {
        state.contentPackageStatus = null;
      } else {
        const result = await apiCall("get_content_package_state", root);
        state.contentPackageStatus = result.data || null;
      }
      if (renderAfter) {
        renderBridgeTools();
        renderDetail();
      }
      return state.contentPackageStatus;
    } catch (_error) {
      state.contentPackageStatus = null;
      if (renderAfter) {
        renderBridgeTools();
        renderDetail();
      }
      return null;
    }
  }

  async function installBridge() {
    if (state.contentPackageStatus?.activeExists) {
      showModal("error", "Install AC EVO Grid Bridge", "content.kspkg is active.", "Disable or rename content.kspkg before installing loose AC EVO UI hooks. Packed UI mode can crash when loose LiveryLab UI hooks are present.");
      return;
    }
    let confirmed = true;
    if (typeof window.showConfirmModal === "function") {
      confirmed = await window.showConfirmModal({
        type: "warning",
        title: "Install AC EVO Grid Bridge",
        message: "Install the LiveryLab Grid Bridge into the AC EVO Single Player UI?",
        details: "This writes the bridge scripts and updates the AC EVO singleplayer, ingame, HUD, and driver labels UI files. Existing files are backed up before changes. The old smoke-test hook is removed if present.",
        confirmLabel: "Install Bridge",
        loadingLabel: "Installing...",
      });
    }
    if (!confirmed) return;
    try {
      const result = await apiCall("install_custom_grid_bridge", { root: gameRoot() });
      state.bridgeStatus = result.data?.status || null;
      renderBridgeTools();
      renderDetail();
      showModal("success", "AC EVO Grid Bridge", "Bridge installed. Restart or reload the AC EVO Single Player UI before applying a grid.", result.message || "");
    } catch (error) {
      showModal("error", "Install AC EVO Grid Bridge", error?.message || String(error));
    }
  }

  async function removeBridge() {
    let confirmed = true;
    if (typeof window.showConfirmModal === "function") {
      confirmed = await window.showConfirmModal({
        type: "warning",
        title: "Remove AC EVO Grid Bridge",
        message: "Remove the LiveryLab Grid Bridge hook from the AC EVO Single Player UI?",
        details: "All LiveryLab bridge hooks, scripts, exported current-grid files, and LiveryLab AI vehicle specs are removed. AC EVO UI files are backed up before changes, and driverlabels.html is restored from the earliest ACE backup when only LiveryLab rewrite noise remains.",
        confirmLabel: "Remove Bridge",
        loadingLabel: "Removing...",
      });
    }
    if (!confirmed) return;
    try {
      const result = await apiCall("remove_custom_grid_bridge", { root: gameRoot() });
      state.bridgeStatus = result.data?.status || null;
      await loadGridCacheStatus(false);
      renderBridgeTools();
      renderDetail();
      showModal("success", "AC EVO Grid Bridge", "Bridge removed.", result.message || "");
    } catch (error) {
      showModal("error", "Remove AC EVO Grid Bridge", error?.message || String(error));
    }
  }

  async function resetAceGridCache() {
    let confirmed = true;
    if (typeof window.showConfirmModal === "function") {
      confirmed = await window.showConfirmModal({
        type: "warning",
        title: "Reset ACE Grid Cache",
        message: "Reset AC EVO's saved quick-race grid cache?",
        details: "This backs up the relevant Saved Games\\ACE files into LiveryLibrary\\GridCacheBackups, then removes last_grid.customgrid, GameModeType_INSTANT_RACE.gamemodesave, and old leaderboard_results session files. It does not change AC EVO game files.",
        confirmLabel: "Reset Cache",
        loadingLabel: "Resetting...",
      });
    }
    if (!confirmed) return;
    try {
      const result = await apiCall("reset_ace_grid_cache");
      state.cacheStatus = result.data?.status || null;
      renderDetail();
      showModal("success", "ACE Grid Cache", "Grid cache reset. Generate a fresh grid in AC EVO before testing default behavior.", result.data?.backup ? `Backup: ${result.data.backup}` : "");
    } catch (error) {
      showModal("error", "Reset ACE Grid Cache", error?.message || String(error));
    }
  }

  async function restoreAceGridCacheBackup() {
    let confirmed = true;
    if (typeof window.showConfirmModal === "function") {
      confirmed = await window.showConfirmModal({
        type: "warning",
        title: "Restore ACE Grid Cache Backup",
        message: "Restore the latest grid-cache backup created by LiveryLab?",
        details: "This copies the latest backup from LiveryLibrary\\GridCacheBackups back into Saved Games\\ACE\\GameModes.",
        confirmLabel: "Restore Backup",
        loadingLabel: "Restoring...",
      });
    }
    if (!confirmed) return;
    try {
      const result = await apiCall("restore_ace_grid_cache_backup");
      state.cacheStatus = result.data?.status || null;
      renderDetail();
      showModal("success", "ACE Grid Cache", "Latest grid-cache backup restored.", result.data?.backup ? `Backup: ${result.data.backup}` : "");
    } catch (error) {
      showModal("error", "Restore ACE Grid Cache Backup", error?.message || String(error));
    }
  }

  async function removeNameCleanup() {
    let confirmed = true;
    if (typeof window.showConfirmModal === "function") {
      confirmed = await window.showConfirmModal({
        type: "warning",
        title: "Remove Legacy AI Name Cleanup",
        message: "Remove the old AI name cleanup hook from AC EVO?",
        details: "This removes only the legacy standalone marker-cleanup hook and script. Custom Grid bridge files are not changed.",
        confirmLabel: "Remove Cleanup",
        loadingLabel: "Removing...",
      });
    }
    if (!confirmed) return;
    try {
      const result = await apiCall("remove_ai_name_marker_cleanup", { root: gameRoot() });
      state.nameCleanupStatus = result.data?.status || null;
      renderDetail();
      showModal("success", "Legacy AI Name Cleanup", "Cleanup removed.", result.message || "");
    } catch (error) {
      showModal("error", "Remove Legacy AI Name Cleanup", error?.message || String(error));
    }
  }

  async function removeAllUiHooks() {
    let confirmed = true;
    if (typeof window.showConfirmModal === "function") {
      confirmed = await window.showConfirmModal({
        type: "warning",
        title: "Remove All AC EVO UI Hooks",
        message: "Remove every LiveryLab Custom Grids UI hook from AC EVO?",
        details: "This removes the Custom Grid Bridge hooks, exported bridge files, legacy standalone AI name cleanup, and LiveryLab AI vehicle specs. Use this before re-enabling content.kspkg. Existing AC EVO UI files are backed up before changes.",
        confirmLabel: "Remove All Hooks",
        loadingLabel: "Removing...",
      });
    }
    if (!confirmed) return;
    try {
      const result = await apiCall("remove_custom_grid_ui_hooks", { root: gameRoot() });
      state.bridgeStatus = result.data?.bridgeStatus || result.data?.bridge?.status || null;
      state.nameCleanupStatus = result.data?.nameCleanupStatus || result.data?.nameCleanup?.status || null;
      await loadContentPackageStatus(false);
      renderBridgeTools();
      renderDetail();
      showModal("success", "AC EVO UI Hooks", "All LiveryLab Custom Grids UI hooks were removed.", result.message || "");
    } catch (error) {
      showModal("error", "Remove All AC EVO UI Hooks", error?.message || String(error));
    }
  }

  async function deactivateSelectedBridgeGrid(grid, action) {
    let confirmed = true;
    if (typeof window.showConfirmModal === "function") {
      confirmed = await window.showConfirmModal({
        type: "warning",
        title: `${action.modalLabel} in AC EVO`,
        message: `${action.modalLabel} "${grid.name || grid.id}" for AC EVO?`,
        details: "This removes the LiveryLab Grid Bridge hook, the current bridge grid file, legacy AI name cleanup, and LiveryLab AI vehicle specs. The local grid preset stays in your library.",
        confirmLabel: action.modalLabel,
        loadingLabel: "Deactivating...",
      });
    }
    if (!confirmed) return;
    try {
      const result = await apiCall("remove_custom_grid_bridge", { root: gameRoot() });
      state.bridgeStatus = result.data?.status || state.bridgeStatus;
      state.nameCleanupStatus = result.data?.nameCleanupStatus || result.data?.nameCleanup?.status || state.nameCleanupStatus;
      await loadGridCacheStatus(false);
      renderBridgeTools();
      renderList();
      renderDetail();
      showModal("success", "Grid Deactivated", `${grid.name || "Custom Grid"} was removed from the AC EVO bridge.`, result.message || "");
    } catch (error) {
      showModal("error", "Deactivate Grid in AC EVO", error?.message || String(error));
    }
  }

  async function exportSelectedToBridge() {
    if (state.contentPackageStatus?.activeExists) {
      showModal("error", "Export Grid to AC EVO", "content.kspkg is active.", "Disable or rename content.kspkg before exporting to the loose AC EVO UI bridge.");
      return;
    }
    const grid = updateSelectedFromForm();
    if (!grid) return;
    const action = bridgeGridActionState(grid);
    if (isBridgeActiveGrid(grid) && !bridgeGridNeedsUpdate(grid)) {
      await deactivateSelectedBridgeGrid(grid, action);
      return;
    }
    const preflightConfirm = await confirmPreflight("Export Grid to AC EVO", preflightGrid(grid, { forExport: true }), action.modalLabel);
    if (!preflightConfirm) return;
    let confirmed = Boolean(preflightConfirm.confirmed);
    if (!confirmed && typeof window.showConfirmModal === "function") {
      const enduranceCount = Array.isArray(grid.entries) ? grid.entries.filter((entry) => aiVehicleSpecValue(entry) === "endurance").length : 0;
    const details = [
        "Only one LiveryLab grid can be active in AC EVO at a time. Activating replaces the currently active grid.",
        "LiveryLab installs or updates the required AC EVO Grid Bridge automatically if needed. Existing AC EVO UI files are backed up before changes.",
      ];
      if (enduranceCount) {
        details.push(`${enduranceCount} Endurance AI spec entr${enduranceCount === 1 ? "y" : "ies"} will use temporary LiveryLab mechanical presets for Lumirank and endurance/front bumper parts where available.`);
      }
      confirmed = await window.showConfirmModal({
        type: "warning",
        title: `${action.modalLabel} in AC EVO`,
        message: `${action.modalLabel} "${grid.name || grid.id}" for AC EVO?`,
        details: details.join("\n\n"),
        confirmLabel: action.modalLabel,
        loadingLabel: "Activating...",
      });
    }
    if (!confirmed) return;
    try {
      const result = await apiCall("export_custom_grid_bridge", { root: gameRoot(), grid });
      state.bridgeStatus = result.data?.status || state.bridgeStatus;
      if (result.data?.nameCleanupStatus || result.data?.legacyNameCleanupRemoval?.status || result.data?.bridgeInstall?.legacyNameCleanupRemoval?.status) {
        state.nameCleanupStatus = result.data?.nameCleanupStatus || result.data?.legacyNameCleanupRemoval?.status || result.data?.bridgeInstall?.legacyNameCleanupRemoval?.status;
      }
      renderBridgeTools();
      renderList();
      renderDetail();
      showModal("success", "Grid Activated", `${grid.name || "Custom Grid"} is ready for the AC EVO bridge.`, result.message || "");
    } catch (error) {
      showModal("error", "Export Grid to AC EVO", error?.message || String(error));
    }
  }

  function addSelectedSkin() {
    const grid = updateSelectedFromForm();
    const select = $("customGridSkinSelect");
    const skin = state.mySkins.find((item) => item.key === select?.value);
    if (!grid || !skin) return;
    grid.entries = Array.isArray(grid.entries) ? grid.entries : [];
    const skinKey = String(skin.key || "").trim().toLowerCase();
    if (skinKey && grid.entries.some((entry) => entrySkinKey(entry) === skinKey)) {
      showModal("error", "Add Skin", "This livery is already in the selected grid.", "Remove the existing entry first, or choose another livery.");
      return;
    }
    grid.entries.push(normalizeEntryFromSkin(skin));
    renderDetail();
    markDirty();
  }

  function removeEntry(index) {
    const grid = updateSelectedFromForm();
    if (!grid) return;
    grid.entries.splice(index, 1);
    renderDetail();
    markDirty();
  }

  function moveEntry(index, direction) {
    const grid = updateSelectedFromForm();
    if (!grid) return;
    const target = index + direction;
    if (target < 0 || target >= grid.entries.length) return;
    const [entry] = grid.entries.splice(index, 1);
    grid.entries.splice(target, 0, entry);
    renderDetail();
    markDirty();
  }

  function skinOptionLabel(skin) {
    return [
      skin.display_name || skin.displayName || skin.skin_id || skin.skinId || "Skin",
      skin.car_model || skin.carModel || "",
    ].filter(Boolean).join(" / ");
  }

  function bridgeCanRemove(bridge = state.bridgeStatus || {}) {
    return !!(
      bridge.installed
      || bridge.requiresCleanup
      || bridge.currentGridExists
      || bridge.currentGridScriptExists
      || bridge.bridgeScriptExists
      || bridge.ingameScriptExists
      || bridge.driverlabelsScriptExists
    );
  }

  function bridgeNeedsUpdate(bridge = state.bridgeStatus || {}) {
    return bridge.bridgeScriptExists && bridge.bridgeVersionCurrent === false;
  }

  function bridgeSummary(bridge = state.bridgeStatus || {}) {
    const needsUpdate = bridgeNeedsUpdate(bridge);
    const label = bridge.installed
      ? (bridge.currentGridExists ? "Bridge installed / grid exported" : "Bridge installed")
      : needsUpdate
        ? "Bridge update required"
      : bridge.requiresCleanup
        ? "Bridge cleanup available"
        : "Bridge not installed";
    const className = bridge.installed ? "complete" : (needsUpdate || bridge.requiresCleanup ? "partial" : "missing");
    return { label, className };
  }

  function contentPackageSummary(contentPackage = state.contentPackageStatus || {}) {
    const active = !!contentPackage.activeExists;
    const label = active
      ? "content.kspkg active / loose UI hooks blocked"
      : contentPackage.disabledExists
        ? "content.kspkg disabled / loose UI hooks allowed"
        : "content.kspkg not active";
    return { active, label, className: active ? "missing" : "complete" };
  }

  function renderBridgeTools() {
    const tools = $("customGridBridgeTools");
    if (!tools) return;
    const bridge = state.bridgeStatus || {};
    const content = contentPackageSummary();
    const bridgeInfo = bridgeSummary(bridge);
    const bridgeMode = content.active
      ? "Disable or rename content.kspkg before activating a grid."
      : "Managed automatically by Activate Grid in Game and Deactivate Grid in Game.";
    tools.innerHTML = `
      <div class="custom-grid-tool-head">
        <strong>AC EVO Bridge</strong>
        <span class="status ${bridgeInfo.className}">${escapeHtml(bridgeInfo.label)}</span>
      </div>
      <div class="custom-grid-tool-status">
        <span class="status ${content.className}">${escapeHtml(content.label)}</span>
        <span>${escapeHtml(bridge.currentGridPath || "uiresources/liverylab_grid_bridge/current_grid.json")}</span>
      </div>
      <div class="custom-grid-tool-actions">
        <span>${escapeHtml(bridgeMode)}</span>
      </div>
    `;
  }

  function renderList() {
    const list = $("customGridList");
    if (!list) return;
    list.innerHTML = "";
    if (state.loading && !state.grids.length) {
      list.innerHTML = `
        <div class="custom-grid-loading">
          <span class="button-spinner" aria-hidden="true"></span>
          <strong>Loading Custom Grids...</strong>
        </div>
      `;
      return;
    }
    if (!state.grids.length) {
      list.innerHTML = `<div class="custom-grid-empty">No custom grids yet.</div>`;
      return;
    }
    state.grids.forEach((grid) => {
      const entries = Array.isArray(grid.entries) ? grid.entries : [];
      const button = document.createElement("button");
      button.type = "button";
      button.className = "custom-grid-item";
      if (grid.id === state.selectedId) button.classList.add("active");
      button.innerHTML = `
        ${gridPreviewMarkHtml(grid)}
        <span class="custom-grid-item-copy">
          <strong>
            <span>${escapeHtml(grid.name || "Grid")}</span>
          </strong>
          <span>${entries.length} entr${entries.length === 1 ? "y" : "ies"}</span>
          <small>${escapeHtml(grid.updatedAt || "")}</small>
        </span>
        ${isBridgeActiveGrid(grid) ? `<span class="custom-grid-item-active-slot">${bridgeActiveGridBadgeHtml(grid)}</span>` : ""}
      `;
      button.addEventListener("click", () => {
        state.selectedId = grid.id;
        state.dirty = false;
        render();
      });
      list.append(button);
    });
    loadGridPreviewImages(list);
  }

  function syncPackageButtons() {
    const hasGrid = !!selectedGrid();
    const exportButton = $("exportCustomGridPreset");
    const importButton = $("importCustomGridPreset");
    if (exportButton) exportButton.disabled = !hasGrid;
    if (importButton) importButton.disabled = false;
  }

  function renderDetail() {
    const detail = $("customGridDetail");
    if (!detail) return;
    const grid = selectedGrid();
    if (state.loading && !grid) {
      detail.innerHTML = `
        <div class="custom-grid-loading">
          <span class="button-spinner" aria-hidden="true"></span>
          <strong>Loading Custom Grids...</strong>
        </div>
      `;
      return;
    }
    if (!grid) {
      detail.innerHTML = `<div class="custom-grid-empty">Create a grid preset to start selecting cars and skins.</div>`;
      return;
    }
    const entries = Array.isArray(grid.entries) ? grid.entries : [];
    const bridge = state.bridgeStatus || {};
    const nameCleanup = state.nameCleanupStatus || {};
    const cache = state.cacheStatus || {};
    const contentPackage = state.contentPackageStatus || {};
    const contentPackageInfo = contentPackageSummary(contentPackage);
    const contentPackageActive = contentPackageInfo.active;
    const bridgeAction = bridgeGridActionState(grid);
    const bridgeActionPulse = Boolean(bridgeAction.pulse && !bridgeAction.disabled && !contentPackageActive);
    const inactiveBridgeText = bridge.activeGridId
      ? `AC EVO currently loads ${bridge.activeGridName || bridge.activeGridId}.`
      : bridgeAction.statusText;
    const activeBridgeActionNote = `<div class="custom-grid-action-status">
      <span class="status ${bridgeAction.statusClass}">${escapeHtml(bridgeAction.statusLabel)}</span>
      <span>${escapeHtml(isBridgeActiveGrid(grid) ? bridgeAction.statusText : inactiveBridgeText)}</span>
    </div>`;
    const latestCacheBackup = cache.latestBackup || null;
    const cleanupLabel = nameCleanup.installed
      ? "Legacy AI name cleanup installed"
      : nameCleanup.requiresCleanup
        ? "Legacy AI name cleanup removable"
      : "Legacy AI name cleanup not installed";
    const cleanupClass = nameCleanup.installed ? "complete" : (nameCleanup.requiresCleanup ? "partial" : "missing");
    const canRemoveNameCleanup = !!(nameCleanup.installed || nameCleanup.requiresCleanup || nameCleanup.scriptExists);
    const cacheFiles = Array.isArray(cache.files) ? cache.files : [];
    const cacheLabel = cache.hasResettableFiles ? "ACE grid cache present" : "ACE grid cache clear";
    const cacheClass = cache.hasResettableFiles ? "partial" : "complete";
    const debugStorageCleanup = isDebugMode() ? `
      <details class="custom-grid-technical">
        <summary>Storage and cleanup</summary>
        <pre>${escapeHtml(state.registryPath || "GridPresets/grid_presets.json")}</pre>
        <div class="custom-grid-cache-status">
          <span class="status ${contentPackageInfo.className}">${escapeHtml(contentPackageInfo.label)}</span>
          <span>${escapeHtml(contentPackage.activePath || "content.kspkg")}</span>
        </div>
        <div class="custom-grid-cache-actions">
          <button id="removeAllCustomGridUiHooks" type="button" class="danger-outline">Remove All AC EVO UI Hooks</button>
        </div>
        <div class="custom-grid-cache-status">
          <span class="status ${cleanupClass}">${escapeHtml(cleanupLabel)}</span>
          <span>${escapeHtml(nameCleanup.scriptPath || "uiresources/js/liverylab_ai_name_cleanup.js")}</span>
        </div>
        <div class="custom-grid-cache-actions">
          <button id="removeNameMarkerCleanup" type="button" class="danger-outline"${canRemoveNameCleanup ? "" : " disabled"}>Remove Legacy AI Name Cleanup</button>
        </div>
        <div class="custom-grid-cache-status">
          <span class="status ${cacheClass}">${escapeHtml(cacheLabel)}</span>
          <span>${escapeHtml(cache.gameModesRoot || "Saved Games\\ACE\\GameModes")}</span>
        </div>
        <div class="custom-grid-cache-actions">
          <button id="resetAceGridCache" type="button" class="danger-outline"${cache.gameModesRootExists ? "" : " disabled"}>Reset ACE Grid Cache</button>
          <button id="restoreAceGridCacheBackup" type="button"${latestCacheBackup ? "" : " disabled"}>Restore Last Grid Cache Backup</button>
        </div>
        <pre>${escapeHtml(cacheFiles.map((item) => `${item.exists ? "present" : "missing"} / ${item.action}: ${item.name}`).join("\n") || "No ACE grid-cache status loaded.")}</pre>
        ${latestCacheBackup ? `<pre>${escapeHtml(`Latest backup: ${latestCacheBackup.path}`)}</pre>` : ""}
      </details>
    ` : "";
    const packedModeWarning = contentPackageActive
      ? `<div class="custom-grid-bridge-status">
          <span class="status missing">Packed content mode</span>
          <span>Install/export actions are blocked while content.kspkg is active. Remove all UI hooks before using packed content mode.</span>
        </div>`
      : "";
    const skinOptions = state.mySkins.map((skin) => `<option value="${escapeHtml(skin.key || "")}">${escapeHtml(skinOptionLabel(skin))}</option>`).join("");
    const entryRows = entries.map((entry, index) => {
      const enduranceSupported = aiVehicleSpecSupported(entry, "endurance");
      const aiSpecValue = aiVehicleSpecUiValue(entry);
      const aiSpecTitle = enduranceSupported ? "" : " title=\"Endurance is only available for cars with matching Endurance/Lumirank compatible parts.\"";
      return `
      <article class="custom-grid-entry" data-custom-grid-entry data-entry-id="${escapeHtml(entry.id || "")}">
        <div class="custom-grid-entry-index">${index + 1}</div>
        <div class="custom-grid-entry-thumb">
          ${entry.thumbnailPngDiskPath
            ? `<img alt="" src="${placeholderSrc()}" data-custom-grid-entry-thumb-path="${escapeHtml(entry.thumbnailPngDiskPath)}" />`
            : `<span>SKIN</span>`}
        </div>
        <div class="custom-grid-entry-copy">
          <strong>${escapeHtml(entry.displayName || entry.skinId || "Skin")}</strong>
          <span>${escapeHtml([entry.carModel || "", entry.skinId || "", entryCarNumber(entry) ? `#${entryCarNumber(entry)}` : ""].filter(Boolean).join(" / "))}</span>
          <span>${escapeHtml(`AI spec: ${aiSpecValue === "endurance" ? "Endurance" : "Standard"}`)}</span>
        </div>
        <label>Driver name
          <input data-entry-field="driverName" type="text" spellcheck="false" required value="${escapeHtml(entry.driverName || entry.displayName || "")}" />
        </label>
        <label data-tutorial-id="custom-grids-ai-spec">AI vehicle spec
          <select data-entry-field="aiVehicleSpec"${aiSpecTitle}>
            <option value="standard"${aiSpecValue === "standard" ? " selected" : ""}>Standard</option>
            <option value="endurance"${aiSpecValue === "endurance" ? " selected" : ""}${enduranceSupported ? "" : " disabled"}>Endurance</option>
          </select>
        </label>
        <label>Team
          <input data-entry-field="team" type="text" spellcheck="false" value="${escapeHtml(entry.team || "")}" />
        </label>
        <div class="custom-grid-entry-actions">
          <button type="button" class="icon-text" data-entry-action="up" data-entry-index="${index}"${index === 0 ? " disabled" : ""}>${icon("up")}Up</button>
          <button type="button" class="icon-text" data-entry-action="down" data-entry-index="${index}"${index === entries.length - 1 ? " disabled" : ""}>${icon("down")}Down</button>
          <button type="button" data-entry-action="remove" data-entry-index="${index}" class="danger-outline icon-text">${icon("trash")}Remove</button>
        </div>
      </article>
    `;
    }).join("");

    detail.innerHTML = `
      <div class="custom-grid-detail-head">
        <div class="custom-grid-title-block">
          <h2>${escapeHtml(grid.name || "Grid")}</h2>
          <div class="custom-grid-subtitle">${entries.length} entr${entries.length === 1 ? "y" : "ies"} / local JSON preset</div>
        </div>
        <div class="custom-grid-detail-actions">
          ${activeBridgeActionNote}
          <button id="exportCustomGridBridge" type="button" class="custom-grid-activate-action custom-grid-white-icon icon-text ${bridgeAction.primary ? "primary" : ""} ${bridgeActionPulse ? "my-skin-game-sync-pulse" : ""}"${contentPackageActive || bridgeAction.disabled ? " disabled" : ""}>${icon("power")}${escapeHtml(bridgeAction.label)}</button>
          <button id="deleteCustomGrid" type="button" class="custom-grid-delete-action custom-grid-white-icon danger-outline icon-text">${icon("trash")}Delete</button>
        </div>
      </div>
      ${packedModeWarning}
      <div class="custom-grid-editor-grid">
        <section class="custom-grid-preview-box">
          <div class="custom-grid-section-head">
            <strong>Grid Preview</strong>
            <span>Square PNG</span>
          </div>
          <div class="custom-grid-preview-stage">
            ${gridPreviewMarkHtml(grid, { large: true })}
          </div>
          <button id="chooseCustomGridPreviewPng" type="button">Choose PNG</button>
        </section>
        <label>Grid name
          <input id="customGridName" type="text" spellcheck="false" value="${escapeHtml(grid.name || "")}" />
        </label>
        <label>Description
          <input id="customGridDescription" type="text" spellcheck="false" value="${escapeHtml(grid.description || "")}" />
        </label>
      </div>
      <div class="custom-grid-add-row">
        <label>Select livery for grid
          <select id="customGridSkinSelect"${state.mySkins.length ? "" : " disabled"}>
            ${skinOptions || `<option value="">No registered My Liveries</option>`}
          </select>
        </label>
        <button id="addCustomGridSkin" type="button" class="primary custom-grid-white-icon icon-text"${state.mySkins.length ? "" : " disabled"}>${icon("plus")}Add to Grid</button>
      </div>
      <div class="custom-grid-entry-list">
        ${entryRows || `<div class="custom-grid-empty">No entries yet. Add skins from My Liveries.</div>`}
      </div>
      <div class="custom-grid-save-row">
        <button id="saveCustomGrid" type="button" class="primary custom-grid-white-icon icon-text">${icon("save")}Save Grid</button>
      </div>
      ${debugStorageCleanup}
    `;

    $("customGridName")?.addEventListener("input", markDirty);
    $("customGridDescription")?.addEventListener("input", markDirty);
    $("chooseCustomGridPreviewPng")?.addEventListener("click", chooseGridPreviewPng);
    $("addCustomGridSkin")?.addEventListener("click", addSelectedSkin);
    $("saveCustomGrid")?.addEventListener("click", saveSelected);
    $("exportCustomGridBridge")?.addEventListener("click", exportSelectedToBridge);
    $("removeAllCustomGridUiHooks")?.addEventListener("click", removeAllUiHooks);
    $("removeNameMarkerCleanup")?.addEventListener("click", removeNameCleanup);
    $("resetAceGridCache")?.addEventListener("click", resetAceGridCache);
    $("restoreAceGridCacheBackup")?.addEventListener("click", restoreAceGridCacheBackup);
    $("duplicateCustomGrid")?.addEventListener("click", duplicateSelected);
    $("deleteCustomGrid")?.addEventListener("click", deleteSelected);
    detail.querySelectorAll("input[data-entry-field], select[data-entry-field]").forEach((input) => {
      input.addEventListener(input.tagName === "SELECT" ? "change" : "input", markDirty);
    });
    detail.querySelectorAll("[data-entry-action]").forEach((button) => {
      button.addEventListener("click", () => {
        const index = Number(button.dataset.entryIndex || -1);
        if (button.dataset.entryAction === "remove") removeEntry(index);
        if (button.dataset.entryAction === "up") moveEntry(index, -1);
        if (button.dataset.entryAction === "down") moveEntry(index, 1);
      });
    });
    loadGridPreviewImages(detail);
  }

  function clearLoadingOverlays() {
    $("customGridList")?.closest(".custom-grid-rail")?.querySelectorAll(".custom-grid-loading-overlay").forEach((overlay) => overlay.remove());
    $("customGridDetail")?.querySelectorAll(".custom-grid-loading-overlay").forEach((overlay) => overlay.remove());
  }

  function render() {
    clearLoadingOverlays();
    renderBridgeTools();
    renderList();
    renderDetail();
    syncPackageButtons();
  }

  function init() {
    if (state.initialized) return;
    state.initialized = true;
    $("refreshCustomGrids")?.addEventListener("click", load);
    $("newCustomGrid")?.addEventListener("click", createGrid);
    $("exportCustomGridPreset")?.addEventListener("click", exportSelectedPackage);
    $("importCustomGridPreset")?.addEventListener("click", importPackage);
  }

  window.LiveryLabCustomGrids = {
    init,
    load,
    render,
    closeBridgeGuideModal,
  };
})();
