diff --git a/PlotLine/Controllers/WordCompanionController.cs b/PlotLine/Controllers/WordCompanionController.cs index 95d41db..75e864d 100644 --- a/PlotLine/Controllers/WordCompanionController.cs +++ b/PlotLine/Controllers/WordCompanionController.cs @@ -102,6 +102,13 @@ public sealed class WordCompanionController(IWordCompanionService wordCompanion) return response is null ? BadRequest() : Ok(response); } + [HttpGet("runtime/book/{bookId:int}")] + public async Task GetRuntimeBook(int bookId, [FromQuery] Guid documentGuid) + { + var response = await wordCompanion.GetRuntimeBookAsync(bookId, documentGuid); + return response is null ? NotFound() : Ok(response); + } + [HttpGet("manuscript/book/{bookId:int}")] public async Task GetManuscriptForBook(int bookId) { diff --git a/PlotLine/Models/WordCompanionApiModels.cs b/PlotLine/Models/WordCompanionApiModels.cs index 59d7889..27972fb 100644 --- a/PlotLine/Models/WordCompanionApiModels.cs +++ b/PlotLine/Models/WordCompanionApiModels.cs @@ -238,6 +238,18 @@ public sealed class WordCompanionManuscriptBookResponse public WordCompanionManuscriptDocumentDto? ManuscriptDocument { get; init; } } +public sealed class WordCompanionRuntimeBookResponse +{ + public int ProjectId { get; init; } + public string ProjectTitle { get; init; } = string.Empty; + public int BookId { get; init; } + public string BookTitle { get; init; } = string.Empty; + public string? BookSubtitle { get; init; } + public bool UsesExplicitScenes { get; init; } + public DateTime? LastSyncUtc { get; init; } + public WordCompanionManuscriptDocumentDto ManuscriptDocument { get; init; } = new(); +} + public sealed class WordCompanionManuscriptLinkRequest { public int BookId { get; set; } diff --git a/PlotLine/Services/WordCompanionService.cs b/PlotLine/Services/WordCompanionService.cs index 5f4ecd5..d8f0f57 100644 --- a/PlotLine/Services/WordCompanionService.cs +++ b/PlotLine/Services/WordCompanionService.cs @@ -19,6 +19,7 @@ public interface IWordCompanionService Task SyncManuscriptAsync(int bookId, WordCompanionSyncManuscriptRequest request); Task UpdateSceneLinksAsync(int sceneId, WordCompanionUpdateSceneLinksRequest request); Task UpdateWordCountAsync(int sceneId, WordCompanionUpdateWordCountRequest request); + Task GetRuntimeBookAsync(int bookId, Guid documentGuid); Task GetManuscriptForBookAsync(int bookId); Task LinkManuscriptAsync(WordCompanionManuscriptLinkRequest request); Task AnalyseManuscriptAsync(WordCompanionManuscriptAnalyseRequest request); @@ -221,6 +222,50 @@ public sealed class WordCompanionService( : repository.UpdateWordCountAsync(sceneId, RequireUserId(), actualWords.Value, request.LastWorkedOn); } + public async Task GetRuntimeBookAsync(int bookId, Guid documentGuid) + { + if (bookId <= 0 || documentGuid == Guid.Empty) + { + return null; + } + + var userId = RequireUserId(); + var document = await manuscriptDocuments.GetByGuidAsync(documentGuid, userId); + if (document is null || document.BookID != bookId || !document.IsActive) + { + return null; + } + + await manuscriptDocuments.UpdateLastOpenedAsync(document.ManuscriptDocumentID, userId); + document = await manuscriptDocuments.GetByGuidAsync(documentGuid, userId) ?? document; + + var projects = await repository.ListProjectsAsync(userId); + var project = projects.FirstOrDefault(item => item.ProjectId == document.ProjectID); + if (project is null) + { + return null; + } + + var books = await repository.ListBooksAsync(document.ProjectID, userId); + var book = books.FirstOrDefault(item => item.BookId == document.BookID); + if (book is null) + { + return null; + } + + return new WordCompanionRuntimeBookResponse + { + ProjectId = project.ProjectId, + ProjectTitle = project.Title, + BookId = book.BookId, + BookTitle = book.Title, + BookSubtitle = book.Subtitle, + UsesExplicitScenes = book.UsesExplicitScenes, + LastSyncUtc = document.LastSyncUtc, + ManuscriptDocument = ToDto(document) + }; + } + public async Task GetManuscriptForBookAsync(int bookId) { if (bookId <= 0) diff --git a/PlotLine/Views/WordCompanionHost/Index.cshtml b/PlotLine/Views/WordCompanionHost/Index.cshtml index 997c952..d787d4a 100644 --- a/PlotLine/Views/WordCompanionHost/Index.cshtml +++ b/PlotLine/Views/WordCompanionHost/Index.cshtml @@ -154,6 +154,10 @@ Revision - +
+ Last Sync + - +
Blocked - diff --git a/PlotLine/wwwroot/js/word-companion-host.js b/PlotLine/wwwroot/js/word-companion-host.js index df2de88..0ad06ac 100644 --- a/PlotLine/wwwroot/js/word-companion-host.js +++ b/PlotLine/wwwroot/js/word-companion-host.js @@ -74,6 +74,7 @@ const plotDirectorBlockedStatus = document.querySelector("[data-plotdirector-blocked-status]"); const plotDirectorBlockedReasonRow = document.querySelector("[data-plotdirector-blocked-reason-row]"); const plotDirectorBlockedReason = document.querySelector("[data-plotdirector-blocked-reason]"); + const runtimeLastSync = document.querySelector("[data-runtime-last-sync]"); const syncSceneProgressButton = document.querySelector("[data-sync-scene-progress]"); const syncWordCount = document.querySelector("[data-sync-word-count]"); const syncPlotDirectorCount = document.querySelector("[data-sync-plotdirector-count]"); @@ -177,6 +178,10 @@ let pendingCreateChapterConfirmation = null; let structurePreviewModel = null; let firstRunDocumentBinding = null; + let runtimeBookContext = null; + let documentStructureCache = null; + let plotDirectorStructureCache = null; + let plotDirectorStructureBookId = null; let firstRunAnalysis = null; let firstRunImportStructure = null; let firstRunCharacterCandidatesModel = []; @@ -467,6 +472,33 @@ return String(value); }; + const formatDateTime = (value) => { + if (!value) { + return "-"; + } + + const date = new Date(value); + return Number.isNaN(date.getTime()) ? "-" : date.toLocaleString(); + }; + + const setRuntimeBookContext = (context) => { + runtimeBookContext = context || null; + setText(runtimeLastSync, formatDateTime(runtimeBookContext?.lastSyncUtc || runtimeBookContext?.manuscriptDocument?.lastSyncUtc)); + setText(syncLastSynced, formatDateTime(runtimeBookContext?.lastSyncUtc || runtimeBookContext?.manuscriptDocument?.lastSyncUtc)); + }; + + const clearRuntimeCaches = () => { + documentStructureCache = null; + plotDirectorStructureCache = null; + plotDirectorStructureBookId = null; + setRuntimeBookContext(null); + }; + + const clearPlotDirectorStructureCache = () => { + plotDirectorStructureCache = null; + plotDirectorStructureBookId = null; + }; + const setSceneLinksStatus = (message) => { setText(sceneLinksStatus, message); }; @@ -755,7 +787,13 @@ }; const getBookStructureChapters = async (bookId) => { + if (plotDirectorStructureBookId === bookId && Array.isArray(plotDirectorStructureCache?.chapters)) { + return plotDirectorStructureCache.chapters; + } + const structure = await fetchJson(`/api/word-companion/books/${bookId}/structure`); + plotDirectorStructureBookId = bookId; + plotDirectorStructureCache = structure || null; return Array.isArray(structure?.chapters) ? structure.chapters : []; }; @@ -1405,6 +1443,191 @@ }; }; + const sceneSeparatorTexts = new Set(["***", "###"]); + + const snapshotParagraph = (paragraph, index) => { + const text = String(paragraph?.text || "").trim(); + return { + index, + text, + styleBuiltIn: paragraph?.styleBuiltIn || "", + style: paragraph?.style || "", + wordCount: countWords(text), + chapterAnchorId: paragraphAnchorId(paragraph, "PD-CHAPTER"), + sceneAnchorId: paragraphAnchorId(paragraph, "PD-SCENE") + }; + }; + + const finishRuntimeScene = (scene, endIndex) => { + if (scene) { + scene.endParagraphIndex = endIndex; + } + }; + + const finishRuntimeChapter = (chapter, endIndex) => { + if (chapter) { + chapter.endParagraphIndex = endIndex; + finishRuntimeScene(chapter.scenes.at(-1), endIndex); + } + }; + + const buildRuntimeDocumentStructure = (paragraphs, usesExplicitScenes) => { + const paragraphSnapshots = paragraphs.map(snapshotParagraph); + const chapters = []; + let heading1Count = 0; + let sceneBoundaryCount = 0; + let chapter = null; + let scene = null; + let documentWordCount = 0; + + const startScene = (startParagraph, title = null, anchorId = null) => { + if (!chapter) { + return null; + } + + finishRuntimeScene(scene, startParagraph.index - 1); + scene = { + index: chapter.scenes.length + 1, + paragraphIndex: startParagraph.index, + startParagraphIndex: startParagraph.index, + endParagraphIndex: startParagraph.index, + title: title || `Scene ${chapter.scenes.length + 1}`, + anchorId, + wordCount: 0 + }; + chapter.scenes.push(scene); + return scene; + }; + + for (const paragraph of paragraphSnapshots) { + if (!paragraph.text) { + continue; + } + + if (isBuiltInHeading(paragraph, 1)) { + finishRuntimeChapter(chapter, paragraph.index - 1); + heading1Count += 1; + chapter = { + index: chapters.length + 1, + paragraphIndex: paragraph.index, + startParagraphIndex: paragraph.index, + endParagraphIndex: paragraph.index, + title: paragraph.text, + anchorId: paragraph.chapterAnchorId, + wordCount: 0, + scenes: [] + }; + chapters.push(chapter); + scene = null; + startScene(paragraph, usesExplicitScenes ? "Scene 1" : "Scene 1", paragraph.sceneAnchorId); + documentWordCount += paragraph.wordCount; + continue; + } + + if (!chapter) { + continue; + } + + if (usesExplicitScenes && sceneSeparatorTexts.has(paragraph.text)) { + sceneBoundaryCount += 1; + startScene(paragraph); + continue; + } + + chapter.wordCount += paragraph.wordCount; + if (scene) { + scene.wordCount += paragraph.wordCount; + } + documentWordCount += paragraph.wordCount; + } + + finishRuntimeChapter(chapter, paragraphSnapshots.length - 1); + + return { + paragraphs: paragraphSnapshots, + chapters, + usesExplicitScenes: !!usesExplicitScenes, + paragraphCount: paragraphSnapshots.length, + heading1Count, + heading2Count: sceneBoundaryCount, + documentWordCount, + currentParagraphIndex: null, + currentChapter: null, + currentScene: null + }; + }; + + const paragraphMatchesSnapshot = (snapshot, paragraph) => { + return String(snapshot?.text || "").trim() === String(paragraph?.text || "").trim() + && normalizedStyleName(snapshot) === normalizedStyleName(paragraph); + }; + + const findSelectedParagraphIndex = (cache, selectionParagraphs) => { + const selectedParagraph = (selectionParagraphs || []).find((paragraph) => String(paragraph.text || "").trim()); + if (!cache || !selectedParagraph) { + return cache?.currentParagraphIndex ?? -1; + } + + const matches = cache.paragraphs + .filter((paragraph) => paragraphMatchesSnapshot(paragraph, selectedParagraph)) + .map((paragraph) => paragraph.index); + if (matches.length === 0) { + return cache.currentParagraphIndex ?? -1; + } + if (!Number.isInteger(cache.currentParagraphIndex)) { + return matches[0]; + } + + return matches.reduce((best, candidate) => + Math.abs(candidate - cache.currentParagraphIndex) < Math.abs(best - cache.currentParagraphIndex) ? candidate : best, matches[0]); + }; + + const chapterForParagraphIndex = (cache, paragraphIndex) => { + if (!cache || !Number.isInteger(paragraphIndex) || paragraphIndex < 0) { + return null; + } + + return cache.chapters + .filter((chapter) => chapter.startParagraphIndex <= paragraphIndex) + .at(-1) || null; + }; + + const sceneForParagraphIndex = (chapter, paragraphIndex) => { + if (!chapter || !Number.isInteger(paragraphIndex) || paragraphIndex < 0) { + return null; + } + + return chapter.scenes + .filter((item) => item.startParagraphIndex <= paragraphIndex) + .at(-1) || null; + }; + + const applyRuntimeSelection = (paragraphIndex) => { + if (!documentStructureCache) { + return false; + } + + const currentChapterItem = chapterForParagraphIndex(documentStructureCache, paragraphIndex); + const currentSceneItem = sceneForParagraphIndex(currentChapterItem, paragraphIndex); + const changed = currentChapterItem?.paragraphIndex !== documentStructureCache.currentChapter?.paragraphIndex + || currentSceneItem?.paragraphIndex !== documentStructureCache.currentScene?.paragraphIndex; + + documentStructureCache.currentParagraphIndex = paragraphIndex; + documentStructureCache.currentChapter = currentChapterItem; + documentStructureCache.currentScene = currentSceneItem; + + setCurrentStructure( + currentChapterItem?.title, + currentSceneItem?.title, + currentSceneItem?.wordCount, + currentChapterItem?.anchorId, + currentSceneItem?.anchorId, + currentChapterItem?.index + ); + + return changed; + }; + const renderOutline = (structure) => { if (!documentOutline) { return; @@ -1828,6 +2051,35 @@ return structure; }; + const readRuntimeDocumentStructure = async (context, usesExplicitScenes) => { + const bodyParagraphs = context.document.body.paragraphs; + const selectionParagraphs = context.document.getSelection().paragraphs; + + bodyParagraphs.load("text,styleBuiltIn,style"); + selectionParagraphs.load("text,styleBuiltIn,style"); + await context.sync(); + + for (const paragraph of bodyParagraphs.items) { + if (isBuiltInHeading(paragraph, 1)) { + paragraph.contentControls.load("items/tag,title"); + } + } + await context.sync(); + + const cache = buildRuntimeDocumentStructure(bodyParagraphs.items, usesExplicitScenes); + const selectedIndex = findSelectedParagraphIndex(cache, selectionParagraphs.items); + documentStructureCache = cache; + applyRuntimeSelection(selectedIndex); + return cache; + }; + + const readSelectionParagraphs = async (context) => { + const selectionParagraphs = context.document.getSelection().paragraphs; + selectionParagraphs.load("text,styleBuiltIn,style"); + await context.sync(); + return selectionParagraphs.items; + }; + const refreshDocumentStructure = async () => { setDocumentMessage(""); @@ -1846,17 +2098,25 @@ try { const structure = await window.Word.run(async (context) => { + const runtimeBook = selectedBook(); + if (runtimeBook) { + return await readRuntimeDocumentStructure(context, !!runtimeBook.usesExplicitScenes); + } + + documentStructureCache = null; return await readDocumentStructure(context); }); - setCurrentStructure( - structure.currentChapter?.title, - structure.currentScene?.title, - structure.currentScene?.wordCount, - structure.currentChapter?.anchorId, - structure.currentScene?.anchorId, - structure.currentChapter?.index - ); + if (!documentStructureCache) { + setCurrentStructure( + structure.currentChapter?.title, + structure.currentScene?.title, + structure.currentScene?.wordCount, + structure.currentChapter?.anchorId, + structure.currentScene?.anchorId, + structure.currentChapter?.index + ); + } resetPlotDirectorScene("Not detected"); renderOutline(structure); setDocumentMessage(""); @@ -2028,6 +2288,7 @@ throw new Error("Chapter creation did not return a chapter ID."); } + clearPlotDirectorStructureCache(); item.pdChapter = { chapterId: response.chapterId, title: response.title || item.wordTitle, @@ -2052,6 +2313,7 @@ throw new Error("Scene creation did not return a scene ID."); } + clearPlotDirectorStructureCache(); item.pdChapter = chapter; item.pdScene = { sceneId: response.sceneId, @@ -2188,6 +2450,7 @@ isApplyingStructureSync = false; setAnalyseButtonEnabled(); if (finalStatus) { + clearPlotDirectorStructureCache(); await analyseManuscriptStructure(); setStructurePreviewStatus(`${finalStatus} Preview refreshed.`); } @@ -2480,6 +2743,45 @@ } }; + const loadRuntimeDocumentAwareness = async () => { + const book = selectedBook(); + if (!book || !officeReady || !wordHostAvailable || !window.Word || typeof window.Word.run !== "function") { + return false; + } + + setDocumentMessage("Reading manuscript position..."); + try { + clearPlotDirectorStructureCache(); + await getBookStructureChapters(book.bookId); + const structure = await window.Word.run(async (context) => await readRuntimeDocumentStructure(context, !!book.usesExplicitScenes)); + renderOutline(structure); + setDiagnostics({ + lastScan: "Success", + lastError: "-", + paragraphs: String(structure.paragraphCount), + heading1: String(structure.heading1Count), + heading2: String(structure.heading2Count) + }); + + if (!detectedSceneTitle) { + await refreshPlotDirectorChapter(); + } else { + await refreshPlotDirectorScene(); + } + setSceneContextStale(false); + setSceneTrackingState("Live"); + setDocumentMessage(""); + return true; + } catch (error) { + console.error("Unable to initialise bound manuscript runtime.", error); + documentStructureCache = null; + setSceneTrackingState("Manual"); + setDocumentMessage(`Unable to read manuscript position: ${errorText(error)}`); + setDiagnostics({ lastScan: "Failure", lastError: errorText(error) }); + return false; + } + }; + const initialiseFirstRunBinding = async () => { if (!isAuthenticated || !wordHostAvailable) { setFirstRunMode(false); @@ -2489,18 +2791,24 @@ const binding = readDocumentBinding(); if (binding) { try { - const response = await fetchJson(`/api/word-companion/manuscript/book/${binding.bookId}`); - const document = response?.manuscriptDocument; - if (document && String(document.documentGuid).toLowerCase() === binding.documentGuid.toLowerCase()) { + const runtime = await fetchJson(`/api/word-companion/runtime/book/${binding.bookId}?documentGuid=${encodeURIComponent(binding.documentGuid)}`); + const document = runtime?.manuscriptDocument; + if (runtime?.bookId === binding.bookId + && runtime?.projectId === binding.projectId + && document + && String(document.documentGuid).toLowerCase() === binding.documentGuid.toLowerCase()) { firstRunDocumentBinding = binding; - writeStoredId(storageKeys.projectId, binding.projectId); - writeStoredId(storageKeys.bookId, binding.bookId); + setRuntimeBookContext(runtime); + writeStoredId(storageKeys.projectId, runtime.projectId); + writeStoredId(storageKeys.bookId, runtime.bookId); if (projectSelect) { - projectSelect.value = String(binding.projectId); + projectSelect.value = String(runtime.projectId); } - await loadBooks(binding.projectId, binding.bookId); + await loadBooks(runtime.projectId, runtime.bookId); setFirstRunMode(false); setConnectionStatus("Connected"); + setBookMessage("Bound manuscript detected."); + await loadRuntimeDocumentAwareness(); return; } } catch { @@ -2509,6 +2817,7 @@ } firstRunDocumentBinding = null; + clearRuntimeCaches(); syncFirstRunProjectOptions(); if (selectedFirstRunProject()) { await loadBooks(selectedFirstRunProject().projectId, null); @@ -2833,6 +3142,7 @@ throw new Error("Chapter creation did not return a chapter ID."); } + clearPlotDirectorStructureCache(); setResolvedScene(null, response.chapterId, "Manual chapter link"); const anchored = await attachResolvedChapterId("Chapter created and linked successfully."); if (!anchored) { @@ -3061,6 +3371,7 @@ throw new Error("Scene creation did not return a scene ID."); } + clearPlotDirectorStructureCache(); await resolveCreatedOrLinkedScene(response.sceneId, response.chapterId, "Scene created and linked successfully."); } catch (error) { setCreateLinkStatus("Unable to create scene."); @@ -3535,36 +3846,23 @@ return; } + if (!documentStructureCache) { + setSceneTrackingState("Manual"); + setDocumentMessage("Document structure is not cached yet. Use Refresh Current Scene."); + return; + } + isAutoRefreshingScene = true; - setSceneTrackingState("Refreshing"); - setDocumentMessage("Updating current scene..."); + setSceneTrackingState("Live"); try { - const structure = await window.Word.run(async (context) => { - return await readDocumentStructure(context); - }); - const changed = hasCurrentWordContextChanged(structure); - setCurrentStructure( - structure.currentChapter?.title, - structure.currentScene?.title, - structure.currentScene?.wordCount, - structure.currentChapter?.anchorId, - structure.currentScene?.anchorId, - structure.currentChapter?.index - ); - renderOutline(structure); - setDiagnostics({ - lastScan: "Success", - lastError: "-", - paragraphs: String(structure.paragraphCount), - heading1: String(structure.heading1Count), - heading2: String(structure.heading2Count) - }); + const selectionParagraphs = await window.Word.run(async (context) => await readSelectionParagraphs(context)); + const selectedIndex = findSelectedParagraphIndex(documentStructureCache, selectionParagraphs); + const changed = applyRuntimeSelection(selectedIndex); if (!changed) { setSceneContextStale(false); setSceneTrackingState("Live"); - setDocumentMessage("Current scene updated."); return; } @@ -3575,10 +3873,10 @@ } setSceneContextStale(false); setSceneTrackingState("Live"); - setDocumentMessage("Current scene updated."); + setDocumentMessage(""); } catch (error) { console.error("Unable to refresh current scene from Word selection.", error); - setDiagnostics({ lastScan: "Failure", lastError: errorText(error) }); + setDiagnostics({ lastError: errorText(error) }); setSceneContextStale(true, "The Word cursor is now in a different scene. Refresh Current Scene before saving."); } finally { isAutoRefreshingScene = false; @@ -3677,6 +3975,8 @@ }; const loadBooks = async (projectId, preferredBookId) => { + documentStructureCache = null; + clearPlotDirectorStructureCache(); if (!projectId) { books = []; resetSelect(bookSelect, "Select a project first"); @@ -3804,6 +4104,7 @@ projectSelect?.addEventListener("change", async () => { const projectId = Number.parseInt(projectSelect.value || "", 10); + clearRuntimeCaches(); if (firstRunProjectSelect && Number.isInteger(projectId) && projectId > 0) { firstRunProjectSelect.value = String(projectId); } @@ -3817,6 +4118,7 @@ bookSelect?.addEventListener("change", () => { const bookId = Number.parseInt(bookSelect.value || "", 10); + clearRuntimeCaches(); writeStoredId(storageKeys.bookId, Number.isInteger(bookId) && bookId > 0 ? bookId : null); if (firstRunBookSelect && Number.isInteger(bookId) && bookId > 0) { firstRunBookSelect.value = String(bookId); @@ -3833,6 +4135,7 @@ firstRunProjectSelect?.addEventListener("change", async () => { const projectId = Number.parseInt(firstRunProjectSelect.value || "", 10); + clearRuntimeCaches(); if (projectSelect && Number.isInteger(projectId) && projectId > 0) { projectSelect.value = String(projectId); } @@ -3844,6 +4147,7 @@ firstRunBookSelect?.addEventListener("change", () => { const bookId = Number.parseInt(firstRunBookSelect.value || "", 10); + clearRuntimeCaches(); if (bookSelect && Number.isInteger(bookId) && bookId > 0) { bookSelect.value = String(bookId); } diff --git a/PlotLine/wwwroot/js/word-companion-host.min.js b/PlotLine/wwwroot/js/word-companion-host.min.js index 6e18a1d..658929c 100644 --- a/PlotLine/wwwroot/js/word-companion-host.min.js +++ b/PlotLine/wwwroot/js/word-companion-host.min.js @@ -1 +1 @@ -(()=>{const e="plotdirector.word.projectId",t="plotdirector.word.bookId",r="plotdirector.word.activeTab",n="plotdirector.word.documentGuid",o="plotdirector.word.boundBookId",a="plotdirector.word.boundProjectId",c="plotdirector.word.bindingVersion",i=new Set(["scene","links","structure","diagnostics"]),s=document.querySelector(".word-companion-shell"),d=document.querySelector(".word-companion-tabs"),l=[...document.querySelectorAll("[data-tab-button]")],u=[...document.querySelectorAll("[data-tab-panel]")],p=document.querySelector("[data-first-run-wizard]"),h=document.querySelector("[data-first-run-project-select]"),m=document.querySelector("[data-first-run-book-select]"),y=document.querySelector("[data-first-run-new-book-title]"),f=document.querySelector("[data-first-run-create-book]"),w=document.querySelector("[data-first-run-scan]"),S=document.querySelector("[data-first-run-cancel]"),g=document.querySelector("[data-first-run-status]"),C=document.querySelector("[data-first-run-summary]"),b=document.querySelector("[data-first-run-character-section]"),I=document.querySelector("[data-first-run-character-status]"),k=document.querySelector("[data-first-run-character-candidates]"),v=document.querySelector("[data-first-run-character-actions]"),E=document.querySelector("[data-first-run-create-characters]"),L=document.querySelector("[data-first-run-skip-characters]"),N=document.querySelector("[data-first-run-import-actions]"),q=document.querySelector("[data-first-run-import]"),x=document.querySelector("[data-first-run-import-cancel]"),P=document.querySelector("[data-first-run-replace-dialog]"),D=document.querySelector("[data-first-run-replace-confirm]"),A=document.querySelector("[data-first-run-replace-cancel]"),T=document.querySelector("[data-office-status]"),$=document.querySelector("[data-connection-status]"),j=document.querySelector("[data-summary-connection]"),R=document.querySelector("[data-summary-project]"),W=document.querySelector("[data-summary-book]"),U=document.querySelector("[data-project-select]"),M=document.querySelector("[data-book-select]"),O=document.querySelector("[data-project-message]"),H=document.querySelector("[data-book-message]"),B=document.querySelector("[data-refresh-current-scene]"),F=document.querySelector("[data-refresh-document]"),G=document.querySelector("[data-current-chapter]"),V=document.querySelector("[data-current-scene]"),J=document.querySelector("[data-current-word-count]"),Y=document.querySelector("[data-scene-tracking-status]"),z=document.querySelector("[data-document-message]"),K=document.querySelector("[data-sync-note]"),Q=document.querySelector("[data-document-outline]"),X=document.querySelector("[data-analyse-manuscript-structure]"),Z=document.querySelector("[data-apply-structure-sync]"),_=document.querySelector("[data-structure-preview-status]"),ee=document.querySelector("[data-structure-preview-results]"),te=document.querySelector("[data-refresh-plotdirector-scene]"),re=document.querySelector("[data-plotdirector-scene-status]"),ne=document.querySelector("[data-anchor-status]"),oe=document.querySelector("[data-anchor-book-id]"),ae=document.querySelector("[data-anchor-chapter-id]"),ce=document.querySelector("[data-anchor-scene-id]"),ie=document.querySelector("[data-attach-plotdirector-ids]"),se=document.querySelector("[data-plotdirector-scene-details]"),de=document.querySelector("[data-plotdirector-scene-title]"),le=document.querySelector("[data-plotdirector-revision-status]"),ue=document.querySelector("[data-plotdirector-estimated-words]"),pe=document.querySelector("[data-plotdirector-actual-words]"),he=document.querySelector("[data-plotdirector-blocked-status]"),me=document.querySelector("[data-plotdirector-blocked-reason-row]"),ye=document.querySelector("[data-plotdirector-blocked-reason]"),fe=document.querySelector("[data-sync-scene-progress]"),we=document.querySelector("[data-sync-word-count]"),Se=document.querySelector("[data-sync-plotdirector-count]"),ge=document.querySelector("[data-sync-last-synced]"),Ce=document.querySelector("[data-sync-status]"),be=document.querySelector("[data-writing-brief-block]"),Ie=document.querySelector("[data-writing-brief]"),ke=document.querySelector("[data-plotdirector-link-groups]"),ve=document.querySelector("[data-character-chips]"),Ee=document.querySelector("[data-asset-chips]"),Le=(document.querySelector("[data-location-chips]"),document.querySelector("[data-primary-location-select]")),Ne=document.querySelector("[data-save-scene-links]"),qe=document.querySelector("[data-scene-links-status]"),xe=document.querySelector("[data-links-editing-scene]"),Pe=document.querySelector("[data-chapter-create-link]"),De=document.querySelector("[data-chapter-create-link-chapter]"),Ae=document.querySelector("[data-create-plotdirector-chapter]"),Te=document.querySelector("[data-link-existing-chapter]"),$e=document.querySelector("[data-chapter-create-link-status]"),je=document.querySelector("[data-scene-create-link]"),Re=document.querySelector("[data-create-link-chapter]"),We=document.querySelector("[data-create-link-scene]"),Ue=document.querySelector("[data-create-plotdirector-scene]"),Me=document.querySelector("[data-link-existing-scene]"),Oe=document.querySelector("[data-create-link-status]"),He=document.querySelector("[data-link-existing-dialog]"),Be=document.querySelector("[data-link-scene-search]"),Fe=document.querySelector("[data-link-scene-options]"),Ge=document.querySelector("[data-link-selected-scene]"),Ve=document.querySelector("[data-link-dialog-cancel]"),Je=document.querySelector("[data-link-dialog-status]"),Ye=document.querySelector("[data-create-scene-dialog]"),ze=document.querySelector("[data-create-dialog-scene]"),Ke=document.querySelector("[data-create-dialog-chapter]"),Qe=document.querySelector("[data-create-dialog-confirm]"),Xe=document.querySelector("[data-create-dialog-cancel]"),Ze=document.querySelector("[data-link-existing-chapter-dialog]"),_e=document.querySelector("[data-link-chapter-search]"),et=document.querySelector("[data-link-chapter-options]"),tt=document.querySelector("[data-link-selected-chapter]"),rt=document.querySelector("[data-link-chapter-dialog-cancel]"),nt=document.querySelector("[data-link-chapter-dialog-status]"),ot=document.querySelector("[data-create-chapter-dialog]"),at=document.querySelector("[data-create-chapter-dialog-chapter]"),ct=document.querySelector("[data-create-chapter-dialog-book]"),it=document.querySelector("[data-create-chapter-dialog-confirm]"),st=document.querySelector("[data-create-chapter-dialog-cancel]"),dt=document.querySelector("[data-apply-structure-sync-dialog]"),lt=document.querySelector("[data-apply-structure-sync-summary]"),ut=document.querySelector("[data-apply-structure-sync-confirm]"),pt=document.querySelector("[data-apply-structure-sync-cancel]"),ht=document.querySelector("[data-resolve-project-id]"),mt=document.querySelector("[data-resolve-project-title]"),yt=document.querySelector("[data-resolve-book-id]"),ft=document.querySelector("[data-resolve-book-title]"),wt=document.querySelector("[data-resolve-detected-chapter]"),St=document.querySelector("[data-resolve-detected-scene]"),gt=document.querySelector("[data-resolve-request-chapter]"),Ct=document.querySelector("[data-resolve-request-scene]"),bt=document.querySelector("[data-resolve-result]"),It=document.querySelector("[data-resolve-chapter-id]"),kt=document.querySelector("[data-resolve-scene-id]"),vt=document.querySelector("[data-run-diagnostics]"),Et=document.querySelector("[data-diagnostic-host]"),Lt=document.querySelector("[data-diagnostic-platform]"),Nt=document.querySelector("[data-diagnostic-ready]"),qt=document.querySelector("[data-diagnostic-word-api]"),xt=document.querySelector("[data-diagnostic-last-scan]"),Pt=document.querySelector("[data-diagnostic-last-error]"),Dt=document.querySelector("[data-diagnostic-anchor-type]"),At=document.querySelector("[data-diagnostic-stored-scene-id]"),Tt=document.querySelector("[data-diagnostic-stored-chapter-id]"),$t=document.querySelector("[data-diagnostic-resolution-method]"),jt=document.querySelector("[data-diagnostic-paragraphs]"),Rt=document.querySelector("[data-diagnostic-heading1]"),Wt=document.querySelector("[data-diagnostic-heading2]"),Ut="true"===s?.dataset.authenticated;let Mt=[],Ot=[],Ht=!1,Bt=!1,Ft="Unknown",Gt="Unknown",Vt="",Jt="",Yt=null,zt=null,Kt=null,Qt=null,Xt=null,Zt=null,_t="",er="Title Match",tr=!1,rr=[],nr=null,or=null,ar=[],cr=null,ir=null,sr=null,dr=null,lr=null,ur=null,pr=[],hr=!1,mr=!1,yr=!1,fr=!1,wr=null,Sr="Manual",gr=!1,Cr=null,br=!1,Ir=!1,kr="",vr="",Er={characters:[],assets:[],locations:[],primaryLocationId:null};const Lr=e=>{T&&(T.textContent=e)},Nr=(e,t=!0)=>{const n=i.has(e)&&l.some(t=>t.dataset.tabButton===e)?e:"scene";for(const e of l){const t=e.dataset.tabButton===n;e.classList.toggle("is-active",t),e.setAttribute("aria-selected",t?"true":"false")}for(const e of u){const t=e.dataset.tabPanel===n;e.classList.toggle("is-active",t),e.hidden=!t}t&&((e,t)=>{try{t?window.localStorage.setItem(e,String(t)):window.localStorage.removeItem(e)}catch{}})(r,n)},qr=()=>{const e=(e=>{try{return window.localStorage.getItem(e)||""}catch{return""}})(r);Nr(i.has(e)?e:"scene",!1)},xr=e=>{$&&($.textContent=e),j&&(j.textContent=e)},Pr=e=>{O&&(O.textContent=e)},Dr=e=>{H&&(H.textContent=e)},Ar=e=>{z&&(z.textContent=e)},Tr=e=>{re&&(re.textContent=e)},$r=e=>{const t=t=>Object.prototype.hasOwnProperty.call(e,t);t("anchorType")&&gn(Dt,Qr(e.anchorType)),t("storedSceneId")&&gn(At,Qr(e.storedSceneId)),t("storedChapterId")&&gn(Tt,Qr(e.storedChapterId)),t("resolutionMethod")&&gn($t,Qr(e.resolutionMethod))},jr=()=>{const e=xn(),t=Number.isInteger(Xt)&&Xt>0&&Qt===Xt,r=!Number.isInteger(Zt)||Zt<=0||Kt===Zt,n=t&&r;gn(ne,n?"Attached to PlotDirector":"Not attached"),gn(oe,e?.bookId?String(e.bookId):"-"),gn(ae,Number.isInteger(Zt)&&Zt>0?String(Zt):"-"),gn(ce,Number.isInteger(Xt)&&Xt>0?String(Xt):"-"),ie&&(ie.disabled=!Xt||n&&!tr,ie.textContent=Qt&&!n?"Reattach PlotDirector IDs":"Attach PlotDirector IDs"),$r({anchorType:er||"Title Match",storedSceneId:Qt,storedChapterId:Kt,resolutionMethod:_t})},Rr=(e,t,r,n=null,o=null,a=null)=>{Vt=e||"",Jt=t||"",Yt=Number.isInteger(r)?r:null,zt=Number.isInteger(a)&&a>0?a:null,Kt=Number.isInteger(n)&&n>0?n:null,Qt=Number.isInteger(o)&&o>0?o:null,G&&(G.textContent=e||"Not detected"),V&&(V.textContent=t||"Not detected"),J&&(J.textContent=Number.isInteger(r)?String(r):"-"),gn(we,Number.isInteger(r)?String(r):"-"),jr()},Wr=(e,t)=>{e&&(e.hidden=t)},Ur=e=>{gn(Ce,e)},Mr=e=>{gn(_,e)},Or=(e="Select a project and book to analyse manuscript structure.")=>{if(sr=null,ee){ee.innerHTML="";const e=document.createElement("p");e.textContent="No preview generated.",ee.append(e)}Mr(e),Br()},Hr=(e=sr)=>((e=sr)=>zn.flatMap(t=>Array.isArray(e?.[t.key])?e[t.key]:[]))(e).filter(e=>"couldLink"===e.category||"wouldCreateChapters"===e.category||"wouldCreateScenes"===e.category),Br=()=>{Z&&(Z.disabled=fr||0===Hr().length)},Fr=()=>{X&&(X.disabled=fr||!qn()||!xn()),Br()},Gr=()=>{xe&&(xe.textContent=Xt?`Editing links for: ${kr||Jt||"Current scene"}`:"Link a PlotDirector scene first.")},Vr=()=>{const e=gr||!Xt;fe&&(fe.disabled=e),Ne&&(Ne.disabled=e),Le&&(Le.disabled=e);for(const t of[ve,Ee])for(const r of t?[...t.querySelectorAll("input[type='checkbox']")]:[])r.disabled=e},Jr=e=>{"Live"!==e&&"Manual"!==e||(Sr=e),gn(Y,e||Sr||"Manual")},Yr=(e,t="")=>{gr=!!e,gn(Y,gr?"Stale":Sr),Vr(),t&&(Ar(t),Xr(t))},zr=(e,t=null,r="")=>{Xt=Number.isInteger(e)&&e>0?e:null,Zt=Number.isInteger(t)&&t>0?t:null,_t=r||"",Vr(),Ur(gr?"Refresh Current Scene before syncing.":Xt?"Ready to sync.":"No resolved PlotDirector scene."),Xr(gr?"Refresh Current Scene before saving.":Xt?"Ready to save.":"Link a PlotDirector scene first."),Gr(),jr()},Kr=e=>{B&&(B.disabled=e,B.textContent=e?"Refreshing...":"Refresh Current Scene")},Qr=e=>null==e||""===e?"-":String(e),Xr=e=>{gn(qe,e)},Zr=e=>{gn(Oe,e)},_r=e=>{gn($e,e)},en=()=>!!xn()&&!!Vt&&!Zt,tn=()=>!!xn()&&!!Jt&&Number.isInteger(Zt)&&Zt>0,rn=()=>{Wr(Pe,!0),_r(""),Ae&&(Ae.disabled=!0,Ae.textContent="Create Chapter in PlotDirector"),Te&&(Te.disabled=!0,Te.textContent="Link to Existing Chapter")},nn=(e="")=>{gn(De,Qr(Vt)),Wr(Pe,!1),_r(e);const t=en();Ae&&(Ae.disabled=!t,Ae.textContent="Create Chapter in PlotDirector"),Te&&(Te.disabled=!t,Te.textContent="Link to Existing Chapter")},on=()=>{Wr(je,!0),Zr(""),Ue&&(Ue.disabled=!0,Ue.textContent="Create Scene in PlotDirector"),Me&&(Me.disabled=!0,Me.textContent="Link to Existing Scene")},an=(e="")=>{gn(Re,Qr(Vt)),gn(We,Qr(Jt)),Wr(je,!1),Zr(e);const t=tn();Ue&&(Ue.disabled=!t,Ue.textContent="Create Scene in PlotDirector"),Me&&(Me.disabled=!t,Me.textContent="Link to Existing Scene")},cn=e=>{Tr(e),Wr(se,!0),Wr(be,!0),Wr(ke,!1),rn(),on(),_t="",kr="",vr="",er=Qt?"SceneID Anchor":Kt?"ChapterID Anchor":"Title Match",tr=!1,Er={characters:[],assets:[],locations:[],primaryLocationId:null},dn(ve,[],"character"),dn(Ee,[],"asset"),ln([],null,!1),zr(null),gn(Se,"-"),gn(de,"-"),gn(le,"-"),gn(ue,"-"),gn(pe,"-"),gn(he,"-"),gn(ye,"-"),Wr(me,!0),jr(),Gr()},sn=(e,t)=>"asset"===t?e?.assetId||e?.AssetId||e?.storyAssetId||e?.StoryAssetId||0:"location"===t?e?.locationId||e?.LocationId||0:e?.characterId||e?.CharacterId||0,dn=(e,t,r,n=!1)=>{if(!e)return;e.innerHTML="";const o=Array.isArray(t)?t:[];if(0===o.length){const t=document.createElement("p");return t.className="word-companion-empty-list",t.textContent="None",void e.append(t)}for(const t of o){const o=Number.parseInt(sn(t,r),10);if(!Number.isInteger(o)||o<=0)continue;const a=document.createElement("label");a.className="word-companion-check-item";const c=document.createElement("input");c.type="checkbox",c.value=String(o),c.checked=!!t.linked,c.disabled=!n;const i=document.createElement("span");i.textContent=t.name||"Unnamed",a.append(c,i),e.append(a)}},ln=(e,t,r=!1)=>{if(!Le)return;Le.innerHTML="";const n=document.createElement("option");n.value="",n.textContent="None",Le.append(n);const o=Number.parseInt(t||"",10);for(const t of Array.isArray(e)?e:[]){const e=Number.parseInt(sn(t,"location"),10);if(!Number.isInteger(e)||e<=0)continue;const r=document.createElement("option");r.value=String(e),r.textContent=t.name||"Unnamed",r.selected=e===o,Le.append(r)}Le.disabled=!r},un=e=>String(e||"").trim().replace(/\s+/g," "),pn=(e,t)=>{const r=un(e);if(!r)return"";const n=new RegExp(`^${"scene"===t?"scene":"chapter"}\\s+(?:\\d+|[ivxlcdm]+|one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen|twenty)\\s*(?::|-|\\u2013|\\u2014)\\s*`,"i");return un(r.replace(n,""))||r},hn=e=>{const t=t=>Object.prototype.hasOwnProperty.call(e,t);t("projectId")&&gn(ht,Qr(e.projectId)),t("projectTitle")&&gn(mt,Qr(e.projectTitle)),t("bookId")&&gn(yt,Qr(e.bookId)),t("bookTitle")&&gn(ft,Qr(e.bookTitle)),t("detectedChapter")&&gn(wt,Qr(e.detectedChapter)),t("detectedScene")&&gn(St,Qr(e.detectedScene)),t("requestChapter")&&gn(gt,Qr(e.requestChapter)),t("requestScene")&&gn(Ct,Qr(e.requestScene)),t("result")&&gn(bt,Qr(e.result)),t("chapterId")&&gn(It,Qr(e.chapterId)),t("sceneId")&&gn(kt,Qr(e.sceneId))},mn=async e=>{const t=await fo(`/api/word-companion/books/${e}/structure`);return Array.isArray(t?.chapters)?t.chapters:[]},yn=async e=>{const t=await fo(`/api/word-companion/books/${e}/chapters`);return Array.isArray(t?.chapters)?t.chapters:[]},fn=e=>{if(Number.isInteger(Zt)&&Zt>0){const t=e.find(e=>e.chapterId===Zt);if(t)return t}const t=pn(Vt,"chapter").toLocaleLowerCase();return t&&e.find(e=>pn(e.title,"chapter").toLocaleLowerCase()===t)||null},wn=async()=>{const e=xn();return e?fn(await mn(e.bookId)):null},Sn=async(e,t,r,n,o)=>{const a=await fo(`/api/word-companion/scenes/${t}/companion`);try{a.revisionStatus=await(async(e,t)=>{const r=await fo(`/api/word-companion/books/${e}/structure`),n=Array.isArray(r?.chapters)?r.chapters:[];for(const e of n){const r=(Array.isArray(e.scenes)?e.scenes:[]).find(e=>e.sceneId===t);if(r)return r.revisionStatus||""}return""})(e,t)}catch{a.revisionStatus=""}var c;er=o||"Title Match",tr=!1,Yr(!1),Tr("Linked to PlotDirector"),Ar(""),rn(),on(),zr(t,r,n),c=a,kr=c?.sceneTitle||Jt||"",vr=c?.chapterTitle||Vt||"",gn(de,Qr(c?.sceneTitle)),gn(le,Qr(c?.revisionStatus||c?.revisionStatusName||"Not provided")),gn(ue,Qr(c?.estimatedWords)),gn(pe,Qr(c?.actualWords)),gn(Se,Qr(c?.actualWords)),gn(he,c?.blocked?"Blocked":"Not blocked"),c?.blockedReason?(gn(ye,c.blockedReason),Wr(me,!1)):(gn(ye,"-"),Wr(me,!0)),Ie&&(Ie.textContent=c?.writingBrief||"No writing brief has been added for this scene."),Er={characters:Array.isArray(c?.characters)?c.characters:[],assets:Array.isArray(c?.assets)?c.assets:[],locations:Array.isArray(c?.locations)?c.locations:[],primaryLocationId:c?.primaryLocationId??null},dn(ve,Er.characters,"character",!!Xt&&!gr),dn(Ee,Er.assets,"asset",!!Xt&&!gr),ln(Er.locations,Er.primaryLocationId,!!Xt&&!gr),Gr(),Xr(gr?"Refresh Current Scene before saving.":Xt?"Ready to save.":"No resolved PlotDirector scene."),Wr(se,!1),Wr(be,!1),Wr(ke,!1)},gn=(e,t)=>{e&&(e.textContent=t)},Cn=e=>{const t=t=>Object.prototype.hasOwnProperty.call(e,t);t("host")&&gn(Et,e.host),t("platform")&&gn(Lt,e.platform),t("ready")&&gn(Nt,e.ready),t("wordApi")&&gn(qt,e.wordApi),t("lastScan")&&gn(xt,e.lastScan),t("lastError")&&gn(Pt,e.lastError),t("paragraphs")&&gn(jt,e.paragraphs),t("heading1")&&gn(Rt,e.heading1),t("heading2")&&gn(Wt,e.heading2)},bn=e=>{const t=[];return e?.name&&t.push(e.name),e?.code&&e.code!==e.name&&t.push(e.code),e?.message&&t.push(e.message),e?.debugInfo?.errorLocation&&t.push(`Location: ${e.debugInfo.errorLocation}`),t.length>0?t.join(": "):String(e)},In=async()=>{if(!window.Office||"function"!=typeof window.Office.onReady)return Ht=!1,Bt=!1,Ft="Unavailable",Gt="Unavailable",Cn({host:Ft,platform:Gt,ready:"No",wordApi:"No"}),null;const e=await window.Office.onReady();return Ht=!0,Ft=e?.host||"Unknown",Gt=e?.platform||"Unknown",Bt=!!window.Word&&!!window.Office.HostType&&e?.host===window.Office.HostType.Word,Cn({host:Ft,platform:Gt,ready:"Yes",wordApi:Bt?"Yes":"No"}),e},kn=e=>{try{const t=window.localStorage.getItem(e),r=Number.parseInt(t||"",10);return Number.isInteger(r)&&r>0?r:null}catch{return null}},vn=(e,t)=>{try{t?window.localStorage.setItem(e,String(t)):window.localStorage.removeItem(e)}catch{}},En=(e,t)=>{if(!e)return;e.innerHTML="";const r=document.createElement("option");r.value="",r.textContent=t,e.append(r),e.disabled=!0},Ln=(e,t,r,n,o)=>{if(!e)return;e.innerHTML="";const a=document.createElement("option");a.value="",a.textContent=t,e.append(a);for(const t of r){const r=document.createElement("option");r.value=String(t[n]),r.textContent=t[o],e.append(r)}e.disabled=0===r.length},Nn=e=>{const t=String(e?.title||"").trim(),r=String(e?.subtitle||"").trim();return r?`${t}: ${r}`:t},qn=()=>{const e=Number.parseInt(U?.value||"",10);return Mt.find(t=>t.projectId===e)||null},xn=()=>{const e=Number.parseInt(M?.value||"",10);return Ot.find(t=>t.bookId===e)||null},Pn=()=>{const e=Number.parseInt(h?.value||"",10);return Mt.find(t=>t.projectId===e)||null},Dn=()=>{const e=Number.parseInt(m?.value||"",10);return Ot.find(t=>t.bookId===e)||null},An=e=>gn(g,e),Tn=()=>{const e=Pn(),t=Dn();w&&(w.disabled=!e||!t||mr),f&&(f.disabled=!e||!String(y?.value||"").trim()||mr),q&&(q.disabled=!lr?.canImport||!ur||mr),E&&(E.disabled=yr||0===Wn().length)},$n=e=>{Wr(p,!e),Wr(d,e);for(const t of u)Wr(t,!!e||"scene"!==t.dataset.tabPanel&&!t.classList.contains("is-active"));e||qr()},jn=()=>{if(!h)return;if(0===Mt.length)return void En(h,"No projects available.");Ln(h,"Choose a project",Mt,"projectId","title");const e=Number.parseInt(U?.value||"",10);Number.isInteger(e)&&e>0&&(h.value=String(e))},Rn=(e="Select a Project and Book to begin.")=>{lr=null,ur=null,pr=[],hr=!1,Wr(C,!0),Wr(N,!0),Wr(b,!0),Wr(v,!0),C&&(C.innerHTML=""),k&&(k.innerHTML=""),gn(I,""),An(e),Tn()},Wn=()=>k?[...k.querySelectorAll("input[type='checkbox']:checked")].map(e=>String(e.value||"").trim()).filter(Boolean):[],Un=e=>{if(pr=Array.isArray(e)?e:[],b&&k){if(k.innerHTML="",Wr(b,!1),Wr(v,!hr||0===pr.length),0===pr.length)return gn(I,"No likely major characters found."),void Tn();gn(I,`${pr.length} likely major characters found.`);for(const e of pr){const t=document.createElement("label");t.className="word-companion-character-candidate";const r=document.createElement("input");r.type="checkbox",r.value=e.text||"",r.checked="high"===String(e.confidence||"").trim().toLowerCase(),r.addEventListener("change",Tn);const n=document.createElement("strong");n.textContent=e.text||"";const o=document.createElement("em"),a=String(e.reason||"").trim();o.textContent=a?`${Number(e.mentionCount||0).toLocaleString()} mentions · ${a}`:`${Number(e.mentionCount||0).toLocaleString()} mentions`;const c=document.createElement("span");c.className="word-companion-character-candidate-text",c.append(n,o),t.append(r,c),k.append(t)}Tn()}},Mn=()=>dr?.documentGuid?dr.documentGuid:window.crypto?.randomUUID?window.crypto.randomUUID():"10000000-1000-4000-8000-100000000000".replace(/[018]/g,e=>(Number(e)^16*Math.random()>>Number(e)/4).toString(16)),On=()=>{const e=qn(),t=xn();R&&(R.textContent=e?.title||"(Not connected)"),W&&(W.textContent=t?Nn(t):"(Not connected)"),K&&(K.textContent=t?"":"Select a PlotDirector book before refreshing."),Fr()},Hn=e=>String(e?.styleBuiltIn||e?.style||"").replace(/\s+/g,"").toLowerCase(),Bn=(e,t)=>{const r=Hn(e);return r===`heading${t}`||r.endsWith(`.heading${t}`)||r.includes(`heading${t}`)},Fn=e=>String(e||"").trim().split(/\s+/).filter(Boolean).length,Gn=(e,t)=>{const r=String(e||"").match(new RegExp(`^${t}-(\\d+)$`,"i"));if(!r)return null;const n=Number.parseInt(r[1],10);return Number.isInteger(n)&&n>0?n:null},Vn=(e,t)=>{const r=Array.isArray(e?.contentControls?.items)?e.contentControls.items:[];for(const e of r){const r=Gn(e.tag,t);if(r)return r}return null},Jn=(e,t)=>{const r=[];let n=0,o=0,a=null,c=null;e.forEach((e,t)=>{const i=String(e.text||"").trim();if(i){if(Bn(e,1))return n+=1,a={index:r.length+1,paragraphIndex:t,title:i,anchorId:Vn(e,"PD-CHAPTER"),scenes:[]},r.push(a),void(c=null);if(Bn(e,2)){if(o+=1,!a)return;return c={index:a.scenes.length+1,paragraphIndex:t,title:i,anchorId:Vn(e,"PD-SCENE"),wordCount:0},void a.scenes.push(c)}c&&(c.wordCount+=Fn(i))}});const i=t.find(e=>String(e.text||"").trim()),s=i?e.findIndex(e=>{return t=e,r=i,String(t?.text||"").trim()===String(r?.text||"").trim()&&Hn(t)===Hn(r);var t,r}):-1,d=s>=0&&r.filter(e=>e.paragraphIndex<=s).at(-1)||null,l=d&&s>=0&&d.scenes.filter(e=>e.paragraphIndex<=s).at(-1)||null;return{chapters:r,currentChapter:d,currentScene:l,paragraphCount:e.length,heading1Count:n,heading2Count:o}},Yn=e=>{if(!Q)return;if(Q.innerHTML="",0===e.chapters.length){const e=document.createElement("p");return e.textContent="No chapters detected. Use Heading 1 for chapter titles.",void Q.append(e)}if(!e.chapters.some(e=>e.scenes.length>0)){const e=document.createElement("p");e.textContent="No scenes detected. Use Heading 2 for scene titles.",Q.append(e)}for(const t of e.chapters){const e=document.createElement("div");e.className="word-companion-outline-chapter";const r=document.createElement("strong");if(r.textContent=t.title,e.append(r),t.scenes.length>0){const r=document.createElement("ul");for(const e of t.scenes){const t=document.createElement("li");t.textContent=e.title,r.append(t)}e.append(r)}Q.append(e)}},zn=[{key:"alreadyLinked",title:"Already Linked"},{key:"couldLink",title:"Could Link"},{key:"wouldCreateChapters",title:"Would Create Chapters"},{key:"wouldCreateScenes",title:"Would Create Scenes"},{key:"manualReview",title:"Manual Review Required"}],Kn={alreadyLinked:"Already Linked",couldLink:"Could Link",wouldCreateChapter:"Would Create Chapter",wouldCreateScene:"Would Create Scene",manualReview:"Manual Review Required"},Qn={alreadyLinked:"✓",couldLink:"~",wouldCreateChapter:"+",wouldCreateScene:"+",manualReview:"?"},Xn=(e,t)=>pn(e,t).toLocaleLowerCase(),Zn=({category:e,action:t,type:r,wordTitle:n,match:o="",anchorStatus:a="None",matches:c=[],pdChapter:i=null,pdScene:s=null,wordChapter:d=null,wordScene:l=null,parentItem:u=null})=>({id:`${r}-${d?.index||0}-${l?.index||0}-${d?.paragraphIndex??l?.paragraphIndex??0}`,category:e,action:t,type:r,wordTitle:n,match:o,anchorStatus:a,matches:c,pdChapter:i,pdScene:s,wordChapter:d,wordScene:l,parentItem:u,result:"Pending",error:""}),_n=(e,t)=>{Array.isArray(e[t.category])&&e[t.category].push(t)},eo=e=>Array.isArray(e?.scenes)?e.scenes:[],to=(e,t,r)=>{const n=e.anchorId?`PD-CHAPTER-${e.anchorId}`:"None";if(e.anchorId){const o=t.find(t=>t.chapterId===e.anchorId);if(o){const t=Zn({category:"alreadyLinked",action:"alreadyLinked",type:"Chapter",wordTitle:e.title,match:`Chapter ${o.chapterId}: ${o.title}`,anchorStatus:n,pdChapter:o,wordChapter:e});return _n(r,t),t}const a=Zn({category:"manualReview",action:"manualReview",type:"Chapter",wordTitle:e.title,anchorStatus:`${n} not found`,matches:[],pdChapter:null,wordChapter:e});return _n(r,a),a}const o=t.filter(t=>Xn(t.title,"chapter")===Xn(e.title,"chapter"));if(1===o.length){const t=Zn({category:"couldLink",action:"couldLink",type:"Chapter",wordTitle:e.title,match:`Chapter ${o[0].chapterId}: ${o[0].title}`,anchorStatus:n,pdChapter:o[0],wordChapter:e});return _n(r,t),t}if(o.length>1){const t=Zn({category:"manualReview",action:"manualReview",type:"Chapter",wordTitle:e.title,anchorStatus:n,matches:o.map(e=>`Chapter ${e.chapterId}: ${e.title}`),pdChapter:null,wordChapter:e});return _n(r,t),t}const a=Zn({category:"wouldCreateChapters",action:"wouldCreateChapter",type:"Chapter",wordTitle:e.title,anchorStatus:n,pdChapter:null,wordChapter:e});return _n(r,a),a},ro=(e,t,r,n)=>{const o=e.anchorId?`PD-SCENE-${e.anchorId}`:"None";if(e.anchorId){const a=((e,t)=>{for(const r of e){const e=eo(r).find(e=>e.sceneId===t);if(e)return{chapter:r,scene:e}}return null})(r,e.anchorId);return a?void _n(n,Zn({category:"alreadyLinked",action:"alreadyLinked",type:"Scene",wordTitle:e.title,match:`Scene ${a.scene.sceneId}: ${a.scene.title}`,anchorStatus:o,pdChapter:a.chapter,pdScene:a.scene,wordChapter:t?.wordChapter,wordScene:e,parentItem:t})):void _n(n,Zn({category:"manualReview",action:"manualReview",type:"Scene",wordTitle:e.title,anchorStatus:`${o} not found`,wordChapter:t?.wordChapter,wordScene:e,parentItem:t}))}if(!t?.pdChapter&&"manualReview"===t?.category)return void _n(n,Zn({category:"manualReview",action:"manualReview",type:"Scene",wordTitle:e.title,anchorStatus:o,matches:["Parent chapter requires manual review."],wordChapter:t?.wordChapter,wordScene:e,parentItem:t}));if(!t?.pdChapter)return void _n(n,Zn({category:"wouldCreateScenes",action:"wouldCreateScene",type:"Scene",wordTitle:e.title,anchorStatus:o,wordChapter:t?.wordChapter,wordScene:e,parentItem:t}));const a=eo(t.pdChapter).filter(t=>Xn(t.title,"scene")===Xn(e.title,"scene"));1!==a.length?a.length>1?_n(n,Zn({category:"manualReview",action:"manualReview",type:"Scene",wordTitle:e.title,anchorStatus:o,matches:a.map(e=>`Scene ${e.sceneId}: ${e.title}`),wordChapter:t.wordChapter,wordScene:e,parentItem:t})):_n(n,Zn({category:"wouldCreateScenes",action:"wouldCreateScene",type:"Scene",wordTitle:e.title,anchorStatus:o,pdChapter:t.pdChapter,wordChapter:t.wordChapter,wordScene:e,parentItem:t})):_n(n,Zn({category:"couldLink",action:"couldLink",type:"Scene",wordTitle:e.title,match:`Scene ${a[0].sceneId}: ${a[0].title}`,anchorStatus:o,pdChapter:t.pdChapter,pdScene:a[0],wordChapter:t.wordChapter,wordScene:e,parentItem:t}))},no=e=>{const t=document.createElement("article");t.className="word-companion-preview-item";const r=document.createElement("strong");r.textContent=`${Qn[e.action]||""} ${e.type}: ${e.wordTitle}`,t.append(r);const n=document.createElement("span");if(n.textContent=`Anchor: ${e.anchorStatus||"None"}`,t.append(n),e.match){const r=document.createElement("span");r.textContent=`Match: ${e.match}`,t.append(r)}if(Array.isArray(e.matches)&&e.matches.length>0){const r=document.createElement("div");r.className="word-companion-preview-matches";const n=document.createElement("span");n.textContent="Matches:",r.append(n);const o=document.createElement("ul");for(const t of e.matches){const e=document.createElement("li");e.textContent=t,o.append(e)}r.append(o),t.append(r)}const o=document.createElement("span");if(o.textContent=`Action: ${Kn[e.action]||e.action}`,t.append(o),e.result&&"Pending"!==e.result){const r=document.createElement("span");r.textContent=e.error?`Result: ${e.result} - ${e.error}`:`Result: ${e.result}`,t.append(r)}return t},oo=e=>{if(ee){ee.innerHTML="";for(const t of zn){const r=document.createElement("section");r.className="word-companion-preview-group";const n=document.createElement("strong");n.textContent=t.title,r.append(n);const o=Array.isArray(e?.[t.key])?e[t.key]:[];if(0===o.length){const e=document.createElement("p");e.className="word-companion-empty-list",e.textContent="None",r.append(e)}else for(const e of o)r.append(no(e));ee.append(r)}Br()}},ao=async e=>{const t=e.document.body.paragraphs,r=e.document.getSelection().paragraphs;t.load("text,styleBuiltIn,style"),r.load("text,styleBuiltIn,style"),await e.sync();for(const e of t.items)(Bn(e,1)||Bn(e,2))&&e.contentControls.load("items/tag,title");await e.sync();const n=Jn(t.items,r.items);return n.bodyParagraphs=t.items,n},co=async()=>{if(Ar(""),!Ht||!Bt||!window.Word||"function"!=typeof window.Word.run)return Rr(null,null,null),Ar("Word document access is unavailable."),Cn({lastScan:"Failure",lastError:"Word document access is unavailable."}),!1;F&&(F.disabled=!0,F.textContent="Scanning..."),Ar("Scanning document structure...");try{const e=await window.Word.run(async e=>await ao(e));return Rr(e.currentChapter?.title,e.currentScene?.title,e.currentScene?.wordCount,e.currentChapter?.anchorId,e.currentScene?.anchorId,e.currentChapter?.index),cn("Not detected"),Yn(e),Ar(""),Cn({lastScan:"Success",lastError:"-",paragraphs:String(e.paragraphCount),heading1:String(e.heading1Count),heading2:String(e.heading2Count)}),!0}catch(e){const t=bn(e);return console.error("Unable to scan the Word document.",e),Rr(null,null,null),Ar(`Unable to scan the Word document: ${t}`),Cn({lastScan:"Failure",lastError:t}),!1}finally{F&&(F.disabled=!1,F.textContent="Refresh Document Structure")}},io=async()=>{const e=xn();if(!qn()||!e)return Mr("Select a project and book to analyse manuscript structure."),!1;if(!Ht||!Bt||!window.Word||"function"!=typeof window.Word.run)return Mr("Word document access is unavailable."),Cn({lastScan:"Failure",lastError:"Word document access is unavailable."}),!1;X&&(X.disabled=!0,X.textContent="Analysing..."),Mr("Analysing manuscript structure...");try{const t=await window.Word.run(async e=>await ao(e)),r=await fo(`/api/word-companion/books/${e.bookId}/structure`);return Rr(t.currentChapter?.title,t.currentScene?.title,t.currentScene?.wordCount,t.currentChapter?.anchorId,t.currentScene?.anchorId,t.currentChapter?.index),Yn(t),sr=((e,t)=>{const r={alreadyLinked:[],couldLink:[],wouldCreateChapters:[],wouldCreateScenes:[],manualReview:[]},n=Array.isArray(t?.chapters)?t.chapters:[];for(const t of Array.isArray(e?.chapters)?e.chapters:[]){const e=to(t,n,r);for(const o of eo(t))ro(o,e,n,r)}return r})(t,r),oo(sr),Mr("Preview generated. No changes have been applied."),Cn({lastScan:"Success",lastError:"-",paragraphs:String(t.paragraphCount),heading1:String(t.heading1Count),heading2:String(t.heading2Count)}),!0}catch(e){return console.error("Unable to analyse manuscript structure.",e),Mr("Unable to analyse manuscript structure."),Cn({lastScan:"Failure",lastError:bn(e)}),!1}finally{X&&(X.textContent="Analyse Manuscript Structure",Fr())}},so=e=>{wr&&(wr(e),wr=null),dt?.close?dt.close():dt&&(dt.hidden=!0)},lo=()=>{const e=((e=sr)=>{const t=Hr(e);return{linkChapters:t.filter(e=>"couldLink"===e.category&&"Chapter"===e.type).length,linkScenes:t.filter(e=>"couldLink"===e.category&&"Scene"===e.type).length,createChapters:t.filter(e=>"wouldCreateChapters"===e.category).length,createScenes:t.filter(e=>"wouldCreateScenes"===e.category).length,manualReview:Array.isArray(e?.manualReview)?e.manualReview.length:0}})();return(e=>{if(!lt)return;lt.innerHTML="";const t=[`Link ${e.linkChapters+e.linkScenes} chapters/scenes`,`Create ${e.createChapters} chapters`,`Create ${e.createScenes} scenes`],r=document.createElement("ul");for(const e of t){const t=document.createElement("li");t.textContent=e,r.append(t)}lt.append(r)})(e),dt?new Promise(e=>{wr=e,dt.showModal?dt.showModal():dt.hidden=!1}):Promise.resolve(window.confirm(`Apply Structure Sync?\n\nThis will:\n\n- Link ${e.linkChapters+e.linkScenes} chapters/scenes\n- Create ${e.createChapters} chapters\n- Create ${e.createScenes} scenes\n\nManual review items will be skipped.`))},uo=(e,t,r="")=>{e.result=t,e.error=r},po=e=>Number.isInteger(e?.wordChapter?.index)&&e.wordChapter.index>0?10*e.wordChapter.index:null,ho=e=>Number.isInteger(e?.wordScene?.index)&&e.wordScene.index>0?10*e.wordScene.index:null,mo=async(e,t)=>{const r=await wo(`/api/word-companion/books/${e}/chapters`,{title:un(t.wordTitle),sortOrder:po(t)});if(!r?.chapterId)throw new Error("Chapter creation did not return a chapter ID.");t.pdChapter={chapterId:r.chapterId,title:r.title||t.wordTitle,sortOrder:r.sortOrder||po(t)||0,scenes:[]},t.match=`Chapter ${t.pdChapter.chapterId}: ${t.pdChapter.title}`},yo=async(e,t)=>{const r=t.pdChapter||t.parentItem?.pdChapter;if(!r?.chapterId)throw new Error("Scene parent chapter is not available.");const n=await wo(`/api/word-companion/books/${e}/chapters/${r.chapterId}/scenes`,{sceneTitle:un(t.wordTitle),sortOrder:ho(t)});if(!n?.sceneId)throw new Error("Scene creation did not return a scene ID.");t.pdChapter=r,t.pdScene={sceneId:n.sceneId,title:t.wordTitle,sortOrder:ho(t)||0},t.match=`Scene ${t.pdScene.sceneId}: ${t.pdScene.title}`},fo=async(e,t={})=>{const r=await window.fetch(e,{credentials:"same-origin",...t,headers:{Accept:"application/json",...t.headers||{}}});if(!r.ok)throw new Error(`Request failed: ${r.status}`);return await r.json()},wo=(e,t)=>fo(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}),So=()=>{$n(!1),An(""),Wr(v,!0)},go=async()=>{if(!Ut||!Bt)return void $n(!1);const r=(()=>{const e=window.Office?.context?.document?.settings;if(!e)return null;const t=String(e.get(n)||"").trim(),r=Number.parseInt(e.get(o)||"",10),i=Number.parseInt(e.get(a)||"",10),s=Number.parseInt(e.get(c)||"",10);return!t||!Number.isInteger(r)||r<=0||!Number.isInteger(i)||i<=0?null:{documentGuid:t,bookId:r,projectId:i,bindingVersion:Number.isInteger(s)&&s>0?s:1}})();if(r)try{const n=await fo(`/api/word-companion/manuscript/book/${r.bookId}`),o=n?.manuscriptDocument;if(o&&String(o.documentGuid).toLowerCase()===r.documentGuid.toLowerCase())return dr=r,vn(e,r.projectId),vn(t,r.bookId),U&&(U.value=String(r.projectId)),await Uo(r.projectId,r.bookId),$n(!1),void xr("Connected")}catch{}dr=null,jn(),Pn()?await Uo(Pn().projectId,null):En(m,"Select a project first"),Rn("Select a Project and Book to begin."),$n(!0)},Co=e=>e?[...e.querySelectorAll("input[type='checkbox']:checked")].map(e=>Number.parseInt(e.value||"",10)).filter(e=>Number.isInteger(e)&&e>0):[],bo=()=>{const e=Number.parseInt(Le?.value||"",10);return Number.isInteger(e)&&e>0?e:null},Io=(e,t,r,n)=>{const o=((e,t)=>(Array.isArray(e?.contentControls?.items)?e.contentControls.items:[]).find(e=>Gn(e.tag,t))||null)(e,n),a=o||e.getRange().insertContentControl();return a.title=t,a.tag=r,a.appearance="Hidden",a},ko=async(e="PlotDirector IDs attached successfully.")=>{if(!Xt||!Zt)return Ar("No resolved PlotDirector scene."),!1;if((Qt&&Qt!==Xt||Kt&&Kt!==Zt)&&!window.confirm("This scene is already linked. Replace the existing PlotDirector link?"))return!1;if(!Ht||!Bt||!window.Word||"function"!=typeof window.Word.run)return Ar("Word document access is unavailable."),!1;ie&&(ie.disabled=!0,ie.textContent="Attaching...");try{return await window.Word.run(async e=>{const t=await ao(e);if(!t.currentChapter||!t.currentScene)throw new Error("No scene detected in Word. Use Heading 2 for scenes.");const r=t.bodyParagraphs[t.currentChapter.paragraphIndex],n=t.bodyParagraphs[t.currentScene.paragraphIndex];if(!r||!n)throw new Error("Unable to locate the current Word headings.");Io(r,"PlotDirector Chapter",`PD-CHAPTER-${Zt}`,"PD-CHAPTER"),Io(n,"PlotDirector Scene",`PD-SCENE-${Xt}`,"PD-SCENE"),await e.sync()}),Kt=Zt,Qt=Xt,tr=!1,er="SceneID Anchor",_t="Anchor",Ar(e),Cn({lastError:"-"}),jr(),!0}catch(e){return console.error("Unable to attach PlotDirector IDs.",e),Ar("Unable to attach PlotDirector IDs."),Cn({lastError:bn(e)}),jr(),!1}finally{ie&&(ie.textContent=Qt===Xt?"Attach PlotDirector IDs":"Reattach PlotDirector IDs",jr())}},vo=async e=>{if(!Zt)return _r("No resolved PlotDirector chapter."),!1;if(!Ht||!Bt||!window.Word||"function"!=typeof window.Word.run)return _r("Word document access is unavailable."),!1;try{return await window.Word.run(async e=>{const t=await ao(e);if(!t.currentChapter)throw new Error("No chapter detected in Word. Use Heading 1 for chapters.");const r=t.bodyParagraphs[t.currentChapter.paragraphIndex];if(!r)throw new Error("Unable to locate the current Word chapter heading.");Io(r,"PlotDirector Chapter",`PD-CHAPTER-${Zt}`,"PD-CHAPTER"),await e.sync()}),Kt=Zt,tr=!1,er="ChapterID Anchor",_t="Chapter anchor",_r(e),Ar(e),Cn({lastError:"-"}),jr(),!0}catch(e){return console.error("Unable to attach PlotDirector chapter ID.",e),_r("Unable to attach PlotDirector chapter ID."),Cn({lastError:bn(e)}),jr(),!1}},Eo=async e=>{rn(),await $o(),Ar(e),_r(e)},Lo=e=>{ir&&(ir(e),ir=null),ot?.close?ot.close():ot&&(ot.hidden=!0)},No=()=>{if(!et)return;const e=un(_e?.value||"").toLocaleLowerCase(),t=ar.filter(t=>!e||String(t.title||"").toLocaleLowerCase().includes(e));if(et.innerHTML="",cr=null,tt&&(tt.disabled=!0),0===t.length){const e=document.createElement("p");return e.className="word-companion-empty-list",e.textContent="No chapters found.",void et.append(e)}for(const e of t){const t=Number.parseInt(e.chapterId||"",10);if(!Number.isInteger(t)||t<=0)continue;const r=document.createElement("label");r.className="word-companion-scene-option";const n=document.createElement("input");n.type="radio",n.name="word-companion-link-chapter",n.value=String(t),n.addEventListener("change",()=>{cr=t,tt&&(tt.disabled=!1)});const o=document.createElement("span");o.textContent=e.title||"Untitled chapter",r.append(n,o),et.append(r)}},qo=()=>{Ze?.close?Ze.close():Ze&&(Ze.hidden=!0)},xo=async(e,t,r)=>{const n=xn();if(!n)return Zr("Select a PlotDirector book first."),!1;await Sn(n.bookId,e,t,"Manual link","Title Match");return!!await ko(r)&&(Zr(r),on(),!0)},Po=e=>{or&&(or(e),or=null),Ye?.close?Ye.close():Ye&&(Ye.hidden=!0)},Do=()=>{if(!Fe)return;const e=un(Be?.value||"").toLocaleLowerCase(),t=rr.filter(t=>!e||String(t.title||"").toLocaleLowerCase().includes(e));if(Fe.innerHTML="",nr=null,Ge&&(Ge.disabled=!0),0===t.length){const e=document.createElement("p");return e.className="word-companion-empty-list",e.textContent="No scenes found.",void Fe.append(e)}for(const e of t){const t=Number.parseInt(e.sceneId||"",10);if(!Number.isInteger(t)||t<=0)continue;const r=document.createElement("label");r.className="word-companion-scene-option";const n=document.createElement("input");n.type="radio",n.name="word-companion-link-scene",n.value=String(t),n.addEventListener("change",()=>{nr=t,Ge&&(Ge.disabled=!1)});const o=document.createElement("span");o.textContent=e.title||"Untitled scene",r.append(n,o),Fe.append(r)}},Ao=()=>{He?.close?He.close():He&&(He.hidden=!0)},To=async()=>{const e=qn(),t=xn(),r=pn(Vt,"chapter");if(hn({projectId:e?.projectId,projectTitle:e?.title,bookId:t?.bookId,bookTitle:t?Nn(t):void 0,detectedChapter:Vt,detectedScene:Jt,requestChapter:r,requestScene:"",result:"Not run",chapterId:null,sceneId:null}),!t)return cn("Not detected"),Ar("Select a PlotDirector book first."),!1;if(!Vt)return cn("Not detected"),Ar("No chapter detected in Word. Use Heading 1 for chapters."),!1;cn("Not detected");try{const e=await yn(t.bookId),n=Kt?e.find(e=>e.chapterId===Kt):null,o=r.toLocaleLowerCase(),a=o?e.find(e=>pn(e.title,"chapter").toLocaleLowerCase()===o):null,c=n||a;return c?(rn(),zr(null,c.chapterId,n?"Chapter anchor":"Chapter title"),er=n?"ChapterID Anchor":"Title Match",Tr("Chapter linked to PlotDirector"),Ar("No scene detected in Word. Use Heading 2 for scenes."),hn({result:"Chapter matched",chapterId:c.chapterId,sceneId:null}),!0):(zr(null),Tr("Chapter not found in PlotDirector."),Ar("Chapter not found in PlotDirector."),hn({result:"Chapter not matched",chapterId:null,sceneId:null}),nn("Chapter not found in PlotDirector."),!1)}catch(e){return cn("Not found in PlotDirector"),Cn({lastError:bn(e)}),Ar("Unable to load PlotDirector chapter data."),!1}},$o=async()=>{const e=qn(),t=xn(),r=pn(Vt,"chapter"),n=pn(Jt,"scene");if(hn({projectId:e?.projectId,projectTitle:e?.title,bookId:t?.bookId,bookTitle:t?Nn(t):void 0,detectedChapter:Vt,detectedScene:Jt,requestChapter:r,requestScene:n,result:"Not run",chapterId:null,sceneId:null}),$r({anchorType:Qt?"SceneID Anchor":Kt?"ChapterID Anchor":"Title Match",storedSceneId:Qt,storedChapterId:Kt,resolutionMethod:"-"}),!t)return cn("Not detected"),Ar("Select a PlotDirector book first."),hn({result:"Error"}),!1;if(!Vt||!Jt)return cn("Not detected"),Ar("No scene detected in Word. Use Heading 2 for scenes."),hn({result:"Error"}),!1;te&&(te.disabled=!0,te.textContent="Refreshing...");const o=()=>{te&&(te.disabled=!1,te.textContent="Refresh PlotDirector Scene")};cn("Not detected"),Ar("Resolving PlotDirector scene...");try{if(Qt){const e=await(async(e,t)=>{const r=await fo(`/api/word-companion/books/${e}/structure`),n=Array.isArray(r?.chapters)?r.chapters:[];for(const e of n){const r=Array.isArray(e.scenes)?e.scenes:[];for(const n of r)if(t(e,n))return{chapter:e,scene:n}}return null})(t.bookId,(e,t)=>t.sceneId===Qt);if(e)return hn({result:"Matched",chapterId:e.chapter.chapterId,sceneId:e.scene.sceneId}),await Sn(t.bookId,e.scene.sceneId,e.chapter.chapterId,"Anchor","SceneID Anchor"),!0;tr=!0,er="SceneID Anchor",Tr("Not found in PlotDirector"),Ar("Stored PlotDirector ID is invalid."),hn({result:"Error",chapterId:Kt,sceneId:Qt}),$r({anchorType:"SceneID Anchor",storedSceneId:Qt,storedChapterId:Kt,resolutionMethod:"Anchor"})}if(Kt){const e=(await mn(t.bookId)).find(e=>e.chapterId===Kt),r=e?(Array.isArray(e.scenes)?e.scenes:[]).find(e=>pn(e.title,"scene").toLocaleLowerCase()===n.toLocaleLowerCase()):null;if(r)return hn({result:"Matched",chapterId:e.chapterId,sceneId:r.sceneId}),await Sn(t.bookId,r.sceneId,e.chapterId,"Anchor","ChapterID Anchor"),!0;e&&!Qt?(er="ChapterID Anchor",zr(null,Kt,"Chapter anchor"),hn({result:"Chapter matched",chapterId:Kt,sceneId:null})):Qt||(er="ChapterID Anchor",hn({result:"Chapter anchor not found",chapterId:Kt,sceneId:null}))}const e=await wo(`/api/word-companion/books/${t.bookId}/resolve-scene`,{chapterTitle:r,sceneTitle:n});if(!e?.matched||!e.sceneId){const t=tr,r=Number.parseInt(e?.chapterId||"",10),n=Number.isInteger(Zt)&&Zt>0?Zt:null,a=Number.isInteger(r)&&r>0?r:n,c=!!e?.chapterMatched||!!a;return cn("Not found in PlotDirector"),tr=t,c&&(zr(null,a,a===n?"Chapter anchor":"Chapter title"),Tr("Scene not found in PlotDirector.")),Ar(t?"Stored PlotDirector ID is invalid.":c?"Scene not found in PlotDirector.":"This chapter does not exist in PlotDirector. Create or link the chapter first."),hn({result:"Not matched",chapterId:c?a:e?.chapterId,sceneId:e?.sceneId}),t||(c?(rn(),an("Scene not found in PlotDirector.")):(on(),nn("Chapter not found in PlotDirector."))),o(),!1}const a=tr;return hn({result:a?"Matched by title fallback":"Matched",chapterId:e.chapterId,sceneId:e.sceneId}),await Sn(t.bookId,e.sceneId,e.chapterId,a?"Title fallback":"Title","Title Match"),a&&(tr=!0,Ar("Stored PlotDirector ID is invalid."),jr()),!0}catch(e){const t=tr;return Cn({lastError:bn(e)}),cn("Not found in PlotDirector"),tr=t,Ar(t?"Stored PlotDirector ID is invalid.":"Unable to load PlotDirector scene data."),hn({result:"Error"}),!1}finally{o()}},jo=async()=>{if(!Ir&&Ut&&xn()){if(!Ht||!Bt||!window.Word||"function"!=typeof window.Word.run)return Jr("Manual"),void Ar("Automatic scene tracking is unavailable in this Word version. Use Refresh Current Scene.");Ir=!0,Jr("Refreshing"),Ar("Updating current scene...");try{const e=await window.Word.run(async e=>await ao(e)),t=(e=>{const t=e.currentChapter?.title||"",r=e.currentScene?.title||"",n=e.currentChapter?.anchorId||null,o=e.currentScene?.anchorId||null;return pn(t,"chapter")!==pn(Vt,"chapter")||pn(r,"scene")!==pn(Jt,"scene")||n!==Kt||o!==Qt})(e);if(Rr(e.currentChapter?.title,e.currentScene?.title,e.currentScene?.wordCount,e.currentChapter?.anchorId,e.currentScene?.anchorId,e.currentChapter?.index),Yn(e),Cn({lastScan:"Success",lastError:"-",paragraphs:String(e.paragraphCount),heading1:String(e.heading1Count),heading2:String(e.heading2Count)}),!t)return Yr(!1),Jr("Live"),void Ar("Current scene updated.");Jt?await $o():await To(),Yr(!1),Jr("Live"),Ar("Current scene updated.")}catch(e){console.error("Unable to refresh current scene from Word selection.",e),Cn({lastScan:"Failure",lastError:bn(e)}),Yr(!0,"The Word cursor is now in a different scene. Refresh Current Scene before saving.")}finally{Ir=!1}}},Ro=()=>{Cr&&window.clearTimeout(Cr),Cr=window.setTimeout(jo,850)},Wo=()=>{if(br&&window.Office?.context?.document&&"function"==typeof window.Office.context.document.removeHandlerAsync&&window.Office?.EventType?.DocumentSelectionChanged)try{window.Office.context.document.removeHandlerAsync(window.Office.EventType.DocumentSelectionChanged,{handler:Ro}),br=!1}catch(e){console.warn("Unable to remove Word selection tracking handler.",e)}},Uo=async(e,r)=>{if(!e)return Ot=[],En(M,"Select a project first"),En(m,"Select a project first"),Dr(""),vn(t,null),On(),cn("Not detected"),void Or();En(M,"Loading books..."),Dr(""),cn("Not detected"),Or("Select a book to analyse manuscript structure.");try{const n=await fo(`/api/word-companion/projects/${e}/books`);if(Ot=Array.isArray(n.books)?n.books:[],0===Ot.length)return En(M,"No books available."),En(m,"No books available."),Dr("No books available."),vn(t,null),On(),void Rn("No books available.");Ln(M,"Choose a book",Ot.map(e=>({...e,displayTitle:Nn(e)})),"bookId","displayTitle");const o=Ot.find(e=>e.bookId===r);o&&M?(M.value=String(o.bookId),vn(t,o.bookId)):vn(t,null),((e=null)=>{if(!m)return;if(0===Ot.length)return void En(m,"No books available.");Ln(m,"Choose a book",Ot.map(e=>({...e,displayTitle:Nn(e)})),"bookId","displayTitle");const t=e||Number.parseInt(M?.value||"",10),r=Ot.find(e=>e.bookId===t);r&&(m.value=String(r.bookId)),Tn()})(o?.bookId||r),On(),cn((xn(),"Not detected")),Or(xn()?"Ready to analyse manuscript structure.":"Select a book to analyse manuscript structure."),Rn(Dn()?"Ready to scan manuscript structure.":"Select a Book to begin.")}catch{Ot=[],En(M,"Unable to load books."),En(m,"Unable to load books."),Dr("Unable to load books."),vn(t,null),On(),cn("Not detected"),Or("Unable to load books."),Rn("Unable to load books.")}};for(const e of l)e.addEventListener("click",()=>Nr(e.dataset.tabButton));qr(),U?.addEventListener("change",async()=>{const r=Number.parseInt(U.value||"",10);h&&Number.isInteger(r)&&r>0&&(h.value=String(r)),vn(e,Number.isInteger(r)&&r>0?r:null),vn(t,null),cn("Not detected"),Or(),Rn("Select a Book to begin."),await Uo(r,null)}),M?.addEventListener("change",()=>{const e=Number.parseInt(M.value||"",10);vn(t,Number.isInteger(e)&&e>0?e:null),m&&Number.isInteger(e)&&e>0&&(m.value=String(e)),On(),cn("Not detected"),Or(xn()?"Ready to analyse manuscript structure.":"Select a book to analyse manuscript structure."),Rn(Dn()?"Ready to scan manuscript structure.":"Select a Book to begin.")}),h?.addEventListener("change",async()=>{const r=Number.parseInt(h.value||"",10);U&&Number.isInteger(r)&&r>0&&(U.value=String(r)),vn(e,Number.isInteger(r)&&r>0?r:null),vn(t,null),Rn("Select a Book to begin."),await Uo(r,null)}),m?.addEventListener("change",()=>{const e=Number.parseInt(m.value||"",10);M&&Number.isInteger(e)&&e>0&&(M.value=String(e)),vn(t,Number.isInteger(e)&&e>0?e:null),On(),Rn(Dn()?"Ready to scan manuscript structure.":"Select a Book to begin.")}),y?.addEventListener("input",Tn),f?.addEventListener("click",async()=>{const e=Pn(),t=String(y?.value||"").trim();if(e&&t){f.disabled=!0,An("Creating Book...");try{const r=await wo(`/api/word-companion/projects/${e.projectId}/books`,{title:t});y&&(y.value=""),U&&(U.value=String(e.projectId)),await Uo(e.projectId,r.bookId),m&&(m.value=String(r.bookId)),An("Ready to scan manuscript structure.")}catch(e){console.error("Unable to create Book from Word Companion.",e),An(`Unable to create Book: ${bn(e)}`)}finally{Tn()}}else Tn()}),w?.addEventListener("click",async()=>{const e=Pn(),t=Dn();if(e&&t)if(Ht&&Bt&&window.Word&&"function"==typeof window.Word.run){w&&(w.disabled=!0,w.textContent="Scanning..."),An("Scanning manuscript structure...");try{const r=await window.Word.run(async e=>{const r=e.document.body.paragraphs;return r.load("text,styleBuiltIn,style"),await e.sync(),((e,t)=>{const r=[];let n=null,o=null,a=0;const c=[],i=new Set(["***","###"]),s=()=>{if(!n)return null;const e={title:`Scene ${n.scenes.length+1}`,sortOrder:10*(n.scenes.length+1),wordCount:0};return n.scenes.push(e),e};return e.forEach(e=>{const d=String(e.text||"").trim();if(!d)return;if(c.push(d),Bn(e,1))return n={title:d,sortOrder:10*(r.length+1),wordCount:0,scenes:[]},r.push(n),o=s(),void(a+=Fn(d));if(!n||!o)return;if(t&&i.has(d))return void(o=s());const l=Fn(d);n.wordCount+=l,o.wordCount+=l,a+=l}),{chapters:r,chapterCount:r.length,sceneCount:r.reduce((e,t)=>e+t.scenes.length,0),wordCount:a,documentText:c.join("\n")}})(r.items,!!t.usesExplicitScenes)});ur=r,hr=!1;const n=await wo("/api/word-companion/manuscript/analyse",{projectId:e.projectId,bookId:t.bookId,documentGuid:Mn(),chapterCount:r.chapterCount,sceneCount:r.sceneCount,wordCount:r.wordCount});lr=n,(e=>{if(!C)return;C.innerHTML="";const t=document.createElement("strong");t.textContent="Manuscript Analysis",C.append(t);const r=document.createElement("dl"),n=[["Project",e.projectTitle],["Book",Nn({title:e.bookTitle,subtitle:e.bookSubtitle})],["Chapters",Number(e.chapterCount||0).toLocaleString()],["Scenes",Number(e.sceneCount||0).toLocaleString()],["Words",Number(e.wordCount||0).toLocaleString()]];for(const[e,t]of n){const n=document.createElement("dt");n.textContent=e;const o=document.createElement("dd");o.textContent=t||"-",r.append(n,o)}C.append(r),Wr(C,!1),Wr(N,!1),An(e.message||"Preview generated."),Tn()})(n);try{const t=await wo("/api/word-companion/manuscript/discover-characters",{projectId:e.projectId,documentText:r.documentText||""});Un(t?.candidates||[])}catch(e){console.error("Unable to discover character candidates.",e),Un([]),gn(I,"Character discovery is unavailable.")}Cn({lastScan:"Success",lastError:"-",paragraphs:"-",heading1:String(r.chapterCount),heading2:"-"})}catch(e){console.error("Unable to scan manuscript for first-run import.",e),Rn(`Unable to scan manuscript: ${bn(e)}`),Cn({lastScan:"Failure",lastError:bn(e)})}finally{w&&(w.textContent="Scan Manuscript"),Tn()}}else Rn("Word document access is unavailable.");else Rn("Select a Project and Book to begin.")}),q?.addEventListener("click",async()=>{const r=Pn(),i=Dn();if(!(r&&i&&ur&&lr?.canImport))return void Tn();let s=!1;if(!lr.requiresReplaceConfirmation||(s=await new Promise(e=>{if(!P||"function"!=typeof P.showModal)return void e(window.confirm("This Book already contains planned chapters and scenes.\n\nImporting this manuscript will replace the planned structure.\n\nContinue?"));const t=t=>{D?.removeEventListener("click",r),A?.removeEventListener("click",n),P?.removeEventListener("cancel",o),P?.close(),e(t)},r=()=>t(!0),n=()=>t(!1),o=e=>{e.preventDefault(),t(!1)};D?.addEventListener("click",r),A?.addEventListener("click",n),P?.addEventListener("cancel",o),P.showModal()}),s)){mr=!0,Tn(),An("Importing manuscript structure...");try{const l=Mn(),u=await wo("/api/word-companion/manuscript/import",{projectId:r.projectId,bookId:i.bookId,documentGuid:l,bindingVersion:1,replacePlanned:s,chapters:ur.chapters});if(!u.imported)return lr={...lr,canImport:!u.requiresReplaceConfirmation,requiresReplaceConfirmation:!!u.requiresReplaceConfirmation,message:u.message||lr.message},An(u.message||"Import was not completed."),void Tn();const p=u.manuscriptDocument;await(d={documentGuid:p?.documentGuid||l,bookId:u.bookId,projectId:u.projectId,bindingVersion:p?.bindingVersion||1},new Promise((e,t)=>{const r=window.Office?.context?.document?.settings;r?(r.set(n,d.documentGuid),r.set(o,String(d.bookId)),r.set(a,String(d.projectId)),r.set(c,String(d.bindingVersion||1)),r.saveAsync(r=>{r.status===window.Office.AsyncResultStatus.Succeeded?e():t(r.error||new Error("Unable to save Word document metadata."))})):t(new Error("Word document settings are unavailable."))})),dr={documentGuid:p?.documentGuid||l,bookId:u.bookId,projectId:u.projectId,bindingVersion:p?.bindingVersion||1},vn(e,u.projectId),vn(t,u.bookId),U&&(U.value=String(u.projectId));const h=pr;await Uo(u.projectId,u.bookId),xr("Connected"),hr=!0,pr=h,h.length>0?($n(!0),Un(h),Wr(N,!0),Wr(v,!1),An(u.message||"Manuscript structure imported."),Ar(u.message||"Manuscript structure imported.")):($n(!1),Ar(u.message||"Manuscript structure imported."))}catch(e){console.error("Unable to import manuscript structure.",e),An(`Unable to import manuscript: ${bn(e)}`)}finally{mr=!1,Tn()}var d}else An("Import cancelled.")}),E?.addEventListener("click",async()=>{const e=Pn()||qn(),t=Wn();if(e&&0!==t.length){yr=!0,Tn(),gn(I,"Creating selected characters...");try{const r=await wo("/api/word-companion/manuscript/create-discovered-characters",{projectId:e.projectId,candidateNames:t});Ar(r.message||"Characters created."),gn(I,`${r.createdCount||0} created, ${r.skippedCount||0} already existed.`),So()}catch(e){console.error("Unable to create discovered characters.",e),gn(I,`Unable to create characters: ${bn(e)}`)}finally{yr=!1,Tn()}}else Tn()}),L?.addEventListener("click",So),S?.addEventListener("click",()=>$n(!1)),x?.addEventListener("click",()=>Rn("Import cancelled.")),F?.addEventListener("click",co),X?.addEventListener("click",io),Z?.addEventListener("click",async()=>{const e=xn();if(!e||0===Hr().length||fr)return void Br();if(!await lo())return;fr=!0,Fr(),Mr("Applying structure sync...");const t={createdChapters:0,createdScenes:0,linkedChapters:0,linkedScenes:0,skipped:Array.isArray(sr?.manualReview)?sr.manualReview.length:0,failed:0},r=Hr().filter(e=>"couldLink"===e.category&&"Chapter"===e.type),n=Hr().filter(e=>"wouldCreateChapters"===e.category),o=Hr().filter(e=>"couldLink"===e.category&&"Scene"===e.type),a=Hr().filter(e=>"wouldCreateScenes"===e.category),c=[];let i="";const s=(e,t)=>{c.push({item:e,counterName:t})},d=async(e,r)=>{try{await(async e=>{if(!Ht||!Bt||!window.Word||"function"!=typeof window.Word.run)throw new Error("Word document access is unavailable.");await window.Word.run(async t=>{const r=await ao(t),n="Chapter"===e.type?e.wordChapter:e.wordScene,o=Number.isInteger(n?.paragraphIndex)?r.bodyParagraphs[n.paragraphIndex]:null;if(!o)throw new Error("Unable to locate the Word heading.");if("Chapter"===e.type){const t=e.pdChapter?.chapterId;if(!t)throw new Error("Chapter ID is not available.");Io(o,"PlotDirector Chapter",`PD-CHAPTER-${t}`,"PD-CHAPTER")}else{const t=e.pdScene?.sceneId;if(!t)throw new Error("Scene ID is not available.");Io(o,"PlotDirector Scene",`PD-SCENE-${t}`,"PD-SCENE")}await t.sync()})})(e),uo(e,"Success"),t[r]+=1}catch(r){uo(e,"Failed",bn(r)),t.failed+=1}};try{for(const e of r)s(e,"linkedChapters");for(const r of n)try{await mo(e.bookId,r),s(r,"createdChapters")}catch(e){uo(r,"Failed",bn(e)),t.failed+=1}for(const e of o)s(e,"linkedScenes");for(const r of a)try{await yo(e.bookId,r),s(r,"createdScenes")}catch(e){uo(r,"Failed",bn(e)),t.failed+=1}for(const e of c)await d(e.item,e.counterName);for(const e of sr.manualReview||[])uo(e,"Skipped");oo(sr),i=(e=>`Structure Sync Complete. Created: ${e.createdChapters} Chapters, ${e.createdScenes} Scenes. Linked: ${e.linkedChapters} Chapters, ${e.linkedScenes} Scenes. Skipped: ${e.skipped} Manual Review items. Failed: ${e.failed} Items.`)(t),Mr(i)}finally{fr=!1,Fr(),i&&(await io(),Mr(`${i} Preview refreshed.`))}}),ut?.addEventListener("click",()=>so(!0)),pt?.addEventListener("click",()=>so(!1)),dt?.addEventListener("cancel",e=>{e.preventDefault(),so(!1)}),te?.addEventListener("click",$o),B?.addEventListener("click",async()=>{if(!xn())return Ar("Select a PlotDirector book first."),void cn("Not detected");Kr(!0);try{if(!await co())return;if(Yr(!1),!Jt)return void await To();await $o()}finally{Kr(!1)}}),fe?.addEventListener("click",async()=>{if(!Xt)return void Ur("No resolved PlotDirector scene.");if(gr)return void Ur("Refresh Current Scene before syncing.");if(!Number.isInteger(Yt))return void Ur("Unable to sync progress.");fe&&(fe.disabled=!0,fe.textContent="Syncing...");const e=(new Date).toISOString();try{const n=await(t=`/api/word-companion/scenes/${Xt}/word-count`,r={actualWordCount:Yt,lastWorkedOn:e},fo(t,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)}));gn(Se,Qr(n?.actualWords??Yt)),gn(pe,Qr(n?.actualWords??Yt)),gn(ge,(new Date).toLocaleString()),Ur("Progress synced successfully.")}catch{Ur("Unable to sync progress.")}finally{fe&&(fe.disabled=!Xt||gr,fe.textContent="Sync Progress")}var t,r}),Ne?.addEventListener("click",async()=>{if(Xt)if(!gr&&await(async()=>{if(!Xt)return!1;if(!Ht||!Bt||!window.Word||"function"!=typeof window.Word.run)return Yr(!0,"The Word cursor is now in a different scene. Refresh Current Scene before saving."),!1;try{const e=await window.Word.run(async e=>await ao(e)),t=e.currentChapter?.title||"",r=e.currentScene?.title||"",n=e.currentScene?.anchorId||null,o=e.currentChapter?.anchorId||null,a=Number.isInteger(n)&&n===Xt,c=Number.isInteger(o)&&o===Zt,i=pn(r,"scene").toLocaleLowerCase()===pn(kr||Jt,"scene").toLocaleLowerCase(),s=pn(t,"chapter").toLocaleLowerCase()===pn(vr||Vt,"chapter").toLocaleLowerCase();return a||i&&(c||s)?(Yr(!1),!0):(Yr(!0,"The Word cursor is now in a different scene. Refresh Current Scene before saving."),!1)}catch(e){return console.error("Unable to verify current Word scene before saving.",e),Cn({lastError:bn(e)}),Yr(!0,"The Word cursor is now in a different scene. Refresh Current Scene before saving."),!1}})()){Ne&&(Ne.disabled=!0,Ne.textContent="Saving...");try{await(e=`/api/word-companion/scenes/${Xt}/links`,t={characterIds:Co(ve),assetIds:Co(Ee),locationIds:[],primaryLocationId:bo()},fo(e,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})),(()=>{const e=new Set(Co(ve)),t=new Set(Co(Ee));Er={characters:Er.characters.map(t=>({...t,linked:e.has(Number.parseInt(sn(t,"character"),10))})),assets:Er.assets.map(e=>({...e,linked:t.has(Number.parseInt(sn(e,"asset"),10))})),locations:Er.locations,primaryLocationId:bo()}})(),Xr("Scene links saved successfully."),Cn({lastError:"-"})}catch(e){Xr("Unable to save scene links."),Cn({lastError:bn(e)})}finally{Ne&&(Ne.disabled=!Xt||gr,Ne.textContent="Save Scene Links")}var e,t}else Xr("The Word cursor is now in a different scene. Refresh Current Scene before saving.");else Xr("Link a PlotDirector scene first.")}),ie?.addEventListener("click",async()=>{await ko()}),Ae?.addEventListener("click",async()=>{const e=xn();if(!e||!Vt||Zt)return void nn("Chapter not found in PlotDirector.");const t=un(Vt),r=await((e,t)=>(gn(at,`"${e}"`),gn(ct,`"${t}"`),ot?new Promise(e=>{ir=e,ot.showModal?ot.showModal():ot.hidden=!1}):Promise.resolve(window.confirm(`Create PlotDirector chapter:\n\n"${e}"\n\nin book:\n\n"${t}"\n\n?`))))(t,Nn(e)||"selected book");if(r){Ae&&(Ae.disabled=!0,Ae.textContent="Creating...");try{const r=Number.isInteger(zt)&&zt>0?10*zt:null,n=await wo(`/api/word-companion/books/${e.bookId}/chapters`,{title:t,sortOrder:r});if(!n?.chapterId)throw new Error("Chapter creation did not return a chapter ID.");zr(null,n.chapterId,"Manual chapter link");if(!await vo("Chapter created and linked successfully."))return;await Eo("Chapter created and linked successfully.")}catch(e){_r("Unable to create chapter."),Cn({lastError:bn(e)})}finally{Ae&&(Ae.disabled=!en(),Ae.textContent="Create Chapter in PlotDirector")}}}),Te?.addEventListener("click",async()=>{const e=xn();if(e&&Vt&&!Zt){Te&&(Te.disabled=!0,Te.textContent="Loading...");try{ar=await yn(e.bookId),cr=null,_e&&(_e.value=""),gn(nt,""),No(),Ze?.showModal?Ze.showModal():Ze&&(Ze.hidden=!1)}catch(e){_r("Unable to load chapters."),Cn({lastError:bn(e)})}finally{Te&&(Te.disabled=!en(),Te.textContent="Link to Existing Chapter")}}else nn("Chapter not found in PlotDirector.")}),_e?.addEventListener("input",No),tt?.addEventListener("click",async()=>{const e=ar.find(e=>e.chapterId===cr);if(e){tt&&(tt.disabled=!0,tt.textContent="Linking...");try{zr(null,e.chapterId,"Manual chapter link");if(!await vo("Chapter linked successfully."))return;qo(),await Eo("Chapter linked successfully.")}catch(e){gn(nt,"Unable to link chapter."),_r("Unable to link chapter."),Cn({lastError:bn(e)})}finally{tt&&(tt.disabled=!cr,tt.textContent="Link Chapter")}}else gn(nt,"Select a chapter.")}),rt?.addEventListener("click",qo),it?.addEventListener("click",()=>Lo(!0)),st?.addEventListener("click",()=>Lo(!1)),ot?.addEventListener("cancel",e=>{e.preventDefault(),Lo(!1)}),Ue?.addEventListener("click",async()=>{const e=xn();if(!e||!Jt)return void an("Scene not found in PlotDirector.");const t=pn(Jt,"scene"),r=pn(Vt,"chapter"),n=await((e,t)=>(gn(ze,`"${e}"`),gn(Ke,`"${t}"`),Ye?new Promise(e=>{or=e,Ye.showModal?Ye.showModal():Ye.hidden=!1}):Promise.resolve(window.confirm(`Create PlotDirector scene:\n\n"${e}"\n\nwithin chapter:\n\n"${t}"\n\n?`))))(t,r);if(n){Ue&&(Ue.disabled=!0,Ue.textContent="Creating...");try{const r=await wn();if(!r)return void an("This chapter does not exist in PlotDirector. Create or link the chapter first.");const n=await wo(`/api/word-companion/books/${e.bookId}/chapters/${r.chapterId}/scenes`,{sceneTitle:t});if(!n?.sceneId||!n?.chapterId)throw new Error("Scene creation did not return a scene ID.");await xo(n.sceneId,n.chapterId,"Scene created and linked successfully.")}catch(e){Zr("Unable to create scene."),Cn({lastError:bn(e)})}finally{Ue&&(Ue.disabled=!tn(),Ue.textContent="Create Scene in PlotDirector")}}}),Me?.addEventListener("click",async()=>{const e=xn();if(e&&Jt){Me&&(Me.disabled=!0,Me.textContent="Loading...");try{const t=await mn(e.bookId),r=fn(t);if(!r)return void an("This chapter does not exist in PlotDirector. Create or link the chapter first.");rr=Array.isArray(r.scenes)?r.scenes:[],nr=null,Be&&(Be.value=""),gn(Je,""),Do(),He?.showModal?He.showModal():He&&(He.hidden=!1)}catch(e){Zr("Unable to load scenes."),Cn({lastError:bn(e)})}finally{Me&&(Me.disabled=!tn(),Me.textContent="Link to Existing Scene")}}else an("Scene not found in PlotDirector.")}),Be?.addEventListener("input",Do),Ge?.addEventListener("click",async()=>{const e=xn(),t=rr.find(e=>e.sceneId===nr);if(e&&t){Ge&&(Ge.disabled=!0,Ge.textContent="Linking...");try{const e=await wn();if(!e)throw new Error("This chapter does not exist in PlotDirector. Create or link the chapter first.");Ao(),await xo(t.sceneId,e.chapterId,"Scene linked successfully.")}catch(e){gn(Je,"Unable to link scene."),Zr("Unable to link scene."),Cn({lastError:bn(e)})}finally{Ge&&(Ge.disabled=!nr,Ge.textContent="Link Scene")}}else gn(Je,"Select a scene.")}),Ve?.addEventListener("click",Ao),Qe?.addEventListener("click",()=>Po(!0)),Xe?.addEventListener("click",()=>Po(!1)),Ye?.addEventListener("cancel",e=>{e.preventDefault(),Po(!1)}),vt?.addEventListener("click",async()=>{vt&&(vt.disabled=!0,vt.textContent="Running...");try{if(await In(),!Ht||!Bt||!window.Word||"function"!=typeof window.Word.run)return void Cn({lastScan:"Failure",lastError:"Word document access is unavailable.",paragraphs:"-",heading1:"-",heading2:"-"});const e=await window.Word.run(async e=>{const t=e.document.body.paragraphs;return t.load("items"),await e.sync(),t.items.length});Cn({lastScan:"Success",lastError:"-",paragraphs:String(e)})}catch(e){console.error("Word Companion diagnostics failed.",e);const t=bn(e);Cn({lastScan:"Failure",lastError:t}),Ar(`Unable to scan the Word document: ${t}`)}finally{vt&&(vt.disabled=!1,vt.textContent="Run Diagnostics")}});const Mo=Ut?(async()=>{En(U,"Loading projects..."),En(M,"Select a project first"),En(h,"Loading projects..."),En(m,"Select a project first"),Pr(""),Dr("");try{const r=await fo("/api/word-companion/projects");if(Mt=Array.isArray(r.projects)?r.projects:[],0===Mt.length)return En(U,"No projects available."),En(h,"No projects available."),Pr("No projects available."),vn(e,null),vn(t,null),On(),void Rn("No projects available.");Ln(U,"Choose a project",Mt,"projectId","title"),jn();const n=kn(e),o=Mt.find(e=>e.projectId===n);o&&U?(U.value=String(o.projectId),h&&(h.value=String(o.projectId)),vn(e,o.projectId),await Uo(o.projectId,kn(t))):(vn(e,null),vn(t,null),On(),Rn("Select a Project and Book to begin."))}catch{Mt=[],Ot=[],En(U,"Unable to connect to PlotDirector."),En(M,"Select a project first"),En(h,"Unable to connect to PlotDirector."),En(m,"Select a project first"),xr("Unable to connect to PlotDirector."),Pr("Unable to connect to PlotDirector."),vn(e,null),vn(t,null),On(),Rn("Unable to connect to PlotDirector.")}})():Promise.resolve();if(Ut||(En(U,"Please sign in to PlotDirector."),En(M,"Please sign in to PlotDirector."),En(h,"Please sign in to PlotDirector."),En(m,"Please sign in to PlotDirector."),On()),!window.Office||"function"!=typeof window.Office.onReady)return Lr("Word Companion ready"),Ar("Word document access is unavailable."),Jr("Manual"),void Cn({host:"Unavailable",platform:"Unavailable",ready:"No",wordApi:"No"});In().then(async()=>{Lr("Word Companion ready"),await Mo,await go(),Bt?(()=>{if(Ut){if(!window.Office?.context?.document||"function"!=typeof window.Office.context.document.addHandlerAsync||!window.Office?.EventType?.DocumentSelectionChanged)return Jr("Manual"),void Ar("Automatic scene tracking is unavailable in this Word version. Use Refresh Current Scene.");try{window.Office.context.document.addHandlerAsync(window.Office.EventType.DocumentSelectionChanged,Ro,e=>{e?.status===window.Office.AsyncResultStatus.Succeeded?(br=!0,Jr("Live")):(Jr("Manual"),Ar("Automatic scene tracking is unavailable in this Word version. Use Refresh Current Scene."))}),window.addEventListener("beforeunload",Wo)}catch(e){console.warn("Unable to register Word selection tracking handler.",e),Jr("Manual"),Ar("Automatic scene tracking is unavailable in this Word version. Use Refresh Current Scene.")}}})():(Ar("Word document access is unavailable."),Jr("Manual"))}).catch(e=>{console.error("Office readiness check failed.",e),xr("Unable to connect to PlotDirector."),Lr("Word Companion unavailable"),Ar("Word document access is unavailable."),Cn({ready:"No",wordApi:"No",lastScan:"Failure"})})})(); \ No newline at end of file +(()=>{const e="plotdirector.word.projectId",t="plotdirector.word.bookId",n="plotdirector.word.activeTab",r="plotdirector.word.documentGuid",o="plotdirector.word.boundBookId",a="plotdirector.word.boundProjectId",c="plotdirector.word.bindingVersion",i=new Set(["scene","links","structure","diagnostics"]),s=document.querySelector(".word-companion-shell"),d=document.querySelector(".word-companion-tabs"),l=[...document.querySelectorAll("[data-tab-button]")],u=[...document.querySelectorAll("[data-tab-panel]")],p=document.querySelector("[data-first-run-wizard]"),h=document.querySelector("[data-first-run-project-select]"),m=document.querySelector("[data-first-run-book-select]"),y=document.querySelector("[data-first-run-new-book-title]"),w=document.querySelector("[data-first-run-create-book]"),f=document.querySelector("[data-first-run-scan]"),g=document.querySelector("[data-first-run-cancel]"),S=document.querySelector("[data-first-run-status]"),C=document.querySelector("[data-first-run-summary]"),b=document.querySelector("[data-first-run-character-section]"),I=document.querySelector("[data-first-run-character-status]"),k=document.querySelector("[data-first-run-character-candidates]"),v=document.querySelector("[data-first-run-character-actions]"),x=document.querySelector("[data-first-run-create-characters]"),E=document.querySelector("[data-first-run-skip-characters]"),N=document.querySelector("[data-first-run-import-actions]"),L=document.querySelector("[data-first-run-import]"),q=document.querySelector("[data-first-run-import-cancel]"),P=document.querySelector("[data-first-run-replace-dialog]"),D=document.querySelector("[data-first-run-replace-confirm]"),A=document.querySelector("[data-first-run-replace-cancel]"),T=document.querySelector("[data-office-status]"),$=document.querySelector("[data-connection-status]"),j=document.querySelector("[data-summary-connection]"),W=document.querySelector("[data-summary-project]"),R=document.querySelector("[data-summary-book]"),U=document.querySelector("[data-project-select]"),M=document.querySelector("[data-book-select]"),O=document.querySelector("[data-project-message]"),H=document.querySelector("[data-book-message]"),B=document.querySelector("[data-refresh-current-scene]"),G=document.querySelector("[data-refresh-document]"),F=document.querySelector("[data-current-chapter]"),V=document.querySelector("[data-current-scene]"),J=document.querySelector("[data-current-word-count]"),Y=document.querySelector("[data-scene-tracking-status]"),z=document.querySelector("[data-document-message]"),K=document.querySelector("[data-sync-note]"),Q=document.querySelector("[data-document-outline]"),X=document.querySelector("[data-analyse-manuscript-structure]"),Z=document.querySelector("[data-apply-structure-sync]"),_=document.querySelector("[data-structure-preview-status]"),ee=document.querySelector("[data-structure-preview-results]"),te=document.querySelector("[data-refresh-plotdirector-scene]"),ne=document.querySelector("[data-plotdirector-scene-status]"),re=document.querySelector("[data-anchor-status]"),oe=document.querySelector("[data-anchor-book-id]"),ae=document.querySelector("[data-anchor-chapter-id]"),ce=document.querySelector("[data-anchor-scene-id]"),ie=document.querySelector("[data-attach-plotdirector-ids]"),se=document.querySelector("[data-plotdirector-scene-details]"),de=document.querySelector("[data-plotdirector-scene-title]"),le=document.querySelector("[data-plotdirector-revision-status]"),ue=document.querySelector("[data-plotdirector-estimated-words]"),pe=document.querySelector("[data-plotdirector-actual-words]"),he=document.querySelector("[data-plotdirector-blocked-status]"),me=document.querySelector("[data-plotdirector-blocked-reason-row]"),ye=document.querySelector("[data-plotdirector-blocked-reason]"),we=document.querySelector("[data-runtime-last-sync]"),fe=document.querySelector("[data-sync-scene-progress]"),ge=document.querySelector("[data-sync-word-count]"),Se=document.querySelector("[data-sync-plotdirector-count]"),Ce=document.querySelector("[data-sync-last-synced]"),be=document.querySelector("[data-sync-status]"),Ie=document.querySelector("[data-writing-brief-block]"),ke=document.querySelector("[data-writing-brief]"),ve=document.querySelector("[data-plotdirector-link-groups]"),xe=document.querySelector("[data-character-chips]"),Ee=document.querySelector("[data-asset-chips]"),Ne=(document.querySelector("[data-location-chips]"),document.querySelector("[data-primary-location-select]")),Le=document.querySelector("[data-save-scene-links]"),qe=document.querySelector("[data-scene-links-status]"),Pe=document.querySelector("[data-links-editing-scene]"),De=document.querySelector("[data-chapter-create-link]"),Ae=document.querySelector("[data-chapter-create-link-chapter]"),Te=document.querySelector("[data-create-plotdirector-chapter]"),$e=document.querySelector("[data-link-existing-chapter]"),je=document.querySelector("[data-chapter-create-link-status]"),We=document.querySelector("[data-scene-create-link]"),Re=document.querySelector("[data-create-link-chapter]"),Ue=document.querySelector("[data-create-link-scene]"),Me=document.querySelector("[data-create-plotdirector-scene]"),Oe=document.querySelector("[data-link-existing-scene]"),He=document.querySelector("[data-create-link-status]"),Be=document.querySelector("[data-link-existing-dialog]"),Ge=document.querySelector("[data-link-scene-search]"),Fe=document.querySelector("[data-link-scene-options]"),Ve=document.querySelector("[data-link-selected-scene]"),Je=document.querySelector("[data-link-dialog-cancel]"),Ye=document.querySelector("[data-link-dialog-status]"),ze=document.querySelector("[data-create-scene-dialog]"),Ke=document.querySelector("[data-create-dialog-scene]"),Qe=document.querySelector("[data-create-dialog-chapter]"),Xe=document.querySelector("[data-create-dialog-confirm]"),Ze=document.querySelector("[data-create-dialog-cancel]"),_e=document.querySelector("[data-link-existing-chapter-dialog]"),et=document.querySelector("[data-link-chapter-search]"),tt=document.querySelector("[data-link-chapter-options]"),nt=document.querySelector("[data-link-selected-chapter]"),rt=document.querySelector("[data-link-chapter-dialog-cancel]"),ot=document.querySelector("[data-link-chapter-dialog-status]"),at=document.querySelector("[data-create-chapter-dialog]"),ct=document.querySelector("[data-create-chapter-dialog-chapter]"),it=document.querySelector("[data-create-chapter-dialog-book]"),st=document.querySelector("[data-create-chapter-dialog-confirm]"),dt=document.querySelector("[data-create-chapter-dialog-cancel]"),lt=document.querySelector("[data-apply-structure-sync-dialog]"),ut=document.querySelector("[data-apply-structure-sync-summary]"),pt=document.querySelector("[data-apply-structure-sync-confirm]"),ht=document.querySelector("[data-apply-structure-sync-cancel]"),mt=document.querySelector("[data-resolve-project-id]"),yt=document.querySelector("[data-resolve-project-title]"),wt=document.querySelector("[data-resolve-book-id]"),ft=document.querySelector("[data-resolve-book-title]"),gt=document.querySelector("[data-resolve-detected-chapter]"),St=document.querySelector("[data-resolve-detected-scene]"),Ct=document.querySelector("[data-resolve-request-chapter]"),bt=document.querySelector("[data-resolve-request-scene]"),It=document.querySelector("[data-resolve-result]"),kt=document.querySelector("[data-resolve-chapter-id]"),vt=document.querySelector("[data-resolve-scene-id]"),xt=document.querySelector("[data-run-diagnostics]"),Et=document.querySelector("[data-diagnostic-host]"),Nt=document.querySelector("[data-diagnostic-platform]"),Lt=document.querySelector("[data-diagnostic-ready]"),qt=document.querySelector("[data-diagnostic-word-api]"),Pt=document.querySelector("[data-diagnostic-last-scan]"),Dt=document.querySelector("[data-diagnostic-last-error]"),At=document.querySelector("[data-diagnostic-anchor-type]"),Tt=document.querySelector("[data-diagnostic-stored-scene-id]"),$t=document.querySelector("[data-diagnostic-stored-chapter-id]"),jt=document.querySelector("[data-diagnostic-resolution-method]"),Wt=document.querySelector("[data-diagnostic-paragraphs]"),Rt=document.querySelector("[data-diagnostic-heading1]"),Ut=document.querySelector("[data-diagnostic-heading2]"),Mt="true"===s?.dataset.authenticated;let Ot=[],Ht=[],Bt=!1,Gt=!1,Ft="Unknown",Vt="Unknown",Jt="",Yt="",zt=null,Kt=null,Qt=null,Xt=null,Zt=null,_t=null,en="",tn="Title Match",nn=!1,rn=[],on=null,an=null,cn=[],sn=null,dn=null,ln=null,un=null,pn=null,hn=null,mn=null,yn=null,wn=null,fn=null,gn=[],Sn=!1,Cn=!1,bn=!1,In=!1,kn=null,vn="Manual",xn=!1,En=null,Nn=!1,Ln=!1,qn="",Pn="",Dn={characters:[],assets:[],locations:[],primaryLocationId:null};const An=e=>{T&&(T.textContent=e)},Tn=(e,t=!0)=>{const r=i.has(e)&&l.some(t=>t.dataset.tabButton===e)?e:"scene";for(const e of l){const t=e.dataset.tabButton===r;e.classList.toggle("is-active",t),e.setAttribute("aria-selected",t?"true":"false")}for(const e of u){const t=e.dataset.tabPanel===r;e.classList.toggle("is-active",t),e.hidden=!t}t&&((e,t)=>{try{t?window.localStorage.setItem(e,String(t)):window.localStorage.removeItem(e)}catch{}})(n,r)},$n=()=>{const e=(e=>{try{return window.localStorage.getItem(e)||""}catch{return""}})(n);Tn(i.has(e)?e:"scene",!1)},jn=e=>{$&&($.textContent=e),j&&(j.textContent=e)},Wn=e=>{O&&(O.textContent=e)},Rn=e=>{H&&(H.textContent=e)},Un=e=>{z&&(z.textContent=e)},Mn=e=>{ne&&(ne.textContent=e)},On=e=>{const t=t=>Object.prototype.hasOwnProperty.call(e,t);t("anchorType")&&Lr(At,nr(e.anchorType)),t("storedSceneId")&&Lr(Tt,nr(e.storedSceneId)),t("storedChapterId")&&Lr($t,nr(e.storedChapterId)),t("resolutionMethod")&&Lr(jt,nr(e.resolutionMethod))},Hn=()=>{const e=Ur(),t=Number.isInteger(Zt)&&Zt>0&&Xt===Zt,n=!Number.isInteger(_t)||_t<=0||Qt===_t,r=t&&n;Lr(re,r?"Attached to PlotDirector":"Not attached"),Lr(oe,e?.bookId?String(e.bookId):"-"),Lr(ae,Number.isInteger(_t)&&_t>0?String(_t):"-"),Lr(ce,Number.isInteger(Zt)&&Zt>0?String(Zt):"-"),ie&&(ie.disabled=!Zt||r&&!nn,ie.textContent=Xt&&!r?"Reattach PlotDirector IDs":"Attach PlotDirector IDs"),On({anchorType:tn||"Title Match",storedSceneId:Xt,storedChapterId:Qt,resolutionMethod:en})},Bn=(e,t,n,r=null,o=null,a=null)=>{Jt=e||"",Yt=t||"",zt=Number.isInteger(n)?n:null,Kt=Number.isInteger(a)&&a>0?a:null,Qt=Number.isInteger(r)&&r>0?r:null,Xt=Number.isInteger(o)&&o>0?o:null,F&&(F.textContent=e||"Not detected"),V&&(V.textContent=t||"Not detected"),J&&(J.textContent=Number.isInteger(n)?String(n):"-"),Lr(ge,Number.isInteger(n)?String(n):"-"),Hn()},Gn=(e,t)=>{e&&(e.hidden=t)},Fn=e=>{Lr(be,e)},Vn=e=>{Lr(_,e)},Jn=(e="Select a project and book to analyse manuscript structure.")=>{if(ln=null,ee){ee.innerHTML="";const e=document.createElement("p");e.textContent="No preview generated.",ee.append(e)}Vn(e),zn()},Yn=(e=ln)=>((e=ln)=>lo.flatMap(t=>Array.isArray(e?.[t.key])?e[t.key]:[]))(e).filter(e=>"couldLink"===e.category||"wouldCreateChapters"===e.category||"wouldCreateScenes"===e.category),zn=()=>{Z&&(Z.disabled=In||0===Yn().length)},Kn=()=>{X&&(X.disabled=In||!Rr()||!Ur()),zn()},Qn=()=>{Pe&&(Pe.textContent=Zt?`Editing links for: ${qn||Yt||"Current scene"}`:"Link a PlotDirector scene first.")},Xn=()=>{const e=xn||!Zt;fe&&(fe.disabled=e),Le&&(Le.disabled=e),Ne&&(Ne.disabled=e);for(const t of[xe,Ee])for(const n of t?[...t.querySelectorAll("input[type='checkbox']")]:[])n.disabled=e},Zn=e=>{"Live"!==e&&"Manual"!==e||(vn=e),Lr(Y,e||vn||"Manual")},_n=(e,t="")=>{xn=!!e,Lr(Y,xn?"Stale":vn),Xn(),t&&(Un(t),ir(t))},er=(e,t=null,n="")=>{Zt=Number.isInteger(e)&&e>0?e:null,_t=Number.isInteger(t)&&t>0?t:null,en=n||"",Xn(),Fn(xn?"Refresh Current Scene before syncing.":Zt?"Ready to sync.":"No resolved PlotDirector scene."),ir(xn?"Refresh Current Scene before saving.":Zt?"Ready to save.":"Link a PlotDirector scene first."),Qn(),Hn()},tr=e=>{B&&(B.disabled=e,B.textContent=e?"Refreshing...":"Refresh Current Scene")},nr=e=>null==e||""===e?"-":String(e),rr=e=>{if(!e)return"-";const t=new Date(e);return Number.isNaN(t.getTime())?"-":t.toLocaleString()},or=e=>{pn=e||null,Lr(we,rr(pn?.lastSyncUtc||pn?.manuscriptDocument?.lastSyncUtc)),Lr(Ce,rr(pn?.lastSyncUtc||pn?.manuscriptDocument?.lastSyncUtc))},ar=()=>{hn=null,mn=null,yn=null,or(null)},cr=()=>{mn=null,yn=null},ir=e=>{Lr(qe,e)},sr=e=>{Lr(He,e)},dr=e=>{Lr(je,e)},lr=()=>!!Ur()&&!!Jt&&!_t,ur=()=>!!Ur()&&!!Yt&&Number.isInteger(_t)&&_t>0,pr=()=>{Gn(De,!0),dr(""),Te&&(Te.disabled=!0,Te.textContent="Create Chapter in PlotDirector"),$e&&($e.disabled=!0,$e.textContent="Link to Existing Chapter")},hr=(e="")=>{Lr(Ae,nr(Jt)),Gn(De,!1),dr(e);const t=lr();Te&&(Te.disabled=!t,Te.textContent="Create Chapter in PlotDirector"),$e&&($e.disabled=!t,$e.textContent="Link to Existing Chapter")},mr=()=>{Gn(We,!0),sr(""),Me&&(Me.disabled=!0,Me.textContent="Create Scene in PlotDirector"),Oe&&(Oe.disabled=!0,Oe.textContent="Link to Existing Scene")},yr=(e="")=>{Lr(Re,nr(Jt)),Lr(Ue,nr(Yt)),Gn(We,!1),sr(e);const t=ur();Me&&(Me.disabled=!t,Me.textContent="Create Scene in PlotDirector"),Oe&&(Oe.disabled=!t,Oe.textContent="Link to Existing Scene")},wr=e=>{Mn(e),Gn(se,!0),Gn(Ie,!0),Gn(ve,!1),pr(),mr(),en="",qn="",Pn="",tn=Xt?"SceneID Anchor":Qt?"ChapterID Anchor":"Title Match",nn=!1,Dn={characters:[],assets:[],locations:[],primaryLocationId:null},gr(xe,[],"character"),gr(Ee,[],"asset"),Sr([],null,!1),er(null),Lr(Se,"-"),Lr(de,"-"),Lr(le,"-"),Lr(ue,"-"),Lr(pe,"-"),Lr(he,"-"),Lr(ye,"-"),Gn(me,!0),Hn(),Qn()},fr=(e,t)=>"asset"===t?e?.assetId||e?.AssetId||e?.storyAssetId||e?.StoryAssetId||0:"location"===t?e?.locationId||e?.LocationId||0:e?.characterId||e?.CharacterId||0,gr=(e,t,n,r=!1)=>{if(!e)return;e.innerHTML="";const o=Array.isArray(t)?t:[];if(0===o.length){const t=document.createElement("p");return t.className="word-companion-empty-list",t.textContent="None",void e.append(t)}for(const t of o){const o=Number.parseInt(fr(t,n),10);if(!Number.isInteger(o)||o<=0)continue;const a=document.createElement("label");a.className="word-companion-check-item";const c=document.createElement("input");c.type="checkbox",c.value=String(o),c.checked=!!t.linked,c.disabled=!r;const i=document.createElement("span");i.textContent=t.name||"Unnamed",a.append(c,i),e.append(a)}},Sr=(e,t,n=!1)=>{if(!Ne)return;Ne.innerHTML="";const r=document.createElement("option");r.value="",r.textContent="None",Ne.append(r);const o=Number.parseInt(t||"",10);for(const t of Array.isArray(e)?e:[]){const e=Number.parseInt(fr(t,"location"),10);if(!Number.isInteger(e)||e<=0)continue;const n=document.createElement("option");n.value=String(e),n.textContent=t.name||"Unnamed",n.selected=e===o,Ne.append(n)}Ne.disabled=!n},Cr=e=>String(e||"").trim().replace(/\s+/g," "),br=(e,t)=>{const n=Cr(e);if(!n)return"";const r=new RegExp(`^${"scene"===t?"scene":"chapter"}\\s+(?:\\d+|[ivxlcdm]+|one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen|twenty)\\s*(?::|-|\\u2013|\\u2014)\\s*`,"i");return Cr(n.replace(r,""))||n},Ir=e=>{const t=t=>Object.prototype.hasOwnProperty.call(e,t);t("projectId")&&Lr(mt,nr(e.projectId)),t("projectTitle")&&Lr(yt,nr(e.projectTitle)),t("bookId")&&Lr(wt,nr(e.bookId)),t("bookTitle")&&Lr(ft,nr(e.bookTitle)),t("detectedChapter")&&Lr(gt,nr(e.detectedChapter)),t("detectedScene")&&Lr(St,nr(e.detectedScene)),t("requestChapter")&&Lr(Ct,nr(e.requestChapter)),t("requestScene")&&Lr(bt,nr(e.requestScene)),t("result")&&Lr(It,nr(e.result)),t("chapterId")&&Lr(kt,nr(e.chapterId)),t("sceneId")&&Lr(vt,nr(e.sceneId))},kr=async e=>{if(yn===e&&Array.isArray(mn?.chapters))return mn.chapters;const t=await Ao(`/api/word-companion/books/${e}/structure`);return yn=e,mn=t||null,Array.isArray(t?.chapters)?t.chapters:[]},vr=async e=>{const t=await Ao(`/api/word-companion/books/${e}/chapters`);return Array.isArray(t?.chapters)?t.chapters:[]},xr=e=>{if(Number.isInteger(_t)&&_t>0){const t=e.find(e=>e.chapterId===_t);if(t)return t}const t=br(Jt,"chapter").toLocaleLowerCase();return t&&e.find(e=>br(e.title,"chapter").toLocaleLowerCase()===t)||null},Er=async()=>{const e=Ur();return e?xr(await kr(e.bookId)):null},Nr=async(e,t,n,r,o)=>{const a=await Ao(`/api/word-companion/scenes/${t}/companion`);try{a.revisionStatus=await(async(e,t)=>{const n=await Ao(`/api/word-companion/books/${e}/structure`),r=Array.isArray(n?.chapters)?n.chapters:[];for(const e of r){const n=(Array.isArray(e.scenes)?e.scenes:[]).find(e=>e.sceneId===t);if(n)return n.revisionStatus||""}return""})(e,t)}catch{a.revisionStatus=""}var c;tn=o||"Title Match",nn=!1,_n(!1),Mn("Linked to PlotDirector"),Un(""),pr(),mr(),er(t,n,r),c=a,qn=c?.sceneTitle||Yt||"",Pn=c?.chapterTitle||Jt||"",Lr(de,nr(c?.sceneTitle)),Lr(le,nr(c?.revisionStatus||c?.revisionStatusName||"Not provided")),Lr(ue,nr(c?.estimatedWords)),Lr(pe,nr(c?.actualWords)),Lr(Se,nr(c?.actualWords)),Lr(he,c?.blocked?"Blocked":"Not blocked"),c?.blockedReason?(Lr(ye,c.blockedReason),Gn(me,!1)):(Lr(ye,"-"),Gn(me,!0)),ke&&(ke.textContent=c?.writingBrief||"No writing brief has been added for this scene."),Dn={characters:Array.isArray(c?.characters)?c.characters:[],assets:Array.isArray(c?.assets)?c.assets:[],locations:Array.isArray(c?.locations)?c.locations:[],primaryLocationId:c?.primaryLocationId??null},gr(xe,Dn.characters,"character",!!Zt&&!xn),gr(Ee,Dn.assets,"asset",!!Zt&&!xn),Sr(Dn.locations,Dn.primaryLocationId,!!Zt&&!xn),Qn(),ir(xn?"Refresh Current Scene before saving.":Zt?"Ready to save.":"No resolved PlotDirector scene."),Gn(se,!1),Gn(Ie,!1),Gn(ve,!1)},Lr=(e,t)=>{e&&(e.textContent=t)},qr=e=>{const t=t=>Object.prototype.hasOwnProperty.call(e,t);t("host")&&Lr(Et,e.host),t("platform")&&Lr(Nt,e.platform),t("ready")&&Lr(Lt,e.ready),t("wordApi")&&Lr(qt,e.wordApi),t("lastScan")&&Lr(Pt,e.lastScan),t("lastError")&&Lr(Dt,e.lastError),t("paragraphs")&&Lr(Wt,e.paragraphs),t("heading1")&&Lr(Rt,e.heading1),t("heading2")&&Lr(Ut,e.heading2)},Pr=e=>{const t=[];return e?.name&&t.push(e.name),e?.code&&e.code!==e.name&&t.push(e.code),e?.message&&t.push(e.message),e?.debugInfo?.errorLocation&&t.push(`Location: ${e.debugInfo.errorLocation}`),t.length>0?t.join(": "):String(e)},Dr=async()=>{if(!window.Office||"function"!=typeof window.Office.onReady)return Bt=!1,Gt=!1,Ft="Unavailable",Vt="Unavailable",qr({host:Ft,platform:Vt,ready:"No",wordApi:"No"}),null;const e=await window.Office.onReady();return Bt=!0,Ft=e?.host||"Unknown",Vt=e?.platform||"Unknown",Gt=!!window.Word&&!!window.Office.HostType&&e?.host===window.Office.HostType.Word,qr({host:Ft,platform:Vt,ready:"Yes",wordApi:Gt?"Yes":"No"}),e},Ar=e=>{try{const t=window.localStorage.getItem(e),n=Number.parseInt(t||"",10);return Number.isInteger(n)&&n>0?n:null}catch{return null}},Tr=(e,t)=>{try{t?window.localStorage.setItem(e,String(t)):window.localStorage.removeItem(e)}catch{}},$r=(e,t)=>{if(!e)return;e.innerHTML="";const n=document.createElement("option");n.value="",n.textContent=t,e.append(n),e.disabled=!0},jr=(e,t,n,r,o)=>{if(!e)return;e.innerHTML="";const a=document.createElement("option");a.value="",a.textContent=t,e.append(a);for(const t of n){const n=document.createElement("option");n.value=String(t[r]),n.textContent=t[o],e.append(n)}e.disabled=0===n.length},Wr=e=>{const t=String(e?.title||"").trim(),n=String(e?.subtitle||"").trim();return n?`${t}: ${n}`:t},Rr=()=>{const e=Number.parseInt(U?.value||"",10);return Ot.find(t=>t.projectId===e)||null},Ur=()=>{const e=Number.parseInt(M?.value||"",10);return Ht.find(t=>t.bookId===e)||null},Mr=()=>{const e=Number.parseInt(h?.value||"",10);return Ot.find(t=>t.projectId===e)||null},Or=()=>{const e=Number.parseInt(m?.value||"",10);return Ht.find(t=>t.bookId===e)||null},Hr=e=>Lr(S,e),Br=()=>{const e=Mr(),t=Or();f&&(f.disabled=!e||!t||Cn),w&&(w.disabled=!e||!String(y?.value||"").trim()||Cn),L&&(L.disabled=!wn?.canImport||!fn||Cn),x&&(x.disabled=bn||0===Jr().length)},Gr=e=>{Gn(p,!e),Gn(d,e);for(const t of u)Gn(t,!!e||"scene"!==t.dataset.tabPanel&&!t.classList.contains("is-active"));e||$n()},Fr=()=>{if(!h)return;if(0===Ot.length)return void $r(h,"No projects available.");jr(h,"Choose a project",Ot,"projectId","title");const e=Number.parseInt(U?.value||"",10);Number.isInteger(e)&&e>0&&(h.value=String(e))},Vr=(e="Select a Project and Book to begin.")=>{wn=null,fn=null,gn=[],Sn=!1,Gn(C,!0),Gn(N,!0),Gn(b,!0),Gn(v,!0),C&&(C.innerHTML=""),k&&(k.innerHTML=""),Lr(I,""),Hr(e),Br()},Jr=()=>k?[...k.querySelectorAll("input[type='checkbox']:checked")].map(e=>String(e.value||"").trim()).filter(Boolean):[],Yr=e=>{if(gn=Array.isArray(e)?e:[],b&&k){if(k.innerHTML="",Gn(b,!1),Gn(v,!Sn||0===gn.length),0===gn.length)return Lr(I,"No likely major characters found."),void Br();Lr(I,`${gn.length} likely major characters found.`);for(const e of gn){const t=document.createElement("label");t.className="word-companion-character-candidate";const n=document.createElement("input");n.type="checkbox",n.value=e.text||"",n.checked="high"===String(e.confidence||"").trim().toLowerCase(),n.addEventListener("change",Br);const r=document.createElement("strong");r.textContent=e.text||"";const o=document.createElement("em"),a=String(e.reason||"").trim();o.textContent=a?`${Number(e.mentionCount||0).toLocaleString()} mentions · ${a}`:`${Number(e.mentionCount||0).toLocaleString()} mentions`;const c=document.createElement("span");c.className="word-companion-character-candidate-text",c.append(r,o),t.append(n,c),k.append(t)}Br()}},zr=()=>un?.documentGuid?un.documentGuid:window.crypto?.randomUUID?window.crypto.randomUUID():"10000000-1000-4000-8000-100000000000".replace(/[018]/g,e=>(Number(e)^16*Math.random()>>Number(e)/4).toString(16)),Kr=()=>{const e=Rr(),t=Ur();W&&(W.textContent=e?.title||"(Not connected)"),R&&(R.textContent=t?Wr(t):"(Not connected)"),K&&(K.textContent=t?"":"Select a PlotDirector book before refreshing."),Kn()},Qr=e=>String(e?.styleBuiltIn||e?.style||"").replace(/\s+/g,"").toLowerCase(),Xr=(e,t)=>{const n=Qr(e);return n===`heading${t}`||n.endsWith(`.heading${t}`)||n.includes(`heading${t}`)},Zr=e=>String(e||"").trim().split(/\s+/).filter(Boolean).length,_r=(e,t)=>{const n=String(e||"").match(new RegExp(`^${t}-(\\d+)$`,"i"));if(!n)return null;const r=Number.parseInt(n[1],10);return Number.isInteger(r)&&r>0?r:null},eo=(e,t)=>{const n=Array.isArray(e?.contentControls?.items)?e.contentControls.items:[];for(const e of n){const n=_r(e.tag,t);if(n)return n}return null},to=(e,t)=>{const n=[];let r=0,o=0,a=null,c=null;e.forEach((e,t)=>{const i=String(e.text||"").trim();if(i){if(Xr(e,1))return r+=1,a={index:n.length+1,paragraphIndex:t,title:i,anchorId:eo(e,"PD-CHAPTER"),scenes:[]},n.push(a),void(c=null);if(Xr(e,2)){if(o+=1,!a)return;return c={index:a.scenes.length+1,paragraphIndex:t,title:i,anchorId:eo(e,"PD-SCENE"),wordCount:0},void a.scenes.push(c)}c&&(c.wordCount+=Zr(i))}});const i=t.find(e=>String(e.text||"").trim()),s=i?e.findIndex(e=>{return t=e,n=i,String(t?.text||"").trim()===String(n?.text||"").trim()&&Qr(t)===Qr(n);var t,n}):-1,d=s>=0&&n.filter(e=>e.paragraphIndex<=s).at(-1)||null,l=d&&s>=0&&d.scenes.filter(e=>e.paragraphIndex<=s).at(-1)||null;return{chapters:n,currentChapter:d,currentScene:l,paragraphCount:e.length,heading1Count:r,heading2Count:o}},no=new Set(["***","###"]),ro=(e,t)=>{const n=String(e?.text||"").trim();return{index:t,text:n,styleBuiltIn:e?.styleBuiltIn||"",style:e?.style||"",wordCount:Zr(n),chapterAnchorId:eo(e,"PD-CHAPTER"),sceneAnchorId:eo(e,"PD-SCENE")}},oo=(e,t)=>{e&&(e.endParagraphIndex=t)},ao=(e,t)=>{e&&(e.endParagraphIndex=t,oo(e.scenes.at(-1),t))},co=(e,t)=>{const n=(t||[]).find(e=>String(e.text||"").trim());if(!e||!n)return e?.currentParagraphIndex??-1;const r=e.paragraphs.filter(e=>((e,t)=>String(e?.text||"").trim()===String(t?.text||"").trim()&&Qr(e)===Qr(t))(e,n)).map(e=>e.index);return 0===r.length?e.currentParagraphIndex??-1:Number.isInteger(e.currentParagraphIndex)?r.reduce((t,n)=>Math.abs(n-e.currentParagraphIndex){if(!hn)return!1;const t=((e,t)=>!e||!Number.isInteger(t)||t<0?null:e.chapters.filter(e=>e.startParagraphIndex<=t).at(-1)||null)(hn,e),n=((e,t)=>!e||!Number.isInteger(t)||t<0?null:e.scenes.filter(e=>e.startParagraphIndex<=t).at(-1)||null)(t,e),r=t?.paragraphIndex!==hn.currentChapter?.paragraphIndex||n?.paragraphIndex!==hn.currentScene?.paragraphIndex;return hn.currentParagraphIndex=e,hn.currentChapter=t,hn.currentScene=n,Bn(t?.title,n?.title,n?.wordCount,t?.anchorId,n?.anchorId,t?.index),r},so=e=>{if(!Q)return;if(Q.innerHTML="",0===e.chapters.length){const e=document.createElement("p");return e.textContent="No chapters detected. Use Heading 1 for chapter titles.",void Q.append(e)}if(!e.chapters.some(e=>e.scenes.length>0)){const e=document.createElement("p");e.textContent="No scenes detected. Use Heading 2 for scene titles.",Q.append(e)}for(const t of e.chapters){const e=document.createElement("div");e.className="word-companion-outline-chapter";const n=document.createElement("strong");if(n.textContent=t.title,e.append(n),t.scenes.length>0){const n=document.createElement("ul");for(const e of t.scenes){const t=document.createElement("li");t.textContent=e.title,n.append(t)}e.append(n)}Q.append(e)}},lo=[{key:"alreadyLinked",title:"Already Linked"},{key:"couldLink",title:"Could Link"},{key:"wouldCreateChapters",title:"Would Create Chapters"},{key:"wouldCreateScenes",title:"Would Create Scenes"},{key:"manualReview",title:"Manual Review Required"}],uo={alreadyLinked:"Already Linked",couldLink:"Could Link",wouldCreateChapter:"Would Create Chapter",wouldCreateScene:"Would Create Scene",manualReview:"Manual Review Required"},po={alreadyLinked:"✓",couldLink:"~",wouldCreateChapter:"+",wouldCreateScene:"+",manualReview:"?"},ho=(e,t)=>br(e,t).toLocaleLowerCase(),mo=({category:e,action:t,type:n,wordTitle:r,match:o="",anchorStatus:a="None",matches:c=[],pdChapter:i=null,pdScene:s=null,wordChapter:d=null,wordScene:l=null,parentItem:u=null})=>({id:`${n}-${d?.index||0}-${l?.index||0}-${d?.paragraphIndex??l?.paragraphIndex??0}`,category:e,action:t,type:n,wordTitle:r,match:o,anchorStatus:a,matches:c,pdChapter:i,pdScene:s,wordChapter:d,wordScene:l,parentItem:u,result:"Pending",error:""}),yo=(e,t)=>{Array.isArray(e[t.category])&&e[t.category].push(t)},wo=e=>Array.isArray(e?.scenes)?e.scenes:[],fo=(e,t,n)=>{const r=e.anchorId?`PD-CHAPTER-${e.anchorId}`:"None";if(e.anchorId){const o=t.find(t=>t.chapterId===e.anchorId);if(o){const t=mo({category:"alreadyLinked",action:"alreadyLinked",type:"Chapter",wordTitle:e.title,match:`Chapter ${o.chapterId}: ${o.title}`,anchorStatus:r,pdChapter:o,wordChapter:e});return yo(n,t),t}const a=mo({category:"manualReview",action:"manualReview",type:"Chapter",wordTitle:e.title,anchorStatus:`${r} not found`,matches:[],pdChapter:null,wordChapter:e});return yo(n,a),a}const o=t.filter(t=>ho(t.title,"chapter")===ho(e.title,"chapter"));if(1===o.length){const t=mo({category:"couldLink",action:"couldLink",type:"Chapter",wordTitle:e.title,match:`Chapter ${o[0].chapterId}: ${o[0].title}`,anchorStatus:r,pdChapter:o[0],wordChapter:e});return yo(n,t),t}if(o.length>1){const t=mo({category:"manualReview",action:"manualReview",type:"Chapter",wordTitle:e.title,anchorStatus:r,matches:o.map(e=>`Chapter ${e.chapterId}: ${e.title}`),pdChapter:null,wordChapter:e});return yo(n,t),t}const a=mo({category:"wouldCreateChapters",action:"wouldCreateChapter",type:"Chapter",wordTitle:e.title,anchorStatus:r,pdChapter:null,wordChapter:e});return yo(n,a),a},go=(e,t,n,r)=>{const o=e.anchorId?`PD-SCENE-${e.anchorId}`:"None";if(e.anchorId){const a=((e,t)=>{for(const n of e){const e=wo(n).find(e=>e.sceneId===t);if(e)return{chapter:n,scene:e}}return null})(n,e.anchorId);return a?void yo(r,mo({category:"alreadyLinked",action:"alreadyLinked",type:"Scene",wordTitle:e.title,match:`Scene ${a.scene.sceneId}: ${a.scene.title}`,anchorStatus:o,pdChapter:a.chapter,pdScene:a.scene,wordChapter:t?.wordChapter,wordScene:e,parentItem:t})):void yo(r,mo({category:"manualReview",action:"manualReview",type:"Scene",wordTitle:e.title,anchorStatus:`${o} not found`,wordChapter:t?.wordChapter,wordScene:e,parentItem:t}))}if(!t?.pdChapter&&"manualReview"===t?.category)return void yo(r,mo({category:"manualReview",action:"manualReview",type:"Scene",wordTitle:e.title,anchorStatus:o,matches:["Parent chapter requires manual review."],wordChapter:t?.wordChapter,wordScene:e,parentItem:t}));if(!t?.pdChapter)return void yo(r,mo({category:"wouldCreateScenes",action:"wouldCreateScene",type:"Scene",wordTitle:e.title,anchorStatus:o,wordChapter:t?.wordChapter,wordScene:e,parentItem:t}));const a=wo(t.pdChapter).filter(t=>ho(t.title,"scene")===ho(e.title,"scene"));1!==a.length?a.length>1?yo(r,mo({category:"manualReview",action:"manualReview",type:"Scene",wordTitle:e.title,anchorStatus:o,matches:a.map(e=>`Scene ${e.sceneId}: ${e.title}`),wordChapter:t.wordChapter,wordScene:e,parentItem:t})):yo(r,mo({category:"wouldCreateScenes",action:"wouldCreateScene",type:"Scene",wordTitle:e.title,anchorStatus:o,pdChapter:t.pdChapter,wordChapter:t.wordChapter,wordScene:e,parentItem:t})):yo(r,mo({category:"couldLink",action:"couldLink",type:"Scene",wordTitle:e.title,match:`Scene ${a[0].sceneId}: ${a[0].title}`,anchorStatus:o,pdChapter:t.pdChapter,pdScene:a[0],wordChapter:t.wordChapter,wordScene:e,parentItem:t}))},So=e=>{const t=document.createElement("article");t.className="word-companion-preview-item";const n=document.createElement("strong");n.textContent=`${po[e.action]||""} ${e.type}: ${e.wordTitle}`,t.append(n);const r=document.createElement("span");if(r.textContent=`Anchor: ${e.anchorStatus||"None"}`,t.append(r),e.match){const n=document.createElement("span");n.textContent=`Match: ${e.match}`,t.append(n)}if(Array.isArray(e.matches)&&e.matches.length>0){const n=document.createElement("div");n.className="word-companion-preview-matches";const r=document.createElement("span");r.textContent="Matches:",n.append(r);const o=document.createElement("ul");for(const t of e.matches){const e=document.createElement("li");e.textContent=t,o.append(e)}n.append(o),t.append(n)}const o=document.createElement("span");if(o.textContent=`Action: ${uo[e.action]||e.action}`,t.append(o),e.result&&"Pending"!==e.result){const n=document.createElement("span");n.textContent=e.error?`Result: ${e.result} - ${e.error}`:`Result: ${e.result}`,t.append(n)}return t},Co=e=>{if(ee){ee.innerHTML="";for(const t of lo){const n=document.createElement("section");n.className="word-companion-preview-group";const r=document.createElement("strong");r.textContent=t.title,n.append(r);const o=Array.isArray(e?.[t.key])?e[t.key]:[];if(0===o.length){const e=document.createElement("p");e.className="word-companion-empty-list",e.textContent="None",n.append(e)}else for(const e of o)n.append(So(e));ee.append(n)}zn()}},bo=async e=>{const t=e.document.body.paragraphs,n=e.document.getSelection().paragraphs;t.load("text,styleBuiltIn,style"),n.load("text,styleBuiltIn,style"),await e.sync();for(const e of t.items)(Xr(e,1)||Xr(e,2))&&e.contentControls.load("items/tag,title");await e.sync();const r=to(t.items,n.items);return r.bodyParagraphs=t.items,r},Io=async(e,t)=>{const n=e.document.body.paragraphs,r=e.document.getSelection().paragraphs;n.load("text,styleBuiltIn,style"),r.load("text,styleBuiltIn,style"),await e.sync();for(const e of n.items)Xr(e,1)&&e.contentControls.load("items/tag,title");await e.sync();const o=((e,t)=>{const n=e.map(ro),r=[];let o=0,a=0,c=null,i=null,s=0;const d=(e,t=null,n=null)=>c?(oo(i,e.index-1),i={index:c.scenes.length+1,paragraphIndex:e.index,startParagraphIndex:e.index,endParagraphIndex:e.index,title:t||`Scene ${c.scenes.length+1}`,anchorId:n,wordCount:0},c.scenes.push(i),i):null;for(const e of n)e.text&&(Xr(e,1)?(ao(c,e.index-1),o+=1,c={index:r.length+1,paragraphIndex:e.index,startParagraphIndex:e.index,endParagraphIndex:e.index,title:e.text,anchorId:e.chapterAnchorId,wordCount:0,scenes:[]},r.push(c),i=null,d(e,"Scene 1",e.sceneAnchorId),s+=e.wordCount):c&&(t&&no.has(e.text)?(a+=1,d(e)):(c.wordCount+=e.wordCount,i&&(i.wordCount+=e.wordCount),s+=e.wordCount)));return ao(c,n.length-1),{paragraphs:n,chapters:r,usesExplicitScenes:!!t,paragraphCount:n.length,heading1Count:o,heading2Count:a,documentWordCount:s,currentParagraphIndex:null,currentChapter:null,currentScene:null}})(n.items,t),a=co(o,r.items);return hn=o,io(a),o},ko=async()=>{if(Un(""),!Bt||!Gt||!window.Word||"function"!=typeof window.Word.run)return Bn(null,null,null),Un("Word document access is unavailable."),qr({lastScan:"Failure",lastError:"Word document access is unavailable."}),!1;G&&(G.disabled=!0,G.textContent="Scanning..."),Un("Scanning document structure...");try{const e=await window.Word.run(async e=>{const t=Ur();return t?await Io(e,!!t.usesExplicitScenes):(hn=null,await bo(e))});return hn||Bn(e.currentChapter?.title,e.currentScene?.title,e.currentScene?.wordCount,e.currentChapter?.anchorId,e.currentScene?.anchorId,e.currentChapter?.index),wr("Not detected"),so(e),Un(""),qr({lastScan:"Success",lastError:"-",paragraphs:String(e.paragraphCount),heading1:String(e.heading1Count),heading2:String(e.heading2Count)}),!0}catch(e){const t=Pr(e);return console.error("Unable to scan the Word document.",e),Bn(null,null,null),Un(`Unable to scan the Word document: ${t}`),qr({lastScan:"Failure",lastError:t}),!1}finally{G&&(G.disabled=!1,G.textContent="Refresh Document Structure")}},vo=async()=>{const e=Ur();if(!Rr()||!e)return Vn("Select a project and book to analyse manuscript structure."),!1;if(!Bt||!Gt||!window.Word||"function"!=typeof window.Word.run)return Vn("Word document access is unavailable."),qr({lastScan:"Failure",lastError:"Word document access is unavailable."}),!1;X&&(X.disabled=!0,X.textContent="Analysing..."),Vn("Analysing manuscript structure...");try{const t=await window.Word.run(async e=>await bo(e)),n=await Ao(`/api/word-companion/books/${e.bookId}/structure`);return Bn(t.currentChapter?.title,t.currentScene?.title,t.currentScene?.wordCount,t.currentChapter?.anchorId,t.currentScene?.anchorId,t.currentChapter?.index),so(t),ln=((e,t)=>{const n={alreadyLinked:[],couldLink:[],wouldCreateChapters:[],wouldCreateScenes:[],manualReview:[]},r=Array.isArray(t?.chapters)?t.chapters:[];for(const t of Array.isArray(e?.chapters)?e.chapters:[]){const e=fo(t,r,n);for(const o of wo(t))go(o,e,r,n)}return n})(t,n),Co(ln),Vn("Preview generated. No changes have been applied."),qr({lastScan:"Success",lastError:"-",paragraphs:String(t.paragraphCount),heading1:String(t.heading1Count),heading2:String(t.heading2Count)}),!0}catch(e){return console.error("Unable to analyse manuscript structure.",e),Vn("Unable to analyse manuscript structure."),qr({lastScan:"Failure",lastError:Pr(e)}),!1}finally{X&&(X.textContent="Analyse Manuscript Structure",Kn())}},xo=e=>{kn&&(kn(e),kn=null),lt?.close?lt.close():lt&&(lt.hidden=!0)},Eo=()=>{const e=((e=ln)=>{const t=Yn(e);return{linkChapters:t.filter(e=>"couldLink"===e.category&&"Chapter"===e.type).length,linkScenes:t.filter(e=>"couldLink"===e.category&&"Scene"===e.type).length,createChapters:t.filter(e=>"wouldCreateChapters"===e.category).length,createScenes:t.filter(e=>"wouldCreateScenes"===e.category).length,manualReview:Array.isArray(e?.manualReview)?e.manualReview.length:0}})();return(e=>{if(!ut)return;ut.innerHTML="";const t=[`Link ${e.linkChapters+e.linkScenes} chapters/scenes`,`Create ${e.createChapters} chapters`,`Create ${e.createScenes} scenes`],n=document.createElement("ul");for(const e of t){const t=document.createElement("li");t.textContent=e,n.append(t)}ut.append(n)})(e),lt?new Promise(e=>{kn=e,lt.showModal?lt.showModal():lt.hidden=!1}):Promise.resolve(window.confirm(`Apply Structure Sync?\n\nThis will:\n\n- Link ${e.linkChapters+e.linkScenes} chapters/scenes\n- Create ${e.createChapters} chapters\n- Create ${e.createScenes} scenes\n\nManual review items will be skipped.`))},No=(e,t,n="")=>{e.result=t,e.error=n},Lo=e=>Number.isInteger(e?.wordChapter?.index)&&e.wordChapter.index>0?10*e.wordChapter.index:null,qo=e=>Number.isInteger(e?.wordScene?.index)&&e.wordScene.index>0?10*e.wordScene.index:null,Po=async(e,t)=>{const n=await To(`/api/word-companion/books/${e}/chapters`,{title:Cr(t.wordTitle),sortOrder:Lo(t)});if(!n?.chapterId)throw new Error("Chapter creation did not return a chapter ID.");cr(),t.pdChapter={chapterId:n.chapterId,title:n.title||t.wordTitle,sortOrder:n.sortOrder||Lo(t)||0,scenes:[]},t.match=`Chapter ${t.pdChapter.chapterId}: ${t.pdChapter.title}`},Do=async(e,t)=>{const n=t.pdChapter||t.parentItem?.pdChapter;if(!n?.chapterId)throw new Error("Scene parent chapter is not available.");const r=await To(`/api/word-companion/books/${e}/chapters/${n.chapterId}/scenes`,{sceneTitle:Cr(t.wordTitle),sortOrder:qo(t)});if(!r?.sceneId)throw new Error("Scene creation did not return a scene ID.");cr(),t.pdChapter=n,t.pdScene={sceneId:r.sceneId,title:t.wordTitle,sortOrder:qo(t)||0},t.match=`Scene ${t.pdScene.sceneId}: ${t.pdScene.title}`},Ao=async(e,t={})=>{const n=await window.fetch(e,{credentials:"same-origin",...t,headers:{Accept:"application/json",...t.headers||{}}});if(!n.ok)throw new Error(`Request failed: ${n.status}`);return await n.json()},To=(e,t)=>Ao(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}),$o=()=>{Gr(!1),Hr(""),Gn(v,!0)},jo=async()=>{if(!Mt||!Gt)return void Gr(!1);const n=(()=>{const e=window.Office?.context?.document?.settings;if(!e)return null;const t=String(e.get(r)||"").trim(),n=Number.parseInt(e.get(o)||"",10),i=Number.parseInt(e.get(a)||"",10),s=Number.parseInt(e.get(c)||"",10);return!t||!Number.isInteger(n)||n<=0||!Number.isInteger(i)||i<=0?null:{documentGuid:t,bookId:n,projectId:i,bindingVersion:Number.isInteger(s)&&s>0?s:1}})();if(n)try{const r=await Ao(`/api/word-companion/runtime/book/${n.bookId}?documentGuid=${encodeURIComponent(n.documentGuid)}`),o=r?.manuscriptDocument;if(r?.bookId===n.bookId&&r?.projectId===n.projectId&&o&&String(o.documentGuid).toLowerCase()===n.documentGuid.toLowerCase())return un=n,or(r),Tr(e,r.projectId),Tr(t,r.bookId),U&&(U.value=String(r.projectId)),await ea(r.projectId,r.bookId),Gr(!1),jn("Connected"),Rn("Bound manuscript detected."),void await(async()=>{const e=Ur();if(!(e&&Bt&&Gt&&window.Word&&"function"==typeof window.Word.run))return!1;Un("Reading manuscript position...");try{cr(),await kr(e.bookId);const t=await window.Word.run(async t=>await Io(t,!!e.usesExplicitScenes));return so(t),qr({lastScan:"Success",lastError:"-",paragraphs:String(t.paragraphCount),heading1:String(t.heading1Count),heading2:String(t.heading2Count)}),Yt?await Qo():await Ko(),_n(!1),Zn("Live"),Un(""),!0}catch(e){return console.error("Unable to initialise bound manuscript runtime.",e),hn=null,Zn("Manual"),Un(`Unable to read manuscript position: ${Pr(e)}`),qr({lastScan:"Failure",lastError:Pr(e)}),!1}})()}catch{}un=null,ar(),Fr(),Mr()?await ea(Mr().projectId,null):$r(m,"Select a project first"),Vr("Select a Project and Book to begin."),Gr(!0)},Wo=e=>e?[...e.querySelectorAll("input[type='checkbox']:checked")].map(e=>Number.parseInt(e.value||"",10)).filter(e=>Number.isInteger(e)&&e>0):[],Ro=()=>{const e=Number.parseInt(Ne?.value||"",10);return Number.isInteger(e)&&e>0?e:null},Uo=(e,t,n,r)=>{const o=((e,t)=>(Array.isArray(e?.contentControls?.items)?e.contentControls.items:[]).find(e=>_r(e.tag,t))||null)(e,r),a=o||e.getRange().insertContentControl();return a.title=t,a.tag=n,a.appearance="Hidden",a},Mo=async(e="PlotDirector IDs attached successfully.")=>{if(!Zt||!_t)return Un("No resolved PlotDirector scene."),!1;if((Xt&&Xt!==Zt||Qt&&Qt!==_t)&&!window.confirm("This scene is already linked. Replace the existing PlotDirector link?"))return!1;if(!Bt||!Gt||!window.Word||"function"!=typeof window.Word.run)return Un("Word document access is unavailable."),!1;ie&&(ie.disabled=!0,ie.textContent="Attaching...");try{return await window.Word.run(async e=>{const t=await bo(e);if(!t.currentChapter||!t.currentScene)throw new Error("No scene detected in Word. Use Heading 2 for scenes.");const n=t.bodyParagraphs[t.currentChapter.paragraphIndex],r=t.bodyParagraphs[t.currentScene.paragraphIndex];if(!n||!r)throw new Error("Unable to locate the current Word headings.");Uo(n,"PlotDirector Chapter",`PD-CHAPTER-${_t}`,"PD-CHAPTER"),Uo(r,"PlotDirector Scene",`PD-SCENE-${Zt}`,"PD-SCENE"),await e.sync()}),Qt=_t,Xt=Zt,nn=!1,tn="SceneID Anchor",en="Anchor",Un(e),qr({lastError:"-"}),Hn(),!0}catch(e){return console.error("Unable to attach PlotDirector IDs.",e),Un("Unable to attach PlotDirector IDs."),qr({lastError:Pr(e)}),Hn(),!1}finally{ie&&(ie.textContent=Xt===Zt?"Attach PlotDirector IDs":"Reattach PlotDirector IDs",Hn())}},Oo=async e=>{if(!_t)return dr("No resolved PlotDirector chapter."),!1;if(!Bt||!Gt||!window.Word||"function"!=typeof window.Word.run)return dr("Word document access is unavailable."),!1;try{return await window.Word.run(async e=>{const t=await bo(e);if(!t.currentChapter)throw new Error("No chapter detected in Word. Use Heading 1 for chapters.");const n=t.bodyParagraphs[t.currentChapter.paragraphIndex];if(!n)throw new Error("Unable to locate the current Word chapter heading.");Uo(n,"PlotDirector Chapter",`PD-CHAPTER-${_t}`,"PD-CHAPTER"),await e.sync()}),Qt=_t,nn=!1,tn="ChapterID Anchor",en="Chapter anchor",dr(e),Un(e),qr({lastError:"-"}),Hn(),!0}catch(e){return console.error("Unable to attach PlotDirector chapter ID.",e),dr("Unable to attach PlotDirector chapter ID."),qr({lastError:Pr(e)}),Hn(),!1}},Ho=async e=>{pr(),await Qo(),Un(e),dr(e)},Bo=e=>{dn&&(dn(e),dn=null),at?.close?at.close():at&&(at.hidden=!0)},Go=()=>{if(!tt)return;const e=Cr(et?.value||"").toLocaleLowerCase(),t=cn.filter(t=>!e||String(t.title||"").toLocaleLowerCase().includes(e));if(tt.innerHTML="",sn=null,nt&&(nt.disabled=!0),0===t.length){const e=document.createElement("p");return e.className="word-companion-empty-list",e.textContent="No chapters found.",void tt.append(e)}for(const e of t){const t=Number.parseInt(e.chapterId||"",10);if(!Number.isInteger(t)||t<=0)continue;const n=document.createElement("label");n.className="word-companion-scene-option";const r=document.createElement("input");r.type="radio",r.name="word-companion-link-chapter",r.value=String(t),r.addEventListener("change",()=>{sn=t,nt&&(nt.disabled=!1)});const o=document.createElement("span");o.textContent=e.title||"Untitled chapter",n.append(r,o),tt.append(n)}},Fo=()=>{_e?.close?_e.close():_e&&(_e.hidden=!0)},Vo=async(e,t,n)=>{const r=Ur();if(!r)return sr("Select a PlotDirector book first."),!1;await Nr(r.bookId,e,t,"Manual link","Title Match");return!!await Mo(n)&&(sr(n),mr(),!0)},Jo=e=>{an&&(an(e),an=null),ze?.close?ze.close():ze&&(ze.hidden=!0)},Yo=()=>{if(!Fe)return;const e=Cr(Ge?.value||"").toLocaleLowerCase(),t=rn.filter(t=>!e||String(t.title||"").toLocaleLowerCase().includes(e));if(Fe.innerHTML="",on=null,Ve&&(Ve.disabled=!0),0===t.length){const e=document.createElement("p");return e.className="word-companion-empty-list",e.textContent="No scenes found.",void Fe.append(e)}for(const e of t){const t=Number.parseInt(e.sceneId||"",10);if(!Number.isInteger(t)||t<=0)continue;const n=document.createElement("label");n.className="word-companion-scene-option";const r=document.createElement("input");r.type="radio",r.name="word-companion-link-scene",r.value=String(t),r.addEventListener("change",()=>{on=t,Ve&&(Ve.disabled=!1)});const o=document.createElement("span");o.textContent=e.title||"Untitled scene",n.append(r,o),Fe.append(n)}},zo=()=>{Be?.close?Be.close():Be&&(Be.hidden=!0)},Ko=async()=>{const e=Rr(),t=Ur(),n=br(Jt,"chapter");if(Ir({projectId:e?.projectId,projectTitle:e?.title,bookId:t?.bookId,bookTitle:t?Wr(t):void 0,detectedChapter:Jt,detectedScene:Yt,requestChapter:n,requestScene:"",result:"Not run",chapterId:null,sceneId:null}),!t)return wr("Not detected"),Un("Select a PlotDirector book first."),!1;if(!Jt)return wr("Not detected"),Un("No chapter detected in Word. Use Heading 1 for chapters."),!1;wr("Not detected");try{const e=await vr(t.bookId),r=Qt?e.find(e=>e.chapterId===Qt):null,o=n.toLocaleLowerCase(),a=o?e.find(e=>br(e.title,"chapter").toLocaleLowerCase()===o):null,c=r||a;return c?(pr(),er(null,c.chapterId,r?"Chapter anchor":"Chapter title"),tn=r?"ChapterID Anchor":"Title Match",Mn("Chapter linked to PlotDirector"),Un("No scene detected in Word. Use Heading 2 for scenes."),Ir({result:"Chapter matched",chapterId:c.chapterId,sceneId:null}),!0):(er(null),Mn("Chapter not found in PlotDirector."),Un("Chapter not found in PlotDirector."),Ir({result:"Chapter not matched",chapterId:null,sceneId:null}),hr("Chapter not found in PlotDirector."),!1)}catch(e){return wr("Not found in PlotDirector"),qr({lastError:Pr(e)}),Un("Unable to load PlotDirector chapter data."),!1}},Qo=async()=>{const e=Rr(),t=Ur(),n=br(Jt,"chapter"),r=br(Yt,"scene");if(Ir({projectId:e?.projectId,projectTitle:e?.title,bookId:t?.bookId,bookTitle:t?Wr(t):void 0,detectedChapter:Jt,detectedScene:Yt,requestChapter:n,requestScene:r,result:"Not run",chapterId:null,sceneId:null}),On({anchorType:Xt?"SceneID Anchor":Qt?"ChapterID Anchor":"Title Match",storedSceneId:Xt,storedChapterId:Qt,resolutionMethod:"-"}),!t)return wr("Not detected"),Un("Select a PlotDirector book first."),Ir({result:"Error"}),!1;if(!Jt||!Yt)return wr("Not detected"),Un("No scene detected in Word. Use Heading 2 for scenes."),Ir({result:"Error"}),!1;te&&(te.disabled=!0,te.textContent="Refreshing...");const o=()=>{te&&(te.disabled=!1,te.textContent="Refresh PlotDirector Scene")};wr("Not detected"),Un("Resolving PlotDirector scene...");try{if(Xt){const e=await(async(e,t)=>{const n=await Ao(`/api/word-companion/books/${e}/structure`),r=Array.isArray(n?.chapters)?n.chapters:[];for(const e of r){const n=Array.isArray(e.scenes)?e.scenes:[];for(const r of n)if(t(e,r))return{chapter:e,scene:r}}return null})(t.bookId,(e,t)=>t.sceneId===Xt);if(e)return Ir({result:"Matched",chapterId:e.chapter.chapterId,sceneId:e.scene.sceneId}),await Nr(t.bookId,e.scene.sceneId,e.chapter.chapterId,"Anchor","SceneID Anchor"),!0;nn=!0,tn="SceneID Anchor",Mn("Not found in PlotDirector"),Un("Stored PlotDirector ID is invalid."),Ir({result:"Error",chapterId:Qt,sceneId:Xt}),On({anchorType:"SceneID Anchor",storedSceneId:Xt,storedChapterId:Qt,resolutionMethod:"Anchor"})}if(Qt){const e=(await kr(t.bookId)).find(e=>e.chapterId===Qt),n=e?(Array.isArray(e.scenes)?e.scenes:[]).find(e=>br(e.title,"scene").toLocaleLowerCase()===r.toLocaleLowerCase()):null;if(n)return Ir({result:"Matched",chapterId:e.chapterId,sceneId:n.sceneId}),await Nr(t.bookId,n.sceneId,e.chapterId,"Anchor","ChapterID Anchor"),!0;e&&!Xt?(tn="ChapterID Anchor",er(null,Qt,"Chapter anchor"),Ir({result:"Chapter matched",chapterId:Qt,sceneId:null})):Xt||(tn="ChapterID Anchor",Ir({result:"Chapter anchor not found",chapterId:Qt,sceneId:null}))}const e=await To(`/api/word-companion/books/${t.bookId}/resolve-scene`,{chapterTitle:n,sceneTitle:r});if(!e?.matched||!e.sceneId){const t=nn,n=Number.parseInt(e?.chapterId||"",10),r=Number.isInteger(_t)&&_t>0?_t:null,a=Number.isInteger(n)&&n>0?n:r,c=!!e?.chapterMatched||!!a;return wr("Not found in PlotDirector"),nn=t,c&&(er(null,a,a===r?"Chapter anchor":"Chapter title"),Mn("Scene not found in PlotDirector.")),Un(t?"Stored PlotDirector ID is invalid.":c?"Scene not found in PlotDirector.":"This chapter does not exist in PlotDirector. Create or link the chapter first."),Ir({result:"Not matched",chapterId:c?a:e?.chapterId,sceneId:e?.sceneId}),t||(c?(pr(),yr("Scene not found in PlotDirector.")):(mr(),hr("Chapter not found in PlotDirector."))),o(),!1}const a=nn;return Ir({result:a?"Matched by title fallback":"Matched",chapterId:e.chapterId,sceneId:e.sceneId}),await Nr(t.bookId,e.sceneId,e.chapterId,a?"Title fallback":"Title","Title Match"),a&&(nn=!0,Un("Stored PlotDirector ID is invalid."),Hn()),!0}catch(e){const t=nn;return qr({lastError:Pr(e)}),wr("Not found in PlotDirector"),nn=t,Un(t?"Stored PlotDirector ID is invalid.":"Unable to load PlotDirector scene data."),Ir({result:"Error"}),!1}finally{o()}},Xo=async()=>{if(!Ln&&Mt&&Ur()){if(!Bt||!Gt||!window.Word||"function"!=typeof window.Word.run)return Zn("Manual"),void Un("Automatic scene tracking is unavailable in this Word version. Use Refresh Current Scene.");if(!hn)return Zn("Manual"),void Un("Document structure is not cached yet. Use Refresh Current Scene.");Ln=!0,Zn("Live");try{const e=await window.Word.run(async e=>await(async e=>{const t=e.document.getSelection().paragraphs;return t.load("text,styleBuiltIn,style"),await e.sync(),t.items})(e)),t=co(hn,e);if(!io(t))return _n(!1),void Zn("Live");Yt?await Qo():await Ko(),_n(!1),Zn("Live"),Un("")}catch(e){console.error("Unable to refresh current scene from Word selection.",e),qr({lastError:Pr(e)}),_n(!0,"The Word cursor is now in a different scene. Refresh Current Scene before saving.")}finally{Ln=!1}}},Zo=()=>{En&&window.clearTimeout(En),En=window.setTimeout(Xo,850)},_o=()=>{if(Nn&&window.Office?.context?.document&&"function"==typeof window.Office.context.document.removeHandlerAsync&&window.Office?.EventType?.DocumentSelectionChanged)try{window.Office.context.document.removeHandlerAsync(window.Office.EventType.DocumentSelectionChanged,{handler:Zo}),Nn=!1}catch(e){console.warn("Unable to remove Word selection tracking handler.",e)}},ea=async(e,n)=>{if(hn=null,cr(),!e)return Ht=[],$r(M,"Select a project first"),$r(m,"Select a project first"),Rn(""),Tr(t,null),Kr(),wr("Not detected"),void Jn();$r(M,"Loading books..."),Rn(""),wr("Not detected"),Jn("Select a book to analyse manuscript structure.");try{const r=await Ao(`/api/word-companion/projects/${e}/books`);if(Ht=Array.isArray(r.books)?r.books:[],0===Ht.length)return $r(M,"No books available."),$r(m,"No books available."),Rn("No books available."),Tr(t,null),Kr(),void Vr("No books available.");jr(M,"Choose a book",Ht.map(e=>({...e,displayTitle:Wr(e)})),"bookId","displayTitle");const o=Ht.find(e=>e.bookId===n);o&&M?(M.value=String(o.bookId),Tr(t,o.bookId)):Tr(t,null),((e=null)=>{if(!m)return;if(0===Ht.length)return void $r(m,"No books available.");jr(m,"Choose a book",Ht.map(e=>({...e,displayTitle:Wr(e)})),"bookId","displayTitle");const t=e||Number.parseInt(M?.value||"",10),n=Ht.find(e=>e.bookId===t);n&&(m.value=String(n.bookId)),Br()})(o?.bookId||n),Kr(),wr((Ur(),"Not detected")),Jn(Ur()?"Ready to analyse manuscript structure.":"Select a book to analyse manuscript structure."),Vr(Or()?"Ready to scan manuscript structure.":"Select a Book to begin.")}catch{Ht=[],$r(M,"Unable to load books."),$r(m,"Unable to load books."),Rn("Unable to load books."),Tr(t,null),Kr(),wr("Not detected"),Jn("Unable to load books."),Vr("Unable to load books.")}};for(const e of l)e.addEventListener("click",()=>Tn(e.dataset.tabButton));$n(),U?.addEventListener("change",async()=>{const n=Number.parseInt(U.value||"",10);ar(),h&&Number.isInteger(n)&&n>0&&(h.value=String(n)),Tr(e,Number.isInteger(n)&&n>0?n:null),Tr(t,null),wr("Not detected"),Jn(),Vr("Select a Book to begin."),await ea(n,null)}),M?.addEventListener("change",()=>{const e=Number.parseInt(M.value||"",10);ar(),Tr(t,Number.isInteger(e)&&e>0?e:null),m&&Number.isInteger(e)&&e>0&&(m.value=String(e)),Kr(),wr("Not detected"),Jn(Ur()?"Ready to analyse manuscript structure.":"Select a book to analyse manuscript structure."),Vr(Or()?"Ready to scan manuscript structure.":"Select a Book to begin.")}),h?.addEventListener("change",async()=>{const n=Number.parseInt(h.value||"",10);ar(),U&&Number.isInteger(n)&&n>0&&(U.value=String(n)),Tr(e,Number.isInteger(n)&&n>0?n:null),Tr(t,null),Vr("Select a Book to begin."),await ea(n,null)}),m?.addEventListener("change",()=>{const e=Number.parseInt(m.value||"",10);ar(),M&&Number.isInteger(e)&&e>0&&(M.value=String(e)),Tr(t,Number.isInteger(e)&&e>0?e:null),Kr(),Vr(Or()?"Ready to scan manuscript structure.":"Select a Book to begin.")}),y?.addEventListener("input",Br),w?.addEventListener("click",async()=>{const e=Mr(),t=String(y?.value||"").trim();if(e&&t){w.disabled=!0,Hr("Creating Book...");try{const n=await To(`/api/word-companion/projects/${e.projectId}/books`,{title:t});y&&(y.value=""),U&&(U.value=String(e.projectId)),await ea(e.projectId,n.bookId),m&&(m.value=String(n.bookId)),Hr("Ready to scan manuscript structure.")}catch(e){console.error("Unable to create Book from Word Companion.",e),Hr(`Unable to create Book: ${Pr(e)}`)}finally{Br()}}else Br()}),f?.addEventListener("click",async()=>{const e=Mr(),t=Or();if(e&&t)if(Bt&&Gt&&window.Word&&"function"==typeof window.Word.run){f&&(f.disabled=!0,f.textContent="Scanning..."),Hr("Scanning manuscript structure...");try{const n=await window.Word.run(async e=>{const n=e.document.body.paragraphs;return n.load("text,styleBuiltIn,style"),await e.sync(),((e,t)=>{const n=[];let r=null,o=null,a=0;const c=[],i=new Set(["***","###"]),s=()=>{if(!r)return null;const e={title:`Scene ${r.scenes.length+1}`,sortOrder:10*(r.scenes.length+1),wordCount:0};return r.scenes.push(e),e};return e.forEach(e=>{const d=String(e.text||"").trim();if(!d)return;if(c.push(d),Xr(e,1))return r={title:d,sortOrder:10*(n.length+1),wordCount:0,scenes:[]},n.push(r),o=s(),void(a+=Zr(d));if(!r||!o)return;if(t&&i.has(d))return void(o=s());const l=Zr(d);r.wordCount+=l,o.wordCount+=l,a+=l}),{chapters:n,chapterCount:n.length,sceneCount:n.reduce((e,t)=>e+t.scenes.length,0),wordCount:a,documentText:c.join("\n")}})(n.items,!!t.usesExplicitScenes)});fn=n,Sn=!1;const r=await To("/api/word-companion/manuscript/analyse",{projectId:e.projectId,bookId:t.bookId,documentGuid:zr(),chapterCount:n.chapterCount,sceneCount:n.sceneCount,wordCount:n.wordCount});wn=r,(e=>{if(!C)return;C.innerHTML="";const t=document.createElement("strong");t.textContent="Manuscript Analysis",C.append(t);const n=document.createElement("dl"),r=[["Project",e.projectTitle],["Book",Wr({title:e.bookTitle,subtitle:e.bookSubtitle})],["Chapters",Number(e.chapterCount||0).toLocaleString()],["Scenes",Number(e.sceneCount||0).toLocaleString()],["Words",Number(e.wordCount||0).toLocaleString()]];for(const[e,t]of r){const r=document.createElement("dt");r.textContent=e;const o=document.createElement("dd");o.textContent=t||"-",n.append(r,o)}C.append(n),Gn(C,!1),Gn(N,!1),Hr(e.message||"Preview generated."),Br()})(r);try{const t=await To("/api/word-companion/manuscript/discover-characters",{projectId:e.projectId,documentText:n.documentText||""});Yr(t?.candidates||[])}catch(e){console.error("Unable to discover character candidates.",e),Yr([]),Lr(I,"Character discovery is unavailable.")}qr({lastScan:"Success",lastError:"-",paragraphs:"-",heading1:String(n.chapterCount),heading2:"-"})}catch(e){console.error("Unable to scan manuscript for first-run import.",e),Vr(`Unable to scan manuscript: ${Pr(e)}`),qr({lastScan:"Failure",lastError:Pr(e)})}finally{f&&(f.textContent="Scan Manuscript"),Br()}}else Vr("Word document access is unavailable.");else Vr("Select a Project and Book to begin.")}),L?.addEventListener("click",async()=>{const n=Mr(),i=Or();if(!(n&&i&&fn&&wn?.canImport))return void Br();let s=!1;if(!wn.requiresReplaceConfirmation||(s=await new Promise(e=>{if(!P||"function"!=typeof P.showModal)return void e(window.confirm("This Book already contains planned chapters and scenes.\n\nImporting this manuscript will replace the planned structure.\n\nContinue?"));const t=t=>{D?.removeEventListener("click",n),A?.removeEventListener("click",r),P?.removeEventListener("cancel",o),P?.close(),e(t)},n=()=>t(!0),r=()=>t(!1),o=e=>{e.preventDefault(),t(!1)};D?.addEventListener("click",n),A?.addEventListener("click",r),P?.addEventListener("cancel",o),P.showModal()}),s)){Cn=!0,Br(),Hr("Importing manuscript structure...");try{const l=zr(),u=await To("/api/word-companion/manuscript/import",{projectId:n.projectId,bookId:i.bookId,documentGuid:l,bindingVersion:1,replacePlanned:s,chapters:fn.chapters});if(!u.imported)return wn={...wn,canImport:!u.requiresReplaceConfirmation,requiresReplaceConfirmation:!!u.requiresReplaceConfirmation,message:u.message||wn.message},Hr(u.message||"Import was not completed."),void Br();const p=u.manuscriptDocument;await(d={documentGuid:p?.documentGuid||l,bookId:u.bookId,projectId:u.projectId,bindingVersion:p?.bindingVersion||1},new Promise((e,t)=>{const n=window.Office?.context?.document?.settings;n?(n.set(r,d.documentGuid),n.set(o,String(d.bookId)),n.set(a,String(d.projectId)),n.set(c,String(d.bindingVersion||1)),n.saveAsync(n=>{n.status===window.Office.AsyncResultStatus.Succeeded?e():t(n.error||new Error("Unable to save Word document metadata."))})):t(new Error("Word document settings are unavailable."))})),un={documentGuid:p?.documentGuid||l,bookId:u.bookId,projectId:u.projectId,bindingVersion:p?.bindingVersion||1},Tr(e,u.projectId),Tr(t,u.bookId),U&&(U.value=String(u.projectId));const h=gn;await ea(u.projectId,u.bookId),jn("Connected"),Sn=!0,gn=h,h.length>0?(Gr(!0),Yr(h),Gn(N,!0),Gn(v,!1),Hr(u.message||"Manuscript structure imported."),Un(u.message||"Manuscript structure imported.")):(Gr(!1),Un(u.message||"Manuscript structure imported."))}catch(e){console.error("Unable to import manuscript structure.",e),Hr(`Unable to import manuscript: ${Pr(e)}`)}finally{Cn=!1,Br()}var d}else Hr("Import cancelled.")}),x?.addEventListener("click",async()=>{const e=Mr()||Rr(),t=Jr();if(e&&0!==t.length){bn=!0,Br(),Lr(I,"Creating selected characters...");try{const n=await To("/api/word-companion/manuscript/create-discovered-characters",{projectId:e.projectId,candidateNames:t});Un(n.message||"Characters created."),Lr(I,`${n.createdCount||0} created, ${n.skippedCount||0} already existed.`),$o()}catch(e){console.error("Unable to create discovered characters.",e),Lr(I,`Unable to create characters: ${Pr(e)}`)}finally{bn=!1,Br()}}else Br()}),E?.addEventListener("click",$o),g?.addEventListener("click",()=>Gr(!1)),q?.addEventListener("click",()=>Vr("Import cancelled.")),G?.addEventListener("click",ko),X?.addEventListener("click",vo),Z?.addEventListener("click",async()=>{const e=Ur();if(!e||0===Yn().length||In)return void zn();if(!await Eo())return;In=!0,Kn(),Vn("Applying structure sync...");const t={createdChapters:0,createdScenes:0,linkedChapters:0,linkedScenes:0,skipped:Array.isArray(ln?.manualReview)?ln.manualReview.length:0,failed:0},n=Yn().filter(e=>"couldLink"===e.category&&"Chapter"===e.type),r=Yn().filter(e=>"wouldCreateChapters"===e.category),o=Yn().filter(e=>"couldLink"===e.category&&"Scene"===e.type),a=Yn().filter(e=>"wouldCreateScenes"===e.category),c=[];let i="";const s=(e,t)=>{c.push({item:e,counterName:t})},d=async(e,n)=>{try{await(async e=>{if(!Bt||!Gt||!window.Word||"function"!=typeof window.Word.run)throw new Error("Word document access is unavailable.");await window.Word.run(async t=>{const n=await bo(t),r="Chapter"===e.type?e.wordChapter:e.wordScene,o=Number.isInteger(r?.paragraphIndex)?n.bodyParagraphs[r.paragraphIndex]:null;if(!o)throw new Error("Unable to locate the Word heading.");if("Chapter"===e.type){const t=e.pdChapter?.chapterId;if(!t)throw new Error("Chapter ID is not available.");Uo(o,"PlotDirector Chapter",`PD-CHAPTER-${t}`,"PD-CHAPTER")}else{const t=e.pdScene?.sceneId;if(!t)throw new Error("Scene ID is not available.");Uo(o,"PlotDirector Scene",`PD-SCENE-${t}`,"PD-SCENE")}await t.sync()})})(e),No(e,"Success"),t[n]+=1}catch(n){No(e,"Failed",Pr(n)),t.failed+=1}};try{for(const e of n)s(e,"linkedChapters");for(const n of r)try{await Po(e.bookId,n),s(n,"createdChapters")}catch(e){No(n,"Failed",Pr(e)),t.failed+=1}for(const e of o)s(e,"linkedScenes");for(const n of a)try{await Do(e.bookId,n),s(n,"createdScenes")}catch(e){No(n,"Failed",Pr(e)),t.failed+=1}for(const e of c)await d(e.item,e.counterName);for(const e of ln.manualReview||[])No(e,"Skipped");Co(ln),i=(e=>`Structure Sync Complete. Created: ${e.createdChapters} Chapters, ${e.createdScenes} Scenes. Linked: ${e.linkedChapters} Chapters, ${e.linkedScenes} Scenes. Skipped: ${e.skipped} Manual Review items. Failed: ${e.failed} Items.`)(t),Vn(i)}finally{In=!1,Kn(),i&&(cr(),await vo(),Vn(`${i} Preview refreshed.`))}}),pt?.addEventListener("click",()=>xo(!0)),ht?.addEventListener("click",()=>xo(!1)),lt?.addEventListener("cancel",e=>{e.preventDefault(),xo(!1)}),te?.addEventListener("click",Qo),B?.addEventListener("click",async()=>{if(!Ur())return Un("Select a PlotDirector book first."),void wr("Not detected");tr(!0);try{if(!await ko())return;if(_n(!1),!Yt)return void await Ko();await Qo()}finally{tr(!1)}}),fe?.addEventListener("click",async()=>{if(!Zt)return void Fn("No resolved PlotDirector scene.");if(xn)return void Fn("Refresh Current Scene before syncing.");if(!Number.isInteger(zt))return void Fn("Unable to sync progress.");fe&&(fe.disabled=!0,fe.textContent="Syncing...");const e=(new Date).toISOString();try{const r=await(t=`/api/word-companion/scenes/${Zt}/word-count`,n={actualWordCount:zt,lastWorkedOn:e},Ao(t,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)}));Lr(Se,nr(r?.actualWords??zt)),Lr(pe,nr(r?.actualWords??zt)),Lr(Ce,(new Date).toLocaleString()),Fn("Progress synced successfully.")}catch{Fn("Unable to sync progress.")}finally{fe&&(fe.disabled=!Zt||xn,fe.textContent="Sync Progress")}var t,n}),Le?.addEventListener("click",async()=>{if(Zt)if(!xn&&await(async()=>{if(!Zt)return!1;if(!Bt||!Gt||!window.Word||"function"!=typeof window.Word.run)return _n(!0,"The Word cursor is now in a different scene. Refresh Current Scene before saving."),!1;try{const e=await window.Word.run(async e=>await bo(e)),t=e.currentChapter?.title||"",n=e.currentScene?.title||"",r=e.currentScene?.anchorId||null,o=e.currentChapter?.anchorId||null,a=Number.isInteger(r)&&r===Zt,c=Number.isInteger(o)&&o===_t,i=br(n,"scene").toLocaleLowerCase()===br(qn||Yt,"scene").toLocaleLowerCase(),s=br(t,"chapter").toLocaleLowerCase()===br(Pn||Jt,"chapter").toLocaleLowerCase();return a||i&&(c||s)?(_n(!1),!0):(_n(!0,"The Word cursor is now in a different scene. Refresh Current Scene before saving."),!1)}catch(e){return console.error("Unable to verify current Word scene before saving.",e),qr({lastError:Pr(e)}),_n(!0,"The Word cursor is now in a different scene. Refresh Current Scene before saving."),!1}})()){Le&&(Le.disabled=!0,Le.textContent="Saving...");try{await(e=`/api/word-companion/scenes/${Zt}/links`,t={characterIds:Wo(xe),assetIds:Wo(Ee),locationIds:[],primaryLocationId:Ro()},Ao(e,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})),(()=>{const e=new Set(Wo(xe)),t=new Set(Wo(Ee));Dn={characters:Dn.characters.map(t=>({...t,linked:e.has(Number.parseInt(fr(t,"character"),10))})),assets:Dn.assets.map(e=>({...e,linked:t.has(Number.parseInt(fr(e,"asset"),10))})),locations:Dn.locations,primaryLocationId:Ro()}})(),ir("Scene links saved successfully."),qr({lastError:"-"})}catch(e){ir("Unable to save scene links."),qr({lastError:Pr(e)})}finally{Le&&(Le.disabled=!Zt||xn,Le.textContent="Save Scene Links")}var e,t}else ir("The Word cursor is now in a different scene. Refresh Current Scene before saving.");else ir("Link a PlotDirector scene first.")}),ie?.addEventListener("click",async()=>{await Mo()}),Te?.addEventListener("click",async()=>{const e=Ur();if(!e||!Jt||_t)return void hr("Chapter not found in PlotDirector.");const t=Cr(Jt),n=await((e,t)=>(Lr(ct,`"${e}"`),Lr(it,`"${t}"`),at?new Promise(e=>{dn=e,at.showModal?at.showModal():at.hidden=!1}):Promise.resolve(window.confirm(`Create PlotDirector chapter:\n\n"${e}"\n\nin book:\n\n"${t}"\n\n?`))))(t,Wr(e)||"selected book");if(n){Te&&(Te.disabled=!0,Te.textContent="Creating...");try{const n=Number.isInteger(Kt)&&Kt>0?10*Kt:null,r=await To(`/api/word-companion/books/${e.bookId}/chapters`,{title:t,sortOrder:n});if(!r?.chapterId)throw new Error("Chapter creation did not return a chapter ID.");cr(),er(null,r.chapterId,"Manual chapter link");if(!await Oo("Chapter created and linked successfully."))return;await Ho("Chapter created and linked successfully.")}catch(e){dr("Unable to create chapter."),qr({lastError:Pr(e)})}finally{Te&&(Te.disabled=!lr(),Te.textContent="Create Chapter in PlotDirector")}}}),$e?.addEventListener("click",async()=>{const e=Ur();if(e&&Jt&&!_t){$e&&($e.disabled=!0,$e.textContent="Loading...");try{cn=await vr(e.bookId),sn=null,et&&(et.value=""),Lr(ot,""),Go(),_e?.showModal?_e.showModal():_e&&(_e.hidden=!1)}catch(e){dr("Unable to load chapters."),qr({lastError:Pr(e)})}finally{$e&&($e.disabled=!lr(),$e.textContent="Link to Existing Chapter")}}else hr("Chapter not found in PlotDirector.")}),et?.addEventListener("input",Go),nt?.addEventListener("click",async()=>{const e=cn.find(e=>e.chapterId===sn);if(e){nt&&(nt.disabled=!0,nt.textContent="Linking...");try{er(null,e.chapterId,"Manual chapter link");if(!await Oo("Chapter linked successfully."))return;Fo(),await Ho("Chapter linked successfully.")}catch(e){Lr(ot,"Unable to link chapter."),dr("Unable to link chapter."),qr({lastError:Pr(e)})}finally{nt&&(nt.disabled=!sn,nt.textContent="Link Chapter")}}else Lr(ot,"Select a chapter.")}),rt?.addEventListener("click",Fo),st?.addEventListener("click",()=>Bo(!0)),dt?.addEventListener("click",()=>Bo(!1)),at?.addEventListener("cancel",e=>{e.preventDefault(),Bo(!1)}),Me?.addEventListener("click",async()=>{const e=Ur();if(!e||!Yt)return void yr("Scene not found in PlotDirector.");const t=br(Yt,"scene"),n=br(Jt,"chapter"),r=await((e,t)=>(Lr(Ke,`"${e}"`),Lr(Qe,`"${t}"`),ze?new Promise(e=>{an=e,ze.showModal?ze.showModal():ze.hidden=!1}):Promise.resolve(window.confirm(`Create PlotDirector scene:\n\n"${e}"\n\nwithin chapter:\n\n"${t}"\n\n?`))))(t,n);if(r){Me&&(Me.disabled=!0,Me.textContent="Creating...");try{const n=await Er();if(!n)return void yr("This chapter does not exist in PlotDirector. Create or link the chapter first.");const r=await To(`/api/word-companion/books/${e.bookId}/chapters/${n.chapterId}/scenes`,{sceneTitle:t});if(!r?.sceneId||!r?.chapterId)throw new Error("Scene creation did not return a scene ID.");cr(),await Vo(r.sceneId,r.chapterId,"Scene created and linked successfully.")}catch(e){sr("Unable to create scene."),qr({lastError:Pr(e)})}finally{Me&&(Me.disabled=!ur(),Me.textContent="Create Scene in PlotDirector")}}}),Oe?.addEventListener("click",async()=>{const e=Ur();if(e&&Yt){Oe&&(Oe.disabled=!0,Oe.textContent="Loading...");try{const t=await kr(e.bookId),n=xr(t);if(!n)return void yr("This chapter does not exist in PlotDirector. Create or link the chapter first.");rn=Array.isArray(n.scenes)?n.scenes:[],on=null,Ge&&(Ge.value=""),Lr(Ye,""),Yo(),Be?.showModal?Be.showModal():Be&&(Be.hidden=!1)}catch(e){sr("Unable to load scenes."),qr({lastError:Pr(e)})}finally{Oe&&(Oe.disabled=!ur(),Oe.textContent="Link to Existing Scene")}}else yr("Scene not found in PlotDirector.")}),Ge?.addEventListener("input",Yo),Ve?.addEventListener("click",async()=>{const e=Ur(),t=rn.find(e=>e.sceneId===on);if(e&&t){Ve&&(Ve.disabled=!0,Ve.textContent="Linking...");try{const e=await Er();if(!e)throw new Error("This chapter does not exist in PlotDirector. Create or link the chapter first.");zo(),await Vo(t.sceneId,e.chapterId,"Scene linked successfully.")}catch(e){Lr(Ye,"Unable to link scene."),sr("Unable to link scene."),qr({lastError:Pr(e)})}finally{Ve&&(Ve.disabled=!on,Ve.textContent="Link Scene")}}else Lr(Ye,"Select a scene.")}),Je?.addEventListener("click",zo),Xe?.addEventListener("click",()=>Jo(!0)),Ze?.addEventListener("click",()=>Jo(!1)),ze?.addEventListener("cancel",e=>{e.preventDefault(),Jo(!1)}),xt?.addEventListener("click",async()=>{xt&&(xt.disabled=!0,xt.textContent="Running...");try{if(await Dr(),!Bt||!Gt||!window.Word||"function"!=typeof window.Word.run)return void qr({lastScan:"Failure",lastError:"Word document access is unavailable.",paragraphs:"-",heading1:"-",heading2:"-"});const e=await window.Word.run(async e=>{const t=e.document.body.paragraphs;return t.load("items"),await e.sync(),t.items.length});qr({lastScan:"Success",lastError:"-",paragraphs:String(e)})}catch(e){console.error("Word Companion diagnostics failed.",e);const t=Pr(e);qr({lastScan:"Failure",lastError:t}),Un(`Unable to scan the Word document: ${t}`)}finally{xt&&(xt.disabled=!1,xt.textContent="Run Diagnostics")}});const ta=Mt?(async()=>{$r(U,"Loading projects..."),$r(M,"Select a project first"),$r(h,"Loading projects..."),$r(m,"Select a project first"),Wn(""),Rn("");try{const n=await Ao("/api/word-companion/projects");if(Ot=Array.isArray(n.projects)?n.projects:[],0===Ot.length)return $r(U,"No projects available."),$r(h,"No projects available."),Wn("No projects available."),Tr(e,null),Tr(t,null),Kr(),void Vr("No projects available.");jr(U,"Choose a project",Ot,"projectId","title"),Fr();const r=Ar(e),o=Ot.find(e=>e.projectId===r);o&&U?(U.value=String(o.projectId),h&&(h.value=String(o.projectId)),Tr(e,o.projectId),await ea(o.projectId,Ar(t))):(Tr(e,null),Tr(t,null),Kr(),Vr("Select a Project and Book to begin."))}catch{Ot=[],Ht=[],$r(U,"Unable to connect to PlotDirector."),$r(M,"Select a project first"),$r(h,"Unable to connect to PlotDirector."),$r(m,"Select a project first"),jn("Unable to connect to PlotDirector."),Wn("Unable to connect to PlotDirector."),Tr(e,null),Tr(t,null),Kr(),Vr("Unable to connect to PlotDirector.")}})():Promise.resolve();if(Mt||($r(U,"Please sign in to PlotDirector."),$r(M,"Please sign in to PlotDirector."),$r(h,"Please sign in to PlotDirector."),$r(m,"Please sign in to PlotDirector."),Kr()),!window.Office||"function"!=typeof window.Office.onReady)return An("Word Companion ready"),Un("Word document access is unavailable."),Zn("Manual"),void qr({host:"Unavailable",platform:"Unavailable",ready:"No",wordApi:"No"});Dr().then(async()=>{An("Word Companion ready"),await ta,await jo(),Gt?(()=>{if(Mt){if(!window.Office?.context?.document||"function"!=typeof window.Office.context.document.addHandlerAsync||!window.Office?.EventType?.DocumentSelectionChanged)return Zn("Manual"),void Un("Automatic scene tracking is unavailable in this Word version. Use Refresh Current Scene.");try{window.Office.context.document.addHandlerAsync(window.Office.EventType.DocumentSelectionChanged,Zo,e=>{e?.status===window.Office.AsyncResultStatus.Succeeded?(Nn=!0,Zn("Live")):(Zn("Manual"),Un("Automatic scene tracking is unavailable in this Word version. Use Refresh Current Scene."))}),window.addEventListener("beforeunload",_o)}catch(e){console.warn("Unable to register Word selection tracking handler.",e),Zn("Manual"),Un("Automatic scene tracking is unavailable in this Word version. Use Refresh Current Scene.")}}})():(Un("Word document access is unavailable."),Zn("Manual"))}).catch(e=>{console.error("Office readiness check failed.",e),jn("Unable to connect to PlotDirector."),An("Word Companion unavailable"),Un("Word document access is unavailable."),qr({ready:"No",wordApi:"No",lastScan:"Failure"})})})(); \ No newline at end of file