javascript:%2F*%0A%20*%20annotate.js%20--%20click-to-annotate%20feedback%20overlay%20for%20staging%20page%20review.%0A%20*%0A%20*%20Load%20via%20the%20bookmarklet%20on%20%2Fannotate-help.html%20(same-origin%3A%20the%20script%0A%20*%20is%20injected%20AFTER%20page%20load%2C%20so%20WP%20Rocket%20Delay%20JS%20%2F%20RUCSS%20%2F%20page%20caching%0A%20*%20never%20see%20it).%20Notes%20persist%20in%20localStorage%20per%20page%20path.%20Export%0A%20*%20produces%20one%20feedback%20JSON%20file%20with%20a%20CSS%20selector%20per%20note.%0A%20*%0A%20*%20Review%20tooling%20only%20--%20never%20reference%20this%20file%20from%20page%20HTML.%0A%20*%2F%0A(function%20()%20%7B%0A%20%20'use%20strict'%3B%0A%0A%20%20if%20(window.__wfAnnotate)%20%7B%20window.__wfAnnotate.show()%3B%20return%3B%20%7D%0A%0A%20%20var%20SCHEMA%20%3D%201%3B%0A%20%20var%20KEY%20%3D%20'wf-annotate%3A'%20%2B%20location.pathname%3B%0A%20%20var%20Z%20%3D%202147483000%3B%0A%0A%20%20var%20state%20%3D%20%7B%20active%3A%20true%2C%20notes%3A%20%5B%5D%2C%20seq%3A%201%2C%20editing%3A%20null%20%7D%3B%0A%0A%20%20try%20%7B%0A%20%20%20%20var%20saved%20%3D%20JSON.parse(localStorage.getItem(KEY)%20%7C%7C%20'null')%3B%0A%20%20%20%20if%20(saved%20%26%26%20saved.notes)%20%7B%0A%20%20%20%20%20%20state.notes%20%3D%20saved.notes%3B%0A%20%20%20%20%20%20state.seq%20%3D%20saved.seq%20%7C%7C%20(state.notes.length%20%2B%201)%3B%0A%20%20%20%20%7D%0A%20%20%7D%20catch%20(e)%20%7B%20%2F*%20corrupt%20store%3A%20start%20fresh%20*%2F%20%7D%0A%0A%20%20function%20persist()%20%7B%0A%20%20%20%20try%20%7B%0A%20%20%20%20%20%20localStorage.setItem(KEY%2C%20JSON.stringify(%7B%20notes%3A%20state.notes%2C%20seq%3A%20state.seq%20%7D))%3B%0A%20%20%20%20%7D%20catch%20(e)%20%7B%20%2F*%20quota%3A%20notes%20still%20live%20in%20memory%20this%20session%20*%2F%20%7D%0A%20%20%7D%0A%0A%20%20%2F*%20----------%20selector%20%2B%20context%20helpers%20----------%20*%2F%0A%0A%20%20function%20cssPath(el)%20%7B%0A%20%20%20%20if%20(el.id)%20return%20'%23'%20%2B%20CSS.escape(el.id)%3B%0A%20%20%20%20var%20parts%20%3D%20%5B%5D%3B%0A%20%20%20%20var%20node%20%3D%20el%3B%0A%20%20%20%20while%20(node%20%26%26%20node.nodeType%20%3D%3D%3D%201%20%26%26%20node%20!%3D%3D%20document.body%20%26%26%20node%20!%3D%3D%20document.documentElement)%20%7B%0A%20%20%20%20%20%20if%20(node.id)%20%7B%20parts.unshift('%23'%20%2B%20CSS.escape(node.id))%3B%20return%20parts.join('%20%3E%20')%3B%20%7D%0A%20%20%20%20%20%20var%20i%20%3D%201%2C%20sib%20%3D%20node%3B%0A%20%20%20%20%20%20while%20((sib%20%3D%20sib.previousElementSibling))%20%7B%0A%20%20%20%20%20%20%20%20if%20(sib.tagName%20%3D%3D%3D%20node.tagName)%20i%2B%2B%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20parts.unshift(node.tagName.toLowerCase()%20%2B%20'%3Anth-of-type('%20%2B%20i%20%2B%20')')%3B%0A%20%20%20%20%20%20node%20%3D%20node.parentElement%3B%0A%20%20%20%20%7D%0A%20%20%20%20parts.unshift('body')%3B%0A%20%20%20%20return%20parts.join('%20%3E%20')%3B%0A%20%20%7D%0A%0A%20%20function%20clean(s)%20%7B%20return%20(s%20%7C%7C%20'').replace(%2F%5Cs%2B%2Fg%2C%20'%20').trim()%3B%20%7D%0A%0A%20%20function%20ownLabel(n)%20%7B%0A%20%20%20%20if%20(!n%20%7C%7C%20!n.getAttribute)%20return%20''%3B%0A%20%20%20%20return%20clean(n.getAttribute('aria-label')%20%7C%7C%20n.getAttribute('alt')%20%7C%7C%20n.getAttribute('title'))%3B%0A%20%20%7D%0A%0A%20%20%2F*%20Nearest%20ancestor%20(or%20self)%20that%20carries%20a%20label.%20*%2F%0A%20%20function%20labelledAncestor(n)%20%7B%0A%20%20%20%20while%20(n%20%26%26%20n.nodeType%20%3D%3D%3D%201%20%26%26%20n%20!%3D%3D%20document.body%20%26%26%20n%20!%3D%3D%20document.documentElement)%20%7B%0A%20%20%20%20%20%20var%20t%20%3D%20ownLabel(n)%3B%0A%20%20%20%20%20%20if%20(t)%20return%20n%3B%0A%20%20%20%20%20%20n%20%3D%20n.parentElement%3B%0A%20%20%20%20%7D%0A%20%20%20%20return%20null%3B%0A%20%20%7D%0A%0A%20%20%2F*%20SVG%20renderers%20such%20as%20published%20Google%20Slides%20draw%20text%20as%20unlabeled%20glyph%20paths%20and%20put%0A%20%20%20%20%20the%20accessible%20labels%20on%20transparent%20shapes%20and%20sibling%20elements%20outside%20the%20glyphs'%0A%20%20%20%20%20ancestry.%20Ask%20the%20browser%20for%20everything%20stacked%20under%20the%20click%20and%20list%20the%20labels%2C%0A%20%20%20%20%20smallest%20labelled%20element%20first%3A%20the%20text%20box%2C%20then%20the%20slide%2C%20then%20anything%20larger.%20*%2F%0A%20%20function%20labelsAtPoint(clientX%2C%20clientY)%20%7B%0A%20%20%20%20if%20(clientX%20%3D%3D%20null%20%7C%7C%20!document.elementsFromPoint)%20return%20%5B%5D%3B%0A%20%20%20%20var%20stack%20%3D%20document.elementsFromPoint(clientX%2C%20clientY)%3B%0A%20%20%20%20var%20seen%20%3D%20%5B%5D%2C%20out%20%3D%20%5B%5D%3B%0A%20%20%20%20for%20(var%20i%20%3D%200%3B%20i%20%3C%20stack.length%3B%20i%2B%2B)%20%7B%0A%20%20%20%20%20%20if%20(root.contains(stack%5Bi%5D))%20continue%3B%0A%20%20%20%20%20%20var%20a%20%3D%20labelledAncestor(stack%5Bi%5D)%3B%0A%20%20%20%20%20%20if%20(!a%20%7C%7C%20seen.indexOf(a)%20!%3D%3D%20-1)%20continue%3B%0A%20%20%20%20%20%20seen.push(a)%3B%0A%20%20%20%20%20%20var%20r%20%3D%20a.getBoundingClientRect()%3B%0A%20%20%20%20%20%20out.push(%7B%20label%3A%20ownLabel(a)%2C%20area%3A%20r.width%20*%20r.height%20%7D)%3B%0A%20%20%20%20%7D%0A%20%20%20%20out.sort(function%20(x%2C%20y)%20%7B%20return%20x.area%20-%20y.area%3B%20%7D)%3B%0A%20%20%20%20return%20out%3B%0A%20%20%7D%0A%0A%20%20function%20textSnippet(el%2C%20clientX%2C%20clientY)%20%7B%0A%20%20%20%20var%20t%20%3D%20clean(el.textContent)%20%7C%7C%20ownLabel(el)%3B%0A%20%20%20%20if%20(!t)%20%7B%0A%20%20%20%20%20%20var%20under%20%3D%20labelsAtPoint(clientX%2C%20clientY)%3B%0A%20%20%20%20%20%20t%20%3D%20under.length%20%3F%20under%5B0%5D.label%20%3A%20''%3B%0A%20%20%20%20%7D%0A%20%20%20%20if%20(!t)%20%7B%0A%20%20%20%20%20%20var%20a%20%3D%20labelledAncestor(el)%3B%0A%20%20%20%20%20%20t%20%3D%20a%20%3F%20ownLabel(a)%20%3A%20''%3B%0A%20%20%20%20%7D%0A%20%20%20%20return%20t.slice(0%2C%20140)%3B%0A%20%20%7D%0A%0A%20%20%2F*%20The%20enclosing%20labelled%20region%2C%20e.g.%20%22Slide%204%20of%2019%3A%20Meet%20Maria%22%20on%20a%20published%20deck.%20*%2F%0A%20%20function%20regionContext(el%2C%20text%2C%20clientX%2C%20clientY)%20%7B%0A%20%20%20%20var%20a%20%3D%20labelledAncestor(el)%3B%0A%20%20%20%20while%20(a%20%26%26%20ownLabel(a).slice(0%2C%20140)%20%3D%3D%3D%20text)%20a%20%3D%20labelledAncestor(a.parentElement)%3B%0A%20%20%20%20if%20(a)%20return%20ownLabel(a).slice(0%2C%20140)%3B%0A%20%20%20%20var%20under%20%3D%20labelsAtPoint(clientX%2C%20clientY)%3B%0A%20%20%20%20for%20(var%20i%20%3D%200%3B%20i%20%3C%20under.length%3B%20i%2B%2B)%20%7B%0A%20%20%20%20%20%20var%20l%20%3D%20under%5Bi%5D.label.slice(0%2C%20140)%3B%0A%20%20%20%20%20%20if%20(l%20!%3D%3D%20text)%20return%20l%3B%0A%20%20%20%20%7D%0A%20%20%20%20return%20null%3B%0A%20%20%7D%0A%0A%20%20function%20headingContext(el)%20%7B%0A%20%20%20%20var%20hs%20%3D%20document.querySelectorAll('h1%2Ch2%2Ch3%2Ch4%2Ch5%2Ch6')%3B%0A%20%20%20%20var%20best%20%3D%20null%3B%0A%20%20%20%20for%20(var%20i%20%3D%200%3B%20i%20%3C%20hs.length%3B%20i%2B%2B)%20%7B%0A%20%20%20%20%20%20if%20(hs%5Bi%5D.contains(el))%20%7B%20best%20%3D%20hs%5Bi%5D%3B%20break%3B%20%7D%0A%20%20%20%20%20%20var%20pos%20%3D%20hs%5Bi%5D.compareDocumentPosition(el)%3B%0A%20%20%20%20%20%20if%20(pos%20%26%20Node.DOCUMENT_POSITION_FOLLOWING)%20best%20%3D%20hs%5Bi%5D%3B%0A%20%20%20%20%7D%0A%20%20%20%20if%20(!best)%20return%20null%3B%0A%20%20%20%20return%20best.tagName%20%2B%20'%3A%20'%20%2B%20(best.textContent%20%7C%7C%20'').replace(%2F%5Cs%2B%2Fg%2C%20'%20').trim().slice(0%2C%20120)%3B%0A%20%20%7D%0A%0A%20%20function%20resolve(note)%20%7B%0A%20%20%20%20if%20(!note.selector)%20return%20null%3B%0A%20%20%20%20try%20%7B%20return%20document.querySelector(note.selector)%3B%20%7D%20catch%20(e)%20%7B%20return%20null%3B%20%7D%0A%20%20%7D%0A%0A%20%20%2F*%20----------%20UI%20scaffolding%20----------%20*%2F%0A%0A%20%20function%20el(tag%2C%20cls%2C%20text)%20%7B%0A%20%20%20%20var%20n%20%3D%20document.createElement(tag)%3B%0A%20%20%20%20if%20(cls)%20n.className%20%3D%20cls%3B%0A%20%20%20%20if%20(text)%20n.textContent%20%3D%20text%3B%0A%20%20%20%20return%20n%3B%0A%20%20%7D%0A%0A%20%20var%20style%20%3D%20el('style')%3B%0A%20%20style.textContent%20%3D%20%5B%0A%20%20%20%20'.wfa-toolbar%7Bposition%3Afixed%3Btop%3A104px%3Bright%3A12px%3Bz-index%3A'%20%2B%20Z%20%2B%20'%3Bbackground%3A%23111827%3Bcolor%3A%23fff%3B'%2C%0A%20%20%20%20'font%3A13px%2F1.4%20system-ui%2Csans-serif%3Bborder-radius%3A10px%3Bpadding%3A10px%2012px%3Bbox-shadow%3A0%204px%2018px%20rgba(0%2C0%2C0%2C.35)%3B'%2C%0A%20%20%20%20'display%3Aflex%3Bflex-direction%3Acolumn%3Bgap%3A6px%3Bwidth%3A190px%7D'%2C%0A%20%20%20%20'.wfa-toolbar%20b%7Bfont-size%3A13px%7D'%2C%0A%20%20%20%20'.wfa-toolbar%20button%7Bfont%3A12px%20system-ui%2Csans-serif%3Bpadding%3A5px%208px%3Bborder%3A0%3Bborder-radius%3A6px%3B'%2C%0A%20%20%20%20'background%3A%23374151%3Bcolor%3A%23fff%3Bcursor%3Apointer%3Btext-align%3Aleft%7D'%2C%0A%20%20%20%20'.wfa-toolbar%20button%3Ahover%7Bbackground%3A%234b5563%7D'%2C%0A%20%20%20%20'.wfa-toolbar%20button.wfa-primary%7Bbackground%3A%231d84c7%7D'%2C%0A%20%20%20%20'.wfa-toolbar%20button.wfa-primary%3Ahover%7Bbackground%3A%232b93d6%7D'%2C%0A%20%20%20%20'.wfa-status%7Bfont-size%3A11px%3Bcolor%3A%239ca3af%7D'%2C%0A%20%20%20%20'.wfa-hl%7Bposition%3Aabsolute%3Bz-index%3A'%20%2B%20(Z%20-%202)%20%2B%20'%3Bpointer-events%3Anone%3Bborder%3A2px%20solid%20%231d84c7%3B'%2C%0A%20%20%20%20'background%3Argba(29%2C132%2C199%2C.08)%3Bborder-radius%3A2px%3Bdisplay%3Anone%7D'%2C%0A%20%20%20%20'.wfa-pin%7Bposition%3Aabsolute%3Bz-index%3A'%20%2B%20(Z%20-%201)%20%2B%20'%3Bwidth%3A24px%3Bheight%3A24px%3Bmargin%3A-12px%200%200%20-12px%3B'%2C%0A%20%20%20%20'border-radius%3A50%25%3Bbackground%3A%23d97706%3Bcolor%3A%23fff%3Bfont%3A700%2012px%2F24px%20system-ui%2Csans-serif%3B'%2C%0A%20%20%20%20'text-align%3Acenter%3Bcursor%3Apointer%3Bbox-shadow%3A0%202px%206px%20rgba(0%2C0%2C0%2C.4)%3Bborder%3A2px%20solid%20%23fff%3Bbox-sizing%3Aborder-box%7D'%2C%0A%20%20%20%20'.wfa-pin.wfa-page%7Bbackground%3A%237c3aed%7D'%2C%0A%20%20%20%20'.wfa-editor%7Bposition%3Afixed%3Bz-index%3A'%20%2B%20Z%20%2B%20'%3Bbackground%3A%23fff%3Bcolor%3A%23111%3Bborder-radius%3A10px%3B'%2C%0A%20%20%20%20'box-shadow%3A0%208px%2030px%20rgba(0%2C0%2C0%2C.4)%3Bpadding%3A12px%3Bwidth%3A320px%3Bfont%3A13px%2F1.45%20system-ui%2Csans-serif%7D'%2C%0A%20%20%20%20'.wfa-editor%20.wfa-target%7Bfont-size%3A11px%3Bcolor%3A%23555%3Bmargin-bottom%3A8px%3Bmax-height%3A60px%3Boverflow%3Ahidden%7D'%2C%0A%20%20%20%20'.wfa-editor%20textarea%7Bwidth%3A100%25%3Bbox-sizing%3Aborder-box%3Bheight%3A90px%3Bfont%3A13px%2F1.4%20system-ui%2Csans-serif%3B'%2C%0A%20%20%20%20'padding%3A6px%3Bborder%3A1px%20solid%20%23cbd5e1%3Bborder-radius%3A6px%3Bresize%3Avertical%7D'%2C%0A%20%20%20%20'.wfa-editor%20.wfa-row%7Bdisplay%3Aflex%3Bgap%3A6px%3Bmargin-top%3A8px%3Bjustify-content%3Aflex-end%7D'%2C%0A%20%20%20%20'.wfa-editor%20button%7Bfont%3A12px%20system-ui%2Csans-serif%3Bpadding%3A6px%2010px%3Bborder%3A0%3Bborder-radius%3A6px%3Bcursor%3Apointer%7D'%2C%0A%20%20%20%20'.wfa-save%7Bbackground%3A%231d84c7%3Bcolor%3A%23fff%7D'%2C%0A%20%20%20%20'.wfa-cancel%7Bbackground%3A%23e5e7eb%3Bcolor%3A%23111%7D'%2C%0A%20%20%20%20'.wfa-delete%7Bbackground%3A%23fee2e2%3Bcolor%3A%23b91c1c%3Bmargin-right%3Aauto%7D'%0A%20%20%5D.join('')%3B%0A%0A%20%20var%20root%20%3D%20el('div'%2C%20'wfa-root')%3B%0A%20%20var%20toolbar%20%3D%20el('div'%2C%20'wfa-toolbar')%3B%0A%20%20var%20pinLayer%20%3D%20el('div'%2C%20'wfa-pins')%3B%0A%20%20var%20highlight%20%3D%20el('div'%2C%20'wfa-hl')%3B%0A%20%20root.appendChild(pinLayer)%3B%0A%20%20root.appendChild(highlight)%3B%0A%20%20root.appendChild(toolbar)%3B%0A%0A%20%20var%20title%20%3D%20el('b'%2C%20null%2C%20'Feedback%20mode')%3B%0A%20%20var%20status%20%3D%20el('div'%2C%20'wfa-status')%3B%0A%20%20var%20btnPause%20%3D%20el('button'%2C%20null%2C%20'')%3B%0A%20%20var%20btnPage%20%3D%20el('button'%2C%20null%2C%20'%2B%20Page-level%20note')%3B%0A%20%20var%20btnExport%20%3D%20el('button'%2C%20'wfa-primary'%2C%20'Export%20JSON%20file')%3B%0A%20%20var%20btnCopy%20%3D%20el('button'%2C%20null%2C%20'Copy%20JSON%20to%20clipboard')%3B%0A%20%20var%20btnClear%20%3D%20el('button'%2C%20null%2C%20'Clear%20all%20notes')%3B%0A%20%20var%20btnHide%20%3D%20el('button'%2C%20null%2C%20'Hide%20overlay')%3B%0A%20%20toolbar.appendChild(title)%3B%0A%20%20toolbar.appendChild(status)%3B%0A%20%20toolbar.appendChild(btnPause)%3B%0A%20%20toolbar.appendChild(btnPage)%3B%0A%20%20toolbar.appendChild(btnExport)%3B%0A%20%20toolbar.appendChild(btnCopy)%3B%0A%20%20toolbar.appendChild(btnClear)%3B%0A%20%20toolbar.appendChild(btnHide)%3B%0A%0A%20%20function%20setStatus()%20%7B%0A%20%20%20%20status.textContent%20%3D%20state.notes.length%20%2B%20'%20note'%20%2B%20(state.notes.length%20%3D%3D%3D%201%20%3F%20''%20%3A%20's')%20%2B%0A%20%20%20%20%20%20(state.active%20%3F%20'%20--%20click%20anything'%20%3A%20'%20--%20paused')%3B%0A%20%20%20%20btnPause.textContent%20%3D%20state.active%20%3F%20'Pause%20(browse%20the%20page)'%20%3A%20'Resume%20annotating'%3B%0A%20%20%7D%0A%0A%20%20%2F*%20----------%20pins%20----------%20*%2F%0A%0A%20%20function%20docRect(elm)%20%7B%0A%20%20%20%20var%20r%20%3D%20elm.getBoundingClientRect()%3B%0A%20%20%20%20return%20%7B%0A%20%20%20%20%20%20x%3A%20r.left%20%2B%20window.scrollX%2C%20y%3A%20r.top%20%2B%20window.scrollY%2C%0A%20%20%20%20%20%20w%3A%20r.width%2C%20h%3A%20r.height%0A%20%20%20%20%7D%3B%0A%20%20%7D%0A%0A%20%20function%20renderPins()%20%7B%0A%20%20%20%20pinLayer.textContent%20%3D%20''%3B%0A%20%20%20%20var%20pageNoteRow%20%3D%200%3B%0A%20%20%20%20state.notes.forEach(function%20(note)%20%7B%0A%20%20%20%20%20%20var%20pin%20%3D%20el('div'%2C%20'wfa-pin'%20%2B%20(note.target%20%3D%3D%3D%20'page'%20%3F%20'%20wfa-page'%20%3A%20'')%2C%20String(note.num))%3B%0A%20%20%20%20%20%20pin.title%20%3D%20note.note%3B%0A%20%20%20%20%20%20var%20x%2C%20y%3B%0A%20%20%20%20%20%20if%20(note.target%20%3D%3D%3D%20'page')%20%7B%0A%20%20%20%20%20%20%20%20x%20%3D%20window.scrollX%20%2B%2030%3B%0A%20%20%20%20%20%20%20%20y%20%3D%20window.scrollY%20%2B%20160%20%2B%20(pageNoteRow%2B%2B%20*%2030)%3B%0A%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20var%20target%20%3D%20resolve(note)%3B%0A%20%20%20%20%20%20%20%20if%20(target)%20%7B%0A%20%20%20%20%20%20%20%20%20%20var%20r%20%3D%20docRect(target)%3B%0A%20%20%20%20%20%20%20%20%20%20x%20%3D%20r.x%20%2B%20r.w%20*%20(note.rx%20%3D%3D%20null%20%3F%200.5%20%3A%20note.rx)%3B%0A%20%20%20%20%20%20%20%20%20%20y%20%3D%20r.y%20%2B%20r.h%20*%20(note.ry%20%3D%3D%20null%20%3F%200.5%20%3A%20note.ry)%3B%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20x%20%3D%20note.docX%3B%20y%20%3D%20note.docY%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20pin.style.left%20%3D%20x%20%2B%20'px'%3B%0A%20%20%20%20%20%20pin.style.top%20%3D%20y%20%2B%20'px'%3B%0A%20%20%20%20%20%20pin.addEventListener('click'%2C%20function%20(ev)%20%7B%0A%20%20%20%20%20%20%20%20ev.preventDefault()%3B%0A%20%20%20%20%20%20%20%20ev.stopPropagation()%3B%0A%20%20%20%20%20%20%20%20openEditor(note%2C%20null%2C%20%7B%20x%3A%20ev.clientX%2C%20y%3A%20ev.clientY%20%7D)%3B%0A%20%20%20%20%20%20%7D)%3B%0A%20%20%20%20%20%20pinLayer.appendChild(pin)%3B%0A%20%20%20%20%7D)%3B%0A%20%20%20%20setStatus()%3B%0A%20%20%7D%0A%0A%20%20%2F*%20----------%20editor%20----------%20*%2F%0A%0A%20%20var%20editor%20%3D%20null%3B%0A%0A%20%20function%20closeEditor()%20%7B%0A%20%20%20%20if%20(editor)%20%7B%20editor.remove()%3B%20editor%20%3D%20null%3B%20%7D%0A%20%20%20%20state.editing%20%3D%20null%3B%0A%20%20%7D%0A%0A%20%20function%20openEditor(existingNote%2C%20pendingTarget%2C%20at)%20%7B%0A%20%20%20%20closeEditor()%3B%0A%20%20%20%20state.editing%20%3D%20existingNote%20%7C%7C%20true%3B%0A%20%20%20%20editor%20%3D%20el('div'%2C%20'wfa-editor')%3B%0A%0A%20%20%20%20var%20targetDesc%3B%0A%20%20%20%20if%20(existingNote)%20%7B%0A%20%20%20%20%20%20targetDesc%20%3D%20existingNote.target%20%3D%3D%3D%20'page'%20%3F%20'Page-level%20note'%20%3A%0A%20%20%20%20%20%20%20%20'%3C'%20%2B%20existingNote.tag%20%2B%20'%3E%20'%20%2B%20(existingNote.elementText%20%7C%7C%20existingNote.selector)%3B%0A%20%20%20%20%7D%20else%20if%20(pendingTarget%20%26%26%20pendingTarget.el)%20%7B%0A%20%20%20%20%20%20targetDesc%20%3D%20'%3C'%20%2B%20pendingTarget.el.tagName.toLowerCase()%20%2B%20'%3E%20'%20%2B%0A%20%20%20%20%20%20%20%20(pendingTarget.text%20%7C%7C%20cssPath(pendingTarget.el))%20%2B%0A%20%20%20%20%20%20%20%20(pendingTarget.context%20%3F%20'%20('%20%2B%20pendingTarget.context%20%2B%20')'%20%3A%20'')%3B%0A%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20targetDesc%20%3D%20'Page-level%20note'%3B%0A%20%20%20%20%7D%0A%20%20%20%20editor.appendChild(el('div'%2C%20'wfa-target'%2C%20targetDesc))%3B%0A%0A%20%20%20%20var%20ta%20%3D%20el('textarea')%3B%0A%20%20%20%20ta.placeholder%20%3D%20'Your%20note...'%3B%0A%20%20%20%20if%20(existingNote)%20ta.value%20%3D%20existingNote.note%3B%0A%20%20%20%20editor.appendChild(ta)%3B%0A%0A%20%20%20%20var%20row%20%3D%20el('div'%2C%20'wfa-row')%3B%0A%20%20%20%20if%20(existingNote)%20%7B%0A%20%20%20%20%20%20var%20bDel%20%3D%20el('button'%2C%20'wfa-delete'%2C%20'Delete')%3B%0A%20%20%20%20%20%20bDel.addEventListener('click'%2C%20function%20()%20%7B%0A%20%20%20%20%20%20%20%20state.notes%20%3D%20state.notes.filter(function%20(n)%20%7B%20return%20n.id%20!%3D%3D%20existingNote.id%3B%20%7D)%3B%0A%20%20%20%20%20%20%20%20persist()%3B%20closeEditor()%3B%20renderPins()%3B%0A%20%20%20%20%20%20%7D)%3B%0A%20%20%20%20%20%20row.appendChild(bDel)%3B%0A%20%20%20%20%7D%0A%20%20%20%20var%20bCancel%20%3D%20el('button'%2C%20'wfa-cancel'%2C%20'Cancel')%3B%0A%20%20%20%20bCancel.addEventListener('click'%2C%20closeEditor)%3B%0A%20%20%20%20var%20bSave%20%3D%20el('button'%2C%20'wfa-save'%2C%20'Save%20note')%3B%0A%20%20%20%20bSave.addEventListener('click'%2C%20function%20()%20%7B%0A%20%20%20%20%20%20var%20text%20%3D%20ta.value.trim()%3B%0A%20%20%20%20%20%20if%20(!text)%20%7B%20closeEditor()%3B%20return%3B%20%7D%0A%20%20%20%20%20%20if%20(existingNote)%20%7B%0A%20%20%20%20%20%20%20%20existingNote.note%20%3D%20text%3B%0A%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20var%20note%20%3D%20%7B%20id%3A%20'n'%20%2B%20state.seq%2C%20num%3A%20state.seq%2C%20note%3A%20text%2C%20createdAt%3A%20new%20Date().toISOString()%20%7D%3B%0A%20%20%20%20%20%20%20%20state.seq%2B%2B%3B%0A%20%20%20%20%20%20%20%20if%20(pendingTarget%20%26%26%20pendingTarget.el)%20%7B%0A%20%20%20%20%20%20%20%20%20%20var%20t%20%3D%20pendingTarget.el%3B%0A%20%20%20%20%20%20%20%20%20%20var%20r%20%3D%20docRect(t)%3B%0A%20%20%20%20%20%20%20%20%20%20note.target%20%3D%20'element'%3B%0A%20%20%20%20%20%20%20%20%20%20note.selector%20%3D%20cssPath(t)%3B%0A%20%20%20%20%20%20%20%20%20%20note.tag%20%3D%20t.tagName.toLowerCase()%3B%0A%20%20%20%20%20%20%20%20%20%20note.elementText%20%3D%20pendingTarget.text%3B%0A%20%20%20%20%20%20%20%20%20%20note.heading%20%3D%20headingContext(t)%3B%0A%20%20%20%20%20%20%20%20%20%20note.context%20%3D%20pendingTarget.context%3B%0A%20%20%20%20%20%20%20%20%20%20note.rx%20%3D%20r.w%20%3F%20Math.max(0%2C%20Math.min(1%2C%20(pendingTarget.docX%20-%20r.x)%20%2F%20r.w))%20%3A%200.5%3B%0A%20%20%20%20%20%20%20%20%20%20note.ry%20%3D%20r.h%20%3F%20Math.max(0%2C%20Math.min(1%2C%20(pendingTarget.docY%20-%20r.y)%20%2F%20r.h))%20%3A%200.5%3B%0A%20%20%20%20%20%20%20%20%20%20note.docX%20%3D%20pendingTarget.docX%3B%0A%20%20%20%20%20%20%20%20%20%20note.docY%20%3D%20pendingTarget.docY%3B%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20note.target%20%3D%20'page'%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20note.viewport%20%3D%20%7B%20w%3A%20window.innerWidth%2C%20h%3A%20window.innerHeight%20%7D%3B%0A%20%20%20%20%20%20%20%20note.pageUrl%20%3D%20location.href%3B%0A%20%20%20%20%20%20%20%20state.notes.push(note)%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20persist()%3B%20closeEditor()%3B%20renderPins()%3B%0A%20%20%20%20%7D)%3B%0A%20%20%20%20row.appendChild(bCancel)%3B%0A%20%20%20%20row.appendChild(bSave)%3B%0A%20%20%20%20editor.appendChild(row)%3B%0A%0A%20%20%20%20var%20ex%20%3D%20Math.min((at%20%3F%20at.x%20%3A%2080)%20%2B%2012%2C%20window.innerWidth%20-%20340)%3B%0A%20%20%20%20var%20ey%20%3D%20Math.min((at%20%3F%20at.y%20%3A%20120)%20%2B%2012%2C%20window.innerHeight%20-%20220)%3B%0A%20%20%20%20editor.style.left%20%3D%20Math.max(8%2C%20ex)%20%2B%20'px'%3B%0A%20%20%20%20editor.style.top%20%3D%20Math.max(8%2C%20ey)%20%2B%20'px'%3B%0A%20%20%20%20root.appendChild(editor)%3B%0A%20%20%20%20ta.focus()%3B%0A%20%20%7D%0A%0A%20%20%2F*%20----------%20export%20----------%20*%2F%0A%0A%20%20function%20exportData()%20%7B%0A%20%20%20%20return%20%7B%0A%20%20%20%20%20%20schema%3A%20SCHEMA%2C%0A%20%20%20%20%20%20page%3A%20document.title%2C%0A%20%20%20%20%20%20url%3A%20location.origin%20%2B%20location.pathname%2C%0A%20%20%20%20%20%20exportedAt%3A%20new%20Date().toISOString()%2C%0A%20%20%20%20%20%20viewport%3A%20%7B%20w%3A%20window.innerWidth%2C%20h%3A%20window.innerHeight%20%7D%2C%0A%20%20%20%20%20%20userAgentMobile%3A%20%2FMobi%2F.test(navigator.userAgent)%2C%0A%20%20%20%20%20%20notes%3A%20state.notes%0A%20%20%20%20%7D%3B%0A%20%20%7D%0A%0A%20%20function%20slug()%20%7B%0A%20%20%20%20return%20(location.pathname.replace(%2F%5C%2F%2Fg%2C%20'-').replace(%2F%5E-%7C-%24%2Fg%2C%20'')%20%7C%7C%20'home')%3B%0A%20%20%7D%0A%0A%20%20function%20downloadJSON()%20%7B%0A%20%20%20%20var%20blob%20%3D%20new%20Blob(%5BJSON.stringify(exportData()%2C%20null%2C%202)%5D%2C%20%7B%20type%3A%20'application%2Fjson'%20%7D)%3B%0A%20%20%20%20var%20a%20%3D%20el('a')%3B%0A%20%20%20%20a.href%20%3D%20URL.createObjectURL(blob)%3B%0A%20%20%20%20a.download%20%3D%20'feedback-'%20%2B%20slug()%20%2B%20'.json'%3B%0A%20%20%20%20document.body.appendChild(a)%3B%0A%20%20%20%20a.click()%3B%0A%20%20%20%20setTimeout(function%20()%20%7B%20URL.revokeObjectURL(a.href)%3B%20a.remove()%3B%20%7D%2C%20500)%3B%0A%20%20%7D%0A%0A%20%20function%20copyJSON()%20%7B%0A%20%20%20%20var%20text%20%3D%20JSON.stringify(exportData()%2C%20null%2C%202)%3B%0A%20%20%20%20function%20fallback()%20%7B%0A%20%20%20%20%20%20var%20ta%20%3D%20el('textarea')%3B%0A%20%20%20%20%20%20ta.value%20%3D%20text%3B%0A%20%20%20%20%20%20document.body.appendChild(ta)%3B%0A%20%20%20%20%20%20ta.select()%3B%0A%20%20%20%20%20%20try%20%7B%20document.execCommand('copy')%3B%20%7D%20catch%20(e)%20%7B%7D%0A%20%20%20%20%20%20ta.remove()%3B%0A%20%20%20%20%7D%0A%20%20%20%20if%20(navigator.clipboard%20%26%26%20navigator.clipboard.writeText)%20%7B%0A%20%20%20%20%20%20navigator.clipboard.writeText(text).catch(fallback)%3B%0A%20%20%20%20%7D%20else%20%7B%20fallback()%3B%20%7D%0A%20%20%20%20btnCopy.textContent%20%3D%20'Copied!'%3B%0A%20%20%20%20setTimeout(function%20()%20%7B%20btnCopy.textContent%20%3D%20'Copy%20JSON%20to%20clipboard'%3B%20%7D%2C%201500)%3B%0A%20%20%7D%0A%0A%20%20%2F*%20----------%20events%20----------%20*%2F%0A%0A%20%20btnPause.addEventListener('click'%2C%20function%20()%20%7B%0A%20%20%20%20state.active%20%3D%20!state.active%3B%0A%20%20%20%20highlight.style.display%20%3D%20'none'%3B%0A%20%20%20%20setStatus()%3B%0A%20%20%7D)%3B%0A%20%20btnPage.addEventListener('click'%2C%20function%20()%20%7B%20openEditor(null%2C%20null%2C%20%7B%20x%3A%2080%2C%20y%3A%20160%20%7D)%3B%20%7D)%3B%0A%20%20btnExport.addEventListener('click'%2C%20downloadJSON)%3B%0A%20%20btnCopy.addEventListener('click'%2C%20copyJSON)%3B%0A%20%20btnClear.addEventListener('click'%2C%20function%20()%20%7B%0A%20%20%20%20if%20(state.notes.length%20%26%26%20!window.confirm('Delete%20all%20'%20%2B%20state.notes.length%20%2B%20'%20notes%20on%20this%20page%3F'))%20return%3B%0A%20%20%20%20state.notes%20%3D%20%5B%5D%3B%20state.seq%20%3D%201%3B%0A%20%20%20%20persist()%3B%20closeEditor()%3B%20renderPins()%3B%0A%20%20%7D)%3B%0A%20%20btnHide.addEventListener('click'%2C%20function%20()%20%7B%0A%20%20%20%20root.style.display%20%3D%20'none'%3B%0A%20%20%20%20state.active%20%3D%20false%3B%0A%20%20%7D)%3B%0A%0A%20%20document.addEventListener('mousemove'%2C%20function%20(e)%20%7B%0A%20%20%20%20if%20(!state.active%20%7C%7C%20state.editing)%20%7B%20highlight.style.display%20%3D%20'none'%3B%20return%3B%20%7D%0A%20%20%20%20var%20t%20%3D%20e.target%3B%0A%20%20%20%20if%20(!t%20%7C%7C%20root.contains(t)%20%7C%7C%20t%20%3D%3D%3D%20document.body%20%7C%7C%20t%20%3D%3D%3D%20document.documentElement)%20%7B%0A%20%20%20%20%20%20highlight.style.display%20%3D%20'none'%3B%0A%20%20%20%20%20%20return%3B%0A%20%20%20%20%7D%0A%20%20%20%20var%20r%20%3D%20docRect(t)%3B%0A%20%20%20%20highlight.style.display%20%3D%20'block'%3B%0A%20%20%20%20highlight.style.left%20%3D%20r.x%20%2B%20'px'%3B%0A%20%20%20%20highlight.style.top%20%3D%20r.y%20%2B%20'px'%3B%0A%20%20%20%20highlight.style.width%20%3D%20r.w%20%2B%20'px'%3B%0A%20%20%20%20highlight.style.height%20%3D%20r.h%20%2B%20'px'%3B%0A%20%20%7D%2C%20true)%3B%0A%0A%20%20document.addEventListener('click'%2C%20function%20(e)%20%7B%0A%20%20%20%20if%20(root.contains(e.target))%20return%3B%20%2F*%20our%20UI%20handles%20itself%20*%2F%0A%20%20%20%20if%20(state.editing)%20%7B%20e.preventDefault()%3B%20e.stopPropagation()%3B%20closeEditor()%3B%20return%3B%20%7D%0A%20%20%20%20if%20(!state.active)%20return%3B%0A%20%20%20%20e.preventDefault()%3B%0A%20%20%20%20e.stopPropagation()%3B%0A%20%20%20%20var%20t%20%3D%20e.target%3B%0A%20%20%20%20if%20(t%20%3D%3D%3D%20document.body%20%7C%7C%20t%20%3D%3D%3D%20document.documentElement)%20return%3B%0A%20%20%20%20%2F*%20Read%20the%20label%20now%2C%20before%20the%20editor%20opens%20over%20the%20page.%20*%2F%0A%20%20%20%20var%20text%20%3D%20textSnippet(t%2C%20e.clientX%2C%20e.clientY)%3B%0A%20%20%20%20openEditor(null%2C%20%7B%0A%20%20%20%20%20%20el%3A%20t%2C%0A%20%20%20%20%20%20text%3A%20text%2C%0A%20%20%20%20%20%20context%3A%20regionContext(t%2C%20text%2C%20e.clientX%2C%20e.clientY)%2C%0A%20%20%20%20%20%20docX%3A%20e.clientX%20%2B%20window.scrollX%2C%0A%20%20%20%20%20%20docY%3A%20e.clientY%20%2B%20window.scrollY%0A%20%20%20%20%7D%2C%20%7B%20x%3A%20e.clientX%2C%20y%3A%20e.clientY%20%7D)%3B%0A%20%20%7D%2C%20true)%3B%0A%0A%20%20document.addEventListener('keydown'%2C%20function%20(e)%20%7B%0A%20%20%20%20if%20(e.key%20%3D%3D%3D%20'Escape')%20closeEditor()%3B%0A%20%20%7D%2C%20true)%3B%0A%0A%20%20window.addEventListener('resize'%2C%20renderPins)%3B%0A%20%20%2F*%20pages%20lazy-load%20content%3B%20keep%20pins%20anchored%20as%20layout%20settles%20*%2F%0A%20%20setInterval(function%20()%20%7B%20if%20(root.style.display%20!%3D%3D%20'none')%20renderPins()%3B%20%7D%2C%202000)%3B%0A%0A%20%20%2F*%20----------%20boot%20----------%20*%2F%0A%0A%20%20document.head.appendChild(style)%3B%0A%20%20document.body.appendChild(root)%3B%0A%20%20renderPins()%3B%0A%0A%20%20window.__wfAnnotate%20%3D%20%7B%0A%20%20%20%20show%3A%20function%20()%20%7B%20root.style.display%20%3D%20''%3B%20state.active%20%3D%20true%3B%20setStatus()%3B%20renderPins()%3B%20%7D%2C%0A%20%20%20%20getData%3A%20exportData%2C%0A%20%20%20%20version%3A%20SCHEMA%0A%20%20%7D%3B%0A%7D)()%3B%0A