/* Event listener for footnotes and sidenotes*/ document.addEventListener("DOMContentLoaded", () => { document.querySelectorAll('a.footref[href^="#fn"]').forEach(ref => { const sup = ref.closest("sup") || ref; // idempotent: don't insert twice if (sup.nextElementSibling && sup.nextElementSibling.classList?.contains("footnote-sidenote")) return; const targetId = ref.getAttribute("href").replace(/^#/, ""); // works for fn.2 or fn2 const anchor = document.getElementById(targetId); if (!anchor) return; const footdef = anchor.closest(".footdef") || anchor.parentElement; if (!footdef) return; // 1) Prefer leaf paragraphs to avoid div+p duplication let paras = footdef.querySelectorAll("p.footpara"); if (!paras.length) { // fallback: any .footpara elements that don't contain another .footpara paras = footdef.querySelectorAll(".footpara:not(:has(.footpara))"); } // 2) Build HTML, de-duplicating by text content let parts = []; if (paras.length) { const seen = new Set(); parts = Array.from(paras).map(p => { const txt = p.textContent.trim().replace(/\s+/g, " "); if (seen.has(txt)) return ""; seen.add(txt); return p.innerHTML.trim(); }).filter(Boolean); } // 3) Fallback: clean full block if no paras found if (!parts.length) { const clone = footdef.cloneNode(true); clone.querySelectorAll("sup.footnum, a[role='doc-backlink']").forEach(n => n.remove()); parts = [clone.innerHTML.trim()]; } // 4) Insert the sidenote const sn = document.createElement("span"); sn.className = "sidenote footnote-sidenote"; sn.setAttribute("data-fn", (ref.textContent || "").trim()); sn.innerHTML = parts.join(" "); sup.insertAdjacentElement("afterend", sn); }); });