const tauriCore = window.__TAURI__?.core;
const invoke = tauriCore?.invoke?.bind(tauriCore);

function setupTauriDragDrop() {
  const tauri = window.__TAURI__;
  if (!tauri?.event?.listen || !invoke) return;
  const handleDrop = (paths) => {
    if (!paths?.length) return;
    if (appShell?.hidden) return;
    const route = document.querySelector(".tool-panel.active")?.dataset?.panel;
    const path = paths[0];
    if (route === "studio") processStudioDropPath(path);
    else if (route === "inspector") verifyInspectorPath(path);
  };
  tauri.event.listen("tauri://file-drop", (e) => {
    const paths = Array.isArray(e.payload) ? e.payload : (e.payload?.paths ?? []);
    handleDrop(paths);
  });
  tauri.event.listen("tauri://drag-drop", (e) => {
    const paths = e.payload?.paths ?? (Array.isArray(e.payload) ? e.payload : []);
    handleDrop(paths);
  });
}
const convertFileSrc = typeof tauriCore?.convertFileSrc === "function"
  ? tauriCore.convertFileSrc.bind(tauriCore)
  : (path) => path;

const lockScreen = document.getElementById("lockScreen");
const appShell = document.getElementById("appShell");
const lockTitle = document.getElementById("lockTitle");
const lockSubtitle = document.getElementById("lockSubtitle");
const lockMessage = document.getElementById("lockMessage");
const masterPasswordLabel = document.getElementById("masterPasswordLabel");
const masterPasswordInput = document.getElementById("masterPasswordInput");
const confirmPasswordGroup = document.getElementById("confirmPasswordGroup");
const confirmPasswordInput = document.getElementById("confirmPasswordInput");
const unlockBtn = document.getElementById("unlockBtn");
const initVaultBtn = document.getElementById("initVaultBtn");
const restoreVaultBtn = document.getElementById("restoreVaultBtn");
const navTabs = document.querySelectorAll(".nav-tab");
const panels = document.querySelectorAll(".tool-panel");
const sidebarIdentityNudge = document.getElementById("sidebarIdentityNudge");
const sidebarActiveIdentity = document.getElementById("sidebarActiveIdentity");
const vaultLocationCopy = document.getElementById("vaultLocationCopy");
const vaultGrid = document.getElementById("vaultGrid");
const vaultEmptyState = document.getElementById("vaultEmptyState");
const vaultFeedback = document.getElementById("vaultFeedback");
const registerArtworkBtn = document.getElementById("registerArtworkBtn");
const registerFirstArtworkBtn = document.getElementById("registerFirstArtworkBtn");
const studioDropzone = document.getElementById("studioDropzone");
const studioBrowseBtn = document.getElementById("studioBrowseBtn");
const studioFileInput = document.getElementById("studioFileInput");
const studioActiveState = document.getElementById("studioActiveState");
const studioPreviewImage = document.getElementById("studioPreviewImage");
const studioTitleInput = document.getElementById("studioTitleInput");
const studioAuthorInput = document.getElementById("studioAuthorInput");
const studioDescriptionInput = document.getElementById("studioDescriptionInput");
const studioDateCreatedInput = document.getElementById("studioDateCreatedInput");
const studioKeywordsInput = document.getElementById("studioKeywordsInput");
const studioGenreInput = document.getElementById("studioGenreInput");
const studioMaterialInput = document.getElementById("studioMaterialInput");
const studioContributorInput = document.getElementById("studioContributorInput");
const studioLicenseInput = document.getElementById("studioLicenseInput");
const studioAbstractInput = document.getElementById("studioAbstractInput");
const studioTagSelect = document.getElementById("studioTagSelect");
const studioInvisibleWatermark = document.getElementById("studioInvisibleWatermark");
const studioSigningMode = document.getElementById("studioSigningMode");
const studioFeedback = document.getElementById("studioFeedback");
const studioSealBtn = document.getElementById("studioSealBtn");
const studioSaveDraftBtn = document.getElementById("studioSaveDraftBtn");
const studioClearBtn = document.getElementById("studioClearBtn");
const studioSuccessState = document.getElementById("studioSuccessState");
const studioManifestId = document.getElementById("studioManifestId");
const studioTagWriteHint = document.getElementById("studioTagWriteHint");
const studioIpfsWarning = document.getElementById("studioIpfsWarning");
const studioIpfsOriginalPath = document.getElementById("studioIpfsOriginalPath");
const studioSealAnotherBtn = document.getElementById("studioSealAnotherBtn");
const studioViewInVaultBtn = document.getElementById("studioViewInVaultBtn");
const inspectorTransferBtn = document.getElementById("inspectorTransferBtn");
const inspectorClearBtn = document.getElementById("inspectorClearBtn");
const inspectorFeedback = document.getElementById("inspectorFeedback");
const inspectorProgressOverlay = document.getElementById("inspectorProgressOverlay");
const inspectorProgressTitle = document.getElementById("inspectorProgressTitle");
const inspectorProgressFill = document.getElementById("inspectorProgressFill");
const inspectorProgressMeta = document.getElementById("inspectorProgressMeta");
const inspectorFileInput = document.getElementById("inspectorFileInput");
const inspectorDropzone = document.getElementById("inspectorDropzone");
const inspectorBrowseBtn = document.getElementById("inspectorBrowseBtn");
const inspectorResults = document.getElementById("inspectorResults");
const inspectorPreviewImage = document.getElementById("inspectorPreviewImage");
const inspectorMetadataFilePath = document.getElementById("inspectorMetadataFilePath");
const inspectorMetadataLabel = document.getElementById("inspectorMetadataLabel");
const inspectorStatusPill = document.getElementById("inspectorStatusPill");
const inspectorCopyDataUriLink = document.getElementById("inspectorCopyDataUriLink");
const inspectorTimeline = document.getElementById("inspectorTimeline");
const inspectorMetadata = document.getElementById("inspectorMetadata");
const inspectorMetadataTitle = document.getElementById("inspectorMetadataTitle");
const inspectorMetadataAuthor = document.getElementById("inspectorMetadataAuthor");
const inspectorMetadataDescription = document.getElementById("inspectorMetadataDescription");
const inspectorMetadataDateCreated = document.getElementById("inspectorMetadataDateCreated");
const inspectorMetadataKeywords = document.getElementById("inspectorMetadataKeywords");
const inspectorMetadataGenre = document.getElementById("inspectorMetadataGenre");
const inspectorMetadataMaterial = document.getElementById("inspectorMetadataMaterial");
const inspectorMetadataContributor = document.getElementById("inspectorMetadataContributor");
const inspectorMetadataAbstract = document.getElementById("inspectorMetadataAbstract");
const inspectorMetadataLicense = document.getElementById("inspectorMetadataLicense");
const inspectorMetadataArt = document.getElementById("inspectorMetadataArt");
const inspectorMetadataInstance = document.getElementById("inspectorMetadataInstance");
const inspectorMetadataManifest = document.getElementById("inspectorMetadataManifest");
const inspectorMetadataPerceptual = document.getElementById("inspectorMetadataPerceptual");
const inspectorMetadataWatermark = document.getElementById("inspectorMetadataWatermark");
const inspectorMetadataTag = document.getElementById("inspectorMetadataTag");
const inspectorMetadataArtworkId = document.getElementById("inspectorMetadataArtworkId");
const transferModalBackdrop = document.getElementById("transferModalBackdrop");
const transferRecipientSelect = document.getElementById("transferRecipientSelect");
const transferNoContactsMsg = document.getElementById("transferNoContactsMsg");
const transferModalFeedback = document.getElementById("transferModalFeedback");
const contactsImportBtn = document.getElementById("contactsImportBtn");
const contactsFeedback = document.getElementById("contactsFeedback");
const contactsList = document.getElementById("contactsList");
const tagsClearBtn = document.getElementById("tagsClearBtn");
const tagsScanBtn = document.getElementById("tagsScanBtn");
const tagsScanEmptyBtn = document.getElementById("tagsScanEmptyBtn");
const tagsRescanBtn = document.getElementById("tagsRescanBtn");
const tagsResetTagBtn = document.getElementById("tagsResetTagBtn");
const tagsFeedback = document.getElementById("tagsFeedback");
const tagsListSection = document.getElementById("tagsListSection");
const tagsListGrid = document.getElementById("tagsListGrid");
const tagsEmptyState = document.getElementById("tagsEmptyState");
const tagsDiscoveryPanel = document.getElementById("tagsDiscoveryPanel");
const tagsVerificationPanel = document.getElementById("tagsVerificationPanel");
const tagsControlPanel = document.getElementById("tagsControlPanel");
const tagsContentPanel = document.getElementById("tagsContentPanel");
const tagsEnrollBtn = document.getElementById("tagsEnrollBtn");
const tagsRotateKeysBtn = document.getElementById("tagsRotateKeysBtn");
const tagsClaimBtn = document.getElementById("tagsClaimBtn");
const tagsReleaseBtn = document.getElementById("tagsReleaseBtn");
const tagsVerificationUrlInput = document.getElementById("tagsVerificationUrlInput");
const tagsContentUrlInput = document.getElementById("tagsContentUrlInput");
const tagsNotesInput = document.getElementById("tagsNotesInput");
const tagsUrlPreview = document.getElementById("tagsUrlPreview");
const tagsRewriteBtn = document.getElementById("tagsRewriteBtn");
const tagsLinkArtworkPanel = document.getElementById("tagsLinkArtworkPanel");
const tagsLinkArtworkSelect = document.getElementById("tagsLinkArtworkSelect");
const tagsLinkArtworkBtn = document.getElementById("tagsLinkArtworkBtn");
const tagsPendingWritePanel = document.getElementById("tagsPendingWritePanel");
const tagsPendingWriteBtn = document.getElementById("tagsPendingWriteBtn");
const transferCancelBtn = document.getElementById("transferCancelBtn");
const transferConfirmBtn = document.getElementById("transferConfirmBtn");
const settingsCreateProfileToggleBtn = document.getElementById("settingsCreateProfileToggleBtn");
const settingsCreateProfileForm = document.getElementById("settingsCreateProfileForm");
const settingsProfileNameInput = document.getElementById("settingsProfileNameInput");
const settingsProfileOrgInput = document.getElementById("settingsProfileOrgInput");
const settingsProfileCountryInput = document.getElementById("settingsProfileCountryInput");
const settingsCreateProfileBtn = document.getElementById("settingsCreateProfileBtn");
const settingsActiveName = document.getElementById("settingsActiveName");
const settingsActiveOrg = document.getElementById("settingsActiveOrg");
const settingsActiveFingerprint = document.getElementById("settingsActiveFingerprint");
const settingsCertStatus = document.getElementById("settingsCertStatus");
const settingsExportCertBtn = document.getElementById("settingsExportCertBtn");
const settingsIdentitySelect = document.getElementById("settingsIdentitySelect");
const settingsSetActiveBtn = document.getElementById("settingsSetActiveBtn");
const settingsDeleteIdentityBtn = document.getElementById("settingsDeleteIdentityBtn");
const settingsProfileFeedback = document.getElementById("settingsProfileFeedback");
const settingsExportBackupBtn = document.getElementById("settingsExportBackupBtn");
const settingsExportVaultBtn = document.getElementById("settingsExportVaultBtn");
const settingsChangePasswordBtn = document.getElementById("settingsChangePasswordBtn");
const settingsBackupFeedback = document.getElementById("settingsBackupFeedback");
const changePasswordModalBackdrop = document.getElementById("changePasswordModalBackdrop");
const changePasswordCurrentInput = document.getElementById("changePasswordCurrentInput");
const changePasswordNewInput = document.getElementById("changePasswordNewInput");
const changePasswordConfirmInput = document.getElementById("changePasswordConfirmInput");
const changePasswordModalFeedback = document.getElementById("changePasswordModalFeedback");
const changePasswordCancelBtn = document.getElementById("changePasswordCancelBtn");
const changePasswordConfirmBtn = document.getElementById("changePasswordConfirmBtn");
const settingsAdvancedToggleBtn = document.getElementById("settingsAdvancedToggleBtn");
const settingsAdvancedPanel = document.getElementById("settingsAdvancedPanel");
const settingsCsrNameInput = document.getElementById("settingsCsrNameInput");
const settingsCsrOrgInput = document.getElementById("settingsCsrOrgInput");
const settingsCsrCountryInput = document.getElementById("settingsCsrCountryInput");
const settingsCsrOutputPathInput = document.getElementById("settingsCsrOutputPathInput");
const settingsBrowseCsrBtn = document.getElementById("settingsBrowseCsrBtn");
const settingsGenerateCsrBtn = document.getElementById("settingsGenerateCsrBtn");
const settingsCaChainPathInput = document.getElementById("settingsCaChainPathInput");
const settingsBrowseCaBtn = document.getElementById("settingsBrowseCaBtn");
const settingsUpgradeCaBtn = document.getElementById("settingsUpgradeCaBtn");
const settingsAdvancedFeedback = document.getElementById("settingsAdvancedFeedback");
const settingsDomReady = Boolean(
  settingsCreateProfileToggleBtn &&
  settingsCreateProfileForm &&
  settingsIdentitySelect &&
  settingsSetActiveBtn &&
  settingsExportCertBtn &&
  settingsExportBackupBtn &&
  settingsAdvancedToggleBtn &&
  settingsBrowseCsrBtn &&
  settingsGenerateCsrBtn &&
  settingsBrowseCaBtn &&
  settingsUpgradeCaBtn
);

const appToast = document.getElementById("appToast");
let _toastTimer = 0;
function showAppToast(msg, tone = "") {
  if (!appToast) return;
  clearTimeout(_toastTimer);
  if (!msg) { appToast.classList.remove("visible"); return; }
  appToast.textContent = msg;
  appToast.classList.remove("error");
  if (tone === "error") appToast.classList.add("error");
  appToast.hidden = false;
  void appToast.offsetWidth;
  appToast.classList.add("visible");
  _toastTimer = setTimeout(() => {
    appToast.classList.remove("visible");
    setTimeout(() => { appToast.hidden = true; }, 200);
  }, 5000);
}

function withNfcTimeout(promise, ms = 16000) {
  return Promise.race([
    promise,
    new Promise((_, reject) =>
      setTimeout(() => reject(new Error("NFC operation timed out. Remove the tag, wait a moment, and try again.")), ms)
    ),
  ]);
}

let lockMode = "unlock";
let preferredAuthorName = "";
let activeMasterPassword = "";
let studioSelectedFilePath = "";
let studioPreviewObjectUrl = "";
let studioActiveDraftId = null;
let studioSealBusy = false;
let inspectorCurrentPath = "";
let inspectorLastVerification = null;
let inspectorDataUriValue = "";
let inspectorWatermarkResult = null;
let inspectorWatermarkBusy = false;
let inspectorWatermarkPath = "";
let inspectorVerifyToken = 0;
let inspectorProgressTimer = null;
let inspectorProgressValue = 0;
let tagsCurrentClassification = "";
let tagsCurrentTag = null; // { id, uid, identity_id, ... } from last scan
let tagsCurrentLiveDetails = null;
let tagsHasPendingWrite = false;
let settingsActiveIdentity = null;
let settingsIdentityList = [];

function setLockMessage(message, tone = "") {
  lockMessage.textContent = message;
  lockMessage.classList.remove("success", "error");
  if (tone) {
    lockMessage.classList.add(tone);
  }
}

function setBusy(isBusy) {
  unlockBtn.disabled = isBusy;
  initVaultBtn.disabled = isBusy;
  masterPasswordInput.disabled = isBusy;
  confirmPasswordInput.disabled = isBusy;
  if (restoreVaultBtn) restoreVaultBtn.disabled = isBusy;
}

function ensureTauriAvailable() {
  if (typeof invoke === "function") {
    return true;
  }
  setLockMode("unlock");
  setLockMessage(
    "Runtime connection failed. Restart dev mode with `bun run tauri dev` so Tauri commands are available.",
    "error"
  );
  setBusy(true);
  return false;
}

function setLockMode(mode) {
  lockMode = mode;
  const isWelcome = mode === "welcome";
  if (lockTitle) {
    lockTitle.hidden = !isWelcome;
    lockTitle.textContent = isWelcome ? "Welcome to Trust Systems by charm.farm" : "";
  }
  if (lockSubtitle) {
    lockSubtitle.hidden = !isWelcome;
    lockSubtitle.textContent = isWelcome
      ? "Create your sovereign local vault to secure your keys and provenance records."
      : "";
  }
  if (masterPasswordLabel) {
    masterPasswordLabel.hidden = !isWelcome;
    masterPasswordLabel.textContent = isWelcome ? "New Master Password" : "";
  }
  masterPasswordInput.placeholder = isWelcome ? "Create master password" : "Enter master password";
  masterPasswordInput.setAttribute("autocomplete", isWelcome ? "new-password" : "current-password");
  confirmPasswordGroup.hidden = !isWelcome;
  unlockBtn.hidden = isWelcome;
  initVaultBtn.hidden = !isWelcome;
  confirmPasswordInput.value = "";
  setLockMessage("");
}

async function refreshVaultLocationCopy() {
  if (!vaultLocationCopy) return;
  if (typeof invoke !== "function") {
    vaultLocationCopy.textContent = "Vault location: unavailable";
    return;
  }
  try {
    const path = await invoke("get_vault_db_path");
    vaultLocationCopy.textContent = `Vault location: ${String(path || "")}`;
  } catch (_) {
    vaultLocationCopy.textContent = "Vault location: unavailable";
  }
}

async function loadStudioTagOptions() {
  if (!studioTagSelect || !ensureTauriAvailable() || !activeMasterPassword.trim()) return;
  const selected = studioTagSelect.value;
  studioTagSelect.innerHTML = '<option value="">— None —</option>';
  try {
    const tags = await invoke("list_tags_available_for_seal", {
      masterPassword: activeMasterPassword
    });
    if (Array.isArray(tags) && tags.length > 0) {
      tags.forEach((tag) => {
        const opt = document.createElement("option");
        opt.value = String(tag.id);
        const chip = tag.tag_family || tag.chip_subtype || "NFC";
        opt.textContent = `${tag.uid} (${chip})`;
        studioTagSelect.appendChild(opt);
      });
      if (selected && tags.some((t) => String(t.id) === selected)) {
        studioTagSelect.value = selected;
      }
    }
  } catch {
    // No active identity or vault error; leave only "None"
  }
}

async function loadLinkArtworkOptions() {
  if (!tagsLinkArtworkSelect || !ensureTauriAvailable() || !activeMasterPassword.trim()) return;
  const selected = tagsLinkArtworkSelect.value;
  tagsLinkArtworkSelect.innerHTML = '<option value="">— Select artwork —</option>';
  try {
    const artworks = await invoke("list_sealed_artworks_for_linking", {
      masterPassword: activeMasterPassword,
    });
    if (Array.isArray(artworks) && artworks.length > 0) {
      artworks.forEach((d) => {
        const opt = document.createElement("option");
        opt.value = String(d.id);
        const title = d.artifact_title?.trim() || `Draft #${d.id}`;
        const author = d.author?.trim();
        opt.textContent = author ? `${title} — ${author}` : title;
        const details = [d.c2pa_manifest_id, d.asset_path].filter(Boolean).join(" | ");
        if (details) opt.title = details;
        tagsLinkArtworkSelect.appendChild(opt);
      });
      if (selected && artworks.some((d) => String(d.id) === selected)) {
        tagsLinkArtworkSelect.value = selected;
      }
    }
  } catch {
    // No sealed artworks or vault error
  }
}

function setStudioSigningMode(message, isProduction = false) {
  if (!studioSigningMode) return;
  studioSigningMode.textContent = message;
  studioSigningMode.classList.toggle("production", Boolean(isProduction));
}

async function refreshStudioSigningMode() {
  if (!studioSigningMode) return;
  if (!ensureTauriAvailable() || !activeMasterPassword.trim()) {
    setStudioSigningMode("");
    return;
  }
  try {
    const identities = await invoke("list_identities", { masterPassword: activeMasterPassword });
    if (!Array.isArray(identities) || identities.length === 0) {
      setStudioSigningMode("Signing mode: no active profile.");
      return;
    }
    const active = identities.find(identityIsActive) || identities[0];
    const activeName = active?.common_name || `#${active?.id ?? "?"}`;
    if (active?.is_production) {
      setStudioSigningMode(
        `Signing mode: Production certificate loaded (${activeName}). Anchor policy: Charm Farm Root (built-in).`,
        true
      );
    } else {
      setStudioSigningMode(
        `Signing mode: Self-signed certificate (${activeName}). Anchor policy: Charm Farm Root (built-in) will not mark self-signed claims as Charmed.`
      );
    }
  } catch (_) {
    setStudioSigningMode("Signing mode unavailable.");
  }
}

function setUnlockedState() {
  lockScreen.hidden = true;
  lockScreen.style.display = "none";
  appShell.hidden = false;
  appShell.style.display = "grid";
}

function setLockedState() {
  lockScreen.hidden = false;
  lockScreen.style.display = "grid";
  appShell.hidden = true;
  appShell.style.display = "none";
}

function lockVault(customMessage) {
  activeMasterPassword = "";
  preferredAuthorName = "";
  pendingDeleteCallback = null;
  if (sidebarIdentityNudge) sidebarIdentityNudge.hidden = true;
  resetStudio();
  resetInspector();
  resetTags(true);
  resetSettings();
  setLockedState();
  setLockMode("unlock");
  setLockMessage(customMessage ?? "Vault locked.");
  masterPasswordInput.value = "";
  masterPasswordInput.focus();
}

