2026-06-19 20:56:46 +01:00

1 line
45 KiB
JavaScript

(()=>{const e="plotline.theme",t=document.querySelectorAll("[data-theme-choice]"),a=a=>{const n="dark"===a?"dark":"light";document.documentElement.dataset.theme=n,document.documentElement.dataset.bsTheme=n,(t=>{try{localStorage.setItem(e,t)}catch{}})(n),t.forEach(e=>{const t=e.dataset.themeChoice===n;e.classList.toggle("active",t),e.setAttribute("aria-pressed",String(t))})};t.forEach(e=>{e.addEventListener("click",()=>a(e.dataset.themeChoice))}),a((()=>{try{return localStorage.getItem(e)}catch{return null}})()||"light")})(),(()=>{const e=document.querySelector("[data-trial-banner]");if(!e)return;const t=`plotline.trialBanner.dismissed.${e.dataset.trialBannerKey||"current"}`;try{if("true"===localStorage.getItem(t))return void(e.hidden=!0)}catch{}e.querySelector("[data-trial-banner-dismiss]")?.addEventListener("click",()=>{e.hidden=!0;try{localStorage.setItem(t,"true")}catch{}})})(),(()=>{const e=document.querySelectorAll(".scene-inspector-root");if(!e.length)return;e.forEach(e=>{e.addEventListener("submit",e=>{const t=e.target;if(!(t instanceof HTMLFormElement))return;let a=t.querySelector("input[name='ReturnUrl']");a||(a=document.createElement("input"),a.type="hidden",a.name="ReturnUrl",t.appendChild(a)),a.value=`${window.location.pathname}${window.location.search}${window.location.hash}`},!0)})})(),(()=>{const e=document.getElementById("plotlineConfirmModal"),t=e&&window.bootstrap?new bootstrap.Modal(e):null,a=e?.querySelector("#plotlineConfirmModalTitle"),n=e?.querySelector("#plotlineConfirmModalMessage"),r=e?.querySelector("[data-confirm-submit]"),o=e?.querySelector("[data-delete-confirm-field]"),s=e?.querySelector("[data-delete-confirm-input]");let i=null,l=null;e?.addEventListener("hidden.bs.modal",()=>{i=null,l=null,s&&(s.value=""),o?.classList.add("d-none"),r?.removeAttribute("disabled")}),s?.addEventListener("input",()=>{"true"===i?.dataset.requireDeleteText&&r&&(r.disabled="DELETE"!==s.value.trim())}),r?.addEventListener("click",()=>{if(i){if("true"===i.dataset.requireDeleteText){const e=i.querySelector("[data-delete-confirm-target], [name='confirmationText']");e&&(e.value=s?.value.trim()||"")}i.dataset.confirmed="true",t?.hide(),i.requestSubmit&&l?i.requestSubmit(l):i.requestSubmit?i.requestSubmit():i.submit()}}),document.addEventListener("submit",c=>{const d=c.target;if(!(d instanceof HTMLFormElement)||"true"===d.dataset.confirmed||"true"===d.dataset.confirmSkip||"true"===d.dataset.noDeleteConfirm)return;const p=d.dataset.confirmMessage,u=c.submitter instanceof HTMLElement?c.submitter:d.querySelector("button[type='submit']"),m=u?.textContent||"",h=d.getAttribute("action")||"",g=/restore/i.test(m)||/\/restore\b/i.test(h),f=/delete forever/i.test(m)||/\/deleteforever\b/i.test(h),y=!g&&!f&&(/archive/i.test(m)||/\/archive\b/i.test(h)),v=!f&&/(delete|remove)/i.test(m);if(!(p||y||g||v||f))return;const L=p||(y?"Archive this item?\n\nThis will hide it from active lists and timelines, but the data will be kept and can be restored later.":g?"Restore this item?\n\nThis will return it to active lists and timelines where applicable.":f?"Permanently delete this item?\n\nThis cannot be undone. Any linked planning data may also be removed or become unavailable. Only continue if you are certain.":"Remove this item?\n\nThis removes the link or supporting record. Major story items are archived instead of permanently deleted.");if(!(t&&e&&a&&n&&r))return;c.preventDefault();const w=(e=>{const t=e.split(/\n\s*\n/);return{title:t.shift()?.trim()||"Confirm action",body:t.join("\n\n").trim()}})(L);i=d,l=u,a.textContent=d.dataset.confirmTitle||w.title,n.textContent=d.dataset.confirmBody||w.body,r.textContent=d.dataset.confirmButtonText||m.trim()||"Confirm",r.className=`btn ${d.dataset.confirmButtonClass||(g?"btn-primary":"btn-danger")}`;const S="true"===d.dataset.requireDeleteText||f;o?.classList.toggle("d-none",!S),S&&r&&(r.disabled=!0,s?.focus()),t.show(),S&&window.setTimeout(()=>s?.focus(),200)})})(),(()=>{const e=document.querySelectorAll("[data-help-icon]");if(!e.length||!window.bootstrap)return;const t=new Map;let a=null;const n=e=>e.querySelector("[data-help-tooltip]")||e,r=e=>bootstrap.Tooltip.getInstance(n(e))?.hide(),o=(e=null)=>{a&&a!==e&&bootstrap.Popover.getInstance(a)?.hide()},s=()=>e.forEach(e=>r(e));e.forEach(e=>{const i=n(e),l=i.dataset.helpMicro||"Help article not found.",c=e.dataset.helpTitle||"Help unavailable",d=e.dataset.helpSummary||"Help content has not yet been written for this feature.";bootstrap.Tooltip.getOrCreateInstance(i,{title:l,trigger:"hover focus",placement:"top",container:"body"});const p=bootstrap.Popover.getOrCreateInstance(e,{title:c,trigger:"click",placement:"auto",container:"body",html:!0,customClass:"plotline-help-popover",content(){const t=document.createElement("div"),a=document.createElement("p");a.className="mb-2",a.textContent=d;const n=document.createElement("a");return n.href="#",n.textContent="More...",n.className="plotline-help-more",n.addEventListener("click",t=>{t.preventDefault(),o(),s(),e.dispatchEvent(new CustomEvent("plotline:help-more",{bubbles:!0,detail:{key:e.dataset.helpKey||""}}))}),t.append(a,n),t}});t.set(e,p),e.addEventListener("click",t=>{window.PlotLineHelpDrawer?.isActive?.()&&(t.preventDefault(),t.stopPropagation(),o(),r(e),window.PlotLineHelpPopovers?.hideAll(),window.PlotLineHelpDrawer.open(e.dataset.helpKey||""))}),e.addEventListener("show.bs.popover",t=>{window.PlotLineHelpDrawer?.isActive?.()?t.preventDefault():(o(e),r(e))}),e.addEventListener("shown.bs.popover",()=>{a=e,r(e)}),e.addEventListener("hidden.bs.popover",()=>{a===e&&(a=null)})}),document.addEventListener("click",e=>{const t=e.target instanceof Element?e.target:null;if(!t||!a)return;if(t.closest("[data-help-icon]"))return;const n=document.querySelector(`#${a.getAttribute("aria-describedby")}`);n?.contains(t)||o()}),document.addEventListener("keydown",e=>{"Escape"===e.key&&o()}),window.PlotLineHelpPopovers={hideAll(){t.forEach(e=>e.hide()),s(),a=null}}})(),(()=>{const e=document.querySelector("[data-help-layout]"),t=document.querySelector("[data-help-drawer]"),a=document.querySelector("[data-help-content]"),n=document.querySelector("[data-help-splitter]"),r=document.querySelector("[data-help-close]"),o=document.querySelector("[data-help-collapse]"),s=document.querySelector("[data-help-expand]"),i=document.querySelector("[data-help-pin]"),l=document.querySelector("[data-help-drawer-heading]");if(!e||!t||!a)return;const c="plotline.helpDrawer.width",d="plotline.helpDrawer.pinned",p="plotline.helpDrawer.key",u="plotline.helpDrawer.collapsed",m=e=>{try{return"true"===localStorage.getItem(e)}catch{return!1}},h=(e,t)=>{try{localStorage.setItem(e,t)}catch{}},g=t=>{const a=`${((e,t,a)=>Math.min(a,Math.max(t,e)))(Number.parseFloat(t)||25,20,50)}%`;e.style.setProperty("--help-drawer-width",a),h(c,a)},f=e=>{h(d,String(e)),i?.setAttribute("aria-pressed",String(e)),i&&(i.textContent=e?"Unpin":"Pin")},y=t=>{e.classList.toggle("help-collapsed",t),h(u,String(t)),o&&(o.textContent=t?"Expand":"Collapse")},v=async(t,n={})=>{const r=t||"";e.classList.add("help-open"),n.keepCollapsed||y(!1),h(p,r),l&&(l.textContent=r||"Help"),a.innerHTML='<p class="muted">Loading help...</p>';try{const e=await fetch(`/HelpDrawer/Article?key=${encodeURIComponent(r)}`,{headers:{"X-Requested-With":"XMLHttpRequest"}});a.innerHTML=e.ok?await e.text():'<p class="muted">Help for this feature has not yet been written.</p>';const t=a.querySelector(".help-drawer-article h2")?.textContent?.trim();l&&t&&(l.textContent=t)}catch{a.innerHTML='<p class="muted">Help for this feature has not yet been written.</p>'}};window.PlotLineHelpDrawer={isActive:()=>e.classList.contains("help-open"),open:e=>v(e)},g(localStorage.getItem(c)||"25%"),f(m(d)),y(m(u)),document.addEventListener("plotline:help-more",e=>{const t=e.detail?.key||e.target?.dataset?.helpKey||"";window.PlotLineHelpPopovers?.hideAll(),v(t)}),document.addEventListener("click",e=>{const t=e.target instanceof Element?e.target.closest("[data-help-open]"):null;t&&(e.preventDefault(),window.PlotLineHelpPopovers?.hideAll(),v(t.dataset.helpOpen||""))}),r?.addEventListener("click",()=>{e.classList.remove("help-open","help-collapsed"),f(!1)}),o?.addEventListener("click",()=>y(!e.classList.contains("help-collapsed"))),s?.addEventListener("click",()=>y(!1)),s?.addEventListener("keydown",e=>{"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),y(!1))}),i?.addEventListener("click",()=>f(!m(d))),n?.addEventListener("pointerdown",t=>{if(!e.classList.contains("help-open")||e.classList.contains("help-collapsed"))return;t.preventDefault(),document.body.classList.add("help-resizing"),n.setPointerCapture?.(t.pointerId);const a=t=>{const a=e.getBoundingClientRect(),n=(a.right-t.clientX)/a.width*100;g(n)},r=()=>{document.body.classList.remove("help-resizing"),document.removeEventListener("pointermove",a),document.removeEventListener("pointerup",r)};document.addEventListener("pointermove",a),document.addEventListener("pointerup",r)});const L=(()=>{try{return localStorage.getItem(p)||""}catch{return""}})();m(d)&&L&&v(L,{keepCollapsed:!0})})(),(()=>{const e=document.querySelectorAll(".scene-inspector-root");if(!e.length)return;e.forEach(e=>{const t=`plotline.inspector.${e.dataset.sceneId||e.querySelector(".scene-inspector-form [name='SceneID']")?.value||"new"}.`,a=new Set(["overview","timing","characters"]),n=[...e.querySelectorAll(".inspector-section")],r=e.querySelector(".scene-inspector-form"),o=e.querySelector("[data-scene-time-editor]");if(r&&o&&"true"!==o.dataset.enhanced){o.dataset.enhanced="true";const e=r.querySelector("[name='TimeModeID']"),t=o.dataset.exactDatetimeModeId||"",a=o.dataset.exactDateModeId||"",n=[...o.querySelectorAll("[data-time-part-field]")],s={StartDateTime:o.querySelector("[data-date-part-for='StartDateTime']"),EndDateTime:o.querySelector("[data-date-part-for='EndDateTime']")},i={StartDateTime:o.querySelector("[data-time-part-for='StartDateTime']"),EndDateTime:o.querySelector("[data-time-part-for='EndDateTime']")},l={StartDateTime:r.querySelector("input[type='hidden'][name='StartDateTime']"),EndDateTime:r.querySelector("input[type='hidden'][name='EndDateTime']")},c=()=>e?.value===t,d=()=>e?.value===a,p=()=>{const e=c();n.forEach(t=>{t.hidden=!e,t.classList.toggle("d-none",!e)})},u=e=>{const t=l[e],a=s[e]?.value||"",n=i[e]?.value||"";if(!t)return;if(!a)return void(t.value="");if(c())return void(t.value=`${a}T${n||"00:00"}`);if(d())return void(t.value=a);const r=t.value.match(/^\\d{4}-\\d{2}-\\d{2}T(\\d{2}:\\d{2})/)?.[1];t.value=r?`${a}T${r}`:a},m=()=>{u("StartDateTime"),u("EndDateTime")};e?.addEventListener("change",p),r.addEventListener("submit",m),p()}n.forEach(e=>{if("true"===e.dataset.enhanced)return;const n=e.querySelector("h3, h2"),r=e.dataset.sectionTitle||n?.textContent?.trim()||"Overview",o=r.toLowerCase().replace(/&/g,"and").replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"");const s=e.dataset.sectionId||`inspector-${o}`,i=s.replace(/^inspector-/,"");e.id=s,e.dataset.searchText=`${r} ${e.textContent}`.toLowerCase(),e.dataset.enhanced="true";const l=document.createElement("div");for(l.className="inspector-accordion-body";e.firstChild;)l.appendChild(e.firstChild);const c=document.createElement("button");c.type="button",c.className="inspector-accordion-toggle",c.setAttribute("aria-expanded","false"),e.append(c,l);const d=l.querySelectorAll(".asset-event-item, .thread-event-item, .warning-mini-card, .dependency-card, .metric-slider").length;c.innerHTML=`<span>${r}</span><span class="accordion-count">${d||""}</span>`;const p=localStorage.getItem(`${t}${i}`),u=null===p?a.has(i):"open"===p;e.classList.toggle("is-open",u),c.setAttribute("aria-expanded",String(u)),c.addEventListener("click",()=>{const a=!e.classList.contains("is-open");e.classList.toggle("is-open",a),c.setAttribute("aria-expanded",String(a)),localStorage.setItem(`${t}${i}`,a?"open":"closed")})}),e.querySelectorAll(".inspector-nav-links a").forEach(t=>{t.addEventListener("click",a=>{const n=e.querySelector(t.getAttribute("href"));n&&(a.preventDefault(),n.classList.add("is-open"),n.querySelector(".inspector-accordion-toggle")?.setAttribute("aria-expanded","true"),n.scrollIntoView({behavior:"smooth",block:"start"}))})});const s=e.querySelector("[data-inspector-search]");if(s?.addEventListener("input",()=>{const e=s.value.trim().toLowerCase();n.forEach(t=>{const a=!e||t.dataset.searchText.includes(e);t.classList.toggle("is-filtered-out",!a),a&&e&&(t.classList.add("is-open"),t.querySelector(".inspector-accordion-toggle")?.setAttribute("aria-expanded","true"))})}),"IntersectionObserver"in window){const t=[...e.querySelectorAll(".inspector-nav-links a")],a=new IntersectionObserver(e=>{e.forEach(e=>{e.isIntersecting&&t.forEach(t=>{t.classList.toggle("active",t.getAttribute("href")===`#${e.target.id}`)})})},{root:e.closest(".scene-inspector-panel")||null,rootMargin:"-10% 0px -70% 0px"});n.forEach(e=>a.observe(e))}})})(),(()=>{const e=document.querySelectorAll("[data-metric-shape-chart]");if(!e.length)return;const t=["#2f6f63","#b35f3b","#6750a4","#c58b2b","#7d3f52","#33759b","#9c4d8f","#a33d3d","#6f8f3d","#d08a2f","#444b57"],a=new Set(["Overall Intensity","Tension","Emotional Weight","Action"]),n=[],r=()=>{window.requestAnimationFrame(()=>{n.forEach(e=>e.resize())})};window.PlotLineMetricCharts={resizeAll:r},window.addEventListener("plotline:timeline-layout-changed",r);const o={id:"plotlineChapterGuides",afterDraw(e){const t=e.config.options.plugins.plotlineScenes||[],{ctx:a,chartArea:n,scales:r}=e;if(!t.length||!r.x)return;a.save(),a.strokeStyle="rgba(47, 111, 99, 0.16)",a.fillStyle="rgba(82, 75, 65, 0.58)",a.lineWidth=1,a.font="700 10px system-ui, -apple-system, Segoe UI, sans-serif";const o=[];t.forEach((e,a)=>{a&&e.chapterLabel===t[a-1].chapterLabel||o.push({scene:e,index:a})});const s=o.filter(e=>!e.scene.isPlaceholder),i=s.length>40?5:s.length>24?4:s.length>14?2:1;s.forEach((e,t)=>{const{scene:o,index:l}=e,c=r.x.getPixelForValue(l+.5);a.beginPath(),a.moveTo(c,n.top),a.lineTo(c,n.bottom),a.stroke();const d=Number.parseInt(String(o.chapterLabel).replace(/[^0-9]/g,""),10);(0===t||t===s.length-1||1===i||Number.isFinite(d)&&d%i===0)&&a.fillText(o.chapterLabel,Math.min(c+4,n.right-70),n.bottom+22)}),a.restore()}};window.Chart&&Chart.register(o),e.forEach(e=>{const r=e.querySelector("script[type='application/json']"),o=e.querySelector("canvas"),s=e.querySelector("[data-metric-toggles]"),i=e.querySelector("[data-chart-fallback]"),l=e.querySelector("[data-timeline-metric-edit-toolbar]"),c=e.querySelector("[data-edit-metric-status]"),d=e.hasAttribute("data-timeline-metric-editor")&&l&&c;if(!r||!o)return;let p;try{p=JSON.parse(r.textContent||"{}")}catch{return void i?.classList.remove("d-none")}if(!window.Chart||!p.scenes?.length||!p.metrics?.length)return void i?.classList.remove("d-none");const u=new Set(p.defaultMetrics?.length?p.defaultMetrics:a),m=p.scenes.length,h=m>80?10:m>40?5:m>24?4:m>14?2:1,g=p.metrics.map((e,a)=>{const n=new Map(e.points.map(e=>[e.sceneId,e.value])),r=t[a%t.length];return{label:e.metricName,metricTypeId:e.metricTypeId,minValue:Number.isFinite(e.minValue)?e.minValue:1,maxValue:Number.isFinite(e.maxValue)?e.maxValue:10,data:p.scenes.map((e,t)=>{const a=n.get(e.sceneId);return null==a?{x:t+.5,y:null,sceneId:e.sceneId}:{x:t+.5,y:a,sceneId:e.sceneId}}),borderColor:r,backgroundColor:r,pointBackgroundColor:r,pointBorderColor:"#fff",pointBorderWidth:1.5,pointRadius:3,pointHoverRadius:5,borderWidth:2,tension:.35,spanGaps:!0,hidden:!u.has(e.metricName)}});let f=null,y=!1;const v=e=>{c&&(c.textContent=e)},L=()=>g.map((e,t)=>t).filter(e=>b?.isDatasetVisible(e)),w=()=>{const e=L();return 1===e.length?e[0]:-1},S=()=>{if(!d)return;const e=w();g.forEach((t,a)=>{t.pointRadius=a===e?5:3,t.pointHoverRadius=a===e?7:5,t.borderWidth=a===e?3:2});const t=L(),a=e>=0;o.classList.toggle("metric-curve-editing",a),c.classList.toggle("d-none",0===t.length),0===t.length?v(""):v(a?"Drag points up or down to edit this metric.":"Show only one metric line to edit its curve."),b?.update()};s.innerHTML="",g.forEach((e,t)=>{const a=`metric-toggle-${Math.random().toString(36).slice(2)}-${t}`,n=document.createElement("label");n.className="metric-toggle-pill",n.style.setProperty("--metric-colour",e.borderColor),n.innerHTML=`<input type="checkbox" id="${a}" ${e.hidden?"":"checked"}><span>${e.label}</span>`,s.appendChild(n),n.querySelector("input").addEventListener("change",e=>{b.setDatasetVisibility(t,e.target.checked),S(),b.update()})});const b=new Chart(o,{type:"line",data:{datasets:g},options:{responsive:!0,maintainAspectRatio:!1,interaction:{mode:"nearest",intersect:!1},scales:{y:{min:1,max:10,ticks:{stepSize:1},grid:{color:"rgba(82, 75, 65, 0.10)"}},x:{type:"linear",min:0,max:m,bounds:"ticks",ticks:{maxRotation:0,autoSkip:!1,maxTicksLimit:16,callback(e){const t=Math.floor(Number(e));if(t<0||t>=m)return"";const a=p.scenes[t];return 0!==t&&t!==m-1&&t%h!==0||a?.isPlaceholder?"":a?.axisLabel||""}},afterBuildTicks(e){e.ticks=p.scenes.map((e,t)=>({value:t+.5}))},grid:{display:!1}}},plugins:{legend:{display:!1},plotlineScenes:p.scenes,tooltip:{callbacks:{title(e){const t=Math.floor(e[0].parsed.x),a=p.scenes[t];return a.isPlaceholder?a.sceneTitle||"No scene":`${a.chapterLabel}, Scene ${a.sceneNumber}: ${a.sceneTitle}`},label:e=>`${e.dataset.label}: ${e.formattedValue}`,afterBody(e){const t=Math.floor(e[0].parsed.x),a=p.scenes[t],n=[];return a.characterPresence?n.push(a.characterPresence):void 0!==a.characterAppears&&n.push(a.characterAppears?"Character appears":"Character does not appear"),a.bookTitle&&n.push(a.bookTitle),n}}}}}});d&&(S(),o.addEventListener("pointerdown",e=>{f=(e=>{if(!d)return null;const t=w();if(t<0)return null;const a=b.getElementsAtEventForMode(e,"nearest",{intersect:!0},!0).find(e=>e.datasetIndex===t);if(!a)return null;const n=b.data.datasets[a.datasetIndex],r=n?.data?.[a.index];return r?.sceneId&&null!=r.y?{datasetIndex:a.datasetIndex,pointIndex:a.index,previousValue:r.y}:null})(e),f&&(e.preventDefault(),o.setPointerCapture?.(e.pointerId),y=!0)}),o.addEventListener("pointermove",e=>{if(!f)return;const t=b.data.datasets[f.datasetIndex],a=t?.data?.[f.pointIndex];t&&a&&(a.y=((e,t)=>{const a=b.scales.y.getValueForPixel(e.offsetY),n=Math.round(a);return Math.max(t.minValue,Math.min(t.maxValue,n))})(e,t),b.update("none"))}),o.addEventListener("pointerup",async t=>{if(!f)return;const a=f;f=null,o.releasePointerCapture?.(t.pointerId),await(async t=>{const a=b.data.datasets[t.datasetIndex],n=a?.data?.[t.pointIndex];if(!a||!n?.sceneId)return;const r=l?.querySelector("input[name='__RequestVerificationToken']")?.value||"";v("Saving...");try{const t=await fetch(e.dataset.updateUrl||"/SceneMetrics/UpdateSceneMetricValue",{method:"POST",headers:{"Content-Type":"application/json",RequestVerificationToken:r},body:JSON.stringify({sceneId:Number(n.sceneId),metricId:Number(a.metricTypeId),value:Number(n.y)})}),o=await t.json().catch(()=>({}));if(!t.ok||!o.success)throw new Error(o.message||"Save failed");n.y=o.value,v("Saved"),b.update()}catch{n.y=t.previousValue,v("Save failed"),b.update()}})(a),window.setTimeout(()=>{y=!1},0)}),o.addEventListener("pointercancel",e=>{if(!f)return;const t=b.data.datasets[f.datasetIndex],a=t?.data?.[f.pointIndex];a&&(a.y=f.previousValue),f=null,o.releasePointerCapture?.(e.pointerId),y=!1,b.update()})),o.addEventListener("click",e=>{if(y)return void e.preventDefault();const t=b.getElementsAtEventForMode(e,"nearest",{intersect:!0},!0);if(!t.length)return;const a=b.data.datasets[t[0].datasetIndex]?.data?.[t[0].index],n=a?Math.floor(a.x):t[0].index,r=p.scenes[n];r?.timelineUrl&&(window.PlotLineTimelineScroll?.save(),window.location.href=r.timelineUrl)}),n.push(b);const E=window.ResizeObserver?new ResizeObserver(()=>b.resize()):null;E&&(E.observe(e),E.observe(e.querySelector(".metric-chart-frame")||e))})})(),(()=>{const e=document.querySelector("[data-timeline-root]"),t=document.querySelector("[data-timeline-controls]");if(!e||!t)return;const a="plotline.timeline.visibility",n={"scene-cards":!0,"plot-lines":!0,assets:!0,characters:!0,locations:!0,warnings:!0,metrics:!0},r=t=>{Object.entries(t).forEach(([t,a])=>{e.classList.toggle(`hide-${t}`,!a),document.querySelectorAll(`[data-timeline-section='${t}']`).forEach(e=>{e.classList.toggle("timeline-section-hidden",!a)})}),document.querySelectorAll("[data-location-marker]").forEach(e=>{e.classList.toggle("timeline-section-hidden",!t.locations)}),document.querySelectorAll("[data-warning-marker]").forEach(e=>{e.classList.toggle("timeline-section-hidden",!t.warnings)}),document.querySelector("[data-visibility-json]")?.setAttribute("value",JSON.stringify(t))},o=(()=>{try{return{...n,...JSON.parse(localStorage.getItem(a)||"{}")}}catch{return{...n}}})();t.querySelectorAll("[data-timeline-toggle]").forEach(e=>{const t=e.dataset.timelineToggle;e.checked=o[t]??!0,e.addEventListener("change",()=>{o[t]=e.checked,localStorage.setItem(a,JSON.stringify(o)),r(o)})}),t.querySelector("[data-timeline-preset-form]")?.addEventListener("submit",()=>{document.querySelector("[data-visibility-json]")?.setAttribute("value",JSON.stringify(o))}),r(o)})(),(()=>{const e=document.querySelector("[data-timeline-root]");if(!e)return;const t=e.querySelector(".timeline-workspace")||e,a=document.querySelector("[data-timeline-density]"),n=document.querySelector("[data-timeline-zoom]"),r=document.querySelector("[data-timeline-search]"),o=e.querySelector("[data-timeline-minimap]"),s=document.querySelectorAll("[data-timeline-jump], [data-timeline-warning-jump], [data-timeline-entity-jump]"),i=[...e.querySelectorAll(".timeline-scene-card[data-scene-id]")],l="plotline.timeline.collapsed",c="plotline.timeline.density",d="plotline.timeline.zoom",p="plotline.timeline.pending-scroll",u="plotdirector.timelineNavigationDiscovered",m="plotline.timeline.inspectorWidth",h=[".timeline-shell",".plot-lane-board",".asset-lane-board",".character-lane-board",".metric-graph-stack","[data-timeline-minimap]"].join(","),g=["compact","comfortable","expanded"],f=["book","chapter","scene-detail"],y=e.querySelector("[data-inspector-drawer]"),v=e.querySelector("[data-inspector-resizer]"),L=e.querySelector("[data-inspector-close]"),w=null!==localStorage.getItem(l),S=(e=>{try{return new Set(JSON.parse(localStorage.getItem(e)||"[]"))}catch{return new Set}})(l),b=()=>[...e.querySelectorAll(h)],E=t=>{if(!y)return;const{minimum:a,maximum:n,defaultWidth:r}=(()=>{const t=e.getBoundingClientRect().width||window.innerWidth,a=Math.min(420,Math.max(320,t-360)),n=Math.max(a,Math.min(.65*t,t-420));return{minimum:a,maximum:n,defaultWidth:Math.max(a,Math.min(n,.4*t))}})(),o=Math.max(a,Math.min(n,Number(t)||r));e.style.setProperty("--timeline-inspector-width",`${Math.round(o)}px`)};y&&(E(localStorage.getItem(m)),window.addEventListener("resize",()=>E(localStorage.getItem(m)))),(()=>{const r=e.querySelector("[data-timeline-navigation-card]");if(!r)return;const o=r.querySelector("[data-timeline-navigation-dismiss]"),s=r.querySelector("[data-timeline-navigation-demo]"),i=()=>e.querySelector(".timeline-shell"),l=e=>Boolean(e&&e.scrollWidth>e.clientWidth+8),c=e=>Math.max(0,e.scrollWidth-e.clientWidth),d=()=>[t,...b()].filter((e,t,a)=>e&&a.indexOf(e)===t);let p=!1,m=!1,h=!1,g=null;const f=new WeakMap,y=e=>f.set(e,e.scrollLeft),v=(e=!1)=>{if(window.clearTimeout(g),!e||window.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches||r.hidden)return r.classList.remove("is-dismissing"),void(r.hidden=!0);r.classList.add("is-dismissing"),g=window.setTimeout(()=>{r.hidden=!0,r.classList.remove("is-dismissing")},1300)},L=e=>{const t=l(e),a=c(e);e.classList.toggle("timeline-horizontal-overflow",t),e.classList.toggle("has-scroll-left",t&&e.scrollLeft>8),e.classList.toggle("has-scroll-right",t&&e.scrollLeft<a-8)},w=()=>{l(i())&&!(()=>{try{return"true"===localStorage.getItem(u)}catch{return!1}})()&&!p?(window.clearTimeout(g),r.hidden=!1,r.classList.remove("is-dismissing")):r.classList.contains("is-dismissing")||v(!1),d().forEach(L)},S=()=>{p=!0,v(!0);try{localStorage.setItem(u,"true")}catch{}};d().forEach(e=>{y(e),e.addEventListener("wheel",t=>{if(!t.defaultPrevented&&t.shiftKey&&Math.abs(t.deltaY)>Math.abs(t.deltaX)&&l(e)){const a=e.scrollLeft;t.preventDefault(),e.scrollLeft+=t.deltaY,window.requestAnimationFrame(()=>{L(e),!m&&Math.abs(e.scrollLeft-a)>4&&S(),y(e)})}},{passive:!1}),e.addEventListener("scroll",()=>(e=>{if(L(e),!h||m)return void y(e);const t=f.get(e)??e.scrollLeft;Math.abs(e.scrollLeft-t)>4&&l(e)?S():y(e)})(e),{passive:!0})}),o?.addEventListener("click",S),s?.addEventListener("click",()=>{const e=i();if(!l(e))return void w();const t=e.scrollLeft,a=c(e)-t;let n=Math.min(220,a),r=1;n<24&&t>0&&(n=Math.min(220,t),r=-1),n<4||(m=!0,e.scrollTo({left:t+n*r,behavior:"smooth"}),window.setTimeout(()=>{e.scrollTo({left:t,behavior:"smooth"})},420),window.setTimeout(()=>{m=!1,d().forEach(e=>{y(e),L(e)}),w()},950))}),window.setTimeout(()=>{h=!0,d().forEach(y)},800),window.requestAnimationFrame(w),window.addEventListener("resize",w),window.addEventListener("plotline:timeline-layout-changed",w),a?.addEventListener("change",()=>window.requestAnimationFrame(w)),n?.addEventListener("change",()=>window.requestAnimationFrame(w))})(),v?.addEventListener("pointerdown",t=>{t.preventDefault(),document.body.classList.add("timeline-inspector-resizing"),v.setPointerCapture(t.pointerId);const a=t=>{const a=e.getBoundingClientRect().right-t.clientX;E(a)},n=()=>{document.body.classList.remove("timeline-inspector-resizing");const e=Math.round(y?.getBoundingClientRect().width||0);e>0&&localStorage.setItem(m,String(e)),window.dispatchEvent(new Event("plotline:timeline-layout-changed")),v.removeEventListener("pointermove",a),v.removeEventListener("pointerup",n),v.removeEventListener("pointercancel",n)};v.addEventListener("pointermove",a),v.addEventListener("pointerup",n),v.addEventListener("pointercancel",n)}),L?.addEventListener("click",e=>{e.preventDefault();const t=new URL(window.location.href),a=t.searchParams.get("FocusType")||t.searchParams.get("focusType");t.searchParams.delete("SelectedSceneID"),t.searchParams.delete("selectedSceneId"),t.searchParams.delete("selectedsceneid"),a&&"scene"!==a.toLowerCase()||(t.searchParams.delete("FocusType"),t.searchParams.delete("focusType"),t.searchParams.delete("FocusID"),t.searchParams.delete("focusId")),x(),window.location.href=t.toString()});const x=()=>{try{sessionStorage.setItem(p,JSON.stringify({path:window.location.pathname,top:window.scrollY,left:window.scrollX,workspaceLeft:t.scrollLeft,workspaceTop:t.scrollTop,containers:b().map((e,t)=>({index:t,left:e.scrollLeft,top:e.scrollTop}))}))}catch{}};window.PlotLineTimelineScroll={save:x};const q=(t,a,n)=>{n.forEach(a=>e.classList.remove(`${t}-${a}`)),e.classList.add(`${t}-${a}`)},I=e=>{const t=g.includes(e)?e:"comfortable";q("density",t,g),a&&(a.value=t),localStorage.setItem(c,t),window.requestAnimationFrame(C)},$=e=>{const t=f.includes(e)?e:"chapter";q("zoom",t,f),n&&(n.value=t),localStorage.setItem(d,t),window.requestAnimationFrame(C)},T=(t,a=!0)=>{const n=(t=>e.querySelector(`[data-scene-id='${CSS.escape(String(t))}']`))(t);n&&(n.classList.add("keyboard-focus"),n.scrollIntoView({behavior:"smooth",block:"center",inline:"center"}),a&&n.focus({preventScroll:!0}),window.setTimeout(()=>n.classList.remove("keyboard-focus"),1800))},C=()=>{e.querySelectorAll("[data-plot-line-svg-board]").forEach(e=>{const t=e.querySelector("[data-plot-line-svg]");if(!t)return;t.replaceChildren();const a=e.getBoundingClientRect(),n=Math.max(e.scrollWidth,a.width),r=Math.max(e.scrollHeight,a.height);t.setAttribute("viewBox",`0 0 ${n} ${r}`),t.setAttribute("width",String(n)),t.setAttribute("height",String(r));const o=(e,t={})=>{const a=document.createElementNS("http://www.w3.org/2000/svg",e);return Object.entries(t).forEach(([e,t])=>a.setAttribute(e,String(t))),a},s=e=>{const t=e.getBoundingClientRect();return t.top-a.top+t.height/2},i=[...new Set([...e.querySelectorAll("[data-plot-line-slot]")].map(e=>{const t=e.getBoundingClientRect();return Math.round(t.left-a.left+t.width/2)}))].sort((e,t)=>e-t),l=Math.max(i.length-1,0),c=new Map;e.querySelectorAll("[data-plot-line-row]").forEach(e=>{e.dataset.plotLineId&&c.set(e.dataset.plotLineId,e)});const d=[...c.values()].map(e=>({row:e,plotLineId:e.dataset.plotLineId,colour:e.dataset.plotColour||"#2f6f63",points:[...e.querySelectorAll("[data-plot-event-node]")].map(t=>((e,t)=>{const n=t.closest("[data-plot-line-slot]");if(!n)return null;const r=n.getBoundingClientRect();return{x:r.left-a.left+r.width/2,y:s(e),sceneIndex:0,type:(t.dataset.plotEventType||"Progress").toLowerCase(),targetPlotLineId:t.dataset.targetPlotLineId||"",targetPlotLineIds:(t.dataset.targetPlotLineIds||"").split(",").map(e=>e.trim()).filter(Boolean)}})(e,t)).filter(Boolean).map(e=>({...e,sceneIndex:Math.max(0,i.findIndex(t=>t===Math.round(e.x)))})).sort((e,t)=>e.x-t.x),incomingStartXs:[]})),p=new Map(d.map(e=>[e.plotLineId,e])),u=(e,a,n,r=0)=>{const s=13+15*r,i=o("g",{class:`plotline-health-marker plotline-health-marker-${a}`}),l=o("title");if(l.textContent=n,i.append(l),"questionable"===a){i.append(o("circle",{cx:e.x+s,cy:e.y-10,r:7}));const t=o("text",{x:e.x+s,y:e.y-6,"text-anchor":"middle"});t.textContent="?",i.append(t)}else i.append(o("path",{d:`M ${e.x+s} ${e.y-18} L ${e.x+s+8} ${e.y-3} L ${e.x+s-8} ${e.y-3} Z`})),i.append(o("line",{x1:e.x+s,y1:e.y-13,x2:e.x+s,y2:e.y-8})),i.append(o("circle",{cx:e.x+s,cy:e.y-5.6,r:1.3}));t.append(i)},m=(e,a,n,r)=>{if(!a)return void(window.console?.warn&&window.console.warn(`Plot line ${r} connector skipped because target plot line data is missing.`));e.x;const i=s(a),l=Math.max(28,Math.min(46,.28*Math.abs(i-e.y))),c=e.x+l,d=e.x+l/2;t.append(o("path",{class:`plot-line-svg-connector plot-line-svg-connector-${r}`,d:`M ${e.x} ${e.y} C ${d} ${e.y}, ${d} ${i}, ${c} ${i}`,stroke:n}))};d.forEach(e=>{e.points.forEach(e=>{"branch"===e.type&&e.targetPlotLineId&&p.get(e.targetPlotLineId)?.incomingStartXs.push(e.x),"split"===e.type&&e.targetPlotLineIds.forEach(t=>{p.get(t)?.incomingStartXs.push(e.x)})})}),d.forEach(e=>{e.health=(e=>{const t=e.some(e=>"resolve"===e.type),a=e.some(e=>"abandon"===e.type),n=e.find(e=>"resolve"===e.type),r=e.find(e=>"abandon"===e.type),o=e.some(e=>"merge"===e.type&&e.targetPlotLineId),s=e.some(e=>"split"===e.type&&e.targetPlotLineIds.length>=2),i=Boolean(n)&&e.some(e=>"branch"===e.type&&e.targetPlotLineId&&e.sceneIndex>=n.sceneIndex),c=e.reduce((e,t)=>Math.max(e,t.sceneIndex),0),d=!t&&!a&&l-c>=10,p=t&&!o&&!s&&!i;let u="active";return a?u="abandoned":t?u=p?"questionable":"resolved":d&&(u="neglected"),{state:u,isNeglected:d,isDangling:!t&&!a&&!o&&!s&&l>=c,isQuestionable:p,isAbandoned:a,resolvePoint:n,abandonPoint:r}})(e.points),e.state=e.health.state}),d.forEach(e=>{const{colour:a,points:n,incomingStartXs:r,state:s}=e;if(n.length>0){const i=n.find(e=>"start"===e.type),l=r.length?Math.min(...r):null,c=n.find(e=>"split"===e.type||"merge"===e.type),d=n[0],p=n[n.length-1],u=null===l||i&&i.x<l?d.x:l,m=c?c.x:p.x;e.lineEndPoint={x:m,y:d.y},m>u&&t.append(o("path",{class:`plot-line-svg-path plotline-state-${s}`,d:`M ${u} ${d.y} L ${m} ${d.y}`,stroke:a}))}}),d.forEach(({points:e,colour:t})=>{e.forEach(e=>{"branch"!==e.type&&"merge"!==e.type||m(e,c.get(e.targetPlotLineId),t,e.type),"split"===e.type&&e.targetPlotLineIds.length>=2?e.targetPlotLineIds.forEach(a=>{m(e,c.get(a),t,e.type)}):"split"===e.type&&e.targetPlotLineIds.length>0&&window.console?.warn&&window.console.warn("Plot line split connector skipped because fewer than two targets are available.")})}),d.forEach(({points:e,colour:a,state:n})=>{e.forEach(e=>{((e,a,n)=>{const r=o("g",{class:`plot-event-svg-node plot-event-svg-node-${e.type} plotline-state-${n}`}),s="branch"===e.type||"split"===e.type||"merge"===e.type;"twist"===e.type?r.append(o("path",{d:`M ${e.x} ${e.y-9} L ${e.x+9} ${e.y} L ${e.x} ${e.y+9} L ${e.x-9} ${e.y} Z`,fill:a})):"abandon"===e.type?(r.append(o("circle",{cx:e.x,cy:e.y,r:9,fill:"#fff5f5"})),r.append(o("line",{x1:e.x-7,y1:e.y-7,x2:e.x+7,y2:e.y+7})),r.append(o("line",{x1:e.x+7,y1:e.y-7,x2:e.x-7,y2:e.y+7}))):"reveal"===e.type?r.append(o("path",{d:`M ${e.x} ${e.y-10} L ${e.x+3} ${e.y-3} L ${e.x+10} ${e.y-3} L ${e.x+4} ${e.y+2} L ${e.x+6} ${e.y+10} L ${e.x} ${e.y+5} L ${e.x-6} ${e.y+10} L ${e.x-4} ${e.y+2} L ${e.x-10} ${e.y-3} L ${e.x-3} ${e.y-3} Z`,fill:a})):(r.append(o("circle",{cx:e.x,cy:e.y,r:s?9:7.5,fill:a})),"resolve"===e.type&&r.append(o("circle",{cx:e.x,cy:e.y,r:12,fill:"none",stroke:a})),s&&r.append(o("circle",{cx:e.x,cy:e.y,r:13,fill:"none",stroke:a}))),t.append(r)})(e,a,n)})}),d.forEach(e=>{const t=e.lineEndPoint||e.points[e.points.length-1];let a=0;e.health?.isNeglected&&t&&u(t,"neglected","No plot event for 10+ scenes. This thread may have been forgotten.",a++),e.health?.isDangling&&t&&u(t,"dangling","This plot line is still unresolved at the end of the current timeline.",a++),e.health?.isQuestionable&&e.health.resolvePoint&&u(e.health.resolvePoint,"questionable","Resolved without merge, split, or branch. Verify this thread has sufficient payoff."),e.health?.isAbandoned&&e.health.abandonPoint&&u(e.health.abandonPoint,"abandoned","This plot line was abandoned. Check this is intentional.")})})},k=(e,t)=>{document.querySelectorAll(`[data-collapse-body='${CSS.escape(e)}']`).forEach(e=>{e.classList.toggle("timeline-section-collapsed",t)}),document.querySelectorAll(`[data-collapse-toggle='${CSS.escape(e)}']`).forEach(e=>{e.classList.toggle("is-collapsed",t),e.setAttribute("aria-expanded",String(!t))})};document.querySelectorAll("[data-collapse-toggle]").forEach(e=>{const t=e.dataset.collapseToggle;w||"collapsed"!==e.dataset.collapseDefault||S.add(t);const a=S.has(t);k(t,a),e.addEventListener("click",()=>{const e=!S.has(t);e?S.add(t):S.delete(t),k(t,e),localStorage.setItem(l,JSON.stringify([...S])),C(),window.dispatchEvent(new Event("plotline:timeline-layout-changed"))})}),a?.addEventListener("change",()=>I(a.value)),n?.addEventListener("change",()=>$(n.value)),I(localStorage.getItem(c)||"comfortable"),$(localStorage.getItem(d)||"chapter");const A=(()=>{try{return null!==sessionStorage.getItem(p)}catch{return!1}})();window.requestAnimationFrame(()=>{C(),((e="auto")=>{const t=o?.querySelector("[data-active-chapter='true']");if(!o||!t)return;const a=o.getBoundingClientRect(),n=t.getBoundingClientRect(),r=n.left+n.width/2,s=a.left+a.width/2;(n.left<a.left||n.right>a.right)&&o.scrollBy({left:r-s,behavior:e})})("auto"),A&&(()=>{let e=null;try{e=JSON.parse(sessionStorage.getItem(p)||"null"),sessionStorage.removeItem(p)}catch{try{sessionStorage.removeItem(p)}catch{}return}e&&e.path===window.location.pathname&&window.requestAnimationFrame(()=>{t.scrollLeft=Number(e.workspaceLeft)||0,t.scrollTop=Number(e.workspaceTop)||0;const a=b();(e.containers||[]).forEach(e=>{const t=a[e.index];t&&(t.scrollLeft=Number(e.left)||0,t.scrollTop=Number(e.top)||0)}),window.scrollTo(Number(e.left)||0,Number(e.top)||0)})})()}),window.addEventListener("resize",C),window.addEventListener("plotline:timeline-layout-changed",C);e.addEventListener("click",t=>{if(0!==t.button||t.metaKey||t.ctrlKey||t.shiftKey||t.altKey)return;const a=t.target instanceof Element?t.target:null,n=a?.closest("a[href]");if(!n||!e.contains(n))return;[...new URL(n.href,window.location.href).searchParams.keys()].some(e=>"selectedsceneid"===e.toLowerCase())&&x()},{capture:!0});const D=()=>{const e=r?.value.trim().toLowerCase()||"";let t=null;return i.forEach(a=>{const n=!e||(a.dataset.timelineSearchText||"").toLowerCase().includes(e);a.classList.toggle("search-hit",Boolean(e&&n)),a.classList.toggle("search-dim",Boolean(e&&!n)),!t&&e&&n&&(t=a)}),t};r?.addEventListener("input",D),r?.addEventListener("keydown",e=>{if("Enter"!==e.key)return;const t=D();t&&(e.preventDefault(),T(t.dataset.sceneId))}),s.forEach(e=>{e.addEventListener("change",()=>{e.value&&T(e.value)})}),document.querySelectorAll("[data-jump-scene]").forEach(e=>{e.addEventListener("click",()=>{e.dataset.jumpScene&&T(e.dataset.jumpScene)})}),document.addEventListener("keydown",e=>{const a=document.activeElement?.tagName?.toLowerCase(),o=["input","select","textarea"].includes(a)||document.activeElement?.isContentEditable;if((e.ctrlKey||e.metaKey)&&"f"===e.key.toLowerCase()&&r)return e.preventDefault(),r.focus(),void r.select();if("Escape"===e.key){const e=new URL(window.location.href),t=e.searchParams.has("FocusType")||e.searchParams.has("FocusID");return e.searchParams.delete("FocusType"),e.searchParams.delete("FocusID"),void(t?window.location.href=e.toString():r?.value&&(r.value="",D()))}if(!o){if("ArrowLeft"===e.key||"ArrowRight"===e.key)return e.preventDefault(),void t.scrollBy({left:"ArrowLeft"===e.key?-260:260,behavior:"smooth"});if("+"===e.key||"="===e.key||"-"===e.key){const t=f.indexOf(n?.value||"chapter"),a="-"===e.key?-1:1,r=Math.min(f.length-1,Math.max(0,t+a));$(f[r])}}})})(),(()=>{const e=document.querySelector("[data-timeline-root]"),t=document.querySelector("[data-drag-drop-panel]");if(!t)return;const a=new Map([...document.querySelectorAll("[data-drag-form]")].map(e=>[e.dataset.dragForm,e])),n=t.querySelector("[data-drag-panel-title]"),r=t.querySelector("[data-drag-panel-kicker]"),o=t.querySelector("[data-drag-panel-summary]"),s=document.querySelector("[data-scene-move-modal]"),i=s&&window.bootstrap?.Modal?window.bootstrap.Modal.getOrCreateInstance(s):null,l=s?.querySelector("[data-scene-move-title]"),c=s?.querySelector("[data-scene-move-summary]"),d=s?.querySelector("[data-scene-move-submit]"),p="plotline.timeline.scroll";let u=null,m=0;const h=(e,t,a)=>{const n=e?.querySelector(`[name='${CSS.escape(t)}']`);n&&(n.value=a??"")},g=e=>e?.selectedOptions?.[0]?.textContent?.trim()||"",f=e=>`${e||"this scene"}`,y=(e,t,a,n,r)=>t&&a&&t===a?`Move ${f(e.label)} to this new position within ${a}?`:t&&a?`Move ${f(e.label)} from ${t} to ${a}?`:`Move ${f(e.label)} ${n.toLowerCase()} ${r}?`,v=(e,s,p,u)=>{if("scene"===e)return t.classList.add("d-none"),t.querySelectorAll("[data-drag-form]").forEach(e=>e.classList.add("d-none")),a.get("scene")?.classList.remove("d-none"),l&&(l.textContent=s),c&&(c.textContent=p),d&&d.classList.toggle("d-none",s.toLowerCase().startsWith("cannot")||s.toLowerCase().startsWith("scene already")),void(i?i.show():t.classList.remove("d-none"));a.forEach((t,a)=>t.classList.toggle("d-none",a!==e)),t.classList.remove("d-none"),n.textContent=s,r.textContent=u,o.textContent=p,t.scrollIntoView({behavior:"smooth",block:"center"})},L=()=>{t.classList.add("d-none"),a.forEach(e=>e.classList.add("d-none"))},w=()=>{document.querySelectorAll(".drop-target-active, .drop-before, .drop-after, .chapter-drop-active, .drop-chapter-end").forEach(e=>e.classList.remove("drop-target-active","drop-before","drop-after","chapter-drop-active","drop-chapter-end"))};try{const t=JSON.parse(sessionStorage.getItem(p)||"null");t&&(sessionStorage.removeItem(p),requestAnimationFrame(()=>{const a=e?.querySelector(".timeline-shell");a&&(a.scrollLeft=t.left||0),window.scrollTo({top:t.top||0})}))}catch{sessionStorage.removeItem(p)}const S=e=>{try{const t=JSON.parse(e.dataTransfer.getData("application/json")||"{}");return t.type?t:u||{}}catch{return u||{}}};document.querySelectorAll("[data-drag-type][draggable='true']").forEach(e=>{e.addEventListener("dragstart",t=>((e,t)=>{const a={type:t.dataset.dragType,id:t.dataset.dragId,label:t.dataset.dragLabel||t.textContent.trim()};e.dataTransfer.effectAllowed="copyMove",e.dataTransfer.setData("application/json",JSON.stringify(a)),e.dataTransfer.setData("text/plain",`${a.type}:${a.id}`),u=a,document.body.classList.add("drag-active",`dragging-${a.type}`),t.classList.add("is-dragging")})(t,e)),e.addEventListener("dragend",()=>{e.classList.remove("is-dragging"),document.body.classList.remove("drag-active","dragging-scene","dragging-character","dragging-asset","dragging-location"),u=null,w()})}),t.querySelectorAll("[data-drag-cancel]").forEach(e=>e.addEventListener("click",L)),a.get("scene")?.addEventListener("submit",()=>{const t=e?.querySelector(".timeline-shell");try{sessionStorage.setItem(p,JSON.stringify({left:t?.scrollLeft||0,top:window.scrollY||0}))}catch{}}),e?.querySelectorAll(".timeline-scene-card[data-scene-id]").forEach(t=>{t.addEventListener("click",e=>{Date.now()<m&&(e.preventDefault(),e.stopPropagation())}),t.addEventListener("dragover",e=>{const a=S(e);["scene","character","asset"].includes(a.type)&&(e.preventDefault(),e.stopPropagation(),e.dataTransfer.dropEffect="scene"===a.type?"move":"copy",t.classList.add("drop-target-active"),t.classList.toggle("drop-before","scene"===a.type&&e.offsetX<t.clientWidth/2),t.classList.toggle("drop-after","scene"===a.type&&e.offsetX>=t.clientWidth/2))}),t.addEventListener("dragleave",()=>t.classList.remove("drop-target-active","drop-before","drop-after")),t.addEventListener("drop",n=>{const r=S(n);if(!["scene","character","asset"].includes(r.type))return;n.preventDefault(),n.stopPropagation(),m=Date.now()+800,t.classList.remove("drop-target-active","drop-before","drop-after");const o=t.dataset.sceneId;if("scene"===r.type){if(r.id===o)return void v("scene","Cannot move scene","Drop a scene before or after a different scene.","Scene move");const s=a.get("scene"),i=n.offsetX<t.clientWidth/2?"Before":"After",l=e.querySelector(`.timeline-scene-card[data-scene-id='${CSS.escape(r.id)}']`),c=l?.dataset.chapterLabel||"",d=t.dataset.chapterLabel||"";return h(s,"SceneID",r.id),h(s,"AnchorSceneID",o),h(s,"TargetChapterID",""),h(s,"Position",i),void v("scene","Move Scene?",y(r,c,d,i,t.dataset.dragLabel),"Scene move")}if("character"===r.type){const e=a.get("character");return h(e,"SceneID",o),h(e,"CharacterID",r.id),void v("character","Add character to scene",`Add ${r.label} to ${t.dataset.dragLabel}.`,"Character drop")}const s=a.get("asset-event");h(s,"SceneID",o),h(s,"StoryAssetID",r.id),h(s,"EventTitle",""),v("asset-event","What happens to this asset?",`Add an event for ${r.label} in ${t.dataset.dragLabel}.`,"Asset drop")})}),e?.querySelectorAll(".timeline-scenes[data-chapter-drop-target]").forEach(t=>{const n=t.closest("[data-chapter-drop-target]"),r=t.dataset.chapterId||n?.dataset.chapterId,o=t.dataset.chapterLabel||n?.dataset.chapterLabel||"this chapter";t.addEventListener("dragover",e=>{"scene"===S(e).type&&r&&(e.target.closest(".timeline-scene-card[data-scene-id]")||(e.preventDefault(),e.dataTransfer.dropEffect="move",t.classList.add("drop-target-active","drop-chapter-end"),n?.classList.add("chapter-drop-active")))}),t.addEventListener("dragleave",e=>{t.contains(e.relatedTarget)||(t.classList.remove("drop-target-active","drop-chapter-end"),n?.classList.remove("chapter-drop-active"))}),t.addEventListener("drop",n=>{const s=S(n);if("scene"!==s.type||!r)return;if(n.target.closest(".timeline-scene-card[data-scene-id]"))return;n.preventDefault(),n.stopPropagation(),m=Date.now()+800,w();const i=e.querySelector(`.timeline-scene-card[data-scene-id='${CSS.escape(s.id)}']`);if(i?.dataset.chapterId===r&&t.lastElementChild?.dataset?.sceneId===s.id)return void v("scene","Scene already here",`${s.label} is already at the end of ${o}.`,"Scene move");const l=a.get("scene");h(l,"SceneID",s.id),h(l,"AnchorSceneID",""),h(l,"TargetChapterID",r),h(l,"Position","End"),v("scene","Move Scene?",y(s,i?.dataset.chapterLabel||"",o,"After",o),"Scene move")})});const b=a.get("asset-dependency"),E=()=>{const e=b?.dataset.sourceLabel||"Source asset",a=b?.dataset.targetLabel||"Target asset",n=g(b?.querySelector("[name='AssetDependencyTypeID']"))||"Requires",r=g(b?.querySelector("[name='SourceRequiredStateID']"))||"the required state",o=g(b?.querySelector("[name='TargetBlockedStateID']"))||"the blocked state",s=t.querySelector("[data-asset-dependency-preview]");s&&(s.textContent=`${e} ${n.toLowerCase()} ${a}. ${e} should be ${r} before ${a} can be ${o}.`)};b?.querySelectorAll("select").forEach(e=>e.addEventListener("change",E)),document.querySelectorAll("[data-asset-drop-target], .drag-chip.asset").forEach(e=>{e.addEventListener("dragover",t=>{"asset"===S(t).type&&(t.preventDefault(),t.dataTransfer.dropEffect="copy",e.classList.add("drop-target-active"))}),e.addEventListener("dragleave",()=>e.classList.remove("drop-target-active")),e.addEventListener("drop",t=>{const a=S(t),n=e.dataset.assetId||e.dataset.dragId,r=e.dataset.assetLabel||e.dataset.dragLabel||e.textContent.trim();"asset"===a.type&&n&&(t.preventDefault(),e.classList.remove("drop-target-active"),a.id!==n?(h(b,"SourceAssetID",a.id),h(b,"TargetAssetID",n),b.dataset.sourceLabel=a.label,b.dataset.targetLabel=r,E(),v("asset-dependency","Create asset dependency",`${a.label} -> ${r}`,"Asset dependency")):v("asset-dependency","Cannot create dependency","Drop one asset onto a different asset.","Asset dependency"))})}),document.querySelectorAll("[data-drag-type='location']").forEach(e=>{e.addEventListener("dragover",t=>{"location"===S(t).type&&(t.preventDefault(),t.dataTransfer.dropEffect="copy",e.classList.add("drop-target-active"))}),e.addEventListener("dragleave",()=>e.classList.remove("drop-target-active")),e.addEventListener("drop",t=>{const n=S(t),r=e.dataset.dragId,o=e.dataset.dragLabel||e.textContent.trim();if("location"!==n.type)return;if(t.preventDefault(),e.classList.remove("drop-target-active"),n.id===r)return void v("location-relationship","Cannot create relationship","Drop one location onto a different location.","Location relationship");const s=a.get("location-relationship");h(s,"FromLocationID",n.id),h(s,"ToLocationID",r),v("location-relationship","Create location relationship",`${n.label} -> ${o}`,"Location drop")})})})();