From 5ff2713afbb6c76c1efb3a896ceb1c7a20814de4 Mon Sep 17 00:00:00 2001 From: Nick Beckley Date: Mon, 29 Jun 2026 14:30:48 +0100 Subject: [PATCH] Phase 16Q Fix - Word Companion Unlink Button Does Nothing --- PlotLine/Views/WordCompanionHost/Index.cshtml | 15 ++++ PlotLine/wwwroot/js/word-companion-host.js | 90 ++++++++++++++++--- .../wwwroot/js/word-companion-host.min.js | 2 +- 3 files changed, 95 insertions(+), 12 deletions(-) diff --git a/PlotLine/Views/WordCompanionHost/Index.cshtml b/PlotLine/Views/WordCompanionHost/Index.cshtml index 78803f8..3d53302 100644 --- a/PlotLine/Views/WordCompanionHost/Index.cshtml +++ b/PlotLine/Views/WordCompanionHost/Index.cshtml @@ -498,6 +498,21 @@ + + +
+
+ Unlink Word Document? +
+

This will remove PlotDirector binding metadata from this Word document.

+

If PlotDirector is reachable, it will also unlink this Book in PlotDirector.

+

Your manuscript text will not be changed.

+
+ + +
+
+
} diff --git a/PlotLine/wwwroot/js/word-companion-host.js b/PlotLine/wwwroot/js/word-companion-host.js index d0d857d..3fb1def 100644 --- a/PlotLine/wwwroot/js/word-companion-host.js +++ b/PlotLine/wwwroot/js/word-companion-host.js @@ -38,6 +38,9 @@ const firstRunReplaceDialog = document.querySelector("[data-first-run-replace-dialog]"); const firstRunReplaceConfirm = document.querySelector("[data-first-run-replace-confirm]"); const firstRunReplaceCancel = document.querySelector("[data-first-run-replace-cancel]"); + const unlinkWordDocumentDialog = document.querySelector("[data-unlink-word-document-dialog]"); + const unlinkWordDocumentConfirm = document.querySelector("[data-unlink-word-document-confirm]"); + const unlinkWordDocumentCancel = document.querySelector("[data-unlink-word-document-cancel]"); const officeStatus = document.querySelector("[data-office-status]"); const connectionStatus = document.querySelector("[data-connection-status]"); const summaryConnection = document.querySelector("[data-summary-connection]"); @@ -1343,6 +1346,27 @@ }; }; + const currentDocumentBinding = () => { + const binding = firstRunDocumentBinding || readDocumentBinding(); + if (binding) { + return binding; + } + + const documentGuid = runtimeBookContext?.manuscriptDocument?.documentGuid || ""; + const bookId = Number.parseInt(runtimeBookContext?.bookId || "", 10); + const projectId = Number.parseInt(runtimeBookContext?.projectId || "", 10); + if (documentGuid && Number.isInteger(bookId) && bookId > 0 && Number.isInteger(projectId) && projectId > 0) { + return { + documentGuid, + bookId, + projectId, + bindingVersion: Number.parseInt(runtimeBookContext?.manuscriptDocument?.bindingVersion || "", 10) || 1 + }; + } + + return null; + }; + const writeDocumentBinding = (binding) => new Promise((resolve, reject) => { const settings = window.Office?.context?.document?.settings; if (!settings) { @@ -2905,6 +2929,32 @@ firstRunReplaceDialog.showModal(); }); + const requestUnlinkWordDocumentConfirmation = () => new Promise((resolve) => { + if (!unlinkWordDocumentDialog || typeof unlinkWordDocumentDialog.showModal !== "function") { + resolve(window.confirm("This will remove PlotDirector binding metadata from this Word document.\n\nIf PlotDirector is reachable, it will also unlink this Book in PlotDirector.\n\nYour manuscript text will not be changed.\n\nContinue?")); + return; + } + + const cleanup = (confirmed) => { + unlinkWordDocumentConfirm?.removeEventListener("click", confirmHandler); + unlinkWordDocumentCancel?.removeEventListener("click", cancelHandler); + unlinkWordDocumentDialog?.removeEventListener("cancel", cancelEventHandler); + unlinkWordDocumentDialog?.close(); + resolve(confirmed); + }; + const confirmHandler = () => cleanup(true); + const cancelHandler = () => cleanup(false); + const cancelEventHandler = (event) => { + event.preventDefault(); + cleanup(false); + }; + + unlinkWordDocumentConfirm?.addEventListener("click", confirmHandler); + unlinkWordDocumentCancel?.addEventListener("click", cancelHandler); + unlinkWordDocumentDialog?.addEventListener("cancel", cancelEventHandler); + unlinkWordDocumentDialog.showModal(); + }); + const importFirstRunManuscript = async () => { const project = selectedFirstRunProject(); const book = selectedFirstRunBook(); @@ -3175,33 +3225,50 @@ const returnToUnboundOnboarding = async (message) => { firstRunDocumentBinding = null; + cancelPendingRuntimeUpdate(); + clearPendingSceneWordCountSync(); clearRuntimeCaches(); resetPlotDirectorScene("Not detected"); setSceneTrackingState("Manual"); setConnectionStatus("Connected"); - syncFirstRunProjectOptions(); - if (selectedFirstRunProject()) { - await loadBooks(selectedFirstRunProject().projectId, null); - } else { - resetSelect(firstRunBookSelect, "Select a project first"); + writeStoredId(storageKeys.projectId, null); + writeStoredId(storageKeys.bookId, null); + if (projectSelect) { + projectSelect.value = ""; } + resetSelect(bookSelect, "Select a project first"); + syncFirstRunProjectOptions(); + if (firstRunProjectSelect) { + firstRunProjectSelect.value = ""; + } + resetSelect(firstRunBookSelect, "Select a project first"); resetFirstRunPreview(message || "Select a Project and Book to begin."); + setDocumentMessage(message || "Manuscript unlinked."); + setSyncStatus("No resolved PlotDirector scene."); setFirstRunMode(true); updateUnlinkWordDocumentButton(); }; const unlinkThisWordDocument = async () => { - const binding = firstRunDocumentBinding || readDocumentBinding(); + console.debug("Word Companion unlink clicked"); + setDocumentMessage("Preparing to unlink manuscript..."); + const binding = currentDocumentBinding(); if (!binding) { setDocumentMessage("This Word document is not linked."); return; } - - const confirmed = window.confirm("This will remove PlotDirector binding metadata from this Word document.\n\nIf PlotDirector is reachable, it will also unlink this Book in PlotDirector.\n\nYour manuscript text will not be changed.\n\nContinue?"); - if (!confirmed) { + if (!binding.documentGuid || !Number.isInteger(binding.bookId) || binding.bookId <= 0) { + setDocumentMessage("Unable to unlink: bound document metadata is incomplete."); return; } + const confirmed = await requestUnlinkWordDocumentConfirmation(); + if (!confirmed) { + setDocumentMessage("Unlink cancelled."); + return; + } + + setDocumentMessage("Unlinking manuscript..."); if (unlinkWordDocumentButton) { unlinkWordDocumentButton.disabled = true; unlinkWordDocumentButton.textContent = "Unlinking..."; @@ -3213,10 +3280,11 @@ bookId: binding.bookId }); await removeDocumentBinding(); - await returnToUnboundOnboarding("Word document unlinked. Select a Project and Book to begin."); + await returnToUnboundOnboarding("Manuscript unlinked."); } catch (error) { console.error("Unable to unlink manuscript binding.", error); - const removeLocalOnly = 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 Word metadata only?"); + setDocumentMessage("Unable to unlink from PlotDirector."); + const removeLocalOnly = 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?"); if (removeLocalOnly) { try { await removeDocumentBinding(); diff --git a/PlotLine/wwwroot/js/word-companion-host.min.js b/PlotLine/wwwroot/js/word-companion-host.min.js index f9aac88..c103836 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","links","structure","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-first-run-wizard]"),l=document.querySelector("[data-first-run-project-select]"),u=document.querySelector("[data-first-run-book-select]"),p=document.querySelector("[data-first-run-new-book-title]"),h=document.querySelector("[data-first-run-create-book]"),m=document.querySelector("[data-first-run-scan]"),y=document.querySelector("[data-first-run-cancel]"),g=document.querySelector("[data-first-run-status]"),f=document.querySelector("[data-first-run-summary]"),w=document.querySelector("[data-first-run-character-section]"),I=document.querySelector("[data-first-run-character-status]"),S=document.querySelector("[data-first-run-character-candidates]"),b=document.querySelector("[data-first-run-character-actions]"),C=document.querySelector("[data-first-run-create-characters]"),k=document.querySelector("[data-first-run-skip-characters]"),v=document.querySelector("[data-first-run-continue]"),x=document.querySelector("[data-first-run-import-actions]"),N=document.querySelector("[data-first-run-import]"),E=document.querySelector("[data-first-run-import-cancel]"),L=document.querySelector("[data-first-run-replace-dialog]"),P=document.querySelector("[data-first-run-replace-confirm]"),q=document.querySelector("[data-first-run-replace-cancel]"),D=document.querySelector("[data-office-status]"),A=document.querySelector("[data-connection-status]"),$=document.querySelector("[data-summary-connection]"),T=document.querySelector("[data-summary-project]"),j=document.querySelector("[data-summary-book]"),W=document.querySelector("[data-project-select]"),R=document.querySelector("[data-book-select]"),U=document.querySelector("[data-project-message]"),M=document.querySelector("[data-book-message]"),O=document.querySelector("[data-refresh-current-scene]"),B=document.querySelector("[data-refresh-document]"),H=document.querySelector("[data-current-chapter]"),G=document.querySelector("[data-current-scene]"),F=document.querySelector("[data-current-word-count]"),V=document.querySelector("[data-scene-tracking-status]"),Y=document.querySelector("[data-document-message]"),J=document.querySelector("[data-sync-note]"),_=document.querySelector("[data-document-outline]"),z=document.querySelector("[data-analyse-manuscript-structure]"),K=document.querySelector("[data-apply-structure-sync]"),Q=document.querySelector("[data-structure-preview-status]"),X=document.querySelector("[data-structure-preview-results]"),Z=document.querySelector("[data-refresh-plotdirector-scene]"),ee=document.querySelector("[data-plotdirector-scene-status]"),te=document.querySelector("[data-anchor-status]"),ne=document.querySelector("[data-anchor-book-id]"),re=document.querySelector("[data-anchor-chapter-id]"),oe=document.querySelector("[data-anchor-scene-id]"),ae=document.querySelector("[data-attach-plotdirector-ids]"),ce=document.querySelector("[data-unlink-word-document]"),ie=document.querySelector("[data-plotdirector-scene-details]"),se=document.querySelector("[data-plotdirector-scene-title]"),de=document.querySelector("[data-plotdirector-revision-status]"),le=document.querySelector("[data-plotdirector-estimated-words]"),ue=document.querySelector("[data-plotdirector-actual-words]"),pe=document.querySelector("[data-plotdirector-blocked-status]"),he=document.querySelector("[data-plotdirector-blocked-reason-row]"),me=document.querySelector("[data-plotdirector-blocked-reason]"),ye=document.querySelector("[data-runtime-last-sync]"),ge=document.querySelector("[data-sync-scene-progress]"),fe=document.querySelector("[data-sync-word-count]"),we=document.querySelector("[data-sync-plotdirector-count]"),Ie=document.querySelector("[data-sync-last-synced]"),Se=document.querySelector("[data-sync-status]"),be=document.querySelector("[data-writing-brief-block]"),Ce=document.querySelector("[data-writing-brief]"),ke=document.querySelector("[data-plotdirector-link-groups]"),ve=document.querySelector("[data-character-chips]"),xe=document.querySelector("[data-asset-chips]"),Ne=(document.querySelector("[data-location-chips]"),document.querySelector("[data-primary-location-select]")),Ee=document.querySelector("[data-save-scene-links]"),Le=document.querySelector("[data-scene-links-status]"),Pe=document.querySelector("[data-links-editing-scene]"),qe=document.querySelector("[data-chapter-create-link]"),De=document.querySelector("[data-chapter-create-link-chapter]"),Ae=document.querySelector("[data-create-plotdirector-chapter]"),$e=document.querySelector("[data-link-existing-chapter]"),Te=document.querySelector("[data-chapter-create-link-status]"),je=document.querySelector("[data-scene-create-link]"),We=document.querySelector("[data-create-link-chapter]"),Re=document.querySelector("[data-create-link-scene]"),Ue=document.querySelector("[data-create-plotdirector-scene]"),Me=document.querySelector("[data-link-existing-scene]"),Oe=document.querySelector("[data-create-link-status]"),Be=document.querySelector("[data-link-existing-dialog]"),He=document.querySelector("[data-link-scene-search]"),Ge=document.querySelector("[data-link-scene-options]"),Fe=document.querySelector("[data-link-selected-scene]"),Ve=document.querySelector("[data-link-dialog-cancel]"),Ye=document.querySelector("[data-link-dialog-status]"),Je=document.querySelector("[data-create-scene-dialog]"),_e=document.querySelector("[data-create-dialog-scene]"),ze=document.querySelector("[data-create-dialog-chapter]"),Ke=document.querySelector("[data-create-dialog-confirm]"),Qe=document.querySelector("[data-create-dialog-cancel]"),Xe=document.querySelector("[data-link-existing-chapter-dialog]"),Ze=document.querySelector("[data-link-chapter-search]"),et=document.querySelector("[data-link-chapter-options]"),tt=document.querySelector("[data-link-selected-chapter]"),nt=document.querySelector("[data-link-chapter-dialog-cancel]"),rt=document.querySelector("[data-link-chapter-dialog-status]"),ot=document.querySelector("[data-create-chapter-dialog]"),at=document.querySelector("[data-create-chapter-dialog-chapter]"),ct=document.querySelector("[data-create-chapter-dialog-book]"),it=document.querySelector("[data-create-chapter-dialog-confirm]"),st=document.querySelector("[data-create-chapter-dialog-cancel]"),dt=document.querySelector("[data-apply-structure-sync-dialog]"),lt=document.querySelector("[data-apply-structure-sync-summary]"),ut=document.querySelector("[data-apply-structure-sync-confirm]"),pt=document.querySelector("[data-apply-structure-sync-cancel]"),ht=document.querySelector("[data-resolve-project-id]"),mt=document.querySelector("[data-resolve-project-title]"),yt=document.querySelector("[data-resolve-book-id]"),gt=document.querySelector("[data-resolve-book-title]"),ft=document.querySelector("[data-resolve-detected-chapter]"),wt=document.querySelector("[data-resolve-detected-scene]"),It=document.querySelector("[data-resolve-request-chapter]"),St=document.querySelector("[data-resolve-request-scene]"),bt=document.querySelector("[data-resolve-result]"),Ct=document.querySelector("[data-resolve-chapter-id]"),kt=document.querySelector("[data-resolve-scene-id]"),vt=document.querySelector("[data-run-diagnostics]"),xt=document.querySelector("[data-diagnostic-host]"),Nt=document.querySelector("[data-diagnostic-platform]"),Et=document.querySelector("[data-diagnostic-ready]"),Lt=document.querySelector("[data-diagnostic-word-api]"),Pt=document.querySelector("[data-diagnostic-last-scan]"),qt=document.querySelector("[data-diagnostic-last-error]"),Dt=document.querySelector("[data-diagnostic-anchor-type]"),At=document.querySelector("[data-diagnostic-stored-scene-id]"),$t=document.querySelector("[data-diagnostic-stored-chapter-id]"),Tt=document.querySelector("[data-diagnostic-resolution-method]"),jt=document.querySelector("[data-diagnostic-paragraphs]"),Wt=document.querySelector("[data-diagnostic-heading1]"),Rt=document.querySelector("[data-diagnostic-heading2]"),Ut="true"===a?.dataset.authenticated;let Mt=[],Ot=[],Bt=!1,Ht=!1,Gt="Unknown",Ft="Unknown",Vt="",Yt="",Jt=null,_t=null,zt=null,Kt=null,Qt=null,Xt=null,Zt="",en="Title Match",tn=!1,nn=[],rn=null,on=null,an=[],cn=null,sn=null,dn=null,ln=null,un=null,pn=null,hn=null,mn=null,yn=null,gn=null,fn=[],wn=!1,In=!1,Sn=0,bn=!1,Cn=!1,kn=!1,vn=null,xn="Manual",Nn=!1,En=null,Ln=!1,Pn=0,qn=!1,Dn=0,An=null;const $n=1200;let Tn=!1,jn=!1,Wn=null,Rn=!1,Un=!1,Mn=null,On=null,Bn=null,Hn=!1,Gn=!1,Fn=null,Vn="",Yn=[],Jn=null,_n="",zn=null,Kn="",Qn=[],Xn=null,Zn="",er=null,tr="",nr=[],rr=null,or="",ar="",cr="",ir="",sr=0,dr={characters:[],assets:[],locations:[],primaryLocationId:null};const lr=e=>{const t=Date.now();t-sr<1e3||(sr=t,console.debug(`[Word Companion Runtime] ${e}`))},ur=e=>{console.debug(`[Word Companion Timing] ${e}`)},pr=e=>{D&&(D.textContent=e)},hr=(e,t=!0)=>{const r=o.has(e)&&i.some(t=>t.dataset.tabButton===e)?e:"scene";for(const e of i){const t=e.dataset.tabButton===r;e.classList.toggle("is-active",t),e.setAttribute("aria-selected",t?"true":"false")}for(const e of s){const t=e.dataset.tabPanel===r;e.classList.toggle("is-active",t),e.hidden=!t}t&&((e,t)=>{try{t?window.localStorage.setItem(e,String(t)):window.localStorage.removeItem(e)}catch{}})(n,r)},mr=()=>{const e=(e=>{try{return window.localStorage.getItem(e)||""}catch{return""}})(n);hr(o.has(e)?e:"scene",!1)},yr=e=>{A&&(A.textContent=e),$&&($.textContent=e)},gr=e=>{U&&(U.textContent=e)},fr=e=>{M&&(M.textContent=e)},wr=e=>{Y&&(Y.textContent=e)},Ir=e=>{ee&&(ee.textContent=e)},Sr=e=>{const t=t=>Object.prototype.hasOwnProperty.call(e,t);t("anchorType")&&uo(Dt,Ur(e.anchorType)),t("storedSceneId")&&uo(At,Ur(e.storedSceneId)),t("storedChapterId")&&uo($t,Ur(e.storedChapterId)),t("resolutionMethod")&&uo(Tt,Ur(e.resolutionMethod))},br=()=>{const e=bo(),t=Number.isInteger(Qt)&&Qt>0&&Kt===Qt,n=!Number.isInteger(Xt)||Xt<=0||zt===Xt,r=t&&n;uo(te,r?"Attached to PlotDirector":"Not attached"),uo(ne,e?.bookId?String(e.bookId):"-"),uo(re,Number.isInteger(Xt)&&Xt>0?String(Xt):"-"),uo(oe,Number.isInteger(Qt)&&Qt>0?String(Qt):"-"),ae&&(ae.disabled=!Qt||r&&!tn,ae.textContent=Kt&&!r?"Reattach PlotDirector IDs":"Attach PlotDirector IDs"),Sr({anchorType:en||"Title Match",storedSceneId:Kt,storedChapterId:zt,resolutionMethod:Zt})},Cr=(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=Vt===c&&Yt===i&&Jt===s&&_t===d&&zt===l&&Kt===u;Vt=e||"",Yt=t||"",Jt=Number.isInteger(n)?n:null,_t=Number.isInteger(a)&&a>0?a:null,zt=Number.isInteger(r)&&r>0?r:null,Kt=Number.isInteger(o)&&o>0?o:null,p||(H&&(H.textContent=e||"Not detected"),G&&(G.textContent=t||"Not detected"),F&&(F.textContent=Number.isInteger(n)?String(n):"-"),uo(fe,Number.isInteger(n)?String(n):"-"),br())},kr=()=>{Wn&&(window.clearTimeout(Wn),Wn=null)},vr=(e,t)=>{e&&(e.hidden=t)},xr=()=>{vr(ce,!ln)},Nr=e=>{uo(Se,e)},Er=e=>{uo(Q,e)},Lr=(e="Select a project and book to analyse manuscript structure.")=>{if(dn=null,X){X.innerHTML="";const e=document.createElement("p");e.textContent="No preview generated.",X.append(e)}Er(e),qr()},Pr=(e=dn)=>((e=dn)=>Ko.flatMap(t=>Array.isArray(e?.[t.key])?e[t.key]:[]))(e).filter(e=>"couldLink"===e.category||"wouldCreateChapters"===e.category||"wouldCreateScenes"===e.category),qr=()=>{K&&(K.disabled=kn||0===Pr().length)},Dr=()=>{z&&(z.disabled=kn||!So()||!bo()),qr()},Ar=()=>{Pe&&(Pe.textContent=Qt?`Editing links for: ${cr||Yt||"Current scene"}`:"Link a PlotDirector scene first.")},$r=()=>{const e=Nn||!Qt,t=e||!Xt||Rn;ge&&(ge.disabled=t),Ee&&(Ee.disabled=e),Ne&&(Ne.disabled=e);for(const t of[ve,xe])for(const n of t?[...t.querySelectorAll("input[type='checkbox']")]:[])n.disabled=e},Tr=e=>{"Live"!==e&&"Manual"!==e||(xn=e),uo(V,e||xn||"Manual")},jr=(e,t="")=>{Nn=!!e,Nn&&(kr(),Fa()),uo(V,Nn?"Stale":xn),$r(),t&&(wr(t),Gr(t))},Wr=(e,t=null,n="")=>{Qt=Number.isInteger(e)&&e>0?e:null,Xt=Number.isInteger(t)&&t>0?t:null,Zt=n||"",Qt!==Mn&&(On=null),Qt||(kr(),Fa()),$r(),Nr(Nn?"Refresh Current Scene before syncing.":Qt?"Ready to sync.":"No resolved PlotDirector scene."),Gr(Nn?"Refresh Current Scene before saving.":Qt?"Ready to save.":"Link a PlotDirector scene first."),Ar(),br()},Rr=e=>{O&&(O.disabled=e,O.textContent=e?"Refreshing...":"Refresh Current Scene")},Ur=e=>null==e||""===e?"-":String(e),Mr=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"})}`},Or=e=>{un=e||null;const t=un?.lastSyncUtc||un?.manuscriptDocument?.lastSyncUtc;uo(ye,Mr(t)),uo(Ie,Mr(t))},Br=()=>{pn=null,hn=null,mn=null,Dn+=1,An=null,Va(),Ya(),Ja(),Or(null)},Hr=()=>{hn=null,mn=null},Gr=e=>{uo(Le,e)},Fr=e=>{uo(Oe,e)},Vr=e=>{uo(Te,e)},Yr=()=>!!bo()&&!!Vt&&!Xt,Jr=()=>!!bo()&&!!Yt&&Number.isInteger(Xt)&&Xt>0,_r=()=>{vr(qe,!0),Vr(""),Ae&&(Ae.disabled=!0,Ae.textContent="Create Chapter in PlotDirector"),$e&&($e.disabled=!0,$e.textContent="Link to Existing Chapter")},zr=(e="")=>{uo(De,Ur(Vt)),vr(qe,!1),Vr(e);const t=Yr();Ae&&(Ae.disabled=!t,Ae.textContent="Create Chapter in PlotDirector"),$e&&($e.disabled=!t,$e.textContent="Link to Existing Chapter")},Kr=()=>{vr(je,!0),Fr(""),Ue&&(Ue.disabled=!0,Ue.textContent="Create Scene in PlotDirector"),Me&&(Me.disabled=!0,Me.textContent="Link to Existing Scene")},Qr=(e="")=>{uo(We,Ur(Vt)),uo(Re,Ur(Yt)),vr(je,!1),Fr(e);const t=Jr();Ue&&(Ue.disabled=!t,Ue.textContent="Create Scene in PlotDirector"),Me&&(Me.disabled=!t,Me.textContent="Link to Existing Scene")},Xr=e=>{Ir(e),vr(ie,!0),vr(be,!0),vr(ke,!1),_r(),Kr(),Zt="",cr="",ir="",en=Kt?"SceneID Anchor":zt?"ChapterID Anchor":"Title Match",tn=!1,dr={characters:[],assets:[],locations:[],primaryLocationId:null},eo(ve,[],"character"),eo(xe,[],"asset"),to([],null,!1),Wr(null),uo(we,"-"),uo(se,"-"),uo(de,"-"),uo(le,"-"),uo(ue,"-"),uo(pe,"-"),uo(me,"-"),vr(he,!0),br(),Ar()},Zr=(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,eo=(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(Zr(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)}},to=(e,t,n=!1)=>{if(!Ne)return;Ne.innerHTML="";const r=document.createElement("option");r.value="",r.textContent="None",Ne.append(r);const o=Number.parseInt(t||"",10);for(const t of Array.isArray(e)?e:[]){const e=Number.parseInt(Zr(t,"location"),10);if(!Number.isInteger(e)||e<=0)continue;const n=document.createElement("option");n.value=String(e),n.textContent=t.name||"Unnamed",n.selected=e===o,Ne.append(n)}Ne.disabled=!n},no=e=>String(e||"").trim().replace(/\s+/g," "),ro=(e,t)=>{const n=no(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 no(n.replace(r,""))||n},oo=e=>{const t=t=>Object.prototype.hasOwnProperty.call(e,t);t("projectId")&&uo(ht,Ur(e.projectId)),t("projectTitle")&&uo(mt,Ur(e.projectTitle)),t("bookId")&&uo(yt,Ur(e.bookId)),t("bookTitle")&&uo(gt,Ur(e.bookTitle)),t("detectedChapter")&&uo(ft,Ur(e.detectedChapter)),t("detectedScene")&&uo(wt,Ur(e.detectedScene)),t("requestChapter")&&uo(It,Ur(e.requestChapter)),t("requestScene")&&uo(St,Ur(e.requestScene)),t("result")&&uo(bt,Ur(e.result)),t("chapterId")&&uo(Ct,Ur(e.chapterId)),t("sceneId")&&uo(kt,Ur(e.sceneId))},ao=async e=>{if(mn===e&&Array.isArray(hn?.chapters))return hn.chapters;const t=await Ca(`/api/word-companion/books/${e}/structure`);return mn=e,hn=t||null,Array.isArray(t?.chapters)?t.chapters:[]},co=async e=>{const t=await Ca(`/api/word-companion/books/${e}/chapters`);return Array.isArray(t?.chapters)?t.chapters:[]},io=e=>{if(Number.isInteger(Xt)&&Xt>0){const t=e.find(e=>e.chapterId===Xt);if(t)return t}const t=ro(Vt,"chapter").toLocaleLowerCase();return t&&e.find(e=>ro(e.title,"chapter").toLocaleLowerCase()===t)||null},so=async()=>{const e=bo();return e?io(await ao(e.bookId)):null},lo=async(e,t,n,r,o)=>{const a=await Ca(`/api/word-companion/scenes/${t}/companion`);try{a.revisionStatus=await(async(e,t)=>{const n=await Ca(`/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;en=o||"Title Match",tn=!1,jr(!1),Ir("Linked to PlotDirector"),wr(""),_r(),Kr(),Wr(t,n,r),c=a,cr=c?.sceneTitle||Yt||"",ir=c?.chapterTitle||Vt||"",uo(se,Ur(c?.sceneTitle)),uo(de,Ur(c?.revisionStatus||c?.revisionStatusName||"Not provided")),uo(le,Ur(c?.estimatedWords)),uo(ue,Ur(c?.actualWords)),uo(we,Ur(c?.actualWords)),uo(pe,c?.blocked?"Blocked":"Not blocked"),c?.blockedReason?(uo(me,c.blockedReason),vr(he,!1)):(uo(me,"-"),vr(he,!0)),Ce&&(Ce.textContent=c?.writingBrief||"No writing brief has been added for this scene."),dr={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},eo(ve,dr.characters,"character",!!Qt&&!Nn),eo(xe,dr.assets,"asset",!!Qt&&!Nn),to(dr.locations,dr.primaryLocationId,!!Qt&&!Nn),Ar(),Gr(Nn?"Refresh Current Scene before saving.":Qt?"Ready to save.":"No resolved PlotDirector scene."),vr(ie,!1),vr(be,!1),vr(ke,!1),xa(t,n),Ga(),ec()},uo=(e,t)=>{if(e){const n=null==t?"":String(t);e.textContent!==n&&(e.textContent=n)}},po=e=>{const t=t=>Object.prototype.hasOwnProperty.call(e,t);t("host")&&uo(xt,e.host),t("platform")&&uo(Nt,e.platform),t("ready")&&uo(Et,e.ready),t("wordApi")&&uo(Lt,e.wordApi),t("lastScan")&&uo(Pt,e.lastScan),t("lastError")&&uo(qt,e.lastError),t("paragraphs")&&uo(jt,e.paragraphs),t("heading1")&&uo(Wt,e.heading1),t("heading2")&&uo(Rt,e.heading2)},ho=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)},mo=async()=>{if(!window.Office||"function"!=typeof window.Office.onReady)return Bt=!1,Ht=!1,Gt="Unavailable",Ft="Unavailable",po({host:Gt,platform:Ft,ready:"No",wordApi:"No"}),null;const e=await window.Office.onReady();return Bt=!0,Gt=e?.host||"Unknown",Ft=e?.platform||"Unknown",Ht=!!window.Word&&!!window.Office.HostType&&e?.host===window.Office.HostType.Word,po({host:Gt,platform:Ft,ready:"Yes",wordApi:Ht?"Yes":"No"}),e},yo=e=>{try{const t=window.localStorage.getItem(e),n=Number.parseInt(t||"",10);return Number.isInteger(n)&&n>0?n:null}catch{return null}},go=(e,t)=>{try{t?window.localStorage.setItem(e,String(t)):window.localStorage.removeItem(e)}catch{}},fo=(e,t)=>{if(!e)return;e.innerHTML="";const n=document.createElement("option");n.value="",n.textContent=t,e.append(n),e.disabled=!0},wo=(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},Io=e=>{const t=String(e?.title||"").trim(),n=String(e?.subtitle||"").trim();return n?`${t}: ${n}`:t},So=()=>{const e=Number.parseInt(W?.value||"",10);return Mt.find(t=>t.projectId===e)||null},bo=()=>{const e=Number.parseInt(R?.value||"",10);return Ot.find(t=>t.bookId===e)||null},Co=()=>{const e=Number.parseInt(l?.value||"",10);return Mt.find(t=>t.projectId===e)||null},ko=()=>{const e=Number.parseInt(u?.value||"",10);return Ot.find(t=>t.bookId===e)||null},vo=e=>uo(g,e),xo=()=>{const e=Co(),t=ko(),n=In&&Date.now()-Sn>=750;m&&(m.disabled=!e||!t||bn),h&&(h.disabled=!e||!String(p?.value||"").trim()||bn),N&&(N.disabled=!yn?.canImport||!gn||bn),C&&(C.disabled=!n||Cn||0===Po().length)},No=e=>{vr(d,!e),vr(c,e),xr();for(const t of s)vr(t,!!e||"scene"!==t.dataset.tabPanel&&!t.classList.contains("is-active"));e||mr()},Eo=()=>{if(!l)return;if(0===Mt.length)return void fo(l,"No projects available.");wo(l,"Choose a project",Mt,"projectId","title");const e=Number.parseInt(W?.value||"",10);Number.isInteger(e)&&e>0&&(l.value=String(e))},Lo=(e="Select a Project and Book to begin.")=>{yn=null,gn=null,fn=[],wn=!1,In=!1,Sn=0,vr(f,!0),vr(x,!0),vr(w,!0),vr(b,!0),f&&(f.innerHTML=""),S&&(S.innerHTML=""),uo(I,""),vo(e),xo()},Po=()=>S?[...S.querySelectorAll("input[type='checkbox']:checked")].map(e=>String(e.value||"").trim()).filter(Boolean):[],qo=e=>{if(fn=Array.isArray(e)?e:[],w&&S){if(S.innerHTML="",vr(w,!1),vr(b,!wn||0===fn.length),vr(C,!1),vr(k,!1),vr(v,!0),0===fn.length)return uo(I,"No likely major characters found."),void xo();uo(I,`${fn.length} likely major characters found.`);for(const e of fn){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",xo);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),S.append(t)}xo()}},Do=()=>{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}},Ao=()=>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."))}),$o=()=>ln?.documentGuid?ln.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)),To=()=>ln?.documentGuid||Do()?.documentGuid||"",jo=()=>{const e=So(),t=bo();T&&(T.textContent=e?.title||"(Not connected)"),j&&(j.textContent=t?Io(t):"(Not connected)"),J&&(J.textContent=t?"":"Select a PlotDirector book before refreshing."),Dr()},Wo=e=>String(e?.styleBuiltIn||e?.style||"").replace(/\s+/g,"").toLowerCase(),Ro=(e,t)=>{const n=Wo(e);return n===`heading${t}`||n.endsWith(`.heading${t}`)||n.includes(`heading${t}`)},Uo=e=>String(e||"").trim().split(/\s+/).filter(Boolean).length,Mo=(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},Oo=e=>{try{return Array.isArray(e?.contentControls?.items)?e.contentControls.items:[]}catch(e){return console.warn("Word paragraph content controls were not available.",e),[]}},Bo=(e,t)=>{const n=Oo(e);for(const e of n){const n=Mo(e.tag,t);if(n)return n}return null},Ho=(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(Ro(e,1))return r+=1,a={index:n.length+1,paragraphIndex:t,title:i,anchorId:Bo(e,"PD-CHAPTER"),scenes:[]},n.push(a),void(c=null);if(Ro(e,2)){if(o+=1,!a)return;return c={index:a.scenes.length+1,paragraphIndex:t,title:i,anchorId:Bo(e,"PD-SCENE"),wordCount:0},void a.scenes.push(c)}c&&(c.wordCount+=Uo(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()&&Wo(t)===Wo(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}},Go=new Set(["***","###"]),Fo=(e,t)=>{const n=String(e?.text||"").trim();return{index:t,text:n,styleBuiltIn:e?.styleBuiltIn||"",style:e?.style||"",wordCount:Uo(n),chapterAnchorId:null,sceneAnchorId:null}},Vo=(e,t)=>{e&&(e.endParagraphIndex=t)},Yo=(e,t)=>{e&&(e.endParagraphIndex=t,Vo(e.scenes.at(-1),t))},Jo=(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()&&Wo(e)===Wo(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(!pn)return!1;const t=((e,t)=>!e||!Number.isInteger(t)||t<0?null:e.chapters.filter(e=>e.startParagraphIndex<=t).at(-1)||null)(pn,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!==pn.currentChapter?.startParagraphIndex||n?.startParagraphIndex!==pn.currentScene?.startParagraphIndex||t?.anchorId!==pn.currentChapter?.anchorId||n?.anchorId!==pn.currentScene?.anchorId;return pn.currentParagraphIndex=e,pn.currentChapter=t,pn.currentScene=n,!!r&&(Cr(t?.title,n?.title,n?.wordCount,t?.anchorId,n?.anchorId,t?.index),r)},zo=e=>{if(!_)return;if(_.innerHTML="",0===e.chapters.length){const e=document.createElement("p");return e.textContent="No chapters detected. Use Heading 1 for chapter titles.",void _.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.",_.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)}_.append(e)}},Ko=[{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"}],Qo={alreadyLinked:"Already Linked",couldLink:"Could Link",wouldCreateChapter:"Would Create Chapter",wouldCreateScene:"Would Create Scene",manualReview:"Manual Review Required"},Xo={alreadyLinked:"✓",couldLink:"~",wouldCreateChapter:"+",wouldCreateScene:"+",manualReview:"?"},Zo=(e,t)=>ro(e,t).toLocaleLowerCase(),ea=({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:""}),ta=(e,t)=>{Array.isArray(e[t.category])&&e[t.category].push(t)},na=e=>Array.isArray(e?.scenes)?e.scenes:[],ra=(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=ea({category:"alreadyLinked",action:"alreadyLinked",type:"Chapter",wordTitle:e.title,match:`Chapter ${o.chapterId}: ${o.title}`,anchorStatus:r,pdChapter:o,wordChapter:e});return ta(n,t),t}const a=ea({category:"manualReview",action:"manualReview",type:"Chapter",wordTitle:e.title,anchorStatus:`${r} not found`,matches:[],pdChapter:null,wordChapter:e});return ta(n,a),a}const o=t.filter(t=>Zo(t.title,"chapter")===Zo(e.title,"chapter"));if(1===o.length){const t=ea({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 ta(n,t),t}if(o.length>1){const t=ea({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 ta(n,t),t}const a=ea({category:"wouldCreateChapters",action:"wouldCreateChapter",type:"Chapter",wordTitle:e.title,anchorStatus:r,pdChapter:null,wordChapter:e});return ta(n,a),a},oa=(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=na(n).find(e=>e.sceneId===t);if(e)return{chapter:n,scene:e}}return null})(n,e.anchorId);return a?void ta(r,ea({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 ta(r,ea({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 ta(r,ea({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 ta(r,ea({category:"wouldCreateScenes",action:"wouldCreateScene",type:"Scene",wordTitle:e.title,anchorStatus:o,wordChapter:t?.wordChapter,wordScene:e,parentItem:t}));const a=na(t.pdChapter).filter(t=>Zo(t.title,"scene")===Zo(e.title,"scene"));1!==a.length?a.length>1?ta(r,ea({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})):ta(r,ea({category:"wouldCreateScenes",action:"wouldCreateScene",type:"Scene",wordTitle:e.title,anchorStatus:o,pdChapter:t.pdChapter,wordChapter:t.wordChapter,wordScene:e,parentItem:t})):ta(r,ea({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}))},aa=e=>{const t=document.createElement("article");t.className="word-companion-preview-item";const n=document.createElement("strong");n.textContent=`${Xo[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: ${Qo[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},ca=e=>{if(X){X.innerHTML="";for(const t of Ko){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(aa(e));X.append(n)}qr()}},ia=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)(Ro(e,1)||Ro(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=Ho(t.items,n.items);return r.bodyParagraphs=t.items,r},sa=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(Fo),r=[];let o=0,a=0,c=null,i=null,s=0;const d=(e,t=null,n=null)=>c?(Vo(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&&(Ro(e,1)?(Yo(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&&Go.has(e.text)?(a+=1,d(e)):(c.wordCount+=e.wordCount,i&&(i.wordCount+=e.wordCount),s+=e.wordCount)));return Yo(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=Jo(o,r.items);return pn=o,_o(a),lr("Cache rebuilt."),o},da=()=>window.performance&&"function"==typeof window.performance.now?window.performance.now():Date.now(),la=e=>!!e&&!e.stale&&e.generation===Dn&&e.documentGuid===To()&&e.sceneId===Qt,ua=async(e={})=>{const t=!!e.includeSelection,n=!1!==e.updateDisplay,r=Dn,o=da(),a=So(),c=bo(),i=pn?.currentScene;if(!i||!Number.isInteger(i.startParagraphIndex)||!Number.isInteger(i.endParagraphIndex))return null;if(!Bt||!Ht||!window.Word||"function"!=typeof window.Word.run)return null;const s=da(),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(da()-s);if(r!==Dn)return ur(`Office snapshot: ${l}ms stale`),{stale:!0,generation:r};let u=!1;if(t){const e=Jo(pn,d.selectionParagraphs);u=_o(e)}const p=pn?.currentScene;if(!p||!Number.isInteger(p.startParagraphIndex)||!Number.isInteger(p.endParagraphIndex))return null;const h=[];let m=0;const y=Math.min(p.endParagraphIndex,d.bodyTexts.length-1),g=pn.currentChapter?.startParagraphIndex;for(let e=p.startParagraphIndex;e<=y;e+=1){const t=String(d.bodyTexts[e]||"").trim();t&&!Go.has(t)&&e!==g&&(h.push(t),m+=Uo(t))}p.wordCount=m,n&&Cr(pn.currentChapter?.title,p.title,m,pn.currentChapter?.anchorId,p.anchorId,pn.currentChapter?.index);const f={documentGuid:To(),projectId:a?.projectId||null,bookId:c?.bookId||null,chapterId:Xt,sceneId:Qt,chapterTitle:pn.currentChapter?.title||"",sceneTitle:p.title||"",sceneText:h.join("\n"),wordCount:m,selectionSignature:`${pn.currentParagraphIndex??-1}:${p.startParagraphIndex}:${p.endParagraphIndex}`,selectionChanged:u,generation:r};return An=f,ur(`Office snapshot: ${l}ms; scene words: ${m}; total snapshot: ${Math.round(da()-o)}ms`),f},pa=async()=>la(An)?An:await ua(),ha=async()=>{if(wr(""),!Bt||!Ht||!window.Word||"function"!=typeof window.Word.run)return Cr(null,null,null),wr("Word document access is unavailable."),po({lastScan:"Failure",lastError:"Word document access is unavailable."}),!1;B&&(B.disabled=!0,B.textContent="Scanning..."),wr("Scanning document structure...");try{const e=await window.Word.run(async e=>{const t=bo();return t?await sa(e,!!t.usesExplicitScenes):(pn=null,await ia(e))});return pn||Cr(e.currentChapter?.title,e.currentScene?.title,e.currentScene?.wordCount,e.currentChapter?.anchorId,e.currentScene?.anchorId,e.currentChapter?.index),Xr("Not detected"),zo(e),wr(""),po({lastScan:"Success",lastError:"-",paragraphs:String(e.paragraphCount),heading1:String(e.heading1Count),heading2:String(e.heading2Count)}),!0}catch(e){const t=ho(e);return console.error("Unable to scan the Word document.",e),Cr(null,null,null),wr(`Unable to scan the Word document: ${t}`),po({lastScan:"Failure",lastError:t}),!1}finally{B&&(B.disabled=!1,B.textContent="Refresh Document Structure")}},ma=async()=>{const e=bo();if(!So()||!e)return Er("Select a project and book to analyse manuscript structure."),!1;if(!Bt||!Ht||!window.Word||"function"!=typeof window.Word.run)return Er("Word document access is unavailable."),po({lastScan:"Failure",lastError:"Word document access is unavailable."}),!1;z&&(z.disabled=!0,z.textContent="Analysing..."),Er("Analysing manuscript structure...");try{const t=await window.Word.run(async e=>await ia(e)),n=await Ca(`/api/word-companion/books/${e.bookId}/structure`);return Cr(t.currentChapter?.title,t.currentScene?.title,t.currentScene?.wordCount,t.currentChapter?.anchorId,t.currentScene?.anchorId,t.currentChapter?.index),zo(t),dn=((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=ra(t,r,n);for(const o of na(t))oa(o,e,r,n)}return n})(t,n),ca(dn),Er("Preview generated. No changes have been applied."),po({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),Er("Unable to analyse manuscript structure."),po({lastScan:"Failure",lastError:ho(e)}),!1}finally{z&&(z.textContent="Analyse Manuscript Structure",Dr())}},ya=e=>{vn&&(vn(e),vn=null),dt?.close?dt.close():dt&&(dt.hidden=!0)},ga=()=>{const e=((e=dn)=>{const t=Pr(e);return{linkChapters:t.filter(e=>"couldLink"===e.category&&"Chapter"===e.type).length,linkScenes:t.filter(e=>"couldLink"===e.category&&"Scene"===e.type).length,createChapters:t.filter(e=>"wouldCreateChapters"===e.category).length,createScenes:t.filter(e=>"wouldCreateScenes"===e.category).length,manualReview:Array.isArray(e?.manualReview)?e.manualReview.length:0}})();return(e=>{if(!lt)return;lt.innerHTML="";const t=[`Link ${e.linkChapters+e.linkScenes} chapters/scenes`,`Create ${e.createChapters} chapters`,`Create ${e.createScenes} scenes`],n=document.createElement("ul");for(const e of t){const t=document.createElement("li");t.textContent=e,n.append(t)}lt.append(n)})(e),dt?new Promise(e=>{vn=e,dt.showModal?dt.showModal():dt.hidden=!1}):Promise.resolve(window.confirm(`Apply Structure Sync?\n\nThis will:\n\n- Link ${e.linkChapters+e.linkScenes} chapters/scenes\n- Create ${e.createChapters} chapters\n- Create ${e.createScenes} scenes\n\nManual review items will be skipped.`))},fa=(e,t,n="")=>{e.result=t,e.error=n},wa=e=>Number.isInteger(e?.wordChapter?.index)&&e.wordChapter.index>0?10*e.wordChapter.index:null,Ia=e=>Number.isInteger(e?.wordScene?.index)&&e.wordScene.index>0?10*e.wordScene.index:null,Sa=async(e,t)=>{const n=await ka(`/api/word-companion/books/${e}/chapters`,{title:no(t.wordTitle),sortOrder:wa(t)});if(!n?.chapterId)throw new Error("Chapter creation did not return a chapter ID.");Hr(),t.pdChapter={chapterId:n.chapterId,title:n.title||t.wordTitle,sortOrder:n.sortOrder||wa(t)||0,scenes:[]},t.match=`Chapter ${t.pdChapter.chapterId}: ${t.pdChapter.title}`},ba=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 ka(`/api/word-companion/books/${e}/chapters/${n.chapterId}/scenes`,{sceneTitle:no(t.wordTitle),sortOrder:Ia(t)});if(!r?.sceneId)throw new Error("Scene creation did not return a scene ID.");Hr(),t.pdChapter=n,t.pdScene={sceneId:r.sceneId,title:t.wordTitle,sortOrder:Ia(t)||0},t.match=`Scene ${t.pdScene.sceneId}: ${t.pdScene.title}`},Ca=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()},ka=(e,t)=>Ca(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}),va=async(e="")=>{In=!1,Sn=0,fn=[],S&&(S.innerHTML=""),vr(w,!0),No(!1),vo(""),vr(b,!0),e&&wr(e);const t=await Na();e&&t&&Vt&&wr(e)},xa=async(e=Qt,t=Xt)=>{const n=So(),r=bo(),o=To(),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(ar!==i){ar=i;try{await ka("/api/word-companion/runtime/current-scene",{documentGuid:o,projectId:n.projectId,bookId:r.bookId,chapterId:c,sceneId:a}),lr("Current scene follow event sent.")}catch(e){ar="",console.debug("Unable to notify PlotDirector of current scene.",e)}}},Na=async()=>{const e=bo();if(!(e&&Bt&&Ht&&window.Word&&"function"==typeof window.Word.run))return!1;wr("Reading manuscript position...");try{Hr(),await Promise.all([_a(!0),za(!0),Ka(!0)]),await ao(e.bookId);const t=await window.Word.run(async t=>await sa(t,!!e.usesExplicitScenes));return zo(t),po({lastScan:"Success",lastError:"-",paragraphs:String(t.paragraphCount),heading1:String(t.heading1Count),heading2:String(t.heading2Count)}),Vt?(Yt?await nc():await tc(),jr(!1),Tr("Live"),wr(""),!0):(Xr("Not detected"),jr(!1),Tr("Live"),wr("Manuscript linked. Click inside a chapter to show the current scene."),!0)}catch(e){return console.error("Unable to initialise bound manuscript runtime.",e),pn=null,Tr("Manual"),wr(`Unable to read manuscript position: ${ho(e)}`),po({lastScan:"Failure",lastError:ho(e)}),!1}},Ea=async e=>{ln=null,Br(),Xr("Not detected"),Tr("Manual"),yr("Connected"),Eo(),Co()?await ic(Co().projectId,null):fo(u,"Select a project first"),Lo(e||"Select a Project and Book to begin."),No(!0),xr()},La=e=>e?[...e.querySelectorAll("input[type='checkbox']:checked")].map(e=>Number.parseInt(e.value||"",10)).filter(e=>Number.isInteger(e)&&e>0):[],Pa=()=>{const e=Number.parseInt(Ne?.value||"",10);return Number.isInteger(e)&&e>0?e:null},qa=(e,t,n,r)=>{const o=((e,t)=>Oo(e).find(e=>Mo(e.tag,t))||null)(e,r),a=o||e.getRange().insertContentControl();return a.title=t,a.tag=n,a.appearance="Hidden",a},Da=async(e="PlotDirector IDs attached successfully.")=>{if(!Qt||!Xt)return wr("No resolved PlotDirector scene."),!1;if((Kt&&Kt!==Qt||zt&&zt!==Xt)&&!window.confirm("This scene is already linked. Replace the existing PlotDirector link?"))return!1;if(!Bt||!Ht||!window.Word||"function"!=typeof window.Word.run)return wr("Word document access is unavailable."),!1;ae&&(ae.disabled=!0,ae.textContent="Attaching...");try{return await window.Word.run(async e=>{const t=await ia(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.");qa(n,"PlotDirector Chapter",`PD-CHAPTER-${Xt}`,"PD-CHAPTER"),qa(r,"PlotDirector Scene",`PD-SCENE-${Qt}`,"PD-SCENE"),await e.sync()}),zt=Xt,Kt=Qt,tn=!1,en="SceneID Anchor",Zt="Anchor",wr(e),po({lastError:"-"}),br(),!0}catch(e){return console.error("Unable to attach PlotDirector IDs.",e),wr("Unable to attach PlotDirector IDs."),po({lastError:ho(e)}),br(),!1}finally{ae&&(ae.textContent=Kt===Qt?"Attach PlotDirector IDs":"Reattach PlotDirector IDs",br())}},Aa=async e=>{if(!Xt)return Vr("No resolved PlotDirector chapter."),!1;if(!Bt||!Ht||!window.Word||"function"!=typeof window.Word.run)return Vr("Word document access is unavailable."),!1;try{return await window.Word.run(async e=>{const t=await ia(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.");qa(n,"PlotDirector Chapter",`PD-CHAPTER-${Xt}`,"PD-CHAPTER"),await e.sync()}),zt=Xt,tn=!1,en="ChapterID Anchor",Zt="Chapter anchor",Vr(e),wr(e),po({lastError:"-"}),br(),!0}catch(e){return console.error("Unable to attach PlotDirector chapter ID.",e),Vr("Unable to attach PlotDirector chapter ID."),po({lastError:ho(e)}),br(),!1}},$a=async e=>{_r(),await nc(),wr(e),Vr(e)},Ta=e=>{sn&&(sn(e),sn=null),ot?.close?ot.close():ot&&(ot.hidden=!0)},ja=()=>{if(!et)return;const e=no(Ze?.value||"").toLocaleLowerCase(),t=an.filter(t=>!e||String(t.title||"").toLocaleLowerCase().includes(e));if(et.innerHTML="",cn=null,tt&&(tt.disabled=!0),0===t.length){const e=document.createElement("p");return e.className="word-companion-empty-list",e.textContent="No chapters found.",void et.append(e)}for(const e of t){const t=Number.parseInt(e.chapterId||"",10);if(!Number.isInteger(t)||t<=0)continue;const 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",()=>{cn=t,tt&&(tt.disabled=!1)});const o=document.createElement("span");o.textContent=e.title||"Untitled chapter",n.append(r,o),et.append(n)}},Wa=()=>{Xe?.close?Xe.close():Xe&&(Xe.hidden=!0)},Ra=async(e,t,n)=>{const r=bo();if(!r)return Fr("Select a PlotDirector book first."),!1;await lo(r.bookId,e,t,"Manual link","Title Match");return!!await Da(n)&&(Fr(n),Kr(),!0)},Ua=e=>{on&&(on(e),on=null),Je?.close?Je.close():Je&&(Je.hidden=!0)},Ma=()=>{if(!Ge)return;const e=no(He?.value||"").toLocaleLowerCase(),t=nn.filter(t=>!e||String(t.title||"").toLocaleLowerCase().includes(e));if(Ge.innerHTML="",rn=null,Fe&&(Fe.disabled=!0),0===t.length){const e=document.createElement("p");return e.className="word-companion-empty-list",e.textContent="No scenes found.",void Ge.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",()=>{rn=t,Fe&&(Fe.disabled=!1)});const o=document.createElement("span");o.textContent=e.title||"Untitled scene",n.append(r,o),Ge.append(n)}},Oa=()=>{Be?.close?Be.close():Be&&(Be.hidden=!0)},Ba=()=>{Rn=!1,$r(),Un&&(Un=!1,Ga(1e3))},Ha=async(e={})=>{const t=e.source||"manual",n=da();if(!Qt)return void Nr("No resolved PlotDirector scene.");if(!Xt)return void Nr("No resolved PlotDirector chapter.");if(Nn)return void Nr("Refresh Current Scene before syncing.");const r=bo(),o=To();if(!r||!o)return void Nr("Bound manuscript metadata is unavailable.");if(Rn)return Un=!0,void lr("Scene sync deferred; sync already running.");kr(),Rn=!0,Un=!1;let a=e.snapshot||null;try{a=la(a)?a:await pa()}catch(e){return Nr("Sync failed"),po({lastError:ho(e)}),lr("Scene sync failed."),void Ba()}if(!la(a))return Nr("Waiting for typing to pause"),lr("Scene sync skipped (stale snapshot)."),void Ba();const c=a.wordCount;if(!Number.isInteger(c)||c<0)return Nr("Sync failed"),lr("Scene sync failed."),void Ba();if(Mn===a.sceneId&&On===c)return Nr("Synced"),lr("Sync skipped (count unchanged)."),void Ba();lr("Scene word count changed."),ge&&(ge.disabled=!0,ge.textContent="Syncing..."),Nr("Syncing..."),lr(`Scene sync started (${t}).`);try{const e=da(),t=await ka("/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(ur(`Word count sync API: ${Math.round(da()-e)}ms`),!la(a))return void lr("Scene sync result ignored (stale snapshot).");const i=t?.actualWords??c,s=new Date;Mn=a.sceneId,On=i,uo(we,Ur(i)),uo(ue,Ur(i)),uo(Ie,Mr(s)),uo(ye,Mr(s)),Nr("Synced"),lr("Scene sync succeeded."),ur(`Total word count sync: ${Math.round(da()-n)}ms`)}catch(e){Nr("Sync failed"),po({lastError:ho(e)}),lr("Scene sync failed.")}finally{ge&&(ge.textContent="Sync Current Scene"),Ba()}},Ga=(e=4e3)=>{kr(),Qt&&Xt&&!Nn&&!Rn&&(Wn=window.setTimeout(()=>{Wn=null,Ha({source:"automatic"})},e))},Fa=()=>{Bn&&(window.clearTimeout(Bn),Bn=null)},Va=()=>{Fn=null,Vn="",Yn=[],Jn=null,_n="",Fa()},Ya=()=>{zn=null,Kn="",Qn=[],Xn=null,Zn=""},Ja=()=>{er=null,tr="",nr=[],rr=null,or=""},_a=async(e=!1)=>{const t=So(),n=To();if(!t||!n)return Yn=[],[];if(!e&&Fn===t.projectId&&Vn===n&&Yn.length>0)return Yn;const r=await Ca(`/api/word-companion/runtime/characters?projectId=${encodeURIComponent(t.projectId)}&documentGuid=${encodeURIComponent(n)}`);return Fn=t.projectId,Vn=n,Yn=Array.isArray(r?.characters)?r.characters:[],lr("Character alias cache refreshed."),Yn},za=async(e=!1)=>{const t=So(),n=To();if(!t||!n)return Qn=[],[];if(!e&&zn===t.projectId&&Kn===n&&Qn.length>0)return Qn;const r=await Ca(`/api/word-companion/runtime/assets?projectId=${encodeURIComponent(t.projectId)}&documentGuid=${encodeURIComponent(n)}`);return zn=t.projectId,Kn=n,Qn=Array.isArray(r?.assets)?r.assets:[],lr(`Asset cache loaded: ${Qn.length} aliases.`),Qn},Ka=async(e=!1)=>{const t=So(),n=To();if(!t||!n)return nr=[],[];if(!e&&er===t.projectId&&tr===n&&nr.length>0)return nr;const r=await Ca(`/api/word-companion/runtime/locations?projectId=${encodeURIComponent(t.projectId)}&documentGuid=${encodeURIComponent(n)}`);return er=t.projectId,tr=n,nr=Array.isArray(r?.locations)?r.locations:[],lr(`Location cache loaded: ${nr.length} aliases.`),nr},Qa=(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)},Xa=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},Za=async()=>{if(Bn=null,!Qt||Nn||!To())return;if(Hn)return Gn=!0,void lr("Character suggestion detection deferred; detection already running.");Hn=!0,Gn=!1;const e=da();try{const t=await pa();if(!la(t))return void lr("Runtime suggestions skipped (stale snapshot).");const[n,r,o]=await Promise.all([_a(),za(),Ka()]);if(!la(t))return void lr("Runtime suggestions skipped after cache load (stale snapshot).");const a=t.sceneText||"",c=da(),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)||Qa(e,r.matchText)&&n.set(t,r.name||r.matchText||"Character")}return[...n.entries()].map(([e,t])=>({characterId:e,name:t}))})(a,n);ur(`Character detection: ${Math.round(da()-c)}ms`);const s=i.map(e=>e.characterId),d=s.slice().sort((e,t)=>e-t).join(","),l=da(),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)||Qa(e,r.matchText)&&n.set(t,r.name||r.matchText||"Asset")}return[...n.entries()].map(([e,t])=>({assetId:e,name:t}))})(a,r);ur(`Asset detection: ${Math.round(da()-l)}ms`);const p=u.map(e=>e.assetId),h=p.slice().sort((e,t)=>e-t).join(","),m=da(),y=((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)||!Xa(r)||Qa(e,r.matchText)&&n.set(t,r.name||r.matchText||"Location")}return[...n.entries()].map(([e,t])=>({locationId:e,name:t}))})(a,o);ur(`Location detection: ${Math.round(da()-m)}ms`);const g=y.map(e=>e.locationId),f=g.slice().sort((e,t)=>e-t).join(",");if(!d||Jn===Qt&&_n===d)lr("Character suggestions skipped.");else{if(!la(t))return void lr("Character suggestions skipped before submit (stale snapshot).");const e=da(),n=await ka("/api/word-companion/runtime/character-suggestions",{documentGuid:t.documentGuid,sceneId:t.sceneId,characterIds:s});if(ur(`Character suggestion API: ${Math.round(da()-e)}ms`),!la(t))return void lr("Character suggestion result ignored (stale snapshot).");if(Jn=t.sceneId,_n=d,(n?.createdCount||0)>0){const e=i.slice(0,3).map(e=>e.name).join(", "),t=i.length>3?" +"+(i.length-3):"";wr(e?`Characters detected: ${e}${t}`:n.message)}lr(n?.message||"Character suggestions submitted.")}if(!h||Xn===Qt&&Zn===h)lr("Asset suggestions skipped.");else{if(!la(t))return void lr("Asset suggestions skipped before submit (stale snapshot).");lr(`Asset matches found: ${u.map(e=>e.name).join(", ")}`);const e=da(),n=await ka("/api/word-companion/runtime/asset-suggestions",{documentGuid:t.documentGuid,sceneId:t.sceneId,assetIds:p});if(ur(`Asset suggestion API: ${Math.round(da()-e)}ms`),!la(t))return void lr("Asset suggestion result ignored (stale snapshot).");if(Xn=t.sceneId,Zn=h,(n?.createdCount||0)>0){const e=u.slice(0,3).map(e=>e.name).join(", "),t=u.length>3?" +"+(u.length-3):"";wr(e?`Assets detected: ${e}${t}`:n.message)}lr(n?.message||"Asset suggestions submitted.")}if(!f||rr===Qt&&or===f)lr("Location suggestions skipped.");else{if(!la(t))return void lr("Location suggestions skipped before submit (stale snapshot).");lr(`Location matches found: ${y.map(e=>e.name).join(", ")}`);const e=da(),n=await ka("/api/word-companion/runtime/location-suggestions",{documentGuid:t.documentGuid,sceneId:t.sceneId,locationIds:g});if(ur(`Location suggestion API: ${Math.round(da()-e)}ms`),!la(t))return void lr("Location suggestion result ignored (stale snapshot).");if(rr=t.sceneId,or=f,(n?.createdCount||0)>0){const e=y.slice(0,3).map(e=>e.name).join(", "),t=y.length>3?" +"+(y.length-3):"";wr(e?`Locations detected: ${e}${t}`:n.message)}lr(n?.message||"Location suggestions submitted.")}ur(`Total suggestion pass: ${Math.round(da()-e)}ms`)}catch(e){console.error("Unable to detect runtime suggestions.",e),po({lastError:ho(e)})}finally{Hn=!1,Gn&&(Gn=!1,ec(1500))}},ec=(e=2500)=>{Fa(),!Qt||Nn||Hn?Hn&&(Gn=!0):Bn=window.setTimeout(()=>{Za()},e)},tc=async()=>{const e=So(),t=bo(),n=ro(Vt,"chapter");if(oo({projectId:e?.projectId,projectTitle:e?.title,bookId:t?.bookId,bookTitle:t?Io(t):void 0,detectedChapter:Vt,detectedScene:Yt,requestChapter:n,requestScene:"",result:"Not run",chapterId:null,sceneId:null}),!t)return Xr("Not detected"),wr("Select a PlotDirector book first."),!1;if(!Vt)return Xr("Not detected"),wr("No chapter detected in Word. Use Heading 1 for chapters."),!1;Xr("Not detected");try{const e=await co(t.bookId),r=zt?e.find(e=>e.chapterId===zt):null,o=n.toLocaleLowerCase(),a=o?e.find(e=>ro(e.title,"chapter").toLocaleLowerCase()===o):null,c=r||a;return c?(_r(),Wr(null,c.chapterId,r?"Chapter anchor":"Chapter title"),en=r?"ChapterID Anchor":"Title Match",Ir("Chapter linked to PlotDirector"),wr("No scene detected in Word. Use Heading 2 for scenes."),oo({result:"Chapter matched",chapterId:c.chapterId,sceneId:null}),!0):(Wr(null),Ir("Chapter not found in PlotDirector."),wr("Chapter not found in PlotDirector."),oo({result:"Chapter not matched",chapterId:null,sceneId:null}),zr("Chapter not found in PlotDirector."),!1)}catch(e){return Xr("Not found in PlotDirector"),po({lastError:ho(e)}),wr("Unable to load PlotDirector chapter data."),!1}},nc=async()=>{const e=So(),t=bo(),n=ro(Vt,"chapter"),r=ro(Yt,"scene");if(oo({projectId:e?.projectId,projectTitle:e?.title,bookId:t?.bookId,bookTitle:t?Io(t):void 0,detectedChapter:Vt,detectedScene:Yt,requestChapter:n,requestScene:r,result:"Not run",chapterId:null,sceneId:null}),Sr({anchorType:Kt?"SceneID Anchor":zt?"ChapterID Anchor":"Title Match",storedSceneId:Kt,storedChapterId:zt,resolutionMethod:"-"}),!t)return Xr("Not detected"),wr("Select a PlotDirector book first."),oo({result:"Error"}),!1;if(!Vt||!Yt)return Xr("Not detected"),wr("No scene detected in Word. Use Heading 2 for scenes."),oo({result:"Error"}),!1;Z&&(Z.disabled=!0,Z.textContent="Refreshing...");const o=()=>{Z&&(Z.disabled=!1,Z.textContent="Refresh PlotDirector Scene")};Xr("Not detected"),wr("Resolving PlotDirector scene...");try{if(Kt){const e=await(async(e,t)=>{const n=await Ca(`/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===Kt);if(e)return oo({result:"Matched",chapterId:e.chapter.chapterId,sceneId:e.scene.sceneId}),await lo(t.bookId,e.scene.sceneId,e.chapter.chapterId,"Anchor","SceneID Anchor"),!0;tn=!0,en="SceneID Anchor",Ir("Not found in PlotDirector"),wr("Stored PlotDirector ID is invalid."),oo({result:"Error",chapterId:zt,sceneId:Kt}),Sr({anchorType:"SceneID Anchor",storedSceneId:Kt,storedChapterId:zt,resolutionMethod:"Anchor"})}if(zt){const e=(await ao(t.bookId)).find(e=>e.chapterId===zt),n=e?(Array.isArray(e.scenes)?e.scenes:[]).find(e=>ro(e.title,"scene").toLocaleLowerCase()===r.toLocaleLowerCase()):null;if(n)return oo({result:"Matched",chapterId:e.chapterId,sceneId:n.sceneId}),await lo(t.bookId,n.sceneId,e.chapterId,"Anchor","ChapterID Anchor"),!0;e&&!Kt?(en="ChapterID Anchor",Wr(null,zt,"Chapter anchor"),oo({result:"Chapter matched",chapterId:zt,sceneId:null})):Kt||(en="ChapterID Anchor",oo({result:"Chapter anchor not found",chapterId:zt,sceneId:null}))}const e=await ka(`/api/word-companion/books/${t.bookId}/resolve-scene`,{chapterTitle:n,sceneTitle:r});if(!e?.matched||!e.sceneId){const t=tn,n=Number.parseInt(e?.chapterId||"",10),r=Number.isInteger(Xt)&&Xt>0?Xt:null,a=Number.isInteger(n)&&n>0?n:r,c=!!e?.chapterMatched||!!a;return Xr("Not found in PlotDirector"),tn=t,c&&(Wr(null,a,a===r?"Chapter anchor":"Chapter title"),Ir("Scene not found in PlotDirector.")),wr(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."),oo({result:"Not matched",chapterId:c?a:e?.chapterId,sceneId:e?.sceneId}),t||(c?(_r(),Qr("Scene not found in PlotDirector.")):(Kr(),zr("Chapter not found in PlotDirector."))),o(),!1}const a=tn;return oo({result:a?"Matched by title fallback":"Matched",chapterId:e.chapterId,sceneId:e.sceneId}),await lo(t.bookId,e.sceneId,e.chapterId,a?"Title fallback":"Title","Title Match"),a&&(tn=!0,wr("Stored PlotDirector ID is invalid."),br()),!0}catch(e){const t=tn;return po({lastError:ho(e)}),Xr("Not found in PlotDirector"),tn=t,wr(t?"Stored PlotDirector ID is invalid.":"Unable to load PlotDirector scene data."),oo({result:"Error"}),!1}finally{o()}},rc=async()=>{if(En=null,jn)return qn=!0,void lr("Runtime update deferred; update already running.");if(!Ut||!bo())return Ln=!1,void lr("Runtime update skipped.");if(!Bt||!Ht||!window.Word||"function"!=typeof window.Word.run)return Ln=!1,Tr("Manual"),void wr("Automatic scene tracking is unavailable in this Word version. Use Refresh Current Scene.");if(!pn)return Ln=!1,Tr("Manual"),void wr("Document structure is not cached yet. Use Refresh Current Scene.");const e=Date.now()-Pn;if(Ln&&e<$n)return lr("Runtime update skipped (typing active)."),void oc($n-e);jn=!0,Ln=!1,qn=!1,Tr("Updating..."),lr("Runtime update executed.");try{const e=await ua({includeSelection:!0});if(!la(e))return Tr("Waiting for typing to pause"),void lr("Runtime update skipped (stale snapshot).");if(!!!e.selectionChanged)return jr(!1),Tr("Current scene updated"),Ga(),void ec();Yt?await nc():await tc(),jr(!1),Tr("Current scene updated"),wr("Current scene updated."),Ga(),ec()}catch(e){console.error("Unable to refresh current scene from Word selection.",e),po({lastError:ho(e)}),jr(!0,"The Word cursor is now in a different scene. Refresh Current Scene before saving.")}finally{jn=!1,(qn||Ln)&&(qn=!1,oc($n))}},oc=(e=1200)=>{En&&window.clearTimeout(En),En=window.setTimeout(rc,Math.max(0,e)),Tr("Waiting for typing to pause"),lr("Runtime update scheduled.")},ac=()=>{((e="selection",t=1200)=>{if(Ln=!0,Pn=Date.now(),Dn+=1,An=null,kr(),Fa(),Rn&&(Un=!0),Hn&&(Gn=!0),lr(`${e} changed.`),jn)return qn=!0,void Tr("Waiting for typing to pause");oc(t)})("Selection")},cc=()=>{if(Tn&&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:ac}),Tn=!1}catch(e){console.warn("Unable to remove Word selection tracking handler.",e)}},ic=async(e,n)=>{if(pn=null,Hr(),!e)return Ot=[],fo(R,"Select a project first"),fo(u,"Select a project first"),fr(""),go(t,null),jo(),Xr("Not detected"),void Lr();fo(R,"Loading books..."),fr(""),Xr("Not detected"),Lr("Select a book to analyse manuscript structure.");try{const r=await Ca(`/api/word-companion/projects/${e}/books`);if(Ot=Array.isArray(r.books)?r.books:[],0===Ot.length)return fo(R,"No books available."),fo(u,"No books available."),fr("No books available."),go(t,null),jo(),void Lo("No books available.");wo(R,"Choose a book",Ot.map(e=>({...e,displayTitle:Io(e)})),"bookId","displayTitle");const o=Ot.find(e=>e.bookId===n);o&&R?(R.value=String(o.bookId),go(t,o.bookId)):go(t,null),((e=null)=>{if(!u)return;if(0===Ot.length)return void fo(u,"No books available.");wo(u,"Choose a book",Ot.map(e=>({...e,displayTitle:Io(e)})),"bookId","displayTitle");const t=e||Number.parseInt(R?.value||"",10),n=Ot.find(e=>e.bookId===t);n&&(u.value=String(n.bookId)),xo()})(o?.bookId||n),jo(),Xr((bo(),"Not detected")),Lr(bo()?"Ready to analyse manuscript structure.":"Select a book to analyse manuscript structure."),Lo(ko()?"Ready to scan manuscript structure.":"Select a Book to begin.")}catch{Ot=[],fo(R,"Unable to load books."),fo(u,"Unable to load books."),fr("Unable to load books."),go(t,null),jo(),Xr("Not detected"),Lr("Unable to load books."),Lo("Unable to load books.")}};for(const e of i)e.addEventListener("click",()=>hr(e.dataset.tabButton));mr(),W?.addEventListener("change",async()=>{const n=Number.parseInt(W.value||"",10);Br(),l&&Number.isInteger(n)&&n>0&&(l.value=String(n)),go(e,Number.isInteger(n)&&n>0?n:null),go(t,null),Xr("Not detected"),Lr(),Lo("Select a Book to begin."),await ic(n,null)}),R?.addEventListener("change",()=>{const e=Number.parseInt(R.value||"",10);Br(),go(t,Number.isInteger(e)&&e>0?e:null),u&&Number.isInteger(e)&&e>0&&(u.value=String(e)),jo(),Xr("Not detected"),Lr(bo()?"Ready to analyse manuscript structure.":"Select a book to analyse manuscript structure."),Lo(ko()?"Ready to scan manuscript structure.":"Select a Book to begin.")}),l?.addEventListener("change",async()=>{const n=Number.parseInt(l.value||"",10);Br(),W&&Number.isInteger(n)&&n>0&&(W.value=String(n)),go(e,Number.isInteger(n)&&n>0?n:null),go(t,null),Lo("Select a Book to begin."),await ic(n,null)}),u?.addEventListener("change",()=>{const e=Number.parseInt(u.value||"",10);Br(),R&&Number.isInteger(e)&&e>0&&(R.value=String(e)),go(t,Number.isInteger(e)&&e>0?e:null),jo(),Lo(ko()?"Ready to scan manuscript structure.":"Select a Book to begin.")}),p?.addEventListener("input",xo),h?.addEventListener("click",async()=>{const e=Co(),t=String(p?.value||"").trim();if(e&&t){h.disabled=!0,vo("Creating Book...");try{const n=await ka(`/api/word-companion/projects/${e.projectId}/books`,{title:t});p&&(p.value=""),W&&(W.value=String(e.projectId)),await ic(e.projectId,n.bookId),u&&(u.value=String(n.bookId)),vo("Ready to scan manuscript structure.")}catch(e){console.error("Unable to create Book from Word Companion.",e),vo(`Unable to create Book: ${ho(e)}`)}finally{xo()}}else xo()}),m?.addEventListener("click",async()=>{const e=Co(),t=ko();if(e&&t)if(Bt&&Ht&&window.Word&&"function"==typeof window.Word.run){m&&(m.disabled=!0,m.textContent="Scanning..."),vo("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),Ro(e,1))return r={title:d,sortOrder:10*(n.length+1),wordCount:0,scenes:[]},n.push(r),o=s(),void(a+=Uo(d));if(!r||!o)return;if(t&&i.has(d))return void(o=s());const l=Uo(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)});gn=n,wn=!1;const r=await ka("/api/word-companion/manuscript/analyse",{projectId:e.projectId,bookId:t.bookId,documentGuid:$o(),chapterCount:n.chapterCount,sceneCount:n.sceneCount,wordCount:n.wordCount});yn=r,(e=>{if(!f)return;f.innerHTML="";const t=document.createElement("strong");t.textContent="Manuscript Analysis",f.append(t);const n=document.createElement("dl"),r=[["Project",e.projectTitle],["Book",Io({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)}f.append(n),vr(f,!1),vr(x,!1),vo(e.message||"Preview generated."),xo()})(r);try{const t=await ka("/api/word-companion/manuscript/discover-characters",{projectId:e.projectId,documentText:n.documentText||""});fn=Array.isArray(t?.candidates)?t.candidates:[],vr(w,!0),vr(b,!0)}catch(e){console.error("Unable to discover character candidates.",e),fn=[],vr(w,!0),vr(b,!0)}po({lastScan:"Success",lastError:"-",paragraphs:"-",heading1:String(n.chapterCount),heading2:"-"})}catch(e){console.error("Unable to scan manuscript for first-run import.",e),Lo(`Unable to scan manuscript: ${ho(e)}`),po({lastScan:"Failure",lastError:ho(e)})}finally{m&&(m.textContent="Scan Manuscript"),xo()}}else Lo("Word document access is unavailable.");else Lo("Select a Project and Book to begin.")}),N?.addEventListener("click",async()=>{const n=Co(),o=ko();if(!(n&&o&&gn&&yn?.canImport))return void xo();let a=!1;if(!yn.requiresReplaceConfirmation||(a=await new Promise(e=>{if(!L||"function"!=typeof L.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=>{P?.removeEventListener("click",n),q?.removeEventListener("click",r),L?.removeEventListener("cancel",o),L?.close(),e(t)},n=()=>t(!0),r=()=>t(!1),o=e=>{e.preventDefault(),t(!1)};P?.addEventListener("click",n),q?.addEventListener("click",r),L?.addEventListener("cancel",o),L.showModal()}),a)){bn=!0,xo(),vo("Importing manuscript structure...");try{const i=$o(),s=await ka("/api/word-companion/manuscript/import",{projectId:n.projectId,bookId:o.bookId,documentGuid:i,bindingVersion:1,replacePlanned:a,chapters:gn.chapters});if(!s.imported)return yn={...yn,canImport:!s.requiresReplaceConfirmation,requiresReplaceConfirmation:!!s.requiresReplaceConfirmation,message:s.message||yn.message},vo(s.message||"Import was not completed."),void xo();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."))})),ln={documentGuid:d?.documentGuid||i,bookId:s.bookId,projectId:s.projectId,bindingVersion:d?.bindingVersion||1},go(e,s.projectId),go(t,s.bookId),W&&(W.value=String(s.projectId));const l=fn;await ic(s.projectId,s.bookId),yr("Connected"),wn=!0,In=l.length>0,Sn=In?Date.now():0,fn=l,l.length>0?(No(!0),qo(l),vr(x,!0),vr(b,!1),vo(s.message||"Manuscript structure imported."),wr(s.message||"Manuscript structure imported."),window.setTimeout(xo,750)):await va(s.message||"Manuscript structure imported.")}catch(e){console.error("Unable to import manuscript structure.",e),vo(`Unable to import manuscript: ${ho(e)}`)}finally{bn=!1,xo()}var c}else vo("Import cancelled.")}),C?.addEventListener("click",async()=>{const e=Co()||So(),t=Po();if(!In||Date.now()-Sn<750||!e||0===t.length)xo();else{Cn=!0,xo(),uo(I,"Creating selected characters...");try{const n=await ka("/api/word-companion/manuscript/create-discovered-characters",{projectId:e.projectId,candidateNames:t});wr(n.message||"Characters created."),uo(I,`${n.createdCount||0} created, ${n.skippedCount||0} already existed.`),await va(n.message||"Characters created.")}catch(e){console.error("Unable to create discovered characters.",e),uo(I,`Unable to create characters: ${ho(e)}`)}finally{Cn=!1,xo()}}}),k?.addEventListener("click",()=>va("Character creation skipped.")),v?.addEventListener("click",()=>va()),y?.addEventListener("click",()=>No(!1)),E?.addEventListener("click",()=>Lo("Import cancelled.")),B?.addEventListener("click",ha),z?.addEventListener("click",ma),K?.addEventListener("click",async()=>{const e=bo();if(!e||0===Pr().length||kn)return void qr();if(!await ga())return;kn=!0,Dr(),Er("Applying structure sync...");const t={createdChapters:0,createdScenes:0,linkedChapters:0,linkedScenes:0,skipped:Array.isArray(dn?.manualReview)?dn.manualReview.length:0,failed:0},n=Pr().filter(e=>"couldLink"===e.category&&"Chapter"===e.type),r=Pr().filter(e=>"wouldCreateChapters"===e.category),o=Pr().filter(e=>"couldLink"===e.category&&"Scene"===e.type),a=Pr().filter(e=>"wouldCreateScenes"===e.category),c=[];let i="";const s=(e,t)=>{c.push({item:e,counterName:t})},d=async(e,n)=>{try{await(async e=>{if(!Bt||!Ht||!window.Word||"function"!=typeof window.Word.run)throw new Error("Word document access is unavailable.");await window.Word.run(async t=>{const n=await ia(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.");qa(o,"PlotDirector Chapter",`PD-CHAPTER-${t}`,"PD-CHAPTER")}else{const t=e.pdScene?.sceneId;if(!t)throw new Error("Scene ID is not available.");qa(o,"PlotDirector Scene",`PD-SCENE-${t}`,"PD-SCENE")}await t.sync()})})(e),fa(e,"Success"),t[n]+=1}catch(n){fa(e,"Failed",ho(n)),t.failed+=1}};try{for(const e of n)s(e,"linkedChapters");for(const n of r)try{await Sa(e.bookId,n),s(n,"createdChapters")}catch(e){fa(n,"Failed",ho(e)),t.failed+=1}for(const e of o)s(e,"linkedScenes");for(const n of a)try{await ba(e.bookId,n),s(n,"createdScenes")}catch(e){fa(n,"Failed",ho(e)),t.failed+=1}for(const e of c)await d(e.item,e.counterName);for(const e of dn.manualReview||[])fa(e,"Skipped");ca(dn),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),Er(i)}finally{kn=!1,Dr(),i&&(Hr(),await ma(),Er(`${i} Preview refreshed.`))}}),ut?.addEventListener("click",()=>ya(!0)),pt?.addEventListener("click",()=>ya(!1)),dt?.addEventListener("cancel",e=>{e.preventDefault(),ya(!1)}),Z?.addEventListener("click",nc),O?.addEventListener("click",async()=>{if(!bo())return wr("Select a PlotDirector book first."),void Xr("Not detected");En&&(window.clearTimeout(En),En=null),Ln=!1,qn=!1,Rr(!0),Tr("Updating...");try{await Promise.all([_a(!0),za(!0),Ka(!0)]);if(!await ha())return;if(jr(!1),!Yt)return await tc(),void Tr("Current scene updated");await nc(),Tr("Current scene updated")}finally{Rr(!1)}}),ge?.addEventListener("click",()=>Ha({source:"manual"})),Ee?.addEventListener("click",async()=>{if(Qt)if(!Nn&&await(async()=>{if(!Qt)return!1;if(!Bt||!Ht||!window.Word||"function"!=typeof window.Word.run)return jr(!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 ia(e)),t=e.currentChapter?.title||"",n=e.currentScene?.title||"",r=e.currentScene?.anchorId||null,o=e.currentChapter?.anchorId||null,a=Number.isInteger(r)&&r===Qt,c=Number.isInteger(o)&&o===Xt,i=ro(n,"scene").toLocaleLowerCase()===ro(cr||Yt,"scene").toLocaleLowerCase(),s=ro(t,"chapter").toLocaleLowerCase()===ro(ir||Vt,"chapter").toLocaleLowerCase();return a||i&&(c||s)?(jr(!1),!0):(jr(!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),po({lastError:ho(e)}),jr(!0,"The Word cursor is now in a different scene. Refresh Current Scene before saving."),!1}})()){Ee&&(Ee.disabled=!0,Ee.textContent="Saving...");try{await(e=`/api/word-companion/scenes/${Qt}/links`,t={characterIds:La(ve),assetIds:La(xe),locationIds:[],primaryLocationId:Pa()},Ca(e,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})),(()=>{const e=new Set(La(ve)),t=new Set(La(xe));dr={characters:dr.characters.map(t=>({...t,linked:e.has(Number.parseInt(Zr(t,"character"),10))})),assets:dr.assets.map(e=>({...e,linked:t.has(Number.parseInt(Zr(e,"asset"),10))})),locations:dr.locations,primaryLocationId:Pa()}})(),Gr("Scene links saved successfully."),po({lastError:"-"})}catch(e){Gr("Unable to save scene links."),po({lastError:ho(e)})}finally{Ee&&(Ee.disabled=!Qt||Nn,Ee.textContent="Save Scene Links")}var e,t}else Gr("The Word cursor is now in a different scene. Refresh Current Scene before saving.");else Gr("Link a PlotDirector scene first.")}),ae?.addEventListener("click",async()=>{await Da()}),ce?.addEventListener("click",async()=>{const e=ln||Do();if(!e)return void wr("This Word document is not linked.");if(window.confirm("This will remove PlotDirector binding metadata from this Word document.\n\nIf PlotDirector is reachable, it will also unlink this Book in PlotDirector.\n\nYour manuscript text will not be changed.\n\nContinue?")){ce&&(ce.disabled=!0,ce.textContent="Unlinking...");try{await ka("/api/word-companion/manuscript/unlink",{documentGuid:e.documentGuid,bookId:e.bookId}),await Ao(),await Ea("Word document unlinked. Select a Project and Book to begin.")}catch(e){console.error("Unable to unlink manuscript binding.",e);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 Word metadata only?"))try{await Ao(),await Ea("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),wr(`Unable to remove Word metadata: ${ho(e)}`)}else wr(`Unable to unlink manuscript: ${ho(e)}`)}finally{ce&&(ce.disabled=!1,ce.textContent="Unlink this Word document"),xr()}}}),Ae?.addEventListener("click",async()=>{const e=bo();if(!e||!Vt||Xt)return void zr("Chapter not found in PlotDirector.");const t=no(Vt),n=await((e,t)=>(uo(at,`"${e}"`),uo(ct,`"${t}"`),ot?new Promise(e=>{sn=e,ot.showModal?ot.showModal():ot.hidden=!1}):Promise.resolve(window.confirm(`Create PlotDirector chapter:\n\n"${e}"\n\nin book:\n\n"${t}"\n\n?`))))(t,Io(e)||"selected book");if(n){Ae&&(Ae.disabled=!0,Ae.textContent="Creating...");try{const n=Number.isInteger(_t)&&_t>0?10*_t:null,r=await ka(`/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.");Hr(),Wr(null,r.chapterId,"Manual chapter link");if(!await Aa("Chapter created and linked successfully."))return;await $a("Chapter created and linked successfully.")}catch(e){Vr("Unable to create chapter."),po({lastError:ho(e)})}finally{Ae&&(Ae.disabled=!Yr(),Ae.textContent="Create Chapter in PlotDirector")}}}),$e?.addEventListener("click",async()=>{const e=bo();if(e&&Vt&&!Xt){$e&&($e.disabled=!0,$e.textContent="Loading...");try{an=await co(e.bookId),cn=null,Ze&&(Ze.value=""),uo(rt,""),ja(),Xe?.showModal?Xe.showModal():Xe&&(Xe.hidden=!1)}catch(e){Vr("Unable to load chapters."),po({lastError:ho(e)})}finally{$e&&($e.disabled=!Yr(),$e.textContent="Link to Existing Chapter")}}else zr("Chapter not found in PlotDirector.")}),Ze?.addEventListener("input",ja),tt?.addEventListener("click",async()=>{const e=an.find(e=>e.chapterId===cn);if(e){tt&&(tt.disabled=!0,tt.textContent="Linking...");try{Wr(null,e.chapterId,"Manual chapter link");if(!await Aa("Chapter linked successfully."))return;Wa(),await $a("Chapter linked successfully.")}catch(e){uo(rt,"Unable to link chapter."),Vr("Unable to link chapter."),po({lastError:ho(e)})}finally{tt&&(tt.disabled=!cn,tt.textContent="Link Chapter")}}else uo(rt,"Select a chapter.")}),nt?.addEventListener("click",Wa),it?.addEventListener("click",()=>Ta(!0)),st?.addEventListener("click",()=>Ta(!1)),ot?.addEventListener("cancel",e=>{e.preventDefault(),Ta(!1)}),Ue?.addEventListener("click",async()=>{const e=bo();if(!e||!Yt)return void Qr("Scene not found in PlotDirector.");const t=ro(Yt,"scene"),n=ro(Vt,"chapter"),r=await((e,t)=>(uo(_e,`"${e}"`),uo(ze,`"${t}"`),Je?new Promise(e=>{on=e,Je.showModal?Je.showModal():Je.hidden=!1}):Promise.resolve(window.confirm(`Create PlotDirector scene:\n\n"${e}"\n\nwithin chapter:\n\n"${t}"\n\n?`))))(t,n);if(r){Ue&&(Ue.disabled=!0,Ue.textContent="Creating...");try{const n=await so();if(!n)return void Qr("This chapter does not exist in PlotDirector. Create or link the chapter first.");const r=await ka(`/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.");Hr(),await Ra(r.sceneId,r.chapterId,"Scene created and linked successfully.")}catch(e){Fr("Unable to create scene."),po({lastError:ho(e)})}finally{Ue&&(Ue.disabled=!Jr(),Ue.textContent="Create Scene in PlotDirector")}}}),Me?.addEventListener("click",async()=>{const e=bo();if(e&&Yt){Me&&(Me.disabled=!0,Me.textContent="Loading...");try{const t=await ao(e.bookId),n=io(t);if(!n)return void Qr("This chapter does not exist in PlotDirector. Create or link the chapter first.");nn=Array.isArray(n.scenes)?n.scenes:[],rn=null,He&&(He.value=""),uo(Ye,""),Ma(),Be?.showModal?Be.showModal():Be&&(Be.hidden=!1)}catch(e){Fr("Unable to load scenes."),po({lastError:ho(e)})}finally{Me&&(Me.disabled=!Jr(),Me.textContent="Link to Existing Scene")}}else Qr("Scene not found in PlotDirector.")}),He?.addEventListener("input",Ma),Fe?.addEventListener("click",async()=>{const e=bo(),t=nn.find(e=>e.sceneId===rn);if(e&&t){Fe&&(Fe.disabled=!0,Fe.textContent="Linking...");try{const e=await so();if(!e)throw new Error("This chapter does not exist in PlotDirector. Create or link the chapter first.");Oa(),await Ra(t.sceneId,e.chapterId,"Scene linked successfully.")}catch(e){uo(Ye,"Unable to link scene."),Fr("Unable to link scene."),po({lastError:ho(e)})}finally{Fe&&(Fe.disabled=!rn,Fe.textContent="Link Scene")}}else uo(Ye,"Select a scene.")}),Ve?.addEventListener("click",Oa),Ke?.addEventListener("click",()=>Ua(!0)),Qe?.addEventListener("click",()=>Ua(!1)),Je?.addEventListener("cancel",e=>{e.preventDefault(),Ua(!1)}),vt?.addEventListener("click",async()=>{vt&&(vt.disabled=!0,vt.textContent="Running...");try{if(await mo(),!Bt||!Ht||!window.Word||"function"!=typeof window.Word.run)return void po({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});po({lastScan:"Success",lastError:"-",paragraphs:String(e)})}catch(e){console.error("Word Companion diagnostics failed.",e);const t=ho(e);po({lastScan:"Failure",lastError:t}),wr(`Unable to scan the Word document: ${t}`)}finally{vt&&(vt.disabled=!1,vt.textContent="Run Diagnostics")}});const sc=Ut?(async()=>{fo(W,"Loading projects..."),fo(R,"Select a project first"),fo(l,"Loading projects..."),fo(u,"Select a project first"),gr(""),fr("");try{const n=await Ca("/api/word-companion/projects");if(Mt=Array.isArray(n.projects)?n.projects:[],0===Mt.length)return fo(W,"No projects available."),fo(l,"No projects available."),gr("No projects available."),go(e,null),go(t,null),jo(),void Lo("No projects available.");wo(W,"Choose a project",Mt,"projectId","title"),Eo();const r=yo(e),o=Mt.find(e=>e.projectId===r);o&&W?(W.value=String(o.projectId),l&&(l.value=String(o.projectId)),go(e,o.projectId),await ic(o.projectId,yo(t))):(go(e,null),go(t,null),jo(),Lo("Select a Project and Book to begin."))}catch{Mt=[],Ot=[],fo(W,"Unable to connect to PlotDirector."),fo(R,"Select a project first"),fo(l,"Unable to connect to PlotDirector."),fo(u,"Select a project first"),yr("Unable to connect to PlotDirector."),gr("Unable to connect to PlotDirector."),go(e,null),go(t,null),jo(),Lo("Unable to connect to PlotDirector.")}})():Promise.resolve();if(Ut||(fo(W,"Please sign in to PlotDirector."),fo(R,"Please sign in to PlotDirector."),fo(l,"Please sign in to PlotDirector."),fo(u,"Please sign in to PlotDirector."),jo()),!window.Office||"function"!=typeof window.Office.onReady)return pr("Word Companion ready"),wr("Word document access is unavailable."),Tr("Manual"),void po({host:"Unavailable",platform:"Unavailable",ready:"No",wordApi:"No"});mo().then(async()=>{pr("Word Companion ready"),await sc,await(async()=>{if(!Ut||!Ht)return void No(!1);const n=Do();if(n)try{const r=await Ca(`/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 ln=n,Or(r),go(e,r.projectId),go(t,r.bookId),W&&(W.value=String(r.projectId)),await ic(r.projectId,r.bookId),No(!1),yr("Connected"),fr("Bound manuscript detected."),void await Na()}catch{}ln=null,Br(),Eo(),Co()?await ic(Co().projectId,null):fo(u,"Select a project first"),Lo("Select a Project and Book to begin."),No(!0)})(),Ht?(()=>{if(Ut){if(!window.Office?.context?.document||"function"!=typeof window.Office.context.document.addHandlerAsync||!window.Office?.EventType?.DocumentSelectionChanged)return Tr("Manual"),void wr("Automatic scene tracking is unavailable in this Word version. Use Refresh Current Scene.");try{window.Office.context.document.addHandlerAsync(window.Office.EventType.DocumentSelectionChanged,ac,e=>{e?.status===window.Office.AsyncResultStatus.Succeeded?(Tn=!0,Tr("Live")):(Tr("Manual"),wr("Automatic scene tracking is unavailable in this Word version. Use Refresh Current Scene."))}),window.addEventListener("beforeunload",cc)}catch(e){console.warn("Unable to register Word selection tracking handler.",e),Tr("Manual"),wr("Automatic scene tracking is unavailable in this Word version. Use Refresh Current Scene.")}}})():(wr("Word document access is unavailable."),Tr("Manual"))}).catch(e=>{console.error("Office readiness check failed.",e),yr("Unable to connect to PlotDirector."),pr("Word Companion unavailable"),wr("Word document access is unavailable."),po({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","links","structure","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-first-run-wizard]"),l=document.querySelector("[data-first-run-project-select]"),u=document.querySelector("[data-first-run-book-select]"),p=document.querySelector("[data-first-run-new-book-title]"),h=document.querySelector("[data-first-run-create-book]"),m=document.querySelector("[data-first-run-scan]"),y=document.querySelector("[data-first-run-cancel]"),g=document.querySelector("[data-first-run-status]"),f=document.querySelector("[data-first-run-summary]"),w=document.querySelector("[data-first-run-character-section]"),I=document.querySelector("[data-first-run-character-status]"),S=document.querySelector("[data-first-run-character-candidates]"),b=document.querySelector("[data-first-run-character-actions]"),C=document.querySelector("[data-first-run-create-characters]"),k=document.querySelector("[data-first-run-skip-characters]"),v=document.querySelector("[data-first-run-continue]"),x=document.querySelector("[data-first-run-import-actions]"),N=document.querySelector("[data-first-run-import]"),E=document.querySelector("[data-first-run-import-cancel]"),L=document.querySelector("[data-first-run-replace-dialog]"),P=document.querySelector("[data-first-run-replace-confirm]"),D=document.querySelector("[data-first-run-replace-cancel]"),q=document.querySelector("[data-unlink-word-document-dialog]"),A=document.querySelector("[data-unlink-word-document-confirm]"),$=document.querySelector("[data-unlink-word-document-cancel]"),T=document.querySelector("[data-office-status]"),j=document.querySelector("[data-connection-status]"),W=document.querySelector("[data-summary-connection]"),R=document.querySelector("[data-summary-project]"),U=document.querySelector("[data-summary-book]"),M=document.querySelector("[data-project-select]"),O=document.querySelector("[data-book-select]"),B=document.querySelector("[data-project-message]"),G=document.querySelector("[data-book-message]"),H=document.querySelector("[data-refresh-current-scene]"),F=document.querySelector("[data-refresh-document]"),V=document.querySelector("[data-current-chapter]"),Y=document.querySelector("[data-current-scene]"),J=document.querySelector("[data-current-word-count]"),_=document.querySelector("[data-scene-tracking-status]"),z=document.querySelector("[data-document-message]"),K=document.querySelector("[data-sync-note]"),Q=document.querySelector("[data-document-outline]"),X=document.querySelector("[data-analyse-manuscript-structure]"),Z=document.querySelector("[data-apply-structure-sync]"),ee=document.querySelector("[data-structure-preview-status]"),te=document.querySelector("[data-structure-preview-results]"),ne=document.querySelector("[data-refresh-plotdirector-scene]"),re=document.querySelector("[data-plotdirector-scene-status]"),oe=document.querySelector("[data-anchor-status]"),ae=document.querySelector("[data-anchor-book-id]"),ce=document.querySelector("[data-anchor-chapter-id]"),ie=document.querySelector("[data-anchor-scene-id]"),se=document.querySelector("[data-attach-plotdirector-ids]"),de=document.querySelector("[data-unlink-word-document]"),le=document.querySelector("[data-plotdirector-scene-details]"),ue=document.querySelector("[data-plotdirector-scene-title]"),pe=document.querySelector("[data-plotdirector-revision-status]"),he=document.querySelector("[data-plotdirector-estimated-words]"),me=document.querySelector("[data-plotdirector-actual-words]"),ye=document.querySelector("[data-plotdirector-blocked-status]"),ge=document.querySelector("[data-plotdirector-blocked-reason-row]"),fe=document.querySelector("[data-plotdirector-blocked-reason]"),we=document.querySelector("[data-runtime-last-sync]"),Ie=document.querySelector("[data-sync-scene-progress]"),Se=document.querySelector("[data-sync-word-count]"),be=document.querySelector("[data-sync-plotdirector-count]"),Ce=document.querySelector("[data-sync-last-synced]"),ke=document.querySelector("[data-sync-status]"),ve=document.querySelector("[data-writing-brief-block]"),xe=document.querySelector("[data-writing-brief]"),Ne=document.querySelector("[data-plotdirector-link-groups]"),Ee=document.querySelector("[data-character-chips]"),Le=document.querySelector("[data-asset-chips]"),Pe=(document.querySelector("[data-location-chips]"),document.querySelector("[data-primary-location-select]")),De=document.querySelector("[data-save-scene-links]"),qe=document.querySelector("[data-scene-links-status]"),Ae=document.querySelector("[data-links-editing-scene]"),$e=document.querySelector("[data-chapter-create-link]"),Te=document.querySelector("[data-chapter-create-link-chapter]"),je=document.querySelector("[data-create-plotdirector-chapter]"),We=document.querySelector("[data-link-existing-chapter]"),Re=document.querySelector("[data-chapter-create-link-status]"),Ue=document.querySelector("[data-scene-create-link]"),Me=document.querySelector("[data-create-link-chapter]"),Oe=document.querySelector("[data-create-link-scene]"),Be=document.querySelector("[data-create-plotdirector-scene]"),Ge=document.querySelector("[data-link-existing-scene]"),He=document.querySelector("[data-create-link-status]"),Fe=document.querySelector("[data-link-existing-dialog]"),Ve=document.querySelector("[data-link-scene-search]"),Ye=document.querySelector("[data-link-scene-options]"),Je=document.querySelector("[data-link-selected-scene]"),_e=document.querySelector("[data-link-dialog-cancel]"),ze=document.querySelector("[data-link-dialog-status]"),Ke=document.querySelector("[data-create-scene-dialog]"),Qe=document.querySelector("[data-create-dialog-scene]"),Xe=document.querySelector("[data-create-dialog-chapter]"),Ze=document.querySelector("[data-create-dialog-confirm]"),et=document.querySelector("[data-create-dialog-cancel]"),tt=document.querySelector("[data-link-existing-chapter-dialog]"),nt=document.querySelector("[data-link-chapter-search]"),rt=document.querySelector("[data-link-chapter-options]"),ot=document.querySelector("[data-link-selected-chapter]"),at=document.querySelector("[data-link-chapter-dialog-cancel]"),ct=document.querySelector("[data-link-chapter-dialog-status]"),it=document.querySelector("[data-create-chapter-dialog]"),st=document.querySelector("[data-create-chapter-dialog-chapter]"),dt=document.querySelector("[data-create-chapter-dialog-book]"),lt=document.querySelector("[data-create-chapter-dialog-confirm]"),ut=document.querySelector("[data-create-chapter-dialog-cancel]"),pt=document.querySelector("[data-apply-structure-sync-dialog]"),ht=document.querySelector("[data-apply-structure-sync-summary]"),mt=document.querySelector("[data-apply-structure-sync-confirm]"),yt=document.querySelector("[data-apply-structure-sync-cancel]"),gt=document.querySelector("[data-resolve-project-id]"),ft=document.querySelector("[data-resolve-project-title]"),wt=document.querySelector("[data-resolve-book-id]"),It=document.querySelector("[data-resolve-book-title]"),St=document.querySelector("[data-resolve-detected-chapter]"),bt=document.querySelector("[data-resolve-detected-scene]"),Ct=document.querySelector("[data-resolve-request-chapter]"),kt=document.querySelector("[data-resolve-request-scene]"),vt=document.querySelector("[data-resolve-result]"),xt=document.querySelector("[data-resolve-chapter-id]"),Nt=document.querySelector("[data-resolve-scene-id]"),Et=document.querySelector("[data-run-diagnostics]"),Lt=document.querySelector("[data-diagnostic-host]"),Pt=document.querySelector("[data-diagnostic-platform]"),Dt=document.querySelector("[data-diagnostic-ready]"),qt=document.querySelector("[data-diagnostic-word-api]"),At=document.querySelector("[data-diagnostic-last-scan]"),$t=document.querySelector("[data-diagnostic-last-error]"),Tt=document.querySelector("[data-diagnostic-anchor-type]"),jt=document.querySelector("[data-diagnostic-stored-scene-id]"),Wt=document.querySelector("[data-diagnostic-stored-chapter-id]"),Rt=document.querySelector("[data-diagnostic-resolution-method]"),Ut=document.querySelector("[data-diagnostic-paragraphs]"),Mt=document.querySelector("[data-diagnostic-heading1]"),Ot=document.querySelector("[data-diagnostic-heading2]"),Bt="true"===a?.dataset.authenticated;let Gt=[],Ht=[],Ft=!1,Vt=!1,Yt="Unknown",Jt="Unknown",_t="",zt="",Kt=null,Qt=null,Xt=null,Zt=null,en=null,tn=null,nn="",rn="Title Match",on=!1,an=[],cn=null,sn=null,dn=[],ln=null,un=null,pn=null,hn=null,mn=null,yn=null,gn=null,fn=null,wn=null,In=null,Sn=[],bn=!1,Cn=!1,kn=0,vn=!1,xn=!1,Nn=!1,En=null,Ln="Manual",Pn=!1,Dn=null,qn=!1,An=0,$n=!1,Tn=0,jn=null;const Wn=1200;let Rn=!1,Un=!1,Mn=null,On=!1,Bn=!1,Gn=null,Hn=null,Fn=null,Vn=!1,Yn=!1,Jn=null,_n="",zn=[],Kn=null,Qn="",Xn=null,Zn="",er=[],tr=null,nr="",rr=null,or="",ar=[],cr=null,ir="",sr="",dr="",lr="",ur=0,pr={characters:[],assets:[],locations:[],primaryLocationId:null};const hr=e=>{const t=Date.now();t-ur<1e3||(ur=t,console.debug(`[Word Companion Runtime] ${e}`))},mr=e=>{console.debug(`[Word Companion Timing] ${e}`)},yr=e=>{T&&(T.textContent=e)},gr=(e,t=!0)=>{const r=o.has(e)&&i.some(t=>t.dataset.tabButton===e)?e:"scene";for(const e of i){const t=e.dataset.tabButton===r;e.classList.toggle("is-active",t),e.setAttribute("aria-selected",t?"true":"false")}for(const e of s){const t=e.dataset.tabPanel===r;e.classList.toggle("is-active",t),e.hidden=!t}t&&((e,t)=>{try{t?window.localStorage.setItem(e,String(t)):window.localStorage.removeItem(e)}catch{}})(n,r)},fr=()=>{const e=(e=>{try{return window.localStorage.getItem(e)||""}catch{return""}})(n);gr(o.has(e)?e:"scene",!1)},wr=e=>{j&&(j.textContent=e),W&&(W.textContent=e)},Ir=e=>{B&&(B.textContent=e)},Sr=e=>{G&&(G.textContent=e)},br=e=>{z&&(z.textContent=e)},Cr=e=>{re&&(re.textContent=e)},kr=e=>{const t=t=>Object.prototype.hasOwnProperty.call(e,t);t("anchorType")&&mo(Tt,Br(e.anchorType)),t("storedSceneId")&&mo(jt,Br(e.storedSceneId)),t("storedChapterId")&&mo(Wt,Br(e.storedChapterId)),t("resolutionMethod")&&mo(Rt,Br(e.resolutionMethod))},vr=()=>{const e=vo(),t=Number.isInteger(en)&&en>0&&Zt===en,n=!Number.isInteger(tn)||tn<=0||Xt===tn,r=t&&n;mo(oe,r?"Attached to PlotDirector":"Not attached"),mo(ae,e?.bookId?String(e.bookId):"-"),mo(ce,Number.isInteger(tn)&&tn>0?String(tn):"-"),mo(ie,Number.isInteger(en)&&en>0?String(en):"-"),se&&(se.disabled=!en||r&&!on,se.textContent=Zt&&!r?"Reattach PlotDirector IDs":"Attach PlotDirector IDs"),kr({anchorType:rn||"Title Match",storedSceneId:Zt,storedChapterId:Xt,resolutionMethod:nn})},xr=(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=_t===c&&zt===i&&Kt===s&&Qt===d&&Xt===l&&Zt===u;_t=e||"",zt=t||"",Kt=Number.isInteger(n)?n:null,Qt=Number.isInteger(a)&&a>0?a:null,Xt=Number.isInteger(r)&&r>0?r:null,Zt=Number.isInteger(o)&&o>0?o:null,p||(V&&(V.textContent=e||"Not detected"),Y&&(Y.textContent=t||"Not detected"),J&&(J.textContent=Number.isInteger(n)?String(n):"-"),mo(Se,Number.isInteger(n)?String(n):"-"),vr())},Nr=()=>{Mn&&(window.clearTimeout(Mn),Mn=null)},Er=(e,t)=>{e&&(e.hidden=t)},Lr=()=>{Er(de,!hn)},Pr=e=>{mo(ke,e)},Dr=e=>{mo(ee,e)},qr=(e="Select a project and book to analyse manuscript structure.")=>{if(pn=null,te){te.innerHTML="";const e=document.createElement("p");e.textContent="No preview generated.",te.append(e)}Dr(e),$r()},Ar=(e=pn)=>((e=pn)=>Zo.flatMap(t=>Array.isArray(e?.[t.key])?e[t.key]:[]))(e).filter(e=>"couldLink"===e.category||"wouldCreateChapters"===e.category||"wouldCreateScenes"===e.category),$r=()=>{Z&&(Z.disabled=Nn||0===Ar().length)},Tr=()=>{X&&(X.disabled=Nn||!ko()||!vo()),$r()},jr=()=>{Ae&&(Ae.textContent=en?`Editing links for: ${dr||zt||"Current scene"}`:"Link a PlotDirector scene first.")},Wr=()=>{const e=Pn||!en,t=e||!tn||On;Ie&&(Ie.disabled=t),De&&(De.disabled=e),Pe&&(Pe.disabled=e);for(const t of[Ee,Le])for(const n of t?[...t.querySelectorAll("input[type='checkbox']")]:[])n.disabled=e},Rr=e=>{"Live"!==e&&"Manual"!==e||(Ln=e),mo(_,e||Ln||"Manual")},Ur=(e,t="")=>{Pn=!!e,Pn&&(Nr(),Ja()),mo(_,Pn?"Stale":Ln),Wr(),t&&(br(t),Yr(t))},Mr=(e,t=null,n="")=>{en=Number.isInteger(e)&&e>0?e:null,tn=Number.isInteger(t)&&t>0?t:null,nn=n||"",en!==Gn&&(Hn=null),en||(Nr(),Ja()),Wr(),Pr(Pn?"Refresh Current Scene before syncing.":en?"Ready to sync.":"No resolved PlotDirector scene."),Yr(Pn?"Refresh Current Scene before saving.":en?"Ready to save.":"Link a PlotDirector scene first."),jr(),vr()},Or=e=>{H&&(H.disabled=e,H.textContent=e?"Refreshing...":"Refresh Current Scene")},Br=e=>null==e||""===e?"-":String(e),Gr=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"})}`},Hr=e=>{mn=e||null;const t=mn?.lastSyncUtc||mn?.manuscriptDocument?.lastSyncUtc;mo(we,Gr(t)),mo(Ce,Gr(t))},Fr=()=>{yn=null,gn=null,fn=null,Tn+=1,jn=null,_a(),za(),Ka(),Hr(null)},Vr=()=>{gn=null,fn=null},Yr=e=>{mo(qe,e)},Jr=e=>{mo(He,e)},_r=e=>{mo(Re,e)},zr=()=>!!vo()&&!!_t&&!tn,Kr=()=>!!vo()&&!!zt&&Number.isInteger(tn)&&tn>0,Qr=()=>{Er($e,!0),_r(""),je&&(je.disabled=!0,je.textContent="Create Chapter in PlotDirector"),We&&(We.disabled=!0,We.textContent="Link to Existing Chapter")},Xr=(e="")=>{mo(Te,Br(_t)),Er($e,!1),_r(e);const t=zr();je&&(je.disabled=!t,je.textContent="Create Chapter in PlotDirector"),We&&(We.disabled=!t,We.textContent="Link to Existing Chapter")},Zr=()=>{Er(Ue,!0),Jr(""),Be&&(Be.disabled=!0,Be.textContent="Create Scene in PlotDirector"),Ge&&(Ge.disabled=!0,Ge.textContent="Link to Existing Scene")},eo=(e="")=>{mo(Me,Br(_t)),mo(Oe,Br(zt)),Er(Ue,!1),Jr(e);const t=Kr();Be&&(Be.disabled=!t,Be.textContent="Create Scene in PlotDirector"),Ge&&(Ge.disabled=!t,Ge.textContent="Link to Existing Scene")},to=e=>{Cr(e),Er(le,!0),Er(ve,!0),Er(Ne,!1),Qr(),Zr(),nn="",dr="",lr="",rn=Zt?"SceneID Anchor":Xt?"ChapterID Anchor":"Title Match",on=!1,pr={characters:[],assets:[],locations:[],primaryLocationId:null},ro(Ee,[],"character"),ro(Le,[],"asset"),oo([],null,!1),Mr(null),mo(be,"-"),mo(ue,"-"),mo(pe,"-"),mo(he,"-"),mo(me,"-"),mo(ye,"-"),mo(fe,"-"),Er(ge,!0),vr(),jr()},no=(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(no(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)}},oo=(e,t,n=!1)=>{if(!Pe)return;Pe.innerHTML="";const r=document.createElement("option");r.value="",r.textContent="None",Pe.append(r);const o=Number.parseInt(t||"",10);for(const t of Array.isArray(e)?e:[]){const e=Number.parseInt(no(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,Pe.append(n)}Pe.disabled=!n},ao=e=>String(e||"").trim().replace(/\s+/g," "),co=(e,t)=>{const n=ao(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 ao(n.replace(r,""))||n},io=e=>{const t=t=>Object.prototype.hasOwnProperty.call(e,t);t("projectId")&&mo(gt,Br(e.projectId)),t("projectTitle")&&mo(ft,Br(e.projectTitle)),t("bookId")&&mo(wt,Br(e.bookId)),t("bookTitle")&&mo(It,Br(e.bookTitle)),t("detectedChapter")&&mo(St,Br(e.detectedChapter)),t("detectedScene")&&mo(bt,Br(e.detectedScene)),t("requestChapter")&&mo(Ct,Br(e.requestChapter)),t("requestScene")&&mo(kt,Br(e.requestScene)),t("result")&&mo(vt,Br(e.result)),t("chapterId")&&mo(xt,Br(e.chapterId)),t("sceneId")&&mo(Nt,Br(e.sceneId))},so=async e=>{if(fn===e&&Array.isArray(gn?.chapters))return gn.chapters;const t=await xa(`/api/word-companion/books/${e}/structure`);return fn=e,gn=t||null,Array.isArray(t?.chapters)?t.chapters:[]},lo=async e=>{const t=await xa(`/api/word-companion/books/${e}/chapters`);return Array.isArray(t?.chapters)?t.chapters:[]},uo=e=>{if(Number.isInteger(tn)&&tn>0){const t=e.find(e=>e.chapterId===tn);if(t)return t}const t=co(_t,"chapter").toLocaleLowerCase();return t&&e.find(e=>co(e.title,"chapter").toLocaleLowerCase()===t)||null},po=async()=>{const e=vo();return e?uo(await so(e.bookId)):null},ho=async(e,t,n,r,o)=>{const a=await xa(`/api/word-companion/scenes/${t}/companion`);try{a.revisionStatus=await(async(e,t)=>{const n=await xa(`/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;rn=o||"Title Match",on=!1,Ur(!1),Cr("Linked to PlotDirector"),br(""),Qr(),Zr(),Mr(t,n,r),c=a,dr=c?.sceneTitle||zt||"",lr=c?.chapterTitle||_t||"",mo(ue,Br(c?.sceneTitle)),mo(pe,Br(c?.revisionStatus||c?.revisionStatusName||"Not provided")),mo(he,Br(c?.estimatedWords)),mo(me,Br(c?.actualWords)),mo(be,Br(c?.actualWords)),mo(ye,c?.blocked?"Blocked":"Not blocked"),c?.blockedReason?(mo(fe,c.blockedReason),Er(ge,!1)):(mo(fe,"-"),Er(ge,!0)),xe&&(xe.textContent=c?.writingBrief||"No writing brief has been added for this scene."),pr={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(Ee,pr.characters,"character",!!en&&!Pn),ro(Le,pr.assets,"asset",!!en&&!Pn),oo(pr.locations,pr.primaryLocationId,!!en&&!Pn),jr(),Yr(Pn?"Refresh Current Scene before saving.":en?"Ready to save.":"No resolved PlotDirector scene."),Er(le,!1),Er(ve,!1),Er(Ne,!1),La(t,n),Ya(),rc()},mo=(e,t)=>{if(e){const n=null==t?"":String(t);e.textContent!==n&&(e.textContent=n)}},yo=e=>{const t=t=>Object.prototype.hasOwnProperty.call(e,t);t("host")&&mo(Lt,e.host),t("platform")&&mo(Pt,e.platform),t("ready")&&mo(Dt,e.ready),t("wordApi")&&mo(qt,e.wordApi),t("lastScan")&&mo(At,e.lastScan),t("lastError")&&mo($t,e.lastError),t("paragraphs")&&mo(Ut,e.paragraphs),t("heading1")&&mo(Mt,e.heading1),t("heading2")&&mo(Ot,e.heading2)},go=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)},fo=async()=>{if(!window.Office||"function"!=typeof window.Office.onReady)return Ft=!1,Vt=!1,Yt="Unavailable",Jt="Unavailable",yo({host:Yt,platform:Jt,ready:"No",wordApi:"No"}),null;const e=await window.Office.onReady();return Ft=!0,Yt=e?.host||"Unknown",Jt=e?.platform||"Unknown",Vt=!!window.Word&&!!window.Office.HostType&&e?.host===window.Office.HostType.Word,yo({host:Yt,platform:Jt,ready:"Yes",wordApi:Vt?"Yes":"No"}),e},wo=e=>{try{const t=window.localStorage.getItem(e),n=Number.parseInt(t||"",10);return Number.isInteger(n)&&n>0?n:null}catch{return null}},Io=(e,t)=>{try{t?window.localStorage.setItem(e,String(t)):window.localStorage.removeItem(e)}catch{}},So=(e,t)=>{if(!e)return;e.innerHTML="";const n=document.createElement("option");n.value="",n.textContent=t,e.append(n),e.disabled=!0},bo=(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},Co=e=>{const t=String(e?.title||"").trim(),n=String(e?.subtitle||"").trim();return n?`${t}: ${n}`:t},ko=()=>{const e=Number.parseInt(M?.value||"",10);return Gt.find(t=>t.projectId===e)||null},vo=()=>{const e=Number.parseInt(O?.value||"",10);return Ht.find(t=>t.bookId===e)||null},xo=()=>{const e=Number.parseInt(l?.value||"",10);return Gt.find(t=>t.projectId===e)||null},No=()=>{const e=Number.parseInt(u?.value||"",10);return Ht.find(t=>t.bookId===e)||null},Eo=e=>mo(g,e),Lo=()=>{const e=xo(),t=No(),n=Cn&&Date.now()-kn>=750;m&&(m.disabled=!e||!t||vn),h&&(h.disabled=!e||!String(p?.value||"").trim()||vn),N&&(N.disabled=!wn?.canImport||!In||vn),C&&(C.disabled=!n||xn||0===Ao().length)},Po=e=>{Er(d,!e),Er(c,e),Lr();for(const t of s)Er(t,!!e||"scene"!==t.dataset.tabPanel&&!t.classList.contains("is-active"));e||fr()},Do=()=>{if(!l)return;if(0===Gt.length)return void So(l,"No projects available.");bo(l,"Choose a project",Gt,"projectId","title");const e=Number.parseInt(M?.value||"",10);Number.isInteger(e)&&e>0&&(l.value=String(e))},qo=(e="Select a Project and Book to begin.")=>{wn=null,In=null,Sn=[],bn=!1,Cn=!1,kn=0,Er(f,!0),Er(x,!0),Er(w,!0),Er(b,!0),f&&(f.innerHTML=""),S&&(S.innerHTML=""),mo(I,""),Eo(e),Lo()},Ao=()=>S?[...S.querySelectorAll("input[type='checkbox']:checked")].map(e=>String(e.value||"").trim()).filter(Boolean):[],$o=e=>{if(Sn=Array.isArray(e)?e:[],w&&S){if(S.innerHTML="",Er(w,!1),Er(b,!bn||0===Sn.length),Er(C,!1),Er(k,!1),Er(v,!0),0===Sn.length)return mo(I,"No likely major characters found."),void Lo();mo(I,`${Sn.length} likely major characters found.`);for(const e of Sn){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",Lo);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),S.append(t)}Lo()}},To=()=>{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}},jo=()=>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."))}),Wo=()=>hn?.documentGuid?hn.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)),Ro=()=>hn?.documentGuid||To()?.documentGuid||"",Uo=()=>{const e=ko(),t=vo();R&&(R.textContent=e?.title||"(Not connected)"),U&&(U.textContent=t?Co(t):"(Not connected)"),K&&(K.textContent=t?"":"Select a PlotDirector book before refreshing."),Tr()},Mo=e=>String(e?.styleBuiltIn||e?.style||"").replace(/\s+/g,"").toLowerCase(),Oo=(e,t)=>{const n=Mo(e);return n===`heading${t}`||n.endsWith(`.heading${t}`)||n.includes(`heading${t}`)},Bo=e=>String(e||"").trim().split(/\s+/).filter(Boolean).length,Go=(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},Ho=e=>{try{return Array.isArray(e?.contentControls?.items)?e.contentControls.items:[]}catch(e){return console.warn("Word paragraph content controls were not available.",e),[]}},Fo=(e,t)=>{const n=Ho(e);for(const e of n){const n=Go(e.tag,t);if(n)return n}return null},Vo=(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(Oo(e,1))return r+=1,a={index:n.length+1,paragraphIndex:t,title:i,anchorId:Fo(e,"PD-CHAPTER"),scenes:[]},n.push(a),void(c=null);if(Oo(e,2)){if(o+=1,!a)return;return c={index:a.scenes.length+1,paragraphIndex:t,title:i,anchorId:Fo(e,"PD-SCENE"),wordCount:0},void a.scenes.push(c)}c&&(c.wordCount+=Bo(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()&&Mo(t)===Mo(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}},Yo=new Set(["***","###"]),Jo=(e,t)=>{const n=String(e?.text||"").trim();return{index:t,text:n,styleBuiltIn:e?.styleBuiltIn||"",style:e?.style||"",wordCount:Bo(n),chapterAnchorId:null,sceneAnchorId:null}},_o=(e,t)=>{e&&(e.endParagraphIndex=t)},zo=(e,t)=>{e&&(e.endParagraphIndex=t,_o(e.scenes.at(-1),t))},Ko=(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()&&Mo(e)===Mo(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(!yn)return!1;const t=((e,t)=>!e||!Number.isInteger(t)||t<0?null:e.chapters.filter(e=>e.startParagraphIndex<=t).at(-1)||null)(yn,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!==yn.currentChapter?.startParagraphIndex||n?.startParagraphIndex!==yn.currentScene?.startParagraphIndex||t?.anchorId!==yn.currentChapter?.anchorId||n?.anchorId!==yn.currentScene?.anchorId;return yn.currentParagraphIndex=e,yn.currentChapter=t,yn.currentScene=n,!!r&&(xr(t?.title,n?.title,n?.wordCount,t?.anchorId,n?.anchorId,t?.index),r)},Xo=e=>{if(!Q)return;if(Q.innerHTML="",0===e.chapters.length){const e=document.createElement("p");return e.textContent="No chapters detected. Use Heading 1 for chapter titles.",void Q.append(e)}if(!e.chapters.some(e=>e.scenes.length>0)){const e=document.createElement("p");e.textContent="No scenes detected. Use Heading 2 for scene titles.",Q.append(e)}for(const t of e.chapters){const e=document.createElement("div");e.className="word-companion-outline-chapter";const n=document.createElement("strong");if(n.textContent=t.title,e.append(n),t.scenes.length>0){const n=document.createElement("ul");for(const e of t.scenes){const t=document.createElement("li");t.textContent=e.title,n.append(t)}e.append(n)}Q.append(e)}},Zo=[{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"}],ea={alreadyLinked:"Already Linked",couldLink:"Could Link",wouldCreateChapter:"Would Create Chapter",wouldCreateScene:"Would Create Scene",manualReview:"Manual Review Required"},ta={alreadyLinked:"✓",couldLink:"~",wouldCreateChapter:"+",wouldCreateScene:"+",manualReview:"?"},na=(e,t)=>co(e,t).toLocaleLowerCase(),ra=({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:""}),oa=(e,t)=>{Array.isArray(e[t.category])&&e[t.category].push(t)},aa=e=>Array.isArray(e?.scenes)?e.scenes:[],ca=(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=ra({category:"alreadyLinked",action:"alreadyLinked",type:"Chapter",wordTitle:e.title,match:`Chapter ${o.chapterId}: ${o.title}`,anchorStatus:r,pdChapter:o,wordChapter:e});return oa(n,t),t}const a=ra({category:"manualReview",action:"manualReview",type:"Chapter",wordTitle:e.title,anchorStatus:`${r} not found`,matches:[],pdChapter:null,wordChapter:e});return oa(n,a),a}const o=t.filter(t=>na(t.title,"chapter")===na(e.title,"chapter"));if(1===o.length){const t=ra({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 oa(n,t),t}if(o.length>1){const t=ra({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 oa(n,t),t}const a=ra({category:"wouldCreateChapters",action:"wouldCreateChapter",type:"Chapter",wordTitle:e.title,anchorStatus:r,pdChapter:null,wordChapter:e});return oa(n,a),a},ia=(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=aa(n).find(e=>e.sceneId===t);if(e)return{chapter:n,scene:e}}return null})(n,e.anchorId);return a?void oa(r,ra({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 oa(r,ra({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 oa(r,ra({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 oa(r,ra({category:"wouldCreateScenes",action:"wouldCreateScene",type:"Scene",wordTitle:e.title,anchorStatus:o,wordChapter:t?.wordChapter,wordScene:e,parentItem:t}));const a=aa(t.pdChapter).filter(t=>na(t.title,"scene")===na(e.title,"scene"));1!==a.length?a.length>1?oa(r,ra({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})):oa(r,ra({category:"wouldCreateScenes",action:"wouldCreateScene",type:"Scene",wordTitle:e.title,anchorStatus:o,pdChapter:t.pdChapter,wordChapter:t.wordChapter,wordScene:e,parentItem:t})):oa(r,ra({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}))},sa=e=>{const t=document.createElement("article");t.className="word-companion-preview-item";const n=document.createElement("strong");n.textContent=`${ta[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: ${ea[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},da=e=>{if(te){te.innerHTML="";for(const t of Zo){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(sa(e));te.append(n)}$r()}},la=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)(Oo(e,1)||Oo(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=Vo(t.items,n.items);return r.bodyParagraphs=t.items,r},ua=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(Jo),r=[];let o=0,a=0,c=null,i=null,s=0;const d=(e,t=null,n=null)=>c?(_o(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&&(Oo(e,1)?(zo(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&&Yo.has(e.text)?(a+=1,d(e)):(c.wordCount+=e.wordCount,i&&(i.wordCount+=e.wordCount),s+=e.wordCount)));return zo(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=Ko(o,r.items);return yn=o,Qo(a),hr("Cache rebuilt."),o},pa=()=>window.performance&&"function"==typeof window.performance.now?window.performance.now():Date.now(),ha=e=>!!e&&!e.stale&&e.generation===Tn&&e.documentGuid===Ro()&&e.sceneId===en,ma=async(e={})=>{const t=!!e.includeSelection,n=!1!==e.updateDisplay,r=Tn,o=pa(),a=ko(),c=vo(),i=yn?.currentScene;if(!i||!Number.isInteger(i.startParagraphIndex)||!Number.isInteger(i.endParagraphIndex))return null;if(!Ft||!Vt||!window.Word||"function"!=typeof window.Word.run)return null;const s=pa(),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(pa()-s);if(r!==Tn)return mr(`Office snapshot: ${l}ms stale`),{stale:!0,generation:r};let u=!1;if(t){const e=Ko(yn,d.selectionParagraphs);u=Qo(e)}const p=yn?.currentScene;if(!p||!Number.isInteger(p.startParagraphIndex)||!Number.isInteger(p.endParagraphIndex))return null;const h=[];let m=0;const y=Math.min(p.endParagraphIndex,d.bodyTexts.length-1),g=yn.currentChapter?.startParagraphIndex;for(let e=p.startParagraphIndex;e<=y;e+=1){const t=String(d.bodyTexts[e]||"").trim();t&&!Yo.has(t)&&e!==g&&(h.push(t),m+=Bo(t))}p.wordCount=m,n&&xr(yn.currentChapter?.title,p.title,m,yn.currentChapter?.anchorId,p.anchorId,yn.currentChapter?.index);const f={documentGuid:Ro(),projectId:a?.projectId||null,bookId:c?.bookId||null,chapterId:tn,sceneId:en,chapterTitle:yn.currentChapter?.title||"",sceneTitle:p.title||"",sceneText:h.join("\n"),wordCount:m,selectionSignature:`${yn.currentParagraphIndex??-1}:${p.startParagraphIndex}:${p.endParagraphIndex}`,selectionChanged:u,generation:r};return jn=f,mr(`Office snapshot: ${l}ms; scene words: ${m}; total snapshot: ${Math.round(pa()-o)}ms`),f},ya=async()=>ha(jn)?jn:await ma(),ga=async()=>{if(br(""),!Ft||!Vt||!window.Word||"function"!=typeof window.Word.run)return xr(null,null,null),br("Word document access is unavailable."),yo({lastScan:"Failure",lastError:"Word document access is unavailable."}),!1;F&&(F.disabled=!0,F.textContent="Scanning..."),br("Scanning document structure...");try{const e=await window.Word.run(async e=>{const t=vo();return t?await ua(e,!!t.usesExplicitScenes):(yn=null,await la(e))});return yn||xr(e.currentChapter?.title,e.currentScene?.title,e.currentScene?.wordCount,e.currentChapter?.anchorId,e.currentScene?.anchorId,e.currentChapter?.index),to("Not detected"),Xo(e),br(""),yo({lastScan:"Success",lastError:"-",paragraphs:String(e.paragraphCount),heading1:String(e.heading1Count),heading2:String(e.heading2Count)}),!0}catch(e){const t=go(e);return console.error("Unable to scan the Word document.",e),xr(null,null,null),br(`Unable to scan the Word document: ${t}`),yo({lastScan:"Failure",lastError:t}),!1}finally{F&&(F.disabled=!1,F.textContent="Refresh Document Structure")}},fa=async()=>{const e=vo();if(!ko()||!e)return Dr("Select a project and book to analyse manuscript structure."),!1;if(!Ft||!Vt||!window.Word||"function"!=typeof window.Word.run)return Dr("Word document access is unavailable."),yo({lastScan:"Failure",lastError:"Word document access is unavailable."}),!1;X&&(X.disabled=!0,X.textContent="Analysing..."),Dr("Analysing manuscript structure...");try{const t=await window.Word.run(async e=>await la(e)),n=await xa(`/api/word-companion/books/${e.bookId}/structure`);return xr(t.currentChapter?.title,t.currentScene?.title,t.currentScene?.wordCount,t.currentChapter?.anchorId,t.currentScene?.anchorId,t.currentChapter?.index),Xo(t),pn=((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=ca(t,r,n);for(const o of aa(t))ia(o,e,r,n)}return n})(t,n),da(pn),Dr("Preview generated. No changes have been applied."),yo({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),Dr("Unable to analyse manuscript structure."),yo({lastScan:"Failure",lastError:go(e)}),!1}finally{X&&(X.textContent="Analyse Manuscript Structure",Tr())}},wa=e=>{En&&(En(e),En=null),pt?.close?pt.close():pt&&(pt.hidden=!0)},Ia=()=>{const e=((e=pn)=>{const t=Ar(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(!ht)return;ht.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)}ht.append(n)})(e),pt?new Promise(e=>{En=e,pt.showModal?pt.showModal():pt.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.`))},Sa=(e,t,n="")=>{e.result=t,e.error=n},ba=e=>Number.isInteger(e?.wordChapter?.index)&&e.wordChapter.index>0?10*e.wordChapter.index:null,Ca=e=>Number.isInteger(e?.wordScene?.index)&&e.wordScene.index>0?10*e.wordScene.index:null,ka=async(e,t)=>{const n=await Na(`/api/word-companion/books/${e}/chapters`,{title:ao(t.wordTitle),sortOrder:ba(t)});if(!n?.chapterId)throw new Error("Chapter creation did not return a chapter ID.");Vr(),t.pdChapter={chapterId:n.chapterId,title:n.title||t.wordTitle,sortOrder:n.sortOrder||ba(t)||0,scenes:[]},t.match=`Chapter ${t.pdChapter.chapterId}: ${t.pdChapter.title}`},va=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 Na(`/api/word-companion/books/${e}/chapters/${n.chapterId}/scenes`,{sceneTitle:ao(t.wordTitle),sortOrder:Ca(t)});if(!r?.sceneId)throw new Error("Scene creation did not return a scene ID.");Vr(),t.pdChapter=n,t.pdScene={sceneId:r.sceneId,title:t.wordTitle,sortOrder:Ca(t)||0},t.match=`Scene ${t.pdScene.sceneId}: ${t.pdScene.title}`},xa=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()},Na=(e,t)=>xa(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}),Ea=async(e="")=>{Cn=!1,kn=0,Sn=[],S&&(S.innerHTML=""),Er(w,!0),Po(!1),Eo(""),Er(b,!0),e&&br(e);const t=await Pa();e&&t&&_t&&br(e)},La=async(e=en,t=tn)=>{const n=ko(),r=vo(),o=Ro(),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(sr!==i){sr=i;try{await Na("/api/word-companion/runtime/current-scene",{documentGuid:o,projectId:n.projectId,bookId:r.bookId,chapterId:c,sceneId:a}),hr("Current scene follow event sent.")}catch(e){sr="",console.debug("Unable to notify PlotDirector of current scene.",e)}}},Pa=async()=>{const e=vo();if(!(e&&Ft&&Vt&&window.Word&&"function"==typeof window.Word.run))return!1;br("Reading manuscript position...");try{Vr(),await Promise.all([Qa(!0),Xa(!0),Za(!0)]),await so(e.bookId);const t=await window.Word.run(async t=>await ua(t,!!e.usesExplicitScenes));return Xo(t),yo({lastScan:"Success",lastError:"-",paragraphs:String(t.paragraphCount),heading1:String(t.heading1Count),heading2:String(t.heading2Count)}),_t?(zt?await ac():await oc(),Ur(!1),Rr("Live"),br(""),!0):(to("Not detected"),Ur(!1),Rr("Live"),br("Manuscript linked. Click inside a chapter to show the current scene."),!0)}catch(e){return console.error("Unable to initialise bound manuscript runtime.",e),yn=null,Rr("Manual"),br(`Unable to read manuscript position: ${go(e)}`),yo({lastScan:"Failure",lastError:go(e)}),!1}},Da=async n=>{hn=null,sc(),Nr(),Fr(),to("Not detected"),Rr("Manual"),wr("Connected"),Io(e,null),Io(t,null),M&&(M.value=""),So(O,"Select a project first"),Do(),l&&(l.value=""),So(u,"Select a project first"),qo(n||"Select a Project and Book to begin."),br(n||"Manuscript unlinked."),Pr("No resolved PlotDirector scene."),Po(!0),Lr()},qa=e=>e?[...e.querySelectorAll("input[type='checkbox']:checked")].map(e=>Number.parseInt(e.value||"",10)).filter(e=>Number.isInteger(e)&&e>0):[],Aa=()=>{const e=Number.parseInt(Pe?.value||"",10);return Number.isInteger(e)&&e>0?e:null},$a=(e,t,n,r)=>{const o=((e,t)=>Ho(e).find(e=>Go(e.tag,t))||null)(e,r),a=o||e.getRange().insertContentControl();return a.title=t,a.tag=n,a.appearance="Hidden",a},Ta=async(e="PlotDirector IDs attached successfully.")=>{if(!en||!tn)return br("No resolved PlotDirector scene."),!1;if((Zt&&Zt!==en||Xt&&Xt!==tn)&&!window.confirm("This scene is already linked. Replace the existing PlotDirector link?"))return!1;if(!Ft||!Vt||!window.Word||"function"!=typeof window.Word.run)return br("Word document access is unavailable."),!1;se&&(se.disabled=!0,se.textContent="Attaching...");try{return await window.Word.run(async e=>{const t=await la(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.");$a(n,"PlotDirector Chapter",`PD-CHAPTER-${tn}`,"PD-CHAPTER"),$a(r,"PlotDirector Scene",`PD-SCENE-${en}`,"PD-SCENE"),await e.sync()}),Xt=tn,Zt=en,on=!1,rn="SceneID Anchor",nn="Anchor",br(e),yo({lastError:"-"}),vr(),!0}catch(e){return console.error("Unable to attach PlotDirector IDs.",e),br("Unable to attach PlotDirector IDs."),yo({lastError:go(e)}),vr(),!1}finally{se&&(se.textContent=Zt===en?"Attach PlotDirector IDs":"Reattach PlotDirector IDs",vr())}},ja=async e=>{if(!tn)return _r("No resolved PlotDirector chapter."),!1;if(!Ft||!Vt||!window.Word||"function"!=typeof window.Word.run)return _r("Word document access is unavailable."),!1;try{return await window.Word.run(async e=>{const t=await la(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.");$a(n,"PlotDirector Chapter",`PD-CHAPTER-${tn}`,"PD-CHAPTER"),await e.sync()}),Xt=tn,on=!1,rn="ChapterID Anchor",nn="Chapter anchor",_r(e),br(e),yo({lastError:"-"}),vr(),!0}catch(e){return console.error("Unable to attach PlotDirector chapter ID.",e),_r("Unable to attach PlotDirector chapter ID."),yo({lastError:go(e)}),vr(),!1}},Wa=async e=>{Qr(),await ac(),br(e),_r(e)},Ra=e=>{un&&(un(e),un=null),it?.close?it.close():it&&(it.hidden=!0)},Ua=()=>{if(!rt)return;const e=ao(nt?.value||"").toLocaleLowerCase(),t=dn.filter(t=>!e||String(t.title||"").toLocaleLowerCase().includes(e));if(rt.innerHTML="",ln=null,ot&&(ot.disabled=!0),0===t.length){const e=document.createElement("p");return e.className="word-companion-empty-list",e.textContent="No chapters found.",void rt.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",()=>{ln=t,ot&&(ot.disabled=!1)});const o=document.createElement("span");o.textContent=e.title||"Untitled chapter",n.append(r,o),rt.append(n)}},Ma=()=>{tt?.close?tt.close():tt&&(tt.hidden=!0)},Oa=async(e,t,n)=>{const r=vo();if(!r)return Jr("Select a PlotDirector book first."),!1;await ho(r.bookId,e,t,"Manual link","Title Match");return!!await Ta(n)&&(Jr(n),Zr(),!0)},Ba=e=>{sn&&(sn(e),sn=null),Ke?.close?Ke.close():Ke&&(Ke.hidden=!0)},Ga=()=>{if(!Ye)return;const e=ao(Ve?.value||"").toLocaleLowerCase(),t=an.filter(t=>!e||String(t.title||"").toLocaleLowerCase().includes(e));if(Ye.innerHTML="",cn=null,Je&&(Je.disabled=!0),0===t.length){const e=document.createElement("p");return e.className="word-companion-empty-list",e.textContent="No scenes found.",void Ye.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",()=>{cn=t,Je&&(Je.disabled=!1)});const o=document.createElement("span");o.textContent=e.title||"Untitled scene",n.append(r,o),Ye.append(n)}},Ha=()=>{Fe?.close?Fe.close():Fe&&(Fe.hidden=!0)},Fa=()=>{On=!1,Wr(),Bn&&(Bn=!1,Ya(1e3))},Va=async(e={})=>{const t=e.source||"manual",n=pa();if(!en)return void Pr("No resolved PlotDirector scene.");if(!tn)return void Pr("No resolved PlotDirector chapter.");if(Pn)return void Pr("Refresh Current Scene before syncing.");const r=vo(),o=Ro();if(!r||!o)return void Pr("Bound manuscript metadata is unavailable.");if(On)return Bn=!0,void hr("Scene sync deferred; sync already running.");Nr(),On=!0,Bn=!1;let a=e.snapshot||null;try{a=ha(a)?a:await ya()}catch(e){return Pr("Sync failed"),yo({lastError:go(e)}),hr("Scene sync failed."),void Fa()}if(!ha(a))return Pr("Waiting for typing to pause"),hr("Scene sync skipped (stale snapshot)."),void Fa();const c=a.wordCount;if(!Number.isInteger(c)||c<0)return Pr("Sync failed"),hr("Scene sync failed."),void Fa();if(Gn===a.sceneId&&Hn===c)return Pr("Synced"),hr("Sync skipped (count unchanged)."),void Fa();hr("Scene word count changed."),Ie&&(Ie.disabled=!0,Ie.textContent="Syncing..."),Pr("Syncing..."),hr(`Scene sync started (${t}).`);try{const e=pa(),t=await Na("/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(mr(`Word count sync API: ${Math.round(pa()-e)}ms`),!ha(a))return void hr("Scene sync result ignored (stale snapshot).");const i=t?.actualWords??c,s=new Date;Gn=a.sceneId,Hn=i,mo(be,Br(i)),mo(me,Br(i)),mo(Ce,Gr(s)),mo(we,Gr(s)),Pr("Synced"),hr("Scene sync succeeded."),mr(`Total word count sync: ${Math.round(pa()-n)}ms`)}catch(e){Pr("Sync failed"),yo({lastError:go(e)}),hr("Scene sync failed.")}finally{Ie&&(Ie.textContent="Sync Current Scene"),Fa()}},Ya=(e=4e3)=>{Nr(),en&&tn&&!Pn&&!On&&(Mn=window.setTimeout(()=>{Mn=null,Va({source:"automatic"})},e))},Ja=()=>{Fn&&(window.clearTimeout(Fn),Fn=null)},_a=()=>{Jn=null,_n="",zn=[],Kn=null,Qn="",Ja()},za=()=>{Xn=null,Zn="",er=[],tr=null,nr=""},Ka=()=>{rr=null,or="",ar=[],cr=null,ir=""},Qa=async(e=!1)=>{const t=ko(),n=Ro();if(!t||!n)return zn=[],[];if(!e&&Jn===t.projectId&&_n===n&&zn.length>0)return zn;const r=await xa(`/api/word-companion/runtime/characters?projectId=${encodeURIComponent(t.projectId)}&documentGuid=${encodeURIComponent(n)}`);return Jn=t.projectId,_n=n,zn=Array.isArray(r?.characters)?r.characters:[],hr("Character alias cache refreshed."),zn},Xa=async(e=!1)=>{const t=ko(),n=Ro();if(!t||!n)return er=[],[];if(!e&&Xn===t.projectId&&Zn===n&&er.length>0)return er;const r=await xa(`/api/word-companion/runtime/assets?projectId=${encodeURIComponent(t.projectId)}&documentGuid=${encodeURIComponent(n)}`);return Xn=t.projectId,Zn=n,er=Array.isArray(r?.assets)?r.assets:[],hr(`Asset cache loaded: ${er.length} aliases.`),er},Za=async(e=!1)=>{const t=ko(),n=Ro();if(!t||!n)return ar=[],[];if(!e&&rr===t.projectId&&or===n&&ar.length>0)return ar;const r=await xa(`/api/word-companion/runtime/locations?projectId=${encodeURIComponent(t.projectId)}&documentGuid=${encodeURIComponent(n)}`);return rr=t.projectId,or=n,ar=Array.isArray(r?.locations)?r.locations:[],hr(`Location cache loaded: ${ar.length} aliases.`),ar},ec=(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)},tc=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},nc=async()=>{if(Fn=null,!en||Pn||!Ro())return;if(Vn)return Yn=!0,void hr("Character suggestion detection deferred; detection already running.");Vn=!0,Yn=!1;const e=pa();try{const t=await ya();if(!ha(t))return void hr("Runtime suggestions skipped (stale snapshot).");const[n,r,o]=await Promise.all([Qa(),Xa(),Za()]);if(!ha(t))return void hr("Runtime suggestions skipped after cache load (stale snapshot).");const a=t.sceneText||"",c=pa(),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)||ec(e,r.matchText)&&n.set(t,r.name||r.matchText||"Character")}return[...n.entries()].map(([e,t])=>({characterId:e,name:t}))})(a,n);mr(`Character detection: ${Math.round(pa()-c)}ms`);const s=i.map(e=>e.characterId),d=s.slice().sort((e,t)=>e-t).join(","),l=pa(),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)||ec(e,r.matchText)&&n.set(t,r.name||r.matchText||"Asset")}return[...n.entries()].map(([e,t])=>({assetId:e,name:t}))})(a,r);mr(`Asset detection: ${Math.round(pa()-l)}ms`);const p=u.map(e=>e.assetId),h=p.slice().sort((e,t)=>e-t).join(","),m=pa(),y=((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)||!tc(r)||ec(e,r.matchText)&&n.set(t,r.name||r.matchText||"Location")}return[...n.entries()].map(([e,t])=>({locationId:e,name:t}))})(a,o);mr(`Location detection: ${Math.round(pa()-m)}ms`);const g=y.map(e=>e.locationId),f=g.slice().sort((e,t)=>e-t).join(",");if(!d||Kn===en&&Qn===d)hr("Character suggestions skipped.");else{if(!ha(t))return void hr("Character suggestions skipped before submit (stale snapshot).");const e=pa(),n=await Na("/api/word-companion/runtime/character-suggestions",{documentGuid:t.documentGuid,sceneId:t.sceneId,characterIds:s});if(mr(`Character suggestion API: ${Math.round(pa()-e)}ms`),!ha(t))return void hr("Character suggestion result ignored (stale snapshot).");if(Kn=t.sceneId,Qn=d,(n?.createdCount||0)>0){const e=i.slice(0,3).map(e=>e.name).join(", "),t=i.length>3?" +"+(i.length-3):"";br(e?`Characters detected: ${e}${t}`:n.message)}hr(n?.message||"Character suggestions submitted.")}if(!h||tr===en&&nr===h)hr("Asset suggestions skipped.");else{if(!ha(t))return void hr("Asset suggestions skipped before submit (stale snapshot).");hr(`Asset matches found: ${u.map(e=>e.name).join(", ")}`);const e=pa(),n=await Na("/api/word-companion/runtime/asset-suggestions",{documentGuid:t.documentGuid,sceneId:t.sceneId,assetIds:p});if(mr(`Asset suggestion API: ${Math.round(pa()-e)}ms`),!ha(t))return void hr("Asset suggestion result ignored (stale snapshot).");if(tr=t.sceneId,nr=h,(n?.createdCount||0)>0){const e=u.slice(0,3).map(e=>e.name).join(", "),t=u.length>3?" +"+(u.length-3):"";br(e?`Assets detected: ${e}${t}`:n.message)}hr(n?.message||"Asset suggestions submitted.")}if(!f||cr===en&&ir===f)hr("Location suggestions skipped.");else{if(!ha(t))return void hr("Location suggestions skipped before submit (stale snapshot).");hr(`Location matches found: ${y.map(e=>e.name).join(", ")}`);const e=pa(),n=await Na("/api/word-companion/runtime/location-suggestions",{documentGuid:t.documentGuid,sceneId:t.sceneId,locationIds:g});if(mr(`Location suggestion API: ${Math.round(pa()-e)}ms`),!ha(t))return void hr("Location suggestion result ignored (stale snapshot).");if(cr=t.sceneId,ir=f,(n?.createdCount||0)>0){const e=y.slice(0,3).map(e=>e.name).join(", "),t=y.length>3?" +"+(y.length-3):"";br(e?`Locations detected: ${e}${t}`:n.message)}hr(n?.message||"Location suggestions submitted.")}mr(`Total suggestion pass: ${Math.round(pa()-e)}ms`)}catch(e){console.error("Unable to detect runtime suggestions.",e),yo({lastError:go(e)})}finally{Vn=!1,Yn&&(Yn=!1,rc(1500))}},rc=(e=2500)=>{Ja(),!en||Pn||Vn?Vn&&(Yn=!0):Fn=window.setTimeout(()=>{nc()},e)},oc=async()=>{const e=ko(),t=vo(),n=co(_t,"chapter");if(io({projectId:e?.projectId,projectTitle:e?.title,bookId:t?.bookId,bookTitle:t?Co(t):void 0,detectedChapter:_t,detectedScene:zt,requestChapter:n,requestScene:"",result:"Not run",chapterId:null,sceneId:null}),!t)return to("Not detected"),br("Select a PlotDirector book first."),!1;if(!_t)return to("Not detected"),br("No chapter detected in Word. Use Heading 1 for chapters."),!1;to("Not detected");try{const e=await lo(t.bookId),r=Xt?e.find(e=>e.chapterId===Xt):null,o=n.toLocaleLowerCase(),a=o?e.find(e=>co(e.title,"chapter").toLocaleLowerCase()===o):null,c=r||a;return c?(Qr(),Mr(null,c.chapterId,r?"Chapter anchor":"Chapter title"),rn=r?"ChapterID Anchor":"Title Match",Cr("Chapter linked to PlotDirector"),br("No scene detected in Word. Use Heading 2 for scenes."),io({result:"Chapter matched",chapterId:c.chapterId,sceneId:null}),!0):(Mr(null),Cr("Chapter not found in PlotDirector."),br("Chapter not found in PlotDirector."),io({result:"Chapter not matched",chapterId:null,sceneId:null}),Xr("Chapter not found in PlotDirector."),!1)}catch(e){return to("Not found in PlotDirector"),yo({lastError:go(e)}),br("Unable to load PlotDirector chapter data."),!1}},ac=async()=>{const e=ko(),t=vo(),n=co(_t,"chapter"),r=co(zt,"scene");if(io({projectId:e?.projectId,projectTitle:e?.title,bookId:t?.bookId,bookTitle:t?Co(t):void 0,detectedChapter:_t,detectedScene:zt,requestChapter:n,requestScene:r,result:"Not run",chapterId:null,sceneId:null}),kr({anchorType:Zt?"SceneID Anchor":Xt?"ChapterID Anchor":"Title Match",storedSceneId:Zt,storedChapterId:Xt,resolutionMethod:"-"}),!t)return to("Not detected"),br("Select a PlotDirector book first."),io({result:"Error"}),!1;if(!_t||!zt)return to("Not detected"),br("No scene detected in Word. Use Heading 2 for scenes."),io({result:"Error"}),!1;ne&&(ne.disabled=!0,ne.textContent="Refreshing...");const o=()=>{ne&&(ne.disabled=!1,ne.textContent="Refresh PlotDirector Scene")};to("Not detected"),br("Resolving PlotDirector scene...");try{if(Zt){const e=await(async(e,t)=>{const n=await xa(`/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===Zt);if(e)return io({result:"Matched",chapterId:e.chapter.chapterId,sceneId:e.scene.sceneId}),await ho(t.bookId,e.scene.sceneId,e.chapter.chapterId,"Anchor","SceneID Anchor"),!0;on=!0,rn="SceneID Anchor",Cr("Not found in PlotDirector"),br("Stored PlotDirector ID is invalid."),io({result:"Error",chapterId:Xt,sceneId:Zt}),kr({anchorType:"SceneID Anchor",storedSceneId:Zt,storedChapterId:Xt,resolutionMethod:"Anchor"})}if(Xt){const e=(await so(t.bookId)).find(e=>e.chapterId===Xt),n=e?(Array.isArray(e.scenes)?e.scenes:[]).find(e=>co(e.title,"scene").toLocaleLowerCase()===r.toLocaleLowerCase()):null;if(n)return io({result:"Matched",chapterId:e.chapterId,sceneId:n.sceneId}),await ho(t.bookId,n.sceneId,e.chapterId,"Anchor","ChapterID Anchor"),!0;e&&!Zt?(rn="ChapterID Anchor",Mr(null,Xt,"Chapter anchor"),io({result:"Chapter matched",chapterId:Xt,sceneId:null})):Zt||(rn="ChapterID Anchor",io({result:"Chapter anchor not found",chapterId:Xt,sceneId:null}))}const e=await Na(`/api/word-companion/books/${t.bookId}/resolve-scene`,{chapterTitle:n,sceneTitle:r});if(!e?.matched||!e.sceneId){const t=on,n=Number.parseInt(e?.chapterId||"",10),r=Number.isInteger(tn)&&tn>0?tn:null,a=Number.isInteger(n)&&n>0?n:r,c=!!e?.chapterMatched||!!a;return to("Not found in PlotDirector"),on=t,c&&(Mr(null,a,a===r?"Chapter anchor":"Chapter title"),Cr("Scene not found in PlotDirector.")),br(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."),io({result:"Not matched",chapterId:c?a:e?.chapterId,sceneId:e?.sceneId}),t||(c?(Qr(),eo("Scene not found in PlotDirector.")):(Zr(),Xr("Chapter not found in PlotDirector."))),o(),!1}const a=on;return io({result:a?"Matched by title fallback":"Matched",chapterId:e.chapterId,sceneId:e.sceneId}),await ho(t.bookId,e.sceneId,e.chapterId,a?"Title fallback":"Title","Title Match"),a&&(on=!0,br("Stored PlotDirector ID is invalid."),vr()),!0}catch(e){const t=on;return yo({lastError:go(e)}),to("Not found in PlotDirector"),on=t,br(t?"Stored PlotDirector ID is invalid.":"Unable to load PlotDirector scene data."),io({result:"Error"}),!1}finally{o()}},cc=async()=>{if(Dn=null,Un)return $n=!0,void hr("Runtime update deferred; update already running.");if(!Bt||!vo())return qn=!1,void hr("Runtime update skipped.");if(!Ft||!Vt||!window.Word||"function"!=typeof window.Word.run)return qn=!1,Rr("Manual"),void br("Automatic scene tracking is unavailable in this Word version. Use Refresh Current Scene.");if(!yn)return qn=!1,Rr("Manual"),void br("Document structure is not cached yet. Use Refresh Current Scene.");const e=Date.now()-An;if(qn&&e{Dn&&window.clearTimeout(Dn),Dn=window.setTimeout(cc,Math.max(0,e)),Rr("Waiting for typing to pause"),hr("Runtime update scheduled.")},sc=()=>{Dn&&(window.clearTimeout(Dn),Dn=null),qn=!1,$n=!1},dc=()=>{((e="selection",t=1200)=>{if(qn=!0,An=Date.now(),Tn+=1,jn=null,Nr(),Ja(),On&&(Bn=!0),Vn&&(Yn=!0),hr(`${e} changed.`),Un)return $n=!0,void Rr("Waiting for typing to pause");ic(t)})("Selection")},lc=()=>{if(Rn&&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:dc}),Rn=!1}catch(e){console.warn("Unable to remove Word selection tracking handler.",e)}},uc=async(e,n)=>{if(yn=null,Vr(),!e)return Ht=[],So(O,"Select a project first"),So(u,"Select a project first"),Sr(""),Io(t,null),Uo(),to("Not detected"),void qr();So(O,"Loading books..."),Sr(""),to("Not detected"),qr("Select a book to analyse manuscript structure.");try{const r=await xa(`/api/word-companion/projects/${e}/books`);if(Ht=Array.isArray(r.books)?r.books:[],0===Ht.length)return So(O,"No books available."),So(u,"No books available."),Sr("No books available."),Io(t,null),Uo(),void qo("No books available.");bo(O,"Choose a book",Ht.map(e=>({...e,displayTitle:Co(e)})),"bookId","displayTitle");const o=Ht.find(e=>e.bookId===n);o&&O?(O.value=String(o.bookId),Io(t,o.bookId)):Io(t,null),((e=null)=>{if(!u)return;if(0===Ht.length)return void So(u,"No books available.");bo(u,"Choose a book",Ht.map(e=>({...e,displayTitle:Co(e)})),"bookId","displayTitle");const t=e||Number.parseInt(O?.value||"",10),n=Ht.find(e=>e.bookId===t);n&&(u.value=String(n.bookId)),Lo()})(o?.bookId||n),Uo(),to((vo(),"Not detected")),qr(vo()?"Ready to analyse manuscript structure.":"Select a book to analyse manuscript structure."),qo(No()?"Ready to scan manuscript structure.":"Select a Book to begin.")}catch{Ht=[],So(O,"Unable to load books."),So(u,"Unable to load books."),Sr("Unable to load books."),Io(t,null),Uo(),to("Not detected"),qr("Unable to load books."),qo("Unable to load books.")}};for(const e of i)e.addEventListener("click",()=>gr(e.dataset.tabButton));fr(),M?.addEventListener("change",async()=>{const n=Number.parseInt(M.value||"",10);Fr(),l&&Number.isInteger(n)&&n>0&&(l.value=String(n)),Io(e,Number.isInteger(n)&&n>0?n:null),Io(t,null),to("Not detected"),qr(),qo("Select a Book to begin."),await uc(n,null)}),O?.addEventListener("change",()=>{const e=Number.parseInt(O.value||"",10);Fr(),Io(t,Number.isInteger(e)&&e>0?e:null),u&&Number.isInteger(e)&&e>0&&(u.value=String(e)),Uo(),to("Not detected"),qr(vo()?"Ready to analyse manuscript structure.":"Select a book to analyse manuscript structure."),qo(No()?"Ready to scan manuscript structure.":"Select a Book to begin.")}),l?.addEventListener("change",async()=>{const n=Number.parseInt(l.value||"",10);Fr(),M&&Number.isInteger(n)&&n>0&&(M.value=String(n)),Io(e,Number.isInteger(n)&&n>0?n:null),Io(t,null),qo("Select a Book to begin."),await uc(n,null)}),u?.addEventListener("change",()=>{const e=Number.parseInt(u.value||"",10);Fr(),O&&Number.isInteger(e)&&e>0&&(O.value=String(e)),Io(t,Number.isInteger(e)&&e>0?e:null),Uo(),qo(No()?"Ready to scan manuscript structure.":"Select a Book to begin.")}),p?.addEventListener("input",Lo),h?.addEventListener("click",async()=>{const e=xo(),t=String(p?.value||"").trim();if(e&&t){h.disabled=!0,Eo("Creating Book...");try{const n=await Na(`/api/word-companion/projects/${e.projectId}/books`,{title:t});p&&(p.value=""),M&&(M.value=String(e.projectId)),await uc(e.projectId,n.bookId),u&&(u.value=String(n.bookId)),Eo("Ready to scan manuscript structure.")}catch(e){console.error("Unable to create Book from Word Companion.",e),Eo(`Unable to create Book: ${go(e)}`)}finally{Lo()}}else Lo()}),m?.addEventListener("click",async()=>{const e=xo(),t=No();if(e&&t)if(Ft&&Vt&&window.Word&&"function"==typeof window.Word.run){m&&(m.disabled=!0,m.textContent="Scanning..."),Eo("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),Oo(e,1))return r={title:d,sortOrder:10*(n.length+1),wordCount:0,scenes:[]},n.push(r),o=s(),void(a+=Bo(d));if(!r||!o)return;if(t&&i.has(d))return void(o=s());const l=Bo(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)});In=n,bn=!1;const r=await Na("/api/word-companion/manuscript/analyse",{projectId:e.projectId,bookId:t.bookId,documentGuid:Wo(),chapterCount:n.chapterCount,sceneCount:n.sceneCount,wordCount:n.wordCount});wn=r,(e=>{if(!f)return;f.innerHTML="";const t=document.createElement("strong");t.textContent="Manuscript Analysis",f.append(t);const n=document.createElement("dl"),r=[["Project",e.projectTitle],["Book",Co({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)}f.append(n),Er(f,!1),Er(x,!1),Eo(e.message||"Preview generated."),Lo()})(r);try{const t=await Na("/api/word-companion/manuscript/discover-characters",{projectId:e.projectId,documentText:n.documentText||""});Sn=Array.isArray(t?.candidates)?t.candidates:[],Er(w,!0),Er(b,!0)}catch(e){console.error("Unable to discover character candidates.",e),Sn=[],Er(w,!0),Er(b,!0)}yo({lastScan:"Success",lastError:"-",paragraphs:"-",heading1:String(n.chapterCount),heading2:"-"})}catch(e){console.error("Unable to scan manuscript for first-run import.",e),qo(`Unable to scan manuscript: ${go(e)}`),yo({lastScan:"Failure",lastError:go(e)})}finally{m&&(m.textContent="Scan Manuscript"),Lo()}}else qo("Word document access is unavailable.");else qo("Select a Project and Book to begin.")}),N?.addEventListener("click",async()=>{const n=xo(),o=No();if(!(n&&o&&In&&wn?.canImport))return void Lo();let a=!1;if(!wn.requiresReplaceConfirmation||(a=await new Promise(e=>{if(!L||"function"!=typeof L.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=>{P?.removeEventListener("click",n),D?.removeEventListener("click",r),L?.removeEventListener("cancel",o),L?.close(),e(t)},n=()=>t(!0),r=()=>t(!1),o=e=>{e.preventDefault(),t(!1)};P?.addEventListener("click",n),D?.addEventListener("click",r),L?.addEventListener("cancel",o),L.showModal()}),a)){vn=!0,Lo(),Eo("Importing manuscript structure...");try{const i=Wo(),s=await Na("/api/word-companion/manuscript/import",{projectId:n.projectId,bookId:o.bookId,documentGuid:i,bindingVersion:1,replacePlanned:a,chapters:In.chapters});if(!s.imported)return wn={...wn,canImport:!s.requiresReplaceConfirmation,requiresReplaceConfirmation:!!s.requiresReplaceConfirmation,message:s.message||wn.message},Eo(s.message||"Import was not completed."),void Lo();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."))})),hn={documentGuid:d?.documentGuid||i,bookId:s.bookId,projectId:s.projectId,bindingVersion:d?.bindingVersion||1},Io(e,s.projectId),Io(t,s.bookId),M&&(M.value=String(s.projectId));const l=Sn;await uc(s.projectId,s.bookId),wr("Connected"),bn=!0,Cn=l.length>0,kn=Cn?Date.now():0,Sn=l,l.length>0?(Po(!0),$o(l),Er(x,!0),Er(b,!1),Eo(s.message||"Manuscript structure imported."),br(s.message||"Manuscript structure imported."),window.setTimeout(Lo,750)):await Ea(s.message||"Manuscript structure imported.")}catch(e){console.error("Unable to import manuscript structure.",e),Eo(`Unable to import manuscript: ${go(e)}`)}finally{vn=!1,Lo()}var c}else Eo("Import cancelled.")}),C?.addEventListener("click",async()=>{const e=xo()||ko(),t=Ao();if(!Cn||Date.now()-kn<750||!e||0===t.length)Lo();else{xn=!0,Lo(),mo(I,"Creating selected characters...");try{const n=await Na("/api/word-companion/manuscript/create-discovered-characters",{projectId:e.projectId,candidateNames:t});br(n.message||"Characters created."),mo(I,`${n.createdCount||0} created, ${n.skippedCount||0} already existed.`),await Ea(n.message||"Characters created.")}catch(e){console.error("Unable to create discovered characters.",e),mo(I,`Unable to create characters: ${go(e)}`)}finally{xn=!1,Lo()}}}),k?.addEventListener("click",()=>Ea("Character creation skipped.")),v?.addEventListener("click",()=>Ea()),y?.addEventListener("click",()=>Po(!1)),E?.addEventListener("click",()=>qo("Import cancelled.")),F?.addEventListener("click",ga),X?.addEventListener("click",fa),Z?.addEventListener("click",async()=>{const e=vo();if(!e||0===Ar().length||Nn)return void $r();if(!await Ia())return;Nn=!0,Tr(),Dr("Applying structure sync...");const t={createdChapters:0,createdScenes:0,linkedChapters:0,linkedScenes:0,skipped:Array.isArray(pn?.manualReview)?pn.manualReview.length:0,failed:0},n=Ar().filter(e=>"couldLink"===e.category&&"Chapter"===e.type),r=Ar().filter(e=>"wouldCreateChapters"===e.category),o=Ar().filter(e=>"couldLink"===e.category&&"Scene"===e.type),a=Ar().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(!Ft||!Vt||!window.Word||"function"!=typeof window.Word.run)throw new Error("Word document access is unavailable.");await window.Word.run(async t=>{const n=await la(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.");$a(o,"PlotDirector Chapter",`PD-CHAPTER-${t}`,"PD-CHAPTER")}else{const t=e.pdScene?.sceneId;if(!t)throw new Error("Scene ID is not available.");$a(o,"PlotDirector Scene",`PD-SCENE-${t}`,"PD-SCENE")}await t.sync()})})(e),Sa(e,"Success"),t[n]+=1}catch(n){Sa(e,"Failed",go(n)),t.failed+=1}};try{for(const e of n)s(e,"linkedChapters");for(const n of r)try{await ka(e.bookId,n),s(n,"createdChapters")}catch(e){Sa(n,"Failed",go(e)),t.failed+=1}for(const e of o)s(e,"linkedScenes");for(const n of a)try{await va(e.bookId,n),s(n,"createdScenes")}catch(e){Sa(n,"Failed",go(e)),t.failed+=1}for(const e of c)await d(e.item,e.counterName);for(const e of pn.manualReview||[])Sa(e,"Skipped");da(pn),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),Dr(i)}finally{Nn=!1,Tr(),i&&(Vr(),await fa(),Dr(`${i} Preview refreshed.`))}}),mt?.addEventListener("click",()=>wa(!0)),yt?.addEventListener("click",()=>wa(!1)),pt?.addEventListener("cancel",e=>{e.preventDefault(),wa(!1)}),ne?.addEventListener("click",ac),H?.addEventListener("click",async()=>{if(!vo())return br("Select a PlotDirector book first."),void to("Not detected");sc(),Or(!0),Rr("Updating...");try{await Promise.all([Qa(!0),Xa(!0),Za(!0)]);if(!await ga())return;if(Ur(!1),!zt)return await oc(),void Rr("Current scene updated");await ac(),Rr("Current scene updated")}finally{Or(!1)}}),Ie?.addEventListener("click",()=>Va({source:"manual"})),De?.addEventListener("click",async()=>{if(en)if(!Pn&&await(async()=>{if(!en)return!1;if(!Ft||!Vt||!window.Word||"function"!=typeof window.Word.run)return Ur(!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 la(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===tn,i=co(n,"scene").toLocaleLowerCase()===co(dr||zt,"scene").toLocaleLowerCase(),s=co(t,"chapter").toLocaleLowerCase()===co(lr||_t,"chapter").toLocaleLowerCase();return a||i&&(c||s)?(Ur(!1),!0):(Ur(!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),yo({lastError:go(e)}),Ur(!0,"The Word cursor is now in a different scene. Refresh Current Scene before saving."),!1}})()){De&&(De.disabled=!0,De.textContent="Saving...");try{await(e=`/api/word-companion/scenes/${en}/links`,t={characterIds:qa(Ee),assetIds:qa(Le),locationIds:[],primaryLocationId:Aa()},xa(e,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})),(()=>{const e=new Set(qa(Ee)),t=new Set(qa(Le));pr={characters:pr.characters.map(t=>({...t,linked:e.has(Number.parseInt(no(t,"character"),10))})),assets:pr.assets.map(e=>({...e,linked:t.has(Number.parseInt(no(e,"asset"),10))})),locations:pr.locations,primaryLocationId:Aa()}})(),Yr("Scene links saved successfully."),yo({lastError:"-"})}catch(e){Yr("Unable to save scene links."),yo({lastError:go(e)})}finally{De&&(De.disabled=!en||Pn,De.textContent="Save Scene Links")}var e,t}else Yr("The Word cursor is now in a different scene. Refresh Current Scene before saving.");else Yr("Link a PlotDirector scene first.")}),se?.addEventListener("click",async()=>{await Ta()}),de?.addEventListener("click",async()=>{console.debug("Word Companion unlink clicked"),br("Preparing to unlink manuscript...");const e=(()=>{const e=hn||To();if(e)return e;const t=mn?.manuscriptDocument?.documentGuid||"",n=Number.parseInt(mn?.bookId||"",10),r=Number.parseInt(mn?.projectId||"",10);return t&&Number.isInteger(n)&&n>0&&Number.isInteger(r)&&r>0?{documentGuid:t,bookId:n,projectId:r,bindingVersion:Number.parseInt(mn?.manuscriptDocument?.bindingVersion||"",10)||1}:null})();if(!e)return void br("This Word document is not linked.");if(!e.documentGuid||!Number.isInteger(e.bookId)||e.bookId<=0)return void br("Unable to unlink: bound document metadata is incomplete.");if(await new Promise(e=>{if(!q||"function"!=typeof q.showModal)return void e(window.confirm("This will remove PlotDirector binding metadata from this Word document.\n\nIf PlotDirector is reachable, it will also unlink this Book in PlotDirector.\n\nYour manuscript text will not be changed.\n\nContinue?"));const t=t=>{A?.removeEventListener("click",n),$?.removeEventListener("click",r),q?.removeEventListener("cancel",o),q?.close(),e(t)},n=()=>t(!0),r=()=>t(!1),o=e=>{e.preventDefault(),t(!1)};A?.addEventListener("click",n),$?.addEventListener("click",r),q?.addEventListener("cancel",o),q.showModal()})){br("Unlinking manuscript..."),de&&(de.disabled=!0,de.textContent="Unlinking...");try{await Na("/api/word-companion/manuscript/unlink",{documentGuid:e.documentGuid,bookId:e.bookId}),await jo(),await Da("Manuscript unlinked.")}catch(e){console.error("Unable to unlink manuscript binding.",e),br("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 jo(),await Da("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),br(`Unable to remove Word metadata: ${go(e)}`)}else br(`Unable to unlink manuscript: ${go(e)}`)}finally{de&&(de.disabled=!1,de.textContent="Unlink this Word document"),Lr()}}else br("Unlink cancelled.")}),je?.addEventListener("click",async()=>{const e=vo();if(!e||!_t||tn)return void Xr("Chapter not found in PlotDirector.");const t=ao(_t),n=await((e,t)=>(mo(st,`"${e}"`),mo(dt,`"${t}"`),it?new Promise(e=>{un=e,it.showModal?it.showModal():it.hidden=!1}):Promise.resolve(window.confirm(`Create PlotDirector chapter:\n\n"${e}"\n\nin book:\n\n"${t}"\n\n?`))))(t,Co(e)||"selected book");if(n){je&&(je.disabled=!0,je.textContent="Creating...");try{const n=Number.isInteger(Qt)&&Qt>0?10*Qt:null,r=await Na(`/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.");Vr(),Mr(null,r.chapterId,"Manual chapter link");if(!await ja("Chapter created and linked successfully."))return;await Wa("Chapter created and linked successfully.")}catch(e){_r("Unable to create chapter."),yo({lastError:go(e)})}finally{je&&(je.disabled=!zr(),je.textContent="Create Chapter in PlotDirector")}}}),We?.addEventListener("click",async()=>{const e=vo();if(e&&_t&&!tn){We&&(We.disabled=!0,We.textContent="Loading...");try{dn=await lo(e.bookId),ln=null,nt&&(nt.value=""),mo(ct,""),Ua(),tt?.showModal?tt.showModal():tt&&(tt.hidden=!1)}catch(e){_r("Unable to load chapters."),yo({lastError:go(e)})}finally{We&&(We.disabled=!zr(),We.textContent="Link to Existing Chapter")}}else Xr("Chapter not found in PlotDirector.")}),nt?.addEventListener("input",Ua),ot?.addEventListener("click",async()=>{const e=dn.find(e=>e.chapterId===ln);if(e){ot&&(ot.disabled=!0,ot.textContent="Linking...");try{Mr(null,e.chapterId,"Manual chapter link");if(!await ja("Chapter linked successfully."))return;Ma(),await Wa("Chapter linked successfully.")}catch(e){mo(ct,"Unable to link chapter."),_r("Unable to link chapter."),yo({lastError:go(e)})}finally{ot&&(ot.disabled=!ln,ot.textContent="Link Chapter")}}else mo(ct,"Select a chapter.")}),at?.addEventListener("click",Ma),lt?.addEventListener("click",()=>Ra(!0)),ut?.addEventListener("click",()=>Ra(!1)),it?.addEventListener("cancel",e=>{e.preventDefault(),Ra(!1)}),Be?.addEventListener("click",async()=>{const e=vo();if(!e||!zt)return void eo("Scene not found in PlotDirector.");const t=co(zt,"scene"),n=co(_t,"chapter"),r=await((e,t)=>(mo(Qe,`"${e}"`),mo(Xe,`"${t}"`),Ke?new Promise(e=>{sn=e,Ke.showModal?Ke.showModal():Ke.hidden=!1}):Promise.resolve(window.confirm(`Create PlotDirector scene:\n\n"${e}"\n\nwithin chapter:\n\n"${t}"\n\n?`))))(t,n);if(r){Be&&(Be.disabled=!0,Be.textContent="Creating...");try{const n=await po();if(!n)return void eo("This chapter does not exist in PlotDirector. Create or link the chapter first.");const r=await Na(`/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.");Vr(),await Oa(r.sceneId,r.chapterId,"Scene created and linked successfully.")}catch(e){Jr("Unable to create scene."),yo({lastError:go(e)})}finally{Be&&(Be.disabled=!Kr(),Be.textContent="Create Scene in PlotDirector")}}}),Ge?.addEventListener("click",async()=>{const e=vo();if(e&&zt){Ge&&(Ge.disabled=!0,Ge.textContent="Loading...");try{const t=await so(e.bookId),n=uo(t);if(!n)return void eo("This chapter does not exist in PlotDirector. Create or link the chapter first.");an=Array.isArray(n.scenes)?n.scenes:[],cn=null,Ve&&(Ve.value=""),mo(ze,""),Ga(),Fe?.showModal?Fe.showModal():Fe&&(Fe.hidden=!1)}catch(e){Jr("Unable to load scenes."),yo({lastError:go(e)})}finally{Ge&&(Ge.disabled=!Kr(),Ge.textContent="Link to Existing Scene")}}else eo("Scene not found in PlotDirector.")}),Ve?.addEventListener("input",Ga),Je?.addEventListener("click",async()=>{const e=vo(),t=an.find(e=>e.sceneId===cn);if(e&&t){Je&&(Je.disabled=!0,Je.textContent="Linking...");try{const e=await po();if(!e)throw new Error("This chapter does not exist in PlotDirector. Create or link the chapter first.");Ha(),await Oa(t.sceneId,e.chapterId,"Scene linked successfully.")}catch(e){mo(ze,"Unable to link scene."),Jr("Unable to link scene."),yo({lastError:go(e)})}finally{Je&&(Je.disabled=!cn,Je.textContent="Link Scene")}}else mo(ze,"Select a scene.")}),_e?.addEventListener("click",Ha),Ze?.addEventListener("click",()=>Ba(!0)),et?.addEventListener("click",()=>Ba(!1)),Ke?.addEventListener("cancel",e=>{e.preventDefault(),Ba(!1)}),Et?.addEventListener("click",async()=>{Et&&(Et.disabled=!0,Et.textContent="Running...");try{if(await fo(),!Ft||!Vt||!window.Word||"function"!=typeof window.Word.run)return void yo({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});yo({lastScan:"Success",lastError:"-",paragraphs:String(e)})}catch(e){console.error("Word Companion diagnostics failed.",e);const t=go(e);yo({lastScan:"Failure",lastError:t}),br(`Unable to scan the Word document: ${t}`)}finally{Et&&(Et.disabled=!1,Et.textContent="Run Diagnostics")}});const pc=Bt?(async()=>{So(M,"Loading projects..."),So(O,"Select a project first"),So(l,"Loading projects..."),So(u,"Select a project first"),Ir(""),Sr("");try{const n=await xa("/api/word-companion/projects");if(Gt=Array.isArray(n.projects)?n.projects:[],0===Gt.length)return So(M,"No projects available."),So(l,"No projects available."),Ir("No projects available."),Io(e,null),Io(t,null),Uo(),void qo("No projects available.");bo(M,"Choose a project",Gt,"projectId","title"),Do();const r=wo(e),o=Gt.find(e=>e.projectId===r);o&&M?(M.value=String(o.projectId),l&&(l.value=String(o.projectId)),Io(e,o.projectId),await uc(o.projectId,wo(t))):(Io(e,null),Io(t,null),Uo(),qo("Select a Project and Book to begin."))}catch{Gt=[],Ht=[],So(M,"Unable to connect to PlotDirector."),So(O,"Select a project first"),So(l,"Unable to connect to PlotDirector."),So(u,"Select a project first"),wr("Unable to connect to PlotDirector."),Ir("Unable to connect to PlotDirector."),Io(e,null),Io(t,null),Uo(),qo("Unable to connect to PlotDirector.")}})():Promise.resolve();if(Bt||(So(M,"Please sign in to PlotDirector."),So(O,"Please sign in to PlotDirector."),So(l,"Please sign in to PlotDirector."),So(u,"Please sign in to PlotDirector."),Uo()),!window.Office||"function"!=typeof window.Office.onReady)return yr("Word Companion ready"),br("Word document access is unavailable."),Rr("Manual"),void yo({host:"Unavailable",platform:"Unavailable",ready:"No",wordApi:"No"});fo().then(async()=>{yr("Word Companion ready"),await pc,await(async()=>{if(!Bt||!Vt)return void Po(!1);const n=To();if(n)try{const r=await xa(`/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 hn=n,Hr(r),Io(e,r.projectId),Io(t,r.bookId),M&&(M.value=String(r.projectId)),await uc(r.projectId,r.bookId),Po(!1),wr("Connected"),Sr("Bound manuscript detected."),void await Pa()}catch{}hn=null,Fr(),Do(),xo()?await uc(xo().projectId,null):So(u,"Select a project first"),qo("Select a Project and Book to begin."),Po(!0)})(),Vt?(()=>{if(Bt){if(!window.Office?.context?.document||"function"!=typeof window.Office.context.document.addHandlerAsync||!window.Office?.EventType?.DocumentSelectionChanged)return Rr("Manual"),void br("Automatic scene tracking is unavailable in this Word version. Use Refresh Current Scene.");try{window.Office.context.document.addHandlerAsync(window.Office.EventType.DocumentSelectionChanged,dc,e=>{e?.status===window.Office.AsyncResultStatus.Succeeded?(Rn=!0,Rr("Live")):(Rr("Manual"),br("Automatic scene tracking is unavailable in this Word version. Use Refresh Current Scene."))}),window.addEventListener("beforeunload",lc)}catch(e){console.warn("Unable to register Word selection tracking handler.",e),Rr("Manual"),br("Automatic scene tracking is unavailable in this Word version. Use Refresh Current Scene.")}}})():(br("Word document access is unavailable."),Rr("Manual"))}).catch(e=>{console.error("Office readiness check failed.",e),wr("Unable to connect to PlotDirector."),yr("Word Companion unavailable"),br("Word document access is unavailable."),yo({ready:"No",wordApi:"No",lastScan:"Failure"})})})(); \ No newline at end of file