async function checkBootState() {
  if (!ensureTauriAvailable()) return;
  setLockedState();
  setBusy(true);
  setLockMessage("Checking secure vault state...");
  try {
    const initialized = await invoke("is_vault_initialized");
    setLockMode(initialized ? "unlock" : "welcome");
    setLockMessage(
      initialized ? "Vault ready." : "Create your master password to initialize your first vault.",
      initialized ? "success" : ""
    );
  } catch (error) {
    setLockMode("unlock");
    setLockMessage(`Unable to check vault state: ${String(error)}`, "error");
  } finally {
    setBusy(false);
    masterPasswordInput.focus();
  }
}

async function unlockVault() {
  if (!ensureTauriAvailable()) return;
  const masterPassword = masterPasswordInput.value;
  masterPasswordInput.value = "";
  if (!masterPassword.trim()) {
    setLockMessage("Master password is required.", "error");
    return;
  }
  setBusy(true);
  setLockMessage("Unlocking vault...");
  try {
    await invoke("validate_vault_password", { masterPassword });
    setLockMessage("Vault unlocked.", "success");
    activeMasterPassword = masterPassword;
    setUnlockedState();
    await Promise.all([
      loadVaultDrafts(masterPassword),
      preloadActiveIdentityName(masterPassword),
      refreshSettingsProfile(masterPassword),
      refreshStudioSigningMode()
    ]);
  } catch (error) {
    setLockMessage(`Unlock failed: ${String(error)}`, "error");
  } finally {
    setBusy(false);
  }
}

async function initializeVault() {
  if (!ensureTauriAvailable()) return;
  const masterPassword = masterPasswordInput.value;
  const confirmPassword = confirmPasswordInput.value;
  masterPasswordInput.value = "";
  confirmPasswordInput.value = "";
  if (!masterPassword.trim()) {
    setLockMessage("New master password is required.", "error");
    return;
  }
  if (masterPassword !== confirmPassword) {
    setLockMessage("Passwords do not match.", "error");
    return;
  }
  setBusy(true);
  setLockMessage("Initializing vault...");
  try {
    await invoke("init_vault", { masterPassword });
    activeMasterPassword = masterPassword;
    setLockMessage("Vault initialized. Entering workspace...", "success");
    setUnlockedState();
    await Promise.all([
      loadVaultDrafts(masterPassword),
      preloadActiveIdentityName(masterPassword),
      refreshSettingsProfile(masterPassword),
      refreshStudioSigningMode()
    ]);
    resetStudio();
  } catch (error) {
    setLockMessage(`Initialization failed: ${String(error)}`, "error");
  } finally {
    setBusy(false);
  }
}

async function handleRestoreVault() {
  if (!ensureTauriAvailable()) return;
  setBusy(true);
  setLockMessage("");
  try {
    const zipPath = await invoke("pick_open_file_path", {
      title: "Select vault backup (zip)",
      extensions: ["zip"]
    });
    if (!zipPath) {
      setLockMessage("Restore cancelled.");
      setBusy(false);
      return;
    }
    const vaultExists = await invoke("is_vault_initialized");
    const message = vaultExists
      ? "This will replace your current vault with the backup. Continue?"
      : "Restore vault from this backup?";
    openDeleteModal(
      "Restore from Backup",
      message,
      async () => {
        try {
          await invoke("import_vault", { zipPath });
          setLockMode("unlock");
          setLockMessage("✓ Vault restored successfully. Unlock with your master password.", "success");
        } catch (error) {
          setLockMessage(`✗ Restore failed: ${String(error)}`, "error");
        } finally {
          setBusy(false);
        }
      },
      "Restore",
      () => {
        setLockMessage("Restore cancelled.");
        setBusy(false);
      }
    );
  } catch (error) {
    setLockMessage(`✗ Restore failed: ${String(error)}`, "error");
    setBusy(false);
  }
}

let _tagsFeedbackTimer = 0;
const TAGS_FEEDBACK_AUTO_CLEAR_MS = 5000;

function setTagsFeedback(msg, tone = "") {
  clearTimeout(_tagsFeedbackTimer);
  _tagsFeedbackTimer = 0;
  if (tagsFeedback) {
    tagsFeedback.textContent = msg;
    tagsFeedback.classList.remove("error");
    if (tone) tagsFeedback.classList.add(tone);
  }
  if (msg) {
    showAppToast(msg, tone);
    _tagsFeedbackTimer = setTimeout(() => {
      _tagsFeedbackTimer = 0;
      if (tagsFeedback) {
        tagsFeedback.textContent = "";
        tagsFeedback.classList.remove("error");
      }
    }, TAGS_FEEDBACK_AUTO_CLEAR_MS);
  }
}

function getIdentityNameById(id) {
  const identity = (settingsIdentityList || []).find((i) => i.id === id);
  return identity?.common_name || null;
}

function getTagOwnerLabel(tag) {
  if (tag?.identity_id == null) return null;
  return getIdentityNameById(tag.identity_id) || `ID ${tag.identity_id}`;
}

function getOtherIdentityGuidance(tag, actionVerb = "modify") {
  const owner = getTagOwnerLabel(tag);
  return owner
    ? `This tag is managed by ${owner}. Switch active identity in Settings to ${actionVerb} it.`
    : `This tag is managed by another identity. Switch active identity in Settings to ${actionVerb} it.`;
}

function formatCounterAccessText(counterAccess, tag = tagsCurrentTag) {
  if (counterAccess === "authenticated") return "Authenticated";
  if (!counterAccess) {
    return tag?.status === "personalized_sdm"
      ? "Scan with the owning identity to view"
      : "Unavailable";
  }
  const value = String(counterAccess);
  const activeId = settingsActiveIdentity?.id ?? null;
  if (value.startsWith("unavailable")) {
    if (tag?.identity_id != null && tag.identity_id !== activeId) {
      const owner = getTagOwnerLabel(tag);
      return owner
        ? `Unavailable. Switch to ${owner} in Settings to view.`
        : "Unavailable. Switch active identity in Settings to view.";
    }
    if (value.includes("91AE") || value.includes("authentication error") || value.includes("Auth part2")) {
      return "Unavailable with current authentication context";
    }
    return "Unavailable with current access";
  }
  return value;
}

function getFriendlyTagScanFeedback(tag) {
  const activeId = settingsActiveIdentity?.id ?? null;
  if (tag?.identity_id != null && tag.identity_id !== activeId) {
    return `Tag scanned. ${getOtherIdentityGuidance(tag)}`;
  }
  if (tag?.status === "released") {
    return "Tag scanned. This tag is released. You can rewrite it and claim it.";
  }
  return "Tag scanned and saved.";
}

function updateTagsStateGating() {
  const activeId = settingsActiveIdentity?.id ?? null;
  const managed = tagsCurrentTag?.identity_id != null && tagsCurrentTag.identity_id === activeId;
  const ownedByAnotherIdentity = tagsCurrentTag?.identity_id != null && tagsCurrentTag.identity_id !== activeId;
  const released = tagsCurrentTag?.identity_id == null && tagsCurrentTag?.status === "released";
  const canEnroll = (tagsCurrentClassification === "plain_ndef" || tagsCurrentClassification === "factory_default_likely") && activeId != null;
  const canRewrite = managed || (released && activeId != null);
  if (tagsControlPanel) tagsControlPanel.hidden = !canEnroll;
  if (tagsEnrollBtn) {
    tagsEnrollBtn.disabled = !canEnroll;
    tagsEnrollBtn.title = canEnroll
      ? "Bind this tag to your identity"
      : "";
  }
  const isPreRotation = tagsCurrentTag?.key_version == null || tagsCurrentTag?.key_version === 0;
  const canRotateKeys = managed && isPreRotation;
  if (tagsRotateKeysBtn) {
    tagsRotateKeysBtn.disabled = !canRotateKeys;
    tagsRotateKeysBtn.hidden = !managed;
    tagsRotateKeysBtn.title = canRotateKeys
      ? "Rotate keys to secure this tag (enrolled before key rotation)"
      : "This tag is already using rotated keys.";
  }
  const canClaim = released && activeId != null;
  if (tagsClaimBtn) {
    tagsClaimBtn.disabled = !canClaim;
    tagsClaimBtn.hidden = !released;
    tagsClaimBtn.title = canClaim
      ? "Associate this released tag with your identity (no NDEF write)"
      : "Claim is only available for released tags.";
  }
  const canResetTag = tagsCurrentClassification === "sdm_enabled" && (managed || tagsCurrentTag?.identity_id == null);
  if (tagsResetTagBtn) {
    tagsResetTagBtn.hidden = tagsCurrentClassification !== "sdm_enabled";
    tagsResetTagBtn.disabled = !canResetTag;
    tagsResetTagBtn.title = canResetTag
      ? "Restore delivery-like NDEF, CC, and transport keys when transport-key access is still available"
      : ownedByAnotherIdentity
        ? getOtherIdentityGuidance(tagsCurrentTag, "reset")
        : "Reset is only for tags currently in a recoverable SDM-enabled state.";
  }
  const canRelease = managed || (tagsCurrentTag?.identity_id == null && (tagsCurrentClassification === "sdm_enabled" || tagsCurrentClassification === "personalized_sdm") && tagsCurrentTag?.status !== "released");
  if (tagsReleaseBtn) {
    tagsReleaseBtn.hidden = !canRelease && !ownedByAnotherIdentity;
    tagsReleaseBtn.disabled = !canRelease;
    tagsReleaseBtn.title = canRelease
      ? (managed ? "Release this tag from your identity" : "Restore released status (was overwritten by rescan)")
      : ownedByAnotherIdentity
        ? getOtherIdentityGuidance(tagsCurrentTag, "release")
        : "Release only for tags you control or previously released";
  }
  if (tagsRewriteBtn) {
    tagsRewriteBtn.disabled = !canRewrite;
    tagsRewriteBtn.textContent = "Update Tag";
    tagsRewriteBtn.title = canRewrite
      ? (managed
        ? "Update NDEF with verification URL; includes artwork CID and manifest ID when linked"
        : "Take control: update NDEF and link to your identity")
      : ownedByAnotherIdentity
        ? getOtherIdentityGuidance(tagsCurrentTag, "rewrite")
        : "Update Tag is available for tags you control or tags in released state.";
  }
  const canLinkArtwork = managed
    && tagsCurrentTag?.status === "personalized_sdm"
    && !tagsCurrentTag?.artwork_id;
  if (tagsLinkArtworkPanel) {
    tagsLinkArtworkPanel.hidden = !canLinkArtwork;
    if (canLinkArtwork) void loadLinkArtworkOptions();
  }
  if (tagsLinkArtworkBtn) tagsLinkArtworkBtn.disabled = !canLinkArtwork;
  if (tagsPendingWritePanel) {
    tagsPendingWritePanel.hidden = !(tagsHasPendingWrite && canRewrite);
  }
  if (tagsPendingWriteBtn) tagsPendingWriteBtn.disabled = !canRewrite;
}

function updateTagsUrlPreview() {
  if (!tagsUrlPreview) return;
  const contentUrl = tagsContentUrlInput?.value?.trim();
  const bindUrl = tagsVerificationUrlInput?.value?.trim();
  const base = (contentUrl || bindUrl || "https://charm.farm/tap").replace(/\/$/, "");
  tagsUrlPreview.textContent = base;
}

function resetTagsView() {
  if (tagsEmptyState) tagsEmptyState.hidden = false;
  if (tagsDiscoveryPanel) tagsDiscoveryPanel.hidden = true;
  if (tagsVerificationPanel) tagsVerificationPanel.hidden = true;
  if (tagsControlPanel) tagsControlPanel.hidden = true;
  if (tagsLinkArtworkPanel) tagsLinkArtworkPanel.hidden = true;
  if (tagsContentPanel) tagsContentPanel.hidden = true;
  if (tagsPendingWritePanel) tagsPendingWritePanel.hidden = true;
  tagsCurrentClassification = "";
  tagsCurrentTag = null;
  tagsHasPendingWrite = false;
  setTagsFeedback("");
}

function resetTags(skipFeedback = false) {
  tagsCurrentClassification = "";
  tagsCurrentTag = null;
  tagsCurrentLiveDetails = null;
  tagsHasPendingWrite = false;
  if (tagsDiscoveryPanel) tagsDiscoveryPanel.hidden = true;
  if (tagsVerificationPanel) tagsVerificationPanel.hidden = true;
  if (tagsControlPanel) tagsControlPanel.hidden = true;
  if (tagsLinkArtworkPanel) tagsLinkArtworkPanel.hidden = true;
  if (tagsPendingWritePanel) tagsPendingWritePanel.hidden = true;
  if (tagsContentPanel) tagsContentPanel.hidden = true;
  document.querySelectorAll(".tags-list-card.selected").forEach((c) => c.classList.remove("selected"));
  if (tagsScanBtn) {
    tagsScanBtn.textContent = "+ Scan Tag";
    tagsScanBtn.disabled = false;
  }
  if (tagsScanEmptyBtn) {
    tagsScanEmptyBtn.textContent = "+ Scan Tag";
    tagsScanEmptyBtn.disabled = false;
  }
  if (tagsEnrollBtn) tagsEnrollBtn.disabled = false;
  if (tagsResetTagBtn) { tagsResetTagBtn.disabled = false; tagsResetTagBtn.hidden = true; }
  if (tagsRotateKeysBtn) { tagsRotateKeysBtn.disabled = false; tagsRotateKeysBtn.hidden = false; }
  if (tagsClaimBtn) { tagsClaimBtn.disabled = false; tagsClaimBtn.hidden = false; }
  if (tagsRewriteBtn) tagsRewriteBtn.disabled = false;
  if (tagsReleaseBtn) tagsReleaseBtn.disabled = false;
  if (!skipFeedback) setTagsFeedback("");
  updateTagsStateGating();
  if (activeMasterPassword.trim()) void loadTagsList();
}

async function loadTagsList() {
  if (!ensureTauriAvailable()) return [];
  if (!tagsListSection || !tagsListGrid) return [];
  if (!activeMasterPassword.trim()) {
    tagsListSection.hidden = true;
    if (tagsEmptyState) {
      tagsEmptyState.hidden = false;
      const textEl = tagsEmptyState.querySelector(".tags-empty-text");
      if (textEl) textEl.textContent = "Unlock vault to view and save tags.";
    }
    tagsCurrentTag = null;
    tagsCurrentLiveDetails = null;
    return [];
  }
  const emptyTextEl = tagsEmptyState?.querySelector(".tags-empty-text");
  if (emptyTextEl) emptyTextEl.textContent = "No tags yet. Place a tag on the reader and click + Scan Tag.";
  try {
    const allTags = await invoke("list_tags", { masterPassword: activeMasterPassword });
    const raw = Array.isArray(allTags) ? allTags : [];
    const seen = new Map();
    for (const t of raw) {
      const key = (t.uid || "").toUpperCase();
      const existing = seen.get(key);
      if (!existing || (t.identity_id != null && existing.identity_id == null) || (t.updated_at && existing.updated_at && t.updated_at > existing.updated_at)) {
        seen.set(key, t);
      }
    }
    const tags = [...seen.values()].sort((a, b) => (b.last_seen_at || "").localeCompare(a.last_seen_at || ""));
    tagsListGrid.replaceChildren();
    if (!tags.length) {
      tagsListSection.hidden = true;
      if (tagsEmptyState) tagsEmptyState.hidden = false;
      tagsCurrentTag = null;
      tagsCurrentLiveDetails = null;
      if (tagsDiscoveryPanel) tagsDiscoveryPanel.hidden = true;
      if (tagsVerificationPanel) tagsVerificationPanel.hidden = true;
      if (tagsControlPanel) tagsControlPanel.hidden = true;
      if (tagsContentPanel) tagsContentPanel.hidden = true;
      updateTagsStateGating();
      return [];
    }
    tagsListSection.hidden = false;
    if (tagsEmptyState) tagsEmptyState.hidden = true;
    const cards = tags.map((tag) => createTagCard(tag));
    tagsListGrid.append(...cards);
    return tags;
  } catch (error) {
    setTagsFeedback(`Could not load tags: ${String(error)}`, "error");
    tagsListSection.hidden = true;
    if (tagsEmptyState) tagsEmptyState.hidden = false;
    tagsCurrentTag = null;
    tagsCurrentLiveDetails = null;
    return [];
  }
}

function createTagCard(tag) {
  const card = document.createElement("div");
  card.className = "tags-list-card";
  card.dataset.tagId = String(tag.id ?? "");
  if (tagsCurrentTag?.id === tag.id) card.classList.add("selected");
  const identityName = tag.identity_id != null ? getIdentityNameById(tag.identity_id) : null;
  const identityBlock = document.createElement("div");
  identityBlock.className = "tags-list-card-identity";
  identityBlock.textContent = identityName || (tag.identity_id != null ? `Identity ${tag.identity_id}` : "No identity");
  const uid = document.createElement("div");
  uid.className = "tags-list-card-uid";
  uid.textContent = tag.uid || "—";
  const meta = document.createElement("div");
  meta.className = "tags-list-card-meta";
  meta.textContent = [formatTagStatus(tag.status), formatLastSeen(tag.last_seen_at)].filter(Boolean).join(" · ");
  const notesEl = document.createElement("div");
  notesEl.className = "tags-list-card-notes";
  notesEl.textContent = tag.notes?.trim() ? (tag.notes.trim().length > 60 ? tag.notes.trim().slice(0, 60) + "…" : tag.notes.trim()) : "";
  const forgetBtn = document.createElement("button");
  forgetBtn.className = "tags-list-card-forget";
  forgetBtn.type = "button";
  forgetBtn.setAttribute("aria-label", "Forget tag record");
  forgetBtn.title = "Forget this tag record (removes from list, chip unchanged)";
  forgetBtn.textContent = "×";
  forgetBtn.addEventListener("click", (e) => {
    e.stopPropagation();
    void forgetTag(tag);
  });
  card.append(identityBlock, uid, meta, notesEl, forgetBtn);
  card.addEventListener("click", (e) => {
    if (e.target.closest(".tags-list-card-forget")) return;
    selectTagFromList(tag);
  });
  return card;
}

function updateTagCardNotes(card, notes) {
  const notesEl = card?.querySelector(".tags-list-card-notes");
  if (notesEl) notesEl.textContent = notes ? (notes.length > 60 ? notes.slice(0, 60) + "…" : notes) : "";
}

function forgetTag(tag) {
  if (!ensureTauriAvailable() || !activeMasterPassword.trim()) return;
  const label = (tag.uid || "").trim() || "this tag";
  openDeleteModal(
    "Forget Tag Record",
    `Forget ${label}? This removes the record from your vault. The physical tag is unchanged.`,
    () => runForgetTag(tag),
    "Forget"
  );
}

async function runForgetTag(tag) {
  if (!ensureTauriAvailable()) return;
  try {
    await invoke("forget_tag", {
      masterPassword: activeMasterPassword,
      request: { tagId: tag.id },
    });
    setTagsFeedback("Tag record removed.");
    if (tagsCurrentTag?.id === tag.id) resetTags();
    else void loadTagsList();
  } catch (error) {
    setTagsFeedback(`Forget failed: ${String(error)}`, "error");
  }
}

function syncSelectedTagCard(tag) {
  document.querySelectorAll(".tags-list-card").forEach((c) => c.classList.remove("selected"));
  const tagId = tag?.id;
  if (tagId == null) return;
  const card = tagsListGrid?.querySelector(`[data-tag-id="${tagId}"]`);
  if (card) card.classList.add("selected");
}

function resolveCurrentClassification(tag, liveDetails) {
  if (liveDetails?.classification) return liveDetails.classification;
  return tag?.status === "personalized_sdm" ? "sdm_enabled" : (tag?.status || "");
}

function formatTagStatus(status) {
  if (!status) return "—";
  const map = {
    personalized_sdm: "Bound",
    sdm_enabled: "Bound",
    plain_ndef: "Plain NDEF",
    factory_default_likely: "Factory default",
    released: "Released",
    discovered: "Discovered",
  };
  return map[status] || status;
}

function formatLastSeen(iso) {
  if (!iso) return "—";
  try {
    const d = new Date(iso);
    const now = new Date();
    const diff = now - d;
    if (diff < 60000) return "Just now";
    if (diff < 3600000) return `${Math.floor(diff / 60000)} min ago`;
    if (diff < 86400000) return d.toLocaleTimeString(undefined, { hour: "numeric", minute: "2-digit" });
    return d.toLocaleDateString(undefined, { month: "short", day: "numeric", year: d.getFullYear() !== now.getFullYear() ? "numeric" : undefined });
  } catch {
    return iso;
  }
}

function resolveLiveNdefLength(liveDetails) {
  if (typeof liveDetails?.ndef_len === "number" && Number.isFinite(liveDetails.ndef_len)) {
    return liveDetails.ndef_len;
  }
  if (liveDetails?.ndef_content && typeof liveDetails.ndef_content.ndef_len === "number" && Number.isFinite(liveDetails.ndef_content.ndef_len)) {
    return liveDetails.ndef_content.ndef_len;
  }
  return null;
}

