From 794606f723c4468f0afca3aed34cf853562d7c51 Mon Sep 17 00:00:00 2001 From: Nick Beckley Date: Sat, 29 Aug 2026 21:42:09 +0000 Subject: [PATCH] Fix structural Word paragraph mapping --- PlotLine.Tests/Program.cs | 226 ++++++++++++++++++ .../ManuscriptStructureAnalysisService.cs | 139 ++++++++++- PlotLine/wwwroot/js/word-companion-host.js | 19 +- .../wwwroot/js/word-companion-host.min.js | 2 +- 4 files changed, 378 insertions(+), 8 deletions(-) diff --git a/PlotLine.Tests/Program.cs b/PlotLine.Tests/Program.cs index 04d74c6..de663bc 100644 --- a/PlotLine.Tests/Program.cs +++ b/PlotLine.Tests/Program.cs @@ -35,6 +35,10 @@ var tests = new (string Name, Action Test)[] ("Chapter Structure boundary normaliser replays full book terminal empty failure", ChapterStructureBoundaryNormaliserReplaysFullBookTerminalEmptyFailure), ("Chapter Structure boundary normaliser keeps meaningful end overflow repair", ChapterStructureBoundaryNormaliserKeepsMeaningfulEndOverflowRepair), ("Chapter Structure boundary normaliser preserves genuine inverted ranges for validation", ChapterStructureBoundaryNormaliserPreservesGenuineInvertedRanges), + ("Structural Word mapping uses paragraph map as authoritative text", StructuralWordMappingUsesParagraphMapAsAuthoritativeText), + ("Structural Word mapping includes filtered Word paragraphs in source coverage", StructuralWordMappingIncludesFilteredWordParagraphsInSourceCoverage), + ("Structural Word mapping fails precisely when map metadata is incomplete", StructuralWordMappingFailsPreciselyWhenMapMetadataIncomplete), + ("Structural Word mapping keeps trailing empty normalisation mapped", StructuralWordMappingKeepsTrailingEmptyNormalisationMapped), ("Shared parser reports raw chapter output on unrecoverable JSON", SharedParserReportsRawOutput), ("Character filtering rejects generic groups", CharacterFilteringRejectsGenericGroups), ("Character filtering preserves titled names", CharacterFilteringPreservesTitledNames), @@ -1937,6 +1941,115 @@ static void ChapterStructureBoundaryNormaliserPreservesGenuineInvertedRanges() Assert(validation.Errors.Any(error => error.Message.Contains("Start paragraph cannot be after end paragraph", StringComparison.Ordinal)), "Validation should report the inverted range."); } +static void StructuralWordMappingUsesParagraphMapAsAuthoritativeText() +{ + var request = MappedStructureRequest( + [ + (1, 100, "Repeated words with an embedded line break are still one Word paragraph."), + (2, 101, "Repeated words with an embedded line break are still one Word paragraph."), + (3, 102, "Straight quote text stays mapped to a single Word paragraph."), + (4, 103, "Curly quote text stays mapped to a single Word paragraph."), + (5, 104, "Final paragraph maps directly back to Word.") + ], + sourceParagraphs: + [ + SourceParagraph(99, "- A Date with Disappointment", include: false, heading: true), + SourceParagraph(100, "Repeated words with an embedded line break are still one Word paragraph."), + SourceParagraph(101, "Repeated words with an embedded line break are still one Word paragraph."), + SourceParagraph(102, "Straight quote text stays mapped to a single Word paragraph."), + SourceParagraph(103, "Curly quote text stays mapped to a single Word paragraph."), + SourceParagraph(104, "Final paragraph maps directly back to Word.") + ], + chapterText: string.Join("\n\n", + [ + "Repeated words with an embedded\nline break are still one Word paragraph.", + "Repeated words with an embedded line break are still one Word paragraph.", + "Straight quote text stays mapped to a single Word paragraph.", + "Curly quote text stays mapped to a single Word paragraph.", + "Final paragraph maps directly back to Word." + ])); + var client = new FakeStoryIntelligenceClient(ChapterStructureResponse(Boundary(1, 1, 4), Boundary(2, 5, 5))); + var service = BuildMappedStructureAnalysisService(client); + + var result = service.AnalyseChapterAsync(request).GetAwaiter().GetResult(); + + Assert(result.Success, result.ErrorMessage ?? "Mapped analysis should succeed."); + Assert(client.Prompts.Single().Contains("[5] Final paragraph maps directly back to Word.", StringComparison.Ordinal), "Prompt should be numbered from paragraph map metadata."); + Assert(!client.Prompts.Single().Contains("[6]", StringComparison.Ordinal), "Embedded line breaks inside a Word paragraph must not create unmapped structural paragraphs."); + Assert(result.Scenes.Count == 2, "Mapped analysis should return both scenes."); + Assert(result.Scenes[1].WordStartPosition == 104 && result.Scenes[1].WordEndPosition == 104, "Scene 2 should map structural paragraph 5 directly to Word paragraph 104."); +} + +static void StructuralWordMappingIncludesFilteredWordParagraphsInSourceCoverage() +{ + var request = MappedStructureRequest( + [ + (1, 50, "Scene opening paragraph with enough words for mapped structural analysis."), + (2, 53, "Scene closing paragraph with enough words for mapped structural analysis.") + ], + sourceParagraphs: + [ + SourceParagraph(49, "Chapter title excluded from structure.", include: false, heading: true), + SourceParagraph(50, "Scene opening paragraph with enough words for mapped structural analysis."), + SourceParagraph(51, "", blank: true), + SourceParagraph(52, "***", include: false, separator: true), + SourceParagraph(53, "Scene closing paragraph with enough words for mapped structural analysis.") + ]); + var service = BuildMappedStructureAnalysisService(new FakeStoryIntelligenceClient(ChapterStructureResponse(Boundary(1, 1, 2)))); + + var result = service.AnalyseChapterAsync(request).GetAwaiter().GetResult(); + + Assert(result.Success, result.ErrorMessage ?? "Mapped analysis should succeed across filtered Word paragraphs."); + var scene = result.Scenes.Single(); + Assert(scene.WordStartPosition == 50 && scene.WordEndPosition == 53, "Scene endpoint mapping should span filtered Word paragraphs between structural endpoints."); + Assert(scene.SourceText.Contains("Scene opening paragraph", StringComparison.Ordinal), "Source text should include the mapped start paragraph."); + Assert(scene.SourceText.Contains("Scene closing paragraph", StringComparison.Ordinal), "Source text should include the mapped end paragraph."); +} + +static void StructuralWordMappingFailsPreciselyWhenMapMetadataIncomplete() +{ + var request = MappedStructureRequest( + [ + (1, 10, "First mapped paragraph has enough words for the structure prompt."), + (3, 12, "Third mapped paragraph exposes the missing second structural index.") + ]); + var client = new FakeStoryIntelligenceClient(ChapterStructureResponse(Boundary(1, 1, 2))); + var service = BuildMappedStructureAnalysisService(client); + + var result = service.AnalyseChapterAsync(request).GetAwaiter().GetResult(); + + Assert(!result.Success, "Missing structural paragraph map metadata should fail before invoking AI."); + Assert(client.Prompts.Count == 0, "Incomplete paragraph maps should not trigger OpenAI work."); + Assert(result.ErrorMessage?.Contains("missing structural paragraph 2", StringComparison.OrdinalIgnoreCase) == true, "Mapping failure should name the missing structural index."); + Assert(result.ErrorMessage?.Contains("nearest mapped neighbours", StringComparison.OrdinalIgnoreCase) == true, "Mapping failure should include nearest mapped neighbours."); +} + +static void StructuralWordMappingKeepsTrailingEmptyNormalisationMapped() +{ + var request = MappedStructureRequest( + Enumerable.Range(1, 366) + .Select(index => (index, 990 + index, $"Paragraph {index} contains enough mapped manuscript words for structural analysis.")) + .ToArray()); + var service = BuildMappedStructureAnalysisService(new FakeStoryIntelligenceClient(ChapterStructureResponse( + Boundary(1, 1, 11), + Boundary(2, 12, 41), + Boundary(3, 42, 66), + Boundary(4, 67, 107), + Boundary(5, 108, 154), + Boundary(6, 155, 200), + Boundary(7, 201, 276), + Boundary(8, 277, 332), + Boundary(9, 333, 346), + Boundary(10, 347, 366), + Boundary(11, 367, 366)))); + + var result = service.AnalyseChapterAsync(request).GetAwaiter().GetResult(); + + Assert(result.Success, result.ErrorMessage ?? "Trailing empty normalisation should remain compatible with Word mapping."); + Assert(result.Scenes.Count == 10, "Trailing empty scene should be discarded before Word mapping."); + Assert(result.Scenes[9].WordStartPosition == 1337 && result.Scenes[9].WordEndPosition == 1356, "Final valid scene should preserve direct Word paragraph mapping."); +} + static ChapterStructureModel ChapterWithBoundaries(params ChapterSceneBoundary[] boundaries) => new() { @@ -1957,6 +2070,74 @@ static ChapterSceneBoundary Boundary(int sceneNumber, int start, int end, string Reason = "Structural boundary identified from the submitted chapter text." }; +static ManuscriptStructureAnalysisService BuildMappedStructureAnalysisService(FakeStoryIntelligenceClient client) + => new( + new FakeStoryPromptRepository(), + new FakeStoryPromptVersionService(), + client, + new ChapterStructureValidator(), + NullLogger.Instance); + +static ManuscriptStructureAnalysisRequest MappedStructureRequest( + IReadOnlyList<(int Structural, int Word, string Text)> map, + IReadOnlyList? sourceParagraphs = null, + string? chapterText = null) + => new() + { + ProjectID = 3067, + BookID = 5075, + PreviewID = Guid.Parse("57eaf531-f483-45ae-87da-5cbb4a3ab16e"), + TemporaryChapterKey = "chapter-18", + ChapterNumber = 18, + SourceLabel = "Word manuscript: - A Date with Disappointment", + ChapterText = chapterText ?? string.Join(Environment.NewLine + Environment.NewLine, map.Select(item => item.Text)), + ParagraphMap = map + .Select(item => new ManuscriptScanParagraphMap + { + StructuralParagraphOrdinal = item.Structural, + WordParagraphIndex = item.Word, + Text = item.Text + }) + .ToList(), + SourceParagraphs = sourceParagraphs ?? map.Select(item => SourceParagraph(item.Word, item.Text)).ToList() + }; + +static ManuscriptScanSourceParagraph SourceParagraph( + int wordIndex, + string text, + bool include = true, + bool blank = false, + bool heading = false, + bool separator = false) + => new() + { + WordParagraphIndex = wordIndex, + Text = text, + IsBlank = blank, + IsChapterHeading = heading, + IsSceneSeparator = separator, + IncludeInSourceText = include + }; + +static string ChapterStructureResponse(params ChapterSceneBoundary[] boundaries) + => JsonSerializer.Serialize(new + { + output = new[] + { + new + { + content = new[] + { + new + { + type = "output_text", + text = JsonSerializer.Serialize(ChapterWithBoundaries(boundaries), ManuscriptScanJsonOptions()) + } + } + } + } + }); + static void SharedParserReportsRawOutput() { const string raw = """{"schemaVersion":"1.0","sceneBoundaries":["""; @@ -6273,6 +6454,51 @@ internal sealed class CaptureImageRequestHandler(Func Task.FromResult(respond(request)); } +internal sealed class FakeStoryPromptRepository : IStoryPromptRepository +{ + public Task LoadPromptAsync(string fileName, CancellationToken cancellationToken) + => Task.FromResult("Context: {{CHAPTER_CONTEXT_JSON}}\n\nText:\n{{CHAPTER_TEXT}}"); +} + +internal sealed class FakeStoryPromptVersionService : IStoryPromptVersionService +{ + public string GetPromptVersion(string fileName) => "Chapter-Structure-Prompt-V2"; +} + +internal sealed class FakeStoryIntelligenceClient(string rawResponseText) : IStoryIntelligenceClient +{ + public List Prompts { get; } = []; + + public Task ExecutePromptAsync( + string completedPrompt, + string promptVersion, + CancellationToken cancellationToken, + string? modelOverride = null, + int? maxOutputTokensOverride = null, + StoryIntelligenceResponseContract? responseContract = null) + { + Prompts.Add(completedPrompt); + return Task.FromResult(new StoryIntelligenceClientResult + { + RawResponseText = rawResponseText, + Model = modelOverride ?? "test-model", + Duration = TimeSpan.FromMilliseconds(1) + }); + } + + public StoryIntelligenceClientConfigurationStatus GetConfigurationStatus() + => new() + { + ApiKeyConfigured = true, + Model = "test-model", + ChapterStructureModel = "test-structure-model", + SceneIntelligenceModel = "test-scene-model", + WholeBookPlotSynthesisModel = "test-whole-book-model", + ClientConstructed = true, + ConnectionStatus = "Configured" + }; +} + internal sealed class FakeManuscriptTextStatisticsRepository(string sourceText) : IManuscriptTextStatisticsRepository { public int? SavedSceneID { get; private set; } diff --git a/PlotLine/Services/ManuscriptStructureAnalysisService.cs b/PlotLine/Services/ManuscriptStructureAnalysisService.cs index 284870d..a4515a3 100644 --- a/PlotLine/Services/ManuscriptStructureAnalysisService.cs +++ b/PlotLine/Services/ManuscriptStructureAnalysisService.cs @@ -28,7 +28,15 @@ public sealed partial class ManuscriptStructureAnalysisService( public async Task AnalyseChapterAsync(ManuscriptStructureAnalysisRequest request, CancellationToken cancellationToken = default) { var text = request.ChapterText?.Trim() ?? string.Empty; - var paragraphs = StoryIntelligenceParagraphs.Split(text); + var structuralParagraphResult = BuildStructuralParagraphs(request, text); + if (!structuralParagraphResult.Success) + { + return ManuscriptStructureAnalysisResult.Failed( + request.TemporaryChapterKey, + structuralParagraphResult.ErrorMessage ?? "The approved chapter paragraph map is not reversible."); + } + + var paragraphs = structuralParagraphResult.Paragraphs; if (paragraphs.Count == 0) { return ManuscriptStructureAnalysisResult.Failed( @@ -141,9 +149,15 @@ public sealed partial class ManuscriptStructureAnalysisService( var endMap = request.ParagraphMap.FirstOrDefault(item => item.StructuralParagraphOrdinal == end); if (startMap is null || endMap is null || startMap.WordParagraphIndex < 0 || endMap.WordParagraphIndex < 0) { + var diagnostic = BuildMappingFailureDiagnostic( + sceneNumber, + start, + end, + request.ParagraphMap, + request.SourceParagraphs); return ManuscriptStructureAnalysisResult.Failed( request.TemporaryChapterKey, - $"Scene {sceneNumber:N0} could not be mapped back to a Word paragraph.", + $"Scene {sceneNumber:N0} could not be mapped back to a Word paragraph. {diagnostic}", persistedJson); } @@ -325,6 +339,66 @@ public sealed partial class ManuscriptStructureAnalysisService( return string.Join(Environment.NewLine + Environment.NewLine, lines); } + private static StructuralParagraphBuildResult BuildStructuralParagraphs(ManuscriptStructureAnalysisRequest request, string chapterText) + { + if (request.ParagraphMap.Count == 0) + { + return StructuralParagraphBuildResult.Succeeded(StoryIntelligenceParagraphs.Split(chapterText)); + } + + var ordered = request.ParagraphMap + .OrderBy(item => item.StructuralParagraphOrdinal) + .ToList(); + var expectedOrdinal = 1; + var previousWordIndex = -1; + var paragraphs = new List(); + foreach (var item in ordered) + { + if (item.StructuralParagraphOrdinal != expectedOrdinal) + { + return StructuralParagraphBuildResult.Failed( + $"Paragraph map is missing structural paragraph {expectedOrdinal:N0}. {BuildMapNeighbourDiagnostic(expectedOrdinal, ordered, request.SourceParagraphs)}"); + } + + if (item.WordParagraphIndex < 0) + { + return StructuralParagraphBuildResult.Failed( + $"Structural paragraph {expectedOrdinal:N0} has no Word paragraph index. {BuildMapNeighbourDiagnostic(expectedOrdinal, ordered, request.SourceParagraphs)}"); + } + + if (item.WordParagraphIndex <= previousWordIndex) + { + return StructuralParagraphBuildResult.Failed( + $"Structural paragraph {expectedOrdinal:N0} maps to non-monotonic Word paragraph {item.WordParagraphIndex:N0}. {BuildMapNeighbourDiagnostic(expectedOrdinal, ordered, request.SourceParagraphs)}"); + } + + var text = NormalizeMappedParagraphText(item.Text); + if (string.IsNullOrWhiteSpace(text)) + { + return StructuralParagraphBuildResult.Failed( + $"Structural paragraph {expectedOrdinal:N0} has no mapped text. {BuildMapNeighbourDiagnostic(expectedOrdinal, ordered, request.SourceParagraphs)}"); + } + + paragraphs.Add(text); + previousWordIndex = item.WordParagraphIndex; + expectedOrdinal++; + } + + return StructuralParagraphBuildResult.Succeeded(paragraphs); + } + + private static string NormalizeMappedParagraphText(string? value) + => Regex.Replace( + (value ?? string.Empty) + .Replace("\r\n", "\n", StringComparison.Ordinal) + .Replace('\r', '\n') + .Replace('\v', '\n') + .Replace('\f', '\n') + .Replace('\u2028', '\n') + .Replace('\u2029', '\n'), + @"\s*\n+\s*", + " ").Trim(); + private static string BuildValidationMessage(ValidationResult validation) { var first = validation.Errors.FirstOrDefault()?.Message @@ -450,6 +524,54 @@ public sealed partial class ManuscriptStructureAnalysisService( return $"Structural paragraphs: 1..{structuralParagraphCount:N0}; final structural paragraph maps to Word paragraph {finalMap:N0}; returned {string.Join("; ", ranges)}."; } + private static string BuildMappingFailureDiagnostic( + int sceneNumber, + int structuralStart, + int structuralEnd, + IReadOnlyList paragraphMap, + IReadOnlyList sourceParagraphs) + { + var startMap = paragraphMap.FirstOrDefault(item => item.StructuralParagraphOrdinal == structuralStart); + var endMap = paragraphMap.FirstOrDefault(item => item.StructuralParagraphOrdinal == structuralEnd); + var missing = new List(); + if (startMap is null || startMap.WordParagraphIndex < 0) + { + missing.Add($"start structural paragraph {structuralStart:N0}"); + } + + if (endMap is null || endMap.WordParagraphIndex < 0) + { + missing.Add($"end structural paragraph {structuralEnd:N0}"); + } + + var wordRange = sourceParagraphs.Count == 0 + ? "unknown" + : $"{sourceParagraphs.Min(item => item.WordParagraphIndex):N0}..{sourceParagraphs.Max(item => item.WordParagraphIndex):N0}"; + var nearestOrdinal = missing.Count > 0 && (endMap is null || endMap.WordParagraphIndex < 0) + ? structuralEnd + : structuralStart; + return $"Scene {sceneNumber:N0} structural range {structuralStart:N0}-{structuralEnd:N0}; missing {string.Join(" and ", missing)}; {BuildMapNeighbourDiagnostic(nearestOrdinal, paragraphMap, sourceParagraphs)}; chapter Word range {wordRange}."; + } + + private static string BuildMapNeighbourDiagnostic( + int structuralOrdinal, + IReadOnlyList paragraphMap, + IReadOnlyList sourceParagraphs) + { + var previous = paragraphMap + .Where(item => item.StructuralParagraphOrdinal < structuralOrdinal && item.WordParagraphIndex >= 0) + .OrderByDescending(item => item.StructuralParagraphOrdinal) + .FirstOrDefault(); + var next = paragraphMap + .Where(item => item.StructuralParagraphOrdinal > structuralOrdinal && item.WordParagraphIndex >= 0) + .OrderBy(item => item.StructuralParagraphOrdinal) + .FirstOrDefault(); + var wordRange = sourceParagraphs.Count == 0 + ? "unknown" + : $"{sourceParagraphs.Min(item => item.WordParagraphIndex):N0}..{sourceParagraphs.Max(item => item.WordParagraphIndex):N0}"; + return $"nearest mapped neighbours: previous {Display(previous?.StructuralParagraphOrdinal)}->{Display(previous?.WordParagraphIndex)}, next {Display(next?.StructuralParagraphOrdinal)}->{Display(next?.WordParagraphIndex)}, chapter Word range {wordRange}"; + } + private static string Display(int? value) => value.HasValue ? value.Value.ToString("N0") : "?"; @@ -612,6 +734,19 @@ public sealed class ManuscriptStructureAnalysisResult => new() { TemporaryChapterKey = temporaryChapterKey, Success = false, ErrorMessage = errorMessage, ParsedJson = parsedJson }; } +internal sealed class StructuralParagraphBuildResult +{ + public bool Success { get; init; } + public IReadOnlyList Paragraphs { get; init; } = []; + public string? ErrorMessage { get; init; } + + public static StructuralParagraphBuildResult Succeeded(IReadOnlyList paragraphs) + => new() { Success = true, Paragraphs = paragraphs }; + + public static StructuralParagraphBuildResult Failed(string errorMessage) + => new() { Success = false, ErrorMessage = errorMessage }; +} + public sealed class ManuscriptStructureSceneBoundary { public string TemporarySceneKey { get; init; } = string.Empty; diff --git a/PlotLine/wwwroot/js/word-companion-host.js b/PlotLine/wwwroot/js/word-companion-host.js index fff9dc4..75266ff 100644 --- a/PlotLine/wwwroot/js/word-companion-host.js +++ b/PlotLine/wwwroot/js/word-companion-host.js @@ -2348,25 +2348,34 @@ }); }; + const normalizeScannedParagraphText = (value) => String(value || "") + .replace(/[\r\n\v\f\u2028\u2029]+/g, " ") + .replace(/\s+/g, " ") + .trim(); + const addWords = (paragraph, text, words) => { if (!chapter || words <= 0) { return; } - chapter.wordCount += words; - chapter.chapterTextParagraphs.push(text); + const structuralText = normalizeScannedParagraphText(text); + if (!structuralText) { + return; + } + + chapter.wordCount += countWords(structuralText); + chapter.chapterTextParagraphs.push(structuralText); chapter.paragraphMap = chapter.paragraphMap || []; chapter.paragraphMap.push({ structuralParagraphOrdinal: chapter.chapterTextParagraphs.length, wordParagraphIndex: Number.isInteger(paragraph?.index) ? paragraph.index : -1, - text + text: structuralText }); }; paragraphs.forEach((paragraph, index) => { paragraph.index = index; - const rawText = String(paragraph.text || ""); - const text = rawText.trim(); + const text = normalizeScannedParagraphText(paragraph.text); if (!text) { if (chapter) { recordSourceParagraph(paragraph, "", { isBlank: true, includeInSourceText: true }); diff --git a/PlotLine/wwwroot/js/word-companion-host.min.js b/PlotLine/wwwroot/js/word-companion-host.min.js index e41431d..dda25bb 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",n="plotdirector.word.activeTab",r={documentGuid:"plotdirector.word.documentGuid",bookId:"plotdirector.word.boundBookId",projectId:"plotdirector.word.boundProjectId",bindingVersion:"plotdirector.word.bindingVersion"},o=new Set(["scene","review","maintenance","diagnostics"]),a=document.querySelector(".word-companion-shell"),c=document.querySelector(".word-companion-tabs"),i=[...document.querySelectorAll("[data-tab-button]")],s=[...document.querySelectorAll("[data-tab-panel]")],d=document.querySelector("[data-linked-manuscript-card]"),l=document.querySelector("[data-linked-project-title]"),u=document.querySelector("[data-linked-book-title]"),p=document.querySelector("[data-first-run-wizard]"),h=document.querySelector("[data-first-run-project-select]"),m=document.querySelector("[data-first-run-book-select]"),w=document.querySelector("[data-first-run-new-book-title]"),g=document.querySelector("[data-first-run-create-book]"),y=document.querySelector("[data-first-run-scan]"),f=document.querySelector("[data-first-run-cancel]"),b=document.querySelector("[data-first-run-status]"),I=document.querySelector("[data-first-run-summary]"),C=document.querySelector("[data-first-run-character-section]"),S=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]"),P=document.querySelector("[data-first-run-skip-characters]"),D=document.querySelector("[data-first-run-continue]"),E=document.querySelector("[data-first-run-import-actions]"),N=document.querySelector("[data-first-run-import]"),L=document.querySelector("[data-first-run-import-cancel]"),q=document.querySelector("[data-first-run-replace-dialog]"),$=document.querySelector("[data-first-run-replace-confirm]"),A=document.querySelector("[data-first-run-replace-cancel]"),T=document.querySelector("[data-unlink-word-document-dialog]"),j=document.querySelector("[data-unlink-word-document-confirm]"),W=document.querySelector("[data-unlink-word-document-cancel]"),R=document.querySelector("[data-clean-unlink-word-document-dialog]"),U=document.querySelector("[data-clean-unlink-word-document-confirm]"),M=document.querySelector("[data-clean-unlink-word-document-cancel]"),O=document.querySelector("[data-office-status]"),B=document.querySelector("[data-connection-status]"),H=document.querySelector("[data-summary-connection]"),G=document.querySelector("[data-summary-project]"),F=document.querySelector("[data-summary-book]"),V=document.querySelector("[data-project-select]"),K=document.querySelector("[data-book-select]"),Y=document.querySelector("[data-runtime-book-selectors]"),_=document.querySelector("[data-project-message]"),J=document.querySelector("[data-book-message]"),z=document.querySelector("[data-refresh-current-scene]"),Q=document.querySelector("[data-refresh-document]"),X=document.querySelector("[data-current-chapter]"),Z=document.querySelector("[data-current-scene]"),ee=document.querySelector("[data-current-word-count]"),te=document.querySelector("[data-scene-tracking-status]"),ne=document.querySelector("[data-document-message]"),re=document.querySelector("[data-sync-note]"),oe=document.querySelector("[data-document-outline]"),ae=document.querySelector("[data-analyse-manuscript-structure]"),ce=document.querySelector("[data-apply-structure-sync]"),ie=document.querySelector("[data-structure-preview-status]"),se=document.querySelector("[data-structure-preview-results]"),de=document.querySelector("[data-refresh-plotdirector-scene]"),le=document.querySelector("[data-plotdirector-scene-status]"),ue=document.querySelector("[data-anchor-status]"),pe=document.querySelector("[data-anchor-book-id]"),he=document.querySelector("[data-anchor-chapter-id]"),me=document.querySelector("[data-anchor-scene-id]"),we=document.querySelector("[data-attach-plotdirector-ids]"),ge=document.querySelector("[data-unlink-word-document]"),ye=document.querySelector("[data-clean-unlink-word-document]"),fe=document.querySelector("[data-marker-binding-status]"),be=document.querySelector("[data-marker-chapter-count]"),Ie=document.querySelector("[data-marker-scene-count]"),Ce=document.querySelector("[data-unlink-dialog-chapter-count]"),Se=document.querySelector("[data-unlink-dialog-scene-count]"),ke=document.querySelector("[data-clean-dialog-chapter-count]"),ve=document.querySelector("[data-clean-dialog-scene-count]"),xe=document.querySelector("[data-open-writing-workspace]"),Pe=document.querySelector("[data-open-writing-context]"),De=document.querySelector("[data-open-writing-intent]"),Ee=document.querySelector("[data-plotdirector-scene-details]"),Ne=document.querySelector("[data-plotdirector-scene-title]"),Le=document.querySelector("[data-plotdirector-revision-status]"),qe=document.querySelector("[data-plotdirector-estimated-words]"),$e=document.querySelector("[data-plotdirector-actual-words]"),Ae=document.querySelector("[data-plotdirector-blocked-status]"),Te=document.querySelector("[data-plotdirector-blocked-reason-row]"),je=document.querySelector("[data-plotdirector-blocked-reason]"),We=document.querySelector("[data-runtime-last-sync]"),Re=document.querySelector("[data-sync-scene-progress]"),Ue=document.querySelector("[data-sync-word-count]"),Me=document.querySelector("[data-sync-plotdirector-count]"),Oe=document.querySelector("[data-sync-last-synced]"),Be=document.querySelector("[data-sync-status]"),He=document.querySelector("[data-writing-brief-block]"),Ge=document.querySelector("[data-writing-brief]"),Fe=document.querySelector("[data-plotdirector-link-groups]"),Ve=document.querySelector("[data-character-review-summary]"),Ke=document.querySelector("[data-asset-review-summary]"),Ye=document.querySelector("[data-location-review-summary]"),_e=document.querySelector("[data-character-chips]"),Je=document.querySelector("[data-asset-chips]"),ze=(document.querySelector("[data-location-chips]"),document.querySelector("[data-primary-location-select]")),Qe=document.querySelector("[data-save-scene-links]"),Xe=document.querySelector("[data-scene-links-status]"),Ze=document.querySelector("[data-links-editing-scene]"),et=document.querySelector("[data-chapter-create-link]"),tt=document.querySelector("[data-chapter-create-link-chapter]"),nt=document.querySelector("[data-create-plotdirector-chapter]"),rt=document.querySelector("[data-link-existing-chapter]"),ot=document.querySelector("[data-chapter-create-link-status]"),at=document.querySelector("[data-scene-create-link]"),ct=document.querySelector("[data-create-link-chapter]"),it=document.querySelector("[data-create-link-scene]"),st=document.querySelector("[data-create-plotdirector-scene]"),dt=document.querySelector("[data-link-existing-scene]"),lt=document.querySelector("[data-create-link-status]"),ut=document.querySelector("[data-link-existing-dialog]"),pt=document.querySelector("[data-link-scene-search]"),ht=document.querySelector("[data-link-scene-options]"),mt=document.querySelector("[data-link-selected-scene]"),wt=document.querySelector("[data-link-dialog-cancel]"),gt=document.querySelector("[data-link-dialog-status]"),yt=document.querySelector("[data-create-scene-dialog]"),ft=document.querySelector("[data-create-dialog-scene]"),bt=document.querySelector("[data-create-dialog-chapter]"),It=document.querySelector("[data-create-dialog-confirm]"),Ct=document.querySelector("[data-create-dialog-cancel]"),St=document.querySelector("[data-link-existing-chapter-dialog]"),kt=document.querySelector("[data-link-chapter-search]"),vt=document.querySelector("[data-link-chapter-options]"),xt=document.querySelector("[data-link-selected-chapter]"),Pt=document.querySelector("[data-link-chapter-dialog-cancel]"),Dt=document.querySelector("[data-link-chapter-dialog-status]"),Et=document.querySelector("[data-create-chapter-dialog]"),Nt=document.querySelector("[data-create-chapter-dialog-chapter]"),Lt=document.querySelector("[data-create-chapter-dialog-book]"),qt=document.querySelector("[data-create-chapter-dialog-confirm]"),$t=document.querySelector("[data-create-chapter-dialog-cancel]"),At=document.querySelector("[data-apply-structure-sync-dialog]"),Tt=document.querySelector("[data-apply-structure-sync-summary]"),jt=document.querySelector("[data-apply-structure-sync-confirm]"),Wt=document.querySelector("[data-apply-structure-sync-cancel]"),Rt=document.querySelector("[data-resolve-project-id]"),Ut=document.querySelector("[data-resolve-project-title]"),Mt=document.querySelector("[data-resolve-book-id]"),Ot=document.querySelector("[data-resolve-book-title]"),Bt=document.querySelector("[data-resolve-detected-chapter]"),Ht=document.querySelector("[data-resolve-detected-scene]"),Gt=document.querySelector("[data-resolve-request-chapter]"),Ft=document.querySelector("[data-resolve-request-scene]"),Vt=document.querySelector("[data-resolve-result]"),Kt=document.querySelector("[data-resolve-chapter-id]"),Yt=document.querySelector("[data-resolve-scene-id]"),_t=document.querySelector("[data-run-diagnostics]"),Jt=document.querySelector("[data-diagnostic-host]"),zt=document.querySelector("[data-diagnostic-platform]"),Qt=document.querySelector("[data-diagnostic-ready]"),Xt=document.querySelector("[data-diagnostic-word-api]"),Zt=document.querySelector("[data-diagnostic-last-scan]"),en=document.querySelector("[data-diagnostic-last-error]"),tn=document.querySelector("[data-diagnostic-anchor-type]"),nn=document.querySelector("[data-diagnostic-stored-scene-id]"),rn=document.querySelector("[data-diagnostic-stored-chapter-id]"),on=document.querySelector("[data-diagnostic-resolution-method]"),an=document.querySelector("[data-diagnostic-paragraphs]"),cn=document.querySelector("[data-diagnostic-heading1]"),sn=document.querySelector("[data-diagnostic-heading2]"),dn="true"===a?.dataset.authenticated,ln=Number.parseInt(a?.dataset.userId||"",10),un=String(a?.dataset.companionVersion||"20C").trim();let pn=[],hn=[],mn=!1,wn=!1,gn="Unknown",yn="Unknown",fn="",bn="",In=null,Cn=null,Sn=null,kn=null,vn=null,xn=null,Pn="",Dn="Title Match",En=!1,Nn=[],Ln=null,qn=null,$n=[],An=null,Tn=null,jn=null,Wn=null,Rn=null,Un=null,Mn=null,On=null,Bn=null,Hn=null,Gn=[],Fn=null,Vn=!1,Kn=!1,Yn=0,_n=!1,Jn=!1,zn=!1,Qn=null,Xn="Manual",Zn=!1,er=null,tr=!1,nr=0,rr=!1,or=0,ar=null;const cr=1200;let ir=!1,sr=!1,dr=null,lr=!1,ur=!1,pr=null,hr=null,mr=null,wr=!1,gr=!1,yr=null,fr="",br=[],Ir=null,Cr="",Sr=null,kr="",vr=[],xr=null,Pr="",Dr=null,Er="",Nr=[],Lr=null,qr="",$r="",Ar="",Tr="",jr=0,Wr=null,Rr=null,Ur={characters:[],assets:[],locations:[],primaryLocationId:null},Mr={chapterCount:0,sceneCount:0,totalCount:0,available:!1,message:"Not inspected"};const Or="PD-CHAPTER-",Br="PD-SCENE-",Hr=e=>{const t=String(e?.tag||"").trim().toUpperCase();return t.startsWith(Or)?"chapter":t.startsWith(Br)?"scene":""};window.PlotDirectorWordMarkers={classify:Hr};const Gr=e=>{const t=Date.now();t-jr<1e3||(jr=t,console.debug(`[Word Companion Runtime] ${e}`))},Fr=e=>{console.debug(`[Word Companion Timing] ${e}`)},Vr=e=>{O&&(O.textContent=e)},Kr=e=>"links"===e?"review":"structure"===e?"maintenance":e,Yr=(e,t=!0)=>{const r=Kr(e),a=o.has(r)&&i.some(e=>e.dataset.tabButton===r)?r:"scene";for(const e of i){const t=e.dataset.tabButton===a;e.classList.toggle("is-active",t),e.setAttribute("aria-selected",t?"true":"false")}for(const e of s){const t=e.dataset.tabPanel===a;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,a)},_r=()=>{const e=Kr((e=>{try{return window.localStorage.getItem(e)||""}catch{return""}})(n));Yr(o.has(e)?e:"scene",!1)},Jr=e=>{B&&(B.textContent=e),H&&(H.textContent=e)},zr=e=>{_&&(_.textContent=e)},Qr=e=>{J&&(J.textContent=e)},Xr=e=>{ne&&(ne.textContent=e)},Zr=e=>{le&&(le.textContent=e)},eo=e=>{const t=t=>Object.prototype.hasOwnProperty.call(e,t);t("anchorType")&&Yo(tn,Co(e.anchorType)),t("storedSceneId")&&Yo(nn,Co(e.storedSceneId)),t("storedChapterId")&&Yo(rn,Co(e.storedChapterId)),t("resolutionMethod")&&Yo(on,Co(e.resolutionMethod))},to=()=>{const e=oa(),t=Number.isInteger(vn)&&vn>0&&kn===vn,n=!Number.isInteger(xn)||xn<=0||Sn===xn,r=t&&n;Yo(ue,r?"Attached to PlotDirector":"Not attached"),Yo(pe,e?.bookId?String(e.bookId):"-"),Yo(he,Number.isInteger(xn)&&xn>0?String(xn):"-"),Yo(me,Number.isInteger(vn)&&vn>0?String(vn):"-"),we&&(oo(we,r&&!En),we.disabled=!vn||r&&!En,we.textContent=kn&&!r?"Reattach PlotDirector IDs":"Attach PlotDirector IDs"),eo({anchorType:Dn||"Title Match",storedSceneId:kn,storedChapterId:Sn,resolutionMethod:Pn})},no=(e,t,n,r=null,o=null,a=null)=>{const c=e||"",i=t||"",s=Number.isInteger(n)?n:null,d=Number.isInteger(a)&&a>0?a:null,l=Number.isInteger(r)&&r>0?r:null,u=Number.isInteger(o)&&o>0?o:null,p=fn===c&&bn===i&&In===s&&Cn===d&&Sn===l&&kn===u;fn=e||"",bn=t||"",In=Number.isInteger(n)?n:null,Cn=Number.isInteger(a)&&a>0?a:null,Sn=Number.isInteger(r)&&r>0?r:null,kn=Number.isInteger(o)&&o>0?o:null,p||(X&&(X.textContent=e||"Not detected"),Z&&(Z.textContent=t||"Not detected"),ee&&(ee.textContent=Number.isInteger(n)?String(n):"-"),Yo(Ue,Number.isInteger(n)?String(n):"-"),to())},ro=()=>{dr&&(window.clearTimeout(dr),dr=null)},oo=(e,t)=>{e&&(e.hidden=t)},ao=()=>{oo(ge,!Wn)},co=(e=Mr)=>{const t=ka();Yo(fe,t?"Linked":"Not linked"),Yo(be,e.available?String(e.chapterCount):"-"),Yo(Ie,e.available?String(e.sceneCount):"-"),Yo(Ce,e.available?String(e.chapterCount):"-"),Yo(Se,e.available?String(e.sceneCount):"-"),Yo(ke,e.available?String(e.chapterCount):"-"),Yo(ve,e.available?String(e.sceneCount):"-"),ye&&(ye.disabled=!wn||!mn)},io=async()=>{if(!mn||!wn||!window.Word||"function"!=typeof window.Word.run)return Mr={chapterCount:0,sceneCount:0,totalCount:0,available:!1,message:"Word document access is unavailable."},co(),Mr;try{return Mr=await window.Word.run(async e=>{const t=e.document.contentControls;t.load("items/tag,title"),await e.sync();let n=0,r=0;for(const e of t.items||[]){const t=Hr(e);"chapter"===t?n+=1:"scene"===t&&(r+=1)}return{chapterCount:n,sceneCount:r,totalCount:n+r,available:!0,message:"Marker inspection complete."}}),co(Mr),Mr}catch(e){throw console.error("Unable to inspect PlotDirector markers.",e),Mr={chapterCount:0,sceneCount:0,totalCount:0,available:!1,message:`Unable to inspect markers: ${Jo(e)}`},co(),e}},so=e=>{Yo(Be,e)},lo=e=>{Yo(ie,e)},uo=(e="Select a project and book to analyse manuscript structure.")=>{if(jn=null,se){se.innerHTML="";const e=document.createElement("p");e.textContent="No preview generated.",se.append(e)}lo(e),ho()},po=(e=jn)=>((e=jn)=>Qa.flatMap(t=>Array.isArray(e?.[t.key])?e[t.key]:[]))(e).filter(e=>"couldLink"===e.category||"wouldCreateChapters"===e.category||"wouldCreateScenes"===e.category),ho=()=>{ce&&(ce.disabled=zn||0===po().length)},mo=()=>{ae&&(ae.disabled=zn||!ra()||!oa()),ho()},wo=()=>{Ze&&(Ze.textContent=vn?`Editing links for: ${Ar||bn||"Current scene"}`:"Link a PlotDirector scene first.")},go=()=>{const e=Zn||!vn,t=e||!xn||lr;Re&&(Re.disabled=t),Qe&&(Qe.disabled=e),ze&&(ze.disabled=e);for(const t of[_e,Je])for(const n of t?[...t.querySelectorAll("input[type='checkbox']")]:[])n.disabled=e},yo=e=>{"Live"!==e&&"Manual"!==e||(Xn=e),Yo(te,e||Xn||"Manual")},fo=(e,t="")=>{Zn=!!e,Zn&&(ro(),Vc()),Yo(te,Zn?"Stale":Xn),go(),t&&(Xr(t),Po(t))},bo=(e,t=null,n="")=>{vn=Number.isInteger(e)&&e>0?e:null,xn=Number.isInteger(t)&&t>0?t:null,Pn=n||"",vn!==pr&&(hr=null),vn||(ro(),Vc()),go(),so(Zn?"Refresh Current Scene before syncing.":vn?"Ready to sync.":"No resolved PlotDirector scene."),Po(Zn?"Refresh Current Scene before saving.":vn?"Ready to save.":"Link a PlotDirector scene first."),wo(),to()},Io=e=>{z&&(z.disabled=e,z.textContent=e?"Refreshing...":"Refresh Current Scene")},Co=e=>null==e||""===e?"-":String(e),So=e=>{if(!e)return"-";const t=e instanceof Date?e:new Date(e);if(Number.isNaN(t.getTime()))return"-";const n=new Date;return`Last synced: ${t.toDateString()===n.toDateString()?"Today":t.toLocaleDateString()} ${t.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}`},ko=e=>{Rn=e||null;const t=Rn?.lastSyncUtc||Rn?.manuscriptDocument?.lastSyncUtc;Yo(We,So(t)),Yo(Oe,So(t)),na()},vo=()=>{Un=null,Mn=null,On=null,or+=1,ar=null,Kc(),Yc(),_c(),ko(null)},xo=()=>{Mn=null,On=null},Po=e=>{Yo(Xe,e)},Do=e=>{Yo(lt,e)},Eo=e=>{Yo(ot,e)},No=()=>!!oa()&&!!fn&&!xn,Lo=()=>!!oa()&&!!bn&&Number.isInteger(xn)&&xn>0,qo=()=>{oo(et,!0),Eo(""),nt&&(nt.disabled=!0,nt.textContent="Create Chapter in PlotDirector"),rt&&(rt.disabled=!0,rt.textContent="Link to Existing Chapter")},$o=(e="")=>{Yo(tt,Co(fn)),oo(et,!1),Eo(e);const t=No();nt&&(nt.disabled=!t,nt.textContent="Create Chapter in PlotDirector"),rt&&(rt.disabled=!t,rt.textContent="Link to Existing Chapter")},Ao=()=>{oo(at,!0),Do(""),st&&(st.disabled=!0,st.textContent="Create Scene in PlotDirector"),dt&&(dt.disabled=!0,dt.textContent="Link to Existing Scene")},To=(e="")=>{Yo(ct,Co(fn)),Yo(it,Co(bn)),oo(at,!1),Do(e);const t=Lo();st&&(st.disabled=!t,st.textContent="Create Scene in PlotDirector"),dt&&(dt.disabled=!t,dt.textContent="Link to Existing Scene")},jo=e=>{Zr(e),oo(Ee,!0),oo(He,!0),oo(Fe,!1),qo(),Ao(),Pn="",Ar="",Tr="",Dn=kn?"SceneID Anchor":Sn?"ChapterID Anchor":"Title Match",En=!1,Ur={characters:[],assets:[],locations:[],primaryLocationId:null},Ro(_e,[],"character"),Ro(Je,[],"asset"),Uo([],null,!1),Ea(),bo(null),Yo(Me,"-"),Yo(Ne,"-"),Yo(Le,"-"),Yo(qe,"-"),Yo($e,"-"),Yo(Ae,"-"),Yo(je,"-"),oo(Te,!0),to(),wo()},Wo=(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,Ro=(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(Wo(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)}},Uo=(e,t,n=!1)=>{if(!ze)return;ze.innerHTML="";const r=document.createElement("option");r.value="",r.textContent="None",ze.append(r);const o=Number.parseInt(t||"",10);for(const t of Array.isArray(e)?e:[]){const e=Number.parseInt(Wo(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,ze.append(n)}ze.disabled=!n},Mo=e=>String(e||"").trim().replace(/\s+/g," "),Oo=(e,t)=>{const n=Mo(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 Mo(n.replace(r,""))||n},Bo=e=>{const t=t=>Object.prototype.hasOwnProperty.call(e,t);t("projectId")&&Yo(Rt,Co(e.projectId)),t("projectTitle")&&Yo(Ut,Co(e.projectTitle)),t("bookId")&&Yo(Mt,Co(e.bookId)),t("bookTitle")&&Yo(Ot,Co(e.bookTitle)),t("detectedChapter")&&Yo(Bt,Co(e.detectedChapter)),t("detectedScene")&&Yo(Ht,Co(e.detectedScene)),t("requestChapter")&&Yo(Gt,Co(e.requestChapter)),t("requestScene")&&Yo(Ft,Co(e.requestScene)),t("result")&&Yo(Vt,Co(e.result)),t("chapterId")&&Yo(Kt,Co(e.chapterId)),t("sceneId")&&Yo(Yt,Co(e.sceneId))},Ho=async e=>{if(On===e&&Array.isArray(Mn?.chapters))return Mn.chapters;const t=await kc(`/api/word-companion/books/${e}/structure`);return On=e,Mn=t||null,Array.isArray(t?.chapters)?t.chapters:[]},Go=async e=>{const t=await kc(`/api/word-companion/books/${e}/chapters`);return Array.isArray(t?.chapters)?t.chapters:[]},Fo=e=>{if(Number.isInteger(xn)&&xn>0){const t=e.find(e=>e.chapterId===xn);if(t)return t}const t=Oo(fn,"chapter").toLocaleLowerCase();return t&&e.find(e=>Oo(e.title,"chapter").toLocaleLowerCase()===t)||null},Vo=async()=>{const e=oa();return e?Fo(await Ho(e.bookId)):null},Ko=async(e,t,n,r,o)=>{const a=await kc(`/api/word-companion/scenes/${t}/companion`);try{a.revisionStatus=await(async(e,t)=>{const n=await kc(`/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;Dn=o||"Title Match",En=!1,fo(!1),Zr("Linked to PlotDirector"),Xr(""),qo(),Ao(),bo(t,n,r),c=a,Ar=c?.sceneTitle||bn||"",Tr=c?.chapterTitle||fn||"",Yo(Ne,Co(c?.sceneTitle)),Yo(Le,Co(c?.revisionStatus||c?.revisionStatusName||"Not provided")),Yo(qe,Co(c?.estimatedWords)),Yo($e,Co(c?.actualWords)),Yo(Me,Co(c?.actualWords)),Yo(Ae,c?.blocked?"Blocked":"Not blocked"),c?.blockedReason?(Yo(je,c.blockedReason),oo(Te,!1)):(Yo(je,"-"),oo(Te,!0)),Ge&&(Ge.textContent=c?.writingBrief||"No writing brief has been added for this scene."),Ur={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},Ro(_e,Ur.characters,"character",!!vn&&!Zn),Ro(Je,Ur.assets,"asset",!!vn&&!Zn),Uo(Ur.locations,Ur.primaryLocationId,!!vn&&!Zn),Ea(),wo(),Po(Zn?"Refresh Current Scene before saving.":vn?"Ready to save.":"No resolved PlotDirector scene."),oo(Ee,!1),oo(He,!1),oo(Fe,!1),Pc(t,n),Fc(),ti()},Yo=(e,t)=>{if(e){const n=null==t?"":String(t);e.textContent!==n&&(e.textContent=n)}},_o=e=>{const t=t=>Object.prototype.hasOwnProperty.call(e,t);t("host")&&Yo(Jt,e.host),t("platform")&&Yo(zt,e.platform),t("ready")&&Yo(Qt,e.ready),t("wordApi")&&Yo(Xt,e.wordApi),t("lastScan")&&Yo(Zt,e.lastScan),t("lastError")&&Yo(en,e.lastError),t("paragraphs")&&Yo(an,e.paragraphs),t("heading1")&&Yo(cn,e.heading1),t("heading2")&&Yo(sn,e.heading2)},Jo=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)},zo=async()=>{if(!window.Office||"function"!=typeof window.Office.onReady)return mn=!1,wn=!1,gn="Unavailable",yn="Unavailable",_o({host:gn,platform:yn,ready:"No",wordApi:"No"}),null;const e=await window.Office.onReady();return mn=!0,gn=e?.host||"Unknown",yn=e?.platform||"Unknown",wn=!!window.Word&&!!window.Office.HostType&&e?.host===window.Office.HostType.Word,_o({host:gn,platform:yn,ready:"Yes",wordApi:wn?"Yes":"No"}),e},Qo=e=>{try{const t=window.localStorage.getItem(e),n=Number.parseInt(t||"",10);return Number.isInteger(n)&&n>0?n:null}catch{return null}},Xo=(e,t)=>{try{t?window.localStorage.setItem(e,String(t)):window.localStorage.removeItem(e)}catch{}},Zo=(e,t)=>{if(!e)return;e.innerHTML="";const n=document.createElement("option");n.value="",n.textContent=t,e.append(n),e.disabled=!0},ea=(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},ta=e=>{const t=String(e?.displayTitle||"").trim();if(t)return t;const n=String(e?.title||"").trim(),r=String(e?.subtitle||"").trim();return r?`${n}: ${r}`:n},na=()=>{const e=!!Wn;oo(d,!e),oo(Y,e),e&&(Yo(l,Rn?.projectTitle||ra()?.title||"Project"),Yo(u,Rn?.bookTitle||ta(oa())||"Book")),co()},ra=()=>{const e=Number.parseInt(V?.value||"",10);return pn.find(t=>t.projectId===e)||null},oa=()=>{const e=Number.parseInt(K?.value||"",10);return hn.find(t=>t.bookId===e)||null},aa=()=>{const e=Number.parseInt(h?.value||"",10);return pn.find(t=>t.projectId===e)||null},ca=()=>{const e=Number.parseInt(m?.value||"",10);return hn.find(t=>t.bookId===e)||null},ia=()=>{const t=Wn?.projectId||aa()?.projectId||ra()?.projectId||Qo(e);return Number.isInteger(t)&&t>0?t:null},sa=()=>{const e=Wn?.bookId||ca()?.bookId||oa()?.bookId||Qo(t);return Number.isInteger(e)&&e>0?e:null},da=()=>({projectId:ia(),bookId:sa()}),la=e=>{const t="context"===e?"Context":"intent"===e?"Intent":"Workspace",n=window.open((e=>{const t=da(),n=new URL("workspace"===e?"/Writer":`/Writing/${e}`,window.location.origin);return t.projectId&&n.searchParams.set("projectId",t.projectId),t.bookId&&"workspace"!==e&&n.searchParams.set("bookId",t.bookId),Sn&&"workspace"!==e&&n.searchParams.set("chapterId",Sn),kn&&"workspace"!==e&&n.searchParams.set("sceneId",kn),`${n.pathname}${n.search}`})(e),(e=>{const t=da();return`PlotDirector${e}_${t.bookId?`Book_${t.bookId}`:t.projectId?`Project_${t.projectId}`:"General"}`})(t));n?n.focus():Xr("Your browser blocked the writing workspace window. Use the browser pop-up prompt to allow PlotDirector windows.")},ua=()=>{const e=String(window.Office?.context?.document?.url||"").trim();if(!e)return"";const t=e.split(/[\\/]/).filter(Boolean).pop()||"";try{return decodeURIComponent(t)}catch{return t}},pa=()=>({userID:Number.isInteger(ln)&&ln>0?ln:null,companionVersion:un,machineName:"",documentOpen:!!wn,currentDocumentName:ua(),linkedProjectID:ia(),linkedBookID:sa()}),ha=()=>{(async()=>{Wr&&Wr.state===signalR.HubConnectionState.Connected&&await Wr.invoke("CompanionHeartbeat",pa())})().catch(e=>{console.debug("Word Companion heartbeat unavailable.",e)})},ma=async()=>{dn&&window.signalR&&!Wr&&(Wr=(new signalR.HubConnectionBuilder).withUrl("/hubs/word-companion-follow").withAutomaticReconnect().build(),Wr.onreconnected(ha),Wr.on("ScanCurrentDocument",e=>{Va(e)}),Wr.on("UpdateOnboardingBuildMarkers",e=>{Ka(e)}),Wr.onclose(()=>{Rr&&(window.clearInterval(Rr),Rr=null)}),await Wr.start(),await Wr.invoke("RegisterCompanion",pa()),Rr=window.setInterval(ha,25e3))};window.addEventListener("beforeunload",()=>{Rr&&(window.clearInterval(Rr),Rr=null),Wr&&Wr.stop().catch(()=>{})});const wa=e=>Yo(b,e),ga=()=>{const e=aa(),t=ca(),n=Kn&&Date.now()-Yn>=750;y&&(y.disabled=!e||!t||_n),g&&(g.disabled=!e||!String(w?.value||"").trim()||_n),N&&(N.disabled=!Bn?.canImport||!Hn||_n),x&&(x.disabled=!n||Jn||0===Ia().length)},ya=e=>{oo(p,!e),oo(c,e),ao(),na();for(const t of s)oo(t,!!e||"scene"!==t.dataset.tabPanel&&!t.classList.contains("is-active"));e||_r()},fa=()=>{if(!h)return;if(0===pn.length)return void Zo(h,"No projects available.");ea(h,"Choose a project",pn,"projectId","title");const e=Number.parseInt(V?.value||"",10);Number.isInteger(e)&&e>0&&(h.value=String(e))},ba=(e="Select a Project and Book to begin.")=>{Bn=null,Hn=null,Gn=[],Vn=!1,Kn=!1,Yn=0,oo(I,!0),oo(E,!0),oo(C,!0),oo(v,!0),I&&(I.innerHTML=""),k&&(k.innerHTML=""),Yo(S,""),wa(e),ga()},Ia=()=>k?[...k.querySelectorAll("input[type='checkbox']:checked")].map(e=>String(e.value||"").trim()).filter(Boolean):[],Ca=e=>{if(Gn=Array.isArray(e)?e:[],C&&k){if(k.innerHTML="",oo(C,!1),oo(v,!Vn||0===Gn.length),oo(x,!1),oo(P,!1),oo(D,!0),0===Gn.length)return Yo(S,"No likely major characters found."),void ga();Yo(S,`${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",ga);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)}ga()}},Sa=()=>{const e=window.Office?.context?.document?.settings;if(!e)return null;const t=String(e.get(r.documentGuid)||"").trim(),n=Number.parseInt(e.get(r.bookId)||"",10),o=Number.parseInt(e.get(r.projectId)||"",10),a=Number.parseInt(e.get(r.bindingVersion)||"",10);return!t||!Number.isInteger(n)||n<=0||!Number.isInteger(o)||o<=0?null:{documentGuid:t,bookId:n,projectId:o,bindingVersion:Number.isInteger(a)&&a>0?a:1}},ka=()=>{const e=Wn||Sa();if(e)return e;const t=Rn?.manuscriptDocument?.documentGuid||"",n=Number.parseInt(Rn?.bookId||"",10),r=Number.parseInt(Rn?.projectId||"",10);return t&&Number.isInteger(n)&&n>0&&Number.isInteger(r)&&r>0?{documentGuid:t,bookId:n,projectId:r,bindingVersion:Number.parseInt(Rn?.manuscriptDocument?.bindingVersion||"",10)||1}:null},va=()=>new Promise((e,t)=>{const n=window.Office?.context?.document?.settings;if(n){for(const e of Object.values(r))"function"==typeof n.remove?n.remove(e):n.set(e,"");n.saveAsync(n=>{n.status===window.Office.AsyncResultStatus.Succeeded?e():t(n.error||new Error("Unable to remove Word document metadata."))})}else t(new Error("Word document settings are unavailable."))}),xa=()=>Wn?.documentGuid?Wn.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)),Pa=()=>Wn?.documentGuid||Sa()?.documentGuid||"",Da=()=>{const e=ra(),t=oa();G&&(G.textContent=e?.title||"(Not connected)"),F&&(F.textContent=t?ta(t):"(Not connected)"),re&&(re.textContent=t?"":"Select a PlotDirector book before refreshing."),mo(),na()},Ea=()=>{const e=Array.isArray(Ur.characters)?Ur.characters.length:0,t=Array.isArray(Ur.assets)?Ur.assets.length:0,n=Array.isArray(Ur.locations)?Ur.locations.length:0;Yo(Ve,`Characters (${e})`),Yo(Ke,`Assets (${t})`),Yo(Ye,`Locations (${n})`)},Na=e=>String(e?.styleBuiltIn||e?.style||"").replace(/\s+/g,"").toLowerCase(),La=(e,t)=>{const n=Na(e);return n===`heading${t}`||n.endsWith(`.heading${t}`)||n.includes(`heading${t}`)},qa=e=>String(e||"").trim().split(/\s+/).filter(Boolean).length,$a=(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},Aa=e=>{try{return Array.isArray(e?.contentControls?.items)?e.contentControls.items:[]}catch(e){return console.warn("Word paragraph content controls were not available.",e),[]}},Ta=(e,t)=>{const n=Aa(e);for(const e of n){const n=$a(e.tag,t);if(n)return n}return null},ja=(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(La(e,1))return r+=1,a={index:n.length+1,paragraphIndex:t,title:i,anchorId:Ta(e,"PD-CHAPTER"),scenes:[]},n.push(a),void(c=null);if(La(e,2)){if(o+=1,!a)return;return c={index:a.scenes.length+1,paragraphIndex:t,title:i,anchorId:Ta(e,"PD-SCENE"),wordCount:0},void a.scenes.push(c)}c&&(c.wordCount+=qa(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()&&Na(t)===Na(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}},Wa=new Set(["***","###"]),Ra=(e,t)=>{const n=String(e?.text||"").trim();return{index:t,text:n,styleBuiltIn:e?.styleBuiltIn||"",style:e?.style||"",wordCount:qa(n),chapterAnchorId:null,sceneAnchorId:null}},Ua=(e,t)=>{e&&(e.endParagraphIndex=t)},Ma=(e,t)=>{e&&(e.endParagraphIndex=t,Ua(e.scenes.at(-1),t))},Oa=(e,t,n)=>e?.[t]??e?.[n]??null,Ba=(e,t)=>{const n=[],r=[],o=[];let a=null,c=null,i=0,s=0,d=!1;const l=()=>{c=null},u=(e,t,r=!1)=>(l(),a={temporaryChapterKey:`chapter-${n.length+1}`,chapterNumber:n.length+1,title:t,wordCount:0,chapterTextParagraphs:[],chapterText:"",startPosition:e?.index??null,existingChapterID:r?null:Ta(e,"PD-CHAPTER")},n.push(a),p(e,null),a),p=(e,t=null)=>a?(l(),c={temporarySceneKey:`scene-${r.length+1}`,temporaryChapterKey:a.temporaryChapterKey,sceneNumberWithinChapter:r.filter(e=>e.temporaryChapterKey===a.temporaryChapterKey).length+1,title:t,wordCount:0,openingTextPreview:"",startPosition:e?.index??null,existingSceneID:e?Ta(e,"PD-SCENE"):null},r.push(c),c):null,h=(e,t)=>{!a||!c||t<=0||(a.wordCount+=t,a.chapterTextParagraphs.push(e),c.wordCount+=t,c.openingTextPreview||!e||Wa.has(e)||(c.openingTextPreview=e.length>180?`${e.slice(0,177)}...`:e))};if(e.forEach((e,t)=>{e.index=t;const n=String(e.text||"").trim();if(!n)return;const r=qa(n);if(La(e,1)){if(!d&&(e=>{const t=Oo(e||"","").toLocaleLowerCase();return["title page","copyright","dedication","contents","table of contents","acknowledgements","acknowledgments","about the author"].includes(t)})(n))return;return d=!0,o.push(n),s+=1,u(e,n),i+=r,a.wordCount+=r,void a.chapterTextParagraphs.push(n)}if(!a){if(!d)return;u(e,"Opening pages",!0)}if(o.push(n),La(e,2))return p(e,n),i+=r,void h(n,r);Wa.has(n)?p(e,null):(i+=r,h(n,r))}),0===i)throw new Error("The document appears to be empty. Add manuscript text, then try again.");if(0===s)throw new Error("No chapters were detected. Make sure your chapter headings use Heading 1, or add clear chapter headings.");n.forEach(e=>{e.chapterText=Array.isArray(e.chapterTextParagraphs)?e.chapterTextParagraphs.join("\n\n"):"",delete e.chapterTextParagraphs});const m=o.join("\n");return{previewID:"00000000-0000-0000-0000-000000000000",userID:Ha(t,"userID","UserID","userId"),onboardingID:Ha(t,"onboardingID","OnboardingID","onboardingId"),projectID:Ha(t,"projectID","ProjectID","projectId"),bookID:Ha(t,"bookID","BookID","bookId"),source:"WordCompanion",documentTitle:ua()||"Word manuscript",companionDocumentIdentifier:Pa(),totalWordCount:i,chapterCount:n.length,sceneCount:r.length,characterCandidateCount:0,createdUtc:(new Date).toISOString(),chapters:n,scenes:r,characterCandidates:[],documentTextForDiscovery:m}},Ha=(e,...t)=>{for(const n of t)if(null!=e?.[n])return e[n];return null},Ga=async(e,t,n,r={})=>{Wr&&Wr.state===signalR.HubConnectionState.Connected&&await Wr.invoke("ReportOnboardingScanProgress",{userID:Ha(e,"userID","UserID","userId"),onboardingID:Ha(e,"onboardingID","OnboardingID","onboardingId"),message:t,percentComplete:n,chapterCount:r.chapterCount||0,sceneCount:r.sceneCount||0,characterCandidateCount:r.characterCandidateCount||0,totalWordCount:r.totalWordCount||0})},Fa=async(e,t)=>{Wr&&Wr.state===signalR.HubConnectionState.Connected&&await Wr.invoke("FailOnboardingScan",{userID:Ha(e,"userID","UserID","userId"),onboardingID:Ha(e,"onboardingID","OnboardingID","onboardingId"),message:t})},Va=async e=>{var t;if(wn&&window.Word)try{await Ga(e,"Preparing document scan",5);const n=await window.Word.run(async t=>{const n=t.document.body.paragraphs;n.load("items/text,items/style,items/styleBuiltIn"),await t.sync(),await Ga(e,"Detecting chapters",20);for(const e of n.items)(La(e,1)||La(e,2))&&e.contentControls.load("items/tag,title");return await t.sync(),n.items}),r=Ba(n,e);await Ga(e,"Detecting scene breaks",50,r),await Ga(e,`Scene ${r.sceneCount} of ${r.sceneCount} scanned`,70,r),await Ga(e,"Finding character candidates",85,r);const o=r.documentTextForDiscovery||"";delete r.documentTextForDiscovery;try{const e=await vc("/api/word-companion/manuscript/discover-characters",{projectId:r.projectID,documentText:o,includeExcluded:!0});r.characterCandidates=(t=e?.candidates,(Array.isArray(t)?t:[]).map((e,t)=>({temporaryCharacterKey:`character-${t+1}`,name:Oa(e,"text","Text")||Oa(e,"name","Name")||"",mentionCount:Number.parseInt(Oa(e,"mentionCount","MentionCount")||"0",10)||0,qualityScore:Number.parseInt(Oa(e,"qualityScore","QualityScore")||"0",10)||0,category:Oa(e,"category","Category")||"PossibleCharacter",reason:Oa(e,"reason","Reason")||"",isExistingCharacterMatch:!!Oa(e,"isExistingCharacterMatch","IsExistingCharacterMatch"),suggestedImportance:null})).filter(e=>e.name)),r.characterCandidateCount=r.characterCandidates.filter(e=>"excluded"!==String(e.category||"").toLowerCase()).length}catch(e){console.warn("Unable to refine onboarding character candidates.",e),r.characterCandidates=[],r.characterCandidateCount=0}await Ga(e,"Preparing preview",95,r),Fn=r,await Wr.invoke("CompleteOnboardingScan",r)}catch(t){console.error("Unable to complete onboarding scan.",t),await Fa(e,Ya(t))}else await Fa(e,"Open your manuscript in Microsoft Word, then try the scan again.")},Ka=async e=>{if(!Fn||!wn||!window.Word||"function"!=typeof window.Word.run)throw new Error("Word document access is unavailable.");const t=new Map((e?.chapterMappings||e?.ChapterMappings||[]).map(e=>[e.temporaryChapterKey||e.TemporaryChapterKey,e.chapterID||e.ChapterID])),n=new Map((e?.sceneMappings||e?.SceneMappings||[]).map(e=>[e.temporarySceneKey||e.TemporarySceneKey,e.sceneID||e.SceneID]));await window.Word.run(async e=>{const r=e.document.body.paragraphs;r.load("items/text,items/style,items/styleBuiltIn"),await e.sync();for(const e of Fn.chapters||[]){const n=t.get(e.temporaryChapterKey),o=Number.parseInt(e.startPosition,10);n&&Number.isInteger(o)&&r.items[o]&&qc(r.items[o],"PlotDirector Chapter",`PD-CHAPTER-${n}`,"PD-CHAPTER")}for(const e of Fn.scenes||[]){const t=n.get(e.temporarySceneKey),o=Number.parseInt(e.startPosition,10);t&&Number.isInteger(o)&&r.items[o]&&qc(r.items[o],"PlotDirector Scene",`PD-SCENE-${t}`,"PD-SCENE")}await e.sync()}),await io().catch(()=>null)},Ya=e=>{const t=Jo(e);return/No chapters were detected/i.test(t)?"No chapters were detected. Make sure your chapter headings use Heading 1, or add clear chapter headings.":/empty/i.test(t)?"The document appears to be empty. Add manuscript text, then try again.":/network|disconnect|connection/i.test(t)?"The Word Companion disconnected before the scan finished. Reopen Word and try again.":`The scan could not finish: ${t}`},_a=(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()&&Na(e)===Na(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(!Un)return!1;const t=((e,t)=>!e||!Number.isInteger(t)||t<0?null:e.chapters.filter(e=>e.startParagraphIndex<=t).at(-1)||null)(Un,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?.startParagraphIndex!==Un.currentChapter?.startParagraphIndex||n?.startParagraphIndex!==Un.currentScene?.startParagraphIndex||t?.anchorId!==Un.currentChapter?.anchorId||n?.anchorId!==Un.currentScene?.anchorId;return Un.currentParagraphIndex=e,Un.currentChapter=t,Un.currentScene=n,!!r&&(no(t?.title,n?.title,n?.wordCount,t?.anchorId,n?.anchorId,t?.index),r)},za=e=>{if(!oe)return;if(oe.innerHTML="",0===e.chapters.length){const e=document.createElement("p");return e.textContent="No chapters detected. Use Heading 1 for chapter titles.",void oe.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.",oe.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)}oe.append(e)}},Qa=[{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"}],Xa={alreadyLinked:"Already Linked",couldLink:"Could Link",wouldCreateChapter:"Would Create Chapter",wouldCreateScene:"Would Create Scene",manualReview:"Manual Review Required"},Za={alreadyLinked:"✓",couldLink:"~",wouldCreateChapter:"+",wouldCreateScene:"+",manualReview:"?"},ec=(e,t)=>Oo(e,t).toLocaleLowerCase(),tc=({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:""}),nc=(e,t)=>{Array.isArray(e[t.category])&&e[t.category].push(t)},rc=e=>Array.isArray(e?.scenes)?e.scenes:[],oc=(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=tc({category:"alreadyLinked",action:"alreadyLinked",type:"Chapter",wordTitle:e.title,match:`Chapter ${o.chapterId}: ${o.title}`,anchorStatus:r,pdChapter:o,wordChapter:e});return nc(n,t),t}const a=tc({category:"manualReview",action:"manualReview",type:"Chapter",wordTitle:e.title,anchorStatus:`${r} not found`,matches:[],pdChapter:null,wordChapter:e});return nc(n,a),a}const o=t.filter(t=>ec(t.title,"chapter")===ec(e.title,"chapter"));if(1===o.length){const t=tc({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 nc(n,t),t}if(o.length>1){const t=tc({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 nc(n,t),t}const a=tc({category:"wouldCreateChapters",action:"wouldCreateChapter",type:"Chapter",wordTitle:e.title,anchorStatus:r,pdChapter:null,wordChapter:e});return nc(n,a),a},ac=(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=rc(n).find(e=>e.sceneId===t);if(e)return{chapter:n,scene:e}}return null})(n,e.anchorId);return a?void nc(r,tc({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 nc(r,tc({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 nc(r,tc({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 nc(r,tc({category:"wouldCreateScenes",action:"wouldCreateScene",type:"Scene",wordTitle:e.title,anchorStatus:o,wordChapter:t?.wordChapter,wordScene:e,parentItem:t}));const a=rc(t.pdChapter).filter(t=>ec(t.title,"scene")===ec(e.title,"scene"));1!==a.length?a.length>1?nc(r,tc({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})):nc(r,tc({category:"wouldCreateScenes",action:"wouldCreateScene",type:"Scene",wordTitle:e.title,anchorStatus:o,pdChapter:t.pdChapter,wordChapter:t.wordChapter,wordScene:e,parentItem:t})):nc(r,tc({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}))},cc=e=>{const t=document.createElement("article");t.className="word-companion-preview-item";const n=document.createElement("strong");n.textContent=`${Za[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: ${Xa[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},ic=e=>{if(se){se.innerHTML="";for(const t of Qa){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(cc(e));se.append(n)}ho()}},sc=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();try{for(const e of t.items)(La(e,1)||La(e,2))&&e.contentControls.load("items/tag,title");await e.sync()}catch(e){console.warn("Unable to load Word heading content controls. Continuing without PlotDirector anchors.",e)}const r=ja(t.items,n.items);return r.bodyParagraphs=t.items,r},dc=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();const o=((e,t)=>{const n=e.map(Ra),r=[];let o=0,a=0,c=null,i=null,s=0;const d=(e,t=null,n=null)=>c?(Ua(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&&(La(e,1)?(Ma(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&&Wa.has(e.text)?(a+=1,d(e)):(c.wordCount+=e.wordCount,i&&(i.wordCount+=e.wordCount),s+=e.wordCount)));return Ma(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=_a(o,r.items);return Un=o,Ja(a),Gr("Cache rebuilt."),o},lc=()=>window.performance&&"function"==typeof window.performance.now?window.performance.now():Date.now(),uc=e=>!!e&&!e.stale&&e.generation===or&&e.documentGuid===Pa()&&e.sceneId===vn,pc=async(e={})=>{const t=!!e.includeSelection,n=!1!==e.updateDisplay,r=or,o=lc(),a=ra(),c=oa(),i=Un?.currentScene;if(!i||!Number.isInteger(i.startParagraphIndex)||!Number.isInteger(i.endParagraphIndex))return null;if(!mn||!wn||!window.Word||"function"!=typeof window.Word.run)return null;const s=lc(),d=await window.Word.run(async e=>{const n=e.document.body.paragraphs;n.load("text");let r=null;return t&&(r=e.document.getSelection().paragraphs,r.load("text,styleBuiltIn,style")),await e.sync(),{bodyTexts:n.items.map(e=>String(e.text||"")),selectionParagraphs:t&&r?r.items.map(e=>({text:String(e.text||""),styleBuiltIn:e.styleBuiltIn,style:e.style})):[]}}),l=Math.round(lc()-s);if(r!==or)return Fr(`Office snapshot: ${l}ms stale`),{stale:!0,generation:r};let u=!1;if(t){const e=_a(Un,d.selectionParagraphs);u=Ja(e)}const p=Un?.currentScene;if(!p||!Number.isInteger(p.startParagraphIndex)||!Number.isInteger(p.endParagraphIndex))return null;const h=[];let m=0;const w=Math.min(p.endParagraphIndex,d.bodyTexts.length-1),g=Un.currentChapter?.startParagraphIndex;for(let e=p.startParagraphIndex;e<=w;e+=1){const t=String(d.bodyTexts[e]||"").trim();t&&!Wa.has(t)&&e!==g&&(h.push(t),m+=qa(t))}p.wordCount=m,n&&no(Un.currentChapter?.title,p.title,m,Un.currentChapter?.anchorId,p.anchorId,Un.currentChapter?.index);const y={documentGuid:Pa(),projectId:a?.projectId||null,bookId:c?.bookId||null,chapterId:xn,sceneId:vn,chapterTitle:Un.currentChapter?.title||"",sceneTitle:p.title||"",sceneText:h.join("\n"),wordCount:m,selectionSignature:`${Un.currentParagraphIndex??-1}:${p.startParagraphIndex}:${p.endParagraphIndex}`,selectionChanged:u,generation:r};return ar=y,Fr(`Office snapshot: ${l}ms; scene words: ${m}; total snapshot: ${Math.round(lc()-o)}ms`),y},hc=async()=>uc(ar)?ar:await pc(),mc=async()=>{if(Xr(""),!mn||!wn||!window.Word||"function"!=typeof window.Word.run)return no(null,null,null),Xr("Word document access is unavailable."),_o({lastScan:"Failure",lastError:"Word document access is unavailable."}),!1;Q&&(Q.disabled=!0,Q.textContent="Scanning..."),Xr("Scanning document structure...");try{const e=await window.Word.run(async e=>{const t=oa();return t?await dc(e,!!t.usesExplicitScenes):(Un=null,await sc(e))});return Un||no(e.currentChapter?.title,e.currentScene?.title,e.currentScene?.wordCount,e.currentChapter?.anchorId,e.currentScene?.anchorId,e.currentChapter?.index),jo("Not detected"),za(e),Xr(""),_o({lastScan:"Success",lastError:"-",paragraphs:String(e.paragraphCount),heading1:String(e.heading1Count),heading2:String(e.heading2Count)}),!0}catch(e){const t=Jo(e);return console.error("Unable to scan the Word document.",e),no(null,null,null),Xr(`Unable to scan the Word document: ${t}`),_o({lastScan:"Failure",lastError:t}),!1}finally{Q&&(Q.disabled=!1,Q.textContent="Refresh Document Structure"),await io().catch(()=>null)}},wc=async()=>{const e=oa();if(!ra()||!e)return lo("Select a project and book to analyse manuscript structure."),!1;if(!mn||!wn||!window.Word||"function"!=typeof window.Word.run)return lo("Word document access is unavailable."),_o({lastScan:"Failure",lastError:"Word document access is unavailable."}),!1;ae&&(ae.disabled=!0,ae.textContent="Analysing..."),lo("Analysing manuscript structure...");try{const t=await window.Word.run(async e=>await sc(e)),n=await kc(`/api/word-companion/books/${e.bookId}/structure`);return no(t.currentChapter?.title,t.currentScene?.title,t.currentScene?.wordCount,t.currentChapter?.anchorId,t.currentScene?.anchorId,t.currentChapter?.index),za(t),jn=((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=oc(t,r,n);for(const o of rc(t))ac(o,e,r,n)}return n})(t,n),ic(jn),lo("Preview generated. No changes have been applied."),_o({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),lo("Unable to analyse manuscript structure."),_o({lastScan:"Failure",lastError:Jo(e)}),!1}finally{ae&&(ae.textContent="Analyse Manuscript Structure",mo())}},gc=e=>{Qn&&(Qn(e),Qn=null),At?.close?At.close():At&&(At.hidden=!0)},yc=()=>{const e=((e=jn)=>{const t=po(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(!Tt)return;Tt.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)}Tt.append(n)})(e),At?new Promise(e=>{Qn=e,At.showModal?At.showModal():At.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.`))},fc=(e,t,n="")=>{e.result=t,e.error=n},bc=e=>Number.isInteger(e?.wordChapter?.index)&&e.wordChapter.index>0?10*e.wordChapter.index:null,Ic=e=>Number.isInteger(e?.wordScene?.index)&&e.wordScene.index>0?10*e.wordScene.index:null,Cc=async(e,t)=>{const n=await vc(`/api/word-companion/books/${e}/chapters`,{title:Mo(t.wordTitle),sortOrder:bc(t)});if(!n?.chapterId)throw new Error("Chapter creation did not return a chapter ID.");xo(),t.pdChapter={chapterId:n.chapterId,title:n.title||t.wordTitle,sortOrder:n.sortOrder||bc(t)||0,scenes:[]},t.match=`Chapter ${t.pdChapter.chapterId}: ${t.pdChapter.title}`},Sc=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 vc(`/api/word-companion/books/${e}/chapters/${n.chapterId}/scenes`,{sceneTitle:Mo(t.wordTitle),sortOrder:Ic(t)});if(!r?.sceneId)throw new Error("Scene creation did not return a scene ID.");xo(),t.pdChapter=n,t.pdScene={sceneId:r.sceneId,title:t.wordTitle,sortOrder:Ic(t)||0},t.match=`Scene ${t.pdScene.sceneId}: ${t.pdScene.title}`},kc=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()},vc=(e,t)=>kc(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}),xc=async(e="")=>{Kn=!1,Yn=0,Gn=[],k&&(k.innerHTML=""),oo(C,!0),ya(!1),wa(""),oo(v,!0),e&&Xr(e);const t=await Dc();e&&t&&fn&&Xr(e)},Pc=async(e=vn,t=xn)=>{const n=ra(),r=oa(),o=Pa(),a=Number.parseInt(e||"",10),c=Number.parseInt(t||"",10);if(!n||!r||!o||!Number.isInteger(a)||a<=0||!Number.isInteger(c)||c<=0)return;const i=`${n.projectId}:${r.bookId}:${a}`;if($r!==i){$r=i;try{await vc("/api/word-companion/runtime/current-scene",{documentGuid:o,projectId:n.projectId,bookId:r.bookId,chapterId:c,sceneId:a}),Gr("Current scene follow event sent.")}catch(e){$r="",console.debug("Unable to notify PlotDirector of current scene.",e)}}},Dc=async()=>{const e=oa();if(!(e&&mn&&wn&&window.Word&&"function"==typeof window.Word.run))return!1;Xr("Reading manuscript position...");try{xo(),await Promise.all([Jc(!0),zc(!0),Qc(!0)]),await Ho(e.bookId);const t=await window.Word.run(async t=>await dc(t,!!e.usesExplicitScenes));return za(t),_o({lastScan:"Success",lastError:"-",paragraphs:String(t.paragraphCount),heading1:String(t.heading1Count),heading2:String(t.heading2Count)}),fn?(bn?await ri():await ni(),fo(!1),yo("Live"),Xr(""),!0):(jo("Not detected"),fo(!1),yo("Live"),Xr("Manuscript linked. Click inside a chapter to show the current scene."),!0)}catch(e){return console.error("Unable to initialise bound manuscript runtime.",e),Un=null,yo("Manual"),Xr(`Unable to read manuscript position: ${Jo(e)}`),_o({lastScan:"Failure",lastError:Jo(e)}),!1}},Ec=async n=>{Wn=null,ci(),ro(),vo(),jo("Not detected"),yo("Manual"),Jr("Connected"),Xo(e,null),Xo(t,null),V&&(V.value=""),Zo(K,"Select a project first"),fa(),h&&(h.value=""),Zo(m,"Select a project first"),ba(n||"Select a Project and Book to begin."),Xr(n||"Manuscript unlinked."),so("No resolved PlotDirector scene."),ya(!0),ao()},Nc=e=>e?[...e.querySelectorAll("input[type='checkbox']:checked")].map(e=>Number.parseInt(e.value||"",10)).filter(e=>Number.isInteger(e)&&e>0):[],Lc=()=>{const e=Number.parseInt(ze?.value||"",10);return Number.isInteger(e)&&e>0?e:null},qc=(e,t,n,r)=>{const o=((e,t)=>Aa(e).find(e=>$a(e.tag,t))||null)(e,r),a=o||e.getRange().insertContentControl();return a.title=t,a.tag=n,a.appearance="Hidden",a},$c=async(e="PlotDirector IDs attached successfully.")=>{if(!vn||!xn)return Xr("No resolved PlotDirector scene."),!1;if((kn&&kn!==vn||Sn&&Sn!==xn)&&!window.confirm("This scene is already linked. Replace the existing PlotDirector link?"))return!1;if(!mn||!wn||!window.Word||"function"!=typeof window.Word.run)return Xr("Word document access is unavailable."),!1;we&&(we.disabled=!0,we.textContent="Attaching...");try{return await window.Word.run(async e=>{const t=await sc(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.");qc(n,"PlotDirector Chapter",`PD-CHAPTER-${xn}`,"PD-CHAPTER"),qc(r,"PlotDirector Scene",`PD-SCENE-${vn}`,"PD-SCENE"),await e.sync()}),await io().catch(()=>null),Sn=xn,kn=vn,En=!1,Dn="SceneID Anchor",Pn="Anchor",Xr(e),_o({lastError:"-"}),to(),!0}catch(e){return console.error("Unable to attach PlotDirector IDs.",e),Xr("Unable to attach PlotDirector IDs."),_o({lastError:Jo(e)}),to(),!1}finally{we&&(we.textContent=kn===vn?"Attach PlotDirector IDs":"Reattach PlotDirector IDs",to())}},Ac=async e=>{if(!xn)return Eo("No resolved PlotDirector chapter."),!1;if(!mn||!wn||!window.Word||"function"!=typeof window.Word.run)return Eo("Word document access is unavailable."),!1;try{return await window.Word.run(async e=>{const t=await sc(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.");qc(n,"PlotDirector Chapter",`PD-CHAPTER-${xn}`,"PD-CHAPTER"),await e.sync()}),await io().catch(()=>null),Sn=xn,En=!1,Dn="ChapterID Anchor",Pn="Chapter anchor",Eo(e),Xr(e),_o({lastError:"-"}),to(),!0}catch(e){return console.error("Unable to attach PlotDirector chapter ID.",e),Eo("Unable to attach PlotDirector chapter ID."),_o({lastError:Jo(e)}),to(),!1}},Tc=async e=>{qo(),await ri(),Xr(e),Eo(e)},jc=e=>{Tn&&(Tn(e),Tn=null),Et?.close?Et.close():Et&&(Et.hidden=!0)},Wc=()=>{if(!vt)return;const e=Mo(kt?.value||"").toLocaleLowerCase(),t=$n.filter(t=>!e||String(t.title||"").toLocaleLowerCase().includes(e));if(vt.innerHTML="",An=null,xt&&(xt.disabled=!0),0===t.length){const e=document.createElement("p");return e.className="word-companion-empty-list",e.textContent="No chapters found.",void vt.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",()=>{An=t,xt&&(xt.disabled=!1)});const o=document.createElement("span");o.textContent=e.title||"Untitled chapter",n.append(r,o),vt.append(n)}},Rc=()=>{St?.close?St.close():St&&(St.hidden=!0)},Uc=async(e,t,n)=>{const r=oa();if(!r)return Do("Select a PlotDirector book first."),!1;await Ko(r.bookId,e,t,"Manual link","Title Match");return!!await $c(n)&&(Do(n),Ao(),!0)},Mc=e=>{qn&&(qn(e),qn=null),yt?.close?yt.close():yt&&(yt.hidden=!0)},Oc=()=>{if(!ht)return;const e=Mo(pt?.value||"").toLocaleLowerCase(),t=Nn.filter(t=>!e||String(t.title||"").toLocaleLowerCase().includes(e));if(ht.innerHTML="",Ln=null,mt&&(mt.disabled=!0),0===t.length){const e=document.createElement("p");return e.className="word-companion-empty-list",e.textContent="No scenes found.",void ht.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",()=>{Ln=t,mt&&(mt.disabled=!1)});const o=document.createElement("span");o.textContent=e.title||"Untitled scene",n.append(r,o),ht.append(n)}},Bc=()=>{ut?.close?ut.close():ut&&(ut.hidden=!0)},Hc=()=>{lr=!1,go(),ur&&(ur=!1,Fc(1e3))},Gc=async(e={})=>{const t=e.source||"manual",n=lc();if(!vn)return void so("No resolved PlotDirector scene.");if(!xn)return void so("No resolved PlotDirector chapter.");if(Zn)return void so("Refresh Current Scene before syncing.");const r=oa(),o=Pa();if(!r||!o)return void so("Bound manuscript metadata is unavailable.");if(lr)return ur=!0,void Gr("Scene sync deferred; sync already running.");ro(),lr=!0,ur=!1;let a=e.snapshot||null;try{a=uc(a)?a:await hc()}catch(e){return so("Sync failed"),_o({lastError:Jo(e)}),Gr("Scene sync failed."),void Hc()}if(!uc(a))return so("Waiting for typing to pause"),Gr("Scene sync skipped (stale snapshot)."),void Hc();const c=a.wordCount;if(!Number.isInteger(c)||c<0)return so("Sync failed"),Gr("Scene sync failed."),void Hc();if(pr===a.sceneId&&hr===c)return so("Synced"),Gr("Sync skipped (count unchanged)."),void Hc();Gr("Scene word count changed."),Re&&(Re.disabled=!0,Re.textContent="Syncing..."),so("Syncing..."),Gr(`Scene sync started (${t}).`);try{const e=lc(),t=await vc("/api/word-companion/runtime/scene-word-count",{documentGuid:a.documentGuid||o,bookId:a.bookId||r.bookId,chapterId:a.chapterId,sceneId:a.sceneId,wordCount:c});if(Fr(`Word count sync API: ${Math.round(lc()-e)}ms`),!uc(a))return void Gr("Scene sync result ignored (stale snapshot).");const i=t?.actualWords??c,s=new Date;pr=a.sceneId,hr=i,Yo(Me,Co(i)),Yo($e,Co(i)),Yo(Oe,So(s)),Yo(We,So(s)),so("Synced"),Gr("Scene sync succeeded."),Fr(`Total word count sync: ${Math.round(lc()-n)}ms`)}catch(e){so("Sync failed"),_o({lastError:Jo(e)}),Gr("Scene sync failed.")}finally{Re&&(Re.textContent="Sync Current Scene"),Hc()}},Fc=(e=4e3)=>{ro(),vn&&xn&&!Zn&&!lr&&(dr=window.setTimeout(()=>{dr=null,Gc({source:"automatic"})},e))},Vc=()=>{mr&&(window.clearTimeout(mr),mr=null)},Kc=()=>{yr=null,fr="",br=[],Ir=null,Cr="",Vc()},Yc=()=>{Sr=null,kr="",vr=[],xr=null,Pr=""},_c=()=>{Dr=null,Er="",Nr=[],Lr=null,qr=""},Jc=async(e=!1)=>{const t=ra(),n=Pa();if(!t||!n)return br=[],[];if(!e&&yr===t.projectId&&fr===n&&br.length>0)return br;const r=await kc(`/api/word-companion/runtime/characters?projectId=${encodeURIComponent(t.projectId)}&documentGuid=${encodeURIComponent(n)}`);return yr=t.projectId,fr=n,br=Array.isArray(r?.characters)?r.characters:[],Gr("Character alias cache refreshed."),br},zc=async(e=!1)=>{const t=ra(),n=Pa();if(!t||!n)return vr=[],[];if(!e&&Sr===t.projectId&&kr===n&&vr.length>0)return vr;const r=await kc(`/api/word-companion/runtime/assets?projectId=${encodeURIComponent(t.projectId)}&documentGuid=${encodeURIComponent(n)}`);return Sr=t.projectId,kr=n,vr=Array.isArray(r?.assets)?r.assets:[],Gr(`Asset cache loaded: ${vr.length} aliases.`),vr},Qc=async(e=!1)=>{const t=ra(),n=Pa();if(!t||!n)return Nr=[],[];if(!e&&Dr===t.projectId&&Er===n&&Nr.length>0)return Nr;const r=await kc(`/api/word-companion/runtime/locations?projectId=${encodeURIComponent(t.projectId)}&documentGuid=${encodeURIComponent(n)}`);return Dr=t.projectId,Er=n,Nr=Array.isArray(r?.locations)?r.locations:[],Gr(`Location cache loaded: ${Nr.length} aliases.`),Nr},Xc=(e,t)=>{const n=String(t||"").trim();if(!n)return!1;const r=(o=n,String(o||"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&")).replace(/\s+/g,"\\s+");var o;return new RegExp(`(^|[^\\p{L}\\p{N}_])${r}(?=$|[^\\p{L}\\p{N}_])`,"iu").test(e)},Zc=e=>{if(e?.excludeFromCompanionDetection)return!1;const t=Number.parseInt(e?.detectionPriority||"0",10);return n=e?.matchText,String(n||"").trim().split(/\s+/).filter(Boolean).length>=2||Number.isInteger(t)&&t>=75;var n},ei=async()=>{if(mr=null,!vn||Zn||!Pa())return;if(wr)return gr=!0,void Gr("Character suggestion detection deferred; detection already running.");wr=!0,gr=!1;const e=lc();try{const t=await hc();if(!uc(t))return void Gr("Runtime suggestions skipped (stale snapshot).");const[n,r,o]=await Promise.all([Jc(),zc(),Qc()]);if(!uc(t))return void Gr("Runtime suggestions skipped after cache load (stale snapshot).");const a=t.sceneText||"",c=lc(),i=((e,t)=>{if(!e||!Array.isArray(t)||0===t.length)return[];const n=new Map;for(const r of t){const t=Number.parseInt(r.characterId||"",10);!Number.isInteger(t)||t<=0||n.has(t)||Xc(e,r.matchText)&&n.set(t,r.name||r.matchText||"Character")}return[...n.entries()].map(([e,t])=>({characterId:e,name:t}))})(a,n);Fr(`Character detection: ${Math.round(lc()-c)}ms`);const s=i.map(e=>e.characterId),d=s.slice().sort((e,t)=>e-t).join(","),l=lc(),u=((e,t)=>{if(!e||!Array.isArray(t)||0===t.length)return[];const n=new Map;for(const r of t){const t=Number.parseInt(r.assetId||"",10);!Number.isInteger(t)||t<=0||n.has(t)||Xc(e,r.matchText)&&n.set(t,r.name||r.matchText||"Asset")}return[...n.entries()].map(([e,t])=>({assetId:e,name:t}))})(a,r);Fr(`Asset detection: ${Math.round(lc()-l)}ms`);const p=u.map(e=>e.assetId),h=p.slice().sort((e,t)=>e-t).join(","),m=lc(),w=((e,t)=>{if(!e||!Array.isArray(t)||0===t.length)return[];const n=new Map;for(const r of t){const t=Number.parseInt(r.locationId||"",10);!Number.isInteger(t)||t<=0||n.has(t)||!Zc(r)||Xc(e,r.matchText)&&n.set(t,r.name||r.matchText||"Location")}return[...n.entries()].map(([e,t])=>({locationId:e,name:t}))})(a,o);Fr(`Location detection: ${Math.round(lc()-m)}ms`);const g=w.map(e=>e.locationId),y=g.slice().sort((e,t)=>e-t).join(",");if(!d||Ir===vn&&Cr===d)Gr("Character suggestions skipped.");else{if(!uc(t))return void Gr("Character suggestions skipped before submit (stale snapshot).");const e=lc(),n=await vc("/api/word-companion/runtime/character-suggestions",{documentGuid:t.documentGuid,sceneId:t.sceneId,characterIds:s});if(Fr(`Character suggestion API: ${Math.round(lc()-e)}ms`),!uc(t))return void Gr("Character suggestion result ignored (stale snapshot).");if(Ir=t.sceneId,Cr=d,(n?.createdCount||0)>0){const e=i.slice(0,3).map(e=>e.name).join(", "),t=i.length>3?" +"+(i.length-3):"";Xr(e?`Characters detected: ${e}${t}`:n.message)}Gr(n?.message||"Character suggestions submitted.")}if(!h||xr===vn&&Pr===h)Gr("Asset suggestions skipped.");else{if(!uc(t))return void Gr("Asset suggestions skipped before submit (stale snapshot).");Gr(`Asset matches found: ${u.map(e=>e.name).join(", ")}`);const e=lc(),n=await vc("/api/word-companion/runtime/asset-suggestions",{documentGuid:t.documentGuid,sceneId:t.sceneId,assetIds:p});if(Fr(`Asset suggestion API: ${Math.round(lc()-e)}ms`),!uc(t))return void Gr("Asset suggestion result ignored (stale snapshot).");if(xr=t.sceneId,Pr=h,(n?.createdCount||0)>0){const e=u.slice(0,3).map(e=>e.name).join(", "),t=u.length>3?" +"+(u.length-3):"";Xr(e?`Assets detected: ${e}${t}`:n.message)}Gr(n?.message||"Asset suggestions submitted.")}if(!y||Lr===vn&&qr===y)Gr("Location suggestions skipped.");else{if(!uc(t))return void Gr("Location suggestions skipped before submit (stale snapshot).");Gr(`Location matches found: ${w.map(e=>e.name).join(", ")}`);const e=lc(),n=await vc("/api/word-companion/runtime/location-suggestions",{documentGuid:t.documentGuid,sceneId:t.sceneId,locationIds:g});if(Fr(`Location suggestion API: ${Math.round(lc()-e)}ms`),!uc(t))return void Gr("Location suggestion result ignored (stale snapshot).");if(Lr=t.sceneId,qr=y,(n?.createdCount||0)>0){const e=w.slice(0,3).map(e=>e.name).join(", "),t=w.length>3?" +"+(w.length-3):"";Xr(e?`Locations detected: ${e}${t}`:n.message)}Gr(n?.message||"Location suggestions submitted.")}Fr(`Total suggestion pass: ${Math.round(lc()-e)}ms`)}catch(e){console.error("Unable to detect runtime suggestions.",e),_o({lastError:Jo(e)})}finally{wr=!1,gr&&(gr=!1,ti(1500))}},ti=(e=2500)=>{Vc(),!vn||Zn||wr?wr&&(gr=!0):mr=window.setTimeout(()=>{ei()},e)},ni=async()=>{const e=ra(),t=oa(),n=Oo(fn,"chapter");if(Bo({projectId:e?.projectId,projectTitle:e?.title,bookId:t?.bookId,bookTitle:t?ta(t):void 0,detectedChapter:fn,detectedScene:bn,requestChapter:n,requestScene:"",result:"Not run",chapterId:null,sceneId:null}),!t)return jo("Not detected"),Xr("Select a PlotDirector book first."),!1;if(!fn)return jo("Not detected"),Xr("No chapter detected in Word. Use Heading 1 for chapters."),!1;jo("Not detected");try{const e=await Go(t.bookId),r=Sn?e.find(e=>e.chapterId===Sn):null,o=n.toLocaleLowerCase(),a=o?e.find(e=>Oo(e.title,"chapter").toLocaleLowerCase()===o):null,c=r||a;return c?(qo(),bo(null,c.chapterId,r?"Chapter anchor":"Chapter title"),Dn=r?"ChapterID Anchor":"Title Match",Zr("Chapter linked to PlotDirector"),Xr("No scene detected in Word. Use Heading 2 for scenes."),Bo({result:"Chapter matched",chapterId:c.chapterId,sceneId:null}),!0):(bo(null),Zr("Chapter not found in PlotDirector."),Xr("Chapter not found in PlotDirector."),Bo({result:"Chapter not matched",chapterId:null,sceneId:null}),$o("Chapter not found in PlotDirector."),!1)}catch(e){return jo("Not found in PlotDirector"),_o({lastError:Jo(e)}),Xr("Unable to load PlotDirector chapter data."),!1}},ri=async()=>{const e=ra(),t=oa(),n=Oo(fn,"chapter"),r=Oo(bn,"scene");if(Bo({projectId:e?.projectId,projectTitle:e?.title,bookId:t?.bookId,bookTitle:t?ta(t):void 0,detectedChapter:fn,detectedScene:bn,requestChapter:n,requestScene:r,result:"Not run",chapterId:null,sceneId:null}),eo({anchorType:kn?"SceneID Anchor":Sn?"ChapterID Anchor":"Title Match",storedSceneId:kn,storedChapterId:Sn,resolutionMethod:"-"}),!t)return jo("Not detected"),Xr("Select a PlotDirector book first."),Bo({result:"Error"}),!1;if(!fn||!bn)return jo("Not detected"),Xr("No scene detected in Word. Use Heading 2 for scenes."),Bo({result:"Error"}),!1;de&&(de.disabled=!0,de.textContent="Refreshing...");const o=()=>{de&&(de.disabled=!1,de.textContent="Refresh PlotDirector Scene")};jo("Not detected"),Xr("Resolving PlotDirector scene...");try{if(kn){const e=await(async(e,t)=>{const n=await kc(`/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===kn);if(e)return Bo({result:"Matched",chapterId:e.chapter.chapterId,sceneId:e.scene.sceneId}),await Ko(t.bookId,e.scene.sceneId,e.chapter.chapterId,"Anchor","SceneID Anchor"),!0;En=!0,Dn="SceneID Anchor",Zr("Not found in PlotDirector"),Xr("Stored PlotDirector ID is invalid."),Bo({result:"Error",chapterId:Sn,sceneId:kn}),eo({anchorType:"SceneID Anchor",storedSceneId:kn,storedChapterId:Sn,resolutionMethod:"Anchor"})}if(Sn){const e=(await Ho(t.bookId)).find(e=>e.chapterId===Sn),n=e?(Array.isArray(e.scenes)?e.scenes:[]).find(e=>Oo(e.title,"scene").toLocaleLowerCase()===r.toLocaleLowerCase()):null;if(n)return Bo({result:"Matched",chapterId:e.chapterId,sceneId:n.sceneId}),await Ko(t.bookId,n.sceneId,e.chapterId,"Anchor","ChapterID Anchor"),!0;e&&!kn?(Dn="ChapterID Anchor",bo(null,Sn,"Chapter anchor"),Bo({result:"Chapter matched",chapterId:Sn,sceneId:null})):kn||(Dn="ChapterID Anchor",Bo({result:"Chapter anchor not found",chapterId:Sn,sceneId:null}))}const e=await vc(`/api/word-companion/books/${t.bookId}/resolve-scene`,{chapterTitle:n,sceneTitle:r});if(!e?.matched||!e.sceneId){const t=En,n=Number.parseInt(e?.chapterId||"",10),r=Number.isInteger(xn)&&xn>0?xn:null,a=Number.isInteger(n)&&n>0?n:r,c=!!e?.chapterMatched||!!a;return jo("Not found in PlotDirector"),En=t,c&&(bo(null,a,a===r?"Chapter anchor":"Chapter title"),Zr("Scene not found in PlotDirector.")),Xr(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."),Bo({result:"Not matched",chapterId:c?a:e?.chapterId,sceneId:e?.sceneId}),t||(c?(qo(),To("Scene not found in PlotDirector.")):(Ao(),$o("Chapter not found in PlotDirector."))),o(),!1}const a=En;return Bo({result:a?"Matched by title fallback":"Matched",chapterId:e.chapterId,sceneId:e.sceneId}),await Ko(t.bookId,e.sceneId,e.chapterId,a?"Title fallback":"Title","Title Match"),a&&(En=!0,Xr("Stored PlotDirector ID is invalid."),to()),!0}catch(e){const t=En;return _o({lastError:Jo(e)}),jo("Not found in PlotDirector"),En=t,Xr(t?"Stored PlotDirector ID is invalid.":"Unable to load PlotDirector scene data."),Bo({result:"Error"}),!1}finally{o()}},oi=async()=>{if(er=null,sr)return rr=!0,void Gr("Runtime update deferred; update already running.");if(!dn||!oa())return tr=!1,void Gr("Runtime update skipped.");if(!mn||!wn||!window.Word||"function"!=typeof window.Word.run)return tr=!1,yo("Manual"),void Xr("Automatic scene tracking is unavailable in this Word version. Use Refresh Current Scene.");if(!Un)return tr=!1,yo("Manual"),void Xr("Document structure is not cached yet. Use Refresh Current Scene.");const e=Date.now()-nr;if(tr&&e{er&&window.clearTimeout(er),er=window.setTimeout(oi,Math.max(0,e)),yo("Waiting for typing to pause"),Gr("Runtime update scheduled.")},ci=()=>{er&&(window.clearTimeout(er),er=null),tr=!1,rr=!1},ii=()=>{((e="selection",t=1200)=>{if(tr=!0,nr=Date.now(),or+=1,ar=null,ro(),Vc(),lr&&(ur=!0),wr&&(gr=!0),Gr(`${e} changed.`),sr)return rr=!0,void yo("Waiting for typing to pause");ai(t)})("Selection")},si=()=>{if(ir&&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:ii}),ir=!1}catch(e){console.warn("Unable to remove Word selection tracking handler.",e)}},di=async(e,n)=>{if(Un=null,xo(),!e)return hn=[],Zo(K,"Select a project first"),Zo(m,"Select a project first"),Qr(""),Xo(t,null),Da(),jo("Not detected"),void uo();Zo(K,"Loading books..."),Qr(""),jo("Not detected"),uo("Select a book to analyse manuscript structure.");try{const r=await kc(`/api/word-companion/projects/${e}/books`);if(hn=Array.isArray(r.books)?r.books:[],0===hn.length)return Zo(K,"No books available."),Zo(m,"No books available."),Qr("No books available."),Xo(t,null),Da(),void ba("No books available.");ea(K,"Choose a book",hn.map(e=>({...e,displayTitle:ta(e)})),"bookId","displayTitle");const o=hn.find(e=>e.bookId===n);o&&K?(K.value=String(o.bookId),Xo(t,o.bookId)):Xo(t,null),((e=null)=>{if(!m)return;if(0===hn.length)return void Zo(m,"No books available.");ea(m,"Choose a book",hn.map(e=>({...e,displayTitle:ta(e)})),"bookId","displayTitle");const t=e||Number.parseInt(K?.value||"",10),n=hn.find(e=>e.bookId===t);n&&(m.value=String(n.bookId)),ga()})(o?.bookId||n),Da(),jo((oa(),"Not detected")),uo(oa()?"Ready to analyse manuscript structure.":"Select a book to analyse manuscript structure."),ba(ca()?"Ready to scan manuscript structure.":"Select a Book to begin.")}catch{hn=[],Zo(K,"Unable to load books."),Zo(m,"Unable to load books."),Qr("Unable to load books."),Xo(t,null),Da(),jo("Not detected"),uo("Unable to load books."),ba("Unable to load books.")}};for(const e of i)e.addEventListener("click",()=>Yr(e.dataset.tabButton));_r(),V?.addEventListener("change",async()=>{const n=Number.parseInt(V.value||"",10);vo(),h&&Number.isInteger(n)&&n>0&&(h.value=String(n)),Xo(e,Number.isInteger(n)&&n>0?n:null),Xo(t,null),jo("Not detected"),uo(),ba("Select a Book to begin."),await di(n,null),ha()}),K?.addEventListener("change",()=>{const e=Number.parseInt(K.value||"",10);vo(),Xo(t,Number.isInteger(e)&&e>0?e:null),m&&Number.isInteger(e)&&e>0&&(m.value=String(e)),Da(),jo("Not detected"),uo(oa()?"Ready to analyse manuscript structure.":"Select a book to analyse manuscript structure."),ba(ca()?"Ready to scan manuscript structure.":"Select a Book to begin."),ha()}),h?.addEventListener("change",async()=>{const n=Number.parseInt(h.value||"",10);vo(),V&&Number.isInteger(n)&&n>0&&(V.value=String(n)),Xo(e,Number.isInteger(n)&&n>0?n:null),Xo(t,null),ba("Select a Book to begin."),await di(n,null),ha()}),m?.addEventListener("change",()=>{const e=Number.parseInt(m.value||"",10);vo(),K&&Number.isInteger(e)&&e>0&&(K.value=String(e)),Xo(t,Number.isInteger(e)&&e>0?e:null),Da(),ba(ca()?"Ready to scan manuscript structure.":"Select a Book to begin."),ha()}),w?.addEventListener("input",ga),g?.addEventListener("click",async()=>{const e=aa(),t=String(w?.value||"").trim();if(e&&t){g.disabled=!0,wa("Creating Book...");try{const n=await vc(`/api/word-companion/projects/${e.projectId}/books`,{title:t});w&&(w.value=""),V&&(V.value=String(e.projectId)),await di(e.projectId,n.bookId),m&&(m.value=String(n.bookId)),wa("Ready to scan manuscript structure.")}catch(e){console.error("Unable to create Book from Word Companion.",e),wa(`Unable to create Book: ${Jo(e)}`)}finally{ga()}}else ga()}),y?.addEventListener("click",async()=>{const e=aa(),t=ca();if(e&&t)if(mn&&wn&&window.Word&&"function"==typeof window.Word.run){y&&(y.disabled=!0,y.textContent="Scanning..."),wa("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),La(e,1))return r={title:d,sortOrder:10*(n.length+1),wordCount:0,scenes:[]},n.push(r),o=s(),void(a+=qa(d));if(!r||!o)return;if(t&&i.has(d))return void(o=s());const l=qa(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)});Hn=n,Vn=!1;const r=await vc("/api/word-companion/manuscript/analyse",{projectId:e.projectId,bookId:t.bookId,documentGuid:xa(),chapterCount:n.chapterCount,sceneCount:n.sceneCount,wordCount:n.wordCount});Bn=r,(e=>{if(!I)return;I.innerHTML="";const t=document.createElement("strong");t.textContent="Manuscript Analysis",I.append(t);const n=document.createElement("dl"),r=[["Project",e.projectTitle],["Book",ta({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)}I.append(n),oo(I,!1),oo(E,!1),wa(e.message||"Preview generated."),ga()})(r);try{const t=await vc("/api/word-companion/manuscript/discover-characters",{projectId:e.projectId,documentText:n.documentText||""});Gn=Array.isArray(t?.candidates)?t.candidates:[],oo(C,!0),oo(v,!0)}catch(e){console.error("Unable to discover character candidates.",e),Gn=[],oo(C,!0),oo(v,!0)}_o({lastScan:"Success",lastError:"-",paragraphs:"-",heading1:String(n.chapterCount),heading2:"-"})}catch(e){console.error("Unable to scan manuscript for first-run import.",e),ba(`Unable to scan manuscript: ${Jo(e)}`),_o({lastScan:"Failure",lastError:Jo(e)})}finally{y&&(y.textContent="Scan Manuscript"),ga()}}else ba("Word document access is unavailable.");else ba("Select a Project and Book to begin.")}),N?.addEventListener("click",async()=>{const n=aa(),o=ca();if(!(n&&o&&Hn&&Bn?.canImport))return void ga();let a=!1;if(!Bn.requiresReplaceConfirmation||(a=await new Promise(e=>{if(!q||"function"!=typeof q.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=>{$?.removeEventListener("click",n),A?.removeEventListener("click",r),q?.removeEventListener("cancel",o),q?.close(),e(t)},n=()=>t(!0),r=()=>t(!1),o=e=>{e.preventDefault(),t(!1)};$?.addEventListener("click",n),A?.addEventListener("click",r),q?.addEventListener("cancel",o),q.showModal()}),a)){_n=!0,ga(),wa("Importing manuscript structure...");try{const i=xa(),s=await vc("/api/word-companion/manuscript/import",{projectId:n.projectId,bookId:o.bookId,documentGuid:i,bindingVersion:1,replacePlanned:a,chapters:Hn.chapters});if(!s.imported)return Bn={...Bn,canImport:!s.requiresReplaceConfirmation,requiresReplaceConfirmation:!!s.requiresReplaceConfirmation,message:s.message||Bn.message},wa(s.message||"Import was not completed."),void ga();const d=s.manuscriptDocument;await(c={documentGuid:d?.documentGuid||i,bookId:s.bookId,projectId:s.projectId,bindingVersion:d?.bindingVersion||1},new Promise((e,t)=>{const n=window.Office?.context?.document?.settings;n?(n.set(r.documentGuid,c.documentGuid),n.set(r.bookId,String(c.bookId)),n.set(r.projectId,String(c.projectId)),n.set(r.bindingVersion,String(c.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."))})),Wn={documentGuid:d?.documentGuid||i,bookId:s.bookId,projectId:s.projectId,bindingVersion:d?.bindingVersion||1},Xo(e,s.projectId),Xo(t,s.bookId),V&&(V.value=String(s.projectId));const l=Gn;await di(s.projectId,s.bookId),Jr("Connected"),Vn=!0,Kn=l.length>0,Yn=Kn?Date.now():0,Gn=l,l.length>0?(ya(!0),Ca(l),oo(E,!0),oo(v,!1),wa(s.message||"Manuscript structure imported."),Xr(s.message||"Manuscript structure imported."),window.setTimeout(ga,750)):await xc(s.message||"Manuscript structure imported.")}catch(e){console.error("Unable to import manuscript structure.",e),wa(`Unable to import manuscript: ${Jo(e)}`)}finally{_n=!1,ga()}var c}else wa("Import cancelled.")}),x?.addEventListener("click",async()=>{const e=aa()||ra(),t=Ia();if(!Kn||Date.now()-Yn<750||!e||0===t.length)ga();else{Jn=!0,ga(),Yo(S,"Creating selected characters...");try{const n=await vc("/api/word-companion/manuscript/create-discovered-characters",{projectId:e.projectId,candidateNames:t});Xr(n.message||"Characters created."),Yo(S,`${n.createdCount||0} created, ${n.skippedCount||0} already existed.`),await xc(n.message||"Characters created.")}catch(e){console.error("Unable to create discovered characters.",e),Yo(S,`Unable to create characters: ${Jo(e)}`)}finally{Jn=!1,ga()}}}),P?.addEventListener("click",()=>xc("Character creation skipped.")),D?.addEventListener("click",()=>xc()),f?.addEventListener("click",()=>ya(!1)),L?.addEventListener("click",()=>ba("Import cancelled.")),Q?.addEventListener("click",mc),ae?.addEventListener("click",wc),ce?.addEventListener("click",async()=>{const e=oa();if(!e||0===po().length||zn)return void ho();if(!await yc())return;zn=!0,mo(),lo("Applying structure sync...");const t={createdChapters:0,createdScenes:0,linkedChapters:0,linkedScenes:0,skipped:Array.isArray(jn?.manualReview)?jn.manualReview.length:0,failed:0},n=po().filter(e=>"couldLink"===e.category&&"Chapter"===e.type),r=po().filter(e=>"wouldCreateChapters"===e.category),o=po().filter(e=>"couldLink"===e.category&&"Scene"===e.type),a=po().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(!mn||!wn||!window.Word||"function"!=typeof window.Word.run)throw new Error("Word document access is unavailable.");await window.Word.run(async t=>{const n=await sc(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.");qc(o,"PlotDirector Chapter",`PD-CHAPTER-${t}`,"PD-CHAPTER")}else{const t=e.pdScene?.sceneId;if(!t)throw new Error("Scene ID is not available.");qc(o,"PlotDirector Scene",`PD-SCENE-${t}`,"PD-SCENE")}await t.sync()}),await io().catch(()=>null)})(e),fc(e,"Success"),t[n]+=1}catch(n){fc(e,"Failed",Jo(n)),t.failed+=1}};try{for(const e of n)s(e,"linkedChapters");for(const n of r)try{await Cc(e.bookId,n),s(n,"createdChapters")}catch(e){fc(n,"Failed",Jo(e)),t.failed+=1}for(const e of o)s(e,"linkedScenes");for(const n of a)try{await Sc(e.bookId,n),s(n,"createdScenes")}catch(e){fc(n,"Failed",Jo(e)),t.failed+=1}for(const e of c)await d(e.item,e.counterName);for(const e of jn.manualReview||[])fc(e,"Skipped");ic(jn),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),lo(i)}finally{zn=!1,mo(),i&&(xo(),await wc(),lo(`${i} Preview refreshed.`))}}),jt?.addEventListener("click",()=>gc(!0)),Wt?.addEventListener("click",()=>gc(!1)),At?.addEventListener("cancel",e=>{e.preventDefault(),gc(!1)}),de?.addEventListener("click",ri),z?.addEventListener("click",async()=>{if(!oa())return Xr("Select a PlotDirector book first."),void jo("Not detected");ci(),Io(!0),yo("Updating...");try{await Promise.all([Jc(!0),zc(!0),Qc(!0)]);if(!await mc())return;if(fo(!1),!bn)return await ni(),void yo("Current scene updated");await ri(),yo("Current scene updated")}finally{Io(!1)}}),Re?.addEventListener("click",()=>Gc({source:"manual"})),Qe?.addEventListener("click",async()=>{if(vn)if(!Zn&&await(async()=>{if(!vn)return!1;if(!mn||!wn||!window.Word||"function"!=typeof window.Word.run)return fo(!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 sc(e)),t=e.currentChapter?.title||"",n=e.currentScene?.title||"",r=e.currentScene?.anchorId||null,o=e.currentChapter?.anchorId||null,a=Number.isInteger(r)&&r===vn,c=Number.isInteger(o)&&o===xn,i=Oo(n,"scene").toLocaleLowerCase()===Oo(Ar||bn,"scene").toLocaleLowerCase(),s=Oo(t,"chapter").toLocaleLowerCase()===Oo(Tr||fn,"chapter").toLocaleLowerCase();return a||i&&(c||s)?(fo(!1),!0):(fo(!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),_o({lastError:Jo(e)}),fo(!0,"The Word cursor is now in a different scene. Refresh Current Scene before saving."),!1}})()){Qe&&(Qe.disabled=!0,Qe.textContent="Saving...");try{await(e=`/api/word-companion/scenes/${vn}/links`,t={characterIds:Nc(_e),assetIds:Nc(Je),locationIds:[],primaryLocationId:Lc()},kc(e,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})),(()=>{const e=new Set(Nc(_e)),t=new Set(Nc(Je));Ur={characters:Ur.characters.map(t=>({...t,linked:e.has(Number.parseInt(Wo(t,"character"),10))})),assets:Ur.assets.map(e=>({...e,linked:t.has(Number.parseInt(Wo(e,"asset"),10))})),locations:Ur.locations,primaryLocationId:Lc()}})(),Po("Scene links saved successfully."),_o({lastError:"-"})}catch(e){Po("Unable to save scene links."),_o({lastError:Jo(e)})}finally{Qe&&(Qe.disabled=!vn||Zn,Qe.textContent="Save Scene Links")}var e,t}else Po("The Word cursor is now in a different scene. Refresh Current Scene before saving.");else Po("Link a PlotDirector scene first.")}),we?.addEventListener("click",async()=>{await $c()}),ge?.addEventListener("click",async()=>{console.debug("Word Companion unlink clicked"),Xr("Preparing to unlink manuscript...");const e=ka();if(!e)return void Xr("This Word document is not linked.");if(!e.documentGuid||!Number.isInteger(e.bookId)||e.bookId<=0)return void Xr("Unable to unlink: bound document metadata is incomplete.");try{await io()}catch{Xr("Marker counts are unavailable. You can still unlink without removing hidden anchors.")}if(await new Promise(e=>{if(!T||"function"!=typeof T.showModal)return void e(window.confirm(`This will remove PlotDirector binding metadata from this Word document and unlink this Book in PlotDirector.\n\nHidden PlotDirector anchors will be left in place for possible reuse.\n\nCurrent marker count:\n${Mr.chapterCount} chapter markers\n${Mr.sceneCount} scene markers\n\nYour manuscript text will not be changed.\n\nContinue?`));const t=t=>{j?.removeEventListener("click",n),W?.removeEventListener("click",r),T?.removeEventListener("cancel",o),T?.close(),e(t)},n=()=>t(!0),r=()=>t(!1),o=e=>{e.preventDefault(),t(!1)};j?.addEventListener("click",n),W?.addEventListener("click",r),T?.addEventListener("cancel",o),T.showModal()})){Xr("Unlinking manuscript..."),ge&&(ge.disabled=!0,ge.textContent="Unlinking...");try{await vc("/api/word-companion/manuscript/unlink",{documentGuid:e.documentGuid,bookId:e.bookId}),await va(),await io().catch(()=>null),await Ec("Manuscript unlinked.")}catch(e){console.error("Unable to unlink manuscript binding.",e),Xr("Unable to unlink from PlotDirector.");if(window.confirm("PlotDirector could not be updated, but you can still remove the binding from this Word document.\n\nYou may need to unlink the Book manually in PlotDirector later.\n\nRemove binding from this Word document only?"))try{await va(),await io().catch(()=>null),await Ec("Word metadata removed. Unlink the Book manually in PlotDirector if it still shows as linked.")}catch(e){console.error("Unable to remove Word document metadata.",e),Xr(`Unable to remove Word metadata: ${Jo(e)}`)}else Xr(`Unable to unlink manuscript: ${Jo(e)}`)}finally{ge&&(ge.disabled=!1,ge.textContent="Unlink from PlotDirector"),ao()}}else Xr("Unlink cancelled.")}),ye?.addEventListener("click",async()=>{console.debug("Word Companion clean and unlink clicked");const e=ka();if(!mn||!wn||!window.Word||"function"!=typeof window.Word.run)return void Xr("Word document access is unavailable.");Xr("Inspecting PlotDirector markers...");try{await io()}catch(e){return void Xr(`Unable to inspect markers: ${Jo(e)}`)}if(await new Promise(e=>{const t=`This will remove PlotDirector hidden anchors from this Word document while preserving manuscript text.\n\nThis will remove:\n${Mr.chapterCount} PlotDirector chapter markers\n${Mr.sceneCount} PlotDirector scene markers\nthe document's PlotDirector binding\n\nThe document can be linked again later if desired.\n\nContinue?`;if(!R||"function"!=typeof R.showModal)return void e(window.confirm(t));const n=t=>{U?.removeEventListener("click",r),M?.removeEventListener("click",o),R?.removeEventListener("cancel",a),R?.close(),e(t)},r=()=>n(!0),o=()=>n(!1),a=e=>{e.preventDefault(),n(!1)};U?.addEventListener("click",r),M?.addEventListener("click",o),R?.addEventListener("cancel",a),R.showModal()})){ye&&(ye.disabled=!0,ye.textContent="Cleaning..."),ge&&(ge.disabled=!0);try{Xr("Removing PlotDirector hidden anchors..."),await(async()=>{if(!mn||!wn||!window.Word||"function"!=typeof window.Word.run)throw new Error("Word document access is unavailable.");return await window.Word.run(async e=>{const t=e.document.contentControls;t.load("items/tag,title"),await e.sync();let n=0,r=0;for(const e of t.items||[]){const t=Hr(e);t&&("chapter"===t?n+=1:"scene"===t&&(r+=1),e.delete(!0))}return await e.sync(),{chapterCount:n,sceneCount:r,totalCount:n+r,available:!0,message:"PlotDirector markers removed."}})})(),await new Promise(e=>{const t=window.Office?.context?.document;t&&"function"==typeof t.saveAsync?t.saveAsync(t=>{e(t.status===window.Office.AsyncResultStatus.Succeeded)}):e(!1)});try{await io()}catch(e){return console.error("Unable to verify PlotDirector marker cleanup.",e),void Xr(`PlotDirector markers were removed, but cleanup verification failed: ${Jo(e)}`)}if(Mr.available&&Mr.totalCount>0)return void Xr(`Cleanup stopped: ${Mr.totalCount} PlotDirector marker${1===Mr.totalCount?"":"s"} remain.`);Xr("Removing PlotDirector binding metadata...");try{await va()}catch(e){return console.error("Unable to remove Word document metadata after marker cleanup.",e),void Xr(`PlotDirector markers were removed, but Word binding metadata remains: ${Jo(e)}`)}let t="";if(e?.documentGuid&&Number.isInteger(e.bookId)&&e.bookId>0)try{await vc("/api/word-companion/manuscript/unlink",{documentGuid:e.documentGuid,bookId:e.bookId})}catch(e){console.error("Word document cleaned, but PlotDirector server unlink failed.",e),t=" Word document is clean, but unlink the Book manually in PlotDirector if it still shows as linked."}await io().catch(()=>null),await Ec(`Word document cleaned and unlinked.${t}`)}catch(e){console.error("Unable to clean PlotDirector markers.",e),Xr(`Cleanup failed before unlinking: ${Jo(e)}`)}finally{ye&&(ye.disabled=!1,ye.textContent="Clean and unlink"),ge&&(ge.disabled=!1),ao(),co()}}else Xr("Clean and unlink cancelled.")}),xe?.addEventListener("click",()=>la("workspace")),Pe?.addEventListener("click",()=>la("context")),De?.addEventListener("click",()=>la("intent")),nt?.addEventListener("click",async()=>{const e=oa();if(!e||!fn||xn)return void $o("Chapter not found in PlotDirector.");const t=Mo(fn),n=await((e,t)=>(Yo(Nt,`"${e}"`),Yo(Lt,`"${t}"`),Et?new Promise(e=>{Tn=e,Et.showModal?Et.showModal():Et.hidden=!1}):Promise.resolve(window.confirm(`Create PlotDirector chapter:\n\n"${e}"\n\nin book:\n\n"${t}"\n\n?`))))(t,ta(e)||"selected book");if(n){nt&&(nt.disabled=!0,nt.textContent="Creating...");try{const n=Number.isInteger(Cn)&&Cn>0?10*Cn:null,r=await vc(`/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.");xo(),bo(null,r.chapterId,"Manual chapter link");if(!await Ac("Chapter created and linked successfully."))return;await Tc("Chapter created and linked successfully.")}catch(e){Eo("Unable to create chapter."),_o({lastError:Jo(e)})}finally{nt&&(nt.disabled=!No(),nt.textContent="Create Chapter in PlotDirector")}}}),rt?.addEventListener("click",async()=>{const e=oa();if(e&&fn&&!xn){rt&&(rt.disabled=!0,rt.textContent="Loading...");try{$n=await Go(e.bookId),An=null,kt&&(kt.value=""),Yo(Dt,""),Wc(),St?.showModal?St.showModal():St&&(St.hidden=!1)}catch(e){Eo("Unable to load chapters."),_o({lastError:Jo(e)})}finally{rt&&(rt.disabled=!No(),rt.textContent="Link to Existing Chapter")}}else $o("Chapter not found in PlotDirector.")}),kt?.addEventListener("input",Wc),xt?.addEventListener("click",async()=>{const e=$n.find(e=>e.chapterId===An);if(e){xt&&(xt.disabled=!0,xt.textContent="Linking...");try{bo(null,e.chapterId,"Manual chapter link");if(!await Ac("Chapter linked successfully."))return;Rc(),await Tc("Chapter linked successfully.")}catch(e){Yo(Dt,"Unable to link chapter."),Eo("Unable to link chapter."),_o({lastError:Jo(e)})}finally{xt&&(xt.disabled=!An,xt.textContent="Link Chapter")}}else Yo(Dt,"Select a chapter.")}),Pt?.addEventListener("click",Rc),qt?.addEventListener("click",()=>jc(!0)),$t?.addEventListener("click",()=>jc(!1)),Et?.addEventListener("cancel",e=>{e.preventDefault(),jc(!1)}),st?.addEventListener("click",async()=>{const e=oa();if(!e||!bn)return void To("Scene not found in PlotDirector.");const t=Oo(bn,"scene"),n=Oo(fn,"chapter"),r=await((e,t)=>(Yo(ft,`"${e}"`),Yo(bt,`"${t}"`),yt?new Promise(e=>{qn=e,yt.showModal?yt.showModal():yt.hidden=!1}):Promise.resolve(window.confirm(`Create PlotDirector scene:\n\n"${e}"\n\nwithin chapter:\n\n"${t}"\n\n?`))))(t,n);if(r){st&&(st.disabled=!0,st.textContent="Creating...");try{const n=await Vo();if(!n)return void To("This chapter does not exist in PlotDirector. Create or link the chapter first.");const r=await vc(`/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.");xo(),await Uc(r.sceneId,r.chapterId,"Scene created and linked successfully.")}catch(e){Do("Unable to create scene."),_o({lastError:Jo(e)})}finally{st&&(st.disabled=!Lo(),st.textContent="Create Scene in PlotDirector")}}}),dt?.addEventListener("click",async()=>{const e=oa();if(e&&bn){dt&&(dt.disabled=!0,dt.textContent="Loading...");try{const t=await Ho(e.bookId),n=Fo(t);if(!n)return void To("This chapter does not exist in PlotDirector. Create or link the chapter first.");Nn=Array.isArray(n.scenes)?n.scenes:[],Ln=null,pt&&(pt.value=""),Yo(gt,""),Oc(),ut?.showModal?ut.showModal():ut&&(ut.hidden=!1)}catch(e){Do("Unable to load scenes."),_o({lastError:Jo(e)})}finally{dt&&(dt.disabled=!Lo(),dt.textContent="Link to Existing Scene")}}else To("Scene not found in PlotDirector.")}),pt?.addEventListener("input",Oc),mt?.addEventListener("click",async()=>{const e=oa(),t=Nn.find(e=>e.sceneId===Ln);if(e&&t){mt&&(mt.disabled=!0,mt.textContent="Linking...");try{const e=await Vo();if(!e)throw new Error("This chapter does not exist in PlotDirector. Create or link the chapter first.");Bc(),await Uc(t.sceneId,e.chapterId,"Scene linked successfully.")}catch(e){Yo(gt,"Unable to link scene."),Do("Unable to link scene."),_o({lastError:Jo(e)})}finally{mt&&(mt.disabled=!Ln,mt.textContent="Link Scene")}}else Yo(gt,"Select a scene.")}),wt?.addEventListener("click",Bc),It?.addEventListener("click",()=>Mc(!0)),Ct?.addEventListener("click",()=>Mc(!1)),yt?.addEventListener("cancel",e=>{e.preventDefault(),Mc(!1)}),_t?.addEventListener("click",async()=>{_t&&(_t.disabled=!0,_t.textContent="Running...");try{if(await zo(),!mn||!wn||!window.Word||"function"!=typeof window.Word.run)return void _o({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});_o({lastScan:"Success",lastError:"-",paragraphs:String(e)})}catch(e){console.error("Word Companion diagnostics failed.",e);const t=Jo(e);_o({lastScan:"Failure",lastError:t}),Xr(`Unable to scan the Word document: ${t}`)}finally{_t&&(_t.disabled=!1,_t.textContent="Run Diagnostics")}});const li=dn?(async()=>{Zo(V,"Loading projects..."),Zo(K,"Select a project first"),Zo(h,"Loading projects..."),Zo(m,"Select a project first"),zr(""),Qr("");try{const n=await kc("/api/word-companion/projects");if(pn=Array.isArray(n.projects)?n.projects:[],0===pn.length)return Zo(V,"No projects available."),Zo(h,"No projects available."),zr("No projects available."),Xo(e,null),Xo(t,null),Da(),void ba("No projects available.");ea(V,"Choose a project",pn,"projectId","title"),fa();const r=Qo(e),o=pn.find(e=>e.projectId===r);o&&V?(V.value=String(o.projectId),h&&(h.value=String(o.projectId)),Xo(e,o.projectId),await di(o.projectId,Qo(t))):(Xo(e,null),Xo(t,null),Da(),ba("Select a Project and Book to begin."))}catch{pn=[],hn=[],Zo(V,"Unable to connect to PlotDirector."),Zo(K,"Select a project first"),Zo(h,"Unable to connect to PlotDirector."),Zo(m,"Select a project first"),Jr("Unable to connect to PlotDirector."),zr("Unable to connect to PlotDirector."),Xo(e,null),Xo(t,null),Da(),ba("Unable to connect to PlotDirector.")}})():Promise.resolve();if(dn||(Zo(V,"Please sign in to PlotDirector."),Zo(K,"Please sign in to PlotDirector."),Zo(h,"Please sign in to PlotDirector."),Zo(m,"Please sign in to PlotDirector."),Da()),!window.Office||"function"!=typeof window.Office.onReady)return Vr("Word Companion ready"),Xr("Word document access is unavailable."),yo("Manual"),_o({host:"Unavailable",platform:"Unavailable",ready:"No",wordApi:"No"}),void ma().catch(e=>{console.debug("Word Companion presence unavailable.",e)});zo().then(async()=>{Vr("Word Companion ready"),await li,await(async()=>{if(!dn||!wn)return void ya(!1);const n=Sa();if(n)try{const r=await kc(`/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 Wn=n,ko(r),Xo(e,r.projectId),Xo(t,r.bookId),V&&(V.value=String(r.projectId)),await di(r.projectId,r.bookId),ya(!1),Jr("Connected"),Qr("Bound manuscript detected."),void await Dc()}catch{}Wn=null,vo(),fa(),aa()?await di(aa().projectId,null):Zo(m,"Select a project first"),ba("Select a Project and Book to begin."),ya(!0)})(),await ma(),wn?(await io().catch(()=>null),(()=>{if(dn){if(!window.Office?.context?.document||"function"!=typeof window.Office.context.document.addHandlerAsync||!window.Office?.EventType?.DocumentSelectionChanged)return yo("Manual"),void Xr("Automatic scene tracking is unavailable in this Word version. Use Refresh Current Scene.");try{window.Office.context.document.addHandlerAsync(window.Office.EventType.DocumentSelectionChanged,ii,e=>{e?.status===window.Office.AsyncResultStatus.Succeeded?(ir=!0,yo("Live")):(yo("Manual"),Xr("Automatic scene tracking is unavailable in this Word version. Use Refresh Current Scene."))}),window.addEventListener("beforeunload",si)}catch(e){console.warn("Unable to register Word selection tracking handler.",e),yo("Manual"),Xr("Automatic scene tracking is unavailable in this Word version. Use Refresh Current Scene.")}}})()):(Xr("Word document access is unavailable."),yo("Manual"))}).catch(e=>{console.error("Office readiness check failed.",e),Jr("Unable to connect to PlotDirector."),Vr("Word Companion unavailable"),Xr("Word document access is unavailable."),_o({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={documentGuid:"plotdirector.word.documentGuid",bookId:"plotdirector.word.boundBookId",projectId:"plotdirector.word.boundProjectId",bindingVersion:"plotdirector.word.bindingVersion"},o=new Set(["scene","review","maintenance","diagnostics"]),a=document.querySelector(".word-companion-shell"),c=document.querySelector(".word-companion-tabs"),i=[...document.querySelectorAll("[data-tab-button]")],s=[...document.querySelectorAll("[data-tab-panel]")],d=document.querySelector("[data-linked-manuscript-card]"),l=document.querySelector("[data-linked-project-title]"),u=document.querySelector("[data-linked-book-title]"),p=document.querySelector("[data-onboarding-manual-save]"),m=document.querySelector("[data-onboarding-manual-save-message]"),h=document.querySelector("[data-onboarding-manual-save-confirm]"),g=document.querySelector("[data-first-run-wizard]"),w=document.querySelector("[data-first-run-project-select]"),y=document.querySelector("[data-first-run-book-select]"),f=document.querySelector("[data-first-run-new-book-title]"),I=document.querySelector("[data-first-run-create-book]"),b=document.querySelector("[data-first-run-link]"),S=document.querySelector("[data-first-run-scan]"),C=document.querySelector("[data-first-run-cancel]"),k=document.querySelector("[data-first-run-status]"),v=document.querySelector("[data-first-run-summary]"),x=document.querySelector("[data-first-run-character-section]"),D=document.querySelector("[data-first-run-character-status]"),P=document.querySelector("[data-first-run-character-candidates]"),E=document.querySelector("[data-first-run-character-actions]"),N=document.querySelector("[data-first-run-create-characters]"),L=document.querySelector("[data-first-run-skip-characters]"),q=document.querySelector("[data-first-run-continue]"),A=document.querySelector("[data-first-run-import-actions]"),$=document.querySelector("[data-first-run-import]"),T=document.querySelector("[data-first-run-import-cancel]"),W=document.querySelector("[data-first-run-replace-dialog]"),j=document.querySelector("[data-first-run-replace-confirm]"),M=document.querySelector("[data-first-run-replace-cancel]"),U=document.querySelector("[data-unlink-word-document-dialog]"),R=document.querySelector("[data-unlink-word-document-confirm]"),O=document.querySelector("[data-unlink-word-document-cancel]"),B=document.querySelector("[data-clean-unlink-word-document-dialog]"),H=document.querySelector("[data-clean-unlink-word-document-confirm]"),G=document.querySelector("[data-clean-unlink-word-document-cancel]"),F=document.querySelector("[data-office-status]"),V=document.querySelector("[data-connection-status]"),K=document.querySelector("[data-summary-connection]"),Y=document.querySelector("[data-summary-project]"),_=document.querySelector("[data-summary-book]"),J=document.querySelector("[data-project-select]"),z=document.querySelector("[data-book-select]"),Q=document.querySelector("[data-runtime-book-selectors]"),X=document.querySelector("[data-project-message]"),Z=document.querySelector("[data-book-message]"),ee=document.querySelector("[data-refresh-current-scene]"),te=document.querySelector("[data-refresh-document]"),ne=document.querySelector("[data-current-chapter]"),re=document.querySelector("[data-current-scene]"),oe=document.querySelector("[data-current-word-count]"),ae=document.querySelector("[data-scene-tracking-status]"),ce=document.querySelector("[data-document-message]"),ie=document.querySelector("[data-sync-note]"),se=document.querySelector("[data-document-outline]"),de=document.querySelector("[data-analyse-manuscript-structure]"),le=document.querySelector("[data-apply-structure-sync]"),ue=document.querySelector("[data-structure-preview-status]"),pe=document.querySelector("[data-structure-preview-results]"),me=document.querySelector("[data-refresh-plotdirector-scene]"),he=document.querySelector("[data-plotdirector-scene-status]"),ge=document.querySelector("[data-anchor-status]"),we=document.querySelector("[data-anchor-book-id]"),ye=document.querySelector("[data-anchor-chapter-id]"),fe=document.querySelector("[data-anchor-scene-id]"),Ie=document.querySelector("[data-attach-plotdirector-ids]"),be=document.querySelector("[data-unlink-word-document]"),Se=document.querySelector("[data-clean-unlink-word-document]"),Ce=document.querySelector("[data-marker-binding-status]"),ke=document.querySelector("[data-marker-chapter-count]"),ve=document.querySelector("[data-marker-scene-count]"),xe=document.querySelector("[data-unlink-dialog-chapter-count]"),De=document.querySelector("[data-unlink-dialog-scene-count]"),Pe=document.querySelector("[data-clean-dialog-chapter-count]"),Ee=document.querySelector("[data-clean-dialog-scene-count]"),Ne=document.querySelector("[data-open-writing-workspace]"),Le=document.querySelector("[data-open-writing-context]"),qe=document.querySelector("[data-open-writing-intent]"),Ae=document.querySelector("[data-plotdirector-scene-details]"),$e=document.querySelector("[data-plotdirector-scene-title]"),Te=document.querySelector("[data-plotdirector-revision-status]"),We=document.querySelector("[data-plotdirector-estimated-words]"),je=document.querySelector("[data-plotdirector-actual-words]"),Me=document.querySelector("[data-plotdirector-blocked-status]"),Ue=document.querySelector("[data-plotdirector-blocked-reason-row]"),Re=document.querySelector("[data-plotdirector-blocked-reason]"),Oe=document.querySelector("[data-runtime-last-sync]"),Be=document.querySelector("[data-sync-scene-progress]"),He=document.querySelector("[data-sync-word-count]"),Ge=document.querySelector("[data-sync-plotdirector-count]"),Fe=document.querySelector("[data-sync-last-synced]"),Ve=document.querySelector("[data-sync-status]"),Ke=document.querySelector("[data-writing-brief-block]"),Ye=document.querySelector("[data-writing-brief]"),_e=document.querySelector("[data-plotdirector-link-groups]"),Je=document.querySelector("[data-character-review-summary]"),ze=document.querySelector("[data-asset-review-summary]"),Qe=document.querySelector("[data-location-review-summary]"),Xe=document.querySelector("[data-character-chips]"),Ze=document.querySelector("[data-asset-chips]"),et=(document.querySelector("[data-location-chips]"),document.querySelector("[data-primary-location-select]")),tt=document.querySelector("[data-save-scene-links]"),nt=document.querySelector("[data-scene-links-status]"),rt=document.querySelector("[data-links-editing-scene]"),ot=document.querySelector("[data-chapter-create-link]"),at=document.querySelector("[data-chapter-create-link-chapter]"),ct=document.querySelector("[data-create-plotdirector-chapter]"),it=document.querySelector("[data-link-existing-chapter]"),st=document.querySelector("[data-chapter-create-link-status]"),dt=document.querySelector("[data-scene-create-link]"),lt=document.querySelector("[data-create-link-chapter]"),ut=document.querySelector("[data-create-link-scene]"),pt=document.querySelector("[data-create-plotdirector-scene]"),mt=document.querySelector("[data-link-existing-scene]"),ht=document.querySelector("[data-create-link-status]"),gt=document.querySelector("[data-link-existing-dialog]"),wt=document.querySelector("[data-link-scene-search]"),yt=document.querySelector("[data-link-scene-options]"),ft=document.querySelector("[data-link-selected-scene]"),It=document.querySelector("[data-link-dialog-cancel]"),bt=document.querySelector("[data-link-dialog-status]"),St=document.querySelector("[data-create-scene-dialog]"),Ct=document.querySelector("[data-create-dialog-scene]"),kt=document.querySelector("[data-create-dialog-chapter]"),vt=document.querySelector("[data-create-dialog-confirm]"),xt=document.querySelector("[data-create-dialog-cancel]"),Dt=document.querySelector("[data-link-existing-chapter-dialog]"),Pt=document.querySelector("[data-link-chapter-search]"),Et=document.querySelector("[data-link-chapter-options]"),Nt=document.querySelector("[data-link-selected-chapter]"),Lt=document.querySelector("[data-link-chapter-dialog-cancel]"),qt=document.querySelector("[data-link-chapter-dialog-status]"),At=document.querySelector("[data-create-chapter-dialog]"),$t=document.querySelector("[data-create-chapter-dialog-chapter]"),Tt=document.querySelector("[data-create-chapter-dialog-book]"),Wt=document.querySelector("[data-create-chapter-dialog-confirm]"),jt=document.querySelector("[data-create-chapter-dialog-cancel]"),Mt=document.querySelector("[data-apply-structure-sync-dialog]"),Ut=document.querySelector("[data-apply-structure-sync-summary]"),Rt=document.querySelector("[data-apply-structure-sync-confirm]"),Ot=document.querySelector("[data-apply-structure-sync-cancel]"),Bt=document.querySelector("[data-resolve-project-id]"),Ht=document.querySelector("[data-resolve-project-title]"),Gt=document.querySelector("[data-resolve-book-id]"),Ft=document.querySelector("[data-resolve-book-title]"),Vt=document.querySelector("[data-resolve-detected-chapter]"),Kt=document.querySelector("[data-resolve-detected-scene]"),Yt=document.querySelector("[data-resolve-request-chapter]"),_t=document.querySelector("[data-resolve-request-scene]"),Jt=document.querySelector("[data-resolve-result]"),zt=document.querySelector("[data-resolve-chapter-id]"),Qt=document.querySelector("[data-resolve-scene-id]"),Xt=document.querySelector("[data-run-diagnostics]"),Zt=document.querySelector("[data-diagnostic-host]"),en=document.querySelector("[data-diagnostic-platform]"),tn=document.querySelector("[data-diagnostic-ready]"),nn=document.querySelector("[data-diagnostic-word-api]"),rn=document.querySelector("[data-diagnostic-last-scan]"),on=document.querySelector("[data-diagnostic-last-error]"),an=document.querySelector("[data-diagnostic-anchor-type]"),cn=document.querySelector("[data-diagnostic-stored-scene-id]"),sn=document.querySelector("[data-diagnostic-stored-chapter-id]"),dn=document.querySelector("[data-diagnostic-resolution-method]"),ln=document.querySelector("[data-diagnostic-paragraphs]"),un=document.querySelector("[data-diagnostic-heading1]"),pn=document.querySelector("[data-diagnostic-heading2]"),mn="true"===a?.dataset.authenticated,hn=Number.parseInt(a?.dataset.userId||"",10),gn=String(a?.dataset.companionVersion||"20C").trim();let wn=[],yn=[],fn=!1,In=!1,bn="Unknown",Sn="Unknown",Cn="",kn="",vn=null,xn=null,Dn=null,Pn=null,En=null,Nn=null,Ln="",qn="Title Match",An=!1,$n=[],Tn=null,Wn=null,jn=[],Mn=null,Un=null,Rn=null,On=null,Bn=null,Hn=null,Gn=null,Fn=null,Vn=null,Kn=null,Yn=[],_n=null,Jn=null,zn=!1,Qn=!1,Xn=0,Zn=!1,er=!1,tr=!1,nr=null,rr="Manual",or=!1,ar=null,cr=!1,ir=0,sr=!1,dr=0,lr=null;const ur=1200,pr=131072;let mr=!1,hr=!1,gr=null,wr=!1,yr=!1,fr=null,Ir=null,br=null,Sr=!1,Cr=!1,kr=null,vr="",xr=[],Dr=null,Pr="",Er=null,Nr="",Lr=[],qr=null,Ar="",$r=null,Tr="",Wr=[],jr=null,Mr="",Ur="",Rr="",Or="",Br=0,Hr=null,Gr=null,Fr={characters:[],assets:[],locations:[],primaryLocationId:null},Vr={chapterCount:0,sceneCount:0,totalCount:0,available:!1,message:"Not inspected"};const Kr="PD-CHAPTER-",Yr="PD-SCENE-",_r=e=>{const t=String(e?.tag||"").trim().toUpperCase();return t.startsWith(Kr)?"chapter":t.startsWith(Yr)?"scene":""};window.PlotDirectorWordMarkers={classify:_r};const Jr=e=>{const t=Date.now();t-Br<1e3||(Br=t,console.debug(`[Word Companion Runtime] ${e}`))},zr=e=>{console.debug(`[Word Companion Timing] ${e}`)},Qr=e=>{F&&(F.textContent=e)},Xr=e=>"links"===e?"review":"structure"===e?"maintenance":e,Zr=(e,t=!0)=>{const r=Xr(e),a=o.has(r)&&i.some(e=>e.dataset.tabButton===r)?r:"scene";for(const e of i){const t=e.dataset.tabButton===a;e.classList.toggle("is-active",t),e.setAttribute("aria-selected",t?"true":"false")}for(const e of s){const t=e.dataset.tabPanel===a;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,a)},eo=()=>{const e=Xr((e=>{try{return window.localStorage.getItem(e)||""}catch{return""}})(n));Zr(o.has(e)?e:"scene",!1)},to=e=>{V&&(V.textContent=e),K&&(K.textContent=e)},no=e=>{X&&(X.textContent=e)},ro=e=>{Z&&(Z.textContent=e)},oo=e=>{ce&&(ce.textContent=e)},ao=e=>{he&&(he.textContent=e)},co=e=>{const t=t=>Object.prototype.hasOwnProperty.call(e,t);t("anchorType")&&Zo(an,Po(e.anchorType)),t("storedSceneId")&&Zo(cn,Po(e.storedSceneId)),t("storedChapterId")&&Zo(sn,Po(e.storedChapterId)),t("resolutionMethod")&&Zo(dn,Po(e.resolutionMethod))},io=()=>{const e=la(),t=Number.isInteger(En)&&En>0&&Pn===En,n=!Number.isInteger(Nn)||Nn<=0||Dn===Nn,r=t&&n;Zo(ge,r?"Attached to PlotDirector":"Not attached"),Zo(we,e?.bookId?String(e.bookId):"-"),Zo(ye,Number.isInteger(Nn)&&Nn>0?String(Nn):"-"),Zo(fe,Number.isInteger(En)&&En>0?String(En):"-"),Ie&&(uo(Ie,r&&!An),Ie.disabled=!En||r&&!An,Ie.textContent=Pn&&!r?"Reattach PlotDirector IDs":"Attach PlotDirector IDs"),co({anchorType:qn||"Title Match",storedSceneId:Pn,storedChapterId:Dn,resolutionMethod:Ln})},so=(e,t,n,r=null,o=null,a=null)=>{const c=e||"",i=t||"",s=Number.isInteger(n)?n:null,d=Number.isInteger(a)&&a>0?a:null,l=Number.isInteger(r)&&r>0?r:null,u=Number.isInteger(o)&&o>0?o:null,p=Cn===c&&kn===i&&vn===s&&xn===d&&Dn===l&&Pn===u;Cn=e||"",kn=t||"",vn=Number.isInteger(n)?n:null,xn=Number.isInteger(a)&&a>0?a:null,Dn=Number.isInteger(r)&&r>0?r:null,Pn=Number.isInteger(o)&&o>0?o:null,p||(ne&&(ne.textContent=e||"Not detected"),re&&(re.textContent=t||"Not detected"),oe&&(oe.textContent=Number.isInteger(n)?String(n):"-"),Zo(He,Number.isInteger(n)?String(n):"-"),io())},lo=()=>{gr&&(window.clearTimeout(gr),gr=null)},uo=(e,t)=>{e&&(e.hidden=t)},po=()=>{uo(be,!On)},mo=(e=Vr)=>{const t=Na();Zo(Ce,t?"Linked":"Not linked"),Zo(ke,e.available?String(e.chapterCount):"-"),Zo(ve,e.available?String(e.sceneCount):"-"),Zo(xe,e.available?String(e.chapterCount):"-"),Zo(De,e.available?String(e.sceneCount):"-"),Zo(Pe,e.available?String(e.chapterCount):"-"),Zo(Ee,e.available?String(e.sceneCount):"-"),Se&&(Se.disabled=!In||!fn)},ho=async()=>{if(!fn||!In||!window.Word||"function"!=typeof window.Word.run)return Vr={chapterCount:0,sceneCount:0,totalCount:0,available:!1,message:"Word document access is unavailable."},mo(),Vr;try{return Vr=await window.Word.run(async e=>{const t=e.document.contentControls;t.load("items/tag,title"),await e.sync();let n=0,r=0;for(const e of t.items||[]){const t=_r(e);"chapter"===t?n+=1:"scene"===t&&(r+=1)}return{chapterCount:n,sceneCount:r,totalCount:n+r,available:!0,message:"Marker inspection complete."}}),mo(Vr),Vr}catch(e){throw console.error("Unable to inspect PlotDirector markers.",e),Vr={chapterCount:0,sceneCount:0,totalCount:0,available:!1,message:`Unable to inspect markers: ${ta(e)}`},mo(),e}},go=e=>{Zo(Ve,e)},wo=e=>{Zo(ue,e)},yo=(e="Select a project and book to analyse manuscript structure.")=>{if(Rn=null,pe){pe.innerHTML="";const e=document.createElement("p");e.textContent="No preview generated.",pe.append(e)}wo(e),Io()},fo=(e=Rn)=>((e=Rn)=>cc.flatMap(t=>Array.isArray(e?.[t.key])?e[t.key]:[]))(e).filter(e=>"couldLink"===e.category||"wouldCreateChapters"===e.category||"wouldCreateScenes"===e.category),Io=()=>{le&&(le.disabled=tr||0===fo().length)},bo=()=>{de&&(de.disabled=tr||!da()||!la()),Io()},So=()=>{rt&&(rt.textContent=En?`Editing links for: ${Rr||kn||"Current scene"}`:"Link a PlotDirector scene first.")},Co=()=>{const e=or||!En,t=e||!Nn||wr;Be&&(Be.disabled=t),tt&&(tt.disabled=e),et&&(et.disabled=e);for(const t of[Xe,Ze])for(const n of t?[...t.querySelectorAll("input[type='checkbox']")]:[])n.disabled=e},ko=e=>{"Live"!==e&&"Manual"!==e||(rr=e),Zo(ae,e||rr||"Manual")},vo=(e,t="")=>{or=!!e,or&&(lo(),ei()),Zo(ae,or?"Stale":rr),Co(),t&&(oo(t),Ao(t))},xo=(e,t=null,n="")=>{En=Number.isInteger(e)&&e>0?e:null,Nn=Number.isInteger(t)&&t>0?t:null,Ln=n||"",En!==fr&&(Ir=null),En||(lo(),ei()),Co(),go(or?"Refresh Current Scene before syncing.":En?"Ready to sync.":"No resolved PlotDirector scene."),Ao(or?"Refresh Current Scene before saving.":En?"Ready to save.":"Link a PlotDirector scene first."),So(),io()},Do=e=>{ee&&(ee.disabled=e,ee.textContent=e?"Refreshing...":"Refresh Current Scene")},Po=e=>null==e||""===e?"-":String(e),Eo=e=>{if(!e)return"-";const t=e instanceof Date?e:new Date(e);if(Number.isNaN(t.getTime()))return"-";const n=new Date;return`Last synced: ${t.toDateString()===n.toDateString()?"Today":t.toLocaleDateString()} ${t.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}`},No=e=>{Bn=e||null;const t=Bn?.lastSyncUtc||Bn?.manuscriptDocument?.lastSyncUtc;Zo(Oe,Eo(t)),Zo(Fe,Eo(t)),sa()},Lo=()=>{Hn=null,Gn=null,Fn=null,dr+=1,lr=null,ti(),ni(),ri(),No(null)},qo=()=>{Gn=null,Fn=null},Ao=e=>{Zo(nt,e)},$o=e=>{Zo(ht,e)},To=e=>{Zo(st,e)},Wo=()=>!!la()&&!!Cn&&!Nn,jo=()=>!!la()&&!!kn&&Number.isInteger(Nn)&&Nn>0,Mo=()=>{uo(ot,!0),To(""),ct&&(ct.disabled=!0,ct.textContent="Create Chapter in PlotDirector"),it&&(it.disabled=!0,it.textContent="Link to Existing Chapter")},Uo=(e="")=>{Zo(at,Po(Cn)),uo(ot,!1),To(e);const t=Wo();ct&&(ct.disabled=!t,ct.textContent="Create Chapter in PlotDirector"),it&&(it.disabled=!t,it.textContent="Link to Existing Chapter")},Ro=()=>{uo(dt,!0),$o(""),pt&&(pt.disabled=!0,pt.textContent="Create Scene in PlotDirector"),mt&&(mt.disabled=!0,mt.textContent="Link to Existing Scene")},Oo=(e="")=>{Zo(lt,Po(Cn)),Zo(ut,Po(kn)),uo(dt,!1),$o(e);const t=jo();pt&&(pt.disabled=!t,pt.textContent="Create Scene in PlotDirector"),mt&&(mt.disabled=!t,mt.textContent="Link to Existing Scene")},Bo=e=>{ao(e),uo(Ae,!0),uo(Ke,!0),uo(_e,!1),Mo(),Ro(),Ln="",Rr="",Or="",qn=Pn?"SceneID Anchor":Dn?"ChapterID Anchor":"Title Match",An=!1,Fr={characters:[],assets:[],locations:[],primaryLocationId:null},Go(Xe,[],"character"),Go(Ze,[],"asset"),Fo([],null,!1),Ua(),xo(null),Zo(Ge,"-"),Zo($e,"-"),Zo(Te,"-"),Zo(We,"-"),Zo(je,"-"),Zo(Me,"-"),Zo(Re,"-"),uo(Ue,!0),io(),So()},Ho=(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,Go=(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(Ho(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)}},Fo=(e,t,n=!1)=>{if(!et)return;et.innerHTML="";const r=document.createElement("option");r.value="",r.textContent="None",et.append(r);const o=Number.parseInt(t||"",10);for(const t of Array.isArray(e)?e:[]){const e=Number.parseInt(Ho(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,et.append(n)}et.disabled=!n},Vo=e=>String(e||"").trim().replace(/\s+/g," "),Ko=(e,t)=>{const n=Vo(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 Vo(n.replace(r,""))||n},Yo=e=>{const t=t=>Object.prototype.hasOwnProperty.call(e,t);t("projectId")&&Zo(Bt,Po(e.projectId)),t("projectTitle")&&Zo(Ht,Po(e.projectTitle)),t("bookId")&&Zo(Gt,Po(e.bookId)),t("bookTitle")&&Zo(Ft,Po(e.bookTitle)),t("detectedChapter")&&Zo(Vt,Po(e.detectedChapter)),t("detectedScene")&&Zo(Kt,Po(e.detectedScene)),t("requestChapter")&&Zo(Yt,Po(e.requestChapter)),t("requestScene")&&Zo(_t,Po(e.requestScene)),t("result")&&Zo(Jt,Po(e.result)),t("chapterId")&&Zo(zt,Po(e.chapterId)),t("sceneId")&&Zo(Qt,Po(e.sceneId))},_o=async e=>{if(Fn===e&&Array.isArray(Gn?.chapters))return Gn.chapters;const t=await Ac(`/api/word-companion/books/${e}/structure`);return Fn=e,Gn=t||null,Array.isArray(t?.chapters)?t.chapters:[]},Jo=async e=>{const t=await Ac(`/api/word-companion/books/${e}/chapters`);return Array.isArray(t?.chapters)?t.chapters:[]},zo=e=>{if(Number.isInteger(Nn)&&Nn>0){const t=e.find(e=>e.chapterId===Nn);if(t)return t}const t=Ko(Cn,"chapter").toLocaleLowerCase();return t&&e.find(e=>Ko(e.title,"chapter").toLocaleLowerCase()===t)||null},Qo=async()=>{const e=la();return e?zo(await _o(e.bookId)):null},Xo=async(e,t,n,r,o)=>{const a=await Ac(`/api/word-companion/scenes/${t}/companion`);try{a.revisionStatus=await(async(e,t)=>{const n=await Ac(`/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;qn=o||"Title Match",An=!1,vo(!1),ao("Linked to PlotDirector"),oo(""),Mo(),Ro(),xo(t,n,r),c=a,Rr=c?.sceneTitle||kn||"",Or=c?.chapterTitle||Cn||"",Zo($e,Po(c?.sceneTitle)),Zo(Te,Po(c?.revisionStatus||c?.revisionStatusName||"Not provided")),Zo(We,Po(c?.estimatedWords)),Zo(je,Po(c?.actualWords)),Zo(Ge,Po(c?.actualWords)),Zo(Me,c?.blocked?"Blocked":"Not blocked"),c?.blockedReason?(Zo(Re,c.blockedReason),uo(Ue,!1)):(Zo(Re,"-"),uo(Ue,!0)),Ye&&(Ye.textContent=c?.writingBrief||"No writing brief has been added for this scene."),Fr={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},Go(Xe,Fr.characters,"character",!!En&&!or),Go(Ze,Fr.assets,"asset",!!En&&!or),Fo(Fr.locations,Fr.primaryLocationId,!!En&&!or),Ua(),So(),Ao(or?"Refresh Current Scene before saving.":En?"Ready to save.":"No resolved PlotDirector scene."),uo(Ae,!1),uo(Ke,!1),uo(_e,!1),Wc(t,n),Zc(),li()},Zo=(e,t)=>{if(e){const n=null==t?"":String(t);e.textContent!==n&&(e.textContent=n)}},ea=e=>{const t=t=>Object.prototype.hasOwnProperty.call(e,t);t("host")&&Zo(Zt,e.host),t("platform")&&Zo(en,e.platform),t("ready")&&Zo(tn,e.ready),t("wordApi")&&Zo(nn,e.wordApi),t("lastScan")&&Zo(rn,e.lastScan),t("lastError")&&Zo(on,e.lastError),t("paragraphs")&&Zo(ln,e.paragraphs),t("heading1")&&Zo(un,e.heading1),t("heading2")&&Zo(pn,e.heading2)},ta=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)},na=async()=>{if(!window.Office||"function"!=typeof window.Office.onReady)return fn=!1,In=!1,bn="Unavailable",Sn="Unavailable",ea({host:bn,platform:Sn,ready:"No",wordApi:"No"}),null;const e=await window.Office.onReady();return fn=!0,bn=e?.host||"Unknown",Sn=e?.platform||"Unknown",In=!!window.Word&&!!window.Office.HostType&&e?.host===window.Office.HostType.Word,ea({host:bn,platform:Sn,ready:"Yes",wordApi:In?"Yes":"No"}),e},ra=e=>{try{const t=window.localStorage.getItem(e),n=Number.parseInt(t||"",10);return Number.isInteger(n)&&n>0?n:null}catch{return null}},oa=(e,t)=>{try{t?window.localStorage.setItem(e,String(t)):window.localStorage.removeItem(e)}catch{}},aa=(e,t)=>{if(!e)return;e.innerHTML="";const n=document.createElement("option");n.value="",n.textContent=t,e.append(n),e.disabled=!0},ca=(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},ia=e=>{const t=String(e?.displayTitle||"").trim();if(t)return t;const n=String(e?.title||"").trim(),r=String(e?.subtitle||"").trim();return r?`${n}: ${r}`:n},sa=()=>{const e=!!On;uo(d,!e),uo(Q,e),e&&(Zo(l,Bn?.projectTitle||da()?.title||"Project"),Zo(u,Bn?.bookTitle||ia(la())||"Book")),mo()},da=()=>{const e=Number.parseInt(J?.value||"",10);return wn.find(t=>t.projectId===e)||null},la=()=>{const e=Number.parseInt(z?.value||"",10);return yn.find(t=>t.bookId===e)||null},ua=()=>{const e=Number.parseInt(w?.value||"",10);return wn.find(t=>t.projectId===e)||null},pa=()=>{const e=Number.parseInt(y?.value||"",10);return yn.find(t=>t.bookId===e)||null},ma=()=>{const t=On?.projectId||ua()?.projectId||da()?.projectId||ra(e);return Number.isInteger(t)&&t>0?t:null},ha=()=>{const e=On?.bookId||pa()?.bookId||la()?.bookId||ra(t);return Number.isInteger(e)&&e>0?e:null},ga=()=>({projectId:ma(),bookId:ha()}),wa=e=>{const t="context"===e?"Context":"intent"===e?"Intent":"Workspace",n=(e=>{const t=ga(),n=new URL("workspace"===e?"/Writer":`/Writing/${e}`,window.location.origin),r=Number.isInteger(Nn)&&Nn>0?Nn:Dn,o=Number.isInteger(En)&&En>0?En:Pn,a=ja();return t.projectId&&n.searchParams.set("projectId",t.projectId),t.bookId&&"workspace"!==e&&n.searchParams.set("bookId",t.bookId),r&&"workspace"!==e&&n.searchParams.set("chapterId",r),o&&"workspace"!==e&&n.searchParams.set("sceneId",o),a&&"workspace"!==e&&n.searchParams.set("documentGuid",a),`${n.pathname}${n.search}`})(e);console.info("[Word Companion] Opening writing screen.",{target:e,url:n,projectId:ma(),bookId:ha(),chapterId:Nn||Dn||null,sceneId:En||Pn||null,documentGuidPresent:!!ja()});const r=window.open(n,(e=>{const t=ga();return`PlotDirector${e}_${t.bookId?`Book_${t.bookId}`:t.projectId?`Project_${t.projectId}`:"General"}`})(t));r?r.focus():oo("Your browser blocked the writing workspace window. Use the browser pop-up prompt to allow PlotDirector windows.")},ya=()=>{const e=String(window.Office?.context?.document?.url||"").trim();if(!e)return"";const t=e.split(/[\\/]/).filter(Boolean).pop()||"";try{return decodeURIComponent(t)}catch{return t}},fa=()=>({userID:Number.isInteger(hn)&&hn>0?hn:null,companionVersion:gn,machineName:"",documentOpen:!!In,currentDocumentName:ya(),linkedProjectID:ma(),linkedBookID:ha()}),Ia=()=>{(async()=>{Hr&&Hr.state===signalR.HubConnectionState.Connected&&(console.debug("[Word Companion] Sending presence heartbeat.",fa()),await Hr.invoke("CompanionHeartbeat",fa()))})().catch(e=>{console.debug("Word Companion heartbeat unavailable.",e)})},ba=async()=>{mn&&window.signalR&&!Hr&&(Hr=(new signalR.HubConnectionBuilder).withUrl("/hubs/word-companion-follow").withAutomaticReconnect().build(),Hr.onreconnected(Ia),Hr.on("ScanCurrentDocument",e=>{ec(e)}),Hr.on("UpdateOnboardingBuildMarkers",e=>{tc(e)}),Hr.onclose(()=>{Gr&&(window.clearInterval(Gr),Gr=null)}),await Hr.start(),console.info("[Word Companion] Registering companion presence.",fa()),await Hr.invoke("RegisterCompanion",fa()),Gr=window.setInterval(Ia,25e3))};window.addEventListener("beforeunload",()=>{Gr&&(window.clearInterval(Gr),Gr=null),Hr&&Hr.stop().catch(()=>{})});const Sa=e=>Zo(k,e),Ca=()=>{const e=ua(),t=pa(),n=Qn&&Date.now()-Xn>=750;S&&(S.disabled=!e||!t||Zn),b&&(b.disabled=!e||!t||Zn),I&&(I.disabled=!e||!String(f?.value||"").trim()||Zn),$&&($.disabled=!Vn?.canImport||!Kn||Zn),N&&(N.disabled=!n||er||0===Da().length)},ka=e=>{uo(g,!e),uo(c,e),po(),sa();for(const t of s)uo(t,!!e||"scene"!==t.dataset.tabPanel&&!t.classList.contains("is-active"));e||eo()},va=()=>{if(!w)return;if(0===wn.length)return void aa(w,"No projects available.");ca(w,"Choose a project",wn,"projectId","title");const e=Number.parseInt(J?.value||"",10);Number.isInteger(e)&&e>0&&(w.value=String(e))},xa=(e="Select a Project and Book to begin.")=>{Vn=null,Kn=null,Yn=[],zn=!1,Qn=!1,Xn=0,uo(v,!0),uo(A,!0),uo(x,!0),uo(E,!0),v&&(v.innerHTML=""),P&&(P.innerHTML=""),Zo(D,""),Sa(e),Ca()},Da=()=>P?[...P.querySelectorAll("input[type='checkbox']:checked")].map(e=>String(e.value||"").trim()).filter(Boolean):[],Pa=e=>{if(Yn=Array.isArray(e)?e:[],x&&P){if(P.innerHTML="",uo(x,!1),uo(E,!zn||0===Yn.length),uo(N,!1),uo(L,!1),uo(q,!0),0===Yn.length)return Zo(D,"No likely major characters found."),void Ca();Zo(D,`${Yn.length} likely major characters found.`);for(const e of Yn){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",Ca);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),P.append(t)}Ca()}},Ea=()=>{const e=window.Office?.context?.document?.settings;if(!e)return null;const t=String(e.get(r.documentGuid)||"").trim(),n=Number.parseInt(e.get(r.bookId)||"",10),o=Number.parseInt(e.get(r.projectId)||"",10),a=Number.parseInt(e.get(r.bindingVersion)||"",10);return!t||!Number.isInteger(n)||n<=0||!Number.isInteger(o)||o<=0?null:{documentGuid:t,bookId:n,projectId:o,bindingVersion:Number.isInteger(a)&&a>0?a:1}},Na=()=>{const e=On||Ea();if(e)return e;const t=Bn?.manuscriptDocument?.documentGuid||"",n=Number.parseInt(Bn?.bookId||"",10),r=Number.parseInt(Bn?.projectId||"",10);return t&&Number.isInteger(n)&&n>0&&Number.isInteger(r)&&r>0?{documentGuid:t,bookId:n,projectId:r,bindingVersion:Number.parseInt(Bn?.manuscriptDocument?.bindingVersion||"",10)||1}:null},La=e=>new Promise((t,n)=>{const o=window.Office?.context?.document?.settings;o?(o.set(r.documentGuid,e.documentGuid),o.set(r.bookId,String(e.bookId)),o.set(r.projectId,String(e.projectId)),o.set(r.bindingVersion,String(e.bindingVersion||1)),o.saveAsync(e=>{e.status===window.Office.AsyncResultStatus.Succeeded?t():n(e.error||new Error("Unable to save Word document metadata."))})):n(new Error("Word document settings are unavailable."))}),qa=()=>new Promise((e,t)=>{const n=window.Office?.context?.document?.settings;if(n){for(const e of Object.values(r))"function"==typeof n.remove?n.remove(e):n.set(e,"");n.saveAsync(n=>{n.status===window.Office.AsyncResultStatus.Succeeded?e():t(n.error||new Error("Unable to remove Word document metadata."))})}else t(new Error("Word document settings are unavailable."))}),Aa=()=>{const e=window.Office?.context?.diagnostics||{},t=window.Office?.context?.document;return{host:e.host||window.Office?.context?.host||bn||"",platform:e.platform||window.Office?.context?.platform||Sn||"",version:e.version||"",documentUrl:t?.url||"",documentGuid:ja()}},$a=async(e,t,n,r={})=>{if(Number.isInteger(e)&&e>0&&Hr)try{return await Hr.invoke("CompleteOnboardingBuildMarkerSync",e,{markerStatus:t,message:n,...r}),!0}catch(e){console.warn("Unable to report onboarding marker sync completion.",e)}return!1},Ta=()=>{Jn=null,uo(p,!0),h&&(h.disabled=!0,h.textContent="I've saved it")},Wa=()=>On?.documentGuid?On.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)),ja=()=>On?.documentGuid||Ea()?.documentGuid||"",Ma=()=>{const e=da(),t=la();Y&&(Y.textContent=e?.title||"(Not connected)"),_&&(_.textContent=t?ia(t):"(Not connected)"),ie&&(ie.textContent=t?"":"Select a PlotDirector book before refreshing."),bo(),sa()},Ua=()=>{const e=Array.isArray(Fr.characters)?Fr.characters.length:0,t=Array.isArray(Fr.assets)?Fr.assets.length:0,n=Array.isArray(Fr.locations)?Fr.locations.length:0;Zo(Je,`Characters (${e})`),Zo(ze,`Assets (${t})`),Zo(Qe,`Locations (${n})`)},Ra=e=>String(e?.styleBuiltIn||e?.style||"").replace(/\s+/g,"").toLowerCase(),Oa=(e,t)=>{const n=Ra(e);return n===`heading${t}`||n.endsWith(`.heading${t}`)||n.includes(`heading${t}`)},Ba=e=>String(e||"").trim().split(/\s+/).filter(Boolean).length,Ha=(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},Ga=e=>{try{return Array.isArray(e?.contentControls?.items)?e.contentControls.items:[]}catch(e){return console.warn("Word paragraph content controls were not available.",e),[]}},Fa=(e,t)=>{const n=Ga(e);for(const e of n){const n=Ha(e.tag,t);if(n)return n}return null},Va=(e,t)=>{const n=[],r=e.some(e=>Fa(e,"PD-SCENE"));let o=0,a=0,c=null,i=null;e.forEach((e,t)=>{const s=String(e.text||"").trim(),d=Fa(e,"PD-CHAPTER"),l=Fa(e,"PD-SCENE");if(s||d||l){if(Oa(e,1))return o+=1,c={index:n.length+1,paragraphIndex:t,title:s,anchorId:d,scenes:[]},n.push(c),i=null,void(l&&(a+=1,i={index:c.scenes.length+1,paragraphIndex:t,title:`Scene ${c.scenes.length+1}`,anchorId:l,wordCount:0},c.scenes.push(i)));if(Oa(e,2)||l){if(a+=1,!c)return;if(i={index:c.scenes.length+1,paragraphIndex:t,title:Oa(e,2)?s:`Scene ${c.scenes.length+1}`,anchorId:l,wordCount:0},c.scenes.push(i),Oa(e,2))return}i&&s&&(!r||i.anchorId)&&(i.wordCount+=Ba(s))}});const s=t.find(e=>String(e.text||"").trim()),d=s?e.findIndex(e=>{return t=e,n=s,String(t?.text||"").trim()===String(n?.text||"").trim()&&Ra(t)===Ra(n);var t,n}):-1,l=d>=0&&n.filter(e=>e.paragraphIndex<=d).at(-1)||null,u=l&&d>=0&&l.scenes.filter(e=>e.paragraphIndex<=d).at(-1)||null;return{chapters:n,currentChapter:l,currentScene:u,paragraphCount:e.length,heading1Count:o,heading2Count:a}},Ka=new Set(["***","###"]),Ya=(e,t)=>{const n=String(e?.text||"").trim();return{index:t,text:n,styleBuiltIn:e?.styleBuiltIn||"",style:e?.style||"",wordCount:Ba(n),chapterAnchorId:Fa(e,"PD-CHAPTER"),sceneAnchorId:Fa(e,"PD-SCENE")}},_a=(e,t)=>{e&&(e.endParagraphIndex=t)},Ja=(e,t)=>{e&&(e.endParagraphIndex=t,_a(e.scenes.at(-1),t))},za=(e,t)=>{const n=[],r=[];let o=null,a=0,c=0,i=!1;const s=(e,t,r=!1)=>(o={temporaryChapterKey:`chapter-${n.length+1}`,chapterNumber:n.length+1,title:t,wordCount:0,chapterTextParagraphs:[],chapterText:"",sourceParagraphs:[],startPosition:e?.index??null,existingChapterID:r?null:Fa(e,"PD-CHAPTER")},n.push(o),o),d=(e,t,n={})=>{o&&e&&Number.isInteger(e.index)&&(o.sourceParagraphs=o.sourceParagraphs||[],o.sourceParagraphs.push({wordParagraphIndex:e.index,text:String(t||""),isBlank:!!n.isBlank,isChapterHeading:!!n.isChapterHeading,isSceneHeading:!!n.isSceneHeading,isSceneSeparator:!!n.isSceneSeparator,includeInSourceText:!1!==n.includeInSourceText}))},l=e=>String(e||"").replace(/[\r\n\v\f\u2028\u2029]+/g," ").replace(/\s+/g," ").trim();if(e.forEach((e,t)=>{e.index=t;const n=l(e.text);if(!n)return void(o&&d(e,"",{isBlank:!0,includeInSourceText:!0}));const u=Ba(n);if(Oa(e,1)){if(!i&&(e=>{const t=Ko(e||"","").toLocaleLowerCase();return["title page","copyright","dedication","contents","table of contents","acknowledgements","acknowledgments","about the author"].includes(t)})(n))return;return i=!0,r.push(n),c+=1,s(e,n),void d(e,n,{isChapterHeading:!0,includeInSourceText:!1})}if(!o){if(!i)return;s(e,"Opening pages",!0)}r.push(n),Oa(e,2)?d(e,n,{isSceneHeading:!0,includeInSourceText:!1}):Ka.has(n)?d(e,n,{isSceneSeparator:!0,includeInSourceText:!1}):(d(e,n,{includeInSourceText:!0}),a+=u,((e,t,n)=>{if(!o||n<=0)return;const r=l(t);r&&(o.wordCount+=Ba(r),o.chapterTextParagraphs.push(r),o.paragraphMap=o.paragraphMap||[],o.paragraphMap.push({structuralParagraphOrdinal:o.chapterTextParagraphs.length,wordParagraphIndex:Number.isInteger(e?.index)?e.index:-1,text:r}))})(e,n,u))}),0===a)throw new Error("The document appears to be empty. Add manuscript text, then try again.");if(0===c)throw new Error("No chapters were detected. Make sure your chapter headings use Heading 1, or add clear chapter headings.");return n.forEach(e=>{e.chapterText=Array.isArray(e.chapterTextParagraphs)?e.chapterTextParagraphs.join("\n\n"):"",delete e.chapterTextParagraphs}),{previewID:"00000000-0000-0000-0000-000000000000",userID:Qa(t,"userID","UserID","userId"),onboardingID:Qa(t,"onboardingID","OnboardingID","onboardingId"),projectID:Qa(t,"projectID","ProjectID","projectId"),bookID:Qa(t,"bookID","BookID","bookId"),source:"WordCompanion",documentTitle:ya()||"Word manuscript",companionDocumentIdentifier:ja(),totalWordCount:a,chapterCount:n.length,sceneCount:0,characterCandidateCount:0,createdUtc:(new Date).toISOString(),chapters:n,scenes:[],characterCandidates:[]}},Qa=(e,...t)=>{for(const n of t)if(null!=e?.[n])return e[n];return null},Xa=async(e,t,n,r={})=>{Hr&&Hr.state===signalR.HubConnectionState.Connected&&await Hr.invoke("ReportOnboardingScanProgress",{userID:Qa(e,"userID","UserID","userId"),onboardingID:Qa(e,"onboardingID","OnboardingID","onboardingId"),message:t,percentComplete:n,chapterCount:r.chapterCount||0,sceneCount:r.sceneCount||0,characterCandidateCount:r.characterCandidateCount||0,totalWordCount:r.totalWordCount||0})},Za=async(e,t)=>{Hr&&Hr.state===signalR.HubConnectionState.Connected&&await Hr.invoke("FailOnboardingScan",{userID:Qa(e,"userID","UserID","userId"),onboardingID:Qa(e,"onboardingID","OnboardingID","onboardingId"),message:t})},ec=async e=>{if(In&&window.Word)try{const t=Date.now();console.info("[Word Companion Scan] Starting onboarding document scan.",{scanID:Qa(e,"scanID","ScanID","scanId"),onboardingID:Qa(e,"onboardingID","OnboardingID","onboardingId")}),await Xa(e,"Preparing document scan",5);const n=Date.now(),r=await window.Word.run(async t=>{const n=t.document.body.paragraphs;n.load("items/text,items/style,items/styleBuiltIn"),await t.sync(),await Xa(e,"Detecting chapters",20);for(const e of n.items)(Oa(e,1)||Oa(e,2))&&e.contentControls.load("items/tag,title");return await t.sync(),n.items});console.info("[Word Companion Scan] Word extraction completed.",{scanID:Qa(e,"scanID","ScanID","scanId"),paragraphCount:r.length,durationMs:Date.now()-n});const o=Date.now(),a=za(r,e);console.info("[Word Companion Scan] Preview built.",{scanID:Qa(e,"scanID","ScanID","scanId"),chapterCount:a.chapterCount,totalWordCount:a.totalWordCount,durationMs:Date.now()-o}),await Xa(e,"Preparing chapter review",85,a),await Xa(e,"Preparing preview",95,a),_n=a,await(async(e,t)=>{if(!Hr||Hr.state!==signalR.HubConnectionState.Connected)throw new Error("The Word Companion connection is not available.");const n=JSON.stringify(t),r=Math.max(1,Math.ceil(n.length/pr)),o=Qa(e,"scanID","ScanID","scanId");if(!o)throw new Error("The scan request did not include a scan ID.");console.info("[Word Companion Scan] Uploading chunked scan result.",{scanID:o,totalChunks:r,payloadCharacters:n.length,payloadBytes:new Blob([n]).size});for(let a=0;a{const t=Number.parseInt(e?.buildID||e?.BuildID||"0",10),n=new Map((e?.chapterMappings||e?.ChapterMappings||[]).map(e=>[e.temporaryChapterKey||e.TemporaryChapterKey,e.chapterID||e.ChapterID])),r=new Map((e?.sceneMappings||e?.SceneMappings||[]).map(e=>[e.temporarySceneKey||e.TemporarySceneKey,e.sceneID||e.SceneID])),o=e?.chapterMarkerInstructions||e?.ChapterMarkerInstructions||[],a=e?.sceneMarkerInstructions||e?.SceneMarkerInstructions||[];if(!_n&&0===o.length&&0===a.length)throw new Error("Word marker instructions are unavailable.");try{if(!In||!window.Word||"function"!=typeof window.Word.run)throw new Error("Word document access is unavailable.");let c=!1;if(await window.Word.run(async e=>{const t=e.document.body.paragraphs;if(t.load("items/text,items/style,items/styleBuiltIn"),await e.sync(),o.length>0||a.length>0){for(const e of o){const n=Number.parseInt(e.wordParagraphIndex??e.WordParagraphIndex,10),r=e.markerTag||e.MarkerTag,o=e.markerTitle||e.MarkerTitle||"PlotDirector Chapter",a=e.markerPrefix||e.MarkerPrefix||"PD-CHAPTER";r&&Number.isInteger(n)&&t.items[n]&&(c=Oc(t.items[n],o,r,a)||c)}for(const e of a){const n=Number.parseInt(e.wordParagraphIndex??e.WordParagraphIndex,10),r=e.markerTag||e.MarkerTag,o=e.markerTitle||e.MarkerTitle||"PlotDirector Scene",a=e.markerPrefix||e.MarkerPrefix||"PD-SCENE";r&&Number.isInteger(n)&&t.items[n]&&(c=Oc(t.items[n],o,r,a)||c)}}else{for(const e of _n.chapters||[]){const r=n.get(e.temporaryChapterKey),o=Number.parseInt(e.startPosition,10);r&&Number.isInteger(o)&&t.items[o]&&(c=Oc(t.items[o],"PlotDirector Chapter",`PD-CHAPTER-${r}`,"PD-CHAPTER")||c)}for(const e of _n.scenes||[]){const n=r.get(e.temporarySceneKey),o=Number.parseInt(e.startPosition,10);n&&Number.isInteger(o)&&t.items[o]&&(c=Oc(t.items[o],"PlotDirector Scene",`PD-SCENE-${n}`,"PD-SCENE")||c)}}await e.sync()}),await ho().catch(()=>null),!c){Ta();const e={markersChanged:!1,saveState:"NotRequired",saveApi:"none",...Aa()};return console.info("Onboarding marker sync completed without Word document changes.",e),await $a(t,"SaveNotRequired","Scene markers already existed. No Word save was required.",e),oo("Scene markers already existed. Word may now be closed."),void ea({lastError:"-"})}const i={previewID:e?.previewID||e?.PreviewID||null,markersChanged:!0,saveState:"UserSaveRequired",saveApi:"manual-companion",...Aa()},s="Scene markers have been added. Save this document in Word, then click I've saved it in PlotDirector or the Companion.";console.info("Onboarding marker sync requires manual Word save confirmation.",i),((e,t,n={})=>{Jn={buildId:e,diagnostics:n},uo(p,!1),Zo(m,t),h&&(h.disabled=!1,h.textContent="I've saved it"),oo(t)})(t,s,i),ea({lastError:"Waiting for manual Word save confirmation."}),await(async(e,t,n={})=>{if(Number.isInteger(e)&&e>0&&Hr)try{await Hr.invoke("RequireOnboardingBuildManualSave",e,t,n)}catch(e){console.warn("Unable to report onboarding manual save requirement.",e)}})(t,s,i)}catch(e){console.error("Unable to update onboarding Word markers.",e),oo("Unable to update PlotDirector scene markers."),ea({lastError:ta(e)}),await(async(e,t,n={})=>{if(Number.isInteger(e)&&e>0&&Hr)try{await Hr.invoke("FailOnboardingBuildMarkerSync",e,t,n)}catch(e){console.warn("Unable to report onboarding marker sync failure.",e)}})(t,ta(e),{markersChanged:null,saveState:"Failed",...Aa(),errorMessage:ta(e)})}},nc=e=>{const t=ta(e);return/No chapters were detected/i.test(t)?"No chapters were detected. Make sure your chapter headings use Heading 1, or add clear chapter headings.":/empty/i.test(t)?"The document appears to be empty. Add manuscript text, then try again.":/network|disconnect|connection/i.test(t)?"The Word Companion disconnected before the scan finished. Reopen Word and try again.":`The scan could not finish: ${t}`},rc=(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()&&Ra(e)===Ra(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?.startParagraphIndex!==Hn.currentChapter?.startParagraphIndex||n?.startParagraphIndex!==Hn.currentScene?.startParagraphIndex||t?.anchorId!==Hn.currentChapter?.anchorId||n?.anchorId!==Hn.currentScene?.anchorId;return Hn.currentParagraphIndex=e,Hn.currentChapter=t,Hn.currentScene=n,!!r&&(so(t?.title,n?.title,n?.wordCount,t?.anchorId,n?.anchorId,t?.index),r)},ac=e=>{if(!se)return;if(se.innerHTML="",0===e.chapters.length){const e=document.createElement("p");return e.textContent="No chapters detected. Use Heading 1 for chapter titles.",void se.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.",se.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)}se.append(e)}},cc=[{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"}],ic={alreadyLinked:"Already Linked",couldLink:"Could Link",wouldCreateChapter:"Would Create Chapter",wouldCreateScene:"Would Create Scene",manualReview:"Manual Review Required"},sc={alreadyLinked:"✓",couldLink:"~",wouldCreateChapter:"+",wouldCreateScene:"+",manualReview:"?"},dc=(e,t)=>Ko(e,t).toLocaleLowerCase(),lc=({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:""}),uc=(e,t)=>{Array.isArray(e[t.category])&&e[t.category].push(t)},pc=e=>Array.isArray(e?.scenes)?e.scenes:[],mc=(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=lc({category:"alreadyLinked",action:"alreadyLinked",type:"Chapter",wordTitle:e.title,match:`Chapter ${o.chapterId}: ${o.title}`,anchorStatus:r,pdChapter:o,wordChapter:e});return uc(n,t),t}const a=lc({category:"manualReview",action:"manualReview",type:"Chapter",wordTitle:e.title,anchorStatus:`${r} not found`,matches:[],pdChapter:null,wordChapter:e});return uc(n,a),a}const o=t.filter(t=>dc(t.title,"chapter")===dc(e.title,"chapter"));if(1===o.length){const t=lc({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 uc(n,t),t}if(o.length>1){const t=lc({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 uc(n,t),t}const a=lc({category:"wouldCreateChapters",action:"wouldCreateChapter",type:"Chapter",wordTitle:e.title,anchorStatus:r,pdChapter:null,wordChapter:e});return uc(n,a),a},hc=(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=pc(n).find(e=>e.sceneId===t);if(e)return{chapter:n,scene:e}}return null})(n,e.anchorId);return a?void uc(r,lc({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 uc(r,lc({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 uc(r,lc({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 uc(r,lc({category:"wouldCreateScenes",action:"wouldCreateScene",type:"Scene",wordTitle:e.title,anchorStatus:o,wordChapter:t?.wordChapter,wordScene:e,parentItem:t}));const a=pc(t.pdChapter).filter(t=>dc(t.title,"scene")===dc(e.title,"scene"));1!==a.length?a.length>1?uc(r,lc({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})):uc(r,lc({category:"wouldCreateScenes",action:"wouldCreateScene",type:"Scene",wordTitle:e.title,anchorStatus:o,pdChapter:t.pdChapter,wordChapter:t.wordChapter,wordScene:e,parentItem:t})):uc(r,lc({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}))},gc=e=>{const t=document.createElement("article");t.className="word-companion-preview-item";const n=document.createElement("strong");n.textContent=`${sc[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: ${ic[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},wc=e=>{if(pe){pe.innerHTML="";for(const t of cc){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(gc(e));pe.append(n)}Io()}},yc=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();try{for(const e of t.items)e.contentControls.load("items/tag,title");await e.sync()}catch(e){console.warn("Unable to load Word content controls. Continuing without PlotDirector anchors.",e)}const r=Va(t.items,n.items);return r.bodyParagraphs=t.items,r},fc=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();try{for(const e of n.items)e.contentControls.load("items/tag,title");await e.sync()}catch(e){console.warn("Unable to load Word runtime content controls. Continuing without PlotDirector anchors.",e)}const o=((e,t)=>{const n=e.map(Ya),r=n.some(e=>e.sceneAnchorId),o=[];let a=0,c=0,i=null,s=null,d=0;const l=(e,t=null,n=null)=>i?(_a(s,e.index-1),s={index:i.scenes.length+1,paragraphIndex:e.index,startParagraphIndex:e.index,endParagraphIndex:e.index,title:t||`Scene ${i.scenes.length+1}`,anchorId:n,wordCount:0},i.scenes.push(s),s):null;for(const e of n)e.text&&(Oa(e,1)?(Ja(i,e.index-1),a+=1,i={index:o.length+1,paragraphIndex:e.index,startParagraphIndex:e.index,endParagraphIndex:e.index,title:e.text,anchorId:e.chapterAnchorId,wordCount:0,scenes:[]},o.push(i),s=null,e.sceneAnchorId?(c+=1,l(e,"Scene 1",e.sceneAnchorId)):r||l(e,"Scene 1",null),d+=e.wordCount):i&&(e.sceneAnchorId?(c+=1,l(e,`Scene ${i.scenes.length+1}`,e.sceneAnchorId)):s||l(e,"Scene 1",null),t&&Ka.has(e.text)?(c+=1,l(e)):(i.wordCount+=e.wordCount,s&&(s.wordCount+=e.wordCount),d+=e.wordCount)));return Ja(i,n.length-1),{paragraphs:n,chapters:o,usesExplicitScenes:!!t,paragraphCount:n.length,heading1Count:a,heading2Count:c,documentWordCount:d,currentParagraphIndex:null,currentChapter:null,currentScene:null}})(n.items,t),a=rc(o,r.items);return Hn=o,oc(a),Jr("Cache rebuilt."),o},Ic=()=>window.performance&&"function"==typeof window.performance.now?window.performance.now():Date.now(),bc=e=>!!e&&!e.stale&&e.generation===dr&&e.documentGuid===ja()&&e.sceneId===En,Sc=async(e={})=>{const t=!!e.includeSelection,n=!1!==e.updateDisplay,r=dr,o=Ic(),a=da(),c=la(),i=Hn?.currentScene;if(!i||!Number.isInteger(i.startParagraphIndex)||!Number.isInteger(i.endParagraphIndex))return null;if(!fn||!In||!window.Word||"function"!=typeof window.Word.run)return null;const s=Ic(),d=await window.Word.run(async e=>{const n=e.document.body.paragraphs;n.load("text");let r=null;return t&&(r=e.document.getSelection().paragraphs,r.load("text,styleBuiltIn,style")),await e.sync(),{bodyTexts:n.items.map(e=>String(e.text||"")),selectionParagraphs:t&&r?r.items.map(e=>({text:String(e.text||""),styleBuiltIn:e.styleBuiltIn,style:e.style})):[]}}),l=Math.round(Ic()-s);if(r!==dr)return zr(`Office snapshot: ${l}ms stale`),{stale:!0,generation:r};let u=!1;if(t){const e=rc(Hn,d.selectionParagraphs);u=oc(e)}const p=Hn?.currentScene;if(!p||!Number.isInteger(p.startParagraphIndex)||!Number.isInteger(p.endParagraphIndex))return null;const m=[];let h=0;const g=Math.min(p.endParagraphIndex,d.bodyTexts.length-1),w=Hn.currentChapter?.startParagraphIndex;for(let e=p.startParagraphIndex;e<=g;e+=1){const t=String(d.bodyTexts[e]||"").trim();t&&!Ka.has(t)&&e!==w&&(m.push(t),h+=Ba(t))}p.wordCount=h,n&&so(Hn.currentChapter?.title,p.title,h,Hn.currentChapter?.anchorId,p.anchorId,Hn.currentChapter?.index);const y={documentGuid:ja(),projectId:a?.projectId||null,bookId:c?.bookId||null,chapterId:Nn,sceneId:En,chapterTitle:Hn.currentChapter?.title||"",sceneTitle:p.title||"",sceneText:m.join("\n"),wordCount:h,selectionSignature:`${Hn.currentParagraphIndex??-1}:${p.startParagraphIndex}:${p.endParagraphIndex}`,selectionChanged:u,generation:r};return lr=y,zr(`Office snapshot: ${l}ms; scene words: ${h}; total snapshot: ${Math.round(Ic()-o)}ms`),y},Cc=async()=>bc(lr)?lr:await Sc(),kc=async()=>{if(oo(""),!fn||!In||!window.Word||"function"!=typeof window.Word.run)return so(null,null,null),oo("Word document access is unavailable."),ea({lastScan:"Failure",lastError:"Word document access is unavailable."}),!1;te&&(te.disabled=!0,te.textContent="Scanning..."),oo("Scanning document structure...");try{const e=await window.Word.run(async e=>{const t=la();return t?await fc(e,!!t.usesExplicitScenes):(Hn=null,await yc(e))});return Hn||so(e.currentChapter?.title,e.currentScene?.title,e.currentScene?.wordCount,e.currentChapter?.anchorId,e.currentScene?.anchorId,e.currentChapter?.index),Bo("Not detected"),ac(e),oo(""),ea({lastScan:"Success",lastError:"-",paragraphs:String(e.paragraphCount),heading1:String(e.heading1Count),heading2:String(e.heading2Count)}),!0}catch(e){const t=ta(e);return console.error("Unable to scan the Word document.",e),so(null,null,null),oo(`Unable to scan the Word document: ${t}`),ea({lastScan:"Failure",lastError:t}),!1}finally{te&&(te.disabled=!1,te.textContent="Refresh Document Structure"),await ho().catch(()=>null)}},vc=async()=>{const e=la();if(!da()||!e)return wo("Select a project and book to analyse manuscript structure."),!1;if(!fn||!In||!window.Word||"function"!=typeof window.Word.run)return wo("Word document access is unavailable."),ea({lastScan:"Failure",lastError:"Word document access is unavailable."}),!1;de&&(de.disabled=!0,de.textContent="Analysing..."),wo("Analysing manuscript structure...");try{const t=await window.Word.run(async e=>await yc(e)),n=await Ac(`/api/word-companion/books/${e.bookId}/structure`);return so(t.currentChapter?.title,t.currentScene?.title,t.currentScene?.wordCount,t.currentChapter?.anchorId,t.currentScene?.anchorId,t.currentChapter?.index),ac(t),Rn=((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=mc(t,r,n);for(const o of pc(t))hc(o,e,r,n)}return n})(t,n),wc(Rn),wo("Preview generated. No changes have been applied."),ea({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),wo("Unable to analyse manuscript structure."),ea({lastScan:"Failure",lastError:ta(e)}),!1}finally{de&&(de.textContent="Analyse Manuscript Structure",bo())}},xc=e=>{nr&&(nr(e),nr=null),Mt?.close?Mt.close():Mt&&(Mt.hidden=!0)},Dc=()=>{const e=((e=Rn)=>{const t=fo(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),Mt?new Promise(e=>{nr=e,Mt.showModal?Mt.showModal():Mt.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.`))},Pc=(e,t,n="")=>{e.result=t,e.error=n},Ec=e=>Number.isInteger(e?.wordChapter?.index)&&e.wordChapter.index>0?10*e.wordChapter.index:null,Nc=e=>Number.isInteger(e?.wordScene?.index)&&e.wordScene.index>0?10*e.wordScene.index:null,Lc=async(e,t)=>{const n=await $c(`/api/word-companion/books/${e}/chapters`,{title:Vo(t.wordTitle),sortOrder:Ec(t)});if(!n?.chapterId)throw new Error("Chapter creation did not return a chapter ID.");qo(),t.pdChapter={chapterId:n.chapterId,title:n.title||t.wordTitle,sortOrder:n.sortOrder||Ec(t)||0,scenes:[]},t.match=`Chapter ${t.pdChapter.chapterId}: ${t.pdChapter.title}`},qc=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 $c(`/api/word-companion/books/${e}/chapters/${n.chapterId}/scenes`,{sceneTitle:Vo(t.wordTitle),sortOrder:Nc(t)});if(!r?.sceneId)throw new Error("Scene creation did not return a scene ID.");qo(),t.pdChapter=n,t.pdScene={sceneId:r.sceneId,title:t.wordTitle,sortOrder:Nc(t)||0},t.match=`Scene ${t.pdScene.sceneId}: ${t.pdScene.title}`},Ac=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()},$c=(e,t)=>Ac(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}),Tc=async(e="")=>{Qn=!1,Xn=0,Yn=[],P&&(P.innerHTML=""),uo(x,!0),ka(!1),Sa(""),uo(E,!0),e&&oo(e);const t=await jc();e&&t&&Cn&&oo(e)},Wc=async(e=En,t=Nn)=>{const n=da(),r=la(),o=ja(),a=Number.parseInt(e||"",10),c=Number.parseInt(t||"",10);if(!n||!r||!o||!Number.isInteger(a)||a<=0||!Number.isInteger(c)||c<=0)return;const i=`${n.projectId}:${r.bookId}:${a}`;if(Ur!==i){Ur=i;try{await $c("/api/word-companion/runtime/current-scene",{documentGuid:o,projectId:n.projectId,bookId:r.bookId,chapterId:c,sceneId:a}),Jr("Current scene follow event sent.")}catch(e){Ur="",console.debug("Unable to notify PlotDirector of current scene.",e)}}},jc=async()=>{const e=la();if(!(e&&fn&&In&&window.Word&&"function"==typeof window.Word.run))return!1;oo("Reading manuscript position...");try{qo(),await Promise.all([oi(!0),ai(!0),ci(!0)]),await _o(e.bookId);const t=await window.Word.run(async t=>await fc(t,!!e.usesExplicitScenes));return ac(t),ea({lastScan:"Success",lastError:"-",paragraphs:String(t.paragraphCount),heading1:String(t.heading1Count),heading2:String(t.heading2Count)}),Cn?(kn?await pi():await ui(),vo(!1),ko("Live"),oo(""),!0):(Bo("Not detected"),vo(!1),ko("Live"),oo("Manuscript linked. Click inside a chapter to show the current scene."),!0)}catch(e){return console.error("Unable to initialise bound manuscript runtime.",e),Hn=null,ko("Manual"),oo(`Unable to read manuscript position: ${ta(e)}`),ea({lastScan:"Failure",lastError:ta(e)}),!1}},Mc=async n=>{On=null,gi(),lo(),Lo(),Bo("Not detected"),ko("Manual"),to("Connected"),oa(e,null),oa(t,null),J&&(J.value=""),aa(z,"Select a project first"),va(),w&&(w.value=""),aa(y,"Select a project first"),xa(n||"Select a Project and Book to begin."),oo(n||"Manuscript unlinked."),go("No resolved PlotDirector scene."),ka(!0),po()},Uc=e=>e?[...e.querySelectorAll("input[type='checkbox']:checked")].map(e=>Number.parseInt(e.value||"",10)).filter(e=>Number.isInteger(e)&&e>0):[],Rc=()=>{const e=Number.parseInt(et?.value||"",10);return Number.isInteger(e)&&e>0?e:null},Oc=(e,t,n,r)=>{const o=((e,t)=>Ga(e).find(e=>String(e.tag||"")===t)||null)(e,n);if(o&&o.tag===n&&o.title===t)return!1;const a=o||e.getRange().insertContentControl();return a.title=t,a.tag=n,a.appearance="Hidden",!0},Bc=async(e="PlotDirector IDs attached successfully.")=>{if(!En||!Nn)return oo("No resolved PlotDirector scene."),!1;if((Pn&&Pn!==En||Dn&&Dn!==Nn)&&!window.confirm("This scene is already linked. Replace the existing PlotDirector link?"))return!1;if(!fn||!In||!window.Word||"function"!=typeof window.Word.run)return oo("Word document access is unavailable."),!1;Ie&&(Ie.disabled=!0,Ie.textContent="Attaching...");try{return await window.Word.run(async e=>{const t=await yc(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.");Oc(n,"PlotDirector Chapter",`PD-CHAPTER-${Nn}`,"PD-CHAPTER"),Oc(r,"PlotDirector Scene",`PD-SCENE-${En}`,"PD-SCENE"),await e.sync()}),await ho().catch(()=>null),Dn=Nn,Pn=En,An=!1,qn="SceneID Anchor",Ln="Anchor",oo(e),ea({lastError:"-"}),io(),!0}catch(e){return console.error("Unable to attach PlotDirector IDs.",e),oo("Unable to attach PlotDirector IDs."),ea({lastError:ta(e)}),io(),!1}finally{Ie&&(Ie.textContent=Pn===En?"Attach PlotDirector IDs":"Reattach PlotDirector IDs",io())}},Hc=async e=>{if(!Nn)return To("No resolved PlotDirector chapter."),!1;if(!fn||!In||!window.Word||"function"!=typeof window.Word.run)return To("Word document access is unavailable."),!1;try{return await window.Word.run(async e=>{const t=await yc(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.");Oc(n,"PlotDirector Chapter",`PD-CHAPTER-${Nn}`,"PD-CHAPTER"),await e.sync()}),await ho().catch(()=>null),Dn=Nn,An=!1,qn="ChapterID Anchor",Ln="Chapter anchor",To(e),oo(e),ea({lastError:"-"}),io(),!0}catch(e){return console.error("Unable to attach PlotDirector chapter ID.",e),To("Unable to attach PlotDirector chapter ID."),ea({lastError:ta(e)}),io(),!1}},Gc=async e=>{Mo(),await pi(),oo(e),To(e)},Fc=e=>{Un&&(Un(e),Un=null),At?.close?At.close():At&&(At.hidden=!0)},Vc=()=>{if(!Et)return;const e=Vo(Pt?.value||"").toLocaleLowerCase(),t=jn.filter(t=>!e||String(t.title||"").toLocaleLowerCase().includes(e));if(Et.innerHTML="",Mn=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 Et.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",()=>{Mn=t,Nt&&(Nt.disabled=!1)});const o=document.createElement("span");o.textContent=e.title||"Untitled chapter",n.append(r,o),Et.append(n)}},Kc=()=>{Dt?.close?Dt.close():Dt&&(Dt.hidden=!0)},Yc=async(e,t,n)=>{const r=la();if(!r)return $o("Select a PlotDirector book first."),!1;await Xo(r.bookId,e,t,"Manual link","Title Match");return!!await Bc(n)&&($o(n),Ro(),!0)},_c=e=>{Wn&&(Wn(e),Wn=null),St?.close?St.close():St&&(St.hidden=!0)},Jc=()=>{if(!yt)return;const e=Vo(wt?.value||"").toLocaleLowerCase(),t=$n.filter(t=>!e||String(t.title||"").toLocaleLowerCase().includes(e));if(yt.innerHTML="",Tn=null,ft&&(ft.disabled=!0),0===t.length){const e=document.createElement("p");return e.className="word-companion-empty-list",e.textContent="No scenes found.",void yt.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",()=>{Tn=t,ft&&(ft.disabled=!1)});const o=document.createElement("span");o.textContent=e.title||"Untitled scene",n.append(r,o),yt.append(n)}},zc=()=>{gt?.close?gt.close():gt&&(gt.hidden=!0)},Qc=()=>{wr=!1,Co(),yr&&(yr=!1,Zc(1e3))},Xc=async(e={})=>{const t=e.source||"manual",n=Ic();if(!En)return void go("No resolved PlotDirector scene.");if(!Nn)return void go("No resolved PlotDirector chapter.");if(or)return void go("Refresh Current Scene before syncing.");const r=la(),o=ja();if(!r||!o)return void go("Bound manuscript metadata is unavailable.");if(wr)return yr=!0,void Jr("Scene sync deferred; sync already running.");lo(),wr=!0,yr=!1;let a=e.snapshot||null;try{a=bc(a)?a:await Cc()}catch(e){return go("Sync failed"),ea({lastError:ta(e)}),Jr("Scene sync failed."),void Qc()}if(!bc(a))return go("Waiting for typing to pause"),Jr("Scene sync skipped (stale snapshot)."),void Qc();const c=a.wordCount;if(!Number.isInteger(c)||c<0)return go("Sync failed"),Jr("Scene sync failed."),void Qc();if(fr===a.sceneId&&Ir===c)return go("Synced"),Jr("Sync skipped (count unchanged)."),void Qc();Jr("Scene word count changed."),Be&&(Be.disabled=!0,Be.textContent="Syncing..."),go("Syncing..."),Jr(`Scene sync started (${t}).`);try{const e=Ic(),t=await $c("/api/word-companion/runtime/scene-word-count",{documentGuid:a.documentGuid||o,bookId:a.bookId||r.bookId,chapterId:a.chapterId,sceneId:a.sceneId,wordCount:c});if(zr(`Word count sync API: ${Math.round(Ic()-e)}ms`),!bc(a))return void Jr("Scene sync result ignored (stale snapshot).");const i=t?.actualWords??c,s=new Date;fr=a.sceneId,Ir=i,Zo(Ge,Po(i)),Zo(je,Po(i)),Zo(Fe,Eo(s)),Zo(Oe,Eo(s)),go("Synced"),Jr("Scene sync succeeded."),zr(`Total word count sync: ${Math.round(Ic()-n)}ms`)}catch(e){go("Sync failed"),ea({lastError:ta(e)}),Jr("Scene sync failed.")}finally{Be&&(Be.textContent="Sync Current Scene"),Qc()}},Zc=(e=4e3)=>{lo(),En&&Nn&&!or&&!wr&&(gr=window.setTimeout(()=>{gr=null,Xc({source:"automatic"})},e))},ei=()=>{br&&(window.clearTimeout(br),br=null)},ti=()=>{kr=null,vr="",xr=[],Dr=null,Pr="",ei()},ni=()=>{Er=null,Nr="",Lr=[],qr=null,Ar=""},ri=()=>{$r=null,Tr="",Wr=[],jr=null,Mr=""},oi=async(e=!1)=>{const t=da(),n=ja();if(!t||!n)return xr=[],[];if(!e&&kr===t.projectId&&vr===n&&xr.length>0)return xr;const r=await Ac(`/api/word-companion/runtime/characters?projectId=${encodeURIComponent(t.projectId)}&documentGuid=${encodeURIComponent(n)}`);return kr=t.projectId,vr=n,xr=Array.isArray(r?.characters)?r.characters:[],Jr("Character alias cache refreshed."),xr},ai=async(e=!1)=>{const t=da(),n=ja();if(!t||!n)return Lr=[],[];if(!e&&Er===t.projectId&&Nr===n&&Lr.length>0)return Lr;const r=await Ac(`/api/word-companion/runtime/assets?projectId=${encodeURIComponent(t.projectId)}&documentGuid=${encodeURIComponent(n)}`);return Er=t.projectId,Nr=n,Lr=Array.isArray(r?.assets)?r.assets:[],Jr(`Asset cache loaded: ${Lr.length} aliases.`),Lr},ci=async(e=!1)=>{const t=da(),n=ja();if(!t||!n)return Wr=[],[];if(!e&&$r===t.projectId&&Tr===n&&Wr.length>0)return Wr;const r=await Ac(`/api/word-companion/runtime/locations?projectId=${encodeURIComponent(t.projectId)}&documentGuid=${encodeURIComponent(n)}`);return $r=t.projectId,Tr=n,Wr=Array.isArray(r?.locations)?r.locations:[],Jr(`Location cache loaded: ${Wr.length} aliases.`),Wr},ii=(e,t)=>{const n=String(t||"").trim();if(!n)return!1;const r=(o=n,String(o||"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&")).replace(/\s+/g,"\\s+");var o;return new RegExp(`(^|[^\\p{L}\\p{N}_])${r}(?=$|[^\\p{L}\\p{N}_])`,"iu").test(e)},si=e=>{if(e?.excludeFromCompanionDetection)return!1;const t=Number.parseInt(e?.detectionPriority||"0",10);return n=e?.matchText,String(n||"").trim().split(/\s+/).filter(Boolean).length>=2||Number.isInteger(t)&&t>=75;var n},di=async()=>{if(br=null,!En||or||!ja())return;if(Sr)return Cr=!0,void Jr("Character suggestion detection deferred; detection already running.");Sr=!0,Cr=!1;const e=Ic();try{const t=await Cc();if(!bc(t))return void Jr("Runtime suggestions skipped (stale snapshot).");const[n,r,o]=await Promise.all([oi(),ai(),ci()]);if(!bc(t))return void Jr("Runtime suggestions skipped after cache load (stale snapshot).");const a=t.sceneText||"",c=Ic(),i=((e,t)=>{if(!e||!Array.isArray(t)||0===t.length)return[];const n=new Map;for(const r of t){const t=Number.parseInt(r.characterId||"",10);!Number.isInteger(t)||t<=0||n.has(t)||ii(e,r.matchText)&&n.set(t,r.name||r.matchText||"Character")}return[...n.entries()].map(([e,t])=>({characterId:e,name:t}))})(a,n);zr(`Character detection: ${Math.round(Ic()-c)}ms`);const s=i.map(e=>e.characterId),d=s.slice().sort((e,t)=>e-t).join(","),l=Ic(),u=((e,t)=>{if(!e||!Array.isArray(t)||0===t.length)return[];const n=new Map;for(const r of t){const t=Number.parseInt(r.assetId||"",10);!Number.isInteger(t)||t<=0||n.has(t)||ii(e,r.matchText)&&n.set(t,r.name||r.matchText||"Asset")}return[...n.entries()].map(([e,t])=>({assetId:e,name:t}))})(a,r);zr(`Asset detection: ${Math.round(Ic()-l)}ms`);const p=u.map(e=>e.assetId),m=p.slice().sort((e,t)=>e-t).join(","),h=Ic(),g=((e,t)=>{if(!e||!Array.isArray(t)||0===t.length)return[];const n=new Map;for(const r of t){const t=Number.parseInt(r.locationId||"",10);!Number.isInteger(t)||t<=0||n.has(t)||!si(r)||ii(e,r.matchText)&&n.set(t,r.name||r.matchText||"Location")}return[...n.entries()].map(([e,t])=>({locationId:e,name:t}))})(a,o);zr(`Location detection: ${Math.round(Ic()-h)}ms`);const w=g.map(e=>e.locationId),y=w.slice().sort((e,t)=>e-t).join(",");if(!d||Dr===En&&Pr===d)Jr("Character suggestions skipped.");else{if(!bc(t))return void Jr("Character suggestions skipped before submit (stale snapshot).");const e=Ic(),n=await $c("/api/word-companion/runtime/character-suggestions",{documentGuid:t.documentGuid,sceneId:t.sceneId,characterIds:s});if(zr(`Character suggestion API: ${Math.round(Ic()-e)}ms`),!bc(t))return void Jr("Character suggestion result ignored (stale snapshot).");if(Dr=t.sceneId,Pr=d,(n?.createdCount||0)>0){const e=i.slice(0,3).map(e=>e.name).join(", "),t=i.length>3?" +"+(i.length-3):"";oo(e?`Characters detected: ${e}${t}`:n.message)}Jr(n?.message||"Character suggestions submitted.")}if(!m||qr===En&&Ar===m)Jr("Asset suggestions skipped.");else{if(!bc(t))return void Jr("Asset suggestions skipped before submit (stale snapshot).");Jr(`Asset matches found: ${u.map(e=>e.name).join(", ")}`);const e=Ic(),n=await $c("/api/word-companion/runtime/asset-suggestions",{documentGuid:t.documentGuid,sceneId:t.sceneId,assetIds:p});if(zr(`Asset suggestion API: ${Math.round(Ic()-e)}ms`),!bc(t))return void Jr("Asset suggestion result ignored (stale snapshot).");if(qr=t.sceneId,Ar=m,(n?.createdCount||0)>0){const e=u.slice(0,3).map(e=>e.name).join(", "),t=u.length>3?" +"+(u.length-3):"";oo(e?`Assets detected: ${e}${t}`:n.message)}Jr(n?.message||"Asset suggestions submitted.")}if(!y||jr===En&&Mr===y)Jr("Location suggestions skipped.");else{if(!bc(t))return void Jr("Location suggestions skipped before submit (stale snapshot).");Jr(`Location matches found: ${g.map(e=>e.name).join(", ")}`);const e=Ic(),n=await $c("/api/word-companion/runtime/location-suggestions",{documentGuid:t.documentGuid,sceneId:t.sceneId,locationIds:w});if(zr(`Location suggestion API: ${Math.round(Ic()-e)}ms`),!bc(t))return void Jr("Location suggestion result ignored (stale snapshot).");if(jr=t.sceneId,Mr=y,(n?.createdCount||0)>0){const e=g.slice(0,3).map(e=>e.name).join(", "),t=g.length>3?" +"+(g.length-3):"";oo(e?`Locations detected: ${e}${t}`:n.message)}Jr(n?.message||"Location suggestions submitted.")}zr(`Total suggestion pass: ${Math.round(Ic()-e)}ms`)}catch(e){console.error("Unable to detect runtime suggestions.",e),ea({lastError:ta(e)})}finally{Sr=!1,Cr&&(Cr=!1,li(1500))}},li=(e=2500)=>{ei(),!En||or||Sr?Sr&&(Cr=!0):br=window.setTimeout(()=>{di()},e)},ui=async()=>{const e=da(),t=la(),n=Ko(Cn,"chapter");if(Yo({projectId:e?.projectId,projectTitle:e?.title,bookId:t?.bookId,bookTitle:t?ia(t):void 0,detectedChapter:Cn,detectedScene:kn,requestChapter:n,requestScene:"",result:"Not run",chapterId:null,sceneId:null}),!t)return Bo("Not detected"),oo("Select a PlotDirector book first."),!1;if(!Cn)return Bo("Not detected"),oo("No chapter detected in Word. Use Heading 1 for chapters."),!1;Bo("Not detected");try{const e=await Jo(t.bookId),r=Dn?e.find(e=>e.chapterId===Dn):null,o=n.toLocaleLowerCase(),a=o?e.find(e=>Ko(e.title,"chapter").toLocaleLowerCase()===o):null,c=r||a;return c?(Mo(),xo(null,c.chapterId,r?"Chapter anchor":"Chapter title"),qn=r?"ChapterID Anchor":"Title Match",ao("Chapter linked to PlotDirector"),oo("No scene detected in Word. Use Heading 2 for scenes."),Yo({result:"Chapter matched",chapterId:c.chapterId,sceneId:null}),!0):(xo(null),ao("Chapter not found in PlotDirector."),oo("Chapter not found in PlotDirector."),Yo({result:"Chapter not matched",chapterId:null,sceneId:null}),Uo("Chapter not found in PlotDirector."),!1)}catch(e){return Bo("Not found in PlotDirector"),ea({lastError:ta(e)}),oo("Unable to load PlotDirector chapter data."),!1}},pi=async()=>{const e=da(),t=la(),n=Ko(Cn,"chapter"),r=Ko(kn,"scene");if(Yo({projectId:e?.projectId,projectTitle:e?.title,bookId:t?.bookId,bookTitle:t?ia(t):void 0,detectedChapter:Cn,detectedScene:kn,requestChapter:n,requestScene:r,result:"Not run",chapterId:null,sceneId:null}),co({anchorType:Pn?"SceneID Anchor":Dn?"ChapterID Anchor":"Title Match",storedSceneId:Pn,storedChapterId:Dn,resolutionMethod:"-"}),!t)return Bo("Not detected"),oo("Select a PlotDirector book first."),Yo({result:"Error"}),!1;if(!Cn||!kn)return Bo("Not detected"),oo("No scene detected in Word. Use Heading 2 for scenes."),Yo({result:"Error"}),!1;me&&(me.disabled=!0,me.textContent="Refreshing...");const o=()=>{me&&(me.disabled=!1,me.textContent="Refresh PlotDirector Scene")};Bo("Not detected"),oo("Resolving PlotDirector scene...");try{if(Pn){const e=await(async(e,t)=>{const n=await Ac(`/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===Pn);if(e)return Yo({result:"Matched",chapterId:e.chapter.chapterId,sceneId:e.scene.sceneId}),await Xo(t.bookId,e.scene.sceneId,e.chapter.chapterId,"Anchor","SceneID Anchor"),!0;An=!0,qn="SceneID Anchor",ao("Not found in PlotDirector"),oo("Stored PlotDirector ID is invalid."),Yo({result:"Error",chapterId:Dn,sceneId:Pn}),co({anchorType:"SceneID Anchor",storedSceneId:Pn,storedChapterId:Dn,resolutionMethod:"Anchor"})}if(Dn){const e=(await _o(t.bookId)).find(e=>e.chapterId===Dn),n=e?(Array.isArray(e.scenes)?e.scenes:[]).find(e=>Ko(e.title,"scene").toLocaleLowerCase()===r.toLocaleLowerCase()):null;if(n)return Yo({result:"Matched",chapterId:e.chapterId,sceneId:n.sceneId}),await Xo(t.bookId,n.sceneId,e.chapterId,"Anchor","ChapterID Anchor"),!0;e&&!Pn?(qn="ChapterID Anchor",xo(null,Dn,"Chapter anchor"),Yo({result:"Chapter matched",chapterId:Dn,sceneId:null})):Pn||(qn="ChapterID Anchor",Yo({result:"Chapter anchor not found",chapterId:Dn,sceneId:null}))}const e=await $c(`/api/word-companion/books/${t.bookId}/resolve-scene`,{chapterTitle:n,sceneTitle:r});if(!e?.matched||!e.sceneId){const t=An,n=Number.parseInt(e?.chapterId||"",10),r=Number.isInteger(Nn)&&Nn>0?Nn:null,a=Number.isInteger(n)&&n>0?n:r,c=!!e?.chapterMatched||!!a;return Bo("Not found in PlotDirector"),An=t,c&&(xo(null,a,a===r?"Chapter anchor":"Chapter title"),ao("Scene not found in PlotDirector.")),oo(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."),Yo({result:"Not matched",chapterId:c?a:e?.chapterId,sceneId:e?.sceneId}),t||(c?(Mo(),Oo("Scene not found in PlotDirector.")):(Ro(),Uo("Chapter not found in PlotDirector."))),o(),!1}const a=An;return Yo({result:a?"Matched by title fallback":"Matched",chapterId:e.chapterId,sceneId:e.sceneId}),await Xo(t.bookId,e.sceneId,e.chapterId,a?"Title fallback":"Title","Title Match"),a&&(An=!0,oo("Stored PlotDirector ID is invalid."),io()),!0}catch(e){const t=An;return ea({lastError:ta(e)}),Bo("Not found in PlotDirector"),An=t,oo(t?"Stored PlotDirector ID is invalid.":"Unable to load PlotDirector scene data."),Yo({result:"Error"}),!1}finally{o()}},mi=async()=>{if(ar=null,hr)return sr=!0,void Jr("Runtime update deferred; update already running.");if(!mn||!la())return cr=!1,void Jr("Runtime update skipped.");if(!fn||!In||!window.Word||"function"!=typeof window.Word.run)return cr=!1,ko("Manual"),void oo("Automatic scene tracking is unavailable in this Word version. Use Refresh Current Scene.");if(!Hn)return cr=!1,ko("Manual"),void oo("Document structure is not cached yet. Use Refresh Current Scene.");const e=Date.now()-ir;if(cr&&e{ar&&window.clearTimeout(ar),ar=window.setTimeout(mi,Math.max(0,e)),ko("Waiting for typing to pause"),Jr("Runtime update scheduled.")},gi=()=>{ar&&(window.clearTimeout(ar),ar=null),cr=!1,sr=!1},wi=()=>{((e="selection",t=1200)=>{if(cr=!0,ir=Date.now(),dr+=1,lr=null,lo(),ei(),wr&&(yr=!0),Sr&&(Cr=!0),Jr(`${e} changed.`),hr)return sr=!0,void ko("Waiting for typing to pause");hi(t)})("Selection")},yi=()=>{if(mr&&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:wi}),mr=!1}catch(e){console.warn("Unable to remove Word selection tracking handler.",e)}},fi=async(e,n)=>{if(Hn=null,qo(),!e)return yn=[],aa(z,"Select a project first"),aa(y,"Select a project first"),ro(""),oa(t,null),Ma(),Bo("Not detected"),void yo();aa(z,"Loading books..."),ro(""),Bo("Not detected"),yo("Select a book to analyse manuscript structure.");try{const r=await Ac(`/api/word-companion/projects/${e}/books`);if(yn=Array.isArray(r.books)?r.books:[],0===yn.length)return aa(z,"No books available."),aa(y,"No books available."),ro("No books available."),oa(t,null),Ma(),void xa("No books available.");ca(z,"Choose a book",yn.map(e=>({...e,displayTitle:ia(e)})),"bookId","displayTitle");const o=yn.find(e=>e.bookId===n);o&&z?(z.value=String(o.bookId),oa(t,o.bookId)):oa(t,null),((e=null)=>{if(!y)return;if(0===yn.length)return void aa(y,"No books available.");ca(y,"Choose a book",yn.map(e=>({...e,displayTitle:ia(e)})),"bookId","displayTitle");const t=e||Number.parseInt(z?.value||"",10),n=yn.find(e=>e.bookId===t);n&&(y.value=String(n.bookId)),Ca()})(o?.bookId||n),Ma(),Bo((la(),"Not detected")),yo(la()?"Ready to analyse manuscript structure.":"Select a book to analyse manuscript structure."),xa(pa()?"Ready to scan manuscript structure.":"Select a Book to begin.")}catch{yn=[],aa(z,"Unable to load books."),aa(y,"Unable to load books."),ro("Unable to load books."),oa(t,null),Ma(),Bo("Not detected"),yo("Unable to load books."),xa("Unable to load books.")}};for(const e of i)e.addEventListener("click",()=>Zr(e.dataset.tabButton));eo(),J?.addEventListener("change",async()=>{const n=Number.parseInt(J.value||"",10);Lo(),w&&Number.isInteger(n)&&n>0&&(w.value=String(n)),oa(e,Number.isInteger(n)&&n>0?n:null),oa(t,null),Bo("Not detected"),yo(),xa("Select a Book to begin."),await fi(n,null),Ia()}),z?.addEventListener("change",()=>{const e=Number.parseInt(z.value||"",10);Lo(),oa(t,Number.isInteger(e)&&e>0?e:null),y&&Number.isInteger(e)&&e>0&&(y.value=String(e)),Ma(),Bo("Not detected"),yo(la()?"Ready to analyse manuscript structure.":"Select a book to analyse manuscript structure."),xa(pa()?"Ready to scan manuscript structure.":"Select a Book to begin."),Ia()}),w?.addEventListener("change",async()=>{const n=Number.parseInt(w.value||"",10);Lo(),J&&Number.isInteger(n)&&n>0&&(J.value=String(n)),oa(e,Number.isInteger(n)&&n>0?n:null),oa(t,null),xa("Select a Book to begin."),await fi(n,null),Ia()}),y?.addEventListener("change",()=>{const e=Number.parseInt(y.value||"",10);Lo(),z&&Number.isInteger(e)&&e>0&&(z.value=String(e)),oa(t,Number.isInteger(e)&&e>0?e:null),Ma(),xa(pa()?"Ready to scan manuscript structure.":"Select a Book to begin."),Ia()}),f?.addEventListener("input",Ca),I?.addEventListener("click",async()=>{const e=ua(),t=String(f?.value||"").trim();if(e&&t){I.disabled=!0,Sa("Creating Book...");try{const n=await $c(`/api/word-companion/projects/${e.projectId}/books`,{title:t});f&&(f.value=""),J&&(J.value=String(e.projectId)),await fi(e.projectId,n.bookId),y&&(y.value=String(n.bookId)),Sa("Ready to scan manuscript structure.")}catch(e){console.error("Unable to create Book from Word Companion.",e),Sa(`Unable to create Book: ${ta(e)}`)}finally{Ca()}}else Ca()}),S?.addEventListener("click",async()=>{const e=ua(),t=pa();if(e&&t)if(fn&&In&&window.Word&&"function"==typeof window.Word.run){S&&(S.disabled=!0,S.textContent="Scanning..."),Sa("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),Oa(e,1))return r={title:d,sortOrder:10*(n.length+1),wordCount:0,scenes:[]},n.push(r),o=s(),void(a+=Ba(d));if(!r||!o)return;if(t&&i.has(d))return void(o=s());const l=Ba(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)});Kn=n,zn=!1;const r=await $c("/api/word-companion/manuscript/analyse",{projectId:e.projectId,bookId:t.bookId,documentGuid:Wa(),chapterCount:n.chapterCount,sceneCount:n.sceneCount,wordCount:n.wordCount});Vn=r,(e=>{if(!v)return;v.innerHTML="";const t=document.createElement("strong");t.textContent="Manuscript Analysis",v.append(t);const n=document.createElement("dl"),r=[["Project",e.projectTitle],["Book",ia({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)}v.append(n),uo(v,!1),uo(A,!1),Sa(e.message||"Preview generated."),Ca()})(r);try{const t=await $c("/api/word-companion/manuscript/discover-characters",{projectId:e.projectId,documentText:n.documentText||""});Yn=Array.isArray(t?.candidates)?t.candidates:[],uo(x,!0),uo(E,!0)}catch(e){console.error("Unable to discover character candidates.",e),Yn=[],uo(x,!0),uo(E,!0)}ea({lastScan:"Success",lastError:"-",paragraphs:"-",heading1:String(n.chapterCount),heading2:"-"})}catch(e){console.error("Unable to scan manuscript for first-run import.",e),xa(`Unable to scan manuscript: ${ta(e)}`),ea({lastScan:"Failure",lastError:ta(e)})}finally{S&&(S.textContent="Scan Manuscript"),Ca()}}else xa("Word document access is unavailable.");else xa("Select a Project and Book to begin.")}),b?.addEventListener("click",async()=>{const n=ua(),r=pa();if(n&&r){Zn=!0,Ca(),Sa("Linking Word document...");try{const o=Wa(),a=await $c("/api/word-companion/manuscript/link",{bookId:r.bookId,documentGuid:o}),c=a.manuscriptDocument;await La({documentGuid:c?.documentGuid||o,bookId:a.bookId||r.bookId,projectId:c?.projectId||n.projectId,bindingVersion:c?.bindingVersion||1}),On={documentGuid:c?.documentGuid||o,bookId:a.bookId||r.bookId,projectId:c?.projectId||n.projectId,bindingVersion:c?.bindingVersion||1},oa(e,On.projectId),oa(t,On.bookId),J&&(J.value=String(On.projectId)),await fi(On.projectId,On.bookId),No({projectId:On.projectId,projectTitle:n.title,bookId:On.bookId,bookTitle:r.title,bookSubtitle:r.subtitle,usesExplicitScenes:!!r.usesExplicitScenes,manuscriptDocument:c}),ka(!1),to("Connected"),ro(a.message||"Manuscript linked."),oo(a.message||"Manuscript linked."),await jc()}catch(e){console.error("Unable to link Word document.",e),Sa(`Unable to link manuscript: ${ta(e)}`)}finally{Zn=!1,Ca()}}else Ca()}),$?.addEventListener("click",async()=>{const n=ua(),r=pa();if(!(n&&r&&Kn&&Vn?.canImport))return void Ca();let o=!1;if(!Vn.requiresReplaceConfirmation||(o=await new Promise(e=>{if(!W||"function"!=typeof W.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=>{j?.removeEventListener("click",n),M?.removeEventListener("click",r),W?.removeEventListener("cancel",o),W?.close(),e(t)},n=()=>t(!0),r=()=>t(!1),o=e=>{e.preventDefault(),t(!1)};j?.addEventListener("click",n),M?.addEventListener("click",r),W?.addEventListener("cancel",o),W.showModal()}),o)){Zn=!0,Ca(),Sa("Importing manuscript structure...");try{const a=Wa(),c=await $c("/api/word-companion/manuscript/import",{projectId:n.projectId,bookId:r.bookId,documentGuid:a,bindingVersion:1,replacePlanned:o,chapters:Kn.chapters});if(!c.imported)return Vn={...Vn,canImport:!c.requiresReplaceConfirmation,requiresReplaceConfirmation:!!c.requiresReplaceConfirmation,message:c.message||Vn.message},Sa(c.message||"Import was not completed."),void Ca();const i=c.manuscriptDocument;await La({documentGuid:i?.documentGuid||a,bookId:c.bookId,projectId:c.projectId,bindingVersion:i?.bindingVersion||1}),On={documentGuid:i?.documentGuid||a,bookId:c.bookId,projectId:c.projectId,bindingVersion:i?.bindingVersion||1},oa(e,c.projectId),oa(t,c.bookId),J&&(J.value=String(c.projectId));const s=Yn;await fi(c.projectId,c.bookId),to("Connected"),zn=!0,Qn=s.length>0,Xn=Qn?Date.now():0,Yn=s,s.length>0?(ka(!0),Pa(s),uo(A,!0),uo(E,!1),Sa(c.message||"Manuscript structure imported."),oo(c.message||"Manuscript structure imported."),window.setTimeout(Ca,750)):await Tc(c.message||"Manuscript structure imported.")}catch(e){console.error("Unable to import manuscript structure.",e),Sa(`Unable to import manuscript: ${ta(e)}`)}finally{Zn=!1,Ca()}}else Sa("Import cancelled.")}),N?.addEventListener("click",async()=>{const e=ua()||da(),t=Da();if(!Qn||Date.now()-Xn<750||!e||0===t.length)Ca();else{er=!0,Ca(),Zo(D,"Creating selected characters...");try{const n=await $c("/api/word-companion/manuscript/create-discovered-characters",{projectId:e.projectId,candidateNames:t});oo(n.message||"Characters created."),Zo(D,`${n.createdCount||0} created, ${n.skippedCount||0} already existed.`),await Tc(n.message||"Characters created.")}catch(e){console.error("Unable to create discovered characters.",e),Zo(D,`Unable to create characters: ${ta(e)}`)}finally{er=!1,Ca()}}}),L?.addEventListener("click",()=>Tc("Character creation skipped.")),q?.addEventListener("click",()=>Tc()),C?.addEventListener("click",()=>ka(!1)),T?.addEventListener("click",()=>xa("Import cancelled.")),h?.addEventListener("click",async()=>{if(!Jn?.buildId)return;h&&(h.disabled=!0,h.textContent="Confirming...");if(!await $a(Jn.buildId,"UserConfirmedSave","Scene markers added; user confirmed the Word document was saved.",{...Jn.diagnostics,markersChanged:!0,saveState:"UserConfirmedSave",saveApi:Jn.diagnostics?.saveApi||"manual-companion",...Aa()}))return oo("PlotDirector could not confirm the save yet. Keep Word open and try again."),void(h&&(h.disabled=!1,h.textContent="I've saved it"));Ta(),oo("Scene markers added and save confirmed. Word may now be closed."),ea({lastError:"-"})}),te?.addEventListener("click",kc),de?.addEventListener("click",vc),le?.addEventListener("click",async()=>{const e=la();if(!e||0===fo().length||tr)return void Io();if(!await Dc())return;tr=!0,bo(),wo("Applying structure sync...");const t={createdChapters:0,createdScenes:0,linkedChapters:0,linkedScenes:0,skipped:Array.isArray(Rn?.manualReview)?Rn.manualReview.length:0,failed:0},n=fo().filter(e=>"couldLink"===e.category&&"Chapter"===e.type),r=fo().filter(e=>"wouldCreateChapters"===e.category),o=fo().filter(e=>"couldLink"===e.category&&"Scene"===e.type),a=fo().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(!fn||!In||!window.Word||"function"!=typeof window.Word.run)throw new Error("Word document access is unavailable.");await window.Word.run(async t=>{const n=await yc(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.");Oc(o,"PlotDirector Chapter",`PD-CHAPTER-${t}`,"PD-CHAPTER")}else{const t=e.pdScene?.sceneId;if(!t)throw new Error("Scene ID is not available.");Oc(o,"PlotDirector Scene",`PD-SCENE-${t}`,"PD-SCENE")}await t.sync()}),await ho().catch(()=>null)})(e),Pc(e,"Success"),t[n]+=1}catch(n){Pc(e,"Failed",ta(n)),t.failed+=1}};try{for(const e of n)s(e,"linkedChapters");for(const n of r)try{await Lc(e.bookId,n),s(n,"createdChapters")}catch(e){Pc(n,"Failed",ta(e)),t.failed+=1}for(const e of o)s(e,"linkedScenes");for(const n of a)try{await qc(e.bookId,n),s(n,"createdScenes")}catch(e){Pc(n,"Failed",ta(e)),t.failed+=1}for(const e of c)await d(e.item,e.counterName);for(const e of Rn.manualReview||[])Pc(e,"Skipped");wc(Rn),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),wo(i)}finally{tr=!1,bo(),i&&(qo(),await vc(),wo(`${i} Preview refreshed.`))}}),Rt?.addEventListener("click",()=>xc(!0)),Ot?.addEventListener("click",()=>xc(!1)),Mt?.addEventListener("cancel",e=>{e.preventDefault(),xc(!1)}),me?.addEventListener("click",pi),ee?.addEventListener("click",async()=>{if(!la())return oo("Select a PlotDirector book first."),void Bo("Not detected");gi(),Do(!0),ko("Updating...");try{await Promise.all([oi(!0),ai(!0),ci(!0)]);if(!await kc())return;if(vo(!1),!kn)return await ui(),void ko("Current scene updated");await pi(),ko("Current scene updated")}finally{Do(!1)}}),Be?.addEventListener("click",()=>Xc({source:"manual"})),tt?.addEventListener("click",async()=>{if(En)if(!or&&await(async()=>{if(!En)return!1;if(!fn||!In||!window.Word||"function"!=typeof window.Word.run)return vo(!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 yc(e)),t=e.currentChapter?.title||"",n=e.currentScene?.title||"",r=e.currentScene?.anchorId||null,o=e.currentChapter?.anchorId||null,a=Number.isInteger(r)&&r===En,c=Number.isInteger(o)&&o===Nn,i=Ko(n,"scene").toLocaleLowerCase()===Ko(Rr||kn,"scene").toLocaleLowerCase(),s=Ko(t,"chapter").toLocaleLowerCase()===Ko(Or||Cn,"chapter").toLocaleLowerCase();return a||i&&(c||s)?(vo(!1),!0):(vo(!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),ea({lastError:ta(e)}),vo(!0,"The Word cursor is now in a different scene. Refresh Current Scene before saving."),!1}})()){tt&&(tt.disabled=!0,tt.textContent="Saving...");try{await(e=`/api/word-companion/scenes/${En}/links`,t={characterIds:Uc(Xe),assetIds:Uc(Ze),locationIds:[],primaryLocationId:Rc()},Ac(e,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})),(()=>{const e=new Set(Uc(Xe)),t=new Set(Uc(Ze));Fr={characters:Fr.characters.map(t=>({...t,linked:e.has(Number.parseInt(Ho(t,"character"),10))})),assets:Fr.assets.map(e=>({...e,linked:t.has(Number.parseInt(Ho(e,"asset"),10))})),locations:Fr.locations,primaryLocationId:Rc()}})(),Ao("Scene links saved successfully."),ea({lastError:"-"})}catch(e){Ao("Unable to save scene links."),ea({lastError:ta(e)})}finally{tt&&(tt.disabled=!En||or,tt.textContent="Save Scene Links")}var e,t}else Ao("The Word cursor is now in a different scene. Refresh Current Scene before saving.");else Ao("Link a PlotDirector scene first.")}),Ie?.addEventListener("click",async()=>{await Bc()}),be?.addEventListener("click",async()=>{console.debug("Word Companion unlink clicked"),oo("Preparing to unlink manuscript...");const e=Na();if(!e)return void oo("This Word document is not linked.");if(!e.documentGuid||!Number.isInteger(e.bookId)||e.bookId<=0)return void oo("Unable to unlink: bound document metadata is incomplete.");try{await ho()}catch{oo("Marker counts are unavailable. You can still unlink without removing hidden anchors.")}if(await new Promise(e=>{if(!U||"function"!=typeof U.showModal)return void e(window.confirm(`This will remove PlotDirector binding metadata from this Word document and unlink this Book in PlotDirector.\n\nHidden PlotDirector anchors will be left in place for possible reuse.\n\nCurrent marker count:\n${Vr.chapterCount} chapter markers\n${Vr.sceneCount} scene markers\n\nYour manuscript text will not be changed.\n\nContinue?`));const t=t=>{R?.removeEventListener("click",n),O?.removeEventListener("click",r),U?.removeEventListener("cancel",o),U?.close(),e(t)},n=()=>t(!0),r=()=>t(!1),o=e=>{e.preventDefault(),t(!1)};R?.addEventListener("click",n),O?.addEventListener("click",r),U?.addEventListener("cancel",o),U.showModal()})){oo("Unlinking manuscript..."),be&&(be.disabled=!0,be.textContent="Unlinking...");try{await $c("/api/word-companion/manuscript/unlink",{documentGuid:e.documentGuid,bookId:e.bookId}),await qa(),await ho().catch(()=>null),await Mc("Manuscript unlinked.")}catch(e){console.error("Unable to unlink manuscript binding.",e),oo("Unable to unlink from PlotDirector.");if(window.confirm("PlotDirector could not be updated, but you can still remove the binding from this Word document.\n\nYou may need to unlink the Book manually in PlotDirector later.\n\nRemove binding from this Word document only?"))try{await qa(),await ho().catch(()=>null),await Mc("Word metadata removed. Unlink the Book manually in PlotDirector if it still shows as linked.")}catch(e){console.error("Unable to remove Word document metadata.",e),oo(`Unable to remove Word metadata: ${ta(e)}`)}else oo(`Unable to unlink manuscript: ${ta(e)}`)}finally{be&&(be.disabled=!1,be.textContent="Unlink from PlotDirector"),po()}}else oo("Unlink cancelled.")}),Se?.addEventListener("click",async()=>{console.debug("Word Companion clean and unlink clicked");const e=Na();if(!fn||!In||!window.Word||"function"!=typeof window.Word.run)return void oo("Word document access is unavailable.");oo("Inspecting PlotDirector markers...");try{await ho()}catch(e){return void oo(`Unable to inspect markers: ${ta(e)}`)}if(await new Promise(e=>{const t=`This will remove PlotDirector hidden anchors from this Word document while preserving manuscript text.\n\nThis will remove:\n${Vr.chapterCount} PlotDirector chapter markers\n${Vr.sceneCount} PlotDirector scene markers\nthe document's PlotDirector binding\n\nThe document can be linked again later if desired.\n\nContinue?`;if(!B||"function"!=typeof B.showModal)return void e(window.confirm(t));const n=t=>{H?.removeEventListener("click",r),G?.removeEventListener("click",o),B?.removeEventListener("cancel",a),B?.close(),e(t)},r=()=>n(!0),o=()=>n(!1),a=e=>{e.preventDefault(),n(!1)};H?.addEventListener("click",r),G?.addEventListener("click",o),B?.addEventListener("cancel",a),B.showModal()})){Se&&(Se.disabled=!0,Se.textContent="Cleaning..."),be&&(be.disabled=!0);try{oo("Removing PlotDirector hidden anchors..."),await(async()=>{if(!fn||!In||!window.Word||"function"!=typeof window.Word.run)throw new Error("Word document access is unavailable.");return await window.Word.run(async e=>{const t=e.document.contentControls;t.load("items/tag,title"),await e.sync();let n=0,r=0;for(const e of t.items||[]){const t=_r(e);t&&("chapter"===t?n+=1:"scene"===t&&(r+=1),e.delete(!0))}return await e.sync(),{chapterCount:n,sceneCount:r,totalCount:n+r,available:!0,message:"PlotDirector markers removed."}})})(),await new Promise(e=>{const t=window.Office?.context?.document;t&&"function"==typeof t.saveAsync?t.saveAsync(t=>{const n=t.status===window.Office.AsyncResultStatus.Succeeded;var r;e({saveState:n?"Saved":"Failed",saveApi:"Office.context.document.saveAsync",...Aa(),...n?{}:(r=t.error,{errorName:r?.name||"",errorCode:r?.code||"",errorMessage:r?.message||ta(r)})})}):e({saveState:"Unsupported",saveApi:"Office.context.document.saveAsync",...Aa(),errorMessage:"Office.context.document.saveAsync is not available in this Word host."})});try{await ho()}catch(e){return console.error("Unable to verify PlotDirector marker cleanup.",e),void oo(`PlotDirector markers were removed, but cleanup verification failed: ${ta(e)}`)}if(Vr.available&&Vr.totalCount>0)return void oo(`Cleanup stopped: ${Vr.totalCount} PlotDirector marker${1===Vr.totalCount?"":"s"} remain.`);oo("Removing PlotDirector binding metadata...");try{await qa()}catch(e){return console.error("Unable to remove Word document metadata after marker cleanup.",e),void oo(`PlotDirector markers were removed, but Word binding metadata remains: ${ta(e)}`)}let t="";if(e?.documentGuid&&Number.isInteger(e.bookId)&&e.bookId>0)try{await $c("/api/word-companion/manuscript/unlink",{documentGuid:e.documentGuid,bookId:e.bookId})}catch(e){console.error("Word document cleaned, but PlotDirector server unlink failed.",e),t=" Word document is clean, but unlink the Book manually in PlotDirector if it still shows as linked."}await ho().catch(()=>null),await Mc(`Word document cleaned and unlinked.${t}`)}catch(e){console.error("Unable to clean PlotDirector markers.",e),oo(`Cleanup failed before unlinking: ${ta(e)}`)}finally{Se&&(Se.disabled=!1,Se.textContent="Clean and unlink"),be&&(be.disabled=!1),po(),mo()}}else oo("Clean and unlink cancelled.")}),Ne?.addEventListener("click",()=>wa("workspace")),Le?.addEventListener("click",()=>wa("context")),qe?.addEventListener("click",()=>wa("intent")),ct?.addEventListener("click",async()=>{const e=la();if(!e||!Cn||Nn)return void Uo("Chapter not found in PlotDirector.");const t=Vo(Cn),n=await((e,t)=>(Zo($t,`"${e}"`),Zo(Tt,`"${t}"`),At?new Promise(e=>{Un=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,ia(e)||"selected book");if(n){ct&&(ct.disabled=!0,ct.textContent="Creating...");try{const n=Number.isInteger(xn)&&xn>0?10*xn:null,r=await $c(`/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.");qo(),xo(null,r.chapterId,"Manual chapter link");if(!await Hc("Chapter created and linked successfully."))return;await Gc("Chapter created and linked successfully.")}catch(e){To("Unable to create chapter."),ea({lastError:ta(e)})}finally{ct&&(ct.disabled=!Wo(),ct.textContent="Create Chapter in PlotDirector")}}}),it?.addEventListener("click",async()=>{const e=la();if(e&&Cn&&!Nn){it&&(it.disabled=!0,it.textContent="Loading...");try{jn=await Jo(e.bookId),Mn=null,Pt&&(Pt.value=""),Zo(qt,""),Vc(),Dt?.showModal?Dt.showModal():Dt&&(Dt.hidden=!1)}catch(e){To("Unable to load chapters."),ea({lastError:ta(e)})}finally{it&&(it.disabled=!Wo(),it.textContent="Link to Existing Chapter")}}else Uo("Chapter not found in PlotDirector.")}),Pt?.addEventListener("input",Vc),Nt?.addEventListener("click",async()=>{const e=jn.find(e=>e.chapterId===Mn);if(e){Nt&&(Nt.disabled=!0,Nt.textContent="Linking...");try{xo(null,e.chapterId,"Manual chapter link");if(!await Hc("Chapter linked successfully."))return;Kc(),await Gc("Chapter linked successfully.")}catch(e){Zo(qt,"Unable to link chapter."),To("Unable to link chapter."),ea({lastError:ta(e)})}finally{Nt&&(Nt.disabled=!Mn,Nt.textContent="Link Chapter")}}else Zo(qt,"Select a chapter.")}),Lt?.addEventListener("click",Kc),Wt?.addEventListener("click",()=>Fc(!0)),jt?.addEventListener("click",()=>Fc(!1)),At?.addEventListener("cancel",e=>{e.preventDefault(),Fc(!1)}),pt?.addEventListener("click",async()=>{const e=la();if(!e||!kn)return void Oo("Scene not found in PlotDirector.");const t=Ko(kn,"scene"),n=Ko(Cn,"chapter"),r=await((e,t)=>(Zo(Ct,`"${e}"`),Zo(kt,`"${t}"`),St?new Promise(e=>{Wn=e,St.showModal?St.showModal():St.hidden=!1}):Promise.resolve(window.confirm(`Create PlotDirector scene:\n\n"${e}"\n\nwithin chapter:\n\n"${t}"\n\n?`))))(t,n);if(r){pt&&(pt.disabled=!0,pt.textContent="Creating...");try{const n=await Qo();if(!n)return void Oo("This chapter does not exist in PlotDirector. Create or link the chapter first.");const r=await $c(`/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.");qo(),await Yc(r.sceneId,r.chapterId,"Scene created and linked successfully.")}catch(e){$o("Unable to create scene."),ea({lastError:ta(e)})}finally{pt&&(pt.disabled=!jo(),pt.textContent="Create Scene in PlotDirector")}}}),mt?.addEventListener("click",async()=>{const e=la();if(e&&kn){mt&&(mt.disabled=!0,mt.textContent="Loading...");try{const t=await _o(e.bookId),n=zo(t);if(!n)return void Oo("This chapter does not exist in PlotDirector. Create or link the chapter first.");$n=Array.isArray(n.scenes)?n.scenes:[],Tn=null,wt&&(wt.value=""),Zo(bt,""),Jc(),gt?.showModal?gt.showModal():gt&&(gt.hidden=!1)}catch(e){$o("Unable to load scenes."),ea({lastError:ta(e)})}finally{mt&&(mt.disabled=!jo(),mt.textContent="Link to Existing Scene")}}else Oo("Scene not found in PlotDirector.")}),wt?.addEventListener("input",Jc),ft?.addEventListener("click",async()=>{const e=la(),t=$n.find(e=>e.sceneId===Tn);if(e&&t){ft&&(ft.disabled=!0,ft.textContent="Linking...");try{const e=await Qo();if(!e)throw new Error("This chapter does not exist in PlotDirector. Create or link the chapter first.");zc(),await Yc(t.sceneId,e.chapterId,"Scene linked successfully.")}catch(e){Zo(bt,"Unable to link scene."),$o("Unable to link scene."),ea({lastError:ta(e)})}finally{ft&&(ft.disabled=!Tn,ft.textContent="Link Scene")}}else Zo(bt,"Select a scene.")}),It?.addEventListener("click",zc),vt?.addEventListener("click",()=>_c(!0)),xt?.addEventListener("click",()=>_c(!1)),St?.addEventListener("cancel",e=>{e.preventDefault(),_c(!1)}),Xt?.addEventListener("click",async()=>{Xt&&(Xt.disabled=!0,Xt.textContent="Running...");try{if(await na(),!fn||!In||!window.Word||"function"!=typeof window.Word.run)return void ea({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});ea({lastScan:"Success",lastError:"-",paragraphs:String(e)})}catch(e){console.error("Word Companion diagnostics failed.",e);const t=ta(e);ea({lastScan:"Failure",lastError:t}),oo(`Unable to scan the Word document: ${t}`)}finally{Xt&&(Xt.disabled=!1,Xt.textContent="Run Diagnostics")}});const Ii=mn?(async()=>{aa(J,"Loading projects..."),aa(z,"Select a project first"),aa(w,"Loading projects..."),aa(y,"Select a project first"),no(""),ro("");try{const n=await Ac("/api/word-companion/projects");if(wn=Array.isArray(n.projects)?n.projects:[],0===wn.length)return aa(J,"No projects available."),aa(w,"No projects available."),no("No projects available."),oa(e,null),oa(t,null),Ma(),void xa("No projects available.");ca(J,"Choose a project",wn,"projectId","title"),va();const r=ra(e),o=wn.find(e=>e.projectId===r);o&&J?(J.value=String(o.projectId),w&&(w.value=String(o.projectId)),oa(e,o.projectId),await fi(o.projectId,ra(t))):(oa(e,null),oa(t,null),Ma(),xa("Select a Project and Book to begin."))}catch{wn=[],yn=[],aa(J,"Unable to connect to PlotDirector."),aa(z,"Select a project first"),aa(w,"Unable to connect to PlotDirector."),aa(y,"Select a project first"),to("Unable to connect to PlotDirector."),no("Unable to connect to PlotDirector."),oa(e,null),oa(t,null),Ma(),xa("Unable to connect to PlotDirector.")}})():Promise.resolve();if(mn||(aa(J,"Please sign in to PlotDirector."),aa(z,"Please sign in to PlotDirector."),aa(w,"Please sign in to PlotDirector."),aa(y,"Please sign in to PlotDirector."),Ma()),!window.Office||"function"!=typeof window.Office.onReady)return Qr("Word Companion ready"),oo("Word document access is unavailable."),ko("Manual"),ea({host:"Unavailable",platform:"Unavailable",ready:"No",wordApi:"No"}),void ba().catch(e=>{console.debug("Word Companion presence unavailable.",e)});na().then(async()=>{Qr("Word Companion ready"),await Ii,await(async()=>{if(!mn||!In)return void ka(!1);const n=Ea();if(n)try{const r=await Ac(`/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 On=n,No(r),oa(e,r.projectId),oa(t,r.bookId),J&&(J.value=String(r.projectId)),await fi(r.projectId,r.bookId),ka(!1),to("Connected"),ro("Bound manuscript detected."),void await jc()}catch{}On=null,Lo(),va(),ua()?await fi(ua().projectId,null):aa(y,"Select a project first"),xa("Select a Project and Book to begin."),ka(!0)})(),await ba(),In?(await ho().catch(()=>null),(()=>{if(mn){if(!window.Office?.context?.document||"function"!=typeof window.Office.context.document.addHandlerAsync||!window.Office?.EventType?.DocumentSelectionChanged)return ko("Manual"),void oo("Automatic scene tracking is unavailable in this Word version. Use Refresh Current Scene.");try{window.Office.context.document.addHandlerAsync(window.Office.EventType.DocumentSelectionChanged,wi,e=>{e?.status===window.Office.AsyncResultStatus.Succeeded?(mr=!0,ko("Live")):(ko("Manual"),oo("Automatic scene tracking is unavailable in this Word version. Use Refresh Current Scene."))}),window.addEventListener("beforeunload",yi)}catch(e){console.warn("Unable to register Word selection tracking handler.",e),ko("Manual"),oo("Automatic scene tracking is unavailable in this Word version. Use Refresh Current Scene.")}}})()):(oo("Word document access is unavailable."),ko("Manual"))}).catch(e=>{console.error("Office readiness check failed.",e),to("Unable to connect to PlotDirector."),Qr("Word Companion unavailable"),oo("Word document access is unavailable."),ea({ready:"No",wordApi:"No",lastScan:"Failure"})})})(); \ No newline at end of file