@siteping/widget 0.10.10 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -4
- package/dist/chunk-26577FDQ.js +9 -0
- package/dist/chunk-26577FDQ.js.map +1 -0
- package/dist/chunk-3EHIWTJH.js +9 -0
- package/dist/chunk-3EHIWTJH.js.map +1 -0
- package/dist/chunk-6MCFOKVG.cjs +9 -0
- package/dist/chunk-6MCFOKVG.cjs.map +1 -0
- package/dist/chunk-Q34GDCKE.cjs +9 -0
- package/dist/chunk-Q34GDCKE.cjs.map +1 -0
- package/dist/concurrency.d.cts +14 -0
- package/dist/concurrency.d.ts +14 -0
- package/dist/de-73CTH2E4.cjs +2 -0
- package/dist/de-73CTH2E4.cjs.map +1 -0
- package/dist/de-GUUJUHYP.js +2 -0
- package/dist/de-GUUJUHYP.js.map +1 -0
- package/dist/deep-link.d.cts +14 -0
- package/dist/deep-link.d.ts +14 -0
- package/dist/email.d.cts +6 -3
- package/dist/email.d.ts +6 -3
- package/dist/errors.d.cts +18 -4
- package/dist/errors.d.ts +18 -4
- package/dist/{es-HEVFJPRI.js → es-3MXMSDUC.js} +2 -2
- package/dist/es-3MXMSDUC.js.map +1 -0
- package/dist/{es-5XQA3TPT.cjs → es-WJZ3XARH.cjs} +2 -2
- package/dist/es-WJZ3XARH.cjs.map +1 -0
- package/dist/filters.d.cts +31 -7
- package/dist/filters.d.ts +31 -7
- package/dist/fr-52F3ZCLQ.js +2 -0
- package/dist/fr-52F3ZCLQ.js.map +1 -0
- package/dist/fr-ZCRIJWI3.cjs +2 -0
- package/dist/fr-ZCRIJWI3.cjs.map +1 -0
- package/dist/i18n.d.cts +18 -0
- package/dist/i18n.d.ts +18 -0
- package/dist/index.cjs +3 -1588
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.global.js +4 -3389
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +3 -1588
- package/dist/index.js.map +1 -1
- package/dist/it-MEUT3RCC.js +2 -0
- package/dist/it-MEUT3RCC.js.map +1 -0
- package/dist/it-TGUTW6MO.cjs +2 -0
- package/dist/it-TGUTW6MO.cjs.map +1 -0
- package/dist/ja-DOS7AWLW.cjs +2 -0
- package/dist/ja-DOS7AWLW.cjs.map +1 -0
- package/dist/ja-U7NRNGPQ.js +2 -0
- package/dist/ja-U7NRNGPQ.js.map +1 -0
- package/dist/ko-U2CS6XQ4.js +2 -0
- package/dist/ko-U2CS6XQ4.js.map +1 -0
- package/dist/ko-ZUL567LW.cjs +2 -0
- package/dist/ko-ZUL567LW.cjs.map +1 -0
- package/dist/panel-3BEMZFIR.cjs +2 -0
- package/dist/panel-3BEMZFIR.cjs.map +1 -0
- package/dist/panel-HPDIAYLQ.js +2 -0
- package/dist/panel-HPDIAYLQ.js.map +1 -0
- package/dist/panel-MIWFGD7X.cjs +2 -0
- package/dist/panel-MIWFGD7X.cjs.map +1 -0
- package/dist/panel-XTNU6XHV.js +2 -0
- package/dist/panel-XTNU6XHV.js.map +1 -0
- package/dist/pt-BZRBHCYN.cjs +2 -0
- package/dist/pt-BZRBHCYN.cjs.map +1 -0
- package/dist/pt-MOS5DVOG.js +2 -0
- package/dist/pt-MOS5DVOG.js.map +1 -0
- package/dist/react.cjs +3 -1588
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +3 -1588
- package/dist/react.js.map +1 -1
- package/dist/ru-KDNRHHNZ.cjs +2 -0
- package/dist/ru-KDNRHHNZ.cjs.map +1 -0
- package/dist/ru-VSWB5NKK.js +2 -0
- package/dist/ru-VSWB5NKK.js.map +1 -0
- package/dist/schema.d.cts +54 -0
- package/dist/schema.d.ts +54 -0
- package/dist/screenshot-storage.d.cts +61 -19
- package/dist/screenshot-storage.d.ts +61 -19
- package/dist/siteping-core.d.cts +9 -6
- package/dist/siteping-core.d.ts +9 -6
- package/dist/store-helpers.d.cts +59 -15
- package/dist/store-helpers.d.ts +59 -15
- package/dist/type-utils.d.cts +8 -0
- package/dist/type-utils.d.ts +8 -0
- package/dist/types.d.cts +399 -33
- package/dist/types.d.ts +399 -33
- package/dist/wire.d.cts +35 -2
- package/dist/wire.d.ts +35 -2
- package/package.json +5 -3
- package/dist/chunk-AFLWWD6M.cjs +0 -1796
- package/dist/chunk-AFLWWD6M.cjs.map +0 -1
- package/dist/chunk-ATTI2TS4.js +0 -1796
- package/dist/chunk-ATTI2TS4.js.map +0 -1
- package/dist/chunk-BP5TH2CD.js +0 -1796
- package/dist/chunk-BP5TH2CD.js.map +0 -1
- package/dist/chunk-OSADAHGS.cjs +0 -1796
- package/dist/chunk-OSADAHGS.cjs.map +0 -1
- package/dist/de-AZUOIGF2.cjs +0 -2
- package/dist/de-AZUOIGF2.cjs.map +0 -1
- package/dist/de-MAGIJBFC.js +0 -2
- package/dist/de-MAGIJBFC.js.map +0 -1
- package/dist/es-5XQA3TPT.cjs.map +0 -1
- package/dist/es-HEVFJPRI.js.map +0 -1
- package/dist/fr-ERYSAH32.cjs +0 -2
- package/dist/fr-ERYSAH32.cjs.map +0 -1
- package/dist/fr-OM2PHLDH.js +0 -2
- package/dist/fr-OM2PHLDH.js.map +0 -1
- package/dist/it-NXAZR4K6.cjs +0 -2
- package/dist/it-NXAZR4K6.cjs.map +0 -1
- package/dist/it-OQVYHKKV.js +0 -2
- package/dist/it-OQVYHKKV.js.map +0 -1
- package/dist/panel-2FEECS2N.cjs +0 -2
- package/dist/panel-2FEECS2N.cjs.map +0 -1
- package/dist/panel-CSFFA5FF.cjs +0 -2
- package/dist/panel-CSFFA5FF.cjs.map +0 -1
- package/dist/panel-S2UR5BSD.js +0 -2
- package/dist/panel-S2UR5BSD.js.map +0 -1
- package/dist/panel-SGSUHR7V.js +0 -2
- package/dist/panel-SGSUHR7V.js.map +0 -1
- package/dist/pt-CODDT6VY.cjs +0 -2
- package/dist/pt-CODDT6VY.cjs.map +0 -1
- package/dist/pt-VUUNL42H.js +0 -2
- package/dist/pt-VUUNL42H.js.map +0 -1
- package/dist/ru-72WUEADV.cjs +0 -2
- package/dist/ru-72WUEADV.cjs.map +0 -1
- package/dist/ru-NDWY7Y36.js +0 -2
- package/dist/ru-NDWY7Y36.js.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../node_modules/.bun/@medv+finder@4.0.2/node_modules/@medv/finder/finder.js","../src/dom/fingerprint.ts","../src/dom/text-context.ts","../src/dom/xpath.ts","../src/dom/anchor.ts","../src/focus-tracker.ts","../src/popup.ts","../src/screenshot.ts","../src/annotator.ts","../src/api-client.ts","../src/diagnostics/console-buffer.ts","../src/diagnostics/network-buffer.ts","../src/events.ts","../src/fab.ts","../src/identity.ts","../src/dom/fuzzy.ts","../src/dom/visibility.ts","../src/dom/resolver.ts","../src/markers.ts","../src/store-client.ts","../src/styles/animations.ts","../src/styles/base.ts","../src/tooltip.ts","../src/launcher.ts","../src/index.ts"],"names":["acceptedAttrNames","attr","name","value","nameIsOk","wordLike","valueIsOk","idName","className","tagName","finder","input","options","defaults","startTime","config","rootDocument","findRootDocument","foundPath","count","candidate","search","fPath","fallback","selector","unique","optimized","optimize","byPenalty","stack","paths","current","i","level","tie","node","combinations","words","word","element","elementId","index","indexOf","nthOfType","nth","nthChild","path","query","penalty","acc","a","b","parent","child","rootNode","css","newPath","STABLE_ATTRS","djb2","str","hash","generateFingerprint","childCount","siblingIdx","attrHash","attrs","val","scoreFingerprint","storedFingerprint","parts","storedChildren","storedSibIdx","storedAttrHash","storedChildCount","storedSibIndex","candidateFp","candChildren","candSibIdx","candAttrHash","score","childDiff","sibDiff","adjacentText","direction","prop","sibling","attempts","text","boundedTextEnd","boundedText","neighborText","prevSibling","nextSibling","prev","next","cap","out","walker","walk","generateXPath","safeId","segments","tag","position","ANCHOR_KEY_ATTR","generateAnchor","cssSelector","xpath","textSnippet","textPrefix","textSuffix","fingerprint","neighbor","anchorKey","containsRect","el","rect","findAnchorElement","root","centerX","centerY","elementAtCenter","rectToPercentages","anchorBounds","isWidgetChrome","createFocusTracker","host","lastPageFocus","onFocusIn","e","target","TYPE_LABEL_KEYS","isMacPlatform","uaData","Popup","colors","t","typeOptions","ICON_QUESTION","ICON_CHANGE","ICON_BUG","ICON_OTHER","option","btn","icon","parseSvg","bgColor","getTypeBgColor","getTypeColor","btnRow","typeButtons","type","key","labelSpan","setText","rectBounds","onSubmit","resolve","popupH","popupW","top","left","aboveTop","focusableEls","first","last","reduceMotion","container","buttons","isActive","color","enabled","result","submitter","spinner","cachedHtml2Canvas","warnedAboutMissingDep","loadHtml2Canvas","mod","err","clamp","min","max","roundPct","captureAnnotatedScreenshot","html2canvas","quality","maxWidth","padX","padY","docX","docY","docW","docH","capX","capY","capW","capH","region","canvas","ratio","targetW","targetH","scaled","ctx","Annotator","bus","enableScreenshot","getFallbackTarget","drawMode","active","dot","style","instruction","cancelBtn","previouslyFocused","bounds","highlight","annotation","screenshotCache","formResult","touch","clientX","clientY","source","evt","x","y","w","h","pointRect","captureRect","capture","reject","cleanup","unsubSent","unsubError","unsubCancelled","reason","anchorElement","anchor","buildRequestHeaders","auth","json","merged","extra","MAX_RETRIES","TIMEOUT_MS","RETRY_QUEUE_KEY","MAX_QUEUE_SIZE","resilientFetch","url","init","retries","attempt","controller","timeout","response","error","baseDelay","jitter","r","isTransientFailure","SitepingNetworkError","SitepingError","isTransientStatus","status","LOCK_NAME","withRetryLock","callback","isRetryEntry","hasOwn","readQueue","raw","parsed","queueForRetry","endpoint","payload","queue","normalizeName","normalizeEmail","flushRetryQueue","currentIdentity","toRetry","unrelated","dropped","entry","failed","rejected","headers","res","remaining","parseJsonAs","ApiClient","projectName","screenshotRegion","rest","body","networkErrorFromException","errorFromResponse","params","feedbackQueryToSearchParams","id","resolved","LEVELS","serializeArg","arg","seen","_key","formatArgs","args","ConsoleBuffer","maxEntries","original","buffer","wrapped","truncateUrl","urlString","NetworkBuffer","startedAt","t0","method","t1","proto","originalOpen","originalSend","meta","wrappedOpen","wrappedSend","info","onEnd","EventBus","event","listener","set","fn","ITEM_GAP","ITEM_LABEL_KEYS","Fab","shadowRoot","isRight","ICON_LIST","ICON_EDIT","ICON_EYE","ICON_EYE_OFF","ICON_SITEPING","item","label","handleEscape","items","activeEl","currentIndex","nextIndex","displayText","tWithParams","ICON_CLOSE","svgStr","badge","unsubscribe","oldSvg","newSvg","STORAGE_KEY","isIdentity","email","isValidEmail","getIdentity","saveIdentity","identity","normalizeText","s","collapseWhitespace","editDistance","aLen","bLen","k","curr","j","prevDiag","tmp","similarity","maxLen","sellersDistance","haystack","needle","best","hc","sub","del","ins","fuzzyIncludes","minScore","capped","bigramCounts","counts","diceAgainst","needleCounts","needleBigramTotal","textBigramTotal","matches","consumed","available","used","wordPairCounts","wordPairDiceAgainst","needlePairs","needlePairTotal","textPairTotal","STRICT_VISIBILITY_OPTIONS","classifyVisibility","visibilityFactor","cls","STRATEGY_PRIORS","MAX_PER_STRATEGY","SCAN_TOP_K","SCAN_HARD_CAP","CANDIDATE_TEXT_CAP","TEXT_FLOOR","STRONG_STRUCT","ACCEPT_SCAN","RAW_FIELD_CAP","STRONG_VERIFY","NEUTRAL_VERIFICATION","AMBIGUITY_EPSILON","boundedField","buildSignals","snippet","snippetWordPairs","snippetWordPairTotal","resolveAnchor","signals","pool","gatherSelectorCandidates","scored","strategy","scoreOne","bestFinal","strongVisibleMatch","c","verifiable","budget","sweepScanCandidates","accepted","isAcceptable","winner","disambiguate","confidenceOf","add","enforceTag","escaped","candidates","storedFp","limit","ranked","cheap","charDice","wordDice","diff","scores","verificationScore","visibility","totalWeight","candidateText","contextScore","contextParts","prevText","nextText","candidateNeighbor","sortedAccepted","contenders","resolveAnnotation","resolution","absoluteRect","toAnchorData","toRectData","MARKER_OFFSET","markerPosition","clusterMarker","cluster","elIdx","HIGHLIGHT_FADE","REPOSITION_DEBOUNCE","HIDDEN_RECHECK_MS","LOW_CONFIDENCE_THRESHOLD","CLUSTER_DISTANCE","FAN_SPACING","MarkerManager","tooltip","liveRegion","visible","mutations","hasRelevantMutation","m","isClosedStatus","cause","recheckVisibility","resizeTick","now","scanBudget","validKeys","markerEl","cacheKey","cachedEl","backedOff","cacheUsable","anchorRect","pos","openCount","feedbacks","feedback","marker","allItems","itemI","itemJ","baseTop","baseLeft","isSolo","totalWidth","startLeft","topMarker","confidence","isResolved","number","typeColor","truncatedMessage","ariaLabel","getTypeLabel","activateMarker","feedbackId","StoreClient","store","record","flattenAnnotation","toResponse","total","toFeedbackUpdate","toAnnotationResponse","ann","SPRING_LINEAR","EASE_OUT_EXPO","SPRING_OVERSHOOT","EASE_OUT_QUART","ANIMATION_CSS","buildStyles","cssVariables","STATS_CSS","SORT_CSS","BULK_CSS","EXPORT_CSS","SHORTCUTS_CSS","DETAIL_CSS","SHOW_DELAY","HIDE_DELAY","Tooltip","locale","children","typeBg","createT","typeLabel","header","date","formatRelativeDate","tooltipRect","gap","isAbove","arrowLeft","instance","normaliseDiagnosticsOptions","skippedInstance","noop","readNodeEnv","normaliseDeepLinkOptions","launch","log","minViewportWidth","localeReady","loadLocale","scopeAnnotationsByUrl","getScope","diagnosticsOpts","consoleBuffer","networkBuffer","buildThemeColors","publicBus","client","publicBridges","fb","wire","shadowMode","shadow","sheet","focusTracker","markers","fab","panelInstance","panelPromise","destroyed","markerGeneration","loadPanel","prefetch","ric","pendingOpen","unsubToggle","open","p","annotator","onContextMenu","pointerType","n","submitting","unsubAnnotation","data","message","screenshotDataUrl","promptIdentity","clientId","scope","diagnostics","initialScope","initialOptions","deepLinkOpts","initialLoadGeneration","f","focusId","matched","doRefresh","generation","opts","teardownNavigation","scopeKey","lastScopeKey","onLocationChange","prevKey","originalPushState","originalReplaceState","patchedPushState","patchedReplaceState","backdrop","modal","titleId","title","nameInputId","emailInputId","nameLabel","nameInput","emailLabel","emailInput","closeModal","onKeydown","submitBtn","focusableSelectors","ke","initSiteping"],"mappings":"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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAAA,EA21BtF,UAAW,CAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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","file":"index.js","sourcesContent":["// License: MIT\n// Author: Anton Medvedev <anton@medv.io>\n// Source: https://github.com/antonmedv/finder\nconst acceptedAttrNames = new Set(['role', 'name', 'aria-label', 'rel', 'href']);\n/** Check if attribute name and value are word-like. */\nexport function attr(name, value) {\n let nameIsOk = acceptedAttrNames.has(name);\n nameIsOk ||= name.startsWith('data-') && wordLike(name);\n let valueIsOk = wordLike(value) && value.length < 100;\n valueIsOk ||= value.startsWith('#') && wordLike(value.slice(1));\n return nameIsOk && valueIsOk;\n}\n/** Check if id name is word-like. */\nexport function idName(name) {\n return wordLike(name);\n}\n/** Check if class name is word-like. */\nexport function className(name) {\n return wordLike(name);\n}\n/** Check if tag name is word-like. */\nexport function tagName(name) {\n return true;\n}\n/** Finds unique CSS selectors for the given element. */\nexport function finder(input, options) {\n if (input.nodeType !== Node.ELEMENT_NODE) {\n throw new Error(`Can't generate CSS selector for non-element node type.`);\n }\n if (input.tagName.toLowerCase() === 'html') {\n return 'html';\n }\n const defaults = {\n root: document.body,\n idName: idName,\n className: className,\n tagName: tagName,\n attr: attr,\n timeoutMs: 1000,\n seedMinLength: 3,\n optimizedMinLength: 2,\n maxNumberOfPathChecks: Infinity,\n };\n const startTime = new Date();\n const config = { ...defaults, ...options };\n const rootDocument = findRootDocument(config.root, defaults);\n let foundPath;\n let count = 0;\n for (const candidate of search(input, config, rootDocument)) {\n const elapsedTimeMs = new Date().getTime() - startTime.getTime();\n if (elapsedTimeMs > config.timeoutMs ||\n count >= config.maxNumberOfPathChecks) {\n const fPath = fallback(input, rootDocument);\n if (!fPath) {\n throw new Error(`Timeout: Can't find a unique selector after ${config.timeoutMs}ms`);\n }\n return selector(fPath);\n }\n count++;\n if (unique(candidate, rootDocument)) {\n foundPath = candidate;\n break;\n }\n }\n if (!foundPath) {\n throw new Error(`Selector was not found.`);\n }\n const optimized = [\n ...optimize(foundPath, input, config, rootDocument, startTime),\n ];\n optimized.sort(byPenalty);\n if (optimized.length > 0) {\n return selector(optimized[0]);\n }\n return selector(foundPath);\n}\nfunction* search(input, config, rootDocument) {\n const stack = [];\n let paths = [];\n let current = input;\n let i = 0;\n while (current && current !== rootDocument) {\n const level = tie(current, config);\n for (const node of level) {\n node.level = i;\n }\n stack.push(level);\n current = current.parentElement;\n i++;\n paths.push(...combinations(stack));\n if (i >= config.seedMinLength) {\n paths.sort(byPenalty);\n for (const candidate of paths) {\n yield candidate;\n }\n paths = [];\n }\n }\n paths.sort(byPenalty);\n for (const candidate of paths) {\n yield candidate;\n }\n}\nfunction wordLike(name) {\n if (/^[a-z\\-]{3,}$/i.test(name)) {\n const words = name.split(/-|[A-Z]/);\n for (const word of words) {\n if (word.length <= 2) {\n return false;\n }\n if (/[^aeiou]{4,}/i.test(word)) {\n return false;\n }\n }\n return true;\n }\n return false;\n}\nfunction tie(element, config) {\n const level = [];\n const elementId = element.getAttribute('id');\n if (elementId && config.idName(elementId)) {\n level.push({\n name: '#' + CSS.escape(elementId),\n penalty: 0,\n });\n }\n for (let i = 0; i < element.classList.length; i++) {\n const name = element.classList[i];\n if (config.className(name)) {\n level.push({\n name: '.' + CSS.escape(name),\n penalty: 1,\n });\n }\n }\n for (let i = 0; i < element.attributes.length; i++) {\n const attr = element.attributes[i];\n if (config.attr(attr.name, attr.value)) {\n level.push({\n name: `[${CSS.escape(attr.name)}=\"${CSS.escape(attr.value)}\"]`,\n penalty: 2,\n });\n }\n }\n const tagName = element.tagName.toLowerCase();\n if (config.tagName(tagName)) {\n level.push({\n name: tagName,\n penalty: 5,\n });\n const index = indexOf(element, tagName);\n if (index !== undefined) {\n level.push({\n name: nthOfType(tagName, index),\n penalty: 10,\n });\n }\n }\n const nth = indexOf(element);\n if (nth !== undefined) {\n level.push({\n name: nthChild(tagName, nth),\n penalty: 50,\n });\n }\n return level;\n}\nfunction selector(path) {\n let node = path[0];\n let query = node.name;\n for (let i = 1; i < path.length; i++) {\n const level = path[i].level || 0;\n if (node.level === level - 1) {\n query = `${path[i].name} > ${query}`;\n }\n else {\n query = `${path[i].name} ${query}`;\n }\n node = path[i];\n }\n return query;\n}\nfunction penalty(path) {\n return path.map((node) => node.penalty).reduce((acc, i) => acc + i, 0);\n}\nfunction byPenalty(a, b) {\n return penalty(a) - penalty(b);\n}\nfunction indexOf(input, tagName) {\n const parent = input.parentNode;\n if (!parent) {\n return undefined;\n }\n let child = parent.firstChild;\n if (!child) {\n return undefined;\n }\n let i = 0;\n while (child) {\n if (child.nodeType === Node.ELEMENT_NODE &&\n (tagName === undefined ||\n child.tagName.toLowerCase() === tagName)) {\n i++;\n }\n if (child === input) {\n break;\n }\n child = child.nextSibling;\n }\n return i;\n}\nfunction fallback(input, rootDocument) {\n let i = 0;\n let current = input;\n const path = [];\n while (current && current !== rootDocument) {\n const tagName = current.tagName.toLowerCase();\n const index = indexOf(current, tagName);\n if (index === undefined) {\n return;\n }\n path.push({\n name: nthOfType(tagName, index),\n penalty: NaN,\n level: i,\n });\n current = current.parentElement;\n i++;\n }\n if (unique(path, rootDocument)) {\n return path;\n }\n}\nfunction nthChild(tagName, index) {\n if (tagName === 'html') {\n return 'html';\n }\n return `${tagName}:nth-child(${index})`;\n}\nfunction nthOfType(tagName, index) {\n if (tagName === 'html') {\n return 'html';\n }\n return `${tagName}:nth-of-type(${index})`;\n}\nfunction* combinations(stack, path = []) {\n if (stack.length > 0) {\n for (let node of stack[0]) {\n yield* combinations(stack.slice(1, stack.length), path.concat(node));\n }\n }\n else {\n yield path;\n }\n}\nfunction findRootDocument(rootNode, defaults) {\n if (rootNode.nodeType === Node.DOCUMENT_NODE) {\n return rootNode;\n }\n if (rootNode === defaults.root) {\n return rootNode.ownerDocument;\n }\n return rootNode;\n}\nfunction unique(path, rootDocument) {\n const css = selector(path);\n switch (rootDocument.querySelectorAll(css).length) {\n case 0:\n throw new Error(`Can't select any node with this selector: ${css}`);\n case 1:\n return true;\n default:\n return false;\n }\n}\nfunction* optimize(path, input, config, rootDocument, startTime) {\n if (path.length > 2 && path.length > config.optimizedMinLength) {\n for (let i = 1; i < path.length - 1; i++) {\n const elapsedTimeMs = new Date().getTime() - startTime.getTime();\n if (elapsedTimeMs > config.timeoutMs) {\n return;\n }\n const newPath = [...path];\n newPath.splice(i, 1);\n if (unique(newPath, rootDocument) &&\n rootDocument.querySelector(selector(newPath)) === input) {\n yield newPath;\n yield* optimize(newPath, input, config, rootDocument, startTime);\n }\n }\n }\n}\n","/**\n * Element fingerprinting for robust DOM re-anchoring.\n *\n * Captures structural properties (child count, sibling index, stable attributes)\n * that survive CSS class changes and minor DOM reshuffling.\n * Inspired by Similo (academic state-of-the-art, 98.8% accuracy).\n */\n\nconst STABLE_ATTRS = [\"role\", \"aria-label\", \"type\", \"name\", \"href\", \"src\", \"data-testid\", \"data-id\"] as const;\n\n/** Simple 32-bit hash (djb2). */\nfunction djb2(str: string): string {\n let hash = 5381;\n for (let i = 0; i < str.length; i++) {\n hash = ((hash << 5) + hash + str.charCodeAt(i)) | 0;\n }\n return (hash >>> 0).toString(36);\n}\n\n/**\n * Generate a compact structural fingerprint for a DOM element.\n *\n * Format: `\"childCount:siblingIdx:attrHash\"`\n * - `childCount` — number of direct child elements\n * - `siblingIdx` — position among same-tag siblings (0-based)\n * - `attrHash` — djb2 hash of stable attributes (role, aria-label, type, etc.)\n *\n * Tag name is NOT included — it's stored separately in `AnchorData.elementTag`.\n */\nexport function generateFingerprint(element: Element): string {\n const childCount = element.children.length;\n\n // Position among same-tag siblings\n let siblingIdx = 0;\n const parent = element.parentElement;\n if (parent) {\n for (const child of parent.children) {\n if (child === element) break;\n if (child.tagName === element.tagName) siblingIdx++;\n }\n }\n\n return `${childCount}:${siblingIdx}:${attrHash(element)}`;\n}\n\n/**\n * Stable-attribute hash component of the fingerprint, exposed separately:\n * unlike the sibling-index component it is O(1) per element (no walk over\n * `parent.children`), so scan prefiltering can afford it on every candidate.\n */\nexport function attrHash(element: Element): string {\n const attrs: string[] = [];\n for (const attr of STABLE_ATTRS) {\n const val = element.getAttribute(attr);\n if (val) attrs.push(`${attr}=${val}`);\n }\n return attrs.length > 0 ? djb2(attrs.join(\",\")) : \"0\";\n}\n\n/**\n * Score how well a candidate element matches a stored fingerprint.\n * Returns 0–1.\n *\n * Weights:\n * - Child count match: 0.2 (tolerant — ±2 gets partial credit)\n * - Sibling index match: 0.4 (positional — most discriminating)\n * - Attribute hash match: 0.4 (identity — exact or nothing)\n */\nexport function scoreFingerprint(candidate: Element, storedFingerprint: string): number {\n const parts = storedFingerprint.split(\":\");\n if (parts.length !== 3) return 0;\n\n const [storedChildren, storedSibIdx, storedAttrHash] = parts;\n const storedChildCount = Number(storedChildren);\n const storedSibIndex = Number(storedSibIdx);\n if (Number.isNaN(storedChildCount) || Number.isNaN(storedSibIndex)) return 0;\n\n const candidateFp = generateFingerprint(candidate);\n const [candChildren, candSibIdx, candAttrHash] = candidateFp.split(\":\");\n\n let score = 0;\n\n // Child count (0.2)\n const childDiff = Math.abs(Number(candChildren) - storedChildCount);\n if (childDiff === 0) score += 0.2;\n else if (childDiff <= 2) score += 0.1;\n else if (childDiff <= 5) score += 0.03;\n\n // Sibling index (0.4)\n const sibDiff = Math.abs(Number(candSibIdx) - storedSibIndex);\n if (sibDiff === 0) score += 0.4;\n else if (sibDiff === 1) score += 0.2;\n else if (sibDiff <= 3) score += 0.08;\n\n // Attribute hash (0.4)\n if (candAttrHash === storedAttrHash) score += 0.4;\n\n return score;\n}\n","/**\n * Shared text-context helpers for DOM anchoring.\n * Used by both anchor generation (anchor.ts) and resolution (resolver.ts).\n */\n\n/** Raw-char budget for sibling reads that only keep 32–40 chars — generous\n * headroom for leading/trailing whitespace that trimming discards. */\nconst SIBLING_READ_CAP = 256;\n\n/**\n * Extract ~32 chars of text from the nearest sibling with content.\n * Walks up to 3 siblings in the given direction.\n *\n * Sibling text is read through the bounded walkers, never `textContent` —\n * a sibling can be an arbitrarily large subtree (a whole `<section>`), and\n * serializing it wholesale to keep 32 chars is the dominant hidden cost of\n * candidate verification on big pages.\n */\nexport function adjacentText(element: Element, direction: \"before\" | \"after\"): string {\n const prop = direction === \"before\" ? \"previousElementSibling\" : \"nextElementSibling\";\n let sibling: Element | null = element[prop];\n let attempts = 3;\n\n while (sibling && attempts > 0) {\n const text =\n direction === \"before\"\n ? boundedTextEnd(sibling, SIBLING_READ_CAP).trim()\n : boundedText(sibling, SIBLING_READ_CAP).trim();\n if (text) {\n return direction === \"before\" ? text.slice(-32) : text.slice(0, 32);\n }\n sibling = sibling[prop];\n attempts--;\n }\n\n return \"\";\n}\n\n/** Collect text from immediate siblings for disambiguation context. */\nexport function neighborText(element: Element): string {\n const prevSibling = element.previousElementSibling;\n const nextSibling = element.nextElementSibling;\n const prev = prevSibling ? boundedText(prevSibling, SIBLING_READ_CAP).trim().slice(0, 40) : \"\";\n const next = nextSibling ? boundedText(nextSibling, SIBLING_READ_CAP).trim().slice(0, 40) : \"\";\n return [prev, next].filter(Boolean).join(\" | \");\n}\n\n/**\n * First `cap` characters of an element's text, without serializing the whole\n * subtree. `textContent.slice(0, cap)` still pays for full subtree\n * serialization first — on a wrapper near the root that is the entire page\n * text, and repeated across scan candidates it degenerates to O(page²).\n * A TreeWalker yields the same text nodes in the same (tree) order and stops\n * as soon as the budget is reached.\n */\nexport function boundedText(element: Element, cap: number): string {\n let out = \"\";\n\n // Leaf fast path — the majority of scan candidates have no element\n // children; their text is the concatenation of their child text nodes,\n // no tree traversal machinery needed.\n if (element.firstElementChild === null) {\n for (const node of element.childNodes) {\n if (node.nodeType === 3) {\n out += (node as Text).data;\n if (out.length >= cap) break;\n }\n }\n return out.length > cap ? out.slice(0, cap) : out;\n }\n\n const walker = element.ownerDocument.createTreeWalker(element, NodeFilter.SHOW_TEXT);\n while (out.length < cap) {\n const node = walker.nextNode();\n if (!node) break;\n out += (node as Text).data;\n }\n return out.length > cap ? out.slice(0, cap) : out;\n}\n\n/**\n * Last `cap` characters of an element's text — the reverse-direction\n * counterpart of `boundedText` (TreeWalker only walks forward). Visits text\n * nodes in reverse tree order and stops once the budget is filled.\n */\nexport function boundedTextEnd(element: Element, cap: number): string {\n let out = \"\";\n const walk = (node: Node): boolean => {\n for (let child: Node | null = node.lastChild; child; child = child.previousSibling) {\n if (child.nodeType === 3) {\n out = (child as Text).data + out;\n if (out.length >= cap) return true;\n } else if (child.nodeType === 1 && walk(child)) {\n return true;\n }\n }\n return false;\n };\n walk(element);\n return out.length > cap ? out.slice(-cap) : out;\n}\n","/**\n * Generate an optimized XPath for a DOM element.\n *\n * Strategy:\n * - If the element has a unique id → //tag[@id='value']\n * - Otherwise, walk up the tree building /tag[position] segments\n * until we hit an ancestor with an id or reach <body>\n * - Cap depth at 6 levels to keep paths short\n */\nexport function generateXPath(element: Element): string {\n if (element.id) {\n const safeId = element.id.includes(\"'\") ? `concat('${element.id.replace(/'/g, \"',\\\"'\\\",'\")}')` : `'${element.id}'`;\n return `//${element.localName}[@id=${safeId}]`;\n }\n\n const segments: string[] = [];\n let current: Element | null = element;\n\n while (current && current !== document.body && segments.length < 6) {\n const tag = current.localName;\n const parent: Element | null = current.parentElement;\n\n if (current.id) {\n const safeId = current.id.includes(\"'\")\n ? `concat('${current.id.replace(/'/g, \"',\\\"'\\\",'\")}')`\n : `'${current.id}'`;\n segments.unshift(`/${tag}[@id=${safeId}]`);\n return \"/\" + segments.join(\"\");\n }\n\n // Compute position among same-tag siblings\n let position = 1;\n if (parent) {\n for (const sibling of parent.children) {\n if (sibling === current) break;\n if (sibling.localName === tag) position++;\n }\n }\n\n segments.unshift(`/${tag}[${position}]`);\n current = parent;\n }\n\n return \"/html/body\" + segments.join(\"\");\n}\n","import { finder } from \"@medv/finder\";\nimport type { AnchorData, RectData } from \"@siteping/core\";\nimport { generateFingerprint } from \"./fingerprint.js\";\nimport { adjacentText, neighborText } from \"./text-context.js\";\nimport { generateXPath } from \"./xpath.js\";\n\n/** HTML attribute hosts use to mark stable semantic anchors. */\nexport const ANCHOR_KEY_ATTR = \"data-feedback-anchor\";\n\n/**\n * Generate a multi-selector anchor for a DOM element.\n *\n * Resolution priority (used by `resolveAnchor`):\n * 1. Semantic anchor (`data-feedback-anchor` on closest ancestor) — hosts opt\n * into stable, narrow anchors that survive viewport changes and refactors\n * 2. Element id\n * 3. CSS selector via @medv/finder\n * 4. XPath\n * 5. Smart scan (fingerprint + text + prefix/suffix + neighbor)\n */\nexport function generateAnchor(element: Element): AnchorData {\n const cssSelector = finder(element, {\n // Filter out CSS-in-JS hashed class names\n className: (name: string) => !/^(css|sc|emotion|styled)-/.test(name) && !/^[a-z]{1,3}[A-Za-z0-9]{4,8}$/.test(name),\n // Prefer stable attributes\n attr: (name: string) => [\"data-testid\", \"data-id\", \"role\", \"aria-label\"].includes(name),\n // Exclude framework-generated dynamic IDs\n idName: (name: string) => !name.startsWith(\"radix-\") && !/^:r[0-9]+:$/.test(name),\n seedMinLength: 3,\n optimizedMinLength: 2,\n });\n\n const xpath = generateXPath(element);\n\n const rawText = element.textContent?.trim() ?? \"\";\n const textSnippet = rawText.slice(0, 120);\n\n const textPrefix = adjacentText(element, \"before\");\n const textSuffix = adjacentText(element, \"after\");\n const fingerprint = generateFingerprint(element);\n const neighbor = neighborText(element);\n\n const semanticAncestor = element.closest(`[${ANCHOR_KEY_ATTR}]`);\n const anchorKey = semanticAncestor?.getAttribute(ANCHOR_KEY_ATTR) ?? null;\n\n return {\n cssSelector,\n xpath,\n textSnippet,\n textPrefix,\n textSuffix,\n fingerprint,\n neighborText: neighbor,\n elementTag: element.tagName,\n elementId: element.id || undefined,\n anchorKey,\n };\n}\n\n/** Whether `el`'s bounding box fully contains `rect`. */\nfunction containsRect(el: Element, rect: DOMRect): boolean {\n const b = el.getBoundingClientRect();\n return b.left <= rect.x && b.top <= rect.y && b.right >= rect.x + rect.width && b.bottom >= rect.y + rect.height;\n}\n\n/**\n * Find the best DOM element to use as the rect's anchor.\n *\n * Priority:\n * 1. Closest ancestor with `data-feedback-anchor` whose bounds contain the rect —\n * semantic anchors are typically narrow section roots, so anchoring against\n * them keeps the percentage-based rect stable across viewport changes\n * instead of stretching to the width of `<main>` or `<body>`.\n * 2. Smallest ancestor that contains the rect (legacy behavior).\n * 3. `document.body` fallback — keeps percentages in [0, 1].\n */\nexport function findAnchorElement(rect: DOMRect, root: Element = document.documentElement): Element {\n const centerX = rect.x + rect.width / 2;\n const centerY = rect.y + rect.height / 2;\n\n const elementAtCenter = document.elementFromPoint(centerX, centerY);\n if (!elementAtCenter || elementAtCenter === root) return document.body;\n\n // Pass 1 — semantic anchor (host-controlled, most stable)\n let current: Element | null = elementAtCenter;\n while (current && current !== document.body) {\n if (current.hasAttribute(ANCHOR_KEY_ATTR) && containsRect(current, rect)) {\n return current;\n }\n current = current.parentElement;\n }\n\n // Pass 2 — original behavior: smallest ancestor that contains the rect\n current = elementAtCenter;\n while (current && current !== document.body) {\n if (containsRect(current, rect)) return current;\n current = current.parentElement;\n }\n\n return document.body;\n}\n\n/**\n * Convert absolute rectangle coordinates to percentages\n * relative to an anchor element's bounding box.\n */\nexport function rectToPercentages(rect: DOMRect, anchorBounds: DOMRect): RectData {\n // Guard against zero-dimension anchors (collapsed/hidden elements)\n if (anchorBounds.width <= 0 || anchorBounds.height <= 0) {\n return { xPct: 0, yPct: 0, wPct: 1, hPct: 1 };\n }\n return {\n xPct: (rect.x - anchorBounds.x) / anchorBounds.width,\n yPct: (rect.y - anchorBounds.y) / anchorBounds.height,\n wPct: rect.width / anchorBounds.width,\n hPct: rect.height / anchorBounds.height,\n };\n}\n","/**\n * Tracks the last *page* element the user focused, so FAB-launched keyboard\n * annotation has a real target: opening the radial menu moves focus into the\n * shadow root, which retargets `document.activeElement` to the 0x0\n * `<siteping-widget>` host — by the time the annotator activates, the element\n * the user actually cares about is no longer the active one. See issue #162.\n */\nexport interface FocusTracker {\n getLastPageFocus(): HTMLElement | null;\n destroy(): void;\n}\n\n/**\n * True when `el` belongs to the widget's own chrome rather than the host\n * page: the shadow host, body-level annotation overlay / toolbar / drawing\n * rect / popup (all carry `data-siteping-ignore`), the markers container\n * (whose markers are focusable but carry no ignore attribute), or the\n * tooltip. Host-independent (tagName/closest checks only) so the annotator\n * can share it without holding a host reference — mirrors the screenshot\n * `ignoreElements` predicate.\n *\n * Host pages may put `data-siteping-ignore` on their own elements to mask\n * them from screenshots — those are deliberately excluded from keyboard\n * annotation targeting too: an element opted out of capture shouldn't become\n * an annotation target through the Enter path.\n */\nexport function isWidgetChrome(el: Element): boolean {\n return (\n el.tagName === \"SITEPING-WIDGET\" ||\n el.closest(\"siteping-widget\") !== null ||\n el.closest('[data-siteping-ignore=\"true\"]') !== null ||\n el.closest(\"#siteping-markers\") !== null ||\n el.closest(\"#sp-tooltip\") !== null\n );\n}\n\nexport function createFocusTracker(host: HTMLElement): FocusTracker {\n let lastPageFocus: HTMLElement | null = null;\n\n const onFocusIn = (e: FocusEvent): void => {\n const target = e.target;\n if (!(target instanceof HTMLElement)) return;\n // <body> / <html> receive focus as a side effect of blurs and overlay\n // teardown — never something the user chose to annotate.\n if (target === document.body || target === document.documentElement) return;\n if (target === host || isWidgetChrome(target)) return;\n lastPageFocus = target;\n };\n\n document.addEventListener(\"focusin\", onFocusIn);\n\n return {\n getLastPageFocus(): HTMLElement | null {\n // Drop detached elements — annotating a node that left the DOM would\n // produce a dead anchor (and retaining it would leak the subtree).\n if (lastPageFocus && !lastPageFocus.isConnected) lastPageFocus = null;\n return lastPageFocus;\n },\n destroy(): void {\n // Both the listener and the reference must go: a retained document\n // listener would keep the tracked element alive past widget destroy.\n document.removeEventListener(\"focusin\", onFocusIn);\n lastPageFocus = null;\n },\n };\n}\n","import type { FeedbackType } from \"@siteping/core\";\nimport { Z_INDEX_MAX } from \"./constants.js\";\nimport { el, parseSvg, setText } from \"./dom-utils.js\";\nimport type { TFunction, Translations } from \"./i18n/index.js\";\nimport { ICON_BUG, ICON_CHANGE, ICON_OTHER, ICON_QUESTION } from \"./icons.js\";\nimport { getTypeBgColor, getTypeColor, type ThemeColors } from \"./styles/theme.js\";\n\n// Map each feedback type to its translation key, so `refreshLabels()` can\n// re-localize the existing type buttons without re-rendering the popup.\nconst TYPE_LABEL_KEYS: Record<FeedbackType, keyof Translations> = {\n question: \"type.question\",\n change: \"type.change\",\n bug: \"type.bug\",\n other: \"type.other\",\n};\n\n/**\n * Detect whether the host platform uses ⌘+Enter (macOS) vs Ctrl+Enter.\n * Resolved at call time so we can recompute the popup hint when the locale\n * dictionary lands.\n */\nfunction isMacPlatform(): boolean {\n const uaData = (navigator as Navigator & { userAgentData?: { platform?: string } }).userAgentData;\n return uaData\n ? uaData.platform === \"macOS\"\n : (navigator.platform?.includes(\"Mac\") ?? /Macintosh|Mac OS X/i.test(navigator.userAgent));\n}\n\ninterface PopupResult {\n type: FeedbackType;\n message: string;\n}\n\ninterface TypeOption {\n type: FeedbackType;\n icon: string;\n}\n\n/**\n * Optional async hook called when the user clicks \"Send\". While the returned\n * promise is pending the popup stays visible in a submitting state (spinner\n * on the submit button, every other control disabled). On resolution the\n * popup closes and `show()` resolves with the submitted result; on rejection\n * the popup restores so the user can retry without re-entering the form.\n */\ntype PopupSubmitHandler = (result: PopupResult) => Promise<void>;\n\n/**\n * Popup form shown after drawing an annotation rectangle.\n *\n * Glassmorphism design: frosted glass background, soft shadows,\n * pill-shaped type buttons, gradient submit button.\n * Lives outside Shadow DOM.\n */\nexport class Popup {\n private root: HTMLElement;\n private selectedType: FeedbackType | null = null;\n private textarea: HTMLTextAreaElement;\n private submitBtn: HTMLButtonElement;\n private cancelBtn: HTMLButtonElement;\n private typeRow: HTMLElement;\n private submitLabel: HTMLSpanElement;\n private hint: HTMLElement;\n private resolve: ((result: PopupResult | null) => void) | null = null;\n private previouslyFocused: HTMLElement | null = null;\n private onKeydownTrap: ((e: KeyboardEvent) => void) | null = null;\n private onSubmit: PopupSubmitHandler | null = null;\n private submittingState = false;\n /** WAAPI handle for the running spinner — cancelled when submitting ends. */\n private spinnerAnimation: Animation | null = null;\n\n /**\n * True from `show()` until its promise settles — through typing, the\n * in-flight `onSubmit` await, AND the failed-submit retry window. The\n * annotator's drawing guards read this to serialize popup sessions\n * (#114/#196): if a refactor ever nulls `resolve` before `onSubmit`\n * settles, those guards die silently — popup.test.ts pins the lifecycle.\n */\n get isOpen(): boolean {\n return this.resolve !== null;\n }\n\n constructor(\n private readonly colors: ThemeColors,\n private readonly t: TFunction,\n ) {\n this.root = el(\"div\", {\n style: `\n position:fixed;\n z-index:${Z_INDEX_MAX};\n width:300px;\n padding:16px;\n border-radius:16px;\n background:${this.colors.glassBg};\n backdrop-filter:blur(24px);\n -webkit-backdrop-filter:blur(24px);\n border:1px solid ${this.colors.glassBorder};\n box-shadow:0 8px 32px ${this.colors.shadow}, 0 2px 8px ${this.colors.shadow};\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n opacity:0;\n transform:translateY(8px) scale(0.98);\n transition:opacity 0.25s cubic-bezier(0.16, 1, 0.3, 1),transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);\n display:none;\n -webkit-font-smoothing:antialiased;\n `,\n });\n\n this.root.setAttribute(\"role\", \"dialog\");\n this.root.setAttribute(\"aria-modal\", \"true\");\n // Screenshot capture now runs while the popup is still visible (so the\n // spinner can show during the upload). Without this attribute the popup\n // would appear baked into the captured JPEG.\n this.root.setAttribute(\"data-siteping-ignore\", \"true\");\n // The dialog `aria-label` is bound by `applyLabels()` at the end of the\n // constructor, alongside every other `t()`-derived string.\n\n // Type selector grid (2x2). Labels are bound later by `applyLabels()` —\n // the constructor only builds the structure (icon + empty label span).\n const typeOptions: TypeOption[] = [\n { type: \"question\", icon: ICON_QUESTION },\n { type: \"change\", icon: ICON_CHANGE },\n { type: \"bug\", icon: ICON_BUG },\n { type: \"other\", icon: ICON_OTHER },\n ];\n this.typeRow = el(\"div\", { style: \"display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-bottom:12px;\" });\n for (const option of typeOptions) {\n const btn = document.createElement(\"button\");\n btn.style.cssText = `\n height:44px;\n border-radius:9999px;border:1px solid ${this.colors.border};\n background:${this.colors.glassBg};cursor:pointer;\n display:flex;align-items:center;justify-content:center;gap:5px;\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:13px;font-weight:500;color:${this.colors.textTertiary};\n transition:all 0.2s ease;\n padding:0 12px;\n `;\n const icon = parseSvg(option.icon);\n icon.setAttribute(\"style\", \"width:13px;height:13px;flex-shrink:0;\");\n btn.appendChild(icon);\n btn.appendChild(document.createElement(\"span\"));\n btn.dataset.type = option.type;\n btn.setAttribute(\"aria-pressed\", \"false\");\n\n btn.addEventListener(\"click\", () => {\n if (this.submittingState) return;\n this.selectType(option.type, this.typeRow);\n });\n\n btn.addEventListener(\"mouseenter\", () => {\n if (this.submittingState) return;\n if (btn.dataset.type !== this.selectedType) {\n const bgColor = getTypeBgColor(btn.dataset.type ?? \"\", this.colors);\n btn.style.background = bgColor;\n btn.style.borderColor = getTypeColor(btn.dataset.type ?? \"\", this.colors) + \"40\";\n }\n });\n\n btn.addEventListener(\"mouseleave\", () => {\n if (this.submittingState) return;\n if (btn.dataset.type !== this.selectedType) {\n btn.style.background = this.colors.glassBg;\n btn.style.borderColor = this.colors.border;\n }\n });\n\n this.typeRow.appendChild(btn);\n }\n\n // Textarea\n this.textarea = document.createElement(\"textarea\");\n this.textarea.style.cssText = `\n width:100%;min-height:72px;max-height:152px;\n padding:10px 12px;border-radius:12px;\n border:1px solid ${this.colors.border};\n background:${this.colors.glassBgHeavy};\n color:${this.colors.text};font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:13px;line-height:1.5;resize:vertical;\n outline:none;transition:all 0.2s ease;\n box-sizing:border-box;\n `;\n this.textarea.maxLength = 5000;\n\n // Keyboard shortcut hint\n this.hint = el(\"div\", {\n style: `\n font-size:11px;color:${this.colors.textTertiary};\n text-align:right;margin-top:4px;\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n letter-spacing:0.01em;\n `,\n });\n\n this.textarea.addEventListener(\"focus\", () => {\n if (this.submittingState) return;\n this.textarea.style.borderColor = this.colors.accent;\n this.textarea.style.boxShadow = `0 0 0 3px ${this.colors.accent}14`;\n this.textarea.style.background = this.colors.bg;\n });\n this.textarea.addEventListener(\"blur\", () => {\n if (this.submittingState) return;\n this.textarea.style.borderColor = this.colors.border;\n this.textarea.style.boxShadow = \"none\";\n this.textarea.style.background = this.colors.glassBgHeavy;\n });\n this.textarea.addEventListener(\"input\", () => {\n this.updateSubmitState();\n });\n this.textarea.addEventListener(\"keydown\", (e) => {\n if (this.submittingState) return;\n if (e.key === \"Enter\" && (e.ctrlKey || e.metaKey)) {\n e.preventDefault();\n this.submit();\n }\n if (e.key === \"Escape\") {\n this.cancel();\n }\n });\n\n // Button row\n const btnRow = el(\"div\", { style: \"display:flex;justify-content:flex-end;gap:8px;margin-top:12px;\" });\n\n this.cancelBtn = document.createElement(\"button\");\n this.cancelBtn.style.cssText = `\n height:34px;padding:0 16px;border-radius:9999px;\n border:1px solid ${this.colors.border};\n background:${this.colors.glassBg};\n color:${this.colors.textTertiary};font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:13px;font-weight:500;cursor:pointer;\n transition:all 0.2s ease;\n `;\n this.cancelBtn.addEventListener(\"click\", () => this.cancel());\n this.cancelBtn.addEventListener(\"mouseenter\", () => {\n if (this.submittingState) return;\n this.cancelBtn.style.borderColor = this.colors.accent;\n this.cancelBtn.style.color = this.colors.accent;\n });\n this.cancelBtn.addEventListener(\"mouseleave\", () => {\n if (this.submittingState) return;\n this.cancelBtn.style.borderColor = this.colors.border;\n this.cancelBtn.style.color = this.colors.textTertiary;\n });\n\n this.submitBtn = document.createElement(\"button\");\n this.submitBtn.style.cssText = `\n height:34px;padding:0 18px;border-radius:9999px;\n border:none;background:${this.colors.accentGradient};\n color:#fff;font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:13px;font-weight:600;cursor:pointer;\n opacity:0.35;pointer-events:none;\n transition:all 0.2s ease;\n box-shadow:0 2px 8px ${this.colors.accentGlow};\n display:inline-flex;align-items:center;justify-content:center;min-width:64px;\n `;\n // The submit label lives in its own <span> so the submitting-state spinner\n // can be appended/removed without disturbing it. `applyLabels()` binds its\n // text — never `setText` the button itself or it would wipe the spinner.\n this.submitLabel = document.createElement(\"span\");\n this.submitBtn.appendChild(this.submitLabel);\n this.submitBtn.addEventListener(\"click\", () => this.submit());\n\n btnRow.appendChild(this.cancelBtn);\n btnRow.appendChild(this.submitBtn);\n\n this.root.appendChild(this.typeRow);\n this.root.appendChild(this.textarea);\n this.root.appendChild(this.hint);\n this.root.appendChild(btnRow);\n document.body.appendChild(this.root);\n\n // Bind every `t()`-derived string into the freshly-built DOM. Kept as a\n // single pass so the constructor and `refreshLabels()` never drift.\n this.applyLabels();\n }\n\n /**\n * Re-read every `t(...)`-derived label, placeholder, and aria-label from\n * the active translation function. Idempotent — call after the locale\n * dictionary has finished loading so the popup swaps from the English\n * fallback to the configured language.\n */\n refreshLabels(): void {\n this.applyLabels();\n }\n\n /**\n * Walk the already-built DOM and bind every translation-derived string —\n * the dialog `aria-label`, the four type-button labels, the textarea\n * `placeholder` + `aria-label`, the `⌘+Enter` / `Ctrl+Enter` hint, and the\n * cancel/submit `textContent`. The single source of truth for which node\n * gets which `t()` string, shared by the constructor and `refreshLabels()`\n * so the two can never drift.\n */\n private applyLabels(): void {\n this.root.setAttribute(\"aria-label\", this.t(\"popup.ariaLabel\"));\n\n const typeButtons = this.root.querySelectorAll<HTMLButtonElement>(\"button[data-type]\");\n for (const btn of typeButtons) {\n const type = btn.dataset.type as FeedbackType | undefined;\n if (!type) continue;\n const key = TYPE_LABEL_KEYS[type];\n if (!key) continue;\n const labelSpan = btn.querySelector<HTMLSpanElement>(\"span\");\n if (labelSpan) setText(labelSpan, this.t(key));\n }\n\n this.textarea.placeholder = this.t(\"popup.placeholder\");\n this.textarea.setAttribute(\"aria-label\", this.t(\"popup.textareaAria\"));\n\n setText(this.hint, isMacPlatform() ? this.t(\"popup.submitHintMac\") : this.t(\"popup.submitHintOther\"));\n setText(this.cancelBtn, this.t(\"popup.cancel\"));\n // Target the label <span>, not the button — the button also hosts the\n // submitting-state spinner, which `setText` on the button would erase.\n setText(this.submitLabel, this.t(\"popup.submit\"));\n }\n\n /**\n * Show the popup near a drawn rectangle and return the user's input.\n * Returns null if cancelled.\n *\n * When `onSubmit` is provided the popup stays visible while the handler\n * runs — the submit button shows a spinner, every other control is\n * disabled. On success the popup closes; on rejection it restores so the\n * user can retry without re-entering the form.\n */\n show(rectBounds: DOMRect, onSubmit?: PopupSubmitHandler): Promise<PopupResult | null> {\n return new Promise((resolve) => {\n this.resolve = resolve;\n this.onSubmit = onSubmit ?? null;\n this.selectedType = null;\n this.textarea.value = \"\";\n this.submittingState = false;\n this.updateSubmitState();\n this.resetTypeButtons();\n\n // Save focus to restore on close\n this.previouslyFocused = document.activeElement as HTMLElement | null;\n\n // Position: bottom-left of rect, 8px below\n const popupH = 220;\n const popupW = 300;\n let top = rectBounds.bottom + 8;\n let left = rectBounds.left;\n\n // Vertical: prefer below; fall back to above; otherwise clamp inside viewport\n if (top + popupH > window.innerHeight) {\n const aboveTop = rectBounds.top - popupH - 8;\n if (aboveTop >= 8) {\n top = aboveTop;\n } else {\n // Rect is taller than the viewport allows on either side —\n // clamp to keep the popup fully visible.\n top = window.innerHeight - popupH - 8;\n }\n }\n // Collision: flip right if not enough space on left\n if (left + popupW > window.innerWidth) {\n left = rectBounds.right - popupW;\n }\n left = Math.max(8, left);\n top = Math.max(8, top);\n\n this.root.style.top = `${top}px`;\n this.root.style.left = `${left}px`;\n this.root.style.display = \"block\";\n\n // Install focus trap\n this.onKeydownTrap = (e: KeyboardEvent) => {\n if (e.key === \"Tab\") {\n const focusableEls = Array.from(\n this.root.querySelectorAll<HTMLElement>(\n 'button:not([disabled]), textarea:not([disabled]), input:not([disabled]), [tabindex]:not([tabindex=\"-1\"])',\n ),\n );\n if (focusableEls.length === 0) return;\n const first = focusableEls[0];\n const last = focusableEls[focusableEls.length - 1];\n if (!first || !last) return;\n if (e.shiftKey) {\n if (document.activeElement === first || !this.root.contains(document.activeElement)) {\n e.preventDefault();\n last.focus();\n }\n } else {\n if (document.activeElement === last || !this.root.contains(document.activeElement)) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n };\n this.root.addEventListener(\"keydown\", this.onKeydownTrap);\n\n // Check prefers-reduced-motion live (not cached at construction time)\n const reduceMotion =\n typeof window !== \"undefined\" && window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n this.root.style.transition = reduceMotion ? \"none\" : \"\";\n\n // Trigger animation\n requestAnimationFrame(() => {\n this.root.style.opacity = \"1\";\n this.root.style.transform = \"translateY(0) scale(1)\";\n this.textarea.focus();\n });\n });\n }\n\n private selectType(type: FeedbackType, container: HTMLElement): void {\n this.selectedType = type;\n const buttons = container.querySelectorAll<HTMLButtonElement>(\"button\");\n for (const btn of buttons) {\n const isActive = btn.dataset.type === type;\n const color = getTypeColor(btn.dataset.type ?? \"\", this.colors);\n const bgColor = getTypeBgColor(btn.dataset.type ?? \"\", this.colors);\n btn.style.background = isActive ? bgColor : this.colors.glassBg;\n btn.style.borderColor = isActive ? color + \"60\" : this.colors.border;\n btn.style.color = isActive ? color : this.colors.textTertiary;\n btn.style.fontWeight = isActive ? \"600\" : \"500\";\n btn.setAttribute(\"aria-pressed\", String(isActive));\n }\n this.updateSubmitState();\n }\n\n private resetTypeButtons(): void {\n const buttons = this.root.querySelectorAll<HTMLButtonElement>(\"button[data-type]\");\n for (const btn of buttons) {\n btn.setAttribute(\"aria-pressed\", \"false\");\n btn.disabled = false;\n btn.style.background = this.colors.glassBg;\n btn.style.borderColor = this.colors.border;\n btn.style.color = this.colors.textTertiary;\n btn.style.fontWeight = \"500\";\n btn.style.cursor = \"pointer\";\n }\n }\n\n private updateSubmitState(): void {\n if (this.submittingState) return;\n const enabled = this.selectedType !== null && this.textarea.value.trim().length > 0;\n this.submitBtn.disabled = !enabled;\n this.submitBtn.style.opacity = enabled ? \"1\" : \"0.35\";\n this.submitBtn.style.pointerEvents = enabled ? \"auto\" : \"none\";\n }\n\n private submit(): void {\n if (this.submittingState) return;\n if (!this.selectedType || !this.textarea.value.trim()) return;\n\n const result: PopupResult = { type: this.selectedType, message: this.textarea.value.trim() };\n\n if (!this.onSubmit) {\n // Legacy fire-and-forget path: resolve immediately and hide.\n this.resolve?.(result);\n this.resolve = null;\n this.hideElement();\n return;\n }\n\n this.enterSubmittingState();\n const submitter = this.onSubmit;\n submitter(result)\n .then(() => {\n this.resolve?.(result);\n this.resolve = null;\n this.hideElement();\n })\n .catch(() => {\n // Restore the form so the user can edit and retry. The caller is\n // responsible for surfacing the error (live region / toast) — we\n // intentionally do not show inline error text in the popup.\n this.exitSubmittingState();\n });\n }\n\n private cancel(): void {\n if (this.submittingState) return;\n this.resolve?.(null);\n this.resolve = null;\n this.hideElement();\n }\n\n /**\n * Swap the submit button's text for a spinner and freeze every other\n * control. Mirrors the panel's resolve/delete buttons (`sp-spinner--sm`)\n * but renders inline because the popup lives outside the Shadow DOM\n * and therefore can't reach the panel's CSS classes.\n */\n private enterSubmittingState(): void {\n this.submittingState = true;\n\n // Submit: spinner instead of text, keep button width stable\n this.submitLabel.style.display = \"none\";\n this.submitBtn.disabled = true;\n this.submitBtn.style.cursor = \"wait\";\n this.submitBtn.style.opacity = \"0.85\";\n this.submitBtn.setAttribute(\"aria-busy\", \"true\");\n this.submitBtn.appendChild(this.buildSpinner());\n\n // Cancel: dimmed and non-interactive — abandoning mid-upload would leak a\n // half-sent feedback on the server, so we hold the user until we know.\n this.cancelBtn.disabled = true;\n this.cancelBtn.style.opacity = \"0.5\";\n this.cancelBtn.style.cursor = \"not-allowed\";\n this.cancelBtn.style.pointerEvents = \"none\";\n\n // Textarea + type buttons: read-only\n this.textarea.disabled = true;\n this.textarea.style.opacity = \"0.6\";\n const typeButtons = this.typeRow.querySelectorAll<HTMLButtonElement>(\"button\");\n for (const btn of typeButtons) {\n btn.disabled = true;\n btn.style.cursor = \"not-allowed\";\n btn.style.opacity = \"0.6\";\n }\n }\n\n private exitSubmittingState(): void {\n this.submittingState = false;\n\n // Submit — tear down the spinner: cancel the WAAPI animation explicitly\n // (it has `iterations: Infinity`, so it never ends on its own) before\n // removing the element it drives.\n this.spinnerAnimation?.cancel();\n this.spinnerAnimation = null;\n const spinner = this.submitBtn.querySelector<HTMLDivElement>('[data-role=\"sp-popup-spinner\"]');\n spinner?.remove();\n this.submitLabel.style.display = \"\";\n this.submitBtn.removeAttribute(\"aria-busy\");\n this.submitBtn.style.cursor = \"pointer\";\n\n // Cancel\n this.cancelBtn.disabled = false;\n this.cancelBtn.style.opacity = \"1\";\n this.cancelBtn.style.cursor = \"pointer\";\n this.cancelBtn.style.pointerEvents = \"auto\";\n\n // Textarea + type buttons\n this.textarea.disabled = false;\n this.textarea.style.opacity = \"1\";\n const typeButtons = this.typeRow.querySelectorAll<HTMLButtonElement>(\"button\");\n for (const btn of typeButtons) {\n btn.disabled = false;\n btn.style.cursor = \"pointer\";\n btn.style.opacity = \"1\";\n }\n\n // Recompute submit enabled state from the (preserved) form fields\n this.updateSubmitState();\n }\n\n /**\n * Build a spinner element styled inline. Web Animations API drives the\n * rotation so we don't have to inject `@keyframes` into the host document.\n * Respects `prefers-reduced-motion`: omits the animation and falls back to\n * a static ring. The returned `Animation` handle is stored on the instance\n * so `exitSubmittingState()` can explicitly cancel it.\n */\n private buildSpinner(): HTMLDivElement {\n const spinner = document.createElement(\"div\");\n spinner.dataset.role = \"sp-popup-spinner\";\n spinner.style.cssText = `\n width:14px;height:14px;\n border:2px solid rgba(255,255,255,0.35);\n border-top-color:#fff;\n border-radius:50%;\n box-sizing:border-box;\n `;\n const reduceMotion =\n typeof window !== \"undefined\" &&\n typeof window.matchMedia === \"function\" &&\n window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n // Web Animations API is available in every browser we target; the guard\n // is defensive for jsdom in tests, where `animate` may be undefined.\n if (!reduceMotion && typeof spinner.animate === \"function\") {\n this.spinnerAnimation = spinner.animate([{ transform: \"rotate(0deg)\" }, { transform: \"rotate(360deg)\" }], {\n duration: 600,\n iterations: Infinity,\n easing: \"linear\",\n });\n }\n return spinner;\n }\n\n private hideElement(): void {\n // Remove focus trap\n if (this.onKeydownTrap) {\n this.root.removeEventListener(\"keydown\", this.onKeydownTrap);\n this.onKeydownTrap = null;\n }\n // Make sure the submitting decoration doesn't leak into the next show()\n if (this.submittingState) this.exitSubmittingState();\n this.onSubmit = null;\n this.root.style.opacity = \"0\";\n this.root.style.transform = \"translateY(8px) scale(0.98)\";\n // Restore focus to the previously focused element\n this.previouslyFocused?.focus();\n this.previouslyFocused = null;\n setTimeout(() => {\n this.root.style.display = \"none\";\n }, 250);\n }\n\n destroy(): void {\n // Settle a pending `show()` promise so it cannot outlive teardown — a\n // `destroy()` mid-submit would otherwise leak the awaiting closure (and\n // whatever it retains: the annotation, the base64 screenshot). Resolving\n // with `null` reads as \"cancelled\", matching `cancel()`.\n if (this.submittingState) this.exitSubmittingState();\n this.resolve?.(null);\n this.resolve = null;\n this.onSubmit = null;\n if (this.onKeydownTrap) {\n this.root.removeEventListener(\"keydown\", this.onKeydownTrap);\n this.onKeydownTrap = null;\n }\n this.root.remove();\n }\n}\n","/**\n * Screenshot capture via html2canvas-pro.\n *\n * `html2canvas-pro` is a regular `dependency` of `@siteping/widget` — every\n * install gets it. We dynamic-import it so bundlers emit a separate chunk\n * loaded only when `enableScreenshot: true` triggers the first capture;\n * hosts that never enable screenshots pay only the disk-space cost.\n *\n * Why the fork rather than html2canvas itself: the original parses only\n * `rgb()` / `hsl()` and has been unmaintained since 2022. Browsers now hand\n * back computed colors in whatever space the stylesheet used — `lab()`,\n * `oklab()`, `oklch()`, `color()` — and Tailwind 4 compiles every opacity\n * modifier (`bg-white/5`) to exactly those. The original threw on the first\n * such element and the whole capture was lost; the fork renders them.\n *\n * On capture failure (content-tainted canvas, version mismatch, missing 2D\n * context) we return `null` rather than throwing — the feedback is still\n * submitted, just without an image.\n */\n\nimport type { ScreenshotRegion } from \"@siteping/core\";\n\ntype Html2CanvasFn = (element: HTMLElement, options?: Html2CanvasOptions) => Promise<HTMLCanvasElement>;\n\ninterface Html2CanvasOptions {\n x?: number;\n y?: number;\n width?: number;\n height?: number;\n scale?: number;\n useCORS?: boolean;\n allowTaint?: boolean;\n logging?: boolean;\n ignoreElements?: (element: Element) => boolean;\n}\n\nlet cachedHtml2Canvas: Html2CanvasFn | null | undefined; // undefined = not loaded yet, null = failed\nlet warnedAboutMissingDep = false;\n\nasync function loadHtml2Canvas(): Promise<Html2CanvasFn | null> {\n if (cachedHtml2Canvas !== undefined) return cachedHtml2Canvas;\n try {\n // Static dynamic import — bundlers (Vite, webpack, esbuild) resolve this\n // at build time and emit a separate chunk loaded only on first capture.\n // html2canvas-pro ships as a regular dependency so this resolves on every\n // install. Earlier attempts to dodge static resolution via magic comments\n // silently broke production: bare specifiers can't be resolved at runtime\n // in browsers without import maps.\n //\n // Through `unknown` because the module namespace also carries the fork's\n // named exports (config, validator, monitor), so TypeScript no longer\n // sees enough overlap with the callable shape we actually consume.\n const mod = (await import(\"html2canvas-pro\")) as unknown as { default?: Html2CanvasFn } & Html2CanvasFn;\n cachedHtml2Canvas = (mod.default ?? mod) as Html2CanvasFn;\n return cachedHtml2Canvas;\n } catch (err) {\n cachedHtml2Canvas = null;\n if (!warnedAboutMissingDep) {\n warnedAboutMissingDep = true;\n console.warn(\n \"[siteping] html2canvas-pro import failed unexpectedly. Capture is disabled for this session — feedbacks are still submitted, just without screenshots. Underlying error:\",\n err,\n );\n }\n return null;\n }\n}\n\nexport interface CaptureOptions {\n /** JPEG quality 0..1 (default 0.85). */\n quality?: number;\n /** Max output width in CSS pixels (default 1200). Wider canvases are downscaled. */\n maxWidth?: number;\n}\n\n/** Result of a contextual capture: the JPEG plus where the drawn rect sits in it. */\nexport interface AnnotatedScreenshot {\n /** Base64 JPEG `data:` URL of the padded capture area. */\n dataUrl: string;\n /** The drawn rect's position within the image, as fractions of its dimensions. */\n region: ScreenshotRegion;\n}\n\n/** Clamp `value` into `[min, max]`. */\nfunction clamp(min: number, value: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n\n/** Round a fraction to 4 decimals and clamp it into [0, 1]. */\nfunction roundPct(value: number): number {\n return clamp(0, Math.round(value * 10_000) / 10_000, 1);\n}\n\n/**\n * Capture the drawn rect *plus surrounding context* as a JPEG data URL, and\n * report where the rect sits inside the image (`region`, as fractions of the\n * image dimensions) so dashboards can re-render the annotation on top.\n * Returns `null` on any failure — callers should not abort feedback submission.\n *\n * - Pads the rect by up to 60% of its own size (48px floor, 280/220px ceiling)\n * so reviewers see the UI around the annotation, not just its pixels\n * - Clamps the capture area to the document bounds (no blank margins)\n * - Excludes Siteping's own overlay elements via `ignoreElements`\n * - Honors devicePixelRatio for crisp captures, then downscales to `maxWidth`\n * — `region` is resolution-independent, so it survives the downscale\n * - JPEG at `quality` (0.85 = ~50–150 KB for a typical annotated area)\n */\nexport async function captureAnnotatedScreenshot(\n rect: DOMRect,\n options?: CaptureOptions,\n): Promise<AnnotatedScreenshot | null> {\n const html2canvas = await loadHtml2Canvas();\n if (!html2canvas) return null;\n\n const quality = options?.quality ?? 0.85;\n const maxWidth = options?.maxWidth ?? 1200;\n\n // Contextual padding, proportional to the rect with fixed floor/ceiling —\n // small rects still get enough context to be recognizable, huge rects\n // don't balloon the capture (CSS px).\n const padX = clamp(48, rect.width * 0.6, 280);\n const padY = clamp(48, rect.height * 0.6, 220);\n\n // Document coordinates of the drawn rect (rect is viewport-relative).\n const docX = window.scrollX + rect.x;\n const docY = window.scrollY + rect.y;\n\n // Clamp the padded capture area to the document bounds so the engine\n // never renders blank out-of-document margins.\n const docW = Math.max(document.documentElement.scrollWidth, document.body.scrollWidth);\n const docH = Math.max(document.documentElement.scrollHeight, document.body.scrollHeight);\n const capX = Math.max(0, docX - padX);\n const capY = Math.max(0, docY - padY);\n const capW = Math.min(docW, docX + rect.width + padX) - capX;\n const capH = Math.min(docH, docY + rect.height + padY) - capY;\n if (capW <= 0 || capH <= 0) return null;\n\n // Fractions are resolution-independent — computed once from CSS-px\n // geometry, they stay valid after the hi-DPI render and the downscale.\n const region: ScreenshotRegion = {\n xPct: roundPct((docX - capX) / capW),\n yPct: roundPct((docY - capY) / capH),\n wPct: roundPct(rect.width / capW),\n hPct: roundPct(rect.height / capH),\n };\n\n try {\n const canvas = await html2canvas(document.body, {\n x: capX,\n y: capY,\n width: capW,\n height: capH,\n scale: window.devicePixelRatio,\n useCORS: true,\n allowTaint: true,\n logging: false,\n ignoreElements: (element: Element) => {\n // Matched elements (and their descendants) are removed from the\n // render pass — the page underneath shows through. Two layers of\n // exclusion:\n //\n // 1. The widget's own shadow host (`<siteping-widget>`).\n // 2. Anything carrying `data-siteping-ignore=\"true\"` — the\n // documented host-facing masking attribute AND how widget\n // chrome that lives OUTSIDE the shadow host (annotator overlay\n // + toolbar + drawing rect, popup) opts itself out of capture.\n // Without (2) the accent-colored selection border ends up\n // baked into the JPEG.\n return (\n element.tagName === \"SITEPING-WIDGET\" ||\n element.closest?.(\"siteping-widget\") !== null ||\n element.getAttribute?.(\"data-siteping-ignore\") === \"true\"\n );\n },\n });\n\n if (canvas.width <= maxWidth) {\n return { dataUrl: canvas.toDataURL(\"image/jpeg\", quality), region };\n }\n\n // Downscale via an off-DOM canvas — keeps payload reasonable on\n // hi-DPI displays where the raw capture can be 2x–3x intended size.\n const ratio = maxWidth / canvas.width;\n const targetW = maxWidth;\n const targetH = Math.round(canvas.height * ratio);\n\n const scaled = document.createElement(\"canvas\");\n scaled.width = targetW;\n scaled.height = targetH;\n const ctx = scaled.getContext(\"2d\");\n if (!ctx) return null;\n ctx.drawImage(canvas, 0, 0, targetW, targetH);\n return { dataUrl: scaled.toDataURL(\"image/jpeg\", quality), region };\n } catch (err) {\n console.warn(\"[siteping] Screenshot capture failed:\", err);\n return null;\n }\n}\n\n/** @internal — exposed for tests. Resets the dynamic-import cache. */\nexport function _resetScreenshotCacheForTests(): void {\n cachedHtml2Canvas = undefined;\n warnedAboutMissingDep = false;\n}\n","import type { AnnotationPayload, FeedbackType, ScreenshotRegion } from \"@siteping/core\";\nimport { INSTANT_ANNOTATION_SIZE, Z_INDEX_MAX } from \"./constants.js\";\nimport { findAnchorElement, generateAnchor, rectToPercentages } from \"./dom/anchor.js\";\nimport { el, setText } from \"./dom-utils.js\";\nimport type { EventBus, WidgetEvents } from \"./events.js\";\nimport { isWidgetChrome } from \"./focus-tracker.js\";\nimport type { TFunction } from \"./i18n/index.js\";\nimport { Popup } from \"./popup.js\";\nimport { type AnnotatedScreenshot, captureAnnotatedScreenshot } from \"./screenshot.js\";\nimport type { ThemeColors } from \"./styles/theme.js\";\n\nexport interface AnnotationComplete {\n annotation: AnnotationPayload;\n type: FeedbackType;\n message: string;\n /**\n * Base64 JPEG `data:` URL captured by html2canvas-pro, or null when capture\n * is disabled / failed / the peer dep is missing.\n */\n screenshotDataUrl?: string | null | undefined;\n /**\n * Where the drawn rect sits within the captured screenshot, as fractions\n * of the image dimensions — see `ScreenshotRegion`. Null whenever\n * `screenshotDataUrl` is null.\n */\n screenshotRegion?: ScreenshotRegion | null | undefined;\n}\n\n/**\n * Annotation mode: full-page overlay with rectangle drawing.\n *\n * Glassmorphism design:\n * - Frosted glass toolbar at top\n * - Subtle tinted overlay\n * - Accent-colored drawing rectangle with glow\n */\nexport class Annotator {\n private overlay: HTMLElement | null = null;\n private toolbar: HTMLElement | null = null;\n private drawingRect: HTMLElement | null = null;\n private startX = 0;\n private startY = 0;\n private isDrawing = false;\n private isActive = false;\n /**\n * True when the current annotation session was triggered by right-click\n * (instant comment) rather than the FAB draw flow. Controls whether the\n * toolbar is shown and whether cancel deactivates unconditionally.\n */\n private instantMode = false;\n private popup: Popup;\n private savedOverflow = \"\";\n private preActiveFocusElement: Element | null = null;\n /**\n * Target of the keyboard (Enter) annotation path — the page element focused\n * at activation, or the focus tracker's fallback when activation came from\n * the widget's own chrome (FAB menu). Distinct from `preActiveFocusElement`,\n * which keeps its focus-restore role untouched. See issue #162.\n */\n private keyboardTarget: HTMLElement | null = null;\n private rafId: number | null = null;\n private pendingMoveEvent: MouseEvent | Touch | null = null;\n /**\n * Reject handle for the in-flight `runSubmission` promise, or null when no\n * submission is pending. `destroy()` calls it to settle the promise rather\n * than leaving the awaiting closure hung past teardown.\n */\n private rejectPendingSubmission: ((reason: Error) => void) | null = null;\n\n constructor(\n private readonly colors: ThemeColors,\n private readonly bus: EventBus<WidgetEvents>,\n private readonly t: TFunction,\n private readonly enableScreenshot: boolean = false,\n private readonly getFallbackTarget?: () => HTMLElement | null,\n ) {\n this.popup = new Popup(colors, t);\n\n this.bus.on(\"annotation:start\", () => this.activate());\n }\n\n /**\n * True while the annotator is active (overlay/popup session in progress).\n * The launcher checks this before calling `preventDefault()` on the\n * `contextmenu` event so a right-click during an active session falls\n * through to the native menu instead of being silently swallowed.\n */\n get isBusy(): boolean {\n return this.isActive;\n }\n\n /**\n * Re-read every `t(...)`-derived label inside the popup. The annotator's\n * own toolbar text is created fresh on every `activate()` call, so only\n * the long-lived popup needs explicit re-localization here.\n */\n refreshLabels(): void {\n this.popup.refreshLabels();\n }\n\n /**\n * Capture a contextual screenshot of the drawn rect (padded with the\n * surrounding UI, plus the rect's region within the image) when\n * `enableScreenshot` is on. Returns null on disable / capture failure /\n * missing peer dep — the feedback is always submitted regardless.\n */\n private async maybeCapture(rect: DOMRect): Promise<AnnotatedScreenshot | null> {\n if (!this.enableScreenshot) return null;\n return captureAnnotatedScreenshot(rect);\n }\n\n private activate(): void {\n if (this.isActive) return;\n this.isActive = true;\n const drawMode = !this.instantMode;\n\n // Capture the focused element before activation for keyboard annotation\n this.preActiveFocusElement = document.activeElement;\n\n // Keyboard (Enter) target. FAB-launched sessions re-focus the FAB before\n // activation, so the active element here is only the widget's 0x0 shadow\n // host — fall back to the last page element the focus tracker recorded\n // instead of silently dead-ending the Enter path. See issue #162.\n const active = document.activeElement;\n this.keyboardTarget =\n active instanceof HTMLElement &&\n active !== document.body &&\n active !== document.documentElement &&\n !isWidgetChrome(active)\n ? active\n : (this.getFallbackTarget?.() ?? null);\n\n // Lock page scroll\n this.savedOverflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n\n // Overlay — subtle blue tint for depth.\n //\n // Overlay, toolbar and the drawn rectangle live on document.body, outside\n // the siteping-widget shadow host. Without the `data-siteping-ignore`\n // marker the screenshot predicate in screenshot.ts cannot reach them —\n // and the accent-colored selection border plus the page tint end up\n // baked into the captured JPEG. See issue #124.\n this.overlay = el(\"div\", {\n style: `\n position:fixed;inset:0;\n z-index:${Z_INDEX_MAX - 1};\n background:rgba(15, 23, 42, 0.04);\n cursor:${drawMode ? \"crosshair\" : \"default\"};\n `,\n });\n // The overlay is an interactive surface (draw with the pointer, Enter to\n // annotate the previously focused element, Escape to cancel) and receives\n // programmatic focus below — so it must be exposed to assistive tech, NOT\n // aria-hidden: focusing an aria-hidden element parks screen-reader users\n // on a node that announces nothing (axe \"aria-hidden-focus\", serious).\n this.overlay.setAttribute(\"role\", \"application\");\n this.overlay.setAttribute(\n \"aria-label\",\n drawMode ? this.t(\"annotator.instruction\") : this.t(\"annotator.instantInstruction\"),\n );\n this.overlay.setAttribute(\"data-siteping-ignore\", \"true\");\n\n // Toolbar — glassmorphism bar (suppressed in instant mode: the\n // \"Draw a rectangle\" copy is wrong when the composer is already open)\n if (drawMode) {\n this.toolbar = el(\"div\", {\n style: `\n position:fixed;top:0;left:0;right:0;\n z-index:${Z_INDEX_MAX};\n height:52px;\n background:${this.colors.glassBg};\n backdrop-filter:blur(24px);\n -webkit-backdrop-filter:blur(24px);\n border-bottom:1px solid ${this.colors.glassBorder};\n display:flex;align-items:center;justify-content:center;gap:16px;\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:14px;color:${this.colors.text};\n box-shadow:0 4px 16px ${this.colors.shadow};\n -webkit-font-smoothing:antialiased;\n `,\n });\n this.toolbar.setAttribute(\"data-siteping-ignore\", \"true\");\n\n const dot = el(\"span\", {\n style: `\n width:8px;height:8px;border-radius:50%;\n background:${this.colors.accent};\n box-shadow:0 0 8px ${this.colors.accentGlow};\n animation:pulse 1.5s ease-in-out infinite;\n `,\n });\n\n // Add pulse animation inline (respects prefers-reduced-motion)\n const style = document.createElement(\"style\");\n style.textContent = [\n \"@keyframes pulse{0%,100%{opacity:1}50%{opacity:0.4}}\",\n \"@media(prefers-reduced-motion:reduce){@keyframes pulse{from,to{opacity:1}}}\",\n ].join(\"\");\n this.toolbar.appendChild(style);\n\n const instruction = el(\"span\", { style: \"font-weight:500;letter-spacing:-0.01em;\" });\n setText(instruction, this.t(\"annotator.instruction\"));\n\n const cancelBtn = document.createElement(\"button\");\n cancelBtn.style.cssText = `\n height:34px;padding:0 18px;border-radius:9999px;\n border:1px solid ${this.colors.border};\n background:${this.colors.glassBg};\n color:${this.colors.textTertiary};font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:13px;font-weight:500;cursor:pointer;\n transition:all 0.2s ease;\n `;\n setText(cancelBtn, this.t(\"annotator.cancel\"));\n cancelBtn.addEventListener(\"click\", () => this.deactivate());\n cancelBtn.addEventListener(\"mouseenter\", () => {\n cancelBtn.style.borderColor = this.colors.typeBug;\n cancelBtn.style.color = this.colors.typeBug;\n cancelBtn.style.background = this.colors.typeBugBg;\n });\n cancelBtn.addEventListener(\"mouseleave\", () => {\n cancelBtn.style.borderColor = this.colors.border;\n cancelBtn.style.color = this.colors.textTertiary;\n cancelBtn.style.background = this.colors.glassBg;\n });\n\n this.toolbar.appendChild(dot);\n this.toolbar.appendChild(instruction);\n this.toolbar.appendChild(cancelBtn);\n }\n\n if (drawMode) {\n // Mouse events\n this.overlay.addEventListener(\"mousedown\", this.onMouseDown);\n this.overlay.addEventListener(\"mousemove\", this.onMouseMove);\n this.overlay.addEventListener(\"mouseup\", this.onMouseUp);\n\n // Touch events (Surface Pro, iPad, etc.)\n this.overlay.addEventListener(\"touchstart\", this.onTouchStart, { passive: false });\n this.overlay.addEventListener(\"touchmove\", this.onTouchMove, { passive: false });\n this.overlay.addEventListener(\"touchend\", this.onTouchEnd);\n\n // Keyboard annotation: Enter selects the captured keyboard target\n this.overlay.addEventListener(\"keydown\", this.onOverlayKeyDown);\n }\n\n // Allow tab-through so keyboard users can reach underlying elements\n this.overlay.setAttribute(\"tabindex\", \"0\");\n\n // Escape to cancel\n document.addEventListener(\"keydown\", this.onKeyDown);\n\n document.body.appendChild(this.overlay);\n if (this.toolbar) document.body.appendChild(this.toolbar);\n\n // Move focus to the overlay so the keyboard-annotation path (Enter →\n // annotate the captured keyboard target) actually receives keydown —\n // onOverlayKeyDown only fires when the overlay itself is focused. The\n // overlay has tabindex=0, and the keyboard target was captured at the top\n // of activate(), before the overlay existed, so focusing here doesn't\n // clobber it. (WCAG 2.1.1 Level A)\n this.overlay.focus({ preventScroll: true });\n }\n\n private deactivate(): void {\n if (!this.isActive) return;\n this.isActive = false;\n this.isDrawing = false;\n this.instantMode = false;\n const previouslyFocused = this.preActiveFocusElement;\n this.preActiveFocusElement = null;\n this.keyboardTarget = null;\n\n // Cancel any pending rAF to prevent stale callbacks\n if (this.rafId !== null) {\n cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n this.pendingMoveEvent = null;\n\n document.body.style.overflow = this.savedOverflow;\n document.removeEventListener(\"keydown\", this.onKeyDown);\n\n this.overlay?.remove();\n this.toolbar?.remove();\n this.drawingRect?.remove();\n this.overlay = null;\n this.toolbar = null;\n this.drawingRect = null;\n\n // Removing the focused overlay drops focus to <body> — hand it back to the\n // element that had it before activation (WCAG 2.4.3 focus order). When\n // activation came from the FAB menu this element is the shadow host and\n // focus() is a no-op; the Fab restores itself on annotation:end instead.\n if (previouslyFocused instanceof HTMLElement && previouslyFocused.isConnected) {\n previouslyFocused.focus({ preventScroll: true });\n }\n\n this.bus.emit(\"annotation:end\");\n }\n\n private onKeyDown = (e: KeyboardEvent): void => {\n if (e.key === \"Escape\") this.deactivate();\n };\n\n /**\n * Keyboard annotation: pressing Enter while the overlay is active selects\n * the keyboard target captured at activation (the focused page element, or\n * the focus tracker's fallback for FAB-launched sessions) and creates a\n * full-bounds annotation covering that element (WCAG 2.1.1 Level A).\n */\n private onOverlayKeyDown = async (e: KeyboardEvent): Promise<void> => {\n if (e.key !== \"Enter\") return;\n e.preventDefault();\n // A submission is already running or the popup is open — ignore so we\n // can't orphan the first `popup.show()` / `runSubmission` pair.\n if (this.popup.isOpen) return;\n // Mid-pointer-drag: the user is drawing — hijacking `drawingRect` for the\n // keyboard highlight here would corrupt the drag's geometry updates.\n if (this.isDrawing) return;\n\n const target = this.keyboardTarget;\n if (!target || !(target instanceof HTMLElement)) return;\n\n const bounds = target.getBoundingClientRect();\n if (bounds.width <= 0 || bounds.height <= 0) return;\n\n const rectBounds = new DOMRect(bounds.x, bounds.y, bounds.width, bounds.height);\n\n // Highlight the target like a pointer-drawn rectangle so keyboard users\n // see what they're about to comment. Assigned to `drawingRect` so every\n // existing cleanup path (deactivate, screenshot exclusion, removal once\n // the popup closes) treats it exactly like the mouse path's rect.\n this.drawingRect?.remove();\n const highlight = this.createDrawingRect();\n highlight.style.left = `${bounds.x}px`;\n highlight.style.top = `${bounds.y}px`;\n highlight.style.width = `${bounds.width}px`;\n highlight.style.height = `${bounds.height}px`;\n this.drawingRect = highlight;\n this.overlay?.appendChild(highlight);\n\n const anchor = generateAnchor(target);\n const annotation: AnnotationPayload = {\n anchor,\n rect: { xPct: 0, yPct: 0, wPct: 1, hPct: 1 },\n scrollX: window.scrollX,\n scrollY: window.scrollY,\n viewportW: window.innerWidth,\n viewportH: window.innerHeight,\n devicePixelRatio: window.devicePixelRatio,\n };\n\n // Submission stays inside the popup so the user gets a visible spinner\n // until the server confirms — see finishDrawing for the rationale.\n const screenshotCache: { value?: AnnotatedScreenshot | null } = {};\n const result = await this.popup.show(rectBounds, (formResult) =>\n this.runSubmission(annotation, formResult, rectBounds, screenshotCache),\n );\n\n this.drawingRect?.remove();\n this.drawingRect = null;\n if (result) this.deactivate();\n };\n\n private onMouseDown = (e: MouseEvent): void => {\n this.startDrawing(e.clientX, e.clientY);\n };\n\n private onTouchStart = (e: TouchEvent): void => {\n e.preventDefault();\n const touch = e.touches[0];\n if (touch) this.startDrawing(touch.clientX, touch.clientY);\n };\n\n private startDrawing(clientX: number, clientY: number): void {\n // Suppress pointer-driven drawing while the popup is open over the page.\n // Starting a second rectangle would orphan the first `popup.show()`\n // promise (and its `runSubmission`). This closes a latent bug where\n // drawing during the open popup overwrote `Popup.resolve`.\n if (this.popup.isOpen) return;\n\n this.isDrawing = true;\n this.startX = clientX;\n this.startY = clientY;\n\n this.drawingRect?.remove();\n this.drawingRect = this.createDrawingRect();\n this.overlay?.appendChild(this.drawingRect);\n }\n\n /**\n * The accent-colored selection rectangle — shared by pointer drawing and\n * the keyboard (Enter) highlight so the two paths can't drift visually.\n * Excluded from screenshot capture (see overlay creation in activate()).\n */\n private createDrawingRect(): HTMLElement {\n const rect = el(\"div\", {\n style: `\n position:fixed;\n border:2px solid ${this.colors.accent};\n background:${this.colors.accent}12;\n pointer-events:none;\n border-radius:8px;\n box-shadow:0 0 16px ${this.colors.accentGlow};\n transition:box-shadow 0.15s ease;\n `,\n });\n rect.setAttribute(\"data-siteping-ignore\", \"true\");\n return rect;\n }\n\n private onMouseMove = (e: MouseEvent): void => {\n this.scheduleRectUpdate(e);\n };\n\n private onTouchMove = (e: TouchEvent): void => {\n e.preventDefault();\n if (e.touches[0]) this.scheduleRectUpdate(e.touches[0]);\n };\n\n private scheduleRectUpdate(source: MouseEvent | Touch): void {\n if (!this.isDrawing || !this.drawingRect) return;\n\n this.pendingMoveEvent = source;\n if (this.rafId !== null) return;\n\n this.rafId = requestAnimationFrame(() => {\n this.rafId = null;\n const evt = this.pendingMoveEvent;\n if (!evt || !this.drawingRect) return;\n\n const x = Math.min(evt.clientX, this.startX);\n const y = Math.min(evt.clientY, this.startY);\n const w = Math.abs(evt.clientX - this.startX);\n const h = Math.abs(evt.clientY - this.startY);\n\n this.drawingRect.style.left = `${x}px`;\n this.drawingRect.style.top = `${y}px`;\n this.drawingRect.style.width = `${w}px`;\n this.drawingRect.style.height = `${h}px`;\n });\n }\n\n private onTouchEnd = async (e: TouchEvent): Promise<void> => {\n const touch = e.changedTouches[0];\n if (touch) await this.finishDrawing(touch.clientX, touch.clientY);\n };\n\n private onMouseUp = async (e: MouseEvent): Promise<void> => {\n await this.finishDrawing(e.clientX, e.clientY);\n };\n\n private finishDrawing = async (clientX: number, clientY: number): Promise<void> => {\n if (!this.isDrawing || !this.drawingRect) return;\n this.isDrawing = false;\n\n const x = Math.min(clientX, this.startX);\n const y = Math.min(clientY, this.startY);\n const w = Math.abs(clientX - this.startX);\n const h = Math.abs(clientY - this.startY);\n\n // Ignore tiny rectangles (accidental clicks)\n if (w < 10 || h < 10) {\n this.drawingRect.remove();\n this.drawingRect = null;\n return;\n }\n\n const rectBounds = new DOMRect(x, y, w, h);\n\n // Build annotation payload BEFORE the popup opens — the overlay is still\n // up so `findAnchorElement` can briefly disable pointer events on it.\n const { annotation } = this.buildAnnotation(rectBounds);\n\n // Keep the drawn rectangle visible while the popup is open so the user\n // can see what they're sending feedback about — including while the\n // submit-spinner is running. We only remove it after the popup closes.\n const screenshotCache: { value?: AnnotatedScreenshot | null } = {};\n const result = await this.popup.show(rectBounds, (formResult) =>\n this.runSubmission(annotation, formResult, rectBounds, screenshotCache),\n );\n\n this.drawingRect?.remove();\n this.drawingRect = null;\n if (result) this.deactivate();\n };\n\n /**\n * Instantly triggers the annotation popup at a specific location without\n * requiring the user to draw a rectangle. Used for right-click commenting.\n *\n * Entry is routed through the event bus (`annotation:start`) so the public\n * event contract (`onAnnotationStart` / `onAnnotationEnd`) is honoured —\n * hosts that pause analytics or chat widgets on annotation hooks see a\n * symmetric start/end pair regardless of entry path.\n */\n public async startInstantAnnotation(clientX: number, clientY: number): Promise<void> {\n // Guard: no-op while the annotator is active (overlay/popup session in\n // progress). `isActive` covers the entire window: draw mode in progress,\n // popup open for typing, and submission in flight. Without this a second\n // right-click (e.g. to paste in the textarea) would reset the form,\n // orphan the pending popup.show(), and leak the old drawing rect.\n if (this.isActive) return;\n\n // Set instant-mode flag BEFORE emitting annotation:start so activate()\n // (called by the bus handler) can read it and suppress the toolbar.\n this.instantMode = true;\n this.bus.emit(\"annotation:start\");\n\n // Build a small point-rect centered at the cursor for the marker/percentage\n // math. Clamped to viewport edges on all sides.\n const x = Math.max(0, Math.min(clientX - INSTANT_ANNOTATION_SIZE / 2, window.innerWidth - INSTANT_ANNOTATION_SIZE));\n const y = Math.max(\n 0,\n Math.min(clientY - INSTANT_ANNOTATION_SIZE / 2, window.innerHeight - INSTANT_ANNOTATION_SIZE),\n );\n const pointRect = new DOMRect(x, y, INSTANT_ANNOTATION_SIZE, INSTANT_ANNOTATION_SIZE);\n\n // Resolve the anchor element and build the annotation payload.\n // We also derive the capture rect from the anchor element's bounding box\n // (clamped to the viewport) so enableScreenshot produces a useful image\n // instead of a postage stamp.\n const { annotation, anchorBounds } = this.buildAnnotation(pointRect);\n\n // Use the anchor element's bounding box (clamped to viewport) for\n // screenshot capture so reviewers get meaningful context, not a 20×20 px\n // postage stamp.\n const left = Math.max(0, anchorBounds.left);\n const top = Math.max(0, anchorBounds.top);\n const captureRect = new DOMRect(\n left,\n top,\n Math.max(0, Math.min(anchorBounds.right, window.innerWidth) - left),\n Math.max(0, Math.min(anchorBounds.bottom, window.innerHeight) - top),\n );\n\n // Create a visual indicator at the click point\n this.drawingRect?.remove();\n this.drawingRect = el(\"div\", {\n style: `\n position:fixed;\n left:${x}px;\n top:${y}px;\n width:${INSTANT_ANNOTATION_SIZE}px;\n height:${INSTANT_ANNOTATION_SIZE}px;\n border:2px solid ${this.colors.accent};\n background:${this.colors.accent}12;\n pointer-events:none;\n border-radius:8px;\n box-shadow:0 0 16px ${this.colors.accentGlow};\n `,\n });\n this.drawingRect.setAttribute(\"data-siteping-ignore\", \"true\");\n this.overlay?.appendChild(this.drawingRect);\n\n const screenshotCache: { value?: AnnotatedScreenshot | null } = {};\n await this.popup.show(pointRect, (formResult) =>\n this.runSubmission(annotation, formResult, captureRect, screenshotCache),\n );\n\n // Instant flow: always deactivate on popup close — unlike the draw flow\n // where cancel keeps the session alive so the user can re-draw, there is\n // no draw phase to return to here. Leaving the overlay, scroll-lock and\n // toolbar up after cancel strands the user in a mode they never opted into.\n this.drawingRect?.remove();\n this.drawingRect = null;\n this.deactivate();\n }\n\n /**\n * Submit handler passed into `popup.show()`. Captures the screenshot once\n * (cached across retries) and emits `annotation:complete` on the bus, then\n * waits for one of three terminal signals:\n *\n * - `feedback:sent` — resolve (popup closes).\n * - `feedback:error` — reject with the genuine error (popup restores for\n * retry; the launcher surfaces the error to the host).\n * - `submission:cancelled` — reject as a silent abort (popup restores; no\n * error is surfaced — e.g. the user cancelled the identity prompt).\n *\n * Submissions are serialized by the popup guard (`this.popup.isOpen`),\n * so exactly one `runSubmission` is ever live — the global outcome events\n * cannot cross-wire between submissions and need no correlation id.\n */\n private async runSubmission(\n annotation: AnnotationPayload,\n formResult: { type: FeedbackType; message: string },\n rectBounds: DOMRect,\n screenshotCache: { value?: AnnotatedScreenshot | null },\n ): Promise<void> {\n // Screenshot capture is the slow part. Capture once and reuse the\n // cached data URL + region on every retry — re-running html2canvas-pro after\n // each failed submit would punish the user for a network blip.\n if (screenshotCache.value === undefined) {\n screenshotCache.value = await this.maybeCapture(rectBounds);\n }\n const capture = screenshotCache.value;\n\n await new Promise<void>((resolve, reject) => {\n const cleanup = () => {\n unsubSent();\n unsubError();\n unsubCancelled();\n this.rejectPendingSubmission = null;\n };\n const unsubSent = this.bus.on(\"feedback:sent\", () => {\n cleanup();\n resolve();\n });\n const unsubError = this.bus.on(\"feedback:error\", (err) => {\n cleanup();\n reject(err);\n });\n const unsubCancelled = this.bus.on(\"submission:cancelled\", () => {\n cleanup();\n // Silent abort — the popup restores but no error is surfaced.\n reject(new Error(\"Feedback submission cancelled\"));\n });\n\n // Expose the reject handle so `destroy()` mid-submit can settle this\n // promise instead of leaving the awaiting closure hung past teardown.\n this.rejectPendingSubmission = (reason) => {\n cleanup();\n reject(reason);\n };\n\n this.bus.emit(\"annotation:complete\", {\n annotation,\n type: formResult.type,\n message: formResult.message,\n screenshotDataUrl: capture?.dataUrl ?? null,\n screenshotRegion: capture?.region ?? null,\n });\n });\n }\n\n /**\n * Build an AnnotationPayload from a drawn rectangle.\n * Temporarily hides the overlay to access the real DOM underneath.\n */\n private buildAnnotation(rectBounds: DOMRect): { annotation: AnnotationPayload; anchorBounds: DOMRect } {\n // Temporarily hide overlay to find the real element underneath\n if (this.overlay) this.overlay.style.pointerEvents = \"none\";\n const anchorElement = findAnchorElement(rectBounds);\n if (this.overlay) this.overlay.style.pointerEvents = \"auto\";\n\n const anchor = generateAnchor(anchorElement);\n const anchorBounds = anchorElement.getBoundingClientRect();\n const rect = rectToPercentages(rectBounds, anchorBounds);\n\n const annotation = {\n anchor,\n rect,\n scrollX: window.scrollX,\n scrollY: window.scrollY,\n viewportW: window.innerWidth,\n viewportH: window.innerHeight,\n devicePixelRatio: window.devicePixelRatio,\n };\n return { annotation, anchorBounds };\n }\n destroy(): void {\n this.deactivate();\n // Settle an in-flight submission BEFORE tearing down the popup, so the\n // `runSubmission` promise cannot outlive teardown. The launcher's\n // `destroy()` also calls `bus.removeAll()`, which would otherwise strip\n // the terminal-event listeners and leave the promise — and the base64\n // screenshot it retains — hung forever.\n this.rejectPendingSubmission?.(new Error(\"Annotator destroyed during submission\"));\n this.popup.destroy();\n }\n}\n","import {\n errorFromResponse,\n type FeedbackPayload,\n type FeedbackQuery,\n type FeedbackResponse,\n type FeedbackResponseList,\n feedbackQueryToSearchParams,\n hasOwn,\n networkErrorFromException,\n type Prettify,\n SitepingError,\n type SitepingHeadersOption,\n SitepingNetworkError,\n} from \"@siteping/core\";\nimport type { Identity } from \"./identity.js\";\n\n/**\n * Abstract client interface used by the widget internals.\n *\n * `ApiClient` (HTTP mode) and `StoreClient` (direct store mode) both satisfy\n * this interface, allowing the widget to work identically in either mode.\n */\nexport interface WidgetClient {\n sendFeedback(payload: FeedbackPayload): Promise<FeedbackResponse>;\n getFeedbacks(projectName: string, options?: GetFeedbacksOptions): Promise<FeedbackResponseList>;\n resolveFeedback(id: string, resolved: boolean): Promise<FeedbackResponse>;\n deleteFeedback(id: string): Promise<void>;\n deleteAllFeedbacks(projectName: string): Promise<void>;\n}\n\n/**\n * Options accepted by `WidgetClient.getFeedbacks` — core's `FeedbackQuery`\n * minus the `projectName` the client already knows. Derived, so a new query\n * filter added to core flows to both the HTTP and store clients\n * automatically.\n */\nexport type GetFeedbacksOptions = Prettify<Omit<FeedbackQuery, \"projectName\">>;\n\n/** Auth options for `ApiClient` / `flushRetryQueue` (HTTP mode). */\nexport interface ApiClientAuth {\n /** Sent as `Authorization: Bearer <apiKey>` on every request. */\n apiKey?: string | undefined;\n /** Extra headers, static or per-request factory. An explicit `Authorization` entry wins over `apiKey`. */\n headers?: SitepingHeadersOption | undefined;\n}\n\n/**\n * Build the headers for one request — mirrors the dashboard's\n * `createEndpointSource` semantics: `Content-Type` when the request carries a\n * JSON body, then `Bearer` from `apiKey`, then `headers` merged on top so an\n * explicit `Authorization` wins.\n *\n * A function `headers` resolves once per call — retries inside\n * `resilientFetch` reuse the values for the whole retry sequence — up to\n * ~45s worst case with 4 attempts x 10s timeout plus backoff (the dashboard\n * has the same per-request semantics, without retries). A\n * throwing/rejecting factory fails the request like a network error.\n */\nexport async function buildRequestHeaders(auth: ApiClientAuth, json: boolean): Promise<Record<string, string>> {\n const merged: Record<string, string> = {};\n if (json) merged[\"Content-Type\"] = \"application/json\";\n if (auth.apiKey) merged.Authorization = `Bearer ${auth.apiKey}`;\n const extra = typeof auth.headers === \"function\" ? await auth.headers() : auth.headers;\n if (extra) Object.assign(merged, extra);\n return merged;\n}\n\nconst MAX_RETRIES = 3;\nconst TIMEOUT_MS = 10_000;\nconst RETRY_QUEUE_KEY = \"siteping_retry_queue\";\nconst MAX_QUEUE_SIZE = 20;\n\n// ---------------------------------------------------------------------------\n// Core fetch with retry + exponential backoff + jitter\n// ---------------------------------------------------------------------------\n\nasync function resilientFetch(url: string, init: RequestInit, retries = MAX_RETRIES): Promise<Response> {\n for (let attempt = 0; attempt <= retries; attempt++) {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), TIMEOUT_MS);\n\n try {\n const response = await fetch(url, {\n ...init,\n signal: controller.signal,\n });\n clearTimeout(timeout);\n\n // Don't retry client errors (4xx) — only server errors (5xx)\n if (response.ok || (response.status >= 400 && response.status < 500)) {\n return response;\n }\n\n if (attempt === retries) return response;\n } catch (error) {\n clearTimeout(timeout);\n if (attempt === retries) throw error;\n }\n\n // Exponential backoff with jitter: 1s, 2s, 4s + random ±500ms\n const baseDelay = 1000 * 2 ** attempt;\n const jitter = Math.random() * 1000 - 500;\n await new Promise((r) => setTimeout(r, baseDelay + jitter));\n }\n\n throw new Error(\"Max retries exceeded\");\n}\n\n// ---------------------------------------------------------------------------\n// Retry queue — persist failed feedbacks for retry on next page load\n// ---------------------------------------------------------------------------\n\ninterface RetryEntry {\n endpoint: string;\n payload: FeedbackPayload;\n}\n\n/**\n * Whether a failed submission is worth replaying later. Network failures and\n * server errors (5xx) are transient — the same payload can succeed once the\n * server is back. A 4xx is the server's verdict on the payload itself\n * (validation, auth, size…): replaying it verbatim fails identically every\n * time, so it is surfaced to the host through `onError` and never queued —\n * a queued rejection used to be replayed, and rejected, on every page load.\n */\nfunction isTransientFailure(error: unknown): boolean {\n return error instanceof SitepingNetworkError || (error instanceof SitepingError && error.code === \"SERVER\");\n}\n\n/** Same verdict for a replayed request: keep 5xx for the next flush, drop 4xx for good. */\nfunction isTransientStatus(status: number): boolean {\n return status >= 500;\n}\n\nconst LOCK_NAME = \"siteping_retry_queue\";\n\n/**\n * Acquire a Web Lock to serialize cross-tab access to the retry queue.\n * Falls back to running the callback without locking on older browsers.\n */\nasync function withRetryLock<T>(callback: () => T | Promise<T>): Promise<T> {\n if (typeof navigator !== \"undefined\" && navigator.locks) {\n return navigator.locks.request(LOCK_NAME, () => callback());\n }\n return callback();\n}\n\n/**\n * Shape-check one queue element — localStorage can hold tampered or legacy\n * entries, and a malformed one used to abort the whole flush via the outer\n * catch. Bad entries are dropped individually instead.\n */\nfunction isRetryEntry(value: unknown): value is RetryEntry {\n return (\n hasOwn(value, \"endpoint\") &&\n typeof value.endpoint === \"string\" &&\n hasOwn(value, \"payload\") &&\n typeof value.payload === \"object\" &&\n value.payload !== null\n );\n}\n\nfunction readQueue(): RetryEntry[] {\n const raw = localStorage.getItem(RETRY_QUEUE_KEY);\n if (!raw) return [];\n const parsed: unknown = JSON.parse(raw);\n return Array.isArray(parsed) ? parsed.filter(isRetryEntry) : [];\n}\n\nfunction queueForRetry(endpoint: string, payload: FeedbackPayload): void {\n // Fire-and-forget — we don't want to block the caller on the lock\n void withRetryLock(() => {\n try {\n const queue = readQueue();\n\n // Cap queue size to prevent unbounded localStorage growth\n if (queue.length >= MAX_QUEUE_SIZE) {\n queue.shift(); // Drop oldest entry\n }\n\n queue.push({ endpoint, payload });\n localStorage.setItem(RETRY_QUEUE_KEY, JSON.stringify(queue));\n } catch {\n // localStorage full or unavailable — silently drop\n }\n });\n}\n\nfunction normalizeName(value: string): string {\n return value.trim();\n}\n\nfunction normalizeEmail(value: string): string {\n return value.trim().toLowerCase();\n}\n\n/**\n * Flush queued feedbacks for `endpoint`. When `currentIdentity` is provided,\n * entries whose stored author doesn't match it are dropped rather than replayed.\n * This prevents user A's offline feedback from being POSTed under user B's\n * identity after a session change. When omitted, all entries are replayed to\n * preserve the legacy behavior for callers that don't track identity.\n *\n * `auth` headers resolve fresh at flush time (once per flush call) — queue\n * entries persist payloads only, never headers or token material.\n */\nexport async function flushRetryQueue(\n endpoint: string,\n currentIdentity?: Identity | null,\n auth: ApiClientAuth = {},\n): Promise<void> {\n await withRetryLock(async () => {\n try {\n const queue = readQueue();\n if (queue.length === 0) return;\n\n const toRetry: RetryEntry[] = [];\n const unrelated: RetryEntry[] = [];\n let dropped = 0;\n\n for (const entry of queue) {\n if (entry.endpoint !== endpoint) {\n unrelated.push(entry);\n continue;\n }\n\n if (\n !currentIdentity ||\n (normalizeName(entry.payload.authorName) === normalizeName(currentIdentity.name) &&\n normalizeEmail(entry.payload.authorEmail) === normalizeEmail(currentIdentity.email))\n ) {\n toRetry.push(entry);\n } else {\n dropped += 1;\n }\n }\n\n if (toRetry.length === 0 && dropped === 0) return;\n\n if (dropped > 0) {\n console.debug(\"[siteping] flushRetryQueue: dropped\", dropped, \"stale entries (identity changed)\");\n }\n\n // Process items sequentially to avoid overwhelming the server\n const failed: RetryEntry[] = [];\n let rejected = 0;\n if (toRetry.length > 0) {\n const headers = await buildRequestHeaders(auth, true);\n for (const entry of toRetry) {\n try {\n const res = await fetch(endpoint, {\n method: \"POST\",\n headers,\n body: JSON.stringify(entry.payload),\n });\n if (res.ok) continue;\n if (isTransientStatus(res.status)) failed.push(entry);\n else rejected += 1;\n } catch {\n failed.push(entry);\n }\n }\n }\n\n if (rejected > 0) {\n console.warn(\n `[siteping] flushRetryQueue: dropped ${rejected} queued feedback(s) the server rejected (4xx) — they would fail identically on every replay`,\n );\n }\n\n // Rebuild queue: keep unrelated entries + failed retries\n const remaining = unrelated.concat(failed);\n if (remaining.length > 0) {\n localStorage.setItem(RETRY_QUEUE_KEY, JSON.stringify(remaining));\n } else {\n localStorage.removeItem(RETRY_QUEUE_KEY);\n }\n } catch {\n // Ignore — localStorage may be unavailable\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// API client\n// ---------------------------------------------------------------------------\n\n/** Parse a JSON body and assert its TypeScript shape — server-side Zod is the source of truth. */\nasync function parseJsonAs<T>(response: Response): Promise<T> {\n return (await response.json()) as T;\n}\n\nexport class ApiClient implements WidgetClient {\n constructor(\n private readonly endpoint: string,\n private readonly projectName: string,\n private readonly auth: ApiClientAuth = {},\n ) {}\n\n async sendFeedback(payload: FeedbackPayload): Promise<FeedbackResponse> {\n // Only put `screenshotRegion` on the wire when a region was actually\n // captured — servers that predate the field would otherwise reject an\n // explicit `screenshotRegion: null` on every legacy capture.\n const { screenshotRegion, ...rest } = payload;\n const body: FeedbackPayload = screenshotRegion ? { ...rest, screenshotRegion } : rest;\n try {\n let response: Response;\n try {\n response = await resilientFetch(this.endpoint, {\n method: \"POST\",\n headers: await buildRequestHeaders(this.auth, true),\n body: JSON.stringify(body),\n });\n } catch (error) {\n throw networkErrorFromException(error, \"Failed to send feedback\");\n }\n\n if (!response.ok) {\n throw await errorFromResponse(response, \"Failed to send feedback\");\n }\n\n return parseJsonAs<FeedbackResponse>(response);\n } catch (error) {\n // Queue the wire shape (region stripped when absent) so a later\n // flushRetryQueue replays exactly what a fresh POST would send — but\n // only when a replay can succeed (see `isTransientFailure`).\n if (isTransientFailure(error)) queueForRetry(this.endpoint, body);\n throw error;\n }\n }\n\n async getFeedbacks(projectName: string, options?: GetFeedbacksOptions): Promise<FeedbackResponseList> {\n const params = feedbackQueryToSearchParams({ projectName, ...options });\n\n let response: Response;\n try {\n // GET carries no body — only attach headers when auth produced some, so\n // the no-auth wire shape stays byte-identical to the legacy client.\n const headers = await buildRequestHeaders(this.auth, false);\n response = await resilientFetch(`${this.endpoint}?${params.toString()}`, {\n method: \"GET\",\n cache: \"no-store\",\n ...(Object.keys(headers).length > 0 ? { headers } : {}),\n });\n } catch (error) {\n throw networkErrorFromException(error, \"Failed to fetch feedbacks\");\n }\n\n if (!response.ok) {\n throw await errorFromResponse(response, \"Failed to fetch feedbacks\");\n }\n\n return parseJsonAs<FeedbackResponseList>(response);\n }\n\n async resolveFeedback(id: string, resolved: boolean): Promise<FeedbackResponse> {\n let response: Response;\n try {\n response = await resilientFetch(this.endpoint, {\n method: \"PATCH\",\n headers: await buildRequestHeaders(this.auth, true),\n body: JSON.stringify({ id, projectName: this.projectName, status: resolved ? \"resolved\" : \"open\" }),\n });\n } catch (error) {\n throw networkErrorFromException(error, \"Failed to update feedback\");\n }\n\n if (!response.ok) {\n throw await errorFromResponse(response, \"Failed to update feedback\");\n }\n\n return parseJsonAs<FeedbackResponse>(response);\n }\n\n async deleteFeedback(id: string): Promise<void> {\n let response: Response;\n try {\n response = await resilientFetch(this.endpoint, {\n method: \"DELETE\",\n headers: await buildRequestHeaders(this.auth, true),\n body: JSON.stringify({ id, projectName: this.projectName }),\n });\n } catch (error) {\n throw networkErrorFromException(error, \"Failed to delete feedback\");\n }\n\n if (!response.ok) {\n throw await errorFromResponse(response, \"Failed to delete feedback\");\n }\n }\n\n async deleteAllFeedbacks(projectName: string): Promise<void> {\n let response: Response;\n try {\n response = await resilientFetch(this.endpoint, {\n method: \"DELETE\",\n headers: await buildRequestHeaders(this.auth, true),\n body: JSON.stringify({ projectName, deleteAll: true }),\n });\n } catch (error) {\n throw networkErrorFromException(error, \"Failed to delete all feedbacks\");\n }\n\n if (!response.ok) {\n throw await errorFromResponse(response, \"Failed to delete all feedbacks\");\n }\n }\n}\n","/**\n * Console buffer — capture the last N `console.{log,info,warn,error}` calls\n * so they ship with every feedback submission.\n *\n * Why a ring buffer:\n * - **bounded memory** even on chatty pages (1000s of logs/min during dev),\n * - **last-N is the relevant slice** for debugging — what was happening just\n * before the user noticed the bug, not the full session history.\n *\n * Why monkey-patching instead of `console.dir`/Performance Timeline:\n * - host code already uses plain `console.*` everywhere, and many libraries\n * only emit through console (no other observable),\n * - patching is reversible via `dispose()` so the widget never leaves state\n * behind on `destroy()`.\n */\n\nconst DEFAULT_MAX_ENTRIES = 50;\nconst MAX_MESSAGE_LENGTH = 500;\n\n/** Per-entry shape — sent to the server in the diagnostics payload. */\nexport interface ConsoleEntry {\n level: \"log\" | \"info\" | \"warn\" | \"error\";\n /** ISO 8601 timestamp captured at log time. */\n timestamp: string;\n /** Best-effort string representation of the console args. */\n message: string;\n}\n\nconst LEVELS: Array<ConsoleEntry[\"level\"]> = [\"log\", \"info\", \"warn\", \"error\"];\n\n/**\n * Best-effort stringification that never throws.\n *\n * - `Error` → `Error: message\\nstack` (capped to 500 chars overall).\n * - circular / huge objects → fall back to `Object#toString()` or `\"[Unserializable]\"`.\n * - all output is truncated to `MAX_MESSAGE_LENGTH` so a single 5MB log\n * doesn't blow up the buffer (Slack-style 500 chars per row is plenty).\n */\nfunction serializeArg(arg: unknown): string {\n if (arg === null) return \"null\";\n if (arg === undefined) return \"undefined\";\n if (typeof arg === \"string\") return arg;\n if (typeof arg === \"number\" || typeof arg === \"boolean\" || typeof arg === \"bigint\") {\n return String(arg);\n }\n if (arg instanceof Error) {\n return `${arg.name}: ${arg.message}${arg.stack ? `\\n${arg.stack}` : \"\"}`;\n }\n try {\n // Replacer drops cycles + functions; functions stringify-default to\n // undefined and disappear from the output, which is the right call (we\n // don't want random function bodies in a feedback payload).\n const seen = new WeakSet<object>();\n return JSON.stringify(arg, (_key, value: unknown) => {\n if (typeof value === \"function\") return \"[Function]\";\n if (typeof value === \"symbol\") return value.toString();\n if (typeof value === \"object\" && value !== null) {\n if (seen.has(value as object)) return \"[Circular]\";\n seen.add(value as object);\n }\n return value;\n });\n } catch {\n try {\n return String(arg);\n } catch {\n return \"[Unserializable]\";\n }\n }\n}\n\nfunction formatArgs(args: readonly unknown[]): string {\n let out = \"\";\n for (let i = 0; i < args.length; i++) {\n if (i > 0) out += \" \";\n out += serializeArg(args[i]);\n if (out.length >= MAX_MESSAGE_LENGTH) break;\n }\n if (out.length > MAX_MESSAGE_LENGTH) {\n out = `${out.slice(0, MAX_MESSAGE_LENGTH - 1)}…`;\n }\n return out;\n}\n\n/**\n * Bounded ring buffer of console messages.\n *\n * Construction installs the wrappers immediately. `dispose()` restores the\n * originals exactly once (calling it twice is a no-op). Designed to be safe\n * against re-entrant or interleaved instances — each wrapper closes over the\n * original method, not over any global, so multiple buffers can coexist\n * (each captures its own copy of the args).\n */\nexport class ConsoleBuffer {\n private readonly maxEntries: number;\n private readonly entries: ConsoleEntry[] = [];\n private originals = new Map<ConsoleEntry[\"level\"], (...args: unknown[]) => void>();\n /** The wrappers we installed — `dispose()` only restores a level whose wrapper is still in place. */\n private wrappers = new Map<ConsoleEntry[\"level\"], (...args: unknown[]) => void>();\n private disposed = false;\n\n constructor(maxEntries: number = DEFAULT_MAX_ENTRIES) {\n // Guard against pathological values — 0 disables silently, negative\n // numbers fall through to the default, and absurdly large numbers are\n // capped so a misuse can't OOM the page.\n this.maxEntries = Math.min(Math.max(Math.floor(maxEntries), 0), 1000);\n\n if (typeof console === \"undefined\") return;\n\n for (const level of LEVELS) {\n const original = (console as unknown as Record<string, ((...args: unknown[]) => void) | undefined>)[level];\n if (typeof original !== \"function\") continue;\n this.originals.set(level, original);\n\n const buffer = this;\n const wrapped = function (this: unknown, ...args: unknown[]): void {\n try {\n buffer.push(level, args);\n } catch {\n // Capturing must never break the host's console — swallow any\n // unexpected error from serialization so the original call\n // (right below) always still runs.\n }\n original.apply(this ?? console, args);\n };\n // Preserve the function name so devtools still show \"console.log\"\n // (browsers display the wrapper's name in stack traces).\n try {\n Object.defineProperty(wrapped, \"name\", { value: level });\n } catch {\n // Older engines reject defineProperty on function name — best-effort only.\n }\n this.wrappers.set(level, wrapped);\n (console as unknown as Record<string, unknown>)[level] = wrapped;\n }\n }\n\n private push(level: ConsoleEntry[\"level\"], args: readonly unknown[]): void {\n if (this.maxEntries === 0) return;\n if (this.entries.length >= this.maxEntries) {\n this.entries.shift();\n }\n this.entries.push({\n level,\n timestamp: new Date().toISOString(),\n message: formatArgs(args),\n });\n }\n\n /** Snapshot of captured entries — returns a new array each call. */\n getEntries(): ConsoleEntry[] {\n return this.entries.slice();\n }\n\n /**\n * Restore the original console methods. Idempotent.\n *\n * A level is restored only if our wrapper is still installed on it — when\n * another library wrapped `console.error` on top of us after init, writing\n * the original back would silently remove its wrapper. Ours then stays in\n * the chain but keeps forwarding to the original, so nothing is lost.\n */\n dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n if (typeof console === \"undefined\") return;\n const target = console as unknown as Record<string, unknown>;\n for (const [level, original] of this.originals) {\n if (target[level] !== this.wrappers.get(level)) continue;\n try {\n target[level] = original;\n } catch {\n // Console may be frozen in exotic environments — leave the wrapper\n // in place; it still proxies to the original via closure.\n }\n }\n this.originals.clear();\n this.wrappers.clear();\n }\n}\n","/**\n * Network buffer — capture the last N failed `fetch` / `XMLHttpRequest`\n * calls (HTTP >= 400 or network error) so they ship with each feedback.\n *\n * Captures only failures because:\n * - successful requests are usually irrelevant for the \"this thing is\n * broken\" workflow,\n * - keeping the volume tiny means we can ship the full payload to the\n * server without bloating Postgres.\n *\n * Both wrappers preserve the original semantics — return values, throws,\n * AbortController behaviour, etc. The only side effect is recording a\n * `NetworkEntry` on failure.\n */\n\nconst DEFAULT_MAX_ENTRIES = 20;\nconst MAX_URL_LENGTH = 2000;\n\n/** Per-entry shape — sent to the server in the diagnostics payload. */\nexport interface NetworkEntry {\n url: string;\n method: string;\n /** HTTP status or 0 when the request never reached the server (network error / CORS / abort). */\n status: number;\n /** End-to-end duration in ms, rounded to the nearest integer. */\n durationMs: number;\n /** ISO 8601 timestamp at the moment the request was initiated. */\n timestamp: string;\n}\n\nfunction truncateUrl(url: string): string {\n if (url.length <= MAX_URL_LENGTH) return url;\n return `${url.slice(0, MAX_URL_LENGTH - 1)}…`;\n}\n\nfunction urlString(input: unknown): string {\n if (typeof input === \"string\") return input;\n if (input instanceof URL) return input.href;\n // `Request` instances expose `.url`\n if (typeof input === \"object\" && input !== null && \"url\" in (input as { url?: unknown })) {\n const candidate = (input as { url?: unknown }).url;\n if (typeof candidate === \"string\") return candidate;\n }\n try {\n return String(input);\n } catch {\n return \"(unknown)\";\n }\n}\n\n/**\n * Bounded ring buffer of failed network requests.\n *\n * Construction monkey-patches `globalThis.fetch` and `XMLHttpRequest` and\n * stores the originals for `dispose()`. Wrappers are designed so that\n * multiple instances can coexist (each captures independently into its own\n * buffer, and the last one disposed restores the chain correctly via the\n * stored originals).\n */\nexport class NetworkBuffer {\n private readonly maxEntries: number;\n private readonly entries: NetworkEntry[] = [];\n private originalFetch: typeof fetch | null = null;\n private originalXhrOpen: typeof XMLHttpRequest.prototype.open | null = null;\n private originalXhrSend: typeof XMLHttpRequest.prototype.send | null = null;\n /** The wrappers we installed — `dispose()` only restores when they are still in place. */\n private wrappedFetch: typeof fetch | null = null;\n private wrappedXhrOpen: typeof XMLHttpRequest.prototype.open | null = null;\n private wrappedXhrSend: typeof XMLHttpRequest.prototype.send | null = null;\n private disposed = false;\n\n constructor(maxEntries: number = DEFAULT_MAX_ENTRIES) {\n this.maxEntries = Math.min(Math.max(Math.floor(maxEntries), 0), 500);\n this.installFetch();\n this.installXhr();\n }\n\n private push(entry: NetworkEntry): void {\n if (this.maxEntries === 0) return;\n if (this.entries.length >= this.maxEntries) {\n this.entries.shift();\n }\n this.entries.push(entry);\n }\n\n private installFetch(): void {\n if (typeof globalThis.fetch !== \"function\") return;\n const original = globalThis.fetch;\n this.originalFetch = original;\n\n const wrapped: typeof fetch = async (input, init) => {\n const startedAt = new Date();\n const t0 = typeof performance !== \"undefined\" ? performance.now() : Date.now();\n const url = truncateUrl(urlString(input));\n const method = (init?.method ?? (input instanceof Request ? input.method : \"GET\")).toUpperCase();\n\n try {\n const response = await original(input, init);\n if (!response.ok) {\n const t1 = typeof performance !== \"undefined\" ? performance.now() : Date.now();\n this.push({\n url,\n method,\n status: response.status,\n durationMs: Math.round(t1 - t0),\n timestamp: startedAt.toISOString(),\n });\n }\n return response;\n } catch (err) {\n const t1 = typeof performance !== \"undefined\" ? performance.now() : Date.now();\n this.push({\n url,\n method,\n status: 0,\n durationMs: Math.round(t1 - t0),\n timestamp: startedAt.toISOString(),\n });\n throw err;\n }\n };\n\n this.wrappedFetch = wrapped;\n globalThis.fetch = wrapped;\n }\n\n private installXhr(): void {\n if (typeof XMLHttpRequest === \"undefined\") return;\n const proto = XMLHttpRequest.prototype;\n const originalOpen = proto.open;\n const originalSend = proto.send;\n this.originalXhrOpen = originalOpen;\n this.originalXhrSend = originalSend;\n const buffer = this;\n\n // Store the open metadata on the XHR instance via a side-channel WeakMap\n // so each request is fully isolated even with concurrent opens.\n const meta = new WeakMap<XMLHttpRequest, { method: string; url: string; startedAt: Date; t0: number }>();\n\n const wrappedOpen = function (this: XMLHttpRequest, method: string, url: string | URL, ...rest: unknown[]) {\n try {\n meta.set(this, {\n method: method.toUpperCase(),\n url: truncateUrl(urlString(url)),\n startedAt: new Date(),\n t0: typeof performance !== \"undefined\" ? performance.now() : Date.now(),\n });\n } catch {\n // Ignore — metadata is best-effort, the underlying open() still runs.\n }\n // XHR.open has two overloaded signatures (3-arg sync, 5-arg async with\n // user/password). Cast to a loose function shape to forward every arg\n // without re-enumerating the overloads here.\n const looseOpen = originalOpen as unknown as (this: XMLHttpRequest, ...a: unknown[]) => void;\n return looseOpen.call(this, method, url, ...rest);\n } as typeof proto.open;\n\n const wrappedSend = function (this: XMLHttpRequest, body?: Document | XMLHttpRequestBodyInit | null) {\n const info = meta.get(this);\n if (info) {\n // `loadend` fires for both success and failure — we just inspect the\n // status to decide whether to log. Use `once: true` so a re-sent XHR\n // doesn't accumulate listeners.\n const onEnd = () => {\n try {\n const t1 = typeof performance !== \"undefined\" ? performance.now() : Date.now();\n const status = this.status; // 0 on network error / abort\n if (status === 0 || status >= 400) {\n buffer.push({\n url: info.url,\n method: info.method,\n status,\n durationMs: Math.round(t1 - info.t0),\n timestamp: info.startedAt.toISOString(),\n });\n }\n } catch {\n // Listener must not throw — would surface as an \"Uncaught\" in\n // the host's console and pollute their logs.\n }\n };\n try {\n this.addEventListener(\"loadend\", onEnd, { once: true });\n } catch {\n // Older engines without options object — fall back to plain listener.\n try {\n this.addEventListener(\"loadend\", onEnd);\n } catch {\n // No-op\n }\n }\n }\n return originalSend.call(this, body ?? null);\n } as typeof proto.send;\n\n this.wrappedXhrOpen = wrappedOpen;\n this.wrappedXhrSend = wrappedSend;\n proto.open = wrappedOpen;\n proto.send = wrappedSend;\n }\n\n /** Snapshot of captured entries — returns a new array each call. */\n getEntries(): NetworkEntry[] {\n return this.entries.slice();\n }\n\n /**\n * Restore the original fetch + XHR methods. Idempotent.\n *\n * Each global is restored only if our wrapper is still the one installed —\n * if another library (an error tracker, a RUM agent) wrapped on top of us\n * after init, writing the original back would silently rip its wrapper\n * out. Our patch then stays in the chain but is inert: it still forwards to\n * the original, and a disposed buffer merely records entries nobody reads.\n * Same rule the launcher applies to the History API.\n */\n dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n\n if (this.originalFetch && globalThis.fetch === this.wrappedFetch) {\n try {\n globalThis.fetch = this.originalFetch;\n } catch {\n // Best-effort\n }\n }\n if (typeof XMLHttpRequest !== \"undefined\") {\n try {\n const proto = XMLHttpRequest.prototype;\n if (this.originalXhrOpen && proto.open === this.wrappedXhrOpen) proto.open = this.originalXhrOpen;\n if (this.originalXhrSend && proto.send === this.wrappedXhrSend) proto.send = this.originalXhrSend;\n } catch {\n // Best-effort\n }\n }\n }\n}\n","import type { FeedbackResponse, SitepingUnsubscribe } from \"@siteping/core\";\nimport type { AnnotationComplete } from \"./annotator.js\";\n\n/** Listener signature for a single key of an `EventBus` event map. */\nexport type EventListener<E extends Record<keyof E, unknown[]>, K extends keyof E> = (...args: E[K]) => void;\n\n/**\n * Lightweight typed `EventEmitter` — zero dependencies.\n *\n * The generic constraint guarantees each event maps to a tuple of argument\n * types, so subscribers and emitters share the exact same shape.\n */\nexport class EventBus<E extends Record<keyof E, unknown[]>> {\n private readonly listeners = new Map<keyof E, Set<EventListener<E, keyof E>>>();\n\n on<K extends keyof E>(event: K, listener: EventListener<E, K>): SitepingUnsubscribe {\n let set = this.listeners.get(event);\n if (!set) {\n set = new Set();\n this.listeners.set(event, set);\n }\n set.add(listener as EventListener<E, keyof E>);\n\n return () => {\n set?.delete(listener as EventListener<E, keyof E>);\n };\n }\n\n off<K extends keyof E>(event: K, listener: EventListener<E, K>): void {\n this.listeners.get(event)?.delete(listener as EventListener<E, keyof E>);\n }\n\n emit<K extends keyof E>(event: K, ...args: E[K]): void {\n const set = this.listeners.get(event);\n if (!set) return;\n for (const fn of set) {\n try {\n (fn as (...a: E[K]) => void)(...args);\n } catch (err) {\n // Isolate listener errors — one bad listener must not kill others\n console.error(`[siteping] Error in event listener for \"${String(event)}\":`, err);\n }\n }\n }\n\n removeAll(): void {\n this.listeners.clear();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Widget event types\n// ---------------------------------------------------------------------------\n\n/** Full internal event map — broader than the public surface exposed to hosts. */\nexport interface WidgetEvents {\n open: [];\n close: [];\n \"feedback:sent\": [FeedbackResponse];\n \"feedback:deleted\": [FeedbackResponse[\"id\"]];\n \"feedback:all-deleted\": [];\n \"feedback:error\": [Error];\n /** Emitted whenever the marker set changes — payload is the open (unresolved) count for the current page. */\n \"markers:changed\": [number];\n \"annotation:start\": [];\n \"annotation:end\": [];\n \"annotation:complete\": [AnnotationComplete];\n /**\n * Internal-only: a feedback submission was aborted by a benign user action\n * (e.g. cancelling the identity prompt). Distinct from `feedback:error` so a\n * cancellation does not surface through the host's `onError` callback. Not\n * part of `SitepingPublicEvents` — never exposed to consumers.\n */\n \"submission:cancelled\": [];\n \"annotations:toggle\": [boolean];\n \"panel:toggle\": [boolean];\n}\n\n// NOTE: the public event surface is `SitepingPublicEvents` from\n// `@siteping/core`. The launcher bridges internal events onto the public bus\n// through a mapped object keyed by `keyof SitepingPublicEvents`, so adding a\n// public event without bridging it is a compile error there — no alias or\n// duplicate map is needed on this side.\n","import type { SitepingConfig } from \"@siteping/core\";\nimport { parseSvg, setText } from \"./dom-utils.js\";\nimport type { EventBus, WidgetEvents } from \"./events.js\";\nimport { type TFunction, type Translations, tWithParams } from \"./i18n/index.js\";\nimport { ICON_CLOSE, ICON_EDIT, ICON_EYE, ICON_EYE_OFF, ICON_LIST, ICON_SITEPING } from \"./icons.js\";\n\n/** Closed set of radial menu item ids — keeps the label lookup exhaustive. */\ntype RadialItemId = \"chat\" | \"annotate\" | \"toggle-annotations\";\n\ninterface RadialItem {\n id: RadialItemId;\n icon: string;\n iconAlt?: string;\n}\n\nconst ITEM_GAP = 54;\n\n// Stable mapping between radial item ids and their translation keys. The\n// label is fully derived from this map via `t()`, so the constructor and\n// `applyLabels()` share one source of truth for which node gets which string.\nconst ITEM_LABEL_KEYS: Record<RadialItemId, keyof Translations> = {\n chat: \"fab.messages\",\n annotate: \"fab.annotate\",\n \"toggle-annotations\": \"fab.annotations\",\n};\n\n/**\n * Floating Action Button with radial menu and notification badge.\n *\n * Glassmorphism: gradient background, glow shadow, glass radial items.\n * Badge shows unresolved feedback count.\n */\nexport class Fab {\n private root: HTMLElement;\n private fab: HTMLButtonElement;\n private radialContainer: HTMLElement;\n private badgeEl: HTMLElement | null = null;\n private isOpen = false;\n private annotationsVisible = true;\n private items: RadialItem[];\n\n constructor(\n shadowRoot: ShadowRoot,\n config: SitepingConfig,\n private readonly bus: EventBus<WidgetEvents>,\n private readonly t: TFunction,\n ) {\n const position = config.position ?? \"bottom-right\";\n const isRight = position === \"bottom-right\";\n\n // Vertical stack above the FAB. Icons:\n // - list → opens the feedback sidebar (panel of feedbacks).\n // - edit → creates a new annotation (the action).\n // - eye → toggles marker visibility on the page (state).\n // The marker-visibility toggle is opt-out via `config.showAnnotationsToggle`:\n // default `true` preserves historical behavior, `false` removes the item from\n // the menu entirely (no DOM, no keyboard slot, no click handler).\n this.items = [\n { id: \"chat\", icon: ICON_LIST },\n { id: \"annotate\", icon: ICON_EDIT },\n ];\n if (config.showAnnotationsToggle !== false) {\n this.items.push({ id: \"toggle-annotations\", icon: ICON_EYE, iconAlt: ICON_EYE_OFF });\n }\n\n // FAB button — needs position:relative for badge positioning\n this.fab = document.createElement(\"button\");\n this.fab.className = `sp-fab sp-fab--${position} sp-anim-fab-in`;\n this.fab.style.position = \"fixed\"; // ensure fixed even with relative children\n this.fab.appendChild(parseSvg(ICON_SITEPING));\n this.fab.setAttribute(\"aria-expanded\", \"false\");\n this.fab.addEventListener(\"click\", () => this.toggle());\n\n // Radial container\n this.radialContainer = document.createElement(\"div\");\n this.radialContainer.className = `sp-radial sp-radial--${position}`;\n this.radialContainer.setAttribute(\"role\", \"menu\");\n\n for (let i = 0; i < this.items.length; i++) {\n const item = this.items[i];\n if (!item) continue;\n const btn = document.createElement(\"button\");\n btn.className = \"sp-radial-item\";\n btn.style.setProperty(\"--sp-i\", String(i));\n btn.appendChild(parseSvg(item.icon));\n btn.setAttribute(\"role\", \"menuitem\");\n btn.dataset.itemId = item.id;\n\n btn.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n this.handleItemClick(item.id);\n });\n\n const label = document.createElement(\"span\");\n label.className = \"sp-radial-label\";\n label.style.cssText = isRight\n ? \"position:absolute; right:54px; top:50%; transform:translateY(-50%); white-space:nowrap;\"\n : \"position:absolute; left:54px; top:50%; transform:translateY(-50%); white-space:nowrap;\";\n btn.appendChild(label);\n\n this.radialContainer.appendChild(btn);\n }\n\n this.root = document.createElement(\"div\");\n this.root.appendChild(this.radialContainer);\n this.root.appendChild(this.fab);\n shadowRoot.appendChild(this.root);\n\n // Bind every `t()`-derived string into the freshly-built DOM. Kept as a\n // single pass so the constructor and `refreshLabels()` never drift.\n this.applyLabels();\n\n // Close radial menu on click outside.\n const host = shadowRoot.host;\n this.onDocumentClick = (e: MouseEvent) => {\n if (this.isOpen && !e.composedPath().includes(host)) {\n this.close();\n }\n };\n document.addEventListener(\"click\", this.onDocumentClick);\n\n // Escape on FAB or menu container closes the menu\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === \"Escape\" && this.isOpen) {\n e.stopPropagation();\n this.close();\n }\n };\n this.fab.addEventListener(\"keydown\", handleEscape);\n this.radialContainer.addEventListener(\"keydown\", handleEscape);\n\n // Arrow key navigation within the radial menu\n this.radialContainer.addEventListener(\"keydown\", (e) => {\n const items = Array.from(this.radialContainer.querySelectorAll<HTMLButtonElement>(\".sp-radial-item\"));\n if (items.length === 0 || !this.isOpen) return;\n const activeEl = (shadowRoot.activeElement ?? document.activeElement) as HTMLElement;\n const currentIndex = items.indexOf(activeEl as HTMLButtonElement);\n\n switch (e.key) {\n case \"ArrowUp\": {\n e.preventDefault();\n const nextIndex = currentIndex <= 0 ? items.length - 1 : currentIndex - 1;\n items[nextIndex]?.focus();\n break;\n }\n case \"ArrowDown\": {\n e.preventDefault();\n const nextIndex = currentIndex >= items.length - 1 ? 0 : currentIndex + 1;\n items[nextIndex]?.focus();\n break;\n }\n case \"Home\": {\n e.preventDefault();\n items[0]?.focus();\n break;\n }\n case \"End\": {\n e.preventDefault();\n items[items.length - 1]?.focus();\n break;\n }\n }\n });\n }\n\n private onDocumentClick: (e: MouseEvent) => void;\n\n /**\n * Re-read every `t(...)`-derived label and aria-label from the active\n * translation function. Idempotent — call after the locale dictionary has\n * finished loading so the FAB labels swap from the English fallback to the\n * configured language.\n */\n refreshLabels(): void {\n this.applyLabels();\n }\n\n /**\n * Walk the already-built DOM and bind every translation-derived string —\n * the FAB `aria-label`, each radial item's `aria-label`, and each\n * `.sp-radial-label` `textContent`. The single source of truth for which\n * node gets which `t()` string, shared by the constructor and\n * `refreshLabels()` so the two can never drift.\n */\n private applyLabels(): void {\n this.fab.setAttribute(\"aria-label\", this.t(\"fab.aria\"));\n\n const buttons = this.radialContainer.querySelectorAll<HTMLButtonElement>(\".sp-radial-item\");\n for (const btn of buttons) {\n const id = btn.dataset.itemId as RadialItemId | undefined;\n if (!id) continue;\n const key = ITEM_LABEL_KEYS[id];\n if (!key) continue;\n const label = this.t(key);\n btn.setAttribute(\"aria-label\", label);\n const labelSpan = btn.querySelector<HTMLSpanElement>(\".sp-radial-label\");\n if (labelSpan) setText(labelSpan, label);\n }\n }\n\n /** Update the badge count. Pass 0 to hide. */\n updateBadge(count: number): void {\n if (count <= 0) {\n this.badgeEl?.remove();\n this.badgeEl = null;\n return;\n }\n\n if (!this.badgeEl) {\n this.badgeEl = document.createElement(\"span\");\n this.badgeEl.className = \"sp-fab-badge\";\n this.badgeEl.setAttribute(\"role\", \"status\");\n this.badgeEl.setAttribute(\"aria-live\", \"polite\");\n this.fab.appendChild(this.badgeEl);\n }\n\n const displayText = count > 99 ? \"99+\" : String(count);\n setText(this.badgeEl, displayText);\n this.badgeEl.setAttribute(\"aria-label\", tWithParams(this.t, \"fab.badge\", { count }));\n }\n\n private toggle(): void {\n this.isOpen ? this.close() : this.open();\n }\n\n private open(): void {\n this.isOpen = true;\n this.setFabIcon(ICON_CLOSE);\n this.fab.setAttribute(\"aria-expanded\", \"true\");\n\n const buttons = this.radialContainer.querySelectorAll<HTMLButtonElement>(\".sp-radial-item\");\n buttons.forEach((btn, i) => {\n // Stack vertically above the FAB with initial offset + gap\n const y = -(16 + ITEM_GAP * (i + 1));\n btn.style.transform = `translate(0px, ${y}px) scale(1)`;\n btn.classList.add(\"sp-radial-item--open\");\n });\n\n // Focus the first menu item after animation\n requestAnimationFrame(() => {\n const firstItem = this.radialContainer.querySelector<HTMLButtonElement>(\".sp-radial-item\");\n firstItem?.focus();\n });\n }\n\n private close(): void {\n this.isOpen = false;\n this.setFabIcon(ICON_SITEPING);\n this.fab.setAttribute(\"aria-expanded\", \"false\");\n\n const buttons = this.radialContainer.querySelectorAll<HTMLButtonElement>(\".sp-radial-item\");\n buttons.forEach((btn) => {\n btn.style.transform = \"translate(0, 0) scale(0.8)\";\n btn.classList.remove(\"sp-radial-item--open\");\n });\n\n // Return focus to FAB\n this.fab.focus();\n }\n\n private setFabIcon(svgStr: string): void {\n const badge = this.badgeEl;\n this.fab.replaceChildren(parseSvg(svgStr));\n // Re-append badge after icon swap\n if (badge) this.fab.appendChild(badge);\n }\n\n private handleItemClick(id: RadialItemId): void {\n this.close();\n\n switch (id) {\n case \"chat\":\n this.bus.emit(\"panel:toggle\", true);\n break;\n case \"annotate\": {\n // close() above re-focused the FAB, so the annotator resolves its\n // keyboard target via the focus tracker's last page element — but\n // putting keyboard users back on the FAB when the session ends is on us.\n const unsubscribe = this.bus.on(\"annotation:end\", () => {\n unsubscribe();\n this.fab.focus();\n });\n this.bus.emit(\"annotation:start\");\n break;\n }\n case \"toggle-annotations\": {\n this.annotationsVisible = !this.annotationsVisible;\n this.bus.emit(\"annotations:toggle\", this.annotationsVisible);\n // Replace ONLY the icon SVG, not every child. The button also carries\n // the `<span class=\"sp-radial-label\">` hover label — `replaceChildren`\n // wiped it on the first click, killing the tooltip until reload.\n const btn = this.radialContainer.querySelector('[data-item-id=\"toggle-annotations\"]');\n const oldSvg = btn?.querySelector(\"svg\");\n if (oldSvg) {\n const newSvg = parseSvg(this.annotationsVisible ? ICON_EYE : ICON_EYE_OFF);\n oldSvg.replaceWith(newSvg);\n }\n break;\n }\n }\n }\n\n destroy(): void {\n document.removeEventListener(\"click\", this.onDocumentClick);\n this.root.remove();\n }\n}\n","import { hasOwn, isValidEmail, type SitepingIdentity } from \"@siteping/core\";\n\nconst STORAGE_KEY = \"siteping_identity\";\n\n/**\n * Author identity persisted by the widget — alias of core's\n * `SitepingIdentity` (one concept, one shape; the alias keeps the widget's\n * historical export name working).\n */\nexport type Identity = SitepingIdentity;\n\n/**\n * Type guard — narrows an unknown value to `Identity` only when the name is a\n * non-empty string and the email is one the server accepts. A stored identity\n * that fails the shared email pattern (persisted by an older, laxer modal) is\n * treated as absent so the modal asks again instead of every submission\n * failing with a 400.\n */\nfunction isIdentity(value: unknown): value is Identity {\n if (!hasOwn(value, \"name\") || !hasOwn(value, \"email\")) return false;\n const { name, email } = value;\n return typeof name === \"string\" && typeof email === \"string\" && name.length > 0 && isValidEmail(email);\n}\n\nexport function getIdentity(): Identity | null {\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) return null;\n const parsed: unknown = JSON.parse(raw);\n return isIdentity(parsed) ? parsed : null;\n } catch {\n return null;\n }\n}\n\nexport function saveIdentity(identity: Identity): void {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(identity));\n } catch {\n // Quota exceeded or localStorage disabled — identity works for this session only\n }\n}\n","/**\n * Lightweight fuzzy text matching for DOM re-anchoring.\n * Zero dependencies — bundled into the widget.\n *\n * Approximate containment uses Sellers' algorithm (1980): a single O(n·m)\n * DP pass over the haystack whose first row is initialized to 0, yielding\n * the minimum edit distance between the needle and ANY substring. This\n * replaces a sliding fixed-length window (O(n·m²)) with identical-or-better\n * scores — a window match is one of the substrings Sellers considers.\n */\n\n/** Below this needle length, approximate substring search over a LONG\n * haystack is statistically meaningless (a 4-char needle \"matches\" almost\n * anything within 1–2 edits somewhere in 500 chars) and was the worst-case\n * cost driver. Exact containment still applies at any length, and short\n * haystacks (≤ SHORT_NEEDLE_HAYSTACK_CAP) keep approximate matching — a\n * near-miss in a short label (\"panier\" vs \"paniers\") is meaningful. */\nexport const MIN_FUZZY_NEEDLE_LENGTH = 8;\n\n/** See MIN_FUZZY_NEEDLE_LENGTH. */\nconst SHORT_NEEDLE_HAYSTACK_CAP = 64;\n\n/** Max haystack length considered for approximate matching. */\nconst HAYSTACK_CAP = 500;\n\n/**\n * Normalize text for comparison: Unicode NFC + collapse whitespace runs to a\n * single space + trim. Absorbs SSR/CSR hydration drift, prettified vs\n * minified markup, and re-indentation (formatting whitespace lives inside\n * `textContent` of nested elements). Applied at comparison time on both\n * sides — already-stored snippets stay valid. Deliberately NOT case-folding:\n * a case change is a real signal (CSS text-transform never affects\n * textContent, so case differences come from actual content edits).\n */\nexport function normalizeText(s: string): string {\n return s.normalize(\"NFC\").replace(/\\s+/g, \" \").trim();\n}\n\n/**\n * Whitespace-only collapse — the cheap subset of `normalizeText` for the scan\n * prefilter, which runs on every same-tag candidate. NFC is a table-driven\n * full-Unicode pass and is deliberately skipped there: the prefilter only\n * RANKS, and mixed composition forms cost at worst a slight rank penalty on\n * accented text (full scoring of survivors re-normalizes both sides).\n */\nexport function collapseWhitespace(s: string): string {\n return s.replace(/\\s+/g, \" \").trim();\n}\n\n/**\n * Levenshtein edit distance.\n * O(n*m) time, O(min(n,m)) space.\n */\nexport function editDistance(a: string, b: string): number {\n if (a === b) return 0;\n if (a.length === 0) return b.length;\n if (b.length === 0) return a.length;\n\n // Ensure `a` is the shorter string for space optimization\n if (a.length > b.length) {\n const t = a;\n a = b;\n b = t;\n }\n\n const aLen = a.length;\n const bLen = b.length;\n let prev = new Array<number>(aLen + 1);\n for (let k = 0; k <= aLen; k++) prev[k] = k;\n let curr = new Array<number>(aLen + 1);\n\n for (let j = 1; j <= bLen; j++) {\n curr[0] = j;\n for (let i = 1; i <= aLen; i++) {\n // Indices are provably in bounds (loop bounds; arrays sized aLen+1) —\n // plain casts instead of ?? fallbacks that could never fire.\n const prevDiag = prev[i - 1] as number;\n curr[i] = a[i - 1] === b[j - 1] ? prevDiag : 1 + Math.min(prevDiag, prev[i] as number, curr[i - 1] as number);\n }\n const tmp = prev;\n prev = curr;\n curr = tmp;\n }\n\n return prev[aLen] as number; // aLen is within bounds — prev has aLen+1 entries\n}\n\n/**\n * Normalized similarity score (0–1, where 1 = identical).\n */\nexport function similarity(a: string, b: string): number {\n if (a === b) return 1;\n const maxLen = Math.max(a.length, b.length);\n if (maxLen === 0) return 1;\n return 1 - editDistance(a, b) / maxLen;\n}\n\n/**\n * Sellers 1980 — minimum edit distance between `needle` and any substring of\n * `haystack`. Row 0 of the DP is zero for every haystack position (a match\n * may start anywhere); the answer is the running minimum of the last row.\n * Distance is bounded by needle.length (deleting the whole needle), so the\n * needle-normalized score 1 - dist/needle.length always lands in [0, 1].\n */\nfunction sellersDistance(haystack: string, needle: string): number {\n const n = needle.length;\n let prev = new Int32Array(n + 1);\n let curr = new Int32Array(n + 1);\n for (let i = 0; i <= n; i++) prev[i] = i;\n let best = n;\n\n for (let j = 1; j <= haystack.length; j++) {\n curr[0] = 0;\n const hc = haystack.charCodeAt(j - 1);\n for (let i = 1; i <= n; i++) {\n // Indices provably in bounds — casts, not ?? arms that can never fire.\n const sub = (prev[i - 1] as number) + (needle.charCodeAt(i - 1) === hc ? 0 : 1);\n const del = (prev[i] as number) + 1;\n const ins = (curr[i - 1] as number) + 1;\n curr[i] = Math.min(sub, del, ins);\n }\n const last = curr[n] as number;\n if (last < best) best = last;\n const tmp = prev;\n prev = curr;\n curr = tmp;\n }\n\n return best;\n}\n\n/**\n * Fuzzy substring search — checks if `needle` approximately exists in `haystack`.\n * Returns the best needle-normalized similarity found, or 0 if below `minScore`.\n *\n * Pipeline (cheapest first): exact containment → direct comparison when the\n * needle is longer than the haystack → Sellers approximate substring search.\n * Short needles never enter approximate search over long haystacks (see\n * MIN_FUZZY_NEEDLE_LENGTH).\n *\n * Callers are expected to pass `normalizeText`-processed strings; this\n * function compares verbatim.\n */\nexport function fuzzyIncludes(haystack: string, needle: string, minScore = 0.6): number {\n if (!needle || !haystack) return 0;\n if (haystack.includes(needle)) return 1;\n\n const capped = haystack.length > HAYSTACK_CAP ? haystack.slice(0, HAYSTACK_CAP) : haystack;\n\n // Needle longer than haystack — direct comparison (no substring to find)\n if (needle.length > capped.length) {\n const score = similarity(capped, needle);\n return score >= minScore ? score : 0;\n }\n\n if (needle.length < MIN_FUZZY_NEEDLE_LENGTH && capped.length > SHORT_NEEDLE_HAYSTACK_CAP) {\n return 0;\n }\n\n const score = 1 - sellersDistance(capped, needle) / needle.length;\n return score >= minScore ? score : 0;\n}\n\n/**\n * Character-bigram multiset of a string, keyed by packed char-code pairs.\n * Built once per resolution for the stored snippet, then streamed against\n * every scan candidate via `diceAgainst` — no per-candidate copy.\n */\nexport function bigramCounts(s: string): Map<number, number> {\n const counts = new Map<number, number>();\n for (let i = 0; i < s.length - 1; i++) {\n const key = (s.charCodeAt(i) << 16) | s.charCodeAt(i + 1);\n counts.set(key, (counts.get(key) ?? 0) + 1);\n }\n return counts;\n}\n\n/**\n * Sørensen–Dice coefficient between a precomputed bigram multiset and a raw\n * string, in O(|text|). Multiset semantics (bigram occurrences are consumed,\n * not just membership-tested) — repeated-bigram strings like \"aaaa\" would\n * otherwise score against sets they barely overlap.\n *\n * Used exclusively as a RANKING signal for scan prefiltering (top-K keep),\n * never as an eliminating threshold — so an imperfect correlation with edit\n * distance can demote a candidate but never drop a true match outright.\n */\nexport function diceAgainst(needleCounts: Map<number, number>, needleBigramTotal: number, text: string): number {\n const textBigramTotal = text.length - 1;\n if (needleBigramTotal <= 0 || textBigramTotal <= 0) return 0;\n\n let matches = 0;\n const consumed = new Map<number, number>();\n for (let i = 0; i < text.length - 1; i++) {\n const key = (text.charCodeAt(i) << 16) | text.charCodeAt(i + 1);\n const available = needleCounts.get(key);\n if (available === undefined) continue;\n const used = consumed.get(key) ?? 0;\n if (used < available) {\n consumed.set(key, used + 1);\n matches++;\n }\n }\n\n return (2 * matches) / (needleBigramTotal + textBigramTotal);\n}\n\n/**\n * Word-pair shingle multiset (\"quick brown\", \"brown fox\", …) of a\n * whitespace-normalized string. Character bigrams are order-blind: on pages\n * where many elements share a vocabulary (card grids, list views), every\n * candidate looks alike to them, while word ORDER still discriminates —\n * a true match preserves most word pairs, shared vocabulary in a different\n * order preserves almost none. Scripts without spaces produce no pairs and\n * callers fall back to character bigrams alone.\n */\nexport function wordPairCounts(s: string): Map<string, number> {\n const counts = new Map<string, number>();\n const words = s.split(\" \");\n for (let i = 0; i < words.length - 1; i++) {\n const key = `${words[i]} ${words[i + 1]}`;\n counts.set(key, (counts.get(key) ?? 0) + 1);\n }\n return counts;\n}\n\n/**\n * Sørensen–Dice over word-pair shingles, multiset semantics, O(|text|).\n * Same ranking-only contract as `diceAgainst`.\n */\nexport function wordPairDiceAgainst(needlePairs: Map<string, number>, needlePairTotal: number, text: string): number {\n if (needlePairTotal <= 0) return 0;\n const words = text.split(\" \");\n const textPairTotal = words.length - 1;\n if (textPairTotal <= 0) return 0;\n\n let matches = 0;\n const consumed = new Map<string, number>();\n for (let i = 0; i < words.length - 1; i++) {\n const key = `${words[i]} ${words[i + 1]}`;\n const available = needlePairs.get(key);\n if (available === undefined) continue;\n const used = consumed.get(key) ?? 0;\n if (used < available) {\n consumed.set(key, used + 1);\n matches++;\n }\n }\n\n return (2 * matches) / (needlePairTotal + textPairTotal);\n}\n","/**\n * Element visibility classification for anchor resolution.\n *\n * Responsive sites render the same component twice (`hidden md:block` mobile +\n * desktop twins); resolution must prefer the rendered copy. Visibility is a\n * scoring TIER, never a hard filter — when every duplicate is hidden (e.g.\n * mobile viewport), the best hidden candidate still resolves rather than\n * orphaning the annotation.\n */\n\nexport type VisibilityClass = \"visible\" | \"soft-hidden\" | \"hidden\" | \"unknown\";\n\n/**\n * Both option-name generations must be passed together: the CSSOM spec ORs\n * the old (checkOpacity/checkVisibilityCSS) and renamed\n * (opacityProperty/visibilityProperty) flags, and Chrome 105–120 /\n * Firefox 106–121 silently ignore the new names.\n * `contentVisibilityAuto` stays OFF — `content-visibility: auto` content is\n * merely offscreen, a perfectly legitimate anchor target.\n */\nconst STRICT_VISIBILITY_OPTIONS: Record<string, boolean> = {\n checkOpacity: true,\n opacityProperty: true,\n checkVisibilityCSS: true,\n visibilityProperty: true,\n};\n\n/**\n * Classify how visible an element currently is.\n *\n * - `\"visible\"` — rendered and painted.\n * - `\"soft-hidden\"` — geometry intact but not painted (visibility:hidden,\n * opacity:0). Anchor rects computed from it stay valid;\n * opacity:0 is common mid fade-in, so this is only a mild\n * penalty, never an exclusion.\n * - `\"hidden\"` — no rendered geometry: display:none chain,\n * content-visibility:hidden (closed <details>), detached.\n * - `\"unknown\"` — the environment performs no layout (jsdom: no\n * checkVisibility, every rect zero/empty). Treated as\n * visible by scorers so layout-less test environments and\n * exotic embedders keep pre-visibility behavior.\n *\n * Fallback chain notes (browsers without checkVisibility — Safari ≤ 17.3):\n * - `getClientRects().length` is the no-box test; `getBoundingClientRect()`\n * zeros are ambiguous (real zero-sized visible elements exist).\n * - NEVER `offsetParent === null` — visible position:fixed elements (sticky\n * headers, FABs: prime feedback targets) report null.\n * - `visibility` is an inherited computed value, so one read on the candidate\n * is sufficient and correctly handles `visibility: visible` re-shows inside\n * hidden ancestors; display:none needs no ancestor walk because the box\n * tree already has no fragments for the whole subtree.\n * - content-visibility:hidden content keeps real geometry, so the fallback\n * misclassifies it as visible — acceptable: every engine old enough to lack\n * checkVisibility also predates content-visibility support.\n * - aria-hidden is deliberately ignored (visually rendered content).\n */\nexport function classifyVisibility(element: Element): VisibilityClass {\n if (!element.isConnected) return \"hidden\";\n\n // Runtime guard stays although lib.dom types it as always-present:\n // jsdom (the test environment) and Safari ≤ 17.3 don't implement it.\n if (typeof element.checkVisibility === \"function\") {\n if (element.checkVisibility(STRICT_VISIBILITY_OPTIONS)) return \"visible\";\n // Base call only rejects display:none chains and content-visibility:hidden;\n // passing it while failing the strict call means visibility/opacity hiding.\n return element.checkVisibility() ? \"soft-hidden\" : \"hidden\";\n }\n\n if (element.getClientRects().length > 0) {\n try {\n const visibility = getComputedStyle(element).visibility;\n return visibility === \"visible\" ? \"visible\" : \"soft-hidden\";\n } catch {\n return \"visible\";\n }\n }\n\n // display:contents generates no box of its own but renders its children.\n const child = element.firstElementChild;\n if (child && child.getClientRects().length > 0) return \"visible\";\n\n // No boxes anywhere — hidden, unless the environment does no layout at all\n // (then every element has zero rects and the signal is meaningless).\n if (element.ownerDocument.documentElement.getClientRects().length === 0) return \"unknown\";\n\n return \"hidden\";\n}\n\n/** Score multiplier for a visibility class — tiering, not filtering. */\nexport function visibilityFactor(cls: VisibilityClass): number {\n switch (cls) {\n case \"hidden\":\n return 0.3;\n case \"soft-hidden\":\n return 0.6;\n default:\n return 1;\n }\n}\n","import type { AnchorData, RectData } from \"@siteping/core\";\nimport { ANCHOR_KEY_ATTR } from \"./anchor.js\";\nimport { attrHash, scoreFingerprint } from \"./fingerprint.js\";\nimport {\n bigramCounts,\n collapseWhitespace,\n diceAgainst,\n fuzzyIncludes,\n normalizeText,\n similarity,\n wordPairCounts,\n wordPairDiceAgainst,\n} from \"./fuzzy.js\";\nimport { adjacentText, boundedText, neighborText } from \"./text-context.js\";\nimport { classifyVisibility, visibilityFactor } from \"./visibility.js\";\n\nexport type ResolutionStrategy = \"anchorKey\" | \"id\" | \"css\" | \"xpath\" | \"scan\";\n\nexport interface AnchorResolution {\n element: Element;\n confidence: number;\n strategy: ResolutionStrategy;\n}\n\nexport interface ResolvedAnnotation {\n element: Element;\n rect: DOMRect;\n confidence: number;\n strategy: ResolutionStrategy;\n}\n\n/**\n * Caller-provided allowance for full tag sweeps across a BATCH of\n * resolutions (marker init, reposition passes). A sweep is the one\n * unbounded-ish cost left in resolution; several drifted or hidden anchors\n * resolved back-to-back must not each pay one synchronously (the Hypothesis\n * issue-#3919 lesson: budget per pass, not per resolution). When the budget\n * is exhausted, resolution proceeds selector-only — the next pass gets a\n * fresh budget and heals the remainder.\n */\nexport interface ScanBudget {\n /** Remaining sweep allowance; decremented each time a sweep actually runs. */\n remaining: number;\n /** Set by the resolver when a sweep was wanted but the budget was empty —\n * callers must NOT cache such degraded results (a selector-only answer may\n * be worse than what the sweep would have found, and a cached wrong\n * element is never re-examined). */\n starved?: boolean;\n}\n\nexport interface ResolveOptions {\n scanBudget?: ScanBudget;\n}\n\n/**\n * Confidence ceiling per strategy — same ladder as v1's cascade, now used as\n * a multiplicative prior in cross-strategy ranking. Multiplicative, not\n * additive: a prior can only amplify verification evidence, never substitute\n * for it, so a stale selector with poor verification cannot outrank a\n * well-verified scan hit.\n */\nconst STRATEGY_PRIORS: Record<ResolutionStrategy, number> = {\n anchorKey: 1.0,\n id: 1.0,\n css: 0.95,\n xpath: 0.9,\n scan: 0.85,\n};\n\n/** Max matches gathered per selector strategy (guards degenerate selectors). */\nconst MAX_PER_STRATEGY = 16;\n\n/** Scan candidates that survive prefiltering and get full multi-signal scoring. */\nconst SCAN_TOP_K = 24;\n\n/** Pathological-DOM guard for the prefilter sweep itself. */\nconst SCAN_HARD_CAP = 10_000;\n\n/** Max candidate text considered for scoring (bounds fuzzy-match cost). */\nconst CANDIDATE_TEXT_CAP = 500;\n\n/**\n * Acceptance for selector strategies gates on the STRONGEST single signal,\n * never on the diluted blend — the blend is a RANKING device. A volatile\n * signal (fingerprints churn with every redesign) must not veto a stable\n * one: v1 resolved `#promo` + fuzzy-passing text regardless of what the\n * surrounding DOM did, and that must survive.\n * - text ≥ 0.5 (v1's effective bar — fuzzyIncludes' own minScore) accepts.\n * - No stored text at all: ALWAYS acceptable — v1 accepted textless selector\n * hits unconditionally, and rejection here silently orphans legacy\n * icon/image anchors whose id still matches (the sweep cannot rescue pool\n * members). Ranking and confidence already penalize structural drift.\n * - Text present but REFUTED: strong structural corroboration required —\n * the i18n case (text translated, fingerprint intact) passes, a weak\n * fingerprint coincidence does not.\n * Scan has no selector evidence, so it keeps v1's 0.4 floor on the blend.\n */\nconst TEXT_FLOOR = 0.5;\nconst STRONG_STRUCT = 0.6;\nconst ACCEPT_SCAN = 0.4;\n\n/** Hostile-stored-data guard: fields are sliced before any normalization\n * (NFC on a multi-megabyte string is itself a freeze) and again after. */\nconst RAW_FIELD_CAP = 2000;\n\n/**\n * Verification at or above this level earns the full strategy prior as\n * confidence; below it, confidence degrades proportionally (and crosses the\n * marker UI's 0.7 \"approximate\" threshold naturally).\n */\nconst STRONG_VERIFY = 0.8;\n\n/**\n * Verification assigned to selector-strategy candidates when the stored\n * anchor carries no verifiable signal at all (no text, no fingerprint, no\n * context — only possible for hand-built or pre-fingerprint data; capture\n * always stores a fingerprint). The selector match is then the only\n * evidence: accept, but rank it below verified alternatives.\n */\nconst NEUTRAL_VERIFICATION = 0.6;\n\n/** Score gap under which two candidates are considered equally plausible. */\nconst AMBIGUITY_EPSILON = 0.05;\n\n/** Stored-anchor signals, normalized once per resolution. */\ninterface AnchorSignals {\n snippet: string;\n snippetBigrams: Map<number, number>;\n snippetBigramTotal: number;\n snippetWordPairs: Map<string, number>;\n snippetWordPairTotal: number;\n prefix: string;\n suffix: string;\n neighbor: string;\n fingerprint: string;\n tag: string;\n}\n\n/** Per-signal verification scores; a signal is absent when undefined. */\ninterface SignalScores {\n blend: number;\n strongest: number;\n text?: number;\n fingerprint?: number;\n context?: number;\n neighbor?: number;\n}\n\ninterface ScoredCandidate {\n element: Element;\n strategy: ResolutionStrategy;\n verification: number;\n strongest: number;\n signals?: SignalScores;\n /** Visibility factor applied to `final` (1 = visible/unknown). */\n visibility: number;\n final: number;\n /** No verifiable signal was stored — verification is a neutral stand-in. */\n unverified?: boolean;\n}\n\nfunction boundedField(value: string | null | undefined, cap: number): string {\n return normalizeText((value ?? \"\").slice(0, RAW_FIELD_CAP)).slice(0, cap);\n}\n\nfunction buildSignals(anchor: AnchorData): AnchorSignals {\n // Capture stores ≤120-char snippets and ≤40-char context — larger values\n // only come from hostile or corrupted storage, and uncapped they turn\n // normalization/edit-distance into a main-thread freeze.\n const snippet = boundedField(anchor.textSnippet, CANDIDATE_TEXT_CAP);\n const snippetWordPairs = wordPairCounts(snippet);\n let snippetWordPairTotal = 0;\n for (const count of snippetWordPairs.values()) snippetWordPairTotal += count;\n return {\n snippet,\n snippetBigrams: bigramCounts(snippet),\n snippetBigramTotal: Math.max(0, snippet.length - 1),\n snippetWordPairs,\n snippetWordPairTotal,\n prefix: boundedField(anchor.textPrefix, 128),\n suffix: boundedField(anchor.textSuffix, 128),\n neighbor: boundedField(anchor.neighborText, 128),\n fingerprint: (anchor.fingerprint ?? \"\").slice(0, 64),\n tag: typeof anchor.elementTag === \"string\" ? anchor.elementTag : \"\",\n };\n}\n\n/**\n * Re-anchor an annotation: gather candidates from EVERY strategy, verify each\n * against all stored signals, rank across strategies, return the best.\n *\n * v1 was a first-match-wins cascade (anchorKey → id → css → xpath → scan)\n * where a wrong-but-text-passing selector hit won outright over a correct\n * element the scan would have found (#175), the first DOM match won even when\n * it was an invisible responsive twin (#171), and elements without text got\n * no verification at all (#172).\n *\n * v2 ranking: final = strategyPrior × verification × visibilityFactor\n * - verification: dynamic-weight blend of text / fingerprint / prefix-suffix /\n * neighbor signals (only signals the stored anchor has contribute).\n * - visibility: tiering, never filtering — hidden duplicates are heavily\n * penalized, but when ONLY hidden candidates exist the best one still\n * resolves (an annotation on a currently-collapsed section survives the\n * breakpoint flipping back).\n * - Confidence keeps the v1 scale: a perfectly verified anchorKey/id/css/\n * xpath match yields exactly 1.0/1.0/0.95/0.9, scan stays capped at 0.85,\n * and weak verification degrades confidence proportionally.\n *\n * The scan sweep is skipped when a selector candidate already scores above\n * anything the scan could produce (its prior caps its final at 0.85) — the\n * happy path costs a handful of querySelector calls, like v1.\n *\n * Returns null if no candidate verifies (annotation is orphaned).\n */\nexport function resolveAnchor(anchor: AnchorData, options?: ResolveOptions): AnchorResolution | null {\n const signals = buildSignals(anchor);\n const pool = gatherSelectorCandidates(anchor);\n\n const scored: ScoredCandidate[] = [];\n for (const [element, strategy] of pool) {\n const candidate = scoreOne(element, strategy, signals);\n if (candidate) scored.push(candidate);\n }\n\n let bestFinal = 0;\n let strongVisibleMatch = false;\n for (const c of scored) {\n if (c.final > bestFinal) bestFinal = c.final;\n // Identity selectors (id, anchorKey — near-unique by contract, the ones\n // v1 trusted absolutely) with near-exact text on a visible element end\n // the search even when CONTEXT signals (neighbors, prefix/suffix)\n // drifted — but not when the element's own fingerprint contradicts:\n // a wrapper that took over the id contains the same text yet scores a\n // partial fingerprint, and only the sweep can surface the true inner\n // element. Fragile selectors (css/xpath) get no shortcut at all: an\n // element that merely CONTAINS the snippet verbatim plus coincidental\n // structure is exactly the #175 impostor — they suppress the sweep\n // solely through the unbeatable-final bound below.\n if (\n (c.strategy === \"id\" || c.strategy === \"anchorKey\") &&\n c.visibility === 1 &&\n (c.signals?.text ?? 0) >= STRONG_VERIFY &&\n (c.signals?.fingerprint === undefined || c.signals.fingerprint >= STRONG_VERIFY)\n ) {\n strongVisibleMatch = true;\n }\n }\n\n // The sweep only helps when something could beat the pool (scan's final is\n // capped by its prior) AND there is at least one stored signal to verify\n // scan candidates against — with none, every scan candidate is discarded\n // and the sweep is pure cost.\n const verifiable = !!(signals.snippet || signals.fingerprint || signals.prefix || signals.suffix || signals.neighbor);\n const budget = options?.scanBudget;\n if (verifiable && bestFinal < STRATEGY_PRIORS.scan && !strongVisibleMatch) {\n if (budget && budget.remaining <= 0) {\n budget.starved = true;\n } else {\n if (budget) budget.remaining--;\n for (const element of sweepScanCandidates(signals, pool)) {\n const candidate = scoreOne(element, \"scan\", signals);\n if (candidate) scored.push(candidate);\n }\n }\n }\n\n const accepted = scored.filter(isAcceptable);\n if (accepted.length === 0) return null;\n\n accepted.sort((a, b) => b.final - a.final);\n const winner = disambiguate(accepted);\n\n return {\n element: winner.element,\n confidence: confidenceOf(winner),\n strategy: winner.strategy,\n };\n}\n\n/**\n * Collect candidates from all selector strategies, ALL matches per strategy\n * (bounded), in priority order. An element found by several strategies keeps\n * the highest-priority one (first insertion wins).\n */\nfunction gatherSelectorCandidates(anchor: AnchorData): Map<Element, ResolutionStrategy> {\n const pool = new Map<Element, ResolutionStrategy>();\n\n const add = (el: Element | null, strategy: ResolutionStrategy, enforceTag: boolean) => {\n if (!el || pool.has(el)) return;\n if (enforceTag && el.tagName !== anchor.elementTag) return;\n pool.set(el, strategy);\n };\n\n // anchorKey — host-controlled semantic key. Tag NOT enforced: hosts may\n // legitimately refactor the wrapper element while keeping the key stable.\n if (anchor.anchorKey) {\n const escaped = anchor.anchorKey.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n try {\n const matches = document.querySelectorAll(`[${ANCHOR_KEY_ATTR}=\"${escaped}\"]`);\n for (let i = 0; i < Math.min(matches.length, MAX_PER_STRATEGY); i++) {\n add(matches[i] ?? null, \"anchorKey\", false);\n }\n } catch {\n // Invalid attribute value — skip strategy\n }\n }\n\n // id — duplicate ids are invalid HTML but common in the wild; gather all so\n // a hidden duplicate can lose to the visible one instead of shadowing it.\n // Attribute selector instead of `#…` to avoid needing CSS.escape (absent in\n // some embedders and in jsdom) — matching semantics are identical.\n if (anchor.elementId) {\n const escaped = anchor.elementId.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n try {\n const matches = document.querySelectorAll(`[id=\"${escaped}\"]`);\n for (let i = 0; i < Math.min(matches.length, MAX_PER_STRATEGY); i++) {\n add(matches[i] ?? null, \"id\", true);\n }\n } catch {\n add(document.getElementById(anchor.elementId), \"id\", true);\n }\n }\n\n // CSS selector\n try {\n const matches = document.querySelectorAll(anchor.cssSelector);\n for (let i = 0; i < Math.min(matches.length, MAX_PER_STRATEGY); i++) {\n add(matches[i] ?? null, \"css\", true);\n }\n } catch {\n // Invalid selector — skip strategy\n }\n\n // XPath — snapshot (not FIRST_ORDERED_NODE) so later duplicates compete too\n try {\n const result = document.evaluate(anchor.xpath, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);\n const count = Math.min(result.snapshotLength, MAX_PER_STRATEGY);\n for (let i = 0; i < count; i++) {\n const node = result.snapshotItem(i);\n if (node instanceof Element) add(node, \"xpath\", true);\n }\n } catch {\n // Invalid XPath — skip strategy\n }\n\n return pool;\n}\n\n/**\n * Same-tag sweep, prefiltered. Every same-tag element is considered (v1\n * stopped dead at the 300th in document order — a correct element past the\n * cap was unreachable), but full scoring only runs on the TOP_K best by a\n * cheap O(text-budget) prefilter: bigram-Dice text overlap plus O(1)\n * structural hints (stable-attribute hash, child count). The prefilter only\n * RANKS — it never eliminates on a threshold, so an imperfect cheap score\n * demotes a candidate but cannot drop the true match on its own.\n */\nfunction sweepScanCandidates(signals: AnchorSignals, pool: Map<Element, ResolutionStrategy>): Element[] {\n const tag = signals.tag.toLowerCase();\n if (!tag) return [];\n let candidates: NodeListOf<Element>;\n try {\n candidates = document.querySelectorAll(tag);\n } catch {\n return [];\n }\n\n // Parse only well-formed 3-part fingerprints (mirrors scoreFingerprint).\n // `Number(\"\")` is 0, not NaN — an empty fingerprint would otherwise grant a\n // phantom child-count-0 bonus that biases top-K toward childless decoys.\n const storedFp = signals.fingerprint.split(\":\");\n const storedChildCount = storedFp.length === 3 ? Number(storedFp[0]) : Number.NaN;\n const storedAttrHash = storedFp.length === 3 ? (storedFp[2] ?? \"\") : \"\";\n\n const limit = Math.min(candidates.length, SCAN_HARD_CAP);\n const ranked: { element: Element; cheap: number }[] = [];\n\n for (let i = 0; i < limit; i++) {\n const el = candidates[i];\n if (!el || pool.has(el)) continue; // already scored under a selector strategy\n\n let cheap = 0;\n if (signals.snippetBigramTotal > 0) {\n // collapseWhitespace, not full normalizeText: NFC on every candidate is\n // the prefilter's dominant hidden cost; survivors get re-normalized in\n // full scoring anyway.\n const text = collapseWhitespace(boundedText(el, CANDIDATE_TEXT_CAP));\n const charDice = diceAgainst(signals.snippetBigrams, signals.snippetBigramTotal, text);\n // Character bigrams are order-blind: on shared-vocabulary pages (card\n // grids) every candidate scores alike. Word-pair shingles restore order\n // sensitivity; when the snippet has no pairs (single word, no-space\n // scripts) the whole weight stays on character bigrams. A shared word\n // pair implies shared bigrams, so charDice 0 makes the word pass moot.\n if (signals.snippetWordPairTotal > 0) {\n const wordDice =\n charDice > 0 ? wordPairDiceAgainst(signals.snippetWordPairs, signals.snippetWordPairTotal, text) : 0;\n cheap += 0.6 * (0.5 * charDice + 0.5 * wordDice);\n } else {\n cheap += 0.6 * charDice;\n }\n }\n if (storedAttrHash && attrHash(el) === storedAttrHash) cheap += 0.25;\n if (!Number.isNaN(storedChildCount)) {\n const diff = Math.abs(el.children.length - storedChildCount);\n if (diff === 0) cheap += 0.15;\n else if (diff <= 2) cheap += 0.07;\n }\n\n ranked.push({ element: el, cheap });\n }\n\n // Stable sort: ties keep document order, mirroring v1's document-order bias.\n ranked.sort((a, b) => b.cheap - a.cheap);\n return ranked.slice(0, SCAN_TOP_K).map((r) => r.element);\n}\n\nfunction scoreOne(element: Element, strategy: ResolutionStrategy, signals: AnchorSignals): ScoredCandidate | null {\n const scores = verificationScore(element, signals);\n const visibility = visibilityFactor(classifyVisibility(element));\n if (scores === null) {\n // No verifiable signal stored: the selector match is the only evidence.\n // A scan candidate with nothing to verify against is meaningless, though.\n if (strategy === \"scan\") return null;\n return {\n element,\n strategy,\n verification: NEUTRAL_VERIFICATION,\n strongest: NEUTRAL_VERIFICATION,\n visibility,\n final: STRATEGY_PRIORS[strategy] * NEUTRAL_VERIFICATION * visibility,\n unverified: true,\n };\n }\n\n return {\n element,\n strategy,\n verification: scores.blend,\n strongest: scores.strongest,\n signals: scores,\n visibility,\n final: STRATEGY_PRIORS[strategy] * scores.blend * visibility,\n };\n}\n\n/**\n * Whether a candidate has enough corroboration to be returned at all.\n * Selector strategies accept on the strongest SINGLE signal clearing its\n * floor — a drifted fingerprint must not veto an exact text match (or vice\n * versa: an icon button's intact fingerprint carries it when there is no\n * text). Scan keeps its blend floor: without selector evidence, agreement\n * across signals is the whole case for the match.\n */\nfunction isAcceptable(c: ScoredCandidate): boolean {\n if (c.strategy === \"scan\") return c.verification >= ACCEPT_SCAN;\n if (c.unverified || !c.signals) return true;\n const s = c.signals;\n // No stored text: ranking-only (see constant doc — v1 parity for legacy\n // textless anchors; drift shows up as low confidence, not orphaning).\n if (s.text === undefined) return true;\n if (s.text >= TEXT_FLOOR) return true;\n // Text present but refuted — accept only on strong structural agreement.\n return (\n (s.fingerprint ?? 0) >= STRONG_STRUCT || (s.context ?? 0) >= STRONG_STRUCT || (s.neighbor ?? 0) >= STRONG_STRUCT\n );\n}\n\n/**\n * Multi-signal verification, 0–1. Dynamic weighting: only signals the stored\n * anchor actually has contribute, then the sum is normalized — anchors\n * captured with fewer signals compete on the signals they do have.\n * Returns null when the anchor stores no verifiable signal at all.\n *\n * All text comparisons run on `normalizeText`-processed strings on BOTH\n * sides, so SSR/CSR whitespace drift and re-indented markup no longer\n * penalize otherwise-identical text (#173) — stored snippets are untouched\n * and stay backward compatible.\n */\nfunction verificationScore(candidate: Element, s: AnchorSignals): SignalScores | null {\n let score = 0;\n let totalWeight = 0;\n const out: SignalScores = { blend: 0, strongest: 0 };\n\n // --- Text snippet (weight 40 — most reliable under reordering) ---\n if (s.snippet) {\n totalWeight += 40;\n const candidateText = normalizeText(boundedText(candidate, CANDIDATE_TEXT_CAP));\n out.text = fuzzyIncludes(candidateText, s.snippet, 0.5);\n score += out.text * 40;\n }\n\n // --- Fingerprint (weight 20) ---\n if (s.fingerprint) {\n totalWeight += 20;\n out.fingerprint = scoreFingerprint(candidate, s.fingerprint);\n score += out.fingerprint * 20;\n }\n\n // --- Prefix/suffix context (weight 20) ---\n if (s.prefix || s.suffix) {\n totalWeight += 20;\n let contextScore = 0;\n let contextParts = 0;\n\n if (s.prefix) {\n const prevText = normalizeText(adjacentText(candidate, \"before\"));\n contextScore += prevText ? similarity(prevText, s.prefix) : 0;\n contextParts++;\n }\n\n if (s.suffix) {\n const nextText = normalizeText(adjacentText(candidate, \"after\"));\n contextScore += nextText ? similarity(nextText, s.suffix) : 0;\n contextParts++;\n }\n\n if (contextParts > 0) {\n out.context = contextScore / contextParts;\n score += out.context * 20;\n }\n }\n\n // --- Neighbor text (weight 20) ---\n if (s.neighbor) {\n totalWeight += 20;\n const candidateNeighbor = normalizeText(neighborText(candidate));\n out.neighbor = candidateNeighbor ? similarity(candidateNeighbor, s.neighbor) : 0;\n score += out.neighbor * 20;\n }\n\n if (totalWeight === 0) return null;\n out.blend = score / totalWeight;\n out.strongest = Math.max(out.text ?? 0, out.fingerprint ?? 0, out.context ?? 0, out.neighbor ?? 0);\n return out;\n}\n\n/**\n * Ancestor-decoy tie-break: a wrapper's text contains its child's text, so it\n * scores nearly as well — but anchoring to the wrapper corrupts the\n * percentage-based rect. Among candidates within AMBIGUITY_EPSILON of the\n * best that sit on the best's own descendant chain, prefer the innermost.\n * Unrelated near-ties keep the plain argmax (strategy priors already encode\n * the preference order there).\n */\nfunction disambiguate(sortedAccepted: ScoredCandidate[]): ScoredCandidate {\n const best = sortedAccepted[0] as ScoredCandidate; // non-empty by caller contract\n const contenders = sortedAccepted.filter(\n (c) => best.final - c.final <= AMBIGUITY_EPSILON && (c === best || best.element.contains(c.element)),\n );\n // Innermost = contained by every other contender that contains anything\n let winner = best;\n for (const c of contenders) {\n if (c !== winner && winner.element.contains(c.element)) winner = c;\n }\n return winner;\n}\n\nfunction confidenceOf(c: ScoredCandidate): number {\n if (c.strategy === \"scan\") {\n // v1 semantics: the scan's confidence IS its verification, hard-capped —\n // a scan is never fully certain.\n return Math.min(c.verification, STRATEGY_PRIORS.scan);\n }\n // Nothing was verifiable → the selector is all the evidence there is;\n // v1 semantics: trust it at full prior rather than inventing doubt.\n if (c.unverified) return STRATEGY_PRIORS[c.strategy];\n // Confidence follows the STRONGEST corroborating signal, not the blend:\n // `<h2 id=\"pricing\">Pricing</h2>` moved into a new wrapper still carries an\n // exact text match — the drifted fingerprint/neighbors around it must not\n // dash-flag a perfectly anchored marker. Absence of a signal stays neutral;\n // a present-but-refuted one still drags `strongest` down when it is all\n // there is. Full prior at STRONG_VERIFY keeps v1's exact values.\n return STRATEGY_PRIORS[c.strategy] * Math.min(1, c.strongest / STRONG_VERIFY);\n}\n\n/**\n * Resolve an annotation's position on the page.\n * Converts stored percentage-based rect back to absolute coordinates\n * using the current bounding box of the resolved anchor element.\n */\nexport function resolveAnnotation(\n anchor: AnchorData,\n rect: RectData,\n options?: ResolveOptions,\n): ResolvedAnnotation | null {\n const resolution = resolveAnchor(anchor, options);\n\n if (!resolution) return null;\n\n const bounds = resolution.element.getBoundingClientRect();\n const absoluteRect = new DOMRect(\n bounds.x + rect.xPct * bounds.width,\n bounds.y + rect.yPct * bounds.height,\n rect.wPct * bounds.width,\n rect.hPct * bounds.height,\n );\n\n return {\n element: resolution.element,\n rect: absoluteRect,\n confidence: resolution.confidence,\n strategy: resolution.strategy,\n };\n}\n","import { type AnchorData, type FeedbackResponse, isClosedStatus, type RectData } from \"@siteping/core\";\nimport { Z_INDEX_MAX } from \"./constants.js\";\nimport { resolveAnnotation } from \"./dom/resolver.js\";\nimport { classifyVisibility } from \"./dom/visibility.js\";\nimport { el, setText } from \"./dom-utils.js\";\nimport type { EventBus, WidgetEvents } from \"./events.js\";\nimport { getTypeLabel, type TFunction, tWithParams } from \"./i18n/index.js\";\nimport { getTypeColor, type ThemeColors } from \"./styles/theme.js\";\nimport type { Tooltip } from \"./tooltip.js\";\n\ntype Annotation = FeedbackResponse[\"annotations\"][number];\n\nfunction toAnchorData(a: Annotation): AnchorData {\n return {\n cssSelector: a.cssSelector,\n xpath: a.xpath,\n textSnippet: a.textSnippet,\n elementTag: a.elementTag,\n elementId: a.elementId ?? undefined,\n textPrefix: a.textPrefix,\n textSuffix: a.textSuffix,\n fingerprint: a.fingerprint,\n neighborText: a.neighborText,\n anchorKey: a.anchorKey ?? null,\n };\n}\n\nfunction toRectData(a: Annotation): RectData {\n return { xPct: a.xPct, yPct: a.yPct, wPct: a.wPct, hPct: a.hPct };\n}\n\n/** Half of the 26px marker diameter — used for centering on anchor corner. */\nconst MARKER_OFFSET = 13;\n\n/** Convert a resolved rect to document-absolute marker position. */\nfunction markerPosition(rect: DOMRect): { top: number; left: number } {\n return {\n top: rect.top + window.scrollY - MARKER_OFFSET,\n left: rect.right + window.scrollX - MARKER_OFFSET,\n };\n}\n\ninterface MarkerEntry {\n feedback: FeedbackResponse;\n elements: HTMLElement[];\n baseTop: number;\n baseLeft: number;\n}\n\ninterface Cluster {\n entries: MarkerEntry[];\n elementIndices: number[];\n expanded: boolean;\n}\n\n/** Get the i-th marker element from a cluster. */\nfunction clusterMarker(cluster: Cluster, i: number): HTMLElement | undefined {\n const entry = cluster.entries[i];\n const elIdx = cluster.elementIndices[i];\n if (!entry || elIdx === undefined) return undefined;\n return entry.elements[elIdx];\n}\n\nconst HIGHLIGHT_FADE = 300;\nconst REPOSITION_DEBOUNCE = 200;\n/** Back-off between full re-resolutions of an anchor that resolved hidden or\n * orphaned, on mutation ticks (resize bypasses it — see hiddenRecheckAt). */\nconst HIDDEN_RECHECK_MS = 3000;\nconst LOW_CONFIDENCE_THRESHOLD = 0.7;\nconst CLUSTER_DISTANCE = 28;\nconst FAN_SPACING = 32;\n\n/**\n * Numbered markers on the page for each feedback annotation.\n *\n * Cluster system: click-to-expand (same pattern as Google Maps / Spiderfier).\n * Hover is only used for tooltip/scale on individual markers — never for expansion.\n */\nexport class MarkerManager {\n private container: HTMLElement;\n private entries: MarkerEntry[] = [];\n private highlightElements: HTMLElement[] = [];\n private pinnedFeedback: FeedbackResponse | null = null;\n private onDocumentClick: ((e: MouseEvent) => void) | null = null;\n private repositionTimer: number | null = null;\n private mutationObserver: MutationObserver | null = null;\n private scrollHandler: (() => void) | null = null;\n private resizeHandler: (() => void) | null = null;\n private anchorCache = new Map<string, WeakRef<Element>>();\n /** Whether a resize/mutation happened since the last reposition pass —\n * the only triggers that can flip an anchor's visibility (responsive\n * breakpoint, SPA re-render). Pure scroll ticks keep the fast path. */\n private pendingLayoutChange = false;\n /** Resize specifically — the breakpoint-flip event: it bypasses the\n * hidden-anchor re-resolution throttle below. */\n private pendingResize = false;\n /** Per-annotation back-off after a resolution concluded \"hidden\" or\n * \"orphaned\": mutation ticks recur every ~200ms on busy SPAs, and\n * re-resolving an annotation in a collapsed accordion each tick is\n * provably-redundant sweep work. Resize clears the back-off. */\n private hiddenRecheckAt = new Map<string, number>();\n private clusters: Cluster[] = [];\n private onDocumentClickForClusters: ((e: MouseEvent) => void) | null = null;\n /** Last `openCount` broadcast via `markers:changed` (-1 = never emitted). */\n private lastOpenCount = -1;\n\n get count(): number {\n return this.entries.length;\n }\n\n get openCount(): number {\n let count = 0;\n for (const entry of this.entries) {\n // Anything not closed (open, in_progress) still needs attention.\n if (!isClosedStatus(entry.feedback.status)) count++;\n }\n return count;\n }\n\n constructor(\n private readonly colors: ThemeColors,\n private readonly tooltip: Tooltip,\n private readonly bus: EventBus<WidgetEvents>,\n private readonly t: TFunction,\n private readonly liveRegion: HTMLElement | null = null,\n ) {\n this.container = el(\"div\", {\n style: `position:absolute;top:0;left:0;pointer-events:none;z-index:${Z_INDEX_MAX - 1};`,\n });\n this.container.id = \"siteping-markers\";\n document.body.appendChild(this.container);\n\n this.bus.on(\"annotations:toggle\", (visible) => {\n this.container.style.display = visible ? \"block\" : \"none\";\n });\n\n this.resizeHandler = () => this.scheduleReposition(\"resize\");\n window.addEventListener(\"resize\", this.resizeHandler, { passive: true });\n\n this.scrollHandler = () => this.scheduleReposition(\"scroll\");\n window.addEventListener(\"scroll\", this.scrollHandler, { passive: true, capture: true });\n\n // Re-resolve after DOM changes (SPA, lazy-load).\n // Filter out widget-owned mutations and skip batches with only irrelevant\n // changes. Filtering short-circuits at the first non-widget mutation, so\n // even large batches stop after one DOM walk.\n //\n // The filter is applied unconditionally — earlier versions had a >20-batch\n // fast-path that skipped filtering, but that lets reposition self-trigger\n // when `repositionAll` re-renders the pinned highlight (showHighlight\n // appends N elements to `this.container`); a host page churning lots of\n // DOM (infinite scroll) would then loop at the 200ms debounce interval.\n this.mutationObserver = new MutationObserver((mutations) => {\n let hasRelevantMutation = false;\n for (const m of mutations) {\n if (this.container.contains(m.target) || this.tooltip.contains(m.target)) continue;\n hasRelevantMutation = true;\n break;\n }\n if (hasRelevantMutation) this.scheduleReposition(\"mutation\");\n });\n this.mutationObserver.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: false,\n characterData: false,\n });\n\n this.onDocumentClickForClusters = (e: MouseEvent) => {\n if (this.container.contains(e.target as Node)) return;\n this.collapseAllClusters();\n };\n document.addEventListener(\"click\", this.onDocumentClickForClusters);\n }\n\n private scheduleReposition(cause: \"scroll\" | \"mutation\" | \"resize\" = \"mutation\"): void {\n // Record the cause even when a tick is already pending — the pending\n // pass must honor the strongest cause seen since it was scheduled.\n if (cause !== \"scroll\") this.pendingLayoutChange = true;\n if (cause === \"resize\") this.pendingResize = true;\n if (this.repositionTimer) return;\n if (\"requestIdleCallback\" in window) {\n this.repositionTimer = window.requestIdleCallback(\n () => {\n this.repositionTimer = null;\n this.repositionAll();\n },\n { timeout: REPOSITION_DEBOUNCE + 100 },\n );\n } else {\n this.repositionTimer = +setTimeout(() => {\n this.repositionTimer = null;\n this.repositionAll();\n }, REPOSITION_DEBOUNCE);\n }\n }\n\n private repositionAll(): void {\n // Only resize/mutation ticks re-check cached anchors' visibility: a\n // responsive breakpoint flip can leave the cached element display:none\n // while its twin became the rendered copy (#171) — but re-checking on\n // every scroll tick would turn a legitimately-hidden anchor (collapsed\n // accordion) into a full re-resolution per scroll event.\n const recheckVisibility = this.pendingLayoutChange;\n const resizeTick = this.pendingResize;\n this.pendingLayoutChange = false;\n this.pendingResize = false;\n // A resize is the responsive breakpoint flip — every hidden-anchor\n // back-off is void, the visible twin may exist right now.\n if (resizeTick) this.hiddenRecheckAt.clear();\n const now = Date.now();\n\n // Reposition ticks recur every ~200ms on mutation-heavy pages; several\n // drifted/hidden anchors must not each pay a full tag sweep per tick.\n // Budget-starved annotations simply retry on the next natural tick.\n const scanBudget = { remaining: 2, starved: false };\n\n // Build set of valid keys to prune stale cache entries afterwards.\n const validKeys = new Set<string>();\n\n for (const entry of this.entries) {\n for (let i = 0; i < entry.feedback.annotations.length; i++) {\n const markerEl = entry.elements[i];\n if (!markerEl) continue;\n\n const annotation = entry.feedback.annotations[i];\n if (!annotation) continue;\n const cacheKey = `${entry.feedback.id}:${i}`;\n validKeys.add(cacheKey);\n\n // Try cached element first to avoid full resolution chain.\n const cachedRef = this.anchorCache.get(cacheKey);\n const cachedEl = cachedRef?.deref();\n let resolved: ReturnType<typeof resolveAnnotation>;\n\n const backedOff = (this.hiddenRecheckAt.get(cacheKey) ?? 0) > now;\n const cacheUsable =\n cachedEl?.isConnected && (backedOff || !(recheckVisibility && classifyVisibility(cachedEl) === \"hidden\"));\n\n if (cachedEl && cacheUsable) {\n const anchorRect = cachedEl.getBoundingClientRect();\n const r = toRectData(annotation);\n resolved = {\n element: cachedEl,\n rect: new DOMRect(\n anchorRect.left + r.xPct * anchorRect.width,\n anchorRect.top + r.yPct * anchorRect.height,\n r.wPct * anchorRect.width,\n r.hPct * anchorRect.height,\n ),\n confidence: 1,\n strategy: \"css\",\n };\n } else if (backedOff) {\n // A recent full resolution concluded hidden/orphaned and the anchor\n // is gone from the cache — don't burn another sweep this tick.\n resolved = null;\n } else {\n scanBudget.starved = false;\n resolved = resolveAnnotation(toAnchorData(annotation), toRectData(annotation), { scanBudget });\n if (scanBudget.starved) {\n // Selector-only answer under an exhausted budget — may be worse\n // than what the sweep would find; never cache it, retry next tick.\n } else {\n if (resolved?.element) {\n this.anchorCache.set(cacheKey, new WeakRef(resolved.element));\n }\n if (!resolved || classifyVisibility(resolved.element) === \"hidden\") {\n this.hiddenRecheckAt.set(cacheKey, now + HIDDEN_RECHECK_MS);\n } else {\n this.hiddenRecheckAt.delete(cacheKey);\n }\n }\n }\n\n if (!resolved) {\n markerEl.style.display = \"none\";\n continue;\n }\n\n const pos = markerPosition(resolved.rect);\n entry.baseTop = pos.top;\n entry.baseLeft = pos.left;\n markerEl.style.display = \"flex\";\n this.applyConfidenceStyle(markerEl, resolved.confidence, entry.feedback);\n }\n }\n\n // Prune cache keys from deleted feedbacks to prevent memory leak.\n for (const key of this.anchorCache.keys()) {\n if (!validKeys.has(key)) this.anchorCache.delete(key);\n }\n for (const key of this.hiddenRecheckAt.keys()) {\n if (!validKeys.has(key)) this.hiddenRecheckAt.delete(key);\n }\n\n this.applyClusterPositions();\n\n // Re-render the pinned highlight rectangle so it tracks the layout after\n // resize / SPA mutation. Marker dots reposition above; without this,\n // the highlight rect keeps its old pixel position and visibly drifts\n // away from the underlying content.\n if (this.pinnedFeedback) {\n this.showHighlight(this.pinnedFeedback);\n }\n }\n\n private applyClusterPositions(): void {\n for (const cluster of this.clusters) {\n if (cluster.expanded) {\n this.applyFanPositions(cluster);\n } else {\n this.applyStackPositions(cluster);\n }\n }\n }\n\n /**\n * Emit `markers:changed` only when the open count actually moved.\n *\n * Mutations that re-render the same set (panel search keystrokes, filter\n * toggles, \"load more\") all call `render()` without changing the page's\n * open count — emitting unconditionally would rebuild the FAB badge DOM on\n * every keystroke. The `-1` sentinel guarantees the first render still\n * emits, even when the page has zero open feedbacks.\n */\n private emitMarkersChanged(): void {\n const openCount = this.openCount;\n if (openCount === this.lastOpenCount) return;\n this.lastOpenCount = openCount;\n this.bus.emit(\"markers:changed\", openCount);\n }\n\n render(feedbacks: FeedbackResponse[]): void {\n this.clear();\n feedbacks.forEach((feedback, i) => {\n const entry = this.buildEntry(feedback, i + 1);\n this.entries.push(entry);\n });\n this.buildClusters();\n // Announce the number of visible markers to assistive tech (WCAG 4.1.3).\n // Skip the announcement when the host page has not provided a live\n // region (tests, embedded use cases) and when no marker is visible to\n // avoid noisy \"0 markers\" updates on every navigation.\n if (this.liveRegion && this.entries.length > 0) {\n this.liveRegion.textContent = tWithParams(this.t, \"marker.count\", { count: this.entries.length });\n }\n this.emitMarkersChanged();\n }\n\n addFeedback(feedback: FeedbackResponse, index: number): void {\n const entry = this.buildEntry(feedback, index);\n for (const m of entry.elements) {\n m.style.animation = \"sp-marker-in 0.35s cubic-bezier(0.34,1.56,0.64,1) both\";\n }\n this.entries.push(entry);\n this.buildClusters();\n this.emitMarkersChanged();\n }\n\n private buildEntry(feedback: FeedbackResponse, index: number): MarkerEntry {\n const entry: MarkerEntry = { feedback, elements: [], baseTop: 0, baseLeft: 0 };\n for (const annotation of feedback.annotations) {\n const resolved = resolveAnnotation(toAnchorData(annotation), toRectData(annotation));\n if (!resolved) continue;\n const pos = markerPosition(resolved.rect);\n entry.baseTop = pos.top;\n entry.baseLeft = pos.left;\n const marker = this.createMarker(index, feedback, pos);\n this.applyConfidenceStyle(marker, resolved.confidence, feedback);\n this.container.appendChild(marker);\n entry.elements.push(marker);\n }\n return entry;\n }\n\n private buildClusters(): void {\n for (const badge of this.container.querySelectorAll<HTMLElement>(\".sp-cluster-badge\")) {\n badge.remove();\n }\n\n const allItems: { entry: MarkerEntry; elIdx: number }[] = [];\n for (const entry of this.entries) {\n for (let i = 0; i < entry.elements.length; i++) {\n allItems.push({ entry, elIdx: i });\n }\n }\n\n const used = new Set<number>();\n this.clusters = [];\n\n for (let i = 0; i < allItems.length; i++) {\n if (used.has(i)) continue;\n const itemI = allItems[i];\n if (!itemI) continue;\n const cluster: Cluster = {\n entries: [itemI.entry],\n elementIndices: [itemI.elIdx],\n expanded: false,\n };\n used.add(i);\n\n for (let j = i + 1; j < allItems.length; j++) {\n if (used.has(j)) continue;\n const a = itemI.entry;\n const itemJ = allItems[j];\n if (!itemJ) continue;\n const b = itemJ.entry;\n const dist = Math.sqrt((a.baseLeft - b.baseLeft) ** 2 + (a.baseTop - b.baseTop) ** 2);\n if (dist < CLUSTER_DISTANCE) {\n cluster.entries.push(b);\n cluster.elementIndices.push(itemJ.elIdx);\n used.add(j);\n }\n }\n\n this.clusters.push(cluster);\n }\n\n for (const cluster of this.clusters) {\n if (cluster.entries.length <= 1) continue;\n this.applyStackPositions(cluster);\n this.addClusterBadge(cluster);\n }\n }\n\n private applyStackPositions(cluster: Cluster): void {\n const first = cluster.entries[0];\n if (!first) return;\n const { baseTop, baseLeft } = first;\n const isSolo = cluster.entries.length <= 1;\n for (let i = 0; i < cluster.entries.length; i++) {\n const m = clusterMarker(cluster, i);\n if (!m) continue;\n m.style.top = `${baseTop + (isSolo ? 0 : i * 3)}px`;\n m.style.left = `${baseLeft + (isSolo ? 0 : i * 3)}px`;\n m.style.zIndex = String(i + 1);\n }\n }\n\n private applyFanPositions(cluster: Cluster): void {\n const first = cluster.entries[0];\n if (!first) return;\n const { baseTop, baseLeft } = first;\n const count = cluster.entries.length;\n const totalWidth = (count - 1) * FAN_SPACING;\n const startLeft = baseLeft - totalWidth / 2;\n\n for (let i = 0; i < count; i++) {\n const m = clusterMarker(cluster, i);\n if (!m) continue;\n m.style.top = `${baseTop}px`;\n m.style.left = `${startLeft + i * FAN_SPACING}px`;\n m.style.zIndex = String(10 + i);\n }\n }\n\n private addClusterBadge(cluster: Cluster): void {\n const topMarker = clusterMarker(cluster, cluster.entries.length - 1);\n if (!topMarker) return;\n const badge = el(\"div\", {\n class: \"sp-cluster-badge\",\n style: `\n position:absolute;top:-6px;right:-6px;\n min-width:16px;height:16px;padding:0 4px;\n border-radius:9999px;\n background:${this.colors.accent};color:#fff;\n font-size:10px;font-weight:700;\n display:flex;align-items:center;justify-content:center;\n border:1.5px solid #fff;\n pointer-events:none;\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n line-height:1;\n `,\n });\n setText(badge, String(cluster.entries.length));\n topMarker.appendChild(badge);\n }\n\n private setBadgesVisible(cluster: Cluster, visible: boolean): void {\n for (let i = 0; i < cluster.entries.length; i++) {\n const badge = clusterMarker(cluster, i)?.querySelector(\".sp-cluster-badge\") as HTMLElement | null;\n if (badge) badge.style.display = visible ? \"flex\" : \"none\";\n }\n }\n\n private findCluster(marker: HTMLElement): Cluster | null {\n for (const cluster of this.clusters) {\n if (cluster.entries.length <= 1) continue;\n for (let i = 0; i < cluster.entries.length; i++) {\n if (clusterMarker(cluster, i) === marker) return cluster;\n }\n }\n return null;\n }\n\n private handleClusterClick(marker: HTMLElement, e: MouseEvent): boolean {\n const cluster = this.findCluster(marker);\n if (!cluster) return false;\n if (!cluster.expanded) {\n e.stopPropagation();\n this.collapseAllClusters();\n cluster.expanded = true;\n this.applyFanPositions(cluster);\n this.setBadgesVisible(cluster, false);\n return true;\n }\n return false;\n }\n\n private collapseCluster(cluster: Cluster): void {\n if (!cluster.expanded) return;\n cluster.expanded = false;\n this.applyStackPositions(cluster);\n this.setBadgesVisible(cluster, true);\n }\n\n private collapseAllClusters(): void {\n for (const cluster of this.clusters) {\n this.collapseCluster(cluster);\n }\n }\n\n private applyConfidenceStyle(marker: HTMLElement, confidence: number, feedback: FeedbackResponse): void {\n const isResolved = isClosedStatus(feedback.status);\n if (confidence < LOW_CONFIDENCE_THRESHOLD && !isResolved) {\n marker.style.borderStyle = \"dashed\";\n marker.style.opacity = \"0.7\";\n marker.title = tWithParams(this.t, \"marker.approximate\", { confidence: Math.round(confidence * 100) });\n } else {\n marker.style.borderStyle = \"solid\";\n marker.style.opacity = \"1\";\n marker.title = \"\";\n }\n }\n\n private createMarker(number: number, feedback: FeedbackResponse, pos: { top: number; left: number }): HTMLElement {\n const typeColor = getTypeColor(feedback.type, this.colors);\n // Closed feedbacks (resolved, wont_fix) render as muted checkmark markers.\n const isResolved = isClosedStatus(feedback.status);\n\n const marker = el(\"div\", {\n style: `\n position:absolute;\n top:${pos.top}px;\n left:${pos.left}px;\n width:26px;height:26px;\n border-radius:50%;\n background:${isResolved ? \"rgba(241,245,249,0.9)\" : \"rgba(255,255,255,0.92)\"};\n border:2px solid ${isResolved ? \"#cbd5e1\" : typeColor};\n display:flex;align-items:center;justify-content:center;\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:11px;font-weight:700;\n color:${isResolved ? \"#94a3b8\" : typeColor};\n cursor:pointer;pointer-events:auto;\n box-shadow:${isResolved ? \"0 2px 8px rgba(0,0,0,0.06)\" : `0 2px 12px ${typeColor}25, 0 2px 6px rgba(0,0,0,0.06)`};\n transition:top 0.25s cubic-bezier(0.34, 1.56, 0.64, 1), left 0.25s cubic-bezier(0.34, 1.56, 0.64, 1), transform 0.15s ease, box-shadow 0.15s ease;\n user-select:none;\n -webkit-font-smoothing:antialiased;\n `,\n });\n marker.dataset.feedbackId = feedback.id;\n marker.setAttribute(\"tabindex\", \"0\");\n marker.setAttribute(\"role\", \"button\");\n const truncatedMessage = feedback.message.length > 60 ? `${feedback.message.slice(0, 60)}...` : feedback.message;\n const ariaLabel = tWithParams(this.t, \"marker.aria\", {\n number,\n type: getTypeLabel(feedback.type, this.t),\n message: truncatedMessage,\n });\n marker.setAttribute(\"aria-label\", ariaLabel);\n marker.setAttribute(\"aria-describedby\", this.tooltip.tooltipId);\n setText(marker, isResolved ? \"\\u2713\" : String(number));\n\n marker.addEventListener(\"mouseenter\", () => {\n marker.style.transform = \"scale(1.2)\";\n marker.style.boxShadow = isResolved\n ? \"0 4px 16px rgba(0,0,0,0.1)\"\n : `0 4px 20px ${typeColor}35, 0 4px 12px rgba(0,0,0,0.08)`;\n this.tooltip.show(feedback, marker.getBoundingClientRect());\n if (!this.pinnedFeedback) this.showHighlight(feedback);\n });\n\n marker.addEventListener(\"mouseleave\", () => {\n marker.style.transform = \"scale(1)\";\n marker.style.boxShadow = isResolved\n ? \"0 2px 8px rgba(0,0,0,0.06)\"\n : `0 2px 12px ${typeColor}25, 0 2px 6px rgba(0,0,0,0.06)`;\n this.tooltip.scheduleHide();\n if (!this.pinnedFeedback) this.clearHighlight();\n });\n\n // WCAG 1.4.13 — tooltip must be reachable via keyboard (focus), not only\n // hover. Mirror mouseenter/mouseleave behaviour for focus/blur so a sighted\n // keyboard user gets the same affordance as a mouse user.\n marker.addEventListener(\"focus\", () => {\n this.tooltip.show(feedback, marker.getBoundingClientRect());\n if (!this.pinnedFeedback) this.showHighlight(feedback);\n });\n\n marker.addEventListener(\"blur\", () => {\n this.tooltip.scheduleHide();\n if (!this.pinnedFeedback) this.clearHighlight();\n });\n\n const activateMarker = (e: MouseEvent | KeyboardEvent) => {\n if (e instanceof MouseEvent && this.handleClusterClick(marker, e)) return;\n this.pinHighlight(feedback);\n this.bus.emit(\"panel:toggle\", true);\n marker.dispatchEvent(\n new CustomEvent(\"sp-marker-click\", {\n detail: { feedbackId: feedback.id },\n bubbles: true,\n }),\n );\n };\n\n marker.addEventListener(\"click\", (e) => activateMarker(e));\n marker.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n activateMarker(e);\n }\n });\n\n return marker;\n }\n\n /**\n * Scroll the annotation into view, pin its highlight, and pulse its marker.\n *\n * Powers the `deepLink` config option and the public\n * `instance.focusFeedback(id)` method. Returns `false` when no entry\n * matches — caller logs that case, the manager stays silent.\n *\n * Scrolling uses the marker element's current document position via\n * `scrollIntoView`, not the original `scrollX/scrollY` captured at\n * annotation time. That keeps the focus correct after layout changes\n * (responsive breakpoints, lazy-loaded content) because the marker has\n * already been re-positioned to track the live anchor.\n */\n focusFeedback(feedbackId: string): boolean {\n const entry = this.entries.find((e) => e.feedback.id === feedbackId);\n if (!entry) return false;\n const markerEl = entry.elements[0];\n if (markerEl) {\n markerEl.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n }\n this.pinHighlight(entry.feedback);\n this.highlight(feedbackId);\n return true;\n }\n\n highlight(feedbackId: string): void {\n for (const entry of this.entries) {\n if (entry.feedback.id === feedbackId) {\n for (const markerEl of entry.elements) {\n markerEl.style.animation = \"sp-pulse-ring 0.7s ease-out\";\n markerEl.addEventListener(\n \"animationend\",\n () => {\n markerEl.style.animation = \"\";\n },\n { once: true },\n );\n }\n }\n }\n }\n\n showHighlight(feedback: FeedbackResponse): void {\n this.removeHighlightElements();\n for (const annotation of feedback.annotations) {\n const resolved = resolveAnnotation(toAnchorData(annotation), toRectData(annotation));\n if (!resolved) continue;\n\n const typeColor = getTypeColor(feedback.type, this.colors);\n const rect = resolved.rect;\n const highlight = el(\"div\", {\n style: `\n position:absolute;\n top:${rect.top + window.scrollY}px;\n left:${rect.left + window.scrollX}px;\n width:${rect.width}px;height:${rect.height}px;\n border:2px solid ${typeColor};\n background:${typeColor}0c;\n border-radius:8px;\n pointer-events:none;z-index:-1;\n opacity:0;\n box-shadow:0 0 16px ${typeColor}20;\n transition:opacity ${HIGHLIGHT_FADE}ms ease;\n `,\n });\n this.container.appendChild(highlight);\n this.highlightElements.push(highlight);\n void highlight.offsetHeight; // Force reflow for CSS transition\n highlight.style.opacity = \"1\";\n }\n }\n\n pinHighlight(feedback: FeedbackResponse): void {\n this.unpinHighlight();\n this.showHighlight(feedback);\n this.pinnedFeedback = feedback;\n this.onDocumentClick = (e: MouseEvent) => {\n if (this.container.contains(e.target as Node)) return;\n this.unpinHighlight();\n };\n document.addEventListener(\"click\", this.onDocumentClick, { capture: true });\n }\n\n private unpinHighlight(): void {\n if (this.onDocumentClick) {\n document.removeEventListener(\"click\", this.onDocumentClick, { capture: true });\n this.onDocumentClick = null;\n }\n this.pinnedFeedback = null;\n this.clearHighlight();\n }\n\n private clearHighlight(): void {\n for (const h of this.highlightElements) {\n h.style.opacity = \"0\";\n setTimeout(() => h.remove(), HIGHLIGHT_FADE);\n }\n this.highlightElements = [];\n }\n\n private removeHighlightElements(): void {\n for (const h of this.highlightElements) h.remove();\n this.highlightElements = [];\n }\n\n clear(): void {\n this.unpinHighlight();\n this.container.replaceChildren();\n this.entries = [];\n this.clusters = [];\n this.anchorCache.clear();\n }\n\n destroy(): void {\n this.unpinHighlight();\n if (this.repositionTimer) {\n if (\"cancelIdleCallback\" in window) {\n window.cancelIdleCallback(this.repositionTimer);\n }\n clearTimeout(this.repositionTimer);\n }\n if (this.resizeHandler) window.removeEventListener(\"resize\", this.resizeHandler);\n if (this.scrollHandler) window.removeEventListener(\"scroll\", this.scrollHandler, { capture: true });\n if (this.onDocumentClickForClusters) document.removeEventListener(\"click\", this.onDocumentClickForClusters);\n this.mutationObserver?.disconnect();\n this.container.remove();\n }\n}\n","import {\n type AnnotationRecord,\n type AnnotationResponse,\n type FeedbackPayload,\n type FeedbackRecord,\n type FeedbackResponse,\n type FeedbackResponseList,\n flattenAnnotation,\n type SitepingStore,\n toFeedbackUpdate,\n} from \"@siteping/core\";\nimport type { GetFeedbacksOptions, WidgetClient } from \"./api-client.js\";\n\n/**\n * `WidgetClient` implementation that delegates directly to a `SitepingStore`.\n *\n * Used in client-side mode — the widget calls the store in-process instead of\n * making HTTP requests. Handles the same conversions the HTTP handler normally\n * performs: flattening annotations and serializing dates.\n */\nexport class StoreClient implements WidgetClient {\n constructor(\n private readonly store: SitepingStore,\n private readonly projectName: string,\n ) {}\n\n async sendFeedback(payload: FeedbackPayload): Promise<FeedbackResponse> {\n const record = await this.store.createFeedback({\n projectName: payload.projectName,\n type: payload.type,\n message: payload.message,\n status: \"open\",\n url: payload.url,\n urlPattern: payload.urlPattern ?? null,\n viewport: payload.viewport,\n userAgent: payload.userAgent,\n authorName: payload.authorName,\n authorEmail: payload.authorEmail,\n clientId: payload.clientId,\n annotations: payload.annotations.map(flattenAnnotation),\n screenshotDataUrl: payload.screenshotDataUrl ?? null,\n screenshotRegion: payload.screenshotRegion ?? null,\n diagnostics: payload.diagnostics ?? null,\n });\n\n return toResponse(record);\n }\n\n async getFeedbacks(projectName: string, options?: GetFeedbacksOptions): Promise<FeedbackResponseList> {\n const { feedbacks, total } = await this.store.getFeedbacks({\n projectName,\n page: options?.page,\n limit: options?.limit,\n type: options?.type,\n status: options?.status,\n statuses: options?.statuses,\n search: options?.search,\n url: options?.url,\n urlPattern: options?.urlPattern,\n });\n\n return { feedbacks: feedbacks.map(toResponse), total };\n }\n\n async resolveFeedback(id: string, resolved: boolean): Promise<FeedbackResponse> {\n const record = await this.store.updateFeedback(id, toFeedbackUpdate(resolved ? \"resolved\" : \"open\"));\n return toResponse(record);\n }\n\n async deleteFeedback(id: string): Promise<void> {\n await this.store.deleteFeedback(id);\n }\n\n async deleteAllFeedbacks(projectName: string): Promise<void> {\n await this.store.deleteAllFeedbacks(projectName);\n }\n}\n\n// ---------------------------------------------------------------------------\n// FeedbackRecord (Date) → FeedbackResponse (string) serialization\n// ---------------------------------------------------------------------------\n\nfunction toResponse(record: FeedbackRecord): FeedbackResponse {\n return {\n id: record.id,\n projectName: record.projectName,\n type: record.type,\n message: record.message,\n status: record.status,\n url: record.url,\n urlPattern: record.urlPattern ?? null,\n viewport: record.viewport,\n userAgent: record.userAgent,\n authorName: record.authorName,\n authorEmail: record.authorEmail,\n resolvedAt: record.resolvedAt?.toISOString() ?? null,\n createdAt: record.createdAt.toISOString(),\n updatedAt: record.updatedAt.toISOString(),\n annotations: record.annotations.map(toAnnotationResponse),\n screenshotUrl: record.screenshotUrl ?? null,\n screenshotRegion: record.screenshotRegion ?? null,\n diagnostics: record.diagnostics ?? null,\n };\n}\n\nfunction toAnnotationResponse(ann: AnnotationRecord): AnnotationResponse {\n return {\n id: ann.id,\n feedbackId: ann.feedbackId,\n cssSelector: ann.cssSelector,\n xpath: ann.xpath,\n textSnippet: ann.textSnippet,\n elementTag: ann.elementTag,\n elementId: ann.elementId,\n textPrefix: ann.textPrefix,\n textSuffix: ann.textSuffix,\n fingerprint: ann.fingerprint,\n neighborText: ann.neighborText,\n anchorKey: ann.anchorKey ?? null,\n xPct: ann.xPct,\n yPct: ann.yPct,\n wPct: ann.wPct,\n hPct: ann.hPct,\n scrollX: ann.scrollX,\n scrollY: ann.scrollY,\n viewportW: ann.viewportW,\n viewportH: ann.viewportH,\n devicePixelRatio: ann.devicePixelRatio,\n createdAt: ann.createdAt.toISOString(),\n };\n}\n","/**\n * CSS keyframes and animation utilities — Glassmorphism edition.\n *\n * Uses CSS-only spring animations via linear() timing function\n * and refined easing curves for premium motion design.\n */\n\n// Spring easing — computed from a spring simulation (damping: 15, stiffness: 100)\nconst SPRING_LINEAR = `linear(0, 0.006, 0.025, 0.06, 0.11, 0.17, 0.25, 0.34, 0.45, 0.56, 0.67, 0.78, 0.88, 0.95, 1.01, 1.04, 1.05, 1.04, 1.02, 1, 0.99, 1)`;\n\n// Ease-out-expo — fast start, smooth deceleration\nconst EASE_OUT_EXPO = `cubic-bezier(0.16, 1, 0.3, 1)`;\n\n// Spring overshoot — bouncy entrance\nconst SPRING_OVERSHOOT = `cubic-bezier(0.34, 1.56, 0.64, 1)`;\n\n// Smooth decel — for glass transitions\nconst EASE_OUT_QUART = `cubic-bezier(0.25, 1, 0.5, 1)`;\n\nexport const ANIMATION_CSS = `\n /* ---- Keyframes ---- */\n\n @keyframes sp-fab-in {\n from {\n transform: scale(0) rotate(-180deg);\n opacity: 0;\n }\n to {\n transform: scale(1) rotate(0deg);\n opacity: 1;\n }\n }\n\n @keyframes sp-fab-glow {\n 0%, 100% { box-shadow: 0 4px 20px var(--sp-accent-glow), 0 2px 8px rgba(0, 0, 0, 0.08); }\n 50% { box-shadow: 0 4px 28px var(--sp-accent-glow), 0 2px 12px rgba(0, 0, 0, 0.1); }\n }\n\n @keyframes sp-marker-in {\n 0% {\n transform: scale(0);\n opacity: 0;\n }\n 60% {\n transform: scale(1.2);\n opacity: 1;\n }\n 100% {\n transform: scale(1);\n }\n }\n\n @keyframes sp-pulse-ring {\n 0% {\n box-shadow: 0 0 0 0 var(--sp-accent-glow);\n }\n 70% {\n box-shadow: 0 0 0 8px transparent;\n }\n 100% {\n box-shadow: 0 0 0 0 transparent;\n }\n }\n\n @keyframes sp-flash-bg {\n 0% { background-color: var(--sp-accent-light); }\n 100% { background-color: transparent; }\n }\n\n @keyframes sp-slide-up {\n from {\n transform: translateY(8px);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n }\n\n @keyframes sp-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n\n @keyframes sp-shimmer {\n 0% { background-position: -200% 0; }\n 100% { background-position: 200% 0; }\n }\n\n /* ---- Animation classes ---- */\n\n .sp-anim-fab-in {\n animation: sp-fab-in 0.5s ${SPRING_LINEAR} both;\n }\n\n .sp-anim-marker-in {\n animation: sp-marker-in 0.35s ${SPRING_OVERSHOOT} both;\n }\n\n .sp-anim-pulse {\n animation: sp-pulse-ring 0.7s ease-out;\n }\n\n .sp-anim-flash {\n animation: sp-flash-bg 0.5s ${EASE_OUT_QUART};\n }\n\n .sp-anim-slide-up {\n animation: sp-slide-up 0.3s ${EASE_OUT_EXPO} both;\n }\n\n .sp-anim-fade-in {\n animation: sp-fade-in 0.2s ease-out both;\n }\n\n /* ---- Transition utilities ---- */\n\n .sp-panel {\n transform: translateX(110%);\n transition: transform 0.4s ${EASE_OUT_EXPO};\n }\n\n .sp-panel.sp-panel--open {\n transform: translateX(0);\n }\n\n .sp-radial-item {\n opacity: 0;\n pointer-events: none;\n transform: translate(0, 0) scale(0.8);\n transition:\n transform 0.35s ${SPRING_OVERSHOOT},\n opacity 0.2s ease,\n background 0.2s ease,\n border-color 0.2s ease,\n box-shadow 0.2s ease;\n }\n\n .sp-radial-item.sp-radial-item--open {\n opacity: 1;\n pointer-events: auto;\n }\n\n /* Stagger delay via CSS custom property --sp-i */\n .sp-radial-item {\n transition-delay: calc(var(--sp-i, 0) * 50ms);\n }\n\n /* ---- Card stagger animation ---- */\n\n @keyframes sp-card-in {\n from {\n transform: translateY(12px);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n }\n\n .sp-card {\n animation: sp-card-in 0.35s ${EASE_OUT_EXPO} both;\n animation-delay: calc(var(--sp-card-i, 0) * 40ms);\n }\n\n /* ---- Loading spinner ---- */\n\n @keyframes sp-spin {\n to { transform: rotate(360deg); }\n }\n\n .sp-spinner {\n width: 20px;\n height: 20px;\n border: 2px solid var(--sp-border);\n border-top-color: var(--sp-accent);\n border-radius: 50%;\n animation: sp-spin 0.6s linear infinite;\n }\n\n /* ---- Badge bounce ---- */\n\n @keyframes sp-badge-in {\n 0% { transform: scale(0); }\n 60% { transform: scale(1.3); }\n 100% { transform: scale(1); }\n }\n\n .sp-fab-badge {\n animation: sp-badge-in 0.4s ${SPRING_OVERSHOOT} both;\n }\n\n /* ---- Reduced motion ---- */\n\n @media (prefers-reduced-motion: reduce) {\n *, *::before, *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n }\n\n`;\n","import { Z_INDEX_MAX } from \"../constants.js\";\nimport { EXPORT_CSS } from \"../export-utils.js\";\nimport { BULK_CSS } from \"../panel-bulk.js\";\nimport { DETAIL_CSS } from \"../panel-detail.js\";\nimport { SORT_CSS } from \"../panel-sort.js\";\nimport { STATS_CSS } from \"../panel-stats.js\";\nimport { SHORTCUTS_CSS } from \"../shortcuts.js\";\nimport { ANIMATION_CSS } from \"./animations.js\";\nimport { cssVariables, type ThemeColors } from \"./theme.js\";\n\n/**\n * Build the complete CSS stylesheet for the Shadow DOM.\n *\n * Design: Glassmorphism — frosted glass surfaces, soft depth,\n * accent gradients, premium micro-interactions.\n *\n * Principles:\n * - :host uses `all: initial` to block inherited styles\n * - All classes prefixed with sp- (defense in depth)\n * - CSS custom properties for theming\n * - No external fonts — system-ui stack (Inter if available)\n * - :focus-visible on all interactive elements\n * - prefers-reduced-motion support\n */\nexport function buildStyles(colors: ThemeColors): string {\n return `\n :host {\n all: initial;\n position: fixed;\n z-index: ${Z_INDEX_MAX};\n font-family: var(--sp-font);\n font-size: 14px;\n line-height: 1.5;\n color: var(--sp-text);\n /* Match native sub-controls (autofill, scrollbars, etc.) to the resolved theme */\n color-scheme: ${colors.bg === \"#ffffff\" ? \"light\" : \"dark\"};\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n ${cssVariables(colors)}\n\n /* Identity modal — theme-aware backdrop + panel */\n --sp-identity-bg: ${colors.glassBgHeavy};\n --sp-identity-overlay: ${colors.bg === \"#ffffff\" ? \"rgba(15, 23, 42, 0.2)\" : \"rgba(0, 0, 0, 0.4)\"};\n }\n\n *, *::before, *::after {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n }\n\n /* ============================\n Focus visible (accessibility)\n ============================ */\n\n :focus-visible {\n outline: 2px solid var(--sp-accent);\n outline-offset: 2px;\n /* Double-ring against any background colour: the bg-coloured halo\n separates the accent ring from busy host-page surfaces. */\n box-shadow: 0 0 0 4px var(--sp-bg);\n }\n\n /* ============================\n FAB (Floating Action Button)\n ============================ */\n\n .sp-fab {\n position: fixed;\n width: 52px;\n height: 52px;\n border-radius: var(--sp-radius-full);\n background: var(--sp-accent-gradient);\n color: #fff;\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow:\n 0 4px 20px var(--sp-accent-glow),\n 0 2px 8px rgba(0, 0, 0, 0.08);\n transition:\n transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1),\n box-shadow 0.3s ease;\n outline: none;\n }\n\n .sp-fab:focus-visible {\n outline: 2px solid #fff;\n outline-offset: 3px;\n }\n\n .sp-fab:hover {\n transform: translateY(-2px) scale(1.05);\n box-shadow:\n 0 8px 28px var(--sp-accent-glow),\n 0 4px 12px rgba(0, 0, 0, 0.1);\n }\n\n .sp-fab:active {\n transform: translateY(0) scale(0.95);\n transition-duration: 0.1s;\n }\n\n .sp-fab--bottom-right {\n bottom: 24px;\n right: 24px;\n }\n\n .sp-fab--bottom-left {\n bottom: 24px;\n left: 24px;\n }\n\n .sp-fab svg {\n width: 22px;\n height: 22px;\n fill: currentColor;\n transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);\n }\n\n /* ---- FAB Badge ---- */\n\n .sp-fab-badge {\n position: absolute;\n top: -4px;\n right: -4px;\n min-width: 20px;\n height: 20px;\n padding: 0 6px;\n border-radius: var(--sp-radius-full);\n background: #ef4444;\n color: #fff;\n font-size: 11px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 2px solid #fff;\n pointer-events: none;\n font-family: var(--sp-font);\n line-height: 1;\n }\n\n /* ============================\n Radial Menu\n ============================ */\n\n .sp-radial {\n position: fixed;\n pointer-events: none;\n width: 52px;\n height: 52px;\n }\n\n .sp-radial--bottom-right {\n bottom: 24px;\n right: 24px;\n }\n\n .sp-radial--bottom-left {\n bottom: 24px;\n left: 24px;\n }\n\n .sp-radial-item {\n position: absolute;\n left: 4px;\n bottom: 4px;\n width: 44px;\n height: 44px;\n border-radius: var(--sp-radius-full);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur));\n -webkit-backdrop-filter: blur(var(--sp-blur));\n color: var(--sp-text);\n border: 1px solid var(--sp-glass-border);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: var(--sp-shadow-md);\n font-size: 12px;\n font-weight: 600;\n }\n\n .sp-radial-item:hover,\n .sp-radial-item:focus-visible {\n background: rgba(255, 255, 255, 0.95);\n border-color: var(--sp-accent);\n color: var(--sp-accent);\n box-shadow:\n var(--sp-shadow-md),\n 0 0 0 3px var(--sp-accent-light);\n outline: none;\n }\n\n .sp-radial-item svg {\n width: 18px;\n height: 18px;\n flex-shrink: 0;\n stroke: currentColor;\n fill: none;\n }\n\n .sp-radial-label {\n white-space: nowrap;\n font-size: 12px;\n font-weight: 500;\n color: var(--sp-text);\n pointer-events: none;\n opacity: 0;\n padding: 4px 12px;\n border-radius: var(--sp-radius);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-sm);\n transform: translateX(4px);\n transition: opacity 0.2s ease, transform 0.2s ease;\n }\n\n .sp-radial-item:hover .sp-radial-label,\n .sp-radial-item:focus-visible .sp-radial-label {\n opacity: 1;\n transform: translateX(0);\n }\n\n /* ============================\n Panel (Side drawer)\n ============================ */\n\n .sp-panel {\n position: fixed;\n top: 0;\n right: 0;\n width: 400px;\n max-width: 100vw;\n height: 100vh;\n height: 100dvh;\n background: var(--sp-glass-bg);\n backdrop-filter: blur(var(--sp-blur-heavy));\n -webkit-backdrop-filter: blur(var(--sp-blur-heavy));\n border-left: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-xl);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n @media (max-width: 480px) {\n .sp-panel {\n width: 100vw;\n border-left: none;\n }\n }\n\n .sp-panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 20px 24px;\n border-bottom: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur));\n -webkit-backdrop-filter: blur(var(--sp-blur));\n position: relative;\n z-index: 2;\n }\n\n .sp-panel-title {\n font-size: 17px;\n font-weight: 700;\n color: var(--sp-text);\n letter-spacing: -0.02em;\n }\n\n .sp-panel-close {\n width: 44px;\n height: 44px;\n border-radius: var(--sp-radius);\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--sp-text-tertiary);\n transition: all 0.2s ease;\n }\n\n .sp-panel-close:hover {\n background: var(--sp-bg-hover);\n color: var(--sp-text);\n }\n\n .sp-panel-close svg {\n width: 16px;\n height: 16px;\n }\n\n /* ============================\n Filters & Search\n ============================ */\n\n .sp-filters {\n padding: 16px 24px;\n border-bottom: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur));\n -webkit-backdrop-filter: blur(var(--sp-blur));\n position: sticky;\n top: 0;\n z-index: 1;\n }\n\n .sp-search-wrap {\n position: relative;\n margin-bottom: 12px;\n }\n\n .sp-search {\n width: 100%;\n height: 40px;\n padding: 0 12px 0 38px;\n border-radius: var(--sp-radius);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n color: var(--sp-text);\n font-family: var(--sp-font);\n font-size: 13px;\n outline: none;\n transition: all 0.2s ease;\n }\n\n .sp-search::placeholder {\n color: var(--sp-text-tertiary);\n }\n\n .sp-search:focus {\n border-color: var(--sp-accent);\n box-shadow: 0 0 0 3px var(--sp-accent-light);\n background: var(--sp-bg);\n }\n\n .sp-search-icon {\n position: absolute;\n left: 12px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--sp-text-tertiary);\n width: 16px;\n height: 16px;\n transition: color 0.2s ease;\n }\n\n .sp-search:focus ~ .sp-search-icon,\n .sp-search-wrap:focus-within .sp-search-icon {\n color: var(--sp-accent);\n }\n\n /* ============================\n Filter bar (type dropdown + status segmented)\n ============================ */\n\n .sp-filter-bar {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 8px;\n flex-wrap: wrap;\n }\n\n /* ============================\n Type filter dropdown\n ============================ */\n\n .sp-filter-dropdown {\n position: relative;\n flex: 1 1 auto;\n min-width: 0;\n }\n\n .sp-filter-dropdown-btn {\n --sp-chip-color: var(--sp-text-secondary);\n --sp-chip-bg: var(--sp-glass-bg-heavy);\n\n display: inline-flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n height: 32px;\n padding: 0 8px 0 10px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n color: var(--sp-text);\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n transition: background 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease;\n }\n\n .sp-filter-dropdown-btn:hover {\n border-color: var(--sp-chip-color);\n background: var(--sp-chip-bg);\n }\n\n .sp-filter-dropdown-btn[aria-expanded=\"true\"] {\n border-color: var(--sp-chip-color);\n background: var(--sp-chip-bg);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--sp-chip-color) 14%, transparent);\n }\n\n .sp-filter-dropdown-btn--filtered {\n border-color: var(--sp-chip-color);\n background: var(--sp-chip-bg);\n }\n\n .sp-filter-dropdown-btn__icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 18px;\n flex-shrink: 0;\n color: var(--sp-chip-color);\n }\n\n .sp-filter-dropdown-btn__icon svg {\n width: 14px;\n height: 14px;\n }\n\n .sp-filter-dropdown-btn__label {\n display: inline-flex;\n align-items: baseline;\n gap: 6px;\n flex: 1;\n min-width: 0;\n overflow: hidden;\n }\n\n .sp-filter-dropdown-btn__prefix {\n color: var(--sp-text-tertiary);\n font-weight: 500;\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n }\n\n .sp-filter-dropdown-btn__value {\n color: var(--sp-chip-color);\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .sp-filter-dropdown-btn__chevron {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 14px;\n height: 14px;\n flex-shrink: 0;\n color: var(--sp-text-tertiary);\n transition: transform 0.18s ease, color 0.18s ease;\n }\n\n .sp-filter-dropdown-btn__chevron svg {\n width: 12px;\n height: 12px;\n }\n\n .sp-filter-dropdown-btn[aria-expanded=\"true\"] .sp-filter-dropdown-btn__chevron {\n transform: rotate(180deg);\n color: var(--sp-chip-color);\n }\n\n .sp-filter-dropdown-menu {\n position: absolute;\n top: calc(100% + 6px);\n left: 0;\n right: 0;\n min-width: 180px;\n padding: 4px;\n border-radius: var(--sp-radius);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur-heavy));\n -webkit-backdrop-filter: blur(var(--sp-blur-heavy));\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-md);\n z-index: 10;\n animation: sp-filter-menu-in 0.15s ease-out both;\n }\n\n @keyframes sp-filter-menu-in {\n from { opacity: 0; transform: translateY(-4px) scale(0.98); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n }\n\n .sp-filter-dropdown-option {\n --sp-chip-color: var(--sp-text-secondary);\n --sp-chip-bg: transparent;\n\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 8px 10px;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: var(--sp-text);\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n text-align: left;\n transition: background 0.12s ease, color 0.12s ease;\n }\n\n .sp-filter-dropdown-option__icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n flex-shrink: 0;\n border-radius: 6px;\n background: var(--sp-chip-bg);\n color: var(--sp-chip-color);\n }\n\n .sp-filter-dropdown-option__icon svg {\n width: 13px;\n height: 13px;\n }\n\n .sp-filter-dropdown-option__label {\n flex: 1;\n min-width: 0;\n }\n\n .sp-filter-dropdown-option__check {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 14px;\n height: 14px;\n flex-shrink: 0;\n color: var(--sp-chip-color);\n }\n\n .sp-filter-dropdown-option__check svg {\n width: 13px;\n height: 13px;\n }\n\n .sp-filter-dropdown-option:hover {\n background: var(--sp-bg-hover);\n }\n\n .sp-filter-dropdown-option--active {\n color: var(--sp-chip-color);\n font-weight: 600;\n }\n\n .sp-filter-dropdown-option--active:hover {\n background: var(--sp-chip-bg);\n }\n\n /* ============================\n Status segmented control\n ============================ */\n\n .sp-segmented {\n display: inline-flex;\n align-items: stretch;\n padding: 2px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n flex-shrink: 0;\n }\n\n .sp-segmented__btn {\n --sp-chip-color: var(--sp-text-tertiary);\n --sp-chip-bg: transparent;\n\n display: inline-flex;\n align-items: center;\n gap: 5px;\n height: 26px;\n padding: 0 10px;\n border: none;\n border-radius: var(--sp-radius-full);\n background: transparent;\n color: var(--sp-text-secondary);\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n transition: background 0.18s ease, color 0.18s ease, box-shadow 0.18s ease;\n }\n\n .sp-segmented__icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 13px;\n height: 13px;\n flex-shrink: 0;\n color: var(--sp-chip-color);\n transition: color 0.18s ease, transform 0.18s ease;\n }\n\n .sp-segmented__icon svg {\n width: 13px;\n height: 13px;\n }\n\n .sp-segmented__btn:hover {\n color: var(--sp-chip-color);\n }\n\n .sp-segmented__btn:hover .sp-segmented__icon {\n color: var(--sp-chip-color);\n }\n\n .sp-segmented__btn--active {\n background: var(--sp-chip-bg);\n color: var(--sp-chip-color);\n font-weight: 600;\n box-shadow:\n inset 0 0 0 1px color-mix(in srgb, var(--sp-chip-color) 35%, transparent),\n 0 1px 2px rgba(0, 0, 0, 0.04);\n }\n\n .sp-segmented__btn--active .sp-segmented__icon {\n color: var(--sp-chip-color);\n }\n\n .sp-segmented__btn--open.sp-segmented__btn--active .sp-segmented__icon {\n animation: sp-segmented-pulse 2.4s ease-in-out infinite;\n }\n\n @keyframes sp-segmented-pulse {\n 0%, 100% { transform: scale(1); }\n 50% { transform: scale(0.85); }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .sp-filter-dropdown-btn,\n .sp-filter-dropdown-btn__chevron,\n .sp-filter-dropdown-option,\n .sp-segmented__btn,\n .sp-segmented__icon {\n transition: none;\n }\n .sp-filter-dropdown-menu {\n animation: none;\n }\n .sp-segmented__btn--open.sp-segmented__btn--active .sp-segmented__icon {\n animation: none;\n }\n }\n\n /* ============================\n Feedback Cards\n ============================ */\n\n .sp-list {\n flex: 1;\n overflow-y: auto;\n padding: 8px 12px;\n }\n\n .sp-list::-webkit-scrollbar {\n width: 6px;\n }\n\n .sp-list::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .sp-list::-webkit-scrollbar-thumb {\n background: var(--sp-border);\n border-radius: var(--sp-radius-full);\n }\n\n .sp-list::-webkit-scrollbar-thumb:hover {\n background: var(--sp-text-tertiary);\n }\n\n .sp-card {\n display: flex;\n padding: 14px 16px;\n margin-bottom: 6px;\n cursor: pointer;\n border-radius: var(--sp-radius);\n background: var(--sp-glass-bg-heavy);\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-xs);\n transition: all 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);\n }\n\n .sp-card:hover {\n background: var(--sp-bg);\n border-color: var(--sp-border);\n box-shadow: var(--sp-shadow-md);\n transform: translateY(-2px);\n }\n\n .sp-card:active {\n transform: translateY(0) scale(0.99);\n transition-duration: 0.1s;\n }\n\n .sp-card-bar {\n width: 3px;\n border-radius: var(--sp-radius-full);\n margin-right: 14px;\n flex-shrink: 0;\n }\n\n .sp-card-body {\n flex: 1;\n min-width: 0;\n }\n\n .sp-card-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 6px;\n }\n\n .sp-card-number {\n font-size: 12px;\n font-weight: 700;\n color: var(--sp-text-tertiary);\n font-variant-numeric: tabular-nums;\n }\n\n .sp-badge {\n padding: 2px 10px;\n border-radius: var(--sp-radius-full);\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.02em;\n }\n\n .sp-card-date {\n font-size: 11px;\n color: var(--sp-text-tertiary);\n margin-left: auto;\n }\n\n .sp-card-message {\n font-size: 13px;\n line-height: 1.5;\n color: var(--sp-text);\n display: -webkit-box;\n -webkit-line-clamp: 3;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n\n .sp-card-message--expanded {\n -webkit-line-clamp: unset;\n }\n\n .sp-card-expand {\n font-size: 12px;\n font-weight: 500;\n color: var(--sp-accent);\n cursor: pointer;\n background: none;\n border: none;\n padding: 4px 0;\n font-family: var(--sp-font);\n transition: opacity 0.15s ease;\n }\n\n .sp-card-expand:hover {\n opacity: 0.8;\n }\n\n .sp-card-footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 6px;\n margin-top: 10px;\n }\n\n .sp-btn-resolve,\n .sp-btn-delete {\n padding: 8px 14px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: transparent;\n color: var(--sp-text-secondary);\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 4px;\n transition: all 0.2s ease;\n }\n\n .sp-btn-resolve svg,\n .sp-btn-delete svg {\n width: 14px;\n height: 14px;\n }\n\n .sp-btn-resolve:hover {\n border-color: #22c55e;\n color: #22c55e;\n background: rgba(34, 197, 94, 0.06);\n }\n\n .sp-btn-delete:hover {\n border-color: #ef4444;\n color: #ef4444;\n background: rgba(239, 68, 68, 0.06);\n }\n\n .sp-btn-resolve:disabled,\n .sp-btn-delete:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n }\n\n .sp-spinner--sm {\n width: 14px;\n height: 14px;\n }\n\n /* ---- Delete All (header) ---- */\n\n .sp-panel-header-right {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .sp-btn-delete-all {\n padding: 5px 12px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: transparent;\n color: var(--sp-text-tertiary);\n font-family: var(--sp-font);\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 4px;\n transition: all 0.2s ease;\n }\n\n .sp-btn-delete-all svg {\n width: 13px;\n height: 13px;\n }\n\n .sp-btn-delete-all:hover {\n border-color: #ef4444;\n color: #ef4444;\n background: rgba(239, 68, 68, 0.06);\n }\n\n .sp-btn-delete-all:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n }\n\n /* ---- Confirm Dialog ---- */\n\n .sp-confirm-backdrop {\n position: fixed;\n inset: 0;\n background: var(--sp-backdrop, rgba(15, 23, 42, 0.2));\n backdrop-filter: blur(var(--sp-blur));\n -webkit-backdrop-filter: blur(var(--sp-blur));\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: ${Z_INDEX_MAX};\n opacity: 0;\n transition: opacity 0.2s ease;\n }\n\n .sp-confirm-dialog {\n width: 340px;\n padding: 28px;\n border-radius: 20px;\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur-heavy));\n -webkit-backdrop-filter: blur(var(--sp-blur-heavy));\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-xl);\n font-family: var(--sp-font);\n transform: translateY(8px) scale(0.97);\n transition: transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);\n }\n\n .sp-confirm-title {\n font-size: 17px;\n font-weight: 700;\n color: var(--sp-text);\n letter-spacing: -0.02em;\n margin-bottom: 8px;\n }\n\n .sp-confirm-message {\n font-size: 14px;\n color: var(--sp-text-secondary);\n line-height: 1.5;\n margin-bottom: 20px;\n }\n\n .sp-confirm-actions {\n display: flex;\n gap: 8px;\n justify-content: flex-end;\n }\n\n .sp-btn-danger {\n height: 40px;\n padding: 0 22px;\n border-radius: var(--sp-radius);\n border: none;\n background: #ef4444;\n color: #fff;\n font-family: var(--sp-font);\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n box-shadow: 0 2px 8px rgba(239, 68, 68, 0.25);\n }\n\n .sp-btn-danger:hover {\n background: #dc2626;\n box-shadow: 0 4px 16px rgba(239, 68, 68, 0.3);\n transform: translateY(-1px);\n }\n\n .sp-btn-danger:active {\n transform: translateY(0) scale(0.98);\n transition-duration: 0.1s;\n }\n\n .sp-card--resolved {\n opacity: 0.5;\n }\n\n .sp-card--resolved .sp-card-message {\n text-decoration: line-through;\n text-decoration-color: var(--sp-text-tertiary);\n }\n\n /* ============================\n Loading State\n ============================ */\n\n .sp-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 48px 24px;\n }\n\n /* ============================\n Identity Form\n ============================ */\n\n .sp-identity-title {\n font-size: 17px;\n font-weight: 700;\n color: var(--sp-text);\n letter-spacing: -0.02em;\n }\n\n .sp-input {\n width: 100%;\n height: 42px;\n padding: 0 14px;\n border-radius: var(--sp-radius);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n color: var(--sp-text);\n font-family: var(--sp-font);\n font-size: 14px;\n outline: none;\n transition: all 0.2s ease;\n }\n\n .sp-input::placeholder {\n color: var(--sp-text-tertiary);\n }\n\n .sp-input:focus {\n border-color: var(--sp-accent);\n box-shadow: 0 0 0 3px var(--sp-accent-light);\n background: var(--sp-bg);\n }\n\n .sp-input-label {\n font-size: 13px;\n font-weight: 500;\n color: var(--sp-text-secondary);\n margin-bottom: 6px;\n display: block;\n }\n\n /* ============================\n Buttons\n ============================ */\n\n .sp-btn-primary {\n height: 40px;\n padding: 0 22px;\n border-radius: var(--sp-radius);\n border: none;\n background: var(--sp-accent-gradient);\n color: #fff;\n font-family: var(--sp-font);\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n box-shadow: 0 2px 8px var(--sp-accent-glow);\n }\n\n .sp-btn-primary:hover {\n box-shadow: 0 4px 16px var(--sp-accent-glow);\n transform: translateY(-1px);\n }\n\n .sp-btn-primary:active {\n transform: translateY(0) scale(0.98);\n transition-duration: 0.1s;\n }\n\n .sp-btn-primary:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n transform: none;\n box-shadow: none;\n }\n\n .sp-btn-ghost {\n height: 40px;\n padding: 0 22px;\n border-radius: var(--sp-radius);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n color: var(--sp-text-secondary);\n font-family: var(--sp-font);\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .sp-btn-ghost:hover {\n border-color: var(--sp-accent);\n color: var(--sp-accent);\n background: var(--sp-accent-light);\n }\n\n /* ============================\n Empty State\n ============================ */\n\n .sp-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 56px 24px;\n color: var(--sp-text-tertiary);\n text-align: center;\n gap: 8px;\n animation: sp-fade-in 0.3s ease-out both;\n }\n\n .sp-empty-text {\n font-size: 14px;\n font-weight: 500;\n }\n\n /* ============================\n Load More\n ============================ */\n\n .sp-load-more-wrap {\n display: flex;\n justify-content: center;\n padding: 12px 0 4px;\n }\n\n .sp-btn-load-more {\n width: 100%;\n }\n\n /* ============================\n Forced Colors / High Contrast\n ============================ */\n\n @media (forced-colors: active) {\n .sp-fab,\n .sp-radial-item,\n .sp-filter-dropdown-btn,\n .sp-segmented,\n .sp-segmented__btn,\n .sp-card,\n .sp-panel-close,\n .sp-search,\n .sp-btn-resolve,\n .sp-btn-delete,\n .sp-btn-delete-all,\n .sp-btn-primary,\n .sp-btn-ghost,\n .sp-btn-danger,\n .sp-card-expand,\n .sp-input,\n .sp-confirm-dialog {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n color: ButtonText !important;\n }\n\n .sp-segmented__btn--active {\n background: Highlight !important;\n color: HighlightText !important;\n }\n\n .sp-filter-dropdown-menu {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n }\n\n .sp-filter-dropdown-option--active {\n background: Highlight !important;\n color: HighlightText !important;\n }\n\n .sp-fab:focus-visible,\n .sp-radial-item:focus-visible,\n .sp-filter-dropdown-btn:focus-visible,\n .sp-segmented__btn:focus-visible,\n .sp-filter-dropdown-option:focus-visible,\n .sp-panel-close:focus-visible,\n .sp-btn-resolve:focus-visible,\n .sp-btn-delete:focus-visible,\n .sp-btn-delete-all:focus-visible,\n .sp-btn-primary:focus-visible,\n .sp-btn-ghost:focus-visible,\n .sp-btn-danger:focus-visible,\n .sp-card-expand:focus-visible,\n .sp-input:focus-visible,\n .sp-search:focus-visible {\n outline: 3px solid Highlight !important;\n }\n\n .sp-panel {\n border: 2px solid ButtonText !important;\n }\n\n .sp-fab-badge {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n color: ButtonText !important;\n }\n\n .sp-card-bar {\n background: ButtonText !important;\n }\n }\n\n ${ANIMATION_CSS}\n ${STATS_CSS}\n ${SORT_CSS}\n ${BULK_CSS}\n ${EXPORT_CSS}\n ${SHORTCUTS_CSS}\n ${DETAIL_CSS}\n `;\n}\n","import type { FeedbackResponse } from \"@siteping/core\";\nimport { Z_INDEX_MAX } from \"./constants.js\";\nimport { el, formatRelativeDate, setText } from \"./dom-utils.js\";\nimport { createT, getTypeLabel } from \"./i18n/index.js\";\nimport { getTypeBgColor, getTypeColor, type ThemeColors } from \"./styles/theme.js\";\n\nconst SHOW_DELAY = 120;\nconst HIDE_DELAY = 80;\n\n/**\n * Tooltip shown on annotation marker hover.\n *\n * Glassmorphism design: frosted glass with pastel badge,\n * smooth entrance animation, directional arrow.\n * Lives outside Shadow DOM.\n */\nexport class Tooltip {\n private root: HTMLElement;\n private arrow: HTMLElement;\n private showTimer: ReturnType<typeof setTimeout> | null = null;\n private hideTimer: ReturnType<typeof setTimeout> | null = null;\n private currentFeedbackId: string | null = null;\n\n readonly tooltipId = \"sp-tooltip\";\n\n constructor(\n private readonly colors: ThemeColors,\n private readonly locale: string = \"en\",\n ) {\n this.root = el(\"div\", {\n style: `\n position: fixed;\n z-index: ${Z_INDEX_MAX};\n max-width: 280px;\n padding: 12px 14px;\n border-radius: 14px;\n background: ${this.colors.glassBgHeavy};\n backdrop-filter: blur(24px);\n -webkit-backdrop-filter: blur(24px);\n border: 1px solid ${this.colors.glassBorder};\n box-shadow: 0 8px 32px ${this.colors.shadow}, 0 2px 8px ${this.colors.shadow};\n font-family: \"Inter\", system-ui, -apple-system, sans-serif;\n pointer-events: auto;\n opacity: 0;\n transform: translateY(6px) scale(0.97);\n transition: opacity 0.2s cubic-bezier(0.16, 1, 0.3, 1), transform 0.2s cubic-bezier(0.16, 1, 0.3, 1);\n visibility: hidden;\n -webkit-font-smoothing: antialiased;\n `,\n });\n\n this.root.setAttribute(\"role\", \"tooltip\");\n this.root.id = this.tooltipId;\n\n // Arrow element\n this.arrow = el(\"div\", {\n style: `\n position: absolute;\n width: 12px;\n height: 12px;\n background: ${this.colors.glassBgHeavy};\n border: 1px solid ${this.colors.glassBorder};\n transform: rotate(45deg);\n pointer-events: none;\n `,\n });\n this.root.appendChild(this.arrow);\n\n this.root.addEventListener(\"mouseenter\", () => this.cancelHide());\n this.root.addEventListener(\"mouseleave\", () => this.scheduleHide());\n document.body.appendChild(this.root);\n }\n\n show(feedback: FeedbackResponse, anchorRect: DOMRect): void {\n if (this.currentFeedbackId === feedback.id) return;\n this.cancelHide();\n this.cancelShow();\n\n this.showTimer = setTimeout(() => {\n this.currentFeedbackId = feedback.id;\n this.render(feedback);\n this.position(anchorRect);\n\n // Check prefers-reduced-motion live (not cached at construction time)\n const reduceMotion =\n typeof window !== \"undefined\" && window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n this.root.style.transition = reduceMotion ? \"none\" : \"\";\n\n this.root.style.visibility = \"visible\";\n this.root.style.opacity = \"1\";\n this.root.style.transform = \"translateY(0) scale(1)\";\n }, SHOW_DELAY);\n }\n\n scheduleHide(): void {\n this.cancelHide();\n this.hideTimer = setTimeout(() => this.hide(), HIDE_DELAY);\n }\n\n hide(): void {\n this.cancelShow();\n this.currentFeedbackId = null;\n this.root.style.opacity = \"0\";\n this.root.style.transform = \"translateY(6px) scale(0.97)\";\n setTimeout(() => {\n if (!this.currentFeedbackId) {\n this.root.style.visibility = \"hidden\";\n }\n }, 200);\n }\n\n private cancelShow(): void {\n if (this.showTimer) {\n clearTimeout(this.showTimer);\n this.showTimer = null;\n }\n }\n\n private cancelHide(): void {\n if (this.hideTimer) {\n clearTimeout(this.hideTimer);\n this.hideTimer = null;\n }\n }\n\n private render(feedback: FeedbackResponse): void {\n // Clear previous content safely (except arrow)\n const children = Array.from(this.root.children);\n for (const child of children) {\n if (child !== this.arrow) child.remove();\n }\n\n const typeColor = getTypeColor(feedback.type, this.colors);\n const typeBg = getTypeBgColor(feedback.type, this.colors);\n const t = createT(this.locale);\n const typeLabel = getTypeLabel(feedback.type, t);\n\n // Header row: badge + date\n const header = el(\"div\", { style: \"display:flex;align-items:center;gap:8px;margin-bottom:8px;\" });\n\n const badge = el(\"span\", {\n style: `\n padding:3px 10px;border-radius:9999px;\n font-size:11px;font-weight:600;\n color:${typeColor};background:${typeBg};\n letter-spacing:0.02em;\n `,\n });\n setText(badge, typeLabel);\n\n const date = el(\"span\", { style: `font-size:11px;color:${this.colors.textSecondary};margin-left:auto;` });\n setText(date, formatRelativeDate(feedback.createdAt, this.locale));\n\n header.appendChild(badge);\n header.appendChild(date);\n\n // Message body (safe — textContent only)\n const body = el(\"div\", {\n style: `font-size:13px;line-height:1.55;color:${this.colors.text};display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;`,\n });\n setText(body, feedback.message);\n\n // Insert content before arrow\n this.root.insertBefore(header, this.arrow);\n this.root.insertBefore(body, this.arrow);\n }\n\n private position(anchorRect: DOMRect): void {\n const tooltipRect = this.root.getBoundingClientRect();\n const gap = 10;\n\n let top = anchorRect.top - tooltipRect.height - gap;\n let left = anchorRect.left + anchorRect.width / 2 - tooltipRect.width / 2;\n let isAbove = true;\n\n // Flip below if not enough space above\n if (top < 8) {\n top = anchorRect.bottom + gap;\n isAbove = false;\n }\n\n left = Math.max(8, Math.min(left, window.innerWidth - tooltipRect.width - 8));\n\n this.root.style.top = `${top}px`;\n this.root.style.left = `${left}px`;\n\n // Position arrow\n const arrowLeft = Math.max(16, Math.min(anchorRect.left + anchorRect.width / 2 - left - 6, tooltipRect.width - 22));\n\n if (isAbove) {\n // Arrow at bottom, pointing down\n this.arrow.style.cssText = `\n position:absolute;\n width:12px;height:12px;\n background:${this.colors.glassBgHeavy};\n border-right:1px solid ${this.colors.glassBorder};\n border-bottom:1px solid ${this.colors.glassBorder};\n transform:rotate(45deg);\n pointer-events:none;\n bottom:-6px;\n left:${arrowLeft}px;\n `;\n } else {\n // Arrow at top, pointing up\n this.arrow.style.cssText = `\n position:absolute;\n width:12px;height:12px;\n background:${this.colors.glassBgHeavy};\n border-left:1px solid ${this.colors.glassBorder};\n border-top:1px solid ${this.colors.glassBorder};\n transform:rotate(45deg);\n pointer-events:none;\n top:-6px;\n left:${arrowLeft}px;\n `;\n }\n }\n\n /** Check if a DOM node belongs to this tooltip (for MutationObserver filtering). */\n contains(node: Node): boolean {\n return this.root.contains(node);\n }\n\n destroy(): void {\n this.cancelShow();\n this.cancelHide();\n this.root.remove();\n }\n}\n","import {\n type DiagnosticsSnapshot,\n type FeedbackPayload,\n isValidEmail,\n type PageScope,\n type SitepingConfig,\n type SitepingInstance,\n type SitepingPublicEventListener,\n type SitepingPublicEvents,\n} from \"@siteping/core\";\nimport { Annotator } from \"./annotator.js\";\nimport { ApiClient, flushRetryQueue, type WidgetClient } from \"./api-client.js\";\nimport { MOBILE_BREAKPOINT, PAGE_SIZE, Z_INDEX_MAX } from \"./constants.js\";\nimport { ConsoleBuffer } from \"./diagnostics/console-buffer.js\";\nimport { NetworkBuffer } from \"./diagnostics/network-buffer.js\";\nimport { EventBus, type WidgetEvents } from \"./events.js\";\nimport { Fab } from \"./fab.js\";\nimport { createFocusTracker } from \"./focus-tracker.js\";\nimport { createT, loadLocale, type TFunction } from \"./i18n/index.js\";\nimport { getIdentity, type Identity, saveIdentity } from \"./identity.js\";\nimport { MarkerManager } from \"./markers.js\";\nimport type { Panel as PanelType } from \"./panel.js\";\nimport { StoreClient } from \"./store-client.js\";\nimport { buildStyles } from \"./styles/base.js\";\nimport { buildThemeColors } from \"./styles/theme.js\";\nimport { Tooltip } from \"./tooltip.js\";\n\n/** Singleton guard — prevents duplicate widgets from overlapping */\nlet instance: SitepingInstance | null = null;\n\ninterface NormalisedDiagnostics {\n console: boolean;\n network: boolean;\n maxConsoleEntries: number;\n maxNetworkEntries: number;\n}\n\n/**\n * Resolve `SitepingConfig.captureDiagnostics` into a normalised shape.\n *\n * - `undefined` / `false` → everything off (no monkey-patching).\n * - `true` → console + network on with the defaults (50 / 20).\n * - object → per-channel toggles + optional custom sizes; missing booleans\n * default to `true` so users can pass `{ maxConsoleEntries: 200 }` and\n * still get both channels.\n */\nfunction normaliseDiagnosticsOptions(value: SitepingConfig[\"captureDiagnostics\"]): NormalisedDiagnostics {\n if (value === undefined || value === false) {\n return { console: false, network: false, maxConsoleEntries: 50, maxNetworkEntries: 20 };\n }\n if (value === true) {\n return { console: true, network: true, maxConsoleEntries: 50, maxNetworkEntries: 20 };\n }\n return {\n console: value.console !== false,\n network: value.network !== false,\n maxConsoleEntries: typeof value.maxConsoleEntries === \"number\" ? value.maxConsoleEntries : 50,\n maxNetworkEntries: typeof value.maxNetworkEntries === \"number\" ? value.maxNetworkEntries : 20,\n };\n}\n\n/** Build a no-op SitepingInstance for when the widget is skipped */\nfunction skippedInstance(): SitepingInstance {\n const noop = () => {};\n return {\n destroy: noop,\n open: noop,\n close: noop,\n refresh: noop,\n focusFeedback: () => false,\n on: () => noop,\n off: noop,\n };\n}\n\n/**\n * Read NODE_ENV so that BOTH detection paths keep working:\n *\n * - The literal `process.env.NODE_ENV` member expression must survive into\n * our own dist — an identity define in tsup.config.ts stops esbuild's\n * browser-platform auto-define from folding it to `\"production\"` and\n * deleting the guard from the shipped bundle (issue #104).\n * - Shipping the literal lets the CONSUMER's bundler (webpack DefinePlugin,\n * Vite, esbuild) inline their real environment, so \"dev-only by default\"\n * works in bundled deployments even when no `process` global exists at\n * runtime. Computed-key dodges (`env[\"NODE_\" + \"ENV\"]`) would defeat that\n * inlining — do not reintroduce them.\n * - No `typeof process` gate: it would return before a consumer-inlined\n * constant is reached. Plain browsers without `process` (script-tag usage)\n * land in the catch instead. Runtime environments with a real `process`\n * (Node/SSR, E2E's `globalThis.process = { env: { NODE_ENV: 'test' } }`)\n * read it live.\n *\n * `scripts/verify-dist-guard.mjs` asserts these invariants against every\n * built bundle after each build.\n */\nfunction readNodeEnv(): string | undefined {\n try {\n return process.env.NODE_ENV;\n } catch {\n // No `process` global (plain browser) or restricted access — no signal\n return undefined;\n }\n}\n\ninterface NormalisedDeepLink {\n enabled: boolean;\n param: string;\n}\n\n/**\n * Resolve `SitepingConfig.deepLink` into a normalised shape.\n *\n * - `undefined` / `false` → disabled, no URL parsing.\n * - `true` → enabled with default param name `siteping`.\n * - object → enabled with optional custom param name. A bare empty object\n * `{}` falls back to the default param so callers never need to repeat it.\n */\nfunction normaliseDeepLinkOptions(value: SitepingConfig[\"deepLink\"]): NormalisedDeepLink {\n if (value === undefined || value === false) return { enabled: false, param: \"siteping\" };\n if (value === true) return { enabled: true, param: \"siteping\" };\n return { enabled: true, param: value.param ?? \"siteping\" };\n}\n\n/**\n * Main widget launcher — orchestrates all UI components.\n *\n * Architecture:\n * - Creates a <siteping-widget> custom element in the document\n * - Attaches a closed Shadow DOM for CSS isolation\n * - FAB + Panel live inside the Shadow DOM\n * - Overlay, markers, tooltips live outside (appended to document.body)\n */\nexport function launch(config: SitepingConfig): SitepingInstance {\n // Guard: no DOM, no widget — SSR frameworks (Next.js, Remix) may run the\n // init on the server. Deliberately NOT bypassed by forceShow: the widget\n // cannot render without a document.\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n config.onSkip?.(\"ssr\");\n return skippedInstance();\n }\n\n // Debug helper — only logs when config.debug is true\n const log: (...args: unknown[]) => void = config.debug\n ? (...args: unknown[]) => console.debug(\"[siteping]\", ...args)\n : () => {};\n\n // Guard: prevent duplicate initSiteping() calls\n if (instance) {\n log(\"initSiteping() called more than once — returning existing instance\");\n return instance;\n }\n\n // Guard: only show in development (forceShow bypasses). Uses readNodeEnv()\n // instead of the literal `process.env.NODE_ENV` — avoids both bundler\n // constant-folding (#104) and \"Critical dependency\" import.meta warnings\n // in Next.js webpack builds.\n if (!config.forceShow && readNodeEnv() === \"production\") {\n const reason = \"production\";\n console.info(\"[siteping] Widget not loaded: production mode detected. Use forceShow: true to override.\");\n config.onSkip?.(reason);\n return skippedInstance();\n }\n\n // Guard: desktop only (viewport below the threshold = hidden). forceShow\n // bypasses this just like the production guard above; minViewportWidth lets\n // hosts tune (or disable, with 0) the threshold. Non-finite values (NaN from\n // an untyped script-tag consumer, Infinity) would silently break the `<`\n // comparison — fail back to the default instead. See issue #103.\n const minViewportWidth =\n typeof config.minViewportWidth === \"number\" && Number.isFinite(config.minViewportWidth)\n ? config.minViewportWidth\n : MOBILE_BREAKPOINT;\n if (!config.forceShow && window.innerWidth < minViewportWidth) {\n const reason = \"mobile\";\n console.info(\n `[siteping] Widget not loaded: viewport width < ${minViewportWidth}px (mobile not supported). Use forceShow: true or lower minViewportWidth to override.`,\n );\n config.onSkip?.(reason);\n return skippedInstance();\n }\n\n // Guard: validate required config fields\n if (!config.store && (!config.endpoint || typeof config.endpoint !== \"string\")) {\n console.error(\n \"[siteping] Missing 'endpoint' or 'store' in config. Provide an endpoint like '/api/siteping' or a SitepingStore instance.\",\n );\n return skippedInstance();\n }\n if (!config.projectName || typeof config.projectName !== \"string\") {\n console.error(\"[siteping] Missing or invalid 'projectName' in config. Expected a non-empty string.\");\n return skippedInstance();\n }\n\n const locale = config.locale ?? \"en\";\n // Kick off the locale fetch immediately. English is bundled synchronously\n // and used as the fallback while the chunk is in flight. The launcher\n // awaits `localeReady` before rendering markers and re-localizes the FAB\n // and popup once the dictionary lands — both are mounted synchronously so\n // the widget is interactive immediately, but their labels start in the\n // English fallback until the chunk arrives.\n const localeReady: Promise<unknown> =\n locale === \"en\"\n ? Promise.resolve()\n : loadLocale(locale).catch(() => {\n /* fallback to English — already handled by createT */\n });\n const t = createT(locale);\n\n // Page scope — concrete URL + optional template, used to keep annotations\n // and panel results scoped to the current page. The widget calls this on\n // every initial markers load and on `instance.refresh()`, so SPA hosts can\n // re-fetch when the route changes.\n const scopeAnnotationsByUrl = config.scopeAnnotationsByUrl ?? true;\n const getScope = (): PageScope => {\n try {\n const result = config.getPageScope?.();\n if (result) return result;\n } catch (e) {\n log(\"getPageScope() threw, falling back to pathname:\", e);\n }\n return { url: window.location.pathname, urlPattern: null };\n };\n\n log(\"Initializing widget\", {\n projectName: config.projectName,\n theme: config.theme ?? \"light\",\n locale,\n scopeAnnotationsByUrl,\n });\n\n // Diagnostics — capture console + failed network at submit time when\n // `captureDiagnostics` is set. Buffers are installed eagerly so they\n // cover the entire session, then snapshotted in the annotation handler\n // below. We default to `false` even in dev to avoid surprise side\n // effects; users opt in via the config flag.\n const diagnosticsOpts = normaliseDiagnosticsOptions(config.captureDiagnostics);\n const consoleBuffer = diagnosticsOpts.console ? new ConsoleBuffer(diagnosticsOpts.maxConsoleEntries) : null;\n const networkBuffer = diagnosticsOpts.network ? new NetworkBuffer(diagnosticsOpts.maxNetworkEntries) : null;\n\n const colors = buildThemeColors(config.accentColor, config.theme);\n const bus = new EventBus<WidgetEvents>();\n const publicBus = new EventBus<SitepingPublicEvents>();\n\n // Client-side mode (store) vs HTTP mode (endpoint).\n // The earlier guard guarantees one of `store` / `endpoint` is set; we\n // capture the chosen branch in a typed local so TypeScript narrows on\n // each side without resorting to a non-null assertion.\n const client: WidgetClient = (() => {\n if (config.store) return new StoreClient(config.store, config.projectName);\n const endpoint = config.endpoint;\n if (typeof endpoint !== \"string\" || endpoint.length === 0) {\n throw new Error(\"[siteping] internal invariant: endpoint must be a non-empty string in HTTP mode\");\n }\n return new ApiClient(endpoint, config.projectName, { apiKey: config.apiKey, headers: config.headers });\n })();\n\n // Wire config callbacks to event bus\n if (config.onOpen) bus.on(\"open\", config.onOpen);\n if (config.onClose) bus.on(\"close\", config.onClose);\n if (config.onFeedbackSent) bus.on(\"feedback:sent\", config.onFeedbackSent);\n if (config.onError) bus.on(\"feedback:error\", config.onError);\n if (config.onAnnotationStart) bus.on(\"annotation:start\", config.onAnnotationStart);\n if (config.onAnnotationEnd) bus.on(\"annotation:end\", config.onAnnotationEnd);\n\n // Bridge internal events to the public bus. The mapped-object type forces\n // one entry per public event — adding a key to SitepingPublicEvents\n // without bridging it here is a compile error, so `instance.on` can never\n // silently miss an event.\n const publicBridges: { [K in keyof SitepingPublicEvents]: () => void } = {\n \"feedback:sent\": () => bus.on(\"feedback:sent\", (fb) => publicBus.emit(\"feedback:sent\", fb)),\n \"feedback:deleted\": () => bus.on(\"feedback:deleted\", (id) => publicBus.emit(\"feedback:deleted\", id)),\n \"feedback:error\": () => bus.on(\"feedback:error\", (err) => publicBus.emit(\"feedback:error\", err)),\n \"panel:open\": () => bus.on(\"open\", () => publicBus.emit(\"panel:open\")),\n \"panel:close\": () => bus.on(\"close\", () => publicBus.emit(\"panel:close\")),\n \"annotation:start\": () => bus.on(\"annotation:start\", () => publicBus.emit(\"annotation:start\")),\n \"annotation:end\": () => bus.on(\"annotation:end\", () => publicBus.emit(\"annotation:end\")),\n };\n for (const wire of Object.values(publicBridges)) wire();\n\n // Debug logging for key lifecycle events\n bus.on(\"open\", () => log(\"Panel opened\"));\n bus.on(\"close\", () => log(\"Panel closed\"));\n bus.on(\"feedback:sent\", (fb) => log(\"Feedback sent\", fb.id));\n bus.on(\"feedback:error\", (err) => log(\"Feedback failed\", err.message));\n bus.on(\"annotation:start\", () => log(\"Annotation started\"));\n bus.on(\"annotation:end\", () => log(\"Annotation ended\"));\n\n // Create host element + Shadow DOM\n const host = document.createElement(\"siteping-widget\");\n host.style.cssText = `position:fixed;z-index:${Z_INDEX_MAX};`;\n // Use open mode only for testing — closed in production for CSS isolation.\n // Shadow DOM mode is determined by environment, never by public config.\n const shadowMode = readNodeEnv() === \"test\" ? (\"open\" as const) : (\"closed\" as const);\n const shadow = host.attachShadow({ mode: shadowMode });\n\n // Inject styles into Shadow DOM — adoptedStyleSheets with fallback for Safari < 16.4\n const supportsAdoptedStyleSheets = \"adoptedStyleSheets\" in ShadowRoot.prototype;\n if (supportsAdoptedStyleSheets) {\n const sheet = new CSSStyleSheet();\n sheet.replaceSync(buildStyles(colors));\n shadow.adoptedStyleSheets = [sheet];\n } else {\n const style = document.createElement(\"style\");\n style.textContent = buildStyles(colors);\n shadow.appendChild(style);\n }\n\n document.body.appendChild(host);\n\n // Track the last page element the user focused. FAB-launched annotation\n // moves focus into the shadow root before the annotator activates, so its\n // own activeElement capture only sees the 0x0 shadow host — the tracker\n // supplies the real keyboard (Enter) target instead. See issue #162.\n const focusTracker = createFocusTracker(host);\n\n // Screen reader live region for feedback submission announcements\n const liveRegion = document.createElement(\"div\");\n liveRegion.setAttribute(\"role\", \"status\");\n liveRegion.setAttribute(\"aria-live\", \"polite\");\n liveRegion.setAttribute(\"aria-atomic\", \"true\");\n liveRegion.style.cssText =\n \"position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;\";\n document.body.appendChild(liveRegion);\n\n // Components outside Shadow DOM\n const tooltip = new Tooltip(colors, locale);\n const markers = new MarkerManager(colors, tooltip, bus, t, liveRegion);\n\n // Components inside Shadow DOM\n const fab = new Fab(shadow, config, bus, t);\n\n // Keep the FAB unread-count badge in sync with the visible markers. Marker\n // mutations (initial render, addFeedback after submit, panel-driven resolve /\n // delete / bulk-delete via re-render) all emit `markers:changed`, so a single\n // listener covers every path that can change the open count.\n bus.on(\"markers:changed\", (openCount) => fab.updateBadge(openCount));\n\n // Lazy-load Panel on first use (FAB click, instance.open, etc.) to keep the\n // initial bundle small. Panel + sub-modules are ~14 KB gzip on their own.\n // Memoize the import promise so subsequent calls reuse the same instance.\n // The promise honestly resolves to null when the widget was destroyed\n // before the panel chunk landed — callers already null-guard.\n let panelInstance: PanelType | null = null;\n let panelPromise: Promise<PanelType | null> | null = null;\n let destroyed = false;\n // Monotonic token guarding the launcher's own marker renders (initial load +\n // doRefresh). The panel guards its own renders with an AbortController; the\n // two direct launcher paths share this counter so the *last-issued* fetch\n // wins, never the last to resolve. Without it, an SPA nav burst (or an\n // initial load racing the first navigation) could render a stale page's\n // markers out of order, since markers.render() is a full clear-and-rebuild.\n let markerGeneration = 0;\n async function loadPanel(): Promise<PanelType | null> {\n if (destroyed) return null;\n if (panelInstance) return panelInstance;\n if (!panelPromise) {\n panelPromise = import(\"./panel.js\").then((mod) => {\n if (destroyed) return null;\n panelInstance = new mod.Panel(shadow, colors, bus, client, config.projectName, markers, t, locale, {\n getScope,\n scopeAnnotationsByUrl,\n });\n return panelInstance;\n });\n }\n return panelPromise;\n }\n\n // Prefetch Panel in idle time so the first FAB click doesn't pay the\n // network/parse cost of the dynamic import. The chunk still ships lazily\n // (saves first-paint gzip), but it's already warming up by the time the\n // user is likely to click. Falls back to setTimeout in browsers without\n // requestIdleCallback (Safari before 17).\n if (typeof window !== \"undefined\") {\n const prefetch = () => {\n if (!destroyed) void loadPanel();\n };\n const ric = (window as { requestIdleCallback?: (cb: () => void) => void }).requestIdleCallback;\n if (typeof ric === \"function\") ric(prefetch);\n else setTimeout(prefetch, 200);\n }\n\n // The FAB emits `panel:toggle` on chat click — we intercept here so the\n // launcher (which holds the lazy loader) can drive the Panel lifecycle.\n // Panel itself also subscribes to `panel:toggle` once loaded; once the\n // dynamic import resolves we manually call `p.open()` because the missed\n // initial emit can't be replayed.\n let pendingOpen = false;\n const unsubToggle = bus.on(\"panel:toggle\", (open) => {\n if (panelInstance) return; // Real Panel already handles subsequent toggles\n if (open) {\n pendingOpen = true;\n loadPanel()\n .then((p) => {\n if (p && pendingOpen) p.open();\n pendingOpen = false;\n })\n .catch((err) => log(\"Failed to lazy-load panel:\", err));\n } else {\n pendingOpen = false;\n }\n });\n\n const annotator = new Annotator(colors, bus, t, config.enableScreenshot ?? false, () =>\n focusTracker.getLastPageFocus(),\n );\n\n let onContextMenu: ((e: MouseEvent) => void) | null = null;\n if (config.enableRightClickComment) {\n onContextMenu = (e: MouseEvent) => {\n // Respect host pages that run their own custom context menus (grids,\n // editors). Element-level handlers fire before this document-level\n // listener, so if they called preventDefault() we yield.\n if (e.defaultPrevented) return;\n // Keyboard-triggered contextmenu (≣ Menu key, Shift+F10): Pointer\n // Events L3 mandates pointerType === \"\" (pointerId -1) for non-pointer\n // activations — yield to the native menu. contextmenu is a PointerEvent\n // in Chrome/Edge 92+, Firefox 129+, Safari 18.2+.\n const pointerType = (e as PointerEvent).pointerType;\n if (pointerType === \"\") return;\n // Legacy MouseEvent engines (no pointerType to consult): fall back to\n // requiring a genuine right-button click.\n if (pointerType === undefined && e.button !== 2) return;\n // Modifier-key escape hatch: Shift/Ctrl/Alt/Meta → native menu.\n if (e.shiftKey || e.ctrlKey || e.altKey || e.metaKey) return;\n // Exclude SitePing's own UI — right-clicking the FAB, panel, markers,\n // popup, or overlay must not hijack the event. composedPath() reaches\n // into the closed shadow root so all retargeted events are caught.\n const path = e.composedPath();\n if (\n path.some(\n (n) =>\n n === host ||\n (n instanceof Element && (n.hasAttribute(\"data-siteping-ignore\") || n.id === \"siteping-markers\")),\n )\n )\n return;\n // Don't swallow the event while the annotator is already active (e.g.\n // the user right-clicks to paste in the popup textarea). Fall through\n // to the native menu instead of silently consuming the event.\n if (annotator.isBusy) return;\n e.preventDefault();\n void annotator\n .startInstantAnnotation(e.clientX, e.clientY)\n .catch((err) => log(\"right-click annotation failed\", err));\n };\n document.addEventListener(\"contextmenu\", onContextMenu);\n }\n\n // Once the locale dictionary lands, swap the FAB + popup labels from the\n // English fallback to the configured language. `t` already resolves to the\n // loaded dictionary at call time, so the markers list rendered below (which\n // calls `t` lazily) only needs to wait on `localeReady` once.\n if (locale !== \"en\") {\n localeReady.then(() => {\n if (destroyed) return;\n fab.refreshLabels();\n annotator.refreshLabels();\n });\n }\n\n // Handle annotation completion via event bus (not DOM events).\n // Concurrency guard: a second `annotation:complete` while one is still in\n // flight must not start a duplicate submission. The Annotator already\n // serializes its own submissions (no second annotation can be drawn while\n // the popup is open), so this is defence-in-depth — but it must not *silently*\n // drop the event: a dropped event would leave any waiting `runSubmission`\n // listener hung forever. We emit `submission:cancelled` so the waiter\n // unblocks as a benign abort (the popup restores, `onError` is not called).\n let submitting = false;\n const unsubAnnotation = bus.on(\"annotation:complete\", async (data) => {\n if (submitting) {\n bus.emit(\"submission:cancelled\");\n return;\n }\n submitting = true;\n try {\n const { annotation, type, message, screenshotDataUrl, screenshotRegion } = data;\n\n // Ensure identity — config wins (host-provided), then localStorage,\n // then prompt the user as a last resort. Host-provided identity is\n // not persisted: the host stays the source of truth on every render.\n let identity = config.identity ?? getIdentity();\n if (!identity) {\n identity = await promptIdentity(shadow, t);\n if (!identity) {\n // User cancelled the identity prompt. Emit `submission:cancelled`\n // (not `feedback:error`) so the popup's pending submit handler\n // unblocks and restores the form — cancelling a prompt is a benign\n // user action, so `config.onError` must not fire for it.\n bus.emit(\"submission:cancelled\");\n return;\n }\n saveIdentity(identity);\n }\n\n // crypto.randomUUID() throws in non-secure contexts (plain HTTP)\n const clientId = (() => {\n try {\n return crypto.randomUUID();\n } catch {\n return `${Date.now()}-${Math.random().toString(36).slice(2)}`;\n }\n })();\n\n // Use scope.url as the single source of truth — same identifier the\n // panel filter and marker filter use. If we stored full URLs here while\n // filtering by pathname, freshly-created feedbacks would never match\n // their own scope filter and would vanish from the UI immediately.\n // Default scope.url is `window.location.pathname` (no query string,\n // so token/key/secret query params can't leak by construction). Hosts\n // that need origin or query in the identifier override `getPageScope`.\n const scope = getScope();\n\n // Snapshot the buffers right before submit so the captured slice\n // matches the moment the user clicked \"send\", not some earlier point.\n let diagnostics: DiagnosticsSnapshot | null = null;\n if (consoleBuffer || networkBuffer) {\n diagnostics = {\n console: consoleBuffer?.getEntries() ?? [],\n network: networkBuffer?.getEntries() ?? [],\n };\n }\n\n const payload: FeedbackPayload = {\n projectName: config.projectName,\n type,\n message,\n url: scope.url,\n urlPattern: scope.urlPattern,\n viewport: `${window.innerWidth}x${window.innerHeight}`,\n userAgent: navigator.userAgent,\n authorName: identity.name,\n authorEmail: identity.email,\n annotations: [annotation],\n clientId,\n screenshotDataUrl: screenshotDataUrl ?? null,\n screenshotRegion: screenshotRegion ?? null,\n diagnostics,\n };\n\n try {\n const response = await client.sendFeedback(payload);\n bus.emit(\"feedback:sent\", response);\n // Compare against the scope captured before submit (route may have\n // changed during the network round-trip — re-reading scope here\n // would race with SPA navigation).\n if (!scopeAnnotationsByUrl || response.url === scope.url) {\n markers.addFeedback(response, markers.count + 1);\n }\n liveRegion.textContent = t(\"feedback.sent.confirmation\");\n // Only refresh the panel if it has been loaded — `refresh()` is a\n // no-op when the panel is closed, so skipping the dynamic import here\n // avoids loading 14 KB of code that would otherwise do nothing.\n if (panelInstance) await panelInstance.refresh();\n } catch (error) {\n bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n liveRegion.textContent = t(\"feedback.error.message\");\n }\n } finally {\n submitting = false;\n }\n });\n\n // Load markers immediately on page load. We always pass the current page URL\n // when scopeAnnotationsByUrl is enabled so the server narrows results to the\n // current page — preventing annotations from one page accidentally rendering\n // on another (when CSS selectors happen to match unrelated elements).\n const initialScope = getScope();\n const initialOptions = scopeAnnotationsByUrl ? { limit: PAGE_SIZE, url: initialScope.url } : { limit: PAGE_SIZE };\n const deepLinkOpts = normaliseDeepLinkOptions(config.deepLink);\n // Claim a generation for the initial load so a navigation that fires while\n // this fetch is in flight (doRefresh bumps the counter) supersedes it — the\n // old page's markers must never clobber the page the user navigated to.\n const initialLoadGeneration = ++markerGeneration;\n // Render markers only once both the feedbacks and the locale dictionary are\n // ready. Marker aria-labels are built via `t(...)` at render time — without\n // this `Promise.all`, a fast HTTP response could outrun a slow locale chunk\n // and freeze marker labels in the English fallback for non-English locales.\n Promise.all([client.getFeedbacks(config.projectName, initialOptions), localeReady])\n .then(([{ feedbacks }]) => {\n if (destroyed || markerGeneration !== initialLoadGeneration) return;\n // Defensive client-side filter — backend may not yet support the `url` query.\n const visible = scopeAnnotationsByUrl ? feedbacks.filter((f) => f.url === initialScope.url) : feedbacks;\n markers.render(visible);\n // Apply deeplink focus once markers exist. Failures here are\n // non-fatal — a malformed URL or an unknown ID just leaves the page\n // as the user found it, so log and move on.\n if (deepLinkOpts.enabled) {\n try {\n const focusId = new URLSearchParams(window.location.search).get(deepLinkOpts.param);\n if (focusId) {\n const matched = markers.focusFeedback(focusId);\n log(\n `deepLink ?${deepLinkOpts.param}=${focusId} ${matched ? \"focused\" : \"did not match a visible feedback\"}`,\n );\n }\n } catch (e) {\n log(\"deepLink parsing failed:\", e);\n }\n }\n })\n .catch((err) => {\n log(\"Failed to load initial markers:\", err);\n });\n\n // Flush retry queue on load (HTTP mode only — store mode has no retry queue)\n if (config.endpoint) {\n flushRetryQueue(config.endpoint, config.identity ?? getIdentity(), {\n apiKey: config.apiKey,\n headers: config.headers,\n })\n .then(() => log(\"Retry queue flushed\"))\n .catch(() => {});\n }\n\n // Re-fetch feedbacks for the *current* scope and update the UI. Shared by the\n // public `instance.refresh()` and the SPA navigation watcher below.\n //\n // When the panel is open, its own `refresh()` already runs `loadFeedbacks()`\n // which re-renders markers — a second fetch here would race with it (the\n // loser overwrites the winner's markers, off by a generation). So we delegate\n // when open, and fetch markers ourselves when closed (the panel won't, but\n // SPA hosts still need the new page's markers after a route change).\n //\n // Returns the in-flight promise (rejecting on fetch failure) so callers can\n // react — `instance.refresh()` swallows it (the public API never rejects onto\n // the host), the navigation watcher uses it to re-arm its dedup on failure.\n const doRefresh = (): Promise<void> => {\n // Bump first, before the open/closed split, so switching to panel-driven\n // rendering also invalidates any closed-panel fetch still in flight.\n const generation = ++markerGeneration;\n if (panelInstance?.isCurrentlyOpen) {\n return panelInstance.refresh();\n }\n const scope = getScope();\n const opts = scopeAnnotationsByUrl ? { limit: PAGE_SIZE, url: scope.url } : { limit: PAGE_SIZE };\n return client.getFeedbacks(config.projectName, opts).then(({ feedbacks }) => {\n // Drop the result if a newer refresh superseded us (out-of-order\n // resolution), the widget was torn down, or the panel opened mid-flight\n // and now owns marker rendering itself.\n if (destroyed || generation !== markerGeneration || panelInstance?.isCurrentlyOpen) return;\n const visible = scopeAnnotationsByUrl ? feedbacks.filter((f) => f.url === scope.url) : feedbacks;\n markers.render(visible);\n });\n };\n\n // SPA route-change watcher. The widget is normally mounted once (singleton)\n // inside a persistent layout — e.g. a Next.js App Router `layout.tsx`, which\n // does NOT remount on client-side navigation. Without this, init runs once and\n // the panel list + markers stay frozen on the page where the widget first\n // mounted. We patch the History API (SPA routers call pushState/replaceState\n // rather than triggering popstate) and listen for popstate/hashchange, then\n // re-fetch only when the scope key actually changes. This re-fetches data\n // only — it deliberately does NOT re-focus/re-scroll (deep-link focus stays\n // initial-load only; see `deepLink`). Opt out with `watchNavigation: false`.\n let teardownNavigation: (() => void) | null = null;\n if (config.watchNavigation !== false && typeof window !== \"undefined\" && typeof history !== \"undefined\") {\n const scopeKey = (s: PageScope): string => `${s.url}\\n${s.urlPattern ?? \"\"}`;\n let lastScopeKey = scopeKey(initialScope);\n const onLocationChange = (): void => {\n if (destroyed) return;\n const key = scopeKey(getScope());\n // Same scope (e.g. query-only or hash-only nav under the default pathname\n // scope) — nothing to re-fetch. Guards against pushState storms too.\n if (key === lastScopeKey) return;\n const prevKey = lastScopeKey;\n lastScopeKey = key;\n log(\"SPA navigation detected — refreshing feedbacks for new scope\");\n doRefresh().catch(() => {\n // The refresh failed (network error). Roll the dedup key back so a\n // later nav *back* to this same scope retries instead of being\n // silently suppressed — unless a newer navigation already moved on.\n if (lastScopeKey === key) lastScopeKey = prevKey;\n });\n };\n\n const originalPushState = history.pushState;\n const originalReplaceState = history.replaceState;\n // Call through to the original first so `location` is already updated by the\n // time onLocationChange() reads getScope().\n const patchedPushState: typeof history.pushState = function (this: History, ...args) {\n originalPushState.apply(this, args);\n onLocationChange();\n };\n const patchedReplaceState: typeof history.replaceState = function (this: History, ...args) {\n originalReplaceState.apply(this, args);\n onLocationChange();\n };\n history.pushState = patchedPushState;\n history.replaceState = patchedReplaceState;\n window.addEventListener(\"popstate\", onLocationChange);\n window.addEventListener(\"hashchange\", onLocationChange);\n\n teardownNavigation = () => {\n window.removeEventListener(\"popstate\", onLocationChange);\n window.removeEventListener(\"hashchange\", onLocationChange);\n // Restore only if nobody patched on top of us — otherwise we'd clobber\n // another library's History wrapper. If a library did wrap on top, our\n // patch stays in the chain (and keeps its closure alive), but it's inert:\n // `destroyed` is already true above, so onLocationChange() is a no-op.\n if (history.pushState === patchedPushState) history.pushState = originalPushState;\n if (history.replaceState === patchedReplaceState) history.replaceState = originalReplaceState;\n };\n }\n\n instance = {\n destroy: () => {\n log(\"Destroying widget\");\n if (onContextMenu) {\n document.removeEventListener(\"contextmenu\", onContextMenu);\n }\n destroyed = true;\n pendingOpen = false;\n teardownNavigation?.();\n focusTracker.destroy();\n unsubAnnotation();\n unsubToggle();\n fab.destroy();\n panelInstance?.destroy();\n annotator.destroy();\n markers.destroy();\n tooltip.destroy();\n // Restore the original console / fetch / XHR so the host page isn't\n // left with patched globals after the widget tears itself down.\n consoleBuffer?.dispose();\n networkBuffer?.dispose();\n bus.removeAll();\n publicBus.removeAll();\n liveRegion.remove();\n host.remove();\n instance = null;\n },\n open: () => {\n // Emit synchronously so consumers wired through `onOpen` / `panel:open`\n // see the open event immediately, even before the Panel module has\n // finished loading on the first call.\n bus.emit(\"panel:toggle\", true);\n },\n close: () => {\n if (panelInstance) {\n panelInstance.close();\n } else {\n // Cancel a pending open before the panel has loaded.\n pendingOpen = false;\n }\n },\n focusFeedback: (feedbackId: string) => {\n // Returns false when no entry matches — unknown ID, feedback filtered\n // out by `scopeAnnotationsByUrl`, or markers not yet loaded (the\n // initial getFeedbacks is async, and the widget exposes no public\n // \"markers ready\" event today). Hosts that race against initial load\n // can retry, or trigger focus from a user gesture instead.\n return markers.focusFeedback(feedbackId);\n },\n // Public API must never reject onto the host — swallow the promise.\n refresh: () => {\n void doRefresh().catch(() => {});\n },\n on: <K extends keyof SitepingPublicEvents>(event: K, listener: SitepingPublicEventListener<K>) =>\n publicBus.on(event, listener),\n off: <K extends keyof SitepingPublicEvents>(event: K, listener: SitepingPublicEventListener<K>) => {\n publicBus.off(event, listener);\n },\n };\n\n return instance;\n}\n\n/**\n * Show a modal identity form inside the Shadow DOM.\n * Glassmorphism: frosted backdrop, glass modal, gradient CTA.\n * Returns null if the user cancels.\n */\nfunction promptIdentity(shadowRoot: ShadowRoot, t: TFunction): Promise<Identity | null> {\n return new Promise((resolve) => {\n // Save the currently focused element to restore on close\n const previouslyFocused = (shadowRoot.activeElement ?? document.activeElement) as HTMLElement | null;\n\n // Move the shadow host to the end of <body> so the identity prompt wins\n // the source-order tiebreak against the feedback popup. Both elements\n // already sit at `Z_INDEX_MAX` (max int32 — no \\\"higher\\\"), and since #114\n // the popup stays visible during submission, so it can be on screen at\n // the moment `promptIdentity` runs. The popup is appended to `document.body`\n // later than the host during init, which made it win when z-indices tied.\n // Re-appending an existing node just moves it; no remount, no listener\n // loss, no visual jitter when the popup isn't open. See issue #126.\n const host = shadowRoot.host;\n if (host.parentNode) host.parentNode.appendChild(host);\n\n const backdrop = document.createElement(\"div\");\n backdrop.style.cssText = `\n position:fixed;inset:0;\n background:var(--sp-identity-overlay);\n backdrop-filter:blur(8px);\n -webkit-backdrop-filter:blur(8px);\n display:flex;align-items:center;justify-content:center;\n z-index:${Z_INDEX_MAX};\n opacity:0;transition:opacity 0.25s ease;\n `;\n\n const modal = document.createElement(\"div\");\n modal.style.cssText = `\n width:340px;padding:28px;border-radius:var(--sp-radius-xl);\n background:var(--sp-identity-bg);\n backdrop-filter:blur(var(--sp-blur-heavy));\n -webkit-backdrop-filter:blur(var(--sp-blur-heavy));\n border:1px solid var(--sp-glass-border);\n box-shadow:0 16px 48px var(--sp-shadow), 0 8px 16px var(--sp-shadow);\n font-family:var(--sp-font, \"Inter\",system-ui,-apple-system,sans-serif);\n color:var(--sp-text);\n transform:translateY(12px) scale(0.97);\n transition:transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);\n -webkit-font-smoothing:antialiased;\n `;\n\n const titleId = `sp-identity-title-${Date.now()}`;\n modal.setAttribute(\"role\", \"dialog\");\n modal.setAttribute(\"aria-modal\", \"true\");\n modal.setAttribute(\"aria-labelledby\", titleId);\n\n const title = document.createElement(\"div\");\n title.className = \"sp-identity-title\";\n title.id = titleId;\n title.textContent = t(\"identity.title\");\n title.style.marginBottom = \"20px\";\n\n const nameInputId = `sp-identity-name-${Date.now()}`;\n const emailInputId = `sp-identity-email-${Date.now()}`;\n\n const nameLabel = document.createElement(\"label\");\n nameLabel.className = \"sp-input-label\";\n nameLabel.textContent = t(\"identity.nameLabel\");\n nameLabel.setAttribute(\"for\", nameInputId);\n const nameInput = document.createElement(\"input\");\n nameInput.className = \"sp-input\";\n nameInput.id = nameInputId;\n nameInput.type = \"text\";\n nameInput.placeholder = t(\"identity.namePlaceholder\");\n nameInput.style.marginBottom = \"14px\";\n\n const emailLabel = document.createElement(\"label\");\n emailLabel.className = \"sp-input-label\";\n emailLabel.textContent = t(\"identity.emailLabel\");\n emailLabel.setAttribute(\"for\", emailInputId);\n const emailInput = document.createElement(\"input\");\n emailInput.className = \"sp-input\";\n emailInput.id = emailInputId;\n emailInput.type = \"email\";\n emailInput.placeholder = t(\"identity.emailPlaceholder\");\n\n const btnRow = document.createElement(\"div\");\n btnRow.style.cssText = \"display:flex;gap:8px;justify-content:flex-end;margin-top:20px;\";\n\n const closeModal = (result: Identity | null) => {\n backdrop.removeEventListener(\"keydown\", onKeydown);\n backdrop.style.opacity = \"0\";\n modal.style.transform = \"translateY(12px) scale(0.97)\";\n setTimeout(() => {\n backdrop.remove();\n previouslyFocused?.focus();\n resolve(result);\n }, 250);\n };\n\n const cancelBtn = document.createElement(\"button\");\n cancelBtn.className = \"sp-btn-ghost\";\n cancelBtn.textContent = t(\"identity.cancel\");\n cancelBtn.addEventListener(\"click\", () => closeModal(null));\n\n const submitBtn = document.createElement(\"button\");\n submitBtn.className = \"sp-btn-primary\";\n submitBtn.textContent = t(\"identity.submit\");\n submitBtn.addEventListener(\"click\", () => {\n const name = nameInput.value.trim();\n const email = emailInput.value.trim();\n if (!name || !email) return;\n // Same pattern the server schema enforces — what the modal accepts here\n // is persisted and replayed on every submission, so it must never be\n // something the server rejects.\n if (!isValidEmail(email)) {\n emailInput.style.borderColor = \"var(--sp-type-bug, #ef4444)\";\n return;\n }\n closeModal({ name, email });\n });\n\n // Focus trap: cycle Tab/Shift+Tab within the modal\n const focusableSelectors = 'input, button, [tabindex]:not([tabindex=\"-1\"])';\n const onKeydown = (e: Event) => {\n const ke = e as KeyboardEvent;\n if (ke.key === \"Escape\") {\n closeModal(null);\n return;\n }\n if (ke.key === \"Tab\") {\n const focusableEls = Array.from(modal.querySelectorAll<HTMLElement>(focusableSelectors));\n if (focusableEls.length === 0) return;\n const first = focusableEls[0];\n const last = focusableEls[focusableEls.length - 1];\n if (!first || !last) return;\n const active = shadowRoot.activeElement as HTMLElement | null;\n if (ke.shiftKey) {\n if (active === first || !modal.contains(active)) {\n ke.preventDefault();\n last.focus();\n }\n } else {\n if (active === last || !modal.contains(active)) {\n ke.preventDefault();\n first.focus();\n }\n }\n }\n };\n backdrop.addEventListener(\"keydown\", onKeydown);\n\n // Close on backdrop click\n backdrop.addEventListener(\"click\", (e) => {\n if (e.target === backdrop) closeModal(null);\n });\n\n btnRow.appendChild(cancelBtn);\n btnRow.appendChild(submitBtn);\n\n modal.appendChild(title);\n modal.appendChild(nameLabel);\n modal.appendChild(nameInput);\n modal.appendChild(emailLabel);\n modal.appendChild(emailInput);\n modal.appendChild(btnRow);\n backdrop.appendChild(modal);\n\n shadowRoot.appendChild(backdrop);\n\n // Animate in\n requestAnimationFrame(() => {\n backdrop.style.opacity = \"1\";\n modal.style.transform = \"translateY(0) scale(1)\";\n nameInput.focus();\n });\n });\n}\n","import type { SitepingConfig, SitepingInstance } from \"@siteping/core\";\nimport { launch } from \"./launcher.js\";\n\nexport type {\n AnchorData,\n AnnotationPayload,\n AnnotationResponse,\n FeedbackPayload,\n FeedbackResponse,\n FeedbackStatus,\n FeedbackType,\n RectData,\n SitepingConfig,\n SitepingHeadersOption,\n SitepingHttpConfig,\n SitepingInstance,\n SitepingLocale,\n SitepingPublicEvents,\n SitepingStore,\n SitepingStoreConfig,\n} from \"@siteping/core\";\nexport type { TFunction, TranslationKey, Translations } from \"./i18n/index.js\";\nexport { loadLocale, registerLocale } from \"./i18n/index.js\";\nexport type { Identity } from \"./identity.js\";\n\n/**\n * Initialize the Siteping feedback widget.\n *\n * @example\n * ```ts\n * import { initSiteping } from '@siteping/widget'\n *\n * const { destroy } = initSiteping({\n * endpoint: '/api/siteping',\n * projectName: 'my-project',\n * })\n * ```\n */\nexport function initSiteping(config: SitepingConfig): SitepingInstance {\n return launch(config);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../node_modules/.bun/@medv+finder@4.0.2/node_modules/@medv/finder/finder.js","../src/dom/fingerprint.ts","../src/focus-tracker.ts","../src/dom/text-context.ts","../src/dom/xpath.ts","../src/dom/anchor.ts","../src/popup-placement.ts","../src/popup.ts","../src/screenshot.ts","../src/annotator.ts","../src/own-feedback.ts","../src/api-client.ts","../src/diagnostics/truncate.ts","../src/diagnostics/console-buffer.ts","../src/diagnostics/network-buffer.ts","../src/events.ts","../src/fab.ts","../src/identity.ts","../src/dom/fuzzy.ts","../src/dom/visibility.ts","../src/dom/resolver.ts","../src/markers.ts","../src/store-client.ts","../src/styles/animations.ts","../src/styles/mobile.ts","../src/styles/base.ts","../src/tooltip.ts","../src/launcher.ts","../src/index.ts"],"names":["acceptedAttrNames","attr","name","value","nameIsOk","wordLike","valueIsOk","idName","className","tagName","finder","input","options","defaults","startTime","config","rootDocument","findRootDocument","foundPath","count","candidate","search","fPath","fallback","selector","unique","optimized","optimize","byPenalty","stack","paths","current","i","level","tie","node","combinations","words","word","element","elementId","index","indexOf","nthOfType","nth","nthChild","path","query","penalty","acc","a","b","parent","child","rootNode","css","newPath","STABLE_ATTRS","djb2","str","hash","generateFingerprint","childCount","siblingIdx","attrHash","attrs","val","scoreFingerprint","storedFingerprint","parts","storedChildren","storedSibIdx","storedAttrHash","storedChildCount","storedSibIndex","candidateFp","candChildren","candSibIdx","candAttrHash","score","childDiff","sibDiff","isWidgetChrome","el","MIN_FOCUS_TARGET_PX","deepFocusTarget","target","inner","box","createFocusTracker","host","lastPageFocus","onFocusIn","e","SIBLING_READ_CAP","pageSibling","sibling","prop","isMasked","rejectMasked","adjacentText","direction","attempts","text","boundedTextEnd","boundedText","neighborText","prevSibling","nextSibling","prev","next","cap","skipMasked","out","walker","walk","generateXPath","shadowXPath","xpathLiteral","segments","tag","position","ANCHOR_KEY_ATTR","SHADOW_BOUNDARY","FINDER_OPTIONS","closestCrossShadow","match","root","parentElementCrossShadow","generateAnchor","selectors","cssSelector","xpath","textSnippet","textPrefix","textSuffix","fingerprint","neighbor","anchorKey","ANCHOR_ELEMENT_TAG_MAX","ANCHOR_ELEMENT_ID_MAX","containsRect","rect","findAnchorElement","elementAtCenter","deepElementFromPoint","x","y","shadowRoot","rectToPercentages","anchorBounds","POPUP_FALLBACK_SIZE","NO_VIEWPORT_INSETS","computePopupPosition","anchor","popup","viewport","insets","minTop","maxBottom","usableHeight","belowTop","aboveTop","fitsInsideUsableBand","candidateTop","top","maxHeight","left","TYPE_LABEL_KEYS","POPUP_TRANSITION","prefersReducedMotion","Popup","colors","t","typeOptions","ICON_QUESTION","ICON_CHANGE","ICON_BUG","ICON_OTHER","option","btn","icon","parseSvg","bgColor","getTypeBgColor","getTypeColor","btnRow","isolateFromHost","typeButtons","type","key","labelSpan","setText","isMacPlatform","rectBounds","onSubmit","resolve","touch","isCoarsePointer","isCompactViewport","buttonHeight","setSurfaceInert","focusableEls","first","last","style","fit","inset","visibleHeight","trackKeyboardInset","width","height","computed","total","container","buttons","isActive","color","enabled","result","submitter","spinner","cachedHtml2Canvas","warnedAboutMissingDep","loadHtml2Canvas","mod","err","clamp","min","max","roundPct","captureAnnotatedScreenshot","html2canvas","quality","maxWidth","padX","padY","docX","docY","docW","docH","capX","capY","capW","capH","region","canvas","ratio","targetW","targetH","scaled","ctx","MIN_RECT_SIZE","clampToViewport","r","newPopupSession","newClientId","Annotator","bus","enableScreenshot","getFallbackTarget","registerEscapeLayer","drawMode","compact","instruction","active","dot","instructionEl","cancelBtn","toolbarRect","viewportHeight","previouslyFocused","tap","bounds","highlight","annotation","clientX","clientY","source","evt","w","h","hit","pointRect","captureRect","session","shown","formResult","sheetTop","wanted","before","capture","reject","cleanup","unsubSent","unsubError","unsubCancelled","reason","anchorElement","ownFeedback","projectName","endpoint","ids","stored","id","write","gone","size","MAX_RETRIES","TIMEOUT_MS","RETRY_QUEUE_KEY","MAX_QUEUE_SIZE","withTimeout","promise","ms","onTimeout","timer","expired","_","buildRequestHeaders","auth","json","extra","mergeRequestHeaders","resilientFetch","url","init","label","read","boundBody","attempt","controller","timeout","response","error","networkErrorFromException","errorFromResponse","baseDelay","jitter","isTransientFailure","SitepingNetworkError","SitepingError","isTransientStatus","status","LOCK_NAME","withRetryLock","callback","isRetryEntry","hasOwn","payload","readQueue","raw","parsed","queueForRetry","queue","entry","tryWriteQueue","kept","stripped","hasScreenshot","withoutScreenshot","dropped","lost","unqueue","clientId","remaining","_screenshotDataUrl","_screenshotRegion","normalizeName","normalizeEmail","flushRetryQueue","currentIdentity","toRetry","unrelated","failed","rejected","headers","res","created","clipSpan","start","from","trimmed","clipRectToAnchor","xPct","wPct","yPct","hPct","parseJsonAs","ignoreBody","ApiClient","screenshotRegion","rest","wire","body","params","feedbackQueryToSearchParams","withSearchParams","feedbackId","resolved","truncateWithEllipsis","maxLength","end","MAX_ENTRIES","MAX_MESSAGE_LENGTH","LEVELS","serializeArg","arg","ancestors","budget","_key","formatArgs","args","ConsoleBuffer","maxEntries","original","buffer","wrapped","MAX_URL_LENGTH","MAX_METHOD_LENGTH","MAX_DURATION_MS","MAX_STATUS","recordableUrl","withoutCredentials","urlString","cut","NetworkBuffer","startedAt","t0","method","t1","proto","originalOpen","originalSend","meta","wrappedOpen","wrappedSend","info","onEnd","EventBus","event","listener","set","fn","ITEM_GAP","ITEM_GAP_TOUCH","ITEM_LABEL_KEYS","Fab","ICON_LIST","ICON_EDIT","ICON_EYE","ICON_EYE_OFF","ICON_SITEPING","item","handleEscape","items","activeEl","currentIndex","nextIndex","displayText","tWithParams","ICON_CLOSE","gap","svgStr","badge","unsubscribe","oldSvg","newSvg","STORAGE_KEY","isIdentity","email","IDENTITY_FIELD_MAX_LENGTH","isValidEmail","getIdentity","saveIdentity","identity","normalizeText","s","collapseWhitespace","editDistance","aLen","bLen","k","curr","j","prevDiag","tmp","similarity","maxLen","sellersDistance","haystack","needle","best","hc","sub","del","ins","fuzzyIncludes","minScore","capped","bigramCounts","counts","diceAgainst","needleCounts","needleBigramTotal","textBigramTotal","matches","consumed","available","used","wordPairCounts","wordPairDiceAgainst","needlePairs","needlePairTotal","textPairTotal","STRICT_VISIBILITY_OPTIONS","classifyVisibility","visibilityFactor","cls","STRATEGY_PRIORS","MAX_PER_STRATEGY","SCAN_TOP_K","SCAN_HARD_CAP","CANDIDATE_TEXT_CAP","TEXT_FLOOR","STRONG_STRUCT","ACCEPT_SCAN","RAW_FIELD_CAP","STRONG_VERIFY","NEUTRAL_VERIFICATION","AMBIGUITY_EPSILON","boundedField","buildSignals","snippet","snippetWordPairs","snippetWordPairTotal","resolveAnchor","signals","pool","treeRoots","gatherSelectorCandidates","scored","strategy","scoreOne","bestFinal","strongVisibleMatch","c","verifiable","sweepScanCandidates","accepted","isAcceptable","winner","disambiguate","confidenceOf","queryRoots","roots","found","resolveShadowLevels","hostSelectors","levels","hosts","add","enforceTag","shadowLevels","keyRoots","escaped","candidates","storedFp","ranked","cheap","charDice","wordDice","diff","scores","verificationScore","visibility","totalWeight","candidateText","contextScore","contextParts","prevText","nextText","candidateNeighbor","sortedAccepted","contenders","resolveAnnotation","resolution","absoluteRect","toAnchorData","toRectData","MARKER_OFFSET","markerPosition","clusterMarker","cluster","elIdx","clusterBase","HIGHLIGHT_FADE","REPOSITION_DEBOUNCE","HIDDEN_RECHECK_MS","LOW_CONFIDENCE_THRESHOLD","CLUSTER_DISTANCE","FAN_SPACING","MarkerManager","tooltip","liveRegion","visible","mutations","hasRelevantMutation","m","isClosedStatus","cause","recheckVisibility","resizeTick","now","scanBudget","validKeys","visibilityChanged","markerEl","cacheKey","cachedEl","backedOff","cacheUsable","anchorRect","wasVisible","openCount","feedbacks","feedback","pos","marker","allItems","itemI","itemJ","base","baseTop","baseLeft","isSolo","totalWidth","startLeft","topMarker","confidence","isResolved","number","typeColor","truncatedMessage","ariaLabel","getTypeLabel","activateMarker","STORE_WRITE_TIMEOUT_MS","StoreClient","store","toResponse","bounded","flattenAnnotation","isStoreDuplicate","existing","record","toFeedbackUpdate","toCommentResponse","toAnnotationResponse","_clientId","createdAt","comment","ann","SPRING_LINEAR","EASE_OUT_EXPO","SPRING_OVERSHOOT","EASE_OUT_QUART","ANIMATION_CSS","MOBILE_CSS","COMPACT_MEDIA","buildStyles","cssVariables","STATS_CSS","SORT_CSS","BULK_CSS","EXPORT_CSS","SHORTCUTS_CSS","DETAIL_CSS","SHOW_DELAY","HIDE_DELAY","TOOLTIP_TRANSITION","Tooltip","locale","reduceMotion","children","typeBg","createT","typeLabel","header","date","formatRelativeDate","tooltipRect","isAbove","arrowLeft","instance","normaliseDiagnosticsOptions","skippedInstance","noop","readNodeEnv","normaliseDeepLinkOptions","launch","log","minViewportWidth","canonicalizeLocale","localeReady","loadLocale","scopeAnnotationsByUrl","getScope","diagnosticsOpts","consoleBuffer","networkBuffer","buildThemeColors","publicBus","client","own","fb","publicBridges","shadowMode","shadow","sheet","removeHostIsolationGuard","installHostIsolationGuard","focusTracker","markers","fab","panelInstance","panelPromise","destroyed","markerGeneration","resolveIdentity","overPopup","known","entered","promptIdentity","loadPanel","prefetch","ric","pendingOpen","unsubToggle","open","p","annotator","onContextMenu","pointerType","n","submitting","unsubAnnotation","data","message","screenshotDataUrl","scope","diagnostics","initialScope","initialOptions","deepLinkOpts","initialLoadGeneration","f","focusId","matched","doRefresh","generation","opts","teardownNavigation","scopeKey","lastScopeKey","onLocationChange","prevKey","originalPushState","originalReplaceState","patchedPushState","patchedReplaceState","self","backdrop","modal","titleId","title","nameInputId","emailInputId","nameLabel","nameInput","emailLabel","emailInput","stopKeyboardTracking","closeModal","onKeydown","unregisterEscapeLayer","submitBtn","setInvalid","invalid","nameInvalid","emailInvalid","focusableSelectors","ke","initSiteping"],"mappings":"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","file":"index.js","sourcesContent":["// License: MIT\n// Author: Anton Medvedev <anton@medv.io>\n// Source: https://github.com/antonmedv/finder\nconst acceptedAttrNames = new Set(['role', 'name', 'aria-label', 'rel', 'href']);\n/** Check if attribute name and value are word-like. */\nexport function attr(name, value) {\n let nameIsOk = acceptedAttrNames.has(name);\n nameIsOk ||= name.startsWith('data-') && wordLike(name);\n let valueIsOk = wordLike(value) && value.length < 100;\n valueIsOk ||= value.startsWith('#') && wordLike(value.slice(1));\n return nameIsOk && valueIsOk;\n}\n/** Check if id name is word-like. */\nexport function idName(name) {\n return wordLike(name);\n}\n/** Check if class name is word-like. */\nexport function className(name) {\n return wordLike(name);\n}\n/** Check if tag name is word-like. */\nexport function tagName(name) {\n return true;\n}\n/** Finds unique CSS selectors for the given element. */\nexport function finder(input, options) {\n if (input.nodeType !== Node.ELEMENT_NODE) {\n throw new Error(`Can't generate CSS selector for non-element node type.`);\n }\n if (input.tagName.toLowerCase() === 'html') {\n return 'html';\n }\n const defaults = {\n root: document.body,\n idName: idName,\n className: className,\n tagName: tagName,\n attr: attr,\n timeoutMs: 1000,\n seedMinLength: 3,\n optimizedMinLength: 2,\n maxNumberOfPathChecks: Infinity,\n };\n const startTime = new Date();\n const config = { ...defaults, ...options };\n const rootDocument = findRootDocument(config.root, defaults);\n let foundPath;\n let count = 0;\n for (const candidate of search(input, config, rootDocument)) {\n const elapsedTimeMs = new Date().getTime() - startTime.getTime();\n if (elapsedTimeMs > config.timeoutMs ||\n count >= config.maxNumberOfPathChecks) {\n const fPath = fallback(input, rootDocument);\n if (!fPath) {\n throw new Error(`Timeout: Can't find a unique selector after ${config.timeoutMs}ms`);\n }\n return selector(fPath);\n }\n count++;\n if (unique(candidate, rootDocument)) {\n foundPath = candidate;\n break;\n }\n }\n if (!foundPath) {\n throw new Error(`Selector was not found.`);\n }\n const optimized = [\n ...optimize(foundPath, input, config, rootDocument, startTime),\n ];\n optimized.sort(byPenalty);\n if (optimized.length > 0) {\n return selector(optimized[0]);\n }\n return selector(foundPath);\n}\nfunction* search(input, config, rootDocument) {\n const stack = [];\n let paths = [];\n let current = input;\n let i = 0;\n while (current && current !== rootDocument) {\n const level = tie(current, config);\n for (const node of level) {\n node.level = i;\n }\n stack.push(level);\n current = current.parentElement;\n i++;\n paths.push(...combinations(stack));\n if (i >= config.seedMinLength) {\n paths.sort(byPenalty);\n for (const candidate of paths) {\n yield candidate;\n }\n paths = [];\n }\n }\n paths.sort(byPenalty);\n for (const candidate of paths) {\n yield candidate;\n }\n}\nfunction wordLike(name) {\n if (/^[a-z\\-]{3,}$/i.test(name)) {\n const words = name.split(/-|[A-Z]/);\n for (const word of words) {\n if (word.length <= 2) {\n return false;\n }\n if (/[^aeiou]{4,}/i.test(word)) {\n return false;\n }\n }\n return true;\n }\n return false;\n}\nfunction tie(element, config) {\n const level = [];\n const elementId = element.getAttribute('id');\n if (elementId && config.idName(elementId)) {\n level.push({\n name: '#' + CSS.escape(elementId),\n penalty: 0,\n });\n }\n for (let i = 0; i < element.classList.length; i++) {\n const name = element.classList[i];\n if (config.className(name)) {\n level.push({\n name: '.' + CSS.escape(name),\n penalty: 1,\n });\n }\n }\n for (let i = 0; i < element.attributes.length; i++) {\n const attr = element.attributes[i];\n if (config.attr(attr.name, attr.value)) {\n level.push({\n name: `[${CSS.escape(attr.name)}=\"${CSS.escape(attr.value)}\"]`,\n penalty: 2,\n });\n }\n }\n const tagName = element.tagName.toLowerCase();\n if (config.tagName(tagName)) {\n level.push({\n name: tagName,\n penalty: 5,\n });\n const index = indexOf(element, tagName);\n if (index !== undefined) {\n level.push({\n name: nthOfType(tagName, index),\n penalty: 10,\n });\n }\n }\n const nth = indexOf(element);\n if (nth !== undefined) {\n level.push({\n name: nthChild(tagName, nth),\n penalty: 50,\n });\n }\n return level;\n}\nfunction selector(path) {\n let node = path[0];\n let query = node.name;\n for (let i = 1; i < path.length; i++) {\n const level = path[i].level || 0;\n if (node.level === level - 1) {\n query = `${path[i].name} > ${query}`;\n }\n else {\n query = `${path[i].name} ${query}`;\n }\n node = path[i];\n }\n return query;\n}\nfunction penalty(path) {\n return path.map((node) => node.penalty).reduce((acc, i) => acc + i, 0);\n}\nfunction byPenalty(a, b) {\n return penalty(a) - penalty(b);\n}\nfunction indexOf(input, tagName) {\n const parent = input.parentNode;\n if (!parent) {\n return undefined;\n }\n let child = parent.firstChild;\n if (!child) {\n return undefined;\n }\n let i = 0;\n while (child) {\n if (child.nodeType === Node.ELEMENT_NODE &&\n (tagName === undefined ||\n child.tagName.toLowerCase() === tagName)) {\n i++;\n }\n if (child === input) {\n break;\n }\n child = child.nextSibling;\n }\n return i;\n}\nfunction fallback(input, rootDocument) {\n let i = 0;\n let current = input;\n const path = [];\n while (current && current !== rootDocument) {\n const tagName = current.tagName.toLowerCase();\n const index = indexOf(current, tagName);\n if (index === undefined) {\n return;\n }\n path.push({\n name: nthOfType(tagName, index),\n penalty: NaN,\n level: i,\n });\n current = current.parentElement;\n i++;\n }\n if (unique(path, rootDocument)) {\n return path;\n }\n}\nfunction nthChild(tagName, index) {\n if (tagName === 'html') {\n return 'html';\n }\n return `${tagName}:nth-child(${index})`;\n}\nfunction nthOfType(tagName, index) {\n if (tagName === 'html') {\n return 'html';\n }\n return `${tagName}:nth-of-type(${index})`;\n}\nfunction* combinations(stack, path = []) {\n if (stack.length > 0) {\n for (let node of stack[0]) {\n yield* combinations(stack.slice(1, stack.length), path.concat(node));\n }\n }\n else {\n yield path;\n }\n}\nfunction findRootDocument(rootNode, defaults) {\n if (rootNode.nodeType === Node.DOCUMENT_NODE) {\n return rootNode;\n }\n if (rootNode === defaults.root) {\n return rootNode.ownerDocument;\n }\n return rootNode;\n}\nfunction unique(path, rootDocument) {\n const css = selector(path);\n switch (rootDocument.querySelectorAll(css).length) {\n case 0:\n throw new Error(`Can't select any node with this selector: ${css}`);\n case 1:\n return true;\n default:\n return false;\n }\n}\nfunction* optimize(path, input, config, rootDocument, startTime) {\n if (path.length > 2 && path.length > config.optimizedMinLength) {\n for (let i = 1; i < path.length - 1; i++) {\n const elapsedTimeMs = new Date().getTime() - startTime.getTime();\n if (elapsedTimeMs > config.timeoutMs) {\n return;\n }\n const newPath = [...path];\n newPath.splice(i, 1);\n if (unique(newPath, rootDocument) &&\n rootDocument.querySelector(selector(newPath)) === input) {\n yield newPath;\n yield* optimize(newPath, input, config, rootDocument, startTime);\n }\n }\n }\n}\n","/**\n * Element fingerprinting for robust DOM re-anchoring.\n *\n * Captures structural properties (child count, sibling index, stable attributes)\n * that survive CSS class changes and minor DOM reshuffling.\n * Inspired by Similo (academic state-of-the-art, 98.8% accuracy).\n */\n\nconst STABLE_ATTRS = [\"role\", \"aria-label\", \"type\", \"name\", \"href\", \"src\", \"data-testid\", \"data-id\"] as const;\n\n/** Simple 32-bit hash (djb2). */\nfunction djb2(str: string): string {\n let hash = 5381;\n for (let i = 0; i < str.length; i++) {\n hash = ((hash << 5) + hash + str.charCodeAt(i)) | 0;\n }\n return (hash >>> 0).toString(36);\n}\n\n/**\n * Generate a compact structural fingerprint for a DOM element.\n *\n * Format: `\"childCount:siblingIdx:attrHash\"`\n * - `childCount` — number of direct child elements\n * - `siblingIdx` — position among same-tag siblings (0-based)\n * - `attrHash` — djb2 hash of stable attributes (role, aria-label, type, etc.)\n *\n * Tag name is NOT included — it's stored separately in `AnchorData.elementTag`.\n */\nexport function generateFingerprint(element: Element): string {\n const childCount = element.children.length;\n\n // Position among same-tag siblings\n let siblingIdx = 0;\n const parent = element.parentElement;\n if (parent) {\n for (const child of parent.children) {\n if (child === element) break;\n if (child.tagName === element.tagName) siblingIdx++;\n }\n }\n\n return `${childCount}:${siblingIdx}:${attrHash(element)}`;\n}\n\n/**\n * Stable-attribute hash component of the fingerprint, exposed separately:\n * unlike the sibling-index component it is O(1) per element (no walk over\n * `parent.children`), so scan prefiltering can afford it on every candidate.\n */\nexport function attrHash(element: Element): string {\n const attrs: string[] = [];\n for (const attr of STABLE_ATTRS) {\n const val = element.getAttribute(attr);\n if (val) attrs.push(`${attr}=${val}`);\n }\n return attrs.length > 0 ? djb2(attrs.join(\",\")) : \"0\";\n}\n\n/**\n * Score how well a candidate element matches a stored fingerprint.\n * Returns 0–1.\n *\n * Weights:\n * - Child count match: 0.2 (tolerant — ±2 gets partial credit)\n * - Sibling index match: 0.4 (positional — most discriminating)\n * - Attribute hash match: 0.4 (identity — exact or nothing)\n */\nexport function scoreFingerprint(candidate: Element, storedFingerprint: string): number {\n const parts = storedFingerprint.split(\":\");\n if (parts.length !== 3) return 0;\n\n const [storedChildren, storedSibIdx, storedAttrHash] = parts;\n const storedChildCount = Number(storedChildren);\n const storedSibIndex = Number(storedSibIdx);\n if (Number.isNaN(storedChildCount) || Number.isNaN(storedSibIndex)) return 0;\n\n const candidateFp = generateFingerprint(candidate);\n const [candChildren, candSibIdx, candAttrHash] = candidateFp.split(\":\");\n\n let score = 0;\n\n // Child count (0.2)\n const childDiff = Math.abs(Number(candChildren) - storedChildCount);\n if (childDiff === 0) score += 0.2;\n else if (childDiff <= 2) score += 0.1;\n else if (childDiff <= 5) score += 0.03;\n\n // Sibling index (0.4)\n const sibDiff = Math.abs(Number(candSibIdx) - storedSibIndex);\n if (sibDiff === 0) score += 0.4;\n else if (sibDiff === 1) score += 0.2;\n else if (sibDiff <= 3) score += 0.08;\n\n // Attribute hash (0.4)\n if (candAttrHash === storedAttrHash) score += 0.4;\n\n return score;\n}\n","/**\n * Tracks the last *page* element the user focused, so FAB-launched keyboard\n * annotation has a real target: opening the radial menu moves focus into the\n * shadow root, which retargets `document.activeElement` to the 0x0\n * `<siteping-widget>` host — by the time the annotator activates, the element\n * the user actually cares about is no longer the active one. See issue #162.\n */\nexport interface FocusTracker {\n getLastPageFocus(): HTMLElement | null;\n destroy(): void;\n}\n\n/**\n * True when `el` belongs to the widget's own chrome rather than the host\n * page: the shadow host, body-level annotation overlay / toolbar / drawing\n * rect / popup (all carry `data-siteping-ignore`), the markers container\n * (whose markers are focusable but carry no ignore attribute), or the\n * tooltip. Host-independent (tagName/closest checks only) so the annotator\n * can share it without holding a host reference — mirrors the screenshot\n * `ignoreElements` predicate.\n *\n * Host pages may put `data-siteping-ignore` on their own elements to mask\n * them from screenshots — those are deliberately excluded from keyboard\n * annotation targeting too: an element opted out of capture shouldn't become\n * an annotation target through the Enter path.\n */\nexport function isWidgetChrome(el: Element): boolean {\n return (\n el.tagName === \"SITEPING-WIDGET\" ||\n el.closest(\"siteping-widget\") !== null ||\n el.closest('[data-siteping-ignore=\"true\"]') !== null ||\n el.closest(\"#siteping-markers\") !== null ||\n el.closest(\"#sp-tooltip\") !== null\n );\n}\n\n/**\n * Below this size (px, either side) a focused element is a visually hidden\n * stand-in — the 1px `sr-only` native control that form components keep in\n * their shadow root — not something the user sees or means to annotate.\n */\nconst MIN_FOCUS_TARGET_PX = 4;\n\n/**\n * The element that actually holds focus under `el`: focus inside a web\n * component retargets `activeElement` (and `focusin` targets) to its shadow\n * host, so drill through open roots to the deepest focused element that has\n * a real box. Closed roots — the widget's own among them — keep their host,\n * and so does focus on a hidden control.\n */\nexport function deepFocusTarget(el: HTMLElement): HTMLElement {\n let target = el;\n let inner = el.shadowRoot?.activeElement;\n while (inner instanceof HTMLElement) {\n const box = inner.getBoundingClientRect();\n if (box.width >= MIN_FOCUS_TARGET_PX && box.height >= MIN_FOCUS_TARGET_PX) target = inner;\n inner = inner.shadowRoot?.activeElement;\n }\n return target;\n}\n\nexport function createFocusTracker(host: HTMLElement): FocusTracker {\n let lastPageFocus: HTMLElement | null = null;\n\n const onFocusIn = (e: FocusEvent): void => {\n const target = e.target;\n if (!(target instanceof HTMLElement)) return;\n // <body> / <html> receive focus as a side effect of blurs and overlay\n // teardown — never something the user chose to annotate.\n if (target === document.body || target === document.documentElement) return;\n if (target === host || isWidgetChrome(target)) return;\n lastPageFocus = deepFocusTarget(target);\n };\n\n document.addEventListener(\"focusin\", onFocusIn);\n\n return {\n getLastPageFocus(): HTMLElement | null {\n // Drop detached elements — annotating a node that left the DOM would\n // produce a dead anchor (and retaining it would leak the subtree).\n if (lastPageFocus && !lastPageFocus.isConnected) lastPageFocus = null;\n return lastPageFocus;\n },\n destroy(): void {\n // Both the listener and the reference must go: a retained document\n // listener would keep the tracked element alive past widget destroy.\n document.removeEventListener(\"focusin\", onFocusIn);\n lastPageFocus = null;\n },\n };\n}\n","/**\n * Shared text-context helpers for DOM anchoring.\n * Used by both anchor generation (anchor.ts) and resolution (resolver.ts).\n */\n\nimport { isWidgetChrome } from \"../focus-tracker.js\";\n\n/** Raw-char budget for sibling reads that only keep 32–40 chars — generous\n * headroom for leading/trailing whitespace that trimming discards. */\nconst SIBLING_READ_CAP = 256;\n\ntype SiblingProp = \"previousElementSibling\" | \"nextElementSibling\";\n\n/**\n * `sibling`, or the nearest page element past it in `prop` direction. The\n * widget appends its own chrome (host, live region, markers, tooltip) to\n * <body> after the page, and its text changes with marker count / tooltip\n * state — as anchor context it would drift, and be empty on reload.\n */\nfunction pageSibling(sibling: Element | null, prop: SiblingProp): Element | null {\n let current = sibling;\n while (current && isWidgetChrome(current)) current = current[prop];\n return current;\n}\n\n/** The host's privacy mask (see screenshot.ts), which widget chrome carries too. */\nfunction isMasked(node: Node): boolean {\n return node.nodeType === 1 && (node as Element).getAttribute(\"data-siteping-ignore\") === \"true\";\n}\n\n/** TreeWalker filter for `skipMasked`: text nodes only, a masked subtree rejected whole. */\nfunction rejectMasked(node: Node): number {\n if (node.nodeType === 3) return NodeFilter.FILTER_ACCEPT;\n return isMasked(node) ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_SKIP;\n}\n\n/**\n * Extract ~32 chars of text from the nearest sibling with content.\n * Walks up to 3 siblings in the given direction.\n *\n * Sibling context is stored with the feedback, so masked text is never read:\n * `pageSibling` skips a masked sibling, the walkers a masked descendant.\n *\n * Sibling text is read through the bounded walkers, never `textContent` —\n * a sibling can be an arbitrarily large subtree (a whole `<section>`), and\n * serializing it wholesale to keep 32 chars is the dominant hidden cost of\n * candidate verification on big pages.\n */\nexport function adjacentText(element: Element, direction: \"before\" | \"after\"): string {\n const prop: SiblingProp = direction === \"before\" ? \"previousElementSibling\" : \"nextElementSibling\";\n let sibling = pageSibling(element[prop], prop);\n let attempts = 3;\n\n while (sibling && attempts > 0) {\n const text =\n direction === \"before\"\n ? boundedTextEnd(sibling, SIBLING_READ_CAP, true).trim()\n : boundedText(sibling, SIBLING_READ_CAP, true).trim();\n if (text) {\n return direction === \"before\" ? text.slice(-32) : text.slice(0, 32);\n }\n sibling = pageSibling(sibling[prop], prop);\n attempts--;\n }\n\n return \"\";\n}\n\n/** Collect text from immediate (page, not widget chrome) siblings for disambiguation context, masked text excluded. */\nexport function neighborText(element: Element): string {\n const prevSibling = pageSibling(element.previousElementSibling, \"previousElementSibling\");\n const nextSibling = pageSibling(element.nextElementSibling, \"nextElementSibling\");\n const prev = prevSibling ? boundedText(prevSibling, SIBLING_READ_CAP, true).trim().slice(0, 40) : \"\";\n const next = nextSibling ? boundedText(nextSibling, SIBLING_READ_CAP, true).trim().slice(0, 40) : \"\";\n return [prev, next].filter(Boolean).join(\" | \");\n}\n\n/**\n * First `cap` characters of an element's text, without serializing the whole\n * subtree. `textContent.slice(0, cap)` still pays for full subtree\n * serialization first — on a wrapper near the root that is the entire page\n * text, and repeated across scan candidates it degenerates to O(page²).\n * A TreeWalker yields the same text nodes in the same (tree) order and stops\n * as soon as the budget is reached.\n *\n * `skipMasked` leaves out text under a `data-siteping-ignore=\"true\"`\n * descendant.\n */\nexport function boundedText(element: Element, cap: number, skipMasked = false): string {\n let out = \"\";\n\n // Leaf fast path — the majority of scan candidates have no element\n // children; their text is the concatenation of their child text nodes,\n // no tree traversal machinery needed.\n if (element.firstElementChild === null) {\n for (const node of element.childNodes) {\n if (node.nodeType === 3) {\n out += (node as Text).data;\n if (out.length >= cap) break;\n }\n }\n return out.length > cap ? out.slice(0, cap) : out;\n }\n\n const walker = skipMasked\n ? element.ownerDocument.createTreeWalker(element, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, rejectMasked)\n : element.ownerDocument.createTreeWalker(element, NodeFilter.SHOW_TEXT);\n while (out.length < cap) {\n const node = walker.nextNode();\n if (!node) break;\n out += (node as Text).data;\n }\n return out.length > cap ? out.slice(0, cap) : out;\n}\n\n/**\n * Last `cap` characters of an element's text — the reverse-direction\n * counterpart of `boundedText` (TreeWalker only walks forward). Visits text\n * nodes in reverse tree order and stops once the budget is filled.\n */\nexport function boundedTextEnd(element: Element, cap: number, skipMasked = false): string {\n let out = \"\";\n const walk = (node: Node): boolean => {\n for (let child: Node | null = node.lastChild; child; child = child.previousSibling) {\n if (child.nodeType === 3) {\n out = (child as Text).data + out;\n if (out.length >= cap) return true;\n } else if (child.nodeType === 1 && !(skipMasked && isMasked(child)) && walk(child)) {\n return true;\n }\n }\n return false;\n };\n walk(element);\n return out.length > cap ? out.slice(-cap) : out;\n}\n","/**\n * Generate an optimized XPath for a DOM element.\n *\n * Strategy:\n * - If the element has a unique id → //tag[@id='value']\n * - Otherwise, walk up the tree building /tag[position] segments\n * until we hit an ancestor with an id or reach <body>\n * - Cap depth at 6 levels to keep paths short — a path that does not reach\n * <body> (truncated, or no parent left) is emitted relative (//tag[n]/…)\n * - Inside a shadow tree: a path rooted at its shadow root (see shadowXPath)\n */\nexport function generateXPath(element: Element): string {\n if (element.getRootNode() instanceof ShadowRoot) return shadowXPath(element);\n\n if (element.id) {\n return `//${element.localName}[@id=${xpathLiteral(element.id)}]`;\n }\n\n const segments: string[] = [];\n let current: Element | null = element;\n\n while (current && current !== document.body && segments.length < 6) {\n const tag = current.localName;\n const parent: Element | null = current.parentElement;\n\n if (current.id) {\n segments.unshift(`/${tag}[@id=${xpathLiteral(current.id)}]`);\n return \"/\" + segments.join(\"\");\n }\n\n // Compute position among same-tag siblings\n let position = 1;\n if (parent) {\n for (const sibling of parent.children) {\n if (sibling === current) break;\n if (sibling.localName === tag) position++;\n }\n }\n\n segments.unshift(`/${tag}[${position}]`);\n current = parent;\n }\n\n // The walk stopped short of <body> — truncated by the depth cap, or out of\n // parents (<html> itself, a detached node): \"/html/body\" + the segments\n // would match nothing, or a shallower decoy with the same shape. The\n // relative form matches the element wherever it sits — possibly alongside\n // look-alikes, which the resolver gathers and verifies like CSS matches.\n // (Shadow-tree elements never get here: see shadowXPath.)\n if (current !== document.body) return \"/\" + segments.join(\"\");\n return \"/html/body\" + segments.join(\"\");\n}\n\n/**\n * XPath cannot enter shadow trees (Chromium even rejects a ShadowRoot context\n * node), so a shadow element's path is informational: the resolver never\n * evaluates it. It is walked all the way up to the shadow root, with no `//`\n * shortcut and no depth cap (`./section[1]/p[@id='x']`), because older\n * widgets evaluate every stored path against the document — where `./…` can\n * only reach `<html>`, so it never matches a light-DOM look-alike.\n */\nfunction shadowXPath(element: Element): string {\n let path = \"\";\n for (let current: Element | null = element; current; current = current.parentElement) {\n const tag = current.localName;\n if (current.id) {\n path = `/${tag}[@id=${xpathLiteral(current.id)}]${path}`;\n continue;\n }\n // Siblings, not parent.children: a top-level element's parent is the\n // shadow root, which parentElement skips.\n let position = 1;\n for (let sibling = current.previousElementSibling; sibling; sibling = sibling.previousElementSibling) {\n if (sibling.localName === tag) position++;\n }\n path = `/${tag}[${position}]${path}`;\n }\n return `.${path}`;\n}\n\n/** An XPath string literal for `value` (`concat()` when it holds a quote). */\nfunction xpathLiteral(value: string): string {\n return value.includes(\"'\") ? `concat('${value.replace(/'/g, \"',\\\"'\\\",'\")}')` : `'${value}'`;\n}\n","import { finder } from \"@medv/finder\";\nimport { ANCHOR_ELEMENT_ID_MAX, ANCHOR_ELEMENT_TAG_MAX, type AnchorData, type RectData } from \"@siteping/core\";\nimport { generateFingerprint } from \"./fingerprint.js\";\nimport { adjacentText, neighborText } from \"./text-context.js\";\nimport { generateXPath } from \"./xpath.js\";\n\n/** HTML attribute hosts use to mark stable semantic anchors. */\nexport const ANCHOR_KEY_ATTR = \"data-feedback-anchor\";\n\n/**\n * Joins the per-tree selectors of an element inside open shadow roots,\n * outermost host first (`my-card >>> .title`). Puppeteer's deep-descendant\n * notation; finder never emits it, since it escapes spaces and `>` inside\n * attribute values.\n */\nexport const SHADOW_BOUNDARY = \" >>> \";\n\nconst FINDER_OPTIONS = {\n // Filter out CSS-in-JS hashed class names\n className: (name: string) => !/^(css|sc|emotion|styled)-/.test(name) && !/^[a-z]{1,3}[A-Za-z0-9]{4,8}$/.test(name),\n // Prefer stable attributes\n attr: (name: string) => [\"data-testid\", \"data-id\", \"role\", \"aria-label\"].includes(name),\n // Exclude framework-generated dynamic IDs\n idName: (name: string) => !name.startsWith(\"radix-\") && !/^:r[0-9]+:$/.test(name),\n seedMinLength: 3,\n optimizedMinLength: 2,\n};\n\n/** Like `element.closest()`, but pierces shadow boundaries upwards. */\nfunction closestCrossShadow(element: Element, selector: string): Element | null {\n let current: Element | null = element;\n while (current) {\n const match = current.closest(selector);\n if (match) return match;\n const root = current.getRootNode();\n current = root instanceof ShadowRoot ? root.host : null;\n }\n return null;\n}\n\n/** Like `element.parentElement`, but pierces shadow boundaries upwards. */\nfunction parentElementCrossShadow(element: Element): Element | null {\n if (element.parentElement) return element.parentElement;\n const root = element.getRootNode();\n return root instanceof ShadowRoot ? root.host : null;\n}\n\n/**\n * Generate a multi-selector anchor for a DOM element.\n *\n * Resolution priority (used by `resolveAnchor`):\n * 1. Semantic anchor (`data-feedback-anchor` on closest ancestor) — hosts opt\n * into stable, narrow anchors that survive viewport changes and refactors\n * 2. Element id\n * 3. CSS selector via @medv/finder\n * 4. XPath\n * 5. Smart scan (fingerprint + text + prefix/suffix + neighbor)\n *\n * Selectors cannot see across a shadow boundary, so an element inside open\n * shadow roots gets one finder selector per tree, joined by SHADOW_BOUNDARY.\n */\nexport function generateAnchor(element: Element): AnchorData {\n const selectors: string[] = [];\n let current: Element | null = element;\n while (current) {\n const root = current.getRootNode();\n if (root instanceof ShadowRoot) {\n // finder types `root` as an Element but only queries it: a ShadowRoot\n // scopes the uniqueness checks to that tree.\n selectors.unshift(finder(current, { ...FINDER_OPTIONS, root: root as unknown as Element }));\n current = root.host;\n } else {\n selectors.unshift(finder(current, FINDER_OPTIONS));\n current = null;\n }\n }\n const cssSelector = selectors.join(SHADOW_BOUNDARY);\n\n const xpath = generateXPath(element);\n\n const rawText = element.textContent?.trim() ?? \"\";\n const textSnippet = rawText.slice(0, 120);\n\n const textPrefix = adjacentText(element, \"before\");\n const textSuffix = adjacentText(element, \"after\");\n const fingerprint = generateFingerprint(element);\n const neighbor = neighborText(element);\n\n const semanticAncestor = closestCrossShadow(element, `[${ANCHOR_KEY_ATTR}]`);\n const anchorKey = semanticAncestor?.getAttribute(ANCHOR_KEY_ATTR) ?? null;\n\n return {\n cssSelector,\n xpath,\n textSnippet,\n textPrefix,\n textSuffix,\n fingerprint,\n neighborText: neighbor,\n elementTag: element.tagName.slice(0, ANCHOR_ELEMENT_TAG_MAX),\n // Over-long ids are dropped, not truncated: a truncated id matches nothing\n // (or the wrong element) — the resolver falls back to other strategies.\n elementId: element.id && element.id.length <= ANCHOR_ELEMENT_ID_MAX ? element.id : undefined,\n anchorKey,\n };\n}\n\n/** Whether `el`'s bounding box fully contains `rect`. */\nfunction containsRect(el: Element, rect: DOMRect): boolean {\n const b = el.getBoundingClientRect();\n return b.left <= rect.x && b.top <= rect.y && b.right >= rect.x + rect.width && b.bottom >= rect.y + rect.height;\n}\n\n/**\n * Find the best DOM element to use as the rect's anchor.\n *\n * Priority:\n * 1. Closest ancestor with `data-feedback-anchor` whose bounds contain the rect —\n * semantic anchors are typically narrow section roots, so anchoring against\n * them keeps the percentage-based rect stable across viewport changes\n * instead of stretching to the width of `<main>` or `<body>`.\n * 2. Smallest ancestor that contains the rect (legacy behavior).\n * 3. `document.body` fallback — it may not contain the rect (a short body, its\n * default margin); the HTTP client clips the rect for the server schema.\n *\n * Both ancestor walks climb out of open shadow roots through their hosts.\n */\nexport function findAnchorElement(rect: DOMRect, root: Element = document.documentElement): Element {\n const elementAtCenter = deepElementFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);\n if (!elementAtCenter || elementAtCenter === root) return document.body;\n\n // Pass 1 — semantic anchor (host-controlled, most stable)\n let current: Element | null = elementAtCenter;\n while (current && current !== document.body) {\n if (current.hasAttribute(ANCHOR_KEY_ATTR) && containsRect(current, rect)) {\n return current;\n }\n current = parentElementCrossShadow(current);\n }\n\n // Pass 2 — original behavior: smallest ancestor that contains the rect\n current = elementAtCenter;\n while (current && current !== document.body) {\n if (containsRect(current, rect)) return current;\n current = parentElementCrossShadow(current);\n }\n\n return document.body;\n}\n\n/**\n * The element under a viewport point, inside open shadow roots too. Document\n * hit-testing retargets to the outermost shadow host, so drill through open\n * roots to the element actually under the point. Only an element of that root\n * is accepted (slotted content hit-tests to the host itself), so every step\n * goes strictly deeper; closed roots stay opaque.\n */\nexport function deepElementFromPoint(x: number, y: number): Element | null {\n // The typeof guard stays although lib.dom types it as always-present:\n // jsdom doesn't implement ShadowRoot.elementFromPoint.\n let element = document.elementFromPoint(x, y);\n let shadowRoot = element?.shadowRoot;\n while (shadowRoot && typeof shadowRoot.elementFromPoint === \"function\") {\n const inner = shadowRoot.elementFromPoint(x, y);\n if (!inner || inner.getRootNode() !== shadowRoot) break;\n element = inner;\n shadowRoot = inner.shadowRoot;\n }\n return element;\n}\n\n/**\n * Convert absolute rectangle coordinates to percentages\n * relative to an anchor element's bounding box.\n */\nexport function rectToPercentages(rect: DOMRect, anchorBounds: DOMRect): RectData {\n // Guard against zero-dimension anchors (collapsed/hidden elements)\n if (anchorBounds.width <= 0 || anchorBounds.height <= 0) {\n return { xPct: 0, yPct: 0, wPct: 1, hPct: 1 };\n }\n return {\n xPct: (rect.x - anchorBounds.x) / anchorBounds.width,\n yPct: (rect.y - anchorBounds.y) / anchorBounds.height,\n wPct: rect.width / anchorBounds.width,\n hPct: rect.height / anchorBounds.height,\n };\n}\n","/**\n * Placement math for the annotation comment popup — pure so it can be unit\n * tested without layout; `Popup.show()` feeds it measured sizes.\n */\n\n/** Gap between the drawn rectangle and the popup, in px. */\nconst POPUP_ANCHOR_GAP_PX = 8;\n/** Minimum distance kept between the popup and the usable viewport edges, in px. */\nconst POPUP_VIEWPORT_MARGIN_PX = 8;\n/**\n * Size used when the popup cannot be measured (a DOM without layout, such as\n * jsdom). The default-locale popup renders at 334 × 276–283 px in Chromium,\n * Firefox and WebKit when the host page does not reset `box-sizing`.\n */\nexport const POPUP_FALLBACK_SIZE = { width: 334, height: 280 } as const;\n\n/**\n * Viewport bands the popup must not cover, e.g. the annotation toolbar. `top`\n * is the height reserved at the top edge, `bottom` the height at the bottom.\n */\nexport interface ViewportInsets {\n top: number;\n bottom: number;\n}\n\nexport const NO_VIEWPORT_INSETS: ViewportInsets = { top: 0, bottom: 0 };\n\ninterface Size {\n width: number;\n height: number;\n}\n\ninterface Rect {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\n/** Where the popup goes, and how tall it may be when the usable band is too short. */\nexport interface PopupPosition {\n top: number;\n left: number;\n /**\n * Height cap in px the popup must apply — making its content scrollable —\n * when its measured height exceeds the usable viewport band; `null` when it\n * fits.\n */\n maxHeight: number | null;\n}\n\n/**\n * Position the popup next to `anchor`: below it when it fits, above it\n * otherwise, and as a last resort clamped inside the usable viewport (the\n * viewport minus `insets`) as close below the anchor as it allows, keeping its\n * bottom — where the actions live — visible. A side is accepted only when the\n * whole popup stays inside the usable band, so an anchor lying inside a\n * toolbar band never drags the popup under that toolbar. When the popup is\n * taller than the usable band it fills the band and reports a `maxHeight`, so\n * its content scrolls instead of the actions being pushed past the bottom\n * edge. Horizontally it aligns with the anchor's left edge, flips to its right\n * edge when it would overflow, and is clamped inside the viewport margins.\n */\nexport function computePopupPosition(\n anchor: Rect,\n popup: Size,\n viewport: Size,\n insets: ViewportInsets = NO_VIEWPORT_INSETS,\n): PopupPosition {\n const minTop = insets.top + POPUP_VIEWPORT_MARGIN_PX;\n const maxBottom = viewport.height - insets.bottom - POPUP_VIEWPORT_MARGIN_PX;\n const usableHeight = Math.max(0, maxBottom - minTop);\n\n const belowTop = anchor.bottom + POPUP_ANCHOR_GAP_PX;\n const aboveTop = anchor.top - POPUP_ANCHOR_GAP_PX - popup.height;\n const fitsInsideUsableBand = (candidateTop: number): boolean =>\n candidateTop >= minTop && candidateTop + popup.height <= maxBottom;\n\n let top: number;\n let maxHeight: number | null = null;\n if (fitsInsideUsableBand(belowTop)) {\n top = belowTop;\n } else if (fitsInsideUsableBand(aboveTop)) {\n top = aboveTop;\n } else if (popup.height <= usableHeight) {\n top = Math.min(Math.max(belowTop, minTop), maxBottom - popup.height);\n } else {\n top = minTop;\n maxHeight = usableHeight;\n }\n\n let left = anchor.left;\n if (left + popup.width > viewport.width - POPUP_VIEWPORT_MARGIN_PX) {\n left = anchor.right - popup.width;\n }\n left = Math.max(POPUP_VIEWPORT_MARGIN_PX, Math.min(left, viewport.width - POPUP_VIEWPORT_MARGIN_PX - popup.width));\n\n return { top, left, maxHeight };\n}\n","import type { FeedbackType } from \"@siteping/core\";\nimport { POPUP_HIDE_TRANSITION_MS, Z_INDEX_MAX } from \"./constants.js\";\nimport { el, isMacPlatform, parseSvg, setText } from \"./dom-utils.js\";\nimport { isolateFromHost, setSurfaceInert } from \"./host-isolation.js\";\nimport type { TFunction, Translations } from \"./i18n/index.js\";\nimport { ICON_BUG, ICON_CHANGE, ICON_OTHER, ICON_QUESTION } from \"./icons.js\";\nimport {\n computePopupPosition,\n NO_VIEWPORT_INSETS,\n POPUP_FALLBACK_SIZE,\n type ViewportInsets,\n} from \"./popup-placement.js\";\nimport { getTypeBgColor, getTypeColor, type ThemeColors } from \"./styles/theme.js\";\nimport { isCoarsePointer, isCompactViewport, trackKeyboardInset } from \"./viewport.js\";\n\n// Map each feedback type to its translation key, so `refreshLabels()` can\n// re-localize the existing type buttons without re-rendering the popup.\nconst TYPE_LABEL_KEYS: Record<FeedbackType, keyof Translations> = {\n question: \"type.question\",\n change: \"type.change\",\n bug: \"type.bug\",\n other: \"type.other\",\n};\n\n/**\n * The popup's open/close animation. Declared once: `show()` swaps it for\n * `none` under reduced motion and must restore this exact value, since the\n * root has no other transition (an empty inline value removes it).\n */\nconst POPUP_TRANSITION = `opacity ${POPUP_HIDE_TRANSITION_MS}ms cubic-bezier(0.16, 1, 0.3, 1),transform ${POPUP_HIDE_TRANSITION_MS}ms cubic-bezier(0.16, 1, 0.3, 1)`;\n\n/** Read live, not cached at construction, so an OS setting change applies to the next open or close. */\nfunction prefersReducedMotion(): boolean {\n return typeof window.matchMedia === \"function\" && window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n}\n\ninterface PopupResult {\n type: FeedbackType;\n message: string;\n}\n\ninterface TypeOption {\n type: FeedbackType;\n icon: string;\n}\n\n/**\n * Optional async hook called when the user clicks \"Send\". While the returned\n * promise is pending the popup stays visible in a submitting state (spinner\n * on the submit button, every other control disabled). On resolution the\n * popup closes and `show()` resolves with the submitted result; on rejection\n * the popup restores so the user can retry without re-entering the form.\n */\ntype PopupSubmitHandler = (result: PopupResult) => Promise<void>;\n\n/**\n * Popup form shown after drawing an annotation rectangle.\n *\n * Glassmorphism design: frosted glass background, soft shadows,\n * pill-shaped type buttons, gradient submit button.\n * On phones it is a solid bottom sheet that rides above the on-screen\n * keyboard instead of a card floating over the annotated area.\n * Lives outside Shadow DOM.\n */\nexport class Popup {\n private root: HTMLElement;\n private selectedType: FeedbackType | null = null;\n private textarea: HTMLTextAreaElement;\n private submitBtn: HTMLButtonElement;\n private cancelBtn: HTMLButtonElement;\n private typeRow: HTMLElement;\n private submitLabel: HTMLSpanElement;\n private hint: HTMLElement;\n private resolve: ((result: PopupResult | null) => void) | null = null;\n private previouslyFocused: HTMLElement | null = null;\n private onKeydownTrap: ((e: KeyboardEvent) => void) | null = null;\n private onSubmit: PopupSubmitHandler | null = null;\n private submittingState = false;\n /**\n * Frame in which `show()` fades the popup in and focuses it. A close that\n * comes first cancels it, or it would bring the closed popup back.\n */\n private showFrame: number | null = null;\n /**\n * Pending `display: none` scheduled by `hideElement()` once the fade-out\n * ends. Cleared by `show()` so a popup reopened inside the transition window\n * is not hidden by the previous session's timer.\n */\n private hideTimeoutId: ReturnType<typeof setTimeout> | null = null;\n /** WAAPI handle for the running spinner — cancelled when submitting ends. */\n private spinnerAnimation: Animation | null = null;\n /** Rendered as a bottom sheet — decided per `show()` from the viewport. */\n private sheet = false;\n private stopKeyboardTracking: (() => void) | null = null;\n\n /**\n * True from `show()` until its promise settles — through typing, the\n * in-flight `onSubmit` await, AND the failed-submit retry window. The\n * annotator's drawing guards read this to serialize popup sessions\n * (#114/#196): if a refactor ever nulls `resolve` before `onSubmit`\n * settles, those guards die silently — popup.test.ts pins the lifecycle.\n */\n get isOpen(): boolean {\n return this.resolve !== null;\n }\n\n /** Where the open bottom sheet begins (viewport y), or null when not shown as a sheet. */\n get sheetTop(): number | null {\n return this.sheet && this.isOpen ? window.innerHeight - this.root.offsetHeight : null;\n }\n\n constructor(\n private readonly colors: ThemeColors,\n private readonly t: TFunction,\n ) {\n this.root = el(\"div\", {\n style: /* css */ `position:fixed;z-index:${Z_INDEX_MAX};pointer-events:auto;width:300px;padding:16px;border-radius:16px;background:${this.colors.glassBg};backdrop-filter:blur(24px);-webkit-backdrop-filter:blur(24px);border:1px solid ${this.colors.glassBorder};box-shadow:0 8px 32px ${this.colors.shadow},0 2px 8px ${this.colors.shadow};font-family:\"Inter\",system-ui,-apple-system,sans-serif;opacity:0;transform:translateY(8px) scale(0.98);transition:${POPUP_TRANSITION};display:none;-webkit-font-smoothing:antialiased;`\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n,\n });\n\n this.root.setAttribute(\"role\", \"dialog\");\n this.root.setAttribute(\"aria-modal\", \"true\");\n // Screenshot capture now runs while the popup is still visible (so the\n // spinner can show during the upload). Without this attribute the popup\n // would appear baked into the captured JPEG.\n this.root.setAttribute(\"data-siteping-ignore\", \"true\");\n // The dialog `aria-label` is bound by `applyLabels()` at the end of the\n // constructor, alongside every other `t()`-derived string.\n\n // Type selector grid (2x2). Labels are bound later by `applyLabels()` —\n // the constructor only builds the structure (icon + empty label span).\n const typeOptions: TypeOption[] = [\n { type: \"question\", icon: ICON_QUESTION },\n { type: \"change\", icon: ICON_CHANGE },\n { type: \"bug\", icon: ICON_BUG },\n { type: \"other\", icon: ICON_OTHER },\n ];\n this.typeRow = el(\"div\", { style: \"display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-bottom:12px;\" });\n for (const option of typeOptions) {\n const btn = document.createElement(\"button\");\n btn.style.cssText = /* css */ `height:44px;border-radius:9999px;border:1px solid ${this.colors.border};background:${this.colors.glassBg};cursor:pointer;display:flex;align-items:center;justify-content:center;gap:5px;font-family:\"Inter\",system-ui,-apple-system,sans-serif;font-size:13px;font-weight:500;color:${this.colors.textTertiary};transition:all 0.2s ease;padding:0 12px;`\n\n\n\n\n\n\n\n\n;\n const icon = parseSvg(option.icon);\n icon.setAttribute(\"style\", \"width:13px;height:13px;flex-shrink:0;\");\n btn.appendChild(icon);\n btn.appendChild(document.createElement(\"span\"));\n btn.dataset.type = option.type;\n btn.setAttribute(\"aria-pressed\", \"false\");\n\n btn.addEventListener(\"click\", () => {\n if (this.submittingState) return;\n this.selectType(option.type, this.typeRow);\n });\n\n btn.addEventListener(\"mouseenter\", () => {\n if (this.submittingState) return;\n if (btn.dataset.type !== this.selectedType) {\n const bgColor = getTypeBgColor(btn.dataset.type ?? \"\", this.colors);\n btn.style.background = bgColor;\n btn.style.borderColor = getTypeColor(btn.dataset.type ?? \"\", this.colors) + \"40\";\n }\n });\n\n btn.addEventListener(\"mouseleave\", () => {\n if (this.submittingState) return;\n if (btn.dataset.type !== this.selectedType) {\n btn.style.background = this.colors.glassBg;\n btn.style.borderColor = this.colors.border;\n }\n });\n\n this.typeRow.appendChild(btn);\n }\n\n // Textarea\n this.textarea = document.createElement(\"textarea\");\n this.textarea.style.cssText = /* css */ `width:100%;min-height:72px;max-height:152px;padding:10px 12px;border-radius:12px;border:1px solid ${this.colors.border};background:${this.colors.glassBgHeavy};color:${this.colors.text};font-family:\"Inter\",system-ui,-apple-system,sans-serif;font-size:13px;line-height:1.5;resize:vertical;outline:none;transition:all 0.2s ease;box-sizing:border-box;`\n\n\n\n\n\n\n\n\n;\n this.textarea.maxLength = 5000;\n\n // Keyboard shortcut hint\n this.hint = el(\"div\", {\n style: /* css */ `font-size:11px;color:${this.colors.textTertiary};text-align:right;margin-top:4px;font-family:\"Inter\",system-ui,-apple-system,sans-serif;letter-spacing:0.01em;`\n\n\n\n\n,\n });\n\n this.textarea.addEventListener(\"focus\", () => {\n if (this.submittingState) return;\n this.textarea.style.borderColor = this.colors.accent;\n this.textarea.style.boxShadow = `0 0 0 3px ${this.colors.accent}14`;\n this.textarea.style.background = this.colors.bg;\n });\n this.textarea.addEventListener(\"blur\", () => {\n if (this.submittingState) return;\n this.textarea.style.borderColor = this.colors.border;\n this.textarea.style.boxShadow = \"none\";\n this.textarea.style.background = this.colors.glassBgHeavy;\n });\n this.textarea.addEventListener(\"input\", () => {\n this.updateSubmitState();\n });\n this.textarea.addEventListener(\"keydown\", (e) => {\n if (this.submittingState) return;\n if (e.key === \"Enter\" && (e.ctrlKey || e.metaKey)) {\n e.preventDefault();\n this.submit();\n }\n });\n\n // Button row\n const btnRow = el(\"div\", { style: \"display:flex;justify-content:flex-end;gap:8px;margin-top:12px;\" });\n\n this.cancelBtn = document.createElement(\"button\");\n this.cancelBtn.style.cssText = /* css */ `height:34px;padding:0 16px;border-radius:9999px;border:1px solid ${this.colors.border};background:${this.colors.glassBg};color:${this.colors.textTertiary};font-family:\"Inter\",system-ui,-apple-system,sans-serif;font-size:13px;font-weight:500;cursor:pointer;transition:all 0.2s ease;`\n\n\n\n\n\n\n;\n this.cancelBtn.addEventListener(\"click\", () => this.dismiss());\n this.cancelBtn.addEventListener(\"mouseenter\", () => {\n if (this.submittingState) return;\n this.cancelBtn.style.borderColor = this.colors.accent;\n this.cancelBtn.style.color = this.colors.accent;\n });\n this.cancelBtn.addEventListener(\"mouseleave\", () => {\n if (this.submittingState) return;\n this.cancelBtn.style.borderColor = this.colors.border;\n this.cancelBtn.style.color = this.colors.textTertiary;\n });\n\n this.submitBtn = document.createElement(\"button\");\n this.submitBtn.style.cssText = /* css */ `height:34px;padding:0 18px;border-radius:9999px;border:none;background:${this.colors.accentGradient};color:#fff;font-family:\"Inter\",system-ui,-apple-system,sans-serif;font-size:13px;font-weight:600;cursor:pointer;opacity:0.35;pointer-events:none;transition:all 0.2s ease;box-shadow:0 2px 8px ${this.colors.accentGlow};display:inline-flex;align-items:center;justify-content:center;min-width:64px;`\n\n\n\n\n\n\n\n\n;\n // The submit label lives in its own <span> so the submitting-state spinner\n // can be appended/removed without disturbing it. `applyLabels()` binds its\n // text — never `setText` the button itself or it would wipe the spinner.\n this.submitLabel = document.createElement(\"span\");\n this.submitBtn.appendChild(this.submitLabel);\n this.submitBtn.addEventListener(\"click\", () => this.submit());\n\n btnRow.appendChild(this.cancelBtn);\n btnRow.appendChild(this.submitBtn);\n\n this.root.appendChild(this.typeRow);\n this.root.appendChild(this.textarea);\n this.root.appendChild(this.hint);\n this.root.appendChild(btnRow);\n isolateFromHost(this.root);\n document.body.appendChild(this.root);\n\n // Bind every `t()`-derived string into the freshly-built DOM. Kept as a\n // single pass so the constructor and `refreshLabels()` never drift.\n this.applyLabels();\n }\n\n /**\n * Re-read every `t(...)`-derived label, placeholder, and aria-label from\n * the active translation function. Idempotent — call after the locale\n * dictionary has finished loading so the popup swaps from the English\n * fallback to the configured language.\n */\n refreshLabels(): void {\n this.applyLabels();\n }\n\n /**\n * Walk the already-built DOM and bind every translation-derived string —\n * the dialog `aria-label`, the four type-button labels, the textarea\n * `placeholder` + `aria-label`, the `⌘+Enter` / `Ctrl+Enter` hint, and the\n * cancel/submit `textContent`. The single source of truth for which node\n * gets which `t()` string, shared by the constructor and `refreshLabels()`\n * so the two can never drift.\n */\n private applyLabels(): void {\n this.root.setAttribute(\"aria-label\", this.t(\"popup.ariaLabel\"));\n\n const typeButtons = this.root.querySelectorAll<HTMLButtonElement>(\"button[data-type]\");\n for (const btn of typeButtons) {\n const type = btn.dataset.type as FeedbackType | undefined;\n if (!type) continue;\n const key = TYPE_LABEL_KEYS[type];\n if (!key) continue;\n const labelSpan = btn.querySelector<HTMLSpanElement>(\"span\");\n if (labelSpan) setText(labelSpan, this.t(key));\n }\n\n this.textarea.placeholder = this.t(\"popup.placeholder\");\n this.textarea.setAttribute(\"aria-label\", this.t(\"popup.textareaAria\"));\n\n setText(this.hint, isMacPlatform() ? this.t(\"popup.submitHintMac\") : this.t(\"popup.submitHintOther\"));\n setText(this.cancelBtn, this.t(\"popup.cancel\"));\n // Target the label <span>, not the button — the button also hosts the\n // submitting-state spinner, which `setText` on the button would erase.\n setText(this.submitLabel, this.t(\"popup.submit\"));\n }\n\n /**\n * Show the popup near a drawn rectangle and return the user's input.\n * Returns null if cancelled.\n *\n * When `onSubmit` is provided the popup stays visible while the handler\n * runs — the submit button shows a spinner, every other control is\n * disabled. On success the popup closes; on rejection it restores so the\n * user can retry without re-entering the form.\n *\n * `insets` reserves viewport bands the popup must not cover (the\n * annotation toolbar), so its actions never land behind them.\n */\n show(\n rectBounds: DOMRect,\n onSubmit?: PopupSubmitHandler,\n insets: ViewportInsets = NO_VIEWPORT_INSETS,\n ): Promise<PopupResult | null> {\n return new Promise((resolve) => {\n this.cancelPendingTransition();\n this.resolve = resolve;\n this.onSubmit = onSubmit ?? null;\n this.selectedType = null;\n this.textarea.value = \"\";\n this.submittingState = false;\n this.updateSubmitState();\n this.resetTypeButtons();\n\n // Save focus to restore on close\n this.previouslyFocused = document.activeElement as HTMLElement | null;\n\n const touch = isCoarsePointer();\n this.sheet = isCompactViewport();\n // Finger-sized actions; 16px text so iOS doesn't zoom the page on focus.\n // No ⌘/Ctrl+Enter hint without a hardware keyboard.\n const buttonHeight = this.sheet ? \"48px\" : touch ? \"44px\" : \"34px\";\n this.cancelBtn.style.height = buttonHeight;\n this.submitBtn.style.height = buttonHeight;\n this.cancelBtn.style.flex = this.sheet ? \"1\" : \"\";\n this.submitBtn.style.flex = this.sheet ? \"2\" : \"\";\n this.textarea.style.fontSize = touch ? \"16px\" : \"13px\";\n this.textarea.style.minHeight = this.sheet ? \"96px\" : \"72px\";\n this.hint.style.display = touch ? \"none\" : \"\";\n this.root.style.transform = this.hiddenTransform();\n setSurfaceInert(this.root, false);\n this.root.style.display = \"block\";\n this.layout(rectBounds, insets);\n\n // Install focus trap. Escape cancels from any control, not only the\n // textarea, and bubbles on so the annotator ends the session too.\n this.onKeydownTrap = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") this.dismiss();\n if (e.key === \"Tab\") {\n const focusableEls = Array.from(\n this.root.querySelectorAll<HTMLElement>(\n 'button:not([disabled]), textarea:not([disabled]), input:not([disabled]), [tabindex]:not([tabindex=\"-1\"])',\n ),\n );\n if (focusableEls.length === 0) return;\n const first = focusableEls[0];\n const last = focusableEls[focusableEls.length - 1];\n if (!first || !last) return;\n if (e.shiftKey) {\n if (document.activeElement === first || !this.root.contains(document.activeElement)) {\n e.preventDefault();\n last.focus();\n }\n } else {\n if (document.activeElement === last || !this.root.contains(document.activeElement)) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n };\n this.root.addEventListener(\"keydown\", this.onKeydownTrap);\n\n this.root.style.transition = prefersReducedMotion() ? \"none\" : POPUP_TRANSITION;\n\n // Trigger animation. Touch: focus the first type button rather than\n // the textarea, so the keyboard doesn't cover the sheet before the user\n // has even picked a type.\n this.showFrame = requestAnimationFrame(() => {\n this.showFrame = null;\n this.root.style.opacity = \"1\";\n this.root.style.transform = \"translateY(0) scale(1)\";\n (touch ? this.typeRow.querySelector(\"button\") : this.textarea)?.focus();\n });\n });\n }\n\n /** Card next to the annotated rect, or — on phones — a bottom sheet above the keyboard. */\n private layout(rectBounds: DOMRect, insets: ViewportInsets): void {\n const style = this.root.style;\n style.width = this.sheet ? \"auto\" : \"300px\";\n style.borderRadius = this.sheet ? \"20px 20px 0 0\" : \"16px\";\n style.background = this.sheet ? this.colors.bg : this.colors.glassBg;\n style.boxShadow = this.sheet\n ? `0 -8px 32px ${this.colors.shadow}`\n : `0 8px 32px ${this.colors.shadow}, 0 2px 8px ${this.colors.shadow}`;\n style.overscrollBehavior = this.sheet ? \"contain\" : \"\";\n this.stopKeyboardTracking?.();\n this.stopKeyboardTracking = null;\n if (this.sheet) {\n style.top = \"auto\";\n style.left = \"0\";\n style.right = \"0\";\n style.overflowY = \"auto\";\n const fit = (inset: number, visibleHeight = window.innerHeight) => {\n style.bottom = `${inset}px`;\n style.maxHeight = `${visibleHeight - 8}px`;\n // The keyboard covers the home indicator — no safe-area gap above it.\n style.padding = `16px 16px ${inset > 0 ? \"16px\" : \"calc(16px + env(safe-area-inset-bottom, 0px))\"}`;\n };\n fit(0);\n this.stopKeyboardTracking = trackKeyboardInset(fit);\n return;\n }\n style.right = \"\";\n style.bottom = \"\";\n style.padding = \"16px\";\n\n // Laid out while still transparent so placement uses its real size — it\n // varies with the locale's label lengths, font metrics, touch sizing and\n // the host's box-sizing. Any height cap from a previous show is dropped\n // first so the natural height is what gets measured.\n style.maxHeight = \"\";\n style.overflowY = \"\";\n const { top, left, maxHeight } = computePopupPosition(\n rectBounds,\n this.measure(),\n { width: window.innerWidth, height: window.innerHeight },\n insets,\n );\n style.top = `${top}px`;\n style.left = `${left}px`;\n if (maxHeight !== null) {\n // Taller than the usable band (short viewport, high zoom, long\n // localized labels): cap it and let it scroll, starting from the top\n // so the type buttons that enable Send are in view.\n style.maxHeight = `${Math.max(0, maxHeight - this.verticalChromeHeight())}px`;\n style.overflowY = \"auto\";\n this.root.scrollTop = 0;\n }\n }\n\n private hiddenTransform(): string {\n return this.sheet ? \"translateY(100%)\" : \"translateY(8px) scale(0.98)\";\n }\n\n /** Rendered size, ignoring the entry transform; falls back when there is no layout. */\n private measure(): { width: number; height: number } {\n const width = this.root.offsetWidth;\n const height = this.root.offsetHeight;\n return width > 0 && height > 0 ? { width, height } : POPUP_FALLBACK_SIZE;\n }\n\n /**\n * Vertical padding + border of the popup: with the default `content-box`, a\n * `max-height` covering its whole rendered height must exclude them. A host\n * page that resets `box-sizing` to `border-box` already includes them.\n */\n private verticalChromeHeight(): number {\n const computed = window.getComputedStyle(this.root);\n if (computed.boxSizing === \"border-box\") return 0;\n return [computed.paddingTop, computed.paddingBottom, computed.borderTopWidth, computed.borderBottomWidth].reduce(\n (total, value) => total + (Number.parseFloat(value) || 0),\n 0,\n );\n }\n\n private selectType(type: FeedbackType, container: HTMLElement): void {\n this.selectedType = type;\n const buttons = container.querySelectorAll<HTMLButtonElement>(\"button\");\n for (const btn of buttons) {\n const isActive = btn.dataset.type === type;\n const color = getTypeColor(btn.dataset.type ?? \"\", this.colors);\n const bgColor = getTypeBgColor(btn.dataset.type ?? \"\", this.colors);\n btn.style.background = isActive ? bgColor : this.colors.glassBg;\n btn.style.borderColor = isActive ? color + \"60\" : this.colors.border;\n btn.style.color = isActive ? color : this.colors.textTertiary;\n btn.style.fontWeight = isActive ? \"600\" : \"500\";\n btn.setAttribute(\"aria-pressed\", String(isActive));\n }\n this.updateSubmitState();\n }\n\n private resetTypeButtons(): void {\n const buttons = this.root.querySelectorAll<HTMLButtonElement>(\"button[data-type]\");\n for (const btn of buttons) {\n btn.setAttribute(\"aria-pressed\", \"false\");\n btn.disabled = false;\n btn.style.background = this.colors.glassBg;\n btn.style.borderColor = this.colors.border;\n btn.style.color = this.colors.textTertiary;\n btn.style.fontWeight = \"500\";\n btn.style.cursor = \"pointer\";\n }\n }\n\n private updateSubmitState(): void {\n if (this.submittingState) return;\n const enabled = this.selectedType !== null && this.textarea.value.trim().length > 0;\n this.submitBtn.disabled = !enabled;\n this.submitBtn.style.opacity = enabled ? \"1\" : \"0.35\";\n this.submitBtn.style.pointerEvents = enabled ? \"auto\" : \"none\";\n }\n\n private submit(): void {\n if (this.submittingState) return;\n if (!this.selectedType || !this.textarea.value.trim()) return;\n\n const result: PopupResult = { type: this.selectedType, message: this.textarea.value.trim() };\n\n if (!this.onSubmit) {\n // Legacy fire-and-forget path: resolve immediately and hide.\n this.resolve?.(result);\n this.resolve = null;\n this.hideElement();\n return;\n }\n\n this.enterSubmittingState();\n const submitter = this.onSubmit;\n submitter(result)\n .then(() => {\n this.resolve?.(result);\n this.resolve = null;\n this.hideElement();\n })\n .catch(() => {\n // Restore the form so the user can edit and retry. The caller is\n // responsible for surfacing the error (live region / toast) — we\n // intentionally do not show inline error text in the popup.\n this.exitSubmittingState();\n });\n }\n\n /**\n * Close the popup as cancelled (`show()` resolves null): its Cancel button,\n * Escape, and the annotation session ending from outside the popup (toolbar\n * Cancel, Escape). No-op when the popup is already closed, or while a\n * submission is in flight: abandoning mid-upload would leak a half-sent\n * feedback.\n */\n dismiss(): void {\n if (this.submittingState || !this.isOpen) return;\n this.resolve?.(null);\n this.resolve = null;\n this.hideElement();\n }\n\n /**\n * Swap the submit button's text for a spinner and freeze every other\n * control. Mirrors the panel's resolve/delete buttons (`sp-spinner--sm`)\n * but renders inline because the popup lives outside the Shadow DOM\n * and therefore can't reach the panel's CSS classes.\n */\n private enterSubmittingState(): void {\n this.submittingState = true;\n\n // Submit: spinner instead of text, keep button width stable\n this.submitLabel.style.display = \"none\";\n this.submitBtn.disabled = true;\n this.submitBtn.style.cursor = \"wait\";\n this.submitBtn.style.opacity = \"0.85\";\n this.submitBtn.setAttribute(\"aria-busy\", \"true\");\n this.submitBtn.appendChild(this.buildSpinner());\n\n // Cancel: dimmed and non-interactive — abandoning mid-upload would leak a\n // half-sent feedback on the server, so we hold the user until we know.\n this.cancelBtn.disabled = true;\n this.cancelBtn.style.opacity = \"0.5\";\n this.cancelBtn.style.cursor = \"not-allowed\";\n this.cancelBtn.style.pointerEvents = \"none\";\n\n // Textarea + type buttons: read-only\n this.textarea.disabled = true;\n this.textarea.style.opacity = \"0.6\";\n const typeButtons = this.typeRow.querySelectorAll<HTMLButtonElement>(\"button\");\n for (const btn of typeButtons) {\n btn.disabled = true;\n btn.style.cursor = \"not-allowed\";\n btn.style.opacity = \"0.6\";\n }\n }\n\n private exitSubmittingState(): void {\n this.submittingState = false;\n\n // Submit — tear down the spinner: cancel the WAAPI animation explicitly\n // (it has `iterations: Infinity`, so it never ends on its own) before\n // removing the element it drives.\n this.spinnerAnimation?.cancel();\n this.spinnerAnimation = null;\n const spinner = this.submitBtn.querySelector<HTMLDivElement>('[data-role=\"sp-popup-spinner\"]');\n spinner?.remove();\n this.submitLabel.style.display = \"\";\n this.submitBtn.removeAttribute(\"aria-busy\");\n this.submitBtn.style.cursor = \"pointer\";\n\n // Cancel\n this.cancelBtn.disabled = false;\n this.cancelBtn.style.opacity = \"1\";\n this.cancelBtn.style.cursor = \"pointer\";\n this.cancelBtn.style.pointerEvents = \"auto\";\n\n // Textarea + type buttons\n this.textarea.disabled = false;\n this.textarea.style.opacity = \"1\";\n const typeButtons = this.typeRow.querySelectorAll<HTMLButtonElement>(\"button\");\n for (const btn of typeButtons) {\n btn.disabled = false;\n btn.style.cursor = \"pointer\";\n btn.style.opacity = \"1\";\n }\n\n // Recompute submit enabled state from the (preserved) form fields\n this.updateSubmitState();\n }\n\n /**\n * Build a spinner element styled inline. Web Animations API drives the\n * rotation so we don't have to inject `@keyframes` into the host document.\n * Respects `prefers-reduced-motion`: omits the animation and falls back to\n * a static ring. The returned `Animation` handle is stored on the instance\n * so `exitSubmittingState()` can explicitly cancel it.\n */\n private buildSpinner(): HTMLDivElement {\n const spinner = document.createElement(\"div\");\n spinner.dataset.role = \"sp-popup-spinner\";\n spinner.style.cssText = /* css */ `width:14px;height:14px;border:2px solid rgba(255,255,255,0.35);border-top-color:#fff;border-radius:50%;box-sizing:border-box;`\n\n\n\n\n\n;\n // Web Animations API is available in every browser we target; the guard\n // is defensive for jsdom in tests, where `animate` may be undefined.\n if (!prefersReducedMotion() && typeof spinner.animate === \"function\") {\n this.spinnerAnimation = spinner.animate([{ transform: \"rotate(0deg)\" }, { transform: \"rotate(360deg)\" }], {\n duration: 600,\n iterations: Infinity,\n easing: \"linear\",\n });\n }\n return spinner;\n }\n\n private hideElement(): void {\n this.cancelPendingTransition();\n // Remove focus trap\n if (this.onKeydownTrap) {\n this.root.removeEventListener(\"keydown\", this.onKeydownTrap);\n this.onKeydownTrap = null;\n }\n // Make sure the submitting decoration doesn't leak into the next show()\n if (this.submittingState) this.exitSubmittingState();\n this.onSubmit = null;\n this.stopKeyboardTracking?.();\n this.stopKeyboardTracking = null;\n this.root.style.opacity = \"0\";\n this.root.style.transform = this.hiddenTransform();\n // Restore focus to the previously focused element\n this.previouslyFocused?.focus();\n this.previouslyFocused = null;\n // Out of hit-testing and the Tab order while it fades: the transparent\n // popup sits above the overlay and the page, and would take the next\n // drag, click or Shift+Tab. The attribute, not the property, so jsdom\n // (which does not implement `inert`) can observe it.\n setSurfaceInert(this.root, true);\n if (prefersReducedMotion()) {\n this.root.style.display = \"none\";\n return;\n }\n this.hideTimeoutId = setTimeout(() => {\n this.hideTimeoutId = null;\n this.root.style.display = \"none\";\n }, POPUP_HIDE_TRANSITION_MS);\n }\n\n /** Drop the fade-in frame or the `display: none` still pending from an earlier show or close. */\n private cancelPendingTransition(): void {\n if (this.showFrame !== null) cancelAnimationFrame(this.showFrame);\n if (this.hideTimeoutId !== null) clearTimeout(this.hideTimeoutId);\n this.showFrame = null;\n this.hideTimeoutId = null;\n }\n\n destroy(): void {\n // Settle a pending `show()` promise so it cannot outlive teardown — a\n // `destroy()` mid-submit would otherwise leak the awaiting closure (and\n // whatever it retains: the annotation, the base64 screenshot). Resolving\n // with `null` reads as \"cancelled\", matching `dismiss()`.\n if (this.submittingState) this.exitSubmittingState();\n this.cancelPendingTransition();\n this.resolve?.(null);\n this.resolve = null;\n this.onSubmit = null;\n if (this.onKeydownTrap) {\n this.root.removeEventListener(\"keydown\", this.onKeydownTrap);\n this.onKeydownTrap = null;\n }\n this.stopKeyboardTracking?.();\n this.stopKeyboardTracking = null;\n this.root.remove();\n }\n}\n","/**\n * Screenshot capture via html2canvas-pro.\n *\n * `html2canvas-pro` is a regular `dependency` of `@siteping/widget` — every\n * install gets it. We dynamic-import it so bundlers emit a separate chunk\n * loaded only when `enableScreenshot: true` triggers the first capture;\n * hosts that never enable screenshots pay only the disk-space cost.\n *\n * Why the fork rather than html2canvas itself: the original parses only\n * `rgb()` / `hsl()` and has been unmaintained since 2022. Browsers now hand\n * back computed colors in whatever space the stylesheet used — `lab()`,\n * `oklab()`, `oklch()`, `color()` — and Tailwind 4 compiles every opacity\n * modifier (`bg-white/5`) to exactly those. The original threw on the first\n * such element and the whole capture was lost; the fork renders them.\n *\n * On capture failure (content-tainted canvas, version mismatch, missing 2D\n * context) we return `null` rather than throwing — the feedback is still\n * submitted, just without an image.\n */\n\nimport type { ScreenshotRegion } from \"@siteping/core\";\n\ntype Html2CanvasFn = (element: HTMLElement, options?: Html2CanvasOptions) => Promise<HTMLCanvasElement>;\n\ninterface Html2CanvasOptions {\n x?: number;\n y?: number;\n width?: number;\n height?: number;\n scale?: number;\n useCORS?: boolean;\n allowTaint?: boolean;\n logging?: boolean;\n ignoreElements?: (element: Element) => boolean;\n}\n\nlet cachedHtml2Canvas: Html2CanvasFn | null | undefined; // undefined = not loaded yet, null = failed\nlet warnedAboutMissingDep = false;\n\nasync function loadHtml2Canvas(): Promise<Html2CanvasFn | null> {\n if (cachedHtml2Canvas !== undefined) return cachedHtml2Canvas;\n try {\n // Static dynamic import — bundlers (Vite, webpack, esbuild) resolve this\n // at build time and emit a separate chunk loaded only on first capture.\n // html2canvas-pro ships as a regular dependency so this resolves on every\n // install. Earlier attempts to dodge static resolution via magic comments\n // silently broke production: bare specifiers can't be resolved at runtime\n // in browsers without import maps.\n //\n // Through `unknown` because the module namespace also carries the fork's\n // named exports (config, validator, monitor), so TypeScript no longer\n // sees enough overlap with the callable shape we actually consume.\n const mod = (await import(\"html2canvas-pro\")) as unknown as { default?: Html2CanvasFn } & Html2CanvasFn;\n cachedHtml2Canvas = (mod.default ?? mod) as Html2CanvasFn;\n return cachedHtml2Canvas;\n } catch (err) {\n cachedHtml2Canvas = null;\n if (!warnedAboutMissingDep) {\n warnedAboutMissingDep = true;\n console.warn(\n \"[siteping] html2canvas-pro import failed unexpectedly. Capture is disabled for this session — feedbacks are still submitted, just without screenshots. Underlying error:\",\n err,\n );\n }\n return null;\n }\n}\n\nexport interface CaptureOptions {\n /** JPEG quality 0..1 (default 0.85). */\n quality?: number;\n /** Max output width in CSS pixels (default 1200). Wider canvases are downscaled. */\n maxWidth?: number;\n}\n\n/** Result of a contextual capture: the JPEG plus where the drawn rect sits in it. */\nexport interface AnnotatedScreenshot {\n /** Base64 JPEG `data:` URL of the padded capture area. */\n dataUrl: string;\n /** The drawn rect's position within the image, as fractions of its dimensions. */\n region: ScreenshotRegion;\n}\n\n/** Clamp `value` into `[min, max]`. */\nfunction clamp(min: number, value: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n\n/** Round a fraction to 4 decimals and clamp it into [0, 1]. */\nfunction roundPct(value: number): number {\n return clamp(0, Math.round(value * 10_000) / 10_000, 1);\n}\n\n/**\n * Capture the drawn rect *plus surrounding context* as a JPEG data URL, and\n * report where the rect sits inside the image (`region`, as fractions of the\n * image dimensions) so dashboards can re-render the annotation on top.\n * Returns `null` on any failure — callers should not abort feedback submission.\n *\n * - Pads the rect by up to 60% of its own size (48px floor, 280/220px ceiling)\n * so reviewers see the UI around the annotation, not just its pixels\n * - Clamps the capture area to the document bounds (no blank margins)\n * - Excludes Siteping's own overlay elements via `ignoreElements`\n * - Honors devicePixelRatio for crisp captures, then downscales to `maxWidth`\n * — `region` is resolution-independent, so it survives the downscale\n * - JPEG at `quality` (0.85 = ~50–150 KB for a typical annotated area)\n */\nexport async function captureAnnotatedScreenshot(\n rect: DOMRect,\n options?: CaptureOptions,\n): Promise<AnnotatedScreenshot | null> {\n const html2canvas = await loadHtml2Canvas();\n if (!html2canvas) return null;\n\n const quality = options?.quality ?? 0.85;\n const maxWidth = options?.maxWidth ?? 1200;\n\n // Contextual padding, proportional to the rect with fixed floor/ceiling —\n // small rects still get enough context to be recognizable, huge rects\n // don't balloon the capture (CSS px).\n const padX = clamp(48, rect.width * 0.6, 280);\n const padY = clamp(48, rect.height * 0.6, 220);\n\n // Document coordinates of the drawn rect (rect is viewport-relative).\n const docX = window.scrollX + rect.x;\n const docY = window.scrollY + rect.y;\n\n // Clamp the padded capture area to the document bounds so the engine\n // never renders blank out-of-document margins.\n const docW = Math.max(document.documentElement.scrollWidth, document.body.scrollWidth);\n const docH = Math.max(document.documentElement.scrollHeight, document.body.scrollHeight);\n const capX = Math.max(0, docX - padX);\n const capY = Math.max(0, docY - padY);\n const capW = Math.min(docW, docX + rect.width + padX) - capX;\n const capH = Math.min(docH, docY + rect.height + padY) - capY;\n if (capW <= 0 || capH <= 0) return null;\n\n // Fractions are resolution-independent — computed once from CSS-px\n // geometry, they stay valid after the hi-DPI render and the downscale.\n const region: ScreenshotRegion = {\n xPct: roundPct((docX - capX) / capW),\n yPct: roundPct((docY - capY) / capH),\n wPct: roundPct(rect.width / capW),\n hPct: roundPct(rect.height / capH),\n };\n\n try {\n const canvas = await html2canvas(document.body, {\n x: capX,\n y: capY,\n width: capW,\n height: capH,\n scale: window.devicePixelRatio,\n useCORS: true,\n allowTaint: true,\n logging: false,\n ignoreElements: (element: Element) => {\n // Matched elements (and their descendants) are removed from the\n // render pass — the page underneath shows through. Two layers of\n // exclusion:\n //\n // 1. The widget's own shadow host (`<siteping-widget>`).\n // 2. Anything carrying `data-siteping-ignore=\"true\"` — the\n // documented host-facing masking attribute AND how widget\n // chrome that lives OUTSIDE the shadow host (annotator overlay\n // + toolbar + drawing rect, popup) opts itself out of capture.\n // Without (2) the accent-colored selection border ends up\n // baked into the JPEG.\n return (\n element.tagName === \"SITEPING-WIDGET\" ||\n element.closest?.(\"siteping-widget\") !== null ||\n element.getAttribute?.(\"data-siteping-ignore\") === \"true\"\n );\n },\n });\n\n if (canvas.width <= maxWidth) {\n return { dataUrl: canvas.toDataURL(\"image/jpeg\", quality), region };\n }\n\n // Downscale via an off-DOM canvas — keeps payload reasonable on\n // hi-DPI displays where the raw capture can be 2x–3x intended size.\n const ratio = maxWidth / canvas.width;\n const targetW = maxWidth;\n const targetH = Math.round(canvas.height * ratio);\n\n const scaled = document.createElement(\"canvas\");\n scaled.width = targetW;\n scaled.height = targetH;\n const ctx = scaled.getContext(\"2d\");\n if (!ctx) return null;\n ctx.drawImage(canvas, 0, 0, targetW, targetH);\n return { dataUrl: scaled.toDataURL(\"image/jpeg\", quality), region };\n } catch (err) {\n console.warn(\"[siteping] Screenshot capture failed:\", err);\n return null;\n }\n}\n\n/** @internal — exposed for tests. Resets the dynamic-import cache. */\nexport function _resetScreenshotCacheForTests(): void {\n cachedHtml2Canvas = undefined;\n warnedAboutMissingDep = false;\n}\n","import { type AnnotationPayload, type FeedbackType, newClientId, type ScreenshotRegion } from \"@siteping/core\";\nimport { INSTANT_ANNOTATION_SIZE, Z_INDEX_MAX } from \"./constants.js\";\nimport { deepElementFromPoint, findAnchorElement, generateAnchor, rectToPercentages } from \"./dom/anchor.js\";\nimport { el, setText } from \"./dom-utils.js\";\nimport type { EventBus, WidgetEvents } from \"./events.js\";\nimport { deepFocusTarget, isWidgetChrome } from \"./focus-tracker.js\";\nimport { isolateFromHost, registerEscapeLayer } from \"./host-isolation.js\";\nimport type { TFunction } from \"./i18n/index.js\";\nimport { Popup } from \"./popup.js\";\nimport { NO_VIEWPORT_INSETS, type ViewportInsets } from \"./popup-placement.js\";\nimport { type AnnotatedScreenshot, captureAnnotatedScreenshot } from \"./screenshot.js\";\nimport type { ThemeColors } from \"./styles/theme.js\";\nimport { isCoarsePointer, isCompactViewport } from \"./viewport.js\";\n\n/** Below this size (px) a drawn rect is an accidental click — or, on touch, a tap. */\nconst MIN_RECT_SIZE = 10;\n\n/** The part of a viewport rect that is on screen. */\nfunction clampToViewport(r: DOMRect): DOMRect {\n const left = Math.max(0, r.left);\n const top = Math.max(0, r.top);\n return new DOMRect(\n left,\n top,\n Math.max(0, Math.min(r.right, window.innerWidth) - left),\n Math.max(0, Math.min(r.bottom, window.innerHeight) - top),\n );\n}\n\nexport interface AnnotationComplete {\n annotation: AnnotationPayload;\n type: FeedbackType;\n message: string;\n /**\n * Idempotency key of this feedback, minted once per popup session: every\n * resend from the same popup carries it, so the server (and the retry\n * queue) dedupe a resend against an earlier attempt instead of storing\n * the feedback twice. See `PopupSession`.\n */\n clientId: string;\n /**\n * Base64 JPEG `data:` URL captured by html2canvas-pro, or null when capture\n * is disabled / failed / the peer dep is missing.\n */\n screenshotDataUrl?: string | null | undefined;\n /**\n * Where the drawn rect sits within the captured screenshot, as fractions\n * of the image dimensions — see `ScreenshotRegion`. Null whenever\n * `screenshotDataUrl` is null.\n */\n screenshotRegion?: ScreenshotRegion | null | undefined;\n}\n\n/**\n * State shared by every submit attempt from one popup session (the popup\n * restores the form after a failure so the user can resend).\n *\n * `clientId` is reused even when the user edits the message before\n * resending. If the first attempt landed although it timed out on our side,\n * the server dedupes the resend and returns the original record, so that\n * edit is lost — accepted: it takes a commit whose response never arrived,\n * and minting a new id on edit would store a duplicate in that same case.\n */\ninterface PopupSession {\n readonly clientId: string;\n /** Captured on the first attempt (`undefined` until then) and reused on every retry. */\n screenshot?: AnnotatedScreenshot | null;\n}\n\nfunction newPopupSession(): PopupSession {\n return { clientId: newClientId() };\n}\n\n/**\n * Annotation mode: full-page overlay with rectangle drawing.\n *\n * Glassmorphism design:\n * - Frosted glass toolbar at top\n * - Subtle tinted overlay\n * - Accent-colored drawing rectangle with glow\n */\nexport class Annotator {\n private overlay: HTMLElement | null = null;\n private toolbar: HTMLElement | null = null;\n private drawingRect: HTMLElement | null = null;\n private startX = 0;\n private startY = 0;\n private isDrawing = false;\n private isActive = false;\n /**\n * True when the current annotation session was triggered by right-click\n * (instant comment) rather than the FAB draw flow. Controls whether the\n * toolbar is shown and whether cancel deactivates unconditionally.\n */\n private instantMode = false;\n private popup: Popup;\n private savedOverflow = \"\";\n private preActiveFocusElement: Element | null = null;\n /**\n * Target of the keyboard (Enter) annotation path — the page element focused\n * at activation, or the focus tracker's fallback when activation came from\n * the widget's own chrome (FAB menu). Distinct from `preActiveFocusElement`,\n * which keeps its focus-restore role untouched. See issue #162.\n */\n private keyboardTarget: HTMLElement | null = null;\n private rafId: number | null = null;\n private pendingMoveEvent: MouseEvent | Touch | null = null;\n /**\n * Reject handle for the in-flight `runSubmission` promise, or null when no\n * submission is pending. `destroy()` calls it to settle the promise rather\n * than leaving the awaiting closure hung past teardown.\n */\n private rejectPendingSubmission: ((reason: Error) => void) | null = null;\n /**\n * The session's Escape handler listens on `document` and also ends a\n * session from its comment popup: one layer covers overlay, toolbar and popup.\n */\n private readonly unregisterEscapeLayer = registerEscapeLayer(document, () => this.isActive);\n\n constructor(\n private readonly colors: ThemeColors,\n private readonly bus: EventBus<WidgetEvents>,\n private readonly t: TFunction,\n private readonly enableScreenshot: boolean = false,\n private readonly getFallbackTarget?: () => HTMLElement | null,\n ) {\n this.popup = new Popup(colors, t);\n\n this.bus.on(\"annotation:start\", () => this.activate());\n }\n\n /**\n * True while the annotator is active (overlay/popup session in progress).\n * The launcher checks this before calling `preventDefault()` on the\n * `contextmenu` event so a right-click during an active session falls\n * through to the native menu instead of being silently swallowed.\n */\n get isBusy(): boolean {\n return this.isActive;\n }\n\n /**\n * Re-read every `t(...)`-derived label inside the popup. The annotator's\n * own toolbar text is created fresh on every `activate()` call, so only\n * the long-lived popup needs explicit re-localization here.\n */\n refreshLabels(): void {\n this.popup.refreshLabels();\n }\n\n /**\n * Capture a contextual screenshot of the drawn rect (padded with the\n * surrounding UI, plus the rect's region within the image) when\n * `enableScreenshot` is on. Returns null on disable / capture failure /\n * missing peer dep — the feedback is always submitted regardless.\n */\n private async maybeCapture(rect: DOMRect): Promise<AnnotatedScreenshot | null> {\n if (!this.enableScreenshot) return null;\n return captureAnnotatedScreenshot(rect);\n }\n\n private activate(): void {\n if (this.isActive) return;\n this.isActive = true;\n const drawMode = !this.instantMode;\n const compact = isCompactViewport();\n const touch = isCoarsePointer();\n // The visible copy on touch says \"tap an element\". The overlay's name keeps\n // the Enter route (#162): tablets with a keyboard, and screen readers on them.\n const instruction = this.t(\"annotator.instruction\");\n\n // Capture the focused element before activation for keyboard annotation\n this.preActiveFocusElement = document.activeElement;\n\n // Keyboard (Enter) target. FAB-launched sessions re-focus the FAB before\n // activation, so the active element here is only the widget's 0x0 shadow\n // host — fall back to the last page element the focus tracker recorded\n // instead of silently dead-ending the Enter path. See issue #162.\n // Focus inside a web component reports its host — annotate the focused\n // element itself, as the pointer path does (#177).\n const active = document.activeElement;\n this.keyboardTarget =\n active instanceof HTMLElement &&\n active !== document.body &&\n active !== document.documentElement &&\n !isWidgetChrome(active)\n ? deepFocusTarget(active)\n : (this.getFallbackTarget?.() ?? null);\n\n // Lock page scroll\n this.savedOverflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n\n // Overlay — subtle blue tint for depth.\n //\n // Overlay, toolbar and the drawn rectangle live on document.body, outside\n // the siteping-widget shadow host. Without the `data-siteping-ignore`\n // marker the screenshot predicate in screenshot.ts cannot reach them —\n // and the accent-colored selection border plus the page tint end up\n // baked into the captured JPEG. See issue #124.\n this.overlay = el(\"div\", {\n style: /* css */ `position:fixed;inset:0;z-index:${Z_INDEX_MAX - 1};pointer-events:auto;background:rgba(15,23,42,0.04);cursor:${drawMode ? \"crosshair\" : \"default\"};touch-action:none;-webkit-touch-callout:none;-webkit-user-select:none;user-select:none;`\n\n\n\n\n\n\n\n,\n });\n // The overlay is an interactive surface (draw with the pointer, Enter to\n // annotate the previously focused element, Escape to cancel) and receives\n // programmatic focus below — so it must be exposed to assistive tech, NOT\n // aria-hidden: focusing an aria-hidden element parks screen-reader users\n // on a node that announces nothing (axe \"aria-hidden-focus\", serious).\n this.overlay.setAttribute(\"role\", \"application\");\n this.overlay.setAttribute(\"aria-label\", drawMode ? instruction : this.t(\"annotator.instantInstruction\"));\n this.overlay.setAttribute(\"data-siteping-ignore\", \"true\");\n\n // Toolbar — glassmorphism bar (suppressed in instant mode: the\n // \"Draw a rectangle\" copy is wrong when the composer is already open)\n if (drawMode) {\n this.toolbar = el(\"div\", {\n style: /* css */ `position:fixed;top:0;left:0;right:0;z-index:${Z_INDEX_MAX};pointer-events:auto;min-height:52px;box-sizing:border-box;padding:calc(env(safe-area-inset-top,0px) + 8px) ${compact ? \"12px 8px 16px\" : \"16px 8px\"};background:${compact ? this.colors.bg : this.colors.glassBg};backdrop-filter:blur(24px);-webkit-backdrop-filter:blur(24px);border-bottom:1px solid ${this.colors.glassBorder};display:flex;align-items:center;justify-content:center;gap:${compact ? 12 : 16}px;font-family:\"Inter\",system-ui,-apple-system,sans-serif;font-size:14px;line-height:1.35;color:${this.colors.text};box-shadow:0 4px 16px ${this.colors.shadow};-webkit-font-smoothing:antialiased;`\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n,\n });\n this.toolbar.setAttribute(\"data-siteping-ignore\", \"true\");\n\n const dot = el(\"span\", {\n style: /* css */ `width:8px;height:8px;border-radius:50%;flex-shrink:0;background:${this.colors.accent};box-shadow:0 0 8px ${this.colors.accentGlow};animation:pulse 1.5s ease-in-out infinite;`\n\n\n\n\n,\n });\n\n // Add pulse animation inline (respects prefers-reduced-motion)\n const style = document.createElement(\"style\");\n style.textContent = [\n \"@keyframes pulse{0%,100%{opacity:1}50%{opacity:0.4}}\",\n \"@media(prefers-reduced-motion:reduce){@keyframes pulse{from,to{opacity:1}}}\",\n ].join(\"\");\n this.toolbar.appendChild(style);\n\n const instructionEl = el(\"span\", { style: \"font-weight:500;letter-spacing:-0.01em;min-width:0;\" });\n setText(instructionEl, touch ? this.t(\"annotator.touchInstruction\") : instruction);\n\n const cancelBtn = document.createElement(\"button\");\n cancelBtn.style.cssText = /* css */ `height:${touch ? 40 : 34}px;padding:0 18px;border-radius:9999px;flex-shrink:0;border:1px solid ${this.colors.border};background:${this.colors.glassBg};color:${this.colors.textTertiary};font-family:\"Inter\",system-ui,-apple-system,sans-serif;font-size:13px;font-weight:500;cursor:pointer;transition:all 0.2s ease;`\n\n\n\n\n\n\n;\n setText(cancelBtn, this.t(\"annotator.cancel\"));\n cancelBtn.addEventListener(\"click\", () => this.cancelSession());\n cancelBtn.addEventListener(\"mouseenter\", () => {\n cancelBtn.style.borderColor = this.colors.typeBug;\n cancelBtn.style.color = this.colors.typeBug;\n cancelBtn.style.background = this.colors.typeBugBg;\n });\n cancelBtn.addEventListener(\"mouseleave\", () => {\n cancelBtn.style.borderColor = this.colors.border;\n cancelBtn.style.color = this.colors.textTertiary;\n cancelBtn.style.background = this.colors.glassBg;\n });\n\n this.toolbar.appendChild(dot);\n this.toolbar.appendChild(instructionEl);\n this.toolbar.appendChild(cancelBtn);\n }\n\n if (drawMode) {\n // Mouse events\n this.overlay.addEventListener(\"mousedown\", this.onMouseDown);\n this.overlay.addEventListener(\"mousemove\", this.onMouseMove);\n this.overlay.addEventListener(\"mouseup\", this.onMouseUp);\n\n // Touch events (Surface Pro, iPad, etc.)\n this.overlay.addEventListener(\"touchstart\", this.onTouchStart, { passive: false });\n this.overlay.addEventListener(\"touchmove\", this.onTouchMove, { passive: false });\n this.overlay.addEventListener(\"touchend\", this.onTouchEnd);\n\n // Keyboard annotation: Enter selects the captured keyboard target\n this.overlay.addEventListener(\"keydown\", this.onOverlayKeyDown);\n }\n\n // Allow tab-through so keyboard users can reach underlying elements\n this.overlay.setAttribute(\"tabindex\", \"0\");\n\n // Escape to cancel\n document.addEventListener(\"keydown\", this.onKeyDown);\n\n isolateFromHost(this.overlay);\n if (this.toolbar) isolateFromHost(this.toolbar);\n document.body.appendChild(this.overlay);\n if (this.toolbar) document.body.appendChild(this.toolbar);\n\n // Move focus to the overlay so the keyboard-annotation path (Enter →\n // annotate the captured keyboard target) actually receives keydown —\n // onOverlayKeyDown only fires when the overlay itself is focused. The\n // overlay has tabindex=0, and the keyboard target was captured at the top\n // of activate(), before the overlay existed, so focusing here doesn't\n // clobber it. (WCAG 2.1.1 Level A)\n this.overlay.focus({ preventScroll: true });\n }\n\n /**\n * Viewport band covered by the toolbar, measured rather than assumed: its\n * height depends on fonts and zoom, and a host may restyle or move it.\n */\n private toolbarInsets(): ViewportInsets {\n if (!this.toolbar) return NO_VIEWPORT_INSETS;\n const toolbarRect = this.toolbar.getBoundingClientRect();\n if (toolbarRect.height === 0) return NO_VIEWPORT_INSETS;\n const viewportHeight = window.innerHeight;\n const sitsInTopHalf = toolbarRect.top + toolbarRect.height / 2 < viewportHeight / 2;\n return sitsInTopHalf\n ? { top: Math.max(0, toolbarRect.bottom), bottom: 0 }\n : { top: 0, bottom: Math.max(0, viewportHeight - toolbarRect.top) };\n }\n\n /**\n * User-initiated end of the session (toolbar Cancel, Escape). Closes an open\n * comment form first so it is not left floating with nothing behind it — the\n * popup's own focus restore runs before the annotator hands focus back to the\n * pre-activation element. While a submission is in flight the popup refuses\n * to close, and the session stays active too: deactivating here would clear\n * `isActive` and emit `annotation:end` while the popup still waits on\n * `feedback:sent`, letting a second annotation overwrite its resolver and\n * submit handler. The session ends once the pending popup settles; the\n * send bounds its network and store waits (#342), so the hold ends too.\n */\n private cancelSession(): void {\n if (!this.isActive) return;\n this.popup.dismiss();\n if (this.popup.isOpen) return;\n this.deactivate();\n }\n\n private deactivate(): void {\n if (!this.isActive) return;\n this.isActive = false;\n this.isDrawing = false;\n this.instantMode = false;\n const previouslyFocused = this.preActiveFocusElement;\n this.preActiveFocusElement = null;\n this.keyboardTarget = null;\n\n // Cancel any pending rAF to prevent stale callbacks\n if (this.rafId !== null) {\n cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n this.pendingMoveEvent = null;\n\n document.body.style.overflow = this.savedOverflow;\n document.removeEventListener(\"keydown\", this.onKeyDown);\n\n this.overlay?.remove();\n this.toolbar?.remove();\n this.drawingRect?.remove();\n this.overlay = null;\n this.toolbar = null;\n this.drawingRect = null;\n\n // Removing the focused overlay drops focus to <body> — hand it back to the\n // element that had it before activation (WCAG 2.4.3 focus order). When\n // activation came from the FAB menu this element is the shadow host and\n // focus() is a no-op; the Fab restores itself on annotation:end instead.\n if (previouslyFocused instanceof HTMLElement && previouslyFocused.isConnected) {\n previouslyFocused.focus({ preventScroll: true });\n }\n\n this.bus.emit(\"annotation:end\");\n }\n\n private onKeyDown = (e: KeyboardEvent): void => {\n if (e.key === \"Escape\") this.cancelSession();\n };\n\n /**\n * Keyboard annotation: pressing Enter while the overlay is active selects\n * the keyboard target captured at activation (the focused page element, or\n * the focus tracker's fallback for FAB-launched sessions) and creates a\n * full-bounds annotation covering that element (WCAG 2.1.1 Level A).\n */\n private onOverlayKeyDown = async (e: KeyboardEvent): Promise<void> => {\n if (e.key !== \"Enter\") return;\n e.preventDefault();\n // A submission is already running or the popup is open — ignore so we\n // can't orphan the first `popup.show()` / `runSubmission` pair.\n if (this.popup.isOpen) return;\n // Mid-pointer-drag: the user is drawing — hijacking `drawingRect` for the\n // keyboard highlight here would corrupt the drag's geometry updates.\n if (this.isDrawing) return;\n\n const target = this.keyboardTarget;\n if (!target || !(target instanceof HTMLElement)) return;\n await this.annotateElement(target);\n };\n\n /**\n * Comment on a whole element with a full-bounds rect — the keyboard (Enter)\n * path and the touch tap path. A tapped element can be far taller than the\n * screen, and the capture renders at devicePixelRatio (3 on phones): the tap\n * path captures only its visible part, like the instant flow.\n */\n private async annotateElement(target: HTMLElement, tap = false): Promise<void> {\n const bounds = target.getBoundingClientRect();\n if (bounds.width <= 0 || bounds.height <= 0) return;\n\n const rectBounds = new DOMRect(bounds.x, bounds.y, bounds.width, bounds.height);\n\n // Highlight the target like a pointer-drawn rectangle so the user sees\n // what they're about to comment. Assigned to `drawingRect` so every\n // existing cleanup path (deactivate, screenshot exclusion, removal once\n // the popup closes) treats it exactly like the mouse path's rect.\n this.drawingRect?.remove();\n const highlight = this.createDrawingRect();\n highlight.style.left = `${bounds.x}px`;\n highlight.style.top = `${bounds.y}px`;\n highlight.style.width = `${bounds.width}px`;\n highlight.style.height = `${bounds.height}px`;\n this.drawingRect = highlight;\n this.overlay?.appendChild(highlight);\n\n const anchor = generateAnchor(target);\n const annotation: AnnotationPayload = {\n anchor,\n rect: { xPct: 0, yPct: 0, wPct: 1, hPct: 1 },\n scrollX: window.scrollX,\n scrollY: window.scrollY,\n viewportW: window.innerWidth,\n viewportH: window.innerHeight,\n devicePixelRatio: window.devicePixelRatio,\n };\n\n // Submission stays inside the popup so the user gets a visible spinner\n // until the server confirms — see finishDrawing for the rationale.\n const result = await this.openForm(annotation, rectBounds, tap ? clampToViewport(rectBounds) : rectBounds);\n\n this.drawingRect?.remove();\n this.drawingRect = null;\n if (result) this.deactivate();\n }\n\n private onMouseDown = (e: MouseEvent): void => {\n this.startDrawing(e.clientX, e.clientY);\n };\n\n private onTouchStart = (e: TouchEvent): void => {\n e.preventDefault();\n const touch = e.touches[0];\n if (touch) this.startDrawing(touch.clientX, touch.clientY);\n };\n\n private startDrawing(clientX: number, clientY: number): void {\n // Suppress pointer-driven drawing while the popup is open over the page.\n // Starting a second rectangle would orphan the first `popup.show()`\n // promise (and its `runSubmission`). This closes a latent bug where\n // drawing during the open popup overwrote `Popup.resolve`.\n if (this.popup.isOpen) return;\n\n this.isDrawing = true;\n this.startX = clientX;\n this.startY = clientY;\n\n this.drawingRect?.remove();\n this.drawingRect = this.createDrawingRect();\n this.overlay?.appendChild(this.drawingRect);\n }\n\n /**\n * The accent-colored selection rectangle — shared by pointer drawing and\n * the keyboard (Enter) highlight so the two paths can't drift visually.\n * Excluded from screenshot capture (see overlay creation in activate()).\n */\n private createDrawingRect(): HTMLElement {\n const rect = el(\"div\", {\n style: /* css */ `position:fixed;border:2px solid ${this.colors.accent};background:${this.colors.accent}12;pointer-events:none;border-radius:8px;box-shadow:0 0 16px ${this.colors.accentGlow};transition:box-shadow 0.15s ease;`\n\n\n\n\n\n\n\n,\n });\n rect.setAttribute(\"data-siteping-ignore\", \"true\");\n return rect;\n }\n\n private onMouseMove = (e: MouseEvent): void => {\n this.scheduleRectUpdate(e);\n };\n\n private onTouchMove = (e: TouchEvent): void => {\n e.preventDefault();\n if (e.touches[0]) this.scheduleRectUpdate(e.touches[0]);\n };\n\n private scheduleRectUpdate(source: MouseEvent | Touch): void {\n if (!this.isDrawing || !this.drawingRect) return;\n\n this.pendingMoveEvent = source;\n if (this.rafId !== null) return;\n\n this.rafId = requestAnimationFrame(() => {\n this.rafId = null;\n const evt = this.pendingMoveEvent;\n if (!evt || !this.drawingRect) return;\n\n const x = Math.min(evt.clientX, this.startX);\n const y = Math.min(evt.clientY, this.startY);\n const w = Math.abs(evt.clientX - this.startX);\n const h = Math.abs(evt.clientY - this.startY);\n\n this.drawingRect.style.left = `${x}px`;\n this.drawingRect.style.top = `${y}px`;\n this.drawingRect.style.width = `${w}px`;\n this.drawingRect.style.height = `${h}px`;\n });\n }\n\n private onTouchEnd = async (e: TouchEvent): Promise<void> => {\n const touch = e.changedTouches[0];\n if (!touch) return;\n // A tap, or a slide too thin to frame an area (a finger along a line of\n // text): comment on the element under the finger instead of dropping the\n // gesture — a fingertip hides the very corner it is trying to place.\n if (\n this.isDrawing &&\n (Math.abs(touch.clientX - this.startX) < MIN_RECT_SIZE || Math.abs(touch.clientY - this.startY) < MIN_RECT_SIZE)\n ) {\n this.isDrawing = false;\n this.drawingRect?.remove();\n this.drawingRect = null;\n const target = this.elementAt(touch.clientX, touch.clientY);\n if (target) await this.annotateElement(target, true);\n return;\n }\n await this.finishDrawing(touch.clientX, touch.clientY);\n };\n\n /**\n * The page element under a point, seen through the overlay and into open\n * shadow roots like the drag path — null for widget chrome and the page root.\n */\n private elementAt(x: number, y: number): HTMLElement | null {\n if (this.overlay) this.overlay.style.pointerEvents = \"none\";\n const hit = deepElementFromPoint(x, y);\n if (this.overlay) this.overlay.style.pointerEvents = \"auto\";\n // An icon's <path> is no target — take the element hosting the <svg>.\n const target = hit instanceof SVGElement ? (hit.ownerSVGElement ?? hit).parentElement : hit;\n return target instanceof HTMLElement &&\n target !== document.body &&\n target !== document.documentElement &&\n !isWidgetChrome(target)\n ? target\n : null;\n }\n\n private onMouseUp = async (e: MouseEvent): Promise<void> => {\n await this.finishDrawing(e.clientX, e.clientY);\n };\n\n private finishDrawing = async (clientX: number, clientY: number): Promise<void> => {\n if (!this.isDrawing || !this.drawingRect) return;\n this.isDrawing = false;\n\n const x = Math.min(clientX, this.startX);\n const y = Math.min(clientY, this.startY);\n const w = Math.abs(clientX - this.startX);\n const h = Math.abs(clientY - this.startY);\n\n // Ignore tiny rectangles (accidental clicks)\n if (w < MIN_RECT_SIZE || h < MIN_RECT_SIZE) {\n this.drawingRect.remove();\n this.drawingRect = null;\n return;\n }\n\n const rectBounds = new DOMRect(x, y, w, h);\n\n // Build annotation payload BEFORE the popup opens — the overlay is still\n // up so `findAnchorElement` can briefly disable pointer events on it.\n const { annotation } = this.buildAnnotation(rectBounds);\n\n // Keep the drawn rectangle visible while the popup is open so the user\n // can see what they're sending feedback about — including while the\n // submit-spinner is running. We only remove it after the popup closes.\n const result = await this.openForm(annotation, rectBounds);\n\n this.drawingRect?.remove();\n this.drawingRect = null;\n if (result) this.deactivate();\n };\n\n /**\n * Instantly triggers the annotation popup at a specific location without\n * requiring the user to draw a rectangle. Used for right-click commenting.\n *\n * Entry is routed through the event bus (`annotation:start`) so the public\n * event contract (`onAnnotationStart` / `onAnnotationEnd`) is honoured —\n * hosts that pause analytics or chat widgets on annotation hooks see a\n * symmetric start/end pair regardless of entry path.\n */\n public async startInstantAnnotation(clientX: number, clientY: number): Promise<void> {\n // Guard: no-op while the annotator is active (overlay/popup session in\n // progress). `isActive` covers the entire window: draw mode in progress,\n // popup open for typing, and submission in flight. Without this a second\n // right-click (e.g. to paste in the textarea) would reset the form,\n // orphan the pending popup.show(), and leak the old drawing rect.\n if (this.isActive) return;\n\n // Set instant-mode flag BEFORE emitting annotation:start so activate()\n // (called by the bus handler) can read it and suppress the toolbar.\n this.instantMode = true;\n this.bus.emit(\"annotation:start\");\n\n // Build a small point-rect centered at the cursor for the marker/percentage\n // math. Clamped to viewport edges on all sides.\n const x = Math.max(0, Math.min(clientX - INSTANT_ANNOTATION_SIZE / 2, window.innerWidth - INSTANT_ANNOTATION_SIZE));\n const y = Math.max(\n 0,\n Math.min(clientY - INSTANT_ANNOTATION_SIZE / 2, window.innerHeight - INSTANT_ANNOTATION_SIZE),\n );\n const pointRect = new DOMRect(x, y, INSTANT_ANNOTATION_SIZE, INSTANT_ANNOTATION_SIZE);\n\n // Resolve the anchor element and build the annotation payload.\n // We also derive the capture rect from the anchor element's bounding box\n // (clamped to the viewport) so enableScreenshot produces a useful image\n // instead of a postage stamp.\n const { annotation, anchorBounds } = this.buildAnnotation(pointRect);\n\n // Use the anchor element's bounding box (clamped to viewport) for\n // screenshot capture so reviewers get meaningful context, not a 20×20 px\n // postage stamp.\n const captureRect = clampToViewport(anchorBounds);\n\n // Create a visual indicator at the click point\n this.drawingRect?.remove();\n this.drawingRect = el(\"div\", {\n style: /* css */ `position:fixed;left:${x}px;top:${y}px;width:${INSTANT_ANNOTATION_SIZE}px;height:${INSTANT_ANNOTATION_SIZE}px;border:2px solid ${this.colors.accent};background:${this.colors.accent}12;pointer-events:none;border-radius:8px;box-shadow:0 0 16px ${this.colors.accentGlow};`\n\n\n\n\n\n\n\n\n\n\n,\n });\n this.drawingRect.setAttribute(\"data-siteping-ignore\", \"true\");\n this.overlay?.appendChild(this.drawingRect);\n\n await this.openForm(annotation, pointRect, captureRect);\n\n // Instant flow: always deactivate on popup close — unlike the draw flow\n // where cancel keeps the session alive so the user can re-draw, there is\n // no draw phase to return to here. Leaving the overlay, scroll-lock and\n // toolbar up after cancel strands the user in a mode they never opted into.\n this.drawingRect?.remove();\n this.drawingRect = null;\n this.deactivate();\n }\n\n /**\n * Open the feedback form for a selection as one popup session (see\n * `PopupSession`); it submits through `runSubmission`. Resolves null when\n * the user cancels.\n */\n private openForm(\n annotation: AnnotationPayload,\n rect: DOMRect,\n captureRect: DOMRect = rect,\n ): ReturnType<Popup[\"show\"]> {\n const session = newPopupSession();\n const shown = this.popup.show(\n rect,\n (formResult) => this.runSubmission(annotation, formResult, captureRect, session),\n this.toolbarInsets(),\n );\n this.revealSelection(rect);\n return shown;\n }\n\n /**\n * Phones: the feedback sheet covers the bottom of the screen. Scroll the\n * page so the selection stays visible above it — the highlight is fixed,\n * so it moves by the same amount. Never scrolls the selection's top under\n * the toolbar.\n */\n private revealSelection(rect: DOMRect): void {\n const sheetTop = this.popup.sheetTop;\n if (sheetTop === null || !this.drawingRect) return;\n const wanted = Math.min(rect.bottom + 16 - sheetTop, rect.top - 72);\n if (wanted <= 0) return;\n const before = window.scrollY;\n window.scrollBy({ top: wanted, behavior: \"instant\" });\n this.drawingRect.style.top = `${rect.top - (window.scrollY - before)}px`;\n }\n\n /**\n * Submit handler passed into `popup.show()`. Captures the screenshot once\n * (cached across retries in the popup `session`, like its `clientId`) and\n * emits `annotation:complete` on the bus, then\n * waits for one of three terminal signals:\n *\n * - `feedback:sent` — resolve (popup closes).\n * - `feedback:error` — reject with the genuine error (popup restores for\n * retry; the launcher surfaces the error to the host).\n * - `submission:cancelled` — reject as a silent abort (popup restores; no\n * error is surfaced — e.g. the user cancelled the identity prompt).\n *\n * Submissions are serialized by the popup guard (`this.popup.isOpen`),\n * so exactly one `runSubmission` is ever live — the global outcome events\n * cannot cross-wire between submissions and need no correlation id.\n */\n private async runSubmission(\n annotation: AnnotationPayload,\n formResult: { type: FeedbackType; message: string },\n rectBounds: DOMRect,\n session: PopupSession,\n ): Promise<void> {\n // Screenshot capture is the slow part. Capture once and reuse the\n // cached data URL + region on every retry — re-running html2canvas-pro after\n // each failed submit would punish the user for a network blip.\n if (session.screenshot === undefined) {\n // The rect is in viewport coordinates of the selection moment — follow\n // any scroll since (revealSelection) so the capture frames the same content.\n session.screenshot = await this.maybeCapture(\n new DOMRect(\n rectBounds.x + annotation.scrollX - window.scrollX,\n rectBounds.y + annotation.scrollY - window.scrollY,\n rectBounds.width,\n rectBounds.height,\n ),\n );\n }\n const capture = session.screenshot;\n\n await new Promise<void>((resolve, reject) => {\n const cleanup = () => {\n unsubSent();\n unsubError();\n unsubCancelled();\n this.rejectPendingSubmission = null;\n };\n const unsubSent = this.bus.on(\"feedback:sent\", () => {\n cleanup();\n resolve();\n });\n const unsubError = this.bus.on(\"feedback:error\", (err) => {\n cleanup();\n reject(err);\n });\n const unsubCancelled = this.bus.on(\"submission:cancelled\", () => {\n cleanup();\n // Silent abort — the popup restores but no error is surfaced.\n reject(new Error(\"Feedback submission cancelled\"));\n });\n\n // Expose the reject handle so `destroy()` mid-submit can settle this\n // promise instead of leaving the awaiting closure hung past teardown.\n this.rejectPendingSubmission = (reason) => {\n cleanup();\n reject(reason);\n };\n\n this.bus.emit(\"annotation:complete\", {\n annotation,\n type: formResult.type,\n message: formResult.message,\n clientId: session.clientId,\n screenshotDataUrl: capture?.dataUrl ?? null,\n screenshotRegion: capture?.region ?? null,\n });\n });\n }\n\n /**\n * Build an AnnotationPayload from a drawn rectangle.\n * Temporarily hides the overlay to access the real DOM underneath.\n */\n private buildAnnotation(rectBounds: DOMRect): { annotation: AnnotationPayload; anchorBounds: DOMRect } {\n // Temporarily hide overlay to find the real element underneath\n if (this.overlay) this.overlay.style.pointerEvents = \"none\";\n const anchorElement = findAnchorElement(rectBounds);\n if (this.overlay) this.overlay.style.pointerEvents = \"auto\";\n\n const anchor = generateAnchor(anchorElement);\n const anchorBounds = anchorElement.getBoundingClientRect();\n const rect = rectToPercentages(rectBounds, anchorBounds);\n\n const annotation = {\n anchor,\n rect,\n scrollX: window.scrollX,\n scrollY: window.scrollY,\n viewportW: window.innerWidth,\n viewportH: window.innerHeight,\n devicePixelRatio: window.devicePixelRatio,\n };\n return { annotation, anchorBounds };\n }\n destroy(): void {\n this.deactivate();\n this.unregisterEscapeLayer();\n // Settle an in-flight submission BEFORE tearing down the popup, so the\n // `runSubmission` promise cannot outlive teardown. The launcher's\n // `destroy()` also calls `bus.removeAll()`, which would otherwise strip\n // the terminal-event listeners and leave the promise — and the base64\n // screenshot it retains — hung forever.\n this.rejectPendingSubmission?.(new Error(\"Annotator destroyed during submission\"));\n this.popup.destroy();\n }\n}\n","/** How many ids a project's list keeps — the oldest are dropped first. */\nconst MAX_OWN_FEEDBACK = 500;\n\n/** The feedback sent from this browser, remembered by id. */\nexport interface OwnFeedback {\n /** The remembered ids, read on every call so another tab's sends count too. */\n ids(): Set<string>;\n add(id: string): void;\n remove(...ids: string[]): void;\n clear(): void;\n}\n\n/**\n * The ids of the feedback sent from this browser, which back the panel's\n * \"Mine\" filter. The server cannot answer \"who sent this\": its GET blanks\n * author emails for unauthenticated callers (#105), and a filter by email\n * would let anyone probe who sent feedback. So the widget keeps its own list\n * in localStorage, one per project and endpoint. When storage is unavailable\n * the list reads as empty and writes are dropped.\n */\nexport function ownFeedback(projectName: string, endpoint?: string): OwnFeedback {\n const key = `siteping_own_feedback:${JSON.stringify([projectName, endpoint ?? null])}`;\n const ids = (): Set<string> => {\n try {\n const stored: unknown = JSON.parse(localStorage.getItem(key) ?? \"[]\");\n return new Set(Array.isArray(stored) ? stored.filter((id): id is string => typeof id === \"string\") : []);\n } catch {\n return new Set();\n }\n };\n const write = (next: Set<string>): void => {\n try {\n if (next.size > 0) localStorage.setItem(key, JSON.stringify([...next].slice(-MAX_OWN_FEEDBACK)));\n else localStorage.removeItem(key);\n } catch {\n // Storage unavailable or full: the list stays as it was\n }\n };\n return {\n ids,\n add(id) {\n const next = ids();\n next.delete(id); // Re-sent: move it to the newest end\n write(next.add(id));\n },\n remove(...gone) {\n const next = ids();\n const size = next.size;\n for (const id of gone) next.delete(id);\n if (next.size < size) write(next);\n },\n clear: () => write(new Set()),\n };\n}\n","import {\n type AnnotationPayload,\n type CommentCreateInput,\n type CommentResponse,\n errorFromResponse,\n type FeedbackPayload,\n type FeedbackQuery,\n type FeedbackResponse,\n type FeedbackResponseList,\n feedbackQueryToSearchParams,\n hasOwn,\n mergeRequestHeaders,\n networkErrorFromException,\n type Prettify,\n SitepingError,\n type SitepingHeadersOption,\n SitepingNetworkError,\n withSearchParams,\n} from \"@siteping/core\";\nimport type { Identity } from \"./identity.js\";\nimport { ownFeedback } from \"./own-feedback.js\";\n\n/**\n * Abstract client interface used by the widget internals.\n *\n * `ApiClient` (HTTP mode) and `StoreClient` (direct store mode) both satisfy\n * this interface, allowing the widget to work identically in either mode.\n */\nexport interface WidgetClient {\n sendFeedback(payload: FeedbackPayload): Promise<FeedbackResponse>;\n getFeedbacks(projectName: string, options?: GetFeedbacksOptions): Promise<FeedbackResponseList>;\n resolveFeedback(id: string, resolved: boolean): Promise<FeedbackResponse>;\n deleteFeedback(id: string): Promise<void>;\n deleteAllFeedbacks(projectName: string): Promise<void>;\n /** Post a reply on a feedback's thread — idempotent on `input.clientId`, so a resend never duplicates it. */\n addComment(feedbackId: string, input: CommentCreateInput): Promise<CommentResponse>;\n}\n\n/**\n * Options accepted by `WidgetClient.getFeedbacks` — core's `FeedbackQuery`\n * minus the `projectName` the client already knows. Derived, so a new query\n * filter added to core flows to both the HTTP and store clients\n * automatically.\n */\nexport type GetFeedbacksOptions = Prettify<Omit<FeedbackQuery, \"projectName\">>;\n\n/** Auth options for `ApiClient` / `flushRetryQueue` (HTTP mode). */\nexport interface ApiClientAuth {\n /** Sent as `Authorization: Bearer <apiKey>` on every request. */\n apiKey?: string | undefined;\n /** Extra headers, static or per-request factory. An explicit `Authorization` entry wins over `apiKey`. */\n headers?: SitepingHeadersOption | undefined;\n}\n\nconst MAX_RETRIES = 3;\nconst TIMEOUT_MS = 10_000;\nconst RETRY_QUEUE_KEY = \"siteping_retry_queue\";\nconst MAX_QUEUE_SIZE = 20;\n\n/**\n * Settle like `promise`, or reject with `onTimeout()` once `ms` elapse; the\n * timer is cleared either way. The underlying work is not cancelled — use it\n * where nothing can abort the call (a store write, a host headers factory).\n */\nexport function withTimeout<T>(promise: Promise<T>, ms: number, onTimeout: () => Error): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const expired = new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(onTimeout()), ms);\n });\n return Promise.race([promise, expired]).finally(() => clearTimeout(timer));\n}\n\n/**\n * Build the headers for one request: `Content-Type` when the request\n * carries a JSON body, then `Bearer` from `apiKey`, then `headers` merged on\n * top case-insensitively, so an explicit `Authorization` in any casing wins.\n *\n * A function `headers` resolves once per call — retries inside\n * `resilientFetch` reuse the values for the whole retry sequence. A factory\n * that throws, rejects, or does not settle within 10 s fails the request\n * like a network error — nothing may hold a send forever.\n */\nexport async function buildRequestHeaders(auth: ApiClientAuth, json: boolean): Promise<Record<string, string>> {\n const defaults: Record<string, string> = {};\n if (json) defaults[\"Content-Type\"] = \"application/json\";\n if (auth.apiKey) defaults.Authorization = `Bearer ${auth.apiKey}`;\n const extra =\n typeof auth.headers === \"function\"\n ? await withTimeout(\n Promise.resolve(auth.headers()),\n TIMEOUT_MS,\n () => new Error(`headers factory did not settle within ${TIMEOUT_MS / 1000} s`),\n )\n : auth.headers;\n return mergeRequestHeaders(defaults, extra);\n}\n\n// ---------------------------------------------------------------------------\n// Core fetch with retry + exponential backoff + jitter\n// ---------------------------------------------------------------------------\n\n/**\n * One HTTP call with retry + exponential backoff + jitter: each attempt is\n * aborted if its headers take more than TIMEOUT_MS. Network failures and 5xx\n * retry; the final response is read through `errorFromResponse` for a non-OK\n * status, `read` for a 2xx.\n *\n * With `boundBody` (the send path, #342), the body gets its own TIMEOUT_MS\n * window under the same abort, so one that stalls after the headers errors\n * instead of holding the popup forever — a non-OK status still maps to its\n * typed error, just without the server's detail. Reads leave it unbounded:\n * a page of inline screenshots can legitimately take longer on a slow link.\n *\n * Failures come out typed: a non-OK status as `errorFromResponse` maps it,\n * anything else (fetch, abort, body read or parse) as a `SitepingNetworkError`.\n */\nasync function resilientFetch<T>(\n url: string,\n init: RequestInit,\n label: string,\n read: (response: Response) => Promise<T>,\n { boundBody = false } = {},\n): Promise<T> {\n for (let attempt = 0; ; attempt++) {\n const controller = new AbortController();\n let timeout = setTimeout(() => controller.abort(), TIMEOUT_MS);\n try {\n const response = await fetch(url, { ...init, signal: controller.signal }).catch((error: unknown) => {\n if (attempt === MAX_RETRIES) throw networkErrorFromException(error, label);\n return null;\n });\n // Don't retry client errors (4xx) — only server errors (5xx)\n if (response && (response.ok || (response.status >= 400 && response.status < 500) || attempt === MAX_RETRIES)) {\n clearTimeout(timeout);\n if (boundBody) timeout = setTimeout(() => controller.abort(), TIMEOUT_MS);\n if (!response.ok) throw await errorFromResponse(response, label);\n return await read(response).catch((error: unknown) => {\n throw networkErrorFromException(error, label);\n });\n }\n } finally {\n clearTimeout(timeout);\n }\n\n // Exponential backoff with jitter: 1s, 2s, 4s + random ±500ms\n const baseDelay = 1000 * 2 ** attempt;\n const jitter = Math.random() * 1000 - 500;\n await new Promise((r) => setTimeout(r, baseDelay + jitter));\n }\n}\n\n// ---------------------------------------------------------------------------\n// Retry queue — persist failed feedbacks for retry on next page load\n// ---------------------------------------------------------------------------\n\ninterface RetryEntry {\n endpoint: string;\n payload: FeedbackPayload;\n}\n\n/**\n * Whether a failed submission is worth replaying later. Network failures and\n * server errors (5xx) are transient — the same payload can succeed once the\n * server is back. A 4xx is the server's verdict on the payload itself\n * (validation, auth, size…): replaying it verbatim fails identically every\n * time, so it is surfaced to the host through `onError` and never queued —\n * a queued rejection used to be replayed, and rejected, on every page load.\n */\nfunction isTransientFailure(error: unknown): boolean {\n return error instanceof SitepingNetworkError || (error instanceof SitepingError && error.code === \"SERVER\");\n}\n\n/** Same verdict for a replayed request: keep 5xx for the next flush, drop 4xx for good. */\nfunction isTransientStatus(status: number): boolean {\n return status >= 500;\n}\n\nconst LOCK_NAME = \"siteping_retry_queue\";\n\n/**\n * Acquire a Web Lock to serialize cross-tab access to the retry queue.\n * Falls back to running the callback without locking on older browsers.\n */\nasync function withRetryLock<T>(callback: () => T | Promise<T>): Promise<T> {\n if (typeof navigator !== \"undefined\" && navigator.locks) {\n return navigator.locks.request(LOCK_NAME, () => callback());\n }\n return callback();\n}\n\n/**\n * Shape-check one queue element — localStorage can hold tampered or legacy\n * entries, and a malformed one used to abort the whole flush via the outer\n * catch. Bad entries are dropped individually instead. The author fields are\n * checked because the flush itself reads them (identity match); anything\n * else wrong with a payload is the server's verdict (4xx → dropped).\n */\nfunction isRetryEntry(value: unknown): value is RetryEntry {\n if (!hasOwn(value, \"endpoint\") || typeof value.endpoint !== \"string\" || !hasOwn(value, \"payload\")) return false;\n const { payload } = value;\n return (\n hasOwn(payload, \"authorName\") &&\n typeof payload.authorName === \"string\" &&\n hasOwn(payload, \"authorEmail\") &&\n typeof payload.authorEmail === \"string\"\n );\n}\n\nfunction readQueue(): RetryEntry[] {\n const raw = localStorage.getItem(RETRY_QUEUE_KEY);\n if (!raw) return [];\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n // The widget only ever writes JSON.stringify output here, so an external\n // writer put this value in place. Nothing in it can be replayed; clear it\n // so the queue works again instead of every write failing on this parse.\n localStorage.removeItem(RETRY_QUEUE_KEY);\n console.warn(`[siteping] discarded an unreadable retry queue from localStorage (${raw.length} chars)`);\n return [];\n }\n return Array.isArray(parsed) ? parsed.filter(isRetryEntry) : [];\n}\n\nfunction queueForRetry(endpoint: string, payload: FeedbackPayload): void {\n // Fire-and-forget — we don't want to block the caller on the lock\n void withRetryLock(() => {\n try {\n // A resend from the same popup reuses its clientId: replace the earlier\n // attempt so the replay carries the latest edit (the server's clientId\n // dedupe would otherwise keep the stale first one).\n const queue = readQueue().filter((entry) => entry.payload.clientId !== payload.clientId);\n\n // Cap queue size to prevent unbounded localStorage growth\n if (queue.length >= MAX_QUEUE_SIZE) {\n queue.shift(); // Drop oldest entry\n }\n\n queue.push({ endpoint, payload });\n if (tryWriteQueue(queue)) return;\n\n // Quota exceeded: screenshots (base64 JPEG data URLs) dominate each\n // entry, and up to MAX_QUEUE_SIZE entries share the origin's ~5 MB\n // localStorage budget with the host page. Shed screenshots (the\n // heaviest, least essential part of a replay) one at a time, oldest\n // first like the eviction above, so no more are lost than the quota\n // requires; the message, annotations and diagnostics still replay.\n // If even the screenshot-free queue does not fit, evict the oldest\n // entries.\n const kept = queue.slice();\n let stripped = 0;\n for (const [index, entry] of kept.entries()) {\n if (!hasScreenshot(entry)) continue;\n kept[index] = withoutScreenshot(entry);\n stripped += 1;\n if (tryWriteQueue(kept)) {\n console.warn(\n `[siteping] retry queue exceeded the localStorage quota — dropped the screenshot of ${stripped} of ${queue.length} queued feedback(s)`,\n );\n return;\n }\n }\n while (kept.length > 1) {\n kept.shift();\n if (tryWriteQueue(kept)) {\n const dropped = queue.length - kept.length;\n const lost = queue.slice(dropped).filter(hasScreenshot).length;\n console.warn(\n `[siteping] retry queue exceeded the localStorage quota — dropped the ${dropped} oldest of ${queue.length} queued feedback(s)${lost > 0 ? `, and the screenshot of ${lost} of the rest` : \"\"}`,\n );\n return;\n }\n }\n // Every write failed, so the queue already stored is left as it was.\n console.warn(\"[siteping] feedback could not be queued for retry — localStorage is full or unavailable\");\n } catch {\n // localStorage unavailable — the new entry is dropped\n }\n });\n}\n\n/**\n * Drop the queued attempt of a feedback that has just landed (a resend from\n * the same popup, same clientId), so the next page load does not re-POST a\n * payload of up to ~1.5 MB only for the server to dedupe it.\n */\nfunction unqueue(clientId: string): void {\n void withRetryLock(() => {\n try {\n const queue = readQueue();\n const remaining = queue.filter((entry) => entry.payload.clientId !== clientId);\n if (remaining.length === queue.length) return;\n if (remaining.length > 0) localStorage.setItem(RETRY_QUEUE_KEY, JSON.stringify(remaining));\n else localStorage.removeItem(RETRY_QUEUE_KEY);\n } catch {\n // localStorage unavailable — a replay of the queued copy is deduped server-side\n }\n });\n}\n\nfunction tryWriteQueue(queue: RetryEntry[]): boolean {\n try {\n localStorage.setItem(RETRY_QUEUE_KEY, JSON.stringify(queue));\n return true;\n } catch {\n return false;\n }\n}\n\nfunction hasScreenshot(entry: RetryEntry): boolean {\n return entry.payload.screenshotDataUrl != null;\n}\n\n/** Replay copy without the screenshot; its region is meaningless without the image. */\nfunction withoutScreenshot(entry: RetryEntry): RetryEntry {\n const { screenshotDataUrl: _screenshotDataUrl, screenshotRegion: _screenshotRegion, ...payload } = entry.payload;\n return { endpoint: entry.endpoint, payload };\n}\n\nfunction normalizeName(value: string): string {\n return value.trim();\n}\n\nfunction normalizeEmail(value: string): string {\n return value.trim().toLowerCase();\n}\n\n/**\n * Flush queued feedbacks for `endpoint`. When `currentIdentity` is provided,\n * entries whose stored author doesn't match it are dropped rather than replayed.\n * This prevents user A's offline feedback from being POSTed under user B's\n * identity after a session change. When omitted, all entries are replayed to\n * preserve the legacy behavior for callers that don't track identity.\n *\n * `auth` headers resolve fresh at flush time (once per flush call) — queue\n * entries persist payloads only, never headers or token material.\n */\nexport async function flushRetryQueue(\n endpoint: string,\n currentIdentity?: Identity | null,\n auth: ApiClientAuth = {},\n): Promise<void> {\n await withRetryLock(async () => {\n try {\n const queue = readQueue();\n if (queue.length === 0) return;\n\n const toRetry: RetryEntry[] = [];\n const unrelated: RetryEntry[] = [];\n let dropped = 0;\n\n for (const entry of queue) {\n if (entry.endpoint !== endpoint) {\n unrelated.push(entry);\n continue;\n }\n\n if (\n !currentIdentity ||\n (normalizeName(entry.payload.authorName) === normalizeName(currentIdentity.name) &&\n normalizeEmail(entry.payload.authorEmail) === normalizeEmail(currentIdentity.email))\n ) {\n toRetry.push(entry);\n } else {\n dropped += 1;\n }\n }\n\n if (toRetry.length === 0 && dropped === 0) return;\n\n if (dropped > 0) {\n console.debug(\"[siteping] flushRetryQueue: dropped\", dropped, \"stale entries (identity changed)\");\n }\n\n // Process items sequentially to avoid overwhelming the server\n const failed: RetryEntry[] = [];\n let rejected = 0;\n if (toRetry.length > 0) {\n const headers = await buildRequestHeaders(auth, true);\n for (const entry of toRetry) {\n // Same bound as a live send's attempt: the replay holds the\n // cross-tab lock, so one that never answers would block every\n // later queueing on this origin.\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), TIMEOUT_MS);\n try {\n const res = await fetch(endpoint, {\n method: \"POST\",\n headers,\n body: JSON.stringify(entry.payload),\n signal: controller.signal,\n });\n if (res.ok) {\n // Sent from this browser after all: the panel's \"Mine\" filter lists it\n const created: unknown = await res.json().catch(() => null);\n if (hasOwn(created, \"id\") && typeof created.id === \"string\") {\n ownFeedback(entry.payload.projectName, endpoint).add(created.id);\n }\n continue;\n }\n if (isTransientStatus(res.status)) failed.push(entry);\n else rejected += 1;\n } catch {\n failed.push(entry);\n } finally {\n clearTimeout(timeout);\n }\n }\n }\n\n if (rejected > 0) {\n console.warn(\n `[siteping] flushRetryQueue: dropped ${rejected} queued feedback(s) the server rejected (4xx) — they would fail identically on every replay`,\n );\n }\n\n // Rebuild queue: keep unrelated entries + failed retries\n const remaining = unrelated.concat(failed);\n if (remaining.length > 0) {\n localStorage.setItem(RETRY_QUEUE_KEY, JSON.stringify(remaining));\n } else {\n localStorage.removeItem(RETRY_QUEUE_KEY);\n }\n } catch {\n // Ignore — localStorage may be unavailable\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// API client\n// ---------------------------------------------------------------------------\n\n/** The span `[start, start + size]` intersected with [0, 1], as `[start, size]`; one already inside comes back as is. */\nfunction clipSpan(start: number, size: number): [number, number] {\n const from = Math.min(1, Math.max(0, start));\n const trimmed = size - (from - start);\n return [from, Math.max(0, from + trimmed <= 1 ? trimmed : 1 - from)];\n}\n\n/**\n * The annotation with its rect intersected with the anchor box: the server\n * schema rejects any rect field outside [0, 1], and the `document.body`\n * fallback anchor may not contain a rect drawn in blank page space (a short\n * body, its default margin). A rect fully outside collapses onto the nearest\n * edge rather than losing the feedback. Store mode has no such schema and\n * keeps the rect as drawn — markers extrapolate past the anchor box.\n */\nfunction clipRectToAnchor(annotation: AnnotationPayload): AnnotationPayload {\n const [xPct, wPct] = clipSpan(annotation.rect.xPct, annotation.rect.wPct);\n const [yPct, hPct] = clipSpan(annotation.rect.yPct, annotation.rect.hPct);\n return { ...annotation, rect: { xPct, yPct, wPct, hPct } };\n}\n\n/** Parse a JSON body and assert its TypeScript shape — server-side Zod is the source of truth. */\nasync function parseJsonAs<T>(response: Response): Promise<T> {\n return (await response.json()) as T;\n}\n\n/** DELETE responses carry nothing the client needs. */\nasync function ignoreBody(): Promise<void> {}\n\nexport class ApiClient implements WidgetClient {\n constructor(\n private readonly endpoint: string,\n private readonly projectName: string,\n private readonly auth: ApiClientAuth = {},\n ) {}\n\n /** `buildRequestHeaders`, with a failing headers factory normalised to a `SitepingNetworkError`. */\n private async headers(json: boolean, label: string): Promise<Record<string, string>> {\n try {\n return await buildRequestHeaders(this.auth, json);\n } catch (error) {\n throw networkErrorFromException(error, label);\n }\n }\n\n async sendFeedback(payload: FeedbackPayload): Promise<FeedbackResponse> {\n const label = \"Failed to send feedback\";\n // Only put `screenshotRegion` on the wire when a region was actually\n // captured — servers that predate the field would otherwise reject an\n // explicit `screenshotRegion: null` on every legacy capture.\n const { screenshotRegion, ...rest } = payload;\n const wire = { ...rest, annotations: rest.annotations.map(clipRectToAnchor) };\n const body: FeedbackPayload = screenshotRegion ? { ...wire, screenshotRegion } : wire;\n try {\n const created = await resilientFetch(\n this.endpoint,\n { method: \"POST\", headers: await this.headers(true, label), body: JSON.stringify(body) },\n label,\n parseJsonAs<FeedbackResponse>,\n { boundBody: true },\n );\n unqueue(body.clientId);\n return created;\n } catch (error) {\n // Queue the wire shape (region stripped when absent) so a later\n // flushRetryQueue replays exactly what a fresh POST would send — but\n // only when a replay can succeed (see `isTransientFailure`).\n if (isTransientFailure(error)) queueForRetry(this.endpoint, body);\n throw error;\n }\n }\n\n async getFeedbacks(projectName: string, options?: GetFeedbacksOptions): Promise<FeedbackResponseList> {\n const label = \"Failed to fetch feedbacks\";\n const params = feedbackQueryToSearchParams({ projectName, ...options });\n // GET carries no body — only attach headers when auth produced some, so\n // the no-auth wire shape stays byte-identical to the legacy client.\n const headers = await this.headers(false, label);\n return resilientFetch(\n withSearchParams(this.endpoint, params),\n { method: \"GET\", cache: \"no-store\", ...(Object.keys(headers).length > 0 ? { headers } : {}) },\n label,\n parseJsonAs<FeedbackResponseList>,\n );\n }\n\n async addComment(feedbackId: string, input: CommentCreateInput): Promise<CommentResponse> {\n const label = \"Failed to post comment\";\n // The same endpoint as a feedback: `feedbackId` routes the POST to the\n // thread. Retries resend the same clientId, which the server dedupes.\n return resilientFetch(\n this.endpoint,\n {\n method: \"POST\",\n headers: await this.headers(true, label),\n body: JSON.stringify({ ...input, projectName: this.projectName, feedbackId }),\n },\n label,\n parseJsonAs<CommentResponse>,\n { boundBody: true },\n );\n }\n\n async resolveFeedback(id: string, resolved: boolean): Promise<FeedbackResponse> {\n const label = \"Failed to update feedback\";\n return resilientFetch(\n this.endpoint,\n {\n method: \"PATCH\",\n headers: await this.headers(true, label),\n body: JSON.stringify({ id, projectName: this.projectName, status: resolved ? \"resolved\" : \"open\" }),\n },\n label,\n parseJsonAs<FeedbackResponse>,\n );\n }\n\n async deleteFeedback(id: string): Promise<void> {\n const label = \"Failed to delete feedback\";\n await resilientFetch(\n this.endpoint,\n {\n method: \"DELETE\",\n headers: await this.headers(true, label),\n body: JSON.stringify({ id, projectName: this.projectName }),\n },\n label,\n ignoreBody,\n );\n }\n\n async deleteAllFeedbacks(projectName: string): Promise<void> {\n const label = \"Failed to delete all feedbacks\";\n await resilientFetch(\n this.endpoint,\n {\n method: \"DELETE\",\n headers: await this.headers(true, label),\n body: JSON.stringify({ projectName, deleteAll: true }),\n },\n label,\n ignoreBody,\n );\n }\n}\n","/**\n * `text` cut to at most `maxLength` code units, the last one `…`. The cut\n * never splits a surrogate pair: half an emoji is a lone surrogate, which a\n * PostgreSQL `jsonb` column refuses — with it the whole feedback was lost.\n */\nexport function truncateWithEllipsis(text: string, maxLength: number): string {\n if (text.length <= maxLength) return text;\n let end = maxLength - 1;\n const last = text.charCodeAt(end - 1);\n if (last >= 0xd800 && last <= 0xdbff) end -= 1;\n return `${text.slice(0, end)}…`;\n}\n","/**\n * Console buffer — capture the last N `console.{log,info,warn,error}` calls\n * so they ship with every feedback submission.\n *\n * Why a ring buffer:\n * - **bounded memory** even on chatty pages (1000s of logs/min during dev),\n * - **last-N is the relevant slice** for debugging — what was happening just\n * before the user noticed the bug, not the full session history.\n *\n * Why monkey-patching instead of `console.dir`/Performance Timeline:\n * - host code already uses plain `console.*` everywhere, and many libraries\n * only emit through console (no other observable),\n * - patching is reversible via `dispose()` so the widget never leaves state\n * behind on `destroy()`.\n */\n\nimport { truncateWithEllipsis } from \"./truncate.js\";\n\n/**\n * Default AND ceiling: adapter-prisma validates `diagnostics.console` at max\n * 50 entries, so a larger buffer would turn every submission into a 400.\n */\nconst MAX_ENTRIES = 50;\n/** Under the server's 600-char `message` cap. */\nconst MAX_MESSAGE_LENGTH = 500;\n\n/** Per-entry shape — sent to the server in the diagnostics payload. */\nexport interface ConsoleEntry {\n level: \"log\" | \"info\" | \"warn\" | \"error\";\n /** ISO 8601 timestamp captured at log time. */\n timestamp: string;\n /** Best-effort string representation of the console args. */\n message: string;\n}\n\nconst LEVELS: Array<ConsoleEntry[\"level\"]> = [\"log\", \"info\", \"warn\", \"error\"];\n\n/**\n * Best-effort stringification that never throws.\n *\n * - `Error` → `Error: message\\nstack` (capped to 500 chars overall).\n * - circular / huge objects → fall back to `Object#toString()` or `\"[Unserializable]\"`.\n * - all output is truncated to `MAX_MESSAGE_LENGTH` so a single 5MB log\n * doesn't blow up the buffer (Slack-style 500 chars per row is plenty).\n */\nfunction serializeArg(arg: unknown): string {\n if (arg === null) return \"null\";\n if (arg === undefined) return \"undefined\";\n if (typeof arg === \"string\") return arg;\n if (typeof arg === \"number\" || typeof arg === \"boolean\" || typeof arg === \"bigint\") {\n return String(arg);\n }\n if (arg instanceof Error) {\n return `${arg.name}: ${arg.message}${arg.stack ? `\\n${arg.stack}` : \"\"}`;\n }\n try {\n // Replacer marks cycles and replaces functions with a placeholder (we\n // don't want random function bodies in a feedback payload). Cycles are\n // detected against the ANCESTOR chain, not every object seen so far: an\n // object referenced twice side by side (`{ a: s, b: s }`) is shared, not\n // circular. `this` is the object holding `value`, so ancestors past it\n // belong to a finished sibling. A shared object is serialized at every\n // reference, so a node budget keeps a diamond-shaped graph from growing\n // exponentially — past it, values are pruned, and what was already\n // emitted fills the MAX_MESSAGE_LENGTH the output is cut to anyway.\n const ancestors: unknown[] = [];\n let budget = MAX_MESSAGE_LENGTH;\n return JSON.stringify(arg, function (this: unknown, _key, value: unknown) {\n if (--budget < 0) return undefined;\n if (typeof value === \"function\") return \"[Function]\";\n if (typeof value === \"symbol\") return value.toString();\n if (typeof value !== \"object\" || value === null) return value;\n while (ancestors.length > 0 && ancestors[ancestors.length - 1] !== this) ancestors.pop();\n if (ancestors.includes(value)) return \"[Circular]\";\n ancestors.push(value);\n return value;\n });\n } catch {\n try {\n return String(arg);\n } catch {\n return \"[Unserializable]\";\n }\n }\n}\n\nfunction formatArgs(args: readonly unknown[]): string {\n let out = \"\";\n for (let i = 0; i < args.length; i++) {\n if (i > 0) out += \" \";\n out += serializeArg(args[i]);\n if (out.length >= MAX_MESSAGE_LENGTH) break;\n }\n return truncateWithEllipsis(out, MAX_MESSAGE_LENGTH);\n}\n\n/**\n * Bounded ring buffer of console messages.\n *\n * Construction installs the wrappers immediately. `dispose()` restores the\n * originals exactly once (calling it twice is a no-op). Designed to be safe\n * against re-entrant or interleaved instances — each wrapper closes over the\n * original method, not over any global, so multiple buffers can coexist\n * (each captures its own copy of the args).\n */\nexport class ConsoleBuffer {\n private readonly maxEntries: number;\n private readonly entries: ConsoleEntry[] = [];\n private originals = new Map<ConsoleEntry[\"level\"], (...args: unknown[]) => void>();\n /** The wrappers we installed — `dispose()` only restores a level whose wrapper is still in place. */\n private wrappers = new Map<ConsoleEntry[\"level\"], (...args: unknown[]) => void>();\n private disposed = false;\n\n constructor(maxEntries: number = MAX_ENTRIES) {\n // Guard against pathological values — 0 disables silently, NaN / Infinity\n // / negative numbers (untyped script-tag configs) fall back to the\n // default, and anything above the server cap is clamped to it.\n this.maxEntries =\n Number.isFinite(maxEntries) && maxEntries >= 0 ? Math.min(Math.floor(maxEntries), MAX_ENTRIES) : MAX_ENTRIES;\n\n if (typeof console === \"undefined\") return;\n\n for (const level of LEVELS) {\n const original = (console as unknown as Record<string, ((...args: unknown[]) => void) | undefined>)[level];\n if (typeof original !== \"function\") continue;\n this.originals.set(level, original);\n\n const buffer = this;\n const wrapped = function (this: unknown, ...args: unknown[]): void {\n try {\n buffer.push(level, args);\n } catch {\n // Capturing must never break the host's console — swallow any\n // unexpected error from serialization so the original call\n // (right below) always still runs.\n }\n original.apply(this ?? console, args);\n };\n // Preserve the function name so devtools still show \"console.log\"\n // (browsers display the wrapper's name in stack traces).\n try {\n Object.defineProperty(wrapped, \"name\", { value: level });\n } catch {\n // Older engines reject defineProperty on function name — best-effort only.\n }\n this.wrappers.set(level, wrapped);\n (console as unknown as Record<string, unknown>)[level] = wrapped;\n }\n }\n\n private push(level: ConsoleEntry[\"level\"], args: readonly unknown[]): void {\n if (this.maxEntries === 0) return;\n if (this.entries.length >= this.maxEntries) {\n this.entries.shift();\n }\n this.entries.push({\n level,\n timestamp: new Date().toISOString(),\n message: formatArgs(args),\n });\n }\n\n /** Snapshot of captured entries — returns a new array each call. */\n getEntries(): ConsoleEntry[] {\n return this.entries.slice();\n }\n\n /**\n * Restore the original console methods. Idempotent.\n *\n * A level is restored only if our wrapper is still installed on it — when\n * another library wrapped `console.error` on top of us after init, writing\n * the original back would silently remove its wrapper. Ours then stays in\n * the chain but keeps forwarding to the original, so nothing is lost.\n */\n dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n if (typeof console === \"undefined\") return;\n const target = console as unknown as Record<string, unknown>;\n for (const [level, original] of this.originals) {\n if (target[level] !== this.wrappers.get(level)) continue;\n try {\n target[level] = original;\n } catch {\n // Console may be frozen in exotic environments — leave the wrapper\n // in place; it still proxies to the original via closure.\n }\n }\n this.originals.clear();\n this.wrappers.clear();\n }\n}\n","/**\n * Network buffer — capture the last N failed `fetch` / `XMLHttpRequest`\n * calls (HTTP >= 400 or network error) so they ship with each feedback.\n *\n * Captures only failures because:\n * - successful requests are usually irrelevant for the \"this thing is\n * broken\" workflow,\n * - keeping the volume tiny means we can ship the full payload to the\n * server without bloating Postgres.\n *\n * Both wrappers preserve the original semantics — return values, throws,\n * AbortController behaviour, etc. The only side effect is recording a\n * `NetworkEntry` on failure.\n */\n\nimport { truncateWithEllipsis } from \"./truncate.js\";\n\n/**\n * Server schema limits (adapter-prisma `networkEntrySchema`). Entries are\n * clamped to them on capture: one out-of-range field fails validation for\n * the whole feedback, not just its diagnostics. `MAX_ENTRIES` is both the\n * default and the ceiling of the buffer size.\n */\nconst MAX_ENTRIES = 20;\nconst MAX_URL_LENGTH = 2000;\nconst MAX_METHOD_LENGTH = 20;\nconst MAX_DURATION_MS = 600_000;\nconst MAX_STATUS = 599;\n\n/** Per-entry shape — sent to the server in the diagnostics payload. */\nexport interface NetworkEntry {\n url: string;\n method: string;\n /** HTTP status or 0 when the request never reached the server (network error / CORS / abort). */\n status: number;\n /** End-to-end duration in ms, rounded to the nearest integer. */\n durationMs: number;\n /** ISO 8601 timestamp at the moment the request was initiated. */\n timestamp: string;\n}\n\n/**\n * The URL as recorded: credentials, query string and hash dropped — they\n * routinely carry secrets (`https://user:pass@…`, `?api_key=…`, OAuth\n * `#access_token=…`) and the docs promise query strings never leave the\n * browser — then capped to the schema's length.\n */\nfunction recordableUrl(input: unknown): string {\n const url = withoutCredentials(urlString(input));\n const cut = url.search(/[?#]/);\n return truncateWithEllipsis(cut === -1 ? url : url.slice(0, cut), MAX_URL_LENGTH);\n}\n\n/**\n * `url` without its userinfo, parsed against the page as fetch and XHR parse\n * it. XHR sends a credentialed URL, and fetch rejects one, a failure the\n * wrapper records. A URL without credentials comes back exactly as given.\n */\nfunction withoutCredentials(url: string): string {\n try {\n const parsed = new URL(url, typeof location === \"undefined\" ? undefined : location.href);\n if (!parsed.username && !parsed.password) return url;\n parsed.username = \"\";\n parsed.password = \"\";\n return parsed.href;\n } catch {\n return url;\n }\n}\n\nfunction urlString(input: unknown): string {\n if (typeof input === \"string\") return input;\n if (input instanceof URL) return input.href;\n // `Request` instances expose `.url`\n if (typeof input === \"object\" && input !== null && \"url\" in (input as { url?: unknown })) {\n const candidate = (input as { url?: unknown }).url;\n if (typeof candidate === \"string\") return candidate;\n }\n try {\n return String(input);\n } catch {\n return \"(unknown)\";\n }\n}\n\n/**\n * Bounded ring buffer of failed network requests.\n *\n * Construction monkey-patches `globalThis.fetch` and `XMLHttpRequest` and\n * stores the originals for `dispose()`. Wrappers are designed so that\n * multiple instances can coexist (each captures independently into its own\n * buffer, and the last one disposed restores the chain correctly via the\n * stored originals).\n */\nexport class NetworkBuffer {\n private readonly maxEntries: number;\n private readonly entries: NetworkEntry[] = [];\n private originalFetch: typeof fetch | null = null;\n private originalXhrOpen: typeof XMLHttpRequest.prototype.open | null = null;\n private originalXhrSend: typeof XMLHttpRequest.prototype.send | null = null;\n /** The wrappers we installed — `dispose()` only restores when they are still in place. */\n private wrappedFetch: typeof fetch | null = null;\n private wrappedXhrOpen: typeof XMLHttpRequest.prototype.open | null = null;\n private wrappedXhrSend: typeof XMLHttpRequest.prototype.send | null = null;\n private disposed = false;\n\n constructor(maxEntries: number = MAX_ENTRIES) {\n // Same guard as ConsoleBuffer: 0 disables, non-finite / negative falls\n // back to the default, larger values clamp to the server cap.\n this.maxEntries =\n Number.isFinite(maxEntries) && maxEntries >= 0 ? Math.min(Math.floor(maxEntries), MAX_ENTRIES) : MAX_ENTRIES;\n this.installFetch();\n this.installXhr();\n }\n\n private push(entry: NetworkEntry): void {\n if (this.maxEntries === 0) return;\n if (this.entries.length >= this.maxEntries) {\n this.entries.shift();\n }\n // A request left open > 10 min, an exotic method, or a non-standard\n // status (fetch allows up to 999 — LinkedIn answers 999) would each 400.\n // An out-of-range status is recorded as 0 (\"no usable status\") rather\n // than clamped to 599, which would pass it off as a real 5xx.\n this.entries.push({\n ...entry,\n method: entry.method.slice(0, MAX_METHOD_LENGTH),\n status: entry.status <= MAX_STATUS ? entry.status : 0,\n durationMs: Math.min(Math.max(entry.durationMs, 0), MAX_DURATION_MS),\n });\n }\n\n private installFetch(): void {\n if (typeof globalThis.fetch !== \"function\") return;\n const original = globalThis.fetch;\n this.originalFetch = original;\n\n const wrapped: typeof fetch = async (input, init) => {\n const startedAt = new Date();\n const t0 = typeof performance !== \"undefined\" ? performance.now() : Date.now();\n const url = recordableUrl(input);\n const method = (init?.method ?? (input instanceof Request ? input.method : \"GET\")).toUpperCase();\n\n try {\n const response = await original(input, init);\n if (!response.ok) {\n const t1 = typeof performance !== \"undefined\" ? performance.now() : Date.now();\n this.push({\n url,\n method,\n status: response.status,\n durationMs: Math.round(t1 - t0),\n timestamp: startedAt.toISOString(),\n });\n }\n return response;\n } catch (err) {\n const t1 = typeof performance !== \"undefined\" ? performance.now() : Date.now();\n this.push({\n url,\n method,\n status: 0,\n durationMs: Math.round(t1 - t0),\n timestamp: startedAt.toISOString(),\n });\n throw err;\n }\n };\n\n this.wrappedFetch = wrapped;\n globalThis.fetch = wrapped;\n }\n\n private installXhr(): void {\n if (typeof XMLHttpRequest === \"undefined\") return;\n const proto = XMLHttpRequest.prototype;\n const originalOpen = proto.open;\n const originalSend = proto.send;\n this.originalXhrOpen = originalOpen;\n this.originalXhrSend = originalSend;\n const buffer = this;\n\n // Store the open metadata on the XHR instance via a side-channel WeakMap\n // so each request is fully isolated even with concurrent opens.\n const meta = new WeakMap<XMLHttpRequest, { method: string; url: string; startedAt: Date; t0: number }>();\n\n const wrappedOpen = function (this: XMLHttpRequest, method: string, url: string | URL, ...rest: unknown[]) {\n try {\n meta.set(this, {\n method: method.toUpperCase(),\n url: recordableUrl(url),\n startedAt: new Date(),\n t0: typeof performance !== \"undefined\" ? performance.now() : Date.now(),\n });\n } catch {\n // Ignore — metadata is best-effort, the underlying open() still runs.\n }\n // XHR.open has two overloaded signatures (3-arg sync, 5-arg async with\n // user/password). Cast to a loose function shape to forward every arg\n // without re-enumerating the overloads here.\n const looseOpen = originalOpen as unknown as (this: XMLHttpRequest, ...a: unknown[]) => void;\n return looseOpen.call(this, method, url, ...rest);\n } as typeof proto.open;\n\n const wrappedSend = function (this: XMLHttpRequest, body?: Document | XMLHttpRequestBodyInit | null) {\n const info = meta.get(this);\n if (info) {\n // `loadend` fires for both success and failure — we just inspect the\n // status to decide whether to log. Use `once: true` so a re-sent XHR\n // doesn't accumulate listeners.\n const onEnd = () => {\n try {\n const t1 = typeof performance !== \"undefined\" ? performance.now() : Date.now();\n const status = this.status; // 0 on network error / abort\n if (status === 0 || status >= 400) {\n buffer.push({\n url: info.url,\n method: info.method,\n status,\n durationMs: Math.round(t1 - info.t0),\n timestamp: info.startedAt.toISOString(),\n });\n }\n } catch {\n // Listener must not throw — would surface as an \"Uncaught\" in\n // the host's console and pollute their logs.\n }\n };\n try {\n this.addEventListener(\"loadend\", onEnd, { once: true });\n } catch {\n // Older engines without options object — fall back to plain listener.\n try {\n this.addEventListener(\"loadend\", onEnd);\n } catch {\n // No-op\n }\n }\n }\n return originalSend.call(this, body ?? null);\n } as typeof proto.send;\n\n this.wrappedXhrOpen = wrappedOpen;\n this.wrappedXhrSend = wrappedSend;\n proto.open = wrappedOpen;\n proto.send = wrappedSend;\n }\n\n /** Snapshot of captured entries — returns a new array each call. */\n getEntries(): NetworkEntry[] {\n return this.entries.slice();\n }\n\n /**\n * Restore the original fetch + XHR methods. Idempotent.\n *\n * Each global is restored only if our wrapper is still the one installed —\n * if another library (an error tracker, a RUM agent) wrapped on top of us\n * after init, writing the original back would silently rip its wrapper\n * out. Our patch then stays in the chain but is inert: it still forwards to\n * the original, and a disposed buffer merely records entries nobody reads.\n * Same rule the launcher applies to the History API.\n */\n dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n\n if (this.originalFetch && globalThis.fetch === this.wrappedFetch) {\n try {\n globalThis.fetch = this.originalFetch;\n } catch {\n // Best-effort\n }\n }\n if (typeof XMLHttpRequest !== \"undefined\") {\n try {\n const proto = XMLHttpRequest.prototype;\n if (this.originalXhrOpen && proto.open === this.wrappedXhrOpen) proto.open = this.originalXhrOpen;\n if (this.originalXhrSend && proto.send === this.wrappedXhrSend) proto.send = this.originalXhrSend;\n } catch {\n // Best-effort\n }\n }\n }\n}\n","import type { CommentResponse, FeedbackResponse, SitepingUnsubscribe } from \"@siteping/core\";\nimport type { AnnotationComplete } from \"./annotator.js\";\n\n/** Listener signature for a single key of an `EventBus` event map. */\nexport type EventListener<E extends Record<keyof E, unknown[]>, K extends keyof E> = (...args: E[K]) => void;\n\n/**\n * Lightweight typed `EventEmitter` — zero dependencies.\n *\n * The generic constraint guarantees each event maps to a tuple of argument\n * types, so subscribers and emitters share the exact same shape.\n */\nexport class EventBus<E extends Record<keyof E, unknown[]>> {\n private readonly listeners = new Map<keyof E, Set<EventListener<E, keyof E>>>();\n\n on<K extends keyof E>(event: K, listener: EventListener<E, K>): SitepingUnsubscribe {\n let set = this.listeners.get(event);\n if (!set) {\n set = new Set();\n this.listeners.set(event, set);\n }\n set.add(listener as EventListener<E, keyof E>);\n\n return () => {\n set?.delete(listener as EventListener<E, keyof E>);\n };\n }\n\n off<K extends keyof E>(event: K, listener: EventListener<E, K>): void {\n this.listeners.get(event)?.delete(listener as EventListener<E, keyof E>);\n }\n\n emit<K extends keyof E>(event: K, ...args: E[K]): void {\n const set = this.listeners.get(event);\n if (!set) return;\n for (const fn of set) {\n try {\n (fn as (...a: E[K]) => void)(...args);\n } catch (err) {\n // Isolate listener errors — one bad listener must not kill others\n console.error(`[siteping] Error in event listener for \"${String(event)}\":`, err);\n }\n }\n }\n\n removeAll(): void {\n this.listeners.clear();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Widget event types\n// ---------------------------------------------------------------------------\n\n/** Full internal event map — broader than the public surface exposed to hosts. */\nexport interface WidgetEvents {\n open: [];\n close: [];\n \"feedback:sent\": [FeedbackResponse];\n \"feedback:deleted\": [FeedbackResponse[\"id\"]];\n \"feedback:all-deleted\": [];\n \"comment:added\": [CommentResponse];\n \"feedback:error\": [Error];\n /** Emitted whenever the marker set changes — payload is the open (unresolved) count for the current page. */\n \"markers:changed\": [number];\n \"annotation:start\": [];\n \"annotation:end\": [];\n \"annotation:complete\": [AnnotationComplete];\n /**\n * Internal-only: a feedback submission was aborted by a benign user action\n * (e.g. cancelling the identity prompt). Distinct from `feedback:error` so a\n * cancellation does not surface through the host's `onError` callback. Not\n * part of `SitepingPublicEvents` — never exposed to consumers.\n */\n \"submission:cancelled\": [];\n /**\n * Internal-only: a host `panelActions` callback threw or rejected. Kept off\n * `feedback:error` on purpose — the annotator settles its pending popup\n * submission on that event, so a host failure must never reach it. The\n * launcher forwards it to `config.onError` only.\n */\n \"panel:action-error\": [Error];\n \"annotations:toggle\": [boolean];\n \"panel:toggle\": [boolean];\n}\n\n// NOTE: the public event surface is `SitepingPublicEvents` from\n// `@siteping/core`. The launcher bridges internal events onto the public bus\n// through a mapped object keyed by `keyof SitepingPublicEvents`, so adding a\n// public event without bridging it is a compile error there — no alias or\n// duplicate map is needed on this side.\n","import type { SitepingConfig } from \"@siteping/core\";\nimport { parseSvg, setText } from \"./dom-utils.js\";\nimport type { EventBus, WidgetEvents } from \"./events.js\";\nimport { registerEscapeLayer } from \"./host-isolation.js\";\nimport { type TFunction, type Translations, tWithParams } from \"./i18n/index.js\";\nimport { ICON_CLOSE, ICON_EDIT, ICON_EYE, ICON_EYE_OFF, ICON_LIST, ICON_SITEPING } from \"./icons.js\";\nimport { isCoarsePointer } from \"./viewport.js\";\n\n/** Closed set of radial menu item ids — keeps the label lookup exhaustive. */\ntype RadialItemId = \"chat\" | \"annotate\" | \"toggle-annotations\";\n\ninterface RadialItem {\n id: RadialItemId;\n icon: string;\n iconAlt?: string;\n}\n\nconst ITEM_GAP = 54;\n/** Touch items are 48px (styles/mobile.ts) — keep a 12px gap between them. */\nconst ITEM_GAP_TOUCH = 60;\n\n// Stable mapping between radial item ids and their translation keys. The\n// label is fully derived from this map via `t()`, so the constructor and\n// `applyLabels()` share one source of truth for which node gets which string.\nconst ITEM_LABEL_KEYS: Record<RadialItemId, keyof Translations> = {\n chat: \"fab.messages\",\n annotate: \"fab.annotate\",\n \"toggle-annotations\": \"fab.annotations\",\n};\n\n/**\n * Floating Action Button with radial menu and notification badge.\n *\n * Glassmorphism: gradient background, glow shadow, glass radial items.\n * Badge shows unresolved feedback count.\n */\nexport class Fab {\n private root: HTMLElement;\n private scrim: HTMLElement;\n private fab: HTMLButtonElement;\n private radialContainer: HTMLElement;\n private badgeEl: HTMLElement | null = null;\n private isOpen = false;\n private annotationsVisible = true;\n private items: RadialItem[];\n\n constructor(\n shadowRoot: ShadowRoot,\n config: SitepingConfig,\n private readonly bus: EventBus<WidgetEvents>,\n private readonly t: TFunction,\n ) {\n const position = config.position ?? \"bottom-right\";\n\n // Vertical stack above the FAB. Icons:\n // - list → opens the feedback sidebar (panel of feedbacks).\n // - edit → creates a new annotation (the action).\n // - eye → toggles marker visibility on the page (state).\n // The marker-visibility toggle is opt-out via `config.showAnnotationsToggle`:\n // default `true` preserves historical behavior, `false` removes the item from\n // the menu entirely (no DOM, no keyboard slot, no click handler).\n this.items = [\n { id: \"chat\", icon: ICON_LIST },\n { id: \"annotate\", icon: ICON_EDIT },\n ];\n if (config.showAnnotationsToggle !== false) {\n this.items.push({ id: \"toggle-annotations\", icon: ICON_EYE, iconAlt: ICON_EYE_OFF });\n }\n\n // FAB button — needs position:relative for badge positioning\n this.fab = document.createElement(\"button\");\n this.fab.className = `sp-fab sp-fab--${position} sp-anim-fab-in`;\n this.fab.style.position = \"fixed\"; // ensure fixed even with relative children\n this.fab.appendChild(parseSvg(ICON_SITEPING));\n this.fab.setAttribute(\"aria-expanded\", \"false\");\n this.fab.addEventListener(\"click\", () => this.toggle());\n\n // Radial container\n this.radialContainer = document.createElement(\"div\");\n this.radialContainer.className = `sp-radial sp-radial--${position}`;\n this.radialContainer.setAttribute(\"role\", \"menu\");\n\n for (let i = 0; i < this.items.length; i++) {\n const item = this.items[i];\n if (!item) continue;\n const btn = document.createElement(\"button\");\n btn.className = \"sp-radial-item\";\n btn.style.setProperty(\"--sp-i\", String(i));\n btn.appendChild(parseSvg(item.icon));\n btn.setAttribute(\"role\", \"menuitem\");\n btn.dataset.itemId = item.id;\n\n btn.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n this.handleItemClick(item.id);\n });\n\n const label = document.createElement(\"span\");\n label.className = \"sp-radial-label\";\n btn.appendChild(label);\n\n this.radialContainer.appendChild(btn);\n }\n\n // Phone layout: dims the page behind the open speed dial so its labels\n // read over any content (CSS renders it on compact viewports only).\n this.scrim = document.createElement(\"div\");\n this.scrim.className = \"sp-scrim\";\n this.scrim.addEventListener(\"click\", () => this.close());\n\n this.root = document.createElement(\"div\");\n this.root.appendChild(this.scrim);\n this.root.appendChild(this.radialContainer);\n this.root.appendChild(this.fab);\n shadowRoot.appendChild(this.root);\n\n // Bind every `t()`-derived string into the freshly-built DOM. Kept as a\n // single pass so the constructor and `refreshLabels()` never drift.\n this.applyLabels();\n\n // Close radial menu on click outside. Capture phase: the widget's other\n // surfaces (markers, popup, overlay) stop `click` from bubbling to the\n // document (host-isolation.ts), and clicking them must still close it.\n const host = shadowRoot.host;\n this.onDocumentClick = (e: MouseEvent) => {\n if (this.isOpen && !e.composedPath().includes(host)) {\n this.close();\n }\n };\n document.addEventListener(\"click\", this.onDocumentClick, true);\n\n // Escape on FAB or menu container closes the menu\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === \"Escape\" && this.isOpen) {\n e.stopPropagation();\n this.close();\n }\n };\n this.fab.addEventListener(\"keydown\", handleEscape);\n this.radialContainer.addEventListener(\"keydown\", handleEscape);\n registerEscapeLayer(this.root, () => this.isOpen);\n\n // Arrow key navigation within the radial menu\n this.radialContainer.addEventListener(\"keydown\", (e) => {\n const items = Array.from(this.radialContainer.querySelectorAll<HTMLButtonElement>(\".sp-radial-item\"));\n if (items.length === 0 || !this.isOpen) return;\n const activeEl = (shadowRoot.activeElement ?? document.activeElement) as HTMLElement;\n const currentIndex = items.indexOf(activeEl as HTMLButtonElement);\n\n switch (e.key) {\n case \"ArrowUp\": {\n e.preventDefault();\n const nextIndex = currentIndex <= 0 ? items.length - 1 : currentIndex - 1;\n items[nextIndex]?.focus();\n break;\n }\n case \"ArrowDown\": {\n e.preventDefault();\n const nextIndex = currentIndex >= items.length - 1 ? 0 : currentIndex + 1;\n items[nextIndex]?.focus();\n break;\n }\n case \"Home\": {\n e.preventDefault();\n items[0]?.focus();\n break;\n }\n case \"End\": {\n e.preventDefault();\n items[items.length - 1]?.focus();\n break;\n }\n }\n });\n }\n\n private onDocumentClick: (e: MouseEvent) => void;\n\n /**\n * Re-read every `t(...)`-derived label and aria-label from the active\n * translation function. Idempotent — call after the locale dictionary has\n * finished loading so the FAB labels swap from the English fallback to the\n * configured language.\n */\n refreshLabels(): void {\n this.applyLabels();\n }\n\n /**\n * Walk the already-built DOM and bind every translation-derived string —\n * the FAB `aria-label`, each radial item's `aria-label`, and each\n * `.sp-radial-label` `textContent`. The single source of truth for which\n * node gets which `t()` string, shared by the constructor and\n * `refreshLabels()` so the two can never drift.\n */\n private applyLabels(): void {\n this.fab.setAttribute(\"aria-label\", this.t(\"fab.aria\"));\n\n const buttons = this.radialContainer.querySelectorAll<HTMLButtonElement>(\".sp-radial-item\");\n for (const btn of buttons) {\n const id = btn.dataset.itemId as RadialItemId | undefined;\n if (!id) continue;\n const key = ITEM_LABEL_KEYS[id];\n if (!key) continue;\n const label = this.t(key);\n btn.setAttribute(\"aria-label\", label);\n const labelSpan = btn.querySelector<HTMLSpanElement>(\".sp-radial-label\");\n if (labelSpan) setText(labelSpan, label);\n }\n }\n\n /** Update the badge count. Pass 0 to hide. */\n updateBadge(count: number): void {\n if (count <= 0) {\n this.badgeEl?.remove();\n this.badgeEl = null;\n return;\n }\n\n if (!this.badgeEl) {\n this.badgeEl = document.createElement(\"span\");\n this.badgeEl.className = \"sp-fab-badge\";\n this.badgeEl.setAttribute(\"role\", \"status\");\n this.badgeEl.setAttribute(\"aria-live\", \"polite\");\n this.fab.appendChild(this.badgeEl);\n }\n\n const displayText = count > 99 ? \"99+\" : String(count);\n setText(this.badgeEl, displayText);\n this.badgeEl.setAttribute(\"aria-label\", tWithParams(this.t, \"fab.badge\", { count }));\n }\n\n private toggle(): void {\n this.isOpen ? this.close() : this.open();\n }\n\n private open(): void {\n this.isOpen = true;\n this.setFabIcon(ICON_CLOSE);\n this.fab.setAttribute(\"aria-expanded\", \"true\");\n this.scrim.classList.add(\"sp-scrim--open\");\n\n const gap = isCoarsePointer() ? ITEM_GAP_TOUCH : ITEM_GAP;\n const buttons = this.radialContainer.querySelectorAll<HTMLButtonElement>(\".sp-radial-item\");\n buttons.forEach((btn, i) => {\n // Stack vertically above the FAB with initial offset + gap\n const y = -(16 + gap * (i + 1));\n btn.style.transform = `translate(0px, ${y}px) scale(1)`;\n btn.classList.add(\"sp-radial-item--open\");\n });\n\n // Focus the first menu item after animation\n requestAnimationFrame(() => {\n const firstItem = this.radialContainer.querySelector<HTMLButtonElement>(\".sp-radial-item\");\n firstItem?.focus();\n });\n }\n\n private close(): void {\n this.isOpen = false;\n this.setFabIcon(ICON_SITEPING);\n this.fab.setAttribute(\"aria-expanded\", \"false\");\n this.scrim.classList.remove(\"sp-scrim--open\");\n\n const buttons = this.radialContainer.querySelectorAll<HTMLButtonElement>(\".sp-radial-item\");\n buttons.forEach((btn) => {\n btn.style.transform = \"translate(0, 0) scale(0.8)\";\n btn.classList.remove(\"sp-radial-item--open\");\n });\n\n // Return focus to FAB\n this.fab.focus();\n }\n\n private setFabIcon(svgStr: string): void {\n const badge = this.badgeEl;\n this.fab.replaceChildren(parseSvg(svgStr));\n // Re-append badge after icon swap\n if (badge) this.fab.appendChild(badge);\n }\n\n private handleItemClick(id: RadialItemId): void {\n this.close();\n\n switch (id) {\n case \"chat\":\n this.bus.emit(\"panel:toggle\", true);\n break;\n case \"annotate\": {\n // close() above re-focused the FAB, so the annotator resolves its\n // keyboard target via the focus tracker's last page element — but\n // putting keyboard users back on the FAB when the session ends is on us.\n const unsubscribe = this.bus.on(\"annotation:end\", () => {\n unsubscribe();\n this.fab.focus();\n });\n this.bus.emit(\"annotation:start\");\n break;\n }\n case \"toggle-annotations\": {\n this.annotationsVisible = !this.annotationsVisible;\n this.bus.emit(\"annotations:toggle\", this.annotationsVisible);\n // Replace ONLY the icon SVG, not every child. The button also carries\n // the `<span class=\"sp-radial-label\">` hover label — `replaceChildren`\n // wiped it on the first click, killing the tooltip until reload.\n const btn = this.radialContainer.querySelector('[data-item-id=\"toggle-annotations\"]');\n const oldSvg = btn?.querySelector(\"svg\");\n if (oldSvg) {\n const newSvg = parseSvg(this.annotationsVisible ? ICON_EYE : ICON_EYE_OFF);\n oldSvg.replaceWith(newSvg);\n }\n break;\n }\n }\n }\n\n destroy(): void {\n document.removeEventListener(\"click\", this.onDocumentClick, true);\n this.root.remove();\n }\n}\n","import { hasOwn, IDENTITY_FIELD_MAX_LENGTH, isValidEmail, type SitepingIdentity } from \"@siteping/core\";\n\nconst STORAGE_KEY = \"siteping_identity\";\n\n/**\n * Author identity persisted by the widget — alias of core's\n * `SitepingIdentity` (one concept, one shape; the alias keeps the widget's\n * historical export name working).\n */\nexport type Identity = SitepingIdentity;\n\n/**\n * Type guard — narrows an unknown value to `Identity` only when the name is a\n * non-empty string and the email is one the server accepts, both within the\n * server's length cap. A stored identity that fails either check (persisted\n * by an older, laxer modal) is treated as absent so the modal asks again\n * instead of every submission failing with a 400.\n */\nfunction isIdentity(value: unknown): value is Identity {\n if (!hasOwn(value, \"name\") || !hasOwn(value, \"email\")) return false;\n const { name, email } = value;\n return (\n typeof name === \"string\" &&\n typeof email === \"string\" &&\n name.length > 0 &&\n name.length <= IDENTITY_FIELD_MAX_LENGTH &&\n email.length <= IDENTITY_FIELD_MAX_LENGTH &&\n isValidEmail(email)\n );\n}\n\nexport function getIdentity(): Identity | null {\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) return null;\n const parsed: unknown = JSON.parse(raw);\n return isIdentity(parsed) ? parsed : null;\n } catch {\n return null;\n }\n}\n\nexport function saveIdentity(identity: Identity): void {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(identity));\n } catch {\n // Quota exceeded or localStorage disabled — identity works for this session only\n }\n}\n","/**\n * Lightweight fuzzy text matching for DOM re-anchoring.\n * Zero dependencies — bundled into the widget.\n *\n * Approximate containment uses Sellers' algorithm (1980): a single O(n·m)\n * DP pass over the haystack whose first row is initialized to 0, yielding\n * the minimum edit distance between the needle and ANY substring. This\n * replaces a sliding fixed-length window (O(n·m²)) with identical-or-better\n * scores — a window match is one of the substrings Sellers considers.\n */\n\n/** Below this needle length, approximate substring search over a LONG\n * haystack is statistically meaningless (a 4-char needle \"matches\" almost\n * anything within 1–2 edits somewhere in 500 chars) and was the worst-case\n * cost driver. Exact containment still applies at any length, and short\n * haystacks (≤ SHORT_NEEDLE_HAYSTACK_CAP) keep approximate matching — a\n * near-miss in a short label (\"panier\" vs \"paniers\") is meaningful. */\nexport const MIN_FUZZY_NEEDLE_LENGTH = 8;\n\n/** See MIN_FUZZY_NEEDLE_LENGTH. */\nconst SHORT_NEEDLE_HAYSTACK_CAP = 64;\n\n/** Max haystack length considered for approximate matching. */\nconst HAYSTACK_CAP = 500;\n\n/**\n * Normalize text for comparison: Unicode NFC + collapse whitespace runs to a\n * single space + trim. Absorbs SSR/CSR hydration drift, prettified vs\n * minified markup, and re-indentation (formatting whitespace lives inside\n * `textContent` of nested elements). Applied at comparison time on both\n * sides — already-stored snippets stay valid. Deliberately NOT case-folding:\n * a case change is a real signal (CSS text-transform never affects\n * textContent, so case differences come from actual content edits).\n */\nexport function normalizeText(s: string): string {\n return s.normalize(\"NFC\").replace(/\\s+/g, \" \").trim();\n}\n\n/**\n * Whitespace-only collapse — the cheap subset of `normalizeText` for the scan\n * prefilter, which runs on every same-tag candidate. NFC is a table-driven\n * full-Unicode pass and is deliberately skipped there: the prefilter only\n * RANKS, and mixed composition forms cost at worst a slight rank penalty on\n * accented text (full scoring of survivors re-normalizes both sides).\n */\nexport function collapseWhitespace(s: string): string {\n return s.replace(/\\s+/g, \" \").trim();\n}\n\n/**\n * Levenshtein edit distance.\n * O(n*m) time, O(min(n,m)) space.\n */\nexport function editDistance(a: string, b: string): number {\n if (a === b) return 0;\n if (a.length === 0) return b.length;\n if (b.length === 0) return a.length;\n\n // Ensure `a` is the shorter string for space optimization\n if (a.length > b.length) {\n const t = a;\n a = b;\n b = t;\n }\n\n const aLen = a.length;\n const bLen = b.length;\n let prev = new Array<number>(aLen + 1);\n for (let k = 0; k <= aLen; k++) prev[k] = k;\n let curr = new Array<number>(aLen + 1);\n\n for (let j = 1; j <= bLen; j++) {\n curr[0] = j;\n for (let i = 1; i <= aLen; i++) {\n // Indices are provably in bounds (loop bounds; arrays sized aLen+1) —\n // plain casts instead of ?? fallbacks that could never fire.\n const prevDiag = prev[i - 1] as number;\n curr[i] = a[i - 1] === b[j - 1] ? prevDiag : 1 + Math.min(prevDiag, prev[i] as number, curr[i - 1] as number);\n }\n const tmp = prev;\n prev = curr;\n curr = tmp;\n }\n\n return prev[aLen] as number; // aLen is within bounds — prev has aLen+1 entries\n}\n\n/**\n * Normalized similarity score (0–1, where 1 = identical).\n */\nexport function similarity(a: string, b: string): number {\n if (a === b) return 1;\n const maxLen = Math.max(a.length, b.length);\n if (maxLen === 0) return 1;\n return 1 - editDistance(a, b) / maxLen;\n}\n\n/**\n * Sellers 1980 — minimum edit distance between `needle` and any substring of\n * `haystack`. Row 0 of the DP is zero for every haystack position (a match\n * may start anywhere); the answer is the running minimum of the last row.\n * Distance is bounded by needle.length (deleting the whole needle), so the\n * needle-normalized score 1 - dist/needle.length always lands in [0, 1].\n */\nfunction sellersDistance(haystack: string, needle: string): number {\n const n = needle.length;\n let prev = new Int32Array(n + 1);\n let curr = new Int32Array(n + 1);\n for (let i = 0; i <= n; i++) prev[i] = i;\n let best = n;\n\n for (let j = 1; j <= haystack.length; j++) {\n curr[0] = 0;\n const hc = haystack.charCodeAt(j - 1);\n for (let i = 1; i <= n; i++) {\n // Indices provably in bounds — casts, not ?? arms that can never fire.\n const sub = (prev[i - 1] as number) + (needle.charCodeAt(i - 1) === hc ? 0 : 1);\n const del = (prev[i] as number) + 1;\n const ins = (curr[i - 1] as number) + 1;\n curr[i] = Math.min(sub, del, ins);\n }\n const last = curr[n] as number;\n if (last < best) best = last;\n const tmp = prev;\n prev = curr;\n curr = tmp;\n }\n\n return best;\n}\n\n/**\n * Fuzzy substring search — checks if `needle` approximately exists in `haystack`.\n * Returns the best needle-normalized similarity found, or 0 if below `minScore`.\n *\n * Pipeline (cheapest first): exact containment → direct comparison when the\n * needle is longer than the haystack → Sellers approximate substring search.\n * Short needles never enter approximate search over long haystacks (see\n * MIN_FUZZY_NEEDLE_LENGTH).\n *\n * Callers are expected to pass `normalizeText`-processed strings; this\n * function compares verbatim.\n */\nexport function fuzzyIncludes(haystack: string, needle: string, minScore = 0.6): number {\n if (!needle || !haystack) return 0;\n if (haystack.includes(needle)) return 1;\n\n const capped = haystack.length > HAYSTACK_CAP ? haystack.slice(0, HAYSTACK_CAP) : haystack;\n\n // Needle longer than haystack — direct comparison (no substring to find)\n if (needle.length > capped.length) {\n const score = similarity(capped, needle);\n return score >= minScore ? score : 0;\n }\n\n if (needle.length < MIN_FUZZY_NEEDLE_LENGTH && capped.length > SHORT_NEEDLE_HAYSTACK_CAP) {\n return 0;\n }\n\n const score = 1 - sellersDistance(capped, needle) / needle.length;\n return score >= minScore ? score : 0;\n}\n\n/**\n * Character-bigram multiset of a string, keyed by packed char-code pairs.\n * Built once per resolution for the stored snippet, then streamed against\n * every scan candidate via `diceAgainst` — no per-candidate copy.\n */\nexport function bigramCounts(s: string): Map<number, number> {\n const counts = new Map<number, number>();\n for (let i = 0; i < s.length - 1; i++) {\n const key = (s.charCodeAt(i) << 16) | s.charCodeAt(i + 1);\n counts.set(key, (counts.get(key) ?? 0) + 1);\n }\n return counts;\n}\n\n/**\n * Sørensen–Dice coefficient between a precomputed bigram multiset and a raw\n * string, in O(|text|). Multiset semantics (bigram occurrences are consumed,\n * not just membership-tested) — repeated-bigram strings like \"aaaa\" would\n * otherwise score against sets they barely overlap.\n *\n * Used exclusively as a RANKING signal for scan prefiltering (top-K keep),\n * never as an eliminating threshold — so an imperfect correlation with edit\n * distance can demote a candidate but never drop a true match outright.\n */\nexport function diceAgainst(needleCounts: Map<number, number>, needleBigramTotal: number, text: string): number {\n const textBigramTotal = text.length - 1;\n if (needleBigramTotal <= 0 || textBigramTotal <= 0) return 0;\n\n let matches = 0;\n const consumed = new Map<number, number>();\n for (let i = 0; i < text.length - 1; i++) {\n const key = (text.charCodeAt(i) << 16) | text.charCodeAt(i + 1);\n const available = needleCounts.get(key);\n if (available === undefined) continue;\n const used = consumed.get(key) ?? 0;\n if (used < available) {\n consumed.set(key, used + 1);\n matches++;\n }\n }\n\n return (2 * matches) / (needleBigramTotal + textBigramTotal);\n}\n\n/**\n * Word-pair shingle multiset (\"quick brown\", \"brown fox\", …) of a\n * whitespace-normalized string. Character bigrams are order-blind: on pages\n * where many elements share a vocabulary (card grids, list views), every\n * candidate looks alike to them, while word ORDER still discriminates —\n * a true match preserves most word pairs, shared vocabulary in a different\n * order preserves almost none. Scripts without spaces produce no pairs and\n * callers fall back to character bigrams alone.\n */\nexport function wordPairCounts(s: string): Map<string, number> {\n const counts = new Map<string, number>();\n const words = s.split(\" \");\n for (let i = 0; i < words.length - 1; i++) {\n const key = `${words[i]} ${words[i + 1]}`;\n counts.set(key, (counts.get(key) ?? 0) + 1);\n }\n return counts;\n}\n\n/**\n * Sørensen–Dice over word-pair shingles, multiset semantics, O(|text|).\n * Same ranking-only contract as `diceAgainst`.\n */\nexport function wordPairDiceAgainst(needlePairs: Map<string, number>, needlePairTotal: number, text: string): number {\n if (needlePairTotal <= 0) return 0;\n const words = text.split(\" \");\n const textPairTotal = words.length - 1;\n if (textPairTotal <= 0) return 0;\n\n let matches = 0;\n const consumed = new Map<string, number>();\n for (let i = 0; i < words.length - 1; i++) {\n const key = `${words[i]} ${words[i + 1]}`;\n const available = needlePairs.get(key);\n if (available === undefined) continue;\n const used = consumed.get(key) ?? 0;\n if (used < available) {\n consumed.set(key, used + 1);\n matches++;\n }\n }\n\n return (2 * matches) / (needlePairTotal + textPairTotal);\n}\n","/**\n * Element visibility classification for anchor resolution.\n *\n * Responsive sites render the same component twice (`hidden md:block` mobile +\n * desktop twins); resolution must prefer the rendered copy. Visibility is a\n * scoring TIER, never a hard filter — when every duplicate is hidden (e.g.\n * mobile viewport), the best hidden candidate still resolves rather than\n * orphaning the annotation.\n */\n\nexport type VisibilityClass = \"visible\" | \"soft-hidden\" | \"hidden\" | \"unknown\";\n\n/**\n * Both option-name generations must be passed together: the CSSOM spec ORs\n * the old (checkOpacity/checkVisibilityCSS) and renamed\n * (opacityProperty/visibilityProperty) flags, and Chrome 105–120 /\n * Firefox 106–121 silently ignore the new names.\n * `contentVisibilityAuto` stays OFF — `content-visibility: auto` content is\n * merely offscreen, a perfectly legitimate anchor target.\n */\nconst STRICT_VISIBILITY_OPTIONS: Record<string, boolean> = {\n checkOpacity: true,\n opacityProperty: true,\n checkVisibilityCSS: true,\n visibilityProperty: true,\n};\n\n/**\n * Classify how visible an element currently is.\n *\n * - `\"visible\"` — rendered and painted.\n * - `\"soft-hidden\"` — geometry intact but not painted (visibility:hidden,\n * opacity:0). Anchor rects computed from it stay valid;\n * opacity:0 is common mid fade-in, so this is only a mild\n * penalty, never an exclusion.\n * - `\"hidden\"` — no rendered geometry: display:none chain,\n * content-visibility:hidden (closed <details>), detached.\n * - `\"unknown\"` — the environment performs no layout (jsdom: no\n * checkVisibility, every rect zero/empty). Treated as\n * visible by scorers so layout-less test environments and\n * exotic embedders keep pre-visibility behavior.\n *\n * Fallback chain notes (browsers without checkVisibility — Safari ≤ 17.3):\n * - `getClientRects().length` is the no-box test; `getBoundingClientRect()`\n * zeros are ambiguous (real zero-sized visible elements exist).\n * - NEVER `offsetParent === null` — visible position:fixed elements (sticky\n * headers, FABs: prime feedback targets) report null.\n * - `visibility` is an inherited computed value, so one read on the candidate\n * is sufficient and correctly handles `visibility: visible` re-shows inside\n * hidden ancestors; display:none needs no ancestor walk because the box\n * tree already has no fragments for the whole subtree.\n * - content-visibility:hidden content keeps real geometry, so the fallback\n * misclassifies it as visible — acceptable: every engine old enough to lack\n * checkVisibility also predates content-visibility support.\n * - aria-hidden is deliberately ignored (visually rendered content).\n */\nexport function classifyVisibility(element: Element): VisibilityClass {\n if (!element.isConnected) return \"hidden\";\n\n // Runtime guard stays although lib.dom types it as always-present:\n // jsdom (the test environment) and Safari ≤ 17.3 don't implement it.\n if (typeof element.checkVisibility === \"function\") {\n if (element.checkVisibility(STRICT_VISIBILITY_OPTIONS)) return \"visible\";\n // Base call only rejects display:none chains and content-visibility:hidden;\n // passing it while failing the strict call means visibility/opacity hiding.\n return element.checkVisibility() ? \"soft-hidden\" : \"hidden\";\n }\n\n if (element.getClientRects().length > 0) {\n try {\n const visibility = getComputedStyle(element).visibility;\n return visibility === \"visible\" ? \"visible\" : \"soft-hidden\";\n } catch {\n return \"visible\";\n }\n }\n\n // display:contents generates no box of its own but renders its children.\n const child = element.firstElementChild;\n if (child && child.getClientRects().length > 0) return \"visible\";\n\n // No boxes anywhere — hidden, unless the environment does no layout at all\n // (then every element has zero rects and the signal is meaningless).\n if (element.ownerDocument.documentElement.getClientRects().length === 0) return \"unknown\";\n\n return \"hidden\";\n}\n\n/** Score multiplier for a visibility class — tiering, not filtering. */\nexport function visibilityFactor(cls: VisibilityClass): number {\n switch (cls) {\n case \"hidden\":\n return 0.3;\n case \"soft-hidden\":\n return 0.6;\n default:\n return 1;\n }\n}\n","import type { AnchorData, RectData } from \"@siteping/core\";\nimport { ANCHOR_KEY_ATTR, SHADOW_BOUNDARY } from \"./anchor.js\";\nimport { attrHash, scoreFingerprint } from \"./fingerprint.js\";\nimport {\n bigramCounts,\n collapseWhitespace,\n diceAgainst,\n fuzzyIncludes,\n normalizeText,\n similarity,\n wordPairCounts,\n wordPairDiceAgainst,\n} from \"./fuzzy.js\";\nimport { adjacentText, boundedText, neighborText } from \"./text-context.js\";\nimport { classifyVisibility, visibilityFactor } from \"./visibility.js\";\n\nexport type ResolutionStrategy = \"anchorKey\" | \"id\" | \"css\" | \"xpath\" | \"scan\";\n\nexport interface AnchorResolution {\n element: Element;\n confidence: number;\n strategy: ResolutionStrategy;\n}\n\nexport interface ResolvedAnnotation {\n element: Element;\n rect: DOMRect;\n confidence: number;\n strategy: ResolutionStrategy;\n}\n\n/**\n * Caller-provided allowance for full tag sweeps across a BATCH of\n * resolutions (marker init, reposition passes). A sweep is the one\n * unbounded-ish cost left in resolution; several drifted or hidden anchors\n * resolved back-to-back must not each pay one synchronously (the Hypothesis\n * issue-#3919 lesson: budget per pass, not per resolution). When the budget\n * is exhausted, resolution proceeds selector-only — the next pass gets a\n * fresh budget and heals the remainder.\n */\nexport interface ScanBudget {\n /** Remaining sweep allowance; decremented each time a sweep actually runs. */\n remaining: number;\n /** Set by the resolver when a sweep was wanted but the budget was empty —\n * callers must NOT cache such degraded results (a selector-only answer may\n * be worse than what the sweep would have found, and a cached wrong\n * element is never re-examined). */\n starved?: boolean;\n}\n\nexport interface ResolveOptions {\n scanBudget?: ScanBudget;\n}\n\n/**\n * Confidence ceiling per strategy — same ladder as v1's cascade, now used as\n * a multiplicative prior in cross-strategy ranking. Multiplicative, not\n * additive: a prior can only amplify verification evidence, never substitute\n * for it, so a stale selector with poor verification cannot outrank a\n * well-verified scan hit.\n */\nconst STRATEGY_PRIORS: Record<ResolutionStrategy, number> = {\n anchorKey: 1.0,\n id: 1.0,\n css: 0.95,\n xpath: 0.9,\n scan: 0.85,\n};\n\n/** Max matches gathered per selector strategy (guards degenerate selectors). */\nconst MAX_PER_STRATEGY = 16;\n\n/** Scan candidates that survive prefiltering and get full multi-signal scoring. */\nconst SCAN_TOP_K = 24;\n\n/** Pathological-DOM guard for the prefilter sweep itself. */\nconst SCAN_HARD_CAP = 10_000;\n\n/** Max candidate text considered for scoring (bounds fuzzy-match cost). */\nconst CANDIDATE_TEXT_CAP = 500;\n\n/**\n * Acceptance for selector strategies gates on the STRONGEST single signal,\n * never on the diluted blend — the blend is a RANKING device. A volatile\n * signal (fingerprints churn with every redesign) must not veto a stable\n * one: v1 resolved `#promo` + fuzzy-passing text regardless of what the\n * surrounding DOM did, and that must survive.\n * - text ≥ 0.5 (v1's effective bar — fuzzyIncludes' own minScore) accepts.\n * - No stored text at all: ALWAYS acceptable — v1 accepted textless selector\n * hits unconditionally, and rejection here silently orphans legacy\n * icon/image anchors whose id still matches (the sweep cannot rescue pool\n * members). Ranking and confidence already penalize structural drift.\n * - Text present but REFUTED: strong structural corroboration required —\n * the i18n case (text translated, fingerprint intact) passes, a weak\n * fingerprint coincidence does not.\n * Scan has no selector evidence, so it keeps v1's 0.4 floor on the blend.\n */\nconst TEXT_FLOOR = 0.5;\nconst STRONG_STRUCT = 0.6;\nconst ACCEPT_SCAN = 0.4;\n\n/** Hostile-stored-data guard: fields are sliced before any normalization\n * (NFC on a multi-megabyte string is itself a freeze) and again after. */\nconst RAW_FIELD_CAP = 2000;\n\n/**\n * Verification at or above this level earns the full strategy prior as\n * confidence; below it, confidence degrades proportionally (and crosses the\n * marker UI's 0.7 \"approximate\" threshold naturally).\n */\nconst STRONG_VERIFY = 0.8;\n\n/**\n * Verification assigned to selector-strategy candidates when the stored\n * anchor carries no verifiable signal at all (no text, no fingerprint, no\n * context — only possible for hand-built or pre-fingerprint data; capture\n * always stores a fingerprint). The selector match is then the only\n * evidence: accept, but rank it below verified alternatives.\n */\nconst NEUTRAL_VERIFICATION = 0.6;\n\n/** Score gap under which two candidates are considered equally plausible. */\nconst AMBIGUITY_EPSILON = 0.05;\n\n/** Stored-anchor signals, normalized once per resolution. */\ninterface AnchorSignals {\n snippet: string;\n snippetBigrams: Map<number, number>;\n snippetBigramTotal: number;\n snippetWordPairs: Map<string, number>;\n snippetWordPairTotal: number;\n prefix: string;\n suffix: string;\n neighbor: string;\n fingerprint: string;\n tag: string;\n}\n\n/** Per-signal verification scores; a signal is absent when undefined. */\ninterface SignalScores {\n blend: number;\n strongest: number;\n text?: number;\n fingerprint?: number;\n context?: number;\n neighbor?: number;\n}\n\ninterface ScoredCandidate {\n element: Element;\n strategy: ResolutionStrategy;\n verification: number;\n strongest: number;\n signals?: SignalScores;\n /** Visibility factor applied to `final` (1 = visible/unknown). */\n visibility: number;\n final: number;\n /** No verifiable signal was stored — verification is a neutral stand-in. */\n unverified?: boolean;\n}\n\nfunction boundedField(value: string | null | undefined, cap: number): string {\n return normalizeText((value ?? \"\").slice(0, RAW_FIELD_CAP)).slice(0, cap);\n}\n\nfunction buildSignals(anchor: AnchorData): AnchorSignals {\n // Capture stores ≤120-char snippets and ≤40-char context — larger values\n // only come from hostile or corrupted storage, and uncapped they turn\n // normalization/edit-distance into a main-thread freeze.\n const snippet = boundedField(anchor.textSnippet, CANDIDATE_TEXT_CAP);\n const snippetWordPairs = wordPairCounts(snippet);\n let snippetWordPairTotal = 0;\n for (const count of snippetWordPairs.values()) snippetWordPairTotal += count;\n return {\n snippet,\n snippetBigrams: bigramCounts(snippet),\n snippetBigramTotal: Math.max(0, snippet.length - 1),\n snippetWordPairs,\n snippetWordPairTotal,\n prefix: boundedField(anchor.textPrefix, 128),\n suffix: boundedField(anchor.textSuffix, 128),\n neighbor: boundedField(anchor.neighborText, 128),\n fingerprint: (anchor.fingerprint ?? \"\").slice(0, 64),\n tag: typeof anchor.elementTag === \"string\" ? anchor.elementTag : \"\",\n };\n}\n\n/**\n * Re-anchor an annotation: gather candidates from EVERY strategy, verify each\n * against all stored signals, rank across strategies, return the best.\n *\n * v1 was a first-match-wins cascade (anchorKey → id → css → xpath → scan)\n * where a wrong-but-text-passing selector hit won outright over a correct\n * element the scan would have found (#175), the first DOM match won even when\n * it was an invisible responsive twin (#171), and elements without text got\n * no verification at all (#172).\n *\n * v2 ranking: final = strategyPrior × verification × visibilityFactor\n * - verification: dynamic-weight blend of text / fingerprint / prefix-suffix /\n * neighbor signals (only signals the stored anchor has contribute).\n * - visibility: tiering, never filtering — hidden duplicates are heavily\n * penalized, but when ONLY hidden candidates exist the best one still\n * resolves (an annotation on a currently-collapsed section survives the\n * breakpoint flipping back).\n * - Confidence keeps the v1 scale: a perfectly verified anchorKey/id/css/\n * xpath match yields exactly 1.0/1.0/0.95/0.9, scan stays capped at 0.85,\n * and weak verification degrades confidence proportionally.\n *\n * The scan sweep is skipped when a selector candidate already scores above\n * anything the scan could produce (its prior caps its final at 0.85) — the\n * happy path costs a handful of querySelector calls, like v1.\n *\n * Returns null if no candidate verifies (annotation is orphaned).\n */\nexport function resolveAnchor(anchor: AnchorData, options?: ResolveOptions): AnchorResolution | null {\n const signals = buildSignals(anchor);\n const { pool, treeRoots } = gatherSelectorCandidates(anchor);\n\n const scored: ScoredCandidate[] = [];\n for (const [element, strategy] of pool) {\n const candidate = scoreOne(element, strategy, signals);\n if (candidate) scored.push(candidate);\n }\n\n let bestFinal = 0;\n let strongVisibleMatch = false;\n for (const c of scored) {\n if (c.final > bestFinal) bestFinal = c.final;\n // Identity selectors (id, anchorKey — near-unique by contract, the ones\n // v1 trusted absolutely) with near-exact text on a visible element end\n // the search even when CONTEXT signals (neighbors, prefix/suffix)\n // drifted — but not when the element's own fingerprint contradicts:\n // a wrapper that took over the id contains the same text yet scores a\n // partial fingerprint, and only the sweep can surface the true inner\n // element. Fragile selectors (css/xpath) get no shortcut at all: an\n // element that merely CONTAINS the snippet verbatim plus coincidental\n // structure is exactly the #175 impostor — they suppress the sweep\n // solely through the unbeatable-final bound below.\n if (\n (c.strategy === \"id\" || c.strategy === \"anchorKey\") &&\n c.visibility === 1 &&\n (c.signals?.text ?? 0) >= STRONG_VERIFY &&\n (c.signals?.fingerprint === undefined || c.signals.fingerprint >= STRONG_VERIFY)\n ) {\n strongVisibleMatch = true;\n }\n }\n\n // The sweep only helps when something could beat the pool (scan's final is\n // capped by its prior) AND there is at least one stored signal to verify\n // scan candidates against — with none, every scan candidate is discarded\n // and the sweep is pure cost. A shadow anchor whose host chain no longer\n // resolves has no tree to sweep at all.\n const verifiable = !!(signals.snippet || signals.fingerprint || signals.prefix || signals.suffix || signals.neighbor);\n const budget = options?.scanBudget;\n if (verifiable && treeRoots.length > 0 && bestFinal < STRATEGY_PRIORS.scan && !strongVisibleMatch) {\n if (budget && budget.remaining <= 0) {\n budget.starved = true;\n } else {\n if (budget) budget.remaining--;\n for (const element of sweepScanCandidates(signals, pool, treeRoots)) {\n const candidate = scoreOne(element, \"scan\", signals);\n if (candidate) scored.push(candidate);\n }\n }\n }\n\n const accepted = scored.filter(isAcceptable);\n if (accepted.length === 0) return null;\n\n accepted.sort((a, b) => b.final - a.final);\n const winner = disambiguate(accepted);\n\n return {\n element: winner.element,\n confidence: confidenceOf(winner),\n strategy: winner.strategy,\n };\n}\n\n/** A tree selector strategies can be queried against. */\ntype QueryRoot = Document | ShadowRoot;\n\n/**\n * The first MAX_PER_STRATEGY matches of `selector` across `roots`, in root\n * order. Throws on an invalid selector, like `querySelectorAll`.\n */\nfunction queryRoots(roots: readonly QueryRoot[], selector: string): Element[] {\n const found: Element[] = [];\n for (const root of roots) {\n const matches = root.querySelectorAll(selector);\n for (let i = 0; i < matches.length && found.length < MAX_PER_STRATEGY; i++) {\n const el = matches[i];\n if (el) found.push(el);\n }\n if (found.length === MAX_PER_STRATEGY) break;\n }\n return found;\n}\n\n/**\n * Follow a shadow-captured selector's host segments down from the document:\n * `levels[i]` holds the open shadow roots of the hosts matched by segment i,\n * the last level being the anchored element's own tree. Each segment is\n * capped at MAX_PER_STRATEGY hosts, so a degenerate host selector cannot fan\n * the lookup out across a whole card grid. Returns [] when the chain breaks\n * (host gone, renamed, or its root closed).\n */\nfunction resolveShadowLevels(hostSelectors: readonly string[]): ShadowRoot[][] {\n const levels: ShadowRoot[][] = [];\n let roots: readonly QueryRoot[] = [document];\n for (const selector of hostSelectors) {\n let hosts: Element[];\n try {\n hosts = queryRoots(roots, selector);\n } catch {\n return [];\n }\n const next: ShadowRoot[] = [];\n for (const host of hosts) {\n if (host.shadowRoot) next.push(host.shadowRoot);\n }\n if (next.length === 0) return [];\n levels.push(next);\n roots = next;\n }\n return levels;\n}\n\n/**\n * Collect candidates from all selector strategies, ALL matches per strategy\n * (bounded), in priority order. An element found by several strategies keeps\n * the highest-priority one (first insertion wins).\n *\n * Light-DOM anchors query the document exactly as before. A shadow-captured\n * selector (`host >>> inner`) cannot match at document level by construction,\n * so that anchor descends into the open roots its host chain leads to —\n * never a whole-document walk. Ids and selectors are tree-scoped (against\n * the document they would only surface cross-tree impostors) and run in the\n * element's own tree; the semantic key may sit on any tree of the chain.\n * Returns those trees too (`treeRoots`), for the sweep.\n */\nfunction gatherSelectorCandidates(anchor: AnchorData): {\n pool: Map<Element, ResolutionStrategy>;\n treeRoots: readonly QueryRoot[];\n} {\n const pool = new Map<Element, ResolutionStrategy>();\n\n const add = (el: Element | null, strategy: ResolutionStrategy, enforceTag: boolean) => {\n if (!el || pool.has(el)) return;\n if (enforceTag && el.tagName !== anchor.elementTag) return;\n pool.set(el, strategy);\n };\n\n const segments = typeof anchor.cssSelector === \"string\" ? anchor.cssSelector.split(SHADOW_BOUNDARY) : [];\n const selector = segments[segments.length - 1] ?? anchor.cssSelector;\n const shadowLevels = segments.length > 1 ? resolveShadowLevels(segments.slice(0, -1)) : null;\n const treeRoots: readonly QueryRoot[] = shadowLevels ? (shadowLevels[shadowLevels.length - 1] ?? []) : [document];\n const keyRoots: readonly QueryRoot[] = shadowLevels ? [document, ...shadowLevels.flat()] : treeRoots;\n\n // anchorKey — host-controlled semantic key. Tag NOT enforced: hosts may\n // legitimately refactor the wrapper element while keeping the key stable.\n if (anchor.anchorKey) {\n const escaped = anchor.anchorKey.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n try {\n for (const el of queryRoots(keyRoots, `[${ANCHOR_KEY_ATTR}=\"${escaped}\"]`)) add(el, \"anchorKey\", false);\n } catch {\n // Invalid attribute value — skip strategy\n }\n }\n\n // id — duplicate ids are invalid HTML but common in the wild; gather all so\n // a hidden duplicate can lose to the visible one instead of shadowing it.\n // Attribute selector instead of `#…` to avoid needing CSS.escape (absent in\n // some embedders and in jsdom) — matching semantics are identical.\n if (anchor.elementId) {\n const escaped = anchor.elementId.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n try {\n for (const el of queryRoots(treeRoots, `[id=\"${escaped}\"]`)) add(el, \"id\", true);\n } catch {\n for (const root of treeRoots) add(root.getElementById(anchor.elementId), \"id\", true);\n }\n }\n\n // CSS selector — its innermost segment, for a shadow anchor\n try {\n for (const el of queryRoots(treeRoots, selector)) add(el, \"css\", true);\n } catch {\n // Invalid selector — skip strategy\n }\n\n // XPath cannot enter shadow trees: a shadow anchor's path is informational.\n if (shadowLevels) return { pool, treeRoots };\n\n // XPath — snapshot (not FIRST_ORDERED_NODE) so later duplicates compete too\n try {\n const result = document.evaluate(anchor.xpath, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);\n const count = Math.min(result.snapshotLength, MAX_PER_STRATEGY);\n for (let i = 0; i < count; i++) {\n const node = result.snapshotItem(i);\n if (node instanceof Element) add(node, \"xpath\", true);\n }\n } catch {\n // Invalid XPath — skip strategy\n }\n\n return { pool, treeRoots };\n}\n\n/**\n * Same-tag sweep, prefiltered. Every same-tag element is considered (v1\n * stopped dead at the 300th in document order — a correct element past the\n * cap was unreachable), but full scoring only runs on the TOP_K best by a\n * cheap O(text-budget) prefilter: bigram-Dice text overlap plus O(1)\n * structural hints (stable-attribute hash, child count). The prefilter only\n * RANKS — it never eliminates on a threshold, so an imperfect cheap score\n * demotes a candidate but cannot drop the true match on its own.\n *\n * SCAN_HARD_CAP bounds the whole sweep however many trees it spans, so one\n * ScanBudget unit costs a shadow anchor no more than a light-DOM one.\n */\nfunction sweepScanCandidates(\n signals: AnchorSignals,\n pool: Map<Element, ResolutionStrategy>,\n roots: readonly QueryRoot[],\n): Element[] {\n const tag = signals.tag.toLowerCase();\n if (!tag) return [];\n const candidates: Element[] = [];\n try {\n for (const root of roots) {\n const matches = root.querySelectorAll(tag);\n for (let i = 0; i < matches.length && candidates.length < SCAN_HARD_CAP; i++) {\n const el = matches[i];\n if (el) candidates.push(el);\n }\n if (candidates.length === SCAN_HARD_CAP) break;\n }\n } catch {\n return [];\n }\n\n // Parse only well-formed 3-part fingerprints (mirrors scoreFingerprint).\n // `Number(\"\")` is 0, not NaN — an empty fingerprint would otherwise grant a\n // phantom child-count-0 bonus that biases top-K toward childless decoys.\n const storedFp = signals.fingerprint.split(\":\");\n const storedChildCount = storedFp.length === 3 ? Number(storedFp[0]) : Number.NaN;\n const storedAttrHash = storedFp.length === 3 ? (storedFp[2] ?? \"\") : \"\";\n\n const ranked: { element: Element; cheap: number }[] = [];\n\n for (const el of candidates) {\n if (pool.has(el)) continue; // already scored under a selector strategy\n\n let cheap = 0;\n if (signals.snippetBigramTotal > 0) {\n // collapseWhitespace, not full normalizeText: NFC on every candidate is\n // the prefilter's dominant hidden cost; survivors get re-normalized in\n // full scoring anyway.\n const text = collapseWhitespace(boundedText(el, CANDIDATE_TEXT_CAP));\n const charDice = diceAgainst(signals.snippetBigrams, signals.snippetBigramTotal, text);\n // Character bigrams are order-blind: on shared-vocabulary pages (card\n // grids) every candidate scores alike. Word-pair shingles restore order\n // sensitivity; when the snippet has no pairs (single word, no-space\n // scripts) the whole weight stays on character bigrams. A shared word\n // pair implies shared bigrams, so charDice 0 makes the word pass moot.\n if (signals.snippetWordPairTotal > 0) {\n const wordDice =\n charDice > 0 ? wordPairDiceAgainst(signals.snippetWordPairs, signals.snippetWordPairTotal, text) : 0;\n cheap += 0.6 * (0.5 * charDice + 0.5 * wordDice);\n } else {\n cheap += 0.6 * charDice;\n }\n }\n if (storedAttrHash && attrHash(el) === storedAttrHash) cheap += 0.25;\n if (!Number.isNaN(storedChildCount)) {\n const diff = Math.abs(el.children.length - storedChildCount);\n if (diff === 0) cheap += 0.15;\n else if (diff <= 2) cheap += 0.07;\n }\n\n ranked.push({ element: el, cheap });\n }\n\n // Stable sort: ties keep document order, mirroring v1's document-order bias.\n ranked.sort((a, b) => b.cheap - a.cheap);\n return ranked.slice(0, SCAN_TOP_K).map((r) => r.element);\n}\n\nfunction scoreOne(element: Element, strategy: ResolutionStrategy, signals: AnchorSignals): ScoredCandidate | null {\n const scores = verificationScore(element, signals);\n const visibility = visibilityFactor(classifyVisibility(element));\n if (scores === null) {\n // No verifiable signal stored: the selector match is the only evidence.\n // A scan candidate with nothing to verify against is meaningless, though.\n if (strategy === \"scan\") return null;\n return {\n element,\n strategy,\n verification: NEUTRAL_VERIFICATION,\n strongest: NEUTRAL_VERIFICATION,\n visibility,\n final: STRATEGY_PRIORS[strategy] * NEUTRAL_VERIFICATION * visibility,\n unverified: true,\n };\n }\n\n return {\n element,\n strategy,\n verification: scores.blend,\n strongest: scores.strongest,\n signals: scores,\n visibility,\n final: STRATEGY_PRIORS[strategy] * scores.blend * visibility,\n };\n}\n\n/**\n * Whether a candidate has enough corroboration to be returned at all.\n * Selector strategies accept on the strongest SINGLE signal clearing its\n * floor — a drifted fingerprint must not veto an exact text match (or vice\n * versa: an icon button's intact fingerprint carries it when there is no\n * text). Scan keeps its blend floor: without selector evidence, agreement\n * across signals is the whole case for the match.\n */\nfunction isAcceptable(c: ScoredCandidate): boolean {\n if (c.strategy === \"scan\") return c.verification >= ACCEPT_SCAN;\n if (c.unverified || !c.signals) return true;\n const s = c.signals;\n // No stored text: ranking-only (see constant doc — v1 parity for legacy\n // textless anchors; drift shows up as low confidence, not orphaning).\n if (s.text === undefined) return true;\n if (s.text >= TEXT_FLOOR) return true;\n // Text present but refuted — accept only on strong structural agreement.\n return (\n (s.fingerprint ?? 0) >= STRONG_STRUCT || (s.context ?? 0) >= STRONG_STRUCT || (s.neighbor ?? 0) >= STRONG_STRUCT\n );\n}\n\n/**\n * Multi-signal verification, 0–1. Dynamic weighting: only signals the stored\n * anchor actually has contribute, then the sum is normalized — anchors\n * captured with fewer signals compete on the signals they do have.\n * Returns null when the anchor stores no verifiable signal at all.\n *\n * All text comparisons run on `normalizeText`-processed strings on BOTH\n * sides, so SSR/CSR whitespace drift and re-indented markup no longer\n * penalize otherwise-identical text (#173) — stored snippets are untouched\n * and stay backward compatible.\n */\nfunction verificationScore(candidate: Element, s: AnchorSignals): SignalScores | null {\n let score = 0;\n let totalWeight = 0;\n const out: SignalScores = { blend: 0, strongest: 0 };\n\n // --- Text snippet (weight 40 — most reliable under reordering) ---\n if (s.snippet) {\n totalWeight += 40;\n const candidateText = normalizeText(boundedText(candidate, CANDIDATE_TEXT_CAP));\n out.text = fuzzyIncludes(candidateText, s.snippet, 0.5);\n score += out.text * 40;\n }\n\n // --- Fingerprint (weight 20) ---\n if (s.fingerprint) {\n totalWeight += 20;\n out.fingerprint = scoreFingerprint(candidate, s.fingerprint);\n score += out.fingerprint * 20;\n }\n\n // --- Prefix/suffix context (weight 20) ---\n if (s.prefix || s.suffix) {\n totalWeight += 20;\n let contextScore = 0;\n let contextParts = 0;\n\n if (s.prefix) {\n const prevText = normalizeText(adjacentText(candidate, \"before\"));\n contextScore += prevText ? similarity(prevText, s.prefix) : 0;\n contextParts++;\n }\n\n if (s.suffix) {\n const nextText = normalizeText(adjacentText(candidate, \"after\"));\n contextScore += nextText ? similarity(nextText, s.suffix) : 0;\n contextParts++;\n }\n\n if (contextParts > 0) {\n out.context = contextScore / contextParts;\n score += out.context * 20;\n }\n }\n\n // --- Neighbor text (weight 20) ---\n if (s.neighbor) {\n totalWeight += 20;\n const candidateNeighbor = normalizeText(neighborText(candidate));\n out.neighbor = candidateNeighbor ? similarity(candidateNeighbor, s.neighbor) : 0;\n score += out.neighbor * 20;\n }\n\n if (totalWeight === 0) return null;\n out.blend = score / totalWeight;\n out.strongest = Math.max(out.text ?? 0, out.fingerprint ?? 0, out.context ?? 0, out.neighbor ?? 0);\n return out;\n}\n\n/**\n * Ancestor-decoy tie-break: a wrapper's text contains its child's text, so it\n * scores nearly as well — but anchoring to the wrapper corrupts the\n * percentage-based rect. Among candidates within AMBIGUITY_EPSILON of the\n * best that sit on the best's own descendant chain, prefer the innermost.\n * Unrelated near-ties keep the plain argmax (strategy priors already encode\n * the preference order there).\n */\nfunction disambiguate(sortedAccepted: ScoredCandidate[]): ScoredCandidate {\n const best = sortedAccepted[0] as ScoredCandidate; // non-empty by caller contract\n const contenders = sortedAccepted.filter(\n (c) => best.final - c.final <= AMBIGUITY_EPSILON && (c === best || best.element.contains(c.element)),\n );\n // Innermost = contained by every other contender that contains anything\n let winner = best;\n for (const c of contenders) {\n if (c !== winner && winner.element.contains(c.element)) winner = c;\n }\n return winner;\n}\n\nfunction confidenceOf(c: ScoredCandidate): number {\n if (c.strategy === \"scan\") {\n // v1 semantics: the scan's confidence IS its verification, hard-capped —\n // a scan is never fully certain.\n return Math.min(c.verification, STRATEGY_PRIORS.scan);\n }\n // Nothing was verifiable → the selector is all the evidence there is;\n // v1 semantics: trust it at full prior rather than inventing doubt.\n if (c.unverified) return STRATEGY_PRIORS[c.strategy];\n // Confidence follows the STRONGEST corroborating signal, not the blend:\n // `<h2 id=\"pricing\">Pricing</h2>` moved into a new wrapper still carries an\n // exact text match — the drifted fingerprint/neighbors around it must not\n // dash-flag a perfectly anchored marker. Absence of a signal stays neutral;\n // a present-but-refuted one still drags `strongest` down when it is all\n // there is. Full prior at STRONG_VERIFY keeps v1's exact values.\n return STRATEGY_PRIORS[c.strategy] * Math.min(1, c.strongest / STRONG_VERIFY);\n}\n\n/**\n * Resolve an annotation's position on the page.\n * Converts stored percentage-based rect back to absolute coordinates\n * using the current bounding box of the resolved anchor element.\n */\nexport function resolveAnnotation(\n anchor: AnchorData,\n rect: RectData,\n options?: ResolveOptions,\n): ResolvedAnnotation | null {\n const resolution = resolveAnchor(anchor, options);\n\n if (!resolution) return null;\n\n const bounds = resolution.element.getBoundingClientRect();\n const absoluteRect = new DOMRect(\n bounds.x + rect.xPct * bounds.width,\n bounds.y + rect.yPct * bounds.height,\n rect.wPct * bounds.width,\n rect.hPct * bounds.height,\n );\n\n return {\n element: resolution.element,\n rect: absoluteRect,\n confidence: resolution.confidence,\n strategy: resolution.strategy,\n };\n}\n","import { type AnchorData, type FeedbackResponse, isClosedStatus, type RectData } from \"@siteping/core\";\nimport { Z_INDEX_MAX } from \"./constants.js\";\nimport { resolveAnnotation } from \"./dom/resolver.js\";\nimport { classifyVisibility } from \"./dom/visibility.js\";\nimport { el, setText } from \"./dom-utils.js\";\nimport type { EventBus, WidgetEvents } from \"./events.js\";\nimport { isolateFromHost } from \"./host-isolation.js\";\nimport { getTypeLabel, type TFunction, tWithParams } from \"./i18n/index.js\";\nimport { getTypeColor, type ThemeColors } from \"./styles/theme.js\";\nimport type { Tooltip } from \"./tooltip.js\";\nimport { isCoarsePointer, isCompactViewport } from \"./viewport.js\";\n\ntype Annotation = FeedbackResponse[\"annotations\"][number];\n\nfunction toAnchorData(a: Annotation): AnchorData {\n return {\n cssSelector: a.cssSelector,\n xpath: a.xpath,\n textSnippet: a.textSnippet,\n elementTag: a.elementTag,\n elementId: a.elementId ?? undefined,\n textPrefix: a.textPrefix,\n textSuffix: a.textSuffix,\n fingerprint: a.fingerprint,\n neighborText: a.neighborText,\n anchorKey: a.anchorKey ?? null,\n };\n}\n\nfunction toRectData(a: Annotation): RectData {\n return { xPct: a.xPct, yPct: a.yPct, wPct: a.wPct, hPct: a.hPct };\n}\n\n/** Half of the 26px marker diameter — used for centering on anchor corner. */\nconst MARKER_OFFSET = 13;\n\ninterface MarkerPos {\n top: number;\n left: number;\n}\n\n/** Convert a resolved rect to document-absolute marker position. */\nfunction markerPosition(rect: DOMRect): MarkerPos {\n return {\n top: rect.top + window.scrollY - MARKER_OFFSET,\n left: rect.right + window.scrollX - MARKER_OFFSET,\n };\n}\n\ninterface MarkerEntry {\n feedback: FeedbackResponse;\n /**\n * One marker per annotation, index-aligned with `feedback.annotations` —\n * hidden (display:none) while its anchor doesn't resolve, so an anchor that\n * appears later (SPA, lazy content) gets its marker on the next reposition.\n */\n elements: HTMLElement[];\n /** Document position of each marker (same index) — annotations can be far apart. */\n positions: MarkerPos[];\n}\n\ninterface Cluster {\n entries: MarkerEntry[];\n elementIndices: number[];\n expanded: boolean;\n}\n\n/** Get the i-th marker element from a cluster. */\nfunction clusterMarker(cluster: Cluster, i: number): HTMLElement | undefined {\n const entry = cluster.entries[i];\n const elIdx = cluster.elementIndices[i];\n if (!entry || elIdx === undefined) return undefined;\n return entry.elements[elIdx];\n}\n\n/** Position of a cluster's first marker — the anchor point for stack/fan layout. */\nfunction clusterBase(cluster: Cluster): MarkerPos | undefined {\n const elIdx = cluster.elementIndices[0];\n return elIdx === undefined ? undefined : cluster.entries[0]?.positions[elIdx];\n}\n\nconst HIGHLIGHT_FADE = 300;\nconst REPOSITION_DEBOUNCE = 200;\n/** Back-off between full re-resolutions of an anchor that resolved hidden or\n * orphaned, on mutation ticks (resize bypasses it — see hiddenRecheckAt). */\nconst HIDDEN_RECHECK_MS = 3000;\nconst LOW_CONFIDENCE_THRESHOLD = 0.7;\nconst CLUSTER_DISTANCE = 28;\nconst FAN_SPACING = 32;\n\n/**\n * Numbered markers on the page for each feedback annotation.\n *\n * Cluster system: click-to-expand (same pattern as Google Maps / Spiderfier).\n * Hover is only used for tooltip/scale on individual markers — never for expansion.\n */\nexport class MarkerManager {\n private container: HTMLElement;\n private entries: MarkerEntry[] = [];\n private highlightElements: HTMLElement[] = [];\n private pinnedFeedback: FeedbackResponse | null = null;\n private onDocumentClick: ((e: MouseEvent) => void) | null = null;\n private repositionTimer: number | null = null;\n private mutationObserver: MutationObserver | null = null;\n private scrollHandler: (() => void) | null = null;\n private resizeHandler: (() => void) | null = null;\n private anchorCache = new Map<string, WeakRef<Element>>();\n /** Whether a resize/mutation happened since the last reposition pass —\n * the only triggers that can flip an anchor's visibility (responsive\n * breakpoint, SPA re-render). Pure scroll ticks keep the fast path. */\n private pendingLayoutChange = false;\n /** Resize specifically — the breakpoint-flip event: it bypasses the\n * hidden-anchor re-resolution throttle below. */\n private pendingResize = false;\n /** Per-annotation back-off after a resolution concluded \"hidden\" or\n * \"orphaned\": mutation ticks recur every ~200ms on busy SPAs, and\n * re-resolving an annotation in a collapsed accordion each tick is\n * provably-redundant sweep work. Resize clears the back-off. */\n private hiddenRecheckAt = new Map<string, number>();\n private clusters: Cluster[] = [];\n private onDocumentClickForClusters: ((e: MouseEvent) => void) | null = null;\n /** Last `openCount` broadcast via `markers:changed` (-1 = never emitted). */\n private lastOpenCount = -1;\n\n get count(): number {\n return this.entries.length;\n }\n\n get openCount(): number {\n let count = 0;\n for (const entry of this.entries) {\n // Anything not closed (open, in_progress) still needs attention.\n if (!isClosedStatus(entry.feedback.status)) count++;\n }\n return count;\n }\n\n constructor(\n private readonly colors: ThemeColors,\n private readonly tooltip: Tooltip,\n private readonly bus: EventBus<WidgetEvents>,\n private readonly t: TFunction,\n private readonly liveRegion: HTMLElement | null = null,\n ) {\n this.container = el(\"div\", {\n style: `position:absolute;top:0;left:0;pointer-events:none;z-index:${Z_INDEX_MAX - 1};`,\n });\n this.container.id = \"siteping-markers\";\n isolateFromHost(this.container);\n document.body.appendChild(this.container);\n\n this.bus.on(\"annotations:toggle\", (visible) => {\n this.container.style.display = visible ? \"block\" : \"none\";\n });\n\n this.resizeHandler = () => this.scheduleReposition(\"resize\");\n window.addEventListener(\"resize\", this.resizeHandler, { passive: true });\n\n this.scrollHandler = () => this.scheduleReposition(\"scroll\");\n window.addEventListener(\"scroll\", this.scrollHandler, { passive: true, capture: true });\n\n // Re-resolve after DOM changes (SPA, lazy-load).\n // Filter out widget-owned mutations and skip batches with only irrelevant\n // changes. Filtering short-circuits at the first non-widget mutation, so\n // even large batches stop after one DOM walk.\n //\n // The filter is applied unconditionally — earlier versions had a >20-batch\n // fast-path that skipped filtering, but that lets reposition self-trigger\n // when `repositionAll` re-renders the pinned highlight (showHighlight\n // appends N elements to `this.container`); a host page churning lots of\n // DOM (infinite scroll) would then loop at the 200ms debounce interval.\n this.mutationObserver = new MutationObserver((mutations) => {\n let hasRelevantMutation = false;\n for (const m of mutations) {\n if (this.container.contains(m.target) || this.tooltip.contains(m.target)) continue;\n hasRelevantMutation = true;\n break;\n }\n if (hasRelevantMutation) this.scheduleReposition(\"mutation\");\n });\n this.mutationObserver.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: false,\n characterData: false,\n });\n\n // Capture phase: the widget's other surfaces (FAB, panel, popup) stop\n // `click` from bubbling to the document, and must still collapse clusters.\n this.onDocumentClickForClusters = (e: MouseEvent) => {\n if (this.container.contains(e.target as Node)) return;\n this.collapseAllClusters();\n };\n document.addEventListener(\"click\", this.onDocumentClickForClusters, true);\n }\n\n private scheduleReposition(cause: \"scroll\" | \"mutation\" | \"resize\" = \"mutation\"): void {\n // Record the cause even when a tick is already pending — the pending\n // pass must honor the strongest cause seen since it was scheduled.\n if (cause !== \"scroll\") this.pendingLayoutChange = true;\n if (cause === \"resize\") this.pendingResize = true;\n if (this.repositionTimer) return;\n if (\"requestIdleCallback\" in window) {\n this.repositionTimer = window.requestIdleCallback(\n () => {\n this.repositionTimer = null;\n this.repositionAll();\n },\n { timeout: REPOSITION_DEBOUNCE + 100 },\n );\n } else {\n this.repositionTimer = +setTimeout(() => {\n this.repositionTimer = null;\n this.repositionAll();\n }, REPOSITION_DEBOUNCE);\n }\n }\n\n private repositionAll(): void {\n // Only resize/mutation ticks re-check cached anchors' visibility: a\n // responsive breakpoint flip can leave the cached element display:none\n // while its twin became the rendered copy (#171) — but re-checking on\n // every scroll tick would turn a legitimately-hidden anchor (collapsed\n // accordion) into a full re-resolution per scroll event.\n const recheckVisibility = this.pendingLayoutChange;\n const resizeTick = this.pendingResize;\n this.pendingLayoutChange = false;\n this.pendingResize = false;\n // A resize is the responsive breakpoint flip — every hidden-anchor\n // back-off is void, the visible twin may exist right now.\n if (resizeTick) this.hiddenRecheckAt.clear();\n const now = Date.now();\n\n // Reposition ticks recur every ~200ms on mutation-heavy pages; several\n // drifted/hidden anchors must not each pay a full tag sweep per tick.\n // Budget-starved annotations simply retry on the next natural tick.\n const scanBudget = { remaining: 2, starved: false };\n\n // Build set of valid keys to prune stale cache entries afterwards.\n const validKeys = new Set<string>();\n // A marker appearing or disappearing changes which markers cluster.\n let visibilityChanged = false;\n\n for (const entry of this.entries) {\n for (let i = 0; i < entry.feedback.annotations.length; i++) {\n const markerEl = entry.elements[i];\n if (!markerEl) continue;\n\n const annotation = entry.feedback.annotations[i];\n if (!annotation) continue;\n const cacheKey = `${entry.feedback.id}:${i}`;\n validKeys.add(cacheKey);\n\n // Try cached element first to avoid full resolution chain.\n const cachedRef = this.anchorCache.get(cacheKey);\n const cachedEl = cachedRef?.deref();\n let resolved: ReturnType<typeof resolveAnnotation>;\n\n const backedOff = (this.hiddenRecheckAt.get(cacheKey) ?? 0) > now;\n const cacheUsable =\n cachedEl?.isConnected && (backedOff || !(recheckVisibility && classifyVisibility(cachedEl) === \"hidden\"));\n\n if (cachedEl && cacheUsable) {\n const anchorRect = cachedEl.getBoundingClientRect();\n const r = toRectData(annotation);\n resolved = {\n element: cachedEl,\n rect: new DOMRect(\n anchorRect.left + r.xPct * anchorRect.width,\n anchorRect.top + r.yPct * anchorRect.height,\n r.wPct * anchorRect.width,\n r.hPct * anchorRect.height,\n ),\n confidence: 1,\n strategy: \"css\",\n };\n } else if (backedOff) {\n // A recent full resolution concluded hidden/orphaned and the anchor\n // is gone from the cache — don't burn another sweep this tick.\n resolved = null;\n } else {\n scanBudget.starved = false;\n resolved = resolveAnnotation(toAnchorData(annotation), toRectData(annotation), { scanBudget });\n if (scanBudget.starved) {\n // Selector-only answer under an exhausted budget — may be worse\n // than what the sweep would find; never cache it, retry next tick.\n } else {\n if (resolved?.element) {\n this.anchorCache.set(cacheKey, new WeakRef(resolved.element));\n }\n if (!resolved || classifyVisibility(resolved.element) === \"hidden\") {\n this.hiddenRecheckAt.set(cacheKey, now + HIDDEN_RECHECK_MS);\n } else {\n this.hiddenRecheckAt.delete(cacheKey);\n }\n }\n }\n\n const wasVisible = markerEl.style.display !== \"none\";\n if (!resolved) {\n if (wasVisible) visibilityChanged = true;\n markerEl.style.display = \"none\";\n continue;\n }\n\n if (!wasVisible) visibilityChanged = true;\n entry.positions[i] = markerPosition(resolved.rect);\n markerEl.style.display = \"flex\";\n this.applyConfidenceStyle(markerEl, resolved.confidence, entry.feedback);\n }\n }\n\n // Prune cache keys from deleted feedbacks to prevent memory leak.\n for (const key of this.anchorCache.keys()) {\n if (!validKeys.has(key)) this.anchorCache.delete(key);\n }\n for (const key of this.hiddenRecheckAt.keys()) {\n if (!validKeys.has(key)) this.hiddenRecheckAt.delete(key);\n }\n\n if (visibilityChanged) this.buildClusters();\n this.applyClusterPositions();\n\n // Re-render the pinned highlight rectangle so it tracks the layout after\n // resize / SPA mutation. Marker dots reposition above; without this,\n // the highlight rect keeps its old pixel position and visibly drifts\n // away from the underlying content.\n if (this.pinnedFeedback) {\n this.showHighlight(this.pinnedFeedback);\n }\n }\n\n private applyClusterPositions(): void {\n for (const cluster of this.clusters) {\n if (cluster.expanded) {\n this.applyFanPositions(cluster);\n } else {\n this.applyStackPositions(cluster);\n }\n }\n }\n\n /**\n * Emit `markers:changed` only when the open count actually moved.\n *\n * Mutations that re-render the same set (panel search keystrokes, filter\n * toggles, \"load more\") all call `render()` without changing the page's\n * open count — emitting unconditionally would rebuild the FAB badge DOM on\n * every keystroke. The `-1` sentinel guarantees the first render still\n * emits, even when the page has zero open feedbacks.\n */\n private emitMarkersChanged(): void {\n const openCount = this.openCount;\n if (openCount === this.lastOpenCount) return;\n this.lastOpenCount = openCount;\n this.bus.emit(\"markers:changed\", openCount);\n }\n\n render(feedbacks: FeedbackResponse[]): void {\n this.clear();\n feedbacks.forEach((feedback, i) => {\n const entry = this.buildEntry(feedback, i + 1);\n this.entries.push(entry);\n });\n this.buildClusters();\n // Announce the number of visible markers to assistive tech (WCAG 4.1.3).\n // Skip the announcement when the host page has not provided a live\n // region (tests, embedded use cases) and when no marker is visible to\n // avoid noisy \"0 markers\" updates on every navigation.\n if (this.liveRegion && this.entries.length > 0) {\n this.liveRegion.textContent = tWithParams(this.t, \"marker.count\", { count: this.entries.length });\n }\n this.emitMarkersChanged();\n }\n\n addFeedback(feedback: FeedbackResponse, index: number): void {\n const entry = this.buildEntry(feedback, index);\n for (const m of entry.elements) {\n m.style.animation = \"sp-marker-in 0.35s cubic-bezier(0.34,1.56,0.64,1) both\";\n }\n this.entries.push(entry);\n this.buildClusters();\n this.emitMarkersChanged();\n }\n\n private buildEntry(feedback: FeedbackResponse, index: number): MarkerEntry {\n const entry: MarkerEntry = { feedback, elements: [], positions: [] };\n for (const annotation of feedback.annotations) {\n const resolved = resolveAnnotation(toAnchorData(annotation), toRectData(annotation));\n const pos = resolved ? markerPosition(resolved.rect) : { top: 0, left: 0 };\n const marker = this.createMarker(index, feedback, pos);\n if (resolved) this.applyConfidenceStyle(marker, resolved.confidence, feedback);\n else marker.style.display = \"none\";\n this.container.appendChild(marker);\n entry.elements.push(marker);\n entry.positions.push(pos);\n }\n return entry;\n }\n\n private buildClusters(): void {\n for (const badge of this.container.querySelectorAll<HTMLElement>(\".sp-cluster-badge\")) {\n badge.remove();\n }\n\n // Hidden (unresolved) markers have no meaningful position — skip them.\n const allItems: { entry: MarkerEntry; elIdx: number; pos: MarkerPos }[] = [];\n for (const entry of this.entries) {\n for (let i = 0; i < entry.elements.length; i++) {\n const pos = entry.positions[i];\n if (!pos || entry.elements[i]?.style.display === \"none\") continue;\n allItems.push({ entry, elIdx: i, pos });\n }\n }\n\n const used = new Set<number>();\n this.clusters = [];\n\n for (let i = 0; i < allItems.length; i++) {\n if (used.has(i)) continue;\n const itemI = allItems[i];\n if (!itemI) continue;\n const cluster: Cluster = {\n entries: [itemI.entry],\n elementIndices: [itemI.elIdx],\n expanded: false,\n };\n used.add(i);\n\n for (let j = i + 1; j < allItems.length; j++) {\n if (used.has(j)) continue;\n const a = itemI.pos;\n const itemJ = allItems[j];\n if (!itemJ) continue;\n const b = itemJ.pos;\n const dist = Math.sqrt((a.left - b.left) ** 2 + (a.top - b.top) ** 2);\n if (dist < CLUSTER_DISTANCE) {\n cluster.entries.push(itemJ.entry);\n cluster.elementIndices.push(itemJ.elIdx);\n used.add(j);\n }\n }\n\n this.clusters.push(cluster);\n }\n\n for (const cluster of this.clusters) {\n if (cluster.entries.length <= 1) continue;\n this.applyStackPositions(cluster);\n this.addClusterBadge(cluster);\n }\n }\n\n private applyStackPositions(cluster: Cluster): void {\n const base = clusterBase(cluster);\n if (!base) return;\n const { top: baseTop, left: baseLeft } = base;\n const isSolo = cluster.entries.length <= 1;\n for (let i = 0; i < cluster.entries.length; i++) {\n const m = clusterMarker(cluster, i);\n if (!m) continue;\n m.style.top = `${baseTop + (isSolo ? 0 : i * 3)}px`;\n m.style.left = `${baseLeft + (isSolo ? 0 : i * 3)}px`;\n m.style.zIndex = String(i + 1);\n }\n }\n\n private applyFanPositions(cluster: Cluster): void {\n const base = clusterBase(cluster);\n if (!base) return;\n const { top: baseTop, left: baseLeft } = base;\n const count = cluster.entries.length;\n const totalWidth = (count - 1) * FAN_SPACING;\n const startLeft = baseLeft - totalWidth / 2;\n\n for (let i = 0; i < count; i++) {\n const m = clusterMarker(cluster, i);\n if (!m) continue;\n m.style.top = `${baseTop}px`;\n m.style.left = `${startLeft + i * FAN_SPACING}px`;\n m.style.zIndex = String(10 + i);\n }\n }\n\n private addClusterBadge(cluster: Cluster): void {\n const topMarker = clusterMarker(cluster, cluster.entries.length - 1);\n if (!topMarker) return;\n const badge = el(\"div\", {\n class: \"sp-cluster-badge\",\n style: /* css */ `position:absolute;top:-6px;right:-6px;min-width:16px;height:16px;padding:0 4px;border-radius:9999px;background:${this.colors.accent};color:#fff;font-size:10px;font-weight:700;display:flex;align-items:center;justify-content:center;border:1.5px solid #fff;pointer-events:none;font-family:\"Inter\",system-ui,-apple-system,sans-serif;line-height:1;`\n\n\n\n\n\n\n\n\n\n\n,\n });\n setText(badge, String(cluster.entries.length));\n topMarker.appendChild(badge);\n }\n\n private setBadgesVisible(cluster: Cluster, visible: boolean): void {\n for (let i = 0; i < cluster.entries.length; i++) {\n const badge = clusterMarker(cluster, i)?.querySelector(\".sp-cluster-badge\") as HTMLElement | null;\n if (badge) badge.style.display = visible ? \"flex\" : \"none\";\n }\n }\n\n private findCluster(marker: HTMLElement): Cluster | null {\n for (const cluster of this.clusters) {\n if (cluster.entries.length <= 1) continue;\n for (let i = 0; i < cluster.entries.length; i++) {\n if (clusterMarker(cluster, i) === marker) return cluster;\n }\n }\n return null;\n }\n\n private handleClusterClick(marker: HTMLElement, e: MouseEvent): boolean {\n const cluster = this.findCluster(marker);\n if (!cluster) return false;\n if (!cluster.expanded) {\n e.stopPropagation();\n this.collapseAllClusters();\n cluster.expanded = true;\n this.applyFanPositions(cluster);\n this.setBadgesVisible(cluster, false);\n return true;\n }\n return false;\n }\n\n private collapseCluster(cluster: Cluster): void {\n if (!cluster.expanded) return;\n cluster.expanded = false;\n this.applyStackPositions(cluster);\n this.setBadgesVisible(cluster, true);\n }\n\n private collapseAllClusters(): void {\n for (const cluster of this.clusters) {\n this.collapseCluster(cluster);\n }\n }\n\n private applyConfidenceStyle(marker: HTMLElement, confidence: number, feedback: FeedbackResponse): void {\n const isResolved = isClosedStatus(feedback.status);\n if (confidence < LOW_CONFIDENCE_THRESHOLD && !isResolved) {\n marker.style.borderStyle = \"dashed\";\n marker.style.opacity = \"0.7\";\n marker.title = tWithParams(this.t, \"marker.approximate\", { confidence: Math.round(confidence * 100) });\n } else {\n marker.style.borderStyle = \"solid\";\n marker.style.opacity = \"1\";\n marker.title = \"\";\n }\n }\n\n private createMarker(number: number, feedback: FeedbackResponse, pos: { top: number; left: number }): HTMLElement {\n const typeColor = getTypeColor(feedback.type, this.colors);\n // Closed feedbacks (resolved, wont_fix) render as muted checkmark markers.\n const isResolved = isClosedStatus(feedback.status);\n\n const marker = el(\"div\", {\n style: /* css */ `position:absolute;top:${pos.top}px;left:${pos.left}px;width:26px;height:26px;border-radius:50%;background:${isResolved ? \"rgba(241,245,249,0.9)\" : \"rgba(255,255,255,0.92)\"};border:2px solid ${isResolved ? \"#cbd5e1\" : typeColor};display:flex;align-items:center;justify-content:center;font-family:\"Inter\",system-ui,-apple-system,sans-serif;font-size:11px;font-weight:700;color:${isResolved ? \"#94a3b8\" : typeColor};cursor:pointer;pointer-events:auto;box-shadow:${isResolved ? \"0 2px 8px rgba(0,0,0,0.06)\" : `0 2px 12px ${typeColor}25, 0 2px 6px rgba(0,0,0,0.06)`};transition:top 0.25s cubic-bezier(0.34,1.56,0.64,1),left 0.25s cubic-bezier(0.34,1.56,0.64,1),transform 0.15s ease,box-shadow 0.15s ease;user-select:none;-webkit-font-smoothing:antialiased;`\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n,\n });\n marker.dataset.feedbackId = feedback.id;\n marker.setAttribute(\"tabindex\", \"0\");\n marker.setAttribute(\"role\", \"button\");\n const truncatedMessage = feedback.message.length > 60 ? `${feedback.message.slice(0, 60)}...` : feedback.message;\n const ariaLabel = tWithParams(this.t, \"marker.aria\", {\n number,\n type: getTypeLabel(feedback.type, this.t),\n message: truncatedMessage,\n });\n marker.setAttribute(\"aria-label\", ariaLabel);\n marker.setAttribute(\"aria-describedby\", this.tooltip.tooltipId);\n setText(marker, isResolved ? \"\\u2713\" : String(number));\n // Fingers need ~44px: widen the hit area, not the 26px pin.\n if (isCoarsePointer()) marker.appendChild(el(\"span\", { style: \"position:absolute;inset:-9px;border-radius:50%;\" }));\n\n marker.addEventListener(\"mouseenter\", () => {\n marker.style.transform = \"scale(1.2)\";\n marker.style.boxShadow = isResolved\n ? \"0 4px 16px rgba(0,0,0,0.1)\"\n : `0 4px 20px ${typeColor}35, 0 4px 12px rgba(0,0,0,0.08)`;\n this.tooltip.show(feedback, marker.getBoundingClientRect());\n if (!this.pinnedFeedback) this.showHighlight(feedback);\n });\n\n marker.addEventListener(\"mouseleave\", () => {\n marker.style.transform = \"scale(1)\";\n marker.style.boxShadow = isResolved\n ? \"0 2px 8px rgba(0,0,0,0.06)\"\n : `0 2px 12px ${typeColor}25, 0 2px 6px rgba(0,0,0,0.06)`;\n this.tooltip.scheduleHide();\n if (!this.pinnedFeedback) this.clearHighlight();\n });\n\n // WCAG 1.4.13 — tooltip must be reachable via keyboard (focus), not only\n // hover. Mirror mouseenter/mouseleave behaviour for focus/blur so a sighted\n // keyboard user gets the same affordance as a mouse user.\n marker.addEventListener(\"focus\", () => {\n this.tooltip.show(feedback, marker.getBoundingClientRect());\n if (!this.pinnedFeedback) this.showHighlight(feedback);\n });\n\n marker.addEventListener(\"blur\", () => {\n this.tooltip.scheduleHide();\n if (!this.pinnedFeedback) this.clearHighlight();\n });\n\n const activateMarker = (e: MouseEvent | KeyboardEvent) => {\n if (e instanceof MouseEvent && this.handleClusterClick(marker, e)) return;\n // Phones: the panel sheet is about to cover the page — a tap's\n // tooltip would be left floating on top of it.\n if (isCompactViewport()) this.tooltip.hide();\n this.pinHighlight(feedback);\n this.bus.emit(\"panel:toggle\", true);\n marker.dispatchEvent(\n new CustomEvent(\"sp-marker-click\", {\n detail: { feedbackId: feedback.id },\n bubbles: true,\n }),\n );\n };\n\n marker.addEventListener(\"click\", (e) => activateMarker(e));\n marker.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n activateMarker(e);\n }\n });\n\n return marker;\n }\n\n /**\n * Scroll the annotation into view, pin its highlight, and pulse its marker.\n *\n * Powers the `deepLink` config option and the public\n * `instance.focusFeedback(id)` method. Returns `false` when no entry\n * matches — caller logs that case, the manager stays silent.\n *\n * Scrolling uses the marker element's current document position via\n * `scrollIntoView`, not the original `scrollX/scrollY` captured at\n * annotation time. That keeps the focus correct after layout changes\n * (responsive breakpoints, lazy-loaded content) because the marker has\n * already been re-positioned to track the live anchor.\n */\n focusFeedback(feedbackId: string): boolean {\n const entry = this.entries.find((e) => e.feedback.id === feedbackId);\n if (!entry) return false;\n const markerEl = entry.elements.find((m) => m.style.display !== \"none\");\n if (markerEl) {\n markerEl.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n }\n this.pinHighlight(entry.feedback);\n this.highlight(feedbackId);\n return true;\n }\n\n /**\n * `focusFeedback`, but only when the feedback has a pin on screen. Returns\n * false (and does nothing) when its anchor no longer resolves (every pin is\n * display:none) or the markers are hidden with the eye toggle: a pin with\n * no box cannot be scrolled to, so the caller falls back to the stored\n * scroll offsets.\n */\n revealPin(feedbackId: string): boolean {\n return (\n this.container.style.display !== \"none\" &&\n this.entries.some((e) => e.feedback.id === feedbackId && e.elements.some((m) => m.style.display !== \"none\")) &&\n this.focusFeedback(feedbackId)\n );\n }\n\n highlight(feedbackId: string): void {\n for (const entry of this.entries) {\n if (entry.feedback.id === feedbackId) {\n for (const markerEl of entry.elements) {\n markerEl.style.animation = \"sp-pulse-ring 0.7s ease-out\";\n markerEl.addEventListener(\n \"animationend\",\n () => {\n markerEl.style.animation = \"\";\n },\n { once: true },\n );\n }\n }\n }\n }\n\n showHighlight(feedback: FeedbackResponse): void {\n this.removeHighlightElements();\n for (const annotation of feedback.annotations) {\n const resolved = resolveAnnotation(toAnchorData(annotation), toRectData(annotation));\n if (!resolved) continue;\n\n const typeColor = getTypeColor(feedback.type, this.colors);\n const rect = resolved.rect;\n const highlight = el(\"div\", {\n style: /* css */ `position:absolute;top:${rect.top + window.scrollY}px;left:${rect.left + window.scrollX}px;width:${rect.width}px;height:${rect.height}px;border:2px solid ${typeColor};background:${typeColor}0c;border-radius:8px;pointer-events:none;z-index:-1;opacity:0;box-shadow:0 0 16px ${typeColor}20;transition:opacity ${HIGHLIGHT_FADE}ms ease;`\n\n\n\n\n\n\n\n\n\n\n\n,\n });\n this.container.appendChild(highlight);\n this.highlightElements.push(highlight);\n void highlight.offsetHeight; // Force reflow for CSS transition\n highlight.style.opacity = \"1\";\n }\n }\n\n pinHighlight(feedback: FeedbackResponse): void {\n this.unpinHighlight();\n this.showHighlight(feedback);\n this.pinnedFeedback = feedback;\n this.onDocumentClick = (e: MouseEvent) => {\n if (this.container.contains(e.target as Node)) return;\n this.unpinHighlight();\n };\n document.addEventListener(\"click\", this.onDocumentClick, { capture: true });\n }\n\n private unpinHighlight(): void {\n if (this.onDocumentClick) {\n document.removeEventListener(\"click\", this.onDocumentClick, { capture: true });\n this.onDocumentClick = null;\n }\n this.pinnedFeedback = null;\n this.clearHighlight();\n }\n\n private clearHighlight(): void {\n for (const h of this.highlightElements) {\n h.style.opacity = \"0\";\n setTimeout(() => h.remove(), HIGHLIGHT_FADE);\n }\n this.highlightElements = [];\n }\n\n private removeHighlightElements(): void {\n for (const h of this.highlightElements) h.remove();\n this.highlightElements = [];\n }\n\n clear(): void {\n this.unpinHighlight();\n this.container.replaceChildren();\n this.entries = [];\n this.clusters = [];\n this.anchorCache.clear();\n }\n\n destroy(): void {\n this.unpinHighlight();\n if (this.repositionTimer) {\n if (\"cancelIdleCallback\" in window) {\n window.cancelIdleCallback(this.repositionTimer);\n }\n clearTimeout(this.repositionTimer);\n }\n if (this.resizeHandler) window.removeEventListener(\"resize\", this.resizeHandler);\n if (this.scrollHandler) window.removeEventListener(\"scroll\", this.scrollHandler, { capture: true });\n if (this.onDocumentClickForClusters) document.removeEventListener(\"click\", this.onDocumentClickForClusters, true);\n this.mutationObserver?.disconnect();\n this.container.remove();\n }\n}\n","import {\n type AnnotationRecord,\n type AnnotationResponse,\n type CommentCreateInput,\n type CommentRecord,\n type CommentResponse,\n type FeedbackPayload,\n type FeedbackRecord,\n type FeedbackResponse,\n type FeedbackResponseList,\n flattenAnnotation,\n isStoreDuplicate,\n SitepingError,\n type SitepingStore,\n toFeedbackUpdate,\n} from \"@siteping/core\";\nimport { type GetFeedbacksOptions, type WidgetClient, withTimeout } from \"./api-client.js\";\n\n/**\n * How long a send waits on `store.createFeedback` (or a reply on\n * `store.addComment`). First-party stores settle at once, but a custom store\n * may be network-backed, and the popup holds the user until the send settles.\n */\nconst STORE_WRITE_TIMEOUT_MS = 30_000;\n\n/**\n * `WidgetClient` implementation that delegates directly to a `SitepingStore`.\n *\n * Used in client-side mode — the widget calls the store in-process instead of\n * making HTTP requests. Handles the same conversions the HTTP handler normally\n * performs: flattening annotations and serializing dates.\n */\nexport class StoreClient implements WidgetClient {\n constructor(\n private readonly store: SitepingStore,\n private readonly projectName: string,\n ) {}\n\n /**\n * `SitepingStore` takes no AbortSignal, so a write that outlives the bound\n * is abandoned, not cancelled: it may still land after the popup restored.\n * Writes are not serialized (a chain would never unblock after one that\n * never settles); a resend from the same popup carries the same clientId,\n * so the store keeps a single record whichever duplicate contract it\n * follows (see `write`).\n */\n async sendFeedback(payload: FeedbackPayload): Promise<FeedbackResponse> {\n return toResponse(await bounded(this.write(payload), \"Failed to send feedback\"));\n }\n\n /**\n * `createFeedback`, resolving a duplicate clientId like the HTTP handler: a\n * store may throw `StoreDuplicateError` instead of returning the existing\n * record, and the popup's earlier attempt (one that timed out, then landed)\n * is then the feedback being resent.\n */\n private async write(payload: FeedbackPayload): Promise<FeedbackRecord> {\n try {\n return await this.store.createFeedback({\n projectName: payload.projectName,\n type: payload.type,\n message: payload.message,\n status: \"open\",\n url: payload.url,\n urlPattern: payload.urlPattern ?? null,\n viewport: payload.viewport,\n userAgent: payload.userAgent,\n authorName: payload.authorName,\n authorEmail: payload.authorEmail,\n clientId: payload.clientId,\n annotations: payload.annotations.map(flattenAnnotation),\n screenshotDataUrl: payload.screenshotDataUrl ?? null,\n screenshotRegion: payload.screenshotRegion ?? null,\n diagnostics: payload.diagnostics ?? null,\n });\n } catch (error) {\n if (!isStoreDuplicate(error)) throw error;\n const existing = await this.store.findByClientId(payload.clientId);\n if (!existing || existing.projectName !== payload.projectName) throw error;\n return existing;\n }\n }\n\n async getFeedbacks(projectName: string, options?: GetFeedbacksOptions): Promise<FeedbackResponseList> {\n const { feedbacks, total } = await this.store.getFeedbacks({\n projectName,\n page: options?.page,\n limit: options?.limit,\n type: options?.type,\n status: options?.status,\n statuses: options?.statuses,\n search: options?.search,\n url: options?.url,\n urlPattern: options?.urlPattern,\n });\n\n return { feedbacks: feedbacks.map(toResponse), total, capabilities: { comments: !!this.store.addComment } };\n }\n\n async resolveFeedback(id: string, resolved: boolean): Promise<FeedbackResponse> {\n const record = await this.store.updateFeedback(id, toFeedbackUpdate(resolved ? \"resolved\" : \"open\"));\n return toResponse(record);\n }\n\n async deleteFeedback(id: string): Promise<void> {\n await this.store.deleteFeedback(id);\n }\n\n async deleteAllFeedbacks(projectName: string): Promise<void> {\n await this.store.deleteAllFeedbacks(projectName);\n }\n\n /** The panel only offers a reply when `getFeedbacks` advertised comments, i.e. the store implements `addComment`. */\n async addComment(feedbackId: string, input: CommentCreateInput): Promise<CommentResponse> {\n const label = \"Failed to post comment\";\n if (!this.store.addComment) throw new SitepingError(`${label}: this store keeps no comments`, \"SERVER\", false);\n return toCommentResponse(await bounded(this.store.addComment(feedbackId, input), label));\n }\n}\n\n/** Settle like `write`, or fail as a retryable `TIMEOUT` once the store has kept the user waiting too long. */\nfunction bounded<T>(write: Promise<T>, label: string): Promise<T> {\n return withTimeout(\n write,\n STORE_WRITE_TIMEOUT_MS,\n () =>\n new SitepingError(\n `${label}: the store did not answer within ${STORE_WRITE_TIMEOUT_MS / 1000} s`,\n \"TIMEOUT\",\n true,\n ),\n );\n}\n\n// ---------------------------------------------------------------------------\n// FeedbackRecord (Date) → FeedbackResponse (string) serialization\n// ---------------------------------------------------------------------------\n\nfunction toResponse(record: FeedbackRecord): FeedbackResponse {\n return {\n id: record.id,\n projectName: record.projectName,\n type: record.type,\n message: record.message,\n status: record.status,\n url: record.url,\n urlPattern: record.urlPattern ?? null,\n viewport: record.viewport,\n userAgent: record.userAgent,\n authorName: record.authorName,\n authorEmail: record.authorEmail,\n resolvedAt: record.resolvedAt?.toISOString() ?? null,\n createdAt: record.createdAt.toISOString(),\n updatedAt: record.updatedAt.toISOString(),\n annotations: record.annotations.map(toAnnotationResponse),\n comments: record.comments?.map(toCommentResponse),\n screenshotUrl: record.screenshotUrl ?? null,\n screenshotRegion: record.screenshotRegion ?? null,\n diagnostics: record.diagnostics ?? null,\n };\n}\n\nfunction toCommentResponse({ clientId: _clientId, createdAt, ...comment }: CommentRecord): CommentResponse {\n return { ...comment, createdAt: createdAt.toISOString() };\n}\n\nfunction toAnnotationResponse(ann: AnnotationRecord): AnnotationResponse {\n return {\n id: ann.id,\n feedbackId: ann.feedbackId,\n cssSelector: ann.cssSelector,\n xpath: ann.xpath,\n textSnippet: ann.textSnippet,\n elementTag: ann.elementTag,\n elementId: ann.elementId,\n textPrefix: ann.textPrefix,\n textSuffix: ann.textSuffix,\n fingerprint: ann.fingerprint,\n neighborText: ann.neighborText,\n anchorKey: ann.anchorKey ?? null,\n xPct: ann.xPct,\n yPct: ann.yPct,\n wPct: ann.wPct,\n hPct: ann.hPct,\n scrollX: ann.scrollX,\n scrollY: ann.scrollY,\n viewportW: ann.viewportW,\n viewportH: ann.viewportH,\n devicePixelRatio: ann.devicePixelRatio,\n createdAt: ann.createdAt.toISOString(),\n };\n}\n","/**\n * CSS keyframes and animation utilities — Glassmorphism edition.\n *\n * Uses CSS-only spring animations via linear() timing function\n * and refined easing curves for premium motion design.\n */\n\n// Spring easing — computed from a spring simulation (damping: 15, stiffness: 100)\nconst SPRING_LINEAR = `linear(0, 0.006, 0.025, 0.06, 0.11, 0.17, 0.25, 0.34, 0.45, 0.56, 0.67, 0.78, 0.88, 0.95, 1.01, 1.04, 1.05, 1.04, 1.02, 1, 0.99, 1)`;\n\n// Ease-out-expo — fast start, smooth deceleration\nconst EASE_OUT_EXPO = `cubic-bezier(0.16, 1, 0.3, 1)`;\n\n// Spring overshoot — bouncy entrance\nconst SPRING_OVERSHOOT = `cubic-bezier(0.34, 1.56, 0.64, 1)`;\n\n// Smooth decel — for glass transitions\nconst EASE_OUT_QUART = `cubic-bezier(0.25, 1, 0.5, 1)`;\n\nexport const ANIMATION_CSS = /* css */ `@keyframes sp-fab-in{from{transform:scale(0) rotate(-180deg);opacity:0;}to{transform:scale(1) rotate(0deg);opacity:1;}}@keyframes sp-fab-glow{0%,100%{box-shadow:0 4px 20px var(--sp-accent-glow),0 2px 8px rgba(0,0,0,0.08);}50%{box-shadow:0 4px 28px var(--sp-accent-glow),0 2px 12px rgba(0,0,0,0.1);}}@keyframes sp-marker-in{0%{transform:scale(0);opacity:0;}60%{transform:scale(1.2);opacity:1;}100%{transform:scale(1);}}@keyframes sp-pulse-ring{0%{box-shadow:0 0 0 0 var(--sp-accent-glow);}70%{box-shadow:0 0 0 8px transparent;}100%{box-shadow:0 0 0 0 transparent;}}@keyframes sp-flash-bg{0%{background-color:var(--sp-accent-light);}100%{background-color:transparent;}}@keyframes sp-slide-up{from{transform:translateY(8px);opacity:0;}to{transform:translateY(0);opacity:1;}}@keyframes sp-fade-in{from{opacity:0;}to{opacity:1;}}@keyframes sp-shimmer{0%{background-position:-200% 0;}100%{background-position:200% 0;}}.sp-anim-fab-in{animation:sp-fab-in 0.5s ${SPRING_LINEAR} both;}.sp-anim-marker-in{animation:sp-marker-in 0.35s ${SPRING_OVERSHOOT} both;}.sp-anim-pulse{animation:sp-pulse-ring 0.7s ease-out;}.sp-anim-flash{animation:sp-flash-bg 0.5s ${EASE_OUT_QUART};}.sp-anim-slide-up{animation:sp-slide-up 0.3s ${EASE_OUT_EXPO} both;}.sp-anim-fade-in{animation:sp-fade-in 0.2s ease-out both;}.sp-panel{transform:translateX(110%);transition:transform 0.4s ${EASE_OUT_EXPO};}.sp-panel.sp-panel--open{transform:translateX(0);}.sp-radial-item{opacity:0;pointer-events:none;transform:translate(0,0) scale(0.8);transition:transform 0.35s ${SPRING_OVERSHOOT},opacity 0.2s ease,background 0.2s ease,border-color 0.2s ease,box-shadow 0.2s ease;}.sp-radial-item.sp-radial-item--open{opacity:1;pointer-events:auto;}.sp-radial-item{transition-delay:calc(var(--sp-i, 0) * 50ms);}@keyframes sp-card-in{from{transform:translateY(12px);opacity:0;}to{transform:translateY(0);opacity:1;}}.sp-card{animation:sp-card-in 0.35s ${EASE_OUT_EXPO} both;animation-delay:calc(var(--sp-card-i, 0) * 40ms);}@keyframes sp-spin{to{transform:rotate(360deg);}}.sp-spinner{width:20px;height:20px;border:2px solid var(--sp-border);border-top-color:var(--sp-accent);border-radius:50%;animation:sp-spin 0.6s linear infinite;}@keyframes sp-badge-in{0%{transform:scale(0);}60%{transform:scale(1.3);}100%{transform:scale(1);}}.sp-fab-badge{animation:sp-badge-in 0.4s ${SPRING_OVERSHOOT} both;}@media (prefers-reduced-motion: reduce){*,*::before,*::after{animation-duration:0.01ms !important;animation-iteration-count:1 !important;transition-duration:0.01ms !important;}}`\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n;\n","import { COMPACT_MEDIA } from \"../constants.js\";\n\n/**\n * Phone and touch layer — appended last in the Shadow DOM stylesheet so it\n * wins over the desktop rules it adapts. Three independent axes:\n *\n * - `hover: none` — touch screens. Tapping leaves `:hover` stuck, so hover\n * lifts are neutralised, and hover-revealed affordances (speed-dial labels,\n * bulk checkboxes) become permanent: invisible elements must never be\n * tappable.\n * - `pointer: coarse` — finger-sized targets, and 16px form fields: iOS\n * Safari zooms the whole page into any input under 16px on focus.\n * - `COMPACT_MEDIA` (up to 640px wide, or a touch screen up to 500px tall: a\n * phone held sideways) — the panel and its menus become bottom sheets. Glass\n * turns solid there: translucent sheets are hard to read on a busy page, and\n * backdrop blur is the most expensive paint on low-end phones.\n *\n * Sheet mechanics worth knowing before editing:\n * - The headers (panel and detail) are the swipe-to-close handles, hence\n * `touch-action: none`; the stats bar and filters take `pan-x`, so only the\n * list scrolls vertically and a drag elsewhere never scrolls the page behind.\n * - Lists use `overscroll-behavior: contain` for the same reason.\n * - The filter row scrolls horizontally, which would clip the type menu — so\n * menus become `position: fixed` action sheets. Fixed positioning resolves\n * against the transformed panel (not the viewport), which lifts them out of\n * the row; that only holds while no ancestor in between has a transform or\n * backdrop-filter (why the filters' glass is dropped here).\n * - Icon-only header buttons keep their text label, visually hidden, as the\n * accessible name.\n *\n * Surfaces that live on `document.body` (popup, annotator toolbar, markers)\n * cannot see this sheet — they adapt in JS through `viewport.ts`. The CSS\n * string below is minified at build time, like the rest of the stylesheet.\n */\nexport const MOBILE_CSS = /* css */ `:host{-webkit-tap-highlight-color:transparent;}.sp-list,.sp-detail-content{overscroll-behavior:contain;}.sp-scrim{display:none;}@media (hover: none){.sp-fab:hover:not(:active),.sp-card:hover:not(:active),.sp-btn-primary:hover:not(:active),.sp-btn-danger:hover:not(:active){transform:none;}.sp-card:hover:not(:active){box-shadow:var(--sp-shadow-xs);}.sp-radial-item--open .sp-radial-label{opacity:1;transform:translate(0,-50%);}.sp-bulk-checkbox{opacity:1;}.sp-bulk-checkbox::after{content:\"\";position:absolute;inset:-12px;}.sp-bulk-select-all{display:none;}.sp-list--has-selection .sp-bulk-select-all{display:flex;}.sp-shortcuts-hint{display:none;}}@media (pointer: coarse){.sp-radial-item{width:48px;height:48px;left:2px;bottom:2px;}.sp-radial-item svg{width:20px;height:20px;}.sp-radial-label{font-size:13px;font-weight:600;padding:8px 12px;}.sp-search,.sp-input{font-size:16px;}.sp-filter-dropdown-btn{height:36px;}.sp-segmented__btn{height:32px;}.sp-sort-btn,.sp-group-toggle,.sp-mine-toggle{min-height:36px;}.sp-btn-resolve,.sp-btn-delete{min-height:40px;}.sp-detail-back{width:44px;height:44px;}.sp-detail-actions button,.sp-detail-actions a{height:44px;}}@media ${COMPACT_MEDIA}{.sp-fab--bottom-right,.sp-radial--bottom-right{right:calc(16px + env(safe-area-inset-right,0px));bottom:calc(16px + env(safe-area-inset-bottom,0px));}.sp-fab--bottom-left,.sp-radial--bottom-left{left:calc(16px + env(safe-area-inset-left,0px));bottom:calc(16px + env(safe-area-inset-bottom,0px));}.sp-scrim{display:block;position:fixed;inset:0;background:var(--sp-scrim);opacity:0;pointer-events:none;touch-action:none;transition:opacity 0.3s ease;}.sp-scrim--open{opacity:1;pointer-events:auto;}.sp-panel{top:auto;left:0;right:0;bottom:0;width:auto;max-width:none;height:calc(100vh - 48px);height:calc(100dvh - 40px - env(safe-area-inset-top,0px));border-left:none;border-top:1px solid var(--sp-glass-border);border-radius:var(--sp-radius-xl) var(--sp-radius-xl) 0 0;background:var(--sp-bg);-webkit-backdrop-filter:none;backdrop-filter:none;transform:translateY(105%);}.sp-panel.sp-panel--open{transform:translateY(0);}.sp-panel-header,.sp-detail-header{position:relative;padding-top:22px;background:var(--sp-bg);-webkit-backdrop-filter:none;backdrop-filter:none;touch-action:none;}.sp-panel-header{padding:22px 12px 12px 20px;}.sp-panel-header::before,.sp-detail-header::before{content:\"\";position:absolute;top:8px;left:50%;width:36px;height:5px;margin-left:-18px;border-radius:3px;background:var(--sp-border);}.sp-export-btn,.sp-btn-delete-all{width:40px;height:40px;padding:0;justify-content:center;border-radius:var(--sp-radius);}.sp-export-btn svg,.sp-btn-delete-all svg{width:17px;height:17px;}.sp-export-btn span,.sp-btn-delete-all span{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;}.sp-stats-bar{padding:10px 20px;}.sp-filters{padding:12px 16px 10px;background:var(--sp-bg);-webkit-backdrop-filter:none;backdrop-filter:none;}.sp-stats-bar,.sp-filters{touch-action:pan-x;}.sp-search{height:44px;}.sp-filter-bar{flex-wrap:nowrap;overflow-x:auto;margin:0 -16px 8px;padding:0 16px 2px;scrollbar-width:none;}.sp-filter-bar::-webkit-scrollbar{display:none;}.sp-filter-dropdown{flex:0 0 auto;}.sp-filter-dropdown-btn{width:auto;}.sp-filter-dropdown-menu,.sp-sort-menu{position:fixed;top:auto;left:12px;right:12px;bottom:calc(12px + env(safe-area-inset-bottom,0px));min-width:0;padding:6px;border-radius:var(--sp-radius-lg);background:var(--sp-bg);-webkit-backdrop-filter:none;backdrop-filter:none;box-shadow:var(--sp-shadow-xl);z-index:30;}.sp-filter-dropdown-option,.sp-sort-option{min-height:44px;font-size:14px;}.sp-list{padding:10px 12px calc(12px + env(safe-area-inset-bottom,0px));}.sp-bulk-bar{bottom:calc(16px + env(safe-area-inset-bottom,0px));}.sp-detail{background:var(--sp-bg);-webkit-backdrop-filter:none;backdrop-filter:none;}.sp-detail-section{padding:18px 20px;}.sp-detail-content{padding-bottom:env(safe-area-inset-bottom,0px);}.sp-identity-backdrop{align-items:flex-end;}.sp-identity-modal{width:100%;max-width:none;margin-bottom:var(--sp-kb, 0px);padding:24px 20px calc(20px + env(safe-area-inset-bottom,0px));border-radius:var(--sp-radius-xl) var(--sp-radius-xl) 0 0;background:var(--sp-bg);transform:translateY(100%);}.sp-identity-actions button{flex:1;height:48px;}.sp-identity-actions .sp-btn-primary{flex:2;}}`\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n;\n","import { Z_INDEX_MAX } from \"../constants.js\";\nimport { EXPORT_CSS } from \"../export-utils.js\";\nimport { BULK_CSS } from \"../panel-bulk.js\";\nimport { DETAIL_CSS } from \"../panel-detail.js\";\nimport { SORT_CSS } from \"../panel-sort.js\";\nimport { STATS_CSS } from \"../panel-stats.js\";\nimport { SHORTCUTS_CSS } from \"../shortcuts.js\";\nimport { ANIMATION_CSS } from \"./animations.js\";\nimport { MOBILE_CSS } from \"./mobile.js\";\nimport { cssVariables, type ThemeColors } from \"./theme.js\";\n\n/**\n * Build the complete CSS stylesheet for the Shadow DOM.\n *\n * Design: Glassmorphism — frosted glass surfaces, soft depth,\n * accent gradients, premium micro-interactions.\n *\n * Principles:\n * - :host uses `all: initial` to block inherited styles\n * - All classes prefixed with sp- (defense in depth)\n * - CSS custom properties for theming\n * - No external fonts — system-ui stack (Inter if available)\n * - :focus-visible on all interactive elements\n * - prefers-reduced-motion support\n */\nexport function buildStyles(colors: ThemeColors): string {\n return /* css */ `:host{all:initial;position:fixed;z-index:${Z_INDEX_MAX};font-family:var(--sp-font);font-size:14px;line-height:1.5;color:var(--sp-text);color-scheme:${colors.bg === \"#ffffff\" ? \"light\" : \"dark\"};-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;${cssVariables(colors)} --sp-identity-bg: ${colors.glassBgHeavy};--sp-identity-overlay: ${colors.bg === \"#ffffff\" ? \"rgba(15, 23, 42, 0.2)\" : \"rgba(0, 0, 0, 0.4)\"};--sp-scrim: ${colors.bg === \"#ffffff\" ? \"rgba(15, 23, 42, 0.32)\" : \"rgba(0, 0, 0, 0.5)\"};}*,*::before,*::after{box-sizing:border-box;margin:0;padding:0;}:focus-visible{outline:2px solid var(--sp-accent);outline-offset:2px;box-shadow:0 0 0 4px var(--sp-bg);}.sp-fab{position:fixed;width:52px;height:52px;border-radius:var(--sp-radius-full);background:var(--sp-accent-gradient);color:#fff;border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;box-shadow:0 4px 20px var(--sp-accent-glow),0 2px 8px rgba(0,0,0,0.08);transition:transform 0.25s cubic-bezier(0.34,1.56,0.64,1),box-shadow 0.3s ease;outline:none;}.sp-fab:focus-visible{outline:2px solid #fff;outline-offset:3px;}.sp-fab:hover{transform:translateY(-2px) scale(1.05);box-shadow:0 8px 28px var(--sp-accent-glow),0 4px 12px rgba(0,0,0,0.1);}.sp-fab:active{transform:translateY(0) scale(0.95);transition-duration:0.1s;}.sp-fab--bottom-right{bottom:24px;right:24px;}.sp-fab--bottom-left{bottom:24px;left:24px;}.sp-fab svg{width:22px;height:22px;fill:currentColor;transition:transform 0.3s cubic-bezier(0.34,1.56,0.64,1);}.sp-fab-badge{position:absolute;top:-4px;right:-4px;min-width:20px;height:20px;padding:0 6px;border-radius:var(--sp-radius-full);background:#ef4444;color:#fff;font-size:11px;font-weight:700;display:flex;align-items:center;justify-content:center;border:2px solid #fff;pointer-events:none;font-family:var(--sp-font);line-height:1;}.sp-radial{position:fixed;pointer-events:none;width:52px;height:52px;}.sp-radial--bottom-right{bottom:24px;right:24px;}.sp-radial--bottom-left{bottom:24px;left:24px;}.sp-radial-item{position:absolute;left:4px;bottom:4px;width:44px;height:44px;border-radius:var(--sp-radius-full);background:var(--sp-glass-bg-heavy);backdrop-filter:blur(var(--sp-blur));-webkit-backdrop-filter:blur(var(--sp-blur));color:var(--sp-text);border:1px solid var(--sp-glass-border);cursor:pointer;display:flex;align-items:center;justify-content:center;box-shadow:var(--sp-shadow-md);font-size:12px;font-weight:600;}.sp-radial-item:hover,.sp-radial-item:focus-visible{background:rgba(255,255,255,0.95);border-color:var(--sp-accent);color:var(--sp-accent);box-shadow:var(--sp-shadow-md),0 0 0 3px var(--sp-accent-light);outline:none;}.sp-radial-item svg{width:18px;height:18px;flex-shrink:0;stroke:currentColor;fill:none;}.sp-radial-label{position:absolute;top:50%;white-space:nowrap;font-size:12px;font-weight:500;color:var(--sp-text);pointer-events:none;opacity:0;padding:4px 12px;border-radius:var(--sp-radius);background:var(--sp-glass-bg-heavy);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border:1px solid var(--sp-glass-border);box-shadow:var(--sp-shadow-sm);transform:translate(4px,-50%);transition:opacity 0.2s ease,transform 0.2s ease;}.sp-radial--bottom-right .sp-radial-label{right:calc(100% + 12px);}.sp-radial--bottom-left .sp-radial-label{left:calc(100% + 12px);transform:translate(-4px,-50%);}.sp-radial-item:hover .sp-radial-label,.sp-radial-item:focus-visible .sp-radial-label{opacity:1;transform:translate(0,-50%);}.sp-panel{position:fixed;top:0;right:0;width:400px;max-width:100vw;height:100vh;height:100dvh;background:var(--sp-glass-bg);backdrop-filter:blur(var(--sp-blur-heavy));-webkit-backdrop-filter:blur(var(--sp-blur-heavy));border-left:1px solid var(--sp-glass-border);box-shadow:var(--sp-shadow-xl);display:flex;flex-direction:column;overflow:hidden;}.sp-panel-header{display:flex;align-items:center;justify-content:space-between;padding:20px 24px;border-bottom:1px solid var(--sp-border);background:var(--sp-glass-bg-heavy);backdrop-filter:blur(var(--sp-blur));-webkit-backdrop-filter:blur(var(--sp-blur));position:relative;z-index:2;}.sp-panel-title{font-size:17px;font-weight:700;color:var(--sp-text);letter-spacing:-0.02em;}.sp-panel-close{width:44px;height:44px;border-radius:var(--sp-radius);border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--sp-text-tertiary);transition:all 0.2s ease;}.sp-panel-close:hover{background:var(--sp-bg-hover);color:var(--sp-text);}.sp-panel-close svg{width:16px;height:16px;}.sp-filters{padding:16px 24px;border-bottom:1px solid var(--sp-border);background:var(--sp-glass-bg-heavy);backdrop-filter:blur(var(--sp-blur));-webkit-backdrop-filter:blur(var(--sp-blur));position:sticky;top:0;z-index:1;}.sp-search-wrap{position:relative;margin-bottom:12px;}.sp-search{width:100%;height:40px;padding:0 12px 0 38px;border-radius:var(--sp-radius);border:1px solid var(--sp-border);background:var(--sp-glass-bg-heavy);color:var(--sp-text);font-family:var(--sp-font);font-size:13px;outline:none;transition:all 0.2s ease;}.sp-search::placeholder{color:var(--sp-text-tertiary);}.sp-search:focus{border-color:var(--sp-accent);box-shadow:0 0 0 3px var(--sp-accent-light);background:var(--sp-bg);}.sp-search-icon{position:absolute;left:12px;top:50%;transform:translateY(-50%);color:var(--sp-text-tertiary);width:16px;height:16px;transition:color 0.2s ease;}.sp-search:focus ~ .sp-search-icon,.sp-search-wrap:focus-within .sp-search-icon{color:var(--sp-accent);}.sp-filter-bar{display:flex;align-items:center;gap:8px;margin-bottom:8px;flex-wrap:wrap;}.sp-filter-dropdown{position:relative;flex:1 1 auto;min-width:0;}.sp-filter-dropdown-btn{--sp-chip-color: var(--sp-text-secondary);--sp-chip-bg: var(--sp-glass-bg-heavy);display:inline-flex;align-items:center;gap:8px;width:100%;height:32px;padding:0 8px 0 10px;border-radius:var(--sp-radius-full);border:1px solid var(--sp-border);background:var(--sp-glass-bg-heavy);color:var(--sp-text);font-family:var(--sp-font);font-size:12px;font-weight:500;cursor:pointer;white-space:nowrap;transition:background 0.18s ease,border-color 0.18s ease,box-shadow 0.18s ease;}.sp-filter-dropdown-btn:hover{border-color:var(--sp-chip-color);background:var(--sp-chip-bg);}.sp-filter-dropdown-btn[aria-expanded=\"true\"]{border-color:var(--sp-chip-color);background:var(--sp-chip-bg);box-shadow:0 0 0 3px color-mix(in srgb,var(--sp-chip-color) 14%,transparent);}.sp-filter-dropdown-btn--filtered{border-color:var(--sp-chip-color);background:var(--sp-chip-bg);}.sp-filter-dropdown-btn__icon{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;flex-shrink:0;color:var(--sp-chip-color);}.sp-filter-dropdown-btn__icon svg{width:14px;height:14px;}.sp-filter-dropdown-btn__label{display:inline-flex;align-items:baseline;gap:6px;flex:1;min-width:0;overflow:hidden;}.sp-filter-dropdown-btn__prefix{color:var(--sp-text-tertiary);font-weight:500;font-size:11px;text-transform:uppercase;letter-spacing:0.06em;}.sp-filter-dropdown-btn__value{color:var(--sp-chip-color);font-weight:600;overflow:hidden;text-overflow:ellipsis;}.sp-filter-dropdown-btn__chevron{display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px;flex-shrink:0;color:var(--sp-text-tertiary);transition:transform 0.18s ease,color 0.18s ease;}.sp-filter-dropdown-btn__chevron svg{width:12px;height:12px;}.sp-filter-dropdown-btn[aria-expanded=\"true\"] .sp-filter-dropdown-btn__chevron{transform:rotate(180deg);color:var(--sp-chip-color);}.sp-filter-dropdown-menu{position:absolute;top:calc(100% + 6px);left:0;right:0;min-width:180px;padding:4px;border-radius:var(--sp-radius);background:var(--sp-glass-bg-heavy);backdrop-filter:blur(var(--sp-blur-heavy));-webkit-backdrop-filter:blur(var(--sp-blur-heavy));border:1px solid var(--sp-glass-border);box-shadow:var(--sp-shadow-md);z-index:10;animation:sp-filter-menu-in 0.15s ease-out both;}@keyframes sp-filter-menu-in{from{opacity:0;transform:translateY(-4px) scale(0.98);}to{opacity:1;transform:translateY(0) scale(1);}}.sp-filter-dropdown-option{--sp-chip-color: var(--sp-text-secondary);--sp-chip-bg: transparent;display:flex;align-items:center;gap:10px;width:100%;padding:8px 10px;border:none;border-radius:8px;background:transparent;color:var(--sp-text);font-family:var(--sp-font);font-size:12px;font-weight:500;cursor:pointer;text-align:left;transition:background 0.12s ease,color 0.12s ease;}.sp-filter-dropdown-option__icon{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;flex-shrink:0;border-radius:6px;background:var(--sp-chip-bg);color:var(--sp-chip-color);}.sp-filter-dropdown-option__icon svg{width:13px;height:13px;}.sp-filter-dropdown-option__label{flex:1;min-width:0;}.sp-filter-dropdown-option__check{display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px;flex-shrink:0;color:var(--sp-chip-color);}.sp-filter-dropdown-option__check svg{width:13px;height:13px;}.sp-filter-dropdown-option:hover{background:var(--sp-bg-hover);}.sp-filter-dropdown-option--active{color:var(--sp-chip-color);font-weight:600;}.sp-filter-dropdown-option--active:hover{background:var(--sp-chip-bg);}.sp-segmented{display:inline-flex;align-items:stretch;padding:2px;border-radius:var(--sp-radius-full);border:1px solid var(--sp-border);background:var(--sp-glass-bg-heavy);flex-shrink:0;}.sp-segmented__btn{--sp-chip-color: var(--sp-text-tertiary);--sp-chip-bg: transparent;display:inline-flex;align-items:center;gap:5px;height:26px;padding:0 10px;border:none;border-radius:var(--sp-radius-full);background:transparent;color:var(--sp-text-secondary);font-family:var(--sp-font);font-size:12px;font-weight:500;cursor:pointer;white-space:nowrap;transition:background 0.18s ease,color 0.18s ease,box-shadow 0.18s ease;}.sp-segmented__icon{display:inline-flex;align-items:center;justify-content:center;width:13px;height:13px;flex-shrink:0;color:var(--sp-chip-color);transition:color 0.18s ease,transform 0.18s ease;}.sp-segmented__icon svg{width:13px;height:13px;}.sp-segmented__btn:hover{color:var(--sp-chip-color);}.sp-segmented__btn:hover .sp-segmented__icon{color:var(--sp-chip-color);}.sp-segmented__btn--active{background:var(--sp-chip-bg);color:var(--sp-chip-color);font-weight:600;box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--sp-chip-color) 35%,transparent),0 1px 2px rgba(0,0,0,0.04);}.sp-segmented__btn--active .sp-segmented__icon{color:var(--sp-chip-color);}.sp-segmented__btn--open.sp-segmented__btn--active .sp-segmented__icon{animation:sp-segmented-pulse 2.4s ease-in-out infinite;}@keyframes sp-segmented-pulse{0%,100%{transform:scale(1);}50%{transform:scale(0.85);}}@media (prefers-reduced-motion: reduce){.sp-filter-dropdown-btn,.sp-filter-dropdown-btn__chevron,.sp-filter-dropdown-option,.sp-segmented__btn,.sp-segmented__icon{transition:none;}.sp-filter-dropdown-menu{animation:none;}.sp-segmented__btn--open.sp-segmented__btn--active .sp-segmented__icon{animation:none;}}.sp-list{flex:1;overflow-y:auto;padding:8px 12px;}.sp-list::-webkit-scrollbar{width:6px;}.sp-list::-webkit-scrollbar-track{background:transparent;}.sp-list::-webkit-scrollbar-thumb{background:var(--sp-border);border-radius:var(--sp-radius-full);}.sp-list::-webkit-scrollbar-thumb:hover{background:var(--sp-text-tertiary);}.sp-card{display:flex;padding:14px 16px;margin-bottom:6px;cursor:pointer;border-radius:var(--sp-radius);background:var(--sp-glass-bg-heavy);border:1px solid var(--sp-glass-border);box-shadow:var(--sp-shadow-xs);transition:all 0.2s cubic-bezier(0.34,1.56,0.64,1);}.sp-card:hover{background:var(--sp-bg);border-color:var(--sp-border);box-shadow:var(--sp-shadow-md);transform:translateY(-2px);}.sp-card:active{transform:translateY(0) scale(0.99);transition-duration:0.1s;}.sp-card-bar{width:3px;border-radius:var(--sp-radius-full);margin-right:14px;flex-shrink:0;}.sp-card-body{flex:1;min-width:0;}.sp-card-header{display:flex;align-items:center;gap:8px;margin-bottom:6px;}.sp-card-number{font-size:12px;font-weight:700;color:var(--sp-text-tertiary);font-variant-numeric:tabular-nums;}.sp-badge{padding:2px 10px;border-radius:var(--sp-radius-full);font-size:11px;font-weight:600;letter-spacing:0.02em;}.sp-card-date{font-size:11px;color:var(--sp-text-tertiary);margin-left:auto;}.sp-card-message{font-size:13px;line-height:1.5;color:var(--sp-text);display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;}.sp-card-message--expanded{-webkit-line-clamp:unset;}.sp-card-expand{font-size:12px;font-weight:500;color:var(--sp-accent);cursor:pointer;background:none;border:none;padding:4px 0;font-family:var(--sp-font);transition:opacity 0.15s ease;}.sp-card-expand:hover{opacity:0.8;}.sp-card-footer{display:flex;align-items:center;justify-content:flex-end;gap:6px;margin-top:10px;}.sp-btn-resolve,.sp-btn-delete{padding:8px 14px;border-radius:var(--sp-radius-full);border:1px solid var(--sp-border);background:transparent;color:var(--sp-text-secondary);font-family:var(--sp-font);font-size:12px;font-weight:500;cursor:pointer;display:flex;align-items:center;gap:4px;transition:all 0.2s ease;}.sp-btn-resolve svg,.sp-btn-delete svg{width:14px;height:14px;}.sp-btn-resolve:hover{border-color:#22c55e;color:#22c55e;background:rgba(34,197,94,0.06);}.sp-btn-delete:hover{border-color:#ef4444;color:#ef4444;background:rgba(239,68,68,0.06);}.sp-btn-resolve:disabled,.sp-btn-delete:disabled{opacity:0.5;cursor:not-allowed;pointer-events:none;}.sp-spinner--sm{width:14px;height:14px;}.sp-panel-header-right{display:flex;align-items:center;gap:8px;}.sp-btn-delete-all{padding:5px 12px;border-radius:var(--sp-radius-full);border:1px solid var(--sp-border);background:transparent;color:var(--sp-text-tertiary);font-family:var(--sp-font);font-size:11px;font-weight:500;cursor:pointer;display:flex;align-items:center;gap:4px;transition:all 0.2s ease;}.sp-btn-delete-all svg{width:13px;height:13px;}.sp-btn-delete-all:hover{border-color:#ef4444;color:#ef4444;background:rgba(239,68,68,0.06);}.sp-btn-delete-all:disabled{opacity:0.5;cursor:not-allowed;pointer-events:none;}.sp-confirm-backdrop{position:fixed;inset:0;background:var(--sp-backdrop, rgba(15, 23, 42, 0.2));backdrop-filter:blur(var(--sp-blur));-webkit-backdrop-filter:blur(var(--sp-blur));display:flex;align-items:center;justify-content:center;z-index:${Z_INDEX_MAX};opacity:0;transition:opacity 0.2s ease;}.sp-confirm-dialog{width:min(340px,calc(100vw - 32px));padding:28px;border-radius:20px;background:var(--sp-glass-bg-heavy);backdrop-filter:blur(var(--sp-blur-heavy));-webkit-backdrop-filter:blur(var(--sp-blur-heavy));border:1px solid var(--sp-glass-border);box-shadow:var(--sp-shadow-xl);font-family:var(--sp-font);transform:translateY(8px) scale(0.97);transition:transform 0.25s cubic-bezier(0.16,1,0.3,1);}.sp-confirm-title{font-size:17px;font-weight:700;color:var(--sp-text);letter-spacing:-0.02em;margin-bottom:8px;}.sp-confirm-message{font-size:14px;color:var(--sp-text-secondary);line-height:1.5;margin-bottom:20px;}.sp-confirm-actions{display:flex;gap:8px;justify-content:flex-end;}.sp-btn-danger{height:40px;padding:0 22px;border-radius:var(--sp-radius);border:none;background:#ef4444;color:#fff;font-family:var(--sp-font);font-size:14px;font-weight:600;cursor:pointer;transition:all 0.2s ease;box-shadow:0 2px 8px rgba(239,68,68,0.25);}.sp-btn-danger:hover{background:#dc2626;box-shadow:0 4px 16px rgba(239,68,68,0.3);transform:translateY(-1px);}.sp-btn-danger:active{transform:translateY(0) scale(0.98);transition-duration:0.1s;}.sp-card--resolved{opacity:0.5;}.sp-card--resolved .sp-card-message{text-decoration:line-through;text-decoration-color:var(--sp-text-tertiary);}.sp-loading{display:flex;align-items:center;justify-content:center;padding:48px 24px;}.sp-identity-backdrop{position:fixed;inset:0;background:var(--sp-identity-overlay);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);display:flex;align-items:center;justify-content:center;z-index:${Z_INDEX_MAX};opacity:0;transition:opacity 0.25s ease;}.sp-identity-modal{width:340px;max-width:calc(100vw - 32px);padding:28px;border-radius:var(--sp-radius-xl);background:var(--sp-identity-bg);backdrop-filter:blur(var(--sp-blur-heavy));-webkit-backdrop-filter:blur(var(--sp-blur-heavy));border:1px solid var(--sp-glass-border);box-shadow:0 16px 48px var(--sp-shadow),0 8px 16px var(--sp-shadow);font-family:var(--sp-font);color:var(--sp-text);transform:translateY(12px) scale(0.97);transition:transform 0.3s cubic-bezier(0.16,1,0.3,1);}.sp-identity--open{opacity:1;}.sp-identity--open .sp-identity-modal{transform:none;}.sp-identity-actions{display:flex;gap:8px;justify-content:flex-end;margin-top:20px;}.sp-identity-title{font-size:17px;font-weight:700;color:var(--sp-text);letter-spacing:-0.02em;}.sp-input{width:100%;height:42px;padding:0 14px;border-radius:var(--sp-radius);border:1px solid var(--sp-border);background:var(--sp-glass-bg-heavy);color:var(--sp-text);font-family:var(--sp-font);font-size:14px;outline:none;transition:all 0.2s ease;}.sp-input::placeholder{color:var(--sp-text-tertiary);}.sp-input:focus{border-color:var(--sp-accent);box-shadow:0 0 0 3px var(--sp-accent-light);background:var(--sp-bg);}.sp-input-label{font-size:13px;font-weight:500;color:var(--sp-text-secondary);margin-bottom:6px;display:block;}.sp-btn-primary{height:40px;padding:0 22px;border-radius:var(--sp-radius);border:none;background:var(--sp-accent-gradient);color:#fff;font-family:var(--sp-font);font-size:14px;font-weight:600;cursor:pointer;transition:all 0.2s ease;box-shadow:0 2px 8px var(--sp-accent-glow);}.sp-btn-primary:hover{box-shadow:0 4px 16px var(--sp-accent-glow);transform:translateY(-1px);}.sp-btn-primary:active{transform:translateY(0) scale(0.98);transition-duration:0.1s;}.sp-btn-primary:disabled{opacity:0.4;cursor:not-allowed;transform:none;box-shadow:none;}.sp-btn-ghost{height:40px;padding:0 22px;border-radius:var(--sp-radius);border:1px solid var(--sp-border);background:var(--sp-glass-bg-heavy);color:var(--sp-text-secondary);font-family:var(--sp-font);font-size:14px;font-weight:500;cursor:pointer;transition:all 0.2s ease;}.sp-btn-ghost:hover{border-color:var(--sp-accent);color:var(--sp-accent);background:var(--sp-accent-light);}.sp-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:56px 24px;color:var(--sp-text-tertiary);text-align:center;gap:8px;animation:sp-fade-in 0.3s ease-out both;}.sp-empty-text{font-size:14px;font-weight:500;}.sp-load-more-wrap{display:flex;justify-content:center;padding:12px 0 4px;}.sp-btn-load-more{width:100%;}@media (forced-colors: active){.sp-fab,.sp-radial-item,.sp-filter-dropdown-btn,.sp-segmented,.sp-segmented__btn,.sp-card,.sp-panel-close,.sp-search,.sp-btn-resolve,.sp-btn-delete,.sp-btn-delete-all,.sp-btn-primary,.sp-btn-ghost,.sp-btn-danger,.sp-card-expand,.sp-input,.sp-confirm-dialog{border:2px solid ButtonText !important;background:Canvas !important;color:ButtonText !important;}.sp-segmented__btn--active{background:Highlight !important;color:HighlightText !important;}.sp-filter-dropdown-menu{border:2px solid ButtonText !important;background:Canvas !important;}.sp-filter-dropdown-option--active{background:Highlight !important;color:HighlightText !important;}.sp-fab:focus-visible,.sp-radial-item:focus-visible,.sp-filter-dropdown-btn:focus-visible,.sp-segmented__btn:focus-visible,.sp-filter-dropdown-option:focus-visible,.sp-panel-close:focus-visible,.sp-btn-resolve:focus-visible,.sp-btn-delete:focus-visible,.sp-btn-delete-all:focus-visible,.sp-btn-primary:focus-visible,.sp-btn-ghost:focus-visible,.sp-btn-danger:focus-visible,.sp-card-expand:focus-visible,.sp-input:focus-visible,.sp-search:focus-visible{outline:3px solid Highlight !important;}.sp-panel{border:2px solid ButtonText !important;}.sp-fab-badge{border:2px solid ButtonText !important;background:Canvas !important;color:ButtonText !important;}.sp-card-bar{background:ButtonText !important;}}${ANIMATION_CSS} ${STATS_CSS} ${SORT_CSS} ${BULK_CSS} ${EXPORT_CSS} ${SHORTCUTS_CSS} ${DETAIL_CSS} ${MOBILE_CSS}`\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n;\n}\n","import type { FeedbackResponse } from \"@siteping/core\";\nimport { Z_INDEX_MAX } from \"./constants.js\";\nimport { el, formatRelativeDate, setText } from \"./dom-utils.js\";\nimport { isolateFromHost } from \"./host-isolation.js\";\nimport { createT, getTypeLabel } from \"./i18n/index.js\";\nimport { getTypeBgColor, getTypeColor, type ThemeColors } from \"./styles/theme.js\";\n\nconst SHOW_DELAY = 120;\nconst HIDE_DELAY = 80;\n/**\n * Declared once: `show()` swaps it for `none` under reduced motion and must\n * restore this exact value, since an empty inline value removes it.\n */\nconst TOOLTIP_TRANSITION = \"opacity 0.2s cubic-bezier(0.16, 1, 0.3, 1), transform 0.2s cubic-bezier(0.16, 1, 0.3, 1)\";\n\n/**\n * Tooltip shown on annotation marker hover.\n *\n * Glassmorphism design: frosted glass with pastel badge,\n * smooth entrance animation, directional arrow.\n * Lives outside Shadow DOM.\n */\nexport class Tooltip {\n private root: HTMLElement;\n private arrow: HTMLElement;\n private showTimer: ReturnType<typeof setTimeout> | null = null;\n private hideTimer: ReturnType<typeof setTimeout> | null = null;\n private currentFeedbackId: string | null = null;\n\n readonly tooltipId = \"sp-tooltip\";\n\n constructor(\n private readonly colors: ThemeColors,\n private readonly locale: string = \"en\",\n ) {\n this.root = el(\"div\", {\n style: /* css */ `position:fixed;z-index:${Z_INDEX_MAX};max-width:280px;padding:12px 14px;border-radius:14px;background:${this.colors.glassBgHeavy};backdrop-filter:blur(24px);-webkit-backdrop-filter:blur(24px);border:1px solid ${this.colors.glassBorder};box-shadow:0 8px 32px ${this.colors.shadow},0 2px 8px ${this.colors.shadow};font-family:\"Inter\",system-ui,-apple-system,sans-serif;pointer-events:auto;opacity:0;transform:translateY(6px) scale(0.97);transition:${TOOLTIP_TRANSITION};visibility:hidden;-webkit-font-smoothing:antialiased;`\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n,\n });\n\n this.root.setAttribute(\"role\", \"tooltip\");\n this.root.id = this.tooltipId;\n\n // Arrow element\n this.arrow = el(\"div\", {\n style: /* css */ `position:absolute;width:12px;height:12px;background:${this.colors.glassBgHeavy};border:1px solid ${this.colors.glassBorder};transform:rotate(45deg);pointer-events:none;`\n\n\n\n\n\n\n\n,\n });\n this.root.appendChild(this.arrow);\n\n this.root.addEventListener(\"mouseenter\", () => this.cancelHide());\n this.root.addEventListener(\"mouseleave\", () => this.scheduleHide());\n isolateFromHost(this.root);\n document.body.appendChild(this.root);\n }\n\n show(feedback: FeedbackResponse, anchorRect: DOMRect): void {\n // Cancel a pending hide first — the pointer may have left the marker and\n // come back within HIDE_DELAY, which re-shows the same feedback.\n this.cancelHide();\n if (this.currentFeedbackId === feedback.id) return;\n this.cancelShow();\n\n this.showTimer = setTimeout(() => {\n this.currentFeedbackId = feedback.id;\n this.render(feedback);\n this.position(anchorRect);\n\n // Check prefers-reduced-motion live (not cached at construction time)\n const reduceMotion =\n typeof window !== \"undefined\" && window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n this.root.style.transition = reduceMotion ? \"none\" : TOOLTIP_TRANSITION;\n\n this.root.style.visibility = \"visible\";\n this.root.style.opacity = \"1\";\n this.root.style.transform = \"translateY(0) scale(1)\";\n }, SHOW_DELAY);\n }\n\n scheduleHide(): void {\n this.cancelHide();\n this.hideTimer = setTimeout(() => this.hide(), HIDE_DELAY);\n }\n\n hide(): void {\n this.cancelShow();\n this.currentFeedbackId = null;\n this.root.style.opacity = \"0\";\n this.root.style.transform = \"translateY(6px) scale(0.97)\";\n setTimeout(() => {\n if (!this.currentFeedbackId) {\n this.root.style.visibility = \"hidden\";\n }\n }, 200);\n }\n\n private cancelShow(): void {\n if (this.showTimer) {\n clearTimeout(this.showTimer);\n this.showTimer = null;\n }\n }\n\n private cancelHide(): void {\n if (this.hideTimer) {\n clearTimeout(this.hideTimer);\n this.hideTimer = null;\n }\n }\n\n private render(feedback: FeedbackResponse): void {\n // Clear previous content safely (except arrow)\n const children = Array.from(this.root.children);\n for (const child of children) {\n if (child !== this.arrow) child.remove();\n }\n\n const typeColor = getTypeColor(feedback.type, this.colors);\n const typeBg = getTypeBgColor(feedback.type, this.colors);\n const t = createT(this.locale);\n const typeLabel = getTypeLabel(feedback.type, t);\n\n // Header row: badge + date\n const header = el(\"div\", { style: \"display:flex;align-items:center;gap:8px;margin-bottom:8px;\" });\n\n const badge = el(\"span\", {\n style: /* css */ `padding:3px 10px;border-radius:9999px;font-size:11px;font-weight:600;color:${typeColor};background:${typeBg};letter-spacing:0.02em;`\n\n\n\n\n,\n });\n setText(badge, typeLabel);\n\n const date = el(\"span\", { style: `font-size:11px;color:${this.colors.textSecondary};margin-left:auto;` });\n setText(date, formatRelativeDate(feedback.createdAt, this.locale));\n\n header.appendChild(badge);\n header.appendChild(date);\n\n // Message body (safe — textContent only)\n const body = el(\"div\", {\n style: `font-size:13px;line-height:1.55;color:${this.colors.text};display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;`,\n });\n setText(body, feedback.message);\n\n // Insert content before arrow\n this.root.insertBefore(header, this.arrow);\n this.root.insertBefore(body, this.arrow);\n }\n\n private position(anchorRect: DOMRect): void {\n const tooltipRect = this.root.getBoundingClientRect();\n const gap = 10;\n\n let top = anchorRect.top - tooltipRect.height - gap;\n let left = anchorRect.left + anchorRect.width / 2 - tooltipRect.width / 2;\n let isAbove = true;\n\n // Flip below if not enough space above\n if (top < 8) {\n top = anchorRect.bottom + gap;\n isAbove = false;\n }\n\n left = Math.max(8, Math.min(left, window.innerWidth - tooltipRect.width - 8));\n\n this.root.style.top = `${top}px`;\n this.root.style.left = `${left}px`;\n\n // Position arrow\n const arrowLeft = Math.max(16, Math.min(anchorRect.left + anchorRect.width / 2 - left - 6, tooltipRect.width - 22));\n\n if (isAbove) {\n // Arrow at bottom, pointing down\n this.arrow.style.cssText = /* css */ `position:absolute;width:12px;height:12px;background:${this.colors.glassBgHeavy};border-right:1px solid ${this.colors.glassBorder};border-bottom:1px solid ${this.colors.glassBorder};transform:rotate(45deg);pointer-events:none;bottom:-6px;left:${arrowLeft}px;`\n\n\n\n\n\n\n\n\n\n;\n } else {\n // Arrow at top, pointing up\n this.arrow.style.cssText = /* css */ `position:absolute;width:12px;height:12px;background:${this.colors.glassBgHeavy};border-left:1px solid ${this.colors.glassBorder};border-top:1px solid ${this.colors.glassBorder};transform:rotate(45deg);pointer-events:none;top:-6px;left:${arrowLeft}px;`\n\n\n\n\n\n\n\n\n\n;\n }\n }\n\n /** Check if a DOM node belongs to this tooltip (for MutationObserver filtering). */\n contains(node: Node): boolean {\n return this.root.contains(node);\n }\n\n destroy(): void {\n this.cancelShow();\n this.cancelHide();\n this.root.remove();\n }\n}\n","import {\n canonicalizeLocale,\n type DiagnosticsSnapshot,\n type FeedbackPayload,\n IDENTITY_FIELD_MAX_LENGTH,\n isValidEmail,\n type PageScope,\n type SitepingConfig,\n type SitepingInstance,\n type SitepingPublicEventListener,\n type SitepingPublicEvents,\n} from \"@siteping/core\";\nimport { Annotator } from \"./annotator.js\";\nimport { ApiClient, flushRetryQueue, type WidgetClient } from \"./api-client.js\";\nimport { DEFAULT_MIN_VIEWPORT_WIDTH, PAGE_SIZE, Z_INDEX_MAX } from \"./constants.js\";\nimport { ConsoleBuffer } from \"./diagnostics/console-buffer.js\";\nimport { NetworkBuffer } from \"./diagnostics/network-buffer.js\";\nimport { EventBus, type WidgetEvents } from \"./events.js\";\nimport { Fab } from \"./fab.js\";\nimport { createFocusTracker } from \"./focus-tracker.js\";\nimport { installHostIsolationGuard, isolateFromHost, registerEscapeLayer } from \"./host-isolation.js\";\nimport { createT, loadLocale, type TFunction } from \"./i18n/index.js\";\nimport { getIdentity, type Identity, saveIdentity } from \"./identity.js\";\nimport { MarkerManager } from \"./markers.js\";\nimport { ownFeedback } from \"./own-feedback.js\";\nimport type { Panel as PanelType } from \"./panel.js\";\nimport { StoreClient } from \"./store-client.js\";\nimport { buildStyles } from \"./styles/base.js\";\nimport { buildThemeColors } from \"./styles/theme.js\";\nimport { Tooltip } from \"./tooltip.js\";\nimport { trackKeyboardInset } from \"./viewport.js\";\n\n/** Singleton guard — prevents duplicate widgets from overlapping */\nlet instance: SitepingInstance | null = null;\n\ninterface NormalisedDiagnostics {\n console: boolean;\n network: boolean;\n maxConsoleEntries: number;\n maxNetworkEntries: number;\n}\n\n/**\n * Resolve `SitepingConfig.captureDiagnostics` into a normalised shape.\n *\n * - `undefined` / `false` → everything off (no monkey-patching).\n * - `true` → console + network on with the defaults (50 / 20).\n * - object → per-channel toggles + optional custom sizes; missing booleans\n * default to `true` so users can pass `{ maxConsoleEntries: 10 }` and\n * still get both channels. The buffers sanitise sizes themselves: capped\n * at the server limits (50 / 20), NaN / negative → default.\n */\nfunction normaliseDiagnosticsOptions(value: SitepingConfig[\"captureDiagnostics\"]): NormalisedDiagnostics {\n if (value === undefined || value === false) {\n return { console: false, network: false, maxConsoleEntries: 50, maxNetworkEntries: 20 };\n }\n if (value === true) {\n return { console: true, network: true, maxConsoleEntries: 50, maxNetworkEntries: 20 };\n }\n return {\n console: value.console !== false,\n network: value.network !== false,\n maxConsoleEntries: typeof value.maxConsoleEntries === \"number\" ? value.maxConsoleEntries : 50,\n maxNetworkEntries: typeof value.maxNetworkEntries === \"number\" ? value.maxNetworkEntries : 20,\n };\n}\n\n/** Build a no-op SitepingInstance for when the widget is skipped */\nfunction skippedInstance(): SitepingInstance {\n const noop = () => {};\n return {\n destroy: noop,\n open: noop,\n close: noop,\n refresh: noop,\n focusFeedback: () => false,\n on: () => noop,\n off: noop,\n };\n}\n\n/**\n * Read NODE_ENV so that BOTH detection paths keep working:\n *\n * - The literal `process.env.NODE_ENV` member expression must survive into\n * our own dist — an identity define in tsup.config.ts stops esbuild's\n * browser-platform auto-define from folding it to `\"production\"` and\n * deleting the guard from the shipped bundle (issue #104).\n * - Shipping the literal lets the CONSUMER's bundler (webpack DefinePlugin,\n * Vite, esbuild) inline their real environment, so \"dev-only by default\"\n * works in bundled deployments even when no `process` global exists at\n * runtime. Computed-key dodges (`env[\"NODE_\" + \"ENV\"]`) would defeat that\n * inlining — do not reintroduce them.\n * - No `typeof process` gate: it would return before a consumer-inlined\n * constant is reached. Plain browsers without `process` (script-tag usage)\n * land in the catch instead. Runtime environments with a real `process`\n * (Node/SSR, E2E's `globalThis.process = { env: { NODE_ENV: 'test' } }`)\n * read it live.\n *\n * `scripts/verify-dist-guard.mjs` asserts these invariants against every\n * built bundle after each build.\n */\nfunction readNodeEnv(): string | undefined {\n try {\n return process.env.NODE_ENV;\n } catch {\n // No `process` global (plain browser) or restricted access — no signal\n return undefined;\n }\n}\n\ninterface NormalisedDeepLink {\n enabled: boolean;\n param: string;\n}\n\n/**\n * Resolve `SitepingConfig.deepLink` into a normalised shape.\n *\n * - `undefined` / `false` → disabled, no URL parsing.\n * - `true` → enabled with default param name `siteping`.\n * - object → enabled with optional custom param name. A bare empty object\n * `{}` falls back to the default param so callers never need to repeat it.\n */\nfunction normaliseDeepLinkOptions(value: SitepingConfig[\"deepLink\"]): NormalisedDeepLink {\n if (value === undefined || value === false) return { enabled: false, param: \"siteping\" };\n if (value === true) return { enabled: true, param: \"siteping\" };\n return { enabled: true, param: value.param ?? \"siteping\" };\n}\n\n/**\n * Main widget launcher — orchestrates all UI components.\n *\n * Architecture:\n * - Creates a <siteping-widget> custom element in the document\n * - Attaches a closed Shadow DOM for CSS isolation\n * - FAB + Panel live inside the Shadow DOM\n * - Overlay, markers, tooltips live outside (appended to document.body)\n */\nexport function launch(config: SitepingConfig): SitepingInstance {\n // Guard: no DOM, no widget — SSR frameworks (Next.js, Remix) may run the\n // init on the server. Deliberately NOT bypassed by forceShow: the widget\n // cannot render without a document.\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n config.onSkip?.(\"ssr\");\n return skippedInstance();\n }\n\n // Debug helper — only logs when config.debug is true\n const log: (...args: unknown[]) => void = config.debug\n ? (...args: unknown[]) => console.debug(\"[siteping]\", ...args)\n : () => {};\n\n // Guard: prevent duplicate initSiteping() calls\n if (instance) {\n log(\"initSiteping() called more than once — returning existing instance\");\n return instance;\n }\n\n // Guard: only show in development (forceShow bypasses). Uses readNodeEnv()\n // instead of the literal `process.env.NODE_ENV` — avoids both bundler\n // constant-folding (#104) and \"Critical dependency\" import.meta warnings\n // in Next.js webpack builds.\n if (!config.forceShow && readNodeEnv() === \"production\") {\n const reason = \"production\";\n console.info(\"[siteping] Widget not loaded: production mode detected. Use forceShow: true to override.\");\n config.onSkip?.(reason);\n return skippedInstance();\n }\n\n // Guard: optional minimum viewport width. The widget has a phone layout, so\n // the default (0) renders everywhere — hosts opt in to hiding it on small\n // screens with `minViewportWidth`. forceShow bypasses this just like the\n // production guard above. Non-finite values (NaN from an untyped script-tag\n // consumer, Infinity) would silently break the `<` comparison — fail back\n // to the default instead. See issue #103.\n const minViewportWidth =\n typeof config.minViewportWidth === \"number\" && Number.isFinite(config.minViewportWidth)\n ? config.minViewportWidth\n : DEFAULT_MIN_VIEWPORT_WIDTH;\n if (!config.forceShow && window.innerWidth < minViewportWidth) {\n const reason = \"mobile\";\n console.info(\n `[siteping] Widget not loaded: viewport width < ${minViewportWidth}px (minViewportWidth). Use forceShow: true or lower minViewportWidth to override.`,\n );\n config.onSkip?.(reason);\n return skippedInstance();\n }\n\n // Guard: validate required config fields\n if (!config.store && (!config.endpoint || typeof config.endpoint !== \"string\")) {\n console.error(\n \"[siteping] Missing 'endpoint' or 'store' in config. Provide an endpoint like '/api/siteping' or a SitepingStore instance.\",\n );\n return skippedInstance();\n }\n if (!config.projectName || typeof config.projectName !== \"string\") {\n console.error(\"[siteping] Missing or invalid 'projectName' in config. Expected a non-empty string.\");\n return skippedInstance();\n }\n\n // Canonical once, here: every consumer (dictionary lookup, Intl date\n // formatting in the panel, tooltip and detail view) gets a tag it accepts.\n const locale = canonicalizeLocale(config.locale ?? \"en\");\n // Kick off the locale fetch immediately. English is bundled synchronously\n // and used as the fallback while the chunk is in flight. The launcher\n // awaits `localeReady` before rendering markers and re-localizes the FAB\n // and popup once the dictionary lands — both are mounted synchronously so\n // the widget is interactive immediately, but their labels start in the\n // English fallback until the chunk arrives.\n const localeReady: Promise<unknown> =\n locale === \"en\"\n ? Promise.resolve()\n : loadLocale(locale).catch(() => {\n /* fallback to English — already handled by createT */\n });\n const t = createT(locale);\n\n // Page scope — concrete URL + optional template, used to keep annotations\n // and panel results scoped to the current page. The widget calls this on\n // every initial markers load and on `instance.refresh()`, so SPA hosts can\n // re-fetch when the route changes.\n const scopeAnnotationsByUrl = config.scopeAnnotationsByUrl ?? true;\n const getScope = (): PageScope => {\n try {\n const result = config.getPageScope?.();\n if (result) return result;\n } catch (e) {\n log(\"getPageScope() threw, falling back to pathname:\", e);\n }\n return { url: window.location.pathname, urlPattern: null };\n };\n\n log(\"Initializing widget\", {\n projectName: config.projectName,\n theme: config.theme ?? \"light\",\n locale,\n scopeAnnotationsByUrl,\n });\n\n // Diagnostics — capture console + failed network at submit time when\n // `captureDiagnostics` is set. Buffers are installed eagerly so they\n // cover the entire session, then snapshotted in the annotation handler\n // below. We default to `false` even in dev to avoid surprise side\n // effects; users opt in via the config flag.\n const diagnosticsOpts = normaliseDiagnosticsOptions(config.captureDiagnostics);\n const consoleBuffer = diagnosticsOpts.console ? new ConsoleBuffer(diagnosticsOpts.maxConsoleEntries) : null;\n const networkBuffer = diagnosticsOpts.network ? new NetworkBuffer(diagnosticsOpts.maxNetworkEntries) : null;\n\n const colors = buildThemeColors(config.accentColor, config.theme);\n const bus = new EventBus<WidgetEvents>();\n const publicBus = new EventBus<SitepingPublicEvents>();\n\n // Client-side mode (store) vs HTTP mode (endpoint).\n // The earlier guard guarantees one of `store` / `endpoint` is set; we\n // capture the chosen branch in a typed local so TypeScript narrows on\n // each side without resorting to a non-null assertion.\n const client: WidgetClient = (() => {\n if (config.store) return new StoreClient(config.store, config.projectName);\n const endpoint = config.endpoint;\n if (typeof endpoint !== \"string\" || endpoint.length === 0) {\n throw new Error(\"[siteping] internal invariant: endpoint must be a non-empty string in HTTP mode\");\n }\n return new ApiClient(endpoint, config.projectName, { apiKey: config.apiKey, headers: config.headers });\n })();\n\n // Wire config callbacks to event bus\n if (config.onOpen) bus.on(\"open\", config.onOpen);\n if (config.onClose) bus.on(\"close\", config.onClose);\n if (config.onFeedbackSent) bus.on(\"feedback:sent\", config.onFeedbackSent);\n if (config.onCommentAdded) bus.on(\"comment:added\", config.onCommentAdded);\n if (config.onError) bus.on(\"feedback:error\", config.onError);\n if (config.onError) bus.on(\"panel:action-error\", config.onError);\n // A failing panel action is a bug in the host's own code, with no widget UI\n // to show it: always log it, even when onError handles it too.\n bus.on(\"panel:action-error\", (err) => console.error(\"[siteping] Panel action failed:\", err));\n if (config.onAnnotationStart) bus.on(\"annotation:start\", config.onAnnotationStart);\n if (config.onAnnotationEnd) bus.on(\"annotation:end\", config.onAnnotationEnd);\n\n // Feedback sent from this browser, listed by the panel's \"Mine\" filter\n const own = ownFeedback(config.projectName, config.endpoint);\n bus.on(\"feedback:sent\", (fb) => own.add(fb.id));\n bus.on(\"feedback:deleted\", (id) => own.remove(id));\n bus.on(\"feedback:all-deleted\", () => own.clear());\n\n // Bridge internal events to the public bus. The mapped-object type forces\n // one entry per public event — adding a key to SitepingPublicEvents\n // without bridging it here is a compile error, so `instance.on` can never\n // silently miss an event.\n const publicBridges: { [K in keyof SitepingPublicEvents]: () => void } = {\n \"feedback:sent\": () => bus.on(\"feedback:sent\", (fb) => publicBus.emit(\"feedback:sent\", fb)),\n \"feedback:deleted\": () => bus.on(\"feedback:deleted\", (id) => publicBus.emit(\"feedback:deleted\", id)),\n \"comment:added\": () => bus.on(\"comment:added\", (comment) => publicBus.emit(\"comment:added\", comment)),\n \"feedback:error\": () => bus.on(\"feedback:error\", (err) => publicBus.emit(\"feedback:error\", err)),\n \"panel:open\": () => bus.on(\"open\", () => publicBus.emit(\"panel:open\")),\n \"panel:close\": () => bus.on(\"close\", () => publicBus.emit(\"panel:close\")),\n \"annotation:start\": () => bus.on(\"annotation:start\", () => publicBus.emit(\"annotation:start\")),\n \"annotation:end\": () => bus.on(\"annotation:end\", () => publicBus.emit(\"annotation:end\")),\n };\n for (const wire of Object.values(publicBridges)) wire();\n\n // Debug logging for key lifecycle events\n bus.on(\"open\", () => log(\"Panel opened\"));\n bus.on(\"close\", () => log(\"Panel closed\"));\n bus.on(\"feedback:sent\", (fb) => log(\"Feedback sent\", fb.id));\n bus.on(\"feedback:error\", (err) => log(\"Feedback failed\", err.message));\n bus.on(\"annotation:start\", () => log(\"Annotation started\"));\n bus.on(\"annotation:end\", () => log(\"Annotation ended\"));\n\n // Create host element + Shadow DOM\n const host = document.createElement(\"siteping-widget\");\n // `pointer-events:auto`: a <body> child inherits a host modal's\n // `body { pointer-events: none }` (see host-isolation.ts).\n host.style.cssText = `position:fixed;z-index:${Z_INDEX_MAX};pointer-events:auto;`;\n // Use open mode only for testing — closed in production for CSS isolation.\n // Shadow DOM mode is determined by environment, never by public config.\n const shadowMode = readNodeEnv() === \"test\" ? (\"open\" as const) : (\"closed\" as const);\n const shadow = host.attachShadow({ mode: shadowMode });\n\n // Inject styles into Shadow DOM — adoptedStyleSheets with fallback for Safari < 16.4\n const supportsAdoptedStyleSheets = \"adoptedStyleSheets\" in ShadowRoot.prototype;\n if (supportsAdoptedStyleSheets) {\n const sheet = new CSSStyleSheet();\n sheet.replaceSync(buildStyles(colors));\n shadow.adoptedStyleSheets = [sheet];\n } else {\n const style = document.createElement(\"style\");\n style.textContent = buildStyles(colors);\n shadow.appendChild(style);\n }\n\n isolateFromHost(host, shadow);\n const removeHostIsolationGuard = installHostIsolationGuard();\n document.body.appendChild(host);\n\n // Track the last page element the user focused. FAB-launched annotation\n // moves focus into the shadow root before the annotator activates, so its\n // own activeElement capture only sees the 0x0 shadow host — the tracker\n // supplies the real keyboard (Enter) target instead. See issue #162.\n const focusTracker = createFocusTracker(host);\n\n // Screen reader live region for feedback submission announcements\n const liveRegion = document.createElement(\"div\");\n liveRegion.setAttribute(\"role\", \"status\");\n liveRegion.setAttribute(\"aria-live\", \"polite\");\n liveRegion.setAttribute(\"aria-atomic\", \"true\");\n // Widget chrome (see `isWidgetChrome`): anchor text context must never\n // read \"1 feedback markers displayed\" off a body-level element's sibling.\n liveRegion.setAttribute(\"data-siteping-ignore\", \"true\");\n liveRegion.style.cssText =\n \"position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;\";\n // A host modal's `aria-hidden` / `inert` would silence the announcements.\n isolateFromHost(liveRegion);\n document.body.appendChild(liveRegion);\n\n // Components outside Shadow DOM\n const tooltip = new Tooltip(colors, locale);\n const markers = new MarkerManager(colors, tooltip, bus, t, liveRegion);\n\n // Components inside Shadow DOM\n const fab = new Fab(shadow, config, bus, t);\n\n // Keep the FAB unread-count badge in sync with the visible markers. Marker\n // mutations (initial render, addFeedback after submit, panel-driven resolve /\n // delete / bulk-delete via re-render) all emit `markers:changed`, so a single\n // listener covers every path that can change the open count.\n bus.on(\"markers:changed\", (openCount) => fab.updateBadge(openCount));\n\n // Lazy-load Panel on first use (FAB click, instance.open, etc.) to keep the\n // initial bundle small. Panel + sub-modules are ~14 KB gzip on their own.\n // Memoize the import promise so subsequent calls reuse the same instance.\n // The promise honestly resolves to null when the widget was destroyed\n // before the panel chunk landed — callers already null-guard.\n let panelInstance: PanelType | null = null;\n let panelPromise: Promise<PanelType | null> | null = null;\n let destroyed = false;\n // Monotonic token guarding the launcher's own marker renders (initial load +\n // doRefresh). The panel guards its own renders with an AbortController; the\n // two direct launcher paths share this counter so the *last-issued* fetch\n // wins, never the last to resolve. Without it, an SPA nav burst (or an\n // initial load racing the first navigation) could render a stale page's\n // markers out of order, since markers.render() is a full clear-and-rebuild.\n let markerGeneration = 0;\n\n /**\n * The author of a write: the host's `identity`, then the one saved in this\n * browser, then the modal's answer (saved) — `null` when the visitor\n * dismisses the modal. Host-provided identity is not persisted: the host\n * stays the source of truth on every render. `overPopup`: the feedback\n * popup is on screen (see `promptIdentity`).\n */\n async function resolveIdentity(overPopup = false): Promise<Identity | null> {\n const known = config.identity ?? getIdentity();\n if (known) return known;\n const entered = await promptIdentity(shadow, t, overPopup);\n if (entered) saveIdentity(entered);\n return entered;\n }\n\n async function loadPanel(): Promise<PanelType | null> {\n if (destroyed) return null;\n if (panelInstance) return panelInstance;\n if (!panelPromise) {\n panelPromise = import(\"./panel.js\").then((mod) => {\n if (destroyed) return null;\n panelInstance = new mod.Panel(shadow, colors, bus, client, config.projectName, markers, t, locale, {\n getScope,\n scopeAnnotationsByUrl,\n panelActions: config.panelActions,\n ownFeedback: own,\n resolveIdentity,\n readOnly: config.readOnly,\n });\n return panelInstance;\n });\n }\n return panelPromise;\n }\n\n // Prefetch Panel in idle time so the first FAB click doesn't pay the\n // network/parse cost of the dynamic import. The chunk still ships lazily\n // (saves first-paint gzip), but it's already warming up by the time the\n // user is likely to click. Falls back to setTimeout in browsers without\n // requestIdleCallback (Safari before 17).\n if (typeof window !== \"undefined\") {\n const prefetch = () => {\n if (!destroyed) void loadPanel();\n };\n const ric = (window as { requestIdleCallback?: (cb: () => void) => void }).requestIdleCallback;\n if (typeof ric === \"function\") ric(prefetch);\n else setTimeout(prefetch, 200);\n }\n\n // The FAB emits `panel:toggle` on chat click — we intercept here so the\n // launcher (which holds the lazy loader) can drive the Panel lifecycle.\n // Panel itself also subscribes to `panel:toggle` once loaded; once the\n // dynamic import resolves we manually call `p.open()` because the missed\n // initial emit can't be replayed.\n let pendingOpen = false;\n const unsubToggle = bus.on(\"panel:toggle\", (open) => {\n if (panelInstance) return; // Real Panel already handles subsequent toggles\n if (open) {\n pendingOpen = true;\n loadPanel()\n .then((p) => {\n if (p && pendingOpen) p.open();\n pendingOpen = false;\n })\n .catch((err) => log(\"Failed to lazy-load panel:\", err));\n } else {\n pendingOpen = false;\n }\n });\n\n const annotator = new Annotator(colors, bus, t, config.enableScreenshot ?? false, () =>\n focusTracker.getLastPageFocus(),\n );\n\n let onContextMenu: ((e: MouseEvent) => void) | null = null;\n if (config.enableRightClickComment) {\n onContextMenu = (e: MouseEvent) => {\n // Respect host pages that run their own custom context menus (grids,\n // editors). Element-level handlers fire before this document-level\n // listener, so if they called preventDefault() we yield.\n if (e.defaultPrevented) return;\n // Keyboard-triggered contextmenu (≣ Menu key, Shift+F10): Pointer\n // Events L3 mandates pointerType === \"\" (pointerId -1) for non-pointer\n // activations — yield to the native menu. contextmenu is a PointerEvent\n // in Chrome/Edge 92+, Firefox 129+, Safari 18.2+.\n const pointerType = (e as PointerEvent).pointerType;\n if (pointerType === \"\") return;\n // Legacy MouseEvent engines (no pointerType to consult): fall back to\n // requiring a genuine right-button click.\n if (pointerType === undefined && e.button !== 2) return;\n // Modifier-key escape hatch: Shift/Ctrl/Alt/Meta → native menu.\n if (e.shiftKey || e.ctrlKey || e.altKey || e.metaKey) return;\n // Exclude SitePing's own UI — right-clicking the FAB, panel, markers,\n // popup, or overlay must not hijack the event. composedPath() reaches\n // into the closed shadow root so all retargeted events are caught.\n const path = e.composedPath();\n if (\n path.some(\n (n) =>\n n === host ||\n (n instanceof Element && (n.hasAttribute(\"data-siteping-ignore\") || n.id === \"siteping-markers\")),\n )\n )\n return;\n // Don't swallow the event while the annotator is already active (e.g.\n // the user right-clicks to paste in the popup textarea). Fall through\n // to the native menu instead of silently consuming the event.\n if (annotator.isBusy) return;\n e.preventDefault();\n void annotator\n .startInstantAnnotation(e.clientX, e.clientY)\n .catch((err) => log(\"right-click annotation failed\", err));\n };\n document.addEventListener(\"contextmenu\", onContextMenu);\n }\n\n // Once the locale dictionary lands, swap the FAB + popup labels from the\n // English fallback to the configured language. `t` already resolves to the\n // loaded dictionary at call time, so the markers list rendered below (which\n // calls `t` lazily) only needs to wait on `localeReady` once.\n if (locale !== \"en\") {\n localeReady.then(() => {\n if (destroyed) return;\n fab.refreshLabels();\n annotator.refreshLabels();\n });\n }\n\n // Handle annotation completion via event bus (not DOM events).\n // Concurrency guard: a second `annotation:complete` while one is still in\n // flight must not start a duplicate submission. The Annotator already\n // serializes its own submissions (no second annotation can be drawn while\n // the popup is open), so this is defence-in-depth — but it must not *silently*\n // drop the event: a dropped event would leave any waiting `runSubmission`\n // listener hung forever. We emit `submission:cancelled` so the waiter\n // unblocks as a benign abort (the popup restores, `onError` is not called).\n let submitting = false;\n const unsubAnnotation = bus.on(\"annotation:complete\", async (data) => {\n if (submitting) {\n bus.emit(\"submission:cancelled\");\n return;\n }\n submitting = true;\n try {\n const { annotation, type, message, clientId, screenshotDataUrl, screenshotRegion } = data;\n\n const identity = await resolveIdentity(true);\n if (!identity) {\n // User cancelled the identity prompt. Emit `submission:cancelled`\n // (not `feedback:error`) so the popup's pending submit handler\n // unblocks and restores the form — cancelling a prompt is a benign\n // user action, so `config.onError` must not fire for it.\n bus.emit(\"submission:cancelled\");\n return;\n }\n\n // Use scope.url as the single source of truth — same identifier the\n // panel filter and marker filter use. If we stored full URLs here while\n // filtering by pathname, freshly-created feedbacks would never match\n // their own scope filter and would vanish from the UI immediately.\n // Default scope.url is `window.location.pathname` (no query string,\n // so token/key/secret query params can't leak by construction). Hosts\n // that need origin or query in the identifier override `getPageScope`.\n const scope = getScope();\n\n // Snapshot the buffers right before submit so the captured slice\n // matches the moment the user clicked \"send\", not some earlier point.\n let diagnostics: DiagnosticsSnapshot | null = null;\n if (consoleBuffer || networkBuffer) {\n diagnostics = {\n console: consoleBuffer?.getEntries() ?? [],\n network: networkBuffer?.getEntries() ?? [],\n };\n }\n\n const payload: FeedbackPayload = {\n projectName: config.projectName,\n type,\n message,\n url: scope.url,\n urlPattern: scope.urlPattern,\n viewport: `${window.innerWidth}x${window.innerHeight}`,\n userAgent: navigator.userAgent,\n authorName: identity.name,\n authorEmail: identity.email,\n annotations: [annotation],\n clientId,\n screenshotDataUrl: screenshotDataUrl ?? null,\n screenshotRegion: screenshotRegion ?? null,\n diagnostics,\n };\n\n try {\n const response = await client.sendFeedback(payload);\n bus.emit(\"feedback:sent\", response);\n // Compare against the scope captured before submit (route may have\n // changed during the network round-trip — re-reading scope here\n // would race with SPA navigation).\n if (!scopeAnnotationsByUrl || response.url === scope.url) {\n markers.addFeedback(response, markers.count + 1);\n }\n liveRegion.textContent = t(\"feedback.sent.confirmation\");\n // Only refresh the panel if it has been loaded — `refresh()` is a\n // no-op when the panel is closed, so skipping the dynamic import here\n // avoids loading 14 KB of code that would otherwise do nothing.\n if (panelInstance) await panelInstance.refresh();\n } catch (error) {\n bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n liveRegion.textContent = t(\"feedback.error.message\");\n }\n } finally {\n submitting = false;\n }\n });\n\n // Load markers immediately on page load. We always pass the current page URL\n // when scopeAnnotationsByUrl is enabled so the server narrows results to the\n // current page — preventing annotations from one page accidentally rendering\n // on another (when CSS selectors happen to match unrelated elements).\n const initialScope = getScope();\n const initialOptions = scopeAnnotationsByUrl ? { limit: PAGE_SIZE, url: initialScope.url } : { limit: PAGE_SIZE };\n const deepLinkOpts = normaliseDeepLinkOptions(config.deepLink);\n // Claim a generation for the initial load so a navigation that fires while\n // this fetch is in flight (doRefresh bumps the counter) supersedes it — the\n // old page's markers must never clobber the page the user navigated to.\n const initialLoadGeneration = ++markerGeneration;\n // Render markers only once both the feedbacks and the locale dictionary are\n // ready. Marker aria-labels are built via `t(...)` at render time — without\n // this `Promise.all`, a fast HTTP response could outrun a slow locale chunk\n // and freeze marker labels in the English fallback for non-English locales.\n Promise.all([client.getFeedbacks(config.projectName, initialOptions), localeReady])\n .then(([{ feedbacks }]) => {\n if (destroyed || markerGeneration !== initialLoadGeneration) return;\n // Defensive client-side filter — backend may not yet support the `url` query.\n const visible = scopeAnnotationsByUrl ? feedbacks.filter((f) => f.url === initialScope.url) : feedbacks;\n markers.render(visible);\n // Apply deeplink focus once markers exist. Failures here are\n // non-fatal — a malformed URL or an unknown ID just leaves the page\n // as the user found it, so log and move on.\n if (deepLinkOpts.enabled) {\n try {\n const focusId = new URLSearchParams(window.location.search).get(deepLinkOpts.param);\n if (focusId) {\n const matched = markers.focusFeedback(focusId);\n log(\n `deepLink ?${deepLinkOpts.param}=${focusId} ${matched ? \"focused\" : \"did not match a visible feedback\"}`,\n );\n }\n } catch (e) {\n log(\"deepLink parsing failed:\", e);\n }\n }\n })\n .catch((err) => {\n log(\"Failed to load initial markers:\", err);\n });\n\n // Flush retry queue on load (HTTP mode only — store mode has no retry queue)\n if (config.endpoint) {\n flushRetryQueue(config.endpoint, config.identity ?? getIdentity(), {\n apiKey: config.apiKey,\n headers: config.headers,\n })\n .then(() => log(\"Retry queue flushed\"))\n .catch(() => {});\n }\n\n // Re-fetch feedbacks for the *current* scope and update the UI. Shared by the\n // public `instance.refresh()` and the SPA navigation watcher below.\n //\n // When the panel is open, its own `refresh()` already runs `loadFeedbacks()`\n // which re-renders markers — a second fetch here would race with it (the\n // loser overwrites the winner's markers, off by a generation). So we delegate\n // when open, and fetch markers ourselves when closed (the panel won't, but\n // SPA hosts still need the new page's markers after a route change).\n //\n // Returns the in-flight promise (rejecting on fetch failure) so callers can\n // react — `instance.refresh()` swallows it (the public API never rejects onto\n // the host), the navigation watcher uses it to re-arm its dedup on failure.\n const doRefresh = (): Promise<void> => {\n // Bump first, before the open/closed split, so switching to panel-driven\n // rendering also invalidates any closed-panel fetch still in flight.\n const generation = ++markerGeneration;\n if (panelInstance?.isCurrentlyOpen) {\n return panelInstance.refresh();\n }\n const scope = getScope();\n const opts = scopeAnnotationsByUrl ? { limit: PAGE_SIZE, url: scope.url } : { limit: PAGE_SIZE };\n return client.getFeedbacks(config.projectName, opts).then(({ feedbacks }) => {\n // Drop the result if a newer refresh superseded us (out-of-order\n // resolution), the widget was torn down, or the panel opened mid-flight\n // and now owns marker rendering itself.\n if (destroyed || generation !== markerGeneration || panelInstance?.isCurrentlyOpen) return;\n const visible = scopeAnnotationsByUrl ? feedbacks.filter((f) => f.url === scope.url) : feedbacks;\n markers.render(visible);\n });\n };\n\n // SPA route-change watcher. The widget is normally mounted once (singleton)\n // inside a persistent layout — e.g. a Next.js App Router `layout.tsx`, which\n // does NOT remount on client-side navigation. Without this, init runs once and\n // the panel list + markers stay frozen on the page where the widget first\n // mounted. We patch the History API (SPA routers call pushState/replaceState\n // rather than triggering popstate) and listen for popstate/hashchange, then\n // re-fetch only when the scope key actually changes. This re-fetches data\n // only — it deliberately does NOT re-focus/re-scroll (deep-link focus stays\n // initial-load only; see `deepLink`). Opt out with `watchNavigation: false`.\n let teardownNavigation: (() => void) | null = null;\n if (config.watchNavigation !== false && typeof window !== \"undefined\" && typeof history !== \"undefined\") {\n const scopeKey = (s: PageScope): string => `${s.url}\\n${s.urlPattern ?? \"\"}`;\n let lastScopeKey = scopeKey(initialScope);\n const onLocationChange = (): void => {\n if (destroyed) return;\n const key = scopeKey(getScope());\n // Same scope (e.g. query-only or hash-only nav under the default pathname\n // scope) — nothing to re-fetch. Guards against pushState storms too.\n if (key === lastScopeKey) return;\n const prevKey = lastScopeKey;\n lastScopeKey = key;\n log(\"SPA navigation detected — refreshing feedbacks for new scope\");\n doRefresh().catch(() => {\n // The refresh failed (network error). Roll the dedup key back so a\n // later nav *back* to this same scope retries instead of being\n // silently suppressed — unless a newer navigation already moved on.\n if (lastScopeKey === key) lastScopeKey = prevKey;\n });\n };\n\n const originalPushState = history.pushState;\n const originalReplaceState = history.replaceState;\n // Call through to the original first so `location` is already updated by the\n // time onLocationChange() reads getScope().\n const patchedPushState: typeof history.pushState = function (this: History, ...args) {\n originalPushState.apply(this, args);\n onLocationChange();\n };\n const patchedReplaceState: typeof history.replaceState = function (this: History, ...args) {\n originalReplaceState.apply(this, args);\n onLocationChange();\n };\n history.pushState = patchedPushState;\n history.replaceState = patchedReplaceState;\n window.addEventListener(\"popstate\", onLocationChange);\n window.addEventListener(\"hashchange\", onLocationChange);\n\n teardownNavigation = () => {\n window.removeEventListener(\"popstate\", onLocationChange);\n window.removeEventListener(\"hashchange\", onLocationChange);\n // Restore only if nobody patched on top of us — otherwise we'd clobber\n // another library's History wrapper. If a library did wrap on top, our\n // patch stays in the chain (and keeps its closure alive), but it's inert:\n // `destroyed` is already true above, so onLocationChange() is a no-op.\n if (history.pushState === patchedPushState) history.pushState = originalPushState;\n if (history.replaceState === patchedReplaceState) history.replaceState = originalReplaceState;\n };\n }\n\n const self: SitepingInstance = {\n destroy: () => {\n // Idempotent: hosts can hold stale handles (two `useSiteping` consumers\n // share the singleton), and a repeat call must not tear anything down\n // again — least of all a newer widget's singleton slot below.\n if (destroyed) return;\n log(\"Destroying widget\");\n if (onContextMenu) {\n document.removeEventListener(\"contextmenu\", onContextMenu);\n }\n destroyed = true;\n pendingOpen = false;\n teardownNavigation?.();\n focusTracker.destroy();\n unsubAnnotation();\n unsubToggle();\n fab.destroy();\n panelInstance?.destroy();\n annotator.destroy();\n markers.destroy();\n tooltip.destroy();\n // Restore the original console / fetch / XHR so the host page isn't\n // left with patched globals after the widget tears itself down.\n consoleBuffer?.dispose();\n networkBuffer?.dispose();\n bus.removeAll();\n publicBus.removeAll();\n liveRegion.remove();\n host.remove();\n // Last: the teardown above moves focus out of the widget (popup focus\n // restore), which a host modal's focus trap must not see either.\n removeHostIsolationGuard();\n if (instance === self) instance = null;\n },\n open: () => {\n // Emit synchronously so consumers wired through `onOpen` / `panel:open`\n // see the open event immediately, even before the Panel module has\n // finished loading on the first call.\n bus.emit(\"panel:toggle\", true);\n },\n close: () => {\n if (panelInstance) {\n panelInstance.close();\n } else {\n // Cancel a pending open before the panel has loaded.\n pendingOpen = false;\n }\n },\n focusFeedback: (feedbackId: string) => {\n // Returns false when no entry matches — unknown ID, feedback filtered\n // out by `scopeAnnotationsByUrl`, or markers not yet loaded (the\n // initial getFeedbacks is async, and the widget exposes no public\n // \"markers ready\" event today). Hosts that race against initial load\n // can retry, or trigger focus from a user gesture instead.\n return markers.focusFeedback(feedbackId);\n },\n // Public API must never reject onto the host — swallow the promise.\n refresh: () => {\n void doRefresh().catch(() => {});\n },\n on: <K extends keyof SitepingPublicEvents>(event: K, listener: SitepingPublicEventListener<K>) =>\n publicBus.on(event, listener),\n off: <K extends keyof SitepingPublicEvents>(event: K, listener: SitepingPublicEventListener<K>) => {\n publicBus.off(event, listener);\n },\n };\n\n instance = self;\n return self;\n}\n\n/**\n * Show a modal identity form inside the Shadow DOM.\n * Glassmorphism: frosted backdrop, glass modal, gradient CTA — a bottom sheet\n * on phones (`styles/mobile.ts`), lifted above the on-screen keyboard.\n * Returns null if the user cancels.\n */\nfunction promptIdentity(shadowRoot: ShadowRoot, t: TFunction, overPopup: boolean): Promise<Identity | null> {\n return new Promise((resolve) => {\n // Save the currently focused element to restore on close\n const previouslyFocused = (shadowRoot.activeElement ?? document.activeElement) as HTMLElement | null;\n\n // Over the feedback popup, move the shadow host to the end of <body> so\n // the identity prompt wins the source-order tiebreak against it. Both\n // elements already sit at `Z_INDEX_MAX` (max int32 — no \\\"higher\\\"), and\n // since #114 the popup stays visible during submission. The popup is\n // appended to `document.body` after the host, which made it win when\n // z-indices tied (#126). Only then: a moved host loses every scroll\n // position and the focus inside its shadow root, so a reply from the\n // panel's thread would jump its detail view back to the top.\n const host = shadowRoot.host;\n if (overPopup && host.parentNode) host.parentNode.appendChild(host);\n\n const backdrop = document.createElement(\"div\");\n backdrop.className = \"sp-identity-backdrop\";\n\n const modal = document.createElement(\"div\");\n modal.className = \"sp-identity-modal\";\n\n const titleId = `sp-identity-title-${Date.now()}`;\n modal.setAttribute(\"role\", \"dialog\");\n modal.setAttribute(\"aria-modal\", \"true\");\n modal.setAttribute(\"aria-labelledby\", titleId);\n\n const title = document.createElement(\"div\");\n title.className = \"sp-identity-title\";\n title.id = titleId;\n title.textContent = t(\"identity.title\");\n title.style.marginBottom = \"20px\";\n\n const nameInputId = `sp-identity-name-${Date.now()}`;\n const emailInputId = `sp-identity-email-${Date.now()}`;\n\n const nameLabel = document.createElement(\"label\");\n nameLabel.className = \"sp-input-label\";\n nameLabel.textContent = t(\"identity.nameLabel\");\n nameLabel.setAttribute(\"for\", nameInputId);\n const nameInput = document.createElement(\"input\");\n nameInput.className = \"sp-input\";\n nameInput.id = nameInputId;\n nameInput.type = \"text\";\n nameInput.maxLength = IDENTITY_FIELD_MAX_LENGTH;\n nameInput.placeholder = t(\"identity.namePlaceholder\");\n nameInput.style.marginBottom = \"14px\";\n\n const emailLabel = document.createElement(\"label\");\n emailLabel.className = \"sp-input-label\";\n emailLabel.textContent = t(\"identity.emailLabel\");\n emailLabel.setAttribute(\"for\", emailInputId);\n const emailInput = document.createElement(\"input\");\n emailInput.className = \"sp-input\";\n emailInput.id = emailInputId;\n emailInput.type = \"email\";\n emailInput.maxLength = IDENTITY_FIELD_MAX_LENGTH;\n emailInput.placeholder = t(\"identity.emailPlaceholder\");\n\n const btnRow = document.createElement(\"div\");\n btnRow.className = \"sp-identity-actions\";\n\n // The phone sheet sits at the bottom edge — keep it above the keyboard.\n const stopKeyboardTracking = trackKeyboardInset((inset) => modal.style.setProperty(\"--sp-kb\", `${inset}px`));\n\n const closeModal = (result: Identity | null) => {\n backdrop.removeEventListener(\"keydown\", onKeydown);\n unregisterEscapeLayer();\n stopKeyboardTracking();\n backdrop.classList.remove(\"sp-identity--open\");\n setTimeout(() => {\n backdrop.remove();\n previouslyFocused?.focus();\n resolve(result);\n }, 250);\n };\n\n const cancelBtn = document.createElement(\"button\");\n cancelBtn.className = \"sp-btn-ghost\";\n cancelBtn.textContent = t(\"identity.cancel\");\n cancelBtn.addEventListener(\"click\", () => closeModal(null));\n\n const submitBtn = document.createElement(\"button\");\n submitBtn.className = \"sp-btn-primary\";\n submitBtn.textContent = t(\"identity.submit\");\n const setInvalid = (input: HTMLInputElement, invalid: boolean) => {\n input.style.borderColor = invalid ? \"var(--sp-type-bug, #ef4444)\" : \"\";\n if (invalid) input.setAttribute(\"aria-invalid\", \"true\");\n else input.removeAttribute(\"aria-invalid\");\n };\n\n submitBtn.addEventListener(\"click\", () => {\n const name = nameInput.value.trim();\n const email = emailInput.value.trim();\n if (!name || !email) return;\n // Same pattern and length cap the server schema enforces — what the\n // modal accepts here is persisted and replayed on every submission, so\n // it must never be something the server rejects. `maxlength` covers\n // typing; this covers values set around it.\n const nameInvalid = name.length > IDENTITY_FIELD_MAX_LENGTH;\n const emailInvalid = email.length > IDENTITY_FIELD_MAX_LENGTH || !isValidEmail(email);\n setInvalid(nameInput, nameInvalid);\n setInvalid(emailInput, emailInvalid);\n if (nameInvalid || emailInvalid) return;\n closeModal({ name, email });\n });\n\n // Focus trap: cycle Tab/Shift+Tab within the modal\n const focusableSelectors = 'input, button, [tabindex]:not([tabindex=\"-1\"])';\n const onKeydown = (e: Event) => {\n const ke = e as KeyboardEvent;\n if (ke.key === \"Escape\") {\n // Cancel the prompt only — opened from a thread, the panel's detail view stays.\n ke.stopPropagation();\n closeModal(null);\n return;\n }\n if (ke.key === \"Tab\") {\n const focusableEls = Array.from(modal.querySelectorAll<HTMLElement>(focusableSelectors));\n if (focusableEls.length === 0) return;\n const first = focusableEls[0];\n const last = focusableEls[focusableEls.length - 1];\n if (!first || !last) return;\n const active = shadowRoot.activeElement as HTMLElement | null;\n if (ke.shiftKey) {\n if (active === first || !modal.contains(active)) {\n ke.preventDefault();\n last.focus();\n }\n } else {\n if (active === last || !modal.contains(active)) {\n ke.preventDefault();\n first.focus();\n }\n }\n }\n };\n backdrop.addEventListener(\"keydown\", onKeydown);\n const unregisterEscapeLayer = registerEscapeLayer(backdrop, () => true);\n\n // Close on backdrop click\n backdrop.addEventListener(\"click\", (e) => {\n if (e.target === backdrop) closeModal(null);\n });\n\n btnRow.appendChild(cancelBtn);\n btnRow.appendChild(submitBtn);\n\n modal.appendChild(title);\n modal.appendChild(nameLabel);\n modal.appendChild(nameInput);\n modal.appendChild(emailLabel);\n modal.appendChild(emailInput);\n modal.appendChild(btnRow);\n backdrop.appendChild(modal);\n\n shadowRoot.appendChild(backdrop);\n\n // Animate in\n requestAnimationFrame(() => {\n backdrop.classList.add(\"sp-identity--open\");\n nameInput.focus();\n });\n });\n}\n","import type { SitepingConfig, SitepingInstance } from \"@siteping/core\";\nimport { launch } from \"./launcher.js\";\n\nexport type {\n AnchorData,\n AnnotationPayload,\n AnnotationResponse,\n CommentResponse,\n FeedbackPayload,\n FeedbackPermissions,\n FeedbackResponse,\n FeedbackStatus,\n FeedbackType,\n RectData,\n SitepingConfig,\n SitepingHeadersOption,\n SitepingHttpConfig,\n SitepingInstance,\n SitepingLocale,\n SitepingPanelAction,\n SitepingPanelActionContext,\n SitepingPanelActionFeedback,\n SitepingPanelButtonAction,\n SitepingPanelLinkAction,\n SitepingPublicEvents,\n SitepingStore,\n SitepingStoreConfig,\n} from \"@siteping/core\";\nexport type { TFunction, TranslationKey, Translations } from \"./i18n/index.js\";\nexport { loadLocale, registerLocale } from \"./i18n/index.js\";\nexport type { Identity } from \"./identity.js\";\n\n/**\n * Initialize the Siteping feedback widget.\n *\n * @example\n * ```ts\n * import { initSiteping } from '@siteping/widget'\n *\n * const { destroy } = initSiteping({\n * endpoint: '/api/siteping',\n * projectName: 'my-project',\n * })\n * ```\n */\nexport function initSiteping(config: SitepingConfig): SitepingInstance {\n return launch(config);\n}\n"]}
|