function renderTagDiscovery(tag, options = {}) {
  if (!tag) return;
  const liveDetails = options.liveDetails || null;
  tagsCurrentTag = tag;
  tagsCurrentLiveDetails = liveDetails;
  tagsCurrentClassification = resolveCurrentClassification(tag, liveDetails);

  syncSelectedTagCard(tag);
  if (tagsEmptyState) tagsEmptyState.hidden = true;
  if (tagsDiscoveryPanel) tagsDiscoveryPanel.hidden = false;
  if (tagsVerificationPanel) tagsVerificationPanel.hidden = false;
  if (tagsContentPanel) tagsContentPanel.hidden = false;

  const idEl = document.getElementById("tagsDiscoveryId");
  const readerEl = document.getElementById("tagsDiscoveryReader");
  const uidEl = document.getElementById("tagsDiscoveryUid");
  const chipEl = document.getElementById("tagsDiscoveryChipFamily");
  const subtypeEl = document.getElementById("tagsDiscoverySubtype");
  const classEl = document.getElementById("tagsDiscoveryClassification");
  const ndefEl = document.getElementById("tagsDiscoveryNdefApp");
  const sdmEl = document.getElementById("tagsDiscoverySdm");
  const sizeEl = document.getElementById("tagsDiscoveryNdefSize");
  const lastSeenEl = document.getElementById("tagsDiscoveryLastSeen");
  const identityEl = document.getElementById("tagsDiscoveryIdentity");
  const artworkEl = document.getElementById("tagsDiscoveryArtwork");
  const counterEl = document.getElementById("tagsDiscoveryCounter");
  const counterAccessEl = document.getElementById("tagsDiscoveryCounterAccess");

  if (idEl) idEl.textContent = tag.id != null ? String(tag.id) : "—";
  if (readerEl) readerEl.textContent = liveDetails?.reader_name || "—";
  if (uidEl) uidEl.textContent = liveDetails?.tag_uid || tag.uid || "—";
  if (chipEl) {
    chipEl.textContent = liveDetails?.get_version?.is_ntag424_dna
      ? "NTAG 424 DNA"
      : (liveDetails?.get_version?.hw_type ?? tag.tag_family ?? "—");
  }
  if (subtypeEl) subtypeEl.textContent = liveDetails?.get_version?.hw_subtype ?? tag.chip_subtype ?? "—";
  if (classEl) classEl.textContent = formatTagStatus(liveDetails?.classification || tag.status);
  if (ndefEl) {
    ndefEl.textContent = typeof liveDetails?.ndef_app_selected === "boolean"
      ? (liveDetails.ndef_app_selected ? "Yes" : "No")
      : "—";
  }
  if (sdmEl) {
    if (typeof liveDetails?.file_settings_02?.sdm_enabled === "boolean") {
      sdmEl.textContent = liveDetails.file_settings_02.sdm_enabled ? "Yes" : "No";
    } else {
      sdmEl.textContent = tag.status === "personalized_sdm" ? "Yes" : "—";
    }
  }
  if (sizeEl) {
    const ndefLen = resolveLiveNdefLength(liveDetails);
    sizeEl.textContent = ndefLen != null ? `${ndefLen} bytes` : "—";
  }
  if (lastSeenEl) lastSeenEl.textContent = formatLastSeen(tag.last_seen_at);
  if (identityEl) {
    identityEl.textContent = tag.identity_id != null
      ? (getIdentityNameById(tag.identity_id) || `Identity ${tag.identity_id}`)
      : "None";
  }
  if (artworkEl) {
    void populateLinkedArtworkDisplay(tag, artworkEl);
  }
  void checkPendingTagWrite(tag);
  if (counterEl) {
    counterEl.textContent = typeof liveDetails?.tag_counter === "number" && Number.isFinite(liveDetails.tag_counter)
      ? String(liveDetails.tag_counter)
      : "—";
  }
  if (counterAccessEl) {
    if (liveDetails && "counter_access" in liveDetails) {
      counterAccessEl.textContent = formatCounterAccessText(liveDetails.counter_access, tag);
    } else {
      if (tag.status === "personalized_sdm") {
        counterAccessEl.textContent = tag.identity_id != null
          ? "Scan with the owning identity to view"
          : "Unavailable until authenticated";
      } else {
        counterAccessEl.textContent = "—";
      }
    }
  }
  if (activeMasterPassword.trim() && tag.id != null) {
    void invoke("get_tag_last_verification_url", {
      masterPassword: activeMasterPassword,
      request: { tagId: tag.id },
    }).then((url) => {
      const val = url || "https://charm.farm/tap";
      if (tagsVerificationUrlInput) tagsVerificationUrlInput.value = val;
      if (tagsContentUrlInput) tagsContentUrlInput.value = val;
      updateTagsUrlPreview();
    }).catch(() => {});
  }
  if (tagsNotesInput) {
    tagsNotesInput.value = tag.notes?.trim() ?? "";
    tagsNotesInput.dataset.tagId = String(tag.id ?? "");
  }
  updateTagsUrlPreview();
  updateTagsStateGating();
}

async function refreshTagSelectionByUid(uid, options = {}) {
  if (!uid || !activeMasterPassword.trim()) return null;
  const preserveDetails = options?.preserveDetails === true;
  const normalized = uid.toUpperCase();
  const tags = await loadTagsList();
  const refreshed = tags.find((t) => (t.uid || "").toUpperCase() === normalized);
  if (refreshed) {
    renderTagDiscovery(refreshed, { liveDetails: preserveDetails ? tagsCurrentLiveDetails : null });
    return refreshed;
  }
  return null;
}

async function populateLinkedArtworkDisplay(tag, artworkEl) {
  if (!artworkEl) return;
  artworkEl.replaceChildren();
  if (!tag?.artwork_id || !ensureTauriAvailable() || !activeMasterPassword.trim()) {
    artworkEl.textContent = "—";
    return;
  }
  try {
    const draft = await invoke("get_draft_by_id", {
      masterPassword: activeMasterPassword,
      request: { draftId: tag.artwork_id }
    });
    const display = draft
      ? (draft.c2pa_manifest_id || draft.artifact_title || `Draft ${tag.artwork_id}`)
      : `Draft ${tag.artwork_id}`;
    if (draft?.asset_path?.trim()) {
      const link = document.createElement("button");
      link.type = "button";
      link.className = "tags-artwork-link";
      link.textContent = display;
      link.setAttribute("aria-label", `View artwork in Inspector: ${display}`);
      link.addEventListener("click", () => {
        setRoute("inspector");
        void verifyInspectorPath(draft.asset_path);
      });
      artworkEl.appendChild(link);
    } else {
      artworkEl.textContent = display;
    }
  } catch {
    artworkEl.textContent = `Draft ${tag.artwork_id}`;
  }
}

async function checkPendingTagWrite(tag) {
  tagsHasPendingWrite = false;
  if (!tag?.artwork_id || !ensureTauriAvailable() || !activeMasterPassword.trim()) {
    updateTagsStateGating();
    return;
  }
  try {
    const draft = await invoke("get_draft_by_id", {
      masterPassword: activeMasterPassword,
      request: { draftId: tag.artwork_id },
    });
    if (!draft) { updateTagsStateGating(); return; }
    const hasData = Boolean(draft.ipfs_cid?.trim() || draft.c2pa_manifest_id?.trim() || draft.perceptual_hash?.trim());
    if (!hasData) { updateTagsStateGating(); return; }
    const lastWrite = tag.last_ndef_write_at;
    const draftUpdated = draft.updated_at;
    tagsHasPendingWrite = !lastWrite || lastWrite < draftUpdated;
  } catch {
    tagsHasPendingWrite = false;
  }
  updateTagsStateGating();
}

function selectTagFromList(tag) {
  renderTagDiscovery(tag, { liveDetails: null });
}

function setRoute(route) {
  navTabs.forEach((tab) => {
    const isActive = tab.dataset.route === route;
    tab.classList.toggle("active", isActive);
    tab.setAttribute("aria-current", isActive ? "page" : "false");
  });

  panels.forEach((panel) => {
    panel.classList.toggle("active", panel.dataset.panel === route);
  });

  if (route === "vault" && activeMasterPassword.trim()) {
    loadVaultDrafts(activeMasterPassword);
  }
  if (route === "studio" && activeMasterPassword.trim()) {
    refreshStudioSigningMode();
    void loadStudioTagOptions();
  }
  if (route === "contacts" && activeMasterPassword.trim()) {
    refreshContacts(activeMasterPassword);
    refreshContactsSignedMessages(activeMasterPassword);
  }
  if (route === "settings" && activeMasterPassword.trim()) {
    refreshSettingsProfile(activeMasterPassword);
  }
  if (route === "tags") {
    void loadTagsList();
    if (tagsCurrentTag && activeMasterPassword.trim()) {
      if (tagsEmptyState) tagsEmptyState.hidden = true;
      if (tagsListSection) tagsListSection.hidden = false;
      if (tagsDiscoveryPanel) tagsDiscoveryPanel.hidden = false;
      if (tagsVerificationPanel) tagsVerificationPanel.hidden = false;
      if (tagsContentPanel) tagsContentPanel.hidden = false;
    } else {
      if (tagsDiscoveryPanel) tagsDiscoveryPanel.hidden = true;
      if (tagsVerificationPanel) tagsVerificationPanel.hidden = true;
      if (tagsControlPanel) tagsControlPanel.hidden = true;
      if (tagsContentPanel) tagsContentPanel.hidden = true;
    }
    updateTagsStateGating();
  }
}

async function preloadActiveIdentityName(masterPassword) {
  if (!ensureTauriAvailable()) return;
  try {
    const identities = await invoke("list_identities", { masterPassword });
    const hasReady = Array.isArray(identities) && identities.some(
      (id) => id.has_certificate_chain
    );
    if (sidebarIdentityNudge) sidebarIdentityNudge.hidden = hasReady;
    if (!Array.isArray(identities) || !identities.length) return;
    const activeIdentity = identities.find((identity) => identity.is_active) || identities[0];
    const name = activeIdentity?.common_name;
    if (typeof name === "string" && name.trim()) {
      preferredAuthorName = name.trim();
    }
  } catch (_) {
    preferredAuthorName = "";
    if (sidebarIdentityNudge) sidebarIdentityNudge.hidden = false;
  }
}

async function refreshContacts(masterPassword) {
  if (!contactsList || !ensureTauriAvailable()) return;
  try {
    const contacts = await invoke("list_trusted_contacts", { masterPassword });
    const list = Array.isArray(contacts) ? contacts : [];
    contactsList.replaceChildren();
    if (list.length === 0) {
      const empty = document.createElement("p");
      empty.className = "contacts-empty";
      empty.textContent = "No trusted contacts yet. Import a .crt file to add one.";
      contactsList.appendChild(empty);
    } else {
      list.forEach((c) => {
        const card = document.createElement("div");
        card.className = "contacts-card";
        card.dataset.contactId = c.id;
        const name = document.createElement("p");
        name.className = "contacts-card-name";
        name.textContent = c.common_name;
        if (c.organization?.trim()) {
          const sep = document.createTextNode(" — ");
          const org = document.createElement("span");
          org.className = "contacts-card-org";
          org.textContent = c.organization.trim();
          name.append(sep, org);
        }
        const notesWrap = document.createElement("div");
        notesWrap.className = "contacts-card-notes";
        const notesInput = document.createElement("textarea");
        notesInput.className = "contacts-card-notes-input";
        notesInput.rows = 1;
        notesInput.placeholder = "Add a short note…";
        notesInput.setAttribute("aria-label", "Notes for this contact");
        notesInput.value = c.notes?.trim() ?? "";
        notesInput.dataset.contactId = c.id;
        notesWrap.appendChild(notesInput);
        const actions = document.createElement("div");
        actions.className = "contacts-card-actions";
        const exportBtn = document.createElement("button");
        exportBtn.className = "contacts-card-action";
        exportBtn.type = "button";
        exportBtn.setAttribute("aria-label", "Export certificate");
        exportBtn.innerHTML = "<svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"/><path d=\"M7 10l5 5 5-5\"/><path d=\"M12 15V3\"/></svg>";
        exportBtn.addEventListener("click", () => handleExportContact(c));
        const removeBtn = document.createElement("button");
        removeBtn.className = "contacts-card-action contacts-card-action-remove";
        removeBtn.type = "button";
        removeBtn.setAttribute("aria-label", "Remove contact");
        removeBtn.innerHTML = "<svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M3 6h18\"/><path d=\"M8 6V4h8v2\"/><path d=\"M7 6l1 14h8l1-14\"/><path d=\"M10 10v7\"/><path d=\"M14 10v7\"/></svg>";
        removeBtn.addEventListener("click", () => handleRemoveContact(c.id, c.common_name));
        actions.append(exportBtn, removeBtn);
        card.append(name, notesWrap, actions);
        setupContactNotesAutoSave(notesInput);
        contactsList.appendChild(card);
      });
    }
    if (contactsFeedback) contactsFeedback.textContent = "";
  } catch (error) {
    if (contactsFeedback) contactsFeedback.textContent = `Could not load contacts: ${String(error)}`;
    contactsFeedback?.classList.add("error");
  }
}

let contactNotesSaveTimeouts = new Map();
function setupContactNotesAutoSave(notesInput) {
  if (!notesInput) return;
  const contactId = notesInput.dataset?.contactId;
  if (!contactId) return;
  notesInput.addEventListener("input", () => {
    if (contactNotesSaveTimeouts.has(contactId)) clearTimeout(contactNotesSaveTimeouts.get(contactId));
    contactNotesSaveTimeouts.set(
      contactId,
      setTimeout(() => saveContactNotes(notesInput), 500)
    );
  });
  notesInput.addEventListener("blur", () => {
    if (contactNotesSaveTimeouts.has(contactId)) {
      clearTimeout(contactNotesSaveTimeouts.get(contactId));
      contactNotesSaveTimeouts.delete(contactId);
    }
    void saveContactNotes(notesInput);
  });
}

async function saveContactNotes(notesInput) {
  if (!notesInput || !ensureTauriAvailable() || !activeMasterPassword?.trim()) return;
  const contactId = notesInput.dataset?.contactId;
  if (!contactId) return;
  const notes = notesInput.value?.trim() || null;
  try {
    await invoke("update_contact_notes", {
      masterPassword: activeMasterPassword,
      request: { contactId, notes: notes || undefined },
    });
  } catch (e) {
    if (contactsFeedback) {
      contactsFeedback.textContent = `Could not save notes: ${String(e)}`;
      contactsFeedback.classList.add("error");
    }
  }
}

let lastVerifiedPem = null;

function setupContactsSignedMessages() {
  const section = document.getElementById("contactsSignedMessagesSection");
  if (!section) return;
  const signTab = section.querySelector('[data-signed-mode="sign"]');
  const verifyTab = section.querySelector('[data-signed-mode="verify"]');
  const signPanel = document.getElementById("contactsSignedSignPanel");
  const verifyPanel = document.getElementById("contactsSignedVerifyPanel");
  const signBtn = document.getElementById("contactsSignedSignBtn");
  const verifyBtn = document.getElementById("contactsSignedVerifyBtn");
  const addContactBtn = document.getElementById("contactsSignedAddContactBtn");

  function switchMode(mode) {
    const isSign = mode === "sign";
    signTab?.classList.toggle("active", isSign);
    verifyTab?.classList.toggle("active", !isSign);
    signPanel.hidden = !isSign;
    verifyPanel.hidden = isSign;
  }

  const copyBtn = document.getElementById("contactsSignedCopyBtn");
  signTab?.addEventListener("click", () => switchMode("sign"));
  verifyTab?.addEventListener("click", () => switchMode("verify"));
  signBtn?.addEventListener("click", handleSignMessage);
  verifyBtn?.addEventListener("click", handleVerifySignedMessage);
  addContactBtn?.addEventListener("click", handleAddContactFromSignedMessage);
  copyBtn?.addEventListener("click", handleCopySignedMessage);
}

async function refreshContactsSignedMessages(masterPassword) {
  const signingAs = document.getElementById("contactsSignedSigningAs");
  if (!signingAs) return;
  if (!ensureTauriAvailable() || !masterPassword?.trim()) {
    signingAs.textContent = "Signing as: —";
    signingAs.classList.add("disabled");
    return;
  }
  try {
    const identities = await invoke("list_identities", { masterPassword });
    const active = Array.isArray(identities) ? identities.find((i) => i.is_active) : null;
    const hasChain = active?.has_certificate_chain;
    if (hasChain && active?.common_name) {
      const org = active.organization ? ` (${active.organization})` : "";
      signingAs.textContent = `Signing as: ${active.common_name}${org}`;
      signingAs.classList.remove("disabled");
    } else {
      signingAs.textContent = "Create an identity in Settings to sign messages.";
      signingAs.classList.add("disabled");
    }
  } catch {
    signingAs.textContent = "Signing as: —";
    signingAs.classList.add("disabled");
  }
}

function handleCopySignedMessage() {
  const output = document.getElementById("contactsSignedOutput");
  const pem = output?.textContent?.trim();
  if (!pem) return;
  navigator.clipboard.writeText(pem).then(
    () => {
      if (contactsFeedback) {
        contactsFeedback.textContent = "Copied to clipboard.";
        contactsFeedback.classList.remove("error");
      }
    },
    () => {
      if (contactsFeedback) {
        contactsFeedback.textContent = "Could not copy to clipboard.";
        contactsFeedback.classList.add("error");
      }
    }
  );
}

async function handleSignMessage() {
  if (!ensureTauriAvailable() || !activeMasterPassword.trim()) {
    if (contactsFeedback) contactsFeedback.textContent = "Unlock vault first.";
    contactsFeedback?.classList.add("error");
    return;
  }
  const input = document.getElementById("contactsSignedMessageInput");
  const outputWrap = document.getElementById("contactsSignedOutputWrap");
  const output = document.getElementById("contactsSignedOutput");
  if (!input || !outputWrap || !output) return;
  const message = input.value?.trim() || "";
  if (!message) {
    if (contactsFeedback) contactsFeedback.textContent = "Enter a message to sign.";
    contactsFeedback?.classList.add("error");
    return;
  }
  try {
    const result = await invoke("sign_message", {
      masterPassword: activeMasterPassword,
      request: { message }
    });
    output.textContent = result?.pem ?? "";
    outputWrap.hidden = false;
    if (contactsFeedback) contactsFeedback.textContent = "";
    contactsFeedback?.classList.remove("error");
  } catch (error) {
    if (contactsFeedback) contactsFeedback.textContent = String(error);
    contactsFeedback?.classList.add("error");
    outputWrap.hidden = true;
  }
}

async function handleVerifySignedMessage() {
  if (!ensureTauriAvailable() || !activeMasterPassword.trim()) {
    if (contactsFeedback) contactsFeedback.textContent = "Unlock vault first.";
    contactsFeedback?.classList.add("error");
    return;
  }
  const input = document.getElementById("contactsSignedVerifyInput");
  const resultWrap = document.getElementById("contactsSignedVerifyResult");
  const msgEl = document.getElementById("contactsSignedVerifyMessage");
  const signerEl = document.getElementById("contactsSignedVerifySigner");
  const addBtn = document.getElementById("contactsSignedAddContactBtn");
  const expiredEl = document.getElementById("contactsSignedVerifyExpired");
  if (!input || !resultWrap || !msgEl || !signerEl) return;
  const pem = input.value?.trim() || "";
  if (!pem) {
    if (contactsFeedback) contactsFeedback.textContent = "Paste a signed message (PEM) to verify.";
    contactsFeedback?.classList.add("error");
    return;
  }
  try {
    const result = await invoke("verify_signed_message", {
      masterPassword: activeMasterPassword,
      request: { pem }
    });
    lastVerifiedPem = pem;
    msgEl.textContent = result?.message ?? "";
    const signer = result?.signer;
    const org = signer?.organization ? ` (${signer.organization})` : "";
    signerEl.textContent = result?.is_trusted_contact
      ? `Signed by: ${signer?.common_name ?? "Unknown"}${org} ✓ trusted contact`
      : `Signed by: ${signer?.common_name ?? "Unknown"}${org}`;
    signerEl.classList.toggle("trusted", !!result?.is_trusted_contact);
    addBtn.hidden = !!result?.is_trusted_contact;
    if (result?.certificate_expired) {
      expiredEl.textContent = "Note: signer's certificate has expired.";
      expiredEl.hidden = false;
    } else {
      expiredEl.hidden = true;
    }
    resultWrap.hidden = false;
    if (contactsFeedback) contactsFeedback.textContent = "";
    contactsFeedback?.classList.remove("error");
  } catch (error) {
    if (contactsFeedback) contactsFeedback.textContent = String(error);
    contactsFeedback?.classList.add("error");
    resultWrap.hidden = true;
  }
}

async function handleAddContactFromSignedMessage() {
  if (!ensureTauriAvailable() || !activeMasterPassword.trim() || !lastVerifiedPem) return;
  const addBtn = document.getElementById("contactsSignedAddContactBtn");
  try {
    await invoke("add_contact_from_signed_message", {
      masterPassword: activeMasterPassword,
      request: { pem: lastVerifiedPem }
    });
    addBtn.hidden = true;
    const signerEl = document.getElementById("contactsSignedVerifySigner");
    if (signerEl) signerEl.classList.add("trusted");
    if (contactsFeedback) contactsFeedback.textContent = "Contact added.";
    contactsFeedback?.classList.remove("error");
    await refreshContacts(activeMasterPassword);
  } catch (error) {
    const msg = String(error || "");
    const duplicate = msg.includes("already") || msg.includes("UNIQUE") || msg.includes("idx_trusted_contacts");
    if (contactsFeedback) {
      contactsFeedback.textContent = duplicate ? "Contact already in list." : `Add failed: ${msg}`;
    }
    if (duplicate) {
      contactsFeedback?.classList.remove("error");
      if (addBtn) addBtn.hidden = true;
    } else {
      contactsFeedback?.classList.add("error");
    }
  }
}

async function handleImportContact() {
  if (!ensureTauriAvailable() || !activeMasterPassword.trim()) {
    if (contactsFeedback) contactsFeedback.textContent = "Unlock vault first.";
    contactsFeedback?.classList.add("error");
    return;
  }
  try {
    const path = await invoke("pick_open_file_path", {
      title: "Select contact certificate",
      extensions: ["crt", "pem"]
    });
    if (!path) return;
    const id = await invoke("import_contact_certificate", {
      masterPassword: activeMasterPassword,
      request: { file_path: path }
    });
    if (contactsFeedback) contactsFeedback.textContent = "Contact imported.";
    contactsFeedback?.classList.remove("error");
    await refreshContacts(activeMasterPassword);
  } catch (error) {
    const message = String(error || "");
    const duplicate = message.includes("already in Trusted Contacts");
    if (contactsFeedback) {
      contactsFeedback.textContent = duplicate
        ? "Contact already imported."
        : `Import failed: ${message}`;
    }
    if (duplicate) {
      contactsFeedback?.classList.remove("error");
    } else {
      contactsFeedback?.classList.add("error");
    }
  }
}

async function handleExportContact(contact) {
  if (!ensureTauriAvailable() || !activeMasterPassword.trim()) {
    if (contactsFeedback) contactsFeedback.textContent = "Unlock vault first.";
    contactsFeedback?.classList.add("error");
    return;
  }
  try {
    const safeName = (contact.common_name || "contact").replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 32);
    const outputPath = await invoke("pick_save_file_path", {
      title: "Export contact certificate",
      defaultName: `${safeName}.crt`
    });
    if (!outputPath) return;
    await invoke("export_contact_certificate", {
      masterPassword: activeMasterPassword,
      request: { contact_id: contact.id, output_path: outputPath }
    });
    if (contactsFeedback) contactsFeedback.textContent = "Certificate exported.";
    contactsFeedback?.classList.remove("error");
  } catch (error) {
    if (contactsFeedback) contactsFeedback.textContent = `Export failed: ${String(error)}`;
    contactsFeedback?.classList.add("error");
  }
}

function handleRemoveContact(contactId, contactName) {
  if (!ensureTauriAvailable() || !activeMasterPassword.trim()) return;
  const name = (contactName || "").trim() || "this contact";
  openDeleteModal(
    "Remove Contact",
    `Remove ${name} from Trusted Contacts? You can re-import their certificate later if needed, but you'll lose any notes you've saved for this contact.`,
    () => runRemoveContact(contactId),
    "Remove"
  );
}

async function runRemoveContact(contactId) {
  if (!ensureTauriAvailable()) return;
  try {
    await invoke("delete_trusted_contact", {
      masterPassword: activeMasterPassword,
      request: { contact_id: contactId }
    });
    await refreshContacts(activeMasterPassword);
    if (contactsFeedback) contactsFeedback.textContent = "Contact removed.";
    contactsFeedback?.classList.remove("error");
  } catch (error) {
    if (contactsFeedback) contactsFeedback.textContent = `Could not remove: ${String(error)}`;
    contactsFeedback?.classList.add("error");
  }
}

async function handleTagsScan() {
  if (!ensureTauriAvailable()) return;
  if (!activeMasterPassword.trim()) {
    setTagsFeedback("Unlock vault first to scan and persist tags.", "error");
    return;
  }
  const scanBtns = [tagsScanBtn, tagsScanEmptyBtn, tagsRescanBtn];
  scanBtns.forEach((btn) => { if (btn) btn.disabled = true; });
  if (tagsScanBtn) tagsScanBtn.textContent = "Scanning…";
  if (tagsScanEmptyBtn) tagsScanEmptyBtn.textContent = "Scanning…";
  if (tagsRescanBtn) tagsRescanBtn.textContent = "Scanning…";
  setTagsFeedback("Checking for NFC reader…");
  try {
    const readers = await invoke("list_nfc_readers");
    if (!Array.isArray(readers) || readers.length === 0) {
      setTagsFeedback("No NFC reader found. Connect an ACR1252U or compatible reader and try again.", "error");
      return;
    }
    setTagsFeedback("Hold tag on reader… (up to 12 seconds)");
    const preflight = await withNfcTimeout(invoke("preflight_tag_state", {
      masterPassword: activeMasterPassword,
      request: { timeout_ms: 12000 },
    }));
    if (!preflight?.tag_uid) {
      setTagsFeedback("No tag detected. Ensure tag is on the reader and try again.", "error");
      return;
    }
    const tag = await invoke("upsert_tag_from_preflight", {
      masterPassword: activeMasterPassword,
      request: {
        uid: preflight.tag_uid,
        classification: preflight.classification || "discovered",
        readerName: preflight.reader_name || null,
        tagFamily: preflight.get_version?.is_ntag424_dna ? "NTAG 424 DNA" : preflight.get_version?.hw_type ?? null,
        chipSubtype: preflight.get_version?.hw_subtype ?? null,
      },
    });
    renderTagDiscovery(tag, { liveDetails: preflight });
    setTagsFeedback(getFriendlyTagScanFeedback(tag));
    await refreshTagSelectionByUid(preflight.tag_uid, { preserveDetails: true });
  } catch (error) {
    setTagsFeedback(`Could not scan this tag: ${String(error)}`, "error");
  } finally {
    scanBtns.forEach((btn) => { if (btn) btn.disabled = false; });
    if (tagsScanBtn) tagsScanBtn.textContent = "+ Scan Tag";
    if (tagsScanEmptyBtn) tagsScanEmptyBtn.textContent = "+ Scan Tag";
    if (tagsRescanBtn) tagsRescanBtn.textContent = "Rescan";
  }
}

async function handleTagsEnroll() {
  if (!ensureTauriAvailable() || !activeMasterPassword.trim()) return;
  const url = tagsVerificationUrlInput?.value?.trim();
  if (!url) {
    setTagsFeedback("Enter a verification URL to bind.", "error");
    return;
  }
  if (tagsCurrentClassification !== "plain_ndef" && tagsCurrentClassification !== "factory_default_likely") {
    if (tagsCurrentTag?.identity_id != null && tagsCurrentTag.identity_id !== settingsActiveIdentity?.id) {
      setTagsFeedback(`${getOtherIdentityGuidance(tagsCurrentTag)} Use a factory-default or plain NDEF tag to bind a new one.`);
    } else if (tagsCurrentTag?.status === "released") {
      setTagsFeedback("This tag is released, not blank. Use Rewrite Content to update it, or Claim Tag to associate it with your identity.");
    } else {
      setTagsFeedback("This tag is not blank enough to bind. Use a factory-default or plain NDEF tag.", "error");
    }
    return;
  }
  if (tagsEnrollBtn) { tagsEnrollBtn.disabled = true; tagsEnrollBtn.textContent = "Binding…"; }
  setTagsFeedback("Binding tag to your identity. Hold it on the reader (up to 12 seconds).");
  try {
    const tag = await withNfcTimeout(invoke("enroll_tag_with_identity", {
      masterPassword: activeMasterPassword,
      request: {
        verificationUrl: url,
        timeoutMs: 12000,
      },
    }));
    setTagsFeedback("Tag bound successfully.");
    renderTagDiscovery(tag, { liveDetails: null });
    await refreshTagSelectionByUid(tag.uid);
  } catch (error) {
    setTagsFeedback(`Could not bind this tag: ${String(error)}`, "error");
  } finally {
    if (tagsEnrollBtn) tagsEnrollBtn.textContent = "Bind Tag";
    updateTagsStateGating();
  }
}

async function handleTagsResetTag() {
  if (!ensureTauriAvailable()) return;
  if (!activeMasterPassword.trim()) {
    setTagsFeedback("Unlock vault first to reset and save the tag.", "error");
    return;
  }
  openDeleteModal(
    "Reset Tag",
    "Reset this tag to a delivery-like state? NDEF, CC, and transport keys will be restored. This cannot be undone.",
    () => runResetTag(),
    "Reset Tag"
  );
}

async function runResetTag() {
  if (!ensureTauriAvailable()) return;
  if (tagsResetTagBtn) { tagsResetTagBtn.disabled = true; tagsResetTagBtn.textContent = "Resetting…"; }
  setTagsFeedback("Resetting tag to a delivery-like state. Hold it on the reader (up to 12 seconds).");
  try {
    const result = await withNfcTimeout(invoke("reset_tag_sdm", {
      masterPassword: activeMasterPassword,
      request: { timeoutMs: 12000 },
    }));
    if (result?.success) {
      const tag = tagsCurrentTag ? {
        ...tagsCurrentTag,
        uid: result.tag_uid || tagsCurrentTag.uid,
        status: "factory_default_likely",
      } : {
        uid: result.tag_uid || "",
        status: "factory_default_likely",
      };
      renderTagDiscovery(tag, {
        liveDetails: {
          classification: "factory_default_likely",
          tag_uid: result.tag_uid || tag.uid,
        },
      });
      setTagsFeedback("Tag reset to a delivery-like state. Scan again to verify the current chip state.");
      await refreshTagSelectionByUid(result.tag_uid || tagsCurrentTag?.uid, { preserveDetails: true });
      void loadStudioTagOptions();
    } else {
      setTagsFeedback("The reset did not complete. Keep the tag on the reader and try again.", "error");
    }
  } catch (error) {
    setTagsFeedback(`Could not reset this tag: ${String(error)}`, "error");
  } finally {
    if (tagsResetTagBtn) { tagsResetTagBtn.disabled = false; tagsResetTagBtn.textContent = "Reset Tag"; }
    updateTagsStateGating();
  }
}

async function handleTagsRewrite() {
  if (!ensureTauriAvailable() || !activeMasterPassword.trim()) return;
  const url = (tagsContentUrlInput || tagsVerificationUrlInput)?.value?.trim();
  if (!url) {
    setTagsFeedback("Enter a verification URL to rewrite.", "error");
    return;
  }
  const managed = tagsCurrentTag?.identity_id === settingsActiveIdentity?.id;
  const released = tagsCurrentTag?.identity_id == null && tagsCurrentTag?.status === "released";
  if (!tagsCurrentTag || (!managed && !released)) {
    if (!tagsCurrentTag) {
      setTagsFeedback("Scan a tag first, then try rewriting it.");
    } else if (tagsCurrentTag.identity_id != null && tagsCurrentTag.identity_id !== settingsActiveIdentity?.id) {
      setTagsFeedback(getOtherIdentityGuidance(tagsCurrentTag, "rewrite"));
    } else {
      setTagsFeedback("Rewrite is available for tags you control or tags in released state.");
    }
    return;
  }
  if (tagsRewriteBtn) { tagsRewriteBtn.disabled = true; tagsRewriteBtn.textContent = "Updating…"; }
  setTagsFeedback("Updating tag content. Hold the tag on the reader (up to 12 seconds).");
  try {
    const result = await withNfcTimeout(invoke("rewrite_tag_ndef", {
      masterPassword: activeMasterPassword,
      request: { baseUrl: url, timeoutMs: 12000 },
    }));
    if (result?.success) {
      if (released) {
        setTagsFeedback("Tag content updated. Use Claim Tag to associate this released tag with your identity.");
      } else {
        const cfsOk = result?.log?.some((l) => l.includes("ChangeFileSettings: OK"));
        setTagsFeedback(cfsOk
          ? "Tag content updated successfully, including SDM settings."
          : "Tag content updated successfully.");
      }
      // Best-effort post-write verification (short timeout — don't block if tag was lifted)
      setTagsFeedback((tagsFeedback?.textContent || "") + " Verifying…");
      try {
        const preflight = await withNfcTimeout(invoke("preflight_tag_state", {
          masterPassword: activeMasterPassword,
          request: { timeout_ms: 2000 },
        }), 5000);
        if (preflight?.tag_uid) {
          const tag = await invoke("upsert_tag_from_preflight", {
            masterPassword: activeMasterPassword,
            request: {
              uid: preflight.tag_uid,
              classification: preflight.classification || "discovered",
              readerName: preflight.reader_name || null,
              tagFamily: preflight.get_version?.is_ntag424_dna ? "NTAG 424 DNA" : preflight.get_version?.hw_type ?? null,
              chipSubtype: preflight.get_version?.hw_subtype ?? null,
            },
          });
          renderTagDiscovery(tag, { liveDetails: preflight });
          await refreshTagSelectionByUid(tag.uid || preflight.tag_uid, { preserveDetails: true });
        }
      } catch (_) { /* tag may have been removed — verification is best-effort */ }
    } else {
      setTagsFeedback(`Could not update this tag: ${(result?.log || []).join("; ")}`, "error");
    }
  } catch (error) {
    setTagsFeedback(`Could not update this tag: ${String(error)}`, "error");
  } finally {
    if (tagsRewriteBtn) tagsRewriteBtn.textContent = "Update Tag";
    updateTagsStateGating();
  }
}

async function handleTagsRotateKeys() {
  if (!ensureTauriAvailable() || !activeMasterPassword.trim()) return;
  const managed = tagsCurrentTag?.identity_id === settingsActiveIdentity?.id;
  const isPreRotation = tagsCurrentTag?.key_version == null || tagsCurrentTag?.key_version === 0;
  if (!tagsCurrentTag || !managed || !isPreRotation) {
    if (!tagsCurrentTag) {
      setTagsFeedback("Scan a tag first, then try rotating its keys.");
    } else if (tagsCurrentTag.identity_id != null && tagsCurrentTag.identity_id !== settingsActiveIdentity?.id) {
      setTagsFeedback(getOtherIdentityGuidance(tagsCurrentTag, "rotate keys on"));
    } else {
      setTagsFeedback("This tag is already using rotated keys, so no key rotation is needed.");
    }
    return;
  }
  if (tagsRotateKeysBtn) { tagsRotateKeysBtn.disabled = true; tagsRotateKeysBtn.textContent = "Rotating…"; }
  setTagsFeedback("Securing tag keys. Hold the tag on the reader (up to 12 seconds).");
  try {
    const tag = await withNfcTimeout(invoke("rotate_tag_keys", {
      masterPassword: activeMasterPassword,
      request: { timeoutMs: 12000 },
    }));
    setTagsFeedback("Tag keys rotated successfully. This tag is now secured.");
    renderTagDiscovery(tag, { liveDetails: null });
    await refreshTagSelectionByUid(tag.uid);
  } catch (error) {
    setTagsFeedback(`Could not rotate keys on this tag: ${String(error)}`, "error");
  } finally {
    if (tagsRotateKeysBtn) tagsRotateKeysBtn.textContent = "Rotate Keys";
    updateTagsStateGating();
  }
}

async function handleTagsClaim() {
  if (!ensureTauriAvailable() || !activeMasterPassword.trim()) return;
  const released = tagsCurrentTag?.identity_id == null && tagsCurrentTag?.status === "released";
  if (!tagsCurrentTag || !released) {
    if (!tagsCurrentTag) {
      setTagsFeedback("Scan a tag first, then claim it if it is released.");
    } else if (tagsCurrentTag.identity_id != null) {
      setTagsFeedback("This tag is already managed. Release it first if you want another identity to claim it.");
    } else {
      setTagsFeedback("Claim is only available for tags that are in released state.");
    }
    return;
  }
  if (tagsClaimBtn) { tagsClaimBtn.disabled = true; tagsClaimBtn.textContent = "Claiming…"; }
  setTagsFeedback("Claiming tag…");
  try {
    const tag = await invoke("take_tag_control", {
      masterPassword: activeMasterPassword,
      request: { uid: tagsCurrentTag.uid, verificationUrl: null },
    });
    setTagsFeedback("Tag claimed and linked to your identity.");
    renderTagDiscovery(tag, { liveDetails: null });
    await refreshTagSelectionByUid(tag.uid);
    void loadStudioTagOptions();
  } catch (error) {
    setTagsFeedback(`Could not claim this tag: ${String(error)}`, "error");
  } finally {
    if (tagsClaimBtn) tagsClaimBtn.textContent = "Claim Tag";
    updateTagsStateGating();
  }
}

async function handleTagsRelease() {
  if (!ensureTauriAvailable() || !activeMasterPassword.trim()) return;
  const managed = tagsCurrentTag?.identity_id === settingsActiveIdentity?.id;
  const canRestore = tagsCurrentTag?.identity_id == null && (tagsCurrentClassification === "sdm_enabled" || tagsCurrentClassification === "personalized_sdm") && tagsCurrentTag?.status !== "released";
  if (!tagsCurrentTag || (!managed && !canRestore)) {
    if (!tagsCurrentTag) {
      setTagsFeedback("Scan a tag first, then release it if you manage it.");
    } else if (tagsCurrentTag.identity_id != null && tagsCurrentTag.identity_id !== settingsActiveIdentity?.id) {
      setTagsFeedback(getOtherIdentityGuidance(tagsCurrentTag, "release"));
    } else {
      setTagsFeedback("Release is only available for tags you manage, or recoverable unowned tags.");
    }
    return;
  }
  openDeleteModal(
    "Release Tag",
    "Release control of this tag? It will no longer be associated with your identity. Anyone can then claim or rewrite it.",
    () => runReleaseTag(managed),
    "Release Tag"
  );
}

async function runReleaseTag(managed) {
  if (!ensureTauriAvailable() || !tagsCurrentTag) return;
  if (tagsReleaseBtn) { tagsReleaseBtn.disabled = true; tagsReleaseBtn.textContent = "Releasing…"; }
  setTagsFeedback(managed ? "Releasing tag control…" : "Restoring released status…");
  try {
    const tag = await invoke("release_tag_control", {
      masterPassword: activeMasterPassword,
      request: { tagId: tagsCurrentTag.id },
    });
    setTagsFeedback(managed ? "Tag control released." : "Released status restored. You can now use Rewrite to take control.");
    renderTagDiscovery(tag, { liveDetails: null });
    await refreshTagSelectionByUid(tag.uid);
    void loadStudioTagOptions();
  } catch (error) {
    setTagsFeedback(`Could not release this tag: ${String(error)}`, "error");
  } finally {
    if (tagsReleaseBtn) tagsReleaseBtn.textContent = "Release Tag";
    updateTagsStateGating();
  }
}

async function handleLinkArtwork() {
  if (!ensureTauriAvailable() || !activeMasterPassword.trim()) return;
  const artworkId = Number(tagsLinkArtworkSelect?.value);
  if (!artworkId || !tagsCurrentTag?.id) {
    setTagsFeedback("Select an artwork to link to this tag.", "error");
    return;
  }
  const url = (tagsContentUrlInput || tagsVerificationUrlInput)?.value?.trim();
  if (!url) {
    setTagsFeedback("Enter a verification URL first.", "error");
    return;
  }
  if (tagsLinkArtworkBtn) { tagsLinkArtworkBtn.disabled = true; tagsLinkArtworkBtn.textContent = "Writing…"; }
  setTagsFeedback("Linking artwork and writing to tag. Hold it on the reader (up to 12 seconds).");
  try {
    await invoke("link_tag_to_artwork", {
      masterPassword: activeMasterPassword,
      request: { tagId: tagsCurrentTag.id, artworkId, identityId: settingsActiveIdentity.id },
    });
    try {
      await withNfcTimeout(invoke("rewrite_tag_ndef", {
        masterPassword: activeMasterPassword,
        request: { baseUrl: url, timeoutMs: 12000 },
      }));
      setTagsFeedback("Artwork linked and written to tag successfully.");
      await refreshTagSelectionByUid(tagsCurrentTag.uid, { preserveDetails: false });
      void loadStudioTagOptions();
      void loadLinkArtworkOptions();
    } catch (nfcError) {
      try { await invoke("unlink_tag_artwork", { masterPassword: activeMasterPassword, request: { tagId: tagsCurrentTag.id } }); } catch (_) {}
      setTagsFeedback(`NFC write failed — artwork unlinked. ${String(nfcError)}`, "error");
    }
  } catch (error) {
    setTagsFeedback(`Could not link artwork: ${String(error)}`, "error");
  } finally {
    if (tagsLinkArtworkBtn) tagsLinkArtworkBtn.textContent = "Write to Tag";
    updateTagsStateGating();
  }
}

function setSettingsFeedback(target, message, tone = "") {
  if (!target) return;
  target.textContent = message;
  target.classList.remove("error");
  if (tone === "error") {
    target.classList.add("error");
  }
  if (message) showAppToast(message, tone);
}

function setSettingsBusy(button, isBusy, busyLabel, normalLabel) {
  if (!button) return;
  button.disabled = isBusy;
  if (isBusy) {
    button.textContent = busyLabel;
  } else {
    button.textContent = normalLabel;
  }
}

function renderActiveSettingsIdentity(identity) {
  if (!settingsDomReady) return;
  settingsActiveIdentity = identity || null;
  if (!identity) {
    settingsActiveName.textContent = "No active identity";
    settingsActiveOrg.textContent = "—";
    if (sidebarActiveIdentity) sidebarActiveIdentity.textContent = "—";
    if (settingsActiveFingerprint) settingsActiveFingerprint.textContent = "—";
    settingsCertStatus.textContent = "Self-Signed";
    settingsCertStatus.classList.remove("production");
    if (settingsExportCertBtn) settingsExportCertBtn.disabled = true;
    return;
  }
  if (settingsExportCertBtn) settingsExportCertBtn.disabled = false;

  settingsActiveName.textContent = identity.common_name || "Unnamed identity";
  settingsActiveOrg.textContent = identity.organization || "(not set)";
  if (sidebarActiveIdentity) {
    const name = identity.common_name || "Unnamed identity";
    const org = identity.organization?.trim();
    sidebarActiveIdentity.textContent = org ? `${name} (${org})` : name;
  }
  if (settingsActiveFingerprint) {
    settingsActiveFingerprint.textContent = identity.public_key_fingerprint || "—";
  }
  if (identity.is_production) {
    settingsCertStatus.textContent = "charm.farm";
    settingsCertStatus.classList.add("production");
  } else {
    settingsCertStatus.textContent = "Self-Signed";
    settingsCertStatus.classList.remove("production");
  }

  // Always sync CSR section to the active identity so switching identities updates it
  settingsCsrNameInput.value = identity.common_name ?? "";
  settingsCsrOrgInput.value = identity.organization ?? "";
  settingsCsrCountryInput.value = identity.country ?? "";
}

function populateSettingsIdentitySelector(identities, activeIdentityId) {
  if (!settingsDomReady) return;
  settingsIdentitySelect.replaceChildren();
  const list = Array.isArray(identities) ? identities : [];
  if (!list.length) {
    const emptyOption = document.createElement("option");
    emptyOption.value = "";
    emptyOption.textContent = "No identities available";
    settingsIdentitySelect.appendChild(emptyOption);
    settingsIdentitySelect.disabled = true;
    settingsSetActiveBtn.disabled = true;
    if (settingsDeleteIdentityBtn) settingsDeleteIdentityBtn.disabled = true;
    return;
  }

  list.forEach((identity) => {
    const option = document.createElement("option");
    option.value = String(identity.id);
    const labelName = identity.common_name || `Identity #${identity.id}`;
    const labelOrg = identity.organization ? ` · ${identity.organization}` : "";
    const productionSuffix = identity.is_production ? " (charm.farm)" : "";
    option.textContent = `${labelName}${labelOrg}${productionSuffix}`;
    settingsIdentitySelect.appendChild(option);
  });

  settingsIdentitySelect.value = String(activeIdentityId ?? list[0].id);
  settingsIdentitySelect.disabled = false;
  settingsSetActiveBtn.disabled = false;
  if (settingsDeleteIdentityBtn) settingsDeleteIdentityBtn.disabled = false;
}

async function refreshSettingsProfile(masterPassword) {
  if (!settingsDomReady) return;
  if (!ensureTauriAvailable()) return;
  if (!masterPassword?.trim()) return;
  try {
    const identities = await invoke("list_identities", { masterPassword });
    settingsIdentityList = Array.isArray(identities) ? identities : [];
    const activeIdentity = Array.isArray(identities)
      ? identities.find((identity) => identity.is_active) || identities[0] || null
      : null;
    populateSettingsIdentitySelector(settingsIdentityList, activeIdentity?.id);
    renderActiveSettingsIdentity(activeIdentity);
  } catch (error) {
    setSettingsFeedback(settingsProfileFeedback, `Unable to load identities: ${String(error)}`, "error");
  }
}

async function handleSetActiveProfile() {
  if (!settingsDomReady) return;
  if (!ensureTauriAvailable()) return;
  if (!activeMasterPassword.trim()) {
    setSettingsFeedback(settingsProfileFeedback, "Unlock vault first.", "error");
    return;
  }
  const selectedValue = settingsIdentitySelect.value;
  const selectedId = Number(selectedValue);
  if (!selectedValue || Number.isNaN(selectedId)) {
    setSettingsFeedback(settingsProfileFeedback, "Select an identity first.", "error");
    return;
  }

  setSettingsBusy(settingsSetActiveBtn, true, "Setting...", "Set Active");
  try {
    await invoke("set_active_identity", {
      masterPassword: activeMasterPassword,
      identityId: selectedId
    });
    await refreshSettingsProfile(activeMasterPassword);
    await preloadActiveIdentityName(activeMasterPassword);
    setSettingsFeedback(settingsProfileFeedback, "Active identity updated.");
  } catch (error) {
    setSettingsFeedback(settingsProfileFeedback, `Could not set active profile: ${String(error)}`, "error");
  } finally {
    setSettingsBusy(settingsSetActiveBtn, false, "Setting...", "Set Active");
  }
}

async function handleDeleteIdentity() {
  if (!settingsDomReady) return;
  if (!ensureTauriAvailable()) return;
  if (!activeMasterPassword.trim()) {
    setSettingsFeedback(settingsProfileFeedback, "Unlock vault first.", "error");
    return;
  }
  const selectedValue = settingsIdentitySelect.value;
  const selectedId = Number(selectedValue);
  if (!selectedValue || Number.isNaN(selectedId)) {
    setSettingsFeedback(settingsProfileFeedback, "Select an identity to delete.", "error");
    return;
  }
  const selectedOption = settingsIdentitySelect.selectedOptions[0];
  const label = selectedOption ? selectedOption.textContent : `Identity #${selectedId}`;
  openDeleteModal(
    "Remove Identity",
    `Remove "${label}"? This permanently deletes the identity and its signing keys.`,
    async () => {
      setSettingsBusy(settingsDeleteIdentityBtn, true, "Deleting...", "Delete");
      try {
        await invoke("delete_identity", {
          masterPassword: activeMasterPassword,
          request: { identity_id: selectedId }
        });
        setSettingsFeedback(settingsProfileFeedback, "Identity deleted.");
        await refreshSettingsProfile(activeMasterPassword);
        await preloadActiveIdentityName(activeMasterPassword);
      } catch (error) {
        setSettingsFeedback(settingsProfileFeedback, `Could not delete identity: ${String(error)}`, "error");
      } finally {
        setSettingsBusy(settingsDeleteIdentityBtn, false, "Deleting...", "Delete");
      }
    }
  );
}

function toggleCreateProfileForm() {
  if (!settingsDomReady) return;
  const isHidden = settingsCreateProfileForm.hidden;
  settingsCreateProfileForm.hidden = !isHidden;
  settingsCreateProfileToggleBtn.textContent = isHidden ? "Hide Form" : "Create New Identity";
}

async function handleCreateProfileSubmit(event) {
  if (!settingsDomReady) return;
  event.preventDefault();
  if (!ensureTauriAvailable()) return;
  if (!activeMasterPassword.trim()) {
    setSettingsFeedback(settingsProfileFeedback, "Unlock vault first.", "error");
    return;
  }

  const name = settingsProfileNameInput.value.trim();
  const organization = settingsProfileOrgInput.value.trim();
  const country = settingsProfileCountryInput.value.trim().toUpperCase();
  if (!name || !organization || !country) {
    setSettingsFeedback(settingsProfileFeedback, "Name, Organization, and Country are required.", "error");
    return;
  }

  setSettingsBusy(settingsCreateProfileBtn, true, "Creating...", "Create Identity");
  setSettingsFeedback(settingsProfileFeedback, "Generating new identity...");
  try {
    const identityId = await invoke("generate_sovereign_identity", {
      masterPassword: activeMasterPassword,
      request: { name, organization, country }
    });
    await invoke("set_active_identity", {
      masterPassword: activeMasterPassword,
      identityId: Number(identityId)
    });
    preferredAuthorName = name;
    settingsProfileNameInput.value = "";
    settingsProfileOrgInput.value = "";
    settingsProfileCountryInput.value = "";
    settingsCreateProfileForm.hidden = true;
    settingsCreateProfileToggleBtn.textContent = "Create New Identity";
    setSettingsFeedback(settingsProfileFeedback, "New identity created and set active.");
    await refreshSettingsProfile(activeMasterPassword);
    await preloadActiveIdentityName(activeMasterPassword);
  } catch (error) {
    setSettingsFeedback(settingsProfileFeedback, `Identity creation failed: ${String(error)}`, "error");
  } finally {
    setSettingsBusy(settingsCreateProfileBtn, false, "Creating...", "Create Identity");
  }
}

async function handleExportCert() {
  if (!settingsDomReady) return;
  if (!ensureTauriAvailable()) return;
  if (!activeMasterPassword.trim()) {
    setSettingsFeedback(settingsProfileFeedback, "Unlock vault first.", "error");
    return;
  }
  if (!settingsActiveIdentity?.id) {
    setSettingsFeedback(settingsProfileFeedback, "No active identity selected.", "error");
    return;
  }
  try {
    const baseName = (settingsActiveIdentity?.common_name || "identity")
      .replace(/[^\w\s-]/g, "")
      .replace(/\s+/g, "_")
      .trim() || "identity";
    const outputPath = await invoke("pick_save_file_path", {
      title: "Save public certificate",
      defaultName: `${baseName}.crt`
    });
    if (!outputPath) return;
    await invoke("export_public_certificate", {
      masterPassword: activeMasterPassword,
      request: { output_path: outputPath }
    });
    setSettingsFeedback(settingsProfileFeedback, `Certificate exported to: ${outputPath}`);
  } catch (error) {
    setSettingsFeedback(settingsProfileFeedback, `Export failed: ${String(error)}`, "error");
  }
}

async function handleExportBackup() {
  if (!settingsDomReady) return;
  if (!ensureTauriAvailable()) return;
  if (!activeMasterPassword.trim()) {
    setSettingsFeedback(settingsBackupFeedback, "Unlock vault first.", "error");
    return;
  }
  if (!settingsActiveIdentity?.id) {
    setSettingsFeedback(settingsBackupFeedback, "No active identity selected.", "error");
    return;
  }

  setSettingsBusy(settingsExportBackupBtn, true, "Preparing...", "Export Private Key Backup");
  setSettingsFeedback(settingsBackupFeedback, "");
  openDeleteModal(
    "Security Warning",
    "You are exporting an unencrypted private key backup. Anyone with this file can sign as this identity. Continue?",
    () => runExportPrivateKeyBackup(),
    "Continue",
    () => {
      setSettingsFeedback(settingsBackupFeedback, "Backup export cancelled.");
      setSettingsBusy(settingsExportBackupBtn, false, "Preparing...", "Export Private Key Backup");
    }
  );
}

async function runExportPrivateKeyBackup() {
  try {
    const outputPath = await invoke("pick_save_file_path", {
      title: "Choose private key backup path",
      defaultName: "private_key_backup.pem"
    });
    if (!outputPath) {
      setSettingsFeedback(settingsBackupFeedback, "Backup export cancelled.");
      return;
    }
    await invoke("export_private_key_backup", {
      masterPassword: activeMasterPassword,
      request: {
        identity_id: Number(settingsActiveIdentity.id),
        output_path: outputPath
      }
    });
    setSettingsFeedback(settingsBackupFeedback, `Backup exported to: ${outputPath}`);
  } catch (error) {
    setSettingsFeedback(settingsBackupFeedback, `Backup failed: ${String(error)}`, "error");
  } finally {
    setSettingsBusy(settingsExportBackupBtn, false, "Preparing...", "Export Private Key Backup");
  }
}

async function handleExportVault() {
  if (!settingsDomReady) return;
  if (!ensureTauriAvailable()) return;
  if (!activeMasterPassword.trim()) {
    setSettingsFeedback(settingsBackupFeedback, "Unlock vault first.", "error");
    return;
  }
  if (settingsExportVaultBtn) {
    setSettingsBusy(settingsExportVaultBtn, true, "Exporting...", "Export Vault");
  }
  setSettingsFeedback(settingsBackupFeedback, "");
  try {
    const outputPath = await invoke("pick_save_file_path", {
      title: "Choose vault export path",
      defaultName: "vault_export.zip"
    });
    if (!outputPath) {
      setSettingsFeedback(settingsBackupFeedback, "Export cancelled.");
      return;
    }
    await invoke("export_vault", {
      masterPassword: activeMasterPassword,
      outputPath: outputPath
    });
    setSettingsFeedback(settingsBackupFeedback, `Vault exported to: ${outputPath}`);
  } catch (error) {
    setSettingsFeedback(settingsBackupFeedback, `Export failed: ${String(error)}`, "error");
  } finally {
    if (settingsExportVaultBtn) {
      setSettingsBusy(settingsExportVaultBtn, false, "Exporting...", "Export Vault");
    }
  }
}

function openChangePasswordModal() {
  if (!changePasswordModalBackdrop) return;
  if (!activeMasterPassword.trim()) {
    setSettingsFeedback(settingsBackupFeedback, "Unlock vault first.", "error");
    return;
  }
  if (changePasswordCurrentInput) changePasswordCurrentInput.value = "";
  if (changePasswordNewInput) changePasswordNewInput.value = "";
  if (changePasswordConfirmInput) changePasswordConfirmInput.value = "";
  if (changePasswordModalFeedback) {
    changePasswordModalFeedback.textContent = "";
    changePasswordModalFeedback.classList.remove("error");
  }
  changePasswordModalBackdrop.classList.add("visible");
  changePasswordModalBackdrop.setAttribute("aria-hidden", "false");
  if (changePasswordCurrentInput) changePasswordCurrentInput.focus();
}

function closeChangePasswordModal() {
  if (!changePasswordModalBackdrop) return;
  changePasswordModalBackdrop.classList.remove("visible");
  changePasswordModalBackdrop.setAttribute("aria-hidden", "true");
}

function setChangePasswordFeedback(message, isError = false) {
  if (!changePasswordModalFeedback) return;
  changePasswordModalFeedback.textContent = message;
  changePasswordModalFeedback.classList.toggle("error", isError);
}

async function handleChangePasswordConfirm() {
  if (!ensureTauriAvailable() || !changePasswordModalBackdrop) return;
  const current = changePasswordCurrentInput?.value ?? "";
  const newPw = changePasswordNewInput?.value ?? "";
  const confirm = changePasswordConfirmInput?.value ?? "";

  if (!current.trim()) {
    setChangePasswordFeedback("Enter your current password.", true);
    return;
  }
  if (!newPw.trim()) {
    setChangePasswordFeedback("Enter a new password.", true);
    return;
  }
  if (newPw !== confirm) {
    setChangePasswordFeedback("New password and confirmation do not match.", true);
    return;
  }
  if (newPw === current) {
    setChangePasswordFeedback("New password must differ from current password.", true);
    return;
  }

  changePasswordConfirmBtn.disabled = true;
  changePasswordConfirmBtn.textContent = "Changing...";
  setChangePasswordFeedback("");
  try {
    await invoke("change_vault_password", {
      request: {
        current_password: current,
        new_password: newPw
      }
    });
    closeChangePasswordModal();
    lockVault("Password changed. Unlock with your new password.");
  } catch (error) {
    setChangePasswordFeedback(String(error), true);
  } finally {
    changePasswordConfirmBtn.disabled = false;
    changePasswordConfirmBtn.textContent = "Change Password";
  }
}

function toggleAdvancedSettings() {
  if (!settingsDomReady) return;
  const isHidden = settingsAdvancedPanel.hidden;
  settingsAdvancedPanel.hidden = !isHidden;
  settingsAdvancedToggleBtn.textContent = isHidden ? "Hide Integration" : "Show Integration";
}

async function handleBrowseCsrPath() {
  if (!settingsDomReady) return;
  if (!ensureTauriAvailable()) return;
  try {
    const baseName = (settingsActiveIdentity?.common_name || "identity")
      .replace(/[^\w\s-]/g, "")
      .replace(/\s+/g, "_")
      .trim() || "identity";
    const outputPath = await invoke("pick_save_file_path", {
      title: "Choose CSR output path",
      defaultName: `${baseName}_identity_request.csr`
    });
    if (outputPath) {
      settingsCsrOutputPathInput.value = outputPath;
    }
  } catch (error) {
    setSettingsFeedback(settingsAdvancedFeedback, `Could not select CSR path: ${String(error)}`, "error");
  }
}

async function handleGenerateCsr() {
  if (!settingsDomReady) return;
  if (!ensureTauriAvailable()) return;
  if (!activeMasterPassword.trim()) {
    setSettingsFeedback(settingsAdvancedFeedback, "Unlock vault first.", "error");
    return;
  }
  if (!settingsActiveIdentity?.id) {
    setSettingsFeedback(settingsAdvancedFeedback, "No active identity selected.", "error");
    return;
  }

  const name = settingsCsrNameInput.value.trim();
  const organization = settingsCsrOrgInput.value.trim();
  const country = settingsCsrCountryInput.value.trim().toUpperCase();
  const outputPath = settingsCsrOutputPathInput.value.trim();
  if (!name || !organization || !country || !outputPath) {
    setSettingsFeedback(settingsAdvancedFeedback, "Name, Organization, Country, and CSR output path are required.", "error");
    return;
  }

  setSettingsBusy(settingsGenerateCsrBtn, true, "Generating...", "Generate Request File");
  setSettingsFeedback(settingsAdvancedFeedback, "Generating CSR...");
  try {
    await invoke("generate_csr", {
      masterPassword: activeMasterPassword,
      request: {
        identity_id: Number(settingsActiveIdentity.id),
        name,
        organization,
        country,
        output_path: outputPath
      }
    });
    setSettingsFeedback(settingsAdvancedFeedback, `CSR generated at: ${outputPath}`);
  } catch (error) {
    setSettingsFeedback(settingsAdvancedFeedback, `CSR generation failed: ${String(error)}`, "error");
  } finally {
    setSettingsBusy(settingsGenerateCsrBtn, false, "Generating...", "Generate Request File");
  }
}

async function handleBrowseCaChainPath() {
  if (!settingsDomReady) return;
  if (!ensureTauriAvailable()) return;
  try {
    const caPath = await invoke("pick_open_file_path", {
      title: "Select certificate chain file",
      extensions: ["pem", "crt"]
    });
    if (caPath) {
      settingsCaChainPathInput.value = caPath;
    }
  } catch (error) {
    setSettingsFeedback(settingsAdvancedFeedback, `Could not select CA chain: ${String(error)}`, "error");
  }
}

async function handleUpgradeCa() {
  if (!settingsDomReady) return;
  if (!ensureTauriAvailable()) return;
  if (!activeMasterPassword.trim()) {
    setSettingsFeedback(settingsAdvancedFeedback, "Unlock vault first.", "error");
    return;
  }
  if (!settingsActiveIdentity?.id) {
    setSettingsFeedback(settingsAdvancedFeedback, "No active identity selected.", "error");
    return;
  }
  const certificateChainPath = settingsCaChainPathInput.value.trim();
  if (!certificateChainPath) {
    setSettingsFeedback(settingsAdvancedFeedback, "CA certificate chain path is required.", "error");
    return;
  }

  setSettingsBusy(settingsUpgradeCaBtn, true, "Upgrading...", "Install Verified Identity");
  setSettingsFeedback(settingsAdvancedFeedback, "Upgrading active profile...");
  try {
    await invoke("import_ca_certificate", {
      masterPassword: activeMasterPassword,
      request: {
        identity_id: Number(settingsActiveIdentity.id),
        certificate_chain_path: certificateChainPath
      }
    });
    setSettingsFeedback(settingsAdvancedFeedback, "Production identity created and set active. You can switch between self-signed and production in the profile selector above.");
    await refreshSettingsProfile(activeMasterPassword);
    await preloadActiveIdentityName(activeMasterPassword);
    await refreshStudioSigningMode();
  } catch (error) {
    setSettingsFeedback(settingsAdvancedFeedback, `Upgrade failed: ${String(error)}`, "error");
  } finally {
    setSettingsBusy(settingsUpgradeCaBtn, false, "Upgrading...", "Install Verified Identity");
  }
}

function setVaultFeedback(message, tone = "") {
  vaultFeedback.textContent = message;
  vaultFeedback.classList.remove("error");
  if (tone === "error") {
    vaultFeedback.classList.add("error");
  }
  if (message) showAppToast(message, tone);
}

function showVaultEmptyState() {
  vaultGrid.hidden = true;
  vaultEmptyState.hidden = false;
}

function showVaultGrid() {
  vaultEmptyState.hidden = true;
  vaultGrid.hidden = false;
}

function createBadge(className, text) {
  const badge = document.createElement("span");
  badge.className = `badge ${className}`;
  badge.textContent = text;
  return badge;
}

function applyVaultThumbnail(thumb, draft) {
  if (!draft?.asset_path) return;
  const image = document.createElement("img");
  image.alt = draft.artifact_title || "Artwork thumbnail";
  image.loading = "lazy";
  image.addEventListener("load", () => {
    thumb.classList.remove("fallback");
  });
  thumb.appendChild(image);
  setImageFromPathRobust(image, draft.asset_path, () => {
    image.remove();
    thumb.classList.add("fallback");
  });
}

async function openVaultDraft(draft) {
  if (!draft?.asset_path) {
    setVaultFeedback("This record has no file path. Re-register the artwork from Studio.", "error");
    return;
  }

  if (draft.is_certified || draft.c2pa_manifest_id) {
    setRoute("inspector");
    resetInspector(true);
    await verifyInspectorPath(draft.asset_path);
    return;
  }

  setRoute("studio");
  studioActiveDraftId = draft.id;
  applySelectedStudioFile(draft.asset_path);
  if (draft.artifact_title) studioTitleInput.value = draft.artifact_title;
  if (draft.author) studioAuthorInput.value = draft.author;
  studioDescriptionInput.value = draft.description ?? "";
  studioDateCreatedInput.value = draft.date_created ?? "";
  studioKeywordsInput.value = draft.keywords ?? "";
  studioGenreInput.value = draft.genre ?? "";
  studioMaterialInput.value = draft.material ?? "";
  studioContributorInput.value = draft.contributor ?? "";
  studioLicenseInput.value = draft.license ?? "";
  studioAbstractInput.value = draft.abstract_ ?? "";
  // Tag selection is for seal-time only; drafts don't store tag_id
  setStudioFeedback("Loaded draft from Vault. Review details and seal when ready.");
}

let pendingDeleteCallback = null;
let pendingCancelCallback = null;

function openDeleteModal(title, message, onConfirm, confirmButtonLabel = "Remove", onCancel = null) {
  pendingDeleteCallback = onConfirm;
  pendingCancelCallback = onCancel ?? null;
  const deleteModalBackdrop = document.getElementById("deleteModalBackdrop");
  const deleteModalTitle = document.getElementById("deleteModalTitle");
  const deleteModalNote = document.getElementById("deleteModalNote");
  const deleteConfirmBtn = document.getElementById("deleteConfirmBtn");
  if (deleteModalTitle) deleteModalTitle.textContent = title;
  deleteModalNote.textContent = message;
  if (deleteConfirmBtn) deleteConfirmBtn.textContent = confirmButtonLabel;
  deleteModalBackdrop.classList.add("visible");
  deleteModalBackdrop.setAttribute("aria-hidden", "false");
}

function closeDeleteModal() {
  const cancel = pendingCancelCallback;
  pendingDeleteCallback = null;
  pendingCancelCallback = null;
  const deleteModalBackdrop = document.getElementById("deleteModalBackdrop");
  const deleteConfirmBtn = document.getElementById("deleteConfirmBtn");
  if (deleteConfirmBtn) deleteConfirmBtn.textContent = "Remove";
  deleteModalBackdrop.classList.remove("visible");
  deleteModalBackdrop.setAttribute("aria-hidden", "true");
  if (cancel) cancel();
}

async function handleDeleteConfirm() {
  const callback = pendingDeleteCallback;
  if (!callback) return;
  closeDeleteModal();
  await callback();
}

function deleteVaultDraft(draft) {
  if (!ensureTauriAvailable()) return;
  if (!activeMasterPassword.trim()) {
    setVaultFeedback("Unlock vault first to remove vault records.", "error");
    return;
  }
  const draftId = Number(draft?.id);
  if (!Number.isFinite(draftId)) {
    setVaultFeedback("This vault record cannot be deleted because its ID is invalid.", "error");
    return;
  }
  const displayTitle = draft?.artifact_title || "this artwork";
  openDeleteModal(
    "Remove Artwork",
    `Remove "${displayTitle}" from the vault? This cannot be undone.`,
    async () => {
      if (!ensureTauriAvailable()) return;
      try {
        await invoke("delete_draft", {
          masterPassword: activeMasterPassword,
          request: { draft_id: draftId }
        });
        setVaultFeedback(`Removed "${displayTitle}" from vault.`);
        await loadVaultDrafts(activeMasterPassword);
      } catch (error) {
        setVaultFeedback(`Could not remove artwork: ${String(error)}`, "error");
      }
    }
  );
}

function createVaultCard(draft) {
  const card = document.createElement("article");
  card.className = "asset-card";
  card.dataset.draftId = String(draft.id ?? "");
  card.dataset.manifestId = draft.c2pa_manifest_id || "";
  card.tabIndex = 0;
  card.setAttribute("role", "button");

  const thumb = document.createElement("div");
  thumb.className = "asset-thumb fallback";
  applyVaultThumbnail(thumb, draft);

  const badges = document.createElement("div");
  badges.className = "card-badges";
  badges.appendChild(
    draft.is_certified
      ? createBadge("badge-certified", "Certified")
      : createBadge("badge-draft", "Draft")
  );
  if (draft.perceptual_hash) {
    badges.appendChild(createBadge("badge-phash", "pHash ✓"));
  }
  const actions = document.createElement("div");
  actions.className = "card-actions";
  const deleteBtn = document.createElement("button");
  deleteBtn.className = "card-delete";
  deleteBtn.type = "button";
  deleteBtn.setAttribute("aria-label", "Delete artwork");
  deleteBtn.innerHTML = "<svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M3 6h18\"/><path d=\"M8 6V4h8v2\"/><path d=\"M7 6l1 14h8l1-14\"/><path d=\"M10 10v7\"/><path d=\"M14 10v7\"/></svg>";
  deleteBtn.addEventListener("pointerdown", (event) => {
    event.preventDefault();
    event.stopPropagation();
  });
  deleteBtn.addEventListener("click", (event) => {
    event.preventDefault();
    event.stopPropagation();
    void deleteVaultDraft(draft);
  });
  actions.appendChild(deleteBtn);

  const meta = document.createElement("div");
  meta.className = "asset-meta";
  const title = document.createElement("h3");
  title.className = "asset-title";
  title.textContent = draft.artifact_title || "(Untitled artwork)";
  if (draft.asset_path) {
    title.classList.add("has-filepath");
    title.title = draft.asset_path;
    title.setAttribute("aria-label", `Local file: ${draft.asset_path}`);
  }
  const author = document.createElement("p");
  author.className = "asset-author";
  author.textContent = draft.author || "Unknown author";
  meta.append(title, author);
  card.append(thumb, badges, actions, meta);
  card.addEventListener("click", () => {
    void openVaultDraft(draft);
  });
  card.addEventListener("keydown", (event) => {
    if (event.key === "Enter" || event.key === " ") {
      event.preventDefault();
      void openVaultDraft(draft);
    }
  });
  return card;
}

function renderVaultDrafts(drafts) {
  vaultGrid.replaceChildren();
  if (!drafts.length) {
    setVaultFeedback("");
    showVaultEmptyState();
    return;
  }

  const cards = drafts.map((draft) => createVaultCard(draft));
  vaultGrid.append(...cards);
  setVaultFeedback(`${drafts.length} artwork${drafts.length === 1 ? "" : "s"} in vault. Click any card to continue.`);
  showVaultGrid();
  refreshCardBadgesLive(drafts);
}

async function refreshCardBadgesLive(drafts) {
  if (typeof invoke !== "function" || !activeMasterPassword.trim()) return;
  const verifiable = drafts.filter((d) => d.asset_path);
  if (!verifiable.length) return;

  let vaultFingerprints = [];
  try {
    vaultFingerprints = await invoke("list_vault_identity_fingerprints", {
      masterPassword: activeMasterPassword
    });
  } catch (_) {}
  const fpSet = new Set((vaultFingerprints || []).map((fp) => fp.toLowerCase()));

  for (const draft of verifiable) {
    invoke("verify_image", { inputPath: draft.asset_path })
      .then((result) => {
        const card = vaultGrid.querySelector(`[data-draft-id="${draft.id}"]`);
        if (!card) return;
        const badgesEl = card.querySelector(".card-badges");
        if (!badgesEl) return;
        const old = badgesEl.querySelector(".badge-certified, .badge-sealed, .badge-charmed, .badge-signed, .badge-draft");
        if (!old) return;

        const status = String(result?.status || "").toLowerCase();
        if (status !== "success") {
          if (!draft.is_certified) return;
          old.className = "badge badge-signed";
          old.textContent = "Signed";
          return;
        }

        const signerFp = String(result?.signer_certificate_fingerprint || "").toLowerCase();
        const isVaultSigner = signerFp && fpSet.has(signerFp);
        const claimGen = String(result?.claim_generator || "").toLowerCase();
        const isTrustSystems = claimGen.includes("trust-systems") || claimGen.includes("trust_systems");

        if (result.is_charmed) {
          old.className = "badge badge-charmed";
          old.textContent = "Charmed";
        } else if (isVaultSigner || isTrustSystems) {
          old.className = "badge badge-sealed";
          old.textContent = "Sealed";
        } else {
          old.className = "badge badge-signed";
          old.textContent = "Signed";
        }
      })
      .catch(() => {});
  }
}

async function loadVaultDrafts(masterPassword) {
  if (!ensureTauriAvailable()) return;
  if (!masterPassword?.trim()) {
    setVaultFeedback("Master password is required to load vault records.", "error");
    showVaultEmptyState();
    return;
  }

  setVaultFeedback("Loading vault records...");
  showVaultEmptyState();

  try {
    const drafts = await invoke("list_drafts", { masterPassword });
    renderVaultDrafts(Array.isArray(drafts) ? drafts : []);
  } catch (error) {
    setVaultFeedback(`Unable to load vault records: ${String(error)}`, "error");
    showVaultEmptyState();
  }
}

function onRegisterArtworkClick() {
  setRoute("studio");
}

function setInspectorFeedback(message, tone = "") {
  inspectorFeedback.textContent = message;
  inspectorFeedback.classList.remove("error");
  if (tone === "error") {
    inspectorFeedback.classList.add("error");
  }
  inspectorFeedback.hidden = !String(message).trim();
  if (message) showAppToast(message, tone);
}

function clearInspectorProgressTimer() {
  if (inspectorProgressTimer) {
    clearInterval(inspectorProgressTimer);
    inspectorProgressTimer = null;
  }
}

function updateInspectorProgressDisplay(value) {
  if (!inspectorProgressFill || !inspectorProgressMeta) return;
  const clamped = Math.max(0, Math.min(100, Math.round(value)));
  inspectorProgressFill.style.width = `${clamped}%`;
  inspectorProgressMeta.textContent = `${clamped}%`;
}

function startInspectorProgress(title = "Checking provenance…") {
  if (!inspectorProgressOverlay) return;
  clearInspectorProgressTimer();
  inspectorProgressValue = 6;
  if (inspectorProgressTitle) inspectorProgressTitle.textContent = title;
  updateInspectorProgressDisplay(inspectorProgressValue);
  inspectorProgressOverlay.hidden = false;
  inspectorProgressTimer = setInterval(() => {
    if (inspectorProgressValue >= 92) return;
    const increment = inspectorProgressValue < 36
      ? 4
      : inspectorProgressValue < 72
        ? 2
        : 1;
    inspectorProgressValue = Math.min(92, inspectorProgressValue + increment);
    updateInspectorProgressDisplay(inspectorProgressValue);
  }, 140);
}

function finishInspectorProgress(success, token) {
  if (token !== inspectorVerifyToken || !inspectorProgressOverlay) return;
  clearInspectorProgressTimer();
  if (inspectorProgressTitle) {
    inspectorProgressTitle.textContent = success ? "Provenance verified" : "Verification failed";
  }
  updateInspectorProgressDisplay(100);
  setTimeout(() => {
    if (token !== inspectorVerifyToken || !inspectorProgressOverlay) return;
    inspectorProgressOverlay.hidden = true;
    inspectorProgressValue = 0;
    updateInspectorProgressDisplay(0);
    if (inspectorProgressTitle) inspectorProgressTitle.textContent = "Checking provenance…";
  }, success ? 300 : 420);
}

function resetInspectorProgress() {
  clearInspectorProgressTimer();
  inspectorProgressValue = 0;
  if (inspectorProgressOverlay) inspectorProgressOverlay.hidden = true;
  if (inspectorProgressTitle) inspectorProgressTitle.textContent = "Checking provenance…";
  updateInspectorProgressDisplay(0);
}

function setTransferModalFeedback(message, tone = "") {
  transferModalFeedback.textContent = message;
  transferModalFeedback.classList.remove("error");
  if (tone === "error") {
    transferModalFeedback.classList.add("error");
  }
  if (message) showAppToast(message, tone);
}

async function openTransferModal() {
  setTransferModalFeedback("");
  if (!ensureTauriAvailable()) return;
  try {
    const contacts = await invoke("list_trusted_contacts", { masterPassword: activeMasterPassword });
    const list = Array.isArray(contacts) ? contacts : [];
    transferRecipientSelect.replaceChildren();
    if (list.length === 0) {
      const empty = document.createElement("option");
      empty.value = "";
      empty.textContent = "No trusted contacts";
      transferRecipientSelect.appendChild(empty);
      transferRecipientSelect.disabled = true;
      if (transferNoContactsMsg) {
        transferNoContactsMsg.textContent = "No trusted contacts found. Import contacts in the Contacts tab.";
        transferNoContactsMsg.hidden = false;
      }
      transferConfirmBtn.disabled = true;
    } else {
      if (transferNoContactsMsg) transferNoContactsMsg.hidden = true;
      transferConfirmBtn.disabled = false;
      list.forEach((c) => {
        const opt = document.createElement("option");
        opt.value = c.id;
        opt.textContent = c.organization ? `${c.common_name} · ${c.organization}` : c.common_name;
        transferRecipientSelect.appendChild(opt);
      });
      transferRecipientSelect.disabled = false;
    }
  } catch (_) {
    if (transferNoContactsMsg) {
      transferNoContactsMsg.textContent = "Could not load contacts. Try the Contacts tab.";
      transferNoContactsMsg.hidden = false;
    }
    transferConfirmBtn.disabled = true;
  }
  transferModalBackdrop.classList.add("visible");
  transferModalBackdrop.setAttribute("aria-hidden", "false");
  transferRecipientSelect.focus();
}

function closeTransferModal() {
  transferModalBackdrop.classList.remove("visible");
  transferModalBackdrop.setAttribute("aria-hidden", "true");
}

function setInspectorStatus(statusRaw, isCharmed = false, isSignedByVault = false) {
  const status = String(statusRaw || "").toLowerCase();
  inspectorStatusPill.classList.remove("status-valid", "status-warning", "status-invalid", "status-charmed", "status-sealed");
  if (status === "success") {
    if (isCharmed) {
      inspectorStatusPill.classList.add("status-charmed");
      inspectorStatusPill.textContent = "Charmed";
    } else if (isSignedByVault) {
      inspectorStatusPill.classList.add("status-sealed");
      inspectorStatusPill.textContent = "Sealed";
    } else {
      inspectorStatusPill.classList.add("status-valid");
      inspectorStatusPill.textContent = "Signed";
    }
    return;
  }
  if (status === "failure") {
    inspectorStatusPill.classList.add("status-invalid");
    inspectorStatusPill.textContent = "Invalid / Tampered";
    return;
  }
  inspectorStatusPill.classList.add("status-warning");
  inspectorStatusPill.textContent = "Unrecognized Status";
}

function createTimelineNode(title, copy, isOwner = false, tooltip) {
  const item = document.createElement("li");
  item.className = "timeline-node";
  if (isOwner) {
    item.classList.add("timeline-node-owner");
  }
  if (tooltip) item.title = tooltip;
  const heading = document.createElement("h4");
  heading.className = "timeline-node-title";
  heading.textContent = title;
  const body = document.createElement("p");
  body.className = "timeline-node-copy";
  body.textContent = copy;
  item.append(heading, body);
  return item;
}

function summarizeManifestStage(entry, index, total) {
  const actions = Array.isArray(entry?.actions) ? entry.actions.map((a) => String(a).toLowerCase()) : [];
  const claimGen = String(entry?.claim_generator || "").toLowerCase();
  const isTrustSystems = claimGen.includes("trust-systems") || claimGen.includes("trust_systems");

  if (actions.some((a) => a.includes("published"))) return "Transfer";
  if (entry?.is_active && isTrustSystems) return "Sealed";
  if (entry?.is_active) return "Current Claim";

  if (index === 0) {
    if (entry?.is_ai_generated) return "AI Generated";
    if (actions.some((a) => a.includes("created"))) return "Created";
    if (actions.some((a) => a.includes("opened"))) return "Opened";
    if (actions.some((a) => a.includes("edited"))) return "Edited";
    return "Origin";
  }

  if (isTrustSystems) return "Sealed";
  if (entry?.is_ai_generated) return "AI Generated";
  return `Claim ${index + 1} of ${total}`;
}

function formatMetaValue(val) {
  const s = String(val || "").trim();
  return s ? s : "—";
}

function createManifestHistoryNode(entry, index, total) {
  const item = document.createElement("li");
  item.className = "timeline-node timeline-node-manifest";

  const stageLabel = summarizeManifestStage(entry, index, total);
  const heading = document.createElement("h4");
  heading.className = "timeline-node-title";
  heading.textContent = stageLabel;

  const who = entry?.publisher || entry?.author || "—";
  const role = entry?.publisher ? "Owner" : "Author";
  const body = document.createElement("p");
  body.className = "timeline-node-copy";
  body.textContent = `Title: ${formatMetaValue(entry?.title)} | ${role}: ${who}`;

  const meta = document.createElement("p");
  meta.className = "timeline-node-meta";
  const metaParts = [
    `Signed: ${formatMetaValue(entry?.signed_at)}`,
    `Signer: ${formatMetaValue(entry?.signer)}`,
    `Tool: ${formatMetaValue(entry?.claim_generator)}`
  ];
  const certFp = entry?.signer_certificate_fingerprint;
  if (certFp) {
    const short = certFp.length > 12 ? `${certFp.slice(0, 12)}…` : certFp;
    metaParts.push(`Cert: ${short}`);
    meta.title = `Signing certificate SHA-256: ${certFp}`;
  }
  meta.textContent = metaParts.join(" | ");

  const tagsWrap = document.createElement("div");
  tagsWrap.className = "timeline-node-tags";
  const tags = [];
  if (entry?.is_root) tags.push({ text: "Root", strong: true, charmed: false });
  if (entry?.is_active) tags.push({ text: "Active", strong: true, charmed: false });
  if (entry?.is_charmed) tags.push({ text: "charm.farm", strong: true, charmed: true });
  if (entry?.is_ai_generated) tags.push({ text: "AI Generated", strong: false, charmed: false });
  const hasPhysicalAnchor =
    entry?.physical_hash ||
    entry?.assertion_labels?.some((l) => String(l).includes("physical-anchor"));
  if (hasPhysicalAnchor) {
    const hash = entry?.physical_hash;
    const tagText = hash
      ? `Physical Anchor | ${hash.length > 16 ? `${hash.slice(0, 16)}…` : hash}`
      : "Physical Anchor";
    const tagTitle = hash ? `Physical anchor hash: ${hash}` : undefined;
    tags.push({ text: tagText, strong: false, charmed: false, title: tagTitle });
  }
  const actions = Array.isArray(entry?.actions) ? entry.actions : [];
  actions.forEach((a) => {
    const label = a.replace(/^c2pa\./, "");
    if (label) tags.push({ text: label, strong: false, charmed: false });
  });
  tags.forEach((tag) => {
    const chip = document.createElement("span");
    chip.className = `timeline-tag${tag.strong ? " timeline-tag-strong" : ""}${tag.charmed ? " timeline-tag-charmed" : ""}`;
    chip.textContent = tag.text;
    if (tag.title) chip.title = tag.title;
    tagsWrap.appendChild(chip);
  });

  item.append(heading, body, meta);
  if (tags.length) item.appendChild(tagsWrap);

  if (entry?.raw_manifest_json) {
    const details = document.createElement("details");
    details.className = "timeline-node-raw";
    const summary = document.createElement("summary");
    summary.className = "timeline-node-raw-summary";
    summary.appendChild(document.createTextNode("Raw manifest JSON"));
    const copyBtn = document.createElement("button");
    copyBtn.className = "btn-copy-minimal";
    copyBtn.type = "button";
    copyBtn.textContent = "Copy";
    copyBtn.addEventListener("click", (e) => {
      e.stopPropagation();
      const val = entry.raw_manifest_json;
      if (!val) return;
      navigator.clipboard.writeText(val).then(
        () => { copyBtn.textContent = "Copied!"; setTimeout(() => { copyBtn.textContent = "Copy"; }, 1500); },
        () => { copyBtn.textContent = "Copy failed"; setTimeout(() => { copyBtn.textContent = "Copy"; }, 1500); }
      );
    });
    summary.appendChild(document.createTextNode(" "));
    summary.appendChild(copyBtn);
    const pre = document.createElement("pre");
    pre.className = "timeline-node-raw-content";
    pre.textContent = entry.raw_manifest_json;
    details.append(summary, pre);
    item.appendChild(details);
  }

  return item;
}

function renderInspectorTimeline(result) {
  const verification = result?.verification || {};
  const nodes = [];
  const history = Array.isArray(verification.manifest_history) ? verification.manifest_history : [];
  if (history.length) {
    history.forEach((entry, index) => {
      nodes.push(createManifestHistoryNode(entry, index, history.length));
    });
  } else {
    const originCopy = [
      `Title: ${verification.origin_title || verification.title || "(unknown)"}`,
      `Author: ${verification.origin_author || verification.author || "(unknown)"}`,
      `Signed: ${verification.origin_signed_at || verification.signed_at || "(unknown)"}`
    ].join(" | ");
    nodes.push(createTimelineNode("Origin", originCopy));
  }

  if (verification.physical_hash) {
    const hash = String(verification.physical_hash);
    const shortHash = hash.length > 24 ? `${hash.slice(0, 24)}...` : hash;
    nodes.push(
      createTimelineNode("Physical Anchor", `NFC Hardware Bound | ${shortHash}`, false, `Physical anchor hash: ${hash}`)
    );
  }

  const vaultStatus = result?.vault_status || "Orphan";
  let vaultCopy = "Not found in your local vault.";
  if (vaultStatus === "Match" || vaultStatus === "PerceptualMatch") {
    const manifestId = verification.instance_id || "—";
    vaultCopy = `Verified by Local Vault (ID: ${manifestId})`;
  }
  nodes.push(createTimelineNode("Vault Correlation", vaultCopy));

  const publisherName = verification.publisher;
  const verifiedSignerContact = result?.publisher_verified_contact;
  if (publisherName || verifiedSignerContact) {
    const ownerBits = [];
    ownerBits.push(`Owned by: ${publisherName || "(not provided in metadata)"}`);
    if (verifiedSignerContact) {
      ownerBits.push(`Signer certificate: ${verifiedSignerContact} ✓ Verified trusted contact`);
    }
    nodes.push(createTimelineNode("Current Owner", ownerBits.join(" | "), true));
  }

  inspectorTimeline.replaceChildren(...nodes);
}

function updateInspectorTransferAvailability() {
  const status = String(inspectorLastVerification?.verification?.status || "").toLowerCase();
  const manifestValid = status === "success";
  const canTransfer = manifestValid && Boolean(activeMasterPassword.trim()) && Boolean(inspectorCurrentPath);
  inspectorTransferBtn.disabled = !canTransfer;
}

function renderInspectorResult(inputPath, result) {
  inspectorCurrentPath = inputPath;
  inspectorLastVerification = result;
  resetInspectorWatermarkState(inputPath);
  setImageFromPathRobust(inspectorPreviewImage, inputPath, () => {
    setInspectorFeedback("Preview unavailable for this file path, but verification loaded.", "error");
  });
  loadInspectorDataUri(inputPath);
  const claimGen = String(result?.verification?.claim_generator || "").toLowerCase();
  const isTrustSystemsOrigin = claimGen.includes("trust-systems") || claimGen.includes("trust_systems");
  setInspectorStatus(
    result?.verification?.status,
    Boolean(result?.verification?.is_charmed),
    Boolean(result?.is_signed_by_vault) || isTrustSystemsOrigin
  );
  renderInspectorTimeline(result);
  updateInspectorTransferAvailability();
  renderInspectorMetadata(inputPath, result);
  inspectorDropzone.hidden = true;
  inspectorResults.hidden = false;
}

function renderInspectorMetadata(inputPath, result) {
  if (!inspectorMetadata || !inspectorMetadataLabel || !inspectorMetadataTitle || !inspectorMetadataAuthor || !inspectorMetadataInstance || !inspectorMetadataManifest || !inspectorMetadataPerceptual || !inspectorMetadataWatermark || !inspectorMetadataTag) return;
  const verification = result?.verification || {};
  const label = result?.artifact_title || "";
  const title = verification.origin_title || verification.title || "";
  const author = verification.origin_author || verification.author || "";
  const description = verification.description || "";
  const dateCreated = verification.date_created || "";
  const keywords = verification.keywords || "";
  const genre = verification.genre || "";
  const material = verification.material || "";
  const contributor = verification.contributor || "";
  const abstractVal = verification.abstract || "";
  const license = verification.license || "";
  const instanceId = verification.instance_id || "";
  const physicalHash = verification.physical_hash || "";
  inspectorMetadata.hidden = false;
  const draftId = result?.draft_id;
  setOptionalMetadataRow("inspectorMetadataArtworkIdRow", inspectorMetadataArtworkId, draftId != null ? String(draftId) : "");
  if (inspectorMetadataFilePath) inspectorMetadataFilePath.textContent = inputPath || "—";
  if (inspectorMetadataLabel) inspectorMetadataLabel.textContent = label || "—";
  inspectorMetadataTitle.textContent = title || "—";
  inspectorMetadataAuthor.textContent = author || "—";
  setOptionalMetadataRow("inspectorMetadataDescriptionRow", inspectorMetadataDescription, description);
  setOptionalMetadataRow("inspectorMetadataDateCreatedRow", inspectorMetadataDateCreated, dateCreated);
  setOptionalMetadataRow("inspectorMetadataKeywordsRow", inspectorMetadataKeywords, keywords);
  setOptionalMetadataRow("inspectorMetadataGenreRow", inspectorMetadataGenre, genre);
  setOptionalMetadataRow("inspectorMetadataMaterialRow", inspectorMetadataMaterial, material);
  setOptionalMetadataRow("inspectorMetadataContributorRow", inspectorMetadataContributor, contributor);
  setOptionalMetadataRow("inspectorMetadataAbstractRow", inspectorMetadataAbstract, abstractVal);
  setOptionalMetadataRow("inspectorMetadataLicenseRow", inspectorMetadataLicense, license);
  const artDisplay = result?.ipfs_cid || "";
  setOptionalMetadataRow("inspectorMetadataArtRow", inspectorMetadataArt, artDisplay);
  inspectorMetadataInstance.textContent = instanceId || "—";
  const activeManifest = verification.manifest_history?.find((m) => m.is_active);
  const manifestLabel = activeManifest?.label || "";
  inspectorMetadataManifest.textContent = manifestLabel || "—";
  const perceptualHash = verification.perceptual_hash || "";
  setOptionalMetadataRow("inspectorMetadataPerceptualRow", inspectorMetadataPerceptual, perceptualHash);
  setInspectorWatermarkDisplay(inspectorMetadataWatermark);
  setInspectorTagDisplay(inspectorMetadataTag, physicalHash);
}

function resetInspectorWatermarkState(path = "") {
  inspectorWatermarkResult = null;
  inspectorWatermarkBusy = false;
  inspectorWatermarkPath = path || "";
}

async function handleInspectorCheckWatermark() {
  if (!ensureTauriAvailable()) return;
  if (inspectorWatermarkBusy) return;
  if (!inspectorCurrentPath) return;
  if (!activeMasterPassword.trim()) {
    setInspectorFeedback("Unlock vault first to check watermark.", "error");
    return;
  }
  inspectorWatermarkBusy = true;
  inspectorWatermarkResult = null;
  inspectorWatermarkPath = inspectorCurrentPath;
  setInspectorWatermarkDisplay(inspectorMetadataWatermark);
  try {
    const result = await invoke("check_image_watermark_with_vault", {
      masterPassword: activeMasterPassword,
      inputPath: inspectorCurrentPath
    });
    if (inspectorCurrentPath === inspectorWatermarkPath) {
      inspectorWatermarkResult = result || { detected: false };
    }
  } catch (error) {
    if (inspectorCurrentPath === inspectorWatermarkPath) {
      inspectorWatermarkResult = { detected: false };
      setInspectorFeedback(`Watermark check failed: ${String(error)}`, "error");
    }
  } finally {
    if (inspectorCurrentPath === inspectorWatermarkPath) {
      inspectorWatermarkBusy = false;
      setInspectorWatermarkDisplay(inspectorMetadataWatermark);
    }
  }
}

function setInspectorWatermarkDisplay(el) {
  if (!el) return;
  el.replaceChildren();
  if (!inspectorWatermarkResult && !inspectorWatermarkBusy) {
    const button = document.createElement("button");
    button.type = "button";
    button.className = "button-link inspector-copy-datauri-link";
    button.textContent = "Check watermark";
    button.addEventListener("click", () => {
      void handleInspectorCheckWatermark();
    });
    el.appendChild(button);
    return;
  }
  if (inspectorWatermarkBusy) {
    el.textContent = "Checking watermark...";
    return;
  }
  const watermark = inspectorWatermarkResult || {};
  const detected = Boolean(watermark.detected);
  if (!detected) {
    el.textContent = "Not detected";
    return;
  }
  const assetId = Number.isFinite(Number(watermark?.asset_id)) ? String(Number(watermark.asset_id)) : "";
  const step = Number.isFinite(Number(watermark?.step_size)) ? Number(watermark.step_size).toFixed(1) : "";
  const bits = ["Detected"];
  if (assetId) bits.push(`asset ${assetId}`);
  if (step) bits.push(`step ${step}`);
  el.appendChild(document.createTextNode(bits.join(" | ")));

  const matchName = String(watermark?.matched_identity_name || "").trim();
  if (matchName) {
    const chip = document.createElement("span");
    chip.className = "watermark-chip identity-match";
    chip.textContent = matchName;
    chip.setAttribute("aria-label", `Watermark matches vault identity ${matchName}`);
    el.appendChild(chip);
  }
}

function parseNfcUidFromPhysicalHash(physicalHash) {
  const s = (physicalHash || "").trim();
  if (s.toLowerCase().startsWith("nfc:uid:")) {
    return s.slice(8).trim();
  }
  return null;
}

async function navigateToTagByUid(uid) {
  if (!uid) return;
  setRoute("tags");
  if (!activeMasterPassword.trim()) return;
  const tags = await loadTagsList();
  const normalized = uid.toUpperCase();
  const tag = tags.find((t) => (t.uid || "").toUpperCase() === normalized);
  if (tag) selectTagFromList(tag);
}

function setInspectorTagDisplay(el, physicalHash) {
  if (!el) return;
  el.replaceChildren();
  const hash = (physicalHash || "").trim();
  if (!hash) {
    el.textContent = "—";
    return;
  }
  const uid = parseNfcUidFromPhysicalHash(hash);
  if (uid) {
    const link = document.createElement("button");
    link.type = "button";
    link.className = "tags-artwork-link";
    link.textContent = hash;
    link.setAttribute("aria-label", `View tag ${uid} in Tags`);
    link.addEventListener("click", () => {
      void navigateToTagByUid(uid);
    });
    el.appendChild(link);
  } else {
    el.textContent = hash;
  }
}

function setOptionalMetadataRow(rowId, ddEl, value) {
  const row = document.getElementById(rowId);
  if (!row || !ddEl) return;
  const v = (value || "").trim();
  row.hidden = !v;
  ddEl.textContent = v || "—";
}

async function loadInspectorDataUri(inputPath) {
  inspectorDataUriValue = "";
  try {
    const dataUrl = await invoke("load_image_data_url", { inputPath });
    inspectorDataUriValue = dataUrl || "";
  } catch (_) {
    inspectorDataUriValue = "";
  }
}

async function verifyInspectorPath(inputPath) {
  if (!ensureTauriAvailable()) return;
  if (!activeMasterPassword.trim()) {
    setInspectorFeedback("Unlock vault first to verify provenance.", "error");
    return;
  }
  const verifyToken = ++inspectorVerifyToken;
  startInspectorProgress("Checking provenance…");
  setInspectorFeedback("Verifying provenance...");
  inspectorTransferBtn.disabled = true;
  try {
    const result = await invoke("verify_image_with_vault", {
      masterPassword: activeMasterPassword,
      inputPath,
      threshold: 10
    });
    renderInspectorResult(inputPath, result);
    finishInspectorProgress(true, verifyToken);
    setInspectorFeedback("");
  } catch (error) {
    finishInspectorProgress(false, verifyToken);
    setInspectorFeedback(`Verification failed: ${String(error)}`, "error");
  }
}

function getPathFromDataTransfer(event) {
  const droppedFile = event.dataTransfer?.files?.[0];
  if (!droppedFile) return "";
  return getPathFromFile(droppedFile);
}

async function handleInspectorBrowse() {
  if (!ensureTauriAvailable()) return;
  try {
    const pickedPath = await invoke("pick_open_file_path", {
      title: "Select artwork to verify",
      extensions: ["jpg", "jpeg", "png", "webp", "tiff", "bmp"]
    });
    if (pickedPath) {
      await verifyInspectorPath(pickedPath);
    }
  } catch (error) {
    setInspectorFeedback(`Could not open file picker: ${String(error)}`, "error");
  }
}

function resetInspector(fromArtworks = false) {
  inspectorVerifyToken += 1;
  resetInspectorProgress();
  inspectorCurrentPath = "";
  inspectorLastVerification = null;
  inspectorDataUriValue = "";
  resetInspectorWatermarkState("");
  inspectorPreviewImage.src = "";
  inspectorTimeline.replaceChildren();
  inspectorDropzone.hidden = fromArtworks;
  inspectorResults.hidden = true;
  inspectorTransferBtn.disabled = true;
  if (inspectorMetadata) inspectorMetadata.hidden = true;
  setInspectorFeedback(fromArtworks ? "Verifying provenance..." : "");
}

async function executeTransfer() {
  if (!ensureTauriAvailable()) return;
  const contactId = transferRecipientSelect.value?.trim();
  if (!contactId) {
    setTransferModalFeedback("Select a recipient.", "error");
    return;
  }
  if (!inspectorCurrentPath) {
    setTransferModalFeedback("Verify an asset first.", "error");
    return;
  }
  transferConfirmBtn.disabled = true;
  transferConfirmBtn.textContent = "Transferring...";
  setTransferModalFeedback("Generating transfer manifest...");
  try {
    const transfer = await invoke("transfer_asset", {
      masterPassword: activeMasterPassword,
      request: {
        input_path: inspectorCurrentPath,
        recipient_contact_id: contactId
      }
    });
    closeTransferModal();
    await verifyInspectorPath(transfer.output_path);
    setInspectorFeedback("Transfer complete. Timeline updated with new owner.");
    await loadVaultDrafts(activeMasterPassword);
  } catch (error) {
    setTransferModalFeedback(`Transfer failed: ${String(error)}`, "error");
  } finally {
    transferConfirmBtn.disabled = false;
    transferConfirmBtn.textContent = "Confirm Transfer";
  }
}

function setStudioFeedback(message, tone = "") {
  studioFeedback.textContent = message;
  studioFeedback.classList.remove("error");
  if (tone === "error") {
    studioFeedback.classList.add("error");
  }
  if (message) showAppToast(message, tone);
}

function setStudioSealBusy(isBusy) {
  studioSealBusy = Boolean(isBusy);
  applyStudioBusyState();
}

function applyStudioBusyState() {
  const isBusy = studioSealBusy;
  studioSealBtn.disabled = isBusy;
  if (studioSaveDraftBtn) studioSaveDraftBtn.disabled = isBusy;
  if (studioClearBtn) studioClearBtn.disabled = isBusy;
  studioTitleInput.disabled = isBusy;
  studioAuthorInput.disabled = isBusy;
  studioDescriptionInput.disabled = isBusy;
  studioDateCreatedInput.disabled = isBusy;
  studioKeywordsInput.disabled = isBusy;
  studioGenreInput.disabled = isBusy;
  studioMaterialInput.disabled = isBusy;
  studioContributorInput.disabled = isBusy;
  studioLicenseInput.disabled = isBusy;
  studioAbstractInput.disabled = isBusy;
  studioTagSelect.disabled = isBusy;
  if (studioInvisibleWatermark) studioInvisibleWatermark.disabled = isBusy;
}

function setStudioState(mode) {
  const isDropzone = mode === "dropzone";
  const isActive = mode === "active";
  const isSuccess = mode === "success";
  studioDropzone.hidden = !isDropzone;
  studioActiveState.hidden = !isActive;
  studioSuccessState.hidden = !isSuccess;
}

function getBasename(filePath) {
  if (!filePath) return "";
  const normalized = filePath.replace(/\\/g, "/");
  const parts = normalized.split("/");
  return parts[parts.length - 1] || "";
}

function deriveTitleFromPath(filePath) {
  const basename = getBasename(filePath);
  if (!basename) return "";
  const dot = basename.lastIndexOf(".");
  const noExt = dot > 0 ? basename.slice(0, dot) : basename;
  return noExt.replace(/[_-]+/g, " ").trim();
}


function setStudioPreviewSource(src, isObjectUrl = false) {
  if (studioPreviewObjectUrl) {
    URL.revokeObjectURL(studioPreviewObjectUrl);
    studioPreviewObjectUrl = "";
  }
  if (isObjectUrl) {
    studioPreviewObjectUrl = src;
  }
  studioPreviewImage.src = src;
}

function normalizedLocalPath(path) {
  if (!path) return "";
  let normalized = String(path).trim().replace(/\\/g, "/");
  if (!normalized.startsWith("/")) {
    normalized = `/${normalized}`;
  }
  return normalized;
}

function encodeSourceUrl(url) {
  if (!url) return "";
  try {
    return encodeURI(url);
  } catch (_) {
    return url;
  }
}

/** In-memory cache for data URLs by file path so we don't re-fetch when the same image is shown again (e.g. Artworks grid scroll). */
const imageDataUrlCache = new Map();
const IMAGE_DATA_URL_CACHE_MAX = 80;

function buildImageSourceCandidates(path) {
  const raw = String(path || "").trim();
  if (!raw) return [];

  const hasScheme = /^[a-zA-Z][a-zA-Z0-9+\-.]*:\/\//.test(raw) || raw.startsWith("data:");
  if (hasScheme) return [raw];

  const candidates = [];
  if (typeof convertFileSrc === "function") {
    try {
      candidates.push(convertFileSrc(raw));
    } catch (_) {}
  }
  const normalized = normalizedLocalPath(raw);
  candidates.push(`https://asset.localhost${normalized}`);
  return [...new Set(candidates.filter(Boolean))];
}

function setImageWithFallback(imageEl, candidates, onFailure) {
  const list = Array.isArray(candidates) ? [...candidates] : [];
  if (!list.length) {
    if (onFailure) onFailure();
    return;
  }
  const next = () => {
    if (!list.length) {
      imageEl.onerror = null;
      if (onFailure) onFailure();
      return;
    }
    const src = list.shift();
    imageEl.onerror = next;
    imageEl.src = src;
  };
  next();
}

async function setImageFromPathRobust(imageEl, filePath, onErrorMessage) {
  const urlCandidates = buildImageSourceCandidates(filePath);
  setImageWithFallback(imageEl, urlCandidates, async () => {
    const cached = imageDataUrlCache.get(filePath);
    if (cached) {
      imageEl.onerror = null;
      imageEl.src = cached;
      return;
    }
    try {
      const dataUrl = await invoke("load_image_data_url", { inputPath: filePath });
      imageEl.onerror = null;
      imageEl.src = dataUrl;
      imageDataUrlCache.set(filePath, dataUrl);
      while (imageDataUrlCache.size > IMAGE_DATA_URL_CACHE_MAX) {
        const oldest = imageDataUrlCache.keys().next().value;
        if (oldest === undefined) break;
        imageDataUrlCache.delete(oldest);
      }
    } catch (_) {
      if (onErrorMessage) onErrorMessage();
    }
  });
}

function applySelectedStudioFile(filePath) {
  studioSelectedFilePath = filePath;
  setStudioPreviewSource("");
  setImageFromPathRobust(studioPreviewImage, filePath, () => {
    setStudioFeedback("Could not render artwork preview for this path.", "error");
  });
  studioTitleInput.value = deriveTitleFromPath(filePath);
  if (!studioAuthorInput.value.trim() && preferredAuthorName) {
    studioAuthorInput.value = preferredAuthorName;
  }
  setStudioFeedback("");
  setStudioState("active");
}

async function pickStudioFilePathViaDialog() {
  if (!ensureTauriAvailable()) return null;
  try {
    return await invoke("pick_open_file_path", {
      title: "Select artwork to seal",
      extensions: ["jpg", "jpeg", "png", "webp", "tiff", "bmp"]
    });
  } catch (error) {
    setStudioFeedback(`Could not open file picker: ${String(error)}`, "error");
    return null;
  }
}

function getPathFromFile(file) {
  if (!file) return "";
  if (typeof file.path === "string" && file.path.trim()) {
    return file.path;
  }
  if (typeof file.webkitRelativePath === "string" && file.webkitRelativePath.trim()) {
    return file.webkitRelativePath;
  }
  return "";
}

async function handleStudioBrowse() {
  const pickedPath = await pickStudioFilePathViaDialog();
  if (!pickedPath) return;
  applySelectedStudioFile(pickedPath);
}

async function processStudioFileSelection(file) {
  if (file) {
    setStudioPreviewSource(URL.createObjectURL(file), true);
    studioTitleInput.value = deriveTitleFromPath(file.name || "artwork");
    if (!studioAuthorInput.value.trim() && preferredAuthorName) {
      studioAuthorInput.value = preferredAuthorName;
    }
    setStudioState("active");
  }

  const filePath = getPathFromFile(file);
  if (filePath) {
    studioSelectedFilePath = filePath;
    setStudioFeedback("");
    return;
  }
  studioSelectedFilePath = "";
  setStudioFeedback(
    "Preview loaded. Local file path will be requested only when you seal.",
    ""
  );
}

function processStudioDropPath(path) {
  if (!path || typeof path !== "string") {
    setStudioFeedback("Dropped item is missing a readable local path.", "error");
    return;
  }
  applySelectedStudioFile(path);
}

async function handleSaveDraft() {
  if (!ensureTauriAvailable()) return;
  const title = studioTitleInput.value.trim();
  const author = studioAuthorInput.value.trim();
  const selectedTagId = studioTagSelect.value.trim();

  if (!activeMasterPassword.trim()) {
    setStudioFeedback("Master password is unavailable. Lock and unlock vault again.", "error");
    return;
  }
  if (!studioSelectedFilePath) {
    setStudioFeedback("Select a local file path to continue.", "error");
    const pickedPath = await pickStudioFilePathViaDialog();
    if (!pickedPath) {
      setStudioFeedback("A local file path is required to save a draft.", "error");
      return;
    }
    applySelectedStudioFile(pickedPath);
  }
  if (!title || !author) {
    setStudioFeedback("Title and Author are required.", "error");
    return;
  }

  setStudioSealBusy(true);
  studioSaveDraftBtn.textContent = "Saving...";

  try {
    const description = studioDescriptionInput.value.trim() || null;
    const dateCreated = studioDateCreatedInput.value.trim() || null;
    const license = studioLicenseInput.value.trim() || null;
    const keywords = studioKeywordsInput.value.trim() || null;
    const genre = studioGenreInput.value.trim() || null;
    const material = studioMaterialInput.value.trim() || null;
    const contributor = studioContributorInput.value.trim() || null;
    const abstractVal = studioAbstractInput.value.trim() || null;
    if (studioActiveDraftId != null) {
      await invoke("update_draft", {
        masterPassword: activeMasterPassword,
        draft: {
          draft_id: Number(studioActiveDraftId),
          artifact_title: title,
          author,
          description,
          date_created: dateCreated,
          license,
          keywords,
          genre,
          material,
          contributor,
          abstract: abstractVal,
          physical_hash: null,
          asset_path: studioSelectedFilePath
        }
      });
    } else {
      const newId = await invoke("save_draft", {
        masterPassword: activeMasterPassword,
        draft: {
          artifact_title: title,
          author,
          description,
          date_created: dateCreated,
          license,
          keywords,
          genre,
          material,
          contributor,
          abstract: abstractVal,
          physical_hash: null,
          draft_status: "draft",
          asset_path: studioSelectedFilePath
        }
      });
      studioActiveDraftId = newId;
    }
    setStudioFeedback("Draft saved to vault. You can seal it now or later from Artworks.");
    await loadVaultDrafts(activeMasterPassword);
  } catch (error) {
    setStudioFeedback(`Save failed: ${String(error)}`, "error");
  } finally {
    setStudioSealBusy(false);
    studioSaveDraftBtn.textContent = "Save as Draft";
  }
}

async function handleSealAndSave() {
  if (!ensureTauriAvailable()) return;
  const title = studioTitleInput.value.trim();
  const author = studioAuthorInput.value.trim();
  const selectedTagId = studioTagSelect.value.trim();

  if (!activeMasterPassword.trim()) {
    setStudioFeedback("Master password is unavailable. Lock and unlock vault again.", "error");
    return;
  }
  const hasActiveIdentity = await ensureActiveIdentityForSealing();
  if (!hasActiveIdentity) {
    return;
  }
  if (!studioSelectedFilePath) {
    setStudioFeedback("Select a local file path to continue sealing...");
    const pickedPath = await pickStudioFilePathViaDialog();
    if (!pickedPath) {
      setStudioFeedback("A local file path is required to seal this artwork.", "error");
      return;
    }
    applySelectedStudioFile(pickedPath);
  }
  if (!title || !author) {
    setStudioFeedback("Title and Author are required.", "error");
    return;
  }

  setStudioSealBusy(true);
  studioSealBtn.textContent = "Sealing...";
  setStudioFeedback("Saving draft and generating perceptual fingerprint...");

  try {
    let draftId = studioActiveDraftId;
    const description = studioDescriptionInput.value.trim() || null;
    const dateCreated = studioDateCreatedInput.value.trim() || null;
    const license = studioLicenseInput.value.trim() || null;
    const keywords = studioKeywordsInput.value.trim() || null;
    const genre = studioGenreInput.value.trim() || null;
    const material = studioMaterialInput.value.trim() || null;
    const contributor = studioContributorInput.value.trim() || null;
    const abstractVal = studioAbstractInput.value.trim() || null;
    if (draftId != null) {
      await invoke("update_draft", {
        masterPassword: activeMasterPassword,
        draft: {
          draft_id: Number(draftId),
          artifact_title: title,
          author,
          description,
          date_created: dateCreated,
          license,
          keywords,
          genre,
          material,
          contributor,
          abstract: abstractVal,
          physical_hash: null,
          asset_path: studioSelectedFilePath
        }
      });
    } else {
      draftId = await invoke("save_draft", {
        masterPassword: activeMasterPassword,
        draft: {
          artifact_title: title,
          author,
          description,
          date_created: dateCreated,
          license,
          keywords,
          genre,
          material,
          contributor,
          abstract: abstractVal,
          physical_hash: null,
          draft_status: "draft",
          asset_path: studioSelectedFilePath
        }
      });
      studioActiveDraftId = draftId;
    }

    setStudioFeedback("Sealing artifact...");
    const invisibleWatermark = Boolean(studioInvisibleWatermark?.checked);
    const sealResult = await invoke("sign_image_from_vault", {
      masterPassword: activeMasterPassword,
      request: {
        input_path: studioSelectedFilePath,
        draft_id: Number(draftId),
        tag_id: selectedTagId ? Number(selectedTagId) : null,
        invisible_watermark: invisibleWatermark
      }
    });

    studioManifestId.textContent = String(sealResult.manifest_id);
    if (sealResult?.ipfs_cid && studioIpfsWarning && studioIpfsOriginalPath) {
      studioIpfsWarning.hidden = false;
      studioIpfsOriginalPath.textContent = sealResult.input_path || studioSelectedFilePath || "";
    } else if (studioIpfsWarning) {
      studioIpfsWarning.hidden = true;
    }
    if (studioTagWriteHint) studioTagWriteHint.hidden = !selectedTagId;
    setStudioState("success");
    await loadVaultDrafts(activeMasterPassword);
    await loadStudioTagOptions();
  } catch (error) {
    const rawError = String(error);
    if (rawError.includes("Failed to load signing certificate or key")) {
      const diagnostics = await getIdentitySigningDiagnostics();
      setStudioFeedback(`Sealing failed: ${rawError}${diagnostics}`, "error");
    } else {
      setStudioFeedback(`Sealing failed: ${rawError}`, "error");
    }
  } finally {
    setStudioSealBusy(false);
    studioSealBtn.textContent = "Seal Artwork";
  }
}

function identityIsActive(identity) {
  return Boolean(identity?.is_active);
}

function identityHasCertificateChain(identity) {
  return Boolean(identity?.has_certificate_chain);
}

async function getIdentitySigningDiagnostics() {
  try {
    const identities = await invoke("list_identities", { masterPassword: activeMasterPassword });
    if (!Array.isArray(identities) || identities.length === 0) {
      return " No identities found in vault.";
    }
    const active = identities.find(identityIsActive) || null;
    const certReadyCount = identities.filter(identityHasCertificateChain).length;
    if (!active) {
      return ` No active identity selected. Profiles with certificate chain: ${certReadyCount}/${identities.length}.`;
    }
    const activeName = active.common_name || `#${active.id}`;
    const hasChain = identityHasCertificateChain(active);
    return ` Active profile: ${activeName}. Certificate chain present: ${hasChain ? "yes" : "no"}. Profiles with certificate chain: ${certReadyCount}/${identities.length}.`;
  } catch {
    return "";
  }
}

async function ensureActiveIdentityForSealing() {
  try {
    const identities = await invoke("list_identities", { masterPassword: activeMasterPassword });
    if (!Array.isArray(identities) || identities.length === 0) {
      setStudioFeedback("No creator profile found. Create one in Settings before sealing.", "error");
      setRoute("settings");
      return false;
    }

    const activeIdentity = identities.find(identityIsActive);
    if (identityHasCertificateChain(activeIdentity)) {
      await refreshStudioSigningMode();
      return true;
    }

    const certReadyIdentity = identities.find(identityHasCertificateChain);
    if (certReadyIdentity) {
      await invoke("set_active_identity", {
        masterPassword: activeMasterPassword,
        identityId: Number(certReadyIdentity.id)
      });
      preferredAuthorName = certReadyIdentity.common_name || preferredAuthorName;
      setStudioFeedback(`Using profile: ${certReadyIdentity.common_name || `#${certReadyIdentity.id}`}.`);
      await refreshSettingsProfile(activeMasterPassword);
      await refreshStudioSigningMode();
      return true;
    }

    const fallbackIdentity = identities[0];
    await invoke("set_active_identity", {
      masterPassword: activeMasterPassword,
      identityId: Number(fallbackIdentity.id)
    });
    setStudioFeedback(
      "Active profile has no signing certificate chain. Open Settings to create a new profile or upgrade one.",
      "error"
    );
    setRoute("settings");
    await refreshSettingsProfile(activeMasterPassword);
    await refreshStudioSigningMode();
    return false;
  } catch (error) {
    setStudioFeedback(`Identity check failed: ${String(error)}`, "error");
    return false;
  }
}

function resetStudio() {
  studioSelectedFilePath = "";
  studioActiveDraftId = null;
  studioSealBusy = false;
  applyStudioBusyState();
  setStudioPreviewSource("");
  studioTitleInput.value = "";
  studioAuthorInput.value = preferredAuthorName || "";
  studioDescriptionInput.value = "";
  studioDateCreatedInput.value = "";
  studioKeywordsInput.value = "";
  studioGenreInput.value = "";
  studioMaterialInput.value = "";
  studioContributorInput.value = "";
  studioLicenseInput.value = "";
  studioAbstractInput.value = "";
  studioTagSelect.value = "";
  if (studioInvisibleWatermark) studioInvisibleWatermark.checked = false;
  setStudioSigningMode("");
  studioManifestId.textContent = "";
  if (studioIpfsWarning) studioIpfsWarning.hidden = true;
  if (studioIpfsOriginalPath) studioIpfsOriginalPath.textContent = "";
  setStudioFeedback("");
  setStudioState("dropzone");
}

function resetSettings() {
  if (!settingsDomReady) return;
  settingsActiveIdentity = null;
  settingsIdentityList = [];
  settingsCreateProfileForm.hidden = true;
  settingsCreateProfileToggleBtn.textContent = "Create New Identity";
  settingsAdvancedPanel.hidden = true;
  settingsAdvancedToggleBtn.textContent = "Show Integration";
  settingsProfileNameInput.value = "";
  settingsProfileOrgInput.value = "";
  settingsProfileCountryInput.value = "";
  settingsCsrNameInput.value = "";
  settingsCsrOrgInput.value = "";
  settingsCsrCountryInput.value = "";
  settingsCsrOutputPathInput.value = "";
  settingsCaChainPathInput.value = "";
  settingsIdentitySelect.replaceChildren();
  settingsIdentitySelect.disabled = true;
  settingsSetActiveBtn.disabled = true;
  if (settingsDeleteIdentityBtn) settingsDeleteIdentityBtn.disabled = true;
  setSettingsFeedback(settingsProfileFeedback, "");
  setSettingsFeedback(settingsBackupFeedback, "");
  setSettingsFeedback(settingsAdvancedFeedback, "");
  renderActiveSettingsIdentity(null);
}

navTabs.forEach((tab) => {
  tab.addEventListener("click", () => {
    const route = tab.dataset.route;
    if (route) setRoute(route);
  });
});

const lockVaultBtn = document.getElementById("lockVaultBtn");
if (lockVaultBtn) {
  lockVaultBtn.addEventListener("click", () => lockVault());
}
if (sidebarIdentityNudge) {
  sidebarIdentityNudge.addEventListener("click", () => setRoute("settings"));
}

const deleteModalBackdrop = document.getElementById("deleteModalBackdrop");
const deleteCancelBtn = document.getElementById("deleteCancelBtn");
const deleteConfirmBtn = document.getElementById("deleteConfirmBtn");
if (deleteModalBackdrop) {
  deleteModalBackdrop.addEventListener("click", (event) => {
    if (event.target === deleteModalBackdrop) closeDeleteModal();
  });
}
if (deleteCancelBtn) {
  deleteCancelBtn.addEventListener("click", closeDeleteModal);
}
if (deleteConfirmBtn) {
  deleteConfirmBtn.addEventListener("click", handleDeleteConfirm);
}

unlockBtn.addEventListener("click", unlockVault);
initVaultBtn.addEventListener("click", initializeVault);
if (restoreVaultBtn) restoreVaultBtn.addEventListener("click", handleRestoreVault);
registerArtworkBtn.addEventListener("click", onRegisterArtworkClick);
registerFirstArtworkBtn.addEventListener("click", onRegisterArtworkClick);
studioBrowseBtn.addEventListener("click", handleStudioBrowse);
if (tagsClearBtn) tagsClearBtn.addEventListener("click", resetTags);
if (tagsScanBtn) tagsScanBtn.addEventListener("click", handleTagsScan);
if (tagsScanEmptyBtn) tagsScanEmptyBtn.addEventListener("click", handleTagsScan);
if (tagsRescanBtn) tagsRescanBtn.addEventListener("click", handleTagsScan);
if (tagsResetTagBtn) tagsResetTagBtn.addEventListener("click", handleTagsResetTag);
if (tagsEnrollBtn) tagsEnrollBtn.addEventListener("click", handleTagsEnroll);
if (tagsVerificationUrlInput) {
  tagsVerificationUrlInput.addEventListener("input", updateTagsUrlPreview);
  tagsVerificationUrlInput.addEventListener("change", updateTagsUrlPreview);
}
if (tagsContentUrlInput) {
  tagsContentUrlInput.addEventListener("input", updateTagsUrlPreview);
  tagsContentUrlInput.addEventListener("change", updateTagsUrlPreview);
}
let tagsNotesSaveTimeout = null;
function scheduleTagsNotesSave() {
  if (tagsNotesSaveTimeout) clearTimeout(tagsNotesSaveTimeout);
  tagsNotesSaveTimeout = setTimeout(saveTagsNotes, 500);
}
async function saveTagsNotes() {
  tagsNotesSaveTimeout = null;
  if (!tagsNotesInput || !ensureTauriAvailable() || !activeMasterPassword?.trim()) return;
  const tagId = tagsNotesInput.dataset?.tagId ? Number(tagsNotesInput.dataset.tagId) : null;
  if (!tagId || !Number.isFinite(tagId)) return;
  const notes = tagsNotesInput.value?.trim() || null;
  try {
    const updated = await invoke("update_tag_notes", {
      masterPassword: activeMasterPassword,
      request: { tagId, notes: notes || undefined },
    });
    if (tagsCurrentTag?.id === tagId) tagsCurrentTag.notes = updated?.notes ?? notes;
    const card = tagsListGrid?.querySelector(`[data-tag-id="${tagId}"]`);
    if (card) updateTagCardNotes(card, notes);
  } catch (e) {
    setTagsFeedback(`Could not save notes: ${String(e)}`, "error");
  }
}
if (tagsNotesInput) {
  tagsNotesInput.addEventListener("input", scheduleTagsNotesSave);
  tagsNotesInput.addEventListener("blur", () => {
    if (tagsNotesSaveTimeout) {
      clearTimeout(tagsNotesSaveTimeout);
      tagsNotesSaveTimeout = null;
      void saveTagsNotes();
    }
  });
}
if (tagsRotateKeysBtn) tagsRotateKeysBtn.addEventListener("click", handleTagsRotateKeys);
if (tagsClaimBtn) tagsClaimBtn.addEventListener("click", handleTagsClaim);
if (tagsReleaseBtn) tagsReleaseBtn.addEventListener("click", handleTagsRelease);
if (tagsRewriteBtn) tagsRewriteBtn.addEventListener("click", handleTagsRewrite);
if (tagsPendingWriteBtn) tagsPendingWriteBtn.addEventListener("click", handleTagsRewrite);
if (tagsLinkArtworkBtn) tagsLinkArtworkBtn.addEventListener("click", handleLinkArtwork);
studioFileInput.addEventListener("change", async (event) => {
  const file = event.target.files?.[0];
  if (!file) return;
  await processStudioFileSelection(file);
});
studioDropzone.addEventListener("dragover", (event) => {
  event.preventDefault();
  studioDropzone.classList.add("is-dragover");
});
studioDropzone.addEventListener("dragleave", () => {
  studioDropzone.classList.remove("is-dragover");
});
studioDropzone.addEventListener("drop", async (event) => {
  event.preventDefault();
  studioDropzone.classList.remove("is-dragover");
  const droppedFile = event.dataTransfer?.files?.[0];
  if (droppedFile) {
    const droppedPath = getPathFromFile(droppedFile);
    if (droppedPath) {
      processStudioDropPath(droppedPath);
      return;
    }
    await processStudioFileSelection(droppedFile);
    return;
  }
  const pickedPath = await pickStudioFilePathViaDialog();
  if (pickedPath) {
    processStudioDropPath(pickedPath);
  }
});
studioSealBtn.addEventListener("click", handleSealAndSave);
if (studioSaveDraftBtn) studioSaveDraftBtn.addEventListener("click", handleSaveDraft);
if (studioClearBtn) studioClearBtn.addEventListener("click", resetStudio);
studioSealAnotherBtn.addEventListener("click", resetStudio);
studioViewInVaultBtn.addEventListener("click", async () => {
  setRoute("vault");
  if (activeMasterPassword.trim()) {
    await loadVaultDrafts(activeMasterPassword);
  }
});
inspectorBrowseBtn.addEventListener("click", handleInspectorBrowse);
if (inspectorClearBtn) inspectorClearBtn.addEventListener("click", () => resetInspector());
function copyInspectorDataUri(linkEl) {
  const val = inspectorDataUriValue?.trim();
  if (!val) return;
  navigator.clipboard.writeText(val).then(
    () => { if (linkEl) { linkEl.textContent = "copied!"; setTimeout(() => { linkEl.textContent = "copy base64 data URI"; }, 1500); } },
    () => { if (linkEl) { linkEl.textContent = "copy failed"; setTimeout(() => { linkEl.textContent = "copy base64 data URI"; }, 1500); } }
  );
}
if (inspectorCopyDataUriLink) {
  inspectorCopyDataUriLink.addEventListener("click", (e) => {
    e.preventDefault();
    copyInspectorDataUri(inspectorCopyDataUriLink);
  });
}
inspectorDropzone.addEventListener("dragover", (event) => {
  event.preventDefault();
  inspectorDropzone.classList.add("is-dragover");
});
inspectorDropzone.addEventListener("dragleave", () => {
  inspectorDropzone.classList.remove("is-dragover");
});
inspectorDropzone.addEventListener("drop", async (event) => {
  event.preventDefault();
  inspectorDropzone.classList.remove("is-dragover");
  const droppedPath = getPathFromDataTransfer(event);
  if (droppedPath) {
    await verifyInspectorPath(droppedPath);
    return;
  }
  const pickedPath = await pickStudioFilePathViaDialog();
  if (pickedPath) {
    await verifyInspectorPath(pickedPath);
  }
});
inspectorTransferBtn.addEventListener("click", openTransferModal);
if (contactsImportBtn) contactsImportBtn.addEventListener("click", handleImportContact);
setupContactsSignedMessages();
transferCancelBtn.addEventListener("click", closeTransferModal);
if (changePasswordModalBackdrop) {
  changePasswordModalBackdrop.addEventListener("click", (event) => {
    if (event.target === changePasswordModalBackdrop) closeChangePasswordModal();
  });
}
if (changePasswordCancelBtn) changePasswordCancelBtn.addEventListener("click", closeChangePasswordModal);
if (changePasswordConfirmBtn) changePasswordConfirmBtn.addEventListener("click", handleChangePasswordConfirm);
transferModalBackdrop.addEventListener("click", (event) => {
  if (event.target === transferModalBackdrop) {
    closeTransferModal();
  }
});
transferConfirmBtn.addEventListener("click", executeTransfer);
if (settingsDomReady) {
  settingsCreateProfileToggleBtn.addEventListener("click", toggleCreateProfileForm);
  settingsCreateProfileForm.addEventListener("submit", handleCreateProfileSubmit);
  settingsSetActiveBtn.addEventListener("click", handleSetActiveProfile);
  if (settingsDeleteIdentityBtn) {
    settingsDeleteIdentityBtn.addEventListener("click", handleDeleteIdentity);
  }
  if (settingsExportCertBtn) {
    settingsExportCertBtn.addEventListener("click", handleExportCert);
  }
  settingsExportBackupBtn.addEventListener("click", handleExportBackup);
  if (settingsExportVaultBtn) settingsExportVaultBtn.addEventListener("click", handleExportVault);
  if (settingsChangePasswordBtn) settingsChangePasswordBtn.addEventListener("click", openChangePasswordModal);
  settingsAdvancedToggleBtn.addEventListener("click", toggleAdvancedSettings);
  settingsBrowseCsrBtn.addEventListener("click", handleBrowseCsrPath);
  settingsGenerateCsrBtn.addEventListener("click", handleGenerateCsr);
  settingsBrowseCaBtn.addEventListener("click", handleBrowseCaChainPath);
  settingsUpgradeCaBtn.addEventListener("click", handleUpgradeCa);
}
masterPasswordInput.addEventListener("keydown", (event) => {
  if (event.key !== "Enter") return;
  if (lockMode === "welcome") {
    initializeVault();
    return;
  }
  unlockVault();
});
confirmPasswordInput.addEventListener("keydown", (event) => {
  if (event.key !== "Enter") return;
  if (lockMode === "welcome") {
    initializeVault();
  }
});

function bootApp() {
  try {
    resetStudio();
    resetInspector();
    resetTags(true);
    resetSettings();
    refreshVaultLocationCopy();
    checkBootState();
    setupTauriDragDrop();
  } catch (error) {
    setLockedState();
    setLockMode("unlock");
    setLockMessage(`Startup error: ${String(error)}`, "error");
  }
}

if (document.readyState === "loading") {
  document.addEventListener("DOMContentLoaded", bootApp, { once: true });
} else {
  bootApp();
}
